10REM SAVE"$.Arabic.Source.StateMC" 20very_temp = T% 30PROCConsts 40True = 0:False = 1 50PROCVars 60data=FNzp(2,"data:StateMC") 70ContextAnalyseFlag = H%: NumberReverseFlag = I% 80OsWrCh = &FFEE 90WrchV = &200+7*2 100ExtWrch = &FF00+7*3 110DIM O% &BFFF-P% 120del = 127 130_Idle = 0 140_FirstC = 1 150_FirstV = 2 160_LastC = 3 170_LastV = 4 180_LastCV = 5 190_LastVC = 6 200R%=P%:Q%=O% 210FOR Pass=4 TO 6+L% STEP 2+L% 220P%=R%:O%=Q% 230[OPT Pass 240\ Because we are pushed for time, this will go via 3-byte vector... 250.ArabicFont 260 OPT FNStack(zp0):OPT FNStack(zp1) 270 Lda #FontDef MOD 256:Sta zp0 280 Lda #FontDef DIV 256:Sta zp1 290.InitFont 300 Lda (zp0):Jsr OsWrCh 310 Inc zp0:Bne qq1:Inc zp1:.qq1 320 Lda zp0:Cmp #FontEnd MOD 256:Bne InitFont 330 Lda zp1:Cmp #FontEnd DIV 256:Bne InitFont 340 OPT FNUnstack(zp1):OPT FNUnstack(zp0) 350 Rts 360 370.WrchHandlerInit 380 OPT FNEnter 390 Lda WrchV:OPT FNSta(HisWrch) 400 Lda WrchV+1:OPT FNSta(HisWrch+1) 410 Lda #ExtWrch MOD 256:Sta WrchV 420 Lda #ExtWrch DIV 256:Sta WrchV+1 430 Lda #MyWrch MOD 256:Sta &D9F+3*7+0 440 Lda #MyWrch DIV 256:Sta &D9F+3*7+1 450 Lda &F4:Sta &D9F+3*7+2 460 Lda #0:OPT FNSta(CurrentState) 470 Lda #False:OPT FNSta(StateMachineActive) 480 Lda #0:Sta Buff 490 Ldx &F4:Lda &DF0,X:Clc:Adc #1:Sta Buff+1 Number buffer MUST BE second page 500 Lda #0:OPT FNSta(Idx) 510OPT FNdebug("T") 520 OPT FNExit 530 Rts 540 550.notalph 560 Rts 570 580.AlphabetHandler 590 Cmp #71:Bne notalph 600 Cpx #0:Bmi notalph 610 Cpx #21:Bne notarabic 620 Jsr ArabicFont 630 OPT FNEnter 640 Lda #True:OPT FNSta(StateMachineActive) 650 OPT FNExit 660 Lda #0 670 Rts 680.notarabic 690\ Tweak variables to say 'don't table-lookup arabic chars' 700 PHA:PHX:PHY 710 OPT FNEnter 720 Lda #False:OPT FNSta(StateMachineActive) 730 OPT FNExit 740 PLY:PLX:PLA 750 Rts 760 770.NextWrch 780 Jsr NumericStateMachine 790 Rts 800.RawWrch 810Jmp &E7E6 \ For now... 820 OPT FNJmpI(HisWrch) 830 840.MyWrch 850 PHX:PHY:PHA 860\Lda &90:\Cmp #ASC("T"):.zzpp \Bne zzpp 870PLA:PHA 880OPT FNdebug("A") 890 TAY:OPT FNEnter:TYA 900 OPT FNSta(ThisChar) 910OPT FNdebug("B") 920 OPT FNLda(StateMachineActive):Cmp #True:Bne DoRaw 930OPT FNdebug("C") 940 Lda #&DA:Ldx #0:Ldy #255: \Jsr OsByte:Ldx &26A \ GOES BANG HERE TOO!!!!!! 950OPT FNdebug("D") 960 Cpx #0:Beq NotInVDUSeq 970.DoRaw 980OPT FNdebug("E") 990 OPT FNLda(ThisChar) 1000 TAY:OPT FNExit:TYA:PLA:PHY 1010 PLA:PLY:PLX 1020OPT FNdebug("U") 1030 Jsr RawWrch 1040OPT FNdebug("T") 1050 Rts 1060.NotInVDUSeq 1070OPT FNdebug("G") 1080\ Entry to state-machine. 1090\ CurrentState initialised to Idle (0) 1100 OPT FNLda(ContextAnalyseFlag):Cmp #True:Beq checkQ 1110 OPT FNLda(ThisChar) 1120OPT FNdebug("H") 1130 Tay:Lda SATab,Y \ Actually, not SATab but that corresponding to 1140 \ current arabic alphabet (Arabic1 - Arabic4) 1150 Jsr NextWrch 1160OPT FNdebug("I") 1170 Jmp MyWrchExit 1180.checkQ 1190OPT FNdebug("J") 1200\ We forgot the concept of 'NUL' characters which don't change the 1210\ state machine, whatever state it is in. CHR$(0) is the obvious 1220\ example; less obvious ones are complete VDU 23 sequences and 1230\ colour changes etc. As the state machine only ever sees the first 1240\ byte of any of these multi-byte sequences anyway, it ought to be 1250\ possible to cause an early exit. Almost special case but not quite - 1260\ the characters causing the exit can be flagged in a table - ideally 1270\ TypeTab if we can find a spare bit which does not affect any other 1280\ tests... 1290 OPT FNLdy(ThisChar) 1300 Lda CharType,Y 1310 Sta TmpVar 1320 Bit TmpVar \ &40 -> V, &80 -> N 1330 Bmi SetC:Bvs VSet 1340 \ Neither - Set N 1350 Clc:Lda #&80:Bra SetOK 1360OPT FNdebug("K") 1370.SetC 1380OPT FNdebug("L") 1390 \ &80 set - set C, clear N (V will be clear) 1400 Sec:Lda #&00:Bra SetOK 1410.VSet 1420OPT FNdebug("M") 1430 Clc:Lda #&00 \ - clear C,N (V will be set) 1440 \ V is set if bit6 is set, i.e. VowelBit 1450 \ C is set if bit7 is set, i.e. ConsonantBit 1460 \ N is set if neither bit6 nor bit7 set, i.e. NeitherBit 1470.SetOK 1480OPT FNdebug("N") 1490 PHP 1500 PLA:Sta TmpVar:PHA 1510 Lda #(ReturnToHere-1) DIV 256:Pha 1520 Lda #(ReturnToHere-1) MOD 256:Pha 1530 Lda TmpVar:PHA 1540 OPT FNLda(CurrentState):Tax 1550 Lda StateTab_high,X:Pha 1560 Lda StateTab_low,X :Pha 1570OPT FNdebug("O") 1580 Rts \ Enter with C,V,N & Y=ThisChar set up. 1590.ReturnToHere 1600OPT FNdebug("P") 1610 PLP 1620 \ Load up next state from table 1630 \ Copy Last into ButLast 1640 \ Copy ThisChar into Last 1650 \ Return... 1660 Lda #0 \ C set => 0 1670 Bcs CState 1680 Php:Clc:Adc #1:Plp \ V set => 1 1690 Bvs VState 1700 Clc:Adc #1 \ neither set => 2 1710.CState:.VState 1720OPT FNdebug("Q") 1730 Clc:OPT FNAdc(CurrentState):OPT FNAdc(CurrentState):OPT FNAdc(CurrentState) 1740 Tay:Lda CTransTab,Y 1750 OPT FNSta(CurrentState) 1760 OPT FNLda(LastChar):OPT FNSta(ButLastChar) 1770 OPT FNLda(ThisChar):OPT FNSta(LastChar) 1780OPT FNdebug("R") 1790.MyWrchExit 1800 OPT FNExit \ *************** MAIN EXIT POINT 1810OPT FNdebug("S") 1820 PLA:PLY:PLX 1830OPT FNdebug("T") 1840 Rts \ <<<<<<< Return from Wrch ???? 1850 1860 1870.StateTab_low 1880 EQUB (Idle-1) MOD 256 1890 EQUB (FirstC-1) MOD 256 1900 EQUB (FirstV-1) MOD 256 1910 EQUB (LastC-1) MOD 256 1920 EQUB (LastV-1) MOD 256 1930 EQUB (LastCV-1) MOD 256 1940 EQUB (LastVC-1) MOD 256 1950 1960.StateTab_high 1970 EQUB (Idle-1) DIV 256 1980 EQUB (FirstC-1) DIV 256 1990 EQUB (FirstV-1) DIV 256 2000 EQUB (LastC-1) DIV 256 2010 EQUB (LastV-1) DIV 256 2020 EQUB (LastCV-1) DIV 256 2030 EQUB (LastVC-1) DIV 256 2040 2050.CTransTab \ Table of state transition 2060\ State OnC OnV OnX 2070\