From 67f1a6259610d617e9c527566ab669f51abfac40 Mon Sep 17 00:00:00 2001 From: Marek Karcz Date: Sun, 13 Mar 2016 19:12:14 -0400 Subject: [PATCH] Version 2.0 Version 2.0, full emulation of 6502 op-codes, fully tested and functional. Extended description in ReadMe file. Bin2Hex tool to convert binary images to memory definition format. Microchess, EhBasic added. --- 6502_func_test.bin | Bin 0 -> 65536 bytes 6502_func_test.dat | 856 +++ 6502_func_test.lst | 14236 +++++++++++++++++++++++++++++++++++++ 6502_functional_test.asm | 6011 ++++++++++++++++ BCDCodes.dev | 124 +- BCDCodes.layout | 8 + Bin2Hex.dev | 62 + Bin2Hex.layout | 8 + Display.cpp | 557 +- Display.h | 114 +- MKBasic.cpp | 26 +- MKBasic.dev | 374 +- MKBasic.h | 36 +- MKBasic.layout | 38 + MKCpu.cpp | 3483 +++++---- MKCpu.h | 886 +-- MKGenException.cpp | 40 +- MKGenException.h | 47 +- Makefile.win | 46 + Memory.cpp | 773 +- Memory.h | 132 +- Notes.txt | 48 +- ReadMe.txt | 324 +- TestBCD.65s | 582 +- VMachine.cpp | 1522 ++-- VMachine.h | 149 +- bcd.c | 112 +- bin2hex.c | 187 + dummy.ram | 628 +- dummy.rom | 628 +- eh_basic.asm | 8723 +++++++++++++++++++++++ eh_basic_kow.asm | 8724 +++++++++++++++++++++++ ehbas.dat | 2064 ++++++ hello_world.bas | 10 +- main.cpp | 1028 ++- makefile | 49 + makefile.mingw | 58 + makeming.bat | 4 + microchess.asm | 1051 +++ microchess.bin | Bin 0 -> 65526 bytes microchess.cfg | 16 + microchess.dat | 114 + microchess.lst | 1033 +++ microchess.o | Bin 0 -> 11613 bytes numbers.bas | 10 + system.h | 3 + t_adc_bcd_01.65s | 196 +- t_adc_bcd_01.dat | 72 +- t_sbc_bcd_01.65s | 168 +- t_sbc_bcd_01.dat | 72 +- tall.bin | Bin 0 -> 65536 bytes tall.dat | 109 + tb.asm | 1484 ++++ tb.dat | 398 ++ tbe.dat | 423 ++ test_char_io_01.65s | 98 +- test_char_io_01.dat | 30 +- testall.asm | 1879 ++--- testall.dat | 390 +- testall.lst | 960 +++ testall.o | Bin 0 -> 11227 bytes testall_cl65.cfg | 24 + testbcd.dat | 138 +- tinybasic.dat | 1548 ++-- 64 files changed, 55712 insertions(+), 7201 deletions(-) create mode 100644 6502_func_test.bin create mode 100644 6502_func_test.dat create mode 100644 6502_func_test.lst create mode 100644 6502_functional_test.asm create mode 100644 BCDCodes.layout create mode 100644 Bin2Hex.dev create mode 100644 Bin2Hex.layout create mode 100644 MKBasic.layout create mode 100644 Makefile.win create mode 100644 bin2hex.c create mode 100644 eh_basic.asm create mode 100644 eh_basic_kow.asm create mode 100644 ehbas.dat create mode 100644 makefile create mode 100644 makefile.mingw create mode 100644 makeming.bat create mode 100644 microchess.asm create mode 100644 microchess.bin create mode 100644 microchess.cfg create mode 100644 microchess.dat create mode 100644 microchess.lst create mode 100644 microchess.o create mode 100644 numbers.bas create mode 100644 system.h create mode 100644 tall.bin create mode 100644 tall.dat create mode 100644 tb.asm create mode 100644 tb.dat create mode 100644 tbe.dat create mode 100644 testall.lst create mode 100644 testall.o create mode 100644 testall_cl65.cfg diff --git a/6502_func_test.bin b/6502_func_test.bin new file mode 100644 index 0000000000000000000000000000000000000000..f553e0cab79cab2ad5aab36601b786177d756456 GIT binary patch literal 65536 zcmeI3e{2-@mB43b*XuE?y^GBc^TXh@kPZo#It{_xsh0z;pf#ORN=llZ?jmwZdrp;9 zMAtjD62^wIoP}^o)FgsPJ#AOn%46Zky(?8gC2?i2*cDV8oq8ojPL>NeF5>Psx`yML zdVTMGf6VtgKdk2G~&nb~eG zH&>V|%{8&OnJ^p7q`5G*%lxdl+x(ol$9&ZMyt&uhX@1&t%+Hu;k%%?KLUBp(drV-x zv9HJ2*JSK_+SvC?V;|drfdRujnmBCyL&G;?Pj2lruKy%Ia40rl!hc50h?$254h_JD z!12ITJ zwPnsdiL&=od)w(sRDR_=oESCCl2NIuY-2TzV8HJqE8w-@Gj zeNcPkcbzeik721<&a(|3pj+ccE$-}KAY%a11d!vgO5Ay&!8H)=iF#MP6sy(8>Y4gT zRS2p=Fgz{<<3fP*FdbRJAv=c;uK1|e7+ z*T~vkEB3D(TUG1G#GO6K-Erp&$rEwsFO!wD^JLO_D(U=9()mi#c{XYFmb$RptX(l{ zapz!i%ml++vdhfGo#V;<=I*%j?W7ya+BLHhcm6SX!W@e`MXo>1_5Yl72Za80?td|v zF}vc61q`O7v-{$(8-2ZlRx4A#={8!SQ75X}l-_XeXQ;kgD*67wneXAQ;ee1Y> z1J^&)==KZ!BaN)S?TxH{hwC40bl(vAC%FDg-2a(I*5BVYBKZVhXuxUh&5rKZ75L4ydO*=RL~BG7AAnxnMR9AzxcQCaoMSg;{18q}?+i%V5z!Ho;`74)jTaPb2bL zo8N|h?e;CJ)b7Elu7&X1D)qv({CNcR9;)B-Kvl1S`aI9x2$3wF-F9~rw&wRZrA@bP zRq8V{H8|N$)OXiQw=4B3L>vEXrCz>t=~B;#^NA*D(#1`7fXP-c*~6n+5Vc80?J4Za zf9jdLn;_`mpaqvx+l%}zxIxtMN3^rB349kw-<^d=^LsiscKh9`;P!cNb2PUF;I>e@ zZ7b}_f7)QlN;6>mC>U>t{&97@(|sX$q|gIS_jU`G2u@^sGalfcJdOt+!ok<2Ak=~W&#oN;2 z;!JUin_-JvaEoI&t5>YiSPaiHoCALVWtWA@&{gn2Q_blrc+gddy@Fon*z#l0J_yPM z(8nlv_j>}!Hwr$06}=#{@`4mXAiSUvArM~BNG~?h0*W*=l8>YQhi%reo(cO@+_ZWo z-dYAX9lbqWZ>@sAgPC{01S*L#>C;Rg%InKa3^QWCoWd||H~}xr+dNF9jf?{}1>_1Fjb+1EQ_FSp|H9T9~Uz+$kD zc!c*bLIxr%f(QlH{14i!lhFKkSo2e&`6+C^oOuUKp!q11KFtK0|1mTVVTSD&vH731 zvEDTkh!SO@MadgyQrz>!)Ol>2)p88#DratD*^8j;RxEq=2g^@>rzuvhLgR(mA9uuF zY{la{g*e8*+$@6T|4a051^+hi$BBQBO?S3<# zkm@Bu-N4mbxq7u!FBR$}SMx=gAI}Ya zzb1F|D30kOACuSiYwco#k2a%rvA^rrmP>65YM1z%er<)+rct|;Yh};=ydyVQV%4)h z@yHF9S@rDCJaU7jRz3SukKACnRnLV9>$X^HuhYU|>vlWL15Qv*7T6TFTDO-AnH*)o zux_sqGTDoYry5Z4RMje;Dpkef^%aaFEIrQQXlfLf{t8wKTUl)81320|nm{oY3)@(1 z;pC6Dj5eSc>wUh#ET%c~qv_Ekim~M9lO}FGgmxE;t$&rB>cjSNw)Ml~fvtaaF+YWm zv#lQJp)5TR%J=*!owO3N_pMVfHi+bS1UO+zMc1ZpAV(x565kTW!E;d2u>| zTR(guu=b~6?b)^K2(JC`g}~mQhP~%%-234RfyF-!i_g`#_`??hn;*!{PdU|hAU8kf zRNsNz{G?NT2XgbXPW7Fiur3ETKY!S|9Nhf;R_k(b^YeyvIk@>Mo@zkFQ&p>Ys#Fz^ z*O&J;|A@Bvu$gl6k7%0@8!0#ch_?C1)#e}3Hvc%^d>Es<1U8>P&7En3=|n%vRr#}A zgoS*1LJPP;oQFMvATNcV;;!=$VFMWf41Vhq94wZ*6bj}yCEs6*xgzgLs{Cdm!b09k zfCb!21a2SxlLtP_yLh1s;=c(mG1X1VbsjftAj5(|MA$--2mUUr_z=eR-9(kka2v&p z;0Y>h#Dg=V$nba-gOkc#hO?YKvs^s&-zm(V?})whTc7 ~SE0-EeAQ3^I)09s8BY zq1_a{pa1aen%E1QQO)n3;-+6+sDJ-~Lz{Vk4Y{ESM&UY&x~SWSa6Z*vIG^e-oKN)^&ZqiwCoJ|vjJF5! zp3psPv1eiZmciX>v8P~^$y)~3u-Nl2%H)%uil^#U@l?Gko~l#DRp16#H1V2URk#5*QwUXw8(@`%P}Qi#R7GkrRh3#yRi+jb z>%^mKP-TfRk;V$3v69os57-wx z8iV{0$`4skWhrT_1RAS24R^r4xXdaIur0v-z#Z>rGH`~?z+@;p$Yee~K3~j==bP?} z=~1TpioU@23XlmUX2M`*CJd(5+*NMPT_xAtRrXSUI62CKxltBOt$bBx<*O1aU(8#8 z&+@X+_s`&(66B4tU}lsBGb>+}S^28W%2#y^Z%>31Ghr|@69!Xj?kczDu99o+m_45; zSiEz%#|c-!gux1!Fj#@+t}4*nRRx;6>i;Ke!^u$=%#E^OYUQgkD_@mZ`Kr8cM&w0V zFfYo2d6loqt9(^n<%@aoinj{R@eVl0*$as?ZT13dsuNzM!%f0e7yK<}X4oqTU2{Ow z7+KKlw5Dv~v)S+CX%0*&4fDA#Do-7wc^W-WOla1MJRALaz=vxNOeqb^^OdODSRPNK z*T(XIW`oG{Nq-(sb6`qnkYNWfT&)=9Qg$+B6;lC_?+TCswd@krSTU$~FmFFn&0AN? z+BNTc=gEytLvUTK=f=)GwI8#Vn|u3NYq`HXPvs)FuGT9Txw+bpUdyekC4ctL^J?I~ zM)8N2H+BoW#DVv%0wdrrsL!;8EhGv4f|^_G5;6RP&|~;5WJh|82j;B5g(!xI=y$-*HoKY3eku@-*PBo*KQufl6b!NVE zB%qd5;D(p4vYSEjRb}&qB-n_w!UPa_efn za*>;>{UgwF>uSlLog5g(!xI=y$-*HoDn-m?tvM7 z1ZQNp2XiTSHn6AJ^>mAPGTIJ*XR2l;;ns7hYC~nJJk6{oLssRk1@LkGyY8V}sxl?Q z!FybKxW1{#aA2i}<5s?Kcs73oD*dRa6fRL%>VE*eQP`$nu?=n=ETGz7l)(foe;Q#~ z?pg>1Uw03IZRHnOF@}X={9#qmfv{ld4=W4T!(!zhh0528%3osi?y&PwFZ)aiDVuH` zs=iisO>XzE5q9M+{ABnY_fX{;)(nPFh#rua5fKpV^nlV%3y9UiyP)nmQ7x=F(yNOt z)eAl!H&w+yhl+*m+tIc>$u+3@=U6owLplDyyr9UyVCxU;*=m8Y`gKtKy;yzx%&MU# ztp5C8n0BXST2p^5R{G2Ex153VgIml6E&8T33wBOmh;^x8gnz>bpyvUUUivdVt`x7~ zj{r<$4GaaQ&@5yOevgdGhgSu?r`gS&Unl)g$J74lu29;Wo};Feo;TV1*JmN)AA{#x z0@_=MWH5uuxokk$Czay8Z&cs&Cw^CaNBf3&+uN__-c0XhelXxYn3?txE1k?cjdQ;j z=Ke80_s*ddWBvrpePO71oIA6CvH2||0cOGH4hGvJ=ibTZ?$b+uoO`F3I~aT>dhX1E z*PvO*7-H_=zPEFpx%+g|Ps|;3f3+vnx|q9PDLuv9LHR}SjGnt+Df!=&a|iX-ZGKnZ z+iKL&Ge2{n&XWfs8PZy^aV3qE%+Xo#G9 zJDTH?X2EOFEMyEZcW__QKF{2JI_W3o4!Vw=q1MIR{YvR6<_^l` z;2Ax4zf$t|<__xEPQR;f?mm5J?x0;1@b>2J)5*NkkK+k%!{FD$;I9^1;G1klE|qJ} zwE+EGI+t8!!1Mid z3+i)=CR=}sAFt-pl}Svp9+KP#N$#>Fr@Rzy4Dw~b7t?I+?AbV(DyA#eWX3%OuC43S zmDFTf|7{1G=~S_~wuI@LC$(SasfWO=x!6+c0%iMTi~5~zRlk!h)2&6!SLAI@XDT_Y z@jj^WeyFkis^#u|dM|zvy!|de%v9=EZ6<^xet=qcW7hq6*1C&-@6B3Qw@4Fy045ms zeu!IxxXzz%bc}>mZ2nSZ0RN^liQc9y+1}hD9p%JD_$HSRr6*A+J&{5wMM0EO9z-eS3Z*CU zPc{>uUx`cx<~7=(kpP1VA>H(ywCY+xAR=L^EDBqv<-asK)P(Do?CEq;kolB`|4*e zeslU<72XcjBE88YeQ)7RaY4_>7UyjDAMpRSM6DA6B0vO)01+SpM1Tko0U|&IhyW2F z0z`la5CI}U1c(3;AOb{y2oM1xKm>>Y5g-CYfCvx)B0vO)01+SpM1Tko0U|&IhyW2F z0z`la5CI}U1c(3;AOb{y2oM1xKm>>Y5g-CYfCvx)B0vO)01+SpM1Tko0U|&IhyW2F z0z`la5CI}U1c(3;AOb{y2oM1xKm>>Y5g-CYfCvx)B0vO)01+SpM1Tko0U|&IhyW2F z0z`la5CI}U1c(3;AOb{y2oM1xKm>>Y5g-CYfCvx)B0vO)01+SpM1Tko0U|&IhyW2F z0z`la5CI}U1c(3;AOb{y2oM1xKm>>Y5g-CYfCvx)B0vO)01+SpM1Tko0U|&IhyW2F z0z`la5CI}U1c(3;AOb{y2oM1xKm>>Y5g-CYfCvx)B0vO)!2eqU&vk#T`y1W=3jl^i A`2YX_ literal 0 HcmV?d00001 diff --git a/6502_func_test.dat b/6502_func_test.dat new file mode 100644 index 0000000..cf63fc6 --- /dev/null +++ b/6502_func_test.dat @@ -0,0 +1,856 @@ +; Created with HEX2BIN (C) Marek Karcz 2016. All rights reserved. +ADDR +$0400 +ORG +$0000 +ORG +$0010 +$00 $00 $00 $c3 $82 $41 $00 $7f $00 $1f $71 $80 $0f $ff $7f $80 +$ff $0f $8f $8f $17 $02 $18 $02 $19 $02 $1a $02 $1b $02 $1f $01 +$03 $02 $04 $02 $05 $02 $06 $02 $0b $01 $4e $02 $4f $02 $50 $02 +$51 $02 $52 $02 $53 $02 $54 $02 $55 $02 $4a $02 $4b $02 $4c $02 +$4d $02 $03 $02 $04 $02 $04 $01 $05 $01 $00 $00 $00 $00 $00 $00 +ORG +$0200 +$00 $00 $00 $00 $00 $00 $00 $00 $29 $00 $60 $49 $00 $60 $09 $00 +$60 $69 $00 $60 $e9 $00 $60 $c3 $82 $41 $00 $7f $80 $80 $00 $02 +$86 $04 $82 $00 $87 $05 $83 $01 $61 $41 $20 $00 $e1 $c1 $a0 $80 +$81 $01 $80 $02 $81 $01 $80 $00 $01 $00 $01 $02 $81 $80 $81 $80 +$7f $80 $ff $00 $01 $00 $80 $80 $02 $00 $00 $1f $71 $80 $0f $ff +$7f $80 $ff $0f $8f $8f $00 $f1 $1f $00 $f0 $ff $ff $ff $ff $f0 +$f0 $0f $00 $ff $7f $80 $02 $80 $00 $80 $00 $00 $00 $00 $00 $00 +ORG +$0400 +$d8 $a2 $ff $9a $a9 $00 $8d $00 $02 $a2 $05 $4c $33 $04 $a0 $05 +$d0 $08 $4c $12 $04 $88 $88 $88 $88 $88 $88 $88 $88 $88 $88 $f0 +$17 $4c $21 $04 $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $f0 $de +$4c $30 $04 $d0 $f4 $4c $35 $04 $ad $00 $02 $c9 $00 $d0 $fe $a9 +$01 $8d $00 $02 $a0 $fe $88 $98 $aa $10 $08 $18 $69 $02 $ea $ea +$ea $ea $ea $ea $ea $ea $ea $ea $49 $7f $8d $e6 $04 $a9 $00 $4c +$e5 $04 $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $f0 $3e $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ea $ea $ea $ea $ea $f0 $08 $4c $6d $05 +$ea $ea $ea $ea $ea $ea $ea $ea $ea $ea $c0 $00 $f0 $03 $4c $46 +$04 $ad $00 $02 $c9 $01 $d0 $fe $a9 $02 $8d $00 $02 $c0 $01 $d0 +$03 $4c $91 $05 $a9 $00 $c9 $00 $d0 $fe $90 $fe $30 $fe $c9 $01 +$f0 $fe $b0 $fe $10 $fe $aa $e0 $00 $d0 $fe $90 $fe $30 $fe $e0 +$01 $f0 $fe $b0 $fe $10 $fe $a8 $c0 $00 $d0 $fe $90 $fe $30 $fe +$c0 $01 $f0 $fe $b0 $fe $10 $fe $ad $00 $02 $c9 $02 $d0 $fe $a9 +$03 $8d $00 $02 $a2 $ff $9a $a9 $55 $48 $a9 $aa $48 $cd $fe $01 +$d0 $fe $ba $8a $c9 $fd $d0 $fe $68 $c9 $aa $d0 $fe $68 $c9 $55 +$d0 $fe $cd $ff $01 $d0 $fe $ba $e0 $ff $d0 $fe $ad $00 $02 $c9 +$03 $d0 $fe $a9 $04 $8d $00 $02 $a9 $ff $48 $28 $10 $1a $50 $1b +$90 $1c $d0 $1d $30 $03 $4c $16 $06 $70 $03 $4c $1b $06 $b0 $03 +$4c $20 $06 $f0 $0f $4c $25 $06 $4c $28 $06 $4c $2b $06 $4c $2e +$06 $4c $31 $06 $08 $ba $e0 $fe $d0 $fe $68 $c9 $ff $d0 $fe $ba +$e0 $ff $d0 $fe $a9 $00 $48 $28 $30 $1a $70 $1b $b0 $1c $f0 $1d +$10 $03 $4c $52 $06 $50 $03 $4c $57 $06 $90 $03 $4c $5c $06 $d0 +$0f $4c $61 $06 $4c $64 $06 $4c $67 $06 $4c $6a $06 $4c $6d $06 +$08 $68 $c9 $30 $d0 $fe $a9 $02 $48 $28 $d0 $02 $f0 $03 $4c $7e +$06 $b0 $02 $90 $03 $4c $85 $06 $30 $02 $10 $03 $4c $8c $06 $70 +$02 $50 $03 $4c $93 $06 $a9 $01 $48 $28 $f0 $02 $d0 $03 $4c $9e +$06 $90 $02 $b0 $03 $4c $a5 $06 $30 $02 $10 $03 $4c $ac $06 $70 +$02 $50 $03 $4c $b3 $06 $a9 $80 $48 $28 $f0 $02 $d0 $03 $4c $be +$06 $b0 $02 $90 $03 $4c $c5 $06 $10 $02 $30 $03 $4c $cc $06 $70 +$02 $50 $03 $4c $d3 $06 $a9 $40 $48 $28 $f0 $02 $d0 $03 $4c $de +$06 $b0 $02 $90 $03 $4c $e5 $06 $30 $02 $10 $03 $4c $ec $06 $50 +$02 $70 $03 $4c $f3 $06 $a9 $fd $48 $28 $f0 $02 $d0 $03 $4c $fe +$06 $90 $02 $b0 $03 $4c $05 $07 $10 $02 $30 $03 $4c $0c $07 $50 +$02 $70 $03 $4c $13 $07 $a9 $fe $48 $28 $d0 $02 $f0 $03 $4c $1e +$07 $b0 $02 $90 $03 $4c $25 $07 $10 $02 $30 $03 $4c $2c $07 $50 +$02 $70 $03 $4c $33 $07 $a9 $7f $48 $28 $d0 $02 $f0 $03 $4c $3e +$07 $90 $02 $b0 $03 $4c $45 $07 $30 $02 $10 $03 $4c $4c $07 $50 +$02 $70 $03 $4c $53 $07 $a9 $bf $48 $28 $d0 $02 $f0 $03 $4c $5e +$07 $90 $02 $b0 $03 $4c $65 $07 $10 $02 $30 $03 $4c $6c $07 $70 +$02 $50 $03 $4c $73 $07 $ad $00 $02 $c9 $04 $d0 $fe $a9 $05 $8d +$00 $02 $a2 $55 $a0 $aa $a9 $ff $48 $a9 $01 $28 $48 $08 $c9 $01 +$d0 $fe $68 $48 $c9 $ff $d0 $fe $28 $a9 $00 $48 $a9 $00 $28 $48 +$08 $c9 $00 $d0 $fe $68 $48 $c9 $30 $d0 $fe $28 $a9 $ff $48 $a9 +$ff $28 $48 $08 $c9 $ff $d0 $fe $68 $48 $c9 $ff $d0 $fe $28 $a9 +$00 $48 $a9 $01 $28 $48 $08 $c9 $01 $d0 $fe $68 $48 $c9 $30 $d0 +$fe $28 $a9 $ff $48 $a9 $00 $28 $48 $08 $c9 $00 $d0 $fe $68 $48 +$c9 $ff $d0 $fe $28 $a9 $00 $48 $a9 $ff $28 $48 $08 $c9 $ff $d0 +$fe $68 $48 $c9 $30 $d0 $fe $28 $a9 $ff $48 $a9 $00 $28 $68 $08 +$c9 $ff $d0 $fe $68 $48 $c9 $fd $d0 $fe $28 $a9 $00 $48 $a9 $ff +$28 $68 $08 $c9 $00 $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 $a9 $ff +$48 $a9 $fe $28 $68 $08 $c9 $01 $d0 $fe $68 $48 $c9 $7d $d0 $fe +$28 $a9 $00 $48 $a9 $00 $28 $68 $08 $c9 $ff $d0 $fe $68 $48 $c9 +$b0 $d0 $fe $28 $a9 $ff $48 $a9 $ff $28 $68 $08 $c9 $00 $d0 $fe +$68 $48 $c9 $7f $d0 $fe $28 $a9 $00 $48 $a9 $fe $28 $68 $08 $c9 +$01 $d0 $fe $68 $48 $c9 $30 $d0 $fe $28 $e0 $55 $d0 $fe $c0 $aa +$d0 $fe $ad $00 $02 $c9 $05 $d0 $fe $a9 $06 $8d $00 $02 $a9 $00 +$48 $a9 $3c $28 $49 $c3 $08 $c9 $ff $d0 $fe $68 $48 $c9 $b0 $d0 +$fe $28 $a9 $00 $48 $a9 $c3 $28 $49 $c3 $08 $c9 $00 $d0 $fe $68 +$48 $c9 $32 $d0 $fe $28 $ad $00 $02 $c9 $06 $d0 $fe $a9 $07 $8d +$00 $02 $a2 $24 $a0 $42 $a9 $00 $48 $a9 $18 $28 $ea $08 $c9 $18 +$d0 $fe $68 $48 $c9 $30 $d0 $fe $28 $e0 $24 $d0 $fe $c0 $42 $d0 +$fe $a2 $db $a0 $bd $a9 $ff $48 $a9 $e7 $28 $ea $08 $c9 $e7 $d0 +$fe $68 $48 $c9 $ff $d0 $fe $28 $e0 $db $d0 $fe $c0 $bd $d0 $fe +$ad $00 $02 $c9 $07 $d0 $fe $a9 $08 $8d $00 $02 $a9 $00 $48 $28 +$a9 $46 $a2 $41 $a0 $52 $4c $c9 $36 $ea $ea $d0 $fe $e8 $e8 $f0 +$fe $10 $fe $90 $fe $50 $fe $c9 $ec $d0 $fe $e0 $42 $d0 $fe $c0 +$4f $d0 $fe $ca $c8 $c8 $c8 $49 $aa $4c $32 $09 $ea $ea $d0 $fe +$e8 $e8 $f0 $fe $30 $fe $90 $fe $50 $fe $c9 $46 $d0 $fe $e0 $41 +$d0 $fe $c0 $52 $d0 $fe $ad $00 $02 $c9 $08 $d0 $fe $a9 $09 $8d +$00 $02 $a9 $00 $48 $28 $a9 $49 $a2 $4e $a0 $44 $6c $f8 $36 $ea +$d0 $fe $88 $88 $08 $88 $88 $88 $28 $f0 $fe $10 $fe $90 $fe $50 +$fe $c9 $e3 $d0 $fe $e0 $4f $d0 $fe $c0 $3e $d0 $fe $ba $e0 $ff +$d0 $fe $ad $00 $02 $c9 $09 $d0 $fe $a9 $0a $8d $00 $02 $a9 $00 +$48 $28 $a9 $4a $a2 $53 $a0 $52 $20 $34 $37 $08 $88 $88 $88 $28 +$f0 $fe $10 $fe $90 $fe $50 $fe $c9 $e0 $d0 $fe $e0 $54 $d0 $fe +$c0 $4c $d0 $fe $ba $e0 $ff $d0 $fe $ad $00 $02 $c9 $0a $d0 $fe +$a9 $0b $8d $00 $02 $a9 $00 $48 $28 $a9 $42 $a2 $52 $a0 $4b $00 +$88 $08 $88 $88 $88 $c9 $e8 $d0 $fe $e0 $53 $d0 $fe $c0 $45 $d0 +$fe $68 $c9 $30 $d0 $fe $ba $e0 $ff $d0 $fe $ad $00 $02 $c9 $0b +$d0 $fe $a9 $0c $8d $00 $02 $a9 $ff $48 $28 $18 $08 $68 $48 $c9 +$fe $d0 $fe $28 $38 $08 $68 $48 $c9 $ff $d0 $fe $28 $58 $08 $68 +$48 $c9 $fb $d0 $fe $28 $78 $08 $68 $48 $c9 $ff $d0 $fe $28 $d8 +$08 $68 $48 $c9 $f7 $d0 $fe $28 $f8 $08 $68 $48 $c9 $ff $d0 $fe +$28 $b8 $08 $68 $48 $c9 $bf $d0 $fe $28 $a9 $00 $48 $28 $08 $68 +$48 $c9 $30 $d0 $fe $28 $38 $08 $68 $48 $c9 $31 $d0 $fe $28 $18 +$08 $68 $48 $c9 $30 $d0 $fe $28 $78 $08 $68 $48 $c9 $34 $d0 $fe +$28 $58 $08 $68 $48 $c9 $30 $d0 $fe $28 $f8 $08 $68 $48 $c9 $38 +$d0 $fe $28 $d8 $08 $68 $48 $c9 $30 $d0 $fe $28 $a9 $40 $48 $28 +$08 $68 $48 $c9 $70 $d0 $fe $28 $b8 $08 $68 $48 $c9 $30 $d0 $fe +$28 $ad $00 $02 $c9 $0c $d0 $fe $a9 $0d $8d $00 $02 $a2 $fe $a9 +$ff $48 $28 $e8 $08 $e0 $ff $d0 $fe $68 $48 $c9 $fd $d0 $fe $28 +$e8 $08 $e0 $00 $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $e8 $08 $e0 +$01 $d0 $fe $68 $48 $c9 $7d $d0 $fe $28 $ca $08 $e0 $00 $d0 $fe +$68 $48 $c9 $7f $d0 $fe $28 $ca $08 $e0 $ff $d0 $fe $68 $48 $c9 +$fd $d0 $fe $28 $ca $a9 $00 $48 $28 $e8 $08 $e0 $ff $d0 $fe $68 +$48 $c9 $b0 $d0 $fe $28 $e8 $08 $e0 $00 $d0 $fe $68 $48 $c9 $32 +$d0 $fe $28 $e8 $08 $e0 $01 $d0 $fe $68 $48 $c9 $30 $d0 $fe $28 +$ca $08 $e0 $00 $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 $ca $08 $e0 +$ff $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 $a0 $fe $a9 $ff $48 $28 +$c8 $08 $c0 $ff $d0 $fe $68 $48 $c9 $fd $d0 $fe $28 $c8 $08 $c0 +$00 $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $c8 $08 $c0 $01 $d0 $fe +$68 $48 $c9 $7d $d0 $fe $28 $88 $08 $c0 $00 $d0 $fe $68 $48 $c9 +$7f $d0 $fe $28 $88 $08 $c0 $ff $d0 $fe $68 $48 $c9 $fd $d0 $fe +$28 $88 $a9 $00 $48 $28 $c8 $08 $c0 $ff $d0 $fe $68 $48 $c9 $b0 +$d0 $fe $28 $c8 $08 $c0 $00 $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 +$c8 $08 $c0 $01 $d0 $fe $68 $48 $c9 $30 $d0 $fe $28 $88 $08 $c0 +$00 $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 $88 $08 $c0 $ff $d0 $fe +$68 $48 $c9 $b0 $d0 $fe $28 $a2 $ff $a9 $ff $48 $28 $8a $08 $c9 +$ff $d0 $fe $68 $48 $c9 $fd $d0 $fe $28 $08 $e8 $28 $8a $08 $c9 +$00 $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $08 $e8 $28 $8a $08 $c9 +$01 $d0 $fe $68 $48 $c9 $7d $d0 $fe $28 $a9 $00 $48 $28 $8a $08 +$c9 $01 $d0 $fe $68 $48 $c9 $30 $d0 $fe $28 $08 $ca $28 $8a $08 +$c9 $00 $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 $08 $ca $28 $8a $08 +$c9 $ff $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 $a0 $ff $a9 $ff $48 +$28 $98 $08 $c9 $ff $d0 $fe $68 $48 $c9 $fd $d0 $fe $28 $08 $c8 +$28 $98 $08 $c9 $00 $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $08 $c8 +$28 $98 $08 $c9 $01 $d0 $fe $68 $48 $c9 $7d $d0 $fe $28 $a9 $00 +$48 $28 $98 $08 $c9 $01 $d0 $fe $68 $48 $c9 $30 $d0 $fe $28 $08 +$88 $28 $98 $08 $c9 $00 $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 $08 +$88 $28 $98 $08 $c9 $ff $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 $a9 +$ff $48 $a2 $ff $8a $28 $a8 $08 $c0 $ff $d0 $fe $68 $48 $c9 $fd +$d0 $fe $28 $08 $e8 $8a $28 $a8 $08 $c0 $00 $d0 $fe $68 $48 $c9 +$7f $d0 $fe $28 $08 $e8 $8a $28 $a8 $08 $c0 $01 $d0 $fe $68 $48 +$c9 $7d $d0 $fe $28 $a9 $00 $48 $a9 $00 $8a $28 $a8 $08 $c0 $01 +$d0 $fe $68 $48 $c9 $30 $d0 $fe $28 $08 $ca $8a $28 $a8 $08 $c0 +$00 $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 $08 $ca $8a $28 $a8 $08 +$c0 $ff $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 $a9 $ff $48 $a0 $ff +$98 $28 $aa $08 $e0 $ff $d0 $fe $68 $48 $c9 $fd $d0 $fe $28 $08 +$c8 $98 $28 $aa $08 $e0 $00 $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 +$08 $c8 $98 $28 $aa $08 $e0 $01 $d0 $fe $68 $48 $c9 $7d $d0 $fe +$28 $a9 $00 $48 $a9 $00 $98 $28 $aa $08 $e0 $01 $d0 $fe $68 $48 +$c9 $30 $d0 $fe $28 $08 $88 $98 $28 $aa $08 $e0 $00 $d0 $fe $68 +$48 $c9 $32 $d0 $fe $28 $08 $88 $98 $28 $aa $08 $e0 $ff $d0 $fe +$68 $48 $c9 $b0 $d0 $fe $28 $ad $00 $02 $c9 $0d $d0 $fe $a9 $0e +$8d $00 $02 $a2 $01 $a9 $ff $48 $28 $9a $08 $ad $01 $01 $c9 $ff +$d0 $fe $a9 $00 $48 $28 $9a $08 $ad $01 $01 $c9 $30 $d0 $fe $ca +$a9 $ff $48 $28 $9a $08 $ad $00 $01 $c9 $ff $d0 $fe $a9 $00 $48 +$28 $9a $08 $ad $00 $01 $c9 $30 $d0 $fe $ca $a9 $ff $48 $28 $9a +$08 $ad $ff $01 $c9 $ff $d0 $fe $a9 $00 $48 $28 $9a $08 $ad $ff +$01 $c9 $30 $a2 $01 $9a $a9 $ff $48 $28 $ba $08 $e0 $01 $d0 $fe +$ad $01 $01 $c9 $7d $d0 $fe $a9 $ff $48 $28 $ba $08 $e0 $00 $d0 +$fe $ad $00 $01 $c9 $7f $d0 $fe $a9 $ff $48 $28 $ba $08 $e0 $ff +$d0 $fe $ad $ff $01 $c9 $fd $d0 $fe $a2 $01 $9a $a9 $00 $48 $28 +$ba $08 $e0 $01 $d0 $fe $ad $01 $01 $c9 $30 $d0 $fe $a9 $00 $48 +$28 $ba $08 $e0 $00 $d0 $fe $ad $00 $01 $c9 $32 $d0 $fe $a9 $00 +$48 $28 $ba $08 $e0 $ff $d0 $fe $ad $ff $01 $c9 $b0 $d0 $fe $68 +$ad $00 $02 $c9 $0e $d0 $fe $a9 $0f $8d $00 $02 $a0 $03 $a9 $00 +$48 $28 $b6 $13 $08 $8a $49 $c3 $28 $99 $03 $02 $08 $49 $c3 $d9 +$17 $02 $d0 $fe $68 $49 $30 $d9 $1c $02 $d0 $fe $88 $10 $df $a0 +$03 $a9 $ff $48 $28 $b6 $13 $08 $8a $49 $c3 $28 $99 $03 $02 $08 +$49 $c3 $d9 $17 $02 $d0 $fe $68 $49 $7d $d9 $1c $02 $d0 $fe $88 +$10 $df $a0 $03 $a9 $00 $48 $28 $be $17 $02 $08 $8a $49 $c3 $aa +$28 $96 $0c $08 $49 $c3 $d9 $13 $00 $d0 $fe $68 $49 $30 $d9 $1c +$02 $d0 $fe $88 $10 $de $a0 $03 $a9 $ff $48 $28 $be $17 $02 $08 +$8a $49 $c3 $aa $28 $96 $0c $08 $49 $c3 $d9 $13 $00 $d0 $fe $68 +$49 $7d $d9 $1c $02 $d0 $fe $88 $10 $de $a0 $03 $a2 $00 $b9 $0c +$00 $49 $c3 $d9 $13 $00 $d0 $fe $96 $0c $b9 $03 $02 $49 $c3 $d9 +$17 $02 $d0 $fe $8a $99 $03 $02 $88 $10 $e3 $ad $00 $02 $c9 $0f +$d0 $fe $a9 $10 $8d $00 $02 $a0 $fd $b6 $19 $8a $99 $09 $01 $88 +$c0 $fa $b0 $f5 $a0 $fd $be $1d $01 $96 $12 $88 $c0 $fa $b0 $f6 +$a0 $03 $a2 $00 $b9 $0c $00 $d9 $13 $00 $d0 $fe $96 $0c $b9 $03 +$02 $d9 $17 $02 $d0 $fe $8a $99 $03 $02 $88 $10 $e7 $ad $00 $02 +$c9 $10 $d0 $fe $a9 $11 $8d $00 $02 $a2 $03 $a9 $00 $48 $28 $b4 +$13 $08 $98 $49 $c3 $28 $9d $03 $02 $08 $49 $c3 $dd $17 $02 $d0 +$fe $68 $49 $30 $dd $1c $02 $d0 $fe $ca $10 $df $a2 $03 $a9 $ff +$48 $28 $b4 $13 $08 $98 $49 $c3 $28 $9d $03 $02 $08 $49 $c3 $dd +$17 $02 $d0 $fe $68 $49 $7d $dd $1c $02 $d0 $fe $ca $10 $df $a2 +$03 $a9 $00 $48 $28 $bc $17 $02 $08 $98 $49 $c3 $a8 $28 $94 $0c +$08 $49 $c3 $d5 $13 $d0 $fe $68 $49 $30 $dd $1c $02 $d0 $fe $ca +$10 $df $a2 $03 $a9 $ff $48 $28 $bc $17 $02 $08 $98 $49 $c3 $a8 +$28 $94 $0c $08 $49 $c3 $d5 $13 $d0 $fe $68 $49 $7d $dd $1c $02 +$d0 $fe $ca $10 $df $a2 $03 $a0 $00 $b5 $0c $49 $c3 $d5 $13 $d0 +$fe $94 $0c $bd $03 $02 $49 $c3 $dd $17 $02 $d0 $fe $8a $9d $03 +$02 $ca $10 $e5 $ad $00 $02 $c9 $11 $d0 $fe $a9 $12 $8d $00 $02 +$a2 $fd $b4 $19 $98 $9d $09 $01 $ca $e0 $fa $b0 $f5 $a2 $fd $bc +$1d $01 $94 $12 $ca $e0 $fa $b0 $f6 $a2 $03 $a0 $00 $b5 $0c $d5 +$13 $d0 $fe $94 $0c $bd $03 $02 $dd $17 $02 $d0 $fe $8a $9d $03 +$02 $ca $10 $e9 $ad $00 $02 $c9 $12 $d0 $fe $a9 $13 $8d $00 $02 +$a9 $00 $48 $28 $a6 $13 $08 $8a $49 $c3 $aa $28 $8e $03 $02 $08 +$49 $c3 $aa $e0 $c3 $d0 $fe $68 $49 $30 $cd $1c $02 $d0 $fe $a9 +$00 $48 $28 $a6 $14 $08 $8a $49 $c3 $aa $28 $8e $04 $02 $08 $49 +$c3 $aa $e0 $82 $d0 $fe $68 $49 $30 $cd $1d $02 $d0 $fe $a9 $00 +$48 $28 $a6 $15 $08 $8a $49 $c3 $aa $28 $8e $05 $02 $08 $49 $c3 +$aa $e0 $41 $d0 $fe $68 $49 $30 $cd $1e $02 $d0 $fe $a9 $00 $48 +$28 $a6 $16 $08 $8a $49 $c3 $aa $28 $8e $06 $02 $08 $49 $c3 $aa +$e0 $00 $d0 $fe $68 $49 $30 $cd $1f $02 $d0 $fe $a9 $ff $48 $28 +$a6 $13 $08 $8a $49 $c3 $aa $28 $8e $03 $02 $08 $49 $c3 $aa $e0 +$c3 $d0 $fe $68 $49 $7d $cd $1c $02 $d0 $fe $a9 $ff $48 $28 $a6 +$14 $08 $8a $49 $c3 $aa $28 $8e $04 $02 $08 $49 $c3 $aa $e0 $82 +$d0 $fe $68 $49 $7d $cd $1d $02 $d0 $fe $a9 $ff $48 $28 $a6 $15 +$08 $8a $49 $c3 $aa $28 $8e $05 $02 $08 $49 $c3 $aa $e0 $41 $d0 +$fe $68 $49 $7d $cd $1e $02 $d0 $fe $a9 $ff $48 $28 $a6 $16 $08 +$8a $49 $c3 $aa $28 $8e $06 $02 $08 $49 $c3 $aa $e0 $00 $d0 $fe +$68 $49 $7d $cd $1f $02 $d0 $fe $a9 $00 $48 $28 $ae $17 $02 $08 +$8a $49 $c3 $aa $28 $86 $0c $08 $49 $c3 $c5 $13 $d0 $fe $68 $49 +$30 $cd $1c $02 $d0 $fe $a9 $00 $48 $28 $ae $18 $02 $08 $8a $49 +$c3 $aa $28 $86 $0d $08 $49 $c3 $c5 $14 $d0 $fe $68 $49 $30 $cd +$1d $02 $d0 $fe $a9 $00 $48 $28 $ae $19 $02 $08 $8a $49 $c3 $aa +$28 $86 $0e $08 $49 $c3 $c5 $15 $d0 $fe $68 $49 $30 $cd $1e $02 +$d0 $fe $a9 $00 $48 $28 $ae $1a $02 $08 $8a $49 $c3 $aa $28 $86 +$0f $08 $49 $c3 $c5 $16 $d0 $fe $68 $49 $30 $cd $1f $02 $d0 $fe +$a9 $ff $48 $28 $ae $17 $02 $08 $8a $49 $c3 $aa $28 $86 $0c $08 +$49 $c3 $aa $e4 $13 $d0 $fe $68 $49 $7d $cd $1c $02 $d0 $fe $a9 +$ff $48 $28 $ae $18 $02 $08 $8a $49 $c3 $aa $28 $86 $0d $08 $49 +$c3 $aa $e4 $14 $d0 $fe $68 $49 $7d $cd $1d $02 $d0 $fe $a9 $ff +$48 $28 $ae $19 $02 $08 $8a $49 $c3 $aa $28 $86 $0e $08 $49 $c3 +$aa $e4 $15 $d0 $fe $68 $49 $7d $cd $1e $02 $d0 $fe $a9 $ff $48 +$28 $ae $1a $02 $08 $8a $49 $c3 $aa $28 $86 $0f $08 $49 $c3 $aa +$e4 $16 $d0 $fe $68 $49 $7d $cd $1f $02 $d0 $fe $a9 $00 $48 $28 +$a2 $c3 $08 $ec $17 $02 $d0 $fe $68 $49 $30 $cd $1c $02 $d0 $fe +$a9 $00 $48 $28 $a2 $82 $08 $ec $18 $02 $d0 $fe $68 $49 $30 $cd +$1d $02 $d0 $fe $a9 $00 $48 $28 $a2 $41 $08 $ec $19 $02 $d0 $fe +$68 $49 $30 $cd $1e $02 $d0 $fe $a9 $00 $48 $28 $a2 $00 $08 $ec +$1a $02 $d0 $fe $68 $49 $30 $cd $1f $02 $d0 $fe $a9 $ff $48 $28 +$a2 $c3 $08 $ec $17 $02 $d0 $fe $68 $49 $7d $cd $1c $02 $d0 $fe +$a9 $ff $48 $28 $a2 $82 $08 $ec $18 $02 $d0 $fe $68 $49 $7d $cd +$1d $02 $d0 $fe $a9 $ff $48 $28 $a2 $41 $08 $ec $19 $02 $d0 $fe +$68 $49 $7d $cd $1e $02 $d0 $fe $a9 $ff $48 $28 $a2 $00 $08 $ec +$1a $02 $d0 $fe $68 $49 $7d $cd $1f $02 $d0 $fe $a2 $00 $a5 $0c +$49 $c3 $c5 $13 $d0 $fe $86 $0c $ad $03 $02 $49 $c3 $cd $17 $02 +$d0 $fe $8e $03 $02 $a5 $0d $49 $c3 $c5 $14 $d0 $fe $86 $0d $ad +$04 $02 $49 $c3 $cd $18 $02 $d0 $fe $8e $04 $02 $a5 $0e $49 $c3 +$c5 $15 $d0 $fe $86 $0e $ad $05 $02 $49 $c3 $cd $19 $02 $d0 $fe +$8e $05 $02 $a5 $0f $49 $c3 $c5 $16 $d0 $fe $86 $0f $ad $06 $02 +$49 $c3 $cd $1a $02 $d0 $fe $8e $06 $02 $ad $00 $02 $c9 $13 $d0 +$fe $a9 $14 $8d $00 $02 $a9 $00 $48 $28 $a4 $13 $08 $98 $49 $c3 +$a8 $28 $8c $03 $02 $08 $49 $c3 $a8 $c0 $c3 $d0 $fe $68 $49 $30 +$cd $1c $02 $d0 $fe $a9 $00 $48 $28 $a4 $14 $08 $98 $49 $c3 $a8 +$28 $8c $04 $02 $08 $49 $c3 $a8 $c0 $82 $d0 $fe $68 $49 $30 $cd +$1d $02 $d0 $fe $a9 $00 $48 $28 $a4 $15 $08 $98 $49 $c3 $a8 $28 +$8c $05 $02 $08 $49 $c3 $a8 $c0 $41 $d0 $fe $68 $49 $30 $cd $1e +$02 $d0 $fe $a9 $00 $48 $28 $a4 $16 $08 $98 $49 $c3 $a8 $28 $8c +$06 $02 $08 $49 $c3 $a8 $c0 $00 $d0 $fe $68 $49 $30 $cd $1f $02 +$d0 $fe $a9 $ff $48 $28 $a4 $13 $08 $98 $49 $c3 $a8 $28 $8c $03 +$02 $08 $49 $c3 $a8 $c0 $c3 $d0 $fe $68 $49 $7d $cd $1c $02 $d0 +$fe $a9 $ff $48 $28 $a4 $14 $08 $98 $49 $c3 $a8 $28 $8c $04 $02 +$08 $49 $c3 $a8 $c0 $82 $d0 $fe $68 $49 $7d $cd $1d $02 $d0 $fe +$a9 $ff $48 $28 $a4 $15 $08 $98 $49 $c3 $a8 $28 $8c $05 $02 $08 +$49 $c3 $a8 $c0 $41 $d0 $fe $68 $49 $7d $cd $1e $02 $d0 $fe $a9 +$ff $48 $28 $a4 $16 $08 $98 $49 $c3 $a8 $28 $8c $06 $02 $08 $49 +$c3 $a8 $c0 $00 $d0 $fe $68 $49 $7d $cd $1f $02 $d0 $fe $a9 $00 +$48 $28 $ac $17 $02 $08 $98 $49 $c3 $a8 $28 $84 $0c $08 $49 $c3 +$a8 $c4 $13 $d0 $fe $68 $49 $30 $cd $1c $02 $d0 $fe $a9 $00 $48 +$28 $ac $18 $02 $08 $98 $49 $c3 $a8 $28 $84 $0d $08 $49 $c3 $a8 +$c4 $14 $d0 $fe $68 $49 $30 $cd $1d $02 $d0 $fe $a9 $00 $48 $28 +$ac $19 $02 $08 $98 $49 $c3 $a8 $28 $84 $0e $08 $49 $c3 $a8 $c4 +$15 $d0 $fe $68 $49 $30 $cd $1e $02 $d0 $fe $a9 $00 $48 $28 $ac +$1a $02 $08 $98 $49 $c3 $a8 $28 $84 $0f $08 $49 $c3 $a8 $c4 $16 +$d0 $fe $68 $49 $30 $cd $1f $02 $d0 $fe $a9 $ff $48 $28 $ac $17 +$02 $08 $98 $49 $c3 $a8 $28 $84 $0c $08 $49 $c3 $a8 $c5 $13 $d0 +$fe $68 $49 $7d $cd $1c $02 $d0 $fe $a9 $ff $48 $28 $ac $18 $02 +$08 $98 $49 $c3 $a8 $28 $84 $0d $08 $49 $c3 $a8 $c5 $14 $d0 $fe +$68 $49 $7d $cd $1d $02 $d0 $fe $a9 $ff $48 $28 $ac $19 $02 $08 +$98 $49 $c3 $a8 $28 $84 $0e $08 $49 $c3 $a8 $c5 $15 $d0 $fe $68 +$49 $7d $cd $1e $02 $d0 $fe $a9 $ff $48 $28 $ac $1a $02 $08 $98 +$49 $c3 $a8 $28 $84 $0f $08 $49 $c3 $a8 $c5 $16 $d0 $fe $68 $49 +$7d $cd $1f $02 $d0 $fe $a9 $00 $48 $28 $a0 $c3 $08 $cc $17 $02 +$d0 $fe $68 $49 $30 $cd $1c $02 $d0 $fe $a9 $00 $48 $28 $a0 $82 +$08 $cc $18 $02 $d0 $fe $68 $49 $30 $cd $1d $02 $d0 $fe $a9 $00 +$48 $28 $a0 $41 $08 $cc $19 $02 $d0 $fe $68 $49 $30 $cd $1e $02 +$d0 $fe $a9 $00 $48 $28 $a0 $00 $08 $cc $1a $02 $d0 $fe $68 $49 +$30 $cd $1f $02 $d0 $fe $a9 $ff $48 $28 $a0 $c3 $08 $cc $17 $02 +$d0 $fe $68 $49 $7d $cd $1c $02 $d0 $fe $a9 $ff $48 $28 $a0 $82 +$08 $cc $18 $02 $d0 $fe $68 $49 $7d $cd $1d $02 $d0 $fe $a9 $ff +$48 $28 $a0 $41 $08 $cc $19 $02 $d0 $fe $68 $49 $7d $cd $1e $02 +$d0 $fe $a9 $ff $48 $28 $a0 $00 $08 $cc $1a $02 $d0 $fe $68 $49 +$7d $cd $1f $02 $d0 $fe $a0 $00 $a5 $0c $49 $c3 $c5 $13 $d0 $fe +$84 $0c $ad $03 $02 $49 $c3 $cd $17 $02 $d0 $fe $8c $03 $02 $a5 +$0d $49 $c3 $c5 $14 $d0 $fe $84 $0d $ad $04 $02 $49 $c3 $cd $18 +$02 $d0 $fe $8c $04 $02 $a5 $0e $49 $c3 $c5 $15 $d0 $fe $84 $0e +$ad $05 $02 $49 $c3 $cd $19 $02 $d0 $fe $8c $05 $02 $a5 $0f $49 +$c3 $c5 $16 $d0 $fe $84 $0f $ad $06 $02 $49 $c3 $cd $1a $02 $d0 +$fe $8c $06 $02 $ad $00 $02 $c9 $14 $d0 $fe $a9 $15 $8d $00 $02 +$a2 $03 $a9 $00 $48 $28 $b5 $13 $08 $49 $c3 $28 $9d $03 $02 $08 +$49 $c3 $dd $17 $02 $d0 $fe $68 $49 $30 $dd $1c $02 $d0 $fe $ca +$10 $e0 $a2 $03 $a9 $ff $48 $28 $b5 $13 $08 $49 $c3 $28 $9d $03 +$02 $08 $49 $c3 $dd $17 $02 $d0 $fe $68 $49 $7d $dd $1c $02 $d0 +$fe $ca $10 $e0 $a2 $03 $a9 $00 $48 $28 $bd $17 $02 $08 $49 $c3 +$28 $95 $0c $08 $49 $c3 $d5 $13 $d0 $fe $68 $49 $30 $dd $1c $02 +$d0 $fe $ca $10 $e1 $a2 $03 $a9 $ff $48 $28 $bd $17 $02 $08 $49 +$c3 $28 $95 $0c $08 $49 $c3 $d5 $13 $d0 $fe $68 $49 $7d $dd $1c +$02 $d0 $fe $ca $10 $e1 $a2 $03 $a0 $00 $b5 $0c $49 $c3 $d5 $13 +$d0 $fe $94 $0c $bd $03 $02 $49 $c3 $dd $17 $02 $d0 $fe $8a $9d +$03 $02 $ca $10 $e5 $ad $00 $02 $c9 $15 $d0 $fe $a9 $16 $8d $00 +$02 $a0 $03 $a9 $00 $48 $28 $b1 $24 $08 $49 $c3 $28 $99 $03 $02 +$08 $49 $c3 $d9 $17 $02 $d0 $fe $68 $49 $30 $d9 $1c $02 $d0 $fe +$88 $10 $e0 $a0 $03 $a9 $ff $48 $28 $b1 $24 $08 $49 $c3 $28 $99 +$03 $02 $08 $49 $c3 $d9 $17 $02 $d0 $fe $68 $49 $7d $d9 $1c $02 +$d0 $fe $88 $10 $e0 $a0 $03 $a2 $00 $b9 $03 $02 $49 $c3 $d9 $17 +$02 $d0 $fe $8a $99 $03 $02 $88 $10 $ef $a0 $03 $a9 $00 $48 $28 +$b9 $17 $02 $08 $49 $c3 $28 $91 $30 $08 $49 $c3 $d1 $24 $d0 $fe +$68 $49 $30 $d9 $1c $02 $d0 $fe $88 $10 $e1 $a0 $03 $a9 $ff $48 +$28 $b9 $17 $02 $08 $49 $c3 $28 $91 $30 $08 $49 $c3 $d1 $24 $d0 +$fe $68 $49 $7d $d9 $1c $02 $d0 $fe $88 $10 $e1 $a0 $03 $a2 $00 +$b9 $03 $02 $49 $c3 $d9 $17 $02 $d0 $fe $8a $99 $03 $02 $88 $10 +$ef $a2 $06 $a0 $03 $a9 $00 $48 $28 $a1 $24 $08 $49 $c3 $28 $81 +$30 $08 $49 $c3 $d9 $17 $02 $d0 $fe $68 $49 $30 $d9 $1c $02 $d0 +$fe $ca $ca $88 $10 $df $a2 $06 $a0 $03 $a9 $ff $48 $28 $a1 $24 +$08 $49 $c3 $28 $81 $30 $08 $49 $c3 $d9 $17 $02 $d0 $fe $68 $49 +$7d $d9 $1c $02 $d0 $fe $ca $ca $88 $10 $df $a0 $03 $a2 $00 $b9 +$03 $02 $49 $c3 $d9 $17 $02 $d0 $fe $8a $99 $03 $02 $88 $10 $ef +$ad $00 $02 $c9 $16 $d0 $fe $a9 $17 $8d $00 $02 $a2 $fd $b5 $19 +$9d $09 $01 $ca $e0 $fa $b0 $f6 $a2 $fd $bd $1d $01 $95 $12 $ca +$e0 $fa $b0 $f6 $a2 $03 $a0 $00 $b5 $0c $d5 $13 $d0 $fe $94 $0c +$bd $03 $02 $dd $17 $02 $d0 $fe $8a $9d $03 $02 $ca $10 $e9 $a0 +$fb $a2 $fe $a1 $2c $99 $0b $01 $ca $ca $88 $c0 $f8 $b0 $f4 $a0 +$03 $a2 $00 $b9 $03 $02 $d9 $17 $02 $d0 $fe $8a $99 $03 $02 $88 +$10 $f1 $a0 $fb $b9 $1f $01 $91 $38 $88 $c0 $f8 $b0 $f6 $a0 $03 +$a2 $00 $b9 $03 $02 $d9 $17 $02 $d0 $fe $8a $99 $03 $02 $88 $10 +$f1 $a0 $fb $a2 $fe $b1 $2e $81 $38 $ca $ca $88 $c0 $f8 $b0 $f5 +$a0 $03 $a2 $00 $b9 $03 $02 $d9 $17 $02 $d0 $fe $8a $99 $03 $02 +$88 $10 $f1 $ad $00 $02 $c9 $17 $d0 $fe $a9 $18 $8d $00 $02 $a9 +$00 $48 $28 $a5 $13 $08 $49 $c3 $28 $8d $03 $02 $08 $49 $c3 $c9 +$c3 $d0 $fe $68 $49 $30 $cd $1c $02 $d0 $fe $a9 $00 $48 $28 $a5 +$14 $08 $49 $c3 $28 $8d $04 $02 $08 $49 $c3 $c9 $82 $d0 $fe $68 +$49 $30 $cd $1d $02 $d0 $fe $a9 $00 $48 $28 $a5 $15 $08 $49 $c3 +$28 $8d $05 $02 $08 $49 $c3 $c9 $41 $d0 $fe $68 $49 $30 $cd $1e +$02 $d0 $fe $a9 $00 $48 $28 $a5 $16 $08 $49 $c3 $28 $8d $06 $02 +$08 $49 $c3 $c9 $00 $d0 $fe $68 $49 $30 $cd $1f $02 $d0 $fe $a9 +$ff $48 $28 $a5 $13 $08 $49 $c3 $28 $8d $03 $02 $08 $49 $c3 $c9 +$c3 $d0 $fe $68 $49 $7d $cd $1c $02 $d0 $fe $a9 $ff $48 $28 $a5 +$14 $08 $49 $c3 $28 $8d $04 $02 $08 $49 $c3 $c9 $82 $d0 $fe $68 +$49 $7d $cd $1d $02 $d0 $fe $a9 $ff $48 $28 $a5 $15 $08 $49 $c3 +$28 $8d $05 $02 $08 $49 $c3 $c9 $41 $d0 $fe $68 $49 $7d $cd $1e +$02 $d0 $fe $a9 $ff $48 $28 $a5 $16 $08 $49 $c3 $28 $8d $06 $02 +$08 $49 $c3 $c9 $00 $d0 $fe $68 $49 $7d $cd $1f $02 $d0 $fe $a9 +$00 $48 $28 $ad $17 $02 $08 $49 $c3 $28 $85 $0c $08 $49 $c3 $c5 +$13 $d0 $fe $68 $49 $30 $cd $1c $02 $d0 $fe $a9 $00 $48 $28 $ad +$18 $02 $08 $49 $c3 $28 $85 $0d $08 $49 $c3 $c5 $14 $d0 $fe $68 +$49 $30 $cd $1d $02 $d0 $fe $a9 $00 $48 $28 $ad $19 $02 $08 $49 +$c3 $28 $85 $0e $08 $49 $c3 $c5 $15 $d0 $fe $68 $49 $30 $cd $1e +$02 $d0 $fe $a9 $00 $48 $28 $ad $1a $02 $08 $49 $c3 $28 $85 $0f +$08 $49 $c3 $c5 $16 $d0 $fe $68 $49 $30 $cd $1f $02 $d0 $fe $a9 +$ff $48 $28 $ad $17 $02 $08 $49 $c3 $28 $85 $0c $08 $49 $c3 $c5 +$13 $d0 $fe $68 $49 $7d $cd $1c $02 $d0 $fe $a9 $ff $48 $28 $ad +$18 $02 $08 $49 $c3 $28 $85 $0d $08 $49 $c3 $c5 $14 $d0 $fe $68 +$49 $7d $cd $1d $02 $d0 $fe $a9 $ff $48 $28 $ad $19 $02 $08 $49 +$c3 $28 $85 $0e $08 $49 $c3 $c5 $15 $d0 $fe $68 $49 $7d $cd $1e +$02 $d0 $fe $a9 $ff $48 $28 $ad $1a $02 $08 $49 $c3 $28 $85 $0f +$08 $49 $c3 $c5 $16 $d0 $fe $68 $49 $7d $cd $1f $02 $d0 $fe $a9 +$00 $48 $28 $a9 $c3 $08 $cd $17 $02 $d0 $fe $68 $49 $30 $cd $1c +$02 $d0 $fe $a9 $00 $48 $28 $a9 $82 $08 $cd $18 $02 $d0 $fe $68 +$49 $30 $cd $1d $02 $d0 $fe $a9 $00 $48 $28 $a9 $41 $08 $cd $19 +$02 $d0 $fe $68 $49 $30 $cd $1e $02 $d0 $fe $a9 $00 $48 $28 $a9 +$00 $08 $cd $1a $02 $d0 $fe $68 $49 $30 $cd $1f $02 $d0 $fe $a9 +$ff $48 $28 $a9 $c3 $08 $cd $17 $02 $d0 $fe $68 $49 $7d $cd $1c +$02 $d0 $fe $a9 $ff $48 $28 $a9 $82 $08 $cd $18 $02 $d0 $fe $68 +$49 $7d $cd $1d $02 $d0 $fe $a9 $ff $48 $28 $a9 $41 $08 $cd $19 +$02 $d0 $fe $68 $49 $7d $cd $1e $02 $d0 $fe $a9 $ff $48 $28 $a9 +$00 $08 $cd $1a $02 $d0 $fe $68 $49 $7d $cd $1f $02 $d0 $fe $a2 +$00 $a5 $0c $49 $c3 $c5 $13 $d0 $fe $86 $0c $ad $03 $02 $49 $c3 +$cd $17 $02 $d0 $fe $8e $03 $02 $a5 $0d $49 $c3 $c5 $14 $d0 $fe +$86 $0d $ad $04 $02 $49 $c3 $cd $18 $02 $d0 $fe $8e $04 $02 $a5 +$0e $49 $c3 $c5 $15 $d0 $fe $86 $0e $ad $05 $02 $49 $c3 $cd $19 +$02 $d0 $fe $8e $05 $02 $a5 $0f $49 $c3 $c5 $16 $d0 $fe $86 $0f +$ad $06 $02 $49 $c3 $cd $1a $02 $d0 $fe $8e $06 $02 $ad $00 $02 +$c9 $18 $d0 $fe $a9 $19 $8d $00 $02 $a9 $00 $48 $a9 $ff $28 $24 +$16 $08 $c9 $ff $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 $a9 $00 $48 +$a9 $01 $28 $24 $15 $08 $c9 $01 $d0 $fe $68 $48 $c9 $70 $d0 $fe +$28 $a9 $00 $48 $a9 $01 $28 $24 $14 $08 $c9 $01 $d0 $fe $68 $48 +$c9 $b2 $d0 $fe $28 $a9 $00 $48 $a9 $01 $28 $24 $13 $08 $c9 $01 +$d0 $fe $68 $48 $c9 $f0 $d0 $fe $28 $a9 $ff $48 $a9 $ff $28 $24 +$16 $08 $c9 $ff $d0 $fe $68 $48 $c9 $3f $d0 $fe $28 $a9 $ff $48 +$a9 $01 $28 $24 $15 $08 $c9 $01 $d0 $fe $68 $48 $c9 $7d $d0 $fe +$28 $a9 $ff $48 $a9 $01 $28 $24 $14 $08 $c9 $01 $d0 $fe $68 $48 +$c9 $bf $d0 $fe $28 $a9 $ff $48 $a9 $01 $28 $24 $13 $08 $c9 $01 +$d0 $fe $68 $48 $c9 $fd $d0 $fe $28 $a9 $00 $48 $a9 $ff $28 $2c +$1a $02 $08 $c9 $ff $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 $a9 $00 +$48 $a9 $01 $28 $2c $19 $02 $08 $c9 $01 $d0 $fe $68 $48 $c9 $70 +$d0 $fe $28 $a9 $00 $48 $a9 $01 $28 $2c $18 $02 $08 $c9 $01 $d0 +$fe $68 $48 $c9 $b2 $d0 $fe $28 $a9 $00 $48 $a9 $01 $28 $2c $17 +$02 $08 $c9 $01 $d0 $fe $68 $48 $c9 $f0 $d0 $fe $28 $a9 $ff $48 +$a9 $ff $28 $2c $1a $02 $08 $c9 $ff $d0 $fe $68 $48 $c9 $3f $d0 +$fe $28 $a9 $ff $48 $a9 $01 $28 $2c $19 $02 $08 $c9 $01 $d0 $fe +$68 $48 $c9 $7d $d0 $fe $28 $a9 $ff $48 $a9 $01 $28 $2c $18 $02 +$08 $c9 $01 $d0 $fe $68 $48 $c9 $bf $d0 $fe $28 $a9 $ff $48 $a9 +$01 $28 $2c $17 $02 $08 $c9 $01 $d0 $fe $68 $48 $c9 $fd $d0 $fe +$28 $ad $00 $02 $c9 $19 $d0 $fe $a9 $1a $8d $00 $02 $a9 $00 $48 +$a2 $80 $28 $e4 $17 $08 $68 $48 $c9 $31 $d0 $fe $28 $ca $e4 $17 +$08 $68 $48 $c9 $33 $d0 $fe $28 $ca $e4 $17 $08 $e0 $7e $d0 $fe +$68 $48 $c9 $b0 $d0 $fe $28 $a9 $ff $48 $a2 $80 $28 $e4 $17 $08 +$68 $48 $c9 $7d $d0 $fe $28 $ca $e4 $17 $08 $68 $48 $c9 $7f $d0 +$fe $28 $ca $e4 $17 $08 $e0 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe +$28 $a9 $00 $48 $a2 $80 $28 $ec $1b $02 $08 $68 $48 $c9 $31 $d0 +$fe $28 $ca $ec $1b $02 $08 $68 $48 $c9 $33 $d0 $fe $28 $ca $ec +$1b $02 $08 $e0 $7e $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 $a9 $ff +$48 $a2 $80 $28 $ec $1b $02 $08 $68 $48 $c9 $7d $d0 $fe $28 $ca +$ec $1b $02 $08 $68 $48 $c9 $7f $d0 $fe $28 $ca $ec $1b $02 $08 +$e0 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe $28 $a9 $00 $48 $a2 $80 +$28 $e0 $7f $08 $68 $48 $c9 $31 $d0 $fe $28 $ca $e0 $7f $08 $68 +$48 $c9 $33 $d0 $fe $28 $ca $e0 $7f $08 $e0 $7e $d0 $fe $68 $48 +$c9 $b0 $d0 $fe $28 $a9 $ff $48 $a2 $80 $28 $e0 $7f $08 $68 $48 +$c9 $7d $d0 $fe $28 $ca $e0 $7f $08 $68 $48 $c9 $7f $d0 $fe $28 +$ca $e0 $7f $08 $e0 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe $28 $ad +$00 $02 $c9 $1a $d0 $fe $a9 $1b $8d $00 $02 $a9 $00 $48 $a0 $80 +$28 $c4 $17 $08 $68 $48 $c9 $31 $d0 $fe $28 $88 $c4 $17 $08 $68 +$48 $c9 $33 $d0 $fe $28 $88 $c4 $17 $08 $c0 $7e $d0 $fe $68 $48 +$c9 $b0 $d0 $fe $28 $a9 $ff $48 $a0 $80 $28 $c4 $17 $08 $68 $48 +$c9 $7d $d0 $fe $28 $88 $c4 $17 $08 $68 $48 $c9 $7f $d0 $fe $28 +$88 $c4 $17 $08 $c0 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe $28 $a9 +$00 $48 $a0 $80 $28 $cc $1b $02 $08 $68 $48 $c9 $31 $d0 $fe $28 +$88 $cc $1b $02 $08 $68 $48 $c9 $33 $d0 $fe $28 $88 $cc $1b $02 +$08 $c0 $7e $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 $a9 $ff $48 $a0 +$80 $28 $cc $1b $02 $08 $68 $48 $c9 $7d $d0 $fe $28 $88 $cc $1b +$02 $08 $68 $48 $c9 $7f $d0 $fe $28 $88 $cc $1b $02 $08 $c0 $7e +$d0 $fe $68 $48 $c9 $fc $d0 $fe $28 $a9 $00 $48 $a0 $80 $28 $c0 +$7f $08 $68 $48 $c9 $31 $d0 $fe $28 $88 $c0 $7f $08 $68 $48 $c9 +$33 $d0 $fe $28 $88 $c0 $7f $08 $c0 $7e $d0 $fe $68 $48 $c9 $b0 +$d0 $fe $28 $a9 $ff $48 $a0 $80 $28 $c0 $7f $08 $68 $48 $c9 $7d +$d0 $fe $28 $88 $c0 $7f $08 $68 $48 $c9 $7f $d0 $fe $28 $88 $c0 +$7f $08 $c0 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe $28 $ad $00 $02 +$c9 $1b $d0 $fe $a9 $1c $8d $00 $02 $a9 $00 $48 $a9 $80 $28 $c5 +$17 $08 $c9 $80 $d0 $fe $68 $48 $c9 $31 $d0 $fe $28 $a9 $00 $48 +$a9 $7f $28 $c5 $17 $08 $c9 $7f $d0 $fe $68 $48 $c9 $33 $d0 $fe +$28 $a9 $00 $48 $a9 $7e $28 $c5 $17 $08 $c9 $7e $d0 $fe $68 $48 +$c9 $b0 $d0 $fe $28 $a9 $ff $48 $a9 $80 $28 $c5 $17 $08 $c9 $80 +$d0 $fe $68 $48 $c9 $7d $d0 $fe $28 $a9 $ff $48 $a9 $7f $28 $c5 +$17 $08 $c9 $7f $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $a9 $ff $48 +$a9 $7e $28 $c5 $17 $08 $c9 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe +$28 $a9 $00 $48 $a9 $80 $28 $cd $1b $02 $08 $c9 $80 $d0 $fe $68 +$48 $c9 $31 $d0 $fe $28 $a9 $00 $48 $a9 $7f $28 $cd $1b $02 $08 +$c9 $7f $d0 $fe $68 $48 $c9 $33 $d0 $fe $28 $a9 $00 $48 $a9 $7e +$28 $cd $1b $02 $08 $c9 $7e $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 +$a9 $ff $48 $a9 $80 $28 $cd $1b $02 $08 $c9 $80 $d0 $fe $68 $48 +$c9 $7d $d0 $fe $28 $a9 $ff $48 $a9 $7f $28 $cd $1b $02 $08 $c9 +$7f $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $a9 $ff $48 $a9 $7e $28 +$cd $1b $02 $08 $c9 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe $28 $a9 +$00 $48 $a9 $80 $28 $c9 $7f $08 $c9 $80 $d0 $fe $68 $48 $c9 $31 +$d0 $fe $28 $a9 $00 $48 $a9 $7f $28 $c9 $7f $08 $c9 $7f $d0 $fe +$68 $48 $c9 $33 $d0 $fe $28 $a9 $00 $48 $a9 $7e $28 $c9 $7f $08 +$c9 $7e $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 $a9 $ff $48 $a9 $80 +$28 $c9 $7f $08 $c9 $80 $d0 $fe $68 $48 $c9 $7d $d0 $fe $28 $a9 +$ff $48 $a9 $7f $28 $c9 $7f $08 $c9 $7f $d0 $fe $68 $48 $c9 $7f +$d0 $fe $28 $a9 $ff $48 $a9 $7e $28 $c9 $7f $08 $c9 $7e $d0 $fe +$68 $48 $c9 $fc $d0 $fe $28 $a2 $04 $a9 $00 $48 $a9 $80 $28 $d5 +$13 $08 $c9 $80 $d0 $fe $68 $48 $c9 $31 $d0 $fe $28 $a9 $00 $48 +$a9 $7f $28 $d5 $13 $08 $c9 $7f $d0 $fe $68 $48 $c9 $33 $d0 $fe +$28 $a9 $00 $48 $a9 $7e $28 $d5 $13 $08 $c9 $7e $d0 $fe $68 $48 +$c9 $b0 $d0 $fe $28 $a9 $ff $48 $a9 $80 $28 $d5 $13 $08 $c9 $80 +$d0 $fe $68 $48 $c9 $7d $d0 $fe $28 $a9 $ff $48 $a9 $7f $28 $d5 +$13 $08 $c9 $7f $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $a9 $ff $48 +$a9 $7e $28 $d5 $13 $08 $c9 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe +$28 $a9 $00 $48 $a9 $80 $28 $dd $17 $02 $08 $c9 $80 $d0 $fe $68 +$48 $c9 $31 $d0 $fe $28 $a9 $00 $48 $a9 $7f $28 $dd $17 $02 $08 +$c9 $7f $d0 $fe $68 $48 $c9 $33 $d0 $fe $28 $a9 $00 $48 $a9 $7e +$28 $dd $17 $02 $08 $c9 $7e $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 +$a9 $ff $48 $a9 $80 $28 $dd $17 $02 $08 $c9 $80 $d0 $fe $68 $48 +$c9 $7d $d0 $fe $28 $a9 $ff $48 $a9 $7f $28 $dd $17 $02 $08 $c9 +$7f $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $a9 $ff $48 $a9 $7e $28 +$dd $17 $02 $08 $c9 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe $28 $a0 +$04 $a2 $08 $a9 $00 $48 $a9 $80 $28 $d9 $17 $02 $08 $c9 $80 $d0 +$fe $68 $48 $c9 $31 $d0 $fe $28 $a9 $00 $48 $a9 $7f $28 $d9 $17 +$02 $08 $c9 $7f $d0 $fe $68 $48 $c9 $33 $d0 $fe $28 $a9 $00 $48 +$a9 $7e $28 $d9 $17 $02 $08 $c9 $7e $d0 $fe $68 $48 $c9 $b0 $d0 +$fe $28 $a9 $ff $48 $a9 $80 $28 $d9 $17 $02 $08 $c9 $80 $d0 $fe +$68 $48 $c9 $7d $d0 $fe $28 $a9 $ff $48 $a9 $7f $28 $d9 $17 $02 +$08 $c9 $7f $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $a9 $ff $48 $a9 +$7e $28 $d9 $17 $02 $08 $c9 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe +$28 $a9 $00 $48 $a9 $80 $28 $c1 $24 $08 $c9 $80 $d0 $fe $68 $48 +$c9 $31 $d0 $fe $28 $a9 $00 $48 $a9 $7f $28 $c1 $24 $08 $c9 $7f +$d0 $fe $68 $48 $c9 $33 $d0 $fe $28 $a9 $00 $48 $a9 $7e $28 $c1 +$24 $08 $c9 $7e $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 $a9 $ff $48 +$a9 $80 $28 $c1 $24 $08 $c9 $80 $d0 $fe $68 $48 $c9 $7d $d0 $fe +$28 $a9 $ff $48 $a9 $7f $28 $c1 $24 $08 $c9 $7f $d0 $fe $68 $48 +$c9 $7f $d0 $fe $28 $a9 $ff $48 $a9 $7e $28 $c1 $24 $08 $c9 $7e +$d0 $fe $68 $48 $c9 $fc $d0 $fe $28 $a9 $00 $48 $a9 $80 $28 $d1 +$24 $08 $c9 $80 $d0 $fe $68 $48 $c9 $31 $d0 $fe $28 $a9 $00 $48 +$a9 $7f $28 $d1 $24 $08 $c9 $7f $d0 $fe $68 $48 $c9 $33 $d0 $fe +$28 $a9 $00 $48 $a9 $7e $28 $d1 $24 $08 $c9 $7e $d0 $fe $68 $48 +$c9 $b0 $d0 $fe $28 $a9 $ff $48 $a9 $80 $28 $d1 $24 $08 $c9 $80 +$d0 $fe $68 $48 $c9 $7d $d0 $fe $28 $a9 $ff $48 $a9 $7f $28 $d1 +$24 $08 $c9 $7f $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $a9 $ff $48 +$a9 $7e $28 $d1 $24 $08 $c9 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe +$28 $ad $00 $02 $c9 $1c $d0 $fe $a9 $1d $8d $00 $02 $a2 $03 $a9 +$00 $48 $b5 $13 $28 $0a $08 $dd $20 $02 $d0 $fe $68 $49 $30 $dd +$30 $02 $d0 $fe $ca $10 $e8 $a2 $03 $a9 $ff $48 $b5 $13 $28 $0a +$08 $dd $20 $02 $d0 $fe $68 $49 $7c $dd $30 $02 $d0 $fe $ca $10 +$e8 $a2 $03 $a9 $00 $48 $b5 $13 $28 $4a $08 $dd $28 $02 $d0 $fe +$68 $49 $30 $dd $38 $02 $d0 $fe $ca $10 $e8 $a2 $03 $a9 $ff $48 +$b5 $13 $28 $4a $08 $dd $28 $02 $d0 $fe $68 $49 $7c $dd $38 $02 +$d0 $fe $ca $10 $e8 $a2 $03 $a9 $00 $48 $b5 $13 $28 $2a $08 $dd +$20 $02 $d0 $fe $68 $49 $30 $dd $30 $02 $d0 $fe $ca $10 $e8 $a2 +$03 $a9 $fe $48 $b5 $13 $28 $2a $08 $dd $20 $02 $d0 $fe $68 $49 +$7c $dd $30 $02 $d0 $fe $ca $10 $e8 $a2 $03 $a9 $01 $48 $b5 $13 +$28 $2a $08 $dd $24 $02 $d0 $fe $68 $49 $30 $dd $34 $02 $d0 $fe +$ca $10 $e8 $a2 $03 $a9 $ff $48 $b5 $13 $28 $2a $08 $dd $24 $02 +$d0 $fe $68 $49 $7c $dd $34 $02 $d0 $fe $ca $10 $e8 $a2 $03 $a9 +$00 $48 $b5 $13 $28 $6a $08 $dd $28 $02 $d0 $fe $68 $49 $30 $dd +$38 $02 $d0 $fe $ca $10 $e8 $a2 $03 $a9 $fe $48 $b5 $13 $28 $6a +$08 $dd $28 $02 $d0 $fe $68 $49 $7c $dd $38 $02 $d0 $fe $ca $10 +$e8 $a2 $03 $a9 $01 $48 $b5 $13 $28 $6a $08 $dd $2c $02 $d0 $fe +$68 $49 $30 $dd $3c $02 $d0 $fe $ca $10 $e8 $a2 $03 $a9 $ff $48 +$b5 $13 $28 $6a $08 $dd $2c $02 $d0 $fe $68 $49 $7c $dd $3c $02 +$d0 $fe $ca $10 $e8 $ad $00 $02 $c9 $1d $d0 $fe $a9 $1e $8d $00 +$02 $a2 $03 $a9 $00 $48 $b5 $13 $85 $0c $28 $06 $0c $08 $a5 $0c +$dd $20 $02 $d0 $fe $68 $49 $30 $dd $30 $02 $d0 $fe $ca $10 $e3 +$a2 $03 $a9 $ff $48 $b5 $13 $85 $0c $28 $06 $0c $08 $a5 $0c $dd +$20 $02 $d0 $fe $68 $49 $7c $dd $30 $02 $d0 $fe $ca $10 $e3 $a2 +$03 $a9 $00 $48 $b5 $13 $85 $0c $28 $46 $0c $08 $a5 $0c $dd $28 +$02 $d0 $fe $68 $49 $30 $dd $38 $02 $d0 $fe $ca $10 $e3 $a2 $03 +$a9 $ff $48 $b5 $13 $85 $0c $28 $46 $0c $08 $a5 $0c $dd $28 $02 +$d0 $fe $68 $49 $7c $dd $38 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 +$00 $48 $b5 $13 $85 $0c $28 $26 $0c $08 $a5 $0c $dd $20 $02 $d0 +$fe $68 $49 $30 $dd $30 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $fe +$48 $b5 $13 $85 $0c $28 $26 $0c $08 $a5 $0c $dd $20 $02 $d0 $fe +$68 $49 $7c $dd $30 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $01 $48 +$b5 $13 $85 $0c $28 $26 $0c $08 $a5 $0c $dd $24 $02 $d0 $fe $68 +$49 $30 $dd $34 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $ff $48 $b5 +$13 $85 $0c $28 $26 $0c $08 $a5 $0c $dd $24 $02 $d0 $fe $68 $49 +$7c $dd $34 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $00 $48 $b5 $13 +$85 $0c $28 $66 $0c $08 $a5 $0c $dd $28 $02 $d0 $fe $68 $49 $30 +$dd $38 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $fe $48 $b5 $13 $85 +$0c $28 $66 $0c $08 $a5 $0c $dd $28 $02 $d0 $fe $68 $49 $7c $dd +$38 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $01 $48 $b5 $13 $85 $0c +$28 $66 $0c $08 $a5 $0c $dd $2c $02 $d0 $fe $68 $49 $30 $dd $3c +$02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $ff $48 $b5 $13 $85 $0c $28 +$66 $0c $08 $a5 $0c $dd $2c $02 $d0 $fe $68 $49 $7c $dd $3c $02 +$d0 $fe $ca $10 $e3 $ad $00 $02 $c9 $1e $d0 $fe $a9 $1f $8d $00 +$02 $a2 $03 $a9 $00 $48 $b5 $13 $8d $03 $02 $28 $0e $03 $02 $08 +$ad $03 $02 $dd $20 $02 $d0 $fe $68 $49 $30 $dd $30 $02 $d0 $fe +$ca $10 $e0 $a2 $03 $a9 $ff $48 $b5 $13 $8d $03 $02 $28 $0e $03 +$02 $08 $ad $03 $02 $dd $20 $02 $d0 $fe $68 $49 $7c $dd $30 $02 +$d0 $fe $ca $10 $e0 $a2 $03 $a9 $00 $48 $b5 $13 $8d $03 $02 $28 +$4e $03 $02 $08 $ad $03 $02 $dd $28 $02 $d0 $fe $68 $49 $30 $dd +$38 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $ff $48 $b5 $13 $8d $03 +$02 $28 $4e $03 $02 $08 $ad $03 $02 $dd $28 $02 $d0 $fe $68 $49 +$7c $dd $38 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $00 $48 $b5 $13 +$8d $03 $02 $28 $2e $03 $02 $08 $ad $03 $02 $dd $20 $02 $d0 $fe +$68 $49 $30 $dd $30 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $fe $48 +$b5 $13 $8d $03 $02 $28 $2e $03 $02 $08 $ad $03 $02 $dd $20 $02 +$d0 $fe $68 $49 $7c $dd $30 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 +$01 $48 $b5 $13 $8d $03 $02 $28 $2e $03 $02 $08 $ad $03 $02 $dd +$24 $02 $d0 $fe $68 $49 $30 $dd $34 $02 $d0 $fe $ca $10 $e0 $a2 +$03 $a9 $ff $48 $b5 $13 $8d $03 $02 $28 $2e $03 $02 $08 $ad $03 +$02 $dd $24 $02 $d0 $fe $68 $49 $7c $dd $34 $02 $d0 $fe $ca $10 +$e0 $a2 $03 $a9 $00 $48 $b5 $13 $8d $03 $02 $28 $6e $03 $02 $08 +$ad $03 $02 $dd $28 $02 $d0 $fe $68 $49 $30 $dd $38 $02 $d0 $fe +$ca $10 $e0 $a2 $03 $a9 $fe $48 $b5 $13 $8d $03 $02 $28 $6e $03 +$02 $08 $ad $03 $02 $dd $28 $02 $d0 $fe $68 $49 $7c $dd $38 $02 +$d0 $fe $ca $10 $e0 $a2 $03 $a9 $01 $48 $b5 $13 $8d $03 $02 $28 +$6e $03 $02 $08 $ad $03 $02 $dd $2c $02 $d0 $fe $68 $49 $30 $dd +$3c $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $ff $48 $b5 $13 $8d $03 +$02 $28 $6e $03 $02 $08 $ad $03 $02 $dd $2c $02 $d0 $fe $68 $49 +$7c $dd $3c $02 $d0 $fe $ca $10 $e0 $ad $00 $02 $c9 $1f $d0 $fe +$a9 $20 $8d $00 $02 $a2 $03 $a9 $00 $48 $b5 $13 $95 $0c $28 $16 +$0c $08 $b5 $0c $dd $20 $02 $d0 $fe $68 $49 $30 $dd $30 $02 $d0 +$fe $ca $10 $e3 $a2 $03 $a9 $ff $48 $b5 $13 $95 $0c $28 $16 $0c +$08 $b5 $0c $dd $20 $02 $d0 $fe $68 $49 $7c $dd $30 $02 $d0 $fe +$ca $10 $e3 $a2 $03 $a9 $00 $48 $b5 $13 $95 $0c $28 $56 $0c $08 +$b5 $0c $dd $28 $02 $d0 $fe $68 $49 $30 $dd $38 $02 $d0 $fe $ca +$10 $e3 $a2 $03 $a9 $ff $48 $b5 $13 $95 $0c $28 $56 $0c $08 $b5 +$0c $dd $28 $02 $d0 $fe $68 $49 $7c $dd $38 $02 $d0 $fe $ca $10 +$e3 $a2 $03 $a9 $00 $48 $b5 $13 $95 $0c $28 $36 $0c $08 $b5 $0c +$dd $20 $02 $d0 $fe $68 $49 $30 $dd $30 $02 $d0 $fe $ca $10 $e3 +$a2 $03 $a9 $fe $48 $b5 $13 $95 $0c $28 $36 $0c $08 $b5 $0c $dd +$20 $02 $d0 $fe $68 $49 $7c $dd $30 $02 $d0 $fe $ca $10 $e3 $a2 +$03 $a9 $01 $48 $b5 $13 $95 $0c $28 $36 $0c $08 $b5 $0c $dd $24 +$02 $d0 $fe $68 $49 $30 $dd $34 $02 $d0 $fe $ca $10 $e3 $a2 $03 +$a9 $ff $48 $b5 $13 $95 $0c $28 $36 $0c $08 $b5 $0c $dd $24 $02 +$d0 $fe $68 $49 $7c $dd $34 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 +$00 $48 $b5 $13 $95 $0c $28 $76 $0c $08 $b5 $0c $dd $28 $02 $d0 +$fe $68 $49 $30 $dd $38 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $fe +$48 $b5 $13 $95 $0c $28 $76 $0c $08 $b5 $0c $dd $28 $02 $d0 $fe +$68 $49 $7c $dd $38 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $01 $48 +$b5 $13 $95 $0c $28 $76 $0c $08 $b5 $0c $dd $2c $02 $d0 $fe $68 +$49 $30 $dd $3c $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $ff $48 $b5 +$13 $95 $0c $28 $76 $0c $08 $b5 $0c $dd $2c $02 $d0 $fe $68 $49 +$7c $dd $3c $02 $d0 $fe $ca $10 $e3 $ad $00 $02 $c9 $20 $d0 $fe +$a9 $21 $8d $00 $02 $a2 $03 $a9 $00 $48 $b5 $13 $9d $03 $02 $28 +$1e $03 $02 $08 $bd $03 $02 $dd $20 $02 $d0 $fe $68 $49 $30 $dd +$30 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $ff $48 $b5 $13 $9d $03 +$02 $28 $1e $03 $02 $08 $bd $03 $02 $dd $20 $02 $d0 $fe $68 $49 +$7c $dd $30 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $00 $48 $b5 $13 +$9d $03 $02 $28 $5e $03 $02 $08 $bd $03 $02 $dd $28 $02 $d0 $fe +$68 $49 $30 $dd $38 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $ff $48 +$b5 $13 $9d $03 $02 $28 $5e $03 $02 $08 $bd $03 $02 $dd $28 $02 +$d0 $fe $68 $49 $7c $dd $38 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 +$00 $48 $b5 $13 $9d $03 $02 $28 $3e $03 $02 $08 $bd $03 $02 $dd +$20 $02 $d0 $fe $68 $49 $30 $dd $30 $02 $d0 $fe $ca $10 $e0 $a2 +$03 $a9 $fe $48 $b5 $13 $9d $03 $02 $28 $3e $03 $02 $08 $bd $03 +$02 $dd $20 $02 $d0 $fe $68 $49 $7c $dd $30 $02 $d0 $fe $ca $10 +$e0 $a2 $03 $a9 $01 $48 $b5 $13 $9d $03 $02 $28 $3e $03 $02 $08 +$bd $03 $02 $dd $24 $02 $d0 $fe $68 $49 $30 $dd $34 $02 $d0 $fe +$ca $10 $e0 $a2 $03 $a9 $ff $48 $b5 $13 $9d $03 $02 $28 $3e $03 +$02 $08 $bd $03 $02 $dd $24 $02 $d0 $fe $68 $49 $7c $dd $34 $02 +$d0 $fe $ca $10 $e0 $a2 $03 $a9 $00 $48 $b5 $13 $9d $03 $02 $28 +$7e $03 $02 $08 $bd $03 $02 $dd $28 $02 $d0 $fe $68 $49 $30 $dd +$38 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $fe $48 $b5 $13 $9d $03 +$02 $28 $7e $03 $02 $08 $bd $03 $02 $dd $28 $02 $d0 $fe $68 $49 +$7c $dd $38 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $01 $48 $b5 $13 +$9d $03 $02 $28 $7e $03 $02 $08 $bd $03 $02 $dd $2c $02 $d0 $fe +$68 $49 $30 $dd $3c $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $ff $48 +$b5 $13 $9d $03 $02 $28 $7e $03 $02 $08 $bd $03 $02 $dd $2c $02 +$d0 $fe $68 $49 $7c $dd $3c $02 $d0 $fe $ca $10 $e0 $ad $00 $02 +$c9 $21 $d0 $fe $a9 $22 $8d $00 $02 $a2 $00 $a9 $7e $85 $0c $a9 +$00 $48 $28 $e6 $0c $08 $a5 $0c $dd $40 $02 $d0 $fe $68 $49 $30 +$dd $45 $02 $d0 $fe $e8 $e0 $02 $d0 $04 $a9 $fe $85 $0c $e0 $05 +$d0 $dd $ca $e6 $0c $a9 $00 $48 $28 $c6 $0c $08 $a5 $0c $dd $40 +$02 $d0 $fe $68 $49 $30 $dd $45 $02 $d0 $fe $ca $30 $0a $e0 $01 +$d0 $e3 $a9 $81 $85 $0c $d0 $dd $a2 $00 $a9 $7e $85 $0c $a9 $ff +$48 $28 $e6 $0c $08 $a5 $0c $dd $40 $02 $d0 $fe $68 $49 $7d $dd +$45 $02 $d0 $fe $e8 $e0 $02 $d0 $04 $a9 $fe $85 $0c $e0 $05 $d0 +$dd $ca $e6 $0c $a9 $ff $48 $28 $c6 $0c $08 $a5 $0c $dd $40 $02 +$d0 $fe $68 $49 $7d $dd $45 $02 $d0 $fe $ca $30 $0a $e0 $01 $d0 +$e3 $a9 $81 $85 $0c $d0 $dd $ad $00 $02 $c9 $22 $d0 $fe $a9 $23 +$8d $00 $02 $a2 $00 $a9 $7e $8d $03 $02 $a9 $00 $48 $28 $ee $03 +$02 $08 $ad $03 $02 $dd $40 $02 $d0 $fe $68 $49 $30 $dd $45 $02 +$d0 $fe $e8 $e0 $02 $d0 $05 $a9 $fe $8d $03 $02 $e0 $05 $d0 $da +$ca $ee $03 $02 $a9 $00 $48 $28 $ce $03 $02 $08 $ad $03 $02 $dd +$40 $02 $d0 $fe $68 $49 $30 $dd $45 $02 $d0 $fe $ca $30 $0b $e0 +$01 $d0 $e1 $a9 $81 $8d $03 $02 $d0 $da $a2 $00 $a9 $7e $8d $03 +$02 $a9 $ff $48 $28 $ee $03 $02 $08 $ad $03 $02 $dd $40 $02 $d0 +$fe $68 $49 $7d $dd $45 $02 $d0 $fe $e8 $e0 $02 $d0 $05 $a9 $fe +$8d $03 $02 $e0 $05 $d0 $da $ca $ee $03 $02 $a9 $ff $48 $28 $ce +$03 $02 $08 $ad $03 $02 $dd $40 $02 $d0 $fe $68 $49 $7d $dd $45 +$02 $d0 $fe $ca $30 $0b $e0 $01 $d0 $e1 $a9 $81 $8d $03 $02 $d0 +$da $ad $00 $02 $c9 $23 $d0 $fe $a9 $24 $8d $00 $02 $a2 $00 $a9 +$7e $95 $0c $a9 $00 $48 $28 $f6 $0c $08 $b5 $0c $dd $40 $02 $d0 +$fe $68 $49 $30 $dd $45 $02 $d0 $fe $b5 $0c $e8 $e0 $02 $d0 $02 +$a9 $fe $e0 $05 $d0 $db $ca $a9 $02 $95 $0c $a9 $00 $48 $28 $d6 +$0c $08 $b5 $0c $dd $40 $02 $d0 $fe $68 $49 $30 $dd $45 $02 $d0 +$fe $b5 $0c $ca $30 $08 $e0 $01 $d0 $df $a9 $81 $d0 $db $a2 $00 +$a9 $7e $95 $0c $a9 $ff $48 $28 $f6 $0c $08 $b5 $0c $dd $40 $02 +$d0 $fe $68 $49 $7d $dd $45 $02 $d0 $fe $b5 $0c $e8 $e0 $02 $d0 +$02 $a9 $fe $e0 $05 $d0 $db $ca $a9 $02 $95 $0c $a9 $ff $48 $28 +$d6 $0c $08 $b5 $0c $dd $40 $02 $d0 $fe $68 $49 $7d $dd $45 $02 +$d0 $fe $b5 $0c $ca $30 $08 $e0 $01 $d0 $df $a9 $81 $d0 $db $ad +$00 $02 $c9 $24 $d0 $fe $a9 $25 $8d $00 $02 $a2 $00 $a9 $7e $9d +$03 $02 $a9 $00 $48 $28 $fe $03 $02 $08 $bd $03 $02 $dd $40 $02 +$d0 $fe $68 $49 $30 $dd $45 $02 $d0 $fe $bd $03 $02 $e8 $e0 $02 +$d0 $02 $a9 $fe $e0 $05 $d0 $d7 $ca $a9 $02 $9d $03 $02 $a9 $00 +$48 $28 $de $03 $02 $08 $bd $03 $02 $dd $40 $02 $d0 $fe $68 $49 +$30 $dd $45 $02 $d0 $fe $bd $03 $02 $ca $30 $08 $e0 $01 $d0 $db +$a9 $81 $d0 $d7 $a2 $00 $a9 $7e $9d $03 $02 $a9 $ff $48 $28 $fe +$03 $02 $08 $bd $03 $02 $dd $40 $02 $d0 $fe $68 $49 $7d $dd $45 +$02 $d0 $fe $bd $03 $02 $e8 $e0 $02 $d0 $02 $a9 $fe $e0 $05 $d0 +$d7 $ca $a9 $02 $9d $03 $02 $a9 $ff $48 $28 $de $03 $02 $08 $bd +$03 $02 $dd $40 $02 $d0 $fe $68 $49 $7d $dd $45 $02 $d0 $fe $bd +$03 $02 $ca $30 $08 $e0 $01 $d0 $db $a9 $81 $d0 $d7 $ad $00 $02 +$c9 $25 $d0 $fe $a9 $26 $8d $00 $02 $a2 $03 $b5 $1c $8d $09 $02 +$a9 $00 $48 $bd $5a $02 $28 $20 $08 $02 $08 $dd $62 $02 $d0 $fe +$68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e0 $a2 $03 $b5 $1c $8d +$09 $02 $a9 $ff $48 $bd $5a $02 $28 $20 $08 $02 $08 $dd $62 $02 +$d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe $ca $10 $e0 $a2 $03 $b5 +$1c $85 $0c $a9 $00 $48 $bd $5a $02 $28 $25 $0c $08 $dd $62 $02 +$d0 $fe $68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e2 $a2 $03 $b5 +$1c $85 $0c $a9 $ff $48 $bd $5a $02 $28 $25 $0c $08 $dd $62 $02 +$d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe $ca $10 $e2 $a2 $03 $b5 +$1c $8d $03 $02 $a9 $00 $48 $bd $5a $02 $28 $2d $03 $02 $08 $dd +$62 $02 $d0 $fe $68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e0 $a2 +$03 $b5 $1c $8d $03 $02 $a9 $ff $48 $bd $5a $02 $28 $2d $03 $02 +$08 $dd $62 $02 $d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe $ca $10 +$02 $a2 $03 $a9 $00 $48 $bd $5a $02 $28 $35 $1c $08 $dd $62 $02 +$d0 $fe $68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e6 $a2 $03 $a9 +$ff $48 $bd $5a $02 $28 $35 $1c $08 $dd $62 $02 $d0 $fe $68 $49 +$7d $dd $66 $02 $d0 $fe $ca $10 $e6 $a2 $03 $a9 $00 $48 $bd $5a +$02 $28 $3d $4e $02 $08 $dd $62 $02 $d0 $fe $68 $49 $30 $dd $66 +$02 $d0 $fe $ca $10 $e5 $a2 $03 $a9 $ff $48 $bd $5a $02 $28 $3d +$4e $02 $08 $dd $62 $02 $d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe +$ca $10 $e5 $a0 $03 $a9 $00 $48 $b9 $5a $02 $28 $39 $4e $02 $08 +$d9 $62 $02 $d0 $fe $68 $49 $30 $d9 $66 $02 $d0 $fe $88 $10 $e5 +$a0 $03 $a9 $ff $48 $b9 $5a $02 $28 $39 $4e $02 $08 $d9 $62 $02 +$d0 $fe $68 $49 $7d $d9 $66 $02 $d0 $fe $88 $10 $e5 $a2 $06 $a0 +$03 $a9 $00 $48 $b9 $5a $02 $28 $21 $3a $08 $d9 $62 $02 $d0 $fe +$68 $49 $30 $d9 $66 $02 $d0 $fe $ca $ca $88 $10 $e4 $a2 $06 $a0 +$03 $a9 $ff $48 $b9 $5a $02 $28 $21 $3a $08 $d9 $62 $02 $d0 $fe +$68 $49 $7d $d9 $66 $02 $d0 $fe $ca $ca $88 $10 $e4 $a0 $03 $a9 +$00 $48 $b9 $5a $02 $28 $31 $3a $08 $d9 $62 $02 $d0 $fe $68 $49 +$30 $d9 $66 $02 $d0 $fe $88 $10 $e6 $a0 $03 $a9 $ff $48 $b9 $5a +$02 $28 $31 $3a $08 $d9 $62 $02 $d0 $fe $68 $49 $7d $d9 $66 $02 +$d0 $fe $88 $10 $e6 $ad $00 $02 $c9 $26 $d0 $fe $a9 $27 $8d $00 +$02 $a2 $03 $b5 $20 $8d $0c $02 $a9 $00 $48 $bd $5e $02 $28 $20 +$0b $02 $08 $dd $62 $02 $d0 $fe $68 $49 $30 $dd $66 $02 $d0 $fe +$ca $10 $e0 $a2 $03 $b5 $20 $8d $0c $02 $a9 $ff $48 $bd $5e $02 +$28 $20 $0b $02 $08 $dd $62 $02 $d0 $fe $68 $49 $7d $dd $66 $02 +$d0 $fe $ca $10 $e0 $a2 $03 $b5 $20 $85 $0c $a9 $00 $48 $bd $5e +$02 $28 $45 $0c $08 $dd $62 $02 $d0 $fe $68 $49 $30 $dd $66 $02 +$d0 $fe $ca $10 $e2 $a2 $03 $b5 $20 $85 $0c $a9 $ff $48 $bd $5e +$02 $28 $45 $0c $08 $dd $62 $02 $d0 $fe $68 $49 $7d $dd $66 $02 +$d0 $fe $ca $10 $e2 $a2 $03 $b5 $20 $8d $03 $02 $a9 $00 $48 $bd +$5e $02 $28 $4d $03 $02 $08 $dd $62 $02 $d0 $fe $68 $49 $30 $dd +$66 $02 $d0 $fe $ca $10 $e0 $a2 $03 $b5 $20 $8d $03 $02 $a9 $ff +$48 $bd $5e $02 $28 $4d $03 $02 $08 $dd $62 $02 $d0 $fe $68 $49 +$7d $dd $66 $02 $d0 $fe $ca $10 $02 $a2 $03 $a9 $00 $48 $bd $5e +$02 $28 $55 $20 $08 $dd $62 $02 $d0 $fe $68 $49 $30 $dd $66 $02 +$d0 $fe $ca $10 $e6 $a2 $03 $a9 $ff $48 $bd $5e $02 $28 $55 $20 +$08 $dd $62 $02 $d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe $ca $10 +$e6 $a2 $03 $a9 $00 $48 $bd $5e $02 $28 $5d $52 $02 $08 $dd $62 +$02 $d0 $fe $68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e5 $a2 $03 +$a9 $ff $48 $bd $5e $02 $28 $5d $52 $02 $08 $dd $62 $02 $d0 $fe +$68 $49 $7d $dd $66 $02 $d0 $fe $ca $10 $e5 $a0 $03 $a9 $00 $48 +$b9 $5e $02 $28 $59 $52 $02 $08 $d9 $62 $02 $d0 $fe $68 $49 $30 +$d9 $66 $02 $d0 $fe $88 $10 $e5 $a0 $03 $a9 $ff $48 $b9 $5e $02 +$28 $59 $52 $02 $08 $d9 $62 $02 $d0 $fe $68 $49 $7d $d9 $66 $02 +$d0 $fe $88 $10 $e5 $a2 $06 $a0 $03 $a9 $00 $48 $b9 $5e $02 $28 +$41 $42 $08 $d9 $62 $02 $d0 $fe $68 $49 $30 $d9 $66 $02 $d0 $fe +$ca $ca $88 $10 $e4 $a2 $06 $a0 $03 $a9 $ff $48 $b9 $5e $02 $28 +$41 $42 $08 $d9 $62 $02 $d0 $fe $68 $49 $7d $d9 $66 $02 $d0 $fe +$ca $ca $88 $10 $e4 $a0 $03 $a9 $00 $48 $b9 $5e $02 $28 $51 $42 +$08 $d9 $62 $02 $d0 $fe $68 $49 $30 $d9 $66 $02 $d0 $fe $88 $10 +$e6 $a0 $03 $a9 $ff $48 $b9 $5e $02 $28 $51 $42 $08 $d9 $62 $02 +$d0 $fe $68 $49 $7d $d9 $66 $02 $d0 $fe $88 $10 $e6 $ad $00 $02 +$c9 $27 $d0 $fe $a9 $28 $8d $00 $02 $a2 $03 $b5 $18 $8d $0f $02 +$a9 $00 $48 $bd $56 $02 $28 $20 $0e $02 $08 $dd $62 $02 $d0 $fe +$68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e0 $a2 $03 $b5 $18 $8d +$0f $02 $a9 $ff $48 $bd $56 $02 $28 $20 $0e $02 $08 $dd $62 $02 +$d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe $ca $10 $e0 $a2 $03 $b5 +$18 $85 $0c $a9 $00 $48 $bd $56 $02 $28 $05 $0c $08 $dd $62 $02 +$d0 $fe $68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e2 $a2 $03 $b5 +$18 $85 $0c $a9 $ff $48 $bd $56 $02 $28 $05 $0c $08 $dd $62 $02 +$d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe $ca $10 $e2 $a2 $03 $b5 +$18 $8d $03 $02 $a9 $00 $48 $bd $56 $02 $28 $0d $03 $02 $08 $dd +$62 $02 $d0 $fe $68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e0 $a2 +$03 $b5 $18 $8d $03 $02 $a9 $ff $48 $bd $56 $02 $28 $0d $03 $02 +$08 $dd $62 $02 $d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe $ca $10 +$02 $a2 $03 $a9 $00 $48 $bd $56 $02 $28 $15 $18 $08 $dd $62 $02 +$d0 $fe $68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e6 $a2 $03 $a9 +$ff $48 $bd $56 $02 $28 $15 $18 $08 $dd $62 $02 $d0 $fe $68 $49 +$7d $dd $66 $02 $d0 $fe $ca $10 $e6 $a2 $03 $a9 $00 $48 $bd $56 +$02 $28 $1d $4a $02 $08 $dd $62 $02 $d0 $fe $68 $49 $30 $dd $66 +$02 $d0 $fe $ca $10 $e5 $a2 $03 $a9 $ff $48 $bd $56 $02 $28 $1d +$4a $02 $08 $dd $62 $02 $d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe +$ca $10 $e5 $a0 $03 $a9 $00 $48 $b9 $56 $02 $28 $19 $4a $02 $08 +$d9 $62 $02 $d0 $fe $68 $49 $30 $d9 $66 $02 $d0 $fe $88 $10 $e5 +$a0 $03 $a9 $ff $48 $b9 $56 $02 $28 $19 $4a $02 $08 $d9 $62 $02 +$d0 $fe $68 $49 $7d $d9 $66 $02 $d0 $fe $88 $10 $e5 $a2 $06 $a0 +$03 $a9 $00 $48 $b9 $56 $02 $28 $01 $4a $08 $d9 $62 $02 $d0 $fe +$68 $49 $30 $d9 $66 $02 $d0 $fe $ca $ca $88 $10 $e4 $a2 $06 $a0 +$03 $a9 $ff $48 $b9 $56 $02 $28 $01 $4a $08 $d9 $62 $02 $d0 $fe +$68 $49 $7d $d9 $66 $02 $d0 $fe $ca $ca $88 $10 $e4 $a0 $03 $a9 +$00 $48 $b9 $56 $02 $28 $11 $4a $08 $d9 $62 $02 $d0 $fe $68 $49 +$30 $d9 $66 $02 $d0 $fe $88 $10 $e6 $a0 $03 $a9 $ff $48 $b9 $56 +$02 $28 $11 $4a $08 $d9 $62 $02 $d0 $fe $68 $49 $7d $d9 $66 $02 +$d0 $fe $88 $10 $e6 $58 $ad $00 $02 $c9 $28 $d0 $fe $a9 $29 $8d +$00 $02 $d8 $a2 $0e $a0 $ff $a9 $00 $85 $0c $85 $0d $85 $0e $8d +$03 $02 $85 $0f $85 $10 $a9 $ff $85 $12 $8d $04 $02 $a9 $02 $85 +$11 $18 $20 $7c $35 $e6 $0c $e6 $0f $08 $08 $68 $29 $82 $28 $d0 +$02 $e6 $10 $05 $10 $85 $11 $38 $20 $7c $35 $c6 $0c $e6 $0d $d0 +$e0 $a9 $00 $85 $10 $ee $03 $02 $e6 $0e $08 $68 $29 $82 $85 $11 +$c6 $12 $ce $04 $02 $a5 $0e $85 $0f $d0 $c6 $ad $00 $02 $c9 $29 +$d0 $fe $a9 $2a $8d $00 $02 $f8 $a2 $0e $a0 $ff $a9 $99 $85 $0d +$85 $0e $8d $03 $02 $85 $0f $a9 $01 $85 $0c $85 $10 $a9 $00 $85 +$12 $8d $04 $02 $38 $20 $49 $34 $c6 $0c $a5 $0f $d0 $08 $c6 $10 +$a9 $99 $85 $0f $d0 $12 $29 $0f $d0 $0c $c6 $0f $c6 $0f $c6 $0f +$c6 $0f $c6 $0f $c6 $0f $c6 $0f $18 $20 $49 $34 $e6 $0c $a5 $0d +$f0 $15 $29 $0f $d0 $0c $c6 $0d $c6 $0d $c6 $0d $c6 $0d $c6 $0d +$c6 $0d $c6 $0d $4c $64 $33 $a9 $99 $85 $0d $a5 $0e $f0 $30 $29 +$0f $d0 $18 $c6 $0e $c6 $0e $c6 $0e $c6 $0e $c6 $0e $c6 $0e $e6 +$12 $e6 $12 $e6 $12 $e6 $12 $e6 $12 $e6 $12 $c6 $0e $e6 $12 $a5 +$12 $8d $04 $02 $a5 $0e $8d $03 $02 $85 $0f $e6 $10 $d0 $85 $ad +$00 $02 $c9 $2a $d0 $fe $a9 $2b $8d $00 $02 $18 $d8 $08 $a9 $55 +$69 $55 $c9 $aa $d0 $fe $18 $f8 $08 $a9 $55 $69 $55 $c9 $10 $d0 +$fe $d8 $28 $a9 $55 $69 $55 $c9 $10 $d0 $fe $28 $a9 $55 $69 $55 +$c9 $aa $d0 $fe $18 $a9 $34 $48 $a9 $2f $48 $08 $f8 $a9 $34 $48 +$a9 $26 $48 $08 $d8 $40 $a9 $55 $69 $55 $c9 $10 $d0 $fe $40 $a9 +$55 $69 $55 $c9 $aa $d0 $fe $ad $00 $02 $c9 $2b $d0 $fe $a9 $f0 +$8d $00 $02 $4c $43 $34 $4c $00 $04 $08 $a5 $0d $65 $0e $08 $c5 +$0f $d0 $fe $68 $29 $01 $c5 $10 $d0 $fe $28 $08 $a5 $0d $e5 $12 +$08 $c5 $0f $d0 $fe $68 $29 $01 $c5 $10 $d0 $fe $28 $08 $a5 $0d +$6d $03 $02 $08 $c5 $0f $d0 $fe $68 $29 $01 $c5 $10 $d0 $fe $28 +$08 $a5 $0d $ed $04 $02 $08 $c5 $0f $d0 $fe $68 $29 $01 $c5 $10 +$d0 $fe $28 $08 $a5 $0e $8d $12 $02 $a5 $0d $20 $11 $02 $08 $c5 +$0f $d0 $fe $68 $29 $01 $c5 $10 $d0 $fe $28 $08 $a5 $12 $8d $15 +$02 $a5 $0d $20 $14 $02 $08 $c5 $0f $d0 $fe $68 $29 $01 $c5 $10 +$d0 $fe $28 $08 $a5 $0d $75 $00 $08 $c5 $0f $d0 $fe $68 $29 $01 +$c5 $10 $d0 $fe $28 $08 $a5 $0d $f5 $04 $08 $c5 $0f $d0 $fe $68 +$29 $01 $c5 $10 $d0 $fe $28 $08 $a5 $0d $7d $f5 $01 $08 $c5 $0f +$d0 $fe $68 $29 $01 $c5 $10 $d0 $fe $28 $08 $a5 $0d $fd $f6 $01 +$08 $c5 $0f $d0 $fe $68 $29 $01 $c5 $10 $d0 $fe $28 $08 $a5 $0d +$79 $04 $01 $08 $c5 $0f $d0 $fe $68 $29 $01 $c5 $10 $d0 $fe $28 +$08 $a5 $0d $f9 $05 $01 $08 $c5 $0f $d0 $fe $68 $29 $01 $c5 $10 +$d0 $fe $28 $08 $a5 $0d $61 $44 $08 $c5 $0f $d0 $fe $68 $29 $01 +$c5 $10 $d0 $fe $28 $08 $a5 $0d $e1 $46 $08 $c5 $0f $d0 $fe $68 +$29 $01 $c5 $10 $d0 $fe $28 $08 $a5 $0d $71 $56 $08 $c5 $0f $d0 +$fe $68 $29 $01 $c5 $10 $d0 $fe $28 $08 $a5 $0d $f1 $58 $08 $c5 +$0f $d0 $fe $68 $29 $01 $c5 $10 $d0 $fe $28 $60 $a5 $11 $29 $83 +$48 $a5 $0d $45 $0e $30 $0a $a5 $0d $45 $0f $10 $04 $68 $09 $40 +$48 $68 $85 $11 $08 $a5 $0d $65 $0e $08 $c5 $0f $d0 $fe $68 $29 +$c3 $c5 $11 $d0 $fe $28 $08 $a5 $0d $e5 $12 $08 $c5 $0f $d0 $fe +$68 $29 $c3 $c5 $11 $d0 $fe $28 $08 $a5 $0d $6d $03 $02 $08 $c5 +$0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 $fe $28 $08 $a5 $0d $ed $04 +$02 $08 $c5 $0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 $fe $28 $08 $a5 +$0e $8d $12 $02 $a5 $0d $20 $11 $02 $08 $c5 $0f $d0 $fe $68 $29 +$c3 $c5 $11 $d0 $fe $28 $08 $a5 $12 $8d $15 $02 $a5 $0d $20 $14 +$02 $08 $c5 $0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 $fe $28 $08 $a5 +$0d $75 $00 $08 $c5 $0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 $fe $28 +$08 $a5 $0d $f5 $04 $08 $c5 $0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 +$fe $28 $08 $a5 $0d $7d $f5 $01 $08 $c5 $0f $d0 $fe $68 $29 $c3 +$c5 $11 $d0 $fe $28 $08 $a5 $0d $fd $f6 $01 $08 $c5 $0f $d0 $fe +$68 $29 $c3 $c5 $11 $d0 $fe $28 $08 $a5 $0d $79 $04 $01 $08 $c5 +$0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 $fe $28 $08 $a5 $0d $f9 $05 +$01 $08 $c5 $0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 $fe $28 $08 $a5 +$0d $61 $44 $08 $c5 $0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 $fe $28 +$08 $a5 $0d $e1 $46 $08 $c5 $0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 +$fe $28 $08 $a5 $0d $71 $56 $08 $c5 $0f $d0 $fe $68 $29 $c3 $c5 +$11 $d0 $fe $28 $08 $a5 $0d $f1 $58 $08 $c5 $0f $d0 $fe $68 $29 +$c3 $c5 $11 $d0 $fe $28 $60 $88 $88 $08 $88 $88 $88 $28 $b0 $fe +$70 $fe $30 $fe $f0 $fe $c9 $46 $d0 $fe $e0 $41 $d0 $fe $c0 $4f +$d0 $fe $48 $8a $48 $ba $e0 $fd $d0 $fe $68 $aa $a9 $ff $48 $28 +$68 $e8 $49 $aa $4c $0f $09 $00 $01 $37 $64 $09 $4c $fc $36 $88 +$88 $08 $88 $88 $88 $28 $b0 $fe $70 $fe $30 $fe $f0 $fe $c9 $49 +$d0 $fe $e0 $4e $d0 $fe $c0 $41 $d0 $fe $48 $8a $48 $ba $e0 $fd +$d0 $fe $68 $aa $a9 $ff $48 $28 $68 $e8 $49 $aa $6c $fa $36 $4c +$2f $37 $88 $88 $08 $88 $88 $88 $28 $b0 $fe $70 $fe $30 $fe $f0 +$fe $c9 $4a $d0 $fe $e0 $53 $d0 $fe $c0 $4f $d0 $fe $48 $8a $48 +$ba $e0 $fb $d0 $fe $ad $ff $01 $c9 $09 $d0 $fe $ad $fe $01 $c9 +$9a $d0 $fe $a9 $ff $48 $28 $68 $aa $68 $e8 $49 $aa $60 $4c $6e +$37 $4c $71 $37 $4c $74 $37 $88 $88 $08 $88 $88 $88 $c9 $42 $d0 +$fe $e0 $52 $d0 $fe $c0 $48 $d0 $fe $85 $0a $86 $0b $ba $bd $02 +$01 $c9 $30 $d0 $fe $68 $c9 $34 $d0 $fe $ba $e0 $fc $d0 $fe $ad +$ff $01 $c9 $09 $d0 $fe $ad $fe $01 $c9 $d1 $d0 $fe $a9 $ff $48 +$28 $a6 $0b $e8 $a5 $0a $49 $aa $40 $4c $b9 $37 $00 $00 $00 $00 +ORG +$fff0 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $71 $37 $74 $37 $79 $37 +EXEC +$0400 diff --git a/6502_func_test.lst b/6502_func_test.lst new file mode 100644 index 0000000..02f070b --- /dev/null +++ b/6502_func_test.lst @@ -0,0 +1,14236 @@ +AS65 Assembler for R6502 [1.42]. Page 1 +-------------------------- 6502_functional_test.asm -------------------------- + +6010 lines read, no errors in pass 1. + ; + ; 6 5 0 2 F U N C T I O N A L T E S T + ; + ; Copyright (C) 2012-2015 Klaus Dormann + ; + ; This program is free software: you can redistribute + ; it under the terms of the GNU General Public License + ; the Free Software Foundation, either version 3 of th + ; (at your option) any later version. + ; + ; This program is distributed in the hope that it will + ; but WITHOUT ANY WARRANTY; without even the implied w + ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + ; GNU General Public License for more details. + ; + ; You should have received a copy of the GNU General P + ; along with this program. If not, see -1 + check_ram macro + cld + lda #0 + sta zpt ;set low byte of indirect + sta zpt+3 ;checksum high byte + if disable_selfmod = 0 + sta range_adr ;reset self modifying code + endif + clc + ldx #zp_bss-zero_page ;zeropage - write te + ccs3\? adc zero_page,x + bcc ccs2\? + inc zpt+3 ;carry to high byte + clc + ccs2\? inx + bne ccs3\? + ldx #hi(abs1) ;set high byte of indirect + stx zpt+1 + ldy #lo(abs1) ;data after write & execut + ccs5\? adc (zpt),y + bcc ccs4\? + inc zpt+3 ;carry to high byte + clc + ccs4\? iny + bne ccs5\? + inx ;advance RAM high address + stx zpt+1 + cpx #ram_top + bne ccs5\? + sta zpt+2 ;checksum low is + cmp ram_chksm ;checksum low expected + trap_ne ;checksum mismatch + lda zpt+3 ;checksum high is + cmp ram_chksm+1 ;checksum high expected + trap_ne ;checksum mismatch + endm + else + check_ram macro + ;RAM check disabled - RAM size not set + endm + endif + + next_test macro ;make sure, tests don't ju + lda test_case ;previous test + cmp #test_num + trap_ne ;test is out of sequence + test_num = test_num + 1 + lda #test_num ;*** next tests' number + sta test_case + ;check_ram ;uncomment to find altere + endm + + if load_data_direct = 1 + data + else + bss ;uninitialized segment, co + endif +0000 = org 0 ;edited to load from 0x0000 (w +0000 : 00000000000000.. ds zero_page ;see above (this line added) + ;break test interrupt save +000a : 00 irq_a ds 1 ;a register +000b : 00 irq_x ds 1 ;x register + if I_flag = 2 + ;masking for I bit in status + flag_I_on ds 1 ;or mask to load flags + flag_I_off ds 1 ;and mask to load flags + endif +000c : zpt ;5 bytes store/modify test + ;add/subtract operand generation and result/flag predi +000c : 00 adfc ds 1 ;carry flag before op +000d : 00 ad1 ds 1 ;operand 1 - accumulator +000e : 00 ad2 ds 1 ;operand 2 - memory / imme +000f : 00 adrl ds 1 ;expected result bits 0-7 +0010 : 00 adrh ds 1 ;expected result bit 8 (ca +0011 : 00 adrf ds 1 ;expected flags NV0000ZC ( +0012 : 00 sb2 ds 1 ;operand 2 complemented fo +0013 : zp_bss +0013 : c3824100 zp1 db $c3,$82,$41,0 ;test patterns for LDx BIT +0017 : 7f zp7f db $7f ;test pattern for compare + ;logical zeropage operands +0018 : 001f7180 zpOR db 0,$1f,$71,$80 ;test pattern for OR +001c : 0fff7f80 zpAN db $0f,$ff,$7f,$80 ;test pattern for AND +0020 : ff0f8f8f zpEO db $ff,$0f,$8f,$8f ;test pattern for EOR + ;indirect addressing pointers +0024 : 1702 ind1 dw abs1 ;indirect pointer to patte +0026 : 1802 dw abs1+1 +0028 : 1902 dw abs1+2 +002a : 1a02 dw abs1+3 +002c : 1b02 dw abs7f +002e : 1f01 inw1 dw abs1-$f8 ;indirect pointer for wrap +0030 : 0302 indt dw abst ;indirect pointer to store +0032 : 0402 dw abst+1 +0034 : 0502 dw abst+2 +0036 : 0602 dw abst+3 +0038 : 0b01 inwt dw abst-$f8 ;indirect pointer for wrap +003a : 4e02 indAN dw absAN ;indirect pointer to AND p +003c : 4f02 dw absAN+1 +003e : 5002 dw absAN+2 +0040 : 5102 dw absAN+3 +0042 : 5202 indEO dw absEO ;indirect pointer to EOR p +0044 : 5302 dw absEO+1 +0046 : 5402 dw absEO+2 +0048 : 5502 dw absEO+3 +004a : 4a02 indOR dw absOR ;indirect pointer to OR pa +004c : 4b02 dw absOR+1 +004e : 4c02 dw absOR+2 +0050 : 4d02 dw absOR+3 + ;add/subtract indirect pointers +0052 : 0302 adi2 dw ada2 ;indirect pointer to opera +0054 : 0402 sbi2 dw sba2 ;indirect pointer to compl +0056 : 0401 adiy2 dw ada2-$ff ;with offset for indirect +0058 : 0501 sbiy2 dw sba2-$ff +005a : zp_bss_end + +0200 = org data_segment +0200 : 00 test_case ds 1 ;current test number +0201 : 0000 ram_chksm ds 2 ;checksum for RAM integrit + ;add/subtract operand copy - abs tests write area +0203 : abst ;5 bytes store/modify test +0203 : 00 ada2 ds 1 ;operand 2 +0204 : 00 sba2 ds 1 ;operand 2 complemented fo +0205 : 000000 ds 3 ;fill remaining bytes +0208 : data_bss + if load_data_direct = 1 +0208 : 2900 ex_andi and #0 ;execute immediate opcodes +020a : 60 rts +020b : 4900 ex_eori eor #0 ;execute immediate opcodes +020d : 60 rts +020e : 0900 ex_orai ora #0 ;execute immediate opcodes +0210 : 60 rts +0211 : 6900 ex_adci adc #0 ;execute immediate opcodes +0213 : 60 rts +0214 : e900 ex_sbci sbc #0 ;execute immediate opcodes +0216 : 60 rts + else + ex_andi ds 3 + ex_eori ds 3 + ex_orai ds 3 + ex_adci ds 3 + ex_sbci ds 3 + endif +0217 : c3824100 abs1 db $c3,$82,$41,0 ;test patterns for LDx BIT +021b : 7f abs7f db $7f ;test pattern for compare + ;loads +021c : 80800002 fLDx db fn,fn,0,fz ;expected flags for load + ;shifts +0220 : rASL ;expected result ASL & ROL +0220 : 86048200 rROL db $86,$04,$82,0 ; " +0224 : 87058301 rROLc db $87,$05,$83,1 ;expected result ROL +carr +0228 : rLSR ;expected result LSR & ROR +0228 : 61412000 rROR db $61,$41,$20,0 ; " +022c : e1c1a080 rRORc db $e1,$c1,$a0,$80 ;expected result ROR +carr +0230 : fASL ;expected flags for shifts +0230 : 81018002 fROL db fnc,fc,fn,fz ;no carry in +0234 : 81018000 fROLc db fnc,fc,fn,0 ;carry in +0238 : fLSR +0238 : 01000102 fROR db fc,0,fc,fz ;no carry in +023c : 81808180 fRORc db fnc,fn,fnc,fn ;carry in + ;increments (decrements) +0240 : 7f80ff0001 rINC db $7f,$80,$ff,0,1 ;expected result for INC/D +0245 : 0080800200 fINC db 0,fn,fn,fz,0 ;expected flags for INC/DE + ;logical memory operand +024a : 001f7180 absOR db 0,$1f,$71,$80 ;test pattern for OR +024e : 0fff7f80 absAN db $0f,$ff,$7f,$80 ;test pattern for AND +0252 : ff0f8f8f absEO db $ff,$0f,$8f,$8f ;test pattern for EOR + ;logical accu operand +0256 : 00f11f00 absORa db 0,$f1,$1f,0 ;test pattern for OR +025a : f0ffffff absANa db $f0,$ff,$ff,$ff ;test pattern for AND +025e : fff0f00f absEOa db $ff,$f0,$f0,$0f ;test pattern for EOR + ;logical results +0262 : 00ff7f80 absrlo db 0,$ff,$7f,$80 +0266 : 02800080 absflo db fz,fn,0,fn +026a : data_bss_end + + + code +0400 = org code_segment +0400 : d8 start cld +0401 : a2ff ldx #$ff +0403 : 9a txs +0404 : a900 lda #0 ;*** test 0 = initialize +0406 : 8d0002 sta test_case +0000 = test_num = 0 + + ;stop interrupts before initializing BSS + if I_flag = 1 + sei + endif + + ;initialize I/O for report channel + if report = 1 + jsr report_init + endif + + ;pretest small branch offset +0409 : a205 ldx #5 +040b : 4c3304 jmp psb_test +040e : psb_bwok +040e : a005 ldy #5 +0410 : d008 bne psb_forw + trap ;branch should be taken +0412 : 4c1204 > jmp * ;failed anyway + +0415 : 88 dey ;forward landing zone +0416 : 88 dey +0417 : 88 dey +0418 : 88 dey +0419 : 88 dey +041a : psb_forw +041a : 88 dey +041b : 88 dey +041c : 88 dey +041d : 88 dey +041e : 88 dey +041f : f017 beq psb_fwok + trap ;forward offset +0421 : 4c2104 > jmp * ;failed anyway + + +0424 : ca dex ;backward landing zone +0425 : ca dex +0426 : ca dex +0427 : ca dex +0428 : ca dex +0429 : psb_back +0429 : ca dex +042a : ca dex +042b : ca dex +042c : ca dex +042d : ca dex +042e : f0de beq psb_bwok + trap ;backward offset +0430 : 4c3004 > jmp * ;failed anyway + +0433 : psb_test +0433 : d0f4 bne psb_back + trap ;branch should be taken +0435 : 4c3504 > jmp * ;failed anyway + +0438 : psb_fwok + + ;initialize BSS segment + if load_data_direct != 1 + ldx #zp_end-zp_init-1 + ld_zp lda zp_init,x + sta zp_bss,x + dex + bpl ld_zp + ldx #data_end-data_init-1 + ld_data lda data_init,x + sta data_bss,x + dex + bpl ld_data + if ROM_vectors = 1 + ldx #5 + ld_vect lda vec_init,x + sta vec_bss,x + dex + bpl ld_vect + endif + endif + + ;retain status of interrupt flag + if I_flag = 2 + php + pla + and #4 ;isolate flag + sta flag_I_on ;or mask + eor #lo(~4) ;reverse + sta flag_I_off ;and mask + endif + + ;generate checksum for RAM integrity test + if ram_top > -1 + lda #0 + sta zpt ;set low byte of indirect poin + sta ram_chksm+1 ;checksum high byte + if disable_selfmod = 0 + sta range_adr ;reset self modifying code + endif + clc + ldx #zp_bss-zero_page ;zeropage - write test a + gcs3 adc zero_page,x + bcc gcs2 + inc ram_chksm+1 ;carry to high byte + clc + gcs2 inx + bne gcs3 + ldx #hi(abs1) ;set high byte of indirect poi + stx zpt+1 + ldy #lo(abs1) ;data after write & execute te + gcs5 adc (zpt),y + bcc gcs4 + inc ram_chksm+1 ;carry to high byte + clc + gcs4 iny + bne gcs5 + inx ;advance RAM high address + stx zpt+1 + cpx #ram_top + bne gcs5 + sta ram_chksm ;checksum complete + endif + next_test +0438 : ad0002 > lda test_case ;previous test +043b : c900 > cmp #test_num + > trap_ne ;test is out of sequence +043d : d0fe > bne * ;failed not equal (non zero) + > +0001 = >test_num = test_num + 1 +043f : a901 > lda #test_num ;*** next tests' number +0441 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + if disable_selfmod = 0 + ;testing relative addressing with BEQ +0444 : a0fe ldy #$fe ;testing maximum range, not -1 +0446 : range_loop +0446 : 88 dey ;next relative address +0447 : 98 tya +0448 : aa tax ;precharge count to end of loo +0449 : 1008 bpl range_fw ;calculate relative address +044b : 18 clc ;avoid branch self or to relat +044c : 6902 adc #2 +044e : ea nop ;offset landing zone - tolerat +044f : ea nop +0450 : ea nop +0451 : ea nop +0452 : ea nop +0453 : range_fw +0453 : ea nop +0454 : ea nop +0455 : ea nop +0456 : ea nop +0457 : ea nop +0458 : 497f eor #$7f ;complement except sign +045a : 8de604 sta range_adr ;load into test target +045d : a900 lda #0 ;should set zero flag in statu +045f : 4ce504 jmp range_op + +0462 : ca dex ; offset landing zone - backwa +0463 : ca dex +0464 : ca dex +0465 : ca dex +0466 : ca dex + ;relative address target field with branch und +0467 : ca dex ;-128 - max backward +0468 : ca dex +0469 : ca dex +046a : ca dex +046b : ca dex +046c : ca dex +046d : ca dex +046e : ca dex +046f : ca dex ;-120 +0470 : ca dex +0471 : ca dex +0472 : ca dex +0473 : ca dex +0474 : ca dex +0475 : ca dex +0476 : ca dex +0477 : ca dex +0478 : ca dex +0479 : ca dex ;-110 +047a : ca dex +047b : ca dex +047c : ca dex +047d : ca dex +047e : ca dex +047f : ca dex +0480 : ca dex +0481 : ca dex +0482 : ca dex +0483 : ca dex ;-100 +0484 : ca dex +0485 : ca dex +0486 : ca dex +0487 : ca dex +0488 : ca dex +0489 : ca dex +048a : ca dex +048b : ca dex +048c : ca dex +048d : ca dex ;-90 +048e : ca dex +048f : ca dex +0490 : ca dex +0491 : ca dex +0492 : ca dex +0493 : ca dex +0494 : ca dex +0495 : ca dex +0496 : ca dex +0497 : ca dex ;-80 +0498 : ca dex +0499 : ca dex +049a : ca dex +049b : ca dex +049c : ca dex +049d : ca dex +049e : ca dex +049f : ca dex +04a0 : ca dex +04a1 : ca dex ;-70 +04a2 : ca dex +04a3 : ca dex +04a4 : ca dex +04a5 : ca dex +04a6 : ca dex +04a7 : ca dex +04a8 : ca dex +04a9 : ca dex +04aa : ca dex +04ab : ca dex ;-60 +04ac : ca dex +04ad : ca dex +04ae : ca dex +04af : ca dex +04b0 : ca dex +04b1 : ca dex +04b2 : ca dex +04b3 : ca dex +04b4 : ca dex +04b5 : ca dex ;-50 +04b6 : ca dex +04b7 : ca dex +04b8 : ca dex +04b9 : ca dex +04ba : ca dex +04bb : ca dex +04bc : ca dex +04bd : ca dex +04be : ca dex +04bf : ca dex ;-40 +04c0 : ca dex +04c1 : ca dex +04c2 : ca dex +04c3 : ca dex +04c4 : ca dex +04c5 : ca dex +04c6 : ca dex +04c7 : ca dex +04c8 : ca dex +04c9 : ca dex ;-30 +04ca : ca dex +04cb : ca dex +04cc : ca dex +04cd : ca dex +04ce : ca dex +04cf : ca dex +04d0 : ca dex +04d1 : ca dex +04d2 : ca dex +04d3 : ca dex ;-20 +04d4 : ca dex +04d5 : ca dex +04d6 : ca dex +04d7 : ca dex +04d8 : ca dex +04d9 : ca dex +04da : ca dex +04db : ca dex +04dc : ca dex +04dd : ca dex ;-10 +04de : ca dex +04df : ca dex +04e0 : ca dex +04e1 : ca dex +04e2 : ca dex +04e3 : ca dex +04e4 : ca dex ;-3 +04e5 : range_op ;test target with zero flag=0, +04e6 = range_adr = *+1 ;modifiable relative address +04e5 : f03e beq *+64 ;+64 if called without modific +04e7 : ca dex ;+0 +04e8 : ca dex +04e9 : ca dex +04ea : ca dex +04eb : ca dex +04ec : ca dex +04ed : ca dex +04ee : ca dex +04ef : ca dex +04f0 : ca dex +04f1 : ca dex ;+10 +04f2 : ca dex +04f3 : ca dex +04f4 : ca dex +04f5 : ca dex +04f6 : ca dex +04f7 : ca dex +04f8 : ca dex +04f9 : ca dex +04fa : ca dex +04fb : ca dex ;+20 +04fc : ca dex +04fd : ca dex +04fe : ca dex +04ff : ca dex +0500 : ca dex +0501 : ca dex +0502 : ca dex +0503 : ca dex +0504 : ca dex +0505 : ca dex ;+30 +0506 : ca dex +0507 : ca dex +0508 : ca dex +0509 : ca dex +050a : ca dex +050b : ca dex +050c : ca dex +050d : ca dex +050e : ca dex +050f : ca dex ;+40 +0510 : ca dex +0511 : ca dex +0512 : ca dex +0513 : ca dex +0514 : ca dex +0515 : ca dex +0516 : ca dex +0517 : ca dex +0518 : ca dex +0519 : ca dex ;+50 +051a : ca dex +051b : ca dex +051c : ca dex +051d : ca dex +051e : ca dex +051f : ca dex +0520 : ca dex +0521 : ca dex +0522 : ca dex +0523 : ca dex ;+60 +0524 : ca dex +0525 : ca dex +0526 : ca dex +0527 : ca dex +0528 : ca dex +0529 : ca dex +052a : ca dex +052b : ca dex +052c : ca dex +052d : ca dex ;+70 +052e : ca dex +052f : ca dex +0530 : ca dex +0531 : ca dex +0532 : ca dex +0533 : ca dex +0534 : ca dex +0535 : ca dex +0536 : ca dex +0537 : ca dex ;+80 +0538 : ca dex +0539 : ca dex +053a : ca dex +053b : ca dex +053c : ca dex +053d : ca dex +053e : ca dex +053f : ca dex +0540 : ca dex +0541 : ca dex ;+90 +0542 : ca dex +0543 : ca dex +0544 : ca dex +0545 : ca dex +0546 : ca dex +0547 : ca dex +0548 : ca dex +0549 : ca dex +054a : ca dex +054b : ca dex ;+100 +054c : ca dex +054d : ca dex +054e : ca dex +054f : ca dex +0550 : ca dex +0551 : ca dex +0552 : ca dex +0553 : ca dex +0554 : ca dex +0555 : ca dex ;+110 +0556 : ca dex +0557 : ca dex +0558 : ca dex +0559 : ca dex +055a : ca dex +055b : ca dex +055c : ca dex +055d : ca dex +055e : ca dex +055f : ca dex ;+120 +0560 : ca dex +0561 : ca dex +0562 : ca dex +0563 : ca dex +0564 : ca dex +0565 : ca dex +0566 : ea nop ;offset landing zone - forward +0567 : ea nop +0568 : ea nop +0569 : ea nop +056a : ea nop +056b : f008 beq range_ok ;+127 - max forward + trap ; bad range +056d : 4c6d05 > jmp * ;failed anyway + +0570 : ea nop ;offset landing zone - tolerat +0571 : ea nop +0572 : ea nop +0573 : ea nop +0574 : ea nop +0575 : range_ok +0575 : ea nop +0576 : ea nop +0577 : ea nop +0578 : ea nop +0579 : ea nop +057a : c000 cpy #0 +057c : f003 beq range_end +057e : 4c4604 jmp range_loop +0581 : range_end ;range test successful + endif + next_test +0581 : ad0002 > lda test_case ;previous test +0584 : c901 > cmp #test_num + > trap_ne ;test is out of sequence +0586 : d0fe > bne * ;failed not equal (non zero) + > +0002 = >test_num = test_num + 1 +0588 : a902 > lda #test_num ;*** next tests' number +058a : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ;partial test BNE & CMP, CPX, CPY immediate +058d : c001 cpy #1 ;testing BNE true +058f : d003 bne test_bne + trap +0591 : 4c9105 > jmp * ;failed anyway + +0594 : test_bne +0594 : a900 lda #0 +0596 : c900 cmp #0 ;test compare immediate + trap_ne +0598 : d0fe > bne * ;failed not equal (non zero) + + trap_cc +059a : 90fe > bcc * ;failed carry clear + + trap_mi +059c : 30fe > bmi * ;failed minus (bit 7 set) + +059e : c901 cmp #1 + trap_eq +05a0 : f0fe > beq * ;failed equal (zero) + + trap_cs +05a2 : b0fe > bcs * ;failed carry set + + trap_pl +05a4 : 10fe > bpl * ;failed plus (bit 7 clear) + +05a6 : aa tax +05a7 : e000 cpx #0 ;test compare x immediate + trap_ne +05a9 : d0fe > bne * ;failed not equal (non zero) + + trap_cc +05ab : 90fe > bcc * ;failed carry clear + + trap_mi +05ad : 30fe > bmi * ;failed minus (bit 7 set) + +05af : e001 cpx #1 + trap_eq +05b1 : f0fe > beq * ;failed equal (zero) + + trap_cs +05b3 : b0fe > bcs * ;failed carry set + + trap_pl +05b5 : 10fe > bpl * ;failed plus (bit 7 clear) + +05b7 : a8 tay +05b8 : c000 cpy #0 ;test compare y immediate + trap_ne +05ba : d0fe > bne * ;failed not equal (non zero) + + trap_cc +05bc : 90fe > bcc * ;failed carry clear + + trap_mi +05be : 30fe > bmi * ;failed minus (bit 7 set) + +05c0 : c001 cpy #1 + trap_eq +05c2 : f0fe > beq * ;failed equal (zero) + + trap_cs +05c4 : b0fe > bcs * ;failed carry set + + trap_pl +05c6 : 10fe > bpl * ;failed plus (bit 7 clear) + + next_test +05c8 : ad0002 > lda test_case ;previous test +05cb : c902 > cmp #test_num + > trap_ne ;test is out of sequence +05cd : d0fe > bne * ;failed not equal (non zero) + > +0003 = >test_num = test_num + 1 +05cf : a903 > lda #test_num ;*** next tests' number +05d1 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + ;testing stack operations PHA PHP PLA PLP + +05d4 : a2ff ldx #$ff ;initialize stack +05d6 : 9a txs +05d7 : a955 lda #$55 +05d9 : 48 pha +05da : a9aa lda #$aa +05dc : 48 pha +05dd : cdfe01 cmp $1fe ;on stack ? + trap_ne +05e0 : d0fe > bne * ;failed not equal (non zero) + +05e2 : ba tsx +05e3 : 8a txa ;overwrite accu +05e4 : c9fd cmp #$fd ;sp decremented? + trap_ne +05e6 : d0fe > bne * ;failed not equal (non zero) + +05e8 : 68 pla +05e9 : c9aa cmp #$aa ;successful retreived from sta + trap_ne +05eb : d0fe > bne * ;failed not equal (non zero) + +05ed : 68 pla +05ee : c955 cmp #$55 + trap_ne +05f0 : d0fe > bne * ;failed not equal (non zero) + +05f2 : cdff01 cmp $1ff ;remains on stack? + trap_ne +05f5 : d0fe > bne * ;failed not equal (non zero) + +05f7 : ba tsx +05f8 : e0ff cpx #$ff ;sp incremented? + trap_ne +05fa : d0fe > bne * ;failed not equal (non zero) + + next_test +05fc : ad0002 > lda test_case ;previous test +05ff : c903 > cmp #test_num + > trap_ne ;test is out of sequence +0601 : d0fe > bne * ;failed not equal (non zero) + > +0004 = >test_num = test_num + 1 +0603 : a904 > lda #test_num ;*** next tests' number +0605 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ;testing branch decisions BPL BMI BVC BVS BCC BCS BNE + set_stat $ff ;all on + > load_flag $ff +0608 : a9ff > lda #$ff ;allow test to ch + > +060a : 48 > pha ;use stack to load status +060b : 28 > plp + +060c : 101a bpl nbr1 ;branches should not be taken +060e : 501b bvc nbr2 +0610 : 901c bcc nbr3 +0612 : d01d bne nbr4 +0614 : 3003 bmi br1 ;branches should be taken + trap +0616 : 4c1606 > jmp * ;failed anyway + +0619 : 7003 br1 bvs br2 + trap +061b : 4c1b06 > jmp * ;failed anyway + +061e : b003 br2 bcs br3 + trap +0620 : 4c2006 > jmp * ;failed anyway + +0623 : f00f br3 beq br4 + trap +0625 : 4c2506 > jmp * ;failed anyway + +0628 : nbr1 + trap ;previous bpl taken +0628 : 4c2806 > jmp * ;failed anyway + +062b : nbr2 + trap ;previous bvc taken +062b : 4c2b06 > jmp * ;failed anyway + +062e : nbr3 + trap ;previous bcc taken +062e : 4c2e06 > jmp * ;failed anyway + +0631 : nbr4 + trap ;previous bne taken +0631 : 4c3106 > jmp * ;failed anyway + +0634 : 08 br4 php +0635 : ba tsx +0636 : e0fe cpx #$fe ;sp after php? + trap_ne +0638 : d0fe > bne * ;failed not equal (non zero) + +063a : 68 pla + cmp_flag $ff ;returned all flags on? +063b : c9ff > cmp #($ff |fao)&m8 ;expected flags + + + trap_ne +063d : d0fe > bne * ;failed not equal (non zero) + +063f : ba tsx +0640 : e0ff cpx #$ff ;sp after php? + trap_ne +0642 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 ;all off + > load_flag 0 +0644 : a900 > lda #0 ;allow test to ch + > +0646 : 48 > pha ;use stack to load status +0647 : 28 > plp + +0648 : 301a bmi nbr11 ;branches should not be taken +064a : 701b bvs nbr12 +064c : b01c bcs nbr13 +064e : f01d beq nbr14 +0650 : 1003 bpl br11 ;branches should be taken + trap +0652 : 4c5206 > jmp * ;failed anyway + +0655 : 5003 br11 bvc br12 + trap +0657 : 4c5706 > jmp * ;failed anyway + +065a : 9003 br12 bcc br13 + trap +065c : 4c5c06 > jmp * ;failed anyway + +065f : d00f br13 bne br14 + trap +0661 : 4c6106 > jmp * ;failed anyway + +0664 : nbr11 + trap ;previous bmi taken +0664 : 4c6406 > jmp * ;failed anyway + +0667 : nbr12 + trap ;previous bvs taken +0667 : 4c6706 > jmp * ;failed anyway + +066a : nbr13 + trap ;previous bcs taken +066a : 4c6a06 > jmp * ;failed anyway + +066d : nbr14 + trap ;previous beq taken +066d : 4c6d06 > jmp * ;failed anyway + +0670 : 08 br14 php +0671 : 68 pla + cmp_flag 0 ;flags off except break (pushe +0672 : c930 > cmp #(0 |fao)&m8 ;expected flags + + + trap_ne +0674 : d0fe > bne * ;failed not equal (non zero) + + ;crosscheck flags + set_stat zero + > load_flag zero +0676 : a902 > lda #zero ;allow test to chang + > +0678 : 48 > pha ;use stack to load status +0679 : 28 > plp + +067a : d002 bne brzs1 +067c : f003 beq brzs2 +067e : brzs1 + trap ;branch zero/non zero +067e : 4c7e06 > jmp * ;failed anyway + +0681 : b002 brzs2 bcs brzs3 +0683 : 9003 bcc brzs4 +0685 : brzs3 + trap ;branch carry/no carry +0685 : 4c8506 > jmp * ;failed anyway + +0688 : 3002 brzs4 bmi brzs5 +068a : 1003 bpl brzs6 +068c : brzs5 + trap ;branch minus/plus +068c : 4c8c06 > jmp * ;failed anyway + +068f : 7002 brzs6 bvs brzs7 +0691 : 5003 bvc brzs8 +0693 : brzs7 + trap ;branch overflow/no overflow +0693 : 4c9306 > jmp * ;failed anyway + +0696 : brzs8 + set_stat carry + > load_flag carry +0696 : a901 > lda #carry ;allow test to chan + > +0698 : 48 > pha ;use stack to load status +0699 : 28 > plp + +069a : f002 beq brcs1 +069c : d003 bne brcs2 +069e : brcs1 + trap ;branch zero/non zero +069e : 4c9e06 > jmp * ;failed anyway + +06a1 : 9002 brcs2 bcc brcs3 +06a3 : b003 bcs brcs4 +06a5 : brcs3 + trap ;branch carry/no carry +06a5 : 4ca506 > jmp * ;failed anyway + +06a8 : 3002 brcs4 bmi brcs5 +06aa : 1003 bpl brcs6 +06ac : brcs5 + trap ;branch minus/plus +06ac : 4cac06 > jmp * ;failed anyway + +06af : 7002 brcs6 bvs brcs7 +06b1 : 5003 bvc brcs8 +06b3 : brcs7 + trap ;branch overflow/no overflow +06b3 : 4cb306 > jmp * ;failed anyway + + +06b6 : brcs8 + set_stat minus + > load_flag minus +06b6 : a980 > lda #minus ;allow test to chan + > +06b8 : 48 > pha ;use stack to load status +06b9 : 28 > plp + +06ba : f002 beq brmi1 +06bc : d003 bne brmi2 +06be : brmi1 + trap ;branch zero/non zero +06be : 4cbe06 > jmp * ;failed anyway + +06c1 : b002 brmi2 bcs brmi3 +06c3 : 9003 bcc brmi4 +06c5 : brmi3 + trap ;branch carry/no carry +06c5 : 4cc506 > jmp * ;failed anyway + +06c8 : 1002 brmi4 bpl brmi5 +06ca : 3003 bmi brmi6 +06cc : brmi5 + trap ;branch minus/plus +06cc : 4ccc06 > jmp * ;failed anyway + +06cf : 7002 brmi6 bvs brmi7 +06d1 : 5003 bvc brmi8 +06d3 : brmi7 + trap ;branch overflow/no overflow +06d3 : 4cd306 > jmp * ;failed anyway + +06d6 : brmi8 + set_stat overfl + > load_flag overfl +06d6 : a940 > lda #overfl ;allow test to cha + > +06d8 : 48 > pha ;use stack to load status +06d9 : 28 > plp + +06da : f002 beq brvs1 +06dc : d003 bne brvs2 +06de : brvs1 + trap ;branch zero/non zero +06de : 4cde06 > jmp * ;failed anyway + +06e1 : b002 brvs2 bcs brvs3 +06e3 : 9003 bcc brvs4 +06e5 : brvs3 + trap ;branch carry/no carry +06e5 : 4ce506 > jmp * ;failed anyway + +06e8 : 3002 brvs4 bmi brvs5 +06ea : 1003 bpl brvs6 +06ec : brvs5 + trap ;branch minus/plus +06ec : 4cec06 > jmp * ;failed anyway + +06ef : 5002 brvs6 bvc brvs7 +06f1 : 7003 bvs brvs8 +06f3 : brvs7 + trap ;branch overflow/no overflow +06f3 : 4cf306 > jmp * ;failed anyway + +06f6 : brvs8 + set_stat $ff-zero + > load_flag $ff-zero +06f6 : a9fd > lda #$ff-zero ;allow test to c + > +06f8 : 48 > pha ;use stack to load status +06f9 : 28 > plp + +06fa : f002 beq brzc1 +06fc : d003 bne brzc2 +06fe : brzc1 + trap ;branch zero/non zero +06fe : 4cfe06 > jmp * ;failed anyway + +0701 : 9002 brzc2 bcc brzc3 +0703 : b003 bcs brzc4 +0705 : brzc3 + trap ;branch carry/no carry +0705 : 4c0507 > jmp * ;failed anyway + +0708 : 1002 brzc4 bpl brzc5 +070a : 3003 bmi brzc6 +070c : brzc5 + trap ;branch minus/plus +070c : 4c0c07 > jmp * ;failed anyway + +070f : 5002 brzc6 bvc brzc7 +0711 : 7003 bvs brzc8 +0713 : brzc7 + trap ;branch overflow/no overflow +0713 : 4c1307 > jmp * ;failed anyway + +0716 : brzc8 + set_stat $ff-carry + > load_flag $ff-carry +0716 : a9fe > lda #$ff-carry ;allow test to + > +0718 : 48 > pha ;use stack to load status +0719 : 28 > plp + +071a : d002 bne brcc1 +071c : f003 beq brcc2 +071e : brcc1 + trap ;branch zero/non zero +071e : 4c1e07 > jmp * ;failed anyway + +0721 : b002 brcc2 bcs brcc3 +0723 : 9003 bcc brcc4 +0725 : brcc3 + trap ;branch carry/no carry +0725 : 4c2507 > jmp * ;failed anyway + +0728 : 1002 brcc4 bpl brcc5 +072a : 3003 bmi brcc6 +072c : brcc5 + trap ;branch minus/plus +072c : 4c2c07 > jmp * ;failed anyway + +072f : 5002 brcc6 bvc brcc7 +0731 : 7003 bvs brcc8 +0733 : brcc7 + trap ;branch overflow/no overflow +0733 : 4c3307 > jmp * ;failed anyway + +0736 : brcc8 + set_stat $ff-minus + > load_flag $ff-minus +0736 : a97f > lda #$ff-minus ;allow test to + > +0738 : 48 > pha ;use stack to load status +0739 : 28 > plp + +073a : d002 bne brpl1 +073c : f003 beq brpl2 +073e : brpl1 + trap ;branch zero/non zero +073e : 4c3e07 > jmp * ;failed anyway + +0741 : 9002 brpl2 bcc brpl3 +0743 : b003 bcs brpl4 +0745 : brpl3 + trap ;branch carry/no carry +0745 : 4c4507 > jmp * ;failed anyway + +0748 : 3002 brpl4 bmi brpl5 +074a : 1003 bpl brpl6 +074c : brpl5 + trap ;branch minus/plus +074c : 4c4c07 > jmp * ;failed anyway + +074f : 5002 brpl6 bvc brpl7 +0751 : 7003 bvs brpl8 +0753 : brpl7 + trap ;branch overflow/no overflow +0753 : 4c5307 > jmp * ;failed anyway + +0756 : brpl8 + set_stat $ff-overfl + > load_flag $ff-overfl +0756 : a9bf > lda #$ff-overfl ;allow test to + > +0758 : 48 > pha ;use stack to load status +0759 : 28 > plp + +075a : d002 bne brvc1 +075c : f003 beq brvc2 +075e : brvc1 + trap ;branch zero/non zero +075e : 4c5e07 > jmp * ;failed anyway + +0761 : 9002 brvc2 bcc brvc3 +0763 : b003 bcs brvc4 +0765 : brvc3 + trap ;branch carry/no carry +0765 : 4c6507 > jmp * ;failed anyway + +0768 : 1002 brvc4 bpl brvc5 +076a : 3003 bmi brvc6 +076c : brvc5 + trap ;branch minus/plus +076c : 4c6c07 > jmp * ;failed anyway + +076f : 7002 brvc6 bvs brvc7 +0771 : 5003 bvc brvc8 +0773 : brvc7 + trap ;branch overflow/no overflow +0773 : 4c7307 > jmp * ;failed anyway + +0776 : brvc8 + next_test +0776 : ad0002 > lda test_case ;previous test +0779 : c904 > cmp #test_num + > trap_ne ;test is out of sequence +077b : d0fe > bne * ;failed not equal (non zero) + > +0005 = >test_num = test_num + 1 +077d : a905 > lda #test_num ;*** next tests' number +077f : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; test PHA does not alter flags or accumulator but PLA +0782 : a255 ldx #$55 ;x & y protected +0784 : a0aa ldy #$aa + set_a 1,$ff ;push + > load_flag $ff +0786 : a9ff > lda #$ff ;allow test to c + > +0788 : 48 > pha ;use stack to load status +0789 : a901 > lda #1 ;precharge accu +078b : 28 > plp + +078c : 48 pha + tst_a 1,$ff +078d : 08 > php ;save flags +078e : c901 > cmp #1 ;test result + > trap_ne +0790 : d0fe > bne * ;failed not equal (non zero) + > +0792 : 68 > pla ;load status +0793 : 48 > pha + > cmp_flag $ff +0794 : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + > + > trap_ne +0796 : d0fe > bne * ;failed not equal (non zero) + > +0798 : 28 > plp ;restore status + + set_a 0,0 + > load_flag 0 +0799 : a900 > lda #0 ;allow test to change I + > +079b : 48 > pha ;use stack to load status +079c : a900 > lda #0 ;precharge accu +079e : 28 > plp + +079f : 48 pha + tst_a 0,0 +07a0 : 08 > php ;save flags +07a1 : c900 > cmp #0 ;test result + > trap_ne +07a3 : d0fe > bne * ;failed not equal (non zero) + > +07a5 : 68 > pla ;load status +07a6 : 48 > pha + > cmp_flag 0 +07a7 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +07a9 : d0fe > bne * ;failed not equal (non zero) + > +07ab : 28 > plp ;restore status + + set_a $ff,$ff + > load_flag $ff +07ac : a9ff > lda #$ff ;allow test to change + > +07ae : 48 > pha ;use stack to load status +07af : a9ff > lda #$ff ;precharge accu +07b1 : 28 > plp + +07b2 : 48 pha + tst_a $ff,$ff +07b3 : 08 > php ;save flags +07b4 : c9ff > cmp #$ff ;test result + > trap_ne +07b6 : d0fe > bne * ;failed not equal (non zero) + > +07b8 : 68 > pla ;load status +07b9 : 48 > pha + > cmp_flag $ff +07ba : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + > + > trap_ne +07bc : d0fe > bne * ;failed not equal (non zero) + > +07be : 28 > plp ;restore status + + set_a 1,0 + > load_flag 0 +07bf : a900 > lda #0 ;allow test to change I + > +07c1 : 48 > pha ;use stack to load status +07c2 : a901 > lda #1 ;precharge accu +07c4 : 28 > plp + +07c5 : 48 pha + tst_a 1,0 +07c6 : 08 > php ;save flags +07c7 : c901 > cmp #1 ;test result + > trap_ne +07c9 : d0fe > bne * ;failed not equal (non zero) + > +07cb : 68 > pla ;load status +07cc : 48 > pha + > cmp_flag 0 +07cd : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +07cf : d0fe > bne * ;failed not equal (non zero) + > +07d1 : 28 > plp ;restore status + + set_a 0,$ff + > load_flag $ff +07d2 : a9ff > lda #$ff ;allow test to change + > +07d4 : 48 > pha ;use stack to load status +07d5 : a900 > lda #0 ;precharge accu +07d7 : 28 > plp + +07d8 : 48 pha + tst_a 0,$ff +07d9 : 08 > php ;save flags +07da : c900 > cmp #0 ;test result + > trap_ne +07dc : d0fe > bne * ;failed not equal (non zero) + > +07de : 68 > pla ;load status +07df : 48 > pha + > cmp_flag $ff +07e0 : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + > + > trap_ne +07e2 : d0fe > bne * ;failed not equal (non zero) + > +07e4 : 28 > plp ;restore status + + set_a $ff,0 + > load_flag 0 +07e5 : a900 > lda #0 ;allow test to change I + > +07e7 : 48 > pha ;use stack to load status +07e8 : a9ff > lda #$ff ;precharge accu +07ea : 28 > plp + +07eb : 48 pha + tst_a $ff,0 +07ec : 08 > php ;save flags +07ed : c9ff > cmp #$ff ;test result + > trap_ne +07ef : d0fe > bne * ;failed not equal (non zero) + > +07f1 : 68 > pla ;load status +07f2 : 48 > pha + > cmp_flag 0 +07f3 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +07f5 : d0fe > bne * ;failed not equal (non zero) + > +07f7 : 28 > plp ;restore status + + set_a 0,$ff ;pull + > load_flag $ff +07f8 : a9ff > lda #$ff ;allow test to c + > +07fa : 48 > pha ;use stack to load status +07fb : a900 > lda #0 ;precharge accu +07fd : 28 > plp + +07fe : 68 pla + tst_a $ff,$ff-zero +07ff : 08 > php ;save flags +0800 : c9ff > cmp #$ff ;test result + > trap_ne +0802 : d0fe > bne * ;failed not equal (non zero) + > +0804 : 68 > pla ;load status +0805 : 48 > pha + > cmp_flag $ff-zero +0806 : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0808 : d0fe > bne * ;failed not equal (non zero) + > +080a : 28 > plp ;restore status + + set_a $ff,0 + > load_flag 0 +080b : a900 > lda #0 ;allow test to change I + > +080d : 48 > pha ;use stack to load status +080e : a9ff > lda #$ff ;precharge accu +0810 : 28 > plp + +0811 : 68 pla + tst_a 0,zero +0812 : 08 > php ;save flags +0813 : c900 > cmp #0 ;test result + > trap_ne +0815 : d0fe > bne * ;failed not equal (non zero) + > +0817 : 68 > pla ;load status +0818 : 48 > pha + > cmp_flag zero +0819 : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +081b : d0fe > bne * ;failed not equal (non zero) + > +081d : 28 > plp ;restore status + + set_a $fe,$ff + > load_flag $ff +081e : a9ff > lda #$ff ;allow test to change + > +0820 : 48 > pha ;use stack to load status +0821 : a9fe > lda #$fe ;precharge accu +0823 : 28 > plp + +0824 : 68 pla + tst_a 1,$ff-zero-minus +0825 : 08 > php ;save flags +0826 : c901 > cmp #1 ;test result + > trap_ne +0828 : d0fe > bne * ;failed not equal (non zero) + > +082a : 68 > pla ;load status +082b : 48 > pha + > cmp_flag $ff-zero-minus +082c : c97d > cmp #($ff-zero-minus|fao)&m8 ;expected + > + > trap_ne +082e : d0fe > bne * ;failed not equal (non zero) + > +0830 : 28 > plp ;restore status + + set_a 0,0 + > load_flag 0 +0831 : a900 > lda #0 ;allow test to change I + > +0833 : 48 > pha ;use stack to load status +0834 : a900 > lda #0 ;precharge accu +0836 : 28 > plp + +0837 : 68 pla + tst_a $ff,minus +0838 : 08 > php ;save flags +0839 : c9ff > cmp #$ff ;test result + > trap_ne +083b : d0fe > bne * ;failed not equal (non zero) + > +083d : 68 > pla ;load status +083e : 48 > pha + > cmp_flag minus +083f : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + > + > trap_ne +0841 : d0fe > bne * ;failed not equal (non zero) + > +0843 : 28 > plp ;restore status + + set_a $ff,$ff + > load_flag $ff +0844 : a9ff > lda #$ff ;allow test to change + > +0846 : 48 > pha ;use stack to load status +0847 : a9ff > lda #$ff ;precharge accu +0849 : 28 > plp + +084a : 68 pla + tst_a 0,$ff-minus +084b : 08 > php ;save flags +084c : c900 > cmp #0 ;test result + > trap_ne +084e : d0fe > bne * ;failed not equal (non zero) + > +0850 : 68 > pla ;load status +0851 : 48 > pha + > cmp_flag $ff-minus +0852 : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0854 : d0fe > bne * ;failed not equal (non zero) + > +0856 : 28 > plp ;restore status + + set_a $fe,0 + > load_flag 0 +0857 : a900 > lda #0 ;allow test to change I + > +0859 : 48 > pha ;use stack to load status +085a : a9fe > lda #$fe ;precharge accu +085c : 28 > plp + +085d : 68 pla + tst_a 1,0 +085e : 08 > php ;save flags +085f : c901 > cmp #1 ;test result + > trap_ne +0861 : d0fe > bne * ;failed not equal (non zero) + > +0863 : 68 > pla ;load status +0864 : 48 > pha + > cmp_flag 0 +0865 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0867 : d0fe > bne * ;failed not equal (non zero) + > +0869 : 28 > plp ;restore status + +086a : e055 cpx #$55 ;x & y unchanged? + trap_ne +086c : d0fe > bne * ;failed not equal (non zero) + +086e : c0aa cpy #$aa + trap_ne +0870 : d0fe > bne * ;failed not equal (non zero) + + next_test +0872 : ad0002 > lda test_case ;previous test +0875 : c905 > cmp #test_num + > trap_ne ;test is out of sequence +0877 : d0fe > bne * ;failed not equal (non zero) + > +0006 = >test_num = test_num + 1 +0879 : a906 > lda #test_num ;*** next tests' number +087b : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; partial pretest EOR # + set_a $3c,0 + > load_flag 0 +087e : a900 > lda #0 ;allow test to change I + > +0880 : 48 > pha ;use stack to load status +0881 : a93c > lda #$3c ;precharge accu +0883 : 28 > plp + +0884 : 49c3 eor #$c3 + tst_a $ff,fn +0886 : 08 > php ;save flags +0887 : c9ff > cmp #$ff ;test result + > trap_ne +0889 : d0fe > bne * ;failed not equal (non zero) + > +088b : 68 > pla ;load status +088c : 48 > pha + > cmp_flag fn +088d : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +088f : d0fe > bne * ;failed not equal (non zero) + > +0891 : 28 > plp ;restore status + + set_a $c3,0 + > load_flag 0 +0892 : a900 > lda #0 ;allow test to change I + > +0894 : 48 > pha ;use stack to load status +0895 : a9c3 > lda #$c3 ;precharge accu +0897 : 28 > plp + +0898 : 49c3 eor #$c3 + tst_a 0,fz +089a : 08 > php ;save flags +089b : c900 > cmp #0 ;test result + > trap_ne +089d : d0fe > bne * ;failed not equal (non zero) + > +089f : 68 > pla ;load status +08a0 : 48 > pha + > cmp_flag fz +08a1 : c932 > cmp #(fz|fao)&m8 ;expected flags + alwa + > + > trap_ne +08a3 : d0fe > bne * ;failed not equal (non zero) + > +08a5 : 28 > plp ;restore status + + next_test +08a6 : ad0002 > lda test_case ;previous test +08a9 : c906 > cmp #test_num + > trap_ne ;test is out of sequence +08ab : d0fe > bne * ;failed not equal (non zero) + > +0007 = >test_num = test_num + 1 +08ad : a907 > lda #test_num ;*** next tests' number +08af : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; PC modifying instructions except branches (NOP, JMP, + ; testing NOP +08b2 : a224 ldx #$24 +08b4 : a042 ldy #$42 + set_a $18,0 + > load_flag 0 +08b6 : a900 > lda #0 ;allow test to change I + > +08b8 : 48 > pha ;use stack to load status +08b9 : a918 > lda #$18 ;precharge accu +08bb : 28 > plp + +08bc : ea nop + tst_a $18,0 +08bd : 08 > php ;save flags +08be : c918 > cmp #$18 ;test result + > trap_ne +08c0 : d0fe > bne * ;failed not equal (non zero) + > +08c2 : 68 > pla ;load status +08c3 : 48 > pha + > cmp_flag 0 +08c4 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +08c6 : d0fe > bne * ;failed not equal (non zero) + > +08c8 : 28 > plp ;restore status + +08c9 : e024 cpx #$24 + trap_ne +08cb : d0fe > bne * ;failed not equal (non zero) + +08cd : c042 cpy #$42 + trap_ne +08cf : d0fe > bne * ;failed not equal (non zero) + +08d1 : a2db ldx #$db +08d3 : a0bd ldy #$bd + set_a $e7,$ff + > load_flag $ff +08d5 : a9ff > lda #$ff ;allow test to change + > +08d7 : 48 > pha ;use stack to load status +08d8 : a9e7 > lda #$e7 ;precharge accu +08da : 28 > plp + +08db : ea nop + tst_a $e7,$ff +08dc : 08 > php ;save flags +08dd : c9e7 > cmp #$e7 ;test result + > trap_ne +08df : d0fe > bne * ;failed not equal (non zero) + > +08e1 : 68 > pla ;load status +08e2 : 48 > pha + > cmp_flag $ff +08e3 : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + > + > trap_ne +08e5 : d0fe > bne * ;failed not equal (non zero) + > +08e7 : 28 > plp ;restore status + +08e8 : e0db cpx #$db + trap_ne +08ea : d0fe > bne * ;failed not equal (non zero) + +08ec : c0bd cpy #$bd + trap_ne +08ee : d0fe > bne * ;failed not equal (non zero) + + next_test +08f0 : ad0002 > lda test_case ;previous test +08f3 : c907 > cmp #test_num + > trap_ne ;test is out of sequence +08f5 : d0fe > bne * ;failed not equal (non zero) + > +0008 = >test_num = test_num + 1 +08f7 : a908 > lda #test_num ;*** next tests' number +08f9 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; jump absolute + set_stat $0 + > load_flag $0 +08fc : a900 > lda #$0 ;allow test to change + > +08fe : 48 > pha ;use stack to load status +08ff : 28 > plp + +0900 : a946 lda #'F' +0902 : a241 ldx #'A' +0904 : a052 ldy #'R' ;N=0, V=0, Z=0, C=0 +0906 : 4cc936 jmp test_far +0909 : ea nop +090a : ea nop + trap_ne ;runover protection +090b : d0fe > bne * ;failed not equal (non zero) + +090d : e8 inx +090e : e8 inx +090f : far_ret + trap_eq ;returned flags OK? +090f : f0fe > beq * ;failed equal (zero) + + trap_pl +0911 : 10fe > bpl * ;failed plus (bit 7 clear) + + trap_cc +0913 : 90fe > bcc * ;failed carry clear + + trap_vc +0915 : 50fe > bvc * ;failed overflow clear + +0917 : c9ec cmp #('F'^$aa) ;returned registers OK? + trap_ne +0919 : d0fe > bne * ;failed not equal (non zero) + +091b : e042 cpx #('A'+1) + trap_ne +091d : d0fe > bne * ;failed not equal (non zero) + +091f : c04f cpy #('R'-3) + trap_ne +0921 : d0fe > bne * ;failed not equal (non zero) + +0923 : ca dex +0924 : c8 iny +0925 : c8 iny +0926 : c8 iny +0927 : 49aa eor #$aa ;N=0, V=1, Z=0, C=1 +0929 : 4c3209 jmp test_near +092c : ea nop +092d : ea nop + trap_ne ;runover protection +092e : d0fe > bne * ;failed not equal (non zero) + +0930 : e8 inx +0931 : e8 inx +0932 : test_near + trap_eq ;passed flags OK? +0932 : f0fe > beq * ;failed equal (zero) + + trap_mi +0934 : 30fe > bmi * ;failed minus (bit 7 set) + + trap_cc +0936 : 90fe > bcc * ;failed carry clear + + trap_vc +0938 : 50fe > bvc * ;failed overflow clear + +093a : c946 cmp #'F' ;passed registers OK? + trap_ne +093c : d0fe > bne * ;failed not equal (non zero) + +093e : e041 cpx #'A' + trap_ne +0940 : d0fe > bne * ;failed not equal (non zero) + +0942 : c052 cpy #'R' + trap_ne +0944 : d0fe > bne * ;failed not equal (non zero) + + next_test +0946 : ad0002 > lda test_case ;previous test +0949 : c908 > cmp #test_num + > trap_ne ;test is out of sequence +094b : d0fe > bne * ;failed not equal (non zero) + > +0009 = >test_num = test_num + 1 +094d : a909 > lda #test_num ;*** next tests' number +094f : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; jump indirect + set_stat 0 + > load_flag 0 +0952 : a900 > lda #0 ;allow test to change I + > +0954 : 48 > pha ;use stack to load status +0955 : 28 > plp + +0956 : a949 lda #'I' +0958 : a24e ldx #'N' +095a : a044 ldy #'D' ;N=0, V=0, Z=0, C=0 +095c : 6cf836 jmp (ptr_tst_ind) +095f : ea nop + trap_ne ;runover protection +0960 : d0fe > bne * ;failed not equal (non zero) + +0962 : 88 dey +0963 : 88 dey +0964 : ind_ret +0964 : 08 php ;either SP or Y count will fai +0965 : 88 dey +0966 : 88 dey +0967 : 88 dey +0968 : 28 plp + trap_eq ;returned flags OK? +0969 : f0fe > beq * ;failed equal (zero) + + trap_pl +096b : 10fe > bpl * ;failed plus (bit 7 clear) + + trap_cc +096d : 90fe > bcc * ;failed carry clear + + trap_vc +096f : 50fe > bvc * ;failed overflow clear + +0971 : c9e3 cmp #('I'^$aa) ;returned registers OK? + trap_ne +0973 : d0fe > bne * ;failed not equal (non zero) + +0975 : e04f cpx #('N'+1) + trap_ne +0977 : d0fe > bne * ;failed not equal (non zero) + +0979 : c03e cpy #('D'-6) + trap_ne +097b : d0fe > bne * ;failed not equal (non zero) + +097d : ba tsx ;SP check +097e : e0ff cpx #$ff + trap_ne +0980 : d0fe > bne * ;failed not equal (non zero) + + next_test +0982 : ad0002 > lda test_case ;previous test +0985 : c909 > cmp #test_num + > trap_ne ;test is out of sequence +0987 : d0fe > bne * ;failed not equal (non zero) + > +000a = >test_num = test_num + 1 +0989 : a90a > lda #test_num ;*** next tests' number +098b : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; jump subroutine & return from subroutine + set_stat 0 + > load_flag 0 +098e : a900 > lda #0 ;allow test to change I + > +0990 : 48 > pha ;use stack to load status +0991 : 28 > plp + +0992 : a94a lda #'J' +0994 : a253 ldx #'S' +0996 : a052 ldy #'R' ;N=0, V=0, Z=0, C=0 +0998 : 203437 jsr test_jsr +099a = jsr_ret = *-1 ;last address of jsr = return +099b : 08 php ;either SP or Y count will fai +099c : 88 dey +099d : 88 dey +099e : 88 dey +099f : 28 plp + trap_eq ;returned flags OK? +09a0 : f0fe > beq * ;failed equal (zero) + + trap_pl +09a2 : 10fe > bpl * ;failed plus (bit 7 clear) + + trap_cc +09a4 : 90fe > bcc * ;failed carry clear + + trap_vc +09a6 : 50fe > bvc * ;failed overflow clear + +09a8 : c9e0 cmp #('J'^$aa) ;returned registers OK? + trap_ne +09aa : d0fe > bne * ;failed not equal (non zero) + +09ac : e054 cpx #('S'+1) + trap_ne +09ae : d0fe > bne * ;failed not equal (non zero) + +09b0 : c04c cpy #('R'-6) + trap_ne +09b2 : d0fe > bne * ;failed not equal (non zero) + +09b4 : ba tsx ;sp? +09b5 : e0ff cpx #$ff + trap_ne +09b7 : d0fe > bne * ;failed not equal (non zero) + + next_test +09b9 : ad0002 > lda test_case ;previous test +09bc : c90a > cmp #test_num + > trap_ne ;test is out of sequence +09be : d0fe > bne * ;failed not equal (non zero) + > +000b = >test_num = test_num + 1 +09c0 : a90b > lda #test_num ;*** next tests' number +09c2 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; break & return from interrupt + if ROM_vectors = 1 + set_stat 0 + > load_flag 0 +09c5 : a900 > lda #0 ;allow test to change I + > +09c7 : 48 > pha ;use stack to load status +09c8 : 28 > plp + +09c9 : a942 lda #'B' +09cb : a252 ldx #'R' +09cd : a04b ldy #'K' ;N=0, V=0, Z=0, C=0 +09cf : 00 brk + else + lda #hi brk_ret ;emulated break + pha + lda #lo brk_ret + pha + lda #fao ;set break & unused on stack + pha + set_stat intdis + lda #'B' + ldx #'R' + ldy #'K' ;N=0, V=0, Z=0, C=0 + jmp irq_trap + endif +09d0 : 88 dey ;should not be executed +09d1 : brk_ret ;address of break return +09d1 : 08 php ;either SP or Y count will fai +09d2 : 88 dey +09d3 : 88 dey +09d4 : 88 dey +09d5 : c9e8 cmp #('B'^$aa) ;returned registers OK? + trap_ne +09d7 : d0fe > bne * ;failed not equal (non zero) + +09d9 : e053 cpx #('R'+1) + trap_ne +09db : d0fe > bne * ;failed not equal (non zero) + +09dd : c045 cpy #('K'-6) + trap_ne +09df : d0fe > bne * ;failed not equal (non zero) + +09e1 : 68 pla ;returned flags OK (unchanged) + cmp_flag 0 +09e2 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + + trap_ne +09e4 : d0fe > bne * ;failed not equal (non zero) + +09e6 : ba tsx ;sp? +09e7 : e0ff cpx #$ff + trap_ne +09e9 : d0fe > bne * ;failed not equal (non zero) + + next_test +09eb : ad0002 > lda test_case ;previous test +09ee : c90b > cmp #test_num + > trap_ne ;test is out of sequence +09f0 : d0fe > bne * ;failed not equal (non zero) + > +000c = >test_num = test_num + 1 +09f2 : a90c > lda #test_num ;*** next tests' number +09f4 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; test set and clear flags CLC CLI CLD CLV SEC SEI SED + set_stat $ff + > load_flag $ff +09f7 : a9ff > lda #$ff ;allow test to change + > +09f9 : 48 > pha ;use stack to load status +09fa : 28 > plp + +09fb : 18 clc + tst_stat $ff-carry +09fc : 08 > php ;save status +09fd : 68 > pla ;use stack to retrieve status +09fe : 48 > pha + > cmp_flag $ff-carry +09ff : c9fe > cmp #($ff-carry|fao)&m8 ;expected flags + > + > trap_ne +0a01 : d0fe > bne * ;failed not equal (non zero) + > +0a03 : 28 > plp ;restore status + +0a04 : 38 sec + tst_stat $ff +0a05 : 08 > php ;save status +0a06 : 68 > pla ;use stack to retrieve status +0a07 : 48 > pha + > cmp_flag $ff +0a08 : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + > + > trap_ne +0a0a : d0fe > bne * ;failed not equal (non zero) + > +0a0c : 28 > plp ;restore status + + if I_flag = 3 +0a0d : 58 cli + tst_stat $ff-intdis +0a0e : 08 > php ;save status +0a0f : 68 > pla ;use stack to retrieve status +0a10 : 48 > pha + > cmp_flag $ff-intdis +0a11 : c9fb > cmp #($ff-intdis|fao)&m8 ;expected flag + > + > trap_ne +0a13 : d0fe > bne * ;failed not equal (non zero) + > +0a15 : 28 > plp ;restore status + +0a16 : 78 sei + tst_stat $ff +0a17 : 08 > php ;save status +0a18 : 68 > pla ;use stack to retrieve status +0a19 : 48 > pha + > cmp_flag $ff +0a1a : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + > + > trap_ne +0a1c : d0fe > bne * ;failed not equal (non zero) + > +0a1e : 28 > plp ;restore status + + endif +0a1f : d8 cld + tst_stat $ff-decmode +0a20 : 08 > php ;save status +0a21 : 68 > pla ;use stack to retrieve status +0a22 : 48 > pha + > cmp_flag $ff-decmode +0a23 : c9f7 > cmp #($ff-decmode|fao)&m8 ;expected fla + > + > trap_ne +0a25 : d0fe > bne * ;failed not equal (non zero) + > +0a27 : 28 > plp ;restore status + +0a28 : f8 sed + tst_stat $ff +0a29 : 08 > php ;save status +0a2a : 68 > pla ;use stack to retrieve status +0a2b : 48 > pha + > cmp_flag $ff +0a2c : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + > + > trap_ne +0a2e : d0fe > bne * ;failed not equal (non zero) + > +0a30 : 28 > plp ;restore status + +0a31 : b8 clv + tst_stat $ff-overfl +0a32 : 08 > php ;save status +0a33 : 68 > pla ;use stack to retrieve status +0a34 : 48 > pha + > cmp_flag $ff-overfl +0a35 : c9bf > cmp #($ff-overfl|fao)&m8 ;expected flag + > + > trap_ne +0a37 : d0fe > bne * ;failed not equal (non zero) + > +0a39 : 28 > plp ;restore status + + set_stat 0 + > load_flag 0 +0a3a : a900 > lda #0 ;allow test to change I + > +0a3c : 48 > pha ;use stack to load status +0a3d : 28 > plp + + tst_stat 0 +0a3e : 08 > php ;save status +0a3f : 68 > pla ;use stack to retrieve status +0a40 : 48 > pha + > cmp_flag 0 +0a41 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0a43 : d0fe > bne * ;failed not equal (non zero) + > +0a45 : 28 > plp ;restore status + +0a46 : 38 sec + tst_stat carry +0a47 : 08 > php ;save status +0a48 : 68 > pla ;use stack to retrieve status +0a49 : 48 > pha + > cmp_flag carry +0a4a : c931 > cmp #(carry|fao)&m8 ;expected flags + a + > + > trap_ne +0a4c : d0fe > bne * ;failed not equal (non zero) + > +0a4e : 28 > plp ;restore status + +0a4f : 18 clc + tst_stat 0 +0a50 : 08 > php ;save status +0a51 : 68 > pla ;use stack to retrieve status +0a52 : 48 > pha + > cmp_flag 0 +0a53 : c930 > cmp #(0 |fao)&m8 ;expected flags + alw + > + > trap_ne +0a55 : d0fe > bne * ;failed not equal (non zero) + > +0a57 : 28 > plp ;restore status + + if I_flag = 3 +0a58 : 78 sei + tst_stat intdis +0a59 : 08 > php ;save status +0a5a : 68 > pla ;use stack to retrieve status +0a5b : 48 > pha + > cmp_flag intdis +0a5c : c934 > cmp #(intdis|fao)&m8 ;expected flags + + > + > trap_ne +0a5e : d0fe > bne * ;failed not equal (non zero) + > +0a60 : 28 > plp ;restore status + +0a61 : 58 cli + tst_stat 0 +0a62 : 08 > php ;save status +0a63 : 68 > pla ;use stack to retrieve status +0a64 : 48 > pha + > cmp_flag 0 +0a65 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0a67 : d0fe > bne * ;failed not equal (non zero) + > +0a69 : 28 > plp ;restore status + + endif +0a6a : f8 sed + tst_stat decmode +0a6b : 08 > php ;save status +0a6c : 68 > pla ;use stack to retrieve status +0a6d : 48 > pha + > cmp_flag decmode +0a6e : c938 > cmp #(decmode|fao)&m8 ;expected flags + + > + > trap_ne +0a70 : d0fe > bne * ;failed not equal (non zero) + > +0a72 : 28 > plp ;restore status + +0a73 : d8 cld + tst_stat 0 +0a74 : 08 > php ;save status +0a75 : 68 > pla ;use stack to retrieve status +0a76 : 48 > pha + > cmp_flag 0 +0a77 : c930 > cmp #(0 |fao)&m8 ;expected flags + alw + > + > trap_ne +0a79 : d0fe > bne * ;failed not equal (non zero) + > +0a7b : 28 > plp ;restore status + + set_stat overfl + > load_flag overfl +0a7c : a940 > lda #overfl ;allow test to cha + > +0a7e : 48 > pha ;use stack to load status +0a7f : 28 > plp + + tst_stat overfl +0a80 : 08 > php ;save status +0a81 : 68 > pla ;use stack to retrieve status +0a82 : 48 > pha + > cmp_flag overfl +0a83 : c970 > cmp #(overfl|fao)&m8 ;expected flags + + > + > trap_ne +0a85 : d0fe > bne * ;failed not equal (non zero) + > +0a87 : 28 > plp ;restore status + +0a88 : b8 clv + tst_stat 0 +0a89 : 08 > php ;save status +0a8a : 68 > pla ;use stack to retrieve status +0a8b : 48 > pha + > cmp_flag 0 +0a8c : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0a8e : d0fe > bne * ;failed not equal (non zero) + > +0a90 : 28 > plp ;restore status + + next_test +0a91 : ad0002 > lda test_case ;previous test +0a94 : c90c > cmp #test_num + > trap_ne ;test is out of sequence +0a96 : d0fe > bne * ;failed not equal (non zero) + > +000d = >test_num = test_num + 1 +0a98 : a90d > lda #test_num ;*** next tests' number +0a9a : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + ; testing index register increment/decrement and trans + ; INX INY DEX DEY TAX TXA TAY TYA +0a9d : a2fe ldx #$fe + set_stat $ff + > load_flag $ff +0a9f : a9ff > lda #$ff ;allow test to change + > +0aa1 : 48 > pha ;use stack to load status +0aa2 : 28 > plp + +0aa3 : e8 inx ;ff + tst_x $ff,$ff-zero +0aa4 : 08 > php ;save flags +0aa5 : e0ff > cpx #$ff ;test result + > trap_ne +0aa7 : d0fe > bne * ;failed not equal (non zero) + > +0aa9 : 68 > pla ;load status +0aaa : 48 > pha + > cmp_flag $ff-zero +0aab : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0aad : d0fe > bne * ;failed not equal (non zero) + > +0aaf : 28 > plp ;restore status + +0ab0 : e8 inx ;00 + tst_x 0,$ff-minus +0ab1 : 08 > php ;save flags +0ab2 : e000 > cpx #0 ;test result + > trap_ne +0ab4 : d0fe > bne * ;failed not equal (non zero) + > +0ab6 : 68 > pla ;load status +0ab7 : 48 > pha + > cmp_flag $ff-minus +0ab8 : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0aba : d0fe > bne * ;failed not equal (non zero) + > +0abc : 28 > plp ;restore status + +0abd : e8 inx ;01 + tst_x 1,$ff-minus-zero +0abe : 08 > php ;save flags +0abf : e001 > cpx #1 ;test result + > trap_ne +0ac1 : d0fe > bne * ;failed not equal (non zero) + > +0ac3 : 68 > pla ;load status +0ac4 : 48 > pha + > cmp_flag $ff-minus-zero +0ac5 : c97d > cmp #($ff-minus-zero|fao)&m8 ;expected + > + > trap_ne +0ac7 : d0fe > bne * ;failed not equal (non zero) + > +0ac9 : 28 > plp ;restore status + +0aca : ca dex ;00 + tst_x 0,$ff-minus +0acb : 08 > php ;save flags +0acc : e000 > cpx #0 ;test result + > trap_ne +0ace : d0fe > bne * ;failed not equal (non zero) + > +0ad0 : 68 > pla ;load status +0ad1 : 48 > pha + > cmp_flag $ff-minus +0ad2 : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0ad4 : d0fe > bne * ;failed not equal (non zero) + > +0ad6 : 28 > plp ;restore status + +0ad7 : ca dex ;ff + tst_x $ff,$ff-zero +0ad8 : 08 > php ;save flags +0ad9 : e0ff > cpx #$ff ;test result + > trap_ne +0adb : d0fe > bne * ;failed not equal (non zero) + > +0add : 68 > pla ;load status +0ade : 48 > pha + > cmp_flag $ff-zero +0adf : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0ae1 : d0fe > bne * ;failed not equal (non zero) + > +0ae3 : 28 > plp ;restore status + +0ae4 : ca dex ;fe + set_stat 0 + > load_flag 0 +0ae5 : a900 > lda #0 ;allow test to change I + > +0ae7 : 48 > pha ;use stack to load status +0ae8 : 28 > plp + +0ae9 : e8 inx ;ff + tst_x $ff,minus +0aea : 08 > php ;save flags +0aeb : e0ff > cpx #$ff ;test result + > trap_ne +0aed : d0fe > bne * ;failed not equal (non zero) + > +0aef : 68 > pla ;load status +0af0 : 48 > pha + > cmp_flag minus +0af1 : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + > + > trap_ne +0af3 : d0fe > bne * ;failed not equal (non zero) + > +0af5 : 28 > plp ;restore status + +0af6 : e8 inx ;00 + tst_x 0,zero +0af7 : 08 > php ;save flags +0af8 : e000 > cpx #0 ;test result + > trap_ne +0afa : d0fe > bne * ;failed not equal (non zero) + > +0afc : 68 > pla ;load status +0afd : 48 > pha + > cmp_flag zero +0afe : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +0b00 : d0fe > bne * ;failed not equal (non zero) + > +0b02 : 28 > plp ;restore status + +0b03 : e8 inx ;01 + tst_x 1,0 +0b04 : 08 > php ;save flags +0b05 : e001 > cpx #1 ;test result + > trap_ne +0b07 : d0fe > bne * ;failed not equal (non zero) + > +0b09 : 68 > pla ;load status +0b0a : 48 > pha + > cmp_flag 0 +0b0b : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0b0d : d0fe > bne * ;failed not equal (non zero) + > +0b0f : 28 > plp ;restore status + +0b10 : ca dex ;00 + tst_x 0,zero +0b11 : 08 > php ;save flags +0b12 : e000 > cpx #0 ;test result + > trap_ne +0b14 : d0fe > bne * ;failed not equal (non zero) + > +0b16 : 68 > pla ;load status +0b17 : 48 > pha + > cmp_flag zero +0b18 : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +0b1a : d0fe > bne * ;failed not equal (non zero) + > +0b1c : 28 > plp ;restore status + +0b1d : ca dex ;ff + tst_x $ff,minus +0b1e : 08 > php ;save flags +0b1f : e0ff > cpx #$ff ;test result + > trap_ne +0b21 : d0fe > bne * ;failed not equal (non zero) + > +0b23 : 68 > pla ;load status +0b24 : 48 > pha + > cmp_flag minus +0b25 : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + > + > trap_ne +0b27 : d0fe > bne * ;failed not equal (non zero) + > +0b29 : 28 > plp ;restore status + + +0b2a : a0fe ldy #$fe + set_stat $ff + > load_flag $ff +0b2c : a9ff > lda #$ff ;allow test to change + > +0b2e : 48 > pha ;use stack to load status +0b2f : 28 > plp + +0b30 : c8 iny ;ff + tst_y $ff,$ff-zero +0b31 : 08 > php ;save flags +0b32 : c0ff > cpy #$ff ;test result + > trap_ne +0b34 : d0fe > bne * ;failed not equal (non zero) + > +0b36 : 68 > pla ;load status +0b37 : 48 > pha + > cmp_flag $ff-zero +0b38 : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0b3a : d0fe > bne * ;failed not equal (non zero) + > +0b3c : 28 > plp ;restore status + +0b3d : c8 iny ;00 + tst_y 0,$ff-minus +0b3e : 08 > php ;save flags +0b3f : c000 > cpy #0 ;test result + > trap_ne +0b41 : d0fe > bne * ;failed not equal (non zero) + > +0b43 : 68 > pla ;load status +0b44 : 48 > pha + > cmp_flag $ff-minus +0b45 : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0b47 : d0fe > bne * ;failed not equal (non zero) + > +0b49 : 28 > plp ;restore status + +0b4a : c8 iny ;01 + tst_y 1,$ff-minus-zero +0b4b : 08 > php ;save flags +0b4c : c001 > cpy #1 ;test result + > trap_ne +0b4e : d0fe > bne * ;failed not equal (non zero) + > +0b50 : 68 > pla ;load status +0b51 : 48 > pha + > cmp_flag $ff-minus-zero +0b52 : c97d > cmp #($ff-minus-zero|fao)&m8 ;expected + > + > trap_ne +0b54 : d0fe > bne * ;failed not equal (non zero) + > +0b56 : 28 > plp ;restore status + +0b57 : 88 dey ;00 + tst_y 0,$ff-minus +0b58 : 08 > php ;save flags +0b59 : c000 > cpy #0 ;test result + > trap_ne +0b5b : d0fe > bne * ;failed not equal (non zero) + > +0b5d : 68 > pla ;load status +0b5e : 48 > pha + > cmp_flag $ff-minus +0b5f : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0b61 : d0fe > bne * ;failed not equal (non zero) + > +0b63 : 28 > plp ;restore status + +0b64 : 88 dey ;ff + tst_y $ff,$ff-zero +0b65 : 08 > php ;save flags +0b66 : c0ff > cpy #$ff ;test result + > trap_ne +0b68 : d0fe > bne * ;failed not equal (non zero) + > +0b6a : 68 > pla ;load status +0b6b : 48 > pha + > cmp_flag $ff-zero +0b6c : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0b6e : d0fe > bne * ;failed not equal (non zero) + > +0b70 : 28 > plp ;restore status + +0b71 : 88 dey ;fe + set_stat 0 + > load_flag 0 +0b72 : a900 > lda #0 ;allow test to change I + > +0b74 : 48 > pha ;use stack to load status +0b75 : 28 > plp + +0b76 : c8 iny ;ff + tst_y $ff,0+minus +0b77 : 08 > php ;save flags +0b78 : c0ff > cpy #$ff ;test result + > trap_ne +0b7a : d0fe > bne * ;failed not equal (non zero) + > +0b7c : 68 > pla ;load status +0b7d : 48 > pha + > cmp_flag 0+minus +0b7e : c9b0 > cmp #(0+minus|fao)&m8 ;expected flags + + > + > trap_ne +0b80 : d0fe > bne * ;failed not equal (non zero) + > +0b82 : 28 > plp ;restore status + +0b83 : c8 iny ;00 + tst_y 0,zero +0b84 : 08 > php ;save flags +0b85 : c000 > cpy #0 ;test result + > trap_ne +0b87 : d0fe > bne * ;failed not equal (non zero) + > +0b89 : 68 > pla ;load status +0b8a : 48 > pha + > cmp_flag zero +0b8b : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +0b8d : d0fe > bne * ;failed not equal (non zero) + > +0b8f : 28 > plp ;restore status + +0b90 : c8 iny ;01 + tst_y 1,0 +0b91 : 08 > php ;save flags +0b92 : c001 > cpy #1 ;test result + > trap_ne +0b94 : d0fe > bne * ;failed not equal (non zero) + > +0b96 : 68 > pla ;load status +0b97 : 48 > pha + > cmp_flag 0 +0b98 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0b9a : d0fe > bne * ;failed not equal (non zero) + > +0b9c : 28 > plp ;restore status + +0b9d : 88 dey ;00 + tst_y 0,zero +0b9e : 08 > php ;save flags +0b9f : c000 > cpy #0 ;test result + > trap_ne +0ba1 : d0fe > bne * ;failed not equal (non zero) + > +0ba3 : 68 > pla ;load status +0ba4 : 48 > pha + > cmp_flag zero +0ba5 : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +0ba7 : d0fe > bne * ;failed not equal (non zero) + > +0ba9 : 28 > plp ;restore status + +0baa : 88 dey ;ff + tst_y $ff,minus +0bab : 08 > php ;save flags +0bac : c0ff > cpy #$ff ;test result + > trap_ne +0bae : d0fe > bne * ;failed not equal (non zero) + > +0bb0 : 68 > pla ;load status +0bb1 : 48 > pha + > cmp_flag minus +0bb2 : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + > + > trap_ne +0bb4 : d0fe > bne * ;failed not equal (non zero) + > +0bb6 : 28 > plp ;restore status + + +0bb7 : a2ff ldx #$ff + set_stat $ff + > load_flag $ff +0bb9 : a9ff > lda #$ff ;allow test to change + > +0bbb : 48 > pha ;use stack to load status +0bbc : 28 > plp + +0bbd : 8a txa + tst_a $ff,$ff-zero +0bbe : 08 > php ;save flags +0bbf : c9ff > cmp #$ff ;test result + > trap_ne +0bc1 : d0fe > bne * ;failed not equal (non zero) + > +0bc3 : 68 > pla ;load status +0bc4 : 48 > pha + > cmp_flag $ff-zero +0bc5 : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0bc7 : d0fe > bne * ;failed not equal (non zero) + > +0bc9 : 28 > plp ;restore status + +0bca : 08 php +0bcb : e8 inx ;00 +0bcc : 28 plp +0bcd : 8a txa + tst_a 0,$ff-minus +0bce : 08 > php ;save flags +0bcf : c900 > cmp #0 ;test result + > trap_ne +0bd1 : d0fe > bne * ;failed not equal (non zero) + > +0bd3 : 68 > pla ;load status +0bd4 : 48 > pha + > cmp_flag $ff-minus +0bd5 : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0bd7 : d0fe > bne * ;failed not equal (non zero) + > +0bd9 : 28 > plp ;restore status + +0bda : 08 php +0bdb : e8 inx ;01 +0bdc : 28 plp +0bdd : 8a txa + tst_a 1,$ff-minus-zero +0bde : 08 > php ;save flags +0bdf : c901 > cmp #1 ;test result + > trap_ne +0be1 : d0fe > bne * ;failed not equal (non zero) + > +0be3 : 68 > pla ;load status +0be4 : 48 > pha + > cmp_flag $ff-minus-zero +0be5 : c97d > cmp #($ff-minus-zero|fao)&m8 ;expected + > + > trap_ne +0be7 : d0fe > bne * ;failed not equal (non zero) + > +0be9 : 28 > plp ;restore status + + set_stat 0 + > load_flag 0 +0bea : a900 > lda #0 ;allow test to change I + > +0bec : 48 > pha ;use stack to load status +0bed : 28 > plp + +0bee : 8a txa + tst_a 1,0 +0bef : 08 > php ;save flags +0bf0 : c901 > cmp #1 ;test result + > trap_ne +0bf2 : d0fe > bne * ;failed not equal (non zero) + > +0bf4 : 68 > pla ;load status +0bf5 : 48 > pha + > cmp_flag 0 +0bf6 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0bf8 : d0fe > bne * ;failed not equal (non zero) + > +0bfa : 28 > plp ;restore status + +0bfb : 08 php +0bfc : ca dex ;00 +0bfd : 28 plp +0bfe : 8a txa + tst_a 0,zero +0bff : 08 > php ;save flags +0c00 : c900 > cmp #0 ;test result + > trap_ne +0c02 : d0fe > bne * ;failed not equal (non zero) + > +0c04 : 68 > pla ;load status +0c05 : 48 > pha + > cmp_flag zero +0c06 : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +0c08 : d0fe > bne * ;failed not equal (non zero) + > +0c0a : 28 > plp ;restore status + +0c0b : 08 php +0c0c : ca dex ;ff +0c0d : 28 plp +0c0e : 8a txa + tst_a $ff,minus +0c0f : 08 > php ;save flags +0c10 : c9ff > cmp #$ff ;test result + > trap_ne +0c12 : d0fe > bne * ;failed not equal (non zero) + > +0c14 : 68 > pla ;load status +0c15 : 48 > pha + > cmp_flag minus +0c16 : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + > + > trap_ne +0c18 : d0fe > bne * ;failed not equal (non zero) + > +0c1a : 28 > plp ;restore status + + +0c1b : a0ff ldy #$ff + set_stat $ff + > load_flag $ff +0c1d : a9ff > lda #$ff ;allow test to change + > +0c1f : 48 > pha ;use stack to load status +0c20 : 28 > plp + +0c21 : 98 tya + tst_a $ff,$ff-zero +0c22 : 08 > php ;save flags +0c23 : c9ff > cmp #$ff ;test result + > trap_ne +0c25 : d0fe > bne * ;failed not equal (non zero) + > +0c27 : 68 > pla ;load status +0c28 : 48 > pha + > cmp_flag $ff-zero +0c29 : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0c2b : d0fe > bne * ;failed not equal (non zero) + > +0c2d : 28 > plp ;restore status + +0c2e : 08 php +0c2f : c8 iny ;00 +0c30 : 28 plp +0c31 : 98 tya + tst_a 0,$ff-minus +0c32 : 08 > php ;save flags +0c33 : c900 > cmp #0 ;test result + > trap_ne +0c35 : d0fe > bne * ;failed not equal (non zero) + > +0c37 : 68 > pla ;load status +0c38 : 48 > pha + > cmp_flag $ff-minus +0c39 : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0c3b : d0fe > bne * ;failed not equal (non zero) + > +0c3d : 28 > plp ;restore status + +0c3e : 08 php +0c3f : c8 iny ;01 +0c40 : 28 plp +0c41 : 98 tya + tst_a 1,$ff-minus-zero +0c42 : 08 > php ;save flags +0c43 : c901 > cmp #1 ;test result + > trap_ne +0c45 : d0fe > bne * ;failed not equal (non zero) + > +0c47 : 68 > pla ;load status +0c48 : 48 > pha + > cmp_flag $ff-minus-zero +0c49 : c97d > cmp #($ff-minus-zero|fao)&m8 ;expected + > + > trap_ne +0c4b : d0fe > bne * ;failed not equal (non zero) + > +0c4d : 28 > plp ;restore status + + set_stat 0 + > load_flag 0 +0c4e : a900 > lda #0 ;allow test to change I + > +0c50 : 48 > pha ;use stack to load status +0c51 : 28 > plp + +0c52 : 98 tya + tst_a 1,0 +0c53 : 08 > php ;save flags +0c54 : c901 > cmp #1 ;test result + > trap_ne +0c56 : d0fe > bne * ;failed not equal (non zero) + > +0c58 : 68 > pla ;load status +0c59 : 48 > pha + > cmp_flag 0 +0c5a : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0c5c : d0fe > bne * ;failed not equal (non zero) + > +0c5e : 28 > plp ;restore status + +0c5f : 08 php +0c60 : 88 dey ;00 +0c61 : 28 plp +0c62 : 98 tya + tst_a 0,zero +0c63 : 08 > php ;save flags +0c64 : c900 > cmp #0 ;test result + > trap_ne +0c66 : d0fe > bne * ;failed not equal (non zero) + > +0c68 : 68 > pla ;load status +0c69 : 48 > pha + > cmp_flag zero +0c6a : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +0c6c : d0fe > bne * ;failed not equal (non zero) + > +0c6e : 28 > plp ;restore status + +0c6f : 08 php +0c70 : 88 dey ;ff +0c71 : 28 plp +0c72 : 98 tya + tst_a $ff,minus +0c73 : 08 > php ;save flags +0c74 : c9ff > cmp #$ff ;test result + > trap_ne +0c76 : d0fe > bne * ;failed not equal (non zero) + > +0c78 : 68 > pla ;load status +0c79 : 48 > pha + > cmp_flag minus +0c7a : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + > + > trap_ne +0c7c : d0fe > bne * ;failed not equal (non zero) + > +0c7e : 28 > plp ;restore status + + + load_flag $ff +0c7f : a9ff > lda #$ff ;allow test to change + +0c81 : 48 pha +0c82 : a2ff ldx #$ff ;ff +0c84 : 8a txa +0c85 : 28 plp +0c86 : a8 tay + tst_y $ff,$ff-zero +0c87 : 08 > php ;save flags +0c88 : c0ff > cpy #$ff ;test result + > trap_ne +0c8a : d0fe > bne * ;failed not equal (non zero) + > +0c8c : 68 > pla ;load status +0c8d : 48 > pha + > cmp_flag $ff-zero +0c8e : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0c90 : d0fe > bne * ;failed not equal (non zero) + > +0c92 : 28 > plp ;restore status + +0c93 : 08 php +0c94 : e8 inx ;00 +0c95 : 8a txa +0c96 : 28 plp +0c97 : a8 tay + tst_y 0,$ff-minus +0c98 : 08 > php ;save flags +0c99 : c000 > cpy #0 ;test result + > trap_ne +0c9b : d0fe > bne * ;failed not equal (non zero) + > +0c9d : 68 > pla ;load status +0c9e : 48 > pha + > cmp_flag $ff-minus +0c9f : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0ca1 : d0fe > bne * ;failed not equal (non zero) + > +0ca3 : 28 > plp ;restore status + +0ca4 : 08 php +0ca5 : e8 inx ;01 +0ca6 : 8a txa +0ca7 : 28 plp +0ca8 : a8 tay + tst_y 1,$ff-minus-zero +0ca9 : 08 > php ;save flags +0caa : c001 > cpy #1 ;test result + > trap_ne +0cac : d0fe > bne * ;failed not equal (non zero) + > +0cae : 68 > pla ;load status +0caf : 48 > pha + > cmp_flag $ff-minus-zero +0cb0 : c97d > cmp #($ff-minus-zero|fao)&m8 ;expected + > + > trap_ne +0cb2 : d0fe > bne * ;failed not equal (non zero) + > +0cb4 : 28 > plp ;restore status + + load_flag 0 +0cb5 : a900 > lda #0 ;allow test to change I + +0cb7 : 48 pha +0cb8 : a900 lda #0 +0cba : 8a txa +0cbb : 28 plp +0cbc : a8 tay + tst_y 1,0 +0cbd : 08 > php ;save flags +0cbe : c001 > cpy #1 ;test result + > trap_ne +0cc0 : d0fe > bne * ;failed not equal (non zero) + > +0cc2 : 68 > pla ;load status +0cc3 : 48 > pha + > cmp_flag 0 +0cc4 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0cc6 : d0fe > bne * ;failed not equal (non zero) + > +0cc8 : 28 > plp ;restore status + +0cc9 : 08 php +0cca : ca dex ;00 +0ccb : 8a txa +0ccc : 28 plp +0ccd : a8 tay + tst_y 0,zero +0cce : 08 > php ;save flags +0ccf : c000 > cpy #0 ;test result + > trap_ne +0cd1 : d0fe > bne * ;failed not equal (non zero) + > +0cd3 : 68 > pla ;load status +0cd4 : 48 > pha + > cmp_flag zero +0cd5 : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +0cd7 : d0fe > bne * ;failed not equal (non zero) + > +0cd9 : 28 > plp ;restore status + +0cda : 08 php +0cdb : ca dex ;ff +0cdc : 8a txa +0cdd : 28 plp +0cde : a8 tay + tst_y $ff,minus +0cdf : 08 > php ;save flags +0ce0 : c0ff > cpy #$ff ;test result + > trap_ne +0ce2 : d0fe > bne * ;failed not equal (non zero) + > +0ce4 : 68 > pla ;load status +0ce5 : 48 > pha + > cmp_flag minus +0ce6 : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + > + > trap_ne +0ce8 : d0fe > bne * ;failed not equal (non zero) + > +0cea : 28 > plp ;restore status + + + + load_flag $ff +0ceb : a9ff > lda #$ff ;allow test to change + +0ced : 48 pha +0cee : a0ff ldy #$ff ;ff +0cf0 : 98 tya +0cf1 : 28 plp +0cf2 : aa tax + tst_x $ff,$ff-zero +0cf3 : 08 > php ;save flags +0cf4 : e0ff > cpx #$ff ;test result + > trap_ne +0cf6 : d0fe > bne * ;failed not equal (non zero) + > +0cf8 : 68 > pla ;load status +0cf9 : 48 > pha + > cmp_flag $ff-zero +0cfa : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0cfc : d0fe > bne * ;failed not equal (non zero) + > +0cfe : 28 > plp ;restore status + +0cff : 08 php +0d00 : c8 iny ;00 +0d01 : 98 tya +0d02 : 28 plp +0d03 : aa tax + tst_x 0,$ff-minus +0d04 : 08 > php ;save flags +0d05 : e000 > cpx #0 ;test result + > trap_ne +0d07 : d0fe > bne * ;failed not equal (non zero) + > +0d09 : 68 > pla ;load status +0d0a : 48 > pha + > cmp_flag $ff-minus +0d0b : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0d0d : d0fe > bne * ;failed not equal (non zero) + > +0d0f : 28 > plp ;restore status + +0d10 : 08 php +0d11 : c8 iny ;01 +0d12 : 98 tya +0d13 : 28 plp +0d14 : aa tax + tst_x 1,$ff-minus-zero +0d15 : 08 > php ;save flags +0d16 : e001 > cpx #1 ;test result + > trap_ne +0d18 : d0fe > bne * ;failed not equal (non zero) + > +0d1a : 68 > pla ;load status +0d1b : 48 > pha + > cmp_flag $ff-minus-zero +0d1c : c97d > cmp #($ff-minus-zero|fao)&m8 ;expected + > + > trap_ne +0d1e : d0fe > bne * ;failed not equal (non zero) + > +0d20 : 28 > plp ;restore status + + load_flag 0 +0d21 : a900 > lda #0 ;allow test to change I + +0d23 : 48 pha +0d24 : a900 lda #0 ;preset status +0d26 : 98 tya +0d27 : 28 plp +0d28 : aa tax + tst_x 1,0 +0d29 : 08 > php ;save flags +0d2a : e001 > cpx #1 ;test result + > trap_ne +0d2c : d0fe > bne * ;failed not equal (non zero) + > +0d2e : 68 > pla ;load status +0d2f : 48 > pha + > cmp_flag 0 +0d30 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0d32 : d0fe > bne * ;failed not equal (non zero) + > +0d34 : 28 > plp ;restore status + +0d35 : 08 php +0d36 : 88 dey ;00 +0d37 : 98 tya +0d38 : 28 plp +0d39 : aa tax + tst_x 0,zero +0d3a : 08 > php ;save flags +0d3b : e000 > cpx #0 ;test result + > trap_ne +0d3d : d0fe > bne * ;failed not equal (non zero) + > +0d3f : 68 > pla ;load status +0d40 : 48 > pha + > cmp_flag zero +0d41 : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +0d43 : d0fe > bne * ;failed not equal (non zero) + > +0d45 : 28 > plp ;restore status + +0d46 : 08 php +0d47 : 88 dey ;ff +0d48 : 98 tya +0d49 : 28 plp +0d4a : aa tax + tst_x $ff,minus +0d4b : 08 > php ;save flags +0d4c : e0ff > cpx #$ff ;test result + > trap_ne +0d4e : d0fe > bne * ;failed not equal (non zero) + > +0d50 : 68 > pla ;load status +0d51 : 48 > pha + > cmp_flag minus +0d52 : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + > + > trap_ne +0d54 : d0fe > bne * ;failed not equal (non zero) + > +0d56 : 28 > plp ;restore status + + next_test +0d57 : ad0002 > lda test_case ;previous test +0d5a : c90d > cmp #test_num + > trap_ne ;test is out of sequence +0d5c : d0fe > bne * ;failed not equal (non zero) + > +000e = >test_num = test_num + 1 +0d5e : a90e > lda #test_num ;*** next tests' number +0d60 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ;TSX sets NZ - TXS does not + ; This section also tests for proper stack wrap aroun +0d63 : a201 ldx #1 ;01 + set_stat $ff + > load_flag $ff +0d65 : a9ff > lda #$ff ;allow test to change + > +0d67 : 48 > pha ;use stack to load status +0d68 : 28 > plp + +0d69 : 9a txs +0d6a : 08 php +0d6b : ad0101 lda $101 + cmp_flag $ff +0d6e : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + + trap_ne +0d70 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +0d72 : a900 > lda #0 ;allow test to change I + > +0d74 : 48 > pha ;use stack to load status +0d75 : 28 > plp + +0d76 : 9a txs +0d77 : 08 php +0d78 : ad0101 lda $101 + cmp_flag 0 +0d7b : c930 > cmp #(0|fao)&m8 ;expected flags + alway + + trap_ne +0d7d : d0fe > bne * ;failed not equal (non zero) + +0d7f : ca dex ;00 + set_stat $ff + > load_flag $ff +0d80 : a9ff > lda #$ff ;allow test to change + > +0d82 : 48 > pha ;use stack to load status +0d83 : 28 > plp + +0d84 : 9a txs +0d85 : 08 php +0d86 : ad0001 lda $100 + cmp_flag $ff +0d89 : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + + trap_ne +0d8b : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +0d8d : a900 > lda #0 ;allow test to change I + > +0d8f : 48 > pha ;use stack to load status +0d90 : 28 > plp + +0d91 : 9a txs +0d92 : 08 php +0d93 : ad0001 lda $100 + cmp_flag 0 +0d96 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + + trap_ne +0d98 : d0fe > bne * ;failed not equal (non zero) + +0d9a : ca dex ;ff + set_stat $ff + > load_flag $ff +0d9b : a9ff > lda #$ff ;allow test to change + > +0d9d : 48 > pha ;use stack to load status +0d9e : 28 > plp + +0d9f : 9a txs +0da0 : 08 php +0da1 : adff01 lda $1ff + cmp_flag $ff +0da4 : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + + trap_ne +0da6 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +0da8 : a900 > lda #0 ;allow test to change I + > +0daa : 48 > pha ;use stack to load status +0dab : 28 > plp + +0dac : 9a txs +0dad : 08 php +0dae : adff01 lda $1ff + cmp_flag 0 +0db1 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + + +0db3 : a201 ldx #1 +0db5 : 9a txs ;sp=01 + set_stat $ff + > load_flag $ff +0db6 : a9ff > lda #$ff ;allow test to change + > +0db8 : 48 > pha ;use stack to load status +0db9 : 28 > plp + +0dba : ba tsx ;clears Z, N +0dbb : 08 php ;sp=00 +0dbc : e001 cpx #1 + trap_ne +0dbe : d0fe > bne * ;failed not equal (non zero) + +0dc0 : ad0101 lda $101 + cmp_flag $ff-minus-zero +0dc3 : c97d > cmp #($ff-minus-zero|fao)&m8 ;expected + + trap_ne +0dc5 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +0dc7 : a9ff > lda #$ff ;allow test to change + > +0dc9 : 48 > pha ;use stack to load status +0dca : 28 > plp + +0dcb : ba tsx ;clears N, sets Z +0dcc : 08 php ;sp=ff +0dcd : e000 cpx #0 + trap_ne +0dcf : d0fe > bne * ;failed not equal (non zero) + +0dd1 : ad0001 lda $100 + cmp_flag $ff-minus +0dd4 : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + + trap_ne +0dd6 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +0dd8 : a9ff > lda #$ff ;allow test to change + > +0dda : 48 > pha ;use stack to load status +0ddb : 28 > plp + +0ddc : ba tsx ;clears N, sets Z +0ddd : 08 php ;sp=fe +0dde : e0ff cpx #$ff + trap_ne +0de0 : d0fe > bne * ;failed not equal (non zero) + +0de2 : adff01 lda $1ff + cmp_flag $ff-zero +0de5 : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + + trap_ne +0de7 : d0fe > bne * ;failed not equal (non zero) + + +0de9 : a201 ldx #1 +0deb : 9a txs ;sp=01 + set_stat 0 + > load_flag 0 +0dec : a900 > lda #0 ;allow test to change I + > +0dee : 48 > pha ;use stack to load status +0def : 28 > plp + +0df0 : ba tsx ;clears Z, N +0df1 : 08 php ;sp=00 +0df2 : e001 cpx #1 + trap_ne +0df4 : d0fe > bne * ;failed not equal (non zero) + +0df6 : ad0101 lda $101 + cmp_flag 0 +0df9 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + + trap_ne +0dfb : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +0dfd : a900 > lda #0 ;allow test to change I + > +0dff : 48 > pha ;use stack to load status +0e00 : 28 > plp + +0e01 : ba tsx ;clears N, sets Z +0e02 : 08 php ;sp=ff +0e03 : e000 cpx #0 + trap_ne +0e05 : d0fe > bne * ;failed not equal (non zero) + +0e07 : ad0001 lda $100 + cmp_flag zero +0e0a : c932 > cmp #(zero|fao)&m8 ;expected flags + al + + trap_ne +0e0c : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +0e0e : a900 > lda #0 ;allow test to change I + > +0e10 : 48 > pha ;use stack to load status +0e11 : 28 > plp + +0e12 : ba tsx ;clears N, sets Z +0e13 : 08 php ;sp=fe +0e14 : e0ff cpx #$ff + trap_ne +0e16 : d0fe > bne * ;failed not equal (non zero) + +0e18 : adff01 lda $1ff + cmp_flag minus +0e1b : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + + trap_ne +0e1d : d0fe > bne * ;failed not equal (non zero) + +0e1f : 68 pla ;sp=ff + next_test +0e20 : ad0002 > lda test_case ;previous test +0e23 : c90e > cmp #test_num + > trap_ne ;test is out of sequence +0e25 : d0fe > bne * ;failed not equal (non zero) + > +000f = >test_num = test_num + 1 +0e27 : a90f > lda #test_num ;*** next tests' number +0e29 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; testing index register load & store LDY LDX STY STX + ; LDX / STX - zp,y / abs,y +0e2c : a003 ldy #3 +0e2e : tldx + set_stat 0 + > load_flag 0 +0e2e : a900 > lda #0 ;allow test to change I + > +0e30 : 48 > pha ;use stack to load status +0e31 : 28 > plp + +0e32 : b613 ldx zp1,y +0e34 : 08 php ;test stores do not alter flags +0e35 : 8a txa +0e36 : 49c3 eor #$c3 +0e38 : 28 plp +0e39 : 990302 sta abst,y +0e3c : 08 php ;flags after load/store sequence +0e3d : 49c3 eor #$c3 +0e3f : d91702 cmp abs1,y ;test result + trap_ne +0e42 : d0fe > bne * ;failed not equal (non zero) + +0e44 : 68 pla ;load status + eor_flag 0 +0e45 : 4930 > eor #0|fao ;invert expected flags + +0e47 : d91c02 cmp fLDx,y ;test flags + trap_ne +0e4a : d0fe > bne * ;failed not equal (non zero) + +0e4c : 88 dey +0e4d : 10df bpl tldx + +0e4f : a003 ldy #3 +0e51 : tldx1 + set_stat $ff + > load_flag $ff +0e51 : a9ff > lda #$ff ;allow test to change + > +0e53 : 48 > pha ;use stack to load status +0e54 : 28 > plp + +0e55 : b613 ldx zp1,y +0e57 : 08 php ;test stores do not alter flags +0e58 : 8a txa +0e59 : 49c3 eor #$c3 +0e5b : 28 plp +0e5c : 990302 sta abst,y +0e5f : 08 php ;flags after load/store sequence +0e60 : 49c3 eor #$c3 +0e62 : d91702 cmp abs1,y ;test result + trap_ne +0e65 : d0fe > bne * ;failed not equal (non zero) + +0e67 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +0e68 : 497d > eor #lo~fnz |fao ;invert expected + +0e6a : d91c02 cmp fLDx,y ;test flags + trap_ne +0e6d : d0fe > bne * ;failed not equal (non zero) + +0e6f : 88 dey +0e70 : 10df bpl tldx1 + +0e72 : a003 ldy #3 +0e74 : tldx2 + set_stat 0 + > load_flag 0 +0e74 : a900 > lda #0 ;allow test to change I + > +0e76 : 48 > pha ;use stack to load status +0e77 : 28 > plp + +0e78 : be1702 ldx abs1,y +0e7b : 08 php ;test stores do not alter flags +0e7c : 8a txa +0e7d : 49c3 eor #$c3 +0e7f : aa tax +0e80 : 28 plp +0e81 : 960c stx zpt,y +0e83 : 08 php ;flags after load/store sequence +0e84 : 49c3 eor #$c3 +0e86 : d91300 cmp zp1,y ;test result + trap_ne +0e89 : d0fe > bne * ;failed not equal (non zero) + +0e8b : 68 pla ;load status + eor_flag 0 +0e8c : 4930 > eor #0|fao ;invert expected flags + +0e8e : d91c02 cmp fLDx,y ;test flags + trap_ne +0e91 : d0fe > bne * ;failed not equal (non zero) + +0e93 : 88 dey +0e94 : 10de bpl tldx2 + +0e96 : a003 ldy #3 +0e98 : tldx3 + set_stat $ff + > load_flag $ff +0e98 : a9ff > lda #$ff ;allow test to change + > +0e9a : 48 > pha ;use stack to load status +0e9b : 28 > plp + +0e9c : be1702 ldx abs1,y +0e9f : 08 php ;test stores do not alter flags +0ea0 : 8a txa +0ea1 : 49c3 eor #$c3 +0ea3 : aa tax +0ea4 : 28 plp +0ea5 : 960c stx zpt,y +0ea7 : 08 php ;flags after load/store sequence +0ea8 : 49c3 eor #$c3 +0eaa : d91300 cmp zp1,y ;test result + trap_ne +0ead : d0fe > bne * ;failed not equal (non zero) + +0eaf : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +0eb0 : 497d > eor #lo~fnz |fao ;invert expected + +0eb2 : d91c02 cmp fLDx,y ;test flags + trap_ne +0eb5 : d0fe > bne * ;failed not equal (non zero) + +0eb7 : 88 dey +0eb8 : 10de bpl tldx3 + +0eba : a003 ldy #3 ;testing store result +0ebc : a200 ldx #0 +0ebe : b90c00 tstx lda zpt,y +0ec1 : 49c3 eor #$c3 +0ec3 : d91300 cmp zp1,y + trap_ne ;store to zp data +0ec6 : d0fe > bne * ;failed not equal (non zero) + +0ec8 : 960c stx zpt,y ;clear +0eca : b90302 lda abst,y +0ecd : 49c3 eor #$c3 +0ecf : d91702 cmp abs1,y + trap_ne ;store to abs data +0ed2 : d0fe > bne * ;failed not equal (non zero) + +0ed4 : 8a txa +0ed5 : 990302 sta abst,y ;clear +0ed8 : 88 dey +0ed9 : 10e3 bpl tstx + next_test +0edb : ad0002 > lda test_case ;previous test +0ede : c90f > cmp #test_num + > trap_ne ;test is out of sequence +0ee0 : d0fe > bne * ;failed not equal (non zero) + > +0010 = >test_num = test_num + 1 +0ee2 : a910 > lda #test_num ;*** next tests' number +0ee4 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; indexed wraparound test (only zp should wrap) +0ee7 : a0fd ldy #3+$fa +0ee9 : b619 tldx4 ldx zp1-$fa&$ff,y ;wrap on indexed zp +0eeb : 8a txa +0eec : 990901 sta abst-$fa,y ;no STX abs,y! +0eef : 88 dey +0ef0 : c0fa cpy #$fa +0ef2 : b0f5 bcs tldx4 +0ef4 : a0fd ldy #3+$fa +0ef6 : be1d01 tldx5 ldx abs1-$fa,y ;no wrap on indexed abs +0ef9 : 9612 stx zpt-$fa&$ff,y +0efb : 88 dey +0efc : c0fa cpy #$fa +0efe : b0f6 bcs tldx5 +0f00 : a003 ldy #3 ;testing wraparound result +0f02 : a200 ldx #0 +0f04 : b90c00 tstx1 lda zpt,y +0f07 : d91300 cmp zp1,y + trap_ne ;store to zp data +0f0a : d0fe > bne * ;failed not equal (non zero) + +0f0c : 960c stx zpt,y ;clear +0f0e : b90302 lda abst,y +0f11 : d91702 cmp abs1,y + trap_ne ;store to abs data +0f14 : d0fe > bne * ;failed not equal (non zero) + +0f16 : 8a txa +0f17 : 990302 sta abst,y ;clear +0f1a : 88 dey +0f1b : 10e7 bpl tstx1 + next_test +0f1d : ad0002 > lda test_case ;previous test +0f20 : c910 > cmp #test_num + > trap_ne ;test is out of sequence +0f22 : d0fe > bne * ;failed not equal (non zero) + > +0011 = >test_num = test_num + 1 +0f24 : a911 > lda #test_num ;*** next tests' number +0f26 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; LDY / STY - zp,x / abs,x +0f29 : a203 ldx #3 +0f2b : tldy + set_stat 0 + > load_flag 0 +0f2b : a900 > lda #0 ;allow test to change I + > +0f2d : 48 > pha ;use stack to load status +0f2e : 28 > plp + +0f2f : b413 ldy zp1,x +0f31 : 08 php ;test stores do not alter flags +0f32 : 98 tya +0f33 : 49c3 eor #$c3 +0f35 : 28 plp +0f36 : 9d0302 sta abst,x +0f39 : 08 php ;flags after load/store sequence +0f3a : 49c3 eor #$c3 +0f3c : dd1702 cmp abs1,x ;test result + trap_ne +0f3f : d0fe > bne * ;failed not equal (non zero) + +0f41 : 68 pla ;load status + eor_flag 0 +0f42 : 4930 > eor #0|fao ;invert expected flags + +0f44 : dd1c02 cmp fLDx,x ;test flags + trap_ne +0f47 : d0fe > bne * ;failed not equal (non zero) + +0f49 : ca dex +0f4a : 10df bpl tldy + +0f4c : a203 ldx #3 +0f4e : tldy1 + set_stat $ff + > load_flag $ff +0f4e : a9ff > lda #$ff ;allow test to change + > +0f50 : 48 > pha ;use stack to load status +0f51 : 28 > plp + +0f52 : b413 ldy zp1,x +0f54 : 08 php ;test stores do not alter flags +0f55 : 98 tya +0f56 : 49c3 eor #$c3 +0f58 : 28 plp +0f59 : 9d0302 sta abst,x +0f5c : 08 php ;flags after load/store sequence +0f5d : 49c3 eor #$c3 +0f5f : dd1702 cmp abs1,x ;test result + trap_ne +0f62 : d0fe > bne * ;failed not equal (non zero) + +0f64 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +0f65 : 497d > eor #lo~fnz |fao ;invert expected + +0f67 : dd1c02 cmp fLDx,x ;test flags + trap_ne +0f6a : d0fe > bne * ;failed not equal (non zero) + +0f6c : ca dex +0f6d : 10df bpl tldy1 + +0f6f : a203 ldx #3 +0f71 : tldy2 + set_stat 0 + > load_flag 0 +0f71 : a900 > lda #0 ;allow test to change I + > +0f73 : 48 > pha ;use stack to load status +0f74 : 28 > plp + +0f75 : bc1702 ldy abs1,x +0f78 : 08 php ;test stores do not alter flags +0f79 : 98 tya +0f7a : 49c3 eor #$c3 +0f7c : a8 tay +0f7d : 28 plp +0f7e : 940c sty zpt,x +0f80 : 08 php ;flags after load/store sequence +0f81 : 49c3 eor #$c3 +0f83 : d513 cmp zp1,x ;test result + trap_ne +0f85 : d0fe > bne * ;failed not equal (non zero) + +0f87 : 68 pla ;load status + eor_flag 0 +0f88 : 4930 > eor #0|fao ;invert expected flags + +0f8a : dd1c02 cmp fLDx,x ;test flags + trap_ne +0f8d : d0fe > bne * ;failed not equal (non zero) + +0f8f : ca dex +0f90 : 10df bpl tldy2 + +0f92 : a203 ldx #3 +0f94 : tldy3 + set_stat $ff + > load_flag $ff +0f94 : a9ff > lda #$ff ;allow test to change + > +0f96 : 48 > pha ;use stack to load status +0f97 : 28 > plp + +0f98 : bc1702 ldy abs1,x +0f9b : 08 php ;test stores do not alter flags +0f9c : 98 tya +0f9d : 49c3 eor #$c3 +0f9f : a8 tay +0fa0 : 28 plp +0fa1 : 940c sty zpt,x +0fa3 : 08 php ;flags after load/store sequence +0fa4 : 49c3 eor #$c3 +0fa6 : d513 cmp zp1,x ;test result + trap_ne +0fa8 : d0fe > bne * ;failed not equal (non zero) + +0faa : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +0fab : 497d > eor #lo~fnz |fao ;invert expected + +0fad : dd1c02 cmp fLDx,x ;test flags + trap_ne +0fb0 : d0fe > bne * ;failed not equal (non zero) + +0fb2 : ca dex +0fb3 : 10df bpl tldy3 + +0fb5 : a203 ldx #3 ;testing store result +0fb7 : a000 ldy #0 +0fb9 : b50c tsty lda zpt,x +0fbb : 49c3 eor #$c3 +0fbd : d513 cmp zp1,x + trap_ne ;store to zp,x data +0fbf : d0fe > bne * ;failed not equal (non zero) + +0fc1 : 940c sty zpt,x ;clear +0fc3 : bd0302 lda abst,x +0fc6 : 49c3 eor #$c3 +0fc8 : dd1702 cmp abs1,x + trap_ne ;store to abs,x data +0fcb : d0fe > bne * ;failed not equal (non zero) + +0fcd : 8a txa +0fce : 9d0302 sta abst,x ;clear +0fd1 : ca dex +0fd2 : 10e5 bpl tsty + next_test +0fd4 : ad0002 > lda test_case ;previous test +0fd7 : c911 > cmp #test_num + > trap_ne ;test is out of sequence +0fd9 : d0fe > bne * ;failed not equal (non zero) + > +0012 = >test_num = test_num + 1 +0fdb : a912 > lda #test_num ;*** next tests' number +0fdd : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; indexed wraparound test (only zp should wrap) +0fe0 : a2fd ldx #3+$fa +0fe2 : b419 tldy4 ldy zp1-$fa&$ff,x ;wrap on indexed zp +0fe4 : 98 tya +0fe5 : 9d0901 sta abst-$fa,x ;no STX abs,x! +0fe8 : ca dex +0fe9 : e0fa cpx #$fa +0feb : b0f5 bcs tldy4 +0fed : a2fd ldx #3+$fa +0fef : bc1d01 tldy5 ldy abs1-$fa,x ;no wrap on indexed abs +0ff2 : 9412 sty zpt-$fa&$ff,x +0ff4 : ca dex +0ff5 : e0fa cpx #$fa +0ff7 : b0f6 bcs tldy5 +0ff9 : a203 ldx #3 ;testing wraparound result +0ffb : a000 ldy #0 +0ffd : b50c tsty1 lda zpt,x +0fff : d513 cmp zp1,x + trap_ne ;store to zp,x data +1001 : d0fe > bne * ;failed not equal (non zero) + +1003 : 940c sty zpt,x ;clear +1005 : bd0302 lda abst,x +1008 : dd1702 cmp abs1,x + trap_ne ;store to abs,x data +100b : d0fe > bne * ;failed not equal (non zero) + +100d : 8a txa +100e : 9d0302 sta abst,x ;clear +1011 : ca dex +1012 : 10e9 bpl tsty1 + next_test +1014 : ad0002 > lda test_case ;previous test +1017 : c912 > cmp #test_num + > trap_ne ;test is out of sequence +1019 : d0fe > bne * ;failed not equal (non zero) + > +0013 = >test_num = test_num + 1 +101b : a913 > lda #test_num ;*** next tests' number +101d : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; LDX / STX - zp / abs / # + set_stat 0 + > load_flag 0 +1020 : a900 > lda #0 ;allow test to change + > +1022 : 48 > pha ;use stack to load status +1023 : 28 > plp + +1024 : a613 ldx zp1 +1026 : 08 php ;test stores do not alter flags +1027 : 8a txa +1028 : 49c3 eor #$c3 +102a : aa tax +102b : 28 plp +102c : 8e0302 stx abst +102f : 08 php ;flags after load/store sequence +1030 : 49c3 eor #$c3 +1032 : aa tax +1033 : e0c3 cpx #$c3 ;test result + trap_ne +1035 : d0fe > bne * ;failed not equal (non zero) + +1037 : 68 pla ;load status + eor_flag 0 +1038 : 4930 > eor #0|fao ;invert expected flags + +103a : cd1c02 cmp fLDx ;test flags + trap_ne +103d : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +103f : a900 > lda #0 ;allow test to change I + > +1041 : 48 > pha ;use stack to load status +1042 : 28 > plp + +1043 : a614 ldx zp1+1 +1045 : 08 php ;test stores do not alter flags +1046 : 8a txa +1047 : 49c3 eor #$c3 +1049 : aa tax +104a : 28 plp +104b : 8e0402 stx abst+1 +104e : 08 php ;flags after load/store sequence +104f : 49c3 eor #$c3 +1051 : aa tax +1052 : e082 cpx #$82 ;test result + trap_ne +1054 : d0fe > bne * ;failed not equal (non zero) + +1056 : 68 pla ;load status + eor_flag 0 +1057 : 4930 > eor #0|fao ;invert expected flags + +1059 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +105c : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +105e : a900 > lda #0 ;allow test to change I + > +1060 : 48 > pha ;use stack to load status +1061 : 28 > plp + +1062 : a615 ldx zp1+2 +1064 : 08 php ;test stores do not alter flags +1065 : 8a txa +1066 : 49c3 eor #$c3 +1068 : aa tax +1069 : 28 plp +106a : 8e0502 stx abst+2 +106d : 08 php ;flags after load/store sequence +106e : 49c3 eor #$c3 +1070 : aa tax +1071 : e041 cpx #$41 ;test result + trap_ne +1073 : d0fe > bne * ;failed not equal (non zero) + +1075 : 68 pla ;load status + eor_flag 0 +1076 : 4930 > eor #0|fao ;invert expected flags + +1078 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +107b : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +107d : a900 > lda #0 ;allow test to change I + > +107f : 48 > pha ;use stack to load status +1080 : 28 > plp + +1081 : a616 ldx zp1+3 +1083 : 08 php ;test stores do not alter flags +1084 : 8a txa +1085 : 49c3 eor #$c3 +1087 : aa tax +1088 : 28 plp +1089 : 8e0602 stx abst+3 +108c : 08 php ;flags after load/store sequence +108d : 49c3 eor #$c3 +108f : aa tax +1090 : e000 cpx #0 ;test result + trap_ne +1092 : d0fe > bne * ;failed not equal (non zero) + +1094 : 68 pla ;load status + eor_flag 0 +1095 : 4930 > eor #0|fao ;invert expected flags + +1097 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +109a : d0fe > bne * ;failed not equal (non zero) + + + set_stat $ff + > load_flag $ff +109c : a9ff > lda #$ff ;allow test to change + > +109e : 48 > pha ;use stack to load status +109f : 28 > plp + +10a0 : a613 ldx zp1 +10a2 : 08 php ;test stores do not alter flags +10a3 : 8a txa +10a4 : 49c3 eor #$c3 +10a6 : aa tax +10a7 : 28 plp +10a8 : 8e0302 stx abst +10ab : 08 php ;flags after load/store sequence +10ac : 49c3 eor #$c3 +10ae : aa tax +10af : e0c3 cpx #$c3 ;test result + trap_ne ; +10b1 : d0fe > bne * ;failed not equal (non zero) + +10b3 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +10b4 : 497d > eor #lo~fnz |fao ;invert expected + +10b6 : cd1c02 cmp fLDx ;test flags + trap_ne +10b9 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +10bb : a9ff > lda #$ff ;allow test to change + > +10bd : 48 > pha ;use stack to load status +10be : 28 > plp + +10bf : a614 ldx zp1+1 +10c1 : 08 php ;test stores do not alter flags +10c2 : 8a txa +10c3 : 49c3 eor #$c3 +10c5 : aa tax +10c6 : 28 plp +10c7 : 8e0402 stx abst+1 +10ca : 08 php ;flags after load/store sequence +10cb : 49c3 eor #$c3 +10cd : aa tax +10ce : e082 cpx #$82 ;test result + trap_ne +10d0 : d0fe > bne * ;failed not equal (non zero) + +10d2 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +10d3 : 497d > eor #lo~fnz |fao ;invert expected + +10d5 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +10d8 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +10da : a9ff > lda #$ff ;allow test to change + > +10dc : 48 > pha ;use stack to load status +10dd : 28 > plp + +10de : a615 ldx zp1+2 +10e0 : 08 php ;test stores do not alter flags +10e1 : 8a txa +10e2 : 49c3 eor #$c3 +10e4 : aa tax +10e5 : 28 plp +10e6 : 8e0502 stx abst+2 +10e9 : 08 php ;flags after load/store sequence +10ea : 49c3 eor #$c3 +10ec : aa tax +10ed : e041 cpx #$41 ;test result + trap_ne ; +10ef : d0fe > bne * ;failed not equal (non zero) + +10f1 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +10f2 : 497d > eor #lo~fnz |fao ;invert expected + +10f4 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +10f7 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +10f9 : a9ff > lda #$ff ;allow test to change + > +10fb : 48 > pha ;use stack to load status +10fc : 28 > plp + +10fd : a616 ldx zp1+3 +10ff : 08 php ;test stores do not alter flags +1100 : 8a txa +1101 : 49c3 eor #$c3 +1103 : aa tax +1104 : 28 plp +1105 : 8e0602 stx abst+3 +1108 : 08 php ;flags after load/store sequence +1109 : 49c3 eor #$c3 +110b : aa tax +110c : e000 cpx #0 ;test result + trap_ne +110e : d0fe > bne * ;failed not equal (non zero) + +1110 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1111 : 497d > eor #lo~fnz |fao ;invert expected + +1113 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +1116 : d0fe > bne * ;failed not equal (non zero) + + + set_stat 0 + > load_flag 0 +1118 : a900 > lda #0 ;allow test to change I + > +111a : 48 > pha ;use stack to load status +111b : 28 > plp + +111c : ae1702 ldx abs1 +111f : 08 php ;test stores do not alter flags +1120 : 8a txa +1121 : 49c3 eor #$c3 +1123 : aa tax +1124 : 28 plp +1125 : 860c stx zpt +1127 : 08 php ;flags after load/store sequence +1128 : 49c3 eor #$c3 +112a : c513 cmp zp1 ;test result + trap_ne +112c : d0fe > bne * ;failed not equal (non zero) + +112e : 68 pla ;load status + eor_flag 0 +112f : 4930 > eor #0|fao ;invert expected flags + +1131 : cd1c02 cmp fLDx ;test flags + trap_ne +1134 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1136 : a900 > lda #0 ;allow test to change I + > +1138 : 48 > pha ;use stack to load status +1139 : 28 > plp + +113a : ae1802 ldx abs1+1 +113d : 08 php ;test stores do not alter flags +113e : 8a txa +113f : 49c3 eor #$c3 +1141 : aa tax +1142 : 28 plp +1143 : 860d stx zpt+1 +1145 : 08 php ;flags after load/store sequence +1146 : 49c3 eor #$c3 +1148 : c514 cmp zp1+1 ;test result + trap_ne +114a : d0fe > bne * ;failed not equal (non zero) + +114c : 68 pla ;load status + eor_flag 0 +114d : 4930 > eor #0|fao ;invert expected flags + +114f : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1152 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1154 : a900 > lda #0 ;allow test to change I + > +1156 : 48 > pha ;use stack to load status +1157 : 28 > plp + +1158 : ae1902 ldx abs1+2 +115b : 08 php ;test stores do not alter flags +115c : 8a txa +115d : 49c3 eor #$c3 +115f : aa tax +1160 : 28 plp +1161 : 860e stx zpt+2 +1163 : 08 php ;flags after load/store sequence +1164 : 49c3 eor #$c3 +1166 : c515 cmp zp1+2 ;test result + trap_ne +1168 : d0fe > bne * ;failed not equal (non zero) + +116a : 68 pla ;load status + eor_flag 0 +116b : 4930 > eor #0|fao ;invert expected flags + +116d : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1170 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1172 : a900 > lda #0 ;allow test to change I + > +1174 : 48 > pha ;use stack to load status +1175 : 28 > plp + +1176 : ae1a02 ldx abs1+3 +1179 : 08 php ;test stores do not alter flags +117a : 8a txa +117b : 49c3 eor #$c3 +117d : aa tax +117e : 28 plp +117f : 860f stx zpt+3 +1181 : 08 php ;flags after load/store sequence +1182 : 49c3 eor #$c3 +1184 : c516 cmp zp1+3 ;test result + trap_ne +1186 : d0fe > bne * ;failed not equal (non zero) + +1188 : 68 pla ;load status + eor_flag 0 +1189 : 4930 > eor #0|fao ;invert expected flags + +118b : cd1f02 cmp fLDx+3 ;test flags + trap_ne +118e : d0fe > bne * ;failed not equal (non zero) + + + set_stat $ff + > load_flag $ff +1190 : a9ff > lda #$ff ;allow test to change + > +1192 : 48 > pha ;use stack to load status +1193 : 28 > plp + +1194 : ae1702 ldx abs1 +1197 : 08 php ;test stores do not alter flags +1198 : 8a txa +1199 : 49c3 eor #$c3 +119b : aa tax +119c : 28 plp +119d : 860c stx zpt +119f : 08 php ;flags after load/store sequence +11a0 : 49c3 eor #$c3 +11a2 : aa tax +11a3 : e413 cpx zp1 ;test result + trap_ne +11a5 : d0fe > bne * ;failed not equal (non zero) + +11a7 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +11a8 : 497d > eor #lo~fnz |fao ;invert expected + +11aa : cd1c02 cmp fLDx ;test flags + trap_ne +11ad : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +11af : a9ff > lda #$ff ;allow test to change + > +11b1 : 48 > pha ;use stack to load status +11b2 : 28 > plp + +11b3 : ae1802 ldx abs1+1 +11b6 : 08 php ;test stores do not alter flags +11b7 : 8a txa +11b8 : 49c3 eor #$c3 +11ba : aa tax +11bb : 28 plp +11bc : 860d stx zpt+1 +11be : 08 php ;flags after load/store sequence +11bf : 49c3 eor #$c3 +11c1 : aa tax +11c2 : e414 cpx zp1+1 ;test result + trap_ne +11c4 : d0fe > bne * ;failed not equal (non zero) + +11c6 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +11c7 : 497d > eor #lo~fnz |fao ;invert expected + +11c9 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +11cc : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +11ce : a9ff > lda #$ff ;allow test to change + > +11d0 : 48 > pha ;use stack to load status +11d1 : 28 > plp + +11d2 : ae1902 ldx abs1+2 +11d5 : 08 php ;test stores do not alter flags +11d6 : 8a txa +11d7 : 49c3 eor #$c3 +11d9 : aa tax +11da : 28 plp +11db : 860e stx zpt+2 +11dd : 08 php ;flags after load/store sequence +11de : 49c3 eor #$c3 +11e0 : aa tax +11e1 : e415 cpx zp1+2 ;test result + trap_ne +11e3 : d0fe > bne * ;failed not equal (non zero) + +11e5 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +11e6 : 497d > eor #lo~fnz |fao ;invert expected + +11e8 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +11eb : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +11ed : a9ff > lda #$ff ;allow test to change + > +11ef : 48 > pha ;use stack to load status +11f0 : 28 > plp + +11f1 : ae1a02 ldx abs1+3 +11f4 : 08 php ;test stores do not alter flags +11f5 : 8a txa +11f6 : 49c3 eor #$c3 +11f8 : aa tax +11f9 : 28 plp +11fa : 860f stx zpt+3 +11fc : 08 php ;flags after load/store sequence +11fd : 49c3 eor #$c3 +11ff : aa tax +1200 : e416 cpx zp1+3 ;test result + trap_ne +1202 : d0fe > bne * ;failed not equal (non zero) + +1204 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1205 : 497d > eor #lo~fnz |fao ;invert expected + +1207 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +120a : d0fe > bne * ;failed not equal (non zero) + + + set_stat 0 + > load_flag 0 +120c : a900 > lda #0 ;allow test to change + > +120e : 48 > pha ;use stack to load status +120f : 28 > plp + +1210 : a2c3 ldx #$c3 +1212 : 08 php +1213 : ec1702 cpx abs1 ;test result + trap_ne +1216 : d0fe > bne * ;failed not equal (non zero) + +1218 : 68 pla ;load status + eor_flag 0 +1219 : 4930 > eor #0|fao ;invert expected flags + +121b : cd1c02 cmp fLDx ;test flags + trap_ne +121e : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1220 : a900 > lda #0 ;allow test to change I + > +1222 : 48 > pha ;use stack to load status +1223 : 28 > plp + +1224 : a282 ldx #$82 +1226 : 08 php +1227 : ec1802 cpx abs1+1 ;test result + trap_ne +122a : d0fe > bne * ;failed not equal (non zero) + +122c : 68 pla ;load status + eor_flag 0 +122d : 4930 > eor #0|fao ;invert expected flags + +122f : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1232 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1234 : a900 > lda #0 ;allow test to change I + > +1236 : 48 > pha ;use stack to load status +1237 : 28 > plp + +1238 : a241 ldx #$41 +123a : 08 php +123b : ec1902 cpx abs1+2 ;test result + trap_ne +123e : d0fe > bne * ;failed not equal (non zero) + +1240 : 68 pla ;load status + eor_flag 0 +1241 : 4930 > eor #0|fao ;invert expected flags + +1243 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1246 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1248 : a900 > lda #0 ;allow test to change I + > +124a : 48 > pha ;use stack to load status +124b : 28 > plp + +124c : a200 ldx #0 +124e : 08 php +124f : ec1a02 cpx abs1+3 ;test result + trap_ne +1252 : d0fe > bne * ;failed not equal (non zero) + +1254 : 68 pla ;load status + eor_flag 0 +1255 : 4930 > eor #0|fao ;invert expected flags + +1257 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +125a : d0fe > bne * ;failed not equal (non zero) + + + set_stat $ff + > load_flag $ff +125c : a9ff > lda #$ff ;allow test to change + > +125e : 48 > pha ;use stack to load status +125f : 28 > plp + +1260 : a2c3 ldx #$c3 +1262 : 08 php +1263 : ec1702 cpx abs1 ;test result + trap_ne +1266 : d0fe > bne * ;failed not equal (non zero) + +1268 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1269 : 497d > eor #lo~fnz |fao ;invert expected + +126b : cd1c02 cmp fLDx ;test flags + trap_ne +126e : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1270 : a9ff > lda #$ff ;allow test to change + > +1272 : 48 > pha ;use stack to load status +1273 : 28 > plp + +1274 : a282 ldx #$82 +1276 : 08 php +1277 : ec1802 cpx abs1+1 ;test result + trap_ne +127a : d0fe > bne * ;failed not equal (non zero) + +127c : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +127d : 497d > eor #lo~fnz |fao ;invert expected + +127f : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1282 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1284 : a9ff > lda #$ff ;allow test to change + > +1286 : 48 > pha ;use stack to load status +1287 : 28 > plp + +1288 : a241 ldx #$41 +128a : 08 php +128b : ec1902 cpx abs1+2 ;test result + trap_ne +128e : d0fe > bne * ;failed not equal (non zero) + +1290 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1291 : 497d > eor #lo~fnz |fao ;invert expected + +1293 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1296 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1298 : a9ff > lda #$ff ;allow test to change + > +129a : 48 > pha ;use stack to load status +129b : 28 > plp + +129c : a200 ldx #0 +129e : 08 php +129f : ec1a02 cpx abs1+3 ;test result + trap_ne +12a2 : d0fe > bne * ;failed not equal (non zero) + +12a4 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +12a5 : 497d > eor #lo~fnz |fao ;invert expected + +12a7 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +12aa : d0fe > bne * ;failed not equal (non zero) + + +12ac : a200 ldx #0 +12ae : a50c lda zpt +12b0 : 49c3 eor #$c3 +12b2 : c513 cmp zp1 + trap_ne ;store to zp data +12b4 : d0fe > bne * ;failed not equal (non zero) + +12b6 : 860c stx zpt ;clear +12b8 : ad0302 lda abst +12bb : 49c3 eor #$c3 +12bd : cd1702 cmp abs1 + trap_ne ;store to abs data +12c0 : d0fe > bne * ;failed not equal (non zero) + +12c2 : 8e0302 stx abst ;clear +12c5 : a50d lda zpt+1 +12c7 : 49c3 eor #$c3 +12c9 : c514 cmp zp1+1 + trap_ne ;store to zp data +12cb : d0fe > bne * ;failed not equal (non zero) + +12cd : 860d stx zpt+1 ;clear +12cf : ad0402 lda abst+1 +12d2 : 49c3 eor #$c3 +12d4 : cd1802 cmp abs1+1 + trap_ne ;store to abs data +12d7 : d0fe > bne * ;failed not equal (non zero) + +12d9 : 8e0402 stx abst+1 ;clear +12dc : a50e lda zpt+2 +12de : 49c3 eor #$c3 +12e0 : c515 cmp zp1+2 + trap_ne ;store to zp data +12e2 : d0fe > bne * ;failed not equal (non zero) + +12e4 : 860e stx zpt+2 ;clear +12e6 : ad0502 lda abst+2 +12e9 : 49c3 eor #$c3 +12eb : cd1902 cmp abs1+2 + trap_ne ;store to abs data +12ee : d0fe > bne * ;failed not equal (non zero) + +12f0 : 8e0502 stx abst+2 ;clear +12f3 : a50f lda zpt+3 +12f5 : 49c3 eor #$c3 +12f7 : c516 cmp zp1+3 + trap_ne ;store to zp data +12f9 : d0fe > bne * ;failed not equal (non zero) + +12fb : 860f stx zpt+3 ;clear +12fd : ad0602 lda abst+3 +1300 : 49c3 eor #$c3 +1302 : cd1a02 cmp abs1+3 + trap_ne ;store to abs data +1305 : d0fe > bne * ;failed not equal (non zero) + +1307 : 8e0602 stx abst+3 ;clear + next_test +130a : ad0002 > lda test_case ;previous test +130d : c913 > cmp #test_num + > trap_ne ;test is out of sequence +130f : d0fe > bne * ;failed not equal (non zero) + > +0014 = >test_num = test_num + 1 +1311 : a914 > lda #test_num ;*** next tests' number +1313 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; LDY / STY - zp / abs / # + set_stat 0 + > load_flag 0 +1316 : a900 > lda #0 ;allow test to change I + > +1318 : 48 > pha ;use stack to load status +1319 : 28 > plp + +131a : a413 ldy zp1 +131c : 08 php ;test stores do not alter flags +131d : 98 tya +131e : 49c3 eor #$c3 +1320 : a8 tay +1321 : 28 plp +1322 : 8c0302 sty abst +1325 : 08 php ;flags after load/store sequence +1326 : 49c3 eor #$c3 +1328 : a8 tay +1329 : c0c3 cpy #$c3 ;test result + trap_ne +132b : d0fe > bne * ;failed not equal (non zero) + +132d : 68 pla ;load status + eor_flag 0 +132e : 4930 > eor #0|fao ;invert expected flags + +1330 : cd1c02 cmp fLDx ;test flags + trap_ne +1333 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1335 : a900 > lda #0 ;allow test to change I + > +1337 : 48 > pha ;use stack to load status +1338 : 28 > plp + +1339 : a414 ldy zp1+1 +133b : 08 php ;test stores do not alter flags +133c : 98 tya +133d : 49c3 eor #$c3 +133f : a8 tay +1340 : 28 plp +1341 : 8c0402 sty abst+1 +1344 : 08 php ;flags after load/store sequence +1345 : 49c3 eor #$c3 +1347 : a8 tay +1348 : c082 cpy #$82 ;test result + trap_ne +134a : d0fe > bne * ;failed not equal (non zero) + +134c : 68 pla ;load status + eor_flag 0 +134d : 4930 > eor #0|fao ;invert expected flags + +134f : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1352 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1354 : a900 > lda #0 ;allow test to change I + > +1356 : 48 > pha ;use stack to load status +1357 : 28 > plp + +1358 : a415 ldy zp1+2 +135a : 08 php ;test stores do not alter flags +135b : 98 tya +135c : 49c3 eor #$c3 +135e : a8 tay +135f : 28 plp +1360 : 8c0502 sty abst+2 +1363 : 08 php ;flags after load/store sequence +1364 : 49c3 eor #$c3 +1366 : a8 tay +1367 : c041 cpy #$41 ;test result + trap_ne +1369 : d0fe > bne * ;failed not equal (non zero) + +136b : 68 pla ;load status + eor_flag 0 +136c : 4930 > eor #0|fao ;invert expected flags + +136e : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1371 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1373 : a900 > lda #0 ;allow test to change I + > +1375 : 48 > pha ;use stack to load status +1376 : 28 > plp + +1377 : a416 ldy zp1+3 +1379 : 08 php ;test stores do not alter flags +137a : 98 tya +137b : 49c3 eor #$c3 +137d : a8 tay +137e : 28 plp +137f : 8c0602 sty abst+3 +1382 : 08 php ;flags after load/store sequence +1383 : 49c3 eor #$c3 +1385 : a8 tay +1386 : c000 cpy #0 ;test result + trap_ne +1388 : d0fe > bne * ;failed not equal (non zero) + +138a : 68 pla ;load status + eor_flag 0 +138b : 4930 > eor #0|fao ;invert expected flags + +138d : cd1f02 cmp fLDx+3 ;test flags + trap_ne +1390 : d0fe > bne * ;failed not equal (non zero) + + + set_stat $ff + > load_flag $ff +1392 : a9ff > lda #$ff ;allow test to change + > +1394 : 48 > pha ;use stack to load status +1395 : 28 > plp + +1396 : a413 ldy zp1 +1398 : 08 php ;test stores do not alter flags +1399 : 98 tya +139a : 49c3 eor #$c3 +139c : a8 tay +139d : 28 plp +139e : 8c0302 sty abst +13a1 : 08 php ;flags after load/store sequence +13a2 : 49c3 eor #$c3 +13a4 : a8 tay +13a5 : c0c3 cpy #$c3 ;test result + trap_ne +13a7 : d0fe > bne * ;failed not equal (non zero) + +13a9 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +13aa : 497d > eor #lo~fnz |fao ;invert expected + +13ac : cd1c02 cmp fLDx ;test flags + trap_ne +13af : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +13b1 : a9ff > lda #$ff ;allow test to change + > +13b3 : 48 > pha ;use stack to load status +13b4 : 28 > plp + +13b5 : a414 ldy zp1+1 +13b7 : 08 php ;test stores do not alter flags +13b8 : 98 tya +13b9 : 49c3 eor #$c3 +13bb : a8 tay +13bc : 28 plp +13bd : 8c0402 sty abst+1 +13c0 : 08 php ;flags after load/store sequence +13c1 : 49c3 eor #$c3 +13c3 : a8 tay +13c4 : c082 cpy #$82 ;test result + trap_ne +13c6 : d0fe > bne * ;failed not equal (non zero) + +13c8 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +13c9 : 497d > eor #lo~fnz |fao ;invert expected + +13cb : cd1d02 cmp fLDx+1 ;test flags + trap_ne +13ce : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +13d0 : a9ff > lda #$ff ;allow test to change + > +13d2 : 48 > pha ;use stack to load status +13d3 : 28 > plp + +13d4 : a415 ldy zp1+2 +13d6 : 08 php ;test stores do not alter flags +13d7 : 98 tya +13d8 : 49c3 eor #$c3 +13da : a8 tay +13db : 28 plp +13dc : 8c0502 sty abst+2 +13df : 08 php ;flags after load/store sequence +13e0 : 49c3 eor #$c3 +13e2 : a8 tay +13e3 : c041 cpy #$41 ;test result + trap_ne +13e5 : d0fe > bne * ;failed not equal (non zero) + +13e7 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +13e8 : 497d > eor #lo~fnz |fao ;invert expected + +13ea : cd1e02 cmp fLDx+2 ;test flags + trap_ne +13ed : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +13ef : a9ff > lda #$ff ;allow test to change + > +13f1 : 48 > pha ;use stack to load status +13f2 : 28 > plp + +13f3 : a416 ldy zp1+3 +13f5 : 08 php ;test stores do not alter flags +13f6 : 98 tya +13f7 : 49c3 eor #$c3 +13f9 : a8 tay +13fa : 28 plp +13fb : 8c0602 sty abst+3 +13fe : 08 php ;flags after load/store sequence +13ff : 49c3 eor #$c3 +1401 : a8 tay +1402 : c000 cpy #0 ;test result + trap_ne +1404 : d0fe > bne * ;failed not equal (non zero) + +1406 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1407 : 497d > eor #lo~fnz |fao ;invert expected + +1409 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +140c : d0fe > bne * ;failed not equal (non zero) + + + set_stat 0 + > load_flag 0 +140e : a900 > lda #0 ;allow test to change I + > +1410 : 48 > pha ;use stack to load status +1411 : 28 > plp + +1412 : ac1702 ldy abs1 +1415 : 08 php ;test stores do not alter flags +1416 : 98 tya +1417 : 49c3 eor #$c3 +1419 : a8 tay +141a : 28 plp +141b : 840c sty zpt +141d : 08 php ;flags after load/store sequence +141e : 49c3 eor #$c3 +1420 : a8 tay +1421 : c413 cpy zp1 ;test result + trap_ne +1423 : d0fe > bne * ;failed not equal (non zero) + +1425 : 68 pla ;load status + eor_flag 0 +1426 : 4930 > eor #0|fao ;invert expected flags + +1428 : cd1c02 cmp fLDx ;test flags + trap_ne +142b : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +142d : a900 > lda #0 ;allow test to change I + > +142f : 48 > pha ;use stack to load status +1430 : 28 > plp + +1431 : ac1802 ldy abs1+1 +1434 : 08 php ;test stores do not alter flags +1435 : 98 tya +1436 : 49c3 eor #$c3 +1438 : a8 tay +1439 : 28 plp +143a : 840d sty zpt+1 +143c : 08 php ;flags after load/store sequence +143d : 49c3 eor #$c3 +143f : a8 tay +1440 : c414 cpy zp1+1 ;test result + trap_ne +1442 : d0fe > bne * ;failed not equal (non zero) + +1444 : 68 pla ;load status + eor_flag 0 +1445 : 4930 > eor #0|fao ;invert expected flags + +1447 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +144a : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +144c : a900 > lda #0 ;allow test to change I + > +144e : 48 > pha ;use stack to load status +144f : 28 > plp + +1450 : ac1902 ldy abs1+2 +1453 : 08 php ;test stores do not alter flags +1454 : 98 tya +1455 : 49c3 eor #$c3 +1457 : a8 tay +1458 : 28 plp +1459 : 840e sty zpt+2 +145b : 08 php ;flags after load/store sequence +145c : 49c3 eor #$c3 +145e : a8 tay +145f : c415 cpy zp1+2 ;test result + trap_ne +1461 : d0fe > bne * ;failed not equal (non zero) + +1463 : 68 pla ;load status + eor_flag 0 +1464 : 4930 > eor #0|fao ;invert expected flags + +1466 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1469 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +146b : a900 > lda #0 ;allow test to change I + > +146d : 48 > pha ;use stack to load status +146e : 28 > plp + +146f : ac1a02 ldy abs1+3 +1472 : 08 php ;test stores do not alter flags +1473 : 98 tya +1474 : 49c3 eor #$c3 +1476 : a8 tay +1477 : 28 plp +1478 : 840f sty zpt+3 +147a : 08 php ;flags after load/store sequence +147b : 49c3 eor #$c3 +147d : a8 tay +147e : c416 cpy zp1+3 ;test result + trap_ne +1480 : d0fe > bne * ;failed not equal (non zero) + +1482 : 68 pla ;load status + eor_flag 0 +1483 : 4930 > eor #0|fao ;invert expected flags + +1485 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +1488 : d0fe > bne * ;failed not equal (non zero) + + + set_stat $ff + > load_flag $ff +148a : a9ff > lda #$ff ;allow test to change + > +148c : 48 > pha ;use stack to load status +148d : 28 > plp + +148e : ac1702 ldy abs1 +1491 : 08 php ;test stores do not alter flags +1492 : 98 tya +1493 : 49c3 eor #$c3 +1495 : a8 tay +1496 : 28 plp +1497 : 840c sty zpt +1499 : 08 php ;flags after load/store sequence +149a : 49c3 eor #$c3 +149c : a8 tay +149d : c513 cmp zp1 ;test result + trap_ne +149f : d0fe > bne * ;failed not equal (non zero) + +14a1 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +14a2 : 497d > eor #lo~fnz |fao ;invert expected + +14a4 : cd1c02 cmp fLDx ;test flags + trap_ne +14a7 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +14a9 : a9ff > lda #$ff ;allow test to change + > +14ab : 48 > pha ;use stack to load status +14ac : 28 > plp + +14ad : ac1802 ldy abs1+1 +14b0 : 08 php ;test stores do not alter flags +14b1 : 98 tya +14b2 : 49c3 eor #$c3 +14b4 : a8 tay +14b5 : 28 plp +14b6 : 840d sty zpt+1 +14b8 : 08 php ;flags after load/store sequence +14b9 : 49c3 eor #$c3 +14bb : a8 tay +14bc : c514 cmp zp1+1 ;test result + trap_ne +14be : d0fe > bne * ;failed not equal (non zero) + +14c0 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +14c1 : 497d > eor #lo~fnz |fao ;invert expected + +14c3 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +14c6 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +14c8 : a9ff > lda #$ff ;allow test to change + > +14ca : 48 > pha ;use stack to load status +14cb : 28 > plp + +14cc : ac1902 ldy abs1+2 +14cf : 08 php ;test stores do not alter flags +14d0 : 98 tya +14d1 : 49c3 eor #$c3 +14d3 : a8 tay +14d4 : 28 plp +14d5 : 840e sty zpt+2 +14d7 : 08 php ;flags after load/store sequence +14d8 : 49c3 eor #$c3 +14da : a8 tay +14db : c515 cmp zp1+2 ;test result + trap_ne +14dd : d0fe > bne * ;failed not equal (non zero) + +14df : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +14e0 : 497d > eor #lo~fnz |fao ;invert expected + +14e2 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +14e5 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +14e7 : a9ff > lda #$ff ;allow test to change + > +14e9 : 48 > pha ;use stack to load status +14ea : 28 > plp + +14eb : ac1a02 ldy abs1+3 +14ee : 08 php ;test stores do not alter flags +14ef : 98 tya +14f0 : 49c3 eor #$c3 +14f2 : a8 tay +14f3 : 28 plp +14f4 : 840f sty zpt+3 +14f6 : 08 php ;flags after load/store sequence +14f7 : 49c3 eor #$c3 +14f9 : a8 tay +14fa : c516 cmp zp1+3 ;test result + trap_ne +14fc : d0fe > bne * ;failed not equal (non zero) + +14fe : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +14ff : 497d > eor #lo~fnz |fao ;invert expected + +1501 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +1504 : d0fe > bne * ;failed not equal (non zero) + + + + set_stat 0 + > load_flag 0 +1506 : a900 > lda #0 ;allow test to change I + > +1508 : 48 > pha ;use stack to load status +1509 : 28 > plp + +150a : a0c3 ldy #$c3 +150c : 08 php +150d : cc1702 cpy abs1 ;test result + trap_ne +1510 : d0fe > bne * ;failed not equal (non zero) + +1512 : 68 pla ;load status + eor_flag 0 +1513 : 4930 > eor #0|fao ;invert expected flags + +1515 : cd1c02 cmp fLDx ;test flags + trap_ne +1518 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +151a : a900 > lda #0 ;allow test to change I + > +151c : 48 > pha ;use stack to load status +151d : 28 > plp + +151e : a082 ldy #$82 +1520 : 08 php +1521 : cc1802 cpy abs1+1 ;test result + trap_ne +1524 : d0fe > bne * ;failed not equal (non zero) + +1526 : 68 pla ;load status + eor_flag 0 +1527 : 4930 > eor #0|fao ;invert expected flags + +1529 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +152c : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +152e : a900 > lda #0 ;allow test to change I + > +1530 : 48 > pha ;use stack to load status +1531 : 28 > plp + +1532 : a041 ldy #$41 +1534 : 08 php +1535 : cc1902 cpy abs1+2 ;test result + trap_ne +1538 : d0fe > bne * ;failed not equal (non zero) + +153a : 68 pla ;load status + eor_flag 0 +153b : 4930 > eor #0|fao ;invert expected flags + +153d : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1540 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1542 : a900 > lda #0 ;allow test to change I + > +1544 : 48 > pha ;use stack to load status +1545 : 28 > plp + +1546 : a000 ldy #0 +1548 : 08 php +1549 : cc1a02 cpy abs1+3 ;test result + trap_ne +154c : d0fe > bne * ;failed not equal (non zero) + +154e : 68 pla ;load status + eor_flag 0 +154f : 4930 > eor #0|fao ;invert expected flags + +1551 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +1554 : d0fe > bne * ;failed not equal (non zero) + + + set_stat $ff + > load_flag $ff +1556 : a9ff > lda #$ff ;allow test to change + > +1558 : 48 > pha ;use stack to load status +1559 : 28 > plp + +155a : a0c3 ldy #$c3 +155c : 08 php +155d : cc1702 cpy abs1 ;test result + trap_ne +1560 : d0fe > bne * ;failed not equal (non zero) + +1562 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1563 : 497d > eor #lo~fnz |fao ;invert expected + +1565 : cd1c02 cmp fLDx ;test flags + trap_ne +1568 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +156a : a9ff > lda #$ff ;allow test to change + > +156c : 48 > pha ;use stack to load status +156d : 28 > plp + +156e : a082 ldy #$82 +1570 : 08 php +1571 : cc1802 cpy abs1+1 ;test result + trap_ne +1574 : d0fe > bne * ;failed not equal (non zero) + +1576 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1577 : 497d > eor #lo~fnz |fao ;invert expected + +1579 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +157c : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +157e : a9ff > lda #$ff ;allow test to change + > +1580 : 48 > pha ;use stack to load status +1581 : 28 > plp + +1582 : a041 ldy #$41 +1584 : 08 php +1585 : cc1902 cpy abs1+2 ;test result + trap_ne +1588 : d0fe > bne * ;failed not equal (non zero) + +158a : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +158b : 497d > eor #lo~fnz |fao ;invert expected + +158d : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1590 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1592 : a9ff > lda #$ff ;allow test to change + > +1594 : 48 > pha ;use stack to load status +1595 : 28 > plp + +1596 : a000 ldy #0 +1598 : 08 php +1599 : cc1a02 cpy abs1+3 ;test result + trap_ne +159c : d0fe > bne * ;failed not equal (non zero) + +159e : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +159f : 497d > eor #lo~fnz |fao ;invert expected + +15a1 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +15a4 : d0fe > bne * ;failed not equal (non zero) + + +15a6 : a000 ldy #0 +15a8 : a50c lda zpt +15aa : 49c3 eor #$c3 +15ac : c513 cmp zp1 + trap_ne ;store to zp data +15ae : d0fe > bne * ;failed not equal (non zero) + +15b0 : 840c sty zpt ;clear +15b2 : ad0302 lda abst +15b5 : 49c3 eor #$c3 +15b7 : cd1702 cmp abs1 + trap_ne ;store to abs data +15ba : d0fe > bne * ;failed not equal (non zero) + +15bc : 8c0302 sty abst ;clear +15bf : a50d lda zpt+1 +15c1 : 49c3 eor #$c3 +15c3 : c514 cmp zp1+1 + trap_ne ;store to zp+1 data +15c5 : d0fe > bne * ;failed not equal (non zero) + +15c7 : 840d sty zpt+1 ;clear +15c9 : ad0402 lda abst+1 +15cc : 49c3 eor #$c3 +15ce : cd1802 cmp abs1+1 + trap_ne ;store to abs+1 data +15d1 : d0fe > bne * ;failed not equal (non zero) + +15d3 : 8c0402 sty abst+1 ;clear +15d6 : a50e lda zpt+2 +15d8 : 49c3 eor #$c3 +15da : c515 cmp zp1+2 + trap_ne ;store to zp+2 data +15dc : d0fe > bne * ;failed not equal (non zero) + +15de : 840e sty zpt+2 ;clear +15e0 : ad0502 lda abst+2 +15e3 : 49c3 eor #$c3 +15e5 : cd1902 cmp abs1+2 + trap_ne ;store to abs+2 data +15e8 : d0fe > bne * ;failed not equal (non zero) + +15ea : 8c0502 sty abst+2 ;clear +15ed : a50f lda zpt+3 +15ef : 49c3 eor #$c3 +15f1 : c516 cmp zp1+3 + trap_ne ;store to zp+3 data +15f3 : d0fe > bne * ;failed not equal (non zero) + +15f5 : 840f sty zpt+3 ;clear +15f7 : ad0602 lda abst+3 +15fa : 49c3 eor #$c3 +15fc : cd1a02 cmp abs1+3 + trap_ne ;store to abs+3 data +15ff : d0fe > bne * ;failed not equal (non zero) + +1601 : 8c0602 sty abst+3 ;clear + next_test +1604 : ad0002 > lda test_case ;previous test +1607 : c914 > cmp #test_num + > trap_ne ;test is out of sequence +1609 : d0fe > bne * ;failed not equal (non zero) + > +0015 = >test_num = test_num + 1 +160b : a915 > lda #test_num ;*** next tests' number +160d : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; testing load / store accumulator LDA / STA all addre + ; LDA / STA - zp,x / abs,x +1610 : a203 ldx #3 +1612 : tldax + set_stat 0 + > load_flag 0 +1612 : a900 > lda #0 ;allow test to change I + > +1614 : 48 > pha ;use stack to load status +1615 : 28 > plp + +1616 : b513 lda zp1,x +1618 : 08 php ;test stores do not alter flags +1619 : 49c3 eor #$c3 +161b : 28 plp +161c : 9d0302 sta abst,x +161f : 08 php ;flags after load/store sequence +1620 : 49c3 eor #$c3 +1622 : dd1702 cmp abs1,x ;test result + trap_ne +1625 : d0fe > bne * ;failed not equal (non zero) + +1627 : 68 pla ;load status + eor_flag 0 +1628 : 4930 > eor #0|fao ;invert expected flags + +162a : dd1c02 cmp fLDx,x ;test flags + trap_ne +162d : d0fe > bne * ;failed not equal (non zero) + +162f : ca dex +1630 : 10e0 bpl tldax + +1632 : a203 ldx #3 +1634 : tldax1 + set_stat $ff + > load_flag $ff +1634 : a9ff > lda #$ff ;allow test to change + > +1636 : 48 > pha ;use stack to load status +1637 : 28 > plp + +1638 : b513 lda zp1,x +163a : 08 php ;test stores do not alter flags +163b : 49c3 eor #$c3 +163d : 28 plp +163e : 9d0302 sta abst,x +1641 : 08 php ;flags after load/store sequence +1642 : 49c3 eor #$c3 +1644 : dd1702 cmp abs1,x ;test result + trap_ne +1647 : d0fe > bne * ;failed not equal (non zero) + +1649 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +164a : 497d > eor #lo~fnz |fao ;invert expected + +164c : dd1c02 cmp fLDx,x ;test flags + trap_ne +164f : d0fe > bne * ;failed not equal (non zero) + +1651 : ca dex +1652 : 10e0 bpl tldax1 + +1654 : a203 ldx #3 +1656 : tldax2 + set_stat 0 + > load_flag 0 +1656 : a900 > lda #0 ;allow test to change I + > +1658 : 48 > pha ;use stack to load status +1659 : 28 > plp + +165a : bd1702 lda abs1,x +165d : 08 php ;test stores do not alter flags +165e : 49c3 eor #$c3 +1660 : 28 plp +1661 : 950c sta zpt,x +1663 : 08 php ;flags after load/store sequence +1664 : 49c3 eor #$c3 +1666 : d513 cmp zp1,x ;test result + trap_ne +1668 : d0fe > bne * ;failed not equal (non zero) + +166a : 68 pla ;load status + eor_flag 0 +166b : 4930 > eor #0|fao ;invert expected flags + +166d : dd1c02 cmp fLDx,x ;test flags + trap_ne +1670 : d0fe > bne * ;failed not equal (non zero) + +1672 : ca dex +1673 : 10e1 bpl tldax2 + +1675 : a203 ldx #3 +1677 : tldax3 + set_stat $ff + > load_flag $ff +1677 : a9ff > lda #$ff ;allow test to change + > +1679 : 48 > pha ;use stack to load status +167a : 28 > plp + +167b : bd1702 lda abs1,x +167e : 08 php ;test stores do not alter flags +167f : 49c3 eor #$c3 +1681 : 28 plp +1682 : 950c sta zpt,x +1684 : 08 php ;flags after load/store sequence +1685 : 49c3 eor #$c3 +1687 : d513 cmp zp1,x ;test result + trap_ne +1689 : d0fe > bne * ;failed not equal (non zero) + +168b : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +168c : 497d > eor #lo~fnz |fao ;invert expected + +168e : dd1c02 cmp fLDx,x ;test flags + trap_ne +1691 : d0fe > bne * ;failed not equal (non zero) + +1693 : ca dex +1694 : 10e1 bpl tldax3 + +1696 : a203 ldx #3 ;testing store result +1698 : a000 ldy #0 +169a : b50c tstax lda zpt,x +169c : 49c3 eor #$c3 +169e : d513 cmp zp1,x + trap_ne ;store to zp,x data +16a0 : d0fe > bne * ;failed not equal (non zero) + +16a2 : 940c sty zpt,x ;clear +16a4 : bd0302 lda abst,x +16a7 : 49c3 eor #$c3 +16a9 : dd1702 cmp abs1,x + trap_ne ;store to abs,x data +16ac : d0fe > bne * ;failed not equal (non zero) + +16ae : 8a txa +16af : 9d0302 sta abst,x ;clear +16b2 : ca dex +16b3 : 10e5 bpl tstax + next_test +16b5 : ad0002 > lda test_case ;previous test +16b8 : c915 > cmp #test_num + > trap_ne ;test is out of sequence +16ba : d0fe > bne * ;failed not equal (non zero) + > +0016 = >test_num = test_num + 1 +16bc : a916 > lda #test_num ;*** next tests' number +16be : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; LDA / STA - (zp),y / abs,y / (zp,x) +16c1 : a003 ldy #3 +16c3 : tlday + set_stat 0 + > load_flag 0 +16c3 : a900 > lda #0 ;allow test to change I + > +16c5 : 48 > pha ;use stack to load status +16c6 : 28 > plp + +16c7 : b124 lda (ind1),y +16c9 : 08 php ;test stores do not alter flags +16ca : 49c3 eor #$c3 +16cc : 28 plp +16cd : 990302 sta abst,y +16d0 : 08 php ;flags after load/store sequence +16d1 : 49c3 eor #$c3 +16d3 : d91702 cmp abs1,y ;test result + trap_ne +16d6 : d0fe > bne * ;failed not equal (non zero) + +16d8 : 68 pla ;load status + eor_flag 0 +16d9 : 4930 > eor #0|fao ;invert expected flags + +16db : d91c02 cmp fLDx,y ;test flags + trap_ne +16de : d0fe > bne * ;failed not equal (non zero) + +16e0 : 88 dey +16e1 : 10e0 bpl tlday + +16e3 : a003 ldy #3 +16e5 : tlday1 + set_stat $ff + > load_flag $ff +16e5 : a9ff > lda #$ff ;allow test to change + > +16e7 : 48 > pha ;use stack to load status +16e8 : 28 > plp + +16e9 : b124 lda (ind1),y +16eb : 08 php ;test stores do not alter flags +16ec : 49c3 eor #$c3 +16ee : 28 plp +16ef : 990302 sta abst,y +16f2 : 08 php ;flags after load/store sequence +16f3 : 49c3 eor #$c3 +16f5 : d91702 cmp abs1,y ;test result + trap_ne +16f8 : d0fe > bne * ;failed not equal (non zero) + +16fa : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +16fb : 497d > eor #lo~fnz |fao ;invert expected + +16fd : d91c02 cmp fLDx,y ;test flags + trap_ne +1700 : d0fe > bne * ;failed not equal (non zero) + +1702 : 88 dey +1703 : 10e0 bpl tlday1 + +1705 : a003 ldy #3 ;testing store result +1707 : a200 ldx #0 +1709 : b90302 tstay lda abst,y +170c : 49c3 eor #$c3 +170e : d91702 cmp abs1,y + trap_ne ;store to abs data +1711 : d0fe > bne * ;failed not equal (non zero) + +1713 : 8a txa +1714 : 990302 sta abst,y ;clear +1717 : 88 dey +1718 : 10ef bpl tstay + +171a : a003 ldy #3 +171c : tlday2 + set_stat 0 + > load_flag 0 +171c : a900 > lda #0 ;allow test to change I + > +171e : 48 > pha ;use stack to load status +171f : 28 > plp + +1720 : b91702 lda abs1,y +1723 : 08 php ;test stores do not alter flags +1724 : 49c3 eor #$c3 +1726 : 28 plp +1727 : 9130 sta (indt),y +1729 : 08 php ;flags after load/store sequence +172a : 49c3 eor #$c3 +172c : d124 cmp (ind1),y ;test result + trap_ne +172e : d0fe > bne * ;failed not equal (non zero) + +1730 : 68 pla ;load status + eor_flag 0 +1731 : 4930 > eor #0|fao ;invert expected flags + +1733 : d91c02 cmp fLDx,y ;test flags + trap_ne +1736 : d0fe > bne * ;failed not equal (non zero) + +1738 : 88 dey +1739 : 10e1 bpl tlday2 + +173b : a003 ldy #3 +173d : tlday3 + set_stat $ff + > load_flag $ff +173d : a9ff > lda #$ff ;allow test to change + > +173f : 48 > pha ;use stack to load status +1740 : 28 > plp + +1741 : b91702 lda abs1,y +1744 : 08 php ;test stores do not alter flags +1745 : 49c3 eor #$c3 +1747 : 28 plp +1748 : 9130 sta (indt),y +174a : 08 php ;flags after load/store sequence +174b : 49c3 eor #$c3 +174d : d124 cmp (ind1),y ;test result + trap_ne +174f : d0fe > bne * ;failed not equal (non zero) + +1751 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1752 : 497d > eor #lo~fnz |fao ;invert expected + +1754 : d91c02 cmp fLDx,y ;test flags + trap_ne +1757 : d0fe > bne * ;failed not equal (non zero) + +1759 : 88 dey +175a : 10e1 bpl tlday3 + +175c : a003 ldy #3 ;testing store result +175e : a200 ldx #0 +1760 : b90302 tstay1 lda abst,y +1763 : 49c3 eor #$c3 +1765 : d91702 cmp abs1,y + trap_ne ;store to abs data +1768 : d0fe > bne * ;failed not equal (non zero) + +176a : 8a txa +176b : 990302 sta abst,y ;clear +176e : 88 dey +176f : 10ef bpl tstay1 + +1771 : a206 ldx #6 +1773 : a003 ldy #3 +1775 : tldax4 + set_stat 0 + > load_flag 0 +1775 : a900 > lda #0 ;allow test to change I + > +1777 : 48 > pha ;use stack to load status +1778 : 28 > plp + +1779 : a124 lda (ind1,x) +177b : 08 php ;test stores do not alter flags +177c : 49c3 eor #$c3 +177e : 28 plp +177f : 8130 sta (indt,x) +1781 : 08 php ;flags after load/store sequence +1782 : 49c3 eor #$c3 +1784 : d91702 cmp abs1,y ;test result + trap_ne +1787 : d0fe > bne * ;failed not equal (non zero) + +1789 : 68 pla ;load status + eor_flag 0 +178a : 4930 > eor #0|fao ;invert expected flags + +178c : d91c02 cmp fLDx,y ;test flags + trap_ne +178f : d0fe > bne * ;failed not equal (non zero) + +1791 : ca dex +1792 : ca dex +1793 : 88 dey +1794 : 10df bpl tldax4 + +1796 : a206 ldx #6 +1798 : a003 ldy #3 +179a : tldax5 + set_stat $ff + > load_flag $ff +179a : a9ff > lda #$ff ;allow test to change + > +179c : 48 > pha ;use stack to load status +179d : 28 > plp + +179e : a124 lda (ind1,x) +17a0 : 08 php ;test stores do not alter flags +17a1 : 49c3 eor #$c3 +17a3 : 28 plp +17a4 : 8130 sta (indt,x) +17a6 : 08 php ;flags after load/store sequence +17a7 : 49c3 eor #$c3 +17a9 : d91702 cmp abs1,y ;test result + trap_ne +17ac : d0fe > bne * ;failed not equal (non zero) + +17ae : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +17af : 497d > eor #lo~fnz |fao ;invert expected + +17b1 : d91c02 cmp fLDx,y ;test flags + trap_ne +17b4 : d0fe > bne * ;failed not equal (non zero) + +17b6 : ca dex +17b7 : ca dex +17b8 : 88 dey +17b9 : 10df bpl tldax5 + +17bb : a003 ldy #3 ;testing store result +17bd : a200 ldx #0 +17bf : b90302 tstay2 lda abst,y +17c2 : 49c3 eor #$c3 +17c4 : d91702 cmp abs1,y + trap_ne ;store to abs data +17c7 : d0fe > bne * ;failed not equal (non zero) + +17c9 : 8a txa +17ca : 990302 sta abst,y ;clear +17cd : 88 dey +17ce : 10ef bpl tstay2 + next_test +17d0 : ad0002 > lda test_case ;previous test +17d3 : c916 > cmp #test_num + > trap_ne ;test is out of sequence +17d5 : d0fe > bne * ;failed not equal (non zero) + > +0017 = >test_num = test_num + 1 +17d7 : a917 > lda #test_num ;*** next tests' number +17d9 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; indexed wraparound test (only zp should wrap) +17dc : a2fd ldx #3+$fa +17de : b519 tldax6 lda zp1-$fa&$ff,x ;wrap on indexed zp +17e0 : 9d0901 sta abst-$fa,x ;no STX abs,x! +17e3 : ca dex +17e4 : e0fa cpx #$fa +17e6 : b0f6 bcs tldax6 +17e8 : a2fd ldx #3+$fa +17ea : bd1d01 tldax7 lda abs1-$fa,x ;no wrap on indexed abs +17ed : 9512 sta zpt-$fa&$ff,x +17ef : ca dex +17f0 : e0fa cpx #$fa +17f2 : b0f6 bcs tldax7 + +17f4 : a203 ldx #3 ;testing wraparound result +17f6 : a000 ldy #0 +17f8 : b50c tstax1 lda zpt,x +17fa : d513 cmp zp1,x + trap_ne ;store to zp,x data +17fc : d0fe > bne * ;failed not equal (non zero) + +17fe : 940c sty zpt,x ;clear +1800 : bd0302 lda abst,x +1803 : dd1702 cmp abs1,x + trap_ne ;store to abs,x data +1806 : d0fe > bne * ;failed not equal (non zero) + +1808 : 8a txa +1809 : 9d0302 sta abst,x ;clear +180c : ca dex +180d : 10e9 bpl tstax1 + +180f : a0fb ldy #3+$f8 +1811 : a2fe ldx #6+$f8 +1813 : a12c tlday4 lda (ind1-$f8&$ff,x) ;wrap on indexed zp indir +1815 : 990b01 sta abst-$f8,y +1818 : ca dex +1819 : ca dex +181a : 88 dey +181b : c0f8 cpy #$f8 +181d : b0f4 bcs tlday4 +181f : a003 ldy #3 ;testing wraparound result +1821 : a200 ldx #0 +1823 : b90302 tstay4 lda abst,y +1826 : d91702 cmp abs1,y + trap_ne ;store to abs data +1829 : d0fe > bne * ;failed not equal (non zero) + +182b : 8a txa +182c : 990302 sta abst,y ;clear +182f : 88 dey +1830 : 10f1 bpl tstay4 + +1832 : a0fb ldy #3+$f8 +1834 : b91f01 tlday5 lda abs1-$f8,y ;no wrap on indexed abs +1837 : 9138 sta (inwt),y +1839 : 88 dey +183a : c0f8 cpy #$f8 +183c : b0f6 bcs tlday5 +183e : a003 ldy #3 ;testing wraparound result +1840 : a200 ldx #0 +1842 : b90302 tstay5 lda abst,y +1845 : d91702 cmp abs1,y + trap_ne ;store to abs data +1848 : d0fe > bne * ;failed not equal (non zero) + +184a : 8a txa +184b : 990302 sta abst,y ;clear +184e : 88 dey +184f : 10f1 bpl tstay5 + +1851 : a0fb ldy #3+$f8 +1853 : a2fe ldx #6+$f8 +1855 : b12e tlday6 lda (inw1),y ;no wrap on zp indirect indexe +1857 : 8138 sta (indt-$f8&$ff,x) +1859 : ca dex +185a : ca dex +185b : 88 dey +185c : c0f8 cpy #$f8 +185e : b0f5 bcs tlday6 +1860 : a003 ldy #3 ;testing wraparound result +1862 : a200 ldx #0 +1864 : b90302 tstay6 lda abst,y +1867 : d91702 cmp abs1,y + trap_ne ;store to abs data +186a : d0fe > bne * ;failed not equal (non zero) + +186c : 8a txa +186d : 990302 sta abst,y ;clear +1870 : 88 dey +1871 : 10f1 bpl tstay6 + next_test +1873 : ad0002 > lda test_case ;previous test +1876 : c917 > cmp #test_num + > trap_ne ;test is out of sequence +1878 : d0fe > bne * ;failed not equal (non zero) + > +0018 = >test_num = test_num + 1 +187a : a918 > lda #test_num ;*** next tests' number +187c : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; LDA / STA - zp / abs / # + set_stat 0 + > load_flag 0 +187f : a900 > lda #0 ;allow test to change + > +1881 : 48 > pha ;use stack to load status +1882 : 28 > plp + +1883 : a513 lda zp1 +1885 : 08 php ;test stores do not alter flags +1886 : 49c3 eor #$c3 +1888 : 28 plp +1889 : 8d0302 sta abst +188c : 08 php ;flags after load/store sequence +188d : 49c3 eor #$c3 +188f : c9c3 cmp #$c3 ;test result + trap_ne +1891 : d0fe > bne * ;failed not equal (non zero) + +1893 : 68 pla ;load status + eor_flag 0 +1894 : 4930 > eor #0|fao ;invert expected flags + +1896 : cd1c02 cmp fLDx ;test flags + trap_ne +1899 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +189b : a900 > lda #0 ;allow test to change I + > +189d : 48 > pha ;use stack to load status +189e : 28 > plp + +189f : a514 lda zp1+1 +18a1 : 08 php ;test stores do not alter flags +18a2 : 49c3 eor #$c3 +18a4 : 28 plp +18a5 : 8d0402 sta abst+1 +18a8 : 08 php ;flags after load/store sequence +18a9 : 49c3 eor #$c3 +18ab : c982 cmp #$82 ;test result + trap_ne +18ad : d0fe > bne * ;failed not equal (non zero) + +18af : 68 pla ;load status + eor_flag 0 +18b0 : 4930 > eor #0|fao ;invert expected flags + +18b2 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +18b5 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +18b7 : a900 > lda #0 ;allow test to change I + > +18b9 : 48 > pha ;use stack to load status +18ba : 28 > plp + +18bb : a515 lda zp1+2 +18bd : 08 php ;test stores do not alter flags +18be : 49c3 eor #$c3 +18c0 : 28 plp +18c1 : 8d0502 sta abst+2 +18c4 : 08 php ;flags after load/store sequence +18c5 : 49c3 eor #$c3 +18c7 : c941 cmp #$41 ;test result + trap_ne +18c9 : d0fe > bne * ;failed not equal (non zero) + +18cb : 68 pla ;load status + eor_flag 0 +18cc : 4930 > eor #0|fao ;invert expected flags + +18ce : cd1e02 cmp fLDx+2 ;test flags + trap_ne +18d1 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +18d3 : a900 > lda #0 ;allow test to change I + > +18d5 : 48 > pha ;use stack to load status +18d6 : 28 > plp + +18d7 : a516 lda zp1+3 +18d9 : 08 php ;test stores do not alter flags +18da : 49c3 eor #$c3 +18dc : 28 plp +18dd : 8d0602 sta abst+3 +18e0 : 08 php ;flags after load/store sequence +18e1 : 49c3 eor #$c3 +18e3 : c900 cmp #0 ;test result + trap_ne +18e5 : d0fe > bne * ;failed not equal (non zero) + +18e7 : 68 pla ;load status + eor_flag 0 +18e8 : 4930 > eor #0|fao ;invert expected flags + +18ea : cd1f02 cmp fLDx+3 ;test flags + trap_ne +18ed : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +18ef : a9ff > lda #$ff ;allow test to change + > +18f1 : 48 > pha ;use stack to load status +18f2 : 28 > plp + +18f3 : a513 lda zp1 +18f5 : 08 php ;test stores do not alter flags +18f6 : 49c3 eor #$c3 +18f8 : 28 plp +18f9 : 8d0302 sta abst +18fc : 08 php ;flags after load/store sequence +18fd : 49c3 eor #$c3 +18ff : c9c3 cmp #$c3 ;test result + trap_ne +1901 : d0fe > bne * ;failed not equal (non zero) + +1903 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1904 : 497d > eor #lo~fnz |fao ;invert expected + +1906 : cd1c02 cmp fLDx ;test flags + trap_ne +1909 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +190b : a9ff > lda #$ff ;allow test to change + > +190d : 48 > pha ;use stack to load status +190e : 28 > plp + +190f : a514 lda zp1+1 +1911 : 08 php ;test stores do not alter flags +1912 : 49c3 eor #$c3 +1914 : 28 plp +1915 : 8d0402 sta abst+1 +1918 : 08 php ;flags after load/store sequence +1919 : 49c3 eor #$c3 +191b : c982 cmp #$82 ;test result + trap_ne +191d : d0fe > bne * ;failed not equal (non zero) + +191f : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1920 : 497d > eor #lo~fnz |fao ;invert expected + +1922 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1925 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1927 : a9ff > lda #$ff ;allow test to change + > +1929 : 48 > pha ;use stack to load status +192a : 28 > plp + +192b : a515 lda zp1+2 +192d : 08 php ;test stores do not alter flags +192e : 49c3 eor #$c3 +1930 : 28 plp +1931 : 8d0502 sta abst+2 +1934 : 08 php ;flags after load/store sequence +1935 : 49c3 eor #$c3 +1937 : c941 cmp #$41 ;test result + trap_ne +1939 : d0fe > bne * ;failed not equal (non zero) + +193b : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +193c : 497d > eor #lo~fnz |fao ;invert expected + +193e : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1941 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1943 : a9ff > lda #$ff ;allow test to change + > +1945 : 48 > pha ;use stack to load status +1946 : 28 > plp + +1947 : a516 lda zp1+3 +1949 : 08 php ;test stores do not alter flags +194a : 49c3 eor #$c3 +194c : 28 plp +194d : 8d0602 sta abst+3 +1950 : 08 php ;flags after load/store sequence +1951 : 49c3 eor #$c3 +1953 : c900 cmp #0 ;test result + trap_ne +1955 : d0fe > bne * ;failed not equal (non zero) + +1957 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1958 : 497d > eor #lo~fnz |fao ;invert expected + +195a : cd1f02 cmp fLDx+3 ;test flags + trap_ne +195d : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +195f : a900 > lda #0 ;allow test to change I + > +1961 : 48 > pha ;use stack to load status +1962 : 28 > plp + +1963 : ad1702 lda abs1 +1966 : 08 php ;test stores do not alter flags +1967 : 49c3 eor #$c3 +1969 : 28 plp +196a : 850c sta zpt +196c : 08 php ;flags after load/store sequence +196d : 49c3 eor #$c3 +196f : c513 cmp zp1 ;test result + trap_ne +1971 : d0fe > bne * ;failed not equal (non zero) + +1973 : 68 pla ;load status + eor_flag 0 +1974 : 4930 > eor #0|fao ;invert expected flags + +1976 : cd1c02 cmp fLDx ;test flags + trap_ne +1979 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +197b : a900 > lda #0 ;allow test to change I + > +197d : 48 > pha ;use stack to load status +197e : 28 > plp + +197f : ad1802 lda abs1+1 +1982 : 08 php ;test stores do not alter flags +1983 : 49c3 eor #$c3 +1985 : 28 plp +1986 : 850d sta zpt+1 +1988 : 08 php ;flags after load/store sequence +1989 : 49c3 eor #$c3 +198b : c514 cmp zp1+1 ;test result + trap_ne +198d : d0fe > bne * ;failed not equal (non zero) + +198f : 68 pla ;load status + eor_flag 0 +1990 : 4930 > eor #0|fao ;invert expected flags + +1992 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1995 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1997 : a900 > lda #0 ;allow test to change I + > +1999 : 48 > pha ;use stack to load status +199a : 28 > plp + +199b : ad1902 lda abs1+2 +199e : 08 php ;test stores do not alter flags +199f : 49c3 eor #$c3 +19a1 : 28 plp +19a2 : 850e sta zpt+2 +19a4 : 08 php ;flags after load/store sequence +19a5 : 49c3 eor #$c3 +19a7 : c515 cmp zp1+2 ;test result + trap_ne +19a9 : d0fe > bne * ;failed not equal (non zero) + +19ab : 68 pla ;load status + eor_flag 0 +19ac : 4930 > eor #0|fao ;invert expected flags + +19ae : cd1e02 cmp fLDx+2 ;test flags + trap_ne +19b1 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +19b3 : a900 > lda #0 ;allow test to change I + > +19b5 : 48 > pha ;use stack to load status +19b6 : 28 > plp + +19b7 : ad1a02 lda abs1+3 +19ba : 08 php ;test stores do not alter flags +19bb : 49c3 eor #$c3 +19bd : 28 plp +19be : 850f sta zpt+3 +19c0 : 08 php ;flags after load/store sequence +19c1 : 49c3 eor #$c3 +19c3 : c516 cmp zp1+3 ;test result + trap_ne +19c5 : d0fe > bne * ;failed not equal (non zero) + +19c7 : 68 pla ;load status + eor_flag 0 +19c8 : 4930 > eor #0|fao ;invert expected flags + +19ca : cd1f02 cmp fLDx+3 ;test flags + trap_ne +19cd : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +19cf : a9ff > lda #$ff ;allow test to change + > +19d1 : 48 > pha ;use stack to load status +19d2 : 28 > plp + +19d3 : ad1702 lda abs1 +19d6 : 08 php ;test stores do not alter flags +19d7 : 49c3 eor #$c3 +19d9 : 28 plp +19da : 850c sta zpt +19dc : 08 php ;flags after load/store sequence +19dd : 49c3 eor #$c3 +19df : c513 cmp zp1 ;test result + trap_ne +19e1 : d0fe > bne * ;failed not equal (non zero) + +19e3 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +19e4 : 497d > eor #lo~fnz |fao ;invert expected + +19e6 : cd1c02 cmp fLDx ;test flags + trap_ne +19e9 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +19eb : a9ff > lda #$ff ;allow test to change + > +19ed : 48 > pha ;use stack to load status +19ee : 28 > plp + +19ef : ad1802 lda abs1+1 +19f2 : 08 php ;test stores do not alter flags +19f3 : 49c3 eor #$c3 +19f5 : 28 plp +19f6 : 850d sta zpt+1 +19f8 : 08 php ;flags after load/store sequence +19f9 : 49c3 eor #$c3 +19fb : c514 cmp zp1+1 ;test result + trap_ne +19fd : d0fe > bne * ;failed not equal (non zero) + +19ff : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1a00 : 497d > eor #lo~fnz |fao ;invert expected + +1a02 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1a05 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1a07 : a9ff > lda #$ff ;allow test to change + > +1a09 : 48 > pha ;use stack to load status +1a0a : 28 > plp + +1a0b : ad1902 lda abs1+2 +1a0e : 08 php ;test stores do not alter flags +1a0f : 49c3 eor #$c3 +1a11 : 28 plp +1a12 : 850e sta zpt+2 +1a14 : 08 php ;flags after load/store sequence +1a15 : 49c3 eor #$c3 +1a17 : c515 cmp zp1+2 ;test result + trap_ne +1a19 : d0fe > bne * ;failed not equal (non zero) + +1a1b : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1a1c : 497d > eor #lo~fnz |fao ;invert expected + +1a1e : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1a21 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1a23 : a9ff > lda #$ff ;allow test to change + > +1a25 : 48 > pha ;use stack to load status +1a26 : 28 > plp + +1a27 : ad1a02 lda abs1+3 +1a2a : 08 php ;test stores do not alter flags +1a2b : 49c3 eor #$c3 +1a2d : 28 plp +1a2e : 850f sta zpt+3 +1a30 : 08 php ;flags after load/store sequence +1a31 : 49c3 eor #$c3 +1a33 : c516 cmp zp1+3 ;test result + trap_ne +1a35 : d0fe > bne * ;failed not equal (non zero) + +1a37 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1a38 : 497d > eor #lo~fnz |fao ;invert expected + +1a3a : cd1f02 cmp fLDx+3 ;test flags + trap_ne +1a3d : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1a3f : a900 > lda #0 ;allow test to change + > +1a41 : 48 > pha ;use stack to load status +1a42 : 28 > plp + +1a43 : a9c3 lda #$c3 +1a45 : 08 php +1a46 : cd1702 cmp abs1 ;test result + trap_ne +1a49 : d0fe > bne * ;failed not equal (non zero) + +1a4b : 68 pla ;load status + eor_flag 0 +1a4c : 4930 > eor #0|fao ;invert expected flags + +1a4e : cd1c02 cmp fLDx ;test flags + trap_ne +1a51 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1a53 : a900 > lda #0 ;allow test to change I + > +1a55 : 48 > pha ;use stack to load status +1a56 : 28 > plp + +1a57 : a982 lda #$82 +1a59 : 08 php +1a5a : cd1802 cmp abs1+1 ;test result + trap_ne +1a5d : d0fe > bne * ;failed not equal (non zero) + +1a5f : 68 pla ;load status + eor_flag 0 +1a60 : 4930 > eor #0|fao ;invert expected flags + +1a62 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1a65 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1a67 : a900 > lda #0 ;allow test to change I + > +1a69 : 48 > pha ;use stack to load status +1a6a : 28 > plp + +1a6b : a941 lda #$41 +1a6d : 08 php +1a6e : cd1902 cmp abs1+2 ;test result + trap_ne +1a71 : d0fe > bne * ;failed not equal (non zero) + +1a73 : 68 pla ;load status + eor_flag 0 +1a74 : 4930 > eor #0|fao ;invert expected flags + +1a76 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1a79 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1a7b : a900 > lda #0 ;allow test to change I + > +1a7d : 48 > pha ;use stack to load status +1a7e : 28 > plp + +1a7f : a900 lda #0 +1a81 : 08 php +1a82 : cd1a02 cmp abs1+3 ;test result + trap_ne +1a85 : d0fe > bne * ;failed not equal (non zero) + +1a87 : 68 pla ;load status + eor_flag 0 +1a88 : 4930 > eor #0|fao ;invert expected flags + +1a8a : cd1f02 cmp fLDx+3 ;test flags + trap_ne +1a8d : d0fe > bne * ;failed not equal (non zero) + + + set_stat $ff + > load_flag $ff +1a8f : a9ff > lda #$ff ;allow test to change + > +1a91 : 48 > pha ;use stack to load status +1a92 : 28 > plp + +1a93 : a9c3 lda #$c3 +1a95 : 08 php +1a96 : cd1702 cmp abs1 ;test result + trap_ne +1a99 : d0fe > bne * ;failed not equal (non zero) + +1a9b : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1a9c : 497d > eor #lo~fnz |fao ;invert expected + +1a9e : cd1c02 cmp fLDx ;test flags + trap_ne +1aa1 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1aa3 : a9ff > lda #$ff ;allow test to change + > +1aa5 : 48 > pha ;use stack to load status +1aa6 : 28 > plp + +1aa7 : a982 lda #$82 +1aa9 : 08 php +1aaa : cd1802 cmp abs1+1 ;test result + trap_ne +1aad : d0fe > bne * ;failed not equal (non zero) + +1aaf : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1ab0 : 497d > eor #lo~fnz |fao ;invert expected + +1ab2 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1ab5 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1ab7 : a9ff > lda #$ff ;allow test to change + > +1ab9 : 48 > pha ;use stack to load status +1aba : 28 > plp + +1abb : a941 lda #$41 +1abd : 08 php +1abe : cd1902 cmp abs1+2 ;test result + trap_ne +1ac1 : d0fe > bne * ;failed not equal (non zero) + +1ac3 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1ac4 : 497d > eor #lo~fnz |fao ;invert expected + +1ac6 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1ac9 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1acb : a9ff > lda #$ff ;allow test to change + > +1acd : 48 > pha ;use stack to load status +1ace : 28 > plp + +1acf : a900 lda #0 +1ad1 : 08 php +1ad2 : cd1a02 cmp abs1+3 ;test result + trap_ne +1ad5 : d0fe > bne * ;failed not equal (non zero) + +1ad7 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1ad8 : 497d > eor #lo~fnz |fao ;invert expected + +1ada : cd1f02 cmp fLDx+3 ;test flags + trap_ne +1add : d0fe > bne * ;failed not equal (non zero) + + +1adf : a200 ldx #0 +1ae1 : a50c lda zpt +1ae3 : 49c3 eor #$c3 +1ae5 : c513 cmp zp1 + trap_ne ;store to zp data +1ae7 : d0fe > bne * ;failed not equal (non zero) + +1ae9 : 860c stx zpt ;clear +1aeb : ad0302 lda abst +1aee : 49c3 eor #$c3 +1af0 : cd1702 cmp abs1 + trap_ne ;store to abs data +1af3 : d0fe > bne * ;failed not equal (non zero) + +1af5 : 8e0302 stx abst ;clear +1af8 : a50d lda zpt+1 +1afa : 49c3 eor #$c3 +1afc : c514 cmp zp1+1 + trap_ne ;store to zp data +1afe : d0fe > bne * ;failed not equal (non zero) + +1b00 : 860d stx zpt+1 ;clear +1b02 : ad0402 lda abst+1 +1b05 : 49c3 eor #$c3 +1b07 : cd1802 cmp abs1+1 + trap_ne ;store to abs data +1b0a : d0fe > bne * ;failed not equal (non zero) + +1b0c : 8e0402 stx abst+1 ;clear +1b0f : a50e lda zpt+2 +1b11 : 49c3 eor #$c3 +1b13 : c515 cmp zp1+2 + trap_ne ;store to zp data +1b15 : d0fe > bne * ;failed not equal (non zero) + +1b17 : 860e stx zpt+2 ;clear +1b19 : ad0502 lda abst+2 +1b1c : 49c3 eor #$c3 +1b1e : cd1902 cmp abs1+2 + trap_ne ;store to abs data +1b21 : d0fe > bne * ;failed not equal (non zero) + +1b23 : 8e0502 stx abst+2 ;clear +1b26 : a50f lda zpt+3 +1b28 : 49c3 eor #$c3 +1b2a : c516 cmp zp1+3 + trap_ne ;store to zp data +1b2c : d0fe > bne * ;failed not equal (non zero) + +1b2e : 860f stx zpt+3 ;clear +1b30 : ad0602 lda abst+3 +1b33 : 49c3 eor #$c3 +1b35 : cd1a02 cmp abs1+3 + trap_ne ;store to abs data +1b38 : d0fe > bne * ;failed not equal (non zero) + +1b3a : 8e0602 stx abst+3 ;clear + next_test +1b3d : ad0002 > lda test_case ;previous test +1b40 : c918 > cmp #test_num + > trap_ne ;test is out of sequence +1b42 : d0fe > bne * ;failed not equal (non zero) + > +0019 = >test_num = test_num + 1 +1b44 : a919 > lda #test_num ;*** next tests' number +1b46 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; testing bit test & compares BIT CPX CPY CMP all addr + ; BIT - zp / abs + set_a $ff,0 + > load_flag 0 +1b49 : a900 > lda #0 ;allow test to change I + > +1b4b : 48 > pha ;use stack to load status +1b4c : a9ff > lda #$ff ;precharge accu +1b4e : 28 > plp + +1b4f : 2416 bit zp1+3 ;00 - should set Z / clear NV + tst_a $ff,fz +1b51 : 08 > php ;save flags +1b52 : c9ff > cmp #$ff ;test result + > trap_ne +1b54 : d0fe > bne * ;failed not equal (non zero) + > +1b56 : 68 > pla ;load status +1b57 : 48 > pha + > cmp_flag fz +1b58 : c932 > cmp #(fz |fao)&m8 ;expected flags + alw + > + > trap_ne +1b5a : d0fe > bne * ;failed not equal (non zero) + > +1b5c : 28 > plp ;restore status + + set_a 1,0 + > load_flag 0 +1b5d : a900 > lda #0 ;allow test to change I + > +1b5f : 48 > pha ;use stack to load status +1b60 : a901 > lda #1 ;precharge accu +1b62 : 28 > plp + +1b63 : 2415 bit zp1+2 ;41 - should set V (M6) / clear NZ + tst_a 1,fv +1b65 : 08 > php ;save flags +1b66 : c901 > cmp #1 ;test result + > trap_ne +1b68 : d0fe > bne * ;failed not equal (non zero) + > +1b6a : 68 > pla ;load status +1b6b : 48 > pha + > cmp_flag fv +1b6c : c970 > cmp #(fv|fao)&m8 ;expected flags + alwa + > + > trap_ne +1b6e : d0fe > bne * ;failed not equal (non zero) + > +1b70 : 28 > plp ;restore status + + set_a 1,0 + > load_flag 0 +1b71 : a900 > lda #0 ;allow test to change I + > +1b73 : 48 > pha ;use stack to load status +1b74 : a901 > lda #1 ;precharge accu +1b76 : 28 > plp + +1b77 : 2414 bit zp1+1 ;82 - should set N (M7) & Z / clea + tst_a 1,fnz +1b79 : 08 > php ;save flags +1b7a : c901 > cmp #1 ;test result + > trap_ne +1b7c : d0fe > bne * ;failed not equal (non zero) + > +1b7e : 68 > pla ;load status +1b7f : 48 > pha + > cmp_flag fnz +1b80 : c9b2 > cmp #(fnz|fao)&m8 ;expected flags + alw + > + > trap_ne +1b82 : d0fe > bne * ;failed not equal (non zero) + > +1b84 : 28 > plp ;restore status + + set_a 1,0 + > load_flag 0 +1b85 : a900 > lda #0 ;allow test to change I + > +1b87 : 48 > pha ;use stack to load status +1b88 : a901 > lda #1 ;precharge accu +1b8a : 28 > plp + +1b8b : 2413 bit zp1 ;c3 - should set N (M7) & V (M6) / + tst_a 1,fnv +1b8d : 08 > php ;save flags +1b8e : c901 > cmp #1 ;test result + > trap_ne +1b90 : d0fe > bne * ;failed not equal (non zero) + > +1b92 : 68 > pla ;load status +1b93 : 48 > pha + > cmp_flag fnv +1b94 : c9f0 > cmp #(fnv|fao)&m8 ;expected flags + alw + > + > trap_ne +1b96 : d0fe > bne * ;failed not equal (non zero) + > +1b98 : 28 > plp ;restore status + + + set_a $ff,$ff + > load_flag $ff +1b99 : a9ff > lda #$ff ;allow test to change + > +1b9b : 48 > pha ;use stack to load status +1b9c : a9ff > lda #$ff ;precharge accu +1b9e : 28 > plp + +1b9f : 2416 bit zp1+3 ;00 - should set Z / clear NV + tst_a $ff,~fnv +1ba1 : 08 > php ;save flags +1ba2 : c9ff > cmp #$ff ;test result + > trap_ne +1ba4 : d0fe > bne * ;failed not equal (non zero) + > +1ba6 : 68 > pla ;load status +1ba7 : 48 > pha + > cmp_flag ~fnv +1ba8 : c93f > cmp #(~fnv |fao)&m8 ;expected flags + a + > + > trap_ne +1baa : d0fe > bne * ;failed not equal (non zero) + > +1bac : 28 > plp ;restore status + + set_a 1,$ff + > load_flag $ff +1bad : a9ff > lda #$ff ;allow test to change + > +1baf : 48 > pha ;use stack to load status +1bb0 : a901 > lda #1 ;precharge accu +1bb2 : 28 > plp + +1bb3 : 2415 bit zp1+2 ;41 - should set V (M6) / clear NZ + tst_a 1,~fnz +1bb5 : 08 > php ;save flags +1bb6 : c901 > cmp #1 ;test result + > trap_ne +1bb8 : d0fe > bne * ;failed not equal (non zero) + > +1bba : 68 > pla ;load status +1bbb : 48 > pha + > cmp_flag ~fnz +1bbc : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1bbe : d0fe > bne * ;failed not equal (non zero) + > +1bc0 : 28 > plp ;restore status + + set_a 1,$ff + > load_flag $ff +1bc1 : a9ff > lda #$ff ;allow test to change + > +1bc3 : 48 > pha ;use stack to load status +1bc4 : a901 > lda #1 ;precharge accu +1bc6 : 28 > plp + +1bc7 : 2414 bit zp1+1 ;82 - should set N (M7) & Z / clea + tst_a 1,~fv +1bc9 : 08 > php ;save flags +1bca : c901 > cmp #1 ;test result + > trap_ne +1bcc : d0fe > bne * ;failed not equal (non zero) + > +1bce : 68 > pla ;load status +1bcf : 48 > pha + > cmp_flag ~fv +1bd0 : c9bf > cmp #(~fv|fao)&m8 ;expected flags + alw + > + > trap_ne +1bd2 : d0fe > bne * ;failed not equal (non zero) + > +1bd4 : 28 > plp ;restore status + + set_a 1,$ff + > load_flag $ff +1bd5 : a9ff > lda #$ff ;allow test to change + > +1bd7 : 48 > pha ;use stack to load status +1bd8 : a901 > lda #1 ;precharge accu +1bda : 28 > plp + +1bdb : 2413 bit zp1 ;c3 - should set N (M7) & V (M6) / + tst_a 1,~fz +1bdd : 08 > php ;save flags +1bde : c901 > cmp #1 ;test result + > trap_ne +1be0 : d0fe > bne * ;failed not equal (non zero) + > +1be2 : 68 > pla ;load status +1be3 : 48 > pha + > cmp_flag ~fz +1be4 : c9fd > cmp #(~fz|fao)&m8 ;expected flags + alw + > + > trap_ne +1be6 : d0fe > bne * ;failed not equal (non zero) + > +1be8 : 28 > plp ;restore status + + + set_a $ff,0 + > load_flag 0 +1be9 : a900 > lda #0 ;allow test to change I + > +1beb : 48 > pha ;use stack to load status +1bec : a9ff > lda #$ff ;precharge accu +1bee : 28 > plp + +1bef : 2c1a02 bit abs1+3 ;00 - should set Z / clear NV + tst_a $ff,fz +1bf2 : 08 > php ;save flags +1bf3 : c9ff > cmp #$ff ;test result + > trap_ne +1bf5 : d0fe > bne * ;failed not equal (non zero) + > +1bf7 : 68 > pla ;load status +1bf8 : 48 > pha + > cmp_flag fz +1bf9 : c932 > cmp #(fz |fao)&m8 ;expected flags + alw + > + > trap_ne +1bfb : d0fe > bne * ;failed not equal (non zero) + > +1bfd : 28 > plp ;restore status + + set_a 1,0 + > load_flag 0 +1bfe : a900 > lda #0 ;allow test to change I + > +1c00 : 48 > pha ;use stack to load status +1c01 : a901 > lda #1 ;precharge accu +1c03 : 28 > plp + +1c04 : 2c1902 bit abs1+2 ;41 - should set V (M6) / clear NZ + tst_a 1,fv +1c07 : 08 > php ;save flags +1c08 : c901 > cmp #1 ;test result + > trap_ne +1c0a : d0fe > bne * ;failed not equal (non zero) + > +1c0c : 68 > pla ;load status +1c0d : 48 > pha + > cmp_flag fv +1c0e : c970 > cmp #(fv|fao)&m8 ;expected flags + alwa + > + > trap_ne +1c10 : d0fe > bne * ;failed not equal (non zero) + > +1c12 : 28 > plp ;restore status + + set_a 1,0 + > load_flag 0 +1c13 : a900 > lda #0 ;allow test to change I + > +1c15 : 48 > pha ;use stack to load status +1c16 : a901 > lda #1 ;precharge accu +1c18 : 28 > plp + +1c19 : 2c1802 bit abs1+1 ;82 - should set N (M7) & Z / clea + tst_a 1,fnz +1c1c : 08 > php ;save flags +1c1d : c901 > cmp #1 ;test result + > trap_ne +1c1f : d0fe > bne * ;failed not equal (non zero) + > +1c21 : 68 > pla ;load status +1c22 : 48 > pha + > cmp_flag fnz +1c23 : c9b2 > cmp #(fnz|fao)&m8 ;expected flags + alw + > + > trap_ne +1c25 : d0fe > bne * ;failed not equal (non zero) + > +1c27 : 28 > plp ;restore status + + set_a 1,0 + > load_flag 0 +1c28 : a900 > lda #0 ;allow test to change I + > +1c2a : 48 > pha ;use stack to load status +1c2b : a901 > lda #1 ;precharge accu +1c2d : 28 > plp + +1c2e : 2c1702 bit abs1 ;c3 - should set N (M7) & V (M6) / + tst_a 1,fnv +1c31 : 08 > php ;save flags +1c32 : c901 > cmp #1 ;test result + > trap_ne +1c34 : d0fe > bne * ;failed not equal (non zero) + > +1c36 : 68 > pla ;load status +1c37 : 48 > pha + > cmp_flag fnv +1c38 : c9f0 > cmp #(fnv|fao)&m8 ;expected flags + alw + > + > trap_ne +1c3a : d0fe > bne * ;failed not equal (non zero) + > +1c3c : 28 > plp ;restore status + + + set_a $ff,$ff + > load_flag $ff +1c3d : a9ff > lda #$ff ;allow test to change + > +1c3f : 48 > pha ;use stack to load status +1c40 : a9ff > lda #$ff ;precharge accu +1c42 : 28 > plp + +1c43 : 2c1a02 bit abs1+3 ;00 - should set Z / clear NV + tst_a $ff,~fnv +1c46 : 08 > php ;save flags +1c47 : c9ff > cmp #$ff ;test result + > trap_ne +1c49 : d0fe > bne * ;failed not equal (non zero) + > +1c4b : 68 > pla ;load status +1c4c : 48 > pha + > cmp_flag ~fnv +1c4d : c93f > cmp #(~fnv |fao)&m8 ;expected flags + a + > + > trap_ne +1c4f : d0fe > bne * ;failed not equal (non zero) + > +1c51 : 28 > plp ;restore status + + set_a 1,$ff + > load_flag $ff +1c52 : a9ff > lda #$ff ;allow test to change + > +1c54 : 48 > pha ;use stack to load status +1c55 : a901 > lda #1 ;precharge accu +1c57 : 28 > plp + +1c58 : 2c1902 bit abs1+2 ;41 - should set V (M6) / clear NZ + tst_a 1,~fnz +1c5b : 08 > php ;save flags +1c5c : c901 > cmp #1 ;test result + > trap_ne +1c5e : d0fe > bne * ;failed not equal (non zero) + > +1c60 : 68 > pla ;load status +1c61 : 48 > pha + > cmp_flag ~fnz +1c62 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1c64 : d0fe > bne * ;failed not equal (non zero) + > +1c66 : 28 > plp ;restore status + + set_a 1,$ff + > load_flag $ff +1c67 : a9ff > lda #$ff ;allow test to change + > +1c69 : 48 > pha ;use stack to load status +1c6a : a901 > lda #1 ;precharge accu +1c6c : 28 > plp + +1c6d : 2c1802 bit abs1+1 ;82 - should set N (M7) & Z / clea + tst_a 1,~fv +1c70 : 08 > php ;save flags +1c71 : c901 > cmp #1 ;test result + > trap_ne +1c73 : d0fe > bne * ;failed not equal (non zero) + > +1c75 : 68 > pla ;load status +1c76 : 48 > pha + > cmp_flag ~fv +1c77 : c9bf > cmp #(~fv|fao)&m8 ;expected flags + alw + > + > trap_ne +1c79 : d0fe > bne * ;failed not equal (non zero) + > +1c7b : 28 > plp ;restore status + + set_a 1,$ff + > load_flag $ff +1c7c : a9ff > lda #$ff ;allow test to change + > +1c7e : 48 > pha ;use stack to load status +1c7f : a901 > lda #1 ;precharge accu +1c81 : 28 > plp + +1c82 : 2c1702 bit abs1 ;c3 - should set N (M7) & V (M6) / + tst_a 1,~fz +1c85 : 08 > php ;save flags +1c86 : c901 > cmp #1 ;test result + > trap_ne +1c88 : d0fe > bne * ;failed not equal (non zero) + > +1c8a : 68 > pla ;load status +1c8b : 48 > pha + > cmp_flag ~fz +1c8c : c9fd > cmp #(~fz|fao)&m8 ;expected flags + alw + > + > trap_ne +1c8e : d0fe > bne * ;failed not equal (non zero) + > +1c90 : 28 > plp ;restore status + + next_test +1c91 : ad0002 > lda test_case ;previous test +1c94 : c919 > cmp #test_num + > trap_ne ;test is out of sequence +1c96 : d0fe > bne * ;failed not equal (non zero) + > +001a = >test_num = test_num + 1 +1c98 : a91a > lda #test_num ;*** next tests' number +1c9a : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; CPX - zp / abs / # + set_x $80,0 + > load_flag 0 +1c9d : a900 > lda #0 ;allow test to change I + > +1c9f : 48 > pha ;use stack to load status +1ca0 : a280 > ldx #$80 ;precharge index x +1ca2 : 28 > plp + +1ca3 : e417 cpx zp7f + tst_stat fc +1ca5 : 08 > php ;save status +1ca6 : 68 > pla ;use stack to retrieve status +1ca7 : 48 > pha + > cmp_flag fc +1ca8 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1caa : d0fe > bne * ;failed not equal (non zero) + > +1cac : 28 > plp ;restore status + +1cad : ca dex +1cae : e417 cpx zp7f + tst_stat fzc +1cb0 : 08 > php ;save status +1cb1 : 68 > pla ;use stack to retrieve status +1cb2 : 48 > pha + > cmp_flag fzc +1cb3 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1cb5 : d0fe > bne * ;failed not equal (non zero) + > +1cb7 : 28 > plp ;restore status + +1cb8 : ca dex +1cb9 : e417 cpx zp7f + tst_x $7e,fn +1cbb : 08 > php ;save flags +1cbc : e07e > cpx #$7e ;test result + > trap_ne +1cbe : d0fe > bne * ;failed not equal (non zero) + > +1cc0 : 68 > pla ;load status +1cc1 : 48 > pha + > cmp_flag fn +1cc2 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1cc4 : d0fe > bne * ;failed not equal (non zero) + > +1cc6 : 28 > plp ;restore status + + set_x $80,$ff + > load_flag $ff +1cc7 : a9ff > lda #$ff ;allow test to change + > +1cc9 : 48 > pha ;use stack to load status +1cca : a280 > ldx #$80 ;precharge index x +1ccc : 28 > plp + +1ccd : e417 cpx zp7f + tst_stat ~fnz +1ccf : 08 > php ;save status +1cd0 : 68 > pla ;use stack to retrieve status +1cd1 : 48 > pha + > cmp_flag ~fnz +1cd2 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1cd4 : d0fe > bne * ;failed not equal (non zero) + > +1cd6 : 28 > plp ;restore status + +1cd7 : ca dex +1cd8 : e417 cpx zp7f + tst_stat ~fn +1cda : 08 > php ;save status +1cdb : 68 > pla ;use stack to retrieve status +1cdc : 48 > pha + > cmp_flag ~fn +1cdd : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +1cdf : d0fe > bne * ;failed not equal (non zero) + > +1ce1 : 28 > plp ;restore status + +1ce2 : ca dex +1ce3 : e417 cpx zp7f + tst_x $7e,~fzc +1ce5 : 08 > php ;save flags +1ce6 : e07e > cpx #$7e ;test result + > trap_ne +1ce8 : d0fe > bne * ;failed not equal (non zero) + > +1cea : 68 > pla ;load status +1ceb : 48 > pha + > cmp_flag ~fzc +1cec : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +1cee : d0fe > bne * ;failed not equal (non zero) + > +1cf0 : 28 > plp ;restore status + + + set_x $80,0 + > load_flag 0 +1cf1 : a900 > lda #0 ;allow test to change I + > +1cf3 : 48 > pha ;use stack to load status +1cf4 : a280 > ldx #$80 ;precharge index x +1cf6 : 28 > plp + +1cf7 : ec1b02 cpx abs7f + tst_stat fc +1cfa : 08 > php ;save status +1cfb : 68 > pla ;use stack to retrieve status +1cfc : 48 > pha + > cmp_flag fc +1cfd : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1cff : d0fe > bne * ;failed not equal (non zero) + > +1d01 : 28 > plp ;restore status + +1d02 : ca dex +1d03 : ec1b02 cpx abs7f + tst_stat fzc +1d06 : 08 > php ;save status +1d07 : 68 > pla ;use stack to retrieve status +1d08 : 48 > pha + > cmp_flag fzc +1d09 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1d0b : d0fe > bne * ;failed not equal (non zero) + > +1d0d : 28 > plp ;restore status + +1d0e : ca dex +1d0f : ec1b02 cpx abs7f + tst_x $7e,fn +1d12 : 08 > php ;save flags +1d13 : e07e > cpx #$7e ;test result + > trap_ne +1d15 : d0fe > bne * ;failed not equal (non zero) + > +1d17 : 68 > pla ;load status +1d18 : 48 > pha + > cmp_flag fn +1d19 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1d1b : d0fe > bne * ;failed not equal (non zero) + > +1d1d : 28 > plp ;restore status + + set_x $80,$ff + > load_flag $ff +1d1e : a9ff > lda #$ff ;allow test to change + > +1d20 : 48 > pha ;use stack to load status +1d21 : a280 > ldx #$80 ;precharge index x +1d23 : 28 > plp + +1d24 : ec1b02 cpx abs7f + tst_stat ~fnz +1d27 : 08 > php ;save status +1d28 : 68 > pla ;use stack to retrieve status +1d29 : 48 > pha + > cmp_flag ~fnz +1d2a : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1d2c : d0fe > bne * ;failed not equal (non zero) + > +1d2e : 28 > plp ;restore status + +1d2f : ca dex +1d30 : ec1b02 cpx abs7f + tst_stat ~fn +1d33 : 08 > php ;save status +1d34 : 68 > pla ;use stack to retrieve status +1d35 : 48 > pha + > cmp_flag ~fn +1d36 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +1d38 : d0fe > bne * ;failed not equal (non zero) + > +1d3a : 28 > plp ;restore status + +1d3b : ca dex +1d3c : ec1b02 cpx abs7f + tst_x $7e,~fzc +1d3f : 08 > php ;save flags +1d40 : e07e > cpx #$7e ;test result + > trap_ne +1d42 : d0fe > bne * ;failed not equal (non zero) + > +1d44 : 68 > pla ;load status +1d45 : 48 > pha + > cmp_flag ~fzc +1d46 : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +1d48 : d0fe > bne * ;failed not equal (non zero) + > +1d4a : 28 > plp ;restore status + + + set_x $80,0 + > load_flag 0 +1d4b : a900 > lda #0 ;allow test to change I + > +1d4d : 48 > pha ;use stack to load status +1d4e : a280 > ldx #$80 ;precharge index x +1d50 : 28 > plp + +1d51 : e07f cpx #$7f + tst_stat fc +1d53 : 08 > php ;save status +1d54 : 68 > pla ;use stack to retrieve status +1d55 : 48 > pha + > cmp_flag fc +1d56 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1d58 : d0fe > bne * ;failed not equal (non zero) + > +1d5a : 28 > plp ;restore status + +1d5b : ca dex +1d5c : e07f cpx #$7f + tst_stat fzc +1d5e : 08 > php ;save status +1d5f : 68 > pla ;use stack to retrieve status +1d60 : 48 > pha + > cmp_flag fzc +1d61 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1d63 : d0fe > bne * ;failed not equal (non zero) + > +1d65 : 28 > plp ;restore status + +1d66 : ca dex +1d67 : e07f cpx #$7f + tst_x $7e,fn +1d69 : 08 > php ;save flags +1d6a : e07e > cpx #$7e ;test result + > trap_ne +1d6c : d0fe > bne * ;failed not equal (non zero) + > +1d6e : 68 > pla ;load status +1d6f : 48 > pha + > cmp_flag fn +1d70 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1d72 : d0fe > bne * ;failed not equal (non zero) + > +1d74 : 28 > plp ;restore status + + set_x $80,$ff + > load_flag $ff +1d75 : a9ff > lda #$ff ;allow test to change + > +1d77 : 48 > pha ;use stack to load status +1d78 : a280 > ldx #$80 ;precharge index x +1d7a : 28 > plp + +1d7b : e07f cpx #$7f + tst_stat ~fnz +1d7d : 08 > php ;save status +1d7e : 68 > pla ;use stack to retrieve status +1d7f : 48 > pha + > cmp_flag ~fnz +1d80 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1d82 : d0fe > bne * ;failed not equal (non zero) + > +1d84 : 28 > plp ;restore status + +1d85 : ca dex +1d86 : e07f cpx #$7f + tst_stat ~fn +1d88 : 08 > php ;save status +1d89 : 68 > pla ;use stack to retrieve status +1d8a : 48 > pha + > cmp_flag ~fn +1d8b : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +1d8d : d0fe > bne * ;failed not equal (non zero) + > +1d8f : 28 > plp ;restore status + +1d90 : ca dex +1d91 : e07f cpx #$7f + tst_x $7e,~fzc +1d93 : 08 > php ;save flags +1d94 : e07e > cpx #$7e ;test result + > trap_ne +1d96 : d0fe > bne * ;failed not equal (non zero) + > +1d98 : 68 > pla ;load status +1d99 : 48 > pha + > cmp_flag ~fzc +1d9a : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +1d9c : d0fe > bne * ;failed not equal (non zero) + > +1d9e : 28 > plp ;restore status + + next_test +1d9f : ad0002 > lda test_case ;previous test +1da2 : c91a > cmp #test_num + > trap_ne ;test is out of sequence +1da4 : d0fe > bne * ;failed not equal (non zero) + > +001b = >test_num = test_num + 1 +1da6 : a91b > lda #test_num ;*** next tests' number +1da8 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; CPY - zp / abs / # + set_y $80,0 + > load_flag 0 +1dab : a900 > lda #0 ;allow test to change I + > +1dad : 48 > pha ;use stack to load status +1dae : a080 > ldy #$80 ;precharge index y +1db0 : 28 > plp + +1db1 : c417 cpy zp7f + tst_stat fc +1db3 : 08 > php ;save status +1db4 : 68 > pla ;use stack to retrieve status +1db5 : 48 > pha + > cmp_flag fc +1db6 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1db8 : d0fe > bne * ;failed not equal (non zero) + > +1dba : 28 > plp ;restore status + +1dbb : 88 dey +1dbc : c417 cpy zp7f + tst_stat fzc +1dbe : 08 > php ;save status +1dbf : 68 > pla ;use stack to retrieve status +1dc0 : 48 > pha + > cmp_flag fzc +1dc1 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1dc3 : d0fe > bne * ;failed not equal (non zero) + > +1dc5 : 28 > plp ;restore status + +1dc6 : 88 dey +1dc7 : c417 cpy zp7f + tst_y $7e,fn +1dc9 : 08 > php ;save flags +1dca : c07e > cpy #$7e ;test result + > trap_ne +1dcc : d0fe > bne * ;failed not equal (non zero) + > +1dce : 68 > pla ;load status +1dcf : 48 > pha + > cmp_flag fn +1dd0 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1dd2 : d0fe > bne * ;failed not equal (non zero) + > +1dd4 : 28 > plp ;restore status + + set_y $80,$ff + > load_flag $ff +1dd5 : a9ff > lda #$ff ;allow test to change + > +1dd7 : 48 > pha ;use stack to load status +1dd8 : a080 > ldy #$80 ;precharge index y +1dda : 28 > plp + +1ddb : c417 cpy zp7f + tst_stat ~fnz +1ddd : 08 > php ;save status +1dde : 68 > pla ;use stack to retrieve status +1ddf : 48 > pha + > cmp_flag ~fnz +1de0 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1de2 : d0fe > bne * ;failed not equal (non zero) + > +1de4 : 28 > plp ;restore status + +1de5 : 88 dey +1de6 : c417 cpy zp7f + tst_stat ~fn +1de8 : 08 > php ;save status +1de9 : 68 > pla ;use stack to retrieve status +1dea : 48 > pha + > cmp_flag ~fn +1deb : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +1ded : d0fe > bne * ;failed not equal (non zero) + > +1def : 28 > plp ;restore status + +1df0 : 88 dey +1df1 : c417 cpy zp7f + tst_y $7e,~fzc +1df3 : 08 > php ;save flags +1df4 : c07e > cpy #$7e ;test result + > trap_ne +1df6 : d0fe > bne * ;failed not equal (non zero) + > +1df8 : 68 > pla ;load status +1df9 : 48 > pha + > cmp_flag ~fzc +1dfa : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +1dfc : d0fe > bne * ;failed not equal (non zero) + > +1dfe : 28 > plp ;restore status + + + set_y $80,0 + > load_flag 0 +1dff : a900 > lda #0 ;allow test to change I + > +1e01 : 48 > pha ;use stack to load status +1e02 : a080 > ldy #$80 ;precharge index y +1e04 : 28 > plp + +1e05 : cc1b02 cpy abs7f + tst_stat fc +1e08 : 08 > php ;save status +1e09 : 68 > pla ;use stack to retrieve status +1e0a : 48 > pha + > cmp_flag fc +1e0b : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1e0d : d0fe > bne * ;failed not equal (non zero) + > +1e0f : 28 > plp ;restore status + +1e10 : 88 dey +1e11 : cc1b02 cpy abs7f + tst_stat fzc +1e14 : 08 > php ;save status +1e15 : 68 > pla ;use stack to retrieve status +1e16 : 48 > pha + > cmp_flag fzc +1e17 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1e19 : d0fe > bne * ;failed not equal (non zero) + > +1e1b : 28 > plp ;restore status + +1e1c : 88 dey +1e1d : cc1b02 cpy abs7f + tst_y $7e,fn +1e20 : 08 > php ;save flags +1e21 : c07e > cpy #$7e ;test result + > trap_ne +1e23 : d0fe > bne * ;failed not equal (non zero) + > +1e25 : 68 > pla ;load status +1e26 : 48 > pha + > cmp_flag fn +1e27 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1e29 : d0fe > bne * ;failed not equal (non zero) + > +1e2b : 28 > plp ;restore status + + set_y $80,$ff + > load_flag $ff +1e2c : a9ff > lda #$ff ;allow test to change + > +1e2e : 48 > pha ;use stack to load status +1e2f : a080 > ldy #$80 ;precharge index y +1e31 : 28 > plp + +1e32 : cc1b02 cpy abs7f + tst_stat ~fnz +1e35 : 08 > php ;save status +1e36 : 68 > pla ;use stack to retrieve status +1e37 : 48 > pha + > cmp_flag ~fnz +1e38 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1e3a : d0fe > bne * ;failed not equal (non zero) + > +1e3c : 28 > plp ;restore status + +1e3d : 88 dey +1e3e : cc1b02 cpy abs7f + tst_stat ~fn +1e41 : 08 > php ;save status +1e42 : 68 > pla ;use stack to retrieve status +1e43 : 48 > pha + > cmp_flag ~fn +1e44 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +1e46 : d0fe > bne * ;failed not equal (non zero) + > +1e48 : 28 > plp ;restore status + +1e49 : 88 dey +1e4a : cc1b02 cpy abs7f + tst_y $7e,~fzc +1e4d : 08 > php ;save flags +1e4e : c07e > cpy #$7e ;test result + > trap_ne +1e50 : d0fe > bne * ;failed not equal (non zero) + > +1e52 : 68 > pla ;load status +1e53 : 48 > pha + > cmp_flag ~fzc +1e54 : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +1e56 : d0fe > bne * ;failed not equal (non zero) + > +1e58 : 28 > plp ;restore status + + + set_y $80,0 + > load_flag 0 +1e59 : a900 > lda #0 ;allow test to change I + > +1e5b : 48 > pha ;use stack to load status +1e5c : a080 > ldy #$80 ;precharge index y +1e5e : 28 > plp + +1e5f : c07f cpy #$7f + tst_stat fc +1e61 : 08 > php ;save status +1e62 : 68 > pla ;use stack to retrieve status +1e63 : 48 > pha + > cmp_flag fc +1e64 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1e66 : d0fe > bne * ;failed not equal (non zero) + > +1e68 : 28 > plp ;restore status + +1e69 : 88 dey +1e6a : c07f cpy #$7f + tst_stat fzc +1e6c : 08 > php ;save status +1e6d : 68 > pla ;use stack to retrieve status +1e6e : 48 > pha + > cmp_flag fzc +1e6f : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1e71 : d0fe > bne * ;failed not equal (non zero) + > +1e73 : 28 > plp ;restore status + +1e74 : 88 dey +1e75 : c07f cpy #$7f + tst_y $7e,fn +1e77 : 08 > php ;save flags +1e78 : c07e > cpy #$7e ;test result + > trap_ne +1e7a : d0fe > bne * ;failed not equal (non zero) + > +1e7c : 68 > pla ;load status +1e7d : 48 > pha + > cmp_flag fn +1e7e : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1e80 : d0fe > bne * ;failed not equal (non zero) + > +1e82 : 28 > plp ;restore status + + set_y $80,$ff + > load_flag $ff +1e83 : a9ff > lda #$ff ;allow test to change + > +1e85 : 48 > pha ;use stack to load status +1e86 : a080 > ldy #$80 ;precharge index y +1e88 : 28 > plp + +1e89 : c07f cpy #$7f + tst_stat ~fnz +1e8b : 08 > php ;save status +1e8c : 68 > pla ;use stack to retrieve status +1e8d : 48 > pha + > cmp_flag ~fnz +1e8e : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1e90 : d0fe > bne * ;failed not equal (non zero) + > +1e92 : 28 > plp ;restore status + +1e93 : 88 dey +1e94 : c07f cpy #$7f + tst_stat ~fn +1e96 : 08 > php ;save status +1e97 : 68 > pla ;use stack to retrieve status +1e98 : 48 > pha + > cmp_flag ~fn +1e99 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +1e9b : d0fe > bne * ;failed not equal (non zero) + > +1e9d : 28 > plp ;restore status + +1e9e : 88 dey +1e9f : c07f cpy #$7f + tst_y $7e,~fzc +1ea1 : 08 > php ;save flags +1ea2 : c07e > cpy #$7e ;test result + > trap_ne +1ea4 : d0fe > bne * ;failed not equal (non zero) + > +1ea6 : 68 > pla ;load status +1ea7 : 48 > pha + > cmp_flag ~fzc +1ea8 : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +1eaa : d0fe > bne * ;failed not equal (non zero) + > +1eac : 28 > plp ;restore status + + next_test +1ead : ad0002 > lda test_case ;previous test +1eb0 : c91b > cmp #test_num + > trap_ne ;test is out of sequence +1eb2 : d0fe > bne * ;failed not equal (non zero) + > +001c = >test_num = test_num + 1 +1eb4 : a91c > lda #test_num ;*** next tests' number +1eb6 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; CMP - zp / abs / # + set_a $80,0 + > load_flag 0 +1eb9 : a900 > lda #0 ;allow test to change I + > +1ebb : 48 > pha ;use stack to load status +1ebc : a980 > lda #$80 ;precharge accu +1ebe : 28 > plp + +1ebf : c517 cmp zp7f + tst_a $80,fc +1ec1 : 08 > php ;save flags +1ec2 : c980 > cmp #$80 ;test result + > trap_ne +1ec4 : d0fe > bne * ;failed not equal (non zero) + > +1ec6 : 68 > pla ;load status +1ec7 : 48 > pha + > cmp_flag fc +1ec8 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1eca : d0fe > bne * ;failed not equal (non zero) + > +1ecc : 28 > plp ;restore status + + set_a $7f,0 + > load_flag 0 +1ecd : a900 > lda #0 ;allow test to change I + > +1ecf : 48 > pha ;use stack to load status +1ed0 : a97f > lda #$7f ;precharge accu +1ed2 : 28 > plp + +1ed3 : c517 cmp zp7f + tst_a $7f,fzc +1ed5 : 08 > php ;save flags +1ed6 : c97f > cmp #$7f ;test result + > trap_ne +1ed8 : d0fe > bne * ;failed not equal (non zero) + > +1eda : 68 > pla ;load status +1edb : 48 > pha + > cmp_flag fzc +1edc : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1ede : d0fe > bne * ;failed not equal (non zero) + > +1ee0 : 28 > plp ;restore status + + set_a $7e,0 + > load_flag 0 +1ee1 : a900 > lda #0 ;allow test to change I + > +1ee3 : 48 > pha ;use stack to load status +1ee4 : a97e > lda #$7e ;precharge accu +1ee6 : 28 > plp + +1ee7 : c517 cmp zp7f + tst_a $7e,fn +1ee9 : 08 > php ;save flags +1eea : c97e > cmp #$7e ;test result + > trap_ne +1eec : d0fe > bne * ;failed not equal (non zero) + > +1eee : 68 > pla ;load status +1eef : 48 > pha + > cmp_flag fn +1ef0 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1ef2 : d0fe > bne * ;failed not equal (non zero) + > +1ef4 : 28 > plp ;restore status + + set_a $80,$ff + > load_flag $ff +1ef5 : a9ff > lda #$ff ;allow test to change + > +1ef7 : 48 > pha ;use stack to load status +1ef8 : a980 > lda #$80 ;precharge accu +1efa : 28 > plp + +1efb : c517 cmp zp7f + tst_a $80,~fnz +1efd : 08 > php ;save flags +1efe : c980 > cmp #$80 ;test result + > trap_ne +1f00 : d0fe > bne * ;failed not equal (non zero) + > +1f02 : 68 > pla ;load status +1f03 : 48 > pha + > cmp_flag ~fnz +1f04 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1f06 : d0fe > bne * ;failed not equal (non zero) + > +1f08 : 28 > plp ;restore status + + set_a $7f,$ff + > load_flag $ff +1f09 : a9ff > lda #$ff ;allow test to change + > +1f0b : 48 > pha ;use stack to load status +1f0c : a97f > lda #$7f ;precharge accu +1f0e : 28 > plp + +1f0f : c517 cmp zp7f + tst_a $7f,~fn +1f11 : 08 > php ;save flags +1f12 : c97f > cmp #$7f ;test result + > trap_ne +1f14 : d0fe > bne * ;failed not equal (non zero) + > +1f16 : 68 > pla ;load status +1f17 : 48 > pha + > cmp_flag ~fn +1f18 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +1f1a : d0fe > bne * ;failed not equal (non zero) + > +1f1c : 28 > plp ;restore status + + set_a $7e,$ff + > load_flag $ff +1f1d : a9ff > lda #$ff ;allow test to change + > +1f1f : 48 > pha ;use stack to load status +1f20 : a97e > lda #$7e ;precharge accu +1f22 : 28 > plp + +1f23 : c517 cmp zp7f + tst_a $7e,~fzc +1f25 : 08 > php ;save flags +1f26 : c97e > cmp #$7e ;test result + > trap_ne +1f28 : d0fe > bne * ;failed not equal (non zero) + > +1f2a : 68 > pla ;load status +1f2b : 48 > pha + > cmp_flag ~fzc +1f2c : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +1f2e : d0fe > bne * ;failed not equal (non zero) + > +1f30 : 28 > plp ;restore status + + + set_a $80,0 + > load_flag 0 +1f31 : a900 > lda #0 ;allow test to change I + > +1f33 : 48 > pha ;use stack to load status +1f34 : a980 > lda #$80 ;precharge accu +1f36 : 28 > plp + +1f37 : cd1b02 cmp abs7f + tst_a $80,fc +1f3a : 08 > php ;save flags +1f3b : c980 > cmp #$80 ;test result + > trap_ne +1f3d : d0fe > bne * ;failed not equal (non zero) + > +1f3f : 68 > pla ;load status +1f40 : 48 > pha + > cmp_flag fc +1f41 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1f43 : d0fe > bne * ;failed not equal (non zero) + > +1f45 : 28 > plp ;restore status + + set_a $7f,0 + > load_flag 0 +1f46 : a900 > lda #0 ;allow test to change I + > +1f48 : 48 > pha ;use stack to load status +1f49 : a97f > lda #$7f ;precharge accu +1f4b : 28 > plp + +1f4c : cd1b02 cmp abs7f + tst_a $7f,fzc +1f4f : 08 > php ;save flags +1f50 : c97f > cmp #$7f ;test result + > trap_ne +1f52 : d0fe > bne * ;failed not equal (non zero) + > +1f54 : 68 > pla ;load status +1f55 : 48 > pha + > cmp_flag fzc +1f56 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1f58 : d0fe > bne * ;failed not equal (non zero) + > +1f5a : 28 > plp ;restore status + + set_a $7e,0 + > load_flag 0 +1f5b : a900 > lda #0 ;allow test to change I + > +1f5d : 48 > pha ;use stack to load status +1f5e : a97e > lda #$7e ;precharge accu +1f60 : 28 > plp + +1f61 : cd1b02 cmp abs7f + tst_a $7e,fn +1f64 : 08 > php ;save flags +1f65 : c97e > cmp #$7e ;test result + > trap_ne +1f67 : d0fe > bne * ;failed not equal (non zero) + > +1f69 : 68 > pla ;load status +1f6a : 48 > pha + > cmp_flag fn +1f6b : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1f6d : d0fe > bne * ;failed not equal (non zero) + > +1f6f : 28 > plp ;restore status + + set_a $80,$ff + > load_flag $ff +1f70 : a9ff > lda #$ff ;allow test to change + > +1f72 : 48 > pha ;use stack to load status +1f73 : a980 > lda #$80 ;precharge accu +1f75 : 28 > plp + +1f76 : cd1b02 cmp abs7f + tst_a $80,~fnz +1f79 : 08 > php ;save flags +1f7a : c980 > cmp #$80 ;test result + > trap_ne +1f7c : d0fe > bne * ;failed not equal (non zero) + > +1f7e : 68 > pla ;load status +1f7f : 48 > pha + > cmp_flag ~fnz +1f80 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1f82 : d0fe > bne * ;failed not equal (non zero) + > +1f84 : 28 > plp ;restore status + + set_a $7f,$ff + > load_flag $ff +1f85 : a9ff > lda #$ff ;allow test to change + > +1f87 : 48 > pha ;use stack to load status +1f88 : a97f > lda #$7f ;precharge accu +1f8a : 28 > plp + +1f8b : cd1b02 cmp abs7f + tst_a $7f,~fn +1f8e : 08 > php ;save flags +1f8f : c97f > cmp #$7f ;test result + > trap_ne +1f91 : d0fe > bne * ;failed not equal (non zero) + > +1f93 : 68 > pla ;load status +1f94 : 48 > pha + > cmp_flag ~fn +1f95 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +1f97 : d0fe > bne * ;failed not equal (non zero) + > +1f99 : 28 > plp ;restore status + + set_a $7e,$ff + > load_flag $ff +1f9a : a9ff > lda #$ff ;allow test to change + > +1f9c : 48 > pha ;use stack to load status +1f9d : a97e > lda #$7e ;precharge accu +1f9f : 28 > plp + +1fa0 : cd1b02 cmp abs7f + tst_a $7e,~fzc +1fa3 : 08 > php ;save flags +1fa4 : c97e > cmp #$7e ;test result + > trap_ne +1fa6 : d0fe > bne * ;failed not equal (non zero) + > +1fa8 : 68 > pla ;load status +1fa9 : 48 > pha + > cmp_flag ~fzc +1faa : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +1fac : d0fe > bne * ;failed not equal (non zero) + > +1fae : 28 > plp ;restore status + + + set_a $80,0 + > load_flag 0 +1faf : a900 > lda #0 ;allow test to change I + > +1fb1 : 48 > pha ;use stack to load status +1fb2 : a980 > lda #$80 ;precharge accu +1fb4 : 28 > plp + +1fb5 : c97f cmp #$7f + tst_a $80,fc +1fb7 : 08 > php ;save flags +1fb8 : c980 > cmp #$80 ;test result + > trap_ne +1fba : d0fe > bne * ;failed not equal (non zero) + > +1fbc : 68 > pla ;load status +1fbd : 48 > pha + > cmp_flag fc +1fbe : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1fc0 : d0fe > bne * ;failed not equal (non zero) + > +1fc2 : 28 > plp ;restore status + + set_a $7f,0 + > load_flag 0 +1fc3 : a900 > lda #0 ;allow test to change I + > +1fc5 : 48 > pha ;use stack to load status +1fc6 : a97f > lda #$7f ;precharge accu +1fc8 : 28 > plp + +1fc9 : c97f cmp #$7f + tst_a $7f,fzc +1fcb : 08 > php ;save flags +1fcc : c97f > cmp #$7f ;test result + > trap_ne +1fce : d0fe > bne * ;failed not equal (non zero) + > +1fd0 : 68 > pla ;load status +1fd1 : 48 > pha + > cmp_flag fzc +1fd2 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1fd4 : d0fe > bne * ;failed not equal (non zero) + > +1fd6 : 28 > plp ;restore status + + set_a $7e,0 + > load_flag 0 +1fd7 : a900 > lda #0 ;allow test to change I + > +1fd9 : 48 > pha ;use stack to load status +1fda : a97e > lda #$7e ;precharge accu +1fdc : 28 > plp + +1fdd : c97f cmp #$7f + tst_a $7e,fn +1fdf : 08 > php ;save flags +1fe0 : c97e > cmp #$7e ;test result + > trap_ne +1fe2 : d0fe > bne * ;failed not equal (non zero) + > +1fe4 : 68 > pla ;load status +1fe5 : 48 > pha + > cmp_flag fn +1fe6 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1fe8 : d0fe > bne * ;failed not equal (non zero) + > +1fea : 28 > plp ;restore status + + set_a $80,$ff + > load_flag $ff +1feb : a9ff > lda #$ff ;allow test to change + > +1fed : 48 > pha ;use stack to load status +1fee : a980 > lda #$80 ;precharge accu +1ff0 : 28 > plp + +1ff1 : c97f cmp #$7f + tst_a $80,~fnz +1ff3 : 08 > php ;save flags +1ff4 : c980 > cmp #$80 ;test result + > trap_ne +1ff6 : d0fe > bne * ;failed not equal (non zero) + > +1ff8 : 68 > pla ;load status +1ff9 : 48 > pha + > cmp_flag ~fnz +1ffa : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1ffc : d0fe > bne * ;failed not equal (non zero) + > +1ffe : 28 > plp ;restore status + + set_a $7f,$ff + > load_flag $ff +1fff : a9ff > lda #$ff ;allow test to change + > +2001 : 48 > pha ;use stack to load status +2002 : a97f > lda #$7f ;precharge accu +2004 : 28 > plp + +2005 : c97f cmp #$7f + tst_a $7f,~fn +2007 : 08 > php ;save flags +2008 : c97f > cmp #$7f ;test result + > trap_ne +200a : d0fe > bne * ;failed not equal (non zero) + > +200c : 68 > pla ;load status +200d : 48 > pha + > cmp_flag ~fn +200e : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +2010 : d0fe > bne * ;failed not equal (non zero) + > +2012 : 28 > plp ;restore status + + set_a $7e,$ff + > load_flag $ff +2013 : a9ff > lda #$ff ;allow test to change + > +2015 : 48 > pha ;use stack to load status +2016 : a97e > lda #$7e ;precharge accu +2018 : 28 > plp + +2019 : c97f cmp #$7f + tst_a $7e,~fzc +201b : 08 > php ;save flags +201c : c97e > cmp #$7e ;test result + > trap_ne +201e : d0fe > bne * ;failed not equal (non zero) + > +2020 : 68 > pla ;load status +2021 : 48 > pha + > cmp_flag ~fzc +2022 : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +2024 : d0fe > bne * ;failed not equal (non zero) + > +2026 : 28 > plp ;restore status + + +2027 : a204 ldx #4 ;with indexing by X + set_a $80,0 + > load_flag 0 +2029 : a900 > lda #0 ;allow test to change I + > +202b : 48 > pha ;use stack to load status +202c : a980 > lda #$80 ;precharge accu +202e : 28 > plp + +202f : d513 cmp zp1,x + tst_a $80,fc +2031 : 08 > php ;save flags +2032 : c980 > cmp #$80 ;test result + > trap_ne +2034 : d0fe > bne * ;failed not equal (non zero) + > +2036 : 68 > pla ;load status +2037 : 48 > pha + > cmp_flag fc +2038 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +203a : d0fe > bne * ;failed not equal (non zero) + > +203c : 28 > plp ;restore status + + set_a $7f,0 + > load_flag 0 +203d : a900 > lda #0 ;allow test to change I + > +203f : 48 > pha ;use stack to load status +2040 : a97f > lda #$7f ;precharge accu +2042 : 28 > plp + +2043 : d513 cmp zp1,x + tst_a $7f,fzc +2045 : 08 > php ;save flags +2046 : c97f > cmp #$7f ;test result + > trap_ne +2048 : d0fe > bne * ;failed not equal (non zero) + > +204a : 68 > pla ;load status +204b : 48 > pha + > cmp_flag fzc +204c : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +204e : d0fe > bne * ;failed not equal (non zero) + > +2050 : 28 > plp ;restore status + + set_a $7e,0 + > load_flag 0 +2051 : a900 > lda #0 ;allow test to change I + > +2053 : 48 > pha ;use stack to load status +2054 : a97e > lda #$7e ;precharge accu +2056 : 28 > plp + +2057 : d513 cmp zp1,x + tst_a $7e,fn +2059 : 08 > php ;save flags +205a : c97e > cmp #$7e ;test result + > trap_ne +205c : d0fe > bne * ;failed not equal (non zero) + > +205e : 68 > pla ;load status +205f : 48 > pha + > cmp_flag fn +2060 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +2062 : d0fe > bne * ;failed not equal (non zero) + > +2064 : 28 > plp ;restore status + + set_a $80,$ff + > load_flag $ff +2065 : a9ff > lda #$ff ;allow test to change + > +2067 : 48 > pha ;use stack to load status +2068 : a980 > lda #$80 ;precharge accu +206a : 28 > plp + +206b : d513 cmp zp1,x + tst_a $80,~fnz +206d : 08 > php ;save flags +206e : c980 > cmp #$80 ;test result + > trap_ne +2070 : d0fe > bne * ;failed not equal (non zero) + > +2072 : 68 > pla ;load status +2073 : 48 > pha + > cmp_flag ~fnz +2074 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +2076 : d0fe > bne * ;failed not equal (non zero) + > +2078 : 28 > plp ;restore status + + set_a $7f,$ff + > load_flag $ff +2079 : a9ff > lda #$ff ;allow test to change + > +207b : 48 > pha ;use stack to load status +207c : a97f > lda #$7f ;precharge accu +207e : 28 > plp + +207f : d513 cmp zp1,x + tst_a $7f,~fn +2081 : 08 > php ;save flags +2082 : c97f > cmp #$7f ;test result + > trap_ne +2084 : d0fe > bne * ;failed not equal (non zero) + > +2086 : 68 > pla ;load status +2087 : 48 > pha + > cmp_flag ~fn +2088 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +208a : d0fe > bne * ;failed not equal (non zero) + > +208c : 28 > plp ;restore status + + set_a $7e,$ff + > load_flag $ff +208d : a9ff > lda #$ff ;allow test to change + > +208f : 48 > pha ;use stack to load status +2090 : a97e > lda #$7e ;precharge accu +2092 : 28 > plp + +2093 : d513 cmp zp1,x + tst_a $7e,~fzc +2095 : 08 > php ;save flags +2096 : c97e > cmp #$7e ;test result + > trap_ne +2098 : d0fe > bne * ;failed not equal (non zero) + > +209a : 68 > pla ;load status +209b : 48 > pha + > cmp_flag ~fzc +209c : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +209e : d0fe > bne * ;failed not equal (non zero) + > +20a0 : 28 > plp ;restore status + + + set_a $80,0 + > load_flag 0 +20a1 : a900 > lda #0 ;allow test to change I + > +20a3 : 48 > pha ;use stack to load status +20a4 : a980 > lda #$80 ;precharge accu +20a6 : 28 > plp + +20a7 : dd1702 cmp abs1,x + tst_a $80,fc +20aa : 08 > php ;save flags +20ab : c980 > cmp #$80 ;test result + > trap_ne +20ad : d0fe > bne * ;failed not equal (non zero) + > +20af : 68 > pla ;load status +20b0 : 48 > pha + > cmp_flag fc +20b1 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +20b3 : d0fe > bne * ;failed not equal (non zero) + > +20b5 : 28 > plp ;restore status + + set_a $7f,0 + > load_flag 0 +20b6 : a900 > lda #0 ;allow test to change I + > +20b8 : 48 > pha ;use stack to load status +20b9 : a97f > lda #$7f ;precharge accu +20bb : 28 > plp + +20bc : dd1702 cmp abs1,x + tst_a $7f,fzc +20bf : 08 > php ;save flags +20c0 : c97f > cmp #$7f ;test result + > trap_ne +20c2 : d0fe > bne * ;failed not equal (non zero) + > +20c4 : 68 > pla ;load status +20c5 : 48 > pha + > cmp_flag fzc +20c6 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +20c8 : d0fe > bne * ;failed not equal (non zero) + > +20ca : 28 > plp ;restore status + + set_a $7e,0 + > load_flag 0 +20cb : a900 > lda #0 ;allow test to change I + > +20cd : 48 > pha ;use stack to load status +20ce : a97e > lda #$7e ;precharge accu +20d0 : 28 > plp + +20d1 : dd1702 cmp abs1,x + tst_a $7e,fn +20d4 : 08 > php ;save flags +20d5 : c97e > cmp #$7e ;test result + > trap_ne +20d7 : d0fe > bne * ;failed not equal (non zero) + > +20d9 : 68 > pla ;load status +20da : 48 > pha + > cmp_flag fn +20db : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +20dd : d0fe > bne * ;failed not equal (non zero) + > +20df : 28 > plp ;restore status + + set_a $80,$ff + > load_flag $ff +20e0 : a9ff > lda #$ff ;allow test to change + > +20e2 : 48 > pha ;use stack to load status +20e3 : a980 > lda #$80 ;precharge accu +20e5 : 28 > plp + +20e6 : dd1702 cmp abs1,x + tst_a $80,~fnz +20e9 : 08 > php ;save flags +20ea : c980 > cmp #$80 ;test result + > trap_ne +20ec : d0fe > bne * ;failed not equal (non zero) + > +20ee : 68 > pla ;load status +20ef : 48 > pha + > cmp_flag ~fnz +20f0 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +20f2 : d0fe > bne * ;failed not equal (non zero) + > +20f4 : 28 > plp ;restore status + + set_a $7f,$ff + > load_flag $ff +20f5 : a9ff > lda #$ff ;allow test to change + > +20f7 : 48 > pha ;use stack to load status +20f8 : a97f > lda #$7f ;precharge accu +20fa : 28 > plp + +20fb : dd1702 cmp abs1,x + tst_a $7f,~fn +20fe : 08 > php ;save flags +20ff : c97f > cmp #$7f ;test result + > trap_ne +2101 : d0fe > bne * ;failed not equal (non zero) + > +2103 : 68 > pla ;load status +2104 : 48 > pha + > cmp_flag ~fn +2105 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +2107 : d0fe > bne * ;failed not equal (non zero) + > +2109 : 28 > plp ;restore status + + set_a $7e,$ff + > load_flag $ff +210a : a9ff > lda #$ff ;allow test to change + > +210c : 48 > pha ;use stack to load status +210d : a97e > lda #$7e ;precharge accu +210f : 28 > plp + +2110 : dd1702 cmp abs1,x + tst_a $7e,~fzc +2113 : 08 > php ;save flags +2114 : c97e > cmp #$7e ;test result + > trap_ne +2116 : d0fe > bne * ;failed not equal (non zero) + > +2118 : 68 > pla ;load status +2119 : 48 > pha + > cmp_flag ~fzc +211a : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +211c : d0fe > bne * ;failed not equal (non zero) + > +211e : 28 > plp ;restore status + + +211f : a004 ldy #4 ;with indexing by Y +2121 : a208 ldx #8 ;with indexed indirect + set_a $80,0 + > load_flag 0 +2123 : a900 > lda #0 ;allow test to change I + > +2125 : 48 > pha ;use stack to load status +2126 : a980 > lda #$80 ;precharge accu +2128 : 28 > plp + +2129 : d91702 cmp abs1,y + tst_a $80,fc +212c : 08 > php ;save flags +212d : c980 > cmp #$80 ;test result + > trap_ne +212f : d0fe > bne * ;failed not equal (non zero) + > +2131 : 68 > pla ;load status +2132 : 48 > pha + > cmp_flag fc +2133 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +2135 : d0fe > bne * ;failed not equal (non zero) + > +2137 : 28 > plp ;restore status + + set_a $7f,0 + > load_flag 0 +2138 : a900 > lda #0 ;allow test to change I + > +213a : 48 > pha ;use stack to load status +213b : a97f > lda #$7f ;precharge accu +213d : 28 > plp + +213e : d91702 cmp abs1,y + tst_a $7f,fzc +2141 : 08 > php ;save flags +2142 : c97f > cmp #$7f ;test result + > trap_ne +2144 : d0fe > bne * ;failed not equal (non zero) + > +2146 : 68 > pla ;load status +2147 : 48 > pha + > cmp_flag fzc +2148 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +214a : d0fe > bne * ;failed not equal (non zero) + > +214c : 28 > plp ;restore status + + set_a $7e,0 + > load_flag 0 +214d : a900 > lda #0 ;allow test to change I + > +214f : 48 > pha ;use stack to load status +2150 : a97e > lda #$7e ;precharge accu +2152 : 28 > plp + +2153 : d91702 cmp abs1,y + tst_a $7e,fn +2156 : 08 > php ;save flags +2157 : c97e > cmp #$7e ;test result + > trap_ne +2159 : d0fe > bne * ;failed not equal (non zero) + > +215b : 68 > pla ;load status +215c : 48 > pha + > cmp_flag fn +215d : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +215f : d0fe > bne * ;failed not equal (non zero) + > +2161 : 28 > plp ;restore status + + set_a $80,$ff + > load_flag $ff +2162 : a9ff > lda #$ff ;allow test to change + > +2164 : 48 > pha ;use stack to load status +2165 : a980 > lda #$80 ;precharge accu +2167 : 28 > plp + +2168 : d91702 cmp abs1,y + tst_a $80,~fnz +216b : 08 > php ;save flags +216c : c980 > cmp #$80 ;test result + > trap_ne +216e : d0fe > bne * ;failed not equal (non zero) + > +2170 : 68 > pla ;load status +2171 : 48 > pha + > cmp_flag ~fnz +2172 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +2174 : d0fe > bne * ;failed not equal (non zero) + > +2176 : 28 > plp ;restore status + + set_a $7f,$ff + > load_flag $ff +2177 : a9ff > lda #$ff ;allow test to change + > +2179 : 48 > pha ;use stack to load status +217a : a97f > lda #$7f ;precharge accu +217c : 28 > plp + +217d : d91702 cmp abs1,y + tst_a $7f,~fn +2180 : 08 > php ;save flags +2181 : c97f > cmp #$7f ;test result + > trap_ne +2183 : d0fe > bne * ;failed not equal (non zero) + > +2185 : 68 > pla ;load status +2186 : 48 > pha + > cmp_flag ~fn +2187 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +2189 : d0fe > bne * ;failed not equal (non zero) + > +218b : 28 > plp ;restore status + + set_a $7e,$ff + > load_flag $ff +218c : a9ff > lda #$ff ;allow test to change + > +218e : 48 > pha ;use stack to load status +218f : a97e > lda #$7e ;precharge accu +2191 : 28 > plp + +2192 : d91702 cmp abs1,y + tst_a $7e,~fzc +2195 : 08 > php ;save flags +2196 : c97e > cmp #$7e ;test result + > trap_ne +2198 : d0fe > bne * ;failed not equal (non zero) + > +219a : 68 > pla ;load status +219b : 48 > pha + > cmp_flag ~fzc +219c : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +219e : d0fe > bne * ;failed not equal (non zero) + > +21a0 : 28 > plp ;restore status + + + set_a $80,0 + > load_flag 0 +21a1 : a900 > lda #0 ;allow test to change I + > +21a3 : 48 > pha ;use stack to load status +21a4 : a980 > lda #$80 ;precharge accu +21a6 : 28 > plp + +21a7 : c124 cmp (ind1,x) + tst_a $80,fc +21a9 : 08 > php ;save flags +21aa : c980 > cmp #$80 ;test result + > trap_ne +21ac : d0fe > bne * ;failed not equal (non zero) + > +21ae : 68 > pla ;load status +21af : 48 > pha + > cmp_flag fc +21b0 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +21b2 : d0fe > bne * ;failed not equal (non zero) + > +21b4 : 28 > plp ;restore status + + set_a $7f,0 + > load_flag 0 +21b5 : a900 > lda #0 ;allow test to change I + > +21b7 : 48 > pha ;use stack to load status +21b8 : a97f > lda #$7f ;precharge accu +21ba : 28 > plp + +21bb : c124 cmp (ind1,x) + tst_a $7f,fzc +21bd : 08 > php ;save flags +21be : c97f > cmp #$7f ;test result + > trap_ne +21c0 : d0fe > bne * ;failed not equal (non zero) + > +21c2 : 68 > pla ;load status +21c3 : 48 > pha + > cmp_flag fzc +21c4 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +21c6 : d0fe > bne * ;failed not equal (non zero) + > +21c8 : 28 > plp ;restore status + + set_a $7e,0 + > load_flag 0 +21c9 : a900 > lda #0 ;allow test to change I + > +21cb : 48 > pha ;use stack to load status +21cc : a97e > lda #$7e ;precharge accu +21ce : 28 > plp + +21cf : c124 cmp (ind1,x) + tst_a $7e,fn +21d1 : 08 > php ;save flags +21d2 : c97e > cmp #$7e ;test result + > trap_ne +21d4 : d0fe > bne * ;failed not equal (non zero) + > +21d6 : 68 > pla ;load status +21d7 : 48 > pha + > cmp_flag fn +21d8 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +21da : d0fe > bne * ;failed not equal (non zero) + > +21dc : 28 > plp ;restore status + + set_a $80,$ff + > load_flag $ff +21dd : a9ff > lda #$ff ;allow test to change + > +21df : 48 > pha ;use stack to load status +21e0 : a980 > lda #$80 ;precharge accu +21e2 : 28 > plp + +21e3 : c124 cmp (ind1,x) + tst_a $80,~fnz +21e5 : 08 > php ;save flags +21e6 : c980 > cmp #$80 ;test result + > trap_ne +21e8 : d0fe > bne * ;failed not equal (non zero) + > +21ea : 68 > pla ;load status +21eb : 48 > pha + > cmp_flag ~fnz +21ec : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +21ee : d0fe > bne * ;failed not equal (non zero) + > +21f0 : 28 > plp ;restore status + + set_a $7f,$ff + > load_flag $ff +21f1 : a9ff > lda #$ff ;allow test to change + > +21f3 : 48 > pha ;use stack to load status +21f4 : a97f > lda #$7f ;precharge accu +21f6 : 28 > plp + +21f7 : c124 cmp (ind1,x) + tst_a $7f,~fn +21f9 : 08 > php ;save flags +21fa : c97f > cmp #$7f ;test result + > trap_ne +21fc : d0fe > bne * ;failed not equal (non zero) + > +21fe : 68 > pla ;load status +21ff : 48 > pha + > cmp_flag ~fn +2200 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +2202 : d0fe > bne * ;failed not equal (non zero) + > +2204 : 28 > plp ;restore status + + set_a $7e,$ff + > load_flag $ff +2205 : a9ff > lda #$ff ;allow test to change + > +2207 : 48 > pha ;use stack to load status +2208 : a97e > lda #$7e ;precharge accu +220a : 28 > plp + +220b : c124 cmp (ind1,x) + tst_a $7e,~fzc +220d : 08 > php ;save flags +220e : c97e > cmp #$7e ;test result + > trap_ne +2210 : d0fe > bne * ;failed not equal (non zero) + > +2212 : 68 > pla ;load status +2213 : 48 > pha + > cmp_flag ~fzc +2214 : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +2216 : d0fe > bne * ;failed not equal (non zero) + > +2218 : 28 > plp ;restore status + + + set_a $80,0 + > load_flag 0 +2219 : a900 > lda #0 ;allow test to change I + > +221b : 48 > pha ;use stack to load status +221c : a980 > lda #$80 ;precharge accu +221e : 28 > plp + +221f : d124 cmp (ind1),y + tst_a $80,fc +2221 : 08 > php ;save flags +2222 : c980 > cmp #$80 ;test result + > trap_ne +2224 : d0fe > bne * ;failed not equal (non zero) + > +2226 : 68 > pla ;load status +2227 : 48 > pha + > cmp_flag fc +2228 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +222a : d0fe > bne * ;failed not equal (non zero) + > +222c : 28 > plp ;restore status + + set_a $7f,0 + > load_flag 0 +222d : a900 > lda #0 ;allow test to change I + > +222f : 48 > pha ;use stack to load status +2230 : a97f > lda #$7f ;precharge accu +2232 : 28 > plp + +2233 : d124 cmp (ind1),y + tst_a $7f,fzc +2235 : 08 > php ;save flags +2236 : c97f > cmp #$7f ;test result + > trap_ne +2238 : d0fe > bne * ;failed not equal (non zero) + > +223a : 68 > pla ;load status +223b : 48 > pha + > cmp_flag fzc +223c : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +223e : d0fe > bne * ;failed not equal (non zero) + > +2240 : 28 > plp ;restore status + + set_a $7e,0 + > load_flag 0 +2241 : a900 > lda #0 ;allow test to change I + > +2243 : 48 > pha ;use stack to load status +2244 : a97e > lda #$7e ;precharge accu +2246 : 28 > plp + +2247 : d124 cmp (ind1),y + tst_a $7e,fn +2249 : 08 > php ;save flags +224a : c97e > cmp #$7e ;test result + > trap_ne +224c : d0fe > bne * ;failed not equal (non zero) + > +224e : 68 > pla ;load status +224f : 48 > pha + > cmp_flag fn +2250 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +2252 : d0fe > bne * ;failed not equal (non zero) + > +2254 : 28 > plp ;restore status + + set_a $80,$ff + > load_flag $ff +2255 : a9ff > lda #$ff ;allow test to change + > +2257 : 48 > pha ;use stack to load status +2258 : a980 > lda #$80 ;precharge accu +225a : 28 > plp + +225b : d124 cmp (ind1),y + tst_a $80,~fnz +225d : 08 > php ;save flags +225e : c980 > cmp #$80 ;test result + > trap_ne +2260 : d0fe > bne * ;failed not equal (non zero) + > +2262 : 68 > pla ;load status +2263 : 48 > pha + > cmp_flag ~fnz +2264 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +2266 : d0fe > bne * ;failed not equal (non zero) + > +2268 : 28 > plp ;restore status + + set_a $7f,$ff + > load_flag $ff +2269 : a9ff > lda #$ff ;allow test to change + > +226b : 48 > pha ;use stack to load status +226c : a97f > lda #$7f ;precharge accu +226e : 28 > plp + +226f : d124 cmp (ind1),y + tst_a $7f,~fn +2271 : 08 > php ;save flags +2272 : c97f > cmp #$7f ;test result + > trap_ne +2274 : d0fe > bne * ;failed not equal (non zero) + > +2276 : 68 > pla ;load status +2277 : 48 > pha + > cmp_flag ~fn +2278 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +227a : d0fe > bne * ;failed not equal (non zero) + > +227c : 28 > plp ;restore status + + set_a $7e,$ff + > load_flag $ff +227d : a9ff > lda #$ff ;allow test to change + > +227f : 48 > pha ;use stack to load status +2280 : a97e > lda #$7e ;precharge accu +2282 : 28 > plp + +2283 : d124 cmp (ind1),y + tst_a $7e,~fzc +2285 : 08 > php ;save flags +2286 : c97e > cmp #$7e ;test result + > trap_ne +2288 : d0fe > bne * ;failed not equal (non zero) + > +228a : 68 > pla ;load status +228b : 48 > pha + > cmp_flag ~fzc +228c : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +228e : d0fe > bne * ;failed not equal (non zero) + > +2290 : 28 > plp ;restore status + + next_test +2291 : ad0002 > lda test_case ;previous test +2294 : c91c > cmp #test_num + > trap_ne ;test is out of sequence +2296 : d0fe > bne * ;failed not equal (non zero) + > +001d = >test_num = test_num + 1 +2298 : a91d > lda #test_num ;*** next tests' number +229a : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; testing shifts - ASL LSR ROL ROR all addressing mode + ; shifts - accumulator +229d : a203 ldx #3 +229f : tasl + set_ax zp1,0 + > load_flag 0 +229f : a900 > lda #0 ;allow test to change I + > +22a1 : 48 > pha ;use stack to load status +22a2 : b513 > lda zp1,x ;precharge accu +22a4 : 28 > plp + +22a5 : 0a asl a + tst_ax rASL,fASL,0 +22a6 : 08 > php ;save flags +22a7 : dd2002 > cmp rASL,x ;test result + > trap_ne +22aa : d0fe > bne * ;failed not equal (non zero) + > +22ac : 68 > pla ;load status + > eor_flag 0 +22ad : 4930 > eor #0|fao ;invert expected flags + > +22af : dd3002 > cmp fASL,x ;test flags + > trap_ne ; +22b2 : d0fe > bne * ;failed not equal (non zero) + > + +22b4 : ca dex +22b5 : 10e8 bpl tasl +22b7 : a203 ldx #3 +22b9 : tasl1 + set_ax zp1,$ff + > load_flag $ff +22b9 : a9ff > lda #$ff ;allow test to change + > +22bb : 48 > pha ;use stack to load status +22bc : b513 > lda zp1,x ;precharge accu +22be : 28 > plp + +22bf : 0a asl a + tst_ax rASL,fASL,$ff-fnzc +22c0 : 08 > php ;save flags +22c1 : dd2002 > cmp rASL,x ;test result + > trap_ne +22c4 : d0fe > bne * ;failed not equal (non zero) + > +22c6 : 68 > pla ;load status + > eor_flag $ff-fnzc +22c7 : 497c > eor #$ff-fnzc|fao ;invert expected + > +22c9 : dd3002 > cmp fASL,x ;test flags + > trap_ne ; +22cc : d0fe > bne * ;failed not equal (non zero) + > + +22ce : ca dex +22cf : 10e8 bpl tasl1 + +22d1 : a203 ldx #3 +22d3 : tlsr + set_ax zp1,0 + > load_flag 0 +22d3 : a900 > lda #0 ;allow test to change I + > +22d5 : 48 > pha ;use stack to load status +22d6 : b513 > lda zp1,x ;precharge accu +22d8 : 28 > plp + +22d9 : 4a lsr a + tst_ax rLSR,fLSR,0 +22da : 08 > php ;save flags +22db : dd2802 > cmp rLSR,x ;test result + > trap_ne +22de : d0fe > bne * ;failed not equal (non zero) + > +22e0 : 68 > pla ;load status + > eor_flag 0 +22e1 : 4930 > eor #0|fao ;invert expected flags + > +22e3 : dd3802 > cmp fLSR,x ;test flags + > trap_ne ; +22e6 : d0fe > bne * ;failed not equal (non zero) + > + +22e8 : ca dex +22e9 : 10e8 bpl tlsr +22eb : a203 ldx #3 +22ed : tlsr1 + set_ax zp1,$ff + > load_flag $ff +22ed : a9ff > lda #$ff ;allow test to change + > +22ef : 48 > pha ;use stack to load status +22f0 : b513 > lda zp1,x ;precharge accu +22f2 : 28 > plp + +22f3 : 4a lsr a + tst_ax rLSR,fLSR,$ff-fnzc +22f4 : 08 > php ;save flags +22f5 : dd2802 > cmp rLSR,x ;test result + > trap_ne +22f8 : d0fe > bne * ;failed not equal (non zero) + > +22fa : 68 > pla ;load status + > eor_flag $ff-fnzc +22fb : 497c > eor #$ff-fnzc|fao ;invert expected + > +22fd : dd3802 > cmp fLSR,x ;test flags + > trap_ne ; +2300 : d0fe > bne * ;failed not equal (non zero) + > + +2302 : ca dex +2303 : 10e8 bpl tlsr1 + +2305 : a203 ldx #3 +2307 : trol + set_ax zp1,0 + > load_flag 0 +2307 : a900 > lda #0 ;allow test to change I + > +2309 : 48 > pha ;use stack to load status +230a : b513 > lda zp1,x ;precharge accu +230c : 28 > plp + +230d : 2a rol a + tst_ax rROL,fROL,0 +230e : 08 > php ;save flags +230f : dd2002 > cmp rROL,x ;test result + > trap_ne +2312 : d0fe > bne * ;failed not equal (non zero) + > +2314 : 68 > pla ;load status + > eor_flag 0 +2315 : 4930 > eor #0|fao ;invert expected flags + > +2317 : dd3002 > cmp fROL,x ;test flags + > trap_ne ; +231a : d0fe > bne * ;failed not equal (non zero) + > + +231c : ca dex +231d : 10e8 bpl trol +231f : a203 ldx #3 +2321 : trol1 + set_ax zp1,$ff-fc + > load_flag $ff-fc +2321 : a9fe > lda #$ff-fc ;allow test to cha + > +2323 : 48 > pha ;use stack to load status +2324 : b513 > lda zp1,x ;precharge accu +2326 : 28 > plp + +2327 : 2a rol a + tst_ax rROL,fROL,$ff-fnzc +2328 : 08 > php ;save flags +2329 : dd2002 > cmp rROL,x ;test result + > trap_ne +232c : d0fe > bne * ;failed not equal (non zero) + > +232e : 68 > pla ;load status + > eor_flag $ff-fnzc +232f : 497c > eor #$ff-fnzc|fao ;invert expected + > +2331 : dd3002 > cmp fROL,x ;test flags + > trap_ne ; +2334 : d0fe > bne * ;failed not equal (non zero) + > + +2336 : ca dex +2337 : 10e8 bpl trol1 + +2339 : a203 ldx #3 +233b : trolc + set_ax zp1,fc + > load_flag fc +233b : a901 > lda #fc ;allow test to change + > +233d : 48 > pha ;use stack to load status +233e : b513 > lda zp1,x ;precharge accu +2340 : 28 > plp + +2341 : 2a rol a + tst_ax rROLc,fROLc,0 +2342 : 08 > php ;save flags +2343 : dd2402 > cmp rROLc,x ;test result + > trap_ne +2346 : d0fe > bne * ;failed not equal (non zero) + > +2348 : 68 > pla ;load status + > eor_flag 0 +2349 : 4930 > eor #0|fao ;invert expected flags + > +234b : dd3402 > cmp fROLc,x ;test flags + > trap_ne ; +234e : d0fe > bne * ;failed not equal (non zero) + > + +2350 : ca dex +2351 : 10e8 bpl trolc +2353 : a203 ldx #3 +2355 : trolc1 + set_ax zp1,$ff + > load_flag $ff +2355 : a9ff > lda #$ff ;allow test to change + > +2357 : 48 > pha ;use stack to load status +2358 : b513 > lda zp1,x ;precharge accu +235a : 28 > plp + +235b : 2a rol a + tst_ax rROLc,fROLc,$ff-fnzc +235c : 08 > php ;save flags +235d : dd2402 > cmp rROLc,x ;test result + > trap_ne +2360 : d0fe > bne * ;failed not equal (non zero) + > +2362 : 68 > pla ;load status + > eor_flag $ff-fnzc +2363 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2365 : dd3402 > cmp fROLc,x ;test flags + > trap_ne ; +2368 : d0fe > bne * ;failed not equal (non zero) + > + +236a : ca dex +236b : 10e8 bpl trolc1 + +236d : a203 ldx #3 +236f : tror + set_ax zp1,0 + > load_flag 0 +236f : a900 > lda #0 ;allow test to change I + > +2371 : 48 > pha ;use stack to load status +2372 : b513 > lda zp1,x ;precharge accu +2374 : 28 > plp + +2375 : 6a ror a + tst_ax rROR,fROR,0 +2376 : 08 > php ;save flags +2377 : dd2802 > cmp rROR,x ;test result + > trap_ne +237a : d0fe > bne * ;failed not equal (non zero) + > +237c : 68 > pla ;load status + > eor_flag 0 +237d : 4930 > eor #0|fao ;invert expected flags + > +237f : dd3802 > cmp fROR,x ;test flags + > trap_ne ; +2382 : d0fe > bne * ;failed not equal (non zero) + > + +2384 : ca dex +2385 : 10e8 bpl tror +2387 : a203 ldx #3 +2389 : tror1 + set_ax zp1,$ff-fc + > load_flag $ff-fc +2389 : a9fe > lda #$ff-fc ;allow test to cha + > +238b : 48 > pha ;use stack to load status +238c : b513 > lda zp1,x ;precharge accu +238e : 28 > plp + +238f : 6a ror a + tst_ax rROR,fROR,$ff-fnzc +2390 : 08 > php ;save flags +2391 : dd2802 > cmp rROR,x ;test result + > trap_ne +2394 : d0fe > bne * ;failed not equal (non zero) + > +2396 : 68 > pla ;load status + > eor_flag $ff-fnzc +2397 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2399 : dd3802 > cmp fROR,x ;test flags + > trap_ne ; +239c : d0fe > bne * ;failed not equal (non zero) + > + +239e : ca dex +239f : 10e8 bpl tror1 + +23a1 : a203 ldx #3 +23a3 : trorc + set_ax zp1,fc + > load_flag fc +23a3 : a901 > lda #fc ;allow test to change + > +23a5 : 48 > pha ;use stack to load status +23a6 : b513 > lda zp1,x ;precharge accu +23a8 : 28 > plp + +23a9 : 6a ror a + tst_ax rRORc,fRORc,0 +23aa : 08 > php ;save flags +23ab : dd2c02 > cmp rRORc,x ;test result + > trap_ne +23ae : d0fe > bne * ;failed not equal (non zero) + > +23b0 : 68 > pla ;load status + > eor_flag 0 +23b1 : 4930 > eor #0|fao ;invert expected flags + > +23b3 : dd3c02 > cmp fRORc,x ;test flags + > trap_ne ; +23b6 : d0fe > bne * ;failed not equal (non zero) + > + +23b8 : ca dex +23b9 : 10e8 bpl trorc +23bb : a203 ldx #3 +23bd : trorc1 + set_ax zp1,$ff + > load_flag $ff +23bd : a9ff > lda #$ff ;allow test to change + > +23bf : 48 > pha ;use stack to load status +23c0 : b513 > lda zp1,x ;precharge accu +23c2 : 28 > plp + +23c3 : 6a ror a + tst_ax rRORc,fRORc,$ff-fnzc +23c4 : 08 > php ;save flags +23c5 : dd2c02 > cmp rRORc,x ;test result + > trap_ne +23c8 : d0fe > bne * ;failed not equal (non zero) + > +23ca : 68 > pla ;load status + > eor_flag $ff-fnzc +23cb : 497c > eor #$ff-fnzc|fao ;invert expected + > +23cd : dd3c02 > cmp fRORc,x ;test flags + > trap_ne ; +23d0 : d0fe > bne * ;failed not equal (non zero) + > + +23d2 : ca dex +23d3 : 10e8 bpl trorc1 + next_test +23d5 : ad0002 > lda test_case ;previous test +23d8 : c91d > cmp #test_num + > trap_ne ;test is out of sequence +23da : d0fe > bne * ;failed not equal (non zero) + > +001e = >test_num = test_num + 1 +23dc : a91e > lda #test_num ;*** next tests' number +23de : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; shifts - zeropage +23e1 : a203 ldx #3 +23e3 : tasl2 + set_z zp1,0 + > load_flag 0 +23e3 : a900 > lda #0 ;allow test to change I + > +23e5 : 48 > pha ;use stack to load status +23e6 : b513 > lda zp1,x ;load to zeropage +23e8 : 850c > sta zpt +23ea : 28 > plp + +23eb : 060c asl zpt + tst_z rASL,fASL,0 +23ed : 08 > php ;save flags +23ee : a50c > lda zpt +23f0 : dd2002 > cmp rASL,x ;test result + > trap_ne +23f3 : d0fe > bne * ;failed not equal (non zero) + > +23f5 : 68 > pla ;load status + > eor_flag 0 +23f6 : 4930 > eor #0|fao ;invert expected flags + > +23f8 : dd3002 > cmp fASL,x ;test flags + > trap_ne +23fb : d0fe > bne * ;failed not equal (non zero) + > + +23fd : ca dex +23fe : 10e3 bpl tasl2 +2400 : a203 ldx #3 +2402 : tasl3 + set_z zp1,$ff + > load_flag $ff +2402 : a9ff > lda #$ff ;allow test to change + > +2404 : 48 > pha ;use stack to load status +2405 : b513 > lda zp1,x ;load to zeropage +2407 : 850c > sta zpt +2409 : 28 > plp + +240a : 060c asl zpt + tst_z rASL,fASL,$ff-fnzc +240c : 08 > php ;save flags +240d : a50c > lda zpt +240f : dd2002 > cmp rASL,x ;test result + > trap_ne +2412 : d0fe > bne * ;failed not equal (non zero) + > +2414 : 68 > pla ;load status + > eor_flag $ff-fnzc +2415 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2417 : dd3002 > cmp fASL,x ;test flags + > trap_ne +241a : d0fe > bne * ;failed not equal (non zero) + > + +241c : ca dex +241d : 10e3 bpl tasl3 + +241f : a203 ldx #3 +2421 : tlsr2 + set_z zp1,0 + > load_flag 0 +2421 : a900 > lda #0 ;allow test to change I + > +2423 : 48 > pha ;use stack to load status +2424 : b513 > lda zp1,x ;load to zeropage +2426 : 850c > sta zpt +2428 : 28 > plp + +2429 : 460c lsr zpt + tst_z rLSR,fLSR,0 +242b : 08 > php ;save flags +242c : a50c > lda zpt +242e : dd2802 > cmp rLSR,x ;test result + > trap_ne +2431 : d0fe > bne * ;failed not equal (non zero) + > +2433 : 68 > pla ;load status + > eor_flag 0 +2434 : 4930 > eor #0|fao ;invert expected flags + > +2436 : dd3802 > cmp fLSR,x ;test flags + > trap_ne +2439 : d0fe > bne * ;failed not equal (non zero) + > + +243b : ca dex +243c : 10e3 bpl tlsr2 +243e : a203 ldx #3 +2440 : tlsr3 + set_z zp1,$ff + > load_flag $ff +2440 : a9ff > lda #$ff ;allow test to change + > +2442 : 48 > pha ;use stack to load status +2443 : b513 > lda zp1,x ;load to zeropage +2445 : 850c > sta zpt +2447 : 28 > plp + +2448 : 460c lsr zpt + tst_z rLSR,fLSR,$ff-fnzc +244a : 08 > php ;save flags +244b : a50c > lda zpt +244d : dd2802 > cmp rLSR,x ;test result + > trap_ne +2450 : d0fe > bne * ;failed not equal (non zero) + > +2452 : 68 > pla ;load status + > eor_flag $ff-fnzc +2453 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2455 : dd3802 > cmp fLSR,x ;test flags + > trap_ne +2458 : d0fe > bne * ;failed not equal (non zero) + > + +245a : ca dex +245b : 10e3 bpl tlsr3 + +245d : a203 ldx #3 +245f : trol2 + set_z zp1,0 + > load_flag 0 +245f : a900 > lda #0 ;allow test to change I + > +2461 : 48 > pha ;use stack to load status +2462 : b513 > lda zp1,x ;load to zeropage +2464 : 850c > sta zpt +2466 : 28 > plp + +2467 : 260c rol zpt + tst_z rROL,fROL,0 +2469 : 08 > php ;save flags +246a : a50c > lda zpt +246c : dd2002 > cmp rROL,x ;test result + > trap_ne +246f : d0fe > bne * ;failed not equal (non zero) + > +2471 : 68 > pla ;load status + > eor_flag 0 +2472 : 4930 > eor #0|fao ;invert expected flags + > +2474 : dd3002 > cmp fROL,x ;test flags + > trap_ne +2477 : d0fe > bne * ;failed not equal (non zero) + > + +2479 : ca dex +247a : 10e3 bpl trol2 +247c : a203 ldx #3 +247e : trol3 + set_z zp1,$ff-fc + > load_flag $ff-fc +247e : a9fe > lda #$ff-fc ;allow test to cha + > +2480 : 48 > pha ;use stack to load status +2481 : b513 > lda zp1,x ;load to zeropage +2483 : 850c > sta zpt +2485 : 28 > plp + +2486 : 260c rol zpt + tst_z rROL,fROL,$ff-fnzc +2488 : 08 > php ;save flags +2489 : a50c > lda zpt +248b : dd2002 > cmp rROL,x ;test result + > trap_ne +248e : d0fe > bne * ;failed not equal (non zero) + > +2490 : 68 > pla ;load status + > eor_flag $ff-fnzc +2491 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2493 : dd3002 > cmp fROL,x ;test flags + > trap_ne +2496 : d0fe > bne * ;failed not equal (non zero) + > + +2498 : ca dex +2499 : 10e3 bpl trol3 + +249b : a203 ldx #3 +249d : trolc2 + set_z zp1,fc + > load_flag fc +249d : a901 > lda #fc ;allow test to change + > +249f : 48 > pha ;use stack to load status +24a0 : b513 > lda zp1,x ;load to zeropage +24a2 : 850c > sta zpt +24a4 : 28 > plp + +24a5 : 260c rol zpt + tst_z rROLc,fROLc,0 +24a7 : 08 > php ;save flags +24a8 : a50c > lda zpt +24aa : dd2402 > cmp rROLc,x ;test result + > trap_ne +24ad : d0fe > bne * ;failed not equal (non zero) + > +24af : 68 > pla ;load status + > eor_flag 0 +24b0 : 4930 > eor #0|fao ;invert expected flags + > +24b2 : dd3402 > cmp fROLc,x ;test flags + > trap_ne +24b5 : d0fe > bne * ;failed not equal (non zero) + > + +24b7 : ca dex +24b8 : 10e3 bpl trolc2 +24ba : a203 ldx #3 +24bc : trolc3 + set_z zp1,$ff + > load_flag $ff +24bc : a9ff > lda #$ff ;allow test to change + > +24be : 48 > pha ;use stack to load status +24bf : b513 > lda zp1,x ;load to zeropage +24c1 : 850c > sta zpt +24c3 : 28 > plp + +24c4 : 260c rol zpt + tst_z rROLc,fROLc,$ff-fnzc +24c6 : 08 > php ;save flags +24c7 : a50c > lda zpt +24c9 : dd2402 > cmp rROLc,x ;test result + > trap_ne +24cc : d0fe > bne * ;failed not equal (non zero) + > +24ce : 68 > pla ;load status + > eor_flag $ff-fnzc +24cf : 497c > eor #$ff-fnzc|fao ;invert expected + > +24d1 : dd3402 > cmp fROLc,x ;test flags + > trap_ne +24d4 : d0fe > bne * ;failed not equal (non zero) + > + +24d6 : ca dex +24d7 : 10e3 bpl trolc3 + +24d9 : a203 ldx #3 +24db : tror2 + set_z zp1,0 + > load_flag 0 +24db : a900 > lda #0 ;allow test to change I + > +24dd : 48 > pha ;use stack to load status +24de : b513 > lda zp1,x ;load to zeropage +24e0 : 850c > sta zpt +24e2 : 28 > plp + +24e3 : 660c ror zpt + tst_z rROR,fROR,0 +24e5 : 08 > php ;save flags +24e6 : a50c > lda zpt +24e8 : dd2802 > cmp rROR,x ;test result + > trap_ne +24eb : d0fe > bne * ;failed not equal (non zero) + > +24ed : 68 > pla ;load status + > eor_flag 0 +24ee : 4930 > eor #0|fao ;invert expected flags + > +24f0 : dd3802 > cmp fROR,x ;test flags + > trap_ne +24f3 : d0fe > bne * ;failed not equal (non zero) + > + +24f5 : ca dex +24f6 : 10e3 bpl tror2 +24f8 : a203 ldx #3 +24fa : tror3 + set_z zp1,$ff-fc + > load_flag $ff-fc +24fa : a9fe > lda #$ff-fc ;allow test to cha + > +24fc : 48 > pha ;use stack to load status +24fd : b513 > lda zp1,x ;load to zeropage +24ff : 850c > sta zpt +2501 : 28 > plp + +2502 : 660c ror zpt + tst_z rROR,fROR,$ff-fnzc +2504 : 08 > php ;save flags +2505 : a50c > lda zpt +2507 : dd2802 > cmp rROR,x ;test result + > trap_ne +250a : d0fe > bne * ;failed not equal (non zero) + > +250c : 68 > pla ;load status + > eor_flag $ff-fnzc +250d : 497c > eor #$ff-fnzc|fao ;invert expected + > +250f : dd3802 > cmp fROR,x ;test flags + > trap_ne +2512 : d0fe > bne * ;failed not equal (non zero) + > + +2514 : ca dex +2515 : 10e3 bpl tror3 + +2517 : a203 ldx #3 +2519 : trorc2 + set_z zp1,fc + > load_flag fc +2519 : a901 > lda #fc ;allow test to change + > +251b : 48 > pha ;use stack to load status +251c : b513 > lda zp1,x ;load to zeropage +251e : 850c > sta zpt +2520 : 28 > plp + +2521 : 660c ror zpt + tst_z rRORc,fRORc,0 +2523 : 08 > php ;save flags +2524 : a50c > lda zpt +2526 : dd2c02 > cmp rRORc,x ;test result + > trap_ne +2529 : d0fe > bne * ;failed not equal (non zero) + > +252b : 68 > pla ;load status + > eor_flag 0 +252c : 4930 > eor #0|fao ;invert expected flags + > +252e : dd3c02 > cmp fRORc,x ;test flags + > trap_ne +2531 : d0fe > bne * ;failed not equal (non zero) + > + +2533 : ca dex +2534 : 10e3 bpl trorc2 +2536 : a203 ldx #3 +2538 : trorc3 + set_z zp1,$ff + > load_flag $ff +2538 : a9ff > lda #$ff ;allow test to change + > +253a : 48 > pha ;use stack to load status +253b : b513 > lda zp1,x ;load to zeropage +253d : 850c > sta zpt +253f : 28 > plp + +2540 : 660c ror zpt + tst_z rRORc,fRORc,$ff-fnzc +2542 : 08 > php ;save flags +2543 : a50c > lda zpt +2545 : dd2c02 > cmp rRORc,x ;test result + > trap_ne +2548 : d0fe > bne * ;failed not equal (non zero) + > +254a : 68 > pla ;load status + > eor_flag $ff-fnzc +254b : 497c > eor #$ff-fnzc|fao ;invert expected + > +254d : dd3c02 > cmp fRORc,x ;test flags + > trap_ne +2550 : d0fe > bne * ;failed not equal (non zero) + > + +2552 : ca dex +2553 : 10e3 bpl trorc3 + next_test +2555 : ad0002 > lda test_case ;previous test +2558 : c91e > cmp #test_num + > trap_ne ;test is out of sequence +255a : d0fe > bne * ;failed not equal (non zero) + > +001f = >test_num = test_num + 1 +255c : a91f > lda #test_num ;*** next tests' number +255e : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; shifts - absolute +2561 : a203 ldx #3 +2563 : tasl4 + set_abs zp1,0 + > load_flag 0 +2563 : a900 > lda #0 ;allow test to change I + > +2565 : 48 > pha ;use stack to load status +2566 : b513 > lda zp1,x ;load to memory +2568 : 8d0302 > sta abst +256b : 28 > plp + +256c : 0e0302 asl abst + tst_abs rASL,fASL,0 +256f : 08 > php ;save flags +2570 : ad0302 > lda abst +2573 : dd2002 > cmp rASL,x ;test result + > trap_ne +2576 : d0fe > bne * ;failed not equal (non zero) + > +2578 : 68 > pla ;load status + > eor_flag 0 +2579 : 4930 > eor #0|fao ;invert expected flags + > +257b : dd3002 > cmp fASL,x ;test flags + > trap_ne +257e : d0fe > bne * ;failed not equal (non zero) + > + +2580 : ca dex +2581 : 10e0 bpl tasl4 +2583 : a203 ldx #3 +2585 : tasl5 + set_abs zp1,$ff + > load_flag $ff +2585 : a9ff > lda #$ff ;allow test to change + > +2587 : 48 > pha ;use stack to load status +2588 : b513 > lda zp1,x ;load to memory +258a : 8d0302 > sta abst +258d : 28 > plp + +258e : 0e0302 asl abst + tst_abs rASL,fASL,$ff-fnzc +2591 : 08 > php ;save flags +2592 : ad0302 > lda abst +2595 : dd2002 > cmp rASL,x ;test result + > trap_ne +2598 : d0fe > bne * ;failed not equal (non zero) + > +259a : 68 > pla ;load status + > eor_flag $ff-fnzc +259b : 497c > eor #$ff-fnzc|fao ;invert expected + > +259d : dd3002 > cmp fASL,x ;test flags + > trap_ne +25a0 : d0fe > bne * ;failed not equal (non zero) + > + +25a2 : ca dex +25a3 : 10e0 bpl tasl5 + +25a5 : a203 ldx #3 +25a7 : tlsr4 + set_abs zp1,0 + > load_flag 0 +25a7 : a900 > lda #0 ;allow test to change I + > +25a9 : 48 > pha ;use stack to load status +25aa : b513 > lda zp1,x ;load to memory +25ac : 8d0302 > sta abst +25af : 28 > plp + +25b0 : 4e0302 lsr abst + tst_abs rLSR,fLSR,0 +25b3 : 08 > php ;save flags +25b4 : ad0302 > lda abst +25b7 : dd2802 > cmp rLSR,x ;test result + > trap_ne +25ba : d0fe > bne * ;failed not equal (non zero) + > +25bc : 68 > pla ;load status + > eor_flag 0 +25bd : 4930 > eor #0|fao ;invert expected flags + > +25bf : dd3802 > cmp fLSR,x ;test flags + > trap_ne +25c2 : d0fe > bne * ;failed not equal (non zero) + > + +25c4 : ca dex +25c5 : 10e0 bpl tlsr4 +25c7 : a203 ldx #3 +25c9 : tlsr5 + set_abs zp1,$ff + > load_flag $ff +25c9 : a9ff > lda #$ff ;allow test to change + > +25cb : 48 > pha ;use stack to load status +25cc : b513 > lda zp1,x ;load to memory +25ce : 8d0302 > sta abst +25d1 : 28 > plp + +25d2 : 4e0302 lsr abst + tst_abs rLSR,fLSR,$ff-fnzc +25d5 : 08 > php ;save flags +25d6 : ad0302 > lda abst +25d9 : dd2802 > cmp rLSR,x ;test result + > trap_ne +25dc : d0fe > bne * ;failed not equal (non zero) + > +25de : 68 > pla ;load status + > eor_flag $ff-fnzc +25df : 497c > eor #$ff-fnzc|fao ;invert expected + > +25e1 : dd3802 > cmp fLSR,x ;test flags + > trap_ne +25e4 : d0fe > bne * ;failed not equal (non zero) + > + +25e6 : ca dex +25e7 : 10e0 bpl tlsr5 + +25e9 : a203 ldx #3 +25eb : trol4 + set_abs zp1,0 + > load_flag 0 +25eb : a900 > lda #0 ;allow test to change I + > +25ed : 48 > pha ;use stack to load status +25ee : b513 > lda zp1,x ;load to memory +25f0 : 8d0302 > sta abst +25f3 : 28 > plp + +25f4 : 2e0302 rol abst + tst_abs rROL,fROL,0 +25f7 : 08 > php ;save flags +25f8 : ad0302 > lda abst +25fb : dd2002 > cmp rROL,x ;test result + > trap_ne +25fe : d0fe > bne * ;failed not equal (non zero) + > +2600 : 68 > pla ;load status + > eor_flag 0 +2601 : 4930 > eor #0|fao ;invert expected flags + > +2603 : dd3002 > cmp fROL,x ;test flags + > trap_ne +2606 : d0fe > bne * ;failed not equal (non zero) + > + +2608 : ca dex +2609 : 10e0 bpl trol4 +260b : a203 ldx #3 +260d : trol5 + set_abs zp1,$ff-fc + > load_flag $ff-fc +260d : a9fe > lda #$ff-fc ;allow test to cha + > +260f : 48 > pha ;use stack to load status +2610 : b513 > lda zp1,x ;load to memory +2612 : 8d0302 > sta abst +2615 : 28 > plp + +2616 : 2e0302 rol abst + tst_abs rROL,fROL,$ff-fnzc +2619 : 08 > php ;save flags +261a : ad0302 > lda abst +261d : dd2002 > cmp rROL,x ;test result + > trap_ne +2620 : d0fe > bne * ;failed not equal (non zero) + > +2622 : 68 > pla ;load status + > eor_flag $ff-fnzc +2623 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2625 : dd3002 > cmp fROL,x ;test flags + > trap_ne +2628 : d0fe > bne * ;failed not equal (non zero) + > + +262a : ca dex +262b : 10e0 bpl trol5 + +262d : a203 ldx #3 +262f : trolc4 + set_abs zp1,fc + > load_flag fc +262f : a901 > lda #fc ;allow test to change + > +2631 : 48 > pha ;use stack to load status +2632 : b513 > lda zp1,x ;load to memory +2634 : 8d0302 > sta abst +2637 : 28 > plp + +2638 : 2e0302 rol abst + tst_abs rROLc,fROLc,0 +263b : 08 > php ;save flags +263c : ad0302 > lda abst +263f : dd2402 > cmp rROLc,x ;test result + > trap_ne +2642 : d0fe > bne * ;failed not equal (non zero) + > +2644 : 68 > pla ;load status + > eor_flag 0 +2645 : 4930 > eor #0|fao ;invert expected flags + > +2647 : dd3402 > cmp fROLc,x ;test flags + > trap_ne +264a : d0fe > bne * ;failed not equal (non zero) + > + +264c : ca dex +264d : 10e0 bpl trolc4 +264f : a203 ldx #3 +2651 : trolc5 + set_abs zp1,$ff + > load_flag $ff +2651 : a9ff > lda #$ff ;allow test to change + > +2653 : 48 > pha ;use stack to load status +2654 : b513 > lda zp1,x ;load to memory +2656 : 8d0302 > sta abst +2659 : 28 > plp + +265a : 2e0302 rol abst + tst_abs rROLc,fROLc,$ff-fnzc +265d : 08 > php ;save flags +265e : ad0302 > lda abst +2661 : dd2402 > cmp rROLc,x ;test result + > trap_ne +2664 : d0fe > bne * ;failed not equal (non zero) + > +2666 : 68 > pla ;load status + > eor_flag $ff-fnzc +2667 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2669 : dd3402 > cmp fROLc,x ;test flags + > trap_ne +266c : d0fe > bne * ;failed not equal (non zero) + > + +266e : ca dex +266f : 10e0 bpl trolc5 + +2671 : a203 ldx #3 +2673 : tror4 + set_abs zp1,0 + > load_flag 0 +2673 : a900 > lda #0 ;allow test to change I + > +2675 : 48 > pha ;use stack to load status +2676 : b513 > lda zp1,x ;load to memory +2678 : 8d0302 > sta abst +267b : 28 > plp + +267c : 6e0302 ror abst + tst_abs rROR,fROR,0 +267f : 08 > php ;save flags +2680 : ad0302 > lda abst +2683 : dd2802 > cmp rROR,x ;test result + > trap_ne +2686 : d0fe > bne * ;failed not equal (non zero) + > +2688 : 68 > pla ;load status + > eor_flag 0 +2689 : 4930 > eor #0|fao ;invert expected flags + > +268b : dd3802 > cmp fROR,x ;test flags + > trap_ne +268e : d0fe > bne * ;failed not equal (non zero) + > + +2690 : ca dex +2691 : 10e0 bpl tror4 +2693 : a203 ldx #3 +2695 : tror5 + set_abs zp1,$ff-fc + > load_flag $ff-fc +2695 : a9fe > lda #$ff-fc ;allow test to cha + > +2697 : 48 > pha ;use stack to load status +2698 : b513 > lda zp1,x ;load to memory +269a : 8d0302 > sta abst +269d : 28 > plp + +269e : 6e0302 ror abst + tst_abs rROR,fROR,$ff-fnzc +26a1 : 08 > php ;save flags +26a2 : ad0302 > lda abst +26a5 : dd2802 > cmp rROR,x ;test result + > trap_ne +26a8 : d0fe > bne * ;failed not equal (non zero) + > +26aa : 68 > pla ;load status + > eor_flag $ff-fnzc +26ab : 497c > eor #$ff-fnzc|fao ;invert expected + > +26ad : dd3802 > cmp fROR,x ;test flags + > trap_ne +26b0 : d0fe > bne * ;failed not equal (non zero) + > + +26b2 : ca dex +26b3 : 10e0 bpl tror5 + +26b5 : a203 ldx #3 +26b7 : trorc4 + set_abs zp1,fc + > load_flag fc +26b7 : a901 > lda #fc ;allow test to change + > +26b9 : 48 > pha ;use stack to load status +26ba : b513 > lda zp1,x ;load to memory +26bc : 8d0302 > sta abst +26bf : 28 > plp + +26c0 : 6e0302 ror abst + tst_abs rRORc,fRORc,0 +26c3 : 08 > php ;save flags +26c4 : ad0302 > lda abst +26c7 : dd2c02 > cmp rRORc,x ;test result + > trap_ne +26ca : d0fe > bne * ;failed not equal (non zero) + > +26cc : 68 > pla ;load status + > eor_flag 0 +26cd : 4930 > eor #0|fao ;invert expected flags + > +26cf : dd3c02 > cmp fRORc,x ;test flags + > trap_ne +26d2 : d0fe > bne * ;failed not equal (non zero) + > + +26d4 : ca dex +26d5 : 10e0 bpl trorc4 +26d7 : a203 ldx #3 +26d9 : trorc5 + set_abs zp1,$ff + > load_flag $ff +26d9 : a9ff > lda #$ff ;allow test to change + > +26db : 48 > pha ;use stack to load status +26dc : b513 > lda zp1,x ;load to memory +26de : 8d0302 > sta abst +26e1 : 28 > plp + +26e2 : 6e0302 ror abst + tst_abs rRORc,fRORc,$ff-fnzc +26e5 : 08 > php ;save flags +26e6 : ad0302 > lda abst +26e9 : dd2c02 > cmp rRORc,x ;test result + > trap_ne +26ec : d0fe > bne * ;failed not equal (non zero) + > +26ee : 68 > pla ;load status + > eor_flag $ff-fnzc +26ef : 497c > eor #$ff-fnzc|fao ;invert expected + > +26f1 : dd3c02 > cmp fRORc,x ;test flags + > trap_ne +26f4 : d0fe > bne * ;failed not equal (non zero) + > + +26f6 : ca dex +26f7 : 10e0 bpl trorc5 + next_test +26f9 : ad0002 > lda test_case ;previous test +26fc : c91f > cmp #test_num + > trap_ne ;test is out of sequence +26fe : d0fe > bne * ;failed not equal (non zero) + > +0020 = >test_num = test_num + 1 +2700 : a920 > lda #test_num ;*** next tests' number +2702 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; shifts - zp indexed +2705 : a203 ldx #3 +2707 : tasl6 + set_zx zp1,0 + > load_flag 0 +2707 : a900 > lda #0 ;allow test to change I + > +2709 : 48 > pha ;use stack to load status +270a : b513 > lda zp1,x ;load to indexed zeropage +270c : 950c > sta zpt,x +270e : 28 > plp + +270f : 160c asl zpt,x + tst_zx rASL,fASL,0 +2711 : 08 > php ;save flags +2712 : b50c > lda zpt,x +2714 : dd2002 > cmp rASL,x ;test result + > trap_ne +2717 : d0fe > bne * ;failed not equal (non zero) + > +2719 : 68 > pla ;load status + > eor_flag 0 +271a : 4930 > eor #0|fao ;invert expected flags + > +271c : dd3002 > cmp fASL,x ;test flags + > trap_ne +271f : d0fe > bne * ;failed not equal (non zero) + > + +2721 : ca dex +2722 : 10e3 bpl tasl6 +2724 : a203 ldx #3 +2726 : tasl7 + set_zx zp1,$ff + > load_flag $ff +2726 : a9ff > lda #$ff ;allow test to change + > +2728 : 48 > pha ;use stack to load status +2729 : b513 > lda zp1,x ;load to indexed zeropage +272b : 950c > sta zpt,x +272d : 28 > plp + +272e : 160c asl zpt,x + tst_zx rASL,fASL,$ff-fnzc +2730 : 08 > php ;save flags +2731 : b50c > lda zpt,x +2733 : dd2002 > cmp rASL,x ;test result + > trap_ne +2736 : d0fe > bne * ;failed not equal (non zero) + > +2738 : 68 > pla ;load status + > eor_flag $ff-fnzc +2739 : 497c > eor #$ff-fnzc|fao ;invert expected + > +273b : dd3002 > cmp fASL,x ;test flags + > trap_ne +273e : d0fe > bne * ;failed not equal (non zero) + > + +2740 : ca dex +2741 : 10e3 bpl tasl7 + +2743 : a203 ldx #3 +2745 : tlsr6 + set_zx zp1,0 + > load_flag 0 +2745 : a900 > lda #0 ;allow test to change I + > +2747 : 48 > pha ;use stack to load status +2748 : b513 > lda zp1,x ;load to indexed zeropage +274a : 950c > sta zpt,x +274c : 28 > plp + +274d : 560c lsr zpt,x + tst_zx rLSR,fLSR,0 +274f : 08 > php ;save flags +2750 : b50c > lda zpt,x +2752 : dd2802 > cmp rLSR,x ;test result + > trap_ne +2755 : d0fe > bne * ;failed not equal (non zero) + > +2757 : 68 > pla ;load status + > eor_flag 0 +2758 : 4930 > eor #0|fao ;invert expected flags + > +275a : dd3802 > cmp fLSR,x ;test flags + > trap_ne +275d : d0fe > bne * ;failed not equal (non zero) + > + +275f : ca dex +2760 : 10e3 bpl tlsr6 +2762 : a203 ldx #3 +2764 : tlsr7 + set_zx zp1,$ff + > load_flag $ff +2764 : a9ff > lda #$ff ;allow test to change + > +2766 : 48 > pha ;use stack to load status +2767 : b513 > lda zp1,x ;load to indexed zeropage +2769 : 950c > sta zpt,x +276b : 28 > plp + +276c : 560c lsr zpt,x + tst_zx rLSR,fLSR,$ff-fnzc +276e : 08 > php ;save flags +276f : b50c > lda zpt,x +2771 : dd2802 > cmp rLSR,x ;test result + > trap_ne +2774 : d0fe > bne * ;failed not equal (non zero) + > +2776 : 68 > pla ;load status + > eor_flag $ff-fnzc +2777 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2779 : dd3802 > cmp fLSR,x ;test flags + > trap_ne +277c : d0fe > bne * ;failed not equal (non zero) + > + +277e : ca dex +277f : 10e3 bpl tlsr7 + +2781 : a203 ldx #3 +2783 : trol6 + set_zx zp1,0 + > load_flag 0 +2783 : a900 > lda #0 ;allow test to change I + > +2785 : 48 > pha ;use stack to load status +2786 : b513 > lda zp1,x ;load to indexed zeropage +2788 : 950c > sta zpt,x +278a : 28 > plp + +278b : 360c rol zpt,x + tst_zx rROL,fROL,0 +278d : 08 > php ;save flags +278e : b50c > lda zpt,x +2790 : dd2002 > cmp rROL,x ;test result + > trap_ne +2793 : d0fe > bne * ;failed not equal (non zero) + > +2795 : 68 > pla ;load status + > eor_flag 0 +2796 : 4930 > eor #0|fao ;invert expected flags + > +2798 : dd3002 > cmp fROL,x ;test flags + > trap_ne +279b : d0fe > bne * ;failed not equal (non zero) + > + +279d : ca dex +279e : 10e3 bpl trol6 +27a0 : a203 ldx #3 +27a2 : trol7 + set_zx zp1,$ff-fc + > load_flag $ff-fc +27a2 : a9fe > lda #$ff-fc ;allow test to cha + > +27a4 : 48 > pha ;use stack to load status +27a5 : b513 > lda zp1,x ;load to indexed zeropage +27a7 : 950c > sta zpt,x +27a9 : 28 > plp + +27aa : 360c rol zpt,x + tst_zx rROL,fROL,$ff-fnzc +27ac : 08 > php ;save flags +27ad : b50c > lda zpt,x +27af : dd2002 > cmp rROL,x ;test result + > trap_ne +27b2 : d0fe > bne * ;failed not equal (non zero) + > +27b4 : 68 > pla ;load status + > eor_flag $ff-fnzc +27b5 : 497c > eor #$ff-fnzc|fao ;invert expected + > +27b7 : dd3002 > cmp fROL,x ;test flags + > trap_ne +27ba : d0fe > bne * ;failed not equal (non zero) + > + +27bc : ca dex +27bd : 10e3 bpl trol7 + +27bf : a203 ldx #3 +27c1 : trolc6 + set_zx zp1,fc + > load_flag fc +27c1 : a901 > lda #fc ;allow test to change + > +27c3 : 48 > pha ;use stack to load status +27c4 : b513 > lda zp1,x ;load to indexed zeropage +27c6 : 950c > sta zpt,x +27c8 : 28 > plp + +27c9 : 360c rol zpt,x + tst_zx rROLc,fROLc,0 +27cb : 08 > php ;save flags +27cc : b50c > lda zpt,x +27ce : dd2402 > cmp rROLc,x ;test result + > trap_ne +27d1 : d0fe > bne * ;failed not equal (non zero) + > +27d3 : 68 > pla ;load status + > eor_flag 0 +27d4 : 4930 > eor #0|fao ;invert expected flags + > +27d6 : dd3402 > cmp fROLc,x ;test flags + > trap_ne +27d9 : d0fe > bne * ;failed not equal (non zero) + > + +27db : ca dex +27dc : 10e3 bpl trolc6 +27de : a203 ldx #3 +27e0 : trolc7 + set_zx zp1,$ff + > load_flag $ff +27e0 : a9ff > lda #$ff ;allow test to change + > +27e2 : 48 > pha ;use stack to load status +27e3 : b513 > lda zp1,x ;load to indexed zeropage +27e5 : 950c > sta zpt,x +27e7 : 28 > plp + +27e8 : 360c rol zpt,x + tst_zx rROLc,fROLc,$ff-fnzc +27ea : 08 > php ;save flags +27eb : b50c > lda zpt,x +27ed : dd2402 > cmp rROLc,x ;test result + > trap_ne +27f0 : d0fe > bne * ;failed not equal (non zero) + > +27f2 : 68 > pla ;load status + > eor_flag $ff-fnzc +27f3 : 497c > eor #$ff-fnzc|fao ;invert expected + > +27f5 : dd3402 > cmp fROLc,x ;test flags + > trap_ne +27f8 : d0fe > bne * ;failed not equal (non zero) + > + +27fa : ca dex +27fb : 10e3 bpl trolc7 + +27fd : a203 ldx #3 +27ff : tror6 + set_zx zp1,0 + > load_flag 0 +27ff : a900 > lda #0 ;allow test to change I + > +2801 : 48 > pha ;use stack to load status +2802 : b513 > lda zp1,x ;load to indexed zeropage +2804 : 950c > sta zpt,x +2806 : 28 > plp + +2807 : 760c ror zpt,x + tst_zx rROR,fROR,0 +2809 : 08 > php ;save flags +280a : b50c > lda zpt,x +280c : dd2802 > cmp rROR,x ;test result + > trap_ne +280f : d0fe > bne * ;failed not equal (non zero) + > +2811 : 68 > pla ;load status + > eor_flag 0 +2812 : 4930 > eor #0|fao ;invert expected flags + > +2814 : dd3802 > cmp fROR,x ;test flags + > trap_ne +2817 : d0fe > bne * ;failed not equal (non zero) + > + +2819 : ca dex +281a : 10e3 bpl tror6 +281c : a203 ldx #3 +281e : tror7 + set_zx zp1,$ff-fc + > load_flag $ff-fc +281e : a9fe > lda #$ff-fc ;allow test to cha + > +2820 : 48 > pha ;use stack to load status +2821 : b513 > lda zp1,x ;load to indexed zeropage +2823 : 950c > sta zpt,x +2825 : 28 > plp + +2826 : 760c ror zpt,x + tst_zx rROR,fROR,$ff-fnzc +2828 : 08 > php ;save flags +2829 : b50c > lda zpt,x +282b : dd2802 > cmp rROR,x ;test result + > trap_ne +282e : d0fe > bne * ;failed not equal (non zero) + > +2830 : 68 > pla ;load status + > eor_flag $ff-fnzc +2831 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2833 : dd3802 > cmp fROR,x ;test flags + > trap_ne +2836 : d0fe > bne * ;failed not equal (non zero) + > + +2838 : ca dex +2839 : 10e3 bpl tror7 + +283b : a203 ldx #3 +283d : trorc6 + set_zx zp1,fc + > load_flag fc +283d : a901 > lda #fc ;allow test to change + > +283f : 48 > pha ;use stack to load status +2840 : b513 > lda zp1,x ;load to indexed zeropage +2842 : 950c > sta zpt,x +2844 : 28 > plp + +2845 : 760c ror zpt,x + tst_zx rRORc,fRORc,0 +2847 : 08 > php ;save flags +2848 : b50c > lda zpt,x +284a : dd2c02 > cmp rRORc,x ;test result + > trap_ne +284d : d0fe > bne * ;failed not equal (non zero) + > +284f : 68 > pla ;load status + > eor_flag 0 +2850 : 4930 > eor #0|fao ;invert expected flags + > +2852 : dd3c02 > cmp fRORc,x ;test flags + > trap_ne +2855 : d0fe > bne * ;failed not equal (non zero) + > + +2857 : ca dex +2858 : 10e3 bpl trorc6 +285a : a203 ldx #3 +285c : trorc7 + set_zx zp1,$ff + > load_flag $ff +285c : a9ff > lda #$ff ;allow test to change + > +285e : 48 > pha ;use stack to load status +285f : b513 > lda zp1,x ;load to indexed zeropage +2861 : 950c > sta zpt,x +2863 : 28 > plp + +2864 : 760c ror zpt,x + tst_zx rRORc,fRORc,$ff-fnzc +2866 : 08 > php ;save flags +2867 : b50c > lda zpt,x +2869 : dd2c02 > cmp rRORc,x ;test result + > trap_ne +286c : d0fe > bne * ;failed not equal (non zero) + > +286e : 68 > pla ;load status + > eor_flag $ff-fnzc +286f : 497c > eor #$ff-fnzc|fao ;invert expected + > +2871 : dd3c02 > cmp fRORc,x ;test flags + > trap_ne +2874 : d0fe > bne * ;failed not equal (non zero) + > + +2876 : ca dex +2877 : 10e3 bpl trorc7 + next_test +2879 : ad0002 > lda test_case ;previous test +287c : c920 > cmp #test_num + > trap_ne ;test is out of sequence +287e : d0fe > bne * ;failed not equal (non zero) + > +0021 = >test_num = test_num + 1 +2880 : a921 > lda #test_num ;*** next tests' number +2882 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; shifts - abs indexed +2885 : a203 ldx #3 +2887 : tasl8 + set_absx zp1,0 + > load_flag 0 +2887 : a900 > lda #0 ;allow test to change I + > +2889 : 48 > pha ;use stack to load status +288a : b513 > lda zp1,x ;load to indexed memory +288c : 9d0302 > sta abst,x +288f : 28 > plp + +2890 : 1e0302 asl abst,x + tst_absx rASL,fASL,0 +2893 : 08 > php ;save flags +2894 : bd0302 > lda abst,x +2897 : dd2002 > cmp rASL,x ;test result + > trap_ne +289a : d0fe > bne * ;failed not equal (non zero) + > +289c : 68 > pla ;load status + > eor_flag 0 +289d : 4930 > eor #0|fao ;invert expected flags + > +289f : dd3002 > cmp fASL,x ;test flags + > trap_ne +28a2 : d0fe > bne * ;failed not equal (non zero) + > + +28a4 : ca dex +28a5 : 10e0 bpl tasl8 +28a7 : a203 ldx #3 +28a9 : tasl9 + set_absx zp1,$ff + > load_flag $ff +28a9 : a9ff > lda #$ff ;allow test to change + > +28ab : 48 > pha ;use stack to load status +28ac : b513 > lda zp1,x ;load to indexed memory +28ae : 9d0302 > sta abst,x +28b1 : 28 > plp + +28b2 : 1e0302 asl abst,x + tst_absx rASL,fASL,$ff-fnzc +28b5 : 08 > php ;save flags +28b6 : bd0302 > lda abst,x +28b9 : dd2002 > cmp rASL,x ;test result + > trap_ne +28bc : d0fe > bne * ;failed not equal (non zero) + > +28be : 68 > pla ;load status + > eor_flag $ff-fnzc +28bf : 497c > eor #$ff-fnzc|fao ;invert expected + > +28c1 : dd3002 > cmp fASL,x ;test flags + > trap_ne +28c4 : d0fe > bne * ;failed not equal (non zero) + > + +28c6 : ca dex +28c7 : 10e0 bpl tasl9 + +28c9 : a203 ldx #3 +28cb : tlsr8 + set_absx zp1,0 + > load_flag 0 +28cb : a900 > lda #0 ;allow test to change I + > +28cd : 48 > pha ;use stack to load status +28ce : b513 > lda zp1,x ;load to indexed memory +28d0 : 9d0302 > sta abst,x +28d3 : 28 > plp + +28d4 : 5e0302 lsr abst,x + tst_absx rLSR,fLSR,0 +28d7 : 08 > php ;save flags +28d8 : bd0302 > lda abst,x +28db : dd2802 > cmp rLSR,x ;test result + > trap_ne +28de : d0fe > bne * ;failed not equal (non zero) + > +28e0 : 68 > pla ;load status + > eor_flag 0 +28e1 : 4930 > eor #0|fao ;invert expected flags + > +28e3 : dd3802 > cmp fLSR,x ;test flags + > trap_ne +28e6 : d0fe > bne * ;failed not equal (non zero) + > + +28e8 : ca dex +28e9 : 10e0 bpl tlsr8 +28eb : a203 ldx #3 +28ed : tlsr9 + set_absx zp1,$ff + > load_flag $ff +28ed : a9ff > lda #$ff ;allow test to change + > +28ef : 48 > pha ;use stack to load status +28f0 : b513 > lda zp1,x ;load to indexed memory +28f2 : 9d0302 > sta abst,x +28f5 : 28 > plp + +28f6 : 5e0302 lsr abst,x + tst_absx rLSR,fLSR,$ff-fnzc +28f9 : 08 > php ;save flags +28fa : bd0302 > lda abst,x +28fd : dd2802 > cmp rLSR,x ;test result + > trap_ne +2900 : d0fe > bne * ;failed not equal (non zero) + > +2902 : 68 > pla ;load status + > eor_flag $ff-fnzc +2903 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2905 : dd3802 > cmp fLSR,x ;test flags + > trap_ne +2908 : d0fe > bne * ;failed not equal (non zero) + > + +290a : ca dex +290b : 10e0 bpl tlsr9 + +290d : a203 ldx #3 +290f : trol8 + set_absx zp1,0 + > load_flag 0 +290f : a900 > lda #0 ;allow test to change I + > +2911 : 48 > pha ;use stack to load status +2912 : b513 > lda zp1,x ;load to indexed memory +2914 : 9d0302 > sta abst,x +2917 : 28 > plp + +2918 : 3e0302 rol abst,x + tst_absx rROL,fROL,0 +291b : 08 > php ;save flags +291c : bd0302 > lda abst,x +291f : dd2002 > cmp rROL,x ;test result + > trap_ne +2922 : d0fe > bne * ;failed not equal (non zero) + > +2924 : 68 > pla ;load status + > eor_flag 0 +2925 : 4930 > eor #0|fao ;invert expected flags + > +2927 : dd3002 > cmp fROL,x ;test flags + > trap_ne +292a : d0fe > bne * ;failed not equal (non zero) + > + +292c : ca dex +292d : 10e0 bpl trol8 +292f : a203 ldx #3 +2931 : trol9 + set_absx zp1,$ff-fc + > load_flag $ff-fc +2931 : a9fe > lda #$ff-fc ;allow test to cha + > +2933 : 48 > pha ;use stack to load status +2934 : b513 > lda zp1,x ;load to indexed memory +2936 : 9d0302 > sta abst,x +2939 : 28 > plp + +293a : 3e0302 rol abst,x + tst_absx rROL,fROL,$ff-fnzc +293d : 08 > php ;save flags +293e : bd0302 > lda abst,x +2941 : dd2002 > cmp rROL,x ;test result + > trap_ne +2944 : d0fe > bne * ;failed not equal (non zero) + > +2946 : 68 > pla ;load status + > eor_flag $ff-fnzc +2947 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2949 : dd3002 > cmp fROL,x ;test flags + > trap_ne +294c : d0fe > bne * ;failed not equal (non zero) + > + +294e : ca dex +294f : 10e0 bpl trol9 + +2951 : a203 ldx #3 +2953 : trolc8 + set_absx zp1,fc + > load_flag fc +2953 : a901 > lda #fc ;allow test to change + > +2955 : 48 > pha ;use stack to load status +2956 : b513 > lda zp1,x ;load to indexed memory +2958 : 9d0302 > sta abst,x +295b : 28 > plp + +295c : 3e0302 rol abst,x + tst_absx rROLc,fROLc,0 +295f : 08 > php ;save flags +2960 : bd0302 > lda abst,x +2963 : dd2402 > cmp rROLc,x ;test result + > trap_ne +2966 : d0fe > bne * ;failed not equal (non zero) + > +2968 : 68 > pla ;load status + > eor_flag 0 +2969 : 4930 > eor #0|fao ;invert expected flags + > +296b : dd3402 > cmp fROLc,x ;test flags + > trap_ne +296e : d0fe > bne * ;failed not equal (non zero) + > + +2970 : ca dex +2971 : 10e0 bpl trolc8 +2973 : a203 ldx #3 +2975 : trolc9 + set_absx zp1,$ff + > load_flag $ff +2975 : a9ff > lda #$ff ;allow test to change + > +2977 : 48 > pha ;use stack to load status +2978 : b513 > lda zp1,x ;load to indexed memory +297a : 9d0302 > sta abst,x +297d : 28 > plp + +297e : 3e0302 rol abst,x + tst_absx rROLc,fROLc,$ff-fnzc +2981 : 08 > php ;save flags +2982 : bd0302 > lda abst,x +2985 : dd2402 > cmp rROLc,x ;test result + > trap_ne +2988 : d0fe > bne * ;failed not equal (non zero) + > +298a : 68 > pla ;load status + > eor_flag $ff-fnzc +298b : 497c > eor #$ff-fnzc|fao ;invert expected + > +298d : dd3402 > cmp fROLc,x ;test flags + > trap_ne +2990 : d0fe > bne * ;failed not equal (non zero) + > + +2992 : ca dex +2993 : 10e0 bpl trolc9 + +2995 : a203 ldx #3 +2997 : tror8 + set_absx zp1,0 + > load_flag 0 +2997 : a900 > lda #0 ;allow test to change I + > +2999 : 48 > pha ;use stack to load status +299a : b513 > lda zp1,x ;load to indexed memory +299c : 9d0302 > sta abst,x +299f : 28 > plp + +29a0 : 7e0302 ror abst,x + tst_absx rROR,fROR,0 +29a3 : 08 > php ;save flags +29a4 : bd0302 > lda abst,x +29a7 : dd2802 > cmp rROR,x ;test result + > trap_ne +29aa : d0fe > bne * ;failed not equal (non zero) + > +29ac : 68 > pla ;load status + > eor_flag 0 +29ad : 4930 > eor #0|fao ;invert expected flags + > +29af : dd3802 > cmp fROR,x ;test flags + > trap_ne +29b2 : d0fe > bne * ;failed not equal (non zero) + > + +29b4 : ca dex +29b5 : 10e0 bpl tror8 +29b7 : a203 ldx #3 +29b9 : tror9 + set_absx zp1,$ff-fc + > load_flag $ff-fc +29b9 : a9fe > lda #$ff-fc ;allow test to cha + > +29bb : 48 > pha ;use stack to load status +29bc : b513 > lda zp1,x ;load to indexed memory +29be : 9d0302 > sta abst,x +29c1 : 28 > plp + +29c2 : 7e0302 ror abst,x + tst_absx rROR,fROR,$ff-fnzc +29c5 : 08 > php ;save flags +29c6 : bd0302 > lda abst,x +29c9 : dd2802 > cmp rROR,x ;test result + > trap_ne +29cc : d0fe > bne * ;failed not equal (non zero) + > +29ce : 68 > pla ;load status + > eor_flag $ff-fnzc +29cf : 497c > eor #$ff-fnzc|fao ;invert expected + > +29d1 : dd3802 > cmp fROR,x ;test flags + > trap_ne +29d4 : d0fe > bne * ;failed not equal (non zero) + > + +29d6 : ca dex +29d7 : 10e0 bpl tror9 + +29d9 : a203 ldx #3 +29db : trorc8 + set_absx zp1,fc + > load_flag fc +29db : a901 > lda #fc ;allow test to change + > +29dd : 48 > pha ;use stack to load status +29de : b513 > lda zp1,x ;load to indexed memory +29e0 : 9d0302 > sta abst,x +29e3 : 28 > plp + +29e4 : 7e0302 ror abst,x + tst_absx rRORc,fRORc,0 +29e7 : 08 > php ;save flags +29e8 : bd0302 > lda abst,x +29eb : dd2c02 > cmp rRORc,x ;test result + > trap_ne +29ee : d0fe > bne * ;failed not equal (non zero) + > +29f0 : 68 > pla ;load status + > eor_flag 0 +29f1 : 4930 > eor #0|fao ;invert expected flags + > +29f3 : dd3c02 > cmp fRORc,x ;test flags + > trap_ne +29f6 : d0fe > bne * ;failed not equal (non zero) + > + +29f8 : ca dex +29f9 : 10e0 bpl trorc8 +29fb : a203 ldx #3 +29fd : trorc9 + set_absx zp1,$ff + > load_flag $ff +29fd : a9ff > lda #$ff ;allow test to change + > +29ff : 48 > pha ;use stack to load status +2a00 : b513 > lda zp1,x ;load to indexed memory +2a02 : 9d0302 > sta abst,x +2a05 : 28 > plp + +2a06 : 7e0302 ror abst,x + tst_absx rRORc,fRORc,$ff-fnzc +2a09 : 08 > php ;save flags +2a0a : bd0302 > lda abst,x +2a0d : dd2c02 > cmp rRORc,x ;test result + > trap_ne +2a10 : d0fe > bne * ;failed not equal (non zero) + > +2a12 : 68 > pla ;load status + > eor_flag $ff-fnzc +2a13 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2a15 : dd3c02 > cmp fRORc,x ;test flags + > trap_ne +2a18 : d0fe > bne * ;failed not equal (non zero) + > + +2a1a : ca dex +2a1b : 10e0 bpl trorc9 + next_test +2a1d : ad0002 > lda test_case ;previous test +2a20 : c921 > cmp #test_num + > trap_ne ;test is out of sequence +2a22 : d0fe > bne * ;failed not equal (non zero) + > +0022 = >test_num = test_num + 1 +2a24 : a922 > lda #test_num ;*** next tests' number +2a26 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; testing memory increment/decrement - INC DEC all add + ; zeropage +2a29 : a200 ldx #0 +2a2b : a97e lda #$7e +2a2d : 850c sta zpt +2a2f : tinc + set_stat 0 + > load_flag 0 +2a2f : a900 > lda #0 ;allow test to change I + > +2a31 : 48 > pha ;use stack to load status +2a32 : 28 > plp + +2a33 : e60c inc zpt + tst_z rINC,fINC,0 +2a35 : 08 > php ;save flags +2a36 : a50c > lda zpt +2a38 : dd4002 > cmp rINC,x ;test result + > trap_ne +2a3b : d0fe > bne * ;failed not equal (non zero) + > +2a3d : 68 > pla ;load status + > eor_flag 0 +2a3e : 4930 > eor #0|fao ;invert expected flags + > +2a40 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2a43 : d0fe > bne * ;failed not equal (non zero) + > + +2a45 : e8 inx +2a46 : e002 cpx #2 +2a48 : d004 bne tinc1 +2a4a : a9fe lda #$fe +2a4c : 850c sta zpt +2a4e : e005 tinc1 cpx #5 +2a50 : d0dd bne tinc +2a52 : ca dex +2a53 : e60c inc zpt +2a55 : tdec + set_stat 0 + > load_flag 0 +2a55 : a900 > lda #0 ;allow test to change I + > +2a57 : 48 > pha ;use stack to load status +2a58 : 28 > plp + +2a59 : c60c dec zpt + tst_z rINC,fINC,0 +2a5b : 08 > php ;save flags +2a5c : a50c > lda zpt +2a5e : dd4002 > cmp rINC,x ;test result + > trap_ne +2a61 : d0fe > bne * ;failed not equal (non zero) + > +2a63 : 68 > pla ;load status + > eor_flag 0 +2a64 : 4930 > eor #0|fao ;invert expected flags + > +2a66 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2a69 : d0fe > bne * ;failed not equal (non zero) + > + +2a6b : ca dex +2a6c : 300a bmi tdec1 +2a6e : e001 cpx #1 +2a70 : d0e3 bne tdec +2a72 : a981 lda #$81 +2a74 : 850c sta zpt +2a76 : d0dd bne tdec +2a78 : tdec1 +2a78 : a200 ldx #0 +2a7a : a97e lda #$7e +2a7c : 850c sta zpt +2a7e : tinc10 + set_stat $ff + > load_flag $ff +2a7e : a9ff > lda #$ff ;allow test to change + > +2a80 : 48 > pha ;use stack to load status +2a81 : 28 > plp + +2a82 : e60c inc zpt + tst_z rINC,fINC,$ff-fnz +2a84 : 08 > php ;save flags +2a85 : a50c > lda zpt +2a87 : dd4002 > cmp rINC,x ;test result + > trap_ne +2a8a : d0fe > bne * ;failed not equal (non zero) + > +2a8c : 68 > pla ;load status + > eor_flag $ff-fnz +2a8d : 497d > eor #$ff-fnz|fao ;invert expected + > +2a8f : dd4502 > cmp fINC,x ;test flags + > trap_ne +2a92 : d0fe > bne * ;failed not equal (non zero) + > + +2a94 : e8 inx +2a95 : e002 cpx #2 +2a97 : d004 bne tinc11 +2a99 : a9fe lda #$fe +2a9b : 850c sta zpt +2a9d : e005 tinc11 cpx #5 +2a9f : d0dd bne tinc10 +2aa1 : ca dex +2aa2 : e60c inc zpt +2aa4 : tdec10 + set_stat $ff + > load_flag $ff +2aa4 : a9ff > lda #$ff ;allow test to change + > +2aa6 : 48 > pha ;use stack to load status +2aa7 : 28 > plp + +2aa8 : c60c dec zpt + tst_z rINC,fINC,$ff-fnz +2aaa : 08 > php ;save flags +2aab : a50c > lda zpt +2aad : dd4002 > cmp rINC,x ;test result + > trap_ne +2ab0 : d0fe > bne * ;failed not equal (non zero) + > +2ab2 : 68 > pla ;load status + > eor_flag $ff-fnz +2ab3 : 497d > eor #$ff-fnz|fao ;invert expected + > +2ab5 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2ab8 : d0fe > bne * ;failed not equal (non zero) + > + +2aba : ca dex +2abb : 300a bmi tdec11 +2abd : e001 cpx #1 +2abf : d0e3 bne tdec10 +2ac1 : a981 lda #$81 +2ac3 : 850c sta zpt +2ac5 : d0dd bne tdec10 +2ac7 : tdec11 + next_test +2ac7 : ad0002 > lda test_case ;previous test +2aca : c922 > cmp #test_num + > trap_ne ;test is out of sequence +2acc : d0fe > bne * ;failed not equal (non zero) + > +0023 = >test_num = test_num + 1 +2ace : a923 > lda #test_num ;*** next tests' number +2ad0 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; absolute memory +2ad3 : a200 ldx #0 +2ad5 : a97e lda #$7e +2ad7 : 8d0302 sta abst +2ada : tinc2 + set_stat 0 + > load_flag 0 +2ada : a900 > lda #0 ;allow test to change I + > +2adc : 48 > pha ;use stack to load status +2add : 28 > plp + +2ade : ee0302 inc abst + tst_abs rINC,fINC,0 +2ae1 : 08 > php ;save flags +2ae2 : ad0302 > lda abst +2ae5 : dd4002 > cmp rINC,x ;test result + > trap_ne +2ae8 : d0fe > bne * ;failed not equal (non zero) + > +2aea : 68 > pla ;load status + > eor_flag 0 +2aeb : 4930 > eor #0|fao ;invert expected flags + > +2aed : dd4502 > cmp fINC,x ;test flags + > trap_ne +2af0 : d0fe > bne * ;failed not equal (non zero) + > + +2af2 : e8 inx +2af3 : e002 cpx #2 +2af5 : d005 bne tinc3 +2af7 : a9fe lda #$fe +2af9 : 8d0302 sta abst +2afc : e005 tinc3 cpx #5 +2afe : d0da bne tinc2 +2b00 : ca dex +2b01 : ee0302 inc abst +2b04 : tdec2 + set_stat 0 + > load_flag 0 +2b04 : a900 > lda #0 ;allow test to change I + > +2b06 : 48 > pha ;use stack to load status +2b07 : 28 > plp + +2b08 : ce0302 dec abst + tst_abs rINC,fINC,0 +2b0b : 08 > php ;save flags +2b0c : ad0302 > lda abst +2b0f : dd4002 > cmp rINC,x ;test result + > trap_ne +2b12 : d0fe > bne * ;failed not equal (non zero) + > +2b14 : 68 > pla ;load status + > eor_flag 0 +2b15 : 4930 > eor #0|fao ;invert expected flags + > +2b17 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2b1a : d0fe > bne * ;failed not equal (non zero) + > + +2b1c : ca dex +2b1d : 300b bmi tdec3 +2b1f : e001 cpx #1 +2b21 : d0e1 bne tdec2 +2b23 : a981 lda #$81 +2b25 : 8d0302 sta abst +2b28 : d0da bne tdec2 +2b2a : tdec3 +2b2a : a200 ldx #0 +2b2c : a97e lda #$7e +2b2e : 8d0302 sta abst +2b31 : tinc12 + set_stat $ff + > load_flag $ff +2b31 : a9ff > lda #$ff ;allow test to change + > +2b33 : 48 > pha ;use stack to load status +2b34 : 28 > plp + +2b35 : ee0302 inc abst + tst_abs rINC,fINC,$ff-fnz +2b38 : 08 > php ;save flags +2b39 : ad0302 > lda abst +2b3c : dd4002 > cmp rINC,x ;test result + > trap_ne +2b3f : d0fe > bne * ;failed not equal (non zero) + > +2b41 : 68 > pla ;load status + > eor_flag $ff-fnz +2b42 : 497d > eor #$ff-fnz|fao ;invert expected + > +2b44 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2b47 : d0fe > bne * ;failed not equal (non zero) + > + +2b49 : e8 inx +2b4a : e002 cpx #2 +2b4c : d005 bne tinc13 +2b4e : a9fe lda #$fe +2b50 : 8d0302 sta abst +2b53 : e005 tinc13 cpx #5 +2b55 : d0da bne tinc12 +2b57 : ca dex +2b58 : ee0302 inc abst +2b5b : tdec12 + set_stat $ff + > load_flag $ff +2b5b : a9ff > lda #$ff ;allow test to change + > +2b5d : 48 > pha ;use stack to load status +2b5e : 28 > plp + +2b5f : ce0302 dec abst + tst_abs rINC,fINC,$ff-fnz +2b62 : 08 > php ;save flags +2b63 : ad0302 > lda abst +2b66 : dd4002 > cmp rINC,x ;test result + > trap_ne +2b69 : d0fe > bne * ;failed not equal (non zero) + > +2b6b : 68 > pla ;load status + > eor_flag $ff-fnz +2b6c : 497d > eor #$ff-fnz|fao ;invert expected + > +2b6e : dd4502 > cmp fINC,x ;test flags + > trap_ne +2b71 : d0fe > bne * ;failed not equal (non zero) + > + +2b73 : ca dex +2b74 : 300b bmi tdec13 +2b76 : e001 cpx #1 +2b78 : d0e1 bne tdec12 +2b7a : a981 lda #$81 +2b7c : 8d0302 sta abst +2b7f : d0da bne tdec12 +2b81 : tdec13 + next_test +2b81 : ad0002 > lda test_case ;previous test +2b84 : c923 > cmp #test_num + > trap_ne ;test is out of sequence +2b86 : d0fe > bne * ;failed not equal (non zero) + > +0024 = >test_num = test_num + 1 +2b88 : a924 > lda #test_num ;*** next tests' number +2b8a : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; zeropage indexed +2b8d : a200 ldx #0 +2b8f : a97e lda #$7e +2b91 : 950c tinc4 sta zpt,x + set_stat 0 + > load_flag 0 +2b93 : a900 > lda #0 ;allow test to change I + > +2b95 : 48 > pha ;use stack to load status +2b96 : 28 > plp + +2b97 : f60c inc zpt,x + tst_zx rINC,fINC,0 +2b99 : 08 > php ;save flags +2b9a : b50c > lda zpt,x +2b9c : dd4002 > cmp rINC,x ;test result + > trap_ne +2b9f : d0fe > bne * ;failed not equal (non zero) + > +2ba1 : 68 > pla ;load status + > eor_flag 0 +2ba2 : 4930 > eor #0|fao ;invert expected flags + > +2ba4 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2ba7 : d0fe > bne * ;failed not equal (non zero) + > + +2ba9 : b50c lda zpt,x +2bab : e8 inx +2bac : e002 cpx #2 +2bae : d002 bne tinc5 +2bb0 : a9fe lda #$fe +2bb2 : e005 tinc5 cpx #5 +2bb4 : d0db bne tinc4 +2bb6 : ca dex +2bb7 : a902 lda #2 +2bb9 : 950c tdec4 sta zpt,x + set_stat 0 + > load_flag 0 +2bbb : a900 > lda #0 ;allow test to change I + > +2bbd : 48 > pha ;use stack to load status +2bbe : 28 > plp + +2bbf : d60c dec zpt,x + tst_zx rINC,fINC,0 +2bc1 : 08 > php ;save flags +2bc2 : b50c > lda zpt,x +2bc4 : dd4002 > cmp rINC,x ;test result + > trap_ne +2bc7 : d0fe > bne * ;failed not equal (non zero) + > +2bc9 : 68 > pla ;load status + > eor_flag 0 +2bca : 4930 > eor #0|fao ;invert expected flags + > +2bcc : dd4502 > cmp fINC,x ;test flags + > trap_ne +2bcf : d0fe > bne * ;failed not equal (non zero) + > + +2bd1 : b50c lda zpt,x +2bd3 : ca dex +2bd4 : 3008 bmi tdec5 +2bd6 : e001 cpx #1 +2bd8 : d0df bne tdec4 +2bda : a981 lda #$81 +2bdc : d0db bne tdec4 +2bde : tdec5 +2bde : a200 ldx #0 +2be0 : a97e lda #$7e +2be2 : 950c tinc14 sta zpt,x + set_stat $ff + > load_flag $ff +2be4 : a9ff > lda #$ff ;allow test to change + > +2be6 : 48 > pha ;use stack to load status +2be7 : 28 > plp + +2be8 : f60c inc zpt,x + tst_zx rINC,fINC,$ff-fnz +2bea : 08 > php ;save flags +2beb : b50c > lda zpt,x +2bed : dd4002 > cmp rINC,x ;test result + > trap_ne +2bf0 : d0fe > bne * ;failed not equal (non zero) + > +2bf2 : 68 > pla ;load status + > eor_flag $ff-fnz +2bf3 : 497d > eor #$ff-fnz|fao ;invert expected + > +2bf5 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2bf8 : d0fe > bne * ;failed not equal (non zero) + > + +2bfa : b50c lda zpt,x +2bfc : e8 inx +2bfd : e002 cpx #2 +2bff : d002 bne tinc15 +2c01 : a9fe lda #$fe +2c03 : e005 tinc15 cpx #5 +2c05 : d0db bne tinc14 +2c07 : ca dex +2c08 : a902 lda #2 +2c0a : 950c tdec14 sta zpt,x + set_stat $ff + > load_flag $ff +2c0c : a9ff > lda #$ff ;allow test to change + > +2c0e : 48 > pha ;use stack to load status +2c0f : 28 > plp + +2c10 : d60c dec zpt,x + tst_zx rINC,fINC,$ff-fnz +2c12 : 08 > php ;save flags +2c13 : b50c > lda zpt,x +2c15 : dd4002 > cmp rINC,x ;test result + > trap_ne +2c18 : d0fe > bne * ;failed not equal (non zero) + > +2c1a : 68 > pla ;load status + > eor_flag $ff-fnz +2c1b : 497d > eor #$ff-fnz|fao ;invert expected + > +2c1d : dd4502 > cmp fINC,x ;test flags + > trap_ne +2c20 : d0fe > bne * ;failed not equal (non zero) + > + +2c22 : b50c lda zpt,x +2c24 : ca dex +2c25 : 3008 bmi tdec15 +2c27 : e001 cpx #1 +2c29 : d0df bne tdec14 +2c2b : a981 lda #$81 +2c2d : d0db bne tdec14 +2c2f : tdec15 + next_test +2c2f : ad0002 > lda test_case ;previous test +2c32 : c924 > cmp #test_num + > trap_ne ;test is out of sequence +2c34 : d0fe > bne * ;failed not equal (non zero) + > +0025 = >test_num = test_num + 1 +2c36 : a925 > lda #test_num ;*** next tests' number +2c38 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; memory indexed +2c3b : a200 ldx #0 +2c3d : a97e lda #$7e +2c3f : 9d0302 tinc6 sta abst,x + set_stat 0 + > load_flag 0 +2c42 : a900 > lda #0 ;allow test to change I + > +2c44 : 48 > pha ;use stack to load status +2c45 : 28 > plp + +2c46 : fe0302 inc abst,x + tst_absx rINC,fINC,0 +2c49 : 08 > php ;save flags +2c4a : bd0302 > lda abst,x +2c4d : dd4002 > cmp rINC,x ;test result + > trap_ne +2c50 : d0fe > bne * ;failed not equal (non zero) + > +2c52 : 68 > pla ;load status + > eor_flag 0 +2c53 : 4930 > eor #0|fao ;invert expected flags + > +2c55 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2c58 : d0fe > bne * ;failed not equal (non zero) + > + +2c5a : bd0302 lda abst,x +2c5d : e8 inx +2c5e : e002 cpx #2 +2c60 : d002 bne tinc7 +2c62 : a9fe lda #$fe +2c64 : e005 tinc7 cpx #5 +2c66 : d0d7 bne tinc6 +2c68 : ca dex +2c69 : a902 lda #2 +2c6b : 9d0302 tdec6 sta abst,x + set_stat 0 + > load_flag 0 +2c6e : a900 > lda #0 ;allow test to change I + > +2c70 : 48 > pha ;use stack to load status +2c71 : 28 > plp + +2c72 : de0302 dec abst,x + tst_absx rINC,fINC,0 +2c75 : 08 > php ;save flags +2c76 : bd0302 > lda abst,x +2c79 : dd4002 > cmp rINC,x ;test result + > trap_ne +2c7c : d0fe > bne * ;failed not equal (non zero) + > +2c7e : 68 > pla ;load status + > eor_flag 0 +2c7f : 4930 > eor #0|fao ;invert expected flags + > +2c81 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2c84 : d0fe > bne * ;failed not equal (non zero) + > + +2c86 : bd0302 lda abst,x +2c89 : ca dex +2c8a : 3008 bmi tdec7 +2c8c : e001 cpx #1 +2c8e : d0db bne tdec6 +2c90 : a981 lda #$81 +2c92 : d0d7 bne tdec6 +2c94 : tdec7 +2c94 : a200 ldx #0 +2c96 : a97e lda #$7e +2c98 : 9d0302 tinc16 sta abst,x + set_stat $ff + > load_flag $ff +2c9b : a9ff > lda #$ff ;allow test to change + > +2c9d : 48 > pha ;use stack to load status +2c9e : 28 > plp + +2c9f : fe0302 inc abst,x + tst_absx rINC,fINC,$ff-fnz +2ca2 : 08 > php ;save flags +2ca3 : bd0302 > lda abst,x +2ca6 : dd4002 > cmp rINC,x ;test result + > trap_ne +2ca9 : d0fe > bne * ;failed not equal (non zero) + > +2cab : 68 > pla ;load status + > eor_flag $ff-fnz +2cac : 497d > eor #$ff-fnz|fao ;invert expected + > +2cae : dd4502 > cmp fINC,x ;test flags + > trap_ne +2cb1 : d0fe > bne * ;failed not equal (non zero) + > + +2cb3 : bd0302 lda abst,x +2cb6 : e8 inx +2cb7 : e002 cpx #2 +2cb9 : d002 bne tinc17 +2cbb : a9fe lda #$fe +2cbd : e005 tinc17 cpx #5 +2cbf : d0d7 bne tinc16 +2cc1 : ca dex +2cc2 : a902 lda #2 +2cc4 : 9d0302 tdec16 sta abst,x + set_stat $ff + > load_flag $ff +2cc7 : a9ff > lda #$ff ;allow test to change + > +2cc9 : 48 > pha ;use stack to load status +2cca : 28 > plp + +2ccb : de0302 dec abst,x + tst_absx rINC,fINC,$ff-fnz +2cce : 08 > php ;save flags +2ccf : bd0302 > lda abst,x +2cd2 : dd4002 > cmp rINC,x ;test result + > trap_ne +2cd5 : d0fe > bne * ;failed not equal (non zero) + > +2cd7 : 68 > pla ;load status + > eor_flag $ff-fnz +2cd8 : 497d > eor #$ff-fnz|fao ;invert expected + > +2cda : dd4502 > cmp fINC,x ;test flags + > trap_ne +2cdd : d0fe > bne * ;failed not equal (non zero) + > + +2cdf : bd0302 lda abst,x +2ce2 : ca dex +2ce3 : 3008 bmi tdec17 +2ce5 : e001 cpx #1 +2ce7 : d0db bne tdec16 +2ce9 : a981 lda #$81 +2ceb : d0d7 bne tdec16 +2ced : tdec17 + next_test +2ced : ad0002 > lda test_case ;previous test +2cf0 : c925 > cmp #test_num + > trap_ne ;test is out of sequence +2cf2 : d0fe > bne * ;failed not equal (non zero) + > +0026 = >test_num = test_num + 1 +2cf4 : a926 > lda #test_num ;*** next tests' number +2cf6 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; testing logical instructions - AND EOR ORA all addre + ; AND +2cf9 : a203 ldx #3 ;immediate +2cfb : b51c tand lda zpAN,x +2cfd : 8d0902 sta ex_andi+1 ;set AND # operand + set_ax absANa,0 + > load_flag 0 +2d00 : a900 > lda #0 ;allow test to change I + > +2d02 : 48 > pha ;use stack to load status +2d03 : bd5a02 > lda absANa,x ;precharge accu +2d06 : 28 > plp + +2d07 : 200802 jsr ex_andi ;execute AND # in RAM + tst_ax absrlo,absflo,0 +2d0a : 08 > php ;save flags +2d0b : dd6202 > cmp absrlo,x ;test result + > trap_ne +2d0e : d0fe > bne * ;failed not equal (non zero) + > +2d10 : 68 > pla ;load status + > eor_flag 0 +2d11 : 4930 > eor #0|fao ;invert expected flags + > +2d13 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2d16 : d0fe > bne * ;failed not equal (non zero) + > + +2d18 : ca dex +2d19 : 10e0 bpl tand +2d1b : a203 ldx #3 +2d1d : b51c tand1 lda zpAN,x +2d1f : 8d0902 sta ex_andi+1 ;set AND # operand + set_ax absANa,$ff + > load_flag $ff +2d22 : a9ff > lda #$ff ;allow test to change + > +2d24 : 48 > pha ;use stack to load status +2d25 : bd5a02 > lda absANa,x ;precharge accu +2d28 : 28 > plp + +2d29 : 200802 jsr ex_andi ;execute AND # in RAM + tst_ax absrlo,absflo,$ff-fnz +2d2c : 08 > php ;save flags +2d2d : dd6202 > cmp absrlo,x ;test result + > trap_ne +2d30 : d0fe > bne * ;failed not equal (non zero) + > +2d32 : 68 > pla ;load status + > eor_flag $ff-fnz +2d33 : 497d > eor #$ff-fnz|fao ;invert expected + > +2d35 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2d38 : d0fe > bne * ;failed not equal (non zero) + > + +2d3a : ca dex +2d3b : 10e0 bpl tand1 + +2d3d : a203 ldx #3 ;zp +2d3f : b51c tand2 lda zpAN,x +2d41 : 850c sta zpt + set_ax absANa,0 + > load_flag 0 +2d43 : a900 > lda #0 ;allow test to change I + > +2d45 : 48 > pha ;use stack to load status +2d46 : bd5a02 > lda absANa,x ;precharge accu +2d49 : 28 > plp + +2d4a : 250c and zpt + tst_ax absrlo,absflo,0 +2d4c : 08 > php ;save flags +2d4d : dd6202 > cmp absrlo,x ;test result + > trap_ne +2d50 : d0fe > bne * ;failed not equal (non zero) + > +2d52 : 68 > pla ;load status + > eor_flag 0 +2d53 : 4930 > eor #0|fao ;invert expected flags + > +2d55 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2d58 : d0fe > bne * ;failed not equal (non zero) + > + +2d5a : ca dex +2d5b : 10e2 bpl tand2 +2d5d : a203 ldx #3 +2d5f : b51c tand3 lda zpAN,x +2d61 : 850c sta zpt + set_ax absANa,$ff + > load_flag $ff +2d63 : a9ff > lda #$ff ;allow test to change + > +2d65 : 48 > pha ;use stack to load status +2d66 : bd5a02 > lda absANa,x ;precharge accu +2d69 : 28 > plp + +2d6a : 250c and zpt + tst_ax absrlo,absflo,$ff-fnz +2d6c : 08 > php ;save flags +2d6d : dd6202 > cmp absrlo,x ;test result + > trap_ne +2d70 : d0fe > bne * ;failed not equal (non zero) + > +2d72 : 68 > pla ;load status + > eor_flag $ff-fnz +2d73 : 497d > eor #$ff-fnz|fao ;invert expected + > +2d75 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2d78 : d0fe > bne * ;failed not equal (non zero) + > + +2d7a : ca dex +2d7b : 10e2 bpl tand3 + +2d7d : a203 ldx #3 ;abs +2d7f : b51c tand4 lda zpAN,x +2d81 : 8d0302 sta abst + set_ax absANa,0 + > load_flag 0 +2d84 : a900 > lda #0 ;allow test to change I + > +2d86 : 48 > pha ;use stack to load status +2d87 : bd5a02 > lda absANa,x ;precharge accu +2d8a : 28 > plp + +2d8b : 2d0302 and abst + tst_ax absrlo,absflo,0 +2d8e : 08 > php ;save flags +2d8f : dd6202 > cmp absrlo,x ;test result + > trap_ne +2d92 : d0fe > bne * ;failed not equal (non zero) + > +2d94 : 68 > pla ;load status + > eor_flag 0 +2d95 : 4930 > eor #0|fao ;invert expected flags + > +2d97 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2d9a : d0fe > bne * ;failed not equal (non zero) + > + +2d9c : ca dex +2d9d : 10e0 bpl tand4 +2d9f : a203 ldx #3 +2da1 : b51c tand5 lda zpAN,x +2da3 : 8d0302 sta abst + set_ax absANa,$ff + > load_flag $ff +2da6 : a9ff > lda #$ff ;allow test to change + > +2da8 : 48 > pha ;use stack to load status +2da9 : bd5a02 > lda absANa,x ;precharge accu +2dac : 28 > plp + +2dad : 2d0302 and abst + tst_ax absrlo,absflo,$ff-fnz +2db0 : 08 > php ;save flags +2db1 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2db4 : d0fe > bne * ;failed not equal (non zero) + > +2db6 : 68 > pla ;load status + > eor_flag $ff-fnz +2db7 : 497d > eor #$ff-fnz|fao ;invert expected + > +2db9 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2dbc : d0fe > bne * ;failed not equal (non zero) + > + +2dbe : ca dex +2dbf : 1002 bpl tand6 + +2dc1 : a203 ldx #3 ;zp,x +2dc3 : tand6 + set_ax absANa,0 + > load_flag 0 +2dc3 : a900 > lda #0 ;allow test to change I + > +2dc5 : 48 > pha ;use stack to load status +2dc6 : bd5a02 > lda absANa,x ;precharge accu +2dc9 : 28 > plp + +2dca : 351c and zpAN,x + tst_ax absrlo,absflo,0 +2dcc : 08 > php ;save flags +2dcd : dd6202 > cmp absrlo,x ;test result + > trap_ne +2dd0 : d0fe > bne * ;failed not equal (non zero) + > +2dd2 : 68 > pla ;load status + > eor_flag 0 +2dd3 : 4930 > eor #0|fao ;invert expected flags + > +2dd5 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2dd8 : d0fe > bne * ;failed not equal (non zero) + > + +2dda : ca dex +2ddb : 10e6 bpl tand6 +2ddd : a203 ldx #3 +2ddf : tand7 + set_ax absANa,$ff + > load_flag $ff +2ddf : a9ff > lda #$ff ;allow test to change + > +2de1 : 48 > pha ;use stack to load status +2de2 : bd5a02 > lda absANa,x ;precharge accu +2de5 : 28 > plp + +2de6 : 351c and zpAN,x + tst_ax absrlo,absflo,$ff-fnz +2de8 : 08 > php ;save flags +2de9 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2dec : d0fe > bne * ;failed not equal (non zero) + > +2dee : 68 > pla ;load status + > eor_flag $ff-fnz +2def : 497d > eor #$ff-fnz|fao ;invert expected + > +2df1 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2df4 : d0fe > bne * ;failed not equal (non zero) + > + +2df6 : ca dex +2df7 : 10e6 bpl tand7 + +2df9 : a203 ldx #3 ;abs,x +2dfb : tand8 + set_ax absANa,0 + > load_flag 0 +2dfb : a900 > lda #0 ;allow test to change I + > +2dfd : 48 > pha ;use stack to load status +2dfe : bd5a02 > lda absANa,x ;precharge accu +2e01 : 28 > plp + +2e02 : 3d4e02 and absAN,x + tst_ax absrlo,absflo,0 +2e05 : 08 > php ;save flags +2e06 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2e09 : d0fe > bne * ;failed not equal (non zero) + > +2e0b : 68 > pla ;load status + > eor_flag 0 +2e0c : 4930 > eor #0|fao ;invert expected flags + > +2e0e : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2e11 : d0fe > bne * ;failed not equal (non zero) + > + +2e13 : ca dex +2e14 : 10e5 bpl tand8 +2e16 : a203 ldx #3 +2e18 : tand9 + set_ax absANa,$ff + > load_flag $ff +2e18 : a9ff > lda #$ff ;allow test to change + > +2e1a : 48 > pha ;use stack to load status +2e1b : bd5a02 > lda absANa,x ;precharge accu +2e1e : 28 > plp + +2e1f : 3d4e02 and absAN,x + tst_ax absrlo,absflo,$ff-fnz +2e22 : 08 > php ;save flags +2e23 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2e26 : d0fe > bne * ;failed not equal (non zero) + > +2e28 : 68 > pla ;load status + > eor_flag $ff-fnz +2e29 : 497d > eor #$ff-fnz|fao ;invert expected + > +2e2b : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2e2e : d0fe > bne * ;failed not equal (non zero) + > + +2e30 : ca dex +2e31 : 10e5 bpl tand9 + +2e33 : a003 ldy #3 ;abs,y +2e35 : tand10 + set_ay absANa,0 + > load_flag 0 +2e35 : a900 > lda #0 ;allow test to change I + > +2e37 : 48 > pha ;use stack to load status +2e38 : b95a02 > lda absANa,y ;precharge accu +2e3b : 28 > plp + +2e3c : 394e02 and absAN,y + tst_ay absrlo,absflo,0 +2e3f : 08 > php ;save flags +2e40 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +2e43 : d0fe > bne * ;failed not equal (non zero) + > +2e45 : 68 > pla ;load status + > eor_flag 0 +2e46 : 4930 > eor #0|fao ;invert expected flags + > +2e48 : d96602 > cmp absflo,y ;test flags + > trap_ne +2e4b : d0fe > bne * ;failed not equal (non zero) + > + +2e4d : 88 dey +2e4e : 10e5 bpl tand10 +2e50 : a003 ldy #3 +2e52 : tand11 + set_ay absANa,$ff + > load_flag $ff +2e52 : a9ff > lda #$ff ;allow test to change + > +2e54 : 48 > pha ;use stack to load status +2e55 : b95a02 > lda absANa,y ;precharge accu +2e58 : 28 > plp + +2e59 : 394e02 and absAN,y + tst_ay absrlo,absflo,$ff-fnz +2e5c : 08 > php ;save flags +2e5d : d96202 > cmp absrlo,y ;test result + > trap_ne ; +2e60 : d0fe > bne * ;failed not equal (non zero) + > +2e62 : 68 > pla ;load status + > eor_flag $ff-fnz +2e63 : 497d > eor #$ff-fnz|fao ;invert expected + > +2e65 : d96602 > cmp absflo,y ;test flags + > trap_ne +2e68 : d0fe > bne * ;failed not equal (non zero) + > + +2e6a : 88 dey +2e6b : 10e5 bpl tand11 + +2e6d : a206 ldx #6 ;(zp,x) +2e6f : a003 ldy #3 +2e71 : tand12 + set_ay absANa,0 + > load_flag 0 +2e71 : a900 > lda #0 ;allow test to change I + > +2e73 : 48 > pha ;use stack to load status +2e74 : b95a02 > lda absANa,y ;precharge accu +2e77 : 28 > plp + +2e78 : 213a and (indAN,x) + tst_ay absrlo,absflo,0 +2e7a : 08 > php ;save flags +2e7b : d96202 > cmp absrlo,y ;test result + > trap_ne ; +2e7e : d0fe > bne * ;failed not equal (non zero) + > +2e80 : 68 > pla ;load status + > eor_flag 0 +2e81 : 4930 > eor #0|fao ;invert expected flags + > +2e83 : d96602 > cmp absflo,y ;test flags + > trap_ne +2e86 : d0fe > bne * ;failed not equal (non zero) + > + +2e88 : ca dex +2e89 : ca dex +2e8a : 88 dey +2e8b : 10e4 bpl tand12 +2e8d : a206 ldx #6 +2e8f : a003 ldy #3 +2e91 : tand13 + set_ay absANa,$ff + > load_flag $ff +2e91 : a9ff > lda #$ff ;allow test to change + > +2e93 : 48 > pha ;use stack to load status +2e94 : b95a02 > lda absANa,y ;precharge accu +2e97 : 28 > plp + +2e98 : 213a and (indAN,x) + tst_ay absrlo,absflo,$ff-fnz +2e9a : 08 > php ;save flags +2e9b : d96202 > cmp absrlo,y ;test result + > trap_ne ; +2e9e : d0fe > bne * ;failed not equal (non zero) + > +2ea0 : 68 > pla ;load status + > eor_flag $ff-fnz +2ea1 : 497d > eor #$ff-fnz|fao ;invert expected + > +2ea3 : d96602 > cmp absflo,y ;test flags + > trap_ne +2ea6 : d0fe > bne * ;failed not equal (non zero) + > + +2ea8 : ca dex +2ea9 : ca dex +2eaa : 88 dey +2eab : 10e4 bpl tand13 + +2ead : a003 ldy #3 ;(zp),y +2eaf : tand14 + set_ay absANa,0 + > load_flag 0 +2eaf : a900 > lda #0 ;allow test to change I + > +2eb1 : 48 > pha ;use stack to load status +2eb2 : b95a02 > lda absANa,y ;precharge accu +2eb5 : 28 > plp + +2eb6 : 313a and (indAN),y + tst_ay absrlo,absflo,0 +2eb8 : 08 > php ;save flags +2eb9 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +2ebc : d0fe > bne * ;failed not equal (non zero) + > +2ebe : 68 > pla ;load status + > eor_flag 0 +2ebf : 4930 > eor #0|fao ;invert expected flags + > +2ec1 : d96602 > cmp absflo,y ;test flags + > trap_ne +2ec4 : d0fe > bne * ;failed not equal (non zero) + > + +2ec6 : 88 dey +2ec7 : 10e6 bpl tand14 +2ec9 : a003 ldy #3 +2ecb : tand15 + set_ay absANa,$ff + > load_flag $ff +2ecb : a9ff > lda #$ff ;allow test to change + > +2ecd : 48 > pha ;use stack to load status +2ece : b95a02 > lda absANa,y ;precharge accu +2ed1 : 28 > plp + +2ed2 : 313a and (indAN),y + tst_ay absrlo,absflo,$ff-fnz +2ed4 : 08 > php ;save flags +2ed5 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +2ed8 : d0fe > bne * ;failed not equal (non zero) + > +2eda : 68 > pla ;load status + > eor_flag $ff-fnz +2edb : 497d > eor #$ff-fnz|fao ;invert expected + > +2edd : d96602 > cmp absflo,y ;test flags + > trap_ne +2ee0 : d0fe > bne * ;failed not equal (non zero) + > + +2ee2 : 88 dey +2ee3 : 10e6 bpl tand15 + next_test +2ee5 : ad0002 > lda test_case ;previous test +2ee8 : c926 > cmp #test_num + > trap_ne ;test is out of sequence +2eea : d0fe > bne * ;failed not equal (non zero) + > +0027 = >test_num = test_num + 1 +2eec : a927 > lda #test_num ;*** next tests' number +2eee : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; EOR +2ef1 : a203 ldx #3 ;immediate - self modifying co +2ef3 : b520 teor lda zpEO,x +2ef5 : 8d0c02 sta ex_eori+1 ;set EOR # operand + set_ax absEOa,0 + > load_flag 0 +2ef8 : a900 > lda #0 ;allow test to change I + > +2efa : 48 > pha ;use stack to load status +2efb : bd5e02 > lda absEOa,x ;precharge accu +2efe : 28 > plp + +2eff : 200b02 jsr ex_eori ;execute EOR # in RAM + tst_ax absrlo,absflo,0 +2f02 : 08 > php ;save flags +2f03 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2f06 : d0fe > bne * ;failed not equal (non zero) + > +2f08 : 68 > pla ;load status + > eor_flag 0 +2f09 : 4930 > eor #0|fao ;invert expected flags + > +2f0b : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2f0e : d0fe > bne * ;failed not equal (non zero) + > + +2f10 : ca dex +2f11 : 10e0 bpl teor +2f13 : a203 ldx #3 +2f15 : b520 teor1 lda zpEO,x +2f17 : 8d0c02 sta ex_eori+1 ;set EOR # operand + set_ax absEOa,$ff + > load_flag $ff +2f1a : a9ff > lda #$ff ;allow test to change + > +2f1c : 48 > pha ;use stack to load status +2f1d : bd5e02 > lda absEOa,x ;precharge accu +2f20 : 28 > plp + +2f21 : 200b02 jsr ex_eori ;execute EOR # in RAM + tst_ax absrlo,absflo,$ff-fnz +2f24 : 08 > php ;save flags +2f25 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2f28 : d0fe > bne * ;failed not equal (non zero) + > +2f2a : 68 > pla ;load status + > eor_flag $ff-fnz +2f2b : 497d > eor #$ff-fnz|fao ;invert expected + > +2f2d : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2f30 : d0fe > bne * ;failed not equal (non zero) + > + +2f32 : ca dex +2f33 : 10e0 bpl teor1 + +2f35 : a203 ldx #3 ;zp +2f37 : b520 teor2 lda zpEO,x +2f39 : 850c sta zpt + set_ax absEOa,0 + > load_flag 0 +2f3b : a900 > lda #0 ;allow test to change I + > +2f3d : 48 > pha ;use stack to load status +2f3e : bd5e02 > lda absEOa,x ;precharge accu +2f41 : 28 > plp + +2f42 : 450c eor zpt + tst_ax absrlo,absflo,0 +2f44 : 08 > php ;save flags +2f45 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2f48 : d0fe > bne * ;failed not equal (non zero) + > +2f4a : 68 > pla ;load status + > eor_flag 0 +2f4b : 4930 > eor #0|fao ;invert expected flags + > +2f4d : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2f50 : d0fe > bne * ;failed not equal (non zero) + > + +2f52 : ca dex +2f53 : 10e2 bpl teor2 +2f55 : a203 ldx #3 +2f57 : b520 teor3 lda zpEO,x +2f59 : 850c sta zpt + set_ax absEOa,$ff + > load_flag $ff +2f5b : a9ff > lda #$ff ;allow test to change + > +2f5d : 48 > pha ;use stack to load status +2f5e : bd5e02 > lda absEOa,x ;precharge accu +2f61 : 28 > plp + +2f62 : 450c eor zpt + tst_ax absrlo,absflo,$ff-fnz +2f64 : 08 > php ;save flags +2f65 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2f68 : d0fe > bne * ;failed not equal (non zero) + > +2f6a : 68 > pla ;load status + > eor_flag $ff-fnz +2f6b : 497d > eor #$ff-fnz|fao ;invert expected + > +2f6d : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2f70 : d0fe > bne * ;failed not equal (non zero) + > + +2f72 : ca dex +2f73 : 10e2 bpl teor3 + +2f75 : a203 ldx #3 ;abs +2f77 : b520 teor4 lda zpEO,x +2f79 : 8d0302 sta abst + set_ax absEOa,0 + > load_flag 0 +2f7c : a900 > lda #0 ;allow test to change I + > +2f7e : 48 > pha ;use stack to load status +2f7f : bd5e02 > lda absEOa,x ;precharge accu +2f82 : 28 > plp + +2f83 : 4d0302 eor abst + tst_ax absrlo,absflo,0 +2f86 : 08 > php ;save flags +2f87 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2f8a : d0fe > bne * ;failed not equal (non zero) + > +2f8c : 68 > pla ;load status + > eor_flag 0 +2f8d : 4930 > eor #0|fao ;invert expected flags + > +2f8f : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2f92 : d0fe > bne * ;failed not equal (non zero) + > + +2f94 : ca dex +2f95 : 10e0 bpl teor4 +2f97 : a203 ldx #3 +2f99 : b520 teor5 lda zpEO,x +2f9b : 8d0302 sta abst + set_ax absEOa,$ff + > load_flag $ff +2f9e : a9ff > lda #$ff ;allow test to change + > +2fa0 : 48 > pha ;use stack to load status +2fa1 : bd5e02 > lda absEOa,x ;precharge accu +2fa4 : 28 > plp + +2fa5 : 4d0302 eor abst + tst_ax absrlo,absflo,$ff-fnz +2fa8 : 08 > php ;save flags +2fa9 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2fac : d0fe > bne * ;failed not equal (non zero) + > +2fae : 68 > pla ;load status + > eor_flag $ff-fnz +2faf : 497d > eor #$ff-fnz|fao ;invert expected + > +2fb1 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2fb4 : d0fe > bne * ;failed not equal (non zero) + > + +2fb6 : ca dex +2fb7 : 1002 bpl teor6 + +2fb9 : a203 ldx #3 ;zp,x +2fbb : teor6 + set_ax absEOa,0 + > load_flag 0 +2fbb : a900 > lda #0 ;allow test to change I + > +2fbd : 48 > pha ;use stack to load status +2fbe : bd5e02 > lda absEOa,x ;precharge accu +2fc1 : 28 > plp + +2fc2 : 5520 eor zpEO,x + tst_ax absrlo,absflo,0 +2fc4 : 08 > php ;save flags +2fc5 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2fc8 : d0fe > bne * ;failed not equal (non zero) + > +2fca : 68 > pla ;load status + > eor_flag 0 +2fcb : 4930 > eor #0|fao ;invert expected flags + > +2fcd : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2fd0 : d0fe > bne * ;failed not equal (non zero) + > + +2fd2 : ca dex +2fd3 : 10e6 bpl teor6 +2fd5 : a203 ldx #3 +2fd7 : teor7 + set_ax absEOa,$ff + > load_flag $ff +2fd7 : a9ff > lda #$ff ;allow test to change + > +2fd9 : 48 > pha ;use stack to load status +2fda : bd5e02 > lda absEOa,x ;precharge accu +2fdd : 28 > plp + +2fde : 5520 eor zpEO,x + tst_ax absrlo,absflo,$ff-fnz +2fe0 : 08 > php ;save flags +2fe1 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2fe4 : d0fe > bne * ;failed not equal (non zero) + > +2fe6 : 68 > pla ;load status + > eor_flag $ff-fnz +2fe7 : 497d > eor #$ff-fnz|fao ;invert expected + > +2fe9 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2fec : d0fe > bne * ;failed not equal (non zero) + > + +2fee : ca dex +2fef : 10e6 bpl teor7 + +2ff1 : a203 ldx #3 ;abs,x +2ff3 : teor8 + set_ax absEOa,0 + > load_flag 0 +2ff3 : a900 > lda #0 ;allow test to change I + > +2ff5 : 48 > pha ;use stack to load status +2ff6 : bd5e02 > lda absEOa,x ;precharge accu +2ff9 : 28 > plp + +2ffa : 5d5202 eor absEO,x + tst_ax absrlo,absflo,0 +2ffd : 08 > php ;save flags +2ffe : dd6202 > cmp absrlo,x ;test result + > trap_ne +3001 : d0fe > bne * ;failed not equal (non zero) + > +3003 : 68 > pla ;load status + > eor_flag 0 +3004 : 4930 > eor #0|fao ;invert expected flags + > +3006 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +3009 : d0fe > bne * ;failed not equal (non zero) + > + +300b : ca dex +300c : 10e5 bpl teor8 +300e : a203 ldx #3 +3010 : teor9 + set_ax absEOa,$ff + > load_flag $ff +3010 : a9ff > lda #$ff ;allow test to change + > +3012 : 48 > pha ;use stack to load status +3013 : bd5e02 > lda absEOa,x ;precharge accu +3016 : 28 > plp + +3017 : 5d5202 eor absEO,x + tst_ax absrlo,absflo,$ff-fnz +301a : 08 > php ;save flags +301b : dd6202 > cmp absrlo,x ;test result + > trap_ne +301e : d0fe > bne * ;failed not equal (non zero) + > +3020 : 68 > pla ;load status + > eor_flag $ff-fnz +3021 : 497d > eor #$ff-fnz|fao ;invert expected + > +3023 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +3026 : d0fe > bne * ;failed not equal (non zero) + > + +3028 : ca dex +3029 : 10e5 bpl teor9 + +302b : a003 ldy #3 ;abs,y +302d : teor10 + set_ay absEOa,0 + > load_flag 0 +302d : a900 > lda #0 ;allow test to change I + > +302f : 48 > pha ;use stack to load status +3030 : b95e02 > lda absEOa,y ;precharge accu +3033 : 28 > plp + +3034 : 595202 eor absEO,y + tst_ay absrlo,absflo,0 +3037 : 08 > php ;save flags +3038 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +303b : d0fe > bne * ;failed not equal (non zero) + > +303d : 68 > pla ;load status + > eor_flag 0 +303e : 4930 > eor #0|fao ;invert expected flags + > +3040 : d96602 > cmp absflo,y ;test flags + > trap_ne +3043 : d0fe > bne * ;failed not equal (non zero) + > + +3045 : 88 dey +3046 : 10e5 bpl teor10 +3048 : a003 ldy #3 +304a : teor11 + set_ay absEOa,$ff + > load_flag $ff +304a : a9ff > lda #$ff ;allow test to change + > +304c : 48 > pha ;use stack to load status +304d : b95e02 > lda absEOa,y ;precharge accu +3050 : 28 > plp + +3051 : 595202 eor absEO,y + tst_ay absrlo,absflo,$ff-fnz +3054 : 08 > php ;save flags +3055 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +3058 : d0fe > bne * ;failed not equal (non zero) + > +305a : 68 > pla ;load status + > eor_flag $ff-fnz +305b : 497d > eor #$ff-fnz|fao ;invert expected + > +305d : d96602 > cmp absflo,y ;test flags + > trap_ne +3060 : d0fe > bne * ;failed not equal (non zero) + > + +3062 : 88 dey +3063 : 10e5 bpl teor11 + +3065 : a206 ldx #6 ;(zp,x) +3067 : a003 ldy #3 +3069 : teor12 + set_ay absEOa,0 + > load_flag 0 +3069 : a900 > lda #0 ;allow test to change I + > +306b : 48 > pha ;use stack to load status +306c : b95e02 > lda absEOa,y ;precharge accu +306f : 28 > plp + +3070 : 4142 eor (indEO,x) + tst_ay absrlo,absflo,0 +3072 : 08 > php ;save flags +3073 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +3076 : d0fe > bne * ;failed not equal (non zero) + > +3078 : 68 > pla ;load status + > eor_flag 0 +3079 : 4930 > eor #0|fao ;invert expected flags + > +307b : d96602 > cmp absflo,y ;test flags + > trap_ne +307e : d0fe > bne * ;failed not equal (non zero) + > + +3080 : ca dex +3081 : ca dex +3082 : 88 dey +3083 : 10e4 bpl teor12 +3085 : a206 ldx #6 +3087 : a003 ldy #3 +3089 : teor13 + set_ay absEOa,$ff + > load_flag $ff +3089 : a9ff > lda #$ff ;allow test to change + > +308b : 48 > pha ;use stack to load status +308c : b95e02 > lda absEOa,y ;precharge accu +308f : 28 > plp + +3090 : 4142 eor (indEO,x) + tst_ay absrlo,absflo,$ff-fnz +3092 : 08 > php ;save flags +3093 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +3096 : d0fe > bne * ;failed not equal (non zero) + > +3098 : 68 > pla ;load status + > eor_flag $ff-fnz +3099 : 497d > eor #$ff-fnz|fao ;invert expected + > +309b : d96602 > cmp absflo,y ;test flags + > trap_ne +309e : d0fe > bne * ;failed not equal (non zero) + > + +30a0 : ca dex +30a1 : ca dex +30a2 : 88 dey +30a3 : 10e4 bpl teor13 + +30a5 : a003 ldy #3 ;(zp),y +30a7 : teor14 + set_ay absEOa,0 + > load_flag 0 +30a7 : a900 > lda #0 ;allow test to change I + > +30a9 : 48 > pha ;use stack to load status +30aa : b95e02 > lda absEOa,y ;precharge accu +30ad : 28 > plp + +30ae : 5142 eor (indEO),y + tst_ay absrlo,absflo,0 +30b0 : 08 > php ;save flags +30b1 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +30b4 : d0fe > bne * ;failed not equal (non zero) + > +30b6 : 68 > pla ;load status + > eor_flag 0 +30b7 : 4930 > eor #0|fao ;invert expected flags + > +30b9 : d96602 > cmp absflo,y ;test flags + > trap_ne +30bc : d0fe > bne * ;failed not equal (non zero) + > + +30be : 88 dey +30bf : 10e6 bpl teor14 +30c1 : a003 ldy #3 +30c3 : teor15 + set_ay absEOa,$ff + > load_flag $ff +30c3 : a9ff > lda #$ff ;allow test to change + > +30c5 : 48 > pha ;use stack to load status +30c6 : b95e02 > lda absEOa,y ;precharge accu +30c9 : 28 > plp + +30ca : 5142 eor (indEO),y + tst_ay absrlo,absflo,$ff-fnz +30cc : 08 > php ;save flags +30cd : d96202 > cmp absrlo,y ;test result + > trap_ne ; +30d0 : d0fe > bne * ;failed not equal (non zero) + > +30d2 : 68 > pla ;load status + > eor_flag $ff-fnz +30d3 : 497d > eor #$ff-fnz|fao ;invert expected + > +30d5 : d96602 > cmp absflo,y ;test flags + > trap_ne +30d8 : d0fe > bne * ;failed not equal (non zero) + > + +30da : 88 dey +30db : 10e6 bpl teor15 + next_test +30dd : ad0002 > lda test_case ;previous test +30e0 : c927 > cmp #test_num + > trap_ne ;test is out of sequence +30e2 : d0fe > bne * ;failed not equal (non zero) + > +0028 = >test_num = test_num + 1 +30e4 : a928 > lda #test_num ;*** next tests' number +30e6 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; OR +30e9 : a203 ldx #3 ;immediate - self modifying co +30eb : b518 tora lda zpOR,x +30ed : 8d0f02 sta ex_orai+1 ;set ORA # operand + set_ax absORa,0 + > load_flag 0 +30f0 : a900 > lda #0 ;allow test to change I + > +30f2 : 48 > pha ;use stack to load status +30f3 : bd5602 > lda absORa,x ;precharge accu +30f6 : 28 > plp + +30f7 : 200e02 jsr ex_orai ;execute ORA # in RAM + tst_ax absrlo,absflo,0 +30fa : 08 > php ;save flags +30fb : dd6202 > cmp absrlo,x ;test result + > trap_ne +30fe : d0fe > bne * ;failed not equal (non zero) + > +3100 : 68 > pla ;load status + > eor_flag 0 +3101 : 4930 > eor #0|fao ;invert expected flags + > +3103 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +3106 : d0fe > bne * ;failed not equal (non zero) + > + +3108 : ca dex +3109 : 10e0 bpl tora +310b : a203 ldx #3 +310d : b518 tora1 lda zpOR,x +310f : 8d0f02 sta ex_orai+1 ;set ORA # operand + set_ax absORa,$ff + > load_flag $ff +3112 : a9ff > lda #$ff ;allow test to change + > +3114 : 48 > pha ;use stack to load status +3115 : bd5602 > lda absORa,x ;precharge accu +3118 : 28 > plp + +3119 : 200e02 jsr ex_orai ;execute ORA # in RAM + tst_ax absrlo,absflo,$ff-fnz +311c : 08 > php ;save flags +311d : dd6202 > cmp absrlo,x ;test result + > trap_ne +3120 : d0fe > bne * ;failed not equal (non zero) + > +3122 : 68 > pla ;load status + > eor_flag $ff-fnz +3123 : 497d > eor #$ff-fnz|fao ;invert expected + > +3125 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +3128 : d0fe > bne * ;failed not equal (non zero) + > + +312a : ca dex +312b : 10e0 bpl tora1 + +312d : a203 ldx #3 ;zp +312f : b518 tora2 lda zpOR,x +3131 : 850c sta zpt + set_ax absORa,0 + > load_flag 0 +3133 : a900 > lda #0 ;allow test to change I + > +3135 : 48 > pha ;use stack to load status +3136 : bd5602 > lda absORa,x ;precharge accu +3139 : 28 > plp + +313a : 050c ora zpt + tst_ax absrlo,absflo,0 +313c : 08 > php ;save flags +313d : dd6202 > cmp absrlo,x ;test result + > trap_ne +3140 : d0fe > bne * ;failed not equal (non zero) + > +3142 : 68 > pla ;load status + > eor_flag 0 +3143 : 4930 > eor #0|fao ;invert expected flags + > +3145 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +3148 : d0fe > bne * ;failed not equal (non zero) + > + +314a : ca dex +314b : 10e2 bpl tora2 +314d : a203 ldx #3 +314f : b518 tora3 lda zpOR,x +3151 : 850c sta zpt + set_ax absORa,$ff + > load_flag $ff +3153 : a9ff > lda #$ff ;allow test to change + > +3155 : 48 > pha ;use stack to load status +3156 : bd5602 > lda absORa,x ;precharge accu +3159 : 28 > plp + +315a : 050c ora zpt + tst_ax absrlo,absflo,$ff-fnz +315c : 08 > php ;save flags +315d : dd6202 > cmp absrlo,x ;test result + > trap_ne +3160 : d0fe > bne * ;failed not equal (non zero) + > +3162 : 68 > pla ;load status + > eor_flag $ff-fnz +3163 : 497d > eor #$ff-fnz|fao ;invert expected + > +3165 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +3168 : d0fe > bne * ;failed not equal (non zero) + > + +316a : ca dex +316b : 10e2 bpl tora3 + +316d : a203 ldx #3 ;abs +316f : b518 tora4 lda zpOR,x +3171 : 8d0302 sta abst + set_ax absORa,0 + > load_flag 0 +3174 : a900 > lda #0 ;allow test to change I + > +3176 : 48 > pha ;use stack to load status +3177 : bd5602 > lda absORa,x ;precharge accu +317a : 28 > plp + +317b : 0d0302 ora abst + tst_ax absrlo,absflo,0 +317e : 08 > php ;save flags +317f : dd6202 > cmp absrlo,x ;test result + > trap_ne +3182 : d0fe > bne * ;failed not equal (non zero) + > +3184 : 68 > pla ;load status + > eor_flag 0 +3185 : 4930 > eor #0|fao ;invert expected flags + > +3187 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +318a : d0fe > bne * ;failed not equal (non zero) + > + +318c : ca dex +318d : 10e0 bpl tora4 +318f : a203 ldx #3 +3191 : b518 tora5 lda zpOR,x +3193 : 8d0302 sta abst + set_ax absORa,$ff + > load_flag $ff +3196 : a9ff > lda #$ff ;allow test to change + > +3198 : 48 > pha ;use stack to load status +3199 : bd5602 > lda absORa,x ;precharge accu +319c : 28 > plp + +319d : 0d0302 ora abst + tst_ax absrlo,absflo,$ff-fnz +31a0 : 08 > php ;save flags +31a1 : dd6202 > cmp absrlo,x ;test result + > trap_ne +31a4 : d0fe > bne * ;failed not equal (non zero) + > +31a6 : 68 > pla ;load status + > eor_flag $ff-fnz +31a7 : 497d > eor #$ff-fnz|fao ;invert expected + > +31a9 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +31ac : d0fe > bne * ;failed not equal (non zero) + > + +31ae : ca dex +31af : 1002 bpl tora6 + +31b1 : a203 ldx #3 ;zp,x +31b3 : tora6 + set_ax absORa,0 + > load_flag 0 +31b3 : a900 > lda #0 ;allow test to change I + > +31b5 : 48 > pha ;use stack to load status +31b6 : bd5602 > lda absORa,x ;precharge accu +31b9 : 28 > plp + +31ba : 1518 ora zpOR,x + tst_ax absrlo,absflo,0 +31bc : 08 > php ;save flags +31bd : dd6202 > cmp absrlo,x ;test result + > trap_ne +31c0 : d0fe > bne * ;failed not equal (non zero) + > +31c2 : 68 > pla ;load status + > eor_flag 0 +31c3 : 4930 > eor #0|fao ;invert expected flags + > +31c5 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +31c8 : d0fe > bne * ;failed not equal (non zero) + > + +31ca : ca dex +31cb : 10e6 bpl tora6 +31cd : a203 ldx #3 +31cf : tora7 + set_ax absORa,$ff + > load_flag $ff +31cf : a9ff > lda #$ff ;allow test to change + > +31d1 : 48 > pha ;use stack to load status +31d2 : bd5602 > lda absORa,x ;precharge accu +31d5 : 28 > plp + +31d6 : 1518 ora zpOR,x + tst_ax absrlo,absflo,$ff-fnz +31d8 : 08 > php ;save flags +31d9 : dd6202 > cmp absrlo,x ;test result + > trap_ne +31dc : d0fe > bne * ;failed not equal (non zero) + > +31de : 68 > pla ;load status + > eor_flag $ff-fnz +31df : 497d > eor #$ff-fnz|fao ;invert expected + > +31e1 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +31e4 : d0fe > bne * ;failed not equal (non zero) + > + +31e6 : ca dex +31e7 : 10e6 bpl tora7 + +31e9 : a203 ldx #3 ;abs,x +31eb : tora8 + set_ax absORa,0 + > load_flag 0 +31eb : a900 > lda #0 ;allow test to change I + > +31ed : 48 > pha ;use stack to load status +31ee : bd5602 > lda absORa,x ;precharge accu +31f1 : 28 > plp + +31f2 : 1d4a02 ora absOR,x + tst_ax absrlo,absflo,0 +31f5 : 08 > php ;save flags +31f6 : dd6202 > cmp absrlo,x ;test result + > trap_ne +31f9 : d0fe > bne * ;failed not equal (non zero) + > +31fb : 68 > pla ;load status + > eor_flag 0 +31fc : 4930 > eor #0|fao ;invert expected flags + > +31fe : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +3201 : d0fe > bne * ;failed not equal (non zero) + > + +3203 : ca dex +3204 : 10e5 bpl tora8 +3206 : a203 ldx #3 +3208 : tora9 + set_ax absORa,$ff + > load_flag $ff +3208 : a9ff > lda #$ff ;allow test to change + > +320a : 48 > pha ;use stack to load status +320b : bd5602 > lda absORa,x ;precharge accu +320e : 28 > plp + +320f : 1d4a02 ora absOR,x + tst_ax absrlo,absflo,$ff-fnz +3212 : 08 > php ;save flags +3213 : dd6202 > cmp absrlo,x ;test result + > trap_ne +3216 : d0fe > bne * ;failed not equal (non zero) + > +3218 : 68 > pla ;load status + > eor_flag $ff-fnz +3219 : 497d > eor #$ff-fnz|fao ;invert expected + > +321b : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +321e : d0fe > bne * ;failed not equal (non zero) + > + +3220 : ca dex +3221 : 10e5 bpl tora9 + +3223 : a003 ldy #3 ;abs,y +3225 : tora10 + set_ay absORa,0 + > load_flag 0 +3225 : a900 > lda #0 ;allow test to change I + > +3227 : 48 > pha ;use stack to load status +3228 : b95602 > lda absORa,y ;precharge accu +322b : 28 > plp + +322c : 194a02 ora absOR,y + tst_ay absrlo,absflo,0 +322f : 08 > php ;save flags +3230 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +3233 : d0fe > bne * ;failed not equal (non zero) + > +3235 : 68 > pla ;load status + > eor_flag 0 +3236 : 4930 > eor #0|fao ;invert expected flags + > +3238 : d96602 > cmp absflo,y ;test flags + > trap_ne +323b : d0fe > bne * ;failed not equal (non zero) + > + +323d : 88 dey +323e : 10e5 bpl tora10 +3240 : a003 ldy #3 +3242 : tora11 + set_ay absORa,$ff + > load_flag $ff +3242 : a9ff > lda #$ff ;allow test to change + > +3244 : 48 > pha ;use stack to load status +3245 : b95602 > lda absORa,y ;precharge accu +3248 : 28 > plp + +3249 : 194a02 ora absOR,y + tst_ay absrlo,absflo,$ff-fnz +324c : 08 > php ;save flags +324d : d96202 > cmp absrlo,y ;test result + > trap_ne ; +3250 : d0fe > bne * ;failed not equal (non zero) + > +3252 : 68 > pla ;load status + > eor_flag $ff-fnz +3253 : 497d > eor #$ff-fnz|fao ;invert expected + > +3255 : d96602 > cmp absflo,y ;test flags + > trap_ne +3258 : d0fe > bne * ;failed not equal (non zero) + > + +325a : 88 dey +325b : 10e5 bpl tora11 + +325d : a206 ldx #6 ;(zp,x) +325f : a003 ldy #3 +3261 : tora12 + set_ay absORa,0 + > load_flag 0 +3261 : a900 > lda #0 ;allow test to change I + > +3263 : 48 > pha ;use stack to load status +3264 : b95602 > lda absORa,y ;precharge accu +3267 : 28 > plp + +3268 : 014a ora (indOR,x) + tst_ay absrlo,absflo,0 +326a : 08 > php ;save flags +326b : d96202 > cmp absrlo,y ;test result + > trap_ne ; +326e : d0fe > bne * ;failed not equal (non zero) + > +3270 : 68 > pla ;load status + > eor_flag 0 +3271 : 4930 > eor #0|fao ;invert expected flags + > +3273 : d96602 > cmp absflo,y ;test flags + > trap_ne +3276 : d0fe > bne * ;failed not equal (non zero) + > + +3278 : ca dex +3279 : ca dex +327a : 88 dey +327b : 10e4 bpl tora12 +327d : a206 ldx #6 +327f : a003 ldy #3 +3281 : tora13 + set_ay absORa,$ff + > load_flag $ff +3281 : a9ff > lda #$ff ;allow test to change + > +3283 : 48 > pha ;use stack to load status +3284 : b95602 > lda absORa,y ;precharge accu +3287 : 28 > plp + +3288 : 014a ora (indOR,x) + tst_ay absrlo,absflo,$ff-fnz +328a : 08 > php ;save flags +328b : d96202 > cmp absrlo,y ;test result + > trap_ne ; +328e : d0fe > bne * ;failed not equal (non zero) + > +3290 : 68 > pla ;load status + > eor_flag $ff-fnz +3291 : 497d > eor #$ff-fnz|fao ;invert expected + > +3293 : d96602 > cmp absflo,y ;test flags + > trap_ne +3296 : d0fe > bne * ;failed not equal (non zero) + > + +3298 : ca dex +3299 : ca dex +329a : 88 dey +329b : 10e4 bpl tora13 + +329d : a003 ldy #3 ;(zp),y +329f : tora14 + set_ay absORa,0 + > load_flag 0 +329f : a900 > lda #0 ;allow test to change I + > +32a1 : 48 > pha ;use stack to load status +32a2 : b95602 > lda absORa,y ;precharge accu +32a5 : 28 > plp + +32a6 : 114a ora (indOR),y + tst_ay absrlo,absflo,0 +32a8 : 08 > php ;save flags +32a9 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +32ac : d0fe > bne * ;failed not equal (non zero) + > +32ae : 68 > pla ;load status + > eor_flag 0 +32af : 4930 > eor #0|fao ;invert expected flags + > +32b1 : d96602 > cmp absflo,y ;test flags + > trap_ne +32b4 : d0fe > bne * ;failed not equal (non zero) + > + +32b6 : 88 dey +32b7 : 10e6 bpl tora14 +32b9 : a003 ldy #3 +32bb : tora15 + set_ay absORa,$ff + > load_flag $ff +32bb : a9ff > lda #$ff ;allow test to change + > +32bd : 48 > pha ;use stack to load status +32be : b95602 > lda absORa,y ;precharge accu +32c1 : 28 > plp + +32c2 : 114a ora (indOR),y + tst_ay absrlo,absflo,$ff-fnz +32c4 : 08 > php ;save flags +32c5 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +32c8 : d0fe > bne * ;failed not equal (non zero) + > +32ca : 68 > pla ;load status + > eor_flag $ff-fnz +32cb : 497d > eor #$ff-fnz|fao ;invert expected + > +32cd : d96602 > cmp absflo,y ;test flags + > trap_ne +32d0 : d0fe > bne * ;failed not equal (non zero) + > + +32d2 : 88 dey +32d3 : 10e6 bpl tora15 + if I_flag = 3 +32d5 : 58 cli + endif + next_test +32d6 : ad0002 > lda test_case ;previous test +32d9 : c928 > cmp #test_num + > trap_ne ;test is out of sequence +32db : d0fe > bne * ;failed not equal (non zero) + > +0029 = >test_num = test_num + 1 +32dd : a929 > lda #test_num ;*** next tests' number +32df : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; full binary add/subtract test + ; iterates through all combinations of operands and ca + ; uses increments/decrements to predict result & resul +32e2 : d8 cld +32e3 : a20e ldx #ad2 ;for indexed test +32e5 : a0ff ldy #$ff ;max range +32e7 : a900 lda #0 ;start with adding zeroes & no +32e9 : 850c sta adfc ;carry in - for diag +32eb : 850d sta ad1 ;operand 1 - accumulator +32ed : 850e sta ad2 ;operand 2 - memory or immedia +32ef : 8d0302 sta ada2 ;non zp +32f2 : 850f sta adrl ;expected result bits 0-7 +32f4 : 8510 sta adrh ;expected result bit 8 (carry +32f6 : a9ff lda #$ff ;complemented operand 2 for su +32f8 : 8512 sta sb2 +32fa : 8d0402 sta sba2 ;non zp +32fd : a902 lda #2 ;expected Z-flag +32ff : 8511 sta adrf +3301 : 18 tadd clc ;test with carry clear +3302 : 207c35 jsr chkadd +3305 : e60c inc adfc ;now with carry +3307 : e60f inc adrl ;result +1 +3309 : 08 php ;save N & Z from low result +330a : 08 php +330b : 68 pla ;accu holds expected flags +330c : 2982 and #$82 ;mask N & Z +330e : 28 plp +330f : d002 bne tadd1 +3311 : e610 inc adrh ;result bit 8 - carry +3313 : 0510 tadd1 ora adrh ;merge C to expected flags +3315 : 8511 sta adrf ;save expected flags except ov +3317 : 38 sec ;test with carry set +3318 : 207c35 jsr chkadd +331b : c60c dec adfc ;same for operand +1 but no ca +331d : e60d inc ad1 +331f : d0e0 bne tadd ;iterate op1 +3321 : a900 lda #0 ;preset result to op2 when op1 +3323 : 8510 sta adrh +3325 : ee0302 inc ada2 +3328 : e60e inc ad2 +332a : 08 php ;save NZ as operand 2 becomes +332b : 68 pla +332c : 2982 and #$82 ;mask N00000Z0 +332e : 8511 sta adrf ;no need to check carry as we +3330 : c612 dec sb2 ;complement subtract operand 2 +3332 : ce0402 dec sba2 +3335 : a50e lda ad2 +3337 : 850f sta adrl +3339 : d0c6 bne tadd ;iterate op2 + if disable_decimal < 1 + next_test +333b : ad0002 > lda test_case ;previous test +333e : c929 > cmp #test_num + > trap_ne ;test is out of sequence +3340 : d0fe > bne * ;failed not equal (non zero) + > +002a = >test_num = test_num + 1 +3342 : a92a > lda #test_num ;*** next tests' number +3344 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; decimal add/subtract test + ; *** WARNING - tests documented behavior only! *** + ; only valid BCD operands are tested, N V Z flags ar + ; iterates through all valid combinations of operands + ; uses increments/decrements to predict result & carry +3347 : f8 sed +3348 : a20e ldx #ad2 ;for indexed test +334a : a0ff ldy #$ff ;max range +334c : a999 lda #$99 ;start with adding 99 to 99 wi +334e : 850d sta ad1 ;operand 1 - accumulator +3350 : 850e sta ad2 ;operand 2 - memory or immedia +3352 : 8d0302 sta ada2 ;non zp +3355 : 850f sta adrl ;expected result bits 0-7 +3357 : a901 lda #1 ;set carry in & out +3359 : 850c sta adfc ;carry in - for diag +335b : 8510 sta adrh ;expected result bit 8 (carry +335d : a900 lda #0 ;complemented operand 2 for su +335f : 8512 sta sb2 +3361 : 8d0402 sta sba2 ;non zp +3364 : 38 tdad sec ;test with carry set +3365 : 204934 jsr chkdad +3368 : c60c dec adfc ;now with carry clear +336a : a50f lda adrl ;decimal adjust result +336c : d008 bne tdad1 ;skip clear carry & preset res +336e : c610 dec adrh +3370 : a999 lda #$99 +3372 : 850f sta adrl +3374 : d012 bne tdad3 +3376 : 290f tdad1 and #$f ;lower nibble mask +3378 : d00c bne tdad2 ;no decimal adjust needed +337a : c60f dec adrl ;decimal adjust (?0-6) +337c : c60f dec adrl +337e : c60f dec adrl +3380 : c60f dec adrl +3382 : c60f dec adrl +3384 : c60f dec adrl +3386 : c60f tdad2 dec adrl ;result -1 +3388 : 18 tdad3 clc ;test with carry clear +3389 : 204934 jsr chkdad +338c : e60c inc adfc ;same for operand -1 but with +338e : a50d lda ad1 ;decimal adjust operand 1 +3390 : f015 beq tdad5 ;iterate operand 2 +3392 : 290f and #$f ;lower nibble mask +3394 : d00c bne tdad4 ;skip decimal adjust +3396 : c60d dec ad1 ;decimal adjust (?0-6) +3398 : c60d dec ad1 +339a : c60d dec ad1 +339c : c60d dec ad1 +339e : c60d dec ad1 +33a0 : c60d dec ad1 +33a2 : c60d tdad4 dec ad1 ;operand 1 -1 +33a4 : 4c6433 jmp tdad ;iterate op1 + +33a7 : a999 tdad5 lda #$99 ;precharge op1 max +33a9 : 850d sta ad1 +33ab : a50e lda ad2 ;decimal adjust operand 2 +33ad : f030 beq tdad7 ;end of iteration +33af : 290f and #$f ;lower nibble mask +33b1 : d018 bne tdad6 ;skip decimal adjust +33b3 : c60e dec ad2 ;decimal adjust (?0-6) +33b5 : c60e dec ad2 +33b7 : c60e dec ad2 +33b9 : c60e dec ad2 +33bb : c60e dec ad2 +33bd : c60e dec ad2 +33bf : e612 inc sb2 ;complemented decimal adjust f +33c1 : e612 inc sb2 +33c3 : e612 inc sb2 +33c5 : e612 inc sb2 +33c7 : e612 inc sb2 +33c9 : e612 inc sb2 +33cb : c60e tdad6 dec ad2 ;operand 2 -1 +33cd : e612 inc sb2 ;complemented operand for subt +33cf : a512 lda sb2 +33d1 : 8d0402 sta sba2 ;copy as non zp operand +33d4 : a50e lda ad2 +33d6 : 8d0302 sta ada2 ;copy as non zp operand +33d9 : 850f sta adrl ;new result since op1+carry=00 +33db : e610 inc adrh ;result carry +33dd : d085 bne tdad ;iterate op2 +33df : tdad7 + next_test +33df : ad0002 > lda test_case ;previous test +33e2 : c92a > cmp #test_num + > trap_ne ;test is out of sequence +33e4 : d0fe > bne * ;failed not equal (non zero) + > +002b = >test_num = test_num + 1 +33e6 : a92b > lda #test_num ;*** next tests' number +33e8 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; decimal/binary switch test + ; tests CLD, SED, PLP, RTI to properly switch between + ; tables +33eb : 18 clc +33ec : d8 cld +33ed : 08 php +33ee : a955 lda #$55 +33f0 : 6955 adc #$55 +33f2 : c9aa cmp #$aa + trap_ne ;expected binary result after +33f4 : d0fe > bne * ;failed not equal (non zero) + +33f6 : 18 clc +33f7 : f8 sed +33f8 : 08 php +33f9 : a955 lda #$55 +33fb : 6955 adc #$55 +33fd : c910 cmp #$10 + trap_ne ;expected decimal result after +33ff : d0fe > bne * ;failed not equal (non zero) + +3401 : d8 cld +3402 : 28 plp +3403 : a955 lda #$55 +3405 : 6955 adc #$55 +3407 : c910 cmp #$10 + trap_ne ;expected decimal result after +3409 : d0fe > bne * ;failed not equal (non zero) + +340b : 28 plp +340c : a955 lda #$55 +340e : 6955 adc #$55 +3410 : c9aa cmp #$aa + trap_ne ;expected binary result after +3412 : d0fe > bne * ;failed not equal (non zero) + +3414 : 18 clc +3415 : a934 lda #hi bin_rti_ret ;emulated interrupt for rt +3417 : 48 pha +3418 : a92f lda #lo bin_rti_ret +341a : 48 pha +341b : 08 php +341c : f8 sed +341d : a934 lda #hi dec_rti_ret ;emulated interrupt for rt +341f : 48 pha +3420 : a926 lda #lo dec_rti_ret +3422 : 48 pha +3423 : 08 php +3424 : d8 cld +3425 : 40 rti +3426 : dec_rti_ret +3426 : a955 lda #$55 +3428 : 6955 adc #$55 +342a : c910 cmp #$10 + trap_ne ;expected decimal result after +342c : d0fe > bne * ;failed not equal (non zero) + +342e : 40 rti +342f : bin_rti_ret +342f : a955 lda #$55 +3431 : 6955 adc #$55 +3433 : c9aa cmp #$aa + trap_ne ;expected binary result after +3435 : d0fe > bne * ;failed not equal (non zero) + + endif + +3437 : ad0002 lda test_case +343a : c92b cmp #test_num + trap_ne ;previous test is out of seque +343c : d0fe > bne * ;failed not equal (non zero) + +343e : a9f0 lda #$f0 ;mark opcode testing complete +3440 : 8d0002 sta test_case + + ; final RAM integrity test + ; verifies that none of the previous tests has alter + ; designated write areas. + check_ram + > ;RAM check disabled - RAM size not set + + ; *** DEBUG INFO *** + ; to debug checksum errors uncomment check_ram in the + ; narrow down the responsible opcode. + ; may give false errors when monitor, OS or other back + ; allowed during previous tests. + + + ; S U C C E S S ************************************** + ; ------------- + success ;if you get here everything we +3443 : 4c4334 > jmp * ;test passed, no errors + + ; ------------- + ; S U C C E S S ************************************** +3446 : 4c0004 jmp start ;run again + + if disable_decimal < 1 + ; core subroutine of the decimal add/subtract test + ; *** WARNING - tests documented behavior only! *** + ; only valid BCD operands are tested, N V Z flags ar + ; iterates through all valid combinations of operands + ; uses increments/decrements to predict result & carry +3449 : chkdad + ; decimal ADC / SBC zp +3449 : 08 php ;save carry for subtract +344a : a50d lda ad1 +344c : 650e adc ad2 ;perform add +344e : 08 php +344f : c50f cmp adrl ;check result + trap_ne ;bad result +3451 : d0fe > bne * ;failed not equal (non zero) + +3453 : 68 pla ;check flags +3454 : 2901 and #1 ;mask carry +3456 : c510 cmp adrh + trap_ne ;bad carry +3458 : d0fe > bne * ;failed not equal (non zero) + +345a : 28 plp +345b : 08 php ;save carry for next add +345c : a50d lda ad1 +345e : e512 sbc sb2 ;perform subtract +3460 : 08 php +3461 : c50f cmp adrl ;check result + trap_ne ;bad result +3463 : d0fe > bne * ;failed not equal (non zero) + +3465 : 68 pla ;check flags +3466 : 2901 and #1 ;mask carry +3468 : c510 cmp adrh + trap_ne ;bad flags +346a : d0fe > bne * ;failed not equal (non zero) + +346c : 28 plp + ; decimal ADC / SBC abs +346d : 08 php ;save carry for subtract +346e : a50d lda ad1 +3470 : 6d0302 adc ada2 ;perform add +3473 : 08 php +3474 : c50f cmp adrl ;check result + trap_ne ;bad result +3476 : d0fe > bne * ;failed not equal (non zero) + +3478 : 68 pla ;check flags +3479 : 2901 and #1 ;mask carry +347b : c510 cmp adrh + trap_ne ;bad carry +347d : d0fe > bne * ;failed not equal (non zero) + +347f : 28 plp +3480 : 08 php ;save carry for next add +3481 : a50d lda ad1 +3483 : ed0402 sbc sba2 ;perform subtract +3486 : 08 php +3487 : c50f cmp adrl ;check result + trap_ne ;bad result +3489 : d0fe > bne * ;failed not equal (non zero) + +348b : 68 pla ;check flags +348c : 2901 and #1 ;mask carry +348e : c510 cmp adrh + trap_ne ;bad carry +3490 : d0fe > bne * ;failed not equal (non zero) + +3492 : 28 plp + ; decimal ADC / SBC # +3493 : 08 php ;save carry for subtract +3494 : a50e lda ad2 +3496 : 8d1202 sta ex_adci+1 ;set ADC # operand +3499 : a50d lda ad1 +349b : 201102 jsr ex_adci ;execute ADC # in RAM +349e : 08 php +349f : c50f cmp adrl ;check result + trap_ne ;bad result +34a1 : d0fe > bne * ;failed not equal (non zero) + +34a3 : 68 pla ;check flags +34a4 : 2901 and #1 ;mask carry +34a6 : c510 cmp adrh + trap_ne ;bad carry +34a8 : d0fe > bne * ;failed not equal (non zero) + +34aa : 28 plp +34ab : 08 php ;save carry for next add +34ac : a512 lda sb2 +34ae : 8d1502 sta ex_sbci+1 ;set SBC # operand +34b1 : a50d lda ad1 +34b3 : 201402 jsr ex_sbci ;execute SBC # in RAM +34b6 : 08 php +34b7 : c50f cmp adrl ;check result + trap_ne ;bad result +34b9 : d0fe > bne * ;failed not equal (non zero) + +34bb : 68 pla ;check flags +34bc : 2901 and #1 ;mask carry +34be : c510 cmp adrh + trap_ne ;bad carry +34c0 : d0fe > bne * ;failed not equal (non zero) + +34c2 : 28 plp + ; decimal ADC / SBC zp,x +34c3 : 08 php ;save carry for subtract +34c4 : a50d lda ad1 +34c6 : 7500 adc 0,x ;perform add +34c8 : 08 php +34c9 : c50f cmp adrl ;check result + trap_ne ;bad result +34cb : d0fe > bne * ;failed not equal (non zero) + +34cd : 68 pla ;check flags +34ce : 2901 and #1 ;mask carry +34d0 : c510 cmp adrh + trap_ne ;bad carry +34d2 : d0fe > bne * ;failed not equal (non zero) + +34d4 : 28 plp +34d5 : 08 php ;save carry for next add +34d6 : a50d lda ad1 +34d8 : f504 sbc sb2-ad2,x ;perform subtract +34da : 08 php +34db : c50f cmp adrl ;check result + trap_ne ;bad result +34dd : d0fe > bne * ;failed not equal (non zero) + +34df : 68 pla ;check flags +34e0 : 2901 and #1 ;mask carry +34e2 : c510 cmp adrh + trap_ne ;bad carry +34e4 : d0fe > bne * ;failed not equal (non zero) + +34e6 : 28 plp + ; decimal ADC / SBC abs,x +34e7 : 08 php ;save carry for subtract +34e8 : a50d lda ad1 +34ea : 7df501 adc ada2-ad2,x ;perform add +34ed : 08 php +34ee : c50f cmp adrl ;check result + trap_ne ;bad result +34f0 : d0fe > bne * ;failed not equal (non zero) + +34f2 : 68 pla ;check flags +34f3 : 2901 and #1 ;mask carry +34f5 : c510 cmp adrh + trap_ne ;bad carry +34f7 : d0fe > bne * ;failed not equal (non zero) + +34f9 : 28 plp +34fa : 08 php ;save carry for next add +34fb : a50d lda ad1 +34fd : fdf601 sbc sba2-ad2,x ;perform subtract +3500 : 08 php +3501 : c50f cmp adrl ;check result + trap_ne ;bad result +3503 : d0fe > bne * ;failed not equal (non zero) + +3505 : 68 pla ;check flags +3506 : 2901 and #1 ;mask carry +3508 : c510 cmp adrh + trap_ne ;bad carry +350a : d0fe > bne * ;failed not equal (non zero) + +350c : 28 plp + ; decimal ADC / SBC abs,y +350d : 08 php ;save carry for subtract +350e : a50d lda ad1 +3510 : 790401 adc ada2-$ff,y ;perform add +3513 : 08 php +3514 : c50f cmp adrl ;check result + trap_ne ;bad result +3516 : d0fe > bne * ;failed not equal (non zero) + +3518 : 68 pla ;check flags +3519 : 2901 and #1 ;mask carry +351b : c510 cmp adrh + trap_ne ;bad carry +351d : d0fe > bne * ;failed not equal (non zero) + +351f : 28 plp +3520 : 08 php ;save carry for next add +3521 : a50d lda ad1 +3523 : f90501 sbc sba2-$ff,y ;perform subtract +3526 : 08 php +3527 : c50f cmp adrl ;check result + trap_ne ;bad result +3529 : d0fe > bne * ;failed not equal (non zero) + +352b : 68 pla ;check flags +352c : 2901 and #1 ;mask carry +352e : c510 cmp adrh + trap_ne ;bad carry +3530 : d0fe > bne * ;failed not equal (non zero) + +3532 : 28 plp + ; decimal ADC / SBC (zp,x) +3533 : 08 php ;save carry for subtract +3534 : a50d lda ad1 +3536 : 6144 adc (lo adi2-ad2,x) ;perform add +3538 : 08 php +3539 : c50f cmp adrl ;check result + trap_ne ;bad result +353b : d0fe > bne * ;failed not equal (non zero) + +353d : 68 pla ;check flags +353e : 2901 and #1 ;mask carry +3540 : c510 cmp adrh + trap_ne ;bad carry +3542 : d0fe > bne * ;failed not equal (non zero) + +3544 : 28 plp +3545 : 08 php ;save carry for next add +3546 : a50d lda ad1 +3548 : e146 sbc (lo sbi2-ad2,x) ;perform subtract +354a : 08 php +354b : c50f cmp adrl ;check result + trap_ne ;bad result +354d : d0fe > bne * ;failed not equal (non zero) + +354f : 68 pla ;check flags +3550 : 2901 and #1 ;mask carry +3552 : c510 cmp adrh + trap_ne ;bad carry +3554 : d0fe > bne * ;failed not equal (non zero) + +3556 : 28 plp + ; decimal ADC / SBC (abs),y +3557 : 08 php ;save carry for subtract +3558 : a50d lda ad1 +355a : 7156 adc (adiy2),y ;perform add +355c : 08 php +355d : c50f cmp adrl ;check result + trap_ne ;bad result +355f : d0fe > bne * ;failed not equal (non zero) + +3561 : 68 pla ;check flags +3562 : 2901 and #1 ;mask carry +3564 : c510 cmp adrh + trap_ne ;bad carry +3566 : d0fe > bne * ;failed not equal (non zero) + +3568 : 28 plp +3569 : 08 php ;save carry for next add +356a : a50d lda ad1 +356c : f158 sbc (sbiy2),y ;perform subtract +356e : 08 php +356f : c50f cmp adrl ;check result + trap_ne ;bad result +3571 : d0fe > bne * ;failed not equal (non zero) + +3573 : 68 pla ;check flags +3574 : 2901 and #1 ;mask carry +3576 : c510 cmp adrh + trap_ne ;bad carry +3578 : d0fe > bne * ;failed not equal (non zero) + +357a : 28 plp +357b : 60 rts + endif + + ; core subroutine of the full binary add/subtract test + ; iterates through all combinations of operands and ca + ; uses increments/decrements to predict result & resul +357c : a511 chkadd lda adrf ;add V-flag if overflow +357e : 2983 and #$83 ;keep N-----ZC / clear V +3580 : 48 pha +3581 : a50d lda ad1 ;test sign unequal between ope +3583 : 450e eor ad2 +3585 : 300a bmi ckad1 ;no overflow possible - operan +3587 : a50d lda ad1 ;test sign equal between opera +3589 : 450f eor adrl +358b : 1004 bpl ckad1 ;no overflow occured - operand +358d : 68 pla +358e : 0940 ora #$40 ;set V +3590 : 48 pha +3591 : 68 ckad1 pla +3592 : 8511 sta adrf ;save expected flags + ; binary ADC / SBC zp +3594 : 08 php ;save carry for subtract +3595 : a50d lda ad1 +3597 : 650e adc ad2 ;perform add +3599 : 08 php +359a : c50f cmp adrl ;check result + trap_ne ;bad result +359c : d0fe > bne * ;failed not equal (non zero) + +359e : 68 pla ;check flags +359f : 29c3 and #$c3 ;mask NV----ZC +35a1 : c511 cmp adrf + trap_ne ;bad flags +35a3 : d0fe > bne * ;failed not equal (non zero) + +35a5 : 28 plp +35a6 : 08 php ;save carry for next add +35a7 : a50d lda ad1 +35a9 : e512 sbc sb2 ;perform subtract +35ab : 08 php +35ac : c50f cmp adrl ;check result + trap_ne ;bad result +35ae : d0fe > bne * ;failed not equal (non zero) + +35b0 : 68 pla ;check flags +35b1 : 29c3 and #$c3 ;mask NV----ZC +35b3 : c511 cmp adrf + trap_ne ;bad flags +35b5 : d0fe > bne * ;failed not equal (non zero) + +35b7 : 28 plp + ; binary ADC / SBC abs +35b8 : 08 php ;save carry for subtract +35b9 : a50d lda ad1 +35bb : 6d0302 adc ada2 ;perform add +35be : 08 php +35bf : c50f cmp adrl ;check result + trap_ne ;bad result +35c1 : d0fe > bne * ;failed not equal (non zero) + +35c3 : 68 pla ;check flags +35c4 : 29c3 and #$c3 ;mask NV----ZC +35c6 : c511 cmp adrf + trap_ne ;bad flags +35c8 : d0fe > bne * ;failed not equal (non zero) + +35ca : 28 plp +35cb : 08 php ;save carry for next add +35cc : a50d lda ad1 +35ce : ed0402 sbc sba2 ;perform subtract +35d1 : 08 php +35d2 : c50f cmp adrl ;check result + trap_ne ;bad result +35d4 : d0fe > bne * ;failed not equal (non zero) + +35d6 : 68 pla ;check flags +35d7 : 29c3 and #$c3 ;mask NV----ZC +35d9 : c511 cmp adrf + trap_ne ;bad flags +35db : d0fe > bne * ;failed not equal (non zero) + +35dd : 28 plp + ; binary ADC / SBC # +35de : 08 php ;save carry for subtract +35df : a50e lda ad2 +35e1 : 8d1202 sta ex_adci+1 ;set ADC # operand +35e4 : a50d lda ad1 +35e6 : 201102 jsr ex_adci ;execute ADC # in RAM +35e9 : 08 php +35ea : c50f cmp adrl ;check result + trap_ne ;bad result +35ec : d0fe > bne * ;failed not equal (non zero) + +35ee : 68 pla ;check flags +35ef : 29c3 and #$c3 ;mask NV----ZC +35f1 : c511 cmp adrf + trap_ne ;bad flags +35f3 : d0fe > bne * ;failed not equal (non zero) + +35f5 : 28 plp +35f6 : 08 php ;save carry for next add +35f7 : a512 lda sb2 +35f9 : 8d1502 sta ex_sbci+1 ;set SBC # operand +35fc : a50d lda ad1 +35fe : 201402 jsr ex_sbci ;execute SBC # in RAM +3601 : 08 php +3602 : c50f cmp adrl ;check result + trap_ne ;bad result +3604 : d0fe > bne * ;failed not equal (non zero) + +3606 : 68 pla ;check flags +3607 : 29c3 and #$c3 ;mask NV----ZC +3609 : c511 cmp adrf + trap_ne ;bad flags +360b : d0fe > bne * ;failed not equal (non zero) + +360d : 28 plp + ; binary ADC / SBC zp,x +360e : 08 php ;save carry for subtract +360f : a50d lda ad1 +3611 : 7500 adc 0,x ;perform add +3613 : 08 php +3614 : c50f cmp adrl ;check result + trap_ne ;bad result +3616 : d0fe > bne * ;failed not equal (non zero) + +3618 : 68 pla ;check flags +3619 : 29c3 and #$c3 ;mask NV----ZC +361b : c511 cmp adrf + trap_ne ;bad flags +361d : d0fe > bne * ;failed not equal (non zero) + +361f : 28 plp +3620 : 08 php ;save carry for next add +3621 : a50d lda ad1 +3623 : f504 sbc sb2-ad2,x ;perform subtract +3625 : 08 php +3626 : c50f cmp adrl ;check result + trap_ne ;bad result +3628 : d0fe > bne * ;failed not equal (non zero) + +362a : 68 pla ;check flags +362b : 29c3 and #$c3 ;mask NV----ZC +362d : c511 cmp adrf + trap_ne ;bad flags +362f : d0fe > bne * ;failed not equal (non zero) + +3631 : 28 plp + ; binary ADC / SBC abs,x +3632 : 08 php ;save carry for subtract +3633 : a50d lda ad1 +3635 : 7df501 adc ada2-ad2,x ;perform add +3638 : 08 php +3639 : c50f cmp adrl ;check result + trap_ne ;bad result +363b : d0fe > bne * ;failed not equal (non zero) + +363d : 68 pla ;check flags +363e : 29c3 and #$c3 ;mask NV----ZC +3640 : c511 cmp adrf + trap_ne ;bad flags +3642 : d0fe > bne * ;failed not equal (non zero) + +3644 : 28 plp +3645 : 08 php ;save carry for next add +3646 : a50d lda ad1 +3648 : fdf601 sbc sba2-ad2,x ;perform subtract +364b : 08 php +364c : c50f cmp adrl ;check result + trap_ne ;bad result +364e : d0fe > bne * ;failed not equal (non zero) + +3650 : 68 pla ;check flags +3651 : 29c3 and #$c3 ;mask NV----ZC +3653 : c511 cmp adrf + trap_ne ;bad flags +3655 : d0fe > bne * ;failed not equal (non zero) + +3657 : 28 plp + ; binary ADC / SBC abs,y +3658 : 08 php ;save carry for subtract +3659 : a50d lda ad1 +365b : 790401 adc ada2-$ff,y ;perform add +365e : 08 php +365f : c50f cmp adrl ;check result + trap_ne ;bad result +3661 : d0fe > bne * ;failed not equal (non zero) + +3663 : 68 pla ;check flags +3664 : 29c3 and #$c3 ;mask NV----ZC +3666 : c511 cmp adrf + trap_ne ;bad flags +3668 : d0fe > bne * ;failed not equal (non zero) + +366a : 28 plp +366b : 08 php ;save carry for next add +366c : a50d lda ad1 +366e : f90501 sbc sba2-$ff,y ;perform subtract +3671 : 08 php +3672 : c50f cmp adrl ;check result + trap_ne ;bad result +3674 : d0fe > bne * ;failed not equal (non zero) + +3676 : 68 pla ;check flags +3677 : 29c3 and #$c3 ;mask NV----ZC +3679 : c511 cmp adrf + trap_ne ;bad flags +367b : d0fe > bne * ;failed not equal (non zero) + +367d : 28 plp + ; binary ADC / SBC (zp,x) +367e : 08 php ;save carry for subtract +367f : a50d lda ad1 +3681 : 6144 adc (lo adi2-ad2,x) ;perform add +3683 : 08 php +3684 : c50f cmp adrl ;check result + trap_ne ;bad result +3686 : d0fe > bne * ;failed not equal (non zero) + +3688 : 68 pla ;check flags +3689 : 29c3 and #$c3 ;mask NV----ZC +368b : c511 cmp adrf + trap_ne ;bad flags +368d : d0fe > bne * ;failed not equal (non zero) + +368f : 28 plp +3690 : 08 php ;save carry for next add +3691 : a50d lda ad1 +3693 : e146 sbc (lo sbi2-ad2,x) ;perform subtract +3695 : 08 php +3696 : c50f cmp adrl ;check result + trap_ne ;bad result +3698 : d0fe > bne * ;failed not equal (non zero) + +369a : 68 pla ;check flags +369b : 29c3 and #$c3 ;mask NV----ZC +369d : c511 cmp adrf + trap_ne ;bad flags +369f : d0fe > bne * ;failed not equal (non zero) + +36a1 : 28 plp + ; binary ADC / SBC (abs),y +36a2 : 08 php ;save carry for subtract +36a3 : a50d lda ad1 +36a5 : 7156 adc (adiy2),y ;perform add +36a7 : 08 php +36a8 : c50f cmp adrl ;check result + trap_ne ;bad result +36aa : d0fe > bne * ;failed not equal (non zero) + +36ac : 68 pla ;check flags +36ad : 29c3 and #$c3 ;mask NV----ZC +36af : c511 cmp adrf + trap_ne ;bad flags +36b1 : d0fe > bne * ;failed not equal (non zero) + +36b3 : 28 plp +36b4 : 08 php ;save carry for next add +36b5 : a50d lda ad1 +36b7 : f158 sbc (sbiy2),y ;perform subtract +36b9 : 08 php +36ba : c50f cmp adrl ;check result + trap_ne ;bad result +36bc : d0fe > bne * ;failed not equal (non zero) + +36be : 68 pla ;check flags +36bf : 29c3 and #$c3 ;mask NV----ZC +36c1 : c511 cmp adrf + trap_ne ;bad flags +36c3 : d0fe > bne * ;failed not equal (non zero) + +36c5 : 28 plp +36c6 : 60 rts + + ; target for the jump absolute test +36c7 : 88 dey +36c8 : 88 dey +36c9 : test_far +36c9 : 08 php ;either SP or Y count will fai +36ca : 88 dey +36cb : 88 dey +36cc : 88 dey +36cd : 28 plp + trap_cs ;flags loaded? +36ce : b0fe > bcs * ;failed carry set + + trap_vs +36d0 : 70fe > bvs * ;failed overflow set + + trap_mi +36d2 : 30fe > bmi * ;failed minus (bit 7 set) + + trap_eq +36d4 : f0fe > beq * ;failed equal (zero) + +36d6 : c946 cmp #'F' ;registers loaded? + trap_ne +36d8 : d0fe > bne * ;failed not equal (non zero) + +36da : e041 cpx #'A' + trap_ne +36dc : d0fe > bne * ;failed not equal (non zero) + +36de : c04f cpy #('R'-3) + trap_ne +36e0 : d0fe > bne * ;failed not equal (non zero) + +36e2 : 48 pha ;save a,x +36e3 : 8a txa +36e4 : 48 pha +36e5 : ba tsx +36e6 : e0fd cpx #$fd ;check SP + trap_ne +36e8 : d0fe > bne * ;failed not equal (non zero) + +36ea : 68 pla ;restore x +36eb : aa tax + set_stat $ff + > load_flag $ff +36ec : a9ff > lda #$ff ;allow test to change + > +36ee : 48 > pha ;use stack to load status +36ef : 28 > plp + +36f0 : 68 pla ;restore a +36f1 : e8 inx ;return registers with modific +36f2 : 49aa eor #$aa ;N=1, V=1, Z=0, C=1 +36f4 : 4c0f09 jmp far_ret + + ; target for the jump indirect test +36f7 : 00 align +36f8 : 0137 ptr_tst_ind dw test_ind +36fa : 6409 ptr_ind_ret dw ind_ret + trap ;runover protection +36fc : 4cfc36 > jmp * ;failed anyway + +36ff : 88 dey +3700 : 88 dey +3701 : test_ind +3701 : 08 php ;either SP or Y count will fai +3702 : 88 dey +3703 : 88 dey +3704 : 88 dey +3705 : 28 plp + trap_cs ;flags loaded? +3706 : b0fe > bcs * ;failed carry set + + trap_vs +3708 : 70fe > bvs * ;failed overflow set + + trap_mi +370a : 30fe > bmi * ;failed minus (bit 7 set) + + trap_eq +370c : f0fe > beq * ;failed equal (zero) + +370e : c949 cmp #'I' ;registers loaded? + trap_ne +3710 : d0fe > bne * ;failed not equal (non zero) + +3712 : e04e cpx #'N' + trap_ne +3714 : d0fe > bne * ;failed not equal (non zero) + +3716 : c041 cpy #('D'-3) + trap_ne +3718 : d0fe > bne * ;failed not equal (non zero) + +371a : 48 pha ;save a,x +371b : 8a txa +371c : 48 pha +371d : ba tsx +371e : e0fd cpx #$fd ;check SP + trap_ne +3720 : d0fe > bne * ;failed not equal (non zero) + +3722 : 68 pla ;restore x +3723 : aa tax + set_stat $ff + > load_flag $ff +3724 : a9ff > lda #$ff ;allow test to change + > +3726 : 48 > pha ;use stack to load status +3727 : 28 > plp + +3728 : 68 pla ;restore a +3729 : e8 inx ;return registers with modific +372a : 49aa eor #$aa ;N=1, V=1, Z=0, C=1 +372c : 6cfa36 jmp (ptr_ind_ret) + trap ;runover protection +372f : 4c2f37 > jmp * ;failed anyway + + + ; target for the jump subroutine test +3732 : 88 dey +3733 : 88 dey +3734 : test_jsr +3734 : 08 php ;either SP or Y count will fai +3735 : 88 dey +3736 : 88 dey +3737 : 88 dey +3738 : 28 plp + trap_cs ;flags loaded? +3739 : b0fe > bcs * ;failed carry set + + trap_vs +373b : 70fe > bvs * ;failed overflow set + + trap_mi +373d : 30fe > bmi * ;failed minus (bit 7 set) + + trap_eq +373f : f0fe > beq * ;failed equal (zero) + +3741 : c94a cmp #'J' ;registers loaded? + trap_ne +3743 : d0fe > bne * ;failed not equal (non zero) + +3745 : e053 cpx #'S' + trap_ne +3747 : d0fe > bne * ;failed not equal (non zero) + +3749 : c04f cpy #('R'-3) + trap_ne +374b : d0fe > bne * ;failed not equal (non zero) + +374d : 48 pha ;save a,x +374e : 8a txa +374f : 48 pha +3750 : ba tsx ;sp -4? (return addr,a,x) +3751 : e0fb cpx #$fb + trap_ne +3753 : d0fe > bne * ;failed not equal (non zero) + +3755 : adff01 lda $1ff ;propper return on stack +3758 : c909 cmp #hi(jsr_ret) + trap_ne +375a : d0fe > bne * ;failed not equal (non zero) + +375c : adfe01 lda $1fe +375f : c99a cmp #lo(jsr_ret) + trap_ne +3761 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +3763 : a9ff > lda #$ff ;allow test to change + > +3765 : 48 > pha ;use stack to load status +3766 : 28 > plp + +3767 : 68 pla ;pull x,a +3768 : aa tax +3769 : 68 pla +376a : e8 inx ;return registers with modific +376b : 49aa eor #$aa ;N=1, V=1, Z=0, C=1 +376d : 60 rts + trap ;runover protection +376e : 4c6e37 > jmp * ;failed anyway + + + ;trap in case of unexpected IRQ, NMI, BRK, RESET - BRK +3771 : nmi_trap + trap ;check stack for conditions at +3771 : 4c7137 > jmp * ;failed anyway + +3774 : res_trap + trap ;unexpected RESET +3774 : 4c7437 > jmp * ;failed anyway + + +3777 : 88 dey +3778 : 88 dey +3779 : irq_trap ;BRK test or unextpected BRK o +3779 : 08 php ;either SP or Y count will fai +377a : 88 dey +377b : 88 dey +377c : 88 dey + ;next 4 traps could be caused by unexpected BR + ;check stack for BREAK and originating locatio + ;possible jump/branch into weeds (uninitialize +377d : c942 cmp #'B' ;registers loaded? + trap_ne +377f : d0fe > bne * ;failed not equal (non zero) + +3781 : e052 cpx #'R' + trap_ne +3783 : d0fe > bne * ;failed not equal (non zero) + +3785 : c048 cpy #('K'-3) + trap_ne +3787 : d0fe > bne * ;failed not equal (non zero) + +3789 : 850a sta irq_a ;save registers during break t +378b : 860b stx irq_x +378d : ba tsx ;test break on stack +378e : bd0201 lda $102,x + cmp_flag 0 ;break test should have B=1 +3791 : c930 > cmp #(0 |fao)&m8 ;expected flags + + + trap_ne ; - no break flag on stack +3793 : d0fe > bne * ;failed not equal (non zero) + +3795 : 68 pla +3796 : c934 cmp #fai ;should have added interrupt d + trap_ne +3798 : d0fe > bne * ;failed not equal (non zero) + +379a : ba tsx +379b : e0fc cpx #$fc ;sp -3? (return addr, flags) + trap_ne +379d : d0fe > bne * ;failed not equal (non zero) + +379f : adff01 lda $1ff ;propper return on stack +37a2 : c909 cmp #hi(brk_ret) + trap_ne +37a4 : d0fe > bne * ;failed not equal (non zero) + +37a6 : adfe01 lda $1fe +37a9 : c9d1 cmp #lo(brk_ret) + trap_ne +37ab : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +37ad : a9ff > lda #$ff ;allow test to change + > +37af : 48 > pha ;use stack to load status +37b0 : 28 > plp + +37b1 : a60b ldx irq_x +37b3 : e8 inx ;return registers with modific +37b4 : a50a lda irq_a +37b6 : 49aa eor #$aa ;N=1, V=1, Z=0, C=1 but origin +37b8 : 40 rti + trap ;runover protection +37b9 : 4cb937 > jmp * ;failed anyway + + + if report = 1 + include "report.i65" + endif + + ;copy of data to initialize BSS segment + if load_data_direct != 1 + zp_init + zp1_ db $c3,$82,$41,0 ;test patterns for LDx BIT + zp7f_ db $7f ;test pattern for compare + ;logical zeropage operands + zpOR_ db 0,$1f,$71,$80 ;test pattern for OR + zpAN_ db $0f,$ff,$7f,$80 ;test pattern for AND + zpEO_ db $ff,$0f,$8f,$8f ;test pattern for EOR + ;indirect addressing pointers + ind1_ dw abs1 ;indirect pointer to patte + dw abs1+1 + dw abs1+2 + dw abs1+3 + dw abs7f + inw1_ dw abs1-$f8 ;indirect pointer for wrap + indt_ dw abst ;indirect pointer to store + dw abst+1 + dw abst+2 + dw abst+3 + inwt_ dw abst-$f8 ;indirect pointer for wrap + indAN_ dw absAN ;indirect pointer to AND p + dw absAN+1 + dw absAN+2 + dw absAN+3 + indEO_ dw absEO ;indirect pointer to EOR p + dw absEO+1 + dw absEO+2 + dw absEO+3 + indOR_ dw absOR ;indirect pointer to OR pa + dw absOR+1 + dw absOR+2 + dw absOR+3 + ;add/subtract indirect pointers + adi2_ dw ada2 ;indirect pointer to opera + sbi2_ dw sba2 ;indirect pointer to compl + adiy2_ dw ada2-$ff ;with offset for indirect + sbiy2_ dw sba2-$ff + zp_end + if (zp_end - zp_init) != (zp_bss_end - zp_bss) + ;force assembler error if size is different + ERROR ERROR ERROR ;mismatch between bss and + endif + data_init + ex_and_ and #0 ;execute immediate opcodes + rts + ex_eor_ eor #0 ;execute immediate opcodes + rts + ex_ora_ ora #0 ;execute immediate opcodes + rts + ex_adc_ adc #0 ;execute immediate opcodes + rts + ex_sbc_ sbc #0 ;execute immediate opcodes + rts + abs1_ db $c3,$82,$41,0 ;test patterns for LDx BIT + abs7f_ db $7f ;test pattern for compare + ;loads + fLDx_ db fn,fn,0,fz ;expected flags for load + ;shifts + rASL_ ;expected result ASL & ROL + rROL_ db $86,$04,$82,0 ; " + rROLc_ db $87,$05,$83,1 ;expected result ROL +carr + rLSR_ ;expected result LSR & ROR + rROR_ db $61,$41,$20,0 ; " + rRORc_ db $e1,$c1,$a0,$80 ;expected result ROR +carr + fASL_ ;expected flags for shifts + fROL_ db fnc,fc,fn,fz ;no carry in + fROLc_ db fnc,fc,fn,0 ;carry in + fLSR_ + fROR_ db fc,0,fc,fz ;no carry in + fRORc_ db fnc,fn,fnc,fn ;carry in + ;increments (decrements) + rINC_ db $7f,$80,$ff,0,1 ;expected result for INC/D + fINC_ db 0,fn,fn,fz,0 ;expected flags for INC/DE + ;logical memory operand + absOR_ db 0,$1f,$71,$80 ;test pattern for OR + absAN_ db $0f,$ff,$7f,$80 ;test pattern for AND + absEO_ db $ff,$0f,$8f,$8f ;test pattern for EOR + ;logical accu operand + absORa_ db 0,$f1,$1f,0 ;test pattern for OR + absANa_ db $f0,$ff,$ff,$ff ;test pattern for AND + absEOa_ db $ff,$f0,$f0,$0f ;test pattern for EOR + ;logical results + absrlo_ db 0,$ff,$7f,$80 + absflo_ db fz,fn,0,fn + data_end + if (data_end - data_init) != (data_bss_end - data_ + ;force assembler error if size is different + ERROR ERROR ERROR ;mismatch between bss and + endif + + vec_init + dw nmi_trap + dw res_trap + dw irq_trap + vec_bss equ $fffa + endif ;end of RAM init data + + if (load_data_direct = 1) & (ROM_vectors = 1) +fffa = org $fffa ;vectors +fffa : 7137 dw nmi_trap +fffc : 7437 dw res_trap +fffe : 7937 dw irq_trap + endif + +fffa = end start + +No errors in pass 2. +Wrote binary from address $0000 through $ffff. +Total size 65536 bytes. +Program start address is at $0400 (1024). + \ No newline at end of file diff --git a/6502_functional_test.asm b/6502_functional_test.asm new file mode 100644 index 0000000..17b68c1 --- /dev/null +++ b/6502_functional_test.asm @@ -0,0 +1,6011 @@ +; +; 6 5 0 2 F U N C T I O N A L T E S T +; +; Copyright (C) 2012-2015 Klaus Dormann +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation, either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see . + + +; This program is designed to test all opcodes of a 6502 emulator using all +; addressing modes with focus on propper setting of the processor status +; register bits. +; +; version 21-oct-2015 +; contact info at http://2m5.de or email K@2m5.de +; +; assembled with AS65 from http://www.kingswood-consulting.co.uk/assemblers/ +; command line switches: -l -m -s2 -w -h0 +; | | | | no page headers in listing +; | | | wide listing (133 char/col) +; | | write intel hex file instead of binary +; | expand macros in listing +; generate pass2 listing +; +; No IO - should be run from a monitor with access to registers. +; To run load intel hex image with a load command, than alter PC to 400 hex +; (code_segment) and enter a go command. +; Loop on program counter determines error or successful completion of test. +; Check listing for relevant traps (jump/branch *). +; Please note that in early tests some instructions will have to be used before +; they are actually tested! +; +; RESET, NMI or IRQ should not occur and will be trapped if vectors are enabled. +; Tests documented behavior of the original NMOS 6502 only! No unofficial +; opcodes. Additional opcodes of newer versions of the CPU (65C02, 65816) will +; not be tested. Decimal ops will only be tested with valid BCD operands and +; N V Z flags will be ignored. +; +; Debugging hints: +; Most of the code is written sequentially. if you hit a trap, check the +; immediately preceeding code for the instruction to be tested. Results are +; tested first, flags are checked second by pushing them onto the stack and +; pulling them to the accumulator after the result was checked. The "real" +; flags are no longer valid for the tested instruction at this time! +; If the tested instruction was indexed, the relevant index (X or Y) must +; also be checked. Opposed to the flags, X and Y registers are still valid. +; +; versions: +; 28-jul-2012 1st version distributed for testing +; 29-jul-2012 fixed references to location 0, now #0 +; added license - GPLv3 +; 30-jul-2012 added configuration options +; 01-aug-2012 added trap macro to allow user to change error handling +; 01-dec-2012 fixed trap in branch field must be a branch +; 02-mar-2013 fixed PLA flags not tested +; 19-jul-2013 allowed ROM vectors to be loaded when load_data_direct = 0 +; added test sequence check to detect if tests jump their fence +; 23-jul-2013 added RAM integrity check option +; 16-aug-2013 added error report to standard output option +; 13-dec-2014 added binary/decimal opcode table switch test +; 14-dec-2014 improved relative address test +; 23-aug-2015 added option to disable self modifying tests +; 24-aug-2015 all self modifying immediate opcodes now execute in data RAM +; added small branch offset pretest +; 21-oct-2015 added option to disable decimal mode ADC & SBC tests + + +; C O N F I G U R A T I O N + +;ROM_vectors writable (0=no, 1=yes) +;if ROM vectors can not be used interrupts will not be trapped +;as a consequence BRK can not be tested but will be emulated to test RTI +ROM_vectors = 1 + +;load_data_direct (0=move from code segment, 1=load directly) +;loading directly is preferred but may not be supported by your platform +;0 produces only consecutive object code, 1 is not suitable for a binary image +load_data_direct = 1 + +;I_flag behavior (0=force enabled, 1=force disabled, 2=prohibit change, 3=allow +;change) 2 requires extra code and is not recommended. SEI & CLI can only be +;tested if you allow changing the interrupt status (I_flag = 3) +I_flag = 3 + +;configure memory - try to stay away from memory used by the system +;zero_page memory start address, $50 (80) consecutive Bytes required +; add 2 if I_flag = 2 +zero_page = $a + +;data_segment memory start address, $6A (106) consecutive Bytes required +data_segment = $200 + if (data_segment & $ff) != 0 + ERROR ERROR ERROR low byte of data_segment MUST be $00 !! + endif + +;code_segment memory start address, 13kB of consecutive space required +; add 2.5 kB if I_flag = 2 +code_segment = $400 + +;self modifying code may be disabled to allow running in ROM +;0=part of the code is self modifying and must reside in RAM +;1=tests disabled: branch range +disable_selfmod = 0 + +;report errors through I/O channel (0=use standard self trap loops, 1=include +;report.i65 as I/O channel, add 3.5 kB) +report = 0 + +;RAM integrity test option. Checks for undesired RAM writes. +;set lowest non RAM or RAM mirror address page (-1=disable, 0=64k, $40=16k) +;leave disabled if a monitor, OS or background interrupt is allowed to alter RAM +ram_top = -1 + +;disable test decimal mode ADC & SBC, 0=enable, 1=disable, +;2=disable including decimal flag in processor status +disable_decimal = 0 + + noopt ;do not take shortcuts + +;macros for error & success traps to allow user modification +;example: +;trap macro +; jsr my_error_handler +; endm +;trap_eq macro +; bne skip\? +; trap ;failed equal (zero) +;skip\? +; endm +; +; my_error_handler should pop the calling address from the stack and report it. +; putting larger portions of code (more than 3 bytes) inside the trap macro +; may lead to branch range problems for some tests. + if report = 0 +trap macro + jmp * ;failed anyway + endm +trap_eq macro + beq * ;failed equal (zero) + endm +trap_ne macro + bne * ;failed not equal (non zero) + endm +trap_cs macro + bcs * ;failed carry set + endm +trap_cc macro + bcc * ;failed carry clear + endm +trap_mi macro + bmi * ;failed minus (bit 7 set) + endm +trap_pl macro + bpl * ;failed plus (bit 7 clear) + endm +trap_vs macro + bvs * ;failed overflow set + endm +trap_vc macro + bvc * ;failed overflow clear + endm +; please observe that during the test the stack gets invalidated +; therefore a RTS inside the success macro is not possible +success macro + jmp * ;test passed, no errors + endm + endif + if report = 1 +trap macro + jsr report_error + endm +trap_eq macro + bne skip\? + trap ;failed equal (zero) +skip\? + endm +trap_ne macro + beq skip\? + trap ;failed not equal (non zero) +skip\? + endm +trap_cs macro + bcc skip\? + trap ;failed carry set +skip\? + endm +trap_cc macro + bcs skip\? + trap ;failed carry clear +skip\? + endm +trap_mi macro + bpl skip\? + trap ;failed minus (bit 7 set) +skip\? + endm +trap_pl macro + bmi skip\? + trap ;failed plus (bit 7 clear) +skip\? + endm +trap_vs macro + bvc skip\? + trap ;failed overflow set +skip\? + endm +trap_vc macro + bvs skip\? + trap ;failed overflow clear +skip\? + endm +; please observe that during the test the stack gets invalidated +; therefore a RTS inside the success macro is not possible +success macro + jsr report_success + endm + endif + + +carry equ %00000001 ;flag bits in status +zero equ %00000010 +intdis equ %00000100 +decmode equ %00001000 +break equ %00010000 +reserv equ %00100000 +overfl equ %01000000 +minus equ %10000000 + +fc equ carry +fz equ zero +fzc equ carry+zero +fv equ overfl +fvz equ overfl+zero +fn equ minus +fnc equ minus+carry +fnz equ minus+zero +fnzc equ minus+zero+carry +fnv equ minus+overfl + +fao equ break+reserv ;bits always on after PHP, BRK +fai equ fao+intdis ;+ forced interrupt disable +faod equ fao+decmode ;+ ignore decimal +faid equ fai+decmode ;+ ignore decimal +m8 equ $ff ;8 bit mask +m8i equ $ff&~intdis ;8 bit mask - interrupt disable + +;macros to allow masking of status bits. +;masking test of decimal bit +;masking of interrupt enable/disable on load and compare +;masking of always on bits after PHP or BRK (unused & break) on compare + if disable_decimal < 2 + if I_flag = 0 +load_flag macro + lda #\1&m8i ;force enable interrupts (mask I) + endm +cmp_flag macro + cmp #(\1|fao)&m8i ;I_flag is always enabled + always on bits + endm +eor_flag macro + eor #(\1&m8i|fao) ;mask I, invert expected flags + always on bits + endm + endif + if I_flag = 1 +load_flag macro + lda #\1|intdis ;force disable interrupts + endm +cmp_flag macro + cmp #(\1|fai)&m8 ;I_flag is always disabled + always on bits + endm +eor_flag macro + eor #(\1|fai) ;invert expected flags + always on bits + I + endm + endif + if I_flag = 2 +load_flag macro + lda #\1 + ora flag_I_on ;restore I-flag + and flag_I_off + endm +cmp_flag macro + eor flag_I_on ;I_flag is never changed + cmp #(\1|fao)&m8i ;expected flags + always on bits, mask I + endm +eor_flag macro + eor flag_I_on ;I_flag is never changed + eor #(\1&m8i|fao) ;mask I, invert expected flags + always on bits + endm + endif + if I_flag = 3 +load_flag macro + lda #\1 ;allow test to change I-flag (no mask) + endm +cmp_flag macro + cmp #(\1|fao)&m8 ;expected flags + always on bits + endm +eor_flag macro + eor #\1|fao ;invert expected flags + always on bits + endm + endif + else + if I_flag = 0 +load_flag macro + lda #\1&m8i ;force enable interrupts (mask I) + endm +cmp_flag macro + ora #decmode ;ignore decimal mode bit + cmp #(\1|faod)&m8i ;I_flag is always enabled + always on bits + endm +eor_flag macro + ora #decmode ;ignore decimal mode bit + eor #(\1&m8i|faod) ;mask I, invert expected flags + always on bits + endm + endif + if I_flag = 1 +load_flag macro + lda #\1|intdis ;force disable interrupts + endm +cmp_flag macro + ora #decmode ;ignore decimal mode bit + cmp #(\1|faid)&m8 ;I_flag is always disabled + always on bits + endm +eor_flag macro + ora #decmode ;ignore decimal mode bit + eor #(\1|faid) ;invert expected flags + always on bits + I + endm + endif + if I_flag = 2 +load_flag macro + lda #\1 + ora flag_I_on ;restore I-flag + and flag_I_off + endm +cmp_flag macro + eor flag_I_on ;I_flag is never changed + ora #decmode ;ignore decimal mode bit + cmp #(\1|faod)&m8i ;expected flags + always on bits, mask I + endm +eor_flag macro + eor flag_I_on ;I_flag is never changed + ora #decmode ;ignore decimal mode bit + eor #(\1&m8i|faod) ;mask I, invert expected flags + always on bits + endm + endif + if I_flag = 3 +load_flag macro + lda #\1 ;allow test to change I-flag (no mask) + endm +cmp_flag macro + ora #decmode ;ignore decimal mode bit + cmp #(\1|faod)&m8 ;expected flags + always on bits + endm +eor_flag macro + ora #decmode ;ignore decimal mode bit + eor #\1|faod ;invert expected flags + always on bits + endm + endif + endif + +;macros to set (register|memory|zeropage) & status +set_stat macro ;setting flags in the processor status register + load_flag \1 + pha ;use stack to load status + plp + endm + +set_a macro ;precharging accu & status + load_flag \2 + pha ;use stack to load status + lda #\1 ;precharge accu + plp + endm + +set_x macro ;precharging index & status + load_flag \2 + pha ;use stack to load status + ldx #\1 ;precharge index x + plp + endm + +set_y macro ;precharging index & status + load_flag \2 + pha ;use stack to load status + ldy #\1 ;precharge index y + plp + endm + +set_ax macro ;precharging indexed accu & immediate status + load_flag \2 + pha ;use stack to load status + lda \1,x ;precharge accu + plp + endm + +set_ay macro ;precharging indexed accu & immediate status + load_flag \2 + pha ;use stack to load status + lda \1,y ;precharge accu + plp + endm + +set_z macro ;precharging indexed zp & immediate status + load_flag \2 + pha ;use stack to load status + lda \1,x ;load to zeropage + sta zpt + plp + endm + +set_zx macro ;precharging zp,x & immediate status + load_flag \2 + pha ;use stack to load status + lda \1,x ;load to indexed zeropage + sta zpt,x + plp + endm + +set_abs macro ;precharging indexed memory & immediate status + load_flag \2 + pha ;use stack to load status + lda \1,x ;load to memory + sta abst + plp + endm + +set_absx macro ;precharging abs,x & immediate status + load_flag \2 + pha ;use stack to load status + lda \1,x ;load to indexed memory + sta abst,x + plp + endm + +;macros to test (register|memory|zeropage) & status & (mask) +tst_stat macro ;testing flags in the processor status register + php ;save status + pla ;use stack to retrieve status + pha + cmp_flag \1 + trap_ne + plp ;restore status + endm + +tst_a macro ;testing result in accu & flags + php ;save flags + cmp #\1 ;test result + trap_ne + pla ;load status + pha + cmp_flag \2 + trap_ne + plp ;restore status + endm + +tst_x macro ;testing result in x index & flags + php ;save flags + cpx #\1 ;test result + trap_ne + pla ;load status + pha + cmp_flag \2 + trap_ne + plp ;restore status + endm + +tst_y macro ;testing result in y index & flags + php ;save flags + cpy #\1 ;test result + trap_ne + pla ;load status + pha + cmp_flag \2 + trap_ne + plp ;restore status + endm + +tst_ax macro ;indexed testing result in accu & flags + php ;save flags + cmp \1,x ;test result + trap_ne + pla ;load status + eor_flag \3 + cmp \2,x ;test flags + trap_ne ; + endm + +tst_ay macro ;indexed testing result in accu & flags + php ;save flags + cmp \1,y ;test result + trap_ne ; + pla ;load status + eor_flag \3 + cmp \2,y ;test flags + trap_ne + endm + +tst_z macro ;indexed testing result in zp & flags + php ;save flags + lda zpt + cmp \1,x ;test result + trap_ne + pla ;load status + eor_flag \3 + cmp \2,x ;test flags + trap_ne + endm + +tst_zx macro ;testing result in zp,x & flags + php ;save flags + lda zpt,x + cmp \1,x ;test result + trap_ne + pla ;load status + eor_flag \3 + cmp \2,x ;test flags + trap_ne + endm + +tst_abs macro ;indexed testing result in memory & flags + php ;save flags + lda abst + cmp \1,x ;test result + trap_ne + pla ;load status + eor_flag \3 + cmp \2,x ;test flags + trap_ne + endm + +tst_absx macro ;testing result in abs,x & flags + php ;save flags + lda abst,x + cmp \1,x ;test result + trap_ne + pla ;load status + eor_flag \3 + cmp \2,x ;test flags + trap_ne + endm + +; RAM integrity test +; verifies that none of the previous tests has altered RAM outside of the +; designated write areas. +; uses zpt word as indirect pointer, zpt+2 word as checksum + if ram_top > -1 +check_ram macro + cld + lda #0 + sta zpt ;set low byte of indirect pointer + sta zpt+3 ;checksum high byte + if disable_selfmod = 0 + sta range_adr ;reset self modifying code + endif + clc + ldx #zp_bss-zero_page ;zeropage - write test area +ccs3\? adc zero_page,x + bcc ccs2\? + inc zpt+3 ;carry to high byte + clc +ccs2\? inx + bne ccs3\? + ldx #hi(abs1) ;set high byte of indirect pointer + stx zpt+1 + ldy #lo(abs1) ;data after write & execute test area +ccs5\? adc (zpt),y + bcc ccs4\? + inc zpt+3 ;carry to high byte + clc +ccs4\? iny + bne ccs5\? + inx ;advance RAM high address + stx zpt+1 + cpx #ram_top + bne ccs5\? + sta zpt+2 ;checksum low is + cmp ram_chksm ;checksum low expected + trap_ne ;checksum mismatch + lda zpt+3 ;checksum high is + cmp ram_chksm+1 ;checksum high expected + trap_ne ;checksum mismatch + endm + else +check_ram macro + ;RAM check disabled - RAM size not set + endm + endif + +next_test macro ;make sure, tests don't jump the fence + lda test_case ;previous test + cmp #test_num + trap_ne ;test is out of sequence +test_num = test_num + 1 + lda #test_num ;*** next tests' number + sta test_case + ;check_ram ;uncomment to find altered RAM after each test + endm + + if load_data_direct = 1 + data + else + bss ;uninitialized segment, copy of data at end of code! + endif + org 0 ;edited to load from 0x0000 (was: org zero_page) + ds zero_page ;see above (this line added) +;break test interrupt save +irq_a ds 1 ;a register +irq_x ds 1 ;x register + if I_flag = 2 +;masking for I bit in status +flag_I_on ds 1 ;or mask to load flags +flag_I_off ds 1 ;and mask to load flags + endif +zpt ;5 bytes store/modify test area +;add/subtract operand generation and result/flag prediction +adfc ds 1 ;carry flag before op +ad1 ds 1 ;operand 1 - accumulator +ad2 ds 1 ;operand 2 - memory / immediate +adrl ds 1 ;expected result bits 0-7 +adrh ds 1 ;expected result bit 8 (carry) +adrf ds 1 ;expected flags NV0000ZC (only binary mode) +sb2 ds 1 ;operand 2 complemented for subtract +zp_bss +zp1 db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR +zp7f db $7f ;test pattern for compare +;logical zeropage operands +zpOR db 0,$1f,$71,$80 ;test pattern for OR +zpAN db $0f,$ff,$7f,$80 ;test pattern for AND +zpEO db $ff,$0f,$8f,$8f ;test pattern for EOR +;indirect addressing pointers +ind1 dw abs1 ;indirect pointer to pattern in absolute memory + dw abs1+1 + dw abs1+2 + dw abs1+3 + dw abs7f +inw1 dw abs1-$f8 ;indirect pointer for wrap-test pattern +indt dw abst ;indirect pointer to store area in absolute memory + dw abst+1 + dw abst+2 + dw abst+3 +inwt dw abst-$f8 ;indirect pointer for wrap-test store +indAN dw absAN ;indirect pointer to AND pattern in absolute memory + dw absAN+1 + dw absAN+2 + dw absAN+3 +indEO dw absEO ;indirect pointer to EOR pattern in absolute memory + dw absEO+1 + dw absEO+2 + dw absEO+3 +indOR dw absOR ;indirect pointer to OR pattern in absolute memory + dw absOR+1 + dw absOR+2 + dw absOR+3 +;add/subtract indirect pointers +adi2 dw ada2 ;indirect pointer to operand 2 in absolute memory +sbi2 dw sba2 ;indirect pointer to complemented operand 2 (SBC) +adiy2 dw ada2-$ff ;with offset for indirect indexed +sbiy2 dw sba2-$ff +zp_bss_end + + org data_segment +test_case ds 1 ;current test number +ram_chksm ds 2 ;checksum for RAM integrity test +;add/subtract operand copy - abs tests write area +abst ;5 bytes store/modify test area +ada2 ds 1 ;operand 2 +sba2 ds 1 ;operand 2 complemented for subtract + ds 3 ;fill remaining bytes +data_bss + if load_data_direct = 1 +ex_andi and #0 ;execute immediate opcodes + rts +ex_eori eor #0 ;execute immediate opcodes + rts +ex_orai ora #0 ;execute immediate opcodes + rts +ex_adci adc #0 ;execute immediate opcodes + rts +ex_sbci sbc #0 ;execute immediate opcodes + rts + else +ex_andi ds 3 +ex_eori ds 3 +ex_orai ds 3 +ex_adci ds 3 +ex_sbci ds 3 + endif +abs1 db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR +abs7f db $7f ;test pattern for compare +;loads +fLDx db fn,fn,0,fz ;expected flags for load +;shifts +rASL ;expected result ASL & ROL -carry +rROL db $86,$04,$82,0 ; " +rROLc db $87,$05,$83,1 ;expected result ROL +carry +rLSR ;expected result LSR & ROR -carry +rROR db $61,$41,$20,0 ; " +rRORc db $e1,$c1,$a0,$80 ;expected result ROR +carry +fASL ;expected flags for shifts +fROL db fnc,fc,fn,fz ;no carry in +fROLc db fnc,fc,fn,0 ;carry in +fLSR +fROR db fc,0,fc,fz ;no carry in +fRORc db fnc,fn,fnc,fn ;carry in +;increments (decrements) +rINC db $7f,$80,$ff,0,1 ;expected result for INC/DEC +fINC db 0,fn,fn,fz,0 ;expected flags for INC/DEC +;logical memory operand +absOR db 0,$1f,$71,$80 ;test pattern for OR +absAN db $0f,$ff,$7f,$80 ;test pattern for AND +absEO db $ff,$0f,$8f,$8f ;test pattern for EOR +;logical accu operand +absORa db 0,$f1,$1f,0 ;test pattern for OR +absANa db $f0,$ff,$ff,$ff ;test pattern for AND +absEOa db $ff,$f0,$f0,$0f ;test pattern for EOR +;logical results +absrlo db 0,$ff,$7f,$80 +absflo db fz,fn,0,fn +data_bss_end + + + code + org code_segment +start cld + ldx #$ff + txs + lda #0 ;*** test 0 = initialize + sta test_case +test_num = 0 + +;stop interrupts before initializing BSS + if I_flag = 1 + sei + endif + +;initialize I/O for report channel + if report = 1 + jsr report_init + endif + +;pretest small branch offset + ldx #5 + jmp psb_test +psb_bwok + ldy #5 + bne psb_forw + trap ;branch should be taken + dey ;forward landing zone + dey + dey + dey + dey +psb_forw + dey + dey + dey + dey + dey + beq psb_fwok + trap ;forward offset + + dex ;backward landing zone + dex + dex + dex + dex +psb_back + dex + dex + dex + dex + dex + beq psb_bwok + trap ;backward offset +psb_test + bne psb_back + trap ;branch should be taken +psb_fwok + +;initialize BSS segment + if load_data_direct != 1 + ldx #zp_end-zp_init-1 +ld_zp lda zp_init,x + sta zp_bss,x + dex + bpl ld_zp + ldx #data_end-data_init-1 +ld_data lda data_init,x + sta data_bss,x + dex + bpl ld_data + if ROM_vectors = 1 + ldx #5 +ld_vect lda vec_init,x + sta vec_bss,x + dex + bpl ld_vect + endif + endif + +;retain status of interrupt flag + if I_flag = 2 + php + pla + and #4 ;isolate flag + sta flag_I_on ;or mask + eor #lo(~4) ;reverse + sta flag_I_off ;and mask + endif + +;generate checksum for RAM integrity test + if ram_top > -1 + lda #0 + sta zpt ;set low byte of indirect pointer + sta ram_chksm+1 ;checksum high byte + if disable_selfmod = 0 + sta range_adr ;reset self modifying code + endif + clc + ldx #zp_bss-zero_page ;zeropage - write test area +gcs3 adc zero_page,x + bcc gcs2 + inc ram_chksm+1 ;carry to high byte + clc +gcs2 inx + bne gcs3 + ldx #hi(abs1) ;set high byte of indirect pointer + stx zpt+1 + ldy #lo(abs1) ;data after write & execute test area +gcs5 adc (zpt),y + bcc gcs4 + inc ram_chksm+1 ;carry to high byte + clc +gcs4 iny + bne gcs5 + inx ;advance RAM high address + stx zpt+1 + cpx #ram_top + bne gcs5 + sta ram_chksm ;checksum complete + endif + next_test + + if disable_selfmod = 0 +;testing relative addressing with BEQ + ldy #$fe ;testing maximum range, not -1/-2 (invalid/self adr) +range_loop + dey ;next relative address + tya + tax ;precharge count to end of loop + bpl range_fw ;calculate relative address + clc ;avoid branch self or to relative address of branch + adc #2 + nop ;offset landing zone - tolerate +/-5 offset to branch + nop + nop + nop + nop +range_fw + nop + nop + nop + nop + nop + eor #$7f ;complement except sign + sta range_adr ;load into test target + lda #0 ;should set zero flag in status register + jmp range_op + + dex ; offset landing zone - backward branch too far + dex + dex + dex + dex + ;relative address target field with branch under test in the middle + dex ;-128 - max backward + dex + dex + dex + dex + dex + dex + dex + dex ;-120 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-110 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-100 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-90 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-80 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-70 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-60 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-50 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-40 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-30 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-20 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-10 + dex + dex + dex + dex + dex + dex + dex ;-3 +range_op ;test target with zero flag=0, z=1 if previous dex +range_adr = *+1 ;modifiable relative address + beq *+64 ;+64 if called without modification + dex ;+0 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+10 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+20 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+30 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+40 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+50 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+60 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+70 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+80 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+90 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+100 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+110 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+120 + dex + dex + dex + dex + dex + dex + nop ;offset landing zone - forward branch too far + nop + nop + nop + nop + beq range_ok ;+127 - max forward + trap ; bad range + nop ;offset landing zone - tolerate +/-5 offset to branch + nop + nop + nop + nop +range_ok + nop + nop + nop + nop + nop + cpy #0 + beq range_end + jmp range_loop +range_end ;range test successful + endif + next_test + +;partial test BNE & CMP, CPX, CPY immediate + cpy #1 ;testing BNE true + bne test_bne + trap +test_bne + lda #0 + cmp #0 ;test compare immediate + trap_ne + trap_cc + trap_mi + cmp #1 + trap_eq + trap_cs + trap_pl + tax + cpx #0 ;test compare x immediate + trap_ne + trap_cc + trap_mi + cpx #1 + trap_eq + trap_cs + trap_pl + tay + cpy #0 ;test compare y immediate + trap_ne + trap_cc + trap_mi + cpy #1 + trap_eq + trap_cs + trap_pl + next_test +;testing stack operations PHA PHP PLA PLP + + ldx #$ff ;initialize stack + txs + lda #$55 + pha + lda #$aa + pha + cmp $1fe ;on stack ? + trap_ne + tsx + txa ;overwrite accu + cmp #$fd ;sp decremented? + trap_ne + pla + cmp #$aa ;successful retreived from stack? + trap_ne + pla + cmp #$55 + trap_ne + cmp $1ff ;remains on stack? + trap_ne + tsx + cpx #$ff ;sp incremented? + trap_ne + next_test + +;testing branch decisions BPL BMI BVC BVS BCC BCS BNE BEQ + set_stat $ff ;all on + bpl nbr1 ;branches should not be taken + bvc nbr2 + bcc nbr3 + bne nbr4 + bmi br1 ;branches should be taken + trap +br1 bvs br2 + trap +br2 bcs br3 + trap +br3 beq br4 + trap +nbr1 + trap ;previous bpl taken +nbr2 + trap ;previous bvc taken +nbr3 + trap ;previous bcc taken +nbr4 + trap ;previous bne taken +br4 php + tsx + cpx #$fe ;sp after php? + trap_ne + pla + cmp_flag $ff ;returned all flags on? + trap_ne + tsx + cpx #$ff ;sp after php? + trap_ne + set_stat 0 ;all off + bmi nbr11 ;branches should not be taken + bvs nbr12 + bcs nbr13 + beq nbr14 + bpl br11 ;branches should be taken + trap +br11 bvc br12 + trap +br12 bcc br13 + trap +br13 bne br14 + trap +nbr11 + trap ;previous bmi taken +nbr12 + trap ;previous bvs taken +nbr13 + trap ;previous bcs taken +nbr14 + trap ;previous beq taken +br14 php + pla + cmp_flag 0 ;flags off except break (pushed by sw) + reserved? + trap_ne + ;crosscheck flags + set_stat zero + bne brzs1 + beq brzs2 +brzs1 + trap ;branch zero/non zero +brzs2 bcs brzs3 + bcc brzs4 +brzs3 + trap ;branch carry/no carry +brzs4 bmi brzs5 + bpl brzs6 +brzs5 + trap ;branch minus/plus +brzs6 bvs brzs7 + bvc brzs8 +brzs7 + trap ;branch overflow/no overflow +brzs8 + set_stat carry + beq brcs1 + bne brcs2 +brcs1 + trap ;branch zero/non zero +brcs2 bcc brcs3 + bcs brcs4 +brcs3 + trap ;branch carry/no carry +brcs4 bmi brcs5 + bpl brcs6 +brcs5 + trap ;branch minus/plus +brcs6 bvs brcs7 + bvc brcs8 +brcs7 + trap ;branch overflow/no overflow + +brcs8 + set_stat minus + beq brmi1 + bne brmi2 +brmi1 + trap ;branch zero/non zero +brmi2 bcs brmi3 + bcc brmi4 +brmi3 + trap ;branch carry/no carry +brmi4 bpl brmi5 + bmi brmi6 +brmi5 + trap ;branch minus/plus +brmi6 bvs brmi7 + bvc brmi8 +brmi7 + trap ;branch overflow/no overflow +brmi8 + set_stat overfl + beq brvs1 + bne brvs2 +brvs1 + trap ;branch zero/non zero +brvs2 bcs brvs3 + bcc brvs4 +brvs3 + trap ;branch carry/no carry +brvs4 bmi brvs5 + bpl brvs6 +brvs5 + trap ;branch minus/plus +brvs6 bvc brvs7 + bvs brvs8 +brvs7 + trap ;branch overflow/no overflow +brvs8 + set_stat $ff-zero + beq brzc1 + bne brzc2 +brzc1 + trap ;branch zero/non zero +brzc2 bcc brzc3 + bcs brzc4 +brzc3 + trap ;branch carry/no carry +brzc4 bpl brzc5 + bmi brzc6 +brzc5 + trap ;branch minus/plus +brzc6 bvc brzc7 + bvs brzc8 +brzc7 + trap ;branch overflow/no overflow +brzc8 + set_stat $ff-carry + bne brcc1 + beq brcc2 +brcc1 + trap ;branch zero/non zero +brcc2 bcs brcc3 + bcc brcc4 +brcc3 + trap ;branch carry/no carry +brcc4 bpl brcc5 + bmi brcc6 +brcc5 + trap ;branch minus/plus +brcc6 bvc brcc7 + bvs brcc8 +brcc7 + trap ;branch overflow/no overflow +brcc8 + set_stat $ff-minus + bne brpl1 + beq brpl2 +brpl1 + trap ;branch zero/non zero +brpl2 bcc brpl3 + bcs brpl4 +brpl3 + trap ;branch carry/no carry +brpl4 bmi brpl5 + bpl brpl6 +brpl5 + trap ;branch minus/plus +brpl6 bvc brpl7 + bvs brpl8 +brpl7 + trap ;branch overflow/no overflow +brpl8 + set_stat $ff-overfl + bne brvc1 + beq brvc2 +brvc1 + trap ;branch zero/non zero +brvc2 bcc brvc3 + bcs brvc4 +brvc3 + trap ;branch carry/no carry +brvc4 bpl brvc5 + bmi brvc6 +brvc5 + trap ;branch minus/plus +brvc6 bvs brvc7 + bvc brvc8 +brvc7 + trap ;branch overflow/no overflow +brvc8 + next_test + +; test PHA does not alter flags or accumulator but PLA does + ldx #$55 ;x & y protected + ldy #$aa + set_a 1,$ff ;push + pha + tst_a 1,$ff + set_a 0,0 + pha + tst_a 0,0 + set_a $ff,$ff + pha + tst_a $ff,$ff + set_a 1,0 + pha + tst_a 1,0 + set_a 0,$ff + pha + tst_a 0,$ff + set_a $ff,0 + pha + tst_a $ff,0 + set_a 0,$ff ;pull + pla + tst_a $ff,$ff-zero + set_a $ff,0 + pla + tst_a 0,zero + set_a $fe,$ff + pla + tst_a 1,$ff-zero-minus + set_a 0,0 + pla + tst_a $ff,minus + set_a $ff,$ff + pla + tst_a 0,$ff-minus + set_a $fe,0 + pla + tst_a 1,0 + cpx #$55 ;x & y unchanged? + trap_ne + cpy #$aa + trap_ne + next_test + +; partial pretest EOR # + set_a $3c,0 + eor #$c3 + tst_a $ff,fn + set_a $c3,0 + eor #$c3 + tst_a 0,fz + next_test + +; PC modifying instructions except branches (NOP, JMP, JSR, RTS, BRK, RTI) +; testing NOP + ldx #$24 + ldy #$42 + set_a $18,0 + nop + tst_a $18,0 + cpx #$24 + trap_ne + cpy #$42 + trap_ne + ldx #$db + ldy #$bd + set_a $e7,$ff + nop + tst_a $e7,$ff + cpx #$db + trap_ne + cpy #$bd + trap_ne + next_test + +; jump absolute + set_stat $0 + lda #'F' + ldx #'A' + ldy #'R' ;N=0, V=0, Z=0, C=0 + jmp test_far + nop + nop + trap_ne ;runover protection + inx + inx +far_ret + trap_eq ;returned flags OK? + trap_pl + trap_cc + trap_vc + cmp #('F'^$aa) ;returned registers OK? + trap_ne + cpx #('A'+1) + trap_ne + cpy #('R'-3) + trap_ne + dex + iny + iny + iny + eor #$aa ;N=0, V=1, Z=0, C=1 + jmp test_near + nop + nop + trap_ne ;runover protection + inx + inx +test_near + trap_eq ;passed flags OK? + trap_mi + trap_cc + trap_vc + cmp #'F' ;passed registers OK? + trap_ne + cpx #'A' + trap_ne + cpy #'R' + trap_ne + next_test + +; jump indirect + set_stat 0 + lda #'I' + ldx #'N' + ldy #'D' ;N=0, V=0, Z=0, C=0 + jmp (ptr_tst_ind) + nop + trap_ne ;runover protection + dey + dey +ind_ret + php ;either SP or Y count will fail, if we do not hit + dey + dey + dey + plp + trap_eq ;returned flags OK? + trap_pl + trap_cc + trap_vc + cmp #('I'^$aa) ;returned registers OK? + trap_ne + cpx #('N'+1) + trap_ne + cpy #('D'-6) + trap_ne + tsx ;SP check + cpx #$ff + trap_ne + next_test + +; jump subroutine & return from subroutine + set_stat 0 + lda #'J' + ldx #'S' + ldy #'R' ;N=0, V=0, Z=0, C=0 + jsr test_jsr +jsr_ret = *-1 ;last address of jsr = return address + php ;either SP or Y count will fail, if we do not hit + dey + dey + dey + plp + trap_eq ;returned flags OK? + trap_pl + trap_cc + trap_vc + cmp #('J'^$aa) ;returned registers OK? + trap_ne + cpx #('S'+1) + trap_ne + cpy #('R'-6) + trap_ne + tsx ;sp? + cpx #$ff + trap_ne + next_test + +; break & return from interrupt + if ROM_vectors = 1 + set_stat 0 + lda #'B' + ldx #'R' + ldy #'K' ;N=0, V=0, Z=0, C=0 + brk + else + lda #hi brk_ret ;emulated break + pha + lda #lo brk_ret + pha + lda #fao ;set break & unused on stack + pha + set_stat intdis + lda #'B' + ldx #'R' + ldy #'K' ;N=0, V=0, Z=0, C=0 + jmp irq_trap + endif + dey ;should not be executed +brk_ret ;address of break return + php ;either SP or Y count will fail, if we do not hit + dey + dey + dey + cmp #('B'^$aa) ;returned registers OK? + trap_ne + cpx #('R'+1) + trap_ne + cpy #('K'-6) + trap_ne + pla ;returned flags OK (unchanged)? + cmp_flag 0 + trap_ne + tsx ;sp? + cpx #$ff + trap_ne + next_test + +; test set and clear flags CLC CLI CLD CLV SEC SEI SED + set_stat $ff + clc + tst_stat $ff-carry + sec + tst_stat $ff + if I_flag = 3 + cli + tst_stat $ff-intdis + sei + tst_stat $ff + endif + cld + tst_stat $ff-decmode + sed + tst_stat $ff + clv + tst_stat $ff-overfl + set_stat 0 + tst_stat 0 + sec + tst_stat carry + clc + tst_stat 0 + if I_flag = 3 + sei + tst_stat intdis + cli + tst_stat 0 + endif + sed + tst_stat decmode + cld + tst_stat 0 + set_stat overfl + tst_stat overfl + clv + tst_stat 0 + next_test +; testing index register increment/decrement and transfer +; INX INY DEX DEY TAX TXA TAY TYA + ldx #$fe + set_stat $ff + inx ;ff + tst_x $ff,$ff-zero + inx ;00 + tst_x 0,$ff-minus + inx ;01 + tst_x 1,$ff-minus-zero + dex ;00 + tst_x 0,$ff-minus + dex ;ff + tst_x $ff,$ff-zero + dex ;fe + set_stat 0 + inx ;ff + tst_x $ff,minus + inx ;00 + tst_x 0,zero + inx ;01 + tst_x 1,0 + dex ;00 + tst_x 0,zero + dex ;ff + tst_x $ff,minus + + ldy #$fe + set_stat $ff + iny ;ff + tst_y $ff,$ff-zero + iny ;00 + tst_y 0,$ff-minus + iny ;01 + tst_y 1,$ff-minus-zero + dey ;00 + tst_y 0,$ff-minus + dey ;ff + tst_y $ff,$ff-zero + dey ;fe + set_stat 0 + iny ;ff + tst_y $ff,0+minus + iny ;00 + tst_y 0,zero + iny ;01 + tst_y 1,0 + dey ;00 + tst_y 0,zero + dey ;ff + tst_y $ff,minus + + ldx #$ff + set_stat $ff + txa + tst_a $ff,$ff-zero + php + inx ;00 + plp + txa + tst_a 0,$ff-minus + php + inx ;01 + plp + txa + tst_a 1,$ff-minus-zero + set_stat 0 + txa + tst_a 1,0 + php + dex ;00 + plp + txa + tst_a 0,zero + php + dex ;ff + plp + txa + tst_a $ff,minus + + ldy #$ff + set_stat $ff + tya + tst_a $ff,$ff-zero + php + iny ;00 + plp + tya + tst_a 0,$ff-minus + php + iny ;01 + plp + tya + tst_a 1,$ff-minus-zero + set_stat 0 + tya + tst_a 1,0 + php + dey ;00 + plp + tya + tst_a 0,zero + php + dey ;ff + plp + tya + tst_a $ff,minus + + load_flag $ff + pha + ldx #$ff ;ff + txa + plp + tay + tst_y $ff,$ff-zero + php + inx ;00 + txa + plp + tay + tst_y 0,$ff-minus + php + inx ;01 + txa + plp + tay + tst_y 1,$ff-minus-zero + load_flag 0 + pha + lda #0 + txa + plp + tay + tst_y 1,0 + php + dex ;00 + txa + plp + tay + tst_y 0,zero + php + dex ;ff + txa + plp + tay + tst_y $ff,minus + + + load_flag $ff + pha + ldy #$ff ;ff + tya + plp + tax + tst_x $ff,$ff-zero + php + iny ;00 + tya + plp + tax + tst_x 0,$ff-minus + php + iny ;01 + tya + plp + tax + tst_x 1,$ff-minus-zero + load_flag 0 + pha + lda #0 ;preset status + tya + plp + tax + tst_x 1,0 + php + dey ;00 + tya + plp + tax + tst_x 0,zero + php + dey ;ff + tya + plp + tax + tst_x $ff,minus + next_test + +;TSX sets NZ - TXS does not +; This section also tests for proper stack wrap around. + ldx #1 ;01 + set_stat $ff + txs + php + lda $101 + cmp_flag $ff + trap_ne + set_stat 0 + txs + php + lda $101 + cmp_flag 0 + trap_ne + dex ;00 + set_stat $ff + txs + php + lda $100 + cmp_flag $ff + trap_ne + set_stat 0 + txs + php + lda $100 + cmp_flag 0 + trap_ne + dex ;ff + set_stat $ff + txs + php + lda $1ff + cmp_flag $ff + trap_ne + set_stat 0 + txs + php + lda $1ff + cmp_flag 0 + + ldx #1 + txs ;sp=01 + set_stat $ff + tsx ;clears Z, N + php ;sp=00 + cpx #1 + trap_ne + lda $101 + cmp_flag $ff-minus-zero + trap_ne + set_stat $ff + tsx ;clears N, sets Z + php ;sp=ff + cpx #0 + trap_ne + lda $100 + cmp_flag $ff-minus + trap_ne + set_stat $ff + tsx ;clears N, sets Z + php ;sp=fe + cpx #$ff + trap_ne + lda $1ff + cmp_flag $ff-zero + trap_ne + + ldx #1 + txs ;sp=01 + set_stat 0 + tsx ;clears Z, N + php ;sp=00 + cpx #1 + trap_ne + lda $101 + cmp_flag 0 + trap_ne + set_stat 0 + tsx ;clears N, sets Z + php ;sp=ff + cpx #0 + trap_ne + lda $100 + cmp_flag zero + trap_ne + set_stat 0 + tsx ;clears N, sets Z + php ;sp=fe + cpx #$ff + trap_ne + lda $1ff + cmp_flag minus + trap_ne + pla ;sp=ff + next_test + +; testing index register load & store LDY LDX STY STX all addressing modes +; LDX / STX - zp,y / abs,y + ldy #3 +tldx + set_stat 0 + ldx zp1,y + php ;test stores do not alter flags + txa + eor #$c3 + plp + sta abst,y + php ;flags after load/store sequence + eor #$c3 + cmp abs1,y ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,y ;test flags + trap_ne + dey + bpl tldx + + ldy #3 +tldx1 + set_stat $ff + ldx zp1,y + php ;test stores do not alter flags + txa + eor #$c3 + plp + sta abst,y + php ;flags after load/store sequence + eor #$c3 + cmp abs1,y ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,y ;test flags + trap_ne + dey + bpl tldx1 + + ldy #3 +tldx2 + set_stat 0 + ldx abs1,y + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt,y + php ;flags after load/store sequence + eor #$c3 + cmp zp1,y ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,y ;test flags + trap_ne + dey + bpl tldx2 + + ldy #3 +tldx3 + set_stat $ff + ldx abs1,y + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt,y + php ;flags after load/store sequence + eor #$c3 + cmp zp1,y ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,y ;test flags + trap_ne + dey + bpl tldx3 + + ldy #3 ;testing store result + ldx #0 +tstx lda zpt,y + eor #$c3 + cmp zp1,y + trap_ne ;store to zp data + stx zpt,y ;clear + lda abst,y + eor #$c3 + cmp abs1,y + trap_ne ;store to abs data + txa + sta abst,y ;clear + dey + bpl tstx + next_test + +; indexed wraparound test (only zp should wrap) + ldy #3+$fa +tldx4 ldx zp1-$fa&$ff,y ;wrap on indexed zp + txa + sta abst-$fa,y ;no STX abs,y! + dey + cpy #$fa + bcs tldx4 + ldy #3+$fa +tldx5 ldx abs1-$fa,y ;no wrap on indexed abs + stx zpt-$fa&$ff,y + dey + cpy #$fa + bcs tldx5 + ldy #3 ;testing wraparound result + ldx #0 +tstx1 lda zpt,y + cmp zp1,y + trap_ne ;store to zp data + stx zpt,y ;clear + lda abst,y + cmp abs1,y + trap_ne ;store to abs data + txa + sta abst,y ;clear + dey + bpl tstx1 + next_test + +; LDY / STY - zp,x / abs,x + ldx #3 +tldy + set_stat 0 + ldy zp1,x + php ;test stores do not alter flags + tya + eor #$c3 + plp + sta abst,x + php ;flags after load/store sequence + eor #$c3 + cmp abs1,x ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,x ;test flags + trap_ne + dex + bpl tldy + + ldx #3 +tldy1 + set_stat $ff + ldy zp1,x + php ;test stores do not alter flags + tya + eor #$c3 + plp + sta abst,x + php ;flags after load/store sequence + eor #$c3 + cmp abs1,x ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,x ;test flags + trap_ne + dex + bpl tldy1 + + ldx #3 +tldy2 + set_stat 0 + ldy abs1,x + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt,x + php ;flags after load/store sequence + eor #$c3 + cmp zp1,x ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,x ;test flags + trap_ne + dex + bpl tldy2 + + ldx #3 +tldy3 + set_stat $ff + ldy abs1,x + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt,x + php ;flags after load/store sequence + eor #$c3 + cmp zp1,x ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,x ;test flags + trap_ne + dex + bpl tldy3 + + ldx #3 ;testing store result + ldy #0 +tsty lda zpt,x + eor #$c3 + cmp zp1,x + trap_ne ;store to zp,x data + sty zpt,x ;clear + lda abst,x + eor #$c3 + cmp abs1,x + trap_ne ;store to abs,x data + txa + sta abst,x ;clear + dex + bpl tsty + next_test + +; indexed wraparound test (only zp should wrap) + ldx #3+$fa +tldy4 ldy zp1-$fa&$ff,x ;wrap on indexed zp + tya + sta abst-$fa,x ;no STX abs,x! + dex + cpx #$fa + bcs tldy4 + ldx #3+$fa +tldy5 ldy abs1-$fa,x ;no wrap on indexed abs + sty zpt-$fa&$ff,x + dex + cpx #$fa + bcs tldy5 + ldx #3 ;testing wraparound result + ldy #0 +tsty1 lda zpt,x + cmp zp1,x + trap_ne ;store to zp,x data + sty zpt,x ;clear + lda abst,x + cmp abs1,x + trap_ne ;store to abs,x data + txa + sta abst,x ;clear + dex + bpl tsty1 + next_test + +; LDX / STX - zp / abs / # + set_stat 0 + ldx zp1 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx abst + php ;flags after load/store sequence + eor #$c3 + tax + cpx #$c3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + ldx zp1+1 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx abst+1 + php ;flags after load/store sequence + eor #$c3 + tax + cpx #$82 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + ldx zp1+2 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx abst+2 + php ;flags after load/store sequence + eor #$c3 + tax + cpx #$41 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + ldx zp1+3 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx abst+3 + php ;flags after load/store sequence + eor #$c3 + tax + cpx #0 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + + set_stat $ff + ldx zp1 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx abst + php ;flags after load/store sequence + eor #$c3 + tax + cpx #$c3 ;test result + trap_ne ; + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + ldx zp1+1 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx abst+1 + php ;flags after load/store sequence + eor #$c3 + tax + cpx #$82 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + ldx zp1+2 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx abst+2 + php ;flags after load/store sequence + eor #$c3 + tax + cpx #$41 ;test result + trap_ne ; + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + ldx zp1+3 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx abst+3 + php ;flags after load/store sequence + eor #$c3 + tax + cpx #0 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + + set_stat 0 + ldx abs1 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt + php ;flags after load/store sequence + eor #$c3 + cmp zp1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + ldx abs1+1 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt+1 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + ldx abs1+2 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt+2 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+2 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + ldx abs1+3 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt+3 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + + set_stat $ff + ldx abs1 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt + php ;flags after load/store sequence + eor #$c3 + tax + cpx zp1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + ldx abs1+1 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt+1 + php ;flags after load/store sequence + eor #$c3 + tax + cpx zp1+1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + ldx abs1+2 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt+2 + php ;flags after load/store sequence + eor #$c3 + tax + cpx zp1+2 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + ldx abs1+3 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt+3 + php ;flags after load/store sequence + eor #$c3 + tax + cpx zp1+3 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + + set_stat 0 + ldx #$c3 + php + cpx abs1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + ldx #$82 + php + cpx abs1+1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + ldx #$41 + php + cpx abs1+2 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + ldx #0 + php + cpx abs1+3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + + set_stat $ff + ldx #$c3 + php + cpx abs1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + ldx #$82 + php + cpx abs1+1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + ldx #$41 + php + cpx abs1+2 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + ldx #0 + php + cpx abs1+3 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + + ldx #0 + lda zpt + eor #$c3 + cmp zp1 + trap_ne ;store to zp data + stx zpt ;clear + lda abst + eor #$c3 + cmp abs1 + trap_ne ;store to abs data + stx abst ;clear + lda zpt+1 + eor #$c3 + cmp zp1+1 + trap_ne ;store to zp data + stx zpt+1 ;clear + lda abst+1 + eor #$c3 + cmp abs1+1 + trap_ne ;store to abs data + stx abst+1 ;clear + lda zpt+2 + eor #$c3 + cmp zp1+2 + trap_ne ;store to zp data + stx zpt+2 ;clear + lda abst+2 + eor #$c3 + cmp abs1+2 + trap_ne ;store to abs data + stx abst+2 ;clear + lda zpt+3 + eor #$c3 + cmp zp1+3 + trap_ne ;store to zp data + stx zpt+3 ;clear + lda abst+3 + eor #$c3 + cmp abs1+3 + trap_ne ;store to abs data + stx abst+3 ;clear + next_test + +; LDY / STY - zp / abs / # + set_stat 0 + ldy zp1 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty abst + php ;flags after load/store sequence + eor #$c3 + tay + cpy #$c3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + ldy zp1+1 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty abst+1 + php ;flags after load/store sequence + eor #$c3 + tay + cpy #$82 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + ldy zp1+2 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty abst+2 + php ;flags after load/store sequence + eor #$c3 + tay + cpy #$41 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + ldy zp1+3 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty abst+3 + php ;flags after load/store sequence + eor #$c3 + tay + cpy #0 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + + set_stat $ff + ldy zp1 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty abst + php ;flags after load/store sequence + eor #$c3 + tay + cpy #$c3 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + ldy zp1+1 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty abst+1 + php ;flags after load/store sequence + eor #$c3 + tay + cpy #$82 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + ldy zp1+2 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty abst+2 + php ;flags after load/store sequence + eor #$c3 + tay + cpy #$41 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + ldy zp1+3 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty abst+3 + php ;flags after load/store sequence + eor #$c3 + tay + cpy #0 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + + set_stat 0 + ldy abs1 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt + php ;flags after load/store sequence + eor #$c3 + tay + cpy zp1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + ldy abs1+1 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt+1 + php ;flags after load/store sequence + eor #$c3 + tay + cpy zp1+1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + ldy abs1+2 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt+2 + php ;flags after load/store sequence + eor #$c3 + tay + cpy zp1+2 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + ldy abs1+3 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt+3 + php ;flags after load/store sequence + eor #$c3 + tay + cpy zp1+3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + + set_stat $ff + ldy abs1 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt + php ;flags after load/store sequence + eor #$c3 + tay + cmp zp1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + ldy abs1+1 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt+1 + php ;flags after load/store sequence + eor #$c3 + tay + cmp zp1+1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + ldy abs1+2 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt+2 + php ;flags after load/store sequence + eor #$c3 + tay + cmp zp1+2 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + ldy abs1+3 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt+3 + php ;flags after load/store sequence + eor #$c3 + tay + cmp zp1+3 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + + + set_stat 0 + ldy #$c3 + php + cpy abs1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + ldy #$82 + php + cpy abs1+1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + ldy #$41 + php + cpy abs1+2 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + ldy #0 + php + cpy abs1+3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + + set_stat $ff + ldy #$c3 + php + cpy abs1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + ldy #$82 + php + cpy abs1+1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + ldy #$41 + php + cpy abs1+2 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + ldy #0 + php + cpy abs1+3 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + + ldy #0 + lda zpt + eor #$c3 + cmp zp1 + trap_ne ;store to zp data + sty zpt ;clear + lda abst + eor #$c3 + cmp abs1 + trap_ne ;store to abs data + sty abst ;clear + lda zpt+1 + eor #$c3 + cmp zp1+1 + trap_ne ;store to zp+1 data + sty zpt+1 ;clear + lda abst+1 + eor #$c3 + cmp abs1+1 + trap_ne ;store to abs+1 data + sty abst+1 ;clear + lda zpt+2 + eor #$c3 + cmp zp1+2 + trap_ne ;store to zp+2 data + sty zpt+2 ;clear + lda abst+2 + eor #$c3 + cmp abs1+2 + trap_ne ;store to abs+2 data + sty abst+2 ;clear + lda zpt+3 + eor #$c3 + cmp zp1+3 + trap_ne ;store to zp+3 data + sty zpt+3 ;clear + lda abst+3 + eor #$c3 + cmp abs1+3 + trap_ne ;store to abs+3 data + sty abst+3 ;clear + next_test + +; testing load / store accumulator LDA / STA all addressing modes +; LDA / STA - zp,x / abs,x + ldx #3 +tldax + set_stat 0 + lda zp1,x + php ;test stores do not alter flags + eor #$c3 + plp + sta abst,x + php ;flags after load/store sequence + eor #$c3 + cmp abs1,x ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,x ;test flags + trap_ne + dex + bpl tldax + + ldx #3 +tldax1 + set_stat $ff + lda zp1,x + php ;test stores do not alter flags + eor #$c3 + plp + sta abst,x + php ;flags after load/store sequence + eor #$c3 + cmp abs1,x ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,x ;test flags + trap_ne + dex + bpl tldax1 + + ldx #3 +tldax2 + set_stat 0 + lda abs1,x + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt,x + php ;flags after load/store sequence + eor #$c3 + cmp zp1,x ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,x ;test flags + trap_ne + dex + bpl tldax2 + + ldx #3 +tldax3 + set_stat $ff + lda abs1,x + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt,x + php ;flags after load/store sequence + eor #$c3 + cmp zp1,x ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,x ;test flags + trap_ne + dex + bpl tldax3 + + ldx #3 ;testing store result + ldy #0 +tstax lda zpt,x + eor #$c3 + cmp zp1,x + trap_ne ;store to zp,x data + sty zpt,x ;clear + lda abst,x + eor #$c3 + cmp abs1,x + trap_ne ;store to abs,x data + txa + sta abst,x ;clear + dex + bpl tstax + next_test + +; LDA / STA - (zp),y / abs,y / (zp,x) + ldy #3 +tlday + set_stat 0 + lda (ind1),y + php ;test stores do not alter flags + eor #$c3 + plp + sta abst,y + php ;flags after load/store sequence + eor #$c3 + cmp abs1,y ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,y ;test flags + trap_ne + dey + bpl tlday + + ldy #3 +tlday1 + set_stat $ff + lda (ind1),y + php ;test stores do not alter flags + eor #$c3 + plp + sta abst,y + php ;flags after load/store sequence + eor #$c3 + cmp abs1,y ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,y ;test flags + trap_ne + dey + bpl tlday1 + + ldy #3 ;testing store result + ldx #0 +tstay lda abst,y + eor #$c3 + cmp abs1,y + trap_ne ;store to abs data + txa + sta abst,y ;clear + dey + bpl tstay + + ldy #3 +tlday2 + set_stat 0 + lda abs1,y + php ;test stores do not alter flags + eor #$c3 + plp + sta (indt),y + php ;flags after load/store sequence + eor #$c3 + cmp (ind1),y ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,y ;test flags + trap_ne + dey + bpl tlday2 + + ldy #3 +tlday3 + set_stat $ff + lda abs1,y + php ;test stores do not alter flags + eor #$c3 + plp + sta (indt),y + php ;flags after load/store sequence + eor #$c3 + cmp (ind1),y ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,y ;test flags + trap_ne + dey + bpl tlday3 + + ldy #3 ;testing store result + ldx #0 +tstay1 lda abst,y + eor #$c3 + cmp abs1,y + trap_ne ;store to abs data + txa + sta abst,y ;clear + dey + bpl tstay1 + + ldx #6 + ldy #3 +tldax4 + set_stat 0 + lda (ind1,x) + php ;test stores do not alter flags + eor #$c3 + plp + sta (indt,x) + php ;flags after load/store sequence + eor #$c3 + cmp abs1,y ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,y ;test flags + trap_ne + dex + dex + dey + bpl tldax4 + + ldx #6 + ldy #3 +tldax5 + set_stat $ff + lda (ind1,x) + php ;test stores do not alter flags + eor #$c3 + plp + sta (indt,x) + php ;flags after load/store sequence + eor #$c3 + cmp abs1,y ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,y ;test flags + trap_ne + dex + dex + dey + bpl tldax5 + + ldy #3 ;testing store result + ldx #0 +tstay2 lda abst,y + eor #$c3 + cmp abs1,y + trap_ne ;store to abs data + txa + sta abst,y ;clear + dey + bpl tstay2 + next_test + +; indexed wraparound test (only zp should wrap) + ldx #3+$fa +tldax6 lda zp1-$fa&$ff,x ;wrap on indexed zp + sta abst-$fa,x ;no STX abs,x! + dex + cpx #$fa + bcs tldax6 + ldx #3+$fa +tldax7 lda abs1-$fa,x ;no wrap on indexed abs + sta zpt-$fa&$ff,x + dex + cpx #$fa + bcs tldax7 + + ldx #3 ;testing wraparound result + ldy #0 +tstax1 lda zpt,x + cmp zp1,x + trap_ne ;store to zp,x data + sty zpt,x ;clear + lda abst,x + cmp abs1,x + trap_ne ;store to abs,x data + txa + sta abst,x ;clear + dex + bpl tstax1 + + ldy #3+$f8 + ldx #6+$f8 +tlday4 lda (ind1-$f8&$ff,x) ;wrap on indexed zp indirect + sta abst-$f8,y + dex + dex + dey + cpy #$f8 + bcs tlday4 + ldy #3 ;testing wraparound result + ldx #0 +tstay4 lda abst,y + cmp abs1,y + trap_ne ;store to abs data + txa + sta abst,y ;clear + dey + bpl tstay4 + + ldy #3+$f8 +tlday5 lda abs1-$f8,y ;no wrap on indexed abs + sta (inwt),y + dey + cpy #$f8 + bcs tlday5 + ldy #3 ;testing wraparound result + ldx #0 +tstay5 lda abst,y + cmp abs1,y + trap_ne ;store to abs data + txa + sta abst,y ;clear + dey + bpl tstay5 + + ldy #3+$f8 + ldx #6+$f8 +tlday6 lda (inw1),y ;no wrap on zp indirect indexed + sta (indt-$f8&$ff,x) + dex + dex + dey + cpy #$f8 + bcs tlday6 + ldy #3 ;testing wraparound result + ldx #0 +tstay6 lda abst,y + cmp abs1,y + trap_ne ;store to abs data + txa + sta abst,y ;clear + dey + bpl tstay6 + next_test + +; LDA / STA - zp / abs / # + set_stat 0 + lda zp1 + php ;test stores do not alter flags + eor #$c3 + plp + sta abst + php ;flags after load/store sequence + eor #$c3 + cmp #$c3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + lda zp1+1 + php ;test stores do not alter flags + eor #$c3 + plp + sta abst+1 + php ;flags after load/store sequence + eor #$c3 + cmp #$82 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + lda zp1+2 + php ;test stores do not alter flags + eor #$c3 + plp + sta abst+2 + php ;flags after load/store sequence + eor #$c3 + cmp #$41 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + lda zp1+3 + php ;test stores do not alter flags + eor #$c3 + plp + sta abst+3 + php ;flags after load/store sequence + eor #$c3 + cmp #0 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + set_stat $ff + lda zp1 + php ;test stores do not alter flags + eor #$c3 + plp + sta abst + php ;flags after load/store sequence + eor #$c3 + cmp #$c3 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + lda zp1+1 + php ;test stores do not alter flags + eor #$c3 + plp + sta abst+1 + php ;flags after load/store sequence + eor #$c3 + cmp #$82 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + lda zp1+2 + php ;test stores do not alter flags + eor #$c3 + plp + sta abst+2 + php ;flags after load/store sequence + eor #$c3 + cmp #$41 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + lda zp1+3 + php ;test stores do not alter flags + eor #$c3 + plp + sta abst+3 + php ;flags after load/store sequence + eor #$c3 + cmp #0 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + set_stat 0 + lda abs1 + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt + php ;flags after load/store sequence + eor #$c3 + cmp zp1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + lda abs1+1 + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt+1 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + lda abs1+2 + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt+2 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+2 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + lda abs1+3 + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt+3 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + set_stat $ff + lda abs1 + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt + php ;flags after load/store sequence + eor #$c3 + cmp zp1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + lda abs1+1 + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt+1 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + lda abs1+2 + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt+2 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+2 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + lda abs1+3 + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt+3 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+3 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + set_stat 0 + lda #$c3 + php + cmp abs1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + lda #$82 + php + cmp abs1+1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + lda #$41 + php + cmp abs1+2 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + lda #0 + php + cmp abs1+3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + + set_stat $ff + lda #$c3 + php + cmp abs1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + lda #$82 + php + cmp abs1+1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + lda #$41 + php + cmp abs1+2 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + lda #0 + php + cmp abs1+3 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + + ldx #0 + lda zpt + eor #$c3 + cmp zp1 + trap_ne ;store to zp data + stx zpt ;clear + lda abst + eor #$c3 + cmp abs1 + trap_ne ;store to abs data + stx abst ;clear + lda zpt+1 + eor #$c3 + cmp zp1+1 + trap_ne ;store to zp data + stx zpt+1 ;clear + lda abst+1 + eor #$c3 + cmp abs1+1 + trap_ne ;store to abs data + stx abst+1 ;clear + lda zpt+2 + eor #$c3 + cmp zp1+2 + trap_ne ;store to zp data + stx zpt+2 ;clear + lda abst+2 + eor #$c3 + cmp abs1+2 + trap_ne ;store to abs data + stx abst+2 ;clear + lda zpt+3 + eor #$c3 + cmp zp1+3 + trap_ne ;store to zp data + stx zpt+3 ;clear + lda abst+3 + eor #$c3 + cmp abs1+3 + trap_ne ;store to abs data + stx abst+3 ;clear + next_test + +; testing bit test & compares BIT CPX CPY CMP all addressing modes +; BIT - zp / abs + set_a $ff,0 + bit zp1+3 ;00 - should set Z / clear NV + tst_a $ff,fz + set_a 1,0 + bit zp1+2 ;41 - should set V (M6) / clear NZ + tst_a 1,fv + set_a 1,0 + bit zp1+1 ;82 - should set N (M7) & Z / clear V + tst_a 1,fnz + set_a 1,0 + bit zp1 ;c3 - should set N (M7) & V (M6) / clear Z + tst_a 1,fnv + + set_a $ff,$ff + bit zp1+3 ;00 - should set Z / clear NV + tst_a $ff,~fnv + set_a 1,$ff + bit zp1+2 ;41 - should set V (M6) / clear NZ + tst_a 1,~fnz + set_a 1,$ff + bit zp1+1 ;82 - should set N (M7) & Z / clear V + tst_a 1,~fv + set_a 1,$ff + bit zp1 ;c3 - should set N (M7) & V (M6) / clear Z + tst_a 1,~fz + + set_a $ff,0 + bit abs1+3 ;00 - should set Z / clear NV + tst_a $ff,fz + set_a 1,0 + bit abs1+2 ;41 - should set V (M6) / clear NZ + tst_a 1,fv + set_a 1,0 + bit abs1+1 ;82 - should set N (M7) & Z / clear V + tst_a 1,fnz + set_a 1,0 + bit abs1 ;c3 - should set N (M7) & V (M6) / clear Z + tst_a 1,fnv + + set_a $ff,$ff + bit abs1+3 ;00 - should set Z / clear NV + tst_a $ff,~fnv + set_a 1,$ff + bit abs1+2 ;41 - should set V (M6) / clear NZ + tst_a 1,~fnz + set_a 1,$ff + bit abs1+1 ;82 - should set N (M7) & Z / clear V + tst_a 1,~fv + set_a 1,$ff + bit abs1 ;c3 - should set N (M7) & V (M6) / clear Z + tst_a 1,~fz + next_test + +; CPX - zp / abs / # + set_x $80,0 + cpx zp7f + tst_stat fc + dex + cpx zp7f + tst_stat fzc + dex + cpx zp7f + tst_x $7e,fn + set_x $80,$ff + cpx zp7f + tst_stat ~fnz + dex + cpx zp7f + tst_stat ~fn + dex + cpx zp7f + tst_x $7e,~fzc + + set_x $80,0 + cpx abs7f + tst_stat fc + dex + cpx abs7f + tst_stat fzc + dex + cpx abs7f + tst_x $7e,fn + set_x $80,$ff + cpx abs7f + tst_stat ~fnz + dex + cpx abs7f + tst_stat ~fn + dex + cpx abs7f + tst_x $7e,~fzc + + set_x $80,0 + cpx #$7f + tst_stat fc + dex + cpx #$7f + tst_stat fzc + dex + cpx #$7f + tst_x $7e,fn + set_x $80,$ff + cpx #$7f + tst_stat ~fnz + dex + cpx #$7f + tst_stat ~fn + dex + cpx #$7f + tst_x $7e,~fzc + next_test + +; CPY - zp / abs / # + set_y $80,0 + cpy zp7f + tst_stat fc + dey + cpy zp7f + tst_stat fzc + dey + cpy zp7f + tst_y $7e,fn + set_y $80,$ff + cpy zp7f + tst_stat ~fnz + dey + cpy zp7f + tst_stat ~fn + dey + cpy zp7f + tst_y $7e,~fzc + + set_y $80,0 + cpy abs7f + tst_stat fc + dey + cpy abs7f + tst_stat fzc + dey + cpy abs7f + tst_y $7e,fn + set_y $80,$ff + cpy abs7f + tst_stat ~fnz + dey + cpy abs7f + tst_stat ~fn + dey + cpy abs7f + tst_y $7e,~fzc + + set_y $80,0 + cpy #$7f + tst_stat fc + dey + cpy #$7f + tst_stat fzc + dey + cpy #$7f + tst_y $7e,fn + set_y $80,$ff + cpy #$7f + tst_stat ~fnz + dey + cpy #$7f + tst_stat ~fn + dey + cpy #$7f + tst_y $7e,~fzc + next_test + +; CMP - zp / abs / # + set_a $80,0 + cmp zp7f + tst_a $80,fc + set_a $7f,0 + cmp zp7f + tst_a $7f,fzc + set_a $7e,0 + cmp zp7f + tst_a $7e,fn + set_a $80,$ff + cmp zp7f + tst_a $80,~fnz + set_a $7f,$ff + cmp zp7f + tst_a $7f,~fn + set_a $7e,$ff + cmp zp7f + tst_a $7e,~fzc + + set_a $80,0 + cmp abs7f + tst_a $80,fc + set_a $7f,0 + cmp abs7f + tst_a $7f,fzc + set_a $7e,0 + cmp abs7f + tst_a $7e,fn + set_a $80,$ff + cmp abs7f + tst_a $80,~fnz + set_a $7f,$ff + cmp abs7f + tst_a $7f,~fn + set_a $7e,$ff + cmp abs7f + tst_a $7e,~fzc + + set_a $80,0 + cmp #$7f + tst_a $80,fc + set_a $7f,0 + cmp #$7f + tst_a $7f,fzc + set_a $7e,0 + cmp #$7f + tst_a $7e,fn + set_a $80,$ff + cmp #$7f + tst_a $80,~fnz + set_a $7f,$ff + cmp #$7f + tst_a $7f,~fn + set_a $7e,$ff + cmp #$7f + tst_a $7e,~fzc + + ldx #4 ;with indexing by X + set_a $80,0 + cmp zp1,x + tst_a $80,fc + set_a $7f,0 + cmp zp1,x + tst_a $7f,fzc + set_a $7e,0 + cmp zp1,x + tst_a $7e,fn + set_a $80,$ff + cmp zp1,x + tst_a $80,~fnz + set_a $7f,$ff + cmp zp1,x + tst_a $7f,~fn + set_a $7e,$ff + cmp zp1,x + tst_a $7e,~fzc + + set_a $80,0 + cmp abs1,x + tst_a $80,fc + set_a $7f,0 + cmp abs1,x + tst_a $7f,fzc + set_a $7e,0 + cmp abs1,x + tst_a $7e,fn + set_a $80,$ff + cmp abs1,x + tst_a $80,~fnz + set_a $7f,$ff + cmp abs1,x + tst_a $7f,~fn + set_a $7e,$ff + cmp abs1,x + tst_a $7e,~fzc + + ldy #4 ;with indexing by Y + ldx #8 ;with indexed indirect + set_a $80,0 + cmp abs1,y + tst_a $80,fc + set_a $7f,0 + cmp abs1,y + tst_a $7f,fzc + set_a $7e,0 + cmp abs1,y + tst_a $7e,fn + set_a $80,$ff + cmp abs1,y + tst_a $80,~fnz + set_a $7f,$ff + cmp abs1,y + tst_a $7f,~fn + set_a $7e,$ff + cmp abs1,y + tst_a $7e,~fzc + + set_a $80,0 + cmp (ind1,x) + tst_a $80,fc + set_a $7f,0 + cmp (ind1,x) + tst_a $7f,fzc + set_a $7e,0 + cmp (ind1,x) + tst_a $7e,fn + set_a $80,$ff + cmp (ind1,x) + tst_a $80,~fnz + set_a $7f,$ff + cmp (ind1,x) + tst_a $7f,~fn + set_a $7e,$ff + cmp (ind1,x) + tst_a $7e,~fzc + + set_a $80,0 + cmp (ind1),y + tst_a $80,fc + set_a $7f,0 + cmp (ind1),y + tst_a $7f,fzc + set_a $7e,0 + cmp (ind1),y + tst_a $7e,fn + set_a $80,$ff + cmp (ind1),y + tst_a $80,~fnz + set_a $7f,$ff + cmp (ind1),y + tst_a $7f,~fn + set_a $7e,$ff + cmp (ind1),y + tst_a $7e,~fzc + next_test + +; testing shifts - ASL LSR ROL ROR all addressing modes +; shifts - accumulator + ldx #3 +tasl + set_ax zp1,0 + asl a + tst_ax rASL,fASL,0 + dex + bpl tasl + ldx #3 +tasl1 + set_ax zp1,$ff + asl a + tst_ax rASL,fASL,$ff-fnzc + dex + bpl tasl1 + + ldx #3 +tlsr + set_ax zp1,0 + lsr a + tst_ax rLSR,fLSR,0 + dex + bpl tlsr + ldx #3 +tlsr1 + set_ax zp1,$ff + lsr a + tst_ax rLSR,fLSR,$ff-fnzc + dex + bpl tlsr1 + + ldx #3 +trol + set_ax zp1,0 + rol a + tst_ax rROL,fROL,0 + dex + bpl trol + ldx #3 +trol1 + set_ax zp1,$ff-fc + rol a + tst_ax rROL,fROL,$ff-fnzc + dex + bpl trol1 + + ldx #3 +trolc + set_ax zp1,fc + rol a + tst_ax rROLc,fROLc,0 + dex + bpl trolc + ldx #3 +trolc1 + set_ax zp1,$ff + rol a + tst_ax rROLc,fROLc,$ff-fnzc + dex + bpl trolc1 + + ldx #3 +tror + set_ax zp1,0 + ror a + tst_ax rROR,fROR,0 + dex + bpl tror + ldx #3 +tror1 + set_ax zp1,$ff-fc + ror a + tst_ax rROR,fROR,$ff-fnzc + dex + bpl tror1 + + ldx #3 +trorc + set_ax zp1,fc + ror a + tst_ax rRORc,fRORc,0 + dex + bpl trorc + ldx #3 +trorc1 + set_ax zp1,$ff + ror a + tst_ax rRORc,fRORc,$ff-fnzc + dex + bpl trorc1 + next_test + +; shifts - zeropage + ldx #3 +tasl2 + set_z zp1,0 + asl zpt + tst_z rASL,fASL,0 + dex + bpl tasl2 + ldx #3 +tasl3 + set_z zp1,$ff + asl zpt + tst_z rASL,fASL,$ff-fnzc + dex + bpl tasl3 + + ldx #3 +tlsr2 + set_z zp1,0 + lsr zpt + tst_z rLSR,fLSR,0 + dex + bpl tlsr2 + ldx #3 +tlsr3 + set_z zp1,$ff + lsr zpt + tst_z rLSR,fLSR,$ff-fnzc + dex + bpl tlsr3 + + ldx #3 +trol2 + set_z zp1,0 + rol zpt + tst_z rROL,fROL,0 + dex + bpl trol2 + ldx #3 +trol3 + set_z zp1,$ff-fc + rol zpt + tst_z rROL,fROL,$ff-fnzc + dex + bpl trol3 + + ldx #3 +trolc2 + set_z zp1,fc + rol zpt + tst_z rROLc,fROLc,0 + dex + bpl trolc2 + ldx #3 +trolc3 + set_z zp1,$ff + rol zpt + tst_z rROLc,fROLc,$ff-fnzc + dex + bpl trolc3 + + ldx #3 +tror2 + set_z zp1,0 + ror zpt + tst_z rROR,fROR,0 + dex + bpl tror2 + ldx #3 +tror3 + set_z zp1,$ff-fc + ror zpt + tst_z rROR,fROR,$ff-fnzc + dex + bpl tror3 + + ldx #3 +trorc2 + set_z zp1,fc + ror zpt + tst_z rRORc,fRORc,0 + dex + bpl trorc2 + ldx #3 +trorc3 + set_z zp1,$ff + ror zpt + tst_z rRORc,fRORc,$ff-fnzc + dex + bpl trorc3 + next_test + +; shifts - absolute + ldx #3 +tasl4 + set_abs zp1,0 + asl abst + tst_abs rASL,fASL,0 + dex + bpl tasl4 + ldx #3 +tasl5 + set_abs zp1,$ff + asl abst + tst_abs rASL,fASL,$ff-fnzc + dex + bpl tasl5 + + ldx #3 +tlsr4 + set_abs zp1,0 + lsr abst + tst_abs rLSR,fLSR,0 + dex + bpl tlsr4 + ldx #3 +tlsr5 + set_abs zp1,$ff + lsr abst + tst_abs rLSR,fLSR,$ff-fnzc + dex + bpl tlsr5 + + ldx #3 +trol4 + set_abs zp1,0 + rol abst + tst_abs rROL,fROL,0 + dex + bpl trol4 + ldx #3 +trol5 + set_abs zp1,$ff-fc + rol abst + tst_abs rROL,fROL,$ff-fnzc + dex + bpl trol5 + + ldx #3 +trolc4 + set_abs zp1,fc + rol abst + tst_abs rROLc,fROLc,0 + dex + bpl trolc4 + ldx #3 +trolc5 + set_abs zp1,$ff + rol abst + tst_abs rROLc,fROLc,$ff-fnzc + dex + bpl trolc5 + + ldx #3 +tror4 + set_abs zp1,0 + ror abst + tst_abs rROR,fROR,0 + dex + bpl tror4 + ldx #3 +tror5 + set_abs zp1,$ff-fc + ror abst + tst_abs rROR,fROR,$ff-fnzc + dex + bpl tror5 + + ldx #3 +trorc4 + set_abs zp1,fc + ror abst + tst_abs rRORc,fRORc,0 + dex + bpl trorc4 + ldx #3 +trorc5 + set_abs zp1,$ff + ror abst + tst_abs rRORc,fRORc,$ff-fnzc + dex + bpl trorc5 + next_test + +; shifts - zp indexed + ldx #3 +tasl6 + set_zx zp1,0 + asl zpt,x + tst_zx rASL,fASL,0 + dex + bpl tasl6 + ldx #3 +tasl7 + set_zx zp1,$ff + asl zpt,x + tst_zx rASL,fASL,$ff-fnzc + dex + bpl tasl7 + + ldx #3 +tlsr6 + set_zx zp1,0 + lsr zpt,x + tst_zx rLSR,fLSR,0 + dex + bpl tlsr6 + ldx #3 +tlsr7 + set_zx zp1,$ff + lsr zpt,x + tst_zx rLSR,fLSR,$ff-fnzc + dex + bpl tlsr7 + + ldx #3 +trol6 + set_zx zp1,0 + rol zpt,x + tst_zx rROL,fROL,0 + dex + bpl trol6 + ldx #3 +trol7 + set_zx zp1,$ff-fc + rol zpt,x + tst_zx rROL,fROL,$ff-fnzc + dex + bpl trol7 + + ldx #3 +trolc6 + set_zx zp1,fc + rol zpt,x + tst_zx rROLc,fROLc,0 + dex + bpl trolc6 + ldx #3 +trolc7 + set_zx zp1,$ff + rol zpt,x + tst_zx rROLc,fROLc,$ff-fnzc + dex + bpl trolc7 + + ldx #3 +tror6 + set_zx zp1,0 + ror zpt,x + tst_zx rROR,fROR,0 + dex + bpl tror6 + ldx #3 +tror7 + set_zx zp1,$ff-fc + ror zpt,x + tst_zx rROR,fROR,$ff-fnzc + dex + bpl tror7 + + ldx #3 +trorc6 + set_zx zp1,fc + ror zpt,x + tst_zx rRORc,fRORc,0 + dex + bpl trorc6 + ldx #3 +trorc7 + set_zx zp1,$ff + ror zpt,x + tst_zx rRORc,fRORc,$ff-fnzc + dex + bpl trorc7 + next_test + +; shifts - abs indexed + ldx #3 +tasl8 + set_absx zp1,0 + asl abst,x + tst_absx rASL,fASL,0 + dex + bpl tasl8 + ldx #3 +tasl9 + set_absx zp1,$ff + asl abst,x + tst_absx rASL,fASL,$ff-fnzc + dex + bpl tasl9 + + ldx #3 +tlsr8 + set_absx zp1,0 + lsr abst,x + tst_absx rLSR,fLSR,0 + dex + bpl tlsr8 + ldx #3 +tlsr9 + set_absx zp1,$ff + lsr abst,x + tst_absx rLSR,fLSR,$ff-fnzc + dex + bpl tlsr9 + + ldx #3 +trol8 + set_absx zp1,0 + rol abst,x + tst_absx rROL,fROL,0 + dex + bpl trol8 + ldx #3 +trol9 + set_absx zp1,$ff-fc + rol abst,x + tst_absx rROL,fROL,$ff-fnzc + dex + bpl trol9 + + ldx #3 +trolc8 + set_absx zp1,fc + rol abst,x + tst_absx rROLc,fROLc,0 + dex + bpl trolc8 + ldx #3 +trolc9 + set_absx zp1,$ff + rol abst,x + tst_absx rROLc,fROLc,$ff-fnzc + dex + bpl trolc9 + + ldx #3 +tror8 + set_absx zp1,0 + ror abst,x + tst_absx rROR,fROR,0 + dex + bpl tror8 + ldx #3 +tror9 + set_absx zp1,$ff-fc + ror abst,x + tst_absx rROR,fROR,$ff-fnzc + dex + bpl tror9 + + ldx #3 +trorc8 + set_absx zp1,fc + ror abst,x + tst_absx rRORc,fRORc,0 + dex + bpl trorc8 + ldx #3 +trorc9 + set_absx zp1,$ff + ror abst,x + tst_absx rRORc,fRORc,$ff-fnzc + dex + bpl trorc9 + next_test + +; testing memory increment/decrement - INC DEC all addressing modes +; zeropage + ldx #0 + lda #$7e + sta zpt +tinc + set_stat 0 + inc zpt + tst_z rINC,fINC,0 + inx + cpx #2 + bne tinc1 + lda #$fe + sta zpt +tinc1 cpx #5 + bne tinc + dex + inc zpt +tdec + set_stat 0 + dec zpt + tst_z rINC,fINC,0 + dex + bmi tdec1 + cpx #1 + bne tdec + lda #$81 + sta zpt + bne tdec +tdec1 + ldx #0 + lda #$7e + sta zpt +tinc10 + set_stat $ff + inc zpt + tst_z rINC,fINC,$ff-fnz + inx + cpx #2 + bne tinc11 + lda #$fe + sta zpt +tinc11 cpx #5 + bne tinc10 + dex + inc zpt +tdec10 + set_stat $ff + dec zpt + tst_z rINC,fINC,$ff-fnz + dex + bmi tdec11 + cpx #1 + bne tdec10 + lda #$81 + sta zpt + bne tdec10 +tdec11 + next_test + +; absolute memory + ldx #0 + lda #$7e + sta abst +tinc2 + set_stat 0 + inc abst + tst_abs rINC,fINC,0 + inx + cpx #2 + bne tinc3 + lda #$fe + sta abst +tinc3 cpx #5 + bne tinc2 + dex + inc abst +tdec2 + set_stat 0 + dec abst + tst_abs rINC,fINC,0 + dex + bmi tdec3 + cpx #1 + bne tdec2 + lda #$81 + sta abst + bne tdec2 +tdec3 + ldx #0 + lda #$7e + sta abst +tinc12 + set_stat $ff + inc abst + tst_abs rINC,fINC,$ff-fnz + inx + cpx #2 + bne tinc13 + lda #$fe + sta abst +tinc13 cpx #5 + bne tinc12 + dex + inc abst +tdec12 + set_stat $ff + dec abst + tst_abs rINC,fINC,$ff-fnz + dex + bmi tdec13 + cpx #1 + bne tdec12 + lda #$81 + sta abst + bne tdec12 +tdec13 + next_test + +; zeropage indexed + ldx #0 + lda #$7e +tinc4 sta zpt,x + set_stat 0 + inc zpt,x + tst_zx rINC,fINC,0 + lda zpt,x + inx + cpx #2 + bne tinc5 + lda #$fe +tinc5 cpx #5 + bne tinc4 + dex + lda #2 +tdec4 sta zpt,x + set_stat 0 + dec zpt,x + tst_zx rINC,fINC,0 + lda zpt,x + dex + bmi tdec5 + cpx #1 + bne tdec4 + lda #$81 + bne tdec4 +tdec5 + ldx #0 + lda #$7e +tinc14 sta zpt,x + set_stat $ff + inc zpt,x + tst_zx rINC,fINC,$ff-fnz + lda zpt,x + inx + cpx #2 + bne tinc15 + lda #$fe +tinc15 cpx #5 + bne tinc14 + dex + lda #2 +tdec14 sta zpt,x + set_stat $ff + dec zpt,x + tst_zx rINC,fINC,$ff-fnz + lda zpt,x + dex + bmi tdec15 + cpx #1 + bne tdec14 + lda #$81 + bne tdec14 +tdec15 + next_test + +; memory indexed + ldx #0 + lda #$7e +tinc6 sta abst,x + set_stat 0 + inc abst,x + tst_absx rINC,fINC,0 + lda abst,x + inx + cpx #2 + bne tinc7 + lda #$fe +tinc7 cpx #5 + bne tinc6 + dex + lda #2 +tdec6 sta abst,x + set_stat 0 + dec abst,x + tst_absx rINC,fINC,0 + lda abst,x + dex + bmi tdec7 + cpx #1 + bne tdec6 + lda #$81 + bne tdec6 +tdec7 + ldx #0 + lda #$7e +tinc16 sta abst,x + set_stat $ff + inc abst,x + tst_absx rINC,fINC,$ff-fnz + lda abst,x + inx + cpx #2 + bne tinc17 + lda #$fe +tinc17 cpx #5 + bne tinc16 + dex + lda #2 +tdec16 sta abst,x + set_stat $ff + dec abst,x + tst_absx rINC,fINC,$ff-fnz + lda abst,x + dex + bmi tdec17 + cpx #1 + bne tdec16 + lda #$81 + bne tdec16 +tdec17 + next_test + +; testing logical instructions - AND EOR ORA all addressing modes +; AND + ldx #3 ;immediate +tand lda zpAN,x + sta ex_andi+1 ;set AND # operand + set_ax absANa,0 + jsr ex_andi ;execute AND # in RAM + tst_ax absrlo,absflo,0 + dex + bpl tand + ldx #3 +tand1 lda zpAN,x + sta ex_andi+1 ;set AND # operand + set_ax absANa,$ff + jsr ex_andi ;execute AND # in RAM + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tand1 + + ldx #3 ;zp +tand2 lda zpAN,x + sta zpt + set_ax absANa,0 + and zpt + tst_ax absrlo,absflo,0 + dex + bpl tand2 + ldx #3 +tand3 lda zpAN,x + sta zpt + set_ax absANa,$ff + and zpt + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tand3 + + ldx #3 ;abs +tand4 lda zpAN,x + sta abst + set_ax absANa,0 + and abst + tst_ax absrlo,absflo,0 + dex + bpl tand4 + ldx #3 +tand5 lda zpAN,x + sta abst + set_ax absANa,$ff + and abst + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tand6 + + ldx #3 ;zp,x +tand6 + set_ax absANa,0 + and zpAN,x + tst_ax absrlo,absflo,0 + dex + bpl tand6 + ldx #3 +tand7 + set_ax absANa,$ff + and zpAN,x + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tand7 + + ldx #3 ;abs,x +tand8 + set_ax absANa,0 + and absAN,x + tst_ax absrlo,absflo,0 + dex + bpl tand8 + ldx #3 +tand9 + set_ax absANa,$ff + and absAN,x + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tand9 + + ldy #3 ;abs,y +tand10 + set_ay absANa,0 + and absAN,y + tst_ay absrlo,absflo,0 + dey + bpl tand10 + ldy #3 +tand11 + set_ay absANa,$ff + and absAN,y + tst_ay absrlo,absflo,$ff-fnz + dey + bpl tand11 + + ldx #6 ;(zp,x) + ldy #3 +tand12 + set_ay absANa,0 + and (indAN,x) + tst_ay absrlo,absflo,0 + dex + dex + dey + bpl tand12 + ldx #6 + ldy #3 +tand13 + set_ay absANa,$ff + and (indAN,x) + tst_ay absrlo,absflo,$ff-fnz + dex + dex + dey + bpl tand13 + + ldy #3 ;(zp),y +tand14 + set_ay absANa,0 + and (indAN),y + tst_ay absrlo,absflo,0 + dey + bpl tand14 + ldy #3 +tand15 + set_ay absANa,$ff + and (indAN),y + tst_ay absrlo,absflo,$ff-fnz + dey + bpl tand15 + next_test + +; EOR + ldx #3 ;immediate - self modifying code +teor lda zpEO,x + sta ex_eori+1 ;set EOR # operand + set_ax absEOa,0 + jsr ex_eori ;execute EOR # in RAM + tst_ax absrlo,absflo,0 + dex + bpl teor + ldx #3 +teor1 lda zpEO,x + sta ex_eori+1 ;set EOR # operand + set_ax absEOa,$ff + jsr ex_eori ;execute EOR # in RAM + tst_ax absrlo,absflo,$ff-fnz + dex + bpl teor1 + + ldx #3 ;zp +teor2 lda zpEO,x + sta zpt + set_ax absEOa,0 + eor zpt + tst_ax absrlo,absflo,0 + dex + bpl teor2 + ldx #3 +teor3 lda zpEO,x + sta zpt + set_ax absEOa,$ff + eor zpt + tst_ax absrlo,absflo,$ff-fnz + dex + bpl teor3 + + ldx #3 ;abs +teor4 lda zpEO,x + sta abst + set_ax absEOa,0 + eor abst + tst_ax absrlo,absflo,0 + dex + bpl teor4 + ldx #3 +teor5 lda zpEO,x + sta abst + set_ax absEOa,$ff + eor abst + tst_ax absrlo,absflo,$ff-fnz + dex + bpl teor6 + + ldx #3 ;zp,x +teor6 + set_ax absEOa,0 + eor zpEO,x + tst_ax absrlo,absflo,0 + dex + bpl teor6 + ldx #3 +teor7 + set_ax absEOa,$ff + eor zpEO,x + tst_ax absrlo,absflo,$ff-fnz + dex + bpl teor7 + + ldx #3 ;abs,x +teor8 + set_ax absEOa,0 + eor absEO,x + tst_ax absrlo,absflo,0 + dex + bpl teor8 + ldx #3 +teor9 + set_ax absEOa,$ff + eor absEO,x + tst_ax absrlo,absflo,$ff-fnz + dex + bpl teor9 + + ldy #3 ;abs,y +teor10 + set_ay absEOa,0 + eor absEO,y + tst_ay absrlo,absflo,0 + dey + bpl teor10 + ldy #3 +teor11 + set_ay absEOa,$ff + eor absEO,y + tst_ay absrlo,absflo,$ff-fnz + dey + bpl teor11 + + ldx #6 ;(zp,x) + ldy #3 +teor12 + set_ay absEOa,0 + eor (indEO,x) + tst_ay absrlo,absflo,0 + dex + dex + dey + bpl teor12 + ldx #6 + ldy #3 +teor13 + set_ay absEOa,$ff + eor (indEO,x) + tst_ay absrlo,absflo,$ff-fnz + dex + dex + dey + bpl teor13 + + ldy #3 ;(zp),y +teor14 + set_ay absEOa,0 + eor (indEO),y + tst_ay absrlo,absflo,0 + dey + bpl teor14 + ldy #3 +teor15 + set_ay absEOa,$ff + eor (indEO),y + tst_ay absrlo,absflo,$ff-fnz + dey + bpl teor15 + next_test + +; OR + ldx #3 ;immediate - self modifying code +tora lda zpOR,x + sta ex_orai+1 ;set ORA # operand + set_ax absORa,0 + jsr ex_orai ;execute ORA # in RAM + tst_ax absrlo,absflo,0 + dex + bpl tora + ldx #3 +tora1 lda zpOR,x + sta ex_orai+1 ;set ORA # operand + set_ax absORa,$ff + jsr ex_orai ;execute ORA # in RAM + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tora1 + + ldx #3 ;zp +tora2 lda zpOR,x + sta zpt + set_ax absORa,0 + ora zpt + tst_ax absrlo,absflo,0 + dex + bpl tora2 + ldx #3 +tora3 lda zpOR,x + sta zpt + set_ax absORa,$ff + ora zpt + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tora3 + + ldx #3 ;abs +tora4 lda zpOR,x + sta abst + set_ax absORa,0 + ora abst + tst_ax absrlo,absflo,0 + dex + bpl tora4 + ldx #3 +tora5 lda zpOR,x + sta abst + set_ax absORa,$ff + ora abst + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tora6 + + ldx #3 ;zp,x +tora6 + set_ax absORa,0 + ora zpOR,x + tst_ax absrlo,absflo,0 + dex + bpl tora6 + ldx #3 +tora7 + set_ax absORa,$ff + ora zpOR,x + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tora7 + + ldx #3 ;abs,x +tora8 + set_ax absORa,0 + ora absOR,x + tst_ax absrlo,absflo,0 + dex + bpl tora8 + ldx #3 +tora9 + set_ax absORa,$ff + ora absOR,x + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tora9 + + ldy #3 ;abs,y +tora10 + set_ay absORa,0 + ora absOR,y + tst_ay absrlo,absflo,0 + dey + bpl tora10 + ldy #3 +tora11 + set_ay absORa,$ff + ora absOR,y + tst_ay absrlo,absflo,$ff-fnz + dey + bpl tora11 + + ldx #6 ;(zp,x) + ldy #3 +tora12 + set_ay absORa,0 + ora (indOR,x) + tst_ay absrlo,absflo,0 + dex + dex + dey + bpl tora12 + ldx #6 + ldy #3 +tora13 + set_ay absORa,$ff + ora (indOR,x) + tst_ay absrlo,absflo,$ff-fnz + dex + dex + dey + bpl tora13 + + ldy #3 ;(zp),y +tora14 + set_ay absORa,0 + ora (indOR),y + tst_ay absrlo,absflo,0 + dey + bpl tora14 + ldy #3 +tora15 + set_ay absORa,$ff + ora (indOR),y + tst_ay absrlo,absflo,$ff-fnz + dey + bpl tora15 + if I_flag = 3 + cli + endif + next_test + +; full binary add/subtract test +; iterates through all combinations of operands and carry input +; uses increments/decrements to predict result & result flags + cld + ldx #ad2 ;for indexed test + ldy #$ff ;max range + lda #0 ;start with adding zeroes & no carry + sta adfc ;carry in - for diag + sta ad1 ;operand 1 - accumulator + sta ad2 ;operand 2 - memory or immediate + sta ada2 ;non zp + sta adrl ;expected result bits 0-7 + sta adrh ;expected result bit 8 (carry out) + lda #$ff ;complemented operand 2 for subtract + sta sb2 + sta sba2 ;non zp + lda #2 ;expected Z-flag + sta adrf +tadd clc ;test with carry clear + jsr chkadd + inc adfc ;now with carry + inc adrl ;result +1 + php ;save N & Z from low result + php + pla ;accu holds expected flags + and #$82 ;mask N & Z + plp + bne tadd1 + inc adrh ;result bit 8 - carry +tadd1 ora adrh ;merge C to expected flags + sta adrf ;save expected flags except overflow + sec ;test with carry set + jsr chkadd + dec adfc ;same for operand +1 but no carry + inc ad1 + bne tadd ;iterate op1 + lda #0 ;preset result to op2 when op1 = 0 + sta adrh + inc ada2 + inc ad2 + php ;save NZ as operand 2 becomes the new result + pla + and #$82 ;mask N00000Z0 + sta adrf ;no need to check carry as we are adding to 0 + dec sb2 ;complement subtract operand 2 + dec sba2 + lda ad2 + sta adrl + bne tadd ;iterate op2 + if disable_decimal < 1 + next_test + +; decimal add/subtract test +; *** WARNING - tests documented behavior only! *** +; only valid BCD operands are tested, N V Z flags are ignored +; iterates through all valid combinations of operands and carry input +; uses increments/decrements to predict result & carry flag + sed + ldx #ad2 ;for indexed test + ldy #$ff ;max range + lda #$99 ;start with adding 99 to 99 with carry + sta ad1 ;operand 1 - accumulator + sta ad2 ;operand 2 - memory or immediate + sta ada2 ;non zp + sta adrl ;expected result bits 0-7 + lda #1 ;set carry in & out + sta adfc ;carry in - for diag + sta adrh ;expected result bit 8 (carry out) + lda #0 ;complemented operand 2 for subtract + sta sb2 + sta sba2 ;non zp +tdad sec ;test with carry set + jsr chkdad + dec adfc ;now with carry clear + lda adrl ;decimal adjust result + bne tdad1 ;skip clear carry & preset result 99 (9A-1) + dec adrh + lda #$99 + sta adrl + bne tdad3 +tdad1 and #$f ;lower nibble mask + bne tdad2 ;no decimal adjust needed + dec adrl ;decimal adjust (?0-6) + dec adrl + dec adrl + dec adrl + dec adrl + dec adrl +tdad2 dec adrl ;result -1 +tdad3 clc ;test with carry clear + jsr chkdad + inc adfc ;same for operand -1 but with carry + lda ad1 ;decimal adjust operand 1 + beq tdad5 ;iterate operand 2 + and #$f ;lower nibble mask + bne tdad4 ;skip decimal adjust + dec ad1 ;decimal adjust (?0-6) + dec ad1 + dec ad1 + dec ad1 + dec ad1 + dec ad1 +tdad4 dec ad1 ;operand 1 -1 + jmp tdad ;iterate op1 + +tdad5 lda #$99 ;precharge op1 max + sta ad1 + lda ad2 ;decimal adjust operand 2 + beq tdad7 ;end of iteration + and #$f ;lower nibble mask + bne tdad6 ;skip decimal adjust + dec ad2 ;decimal adjust (?0-6) + dec ad2 + dec ad2 + dec ad2 + dec ad2 + dec ad2 + inc sb2 ;complemented decimal adjust for subtract (?9+6) + inc sb2 + inc sb2 + inc sb2 + inc sb2 + inc sb2 +tdad6 dec ad2 ;operand 2 -1 + inc sb2 ;complemented operand for subtract + lda sb2 + sta sba2 ;copy as non zp operand + lda ad2 + sta ada2 ;copy as non zp operand + sta adrl ;new result since op1+carry=00+carry +op2=op2 + inc adrh ;result carry + bne tdad ;iterate op2 +tdad7 + next_test + +; decimal/binary switch test +; tests CLD, SED, PLP, RTI to properly switch between decimal & binary opcode +; tables + clc + cld + php + lda #$55 + adc #$55 + cmp #$aa + trap_ne ;expected binary result after cld + clc + sed + php + lda #$55 + adc #$55 + cmp #$10 + trap_ne ;expected decimal result after sed + cld + plp + lda #$55 + adc #$55 + cmp #$10 + trap_ne ;expected decimal result after plp D=1 + plp + lda #$55 + adc #$55 + cmp #$aa + trap_ne ;expected binary result after plp D=0 + clc + lda #hi bin_rti_ret ;emulated interrupt for rti + pha + lda #lo bin_rti_ret + pha + php + sed + lda #hi dec_rti_ret ;emulated interrupt for rti + pha + lda #lo dec_rti_ret + pha + php + cld + rti +dec_rti_ret + lda #$55 + adc #$55 + cmp #$10 + trap_ne ;expected decimal result after rti D=1 + rti +bin_rti_ret + lda #$55 + adc #$55 + cmp #$aa + trap_ne ;expected binary result after rti D=0 + endif + + lda test_case + cmp #test_num + trap_ne ;previous test is out of sequence + lda #$f0 ;mark opcode testing complete + sta test_case + +; final RAM integrity test +; verifies that none of the previous tests has altered RAM outside of the +; designated write areas. + check_ram +; *** DEBUG INFO *** +; to debug checksum errors uncomment check_ram in the next_test macro to +; narrow down the responsible opcode. +; may give false errors when monitor, OS or other background activity is +; allowed during previous tests. + + +; S U C C E S S ************************************************ +; ------------- + success ;if you get here everything went well +; ------------- +; S U C C E S S ************************************************ + jmp start ;run again + + if disable_decimal < 1 +; core subroutine of the decimal add/subtract test +; *** WARNING - tests documented behavior only! *** +; only valid BCD operands are tested, N V Z flags are ignored +; iterates through all valid combinations of operands and carry input +; uses increments/decrements to predict result & carry flag +chkdad +; decimal ADC / SBC zp + php ;save carry for subtract + lda ad1 + adc ad2 ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + php ;save carry for next add + lda ad1 + sbc sb2 ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad flags + plp +; decimal ADC / SBC abs + php ;save carry for subtract + lda ad1 + adc ada2 ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + php ;save carry for next add + lda ad1 + sbc sba2 ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp +; decimal ADC / SBC # + php ;save carry for subtract + lda ad2 + sta ex_adci+1 ;set ADC # operand + lda ad1 + jsr ex_adci ;execute ADC # in RAM + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + php ;save carry for next add + lda sb2 + sta ex_sbci+1 ;set SBC # operand + lda ad1 + jsr ex_sbci ;execute SBC # in RAM + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp +; decimal ADC / SBC zp,x + php ;save carry for subtract + lda ad1 + adc 0,x ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + php ;save carry for next add + lda ad1 + sbc sb2-ad2,x ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp +; decimal ADC / SBC abs,x + php ;save carry for subtract + lda ad1 + adc ada2-ad2,x ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + php ;save carry for next add + lda ad1 + sbc sba2-ad2,x ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp +; decimal ADC / SBC abs,y + php ;save carry for subtract + lda ad1 + adc ada2-$ff,y ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + php ;save carry for next add + lda ad1 + sbc sba2-$ff,y ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp +; decimal ADC / SBC (zp,x) + php ;save carry for subtract + lda ad1 + adc (lo adi2-ad2,x) ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + php ;save carry for next add + lda ad1 + sbc (lo sbi2-ad2,x) ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp +; decimal ADC / SBC (abs),y + php ;save carry for subtract + lda ad1 + adc (adiy2),y ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + php ;save carry for next add + lda ad1 + sbc (sbiy2),y ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + rts + endif + +; core subroutine of the full binary add/subtract test +; iterates through all combinations of operands and carry input +; uses increments/decrements to predict result & result flags +chkadd lda adrf ;add V-flag if overflow + and #$83 ;keep N-----ZC / clear V + pha + lda ad1 ;test sign unequal between operands + eor ad2 + bmi ckad1 ;no overflow possible - operands have different sign + lda ad1 ;test sign equal between operands and result + eor adrl + bpl ckad1 ;no overflow occured - operand and result have same sign + pla + ora #$40 ;set V + pha +ckad1 pla + sta adrf ;save expected flags +; binary ADC / SBC zp + php ;save carry for subtract + lda ad1 + adc ad2 ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + php ;save carry for next add + lda ad1 + sbc sb2 ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp +; binary ADC / SBC abs + php ;save carry for subtract + lda ad1 + adc ada2 ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + php ;save carry for next add + lda ad1 + sbc sba2 ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp +; binary ADC / SBC # + php ;save carry for subtract + lda ad2 + sta ex_adci+1 ;set ADC # operand + lda ad1 + jsr ex_adci ;execute ADC # in RAM + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + php ;save carry for next add + lda sb2 + sta ex_sbci+1 ;set SBC # operand + lda ad1 + jsr ex_sbci ;execute SBC # in RAM + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp +; binary ADC / SBC zp,x + php ;save carry for subtract + lda ad1 + adc 0,x ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + php ;save carry for next add + lda ad1 + sbc sb2-ad2,x ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp +; binary ADC / SBC abs,x + php ;save carry for subtract + lda ad1 + adc ada2-ad2,x ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + php ;save carry for next add + lda ad1 + sbc sba2-ad2,x ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp +; binary ADC / SBC abs,y + php ;save carry for subtract + lda ad1 + adc ada2-$ff,y ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + php ;save carry for next add + lda ad1 + sbc sba2-$ff,y ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp +; binary ADC / SBC (zp,x) + php ;save carry for subtract + lda ad1 + adc (lo adi2-ad2,x) ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + php ;save carry for next add + lda ad1 + sbc (lo sbi2-ad2,x) ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp +; binary ADC / SBC (abs),y + php ;save carry for subtract + lda ad1 + adc (adiy2),y ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + php ;save carry for next add + lda ad1 + sbc (sbiy2),y ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + rts + +; target for the jump absolute test + dey + dey +test_far + php ;either SP or Y count will fail, if we do not hit + dey + dey + dey + plp + trap_cs ;flags loaded? + trap_vs + trap_mi + trap_eq + cmp #'F' ;registers loaded? + trap_ne + cpx #'A' + trap_ne + cpy #('R'-3) + trap_ne + pha ;save a,x + txa + pha + tsx + cpx #$fd ;check SP + trap_ne + pla ;restore x + tax + set_stat $ff + pla ;restore a + inx ;return registers with modifications + eor #$aa ;N=1, V=1, Z=0, C=1 + jmp far_ret + +; target for the jump indirect test + align +ptr_tst_ind dw test_ind +ptr_ind_ret dw ind_ret + trap ;runover protection + dey + dey +test_ind + php ;either SP or Y count will fail, if we do not hit + dey + dey + dey + plp + trap_cs ;flags loaded? + trap_vs + trap_mi + trap_eq + cmp #'I' ;registers loaded? + trap_ne + cpx #'N' + trap_ne + cpy #('D'-3) + trap_ne + pha ;save a,x + txa + pha + tsx + cpx #$fd ;check SP + trap_ne + pla ;restore x + tax + set_stat $ff + pla ;restore a + inx ;return registers with modifications + eor #$aa ;N=1, V=1, Z=0, C=1 + jmp (ptr_ind_ret) + trap ;runover protection + +; target for the jump subroutine test + dey + dey +test_jsr + php ;either SP or Y count will fail, if we do not hit + dey + dey + dey + plp + trap_cs ;flags loaded? + trap_vs + trap_mi + trap_eq + cmp #'J' ;registers loaded? + trap_ne + cpx #'S' + trap_ne + cpy #('R'-3) + trap_ne + pha ;save a,x + txa + pha + tsx ;sp -4? (return addr,a,x) + cpx #$fb + trap_ne + lda $1ff ;propper return on stack + cmp #hi(jsr_ret) + trap_ne + lda $1fe + cmp #lo(jsr_ret) + trap_ne + set_stat $ff + pla ;pull x,a + tax + pla + inx ;return registers with modifications + eor #$aa ;N=1, V=1, Z=0, C=1 + rts + trap ;runover protection + +;trap in case of unexpected IRQ, NMI, BRK, RESET - BRK test target +nmi_trap + trap ;check stack for conditions at NMI +res_trap + trap ;unexpected RESET + + dey + dey +irq_trap ;BRK test or unextpected BRK or IRQ + php ;either SP or Y count will fail, if we do not hit + dey + dey + dey + ;next 4 traps could be caused by unexpected BRK or IRQ + ;check stack for BREAK and originating location + ;possible jump/branch into weeds (uninitialized space) + cmp #'B' ;registers loaded? + trap_ne + cpx #'R' + trap_ne + cpy #('K'-3) + trap_ne + sta irq_a ;save registers during break test + stx irq_x + tsx ;test break on stack + lda $102,x + cmp_flag 0 ;break test should have B=1 + trap_ne ; - no break flag on stack + pla + cmp #fai ;should have added interrupt disable + trap_ne + tsx + cpx #$fc ;sp -3? (return addr, flags) + trap_ne + lda $1ff ;propper return on stack + cmp #hi(brk_ret) + trap_ne + lda $1fe + cmp #lo(brk_ret) + trap_ne + set_stat $ff + ldx irq_x + inx ;return registers with modifications + lda irq_a + eor #$aa ;N=1, V=1, Z=0, C=1 but original flags should be restored + rti + trap ;runover protection + + if report = 1 + include "report.i65" + endif + +;copy of data to initialize BSS segment + if load_data_direct != 1 +zp_init +zp1_ db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR +zp7f_ db $7f ;test pattern for compare +;logical zeropage operands +zpOR_ db 0,$1f,$71,$80 ;test pattern for OR +zpAN_ db $0f,$ff,$7f,$80 ;test pattern for AND +zpEO_ db $ff,$0f,$8f,$8f ;test pattern for EOR +;indirect addressing pointers +ind1_ dw abs1 ;indirect pointer to pattern in absolute memory + dw abs1+1 + dw abs1+2 + dw abs1+3 + dw abs7f +inw1_ dw abs1-$f8 ;indirect pointer for wrap-test pattern +indt_ dw abst ;indirect pointer to store area in absolute memory + dw abst+1 + dw abst+2 + dw abst+3 +inwt_ dw abst-$f8 ;indirect pointer for wrap-test store +indAN_ dw absAN ;indirect pointer to AND pattern in absolute memory + dw absAN+1 + dw absAN+2 + dw absAN+3 +indEO_ dw absEO ;indirect pointer to EOR pattern in absolute memory + dw absEO+1 + dw absEO+2 + dw absEO+3 +indOR_ dw absOR ;indirect pointer to OR pattern in absolute memory + dw absOR+1 + dw absOR+2 + dw absOR+3 +;add/subtract indirect pointers +adi2_ dw ada2 ;indirect pointer to operand 2 in absolute memory +sbi2_ dw sba2 ;indirect pointer to complemented operand 2 (SBC) +adiy2_ dw ada2-$ff ;with offset for indirect indexed +sbiy2_ dw sba2-$ff +zp_end + if (zp_end - zp_init) != (zp_bss_end - zp_bss) + ;force assembler error if size is different + ERROR ERROR ERROR ;mismatch between bss and zeropage data + endif +data_init +ex_and_ and #0 ;execute immediate opcodes + rts +ex_eor_ eor #0 ;execute immediate opcodes + rts +ex_ora_ ora #0 ;execute immediate opcodes + rts +ex_adc_ adc #0 ;execute immediate opcodes + rts +ex_sbc_ sbc #0 ;execute immediate opcodes + rts +abs1_ db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR +abs7f_ db $7f ;test pattern for compare +;loads +fLDx_ db fn,fn,0,fz ;expected flags for load +;shifts +rASL_ ;expected result ASL & ROL -carry +rROL_ db $86,$04,$82,0 ; " +rROLc_ db $87,$05,$83,1 ;expected result ROL +carry +rLSR_ ;expected result LSR & ROR -carry +rROR_ db $61,$41,$20,0 ; " +rRORc_ db $e1,$c1,$a0,$80 ;expected result ROR +carry +fASL_ ;expected flags for shifts +fROL_ db fnc,fc,fn,fz ;no carry in +fROLc_ db fnc,fc,fn,0 ;carry in +fLSR_ +fROR_ db fc,0,fc,fz ;no carry in +fRORc_ db fnc,fn,fnc,fn ;carry in +;increments (decrements) +rINC_ db $7f,$80,$ff,0,1 ;expected result for INC/DEC +fINC_ db 0,fn,fn,fz,0 ;expected flags for INC/DEC +;logical memory operand +absOR_ db 0,$1f,$71,$80 ;test pattern for OR +absAN_ db $0f,$ff,$7f,$80 ;test pattern for AND +absEO_ db $ff,$0f,$8f,$8f ;test pattern for EOR +;logical accu operand +absORa_ db 0,$f1,$1f,0 ;test pattern for OR +absANa_ db $f0,$ff,$ff,$ff ;test pattern for AND +absEOa_ db $ff,$f0,$f0,$0f ;test pattern for EOR +;logical results +absrlo_ db 0,$ff,$7f,$80 +absflo_ db fz,fn,0,fn +data_end + if (data_end - data_init) != (data_bss_end - data_bss) + ;force assembler error if size is different + ERROR ERROR ERROR ;mismatch between bss and data + endif + +vec_init + dw nmi_trap + dw res_trap + dw irq_trap +vec_bss equ $fffa + endif ;end of RAM init data + + if (load_data_direct = 1) & (ROM_vectors = 1) + org $fffa ;vectors + dw nmi_trap + dw res_trap + dw irq_trap + endif + + end start + \ No newline at end of file diff --git a/BCDCodes.dev b/BCDCodes.dev index 8a12981..1a9f0e2 100644 --- a/BCDCodes.dev +++ b/BCDCodes.dev @@ -1,62 +1,62 @@ -[Project] -FileName=BCDCodes.dev -Name=BCDCodes -Type=1 -Ver=2 -ObjFiles= -Includes= -Libs= -PrivateResource= -ResourceIncludes= -MakeIncludes= -Compiler= -CppCompiler= -Linker= -IsCpp=0 -Icon= -ExeOutput= -ObjectOutput= -LogOutput= -LogOutputEnabled=0 -OverrideOutput=0 -OverrideOutputName= -HostApplication= -UseCustomMakefile=0 -CustomMakefile= -CommandLine= -Folders= -IncludeVersionInfo=0 -SupportXPThemes=0 -CompilerSet=3 -CompilerSettings=0000000100000000000000000 -UnitCount=1 - -[VersionInfo] -Major=1 -Minor=0 -Release=0 -Build=0 -LanguageID=1033 -CharsetID=1252 -CompanyName= -FileVersion= -FileDescription=Developed using the Dev-C++ IDE -InternalName= -LegalCopyright= -LegalTrademarks= -OriginalFilename= -ProductName= -ProductVersion= -AutoIncBuildNr=0 -SyncProduct=1 - -[Unit1] -FileName=bcd.c -CompileCpp=0 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - +[Project] +FileName=BCDCodes.dev +Name=BCDCodes +Type=1 +Ver=2 +ObjFiles= +Includes= +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler= +Linker= +IsCpp=0 +Icon= +ExeOutput= +ObjectOutput= +LogOutput= +LogOutputEnabled=0 +OverrideOutput=0 +OverrideOutputName= +HostApplication= +UseCustomMakefile=0 +CustomMakefile= +CommandLine= +Folders= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=3 +CompilerSettings=0000000100000000000000000 +UnitCount=1 + +[VersionInfo] +Major=1 +Minor=0 +Release=0 +Build=0 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 +SyncProduct=1 + +[Unit1] +FileName=bcd.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/BCDCodes.layout b/BCDCodes.layout new file mode 100644 index 0000000..b71ad5b --- /dev/null +++ b/BCDCodes.layout @@ -0,0 +1,8 @@ +[Editors] +Order=0 +Focused=0 +[Editor_0] +CursorCol=1 +CursorRow=34 +TopLine=1 +LeftChar=1 diff --git a/Bin2Hex.dev b/Bin2Hex.dev new file mode 100644 index 0000000..65c0362 --- /dev/null +++ b/Bin2Hex.dev @@ -0,0 +1,62 @@ +[Project] +FileName=Bin2Hex.dev +Name=Bin2Hex +Type=1 +Ver=2 +ObjFiles= +Includes= +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler= +Linker= +IsCpp=0 +Icon= +ExeOutput= +ObjectOutput= +LogOutput= +LogOutputEnabled=0 +OverrideOutput=0 +OverrideOutputName= +HostApplication= +UseCustomMakefile=0 +CustomMakefile= +CommandLine= +Folders= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=3 +CompilerSettings=0000000100000000000000000 +UnitCount=1 + +[VersionInfo] +Major=1 +Minor=0 +Release=0 +Build=0 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 +SyncProduct=1 + +[Unit1] +FileName=bin2hex.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/Bin2Hex.layout b/Bin2Hex.layout new file mode 100644 index 0000000..c3de494 --- /dev/null +++ b/Bin2Hex.layout @@ -0,0 +1,8 @@ +[Editor_0] +CursorCol=26 +CursorRow=111 +TopLine=28 +LeftChar=1 +[Editors] +Order=0 +Focused=0 diff --git a/Display.cpp b/Display.cpp index 1c36c90..d0ec1bf 100644 --- a/Display.cpp +++ b/Display.cpp @@ -1,245 +1,312 @@ -#include "Display.h" -#include -#include -#include -#include - -using namespace std; - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ - -namespace MKBasic { - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -Display::Display() -{ - InitScr(); -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -Display::~Display() -{ -} - -/* - *-------------------------------------------------------------------- - * Method: InitScr() - * Purpose: Initialize screen. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void Display::InitScr() -{ - ClrScr(); -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void Display::ScrollUp() -{ - for (int row=0; row= SCREENDIM_ROW) { - ScrollUp(); - mCursorCoord.row = SCREENDIM_ROW-1; - } - } else if (c == SCREENSPECCHARS_CR) { - mCursorCoord.col = 0; - } else if (c == SCREENSPECCHARS_TB) { - mCursorCoord.col += TABSIZE; - if (mCursorCoord.col >= SCREENDIM_COL) { - mCursorCoord.col = SCREENDIM_COL-1; // must work on it some more - } - } else if (c == SCREENSPECCHARS_BS) { - if (mCursorCoord.col > 0) mCursorCoord.col--; - } else if (c == SCREENSPECCHARS_BE) { - // no action - } - else { - mScreen[mCursorCoord.col][mCursorCoord.row] = c; - mCursorCoord.col++; - if (mCursorCoord.col >= SCREENDIM_COL) { - mCursorCoord.col = 0; - mCursorCoord.row++; - if (mCursorCoord.row >= SCREENDIM_ROW) { - ScrollUp(); - mCursorCoord.row = SCREENDIM_ROW-1; - } - } - } - } -} - -/* - *-------------------------------------------------------------------- - * Method: ClrScr() - * Purpose: Fill the screen with spaces. Set cursor in left-upper - * corner. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void Display::ClrScr() -{ - for (int col=0; col +#include +#include +#include + +using namespace std; + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ + +namespace MKBasic { + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +Display::Display() +{ + InitScr(); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +Display::~Display() +{ +} + +/* + *-------------------------------------------------------------------- + * Method: InitScr() + * Purpose: Initialize screen. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void Display::InitScr() +{ + mScrLines = SCREENDIM_ROW; + mScrColumns = SCREENDIM_COL; + mShellConsoleWidth = GetConsoleWidth(); + if (mScrColumns > mShellConsoleWidth) { + mScrColumns = mShellConsoleWidth; + } + ClrScr(); +} + +#if defined(WINDOWS) + +#include +#include + +/* + *-------------------------------------------------------------------- + * Method: GetConsoleWidth() + * Purpose: Obtain the width of shell console (the real one, not + * the emulated one) on Windows. + * Arguments: n/a + * Returns: int - width of the shell console. + *-------------------------------------------------------------------- + */ +int Display::GetConsoleWidth() +{ + HANDLE hStdOut; + CONSOLE_SCREEN_BUFFER_INFO csbi; + + hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); + if (hStdOut == INVALID_HANDLE_VALUE) return -1; + + if (!GetConsoleScreenBufferInfo( hStdOut, &csbi )) return -2; + + return csbi.dwSize.X; +} + +#endif + +#if defined(LINUX) + +#include + +/* + *-------------------------------------------------------------------- + * Method: GetConsoleWidth() + * Purpose: Obtain the width of shell console (the real one, not + * the emulated one) on Linux. + * Arguments: n/a + * Returns: int - width of the shell console. + *-------------------------------------------------------------------- + */ +int Display::GetConsoleWidth() +{ + unsigned int conwidth = SCREENDIM_COL; + char *termtype = getenv("TERM"); + static char termbuf[2048]; + + if (tgetent(termbuf, termtype) < 0) { + cout << "WARNING: Could not access the termcap data base." << endl; + cout << " Unable to determine console width." << endl; + } else { + conwidth = tgetnum("co"); + } + + return conwidth; +} + +#endif + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void Display::ScrollUp() +{ + for (unsigned int row=0; row= mScrLines) { + ScrollUp(); + mCursorCoord.row = mScrLines-1; + } + } else if (c == SCREENSPECCHARS_CR) { + mCursorCoord.col = 0; + } else if (c == SCREENSPECCHARS_TB) { + mCursorCoord.col += TABSIZE; + if (mCursorCoord.col >= mScrColumns) { + mCursorCoord.col = mScrColumns-1; // must work on it some more + } + } else if (c == SCREENSPECCHARS_BS) { + if (mCursorCoord.col > 0) mCursorCoord.col--; + } else if (c == SCREENSPECCHARS_BE) { + // no action + } + else { + mScreen[mCursorCoord.col][mCursorCoord.row] = c; + mCursorCoord.col++; + if (mCursorCoord.col >= mScrColumns) { + mCursorCoord.col = 0; + mCursorCoord.row++; + if (mCursorCoord.row >= mScrLines) { + ScrollUp(); + mCursorCoord.row = mScrLines-1; + } + } + } + } +} + +/* + *-------------------------------------------------------------------- + * Method: ClrScr() + * Purpose: Fill the screen with spaces. Set cursor in left-upper + * corner. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void Display::ClrScr() +{ + for (unsigned int col=0; col mScrColumns) cout << endl; + } +} + +/* + *-------------------------------------------------------------------- + * Method: GetCursorCoord() + * Purpose: Get cursor coordinates. + * Arguments: n/a + * Returns: pointer to cursor coordinates + *-------------------------------------------------------------------- + */ +CursorCoord *Display::GetCursorCoord() +{ + return &mCursorCoord; +} + +} // namespace MKBasic diff --git a/Display.h b/Display.h index db80bcc..56993f5 100644 --- a/Display.h +++ b/Display.h @@ -1,54 +1,60 @@ -#ifndef DISPLAY_H -#define DISPLAY_H - -#define TABSIZE 4 - -namespace MKBasic { - -enum eScreenDimensions { - SCREENDIM_COL = 80, - SCREENDIM_ROW = 24 -}; - -enum eScreenSpecChars { - SCREENSPECCHARS_NL = (int)'\n', // new line - SCREENSPECCHARS_CR = (int)'\r', // caret - SCREENSPECCHARS_TB = (int)'\t', // tab - SCREENSPECCHARS_BS = (int)'\b', // backspace - SCREENSPECCHARS_BE = (int)'\a' // bell -}; - -struct CursorCoord { - int row; - int col; -}; - -class Display -{ - public: - - Display(); - ~Display(); - void GotoXY(unsigned int col, unsigned int row); - void PutChar(char c); - void ClrScr(); - char GetCharAt(unsigned int col, unsigned int row); - void ShowScr(); - CursorCoord *GetCursorCoord(); - - protected: - - private: - - char mScreen[SCREENDIM_COL][SCREENDIM_ROW]; - CursorCoord mCursorCoord; - - void InitScr(); - void ScrollUp(); - bool IsSpecChar(char c); - -}; - -} // namespace MKBasic - -#endif +#ifndef DISPLAY_H +#define DISPLAY_H + +#include "system.h" + +#define TABSIZE 4 + +namespace MKBasic { + +enum eScreenDimensions { + SCREENDIM_COL = 80, + SCREENDIM_ROW = 24 +}; + +enum eScreenSpecChars { + SCREENSPECCHARS_NL = (int)'\n', // new line + SCREENSPECCHARS_CR = (int)'\r', // caret + SCREENSPECCHARS_TB = (int)'\t', // tab + SCREENSPECCHARS_BS = (int)'\b', // backspace + SCREENSPECCHARS_BE = (int)'\a' // bell +}; + +struct CursorCoord { + unsigned int row; + unsigned int col; +}; + +class Display +{ + public: + + Display(); + ~Display(); + void GotoXY(unsigned int col, unsigned int row); + void PutChar(char c); + void ClrScr(); + char GetCharAt(unsigned int col, unsigned int row); + void ShowScr(); + CursorCoord *GetCursorCoord(); + + protected: + + private: + + char mScreen[SCREENDIM_COL][SCREENDIM_ROW]; + CursorCoord mCursorCoord; + unsigned int mShellConsoleWidth; + unsigned int mScrLines; + unsigned int mScrColumns; + + void InitScr(); + void ScrollUp(); + bool IsSpecChar(char c); + int GetConsoleWidth(); + +}; + +} // namespace MKBasic + +#endif diff --git a/MKBasic.cpp b/MKBasic.cpp index e1c928f..6f84b69 100644 --- a/MKBasic.cpp +++ b/MKBasic.cpp @@ -1,13 +1,13 @@ -#include "MKBasic.h" - -namespace MKBasic { - -MKBasic::MKBasic() -{ -} - -MKBasic::~MKBasic() -{ -} - -} // namespace MKBasic +#include "MKBasic.h" + +namespace MKBasic { + +MKBasic::MKBasic() +{ +} + +MKBasic::~MKBasic() +{ +} + +} // namespace MKBasic diff --git a/MKBasic.dev b/MKBasic.dev index c14bae8..650819b 100644 --- a/MKBasic.dev +++ b/MKBasic.dev @@ -1,182 +1,192 @@ -[Project] -FileName=MKBasic.dev -Name=MKBasic -Type=1 -Ver=2 -ObjFiles= -Includes= -Libs= -PrivateResource= -ResourceIncludes= -MakeIncludes= -Compiler= -CppCompiler= -Linker= -IsCpp=1 -Icon= -ExeOutput= -ObjectOutput= -LogOutput= -LogOutputEnabled=0 -OverrideOutput=0 -OverrideOutputName=MKBasic.exe -HostApplication= -UseCustomMakefile=0 -CustomMakefile= -CommandLine= -Folders= -IncludeVersionInfo=0 -SupportXPThemes=0 -CompilerSet=3 -CompilerSettings=00000001c0111000001000000 -UnitCount=13 - -[VersionInfo] -Major=1 -Minor=0 -Release=0 -Build=0 -LanguageID=1033 -CharsetID=1252 -CompanyName= -FileVersion=1.0.0.0 -FileDescription=Developed using the Dev-C++ IDE -InternalName= -LegalCopyright= -LegalTrademarks= -OriginalFilename= -ProductName= -ProductVersion=1.0.0.0 -AutoIncBuildNr=0 -SyncProduct=1 - -[Unit1] -FileName=main.cpp -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit2] -FileName=VMachine.h -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit3] -FileName=VMachine.cpp -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit4] -FileName=MKBasic.h -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit5] -FileName=MKBasic.cpp -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit6] -FileName=MKCpu.h -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit7] -FileName=MKCpu.cpp -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit8] -FileName=Memory.h -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit9] -FileName=Memory.cpp -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit10] -FileName=Display.h -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit11] -FileName=Display.cpp -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit12] -FileName=MKGenException.h -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit13] -FileName=MKGenException.cpp -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - +[Project] +FileName=MKBasic.dev +Name=MKBasic +Type=1 +Ver=2 +ObjFiles= +Includes= +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler= +Linker= +IsCpp=1 +Icon= +ExeOutput= +ObjectOutput= +LogOutput= +LogOutputEnabled=0 +OverrideOutput=0 +OverrideOutputName=MKBasic.exe +HostApplication= +UseCustomMakefile=0 +CustomMakefile= +CommandLine= +Folders= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=3 +CompilerSettings=00000001c0111000001000000 +UnitCount=14 + +[VersionInfo] +Major=1 +Minor=0 +Release=0 +Build=0 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion=1.0.0.0 +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +AutoIncBuildNr=0 +SyncProduct=1 + +[Unit1] +FileName=main.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=VMachine.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=VMachine.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=MKBasic.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=MKBasic.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=MKCpu.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=MKCpu.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=Memory.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=Memory.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=Display.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=Display.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit12] +FileName=MKGenException.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit13] +FileName=MKGenException.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit14] +FileName=system.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/MKBasic.h b/MKBasic.h index 1e7cad6..fbe06ff 100644 --- a/MKBasic.h +++ b/MKBasic.h @@ -1,18 +1,18 @@ -#ifndef MKBASIC_H -#define MKBASIC_H - -#include "VMachine.h" - -namespace MKBasic { - -class MKBasic : public VMachine -{ - public: - MKBasic(); - ~MKBasic(); - protected: -}; - -} // namespace MKBasic - -#endif +#ifndef MKBASIC_H +#define MKBASIC_H + +#include "VMachine.h" + +namespace MKBasic { + +class MKBasic : public VMachine +{ + public: + MKBasic(); + ~MKBasic(); + protected: +}; + +} // namespace MKBasic + +#endif diff --git a/MKBasic.layout b/MKBasic.layout new file mode 100644 index 0000000..0187f9c --- /dev/null +++ b/MKBasic.layout @@ -0,0 +1,38 @@ +[Editors] +Order=0,7,8,1,2,5,6 +Focused=0 +[Editor_0] +CursorCol=17 +CursorRow=470 +TopLine=424 +LeftChar=1 +[Editor_1] +CursorCol=33 +CursorRow=38 +TopLine=28 +LeftChar=1 +[Editor_2] +CursorCol=15 +CursorRow=600 +TopLine=554 +LeftChar=1 +[Editor_5] +CursorCol=1 +CursorRow=1 +TopLine=260 +LeftChar=1 +[Editor_6] +CursorCol=17 +CursorRow=1151 +TopLine=332 +LeftChar=1 +[Editor_7] +CursorCol=1 +CursorRow=1 +TopLine=25 +LeftChar=1 +[Editor_8] +CursorCol=1 +CursorRow=1 +TopLine=220 +LeftChar=1 diff --git a/MKCpu.cpp b/MKCpu.cpp index 3f82456..2973d49 100644 --- a/MKCpu.cpp +++ b/MKCpu.cpp @@ -1,1471 +1,2012 @@ -#include "MKCpu.h" -#include "MKGenException.h" - -namespace MKBasic { - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ - -/* - *-------------------------------------------------------------------- - * Method: MKCpu() - * Purpose: Default constructor. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -MKCpu::MKCpu() -{ - InitCpu(); -} - -/* - *-------------------------------------------------------------------- - * Method: MKCpu() - * Purpose: Custom constructor. - * Arguments: pmem - pointer to Memory object. - * Returns: n/a - *-------------------------------------------------------------------- - */ -MKCpu::MKCpu(Memory *pmem) -{ - mpMem = pmem; - InitCpu(); -} - -/* - *-------------------------------------------------------------------- - * Method: InitCpu() - * Purpose: Initialize internal variables and flags. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void MKCpu::InitCpu() -{ - mReg.Acc = 0; - mReg.Acc16 = 0; - mReg.Flags = FLAGS_UNUSED; - mReg.IndX = 0; - mReg.IndY = 0; - mReg.Ptr16 = 0; - mReg.PtrAddr = 0; - mReg.PtrStack = 0xFF; // top of stack - mReg.SoftIrq = false; - mLocalMem = false; - if (NULL == mpMem) { - mpMem = new Memory(); - if (NULL == mpMem) { - throw MKGenException("Unable to allocate memory!"); - } - mLocalMem = true; - } - // Set default BRK vector. - mpMem->Poke8bit(0xFFFE,0xF0); - mpMem->Poke8bit(0xFFFF,0xFF); - // Put RTI opcode at BRK address. - mpMem->Poke8bit(0xFFF0, OPCODE_RTI); -} - -/* - *-------------------------------------------------------------------- - * Method: SetFlags() - * Purpose: Set CPU status flags ZERO and SIGN based on Acc, X or Y - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void MKCpu::SetFlags(unsigned char reg) -{ - SetFlag((0 == reg), FLAGS_ZERO); - SetFlag(((reg & FLAGS_SIGN) == FLAGS_SIGN), FLAGS_SIGN); -} - -/* - *-------------------------------------------------------------------- - * Method: ShiftLeft() - * Purpose: Arithmetic shift left (1 bit), set Carry flag, shift 0 - * into bit #0. Update flags NZ. - * Arguments: arg8 - 8-bit value - * Returns: 8-bit value after shift - *-------------------------------------------------------------------- - */ -unsigned char MKCpu::ShiftLeft(unsigned char arg8) -{ - // set Carry flag based on original bit #7 - SetFlag(((arg8 & FLAGS_SIGN) == FLAGS_SIGN), FLAGS_CARRY); - arg8 = arg8 << 1; // shift left - arg8 &= 0xFE; // shift 0 into bit #0 - - SetFlags(arg8); - - return arg8; -} - -/* - *-------------------------------------------------------------------- - * Method: ShiftRight() - * Purpose: Logical Shift Right, update flags NZC. - * Arguments: arg8 - byte value - * Returns: unsigned char (byte) - after shift - *-------------------------------------------------------------------- - */ -unsigned char MKCpu::ShiftRight(unsigned char arg8) -{ - SetFlag(((arg8 & 0x01) == 0x01), FLAGS_CARRY); - arg8 = arg8 >> 1; - arg8 &= 0x7F; // unset bit #7 - SetFlags(arg8); - - return arg8; -} - -/* - *-------------------------------------------------------------------- - * Method: RotateLeft() - * Purpose: Rotate left, Carry to bit 0, bit 7 to Carry, update - flags N and Z. - * Arguments: arg8 - byte value to rotate - * Returns: unsigned char (byte) - rotated value - *-------------------------------------------------------------------- - */ -unsigned char MKCpu::RotateLeft(unsigned char arg8) -{ - unsigned char tmp8 = 0; - - tmp8 = arg8; - arg8 = arg8 << 1; - // Carry goes to bit #0. - if (mReg.Flags & FLAGS_CARRY) { - arg8 |= 0x01; - } else { - arg8 &= 0xFE; - } - // Original (before ROL) bit #7 goes to Carry. - SetFlag(((tmp8 & FLAGS_SIGN) == FLAGS_SIGN), FLAGS_CARRY); - SetFlags(arg8); // set flags Z and N - - return arg8; -} - -/* - *-------------------------------------------------------------------- - * Method: RotateRight() - * Purpose: Rotate Right, Carry to bit 7, bit 0 to Carry, update - flags N and Z. - * Arguments: arg8 - byte value to rotate - * Returns: unsigned char (byte) - rotated value - *-------------------------------------------------------------------- - */ -unsigned char MKCpu::RotateRight(unsigned char arg8) -{ - unsigned char tmp8 = 0; - - tmp8 = arg8; - arg8 = arg8 >> 1; - // Carry goes to bit #7. - if (CheckFlag(FLAGS_CARRY)) { - arg8 |= 0x80; - } else { - arg8 &= 0x7F; - } - // Original (before ROR) bit #0 goes to Carry. - SetFlag(((tmp8 & 0x01) == 0x01), FLAGS_CARRY); - SetFlags(arg8); // set flags Z and N - - return arg8; -} - -/* - *-------------------------------------------------------------------- - * Method: GetArg16() - * Purpose: Get 2-byte argument, add offset, increase PC. - * Arguments: addr - address of argument in memory - * offs - offset to be added to returned value - * Returns: 16-bit address - *-------------------------------------------------------------------- - */ -unsigned short MKCpu::GetArg16(unsigned char offs) -{ - unsigned short ret = 0; - - ret = mpMem->Peek16bit(mReg.PtrAddr++); - mReg.PtrAddr++; - ret += offs; - - return ret; -} - -/* - *-------------------------------------------------------------------- - * Method: LogicOpAcc() - * Purpose: Perform logical bitwise operation between memory - * location and Acc, result in Acc. Set flags. - * Arguments: addr - memory location - * logop - logical operation code: LOGOP_OR, LOGOP_AND, - * LOGOP_EOR - * Returns: n/a - *-------------------------------------------------------------------- - */ -void MKCpu::LogicOpAcc(unsigned short addr, int logop) -{ - unsigned char val = 0; - - val = mpMem->Peek8bit(addr); - switch (logop) { - case LOGOP_OR: - mReg.Acc |= val; - break; - case LOGOP_AND: - mReg.Acc &= val; - break; - case LOGOP_EOR: - mReg.Acc ^= val; - break; - default: - break; - } - SetFlags(mReg.Acc); -} - -/* - *-------------------------------------------------------------------- - * Method: ComputeRelJump() - * Purpose: Compute new PC based on relative offset. - * Arguments: offs - relative offset [-128 ($80)..127 ($7F)] - * Returns: unsigned short - new PC (Program Counter). - * NOTE: - * Program Counter (http://www.6502.org/tutorials/6502opcodes.html#PC) - * When the 6502 is ready for the next instruction it increments the - * program counter before fetching the instruction. Once it has the op - * code, it increments the program counter by the length of the - * operand, if any. This must be accounted for when calculating - * branches or when pushing bytes to create a false return address - * (i.e. jump table addresses are made up of addresses-1 when it is - * intended to use an RTS rather than a JMP). - * The program counter is loaded least signifigant byte first. - * Therefore the most signifigant byte must be pushed first when - * creating a false return address. - * When calculating branches a forward branch of 6 skips the following - * 6 bytes so, effectively the program counter points to the address - * that is 8 bytes beyond the address of the branch opcode; - * and a backward branch of $FA (256-6) goes to an address 4 bytes - * before the branch instruction. - *-------------------------------------------------------------------- - */ -unsigned short MKCpu::ComputeRelJump(unsigned char offs) -{ - unsigned short newpc = mReg.PtrAddr; // PtrAddr must be at the next - // opcode at this point - if (offs < 0x80) { - newpc += (unsigned short) offs; - } else { - newpc -= (unsigned short) ((unsigned char)(~offs + 1)); // use binary 2's complement instead of arithmetics - } - - return newpc; -} - -/* - *-------------------------------------------------------------------- - * Method: Conv2Bcd() - * Purpose: Convert 16-bit unsigned number to 8-bit BCD - * representation. - * Arguments: v - 16-bit unsigned integer. - * Returns: byte representing BCD code of the 'v'. - *-------------------------------------------------------------------- - */ -unsigned char MKCpu::Conv2Bcd(unsigned short v) -{ - unsigned char arg8 = 0; - arg8 = (unsigned char)((v/10) << 4); - arg8 |= ((unsigned char)(v - (v/10)*10)) & 0x0F; - return arg8; -} - -/* - *-------------------------------------------------------------------- - * Method: Bcd2Num() - * Purpose: Convert 8-bit BCD code to a number. - * Arguments: v - BCD code. - * Returns: 16-bit unsigned integer - *-------------------------------------------------------------------- - */ -unsigned short MKCpu::Bcd2Num(unsigned char v) -{ - unsigned short ret = 0; - ret = 10 * ((v & 0xF0) >> 4) + (unsigned char)(v & 0x0F); - return ret; -} - -/* - *-------------------------------------------------------------------- - * Method: CheckFlag() - * Purpose: Check if given bit flag in CPU status register is set - * or not. - * Arguments: flag - byte with the bit to be checked set and other - * bits not set. - * Returns: bool - *-------------------------------------------------------------------- - */ -bool MKCpu::CheckFlag(unsigned char flag) -{ - return ((mReg.Flags & flag) == flag); -} - -/* - *-------------------------------------------------------------------- - * Method: SetFlag() - * Purpose: Set or unset CPU status flag. - * Arguments: set - if true, set flag, if false, unset flag. - * flag - a byte with a bit set on the position of flag - * being altered and zeroes on other positions. - * Returns: n/a - *-------------------------------------------------------------------- - */ -void MKCpu::SetFlag(bool set, unsigned char flag) -{ - if (set) { - mReg.Flags |= flag; - } else { - mReg.Flags &= ~flag; - } -} - -/* - *-------------------------------------------------------------------- - * Method: AddWithCarry() - * Purpose: Add Acc + Mem with Carry, update flags and Acc. - * Arguments: mem8 - memory argument (byte) - * Returns: byte value Acc + Mem + Carry - *-------------------------------------------------------------------- - */ -unsigned char MKCpu::AddWithCarry(unsigned char mem8) -{ - /* This algorithm was shamelessly ripped from Frodo emulator code. - Well, maybe not totally shamelessly, I put up a fight to roll my own. - I gave up after one day of trying to make it right based only on MOS documentation. - For my defense I have this - Frodo also does not work 100% as real metal MOS 6502). - And so doesn't Kowalski's emulator. - E.g.: - Real CPU - Rockwell 6502 AP in BCD mode: - 80 + f0 and C=0 gives d0 and N=1 V=1 Z=0 C=1 (F9) - Kowalski's 6502 emulator gives: d0 and N=0, V=0, Z=0, C=1 - My emulator gives: d0 and N=0, V=1, Z=0, C=1 - */ - unsigned short utmp16 = mReg.Acc + mem8 + (CheckFlag(FLAGS_CARRY) ? 1 : 0); - if (CheckFlag(FLAGS_DEC)) { // BCD mode - - unsigned short al = (mReg.Acc & 0x0F) + (mem8 & 0x0F) + (CheckFlag(FLAGS_CARRY) ? 1 : 0); - if (al > 9) al += 6; - unsigned short ah = (mReg.Acc >> 4) + (mem8 >> 4); - if (al > 0x0F) ah++; - SetFlag((utmp16 == 0), FLAGS_ZERO); - SetFlag((((ah << 4) & FLAGS_SIGN) == FLAGS_SIGN), FLAGS_SIGN); - SetFlag(((((ah << 4) ^ mReg.Acc) & 0x80) && !((mReg.Acc ^ mem8) & 0x80)), FLAGS_OVERFLOW); - if (ah > 9) ah += 6; - SetFlag((ah > 0x0F), FLAGS_CARRY); - mReg.Acc = (ah << 4) | (al & 0x0f); - } else { // binary mode - - SetFlag((utmp16 > 0xff), FLAGS_CARRY); - SetFlag((!((mReg.Acc ^ mem8) & 0x80) && ((mReg.Acc ^ utmp16) & 0x80)), FLAGS_OVERFLOW); - SetFlag((utmp16 == 0), FLAGS_ZERO); - SetFlag(((utmp16 & 0xFF) & FLAGS_SIGN), FLAGS_SIGN); - mReg.Acc = utmp16 & 0xFF; - } - return mReg.Acc; -} - -/* - *-------------------------------------------------------------------- - * Method: SubWithCarry() - * Purpose: Subtract Acc - Mem with Carry, update flags and Acc. - * Arguments: mem8 - memory argument (byte) - * Returns: byte value Acc - Mem - Carry - *-------------------------------------------------------------------- - */ -unsigned char MKCpu::SubWithCarry(unsigned char mem8) -{ - unsigned short utmp16 = mReg.Acc - mem8 - (CheckFlag(FLAGS_CARRY) ? 0 : 1); - - /* This algorithm was shamelessly ripped from Frodo emulator code. - See my comments in AddWithCarry() method. - This method returned the same results when testing BCD mode as Rockwell 6502 AP CPU. - Kowalski's emulator returned different results. - My method also passes BCD mode behavior test by Bruce Clark (TestBCD.65s). - */ - if (CheckFlag(FLAGS_DEC)) { // BCD mode - - unsigned char al = (mReg.Acc & 0x0F) - (mem8 & 0x0F) - (CheckFlag(FLAGS_CARRY) ? 0 : 1); - unsigned char ah = (mReg.Acc >> 4) - (mem8 >> 4); - if (al & 0x10) { - al -= 6; ah--; - } - if (ah & 0x10) ah -= 6; - SetFlag((utmp16 < 0x100), FLAGS_CARRY); - SetFlag(((mReg.Acc ^ utmp16) & 0x80) && ((mReg.Acc ^ mem8) & 0x80), FLAGS_OVERFLOW); - SetFlag((utmp16 == 0), FLAGS_ZERO); - SetFlag(((utmp16 & 0xFF) & FLAGS_SIGN) == FLAGS_SIGN, FLAGS_SIGN); - mReg.Acc = (ah << 4) | (al & 0x0f); - - } else { // binary mode - - SetFlag((utmp16 < 0x100), FLAGS_CARRY); - SetFlag(((mReg.Acc ^ utmp16) & 0x80) && ((mReg.Acc ^ mem8) & 0x80), FLAGS_OVERFLOW); - SetFlag((utmp16 == 0), FLAGS_ZERO); - SetFlag(((utmp16 & 0xFF) & FLAGS_SIGN) == FLAGS_SIGN, FLAGS_SIGN); - mReg.Acc = utmp16 & 0xFF; - - } - return mReg.Acc; -} - -/* - *-------------------------------------------------------------------- - * Method: ~MKCpu() - * Purpose: Class destructor. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -MKCpu::~MKCpu() -{ - if (mLocalMem) { - if (NULL != mpMem) - delete mpMem; - } -} - -/* - *-------------------------------------------------------------------- - * Method: GetAddrWithMode() - * Purpose: Get address of the argument with specified mode. - * Increment PC. - * Arguments: mode - code of the addressing mode, see eAddrModes. - * Returns: 16-bit address - *-------------------------------------------------------------------- - */ -unsigned short MKCpu::GetAddrWithMode(int mode) -{ - unsigned short arg16 = 0; - - switch (mode) { - - case ADDRMODE_IMM: - arg16 = mReg.PtrAddr++; - break; - - case ADDRMODE_ABS: - arg16 = GetArg16(0); - break; - - case ADDRMODE_ZP: - arg16 = (unsigned short) mpMem->Peek8bit(mReg.PtrAddr++); - break; - - case ADDRMODE_IMP: - // implied mode is an internal CPU register - break; - - case ADDRMODE_IND: - arg16 = mpMem->Peek16bit(mReg.PtrAddr++); - arg16 = mpMem->Peek16bit(arg16); - break; - - case ADDRMODE_ABX: - arg16 = GetArg16(mReg.IndX); - break; - - case ADDRMODE_ABY: - arg16 = GetArg16(mReg.IndY); - break; - - case ADDRMODE_ZPX: - arg16 = (mpMem->Peek8bit(mReg.PtrAddr++) + mReg.IndX) & 0xFF; - break; - - case ADDRMODE_ZPY: - arg16 = (mpMem->Peek8bit(mReg.PtrAddr++) + mReg.IndY) & 0xFF; - break; - - case ADDRMODE_IZX: - arg16 = (mpMem->Peek8bit(mReg.PtrAddr++) + mReg.IndX) & 0xFF; - arg16 = mpMem->Peek16bit(arg16); - break; - - case ADDRMODE_IZY: - arg16 = mpMem->Peek8bit(mReg.PtrAddr++); - arg16 = mpMem->Peek16bit(arg16) + mReg.IndY; - break; - - case ADDRMODE_REL: - arg16 = ComputeRelJump(mpMem->Peek8bit(mReg.PtrAddr++)); - break; - - case ADDRMODE_ACC: - // acc mode is an internal CPU register - break; - - default: - throw MKGenException("ERROR: Wrong addressing mode!"); - break; - } - - return arg16; -} - -/* - *-------------------------------------------------------------------- - * Method: ExecOpcode() - * Purpose: Execute VM's opcode. - * Arguments: memaddr - address of code in virtual memory. - * Returns: Pointer to CPU registers and flags structure. - *-------------------------------------------------------------------- - */ -Regs *MKCpu::ExecOpcode(unsigned short memaddr) -{ - mReg.PtrAddr = memaddr; - unsigned char opcode = mpMem->Peek8bit(mReg.PtrAddr++); - unsigned char arg8 = 0; - unsigned short arg16 = 0; - - SetFlag(false, FLAGS_BRK); // reset BRK flag - we want to detect - mReg.SoftIrq = false; // software interrupt each time it happens - // (non-maskable) - mReg.LastRTS = false; - - switch (opcode) { - - case OPCODE_BRK: // software interrupt, Implied ($00 : BRK) - arg16 = 0x100; - arg16 += mReg.PtrStack--; - // Note that BRK is really a 2-bytes opcode. Each BRK opcode should be padded by extra byte, - // because the return address put on stack is PC + 1 (where PC is the next address after BRK). - // That means the next opcode after BRK will not be executed upon return from interrupt, - // but the next after that will be. - mReg.PtrAddr++; - mpMem->Poke8bit(arg16, (unsigned char) (((mReg.PtrAddr) & 0xFF00) >> 8)); // HI(PC+1) - HI part of next instr. addr. + 1 - arg16 = 0x100; - arg16 += mReg.PtrStack--; - mpMem->Poke8bit(arg16, (unsigned char) ((mReg.PtrAddr) & 0x00FF)); // LO(PC+1) - LO part of next instr. addr. + 1 - arg16 = 0x100; - arg16 += mReg.PtrStack--; - SetFlag(true, FLAGS_BRK); // The BRK flag that goes on stack is set. - mpMem->Poke8bit(arg16, mReg.Flags); - SetFlag(false, FLAGS_BRK); // The BRK flag that remains in CPU status is unchanged, so unset after putting on stack. - //mReg.SoftIrq = true; - mReg.PtrAddr = mpMem->Peek16bit(0xFFFE); // Load BRK vector into the PC. - break; - - case OPCODE_NOP: // NO oPeration, Implied ($EA : NOP) - break; - - case OPCODE_LDA_IZX: // LoaD Accumulator, Indexed Indirect ($A1 arg : LDA (arg,X) ;arg=0..$FF), MEM=&(arg+X) - arg16 = GetAddrWithMode(ADDRMODE_IZX); - mReg.Acc = mpMem->Peek8bit(arg16); - SetFlags(mReg.Acc); - break; - - case OPCODE_LDA_ZP: // LoaD Accumulator, Zero Page ($A5 arg : LDA arg ;arg=0..$FF), MEM=arg - mReg.Acc = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_ZP)); - SetFlags(mReg.Acc); - break; - - case OPCODE_LDA_IMM: // LoaD Accumulator, Immediate ($A9 arg : LDA #arg ;arg=0..$FF), MEM=PC+1 - mReg.Acc = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); - SetFlags(mReg.Acc); - break; - - case OPCODE_LDA_ABS: // LoaD Accumulator, Absolute ($AD addrlo addrhi : LDA addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - mReg.Acc = mpMem->Peek8bit(arg16); - SetFlags(mReg.Acc); - break; - - case OPCODE_LDA_IZY: // LoaD Accumulator, Indirect Indexed ($B1 arg : LDA (arg),Y ;arg=0..$FF), MEM=&arg+Y - arg16 = GetAddrWithMode(ADDRMODE_IZY); - mReg.Acc = mpMem->Peek8bit(arg16); - SetFlags(mReg.Acc); - break; - - case OPCODE_LDA_ZPX: // LoaD Accumulator, Zero Page Indexed, X ($B5 arg : LDA arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - mReg.Acc = mpMem->Peek8bit(arg16); - SetFlags(mReg.Acc); - break; - - case OPCODE_LDA_ABY: // LoaD Accumulator, Absolute Indexed, Y ($B9 addrlo addrhi : LDA addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - mReg.Acc = mpMem->Peek8bit(arg16); - SetFlags(mReg.Acc); - break; - - case OPCODE_LDA_ABX: // LoaD Accumulator, Absolute Indexed, X ($BD addrlo addrhi : LDA addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - mReg.Acc = mpMem->Peek8bit(arg16); - SetFlags(mReg.Acc); - break; - - case OPCODE_LDX_IMM: // LoaD X register, Immediate ($A2 arg : LDX #arg ;arg=0..$FF), MEM=PC+1 - mReg.IndX = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); - SetFlags(mReg.IndX); - break; - - case OPCODE_LDX_ZP: // LoaD X register, Zero Page ($A6 arg : LDX arg ;arg=0..$FF), MEM=arg - mReg.IndX = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_ZP)); - SetFlags(mReg.IndX); - break; - - case OPCODE_LDX_ABS: // LoaD X register, Absolute ($AE addrlo addrhi : LDX addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - mReg.IndX = mpMem->Peek8bit(arg16); - SetFlags(mReg.IndX); - break; - - case OPCODE_LDX_ZPY: // LoaD X register, Zero Page Indexed, Y ($B6 arg : LDX arg,Y ;arg=0..$FF), MEM=arg+Y - arg16 = GetAddrWithMode(ADDRMODE_ZPY); - mReg.IndX = mpMem->Peek8bit(arg16); - SetFlags(mReg.IndX); - break; - - case OPCODE_LDX_ABY: // LoaD X register, Absolute Indexed, Y ($BE addrlo addrhi : LDX addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - mReg.IndX = mpMem->Peek8bit(arg16); - SetFlags(mReg.IndX); - break; - - case OPCODE_LDY_IMM: // LoaD Y register, Immediate ($A0 arg : LDY #arg ;arg=0..$FF), MEM=PC+1 - mReg.IndY = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); - SetFlags(mReg.IndY); - break; - - case OPCODE_LDY_ZP: // LoaD Y register, Zero Page ($A4 arg : LDY arg ;arg=0..$FF), MEM=arg - mReg.IndY = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_ZP)); - SetFlags(mReg.IndY); - break; - - case OPCODE_LDY_ABS: // LoaD Y register, Absolute ($AC addrlo addrhi : LDY addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - mReg.IndY = mpMem->Peek8bit(arg16); - SetFlags(mReg.IndY); - break; - - case OPCODE_LDY_ZPX: // LoaD Y register, Zero Page Indexed, X ($B4 arg : LDY arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - mReg.IndY = mpMem->Peek8bit(arg16); - SetFlags(mReg.IndY); - break; - - case OPCODE_LDY_ABX: // LoaD Y register, Absolute Indexed, X ($BC addrlo addrhi : LDY addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - mReg.IndY = mpMem->Peek8bit(arg16); - SetFlags(mReg.IndY); - break; - - case OPCODE_TAX: // Transfer A to X, Implied ($AA : TAX) - mReg.IndX = mReg.Acc; - SetFlags(mReg.IndX); - break; - - case OPCODE_TAY: // Transfer A to Y, Implied ($A8 : TAY) - mReg.IndY = mReg.Acc; - SetFlags(mReg.IndY); - break; - - case OPCODE_TXA: // Transfer X to A, Implied ($8A : TXA) - mReg.Acc = mReg.IndX; - SetFlags(mReg.Acc); - break; - - case OPCODE_TYA: // Transfer Y to A, Implied ($98 : TYA) - mReg.Acc = mReg.IndY; - SetFlags(mReg.Acc); - break; - - case OPCODE_TSX: // Transfer Stack ptr to X, Implied ($BA : TSX) - mReg.IndX = mReg.PtrStack; - SetFlags(mReg.IndX); - break; - - case OPCODE_TXS: // Transfer X to Stack ptr, Implied ($9A : TXS) - mReg.PtrStack = mReg.IndX; - break; - - case OPCODE_STA_IZX: // STore Accumulator, Indexed Indirect ($81 arg : STA (arg,X) ;arg=0..$FF), MEM=&(arg+X) - arg16 = GetAddrWithMode(ADDRMODE_IZX); - mpMem->Poke8bit(arg16, mReg.Acc); - break; - - case OPCODE_STA_ZP: // STore Accumulator, Zero Page ($85 arg : STA arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - mpMem->Poke8bit(arg16, mReg.Acc); - break; - - case OPCODE_STA_ABS: // STore Accumulator, Absolute ($8D addrlo addrhi : STA addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - mpMem->Poke8bit(arg16, mReg.Acc); - break; - - case OPCODE_STA_IZY: // STore Accumulator, Indirect Indexed ($91 arg : STA (arg),Y ;arg=0..$FF), MEM=&arg+Y - arg16 = GetAddrWithMode(ADDRMODE_IZY); - mpMem->Poke8bit(arg16, mReg.Acc); - break; - - case OPCODE_STA_ZPX: // STore Accumulator, Zero Page Indexed, X ($95 arg : STA arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - mpMem->Poke8bit(arg16, mReg.Acc); - break; - - case OPCODE_STA_ABY: // STore Accumulator, Absolute Indexed, Y ($99 addrlo addrhi : STA addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - mpMem->Poke8bit(arg16, mReg.Acc); - break; - - case OPCODE_STA_ABX: // STore Accumulator, Absolute Indexed, X ($9D addrlo addrhi : STA addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - mpMem->Poke8bit(arg16, mReg.Acc); - break; - - case OPCODE_STX_ZP: // STore X register, Zero Page ($86 arg : STX arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - mpMem->Poke8bit(arg16, mReg.IndX); - break; - - case OPCODE_STX_ABS: // STore X register, Absolute ($8E addrlo addrhi : STX addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - mpMem->Poke8bit(arg16, mReg.IndX); - break; - - case OPCODE_STX_ZPY: // STore X register, Zero Page Indexed, Y ($96 arg : STX arg,Y ;arg=0..$FF), MEM=arg+Y - arg16 = GetAddrWithMode(ADDRMODE_ZPY); - mpMem->Poke8bit(arg16, mReg.IndX); - break; - - case OPCODE_STY_ZP: // STore Y register, Zero Page ($84 arg : STY arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - mpMem->Poke8bit(arg16, mReg.IndY); - break; - - case OPCODE_STY_ABS: // STore Y register, Absolute ($8C addrlo addrhi : STY addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - mpMem->Poke8bit(arg16, mReg.IndY); - break; - - case OPCODE_STY_ZPX: // STore Y register, Zero Page Indexed, X ($94 arg : STY arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - mpMem->Poke8bit(arg16, mReg.IndY); - break; - - case OPCODE_BNE_REL: // Branch on Not Equal, Relative ($D0 signoffs : BNE signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - arg16 = GetAddrWithMode(ADDRMODE_REL); - if (!CheckFlag(FLAGS_ZERO)) { - mReg.PtrAddr = arg16; - } - break; - - case OPCODE_BEQ_REL: // Branch on EQual, Relative ($F0 signoffs : BEQ signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - arg16 = GetAddrWithMode(ADDRMODE_REL); - if (CheckFlag(FLAGS_ZERO)) { - mReg.PtrAddr = arg16; - } - break; - - case OPCODE_BPL_REL: // Branch on PLus, Relative ($10 signoffs : BPL signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - arg16 = GetAddrWithMode(ADDRMODE_REL); - if (!CheckFlag(FLAGS_SIGN)) { - mReg.PtrAddr = arg16; - } - break; - - case OPCODE_BMI_REL: // Branch on MInus, Relative ($30 signoffs : BMI signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - arg16 = GetAddrWithMode(ADDRMODE_REL); - if (CheckFlag(FLAGS_SIGN)) { - mReg.PtrAddr = arg16; - } - break; - - case OPCODE_BVC_REL: // Branch on oVerflow Clear, Relative ($50 signoffs : BVC signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - arg16 = GetAddrWithMode(ADDRMODE_REL); - if (!CheckFlag(FLAGS_OVERFLOW)) { - mReg.PtrAddr = arg16; - } - break; - - case OPCODE_BVS_REL: // Branch on oVerflow Set, Relative ($70 signoffs : BVS signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - arg16 = GetAddrWithMode(ADDRMODE_REL); - if (CheckFlag(FLAGS_OVERFLOW)) { - mReg.PtrAddr = arg16; - } - break; - - case OPCODE_BCC_REL: // Branch on Carry Clear, Relative ($90 signoffs : BCC signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - arg16 = GetAddrWithMode(ADDRMODE_REL); - if (!CheckFlag(FLAGS_CARRY)) { - mReg.PtrAddr = arg16; - } - break; - - case OPCODE_BCS_REL: // Branch on Carry Set, Relative ($B0 signoffs : BCS signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - arg16 = GetAddrWithMode(ADDRMODE_REL); - if (CheckFlag(FLAGS_CARRY)) { - mReg.PtrAddr = arg16; - } - break; - - /*** - case OPCODE_BRA: // branch always to a relative 1-byte address offset -128 ($80)..127 ($7F) (OPCODE_BEQ reladdr : BEQ reladdr) - arg8 = mpMem->Peek8bit(mReg.PtrAddr++); - mReg.PtrAddr = ComputeRelJump(arg8); - break; - ***/ - - case OPCODE_INC_ZP: // INCrement memory, Zero Page ($E6 arg : INC arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16) + 1; - mpMem->Poke8bit(arg16, arg8); - SetFlags(arg8); - break; - - case OPCODE_INC_ABS: // INCrement memory, Absolute ($EE addrlo addrhi : INC addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16) + 1; - mpMem->Poke8bit(arg16, arg8); - SetFlags(arg8); - break; - - case OPCODE_INC_ZPX: // INCrement memory, Zero Page Indexed, X ($F6 arg : INC arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - arg8 = mpMem->Peek8bit(arg16) + 1; - mpMem->Poke8bit(arg16, arg8); - SetFlags(arg8); - break; - - case OPCODE_INC_ABX: // INCrement memory, Absolute Indexed, X ($FE addrlo addrhi : INC addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - arg8 = mpMem->Peek8bit(arg16) + 1; - mpMem->Poke8bit(arg16, arg8); - SetFlags(arg8); - break; - - case OPCODE_INX: // INcrement X, Implied ($E8 : INX) - mReg.IndX++; - SetFlags(mReg.IndX); - break; - - case OPCODE_DEX: // DEcrement X, Implied ($CA : DEX) - mReg.IndX--; - SetFlags(mReg.IndX); - break; - - case OPCODE_INY: // INcrement Y, Implied ($C8 : INY) - mReg.IndY++; - SetFlags(mReg.IndY); - break; - - case OPCODE_DEY: // DEcrement Y, Implied ($88 : DEY) - mReg.IndY--; - SetFlags(mReg.IndY); - break; - - case OPCODE_JMP_ABS: // JuMP, Absolute ($4C addrlo addrhi : JMP addr ;addr=0..$FFFF), MEM=addr - mReg.PtrAddr = GetAddrWithMode(ADDRMODE_ABS); - break; - - case OPCODE_JMP_IND: // JuMP, Indirect Absolute ($6C addrlo addrhi : JMP (addr) ;addr=0..FFFF), MEM=&addr - mReg.PtrAddr = GetAddrWithMode(ADDRMODE_IND); - break; - - case OPCODE_ORA_IZX: // bitwise OR with Accumulator, Indexed Indirect ($01 arg : ORA (arg,X) ;arg=0..$FF), MEM=&(arg+X) - arg16 = GetAddrWithMode(ADDRMODE_IZX); - LogicOpAcc(arg16, LOGOP_OR); - break; - - case OPCODE_ORA_ZP: // bitwise OR with Accumulator, Zero Page ($05 arg : ORA arg ;arg=0..$FF), MEM=arg - LogicOpAcc(GetAddrWithMode(ADDRMODE_ZP), LOGOP_OR); - break; - - case OPCODE_ORA_IMM: // bitwise OR with Accumulator, Immediate ($09 arg : ORA #arg ;arg=0..$FF), MEM=PC+1 - LogicOpAcc(GetAddrWithMode(ADDRMODE_IMM), LOGOP_OR); - break; - - case OPCODE_ORA_ABS: // bitwise OR with Accumulator, Absolute ($0D addrlo addrhi : ORA addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - LogicOpAcc(arg16, LOGOP_OR); - break; - - case OPCODE_ORA_IZY: // bitwise OR with Accumulator, Indirect Indexed ($11 arg : ORA (arg),Y ;arg=0..$FF), MEM=&arg+Y - arg16 = GetAddrWithMode(ADDRMODE_IZY); - LogicOpAcc(arg16, LOGOP_OR); - break; - - case OPCODE_ORA_ZPX: // bitwise OR with Accumulator, Zero Page Indexed, X ($15 arg : ORA arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - LogicOpAcc(arg16, LOGOP_OR); - break; - - case OPCODE_ORA_ABY: // bitwise OR with Accumulator, Absolute Indexed, Y ($19 addrlo addrhi : ORA addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - LogicOpAcc(arg16, LOGOP_OR); - break; - - case OPCODE_ORA_ABX: // bitwise OR with Accumulator, Absolute Indexed, X ($1D addrlo addrhi : ORA addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - LogicOpAcc(arg16, LOGOP_OR); - break; - - case OPCODE_ASL_ZP: // Arithmetic Shift Left, Zero Page ($06 arg : ASL arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16); - arg8 = ShiftLeft(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_ASL: // Arithmetic Shift Left, Accumulator ($0A : ASL) - mReg.Acc = ShiftLeft(mReg.Acc); - break; - - case OPCODE_ASL_ABS: // Arithmetic Shift Left, Absolute ($0E addrlo addrhi : ASL addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16); - arg8 = ShiftLeft(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_ASL_ZPX: // Arithmetic Shift Left, Zero Page Indexed, X ($16 arg : ASL arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - arg8 = mpMem->Peek8bit(arg16); - arg8 = ShiftLeft(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_ASL_ABX: // Arithmetic Shift Left, Absolute Indexed, X ($1E addrlo addrhi : ASL addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - arg8 = mpMem->Peek8bit(arg16); - arg8 = ShiftLeft(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_JSR_ABS: // Jump to SubRoutine, Absolute ($20 addrlo addrhi : JSR addr ;addr=0..$FFFF), MEM=addr - // PC - next instruction address - // Push PC-1 on stack (HI, then LO). - // Currently PC (mReg.PtrAddr) is at the 1-st argument of JSR. - // Therefore the actual PC-1 used in calculations equals: mReg.PtrAddr+1 - arg16 = 0x100; - arg16 += mReg.PtrStack--; - mpMem->Poke8bit(arg16, (unsigned char) (((mReg.PtrAddr+1) & 0xFF00) >> 8)); // HI(PC-1) - HI part of next instr. addr. - 1 - arg16 = 0x100; - arg16 += mReg.PtrStack--; - mpMem->Poke8bit(arg16, (unsigned char) ((mReg.PtrAddr+1) & 0x00FF)); // LO(PC-1) - LO part of next instr. addr. - 1 - mReg.PtrAddr = GetAddrWithMode(ADDRMODE_ABS); - break; - - case OPCODE_AND_IZX: // bitwise AND with accumulator, Indexed Indirect ($21 arg : AND (arg,X) ;arg=0..$FF), MEM=&(arg+X) - arg16 = GetAddrWithMode(ADDRMODE_IZX); - LogicOpAcc(arg16, LOGOP_AND); - break; - - case OPCODE_AND_ZP: // bitwise AND with accumulator, Zero Page ($25 arg : AND arg ;arg=0..$FF), MEM=arg - LogicOpAcc(GetAddrWithMode(ADDRMODE_ZP), LOGOP_AND); - break; - - case OPCODE_AND_IMM: // bitwise AND with accumulator, Immediate ($29 arg : AND #arg ;arg=0..$FF), MEM=PC+1 - LogicOpAcc(GetAddrWithMode(ADDRMODE_IMM), LOGOP_AND); - break; - - case OPCODE_AND_ABS: // bitwise AND with accumulator, Absolute ($2D addrlo addrhi : AND addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - LogicOpAcc(arg16, LOGOP_AND); - break; - - case OPCODE_AND_IZY: // bitwise AND with accumulator, Indirect Indexed ($31 arg : AND (arg),Y ;arg=0..$FF), MEM=&arg+Y - arg16 = GetAddrWithMode(ADDRMODE_IZY); - LogicOpAcc(arg16, LOGOP_AND); - break; - - case OPCODE_AND_ZPX: // bitwise AND with accumulator, Zero Page Indexed, X ($35 arg : AND arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - LogicOpAcc(arg16, LOGOP_AND); - break; - - case OPCODE_AND_ABY: // bitwise AND with accumulator, Absolute Indexed, Y ($39 addrlo addrhi : AND addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - LogicOpAcc(arg16, LOGOP_AND); - break; - - case OPCODE_AND_ABX: // bitwise AND with accumulator, Absolute Indexed, X ($3D addrlo addrhi : AND addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - LogicOpAcc(arg16, LOGOP_AND); - break; - - case OPCODE_BIT_ZP: // test BITs, Zero Page ($24 arg : BIT arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16); - arg8 &= mReg.Acc; - SetFlags(arg8); - mReg.Flags |= (arg8 & FLAGS_OVERFLOW); - break; - - case OPCODE_BIT_ABS: // test BITs, Absolute ($2C addrlo addrhi : BIT addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16); - arg8 &= mReg.Acc; - SetFlags(arg8); - mReg.Flags |= (arg8 & FLAGS_OVERFLOW); - break; - - case OPCODE_ROL_ZP: // ROtate Left, Zero Page ($26 arg : ROL arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16); - arg8 = RotateLeft(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_ROL: // ROtate Left, Accumulator ($2A : ROL) - mReg.Acc = RotateLeft(mReg.Acc); - break; - - case OPCODE_ROL_ABS: // ROtate Left, Absolute ($2E addrlo addrhi : ROL addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16); - arg8 = RotateLeft(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_ROL_ZPX: // ROtate Left, Zero Page Indexed, X ($36 arg : ROL arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - arg8 = mpMem->Peek8bit(arg16); - arg8 = RotateLeft(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_ROL_ABX: // ROtate Left, Absolute Indexed, X ($3E addrlo addrhi : ROL addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - arg8 = mpMem->Peek8bit(arg16); - arg8 = RotateLeft(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_PHP: // PusH Processor status on Stack, Implied ($08 : PHP) - arg16 = 0x100; - arg16 += mReg.PtrStack--; - arg8 = mReg.Flags | FLAGS_BRK; - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_PHA: // PusH Accumulator, Implied ($48 : PHA) - arg16 = 0x100; - arg16 += mReg.PtrStack--; - mpMem->Poke8bit(arg16, mReg.Acc); - break; - - case OPCODE_PLP: // PuLl Processor status, Implied ($28 : PLP) - arg16 = 0x100; - arg16 += ++mReg.PtrStack; - mReg.Flags = mpMem->Peek8bit(arg16); - break; - - case OPCODE_PLA: // PuLl Accumulator, Implied ($68 : PLA) - arg16 = 0x100; - arg16 += ++mReg.PtrStack; - mReg.Acc = mpMem->Peek8bit(arg16); - SetFlags(mReg.Acc); - break; - - case OPCODE_CLC: // CLear Carry, Implied ($18 : CLC) - SetFlag(false, FLAGS_CARRY); - break; - - case OPCODE_SEC: // SEt Carry, Implied ($38 : SEC) - SetFlag(true, FLAGS_CARRY); - break; - - case OPCODE_CLI: // CLear Interrupt, Implied ($58 : CLI) - SetFlag(false, FLAGS_IRQ); - break; - - case OPCODE_CLV: // CLear oVerflow, Implied ($B8 : CLV) - SetFlag(false, FLAGS_OVERFLOW); - break; - - case OPCODE_CLD: // CLear Decimal, Implied ($D8 : CLD) - SetFlag(false, FLAGS_DEC); - break; - - case OPCODE_SED: // SEt Decimal, Implied ($F8 : SED) - SetFlag(true, FLAGS_DEC); - break; - - case OPCODE_SEI: // SEt Interrupt, Implied ($78 : SEI) - SetFlag(true, FLAGS_IRQ); - break; - - /* - * RTI retrieves the Processor Status Word (flags) and the Program Counter from the stack in that order - * (interrupts push the PC first and then the PSW). - * Note that unlike RTS, the return address on the stack is the actual address rather than the address-1. - */ - case OPCODE_RTI: // ReTurn from Interrupt, Implied ($40 : RTI) - arg16 = 0x100; - arg16 += ++mReg.PtrStack; - mReg.Flags = mpMem->Peek8bit(arg16); - arg16++; mReg.PtrStack++; - mReg.PtrAddr = mpMem->Peek8bit(arg16); - arg16++; mReg.PtrStack++; - mReg.PtrAddr += (mpMem->Peek8bit(arg16) * 0x100); - mReg.SoftIrq = CheckFlag(FLAGS_BRK); - break; - - case OPCODE_RTS: // ReTurn from Subroutine, Implied ($60 : RTS) - if (mReg.PtrStack == 0xFF) { - mReg.LastRTS = true; - break; - } - arg16 = 0x100; - arg16 += ++mReg.PtrStack; - mReg.PtrAddr = mpMem->Peek8bit(arg16); - arg16++; mReg.PtrStack++; - mReg.PtrAddr += (mpMem->Peek8bit(arg16) * 0x100); - mReg.PtrAddr++; - break; - - case OPCODE_EOR_IZX: // bitwise Exclusive OR, Indexed Indirect ($41 arg : EOR (arg,X) ;arg=0..$FF), MEM=&(arg+X) - arg16 = GetAddrWithMode(ADDRMODE_IZX); - LogicOpAcc(arg16, LOGOP_EOR); - break; - - case OPCODE_EOR_ZP: // bitwise Exclusive OR, Zero Page ($45 arg : EOR arg ;arg=0..$FF), MEM=arg - LogicOpAcc(GetAddrWithMode(ADDRMODE_ZP), LOGOP_EOR); - break; - - case OPCODE_EOR_IMM: // bitwise Exclusive OR, Immediate ($49 arg : EOR #arg ;arg=0..$FF), MEM=PC+1 - LogicOpAcc(GetAddrWithMode(ADDRMODE_IMM), LOGOP_EOR); - break; - - case OPCODE_EOR_ABS: // bitwise Exclusive OR, Absolute ($4D addrlo addrhi : EOR addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - LogicOpAcc(arg16, LOGOP_EOR); - break; - - case OPCODE_EOR_IZY: // bitwise Exclusive OR, Indirect Indexed ($51 arg : EOR (arg),Y ;arg=0..$FF), MEM=&arg+Y - arg16 = GetAddrWithMode(ADDRMODE_IZY); - LogicOpAcc(arg16, LOGOP_EOR); - break; - - case OPCODE_EOR_ZPX: // bitwise Exclusive OR, Zero Page Indexed, X ($55 arg : EOR arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - LogicOpAcc(arg16, LOGOP_EOR); - break; - - case OPCODE_EOR_ABY: // bitwise Exclusive OR, Absolute Indexed, Y ($59 addrlo addrhi : EOR addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - LogicOpAcc(arg16, LOGOP_EOR); - break; - - case OPCODE_EOR_ABX: // bitwise Exclusive OR, Absolute Indexed, X ($5D addrlo addrhi : EOR addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - LogicOpAcc(arg16, LOGOP_EOR); - break; - - case OPCODE_LSR_ZP: // Logical Shift Right, Zero Page ($46 arg : LSR arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16); - arg8 = ShiftRight(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_LSR: // Logical Shift Right, Accumulator ($4A : LSR) - mReg.Acc = ShiftRight(mReg.Acc); - break; - - case OPCODE_LSR_ABS: // Logical Shift Right, Absolute ($4E addrlo addrhi : LSR addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16); - arg8 = ShiftRight(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_LSR_ZPX: // Logical Shift Right, Zero Page Indexed, X ($56 arg : LSR arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - arg8 = mpMem->Peek8bit(arg16); - arg8 = ShiftRight(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_LSR_ABX: // Logical Shift Right, Absolute Indexed, X ($5E addrlo addrhi : LSR addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - arg8 = mpMem->Peek8bit(arg16); - arg8 = ShiftRight(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_ADC_IZX: // ADd with Carry, Indexed Indirect ($61 arg : ADC (arg,X) ;arg=0..$FF), MEM=&(arg+X) - arg16 = GetAddrWithMode(ADDRMODE_IZX); - AddWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_ADC_ZP: // ADd with Carry, Zero Page ($65 arg : ADC arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - AddWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_ADC_IMM: // ADd with Carry, Immediate ($69 arg : ADC #arg ;arg=0..$FF), MEM=PC+1 - AddWithCarry(mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM))); - break; - - case OPCODE_ADC_ABS: // ADd with Carry, Absolute ($6D addrlo addrhi : ADC addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - AddWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_ADC_IZY: // ADd with Carry, Indirect Indexed ($71 arg : ADC (arg),Y ;arg=0..$FF), MEM=&arg+Y - arg16 = GetAddrWithMode(ADDRMODE_IZY); - AddWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_ADC_ZPX: // ADd with Carry, Zero Page Indexed, X ($75 arg : ADC arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - AddWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_ADC_ABY: // ADd with Carry, Absolute Indexed, Y ($79 addrlo addrhi : ADC addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - AddWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_ADC_ABX: // ADd with Carry, Absolute Indexed, X ($7D addrlo addrhi : ADC addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - AddWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_ROR_ZP: // ROtate Right, Zero Page ($66 arg : ROR arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16); - mpMem->Poke8bit(arg16, RotateRight(arg8)); - break; - - case OPCODE_ROR: // ROtate Right, Accumulator ($6A : ROR) - mReg.Acc = RotateRight(mReg.Acc); - break; - - case OPCODE_ROR_ABS: // ROtate Right, Absolute ($6E addrlo addrhi : ROR addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16); - mpMem->Poke8bit(arg16, RotateRight(arg8)); - break; - - case OPCODE_ROR_ZPX: // ROtate Right, Zero Page Indexed, X ($76 arg : ROR arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - arg8 = mpMem->Peek8bit(arg16); - mpMem->Poke8bit(arg16, RotateRight(arg8)); - break; - - case OPCODE_ROR_ABX: // ROtate Right, Absolute Indexed, X ($7E addrlo addrhi : ROR addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - arg8 = mpMem->Peek8bit(arg16); - mpMem->Poke8bit(arg16, RotateRight(arg8)); - break; - - case OPCODE_CPY_IMM: // ComPare Y register, Immediate ($C0 arg : CPY #arg ;arg=0..$FF), MEM=PC+1 - arg8 = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); - SetFlag((mReg.IndY >= arg8), FLAGS_CARRY); - arg8 = mReg.IndY - arg8; - SetFlags(arg8); - break; - - case OPCODE_CPY_ZP: // ComPare Y register, Zero Page ($C4 arg : CPY arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.IndY >= arg8), FLAGS_CARRY); - arg8 = mReg.IndY - arg8; - SetFlags(arg8); - break; - - case OPCODE_CPY_ABS: // ComPare Y register, Absolute ($CC addrlo addrhi : CPY addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.IndY >= arg8), FLAGS_CARRY); - arg8 = mReg.IndY - arg8; - SetFlags(arg8); - break; - - case OPCODE_CMP_IZX: // CoMPare accumulator, Indexed Indirect ($A1 arg : LDA (arg,X) ;arg=0..$FF), MEM=&(arg+X) - arg16 = GetAddrWithMode(ADDRMODE_IZX); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); - arg8 = mReg.Acc - arg8; - SetFlags(arg8); - break; - - case OPCODE_CMP_ZP: // CoMPare accumulator, Zero Page ($C5 arg : CMP arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); - arg8 = mReg.Acc - arg8; - SetFlags(arg8); - break; - - case OPCODE_CMP_IMM: // CoMPare accumulator, Immediate ($C9 arg : CMP #arg ;arg=0..$FF), MEM=PC+1 - arg8 = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); - SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); - arg8 = mReg.Acc - arg8; - SetFlags(arg8); - break; - - case OPCODE_CMP_ABS: // CoMPare accumulator, Absolute ($CD addrlo addrhi : CMP addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); - arg8 = mReg.Acc - arg8; - SetFlags(arg8); - break; - - case OPCODE_CMP_IZY: // CoMPare accumulator, Indirect Indexed ($D1 arg : CMP (arg),Y ;arg=0..$FF), MEM=&arg+Y - arg16 = GetAddrWithMode(ADDRMODE_IZY); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); - arg8 = mReg.Acc - arg8; - SetFlags(arg8); - break; - - case OPCODE_CMP_ZPX: // CoMPare accumulator, Zero Page Indexed, X ($D5 arg : CMP arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); - arg8 = mReg.Acc - arg8; - SetFlags(arg8); - break; - - case OPCODE_CMP_ABY: // CoMPare accumulator, Absolute Indexed, Y ($D9 addrlo addrhi : CMP addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); - arg8 = mReg.Acc - arg8; - SetFlags(arg8); - break; - - case OPCODE_CMP_ABX: // CoMPare accumulator, Absolute Indexed, X ($DD addrlo addrhi : CMP addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); - arg8 = mReg.Acc - arg8; - SetFlags(arg8); - break; - - case OPCODE_DEC_ZP: // DECrement memory, Zero Page ($C6 arg : DEC arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16) - 1; - mpMem->Poke8bit(arg16, arg8); - SetFlags(arg8); - break; - - case OPCODE_DEC_ABS: // DECrement memory, Absolute ($CE addrlo addrhi : CMP addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16) - 1; - mpMem->Poke8bit(arg16, arg8); - SetFlags(arg8); - break; - - case OPCODE_DEC_ZPX: // DECrement memory, Zero Page Indexed, X ($D6 arg : DEC arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - arg8 = mpMem->Peek8bit(arg16) - 1; - mpMem->Poke8bit(arg16, arg8); - SetFlags(arg8); - break; - - case OPCODE_DEC_ABX: // DECrement memory, Absolute Indexed, X ($DE addrlo addrhi : DEC addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - arg8 = mpMem->Peek8bit(arg16) - 1; - mpMem->Poke8bit(arg16, arg8); - SetFlags(arg8); - break; - - case OPCODE_CPX_IMM: // ComPare X register, Immediate ($E0 arg : CPX #arg ;arg=0..$FF), MEM=PC+1 - arg8 = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); - SetFlag((mReg.IndX >= arg8), FLAGS_CARRY); - arg8 = mReg.IndX - arg8; - SetFlags(arg8); - break; - - case OPCODE_CPX_ZP: // ComPare X register, Zero Page ($E4 arg : CPX arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.IndX >= arg8), FLAGS_CARRY); - arg8 = mReg.IndX - arg8; - SetFlags(arg8); - break; - - case OPCODE_CPX_ABS: // ComPare X register, Absolute ($EC addrlo addrhi : CPX addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.IndX >= arg8), FLAGS_CARRY); - arg8 = mReg.IndX - arg8; - SetFlags(arg8); - break; - - case OPCODE_SBC_ZP: // SuBtract with Carry, Zero Page ($E5 arg : SBC arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - SubWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_SBC_ABS: // SuBtract with Carry, Absolute ($ED addrlo addrhi : SBC addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - SubWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_SBC_IZX: // SuBtract with Carry, Indexed Indirect ($E1 arg : SBC (arg,X) ;arg=0..$FF), MEM=&(arg+X) - arg16 = GetAddrWithMode(ADDRMODE_IZX); - SubWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_SBC_IZY: // SuBtract with Carry, Indirect Indexed ($F1 arg : SBC (arg),Y ;arg=0..$FF), MEM=&arg+Y - arg16 = GetAddrWithMode(ADDRMODE_IZY); - SubWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_SBC_ZPX: // SuBtract with Carry, Zero Page Indexed, X ($F5 arg : SBC arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - SubWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_SBC_ABY: // SuBtract with Carry, Absolute Indexed, Y ($F9 addrlo addrhi : SBC addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - SubWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_SBC_ABX: // SuBtract with Carry, Absolute Indexed, X ($FD addrlo addrhi : SBC addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - SubWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_SBC_IMM: // SuBtract with Carry, Immediate ($E9 arg : SBC #arg ;arg=0..$FF), MEM=PC+1 - SubWithCarry(mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM))); - break; - - default: - break; - } - - return &mReg; -} - -/* - *-------------------------------------------------------------------- - * Method: GetRegs() - * Purpose: Return pointer to CPU registers and status. - * Arguments: n/a - * Returns: pointer to Regs structure. - *-------------------------------------------------------------------- - */ -Regs *MKCpu::GetRegs() -{ - return &mReg; -} - -} // namespace MKBasic + +#include +#include "MKCpu.h" +#include "MKGenException.h" + +namespace MKBasic { + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ + +/* + *-------------------------------------------------------------------- + * Method: MKCpu() + * Purpose: Default constructor. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +MKCpu::MKCpu() +{ + InitCpu(); +} + +/* + *-------------------------------------------------------------------- + * Method: MKCpu() + * Purpose: Custom constructor. + * Arguments: pmem - pointer to Memory object. + * Returns: n/a + *-------------------------------------------------------------------- + */ +MKCpu::MKCpu(Memory *pmem) +{ + mpMem = pmem; + InitCpu(); +} + +/* + *-------------------------------------------------------------------- + * Method: InitCpu() + * Purpose: Initialize internal variables and flags. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + ADDRMODE_IMM = 0, + ADDRMODE_ABS, + ADDRMODE_ZP, + ADDRMODE_IMP, + ADDRMODE_IND, + ADDRMODE_ABX, + ADDRMODE_ABY, + ADDRMODE_ZPX, + ADDRMODE_ZPY, + ADDRMODE_IZX, + ADDRMODE_IZY, + ADDRMODE_REL, + ADDRMODE_ACC, + */ +void MKCpu::InitCpu() +{ + string saArgFmtTbl[] = {"#$%02x", "$%04x", "$%02x", " ", "($%04x)", "$%04x,X", "$%04x,Y", + "$%02x,X", "$%02x,Y", "($%02x,X)", "($%02x),Y", "$%04x", " ", " "}; + int naAddrModesLen[] = {2, 3, 2, 1, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1}; + // Initialize instructions lengths table based on addressing modes + // Initialize assembly argument formats table based on addressing modes + for (int i=0; i $FFF0) + mpMem->Poke8bit(0xFFFE,0xF0); // LSB + mpMem->Poke8bit(0xFFFF,0xFF); // MSB + // Put RTI opcode at BRK procedure address. + mpMem->Poke8bit(0xFFF0, OPCODE_RTI); + // Set default RESET vector ($FFFC -> $0200) + mpMem->Poke8bit(0xFFFC,0x00); // LSB + mpMem->Poke8bit(0xFFFD,0x02); // MSB + // Set BRK code at the RESET procedure address. + mpMem->Poke8bit(0x0200,OPCODE_BRK); +} + +/* + *-------------------------------------------------------------------- + * Method: SetFlags() + * Purpose: Set CPU status flags ZERO and SIGN based on Acc, X or Y + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void MKCpu::SetFlags(unsigned char reg) +{ + SetFlag((0 == reg), FLAGS_ZERO); + SetFlag(((reg & FLAGS_SIGN) == FLAGS_SIGN), FLAGS_SIGN); + SetFlag(true, FLAGS_UNUSED); +} + +/* + *-------------------------------------------------------------------- + * Method: ShiftLeft() + * Purpose: Arithmetic shift left (1 bit), set Carry flag, shift 0 + * into bit #0. Update flags NZ. + * Arguments: arg8 - 8-bit value + * Returns: 8-bit value after shift + *-------------------------------------------------------------------- + */ +unsigned char MKCpu::ShiftLeft(unsigned char arg8) +{ + // set Carry flag based on original bit #7 + SetFlag(((arg8 & FLAGS_SIGN) == FLAGS_SIGN), FLAGS_CARRY); + arg8 = arg8 << 1; // shift left + arg8 &= 0xFE; // shift 0 into bit #0 + + SetFlags(arg8); + + return arg8; +} + +/* + *-------------------------------------------------------------------- + * Method: ShiftRight() + * Purpose: Logical Shift Right, update flags NZC. + * Arguments: arg8 - byte value + * Returns: unsigned char (byte) - after shift + *-------------------------------------------------------------------- + */ +unsigned char MKCpu::ShiftRight(unsigned char arg8) +{ + SetFlag(((arg8 & 0x01) == 0x01), FLAGS_CARRY); + arg8 = arg8 >> 1; + arg8 &= 0x7F; // unset bit #7 + SetFlags(arg8); + + return arg8; +} + +/* + *-------------------------------------------------------------------- + * Method: RotateLeft() + * Purpose: Rotate left, Carry to bit 0, bit 7 to Carry, update + flags N and Z. + * Arguments: arg8 - byte value to rotate + * Returns: unsigned char (byte) - rotated value + *-------------------------------------------------------------------- + */ +unsigned char MKCpu::RotateLeft(unsigned char arg8) +{ + unsigned char tmp8 = 0; + + tmp8 = arg8; + arg8 = arg8 << 1; + // Carry goes to bit #0. + if (mReg.Flags & FLAGS_CARRY) { + arg8 |= 0x01; + } else { + arg8 &= 0xFE; + } + // Original (before ROL) bit #7 goes to Carry. + SetFlag(((tmp8 & FLAGS_SIGN) == FLAGS_SIGN), FLAGS_CARRY); + SetFlags(arg8); // set flags Z and N + + return arg8; +} + +/* + *-------------------------------------------------------------------- + * Method: RotateRight() + * Purpose: Rotate Right, Carry to bit 7, bit 0 to Carry, update + flags N and Z. + * Arguments: arg8 - byte value to rotate + * Returns: unsigned char (byte) - rotated value + *-------------------------------------------------------------------- + */ +unsigned char MKCpu::RotateRight(unsigned char arg8) +{ + unsigned char tmp8 = 0; + + tmp8 = arg8; + arg8 = arg8 >> 1; + // Carry goes to bit #7. + if (CheckFlag(FLAGS_CARRY)) { + arg8 |= 0x80; + } else { + arg8 &= 0x7F; + } + // Original (before ROR) bit #0 goes to Carry. + SetFlag(((tmp8 & 0x01) == 0x01), FLAGS_CARRY); + SetFlags(arg8); // set flags Z and N + + return arg8; +} + +/* + *-------------------------------------------------------------------- + * Method: GetArg16() + * Purpose: Get 2-byte argument, add offset, increase PC. + * Arguments: addr - address of argument in memory + * offs - offset to be added to returned value + * Returns: 16-bit address + *-------------------------------------------------------------------- + */ +unsigned short MKCpu::GetArg16(unsigned char offs) +{ + unsigned short ret = 0; + + ret = mpMem->Peek16bit(mReg.PtrAddr++); + mReg.PtrAddr++; + ret += offs; + + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: LogicOpAcc() + * Purpose: Perform logical bitwise operation between memory + * location and Acc, result in Acc. Set flags. + * Arguments: addr - memory location + * logop - logical operation code: LOGOP_OR, LOGOP_AND, + * LOGOP_EOR + * Returns: n/a + *-------------------------------------------------------------------- + */ +void MKCpu::LogicOpAcc(unsigned short addr, int logop) +{ + unsigned char val = 0; + + val = mpMem->Peek8bit(addr); + switch (logop) { + case LOGOP_OR: + mReg.Acc |= val; + break; + case LOGOP_AND: + mReg.Acc &= val; + break; + case LOGOP_EOR: + mReg.Acc ^= val; + break; + default: + break; + } + SetFlags(mReg.Acc); +} + +/* + *-------------------------------------------------------------------- + * Method: ComputeRelJump() + * Purpose: Compute new PC based on relative offset. + * Arguments: offs - relative offset [-128 ($80)..127 ($7F)] + * Returns: unsigned short - new PC (Program Counter). + * NOTE: + * Program Counter (http://www.6502.org/tutorials/6502opcodes.html#PC) + * When the 6502 is ready for the next instruction it increments the + * program counter before fetching the instruction. Once it has the op + * code, it increments the program counter by the length of the + * operand, if any. This must be accounted for when calculating + * branches or when pushing bytes to create a false return address + * (i.e. jump table addresses are made up of addresses-1 when it is + * intended to use an RTS rather than a JMP). + * The program counter is loaded least signifigant byte first. + * Therefore the most signifigant byte must be pushed first when + * creating a false return address. + * When calculating branches a forward branch of 6 skips the following + * 6 bytes so, effectively the program counter points to the address + * that is 8 bytes beyond the address of the branch opcode; + * and a backward branch of $FA (256-6) goes to an address 4 bytes + * before the branch instruction. + *-------------------------------------------------------------------- + */ +unsigned short MKCpu::ComputeRelJump(unsigned char offs) +{ + // NOTE: mReg.PtrAddr (PC) must be at the next opcode (after branch instr.) at this point. + return ComputeRelJump(mReg.PtrAddr, offs); +} + +/* + *-------------------------------------------------------------------- + * Method: ComputeRelJump() + * Purpose: Compute new address after branch based on relative + * offset. + * Arguments: addr - next opcode address (after branch instr.) + * offs - relative offset [-128 ($80)..127 ($7F)] + * Returns: unsigned short - new address for branch jump + *-------------------------------------------------------------------- + */ +unsigned short MKCpu::ComputeRelJump(unsigned short addr, unsigned char offs) +{ + unsigned short newpc = addr; + + if (offs < 0x80) { + newpc += (unsigned short) offs; + } else { + newpc -= (unsigned short) ((unsigned char)(~offs + 1)); // use binary 2's complement instead of arithmetics + } + + return newpc; +} + +/* + *-------------------------------------------------------------------- + * Method: Conv2Bcd() + * Purpose: Convert 16-bit unsigned number to 8-bit BCD + * representation. + * Arguments: v - 16-bit unsigned integer. + * Returns: byte representing BCD code of the 'v'. + *-------------------------------------------------------------------- + */ +unsigned char MKCpu::Conv2Bcd(unsigned short v) +{ + unsigned char arg8 = 0; + arg8 = (unsigned char)((v/10) << 4); + arg8 |= ((unsigned char)(v - (v/10)*10)) & 0x0F; + return arg8; +} + +/* + *-------------------------------------------------------------------- + * Method: Bcd2Num() + * Purpose: Convert 8-bit BCD code to a number. + * Arguments: v - BCD code. + * Returns: 16-bit unsigned integer + *-------------------------------------------------------------------- + */ +unsigned short MKCpu::Bcd2Num(unsigned char v) +{ + unsigned short ret = 0; + ret = 10 * ((v & 0xF0) >> 4) + (unsigned char)(v & 0x0F); + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: CheckFlag() + * Purpose: Check if given bit flag in CPU status register is set + * or not. + * Arguments: flag - byte with the bit to be checked set and other + * bits not set. + * Returns: bool + *-------------------------------------------------------------------- + */ +bool MKCpu::CheckFlag(unsigned char flag) +{ + return ((mReg.Flags & flag) == flag); +} + +/* + *-------------------------------------------------------------------- + * Method: SetFlag() + * Purpose: Set or unset CPU status flag. + * Arguments: set - if true, set flag, if false, unset flag. + * flag - a byte with a bit set on the position of flag + * being altered and zeroes on other positions. + * Returns: n/a + *-------------------------------------------------------------------- + */ +void MKCpu::SetFlag(bool set, unsigned char flag) +{ + if (set) { + mReg.Flags |= flag; + } else { + mReg.Flags &= ~flag; + } +} + +/* + *-------------------------------------------------------------------- + * Method: AddWithCarry() + * Purpose: Add Acc + Mem with Carry, update flags and Acc. + * Arguments: mem8 - memory argument (byte) + * Returns: byte value Acc + Mem + Carry + *-------------------------------------------------------------------- + */ +unsigned char MKCpu::AddWithCarry(unsigned char mem8) +{ + // This algorithm was adapted from Frodo emulator code. + unsigned short utmp16 = mReg.Acc + mem8 + (CheckFlag(FLAGS_CARRY) ? 1 : 0); + if (CheckFlag(FLAGS_DEC)) { // BCD mode + + unsigned short al = (mReg.Acc & 0x0F) + (mem8 & 0x0F) + (CheckFlag(FLAGS_CARRY) ? 1 : 0); + if (al > 9) al += 6; + unsigned short ah = (mReg.Acc >> 4) + (mem8 >> 4); + if (al > 0x0F) ah++; + SetFlag((utmp16 == 0), FLAGS_ZERO); + SetFlag(((((ah << 4) ^ mReg.Acc) & 0x80) && !((mReg.Acc ^ mem8) & 0x80)), FLAGS_OVERFLOW); + if (ah > 9) ah += 6; + SetFlag((ah > 0x0F), FLAGS_CARRY); + mReg.Acc = (ah << 4) | (al & 0x0f); + SetFlag((mReg.Acc & FLAGS_SIGN) == FLAGS_SIGN, FLAGS_SIGN); + } else { // binary mode + + SetFlag((utmp16 > 0xff), FLAGS_CARRY); + SetFlag((!((mReg.Acc ^ mem8) & 0x80) && ((mReg.Acc ^ utmp16) & 0x80)), FLAGS_OVERFLOW); + mReg.Acc = utmp16 & 0xFF; + SetFlag((mReg.Acc == 0), FLAGS_ZERO); + SetFlag((mReg.Acc & FLAGS_SIGN) == FLAGS_SIGN, FLAGS_SIGN); + } + SetFlag(true, FLAGS_UNUSED); + return mReg.Acc; +} + +/* + *-------------------------------------------------------------------- + * Method: SubWithCarry() + * Purpose: Subtract Acc - Mem with Carry, update flags and Acc. + * Arguments: mem8 - memory argument (byte) + * Returns: byte value Acc - Mem - Carry + *-------------------------------------------------------------------- + */ +unsigned char MKCpu::SubWithCarry(unsigned char mem8) +{ + unsigned short utmp16 = mReg.Acc - mem8 - (CheckFlag(FLAGS_CARRY) ? 0 : 1); + + // This algorithm was adapted from Frodo emulator code. + if (CheckFlag(FLAGS_DEC)) { // BCD mode + + unsigned char al = (mReg.Acc & 0x0F) - (mem8 & 0x0F) - (CheckFlag(FLAGS_CARRY) ? 0 : 1); + unsigned char ah = (mReg.Acc >> 4) - (mem8 >> 4); + if (al & 0x10) { + al -= 6; ah--; + } + if (ah & 0x10) ah -= 6; + SetFlag((utmp16 < 0x100), FLAGS_CARRY); + SetFlag(((mReg.Acc ^ utmp16) & 0x80) && ((mReg.Acc ^ mem8) & 0x80), FLAGS_OVERFLOW); + SetFlag((utmp16 == 0), FLAGS_ZERO); + mReg.Acc = (ah << 4) | (al & 0x0f); + SetFlag((mReg.Acc & FLAGS_SIGN) == FLAGS_SIGN, FLAGS_SIGN); + + } else { // binary mode + + SetFlag((utmp16 < 0x100), FLAGS_CARRY); + SetFlag(((mReg.Acc ^ utmp16) & 0x80) && ((mReg.Acc ^ mem8) & 0x80), FLAGS_OVERFLOW); + mReg.Acc = utmp16 & 0xFF; + SetFlag((mReg.Acc == 0), FLAGS_ZERO); + SetFlag((mReg.Acc & FLAGS_SIGN) == FLAGS_SIGN, FLAGS_SIGN); + + } + SetFlag(true, FLAGS_UNUSED); + return mReg.Acc; +} + +/* + *-------------------------------------------------------------------- + * Method: ~MKCpu() + * Purpose: Class destructor. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +MKCpu::~MKCpu() +{ + if (mLocalMem) { + if (NULL != mpMem) + delete mpMem; + } +} + +/* + *-------------------------------------------------------------------- + * Method: GetAddrWithMode() + * Purpose: Get address of the argument with specified mode. + * Increment PC. + * Arguments: mode - code of the addressing mode, see eAddrModes. + * Returns: 16-bit address + *-------------------------------------------------------------------- + */ +unsigned short MKCpu::GetAddrWithMode(int mode) +{ + unsigned short arg16 = 0; + + mReg.LastAddrMode = mode; + switch (mode) { + + case ADDRMODE_IMM: + arg16 = mReg.PtrAddr++; + break; + + case ADDRMODE_ABS: + mReg.LastArg = arg16 = GetArg16(0); + break; + + case ADDRMODE_ZP: + mReg.LastArg = arg16 = (unsigned short) mpMem->Peek8bit(mReg.PtrAddr++); + break; + + case ADDRMODE_IMP: + // DO NOTHING - implied mode operates on internal CPU register + break; + + case ADDRMODE_IND: + mReg.LastArg = arg16 = mpMem->Peek16bit(mReg.PtrAddr++); + arg16 = mpMem->Peek16bit(arg16); + break; + + case ADDRMODE_ABX: + arg16 = GetArg16(mReg.IndX); + mReg.LastArg = arg16 - mReg.IndX; + break; + + case ADDRMODE_ABY: + arg16 = GetArg16(mReg.IndY); + mReg.LastArg = arg16 - mReg.IndY; + break; + + case ADDRMODE_ZPX: + mReg.LastArg = arg16 = mpMem->Peek8bit(mReg.PtrAddr++); + arg16 = (arg16 + mReg.IndX) & 0xFF; + break; + + case ADDRMODE_ZPY: + mReg.LastArg = arg16 = mpMem->Peek8bit(mReg.PtrAddr++); + arg16 = (arg16 + mReg.IndY) & 0xFF; + break; + + case ADDRMODE_IZX: + mReg.LastArg = arg16 = mpMem->Peek8bit(mReg.PtrAddr++); + arg16 = (arg16 + mReg.IndX) & 0xFF; + arg16 = mpMem->Peek16bit(arg16); + break; + + case ADDRMODE_IZY: + mReg.LastArg = arg16 = mpMem->Peek8bit(mReg.PtrAddr++); + arg16 = mpMem->Peek16bit(arg16) + mReg.IndY; + break; + + case ADDRMODE_REL: + mReg.LastArg = arg16 = ComputeRelJump(mpMem->Peek8bit(mReg.PtrAddr++)); + break; + + case ADDRMODE_ACC: + // DO NOTHING - acc mode operates on internal CPU register + break; + + default: + throw MKGenException("ERROR: Wrong addressing mode!"); + break; + } + + return arg16; +} + +/* + *-------------------------------------------------------------------- + * Method: GetArgWithMode() + * Purpose: Get argument from address with specified mode. + * Arguments: addr - address in memory + * mode - code of the addressing mode, see eAddrModes. + * Returns: argument + *-------------------------------------------------------------------- + */ +unsigned short MKCpu::GetArgWithMode(unsigned short addr, int mode) +{ + unsigned short arg16 = 0; + + switch (mode) { + + case ADDRMODE_IMM: + arg16 = mpMem->Peek8bit(addr); + break; + + case ADDRMODE_ABS: + arg16 = mpMem->Peek16bit(addr); + break; + + case ADDRMODE_ZP: + arg16 = (unsigned short) mpMem->Peek8bit(addr); + break; + + case ADDRMODE_IMP: + // DO NOTHING - implied mode operates on internal CPU register + break; + + case ADDRMODE_IND: + arg16 = mpMem->Peek16bit(addr); + break; + + case ADDRMODE_ABX: + arg16 = mpMem->Peek16bit(addr); + break; + + case ADDRMODE_ABY: + arg16 = mpMem->Peek16bit(addr); + break; + + case ADDRMODE_ZPX: + arg16 = mpMem->Peek8bit(addr); + break; + + case ADDRMODE_ZPY: + arg16 = mpMem->Peek8bit(addr); + break; + + case ADDRMODE_IZX: + arg16 = mpMem->Peek8bit(addr); + break; + + case ADDRMODE_IZY: + arg16 = mpMem->Peek8bit(addr); + break; + + case ADDRMODE_REL: + arg16 = ComputeRelJump(addr+1, mpMem->Peek8bit(addr)); + break; + + case ADDRMODE_ACC: + // DO NOTHING - acc mode operates on internal CPU register + break; + + default: + break; + } + + return arg16; +} + +/* + *-------------------------------------------------------------------- + * Method: Disassemble() + * Purpose: Disassemble instruction and argument per addressing mode + * Arguments: n/a - internal + * Returns: 0 + *-------------------------------------------------------------------- + */ +unsigned short MKCpu::Disassemble() +{ + char sArg[40]; + char sFmt[20]; + + strcpy(sFmt, "%s "); + strcat(sFmt, mArgFmtTbl[mReg.LastAddrMode].c_str()); + sprintf(sArg, sFmt, + ((mOpCodesMap[(eOpCodes)mReg.LastOpCode]).amf.length() > 0 + ? (mOpCodesMap[(eOpCodes)mReg.LastOpCode]).amf.c_str() : "???"), + mReg.LastArg); + for (unsigned int i=0; iPeek8bit(addr++); + addrmode = (mOpCodesMap[(eOpCodes)opcode]).amf.length() > 0 + ? (mOpCodesMap[(eOpCodes)opcode]).addrmode : -1; + + if (addrmode < 0 || NULL == instrbuf) return 0; + switch (mAddrModesLen[addrmode]) + { + case 2: + sprintf(sBuf, "$%02x ", mpMem->Peek8bit(addr)); + break; + + case 3: + sprintf(sBuf, "$%02x $%02x", mpMem->Peek8bit(addr), mpMem->Peek8bit(addr+1)); + break; + + default: + strcpy(sBuf, " "); + break; + } + strcpy(sFmt, "$%04x: $%02x %s %s "); + strcat(sFmt, mArgFmtTbl[addrmode].c_str()); + sprintf(sArg, sFmt, opcaddr, mpMem->Peek8bit(opcaddr), sBuf, + ((mOpCodesMap[(eOpCodes)opcode]).amf.length() > 0 + ? (mOpCodesMap[(eOpCodes)opcode]).amf.c_str() : "???"), + GetArgWithMode(addr,addrmode)); + for (unsigned int i=0; iPeek8bit(mReg.PtrAddr++); + unsigned char arg8 = 0; + unsigned short arg16 = 0; + + SetFlag(false, FLAGS_BRK); // reset BRK flag - we want to detect + mReg.SoftIrq = false; // software interrupt each time it happens + // (non-maskable) + mReg.LastRTS = false; + mReg.LastOpCode = opcode; + mReg.LastAddrMode = ADDRMODE_UND; + mReg.LastArg = 0; + + switch (opcode) { + + case OPCODE_BRK: // software interrupt, Implied ($00 : BRK) + mReg.LastAddrMode = ADDRMODE_IMP; + if (!CheckFlag(FLAGS_IRQ)) { // only if IRQ not masked + arg16 = 0x100; + arg16 += mReg.PtrStack--; + // Note that BRK is really a 2-bytes opcode. Each BRK opcode should be padded by extra byte, + // because the return address put on stack is PC + 1 (where PC is the next address after BRK). + // That means the next opcode after BRK will not be executed upon return from interrupt, + // but the next after that will be. + mReg.PtrAddr++; + mpMem->Poke8bit(arg16, (unsigned char) (((mReg.PtrAddr) & 0xFF00) >> 8)); // HI(PC+1) - HI part of next instr. addr. + 1 + arg16 = 0x100; + arg16 += mReg.PtrStack--; + mpMem->Poke8bit(arg16, (unsigned char) ((mReg.PtrAddr) & 0x00FF)); // LO(PC+1) - LO part of next instr. addr. + 1 + arg16 = 0x100; + arg16 += mReg.PtrStack--; + SetFlag(true, FLAGS_BRK); // The BRK flag that goes on stack is set. + mpMem->Poke8bit(arg16, mReg.Flags); + SetFlag(false, FLAGS_BRK); // The BRK flag that remains in CPU status is unchanged, so unset after putting on stack. + //mReg.SoftIrq = true; + mReg.PtrAddr = mpMem->Peek16bit(0xFFFE); // Load BRK vector into the PC. + SetFlag(true,FLAGS_IRQ); + } else { + mReg.PtrAddr++; + } + break; + + case OPCODE_NOP: // NO oPeration, Implied ($EA : NOP) + mReg.LastAddrMode = ADDRMODE_IMP; + break; + + case OPCODE_LDA_IZX: // LoaD Accumulator, Indexed Indirect ($A1 arg : LDA (arg,X) ;arg=0..$FF), MEM=&(arg+X) + arg16 = GetAddrWithMode(ADDRMODE_IZX); + mReg.Acc = mpMem->Peek8bit(arg16); + SetFlags(mReg.Acc); + break; + + case OPCODE_LDA_ZP: // LoaD Accumulator, Zero Page ($A5 arg : LDA arg ;arg=0..$FF), MEM=arg + mReg.Acc = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_ZP)); + SetFlags(mReg.Acc); + break; + + case OPCODE_LDA_IMM: // LoaD Accumulator, Immediate ($A9 arg : LDA #arg ;arg=0..$FF), MEM=PC+1 + mReg.LastArg = mReg.Acc = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); + SetFlags(mReg.Acc); + break; + + case OPCODE_LDA_ABS: // LoaD Accumulator, Absolute ($AD addrlo addrhi : LDA addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + mReg.Acc = mpMem->Peek8bit(arg16); + SetFlags(mReg.Acc); + break; + + case OPCODE_LDA_IZY: // LoaD Accumulator, Indirect Indexed ($B1 arg : LDA (arg),Y ;arg=0..$FF), MEM=&arg+Y + arg16 = GetAddrWithMode(ADDRMODE_IZY); + mReg.Acc = mpMem->Peek8bit(arg16); + SetFlags(mReg.Acc); + break; + + case OPCODE_LDA_ZPX: // LoaD Accumulator, Zero Page Indexed, X ($B5 arg : LDA arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + mReg.Acc = mpMem->Peek8bit(arg16); + SetFlags(mReg.Acc); + break; + + case OPCODE_LDA_ABY: // LoaD Accumulator, Absolute Indexed, Y ($B9 addrlo addrhi : LDA addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + mReg.Acc = mpMem->Peek8bit(arg16); + SetFlags(mReg.Acc); + break; + + case OPCODE_LDA_ABX: // LoaD Accumulator, Absolute Indexed, X ($BD addrlo addrhi : LDA addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + mReg.Acc = mpMem->Peek8bit(arg16); + SetFlags(mReg.Acc); + break; + + case OPCODE_LDX_IMM: // LoaD X register, Immediate ($A2 arg : LDX #arg ;arg=0..$FF), MEM=PC+1 + mReg.LastArg = mReg.IndX = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); + SetFlags(mReg.IndX); + break; + + case OPCODE_LDX_ZP: // LoaD X register, Zero Page ($A6 arg : LDX arg ;arg=0..$FF), MEM=arg + mReg.IndX = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_ZP)); + SetFlags(mReg.IndX); + break; + + case OPCODE_LDX_ABS: // LoaD X register, Absolute ($AE addrlo addrhi : LDX addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + mReg.IndX = mpMem->Peek8bit(arg16); + SetFlags(mReg.IndX); + break; + + case OPCODE_LDX_ZPY: // LoaD X register, Zero Page Indexed, Y ($B6 arg : LDX arg,Y ;arg=0..$FF), MEM=arg+Y + arg16 = GetAddrWithMode(ADDRMODE_ZPY); + mReg.IndX = mpMem->Peek8bit(arg16); + SetFlags(mReg.IndX); + break; + + case OPCODE_LDX_ABY: // LoaD X register, Absolute Indexed, Y ($BE addrlo addrhi : LDX addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + mReg.IndX = mpMem->Peek8bit(arg16); + SetFlags(mReg.IndX); + break; + + case OPCODE_LDY_IMM: // LoaD Y register, Immediate ($A0 arg : LDY #arg ;arg=0..$FF), MEM=PC+1 + mReg.LastArg = mReg.IndY = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); + SetFlags(mReg.IndY); + break; + + case OPCODE_LDY_ZP: // LoaD Y register, Zero Page ($A4 arg : LDY arg ;arg=0..$FF), MEM=arg + mReg.IndY = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_ZP)); + SetFlags(mReg.IndY); + break; + + case OPCODE_LDY_ABS: // LoaD Y register, Absolute ($AC addrlo addrhi : LDY addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + mReg.IndY = mpMem->Peek8bit(arg16); + SetFlags(mReg.IndY); + break; + + case OPCODE_LDY_ZPX: // LoaD Y register, Zero Page Indexed, X ($B4 arg : LDY arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + mReg.IndY = mpMem->Peek8bit(arg16); + SetFlags(mReg.IndY); + break; + + case OPCODE_LDY_ABX: // LoaD Y register, Absolute Indexed, X ($BC addrlo addrhi : LDY addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + mReg.IndY = mpMem->Peek8bit(arg16); + SetFlags(mReg.IndY); + break; + + case OPCODE_TAX: // Transfer A to X, Implied ($AA : TAX) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.IndX = mReg.Acc; + SetFlags(mReg.IndX); + break; + + case OPCODE_TAY: // Transfer A to Y, Implied ($A8 : TAY) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.IndY = mReg.Acc; + SetFlags(mReg.IndY); + break; + + case OPCODE_TXA: // Transfer X to A, Implied ($8A : TXA) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.Acc = mReg.IndX; + SetFlags(mReg.Acc); + break; + + case OPCODE_TYA: // Transfer Y to A, Implied ($98 : TYA) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.Acc = mReg.IndY; + SetFlags(mReg.Acc); + break; + + case OPCODE_TSX: // Transfer Stack ptr to X, Implied ($BA : TSX) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.IndX = mReg.PtrStack; + SetFlags(mReg.IndX); + break; + + case OPCODE_TXS: // Transfer X to Stack ptr, Implied ($9A : TXS) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.PtrStack = mReg.IndX; + break; + + case OPCODE_STA_IZX: // STore Accumulator, Indexed Indirect ($81 arg : STA (arg,X) ;arg=0..$FF), MEM=&(arg+X) + arg16 = GetAddrWithMode(ADDRMODE_IZX); + mpMem->Poke8bit(arg16, mReg.Acc); + break; + + case OPCODE_STA_ZP: // STore Accumulator, Zero Page ($85 arg : STA arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + mpMem->Poke8bit(arg16, mReg.Acc); + break; + + case OPCODE_STA_ABS: // STore Accumulator, Absolute ($8D addrlo addrhi : STA addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + mpMem->Poke8bit(arg16, mReg.Acc); + break; + + case OPCODE_STA_IZY: // STore Accumulator, Indirect Indexed ($91 arg : STA (arg),Y ;arg=0..$FF), MEM=&arg+Y + arg16 = GetAddrWithMode(ADDRMODE_IZY); + mpMem->Poke8bit(arg16, mReg.Acc); + break; + + case OPCODE_STA_ZPX: // STore Accumulator, Zero Page Indexed, X ($95 arg : STA arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + mpMem->Poke8bit(arg16, mReg.Acc); + break; + + case OPCODE_STA_ABY: // STore Accumulator, Absolute Indexed, Y ($99 addrlo addrhi : STA addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + mpMem->Poke8bit(arg16, mReg.Acc); + break; + + case OPCODE_STA_ABX: // STore Accumulator, Absolute Indexed, X ($9D addrlo addrhi : STA addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + mpMem->Poke8bit(arg16, mReg.Acc); + break; + + case OPCODE_STX_ZP: // STore X register, Zero Page ($86 arg : STX arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + mpMem->Poke8bit(arg16, mReg.IndX); + break; + + case OPCODE_STX_ABS: // STore X register, Absolute ($8E addrlo addrhi : STX addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + mpMem->Poke8bit(arg16, mReg.IndX); + break; + + case OPCODE_STX_ZPY: // STore X register, Zero Page Indexed, Y ($96 arg : STX arg,Y ;arg=0..$FF), MEM=arg+Y + arg16 = GetAddrWithMode(ADDRMODE_ZPY); + mpMem->Poke8bit(arg16, mReg.IndX); + break; + + case OPCODE_STY_ZP: // STore Y register, Zero Page ($84 arg : STY arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + mpMem->Poke8bit(arg16, mReg.IndY); + break; + + case OPCODE_STY_ABS: // STore Y register, Absolute ($8C addrlo addrhi : STY addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + mpMem->Poke8bit(arg16, mReg.IndY); + break; + + case OPCODE_STY_ZPX: // STore Y register, Zero Page Indexed, X ($94 arg : STY arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + mpMem->Poke8bit(arg16, mReg.IndY); + break; + + case OPCODE_BNE_REL: // Branch on Not Equal, Relative ($D0 signoffs : BNE signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + arg16 = GetAddrWithMode(ADDRMODE_REL); + if (!CheckFlag(FLAGS_ZERO)) { + mReg.PtrAddr = arg16; + } + break; + + case OPCODE_BEQ_REL: // Branch on EQual, Relative ($F0 signoffs : BEQ signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + arg16 = GetAddrWithMode(ADDRMODE_REL); + if (CheckFlag(FLAGS_ZERO)) { + mReg.PtrAddr = arg16; + } + break; + + case OPCODE_BPL_REL: // Branch on PLus, Relative ($10 signoffs : BPL signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + arg16 = GetAddrWithMode(ADDRMODE_REL); + if (!CheckFlag(FLAGS_SIGN)) { + mReg.PtrAddr = arg16; + } + break; + + case OPCODE_BMI_REL: // Branch on MInus, Relative ($30 signoffs : BMI signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + arg16 = GetAddrWithMode(ADDRMODE_REL); + if (CheckFlag(FLAGS_SIGN)) { + mReg.PtrAddr = arg16; + } + break; + + case OPCODE_BVC_REL: // Branch on oVerflow Clear, Relative ($50 signoffs : BVC signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + arg16 = GetAddrWithMode(ADDRMODE_REL); + if (!CheckFlag(FLAGS_OVERFLOW)) { + mReg.PtrAddr = arg16; + } + break; + + case OPCODE_BVS_REL: // Branch on oVerflow Set, Relative ($70 signoffs : BVS signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + arg16 = GetAddrWithMode(ADDRMODE_REL); + if (CheckFlag(FLAGS_OVERFLOW)) { + mReg.PtrAddr = arg16; + } + break; + + case OPCODE_BCC_REL: // Branch on Carry Clear, Relative ($90 signoffs : BCC signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + arg16 = GetAddrWithMode(ADDRMODE_REL); + if (!CheckFlag(FLAGS_CARRY)) { + mReg.PtrAddr = arg16; + } + break; + + case OPCODE_BCS_REL: // Branch on Carry Set, Relative ($B0 signoffs : BCS signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + arg16 = GetAddrWithMode(ADDRMODE_REL); + if (CheckFlag(FLAGS_CARRY)) { + mReg.PtrAddr = arg16; + } + break; + + /*** + case OPCODE_BRA: // branch always to a relative 1-byte address offset -128 ($80)..127 ($7F) (OPCODE_BEQ reladdr : BEQ reladdr) + arg8 = mpMem->Peek8bit(mReg.PtrAddr++); + mReg.PtrAddr = ComputeRelJump(arg8); + break; + ***/ + + case OPCODE_INC_ZP: // INCrement memory, Zero Page ($E6 arg : INC arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16) + 1; + mpMem->Poke8bit(arg16, arg8); + SetFlags(arg8); + break; + + case OPCODE_INC_ABS: // INCrement memory, Absolute ($EE addrlo addrhi : INC addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16) + 1; + mpMem->Poke8bit(arg16, arg8); + SetFlags(arg8); + break; + + case OPCODE_INC_ZPX: // INCrement memory, Zero Page Indexed, X ($F6 arg : INC arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + arg8 = mpMem->Peek8bit(arg16) + 1; + mpMem->Poke8bit(arg16, arg8); + SetFlags(arg8); + break; + + case OPCODE_INC_ABX: // INCrement memory, Absolute Indexed, X ($FE addrlo addrhi : INC addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + arg8 = mpMem->Peek8bit(arg16) + 1; + mpMem->Poke8bit(arg16, arg8); + SetFlags(arg8); + break; + + case OPCODE_INX: // INcrement X, Implied ($E8 : INX) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.IndX++; + SetFlags(mReg.IndX); + break; + + case OPCODE_DEX: // DEcrement X, Implied ($CA : DEX) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.IndX--; + SetFlags(mReg.IndX); + break; + + case OPCODE_INY: // INcrement Y, Implied ($C8 : INY) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.IndY++; + SetFlags(mReg.IndY); + break; + + case OPCODE_DEY: // DEcrement Y, Implied ($88 : DEY) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.IndY--; + SetFlags(mReg.IndY); + break; + + case OPCODE_JMP_ABS: // JuMP, Absolute ($4C addrlo addrhi : JMP addr ;addr=0..$FFFF), MEM=addr + mReg.PtrAddr = GetAddrWithMode(ADDRMODE_ABS); + break; + + case OPCODE_JMP_IND: // JuMP, Indirect Absolute ($6C addrlo addrhi : JMP (addr) ;addr=0..FFFF), MEM=&addr + mReg.PtrAddr = GetAddrWithMode(ADDRMODE_IND); + break; + + case OPCODE_ORA_IZX: // bitwise OR with Accumulator, Indexed Indirect ($01 arg : ORA (arg,X) ;arg=0..$FF), MEM=&(arg+X) + arg16 = GetAddrWithMode(ADDRMODE_IZX); + LogicOpAcc(arg16, LOGOP_OR); + break; + + case OPCODE_ORA_ZP: // bitwise OR with Accumulator, Zero Page ($05 arg : ORA arg ;arg=0..$FF), MEM=arg + LogicOpAcc(GetAddrWithMode(ADDRMODE_ZP), LOGOP_OR); + break; + + case OPCODE_ORA_IMM: // bitwise OR with Accumulator, Immediate ($09 arg : ORA #arg ;arg=0..$FF), MEM=PC+1 + arg16 = GetAddrWithMode(ADDRMODE_IMM); + mReg.LastArg = mpMem->Peek8bit(arg16); + LogicOpAcc(arg16, LOGOP_OR); + break; + + case OPCODE_ORA_ABS: // bitwise OR with Accumulator, Absolute ($0D addrlo addrhi : ORA addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + LogicOpAcc(arg16, LOGOP_OR); + break; + + case OPCODE_ORA_IZY: // bitwise OR with Accumulator, Indirect Indexed ($11 arg : ORA (arg),Y ;arg=0..$FF), MEM=&arg+Y + arg16 = GetAddrWithMode(ADDRMODE_IZY); + LogicOpAcc(arg16, LOGOP_OR); + break; + + case OPCODE_ORA_ZPX: // bitwise OR with Accumulator, Zero Page Indexed, X ($15 arg : ORA arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + LogicOpAcc(arg16, LOGOP_OR); + break; + + case OPCODE_ORA_ABY: // bitwise OR with Accumulator, Absolute Indexed, Y ($19 addrlo addrhi : ORA addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + LogicOpAcc(arg16, LOGOP_OR); + break; + + case OPCODE_ORA_ABX: // bitwise OR with Accumulator, Absolute Indexed, X ($1D addrlo addrhi : ORA addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + LogicOpAcc(arg16, LOGOP_OR); + break; + + case OPCODE_ASL_ZP: // Arithmetic Shift Left, Zero Page ($06 arg : ASL arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16); + arg8 = ShiftLeft(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_ASL: // Arithmetic Shift Left, Accumulator ($0A : ASL) + mReg.LastAddrMode = ADDRMODE_ACC; + mReg.Acc = ShiftLeft(mReg.Acc); + break; + + case OPCODE_ASL_ABS: // Arithmetic Shift Left, Absolute ($0E addrlo addrhi : ASL addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16); + arg8 = ShiftLeft(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_ASL_ZPX: // Arithmetic Shift Left, Zero Page Indexed, X ($16 arg : ASL arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + arg8 = mpMem->Peek8bit(arg16); + arg8 = ShiftLeft(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_ASL_ABX: // Arithmetic Shift Left, Absolute Indexed, X ($1E addrlo addrhi : ASL addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + arg8 = mpMem->Peek8bit(arg16); + arg8 = ShiftLeft(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_JSR_ABS: // Jump to SubRoutine, Absolute ($20 addrlo addrhi : JSR addr ;addr=0..$FFFF), MEM=addr + // PC - next instruction address + // Push PC-1 on stack (HI, then LO). + // Currently PC (mReg.PtrAddr) is at the 1-st argument of JSR. + // Therefore the actual PC-1 used in calculations equals: mReg.PtrAddr+1 + arg16 = 0x100; + arg16 += mReg.PtrStack--; + mpMem->Poke8bit(arg16, (unsigned char) (((mReg.PtrAddr+1) & 0xFF00) >> 8)); // HI(PC-1) - HI part of next instr. addr. - 1 + arg16 = 0x100; + arg16 += mReg.PtrStack--; + mpMem->Poke8bit(arg16, (unsigned char) ((mReg.PtrAddr+1) & 0x00FF)); // LO(PC-1) - LO part of next instr. addr. - 1 + mReg.PtrAddr = GetAddrWithMode(ADDRMODE_ABS); + break; + + case OPCODE_AND_IZX: // bitwise AND with accumulator, Indexed Indirect ($21 arg : AND (arg,X) ;arg=0..$FF), MEM=&(arg+X) + arg16 = GetAddrWithMode(ADDRMODE_IZX); + LogicOpAcc(arg16, LOGOP_AND); + break; + + case OPCODE_AND_ZP: // bitwise AND with accumulator, Zero Page ($25 arg : AND arg ;arg=0..$FF), MEM=arg + LogicOpAcc(GetAddrWithMode(ADDRMODE_ZP), LOGOP_AND); + break; + + case OPCODE_AND_IMM: // bitwise AND with accumulator, Immediate ($29 arg : AND #arg ;arg=0..$FF), MEM=PC+1 + arg16 = GetAddrWithMode(ADDRMODE_IMM); + mReg.LastArg = mpMem->Peek8bit(arg16); + LogicOpAcc(arg16, LOGOP_AND); + break; + + case OPCODE_AND_ABS: // bitwise AND with accumulator, Absolute ($2D addrlo addrhi : AND addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + LogicOpAcc(arg16, LOGOP_AND); + break; + + case OPCODE_AND_IZY: // bitwise AND with accumulator, Indirect Indexed ($31 arg : AND (arg),Y ;arg=0..$FF), MEM=&arg+Y + arg16 = GetAddrWithMode(ADDRMODE_IZY); + LogicOpAcc(arg16, LOGOP_AND); + break; + + case OPCODE_AND_ZPX: // bitwise AND with accumulator, Zero Page Indexed, X ($35 arg : AND arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + LogicOpAcc(arg16, LOGOP_AND); + break; + + case OPCODE_AND_ABY: // bitwise AND with accumulator, Absolute Indexed, Y ($39 addrlo addrhi : AND addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + LogicOpAcc(arg16, LOGOP_AND); + break; + + case OPCODE_AND_ABX: // bitwise AND with accumulator, Absolute Indexed, X ($3D addrlo addrhi : AND addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + LogicOpAcc(arg16, LOGOP_AND); + break; + + case OPCODE_BIT_ZP: // test BITs, Zero Page ($24 arg : BIT arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((arg8 & FLAGS_OVERFLOW) == FLAGS_OVERFLOW, FLAGS_OVERFLOW); + SetFlag((arg8 & FLAGS_SIGN) == FLAGS_SIGN, FLAGS_SIGN); + arg8 &= mReg.Acc; + SetFlag((arg8 == 0), FLAGS_ZERO); + break; + + case OPCODE_BIT_ABS: // test BITs, Absolute ($2C addrlo addrhi : BIT addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((arg8 & FLAGS_OVERFLOW) == FLAGS_OVERFLOW, FLAGS_OVERFLOW); + SetFlag((arg8 & FLAGS_SIGN) == FLAGS_SIGN, FLAGS_SIGN); + arg8 &= mReg.Acc; + SetFlag((arg8 == 0), FLAGS_ZERO); + break; + + case OPCODE_ROL_ZP: // ROtate Left, Zero Page ($26 arg : ROL arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16); + arg8 = RotateLeft(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_ROL: // ROtate Left, Accumulator ($2A : ROL) + mReg.LastAddrMode = ADDRMODE_ACC; + mReg.Acc = RotateLeft(mReg.Acc); + break; + + case OPCODE_ROL_ABS: // ROtate Left, Absolute ($2E addrlo addrhi : ROL addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16); + arg8 = RotateLeft(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_ROL_ZPX: // ROtate Left, Zero Page Indexed, X ($36 arg : ROL arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + arg8 = mpMem->Peek8bit(arg16); + arg8 = RotateLeft(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_ROL_ABX: // ROtate Left, Absolute Indexed, X ($3E addrlo addrhi : ROL addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + arg8 = mpMem->Peek8bit(arg16); + arg8 = RotateLeft(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_PHP: // PusH Processor status on Stack, Implied ($08 : PHP) + mReg.LastAddrMode = ADDRMODE_IMP; + arg16 = 0x100; + arg16 += mReg.PtrStack--; + arg8 = mReg.Flags | FLAGS_BRK | FLAGS_UNUSED; + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_PHA: // PusH Accumulator, Implied ($48 : PHA) + mReg.LastAddrMode = ADDRMODE_IMP; + arg16 = 0x100; + arg16 += mReg.PtrStack--; + mpMem->Poke8bit(arg16, mReg.Acc); + break; + + case OPCODE_PLP: // PuLl Processor status, Implied ($28 : PLP) + mReg.LastAddrMode = ADDRMODE_IMP; + arg16 = 0x100; + arg16 += ++mReg.PtrStack; + mReg.Flags = mpMem->Peek8bit(arg16) | FLAGS_UNUSED; + break; + + case OPCODE_PLA: // PuLl Accumulator, Implied ($68 : PLA) + mReg.LastAddrMode = ADDRMODE_IMP; + arg16 = 0x100; + arg16 += ++mReg.PtrStack; + mReg.Acc = mpMem->Peek8bit(arg16); + SetFlags(mReg.Acc); + break; + + case OPCODE_CLC: // CLear Carry, Implied ($18 : CLC) + mReg.LastAddrMode = ADDRMODE_IMP; + SetFlag(false, FLAGS_CARRY); + break; + + case OPCODE_SEC: // SEt Carry, Implied ($38 : SEC) + mReg.LastAddrMode = ADDRMODE_IMP; + SetFlag(true, FLAGS_CARRY); + break; + + case OPCODE_CLI: // CLear Interrupt, Implied ($58 : CLI) + mReg.LastAddrMode = ADDRMODE_IMP; + SetFlag(false, FLAGS_IRQ); + break; + + case OPCODE_CLV: // CLear oVerflow, Implied ($B8 : CLV) + mReg.LastAddrMode = ADDRMODE_IMP; + SetFlag(false, FLAGS_OVERFLOW); + break; + + case OPCODE_CLD: // CLear Decimal, Implied ($D8 : CLD) + mReg.LastAddrMode = ADDRMODE_IMP; + SetFlag(false, FLAGS_DEC); + break; + + case OPCODE_SED: // SEt Decimal, Implied ($F8 : SED) + mReg.LastAddrMode = ADDRMODE_IMP; + SetFlag(true, FLAGS_DEC); + break; + + case OPCODE_SEI: // SEt Interrupt, Implied ($78 : SEI) + mReg.LastAddrMode = ADDRMODE_IMP; + SetFlag(true, FLAGS_IRQ); + break; + + /* + * RTI retrieves the Processor Status Word (flags) and the Program Counter from the stack in that order + * (interrupts push the PC first and then the PSW). + * Note that unlike RTS, the return address on the stack is the actual address rather than the address-1. + */ + case OPCODE_RTI: // ReTurn from Interrupt, Implied ($40 : RTI) + mReg.LastAddrMode = ADDRMODE_IMP; + arg16 = 0x100; + arg16 += ++mReg.PtrStack; + mReg.Flags = mpMem->Peek8bit(arg16); + SetFlag(true,FLAGS_UNUSED); + arg16++; mReg.PtrStack++; + mReg.PtrAddr = mpMem->Peek8bit(arg16); + arg16++; mReg.PtrStack++; + mReg.PtrAddr += (mpMem->Peek8bit(arg16) * 0x100); + mReg.SoftIrq = CheckFlag(FLAGS_BRK); + SetFlag(false,FLAGS_IRQ); + break; + + case OPCODE_RTS: // ReTurn from Subroutine, Implied ($60 : RTS) + mReg.LastAddrMode = ADDRMODE_IMP; + if (mReg.PtrStack == 0xFF) { + mReg.LastRTS = true; + break; + } + arg16 = 0x100; + arg16 += ++mReg.PtrStack; + mReg.PtrAddr = mpMem->Peek8bit(arg16); + arg16++; mReg.PtrStack++; + mReg.PtrAddr += (mpMem->Peek8bit(arg16) * 0x100); + mReg.PtrAddr++; + break; + + case OPCODE_EOR_IZX: // bitwise Exclusive OR, Indexed Indirect ($41 arg : EOR (arg,X) ;arg=0..$FF), MEM=&(arg+X) + arg16 = GetAddrWithMode(ADDRMODE_IZX); + LogicOpAcc(arg16, LOGOP_EOR); + break; + + case OPCODE_EOR_ZP: // bitwise Exclusive OR, Zero Page ($45 arg : EOR arg ;arg=0..$FF), MEM=arg + LogicOpAcc(GetAddrWithMode(ADDRMODE_ZP), LOGOP_EOR); + break; + + case OPCODE_EOR_IMM: // bitwise Exclusive OR, Immediate ($49 arg : EOR #arg ;arg=0..$FF), MEM=PC+1 + arg16 = GetAddrWithMode(ADDRMODE_IMM); + mReg.LastArg = mpMem->Peek8bit(arg16); + LogicOpAcc(arg16, LOGOP_EOR); + break; + + case OPCODE_EOR_ABS: // bitwise Exclusive OR, Absolute ($4D addrlo addrhi : EOR addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + LogicOpAcc(arg16, LOGOP_EOR); + break; + + case OPCODE_EOR_IZY: // bitwise Exclusive OR, Indirect Indexed ($51 arg : EOR (arg),Y ;arg=0..$FF), MEM=&arg+Y + arg16 = GetAddrWithMode(ADDRMODE_IZY); + LogicOpAcc(arg16, LOGOP_EOR); + break; + + case OPCODE_EOR_ZPX: // bitwise Exclusive OR, Zero Page Indexed, X ($55 arg : EOR arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + LogicOpAcc(arg16, LOGOP_EOR); + break; + + case OPCODE_EOR_ABY: // bitwise Exclusive OR, Absolute Indexed, Y ($59 addrlo addrhi : EOR addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + LogicOpAcc(arg16, LOGOP_EOR); + break; + + case OPCODE_EOR_ABX: // bitwise Exclusive OR, Absolute Indexed, X ($5D addrlo addrhi : EOR addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + LogicOpAcc(arg16, LOGOP_EOR); + break; + + case OPCODE_LSR_ZP: // Logical Shift Right, Zero Page ($46 arg : LSR arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16); + arg8 = ShiftRight(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_LSR: // Logical Shift Right, Accumulator ($4A : LSR) + mReg.LastAddrMode = ADDRMODE_ACC; + mReg.Acc = ShiftRight(mReg.Acc); + break; + + case OPCODE_LSR_ABS: // Logical Shift Right, Absolute ($4E addrlo addrhi : LSR addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16); + arg8 = ShiftRight(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_LSR_ZPX: // Logical Shift Right, Zero Page Indexed, X ($56 arg : LSR arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + arg8 = mpMem->Peek8bit(arg16); + arg8 = ShiftRight(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_LSR_ABX: // Logical Shift Right, Absolute Indexed, X ($5E addrlo addrhi : LSR addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + arg8 = mpMem->Peek8bit(arg16); + arg8 = ShiftRight(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_ADC_IZX: // ADd with Carry, Indexed Indirect ($61 arg : ADC (arg,X) ;arg=0..$FF), MEM=&(arg+X) + arg16 = GetAddrWithMode(ADDRMODE_IZX); + AddWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_ADC_ZP: // ADd with Carry, Zero Page ($65 arg : ADC arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + AddWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_ADC_IMM: // ADd with Carry, Immediate ($69 arg : ADC #arg ;arg=0..$FF), MEM=PC+1 + mReg.LastArg = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); + AddWithCarry(mReg.LastArg); + break; + + case OPCODE_ADC_ABS: // ADd with Carry, Absolute ($6D addrlo addrhi : ADC addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + AddWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_ADC_IZY: // ADd with Carry, Indirect Indexed ($71 arg : ADC (arg),Y ;arg=0..$FF), MEM=&arg+Y + arg16 = GetAddrWithMode(ADDRMODE_IZY); + AddWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_ADC_ZPX: // ADd with Carry, Zero Page Indexed, X ($75 arg : ADC arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + AddWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_ADC_ABY: // ADd with Carry, Absolute Indexed, Y ($79 addrlo addrhi : ADC addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + AddWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_ADC_ABX: // ADd with Carry, Absolute Indexed, X ($7D addrlo addrhi : ADC addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + AddWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_ROR_ZP: // ROtate Right, Zero Page ($66 arg : ROR arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16); + mpMem->Poke8bit(arg16, RotateRight(arg8)); + break; + + case OPCODE_ROR: // ROtate Right, Accumulator ($6A : ROR) + mReg.LastAddrMode = ADDRMODE_ACC; + mReg.Acc = RotateRight(mReg.Acc); + break; + + case OPCODE_ROR_ABS: // ROtate Right, Absolute ($6E addrlo addrhi : ROR addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16); + mpMem->Poke8bit(arg16, RotateRight(arg8)); + break; + + case OPCODE_ROR_ZPX: // ROtate Right, Zero Page Indexed, X ($76 arg : ROR arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + arg8 = mpMem->Peek8bit(arg16); + mpMem->Poke8bit(arg16, RotateRight(arg8)); + break; + + case OPCODE_ROR_ABX: // ROtate Right, Absolute Indexed, X ($7E addrlo addrhi : ROR addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + arg8 = mpMem->Peek8bit(arg16); + mpMem->Poke8bit(arg16, RotateRight(arg8)); + break; + + case OPCODE_CPY_IMM: // ComPare Y register, Immediate ($C0 arg : CPY #arg ;arg=0..$FF), MEM=PC+1 + mReg.LastArg = arg8 = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); + SetFlag((mReg.IndY >= arg8), FLAGS_CARRY); + arg8 = mReg.IndY - arg8; + SetFlags(arg8); + break; + + case OPCODE_CPY_ZP: // ComPare Y register, Zero Page ($C4 arg : CPY arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.IndY >= arg8), FLAGS_CARRY); + arg8 = mReg.IndY - arg8; + SetFlags(arg8); + break; + + case OPCODE_CPY_ABS: // ComPare Y register, Absolute ($CC addrlo addrhi : CPY addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.IndY >= arg8), FLAGS_CARRY); + arg8 = mReg.IndY - arg8; + SetFlags(arg8); + break; + + case OPCODE_CMP_IZX: // CoMPare accumulator, Indexed Indirect ($A1 arg : LDA (arg,X) ;arg=0..$FF), MEM=&(arg+X) + arg16 = GetAddrWithMode(ADDRMODE_IZX); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); + arg8 = mReg.Acc - arg8; + SetFlags(arg8); + break; + + case OPCODE_CMP_ZP: // CoMPare accumulator, Zero Page ($C5 arg : CMP arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); + arg8 = mReg.Acc - arg8; + SetFlags(arg8); + break; + + case OPCODE_CMP_IMM: // CoMPare accumulator, Immediate ($C9 arg : CMP #arg ;arg=0..$FF), MEM=PC+1 + mReg.LastArg = arg8 = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); + SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); + arg8 = mReg.Acc - arg8; + SetFlags(arg8); + break; + + case OPCODE_CMP_ABS: // CoMPare accumulator, Absolute ($CD addrlo addrhi : CMP addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); + arg8 = mReg.Acc - arg8; + SetFlags(arg8); + break; + + case OPCODE_CMP_IZY: // CoMPare accumulator, Indirect Indexed ($D1 arg : CMP (arg),Y ;arg=0..$FF), MEM=&arg+Y + arg16 = GetAddrWithMode(ADDRMODE_IZY); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); + arg8 = mReg.Acc - arg8; + SetFlags(arg8); + break; + + case OPCODE_CMP_ZPX: // CoMPare accumulator, Zero Page Indexed, X ($D5 arg : CMP arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); + arg8 = mReg.Acc - arg8; + SetFlags(arg8); + break; + + case OPCODE_CMP_ABY: // CoMPare accumulator, Absolute Indexed, Y ($D9 addrlo addrhi : CMP addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); + arg8 = mReg.Acc - arg8; + SetFlags(arg8); + break; + + case OPCODE_CMP_ABX: // CoMPare accumulator, Absolute Indexed, X ($DD addrlo addrhi : CMP addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); + arg8 = mReg.Acc - arg8; + SetFlags(arg8); + break; + + case OPCODE_DEC_ZP: // DECrement memory, Zero Page ($C6 arg : DEC arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16) - 1; + mpMem->Poke8bit(arg16, arg8); + SetFlags(arg8); + break; + + case OPCODE_DEC_ABS: // DECrement memory, Absolute ($CE addrlo addrhi : CMP addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16) - 1; + mpMem->Poke8bit(arg16, arg8); + SetFlags(arg8); + break; + + case OPCODE_DEC_ZPX: // DECrement memory, Zero Page Indexed, X ($D6 arg : DEC arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + arg8 = mpMem->Peek8bit(arg16) - 1; + mpMem->Poke8bit(arg16, arg8); + SetFlags(arg8); + break; + + case OPCODE_DEC_ABX: // DECrement memory, Absolute Indexed, X ($DE addrlo addrhi : DEC addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + arg8 = mpMem->Peek8bit(arg16) - 1; + mpMem->Poke8bit(arg16, arg8); + SetFlags(arg8); + break; + + case OPCODE_CPX_IMM: // ComPare X register, Immediate ($E0 arg : CPX #arg ;arg=0..$FF), MEM=PC+1 + mReg.LastArg = arg8 = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); + SetFlag((mReg.IndX >= arg8), FLAGS_CARRY); + arg8 = mReg.IndX - arg8; + SetFlags(arg8); + break; + + case OPCODE_CPX_ZP: // ComPare X register, Zero Page ($E4 arg : CPX arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.IndX >= arg8), FLAGS_CARRY); + arg8 = mReg.IndX - arg8; + SetFlags(arg8); + break; + + case OPCODE_CPX_ABS: // ComPare X register, Absolute ($EC addrlo addrhi : CPX addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.IndX >= arg8), FLAGS_CARRY); + arg8 = mReg.IndX - arg8; + SetFlags(arg8); + break; + + case OPCODE_SBC_ZP: // SuBtract with Carry, Zero Page ($E5 arg : SBC arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + SubWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_SBC_ABS: // SuBtract with Carry, Absolute ($ED addrlo addrhi : SBC addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + SubWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_SBC_IZX: // SuBtract with Carry, Indexed Indirect ($E1 arg : SBC (arg,X) ;arg=0..$FF), MEM=&(arg+X) + arg16 = GetAddrWithMode(ADDRMODE_IZX); + SubWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_SBC_IZY: // SuBtract with Carry, Indirect Indexed ($F1 arg : SBC (arg),Y ;arg=0..$FF), MEM=&arg+Y + arg16 = GetAddrWithMode(ADDRMODE_IZY); + SubWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_SBC_ZPX: // SuBtract with Carry, Zero Page Indexed, X ($F5 arg : SBC arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + SubWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_SBC_ABY: // SuBtract with Carry, Absolute Indexed, Y ($F9 addrlo addrhi : SBC addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + SubWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_SBC_ABX: // SuBtract with Carry, Absolute Indexed, X ($FD addrlo addrhi : SBC addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + SubWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_SBC_IMM: // SuBtract with Carry, Immediate ($E9 arg : SBC #arg ;arg=0..$FF), MEM=PC+1 + mReg.LastArg = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); + SubWithCarry(mReg.LastArg); + break; + + default: + // trap illegal opcode that has unidentified behavior + { + string s = ((mOpCodesMap[(eOpCodes)mReg.LastOpCode]).amf.length() > 0 + ? (mOpCodesMap[(eOpCodes)mReg.LastOpCode]).amf.c_str() : "???"); + if (s.compare("ILL") == 0) { + mReg.SoftIrq = true; + } + } + break; + } + + Disassemble(); + char histentry[80]; + sprintf(histentry, "$%04x: %-16s \t$%02x | $%02x | $%02x | $%02x | $%02x", + mReg.LastAddr, mReg.LastInstr.c_str(), mReg.Acc, mReg.IndX, mReg.IndY, mReg.Flags, mReg.PtrStack); + Add2History(histentry); + + return &mReg; +} + +/* + *-------------------------------------------------------------------- + * Method: GetRegs() + * Purpose: Return pointer to CPU registers and status. + * Arguments: n/a + * Returns: pointer to Regs structure. + *-------------------------------------------------------------------- + */ +Regs *MKCpu::GetRegs() +{ + return &mReg; +} + +/* + *-------------------------------------------------------------------- + * Method: Add2History() + * Purpose: Add entry to execute history. + * Arguments: s - string (entry) + * Returns: n/a + *-------------------------------------------------------------------- + */ +void MKCpu::Add2History(string s) +{ + mExecHistory.push(s); + while (mExecHistory.size() > 20) mExecHistory.pop(); +} + +/* + *-------------------------------------------------------------------- + * Method: GetExecHistory() + * Purpose: Return queue with execute history. + * Arguments: n/a + * Returns: queue + *-------------------------------------------------------------------- + */ +queue MKCpu::GetExecHistory() +{ + return mExecHistory; +} + +} // namespace MKBasic diff --git a/MKCpu.h b/MKCpu.h index ddcdf94..3ccdf4f 100644 --- a/MKCpu.h +++ b/MKCpu.h @@ -1,424 +1,462 @@ -#ifndef MKCPU_H -#define MKCPU_H - -#include "Memory.h" - -namespace MKBasic { - -struct Regs { - unsigned char Acc; // 8-bit accumulator - unsigned short Acc16; // 16-bit accumulator - unsigned char IndX; // 8-bit index register X - unsigned char IndY; // 8-bit index register Y - unsigned short Ptr16; // general purpose 16-bit register - unsigned short PtrAddr; // cpu code counter - current read/write address - unsigned char PtrStack; // 8-bit stack pointer (0-255). - unsigned char Flags; // CPU flags - bool SoftIrq; // true when interrupted with BRK - bool LastRTS; // true if RTS encountered and stack empty. -}; - -/* - * Virtual CPU, 6502 addressing modes: - - +---------------------+--------------------------+ - | mode | assembler format | - +=====================+==========================+ - | Immediate | #aa | - | Absolute | aaaa | - | Zero Page | aa | Note: - | Implied | | - | Indirect Absolute | (aaaa) | aa = 2 hex digits - | Absolute Indexed,X | aaaa,X | as $FF - | Absolute Indexed,Y | aaaa,Y | - | Zero Page Indexed,X | aa,X | aaaa = 4 hex - | Zero Page Indexed,Y | aa,Y | digits as - | Indexed Indirect | (aa,X) | $FFFF - | Indirect Indexed | (aa),Y | - | Relative | aaaa | Can also be - | Accumulator | A | assembler labels - +---------------------+--------------------------+ - -Short notation: - -imm = #$00 -zp = $00 -zpx = $00,X -zpy = $00,Y -izx = ($00,X) -izy = ($00),Y -abs = $0000 -abx = $0000,X -aby = $0000,Y -ind = ($0000) -rel = $0000 (PC-relative) - -See: 6502AssemblyInOneStep.txt for details. - - */ -enum eAddrModes { - ADDRMODE_IMM = 0, - ADDRMODE_ABS, - ADDRMODE_ZP, - ADDRMODE_IMP, - ADDRMODE_IND, - ADDRMODE_ABX, - ADDRMODE_ABY, - ADDRMODE_ZPX, - ADDRMODE_ZPY, - ADDRMODE_IZX, - ADDRMODE_IZY, - ADDRMODE_REL, - ADDRMODE_ACC -}; -// assumed little-endian order of bytes (start with least significant) -// MEM - memory location from where the value is read/written, -// & - reference operator (e.g.: &addr means: value under addr memory location) -// PC - program counter (PC+1 means - next memory location after opcode) -enum eOpCodes { - OPCODE_BRK = 0x00, // software interrupt, no arguments ($00 : BRK) - - /* full compatibility with 65C02 (illegal opcodes not supported, will be used for extended functions */ - OPCODE_ORA_IZX = 0x01, // bitwise OR with Accumulator, Indexed Indirect ($01 arg : ORA (arg,X) ;arg=0..$FF), MEM=&(arg+X) - OPCODE_ILL_02 = 0x02, // illegal opcode - OPCODE_ILL_03 = 0x03, // illegal opcode - OPCODE_ILL_04 = 0x04, // illegal opcode - OPCODE_ORA_ZP = 0x05, // bitwise OR with Accumulator, Zero Page ($05 arg : ORA arg ;arg=0..$FF), MEM=arg - OPCODE_ASL_ZP = 0x06, // Arithmetic Shift Left, Zero Page ($06 arg : ASL arg ;arg=0..$FF), MEM=arg - OPCODE_ILL_07 = 0x07, // illegal opcode - OPCODE_PHP = 0x08, // PusH Processor status on Stack, Implied ($08 : PHP) - OPCODE_ORA_IMM = 0x09, // bitwise OR with Accumulator, Immediate ($09 arg : ORA #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_ASL = 0x0A, // Arithmetic Shift Left, Accumulator ($0A : ASL) - OPCODE_ILL_0B = 0x0B, // illegal opcode - OPCODE_ILL_0C = 0x0C, // illegal opcode - OPCODE_ORA_ABS = 0x0D, // bitwise OR with Accumulator, Absolute ($0D addrlo addrhi : ORA addr ;addr=0..$FFFF), MEM=addr - OPCODE_ASL_ABS = 0x0E, // Arithmetic Shift Left, Absolute ($0E addrlo addrhi : ASL addr ;addr=0..$FFFF), MEM=addr - OPCODE_ILL_0F = 0x0F, // illegal opcode - OPCODE_BPL_REL = 0x10, // Branch on PLus, Relative ($10 signoffs : BPL signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - OPCODE_ORA_IZY = 0x11, // bitwise OR with Accumulator, Indirect Indexed ($11 arg : ORA (arg),Y ;arg=0..$FF), MEM=&arg+Y - OPCODE_ILL_12 = 0x12, // illegal opcode - OPCODE_ILL_13 = 0x13, // illegal opcode - OPCODE_ILL_14 = 0x14, // illegal opcode - OPCODE_ORA_ZPX = 0x15, // bitwise OR with Accumulator, Zero Page Indexed, X ($15 arg : ORA arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ASL_ZPX = 0x16, // Arithmetic Shift Left, Zero Page Indexed, X ($16 arg : ASL arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ILL_17 = 0x17, // illegal opcode - OPCODE_CLC = 0x18, // CLear Carry, Implied ($18 : CLC) - OPCODE_ORA_ABY = 0x19, // bitwise OR with Accumulator, Absolute Indexed, Y ($19 addrlo addrhi : ORA addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_ILL_1A = 0x1A, // illegal opcode - OPCODE_ILL_1B = 0x1B, // illegal opcode - OPCODE_ILL_1C = 0x1C, // illegal opcode - OPCODE_ORA_ABX = 0x1D, // bitwise OR with Accumulator, Absolute Indexed, X ($1D addrlo addrhi : ORA addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ASL_ABX = 0x1E, // Arithmetic Shift Left, Absolute Indexed, X ($1E addrlo addrhi : ASL addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ILL_1F = 0x1F, // illegal opcode - OPCODE_JSR_ABS = 0x20, // Jump to SubRoutine, Absolute ($20 addrlo addrhi : JSR addr ;addr=0..$FFFF), MEM=addr - OPCODE_AND_IZX = 0x21, // bitwise AND with accumulator, Indexed Indirect ($21 arg : AND (arg,X) ;arg=0..$FF), MEM=&(arg+X) - OPCODE_ILL_22 = 0x22, // illegal opcode - OPCODE_ILL_23 = 0x23, // illegal opcode - OPCODE_BIT_ZP = 0x24, // test BITs, Zero Page ($24 arg : BIT arg ;arg=0..$FF), MEM=arg - OPCODE_AND_ZP = 0x25, // bitwise AND with accumulator, Zero Page ($25 arg : AND arg ;arg=0..$FF), MEM=arg - OPCODE_ROL_ZP = 0x26, // ROtate Left, Zero Page ($26 arg : ROL arg ;arg=0..$FF), MEM=arg - OPCODE_ILL_27 = 0x27, // illegal opcode - OPCODE_PLP = 0x28, // PuLl Processor status, Implied ($28 : PLP) - OPCODE_AND_IMM = 0x29, // bitwise AND with accumulator, Immediate ($29 arg : AND #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_ROL = 0x2A, // ROtate Left, Accumulator ($2A : ROL) - OPCODE_ILL_2B = 0x2B, // illegal opcode - OPCODE_BIT_ABS = 0x2C, // test BITs, Absolute ($2C addrlo addrhi : BIT addr ;addr=0..$FFFF), MEM=addr - OPCODE_AND_ABS = 0x2D, // bitwise AND with accumulator, Absolute ($2D addrlo addrhi : AND addr ;addr=0..$FFFF), MEM=addr - OPCODE_ROL_ABS = 0x2E, // ROtate Left, Absolute ($2E addrlo addrhi : ROL addr ;addr=0..$FFFF), MEM=addr - OPCODE_ILL_2F = 0x2F, // illegal opcode - OPCODE_BMI_REL = 0x30, // Branch on MInus, Relative ($30 signoffs : BMI signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - OPCODE_AND_IZY = 0x31, // bitwise AND with accumulator, Indirect Indexed ($31 arg : AND (arg),Y ;arg=0..$FF), MEM=&arg+Y - OPCODE_ILL_32 = 0x32, // illegal opcode - OPCODE_ILL_33 = 0x33, // illegal opcode - OPCODE_ILL_34 = 0x34, // illegal opcode - OPCODE_AND_ZPX = 0x35, // bitwise AND with accumulator, Zero Page Indexed, X ($35 arg : AND arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ROL_ZPX = 0x36, // ROtate Left, Zero Page Indexed, X ($36 arg : ROL arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ILL_37 = 0x37, // illegal opcode - OPCODE_SEC = 0x38, // SEt Carry, Implied ($38 : SEC) - OPCODE_AND_ABY = 0x39, // bitwise AND with accumulator, Absolute Indexed, Y ($39 addrlo addrhi : AND addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_ILL_3A = 0x3A, // illegal opcode - OPCODE_ILL_3B = 0x3B, // illegal opcode - OPCODE_ILL_3C = 0x3C, // illegal opcode - OPCODE_AND_ABX = 0x3D, // bitwise AND with accumulator, Absolute Indexed, X ($3D addrlo addrhi : AND addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ROL_ABX = 0x3E, // ROtate Left, Absolute Indexed, X ($3E addrlo addrhi : ROL addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ILL_3F = 0x3F, // illegal opcode - OPCODE_RTI = 0x40, // ReTurn from Interrupt, Implied ($40 : RTI) - OPCODE_EOR_IZX = 0x41, // bitwise Exclusive OR, Indexed Indirect ($41 arg : EOR (arg,X) ;arg=0..$FF), MEM=&(arg+X) - OPCODE_ILL_42 = 0x42, // illegal opcode - OPCODE_ILL_43 = 0x43, // illegal opcode - OPCODE_ILL_44 = 0x44, // illegal opcode - OPCODE_EOR_ZP = 0x45, // bitwise Exclusive OR, Zero Page ($45 arg : EOR arg ;arg=0..$FF), MEM=arg - OPCODE_LSR_ZP = 0x46, // Logical Shift Right, Zero Page ($46 arg : LSR arg ;arg=0..$FF), MEM=arg - OPCODE_ILL_47 = 0x47, // illegal opcode - OPCODE_PHA = 0x48, // PusH Accumulator, Implied ($48 : PHA) - OPCODE_EOR_IMM = 0x49, // bitwise Exclusive OR, Immediate ($49 arg : EOR #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_LSR = 0x4A, // Logical Shift Right, Accumulator ($4A : LSR) - OPCODE_ILL_4B = 0x4B, // illegal opcode - OPCODE_JMP_ABS = 0x4C, // JuMP, Absolute ($4C addrlo addrhi : JMP addr ;addr=0..$FFFF), MEM=addr - OPCODE_EOR_ABS = 0x4D, // bitwise Exclusive OR, Absolute ($4D addrlo addrhi : EOR addr ;addr=0..$FFFF), MEM=addr - OPCODE_LSR_ABS = 0x4E, // Logical Shift Right, Absolute ($4E addrlo addrhi : LSR addr ;addr=0..$FFFF), MEM=addr - OPCODE_ILL_4F = 0x4F, // illegal opcode - OPCODE_BVC_REL = 0x50, // Branch on oVerflow Clear, Relative ($50 signoffs : BVC signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - OPCODE_EOR_IZY = 0x51, // bitwise Exclusive OR, Indirect Indexed ($51 arg : EOR (arg),Y ;arg=0..$FF), MEM=&arg+Y - OPCODE_ILL_52 = 0x52, // illegal opcode - OPCODE_ILL_53 = 0x53, // illegal opcode - OPCODE_ILL_54 = 0x54, // illegal opcode - OPCODE_EOR_ZPX = 0x55, // bitwise Exclusive OR, Zero Page Indexed, X ($55 arg : EOR arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_LSR_ZPX = 0x56, // Logical Shift Right, Zero Page Indexed, X ($56 arg : LSR arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ILL_57 = 0x57, // illegal opcode - OPCODE_CLI = 0x58, // CLear Interrupt, Implied ($58 : CLI) - OPCODE_EOR_ABY = 0x59, // bitwise Exclusive OR, Absolute Indexed, Y ($59 addrlo addrhi : EOR addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_ILL_5A = 0x5A, // illegal opcode - OPCODE_ILL_5B = 0x5B, // illegal opcode - OPCODE_ILL_5C = 0x5C, // illegal opcode - OPCODE_EOR_ABX = 0x5D, // bitwise Exclusive OR, Absolute Indexed, X ($5D addrlo addrhi : EOR addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_LSR_ABX = 0x5E, // Logical Shift Right, Absolute Indexed, X ($5E addrlo addrhi : LSR addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ILL_5F = 0x5F, // illegal opcode - OPCODE_RTS = 0x60, // ReTurn from Subroutine, Implied ($60 : RTS) - OPCODE_ADC_IZX = 0x61, // ADd with Carry, Indexed Indirect ($61 arg : ADC (arg,X) ;arg=0..$FF), MEM=&(arg+X) - OPCODE_ILL_62 = 0x62, // illegal opcode - OPCODE_ILL_63 = 0x63, // illegal opcode - OPCODE_ILL_64 = 0x64, // illegal opcode - OPCODE_ADC_ZP = 0x65, // ADd with Carry, Zero Page ($65 arg : ADC arg ;arg=0..$FF), MEM=arg - OPCODE_ROR_ZP = 0x66, // ROtate Right, Zero Page ($66 arg : ROR arg ;arg=0..$FF), MEM=arg - OPCODE_ILL_67 = 0x67, // illegal opcode - OPCODE_PLA = 0x68, // PuLl Accumulator, Implied ($68 : PLA) - OPCODE_ADC_IMM = 0x69, // ADd with Carry, Immediate ($69 arg : ADC #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_ROR = 0x6A, // ROtate Right, Accumulator ($6A : ROR) - OPCODE_ILL_6B = 0x6B, // illegal opcode - OPCODE_JMP_IND = 0x6C, // JuMP, Indirect Absolute ($6C addrlo addrhi : JMP (addr) ;addr=0..FFFF), MEM=&addr - OPCODE_ADC_ABS = 0x6D, // ADd with Carry, Absolute ($6D addrlo addrhi : ADC addr ;addr=0..$FFFF), MEM=addr - OPCODE_ROR_ABS = 0x6E, // ROtate Right, Absolute ($6E addrlo addrhi : ROR addr ;addr=0..$FFFF), MEM=addr - OPCODE_ILL_6F = 0x6F, // illegal opcode - OPCODE_BVS_REL = 0x70, // Branch on oVerflow Set, Relative ($70 signoffs : BVS signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - OPCODE_ADC_IZY = 0x71, // ADd with Carry, Indirect Indexed ($71 arg : ADC (arg),Y ;arg=0..$FF), MEM=&arg+Y - OPCODE_ILL_72 = 0x72, // illegal opcode - OPCODE_ILL_73 = 0x73, // illegal opcode - OPCODE_ILL_74 = 0x74, // illegal opcode - OPCODE_ADC_ZPX = 0x75, // ADd with Carry, Zero Page Indexed, X ($75 arg : ADC arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ROR_ZPX = 0x76, // ROtate Right, Zero Page Indexed, X ($76 arg : ROR arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ILL_77 = 0x77, // illegal opcode - OPCODE_SEI = 0x78, // SEt Interrupt, Implied ($78 : SEI) - OPCODE_ADC_ABY = 0x79, // ADd with Carry, Absolute Indexed, Y ($79 addrlo addrhi : ADC addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_ILL_7A = 0x7A, // illegal opcode - OPCODE_ILL_7B = 0x7B, // illegal opcode - OPCODE_ILL_7C = 0x7C, // illegal opcode - OPCODE_ADC_ABX = 0x7D, // ADd with Carry, Absolute Indexed, X ($7D addrlo addrhi : ADC addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ROR_ABX = 0x7E, // ROtate Right, Absolute Indexed, X ($7E addrlo addrhi : ROR addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ILL_7F = 0x7F, // illegal opcode - OPCODE_ILL_80 = 0x80, // illegal opcode - OPCODE_STA_IZX = 0x81, // STore Accumulator, Indexed Indirect ($81 arg : STA (arg,X) ;arg=0..$FF), MEM=&(arg+X) - OPCODE_ILL_82 = 0x82, // illegal opcode - OPCODE_ILL_83 = 0x83, // illegal opcode - OPCODE_STY_ZP = 0x84, // STore Y register, Zero Page ($84 arg : STY arg ;arg=0..$FF), MEM=arg - OPCODE_STA_ZP = 0x85, // STore Accumulator, Zero Page ($85 arg : STA arg ;arg=0..$FF), MEM=arg - OPCODE_STX_ZP = 0x86, // STore X register, Zero Page ($86 arg : STX arg ;arg=0..$FF), MEM=arg - OPCODE_ILL_87 = 0x87, // illegal opcode - OPCODE_DEY = 0x88, // DEcrement Y, Implied ($88 : DEY) - OPCODE_ILL_89 = 0x89, // illegal opcode - OPCODE_TXA = 0x8A, // Transfer X to A, Implied ($8A : TXA) - OPCODE_ILL_8B = 0x8B, // illegal opcode - OPCODE_STY_ABS = 0x8C, // STore Y register, Absolute ($8C addrlo addrhi : STY addr ;addr=0..$FFFF), MEM=addr - OPCODE_STA_ABS = 0x8D, // STore Accumulator, Absolute ($8D addrlo addrhi : STA addr ;addr=0..$FFFF), MEM=addr - OPCODE_STX_ABS = 0x8E, // STore X register, Absolute ($8E addrlo addrhi : STX addr ;addr=0..$FFFF), MEM=addr - OPCODE_ILL_8F = 0x8F, // illegal opcode - OPCODE_BCC_REL = 0x90, // Branch on Carry Clear, Relative ($90 signoffs : BCC signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - OPCODE_STA_IZY = 0x91, // STore Accumulator, Indirect Indexed ($91 arg : STA (arg),Y ;arg=0..$FF), MEM=&arg+Y - OPCODE_ILL_92 = 0x92, // illegal opcode - OPCODE_ILL_93 = 0x93, // illegal opcode - OPCODE_STY_ZPX = 0x94, // STore Y register, Zero Page Indexed, X ($94 arg : STY arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_STA_ZPX = 0x95, // STore Accumulator, Zero Page Indexed, X ($95 arg : STA arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_STX_ZPY = 0x96, // STore X register, Zero Page Indexed, Y ($96 arg : STX arg,Y ;arg=0..$FF), MEM=arg+Y - OPCODE_ILL_97 = 0x97, // illegal opcode - OPCODE_TYA = 0x98, // Transfer Y to A, Implied ($98 : TYA) - OPCODE_STA_ABY = 0x99, // STore Accumulator, Absolute Indexed, Y ($99 addrlo addrhi : STA addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_TXS = 0x9A, // Transfer X to Stack ptr, Implied ($9A : TXS) - OPCODE_ILL_9B = 0x9B, // illegal opcode - OPCODE_ILL_9C = 0x9C, // illegal opcode - OPCODE_STA_ABX = 0x9D, // STore Accumulator, Absolute Indexed, X ($9D addrlo addrhi : STA addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ILL_9E = 0x9E, // illegal opcode - OPCODE_ILL_9F = 0x9F, // illegal opcode - OPCODE_LDY_IMM = 0xA0, // LoaD Y register, Immediate ($A0 arg : LDY #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_LDA_IZX = 0xA1, // LoaD Accumulator, Indexed Indirect ($A1 arg : LDA (arg,X) ;arg=0..$FF), MEM=&(arg+X) - OPCODE_LDX_IMM = 0xA2, // LoaD X register, Immediate ($A2 arg : LDX #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_ILL_A3 = 0xA3, // illegal opcode - OPCODE_LDY_ZP = 0xA4, // LoaD Y register, Zero Page ($A4 arg : LDY arg ;arg=0..$FF), MEM=arg - OPCODE_LDA_ZP = 0xA5, // LoaD Accumulator, Zero Page ($A5 arg : LDA arg ;arg=0..$FF), MEM=arg - OPCODE_LDX_ZP = 0xA6, // LoaD X register, Zero Page ($A6 arg : LDX arg ;arg=0..$FF), MEM=arg - OPCODE_ILL_A7 = 0xA7, // illegal opcode - OPCODE_TAY = 0xA8, // Transfer A to Y, Implied ($A8 : TAY) - OPCODE_LDA_IMM = 0xA9, // LoaD Accumulator, Immediate ($A9 arg : LDA #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_TAX = 0xAA, // Transfer A to X, Implied ($AA : TAX) - OPCODE_ILL_AB = 0xAB, // illegal opcode - OPCODE_LDY_ABS = 0xAC, // LoaD Y register, Absolute ($AC addrlo addrhi : LDY addr ;addr=0..$FFFF), MEM=addr - OPCODE_LDA_ABS = 0xAD, // LoaD Accumulator, Absolute ($AD addrlo addrhi : LDA addr ;addr=0..$FFFF), MEM=addr - OPCODE_LDX_ABS = 0xAE, // LoaD X register, Absolute ($AE addrlo addrhi : LDX addr ;addr=0..$FFFF), MEM=addr - OPCODE_ILL_AF = 0xAF, // illegal opcode - OPCODE_BCS_REL = 0xB0, // Branch on Carry Set, Relative ($B0 signoffs : BCS signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - OPCODE_LDA_IZY = 0xB1, // LoaD Accumulator, Indirect Indexed ($B1 arg : LDA (arg),Y ;arg=0..$FF), MEM=&arg+Y - OPCODE_ILL_B2 = 0xB2, // illegal opcode - OPCODE_ILL_B3 = 0xB3, // illegal opcode - OPCODE_LDY_ZPX = 0xB4, // LoaD Y register, Zero Page Indexed, X ($B4 arg : LDY arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_LDA_ZPX = 0xB5, // LoaD Accumulator, Zero Page Indexed, X ($B5 arg : LDA arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_LDX_ZPY = 0xB6, // LoaD X register, Zero Page Indexed, Y ($B6 arg : LDX arg,Y ;arg=0..$FF), MEM=arg+Y - OPCODE_ILL_B7 = 0xB7, // illegal opcode - OPCODE_CLV = 0xB8, // CLear oVerflow, Implied ($B8 : CLV) - OPCODE_LDA_ABY = 0xB9, // LoaD Accumulator, Absolute Indexed, Y ($B9 addrlo addrhi : LDA addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_TSX = 0xBA, // Transfer Stack ptr to X, Implied ($BA : TSX) - OPCODE_ILL_BB = 0xBB, // illegal opcode - OPCODE_LDY_ABX = 0xBC, // LoaD Y register, Absolute Indexed, X ($BC addrlo addrhi : LDY addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_LDA_ABX = 0xBD, // LoaD Accumulator, Absolute Indexed, X ($BD addrlo addrhi : LDA addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_LDX_ABY = 0xBE, // LoaD X register, Absolute Indexed, Y ($BE addrlo addrhi : LDX addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_ILL_BF = 0xBF, // illegal opcode - OPCODE_CPY_IMM = 0xC0, // ComPare Y register, Immediate ($C0 arg : CPY #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_CMP_IZX = 0xC1, // CoMPare accumulator, Indexed Indirect ($A1 arg : LDA (arg,X) ;arg=0..$FF), MEM=&(arg+X) - OPCODE_ILL_C2 = 0xC2, // illegal opcode - OPCODE_ILL_C3 = 0xC3, // illegal opcode - OPCODE_CPY_ZP = 0xC4, // ComPare Y register, Zero Page ($C4 arg : CPY arg ;arg=0..$FF), MEM=arg - OPCODE_CMP_ZP = 0xC5, // CoMPare accumulator, Zero Page ($C5 arg : CMP arg ;arg=0..$FF), MEM=arg - OPCODE_DEC_ZP = 0xC6, // DECrement memory, Zero Page ($C6 arg : DEC arg ;arg=0..$FF), MEM=arg - OPCODE_ILL_C7 = 0xC7, // illegal opcode - OPCODE_INY = 0xC8, // INcrement Y, Implied ($C8 : INY)OPCODE_INY = 0xC8, // INcrement Y, Implied ($C8 : INY) - OPCODE_CMP_IMM = 0xC9, // CoMPare accumulator, Immediate ($C9 arg : CMP #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_DEX = 0xCA, // DEcrement X, Implied ($CA : DEX) - OPCODE_ILL_CB = 0xCB, // illegal opcode - OPCODE_CPY_ABS = 0xCC, // ComPare Y register, Absolute ($CC addrlo addrhi : CPY addr ;addr=0..$FFFF), MEM=addr - OPCODE_CMP_ABS = 0xCD, // CoMPare accumulator, Absolute ($CD addrlo addrhi : CMP addr ;addr=0..$FFFF), MEM=addr - OPCODE_DEC_ABS = 0xCE, // DECrement memory, Absolute ($CE addrlo addrhi : CMP addr ;addr=0..$FFFF), MEM=addr - OPCODE_ILL_CF = 0xCF, // illegal opcode - OPCODE_BNE_REL = 0xD0, // Branch on Not Equal, Relative ($D0 signoffs : BNE signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - OPCODE_CMP_IZY = 0xD1, // CoMPare accumulator, Indirect Indexed ($D1 arg : CMP (arg),Y ;arg=0..$FF), MEM=&arg+Y - OPCODE_ILL_D2 = 0xD2, // illegal opcode - OPCODE_ILL_D3 = 0xD3, // illegal opcode - OPCODE_ILL_D4 = 0xD4, // illegal opcode - OPCODE_CMP_ZPX = 0xD5, // CoMPare accumulator, Zero Page Indexed, X ($D5 arg : CMP arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_DEC_ZPX = 0xD6, // DECrement memory, Zero Page Indexed, X ($D6 arg : DEC arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ILL_D7 = 0xD7, // illegal opcode - OPCODE_CLD = 0xD8, // CLear Decimal, Implied ($D8 : CLD) - OPCODE_CMP_ABY = 0xD9, // CoMPare accumulator, Absolute Indexed, Y ($D9 addrlo addrhi : CMP addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_ILL_DA = 0xDA, // illegal opcode - OPCODE_ILL_DB = 0xDB, // illegal opcode - OPCODE_ILL_DC = 0xDC, // illegal opcode - OPCODE_CMP_ABX = 0xDD, // CoMPare accumulator, Absolute Indexed, X ($DD addrlo addrhi : CMP addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_DEC_ABX = 0xDE, // DECrement memory, Absolute Indexed, X ($DE addrlo addrhi : DEC addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ILL_DF = 0xDF, // illegal opcode - OPCODE_CPX_IMM = 0xE0, // ComPare X register, Immediate ($E0 arg : CPX #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_SBC_IZX = 0xE1, // SuBtract with Carry, Indexed Indirect ($E1 arg : SBC (arg,X) ;arg=0..$FF), MEM=&(arg+X) - OPCODE_ILL_E2 = 0xE2, // illegal opcode - OPCODE_ILL_E3 = 0xE3, // illegal opcode - OPCODE_CPX_ZP = 0xE4, // ComPare X register, Zero Page ($E4 arg : CPX arg ;arg=0..$FF), MEM=arg - OPCODE_SBC_ZP = 0xE5, // SuBtract with Carry, Zero Page ($E5 arg : SBC arg ;arg=0..$FF), MEM=arg - OPCODE_INC_ZP = 0xE6, // INCrement memory, Zero Page ($E6 arg : INC arg ;arg=0..$FF), MEM=arg - OPCODE_ILL_E7 = 0xE7, // illegal opcode - OPCODE_INX = 0xE8, // INcrement X, Implied ($E8 : INX) - OPCODE_SBC_IMM = 0xE9, // SuBtract with Carry, Immediate ($E9 arg : SBC #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_NOP = 0xEA, // NO oPeration, Implied ($EA : NOP) - OPCODE_ILL_EB = 0xEB, // illegal opcode - OPCODE_CPX_ABS = 0xEC, // ComPare X register, Absolute ($EC addrlo addrhi : CPX addr ;addr=0..$FFFF), MEM=addr - OPCODE_SBC_ABS = 0xED, // SuBtract with Carry, Absolute ($ED addrlo addrhi : SBC addr ;addr=0..$FFFF), MEM=addr - OPCODE_INC_ABS = 0xEE, // INCrement memory, Absolute ($EE addrlo addrhi : INC addr ;addr=0..$FFFF), MEM=addr - OPCODE_ILL_EF = 0xEF, // illegal opcode - OPCODE_BEQ_REL = 0xF0, // Branch on EQual, Relative ($F0 signoffs : BEQ signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - OPCODE_SBC_IZY = 0xF1, // SuBtract with Carry, Indirect Indexed ($F1 arg : SBC (arg),Y ;arg=0..$FF), MEM=&arg+Y - OPCODE_ILL_F2 = 0xF2, // illegal opcode - OPCODE_ILL_F3 = 0xF3, // illegal opcode - OPCODE_ILL_F4 = 0xF4, // illegal opcode - OPCODE_SBC_ZPX = 0xF5, // SuBtract with Carry, Zero Page Indexed, X ($F5 arg : SBC arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_INC_ZPX = 0xF6, // INCrement memory, Zero Page Indexed, X ($F6 arg : INC arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ILL_F7 = 0xF7, // illegal opcode - OPCODE_SED = 0xF8, // SEt Decimal, Implied ($F8 : SED) - OPCODE_SBC_ABY = 0xF9, // SuBtract with Carry, Absolute Indexed, Y ($F9 addrlo addrhi : SBC addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_ILL_FA = 0xFA, // illegal opcode - OPCODE_ILL_FB = 0xFB, // illegal opcode - OPCODE_ILL_FC = 0xFC, // illegal opcode - OPCODE_SBC_ABX = 0xFD, // SuBtract with Carry, Absolute Indexed, X ($FD addrlo addrhi : SBC addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_INC_ABX = 0xFE, // INCrement memory, Absolute Indexed, X ($FE addrlo addrhi : INC addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ILL_FF = 0xFF, // illegal opcode -}; - -/* - *------------------------------------------------------------------------------ - bit -> 7 0 - +---+---+---+---+---+---+---+---+ - | N | V | | B | D | I | Z | C | <-- flag, 0/1 = reset/set - +---+---+---+---+---+---+---+---+ - - - N = NEGATIVE. Set if bit 7 of the accumulator is set. - - V = OVERFLOW. Set if the addition of two like-signed numbers or the - subtraction of two unlike-signed numbers produces a result - greater than +127 or less than -128. - - B = BRK COMMAND. Set if an interrupt caused by a BRK, reset if - caused by an external interrupt. - - D = DECIMAL MODE. Set if decimal mode active. - - I = IRQ DISABLE. Set if maskable interrupts are disabled. - - Z = ZERO. Set if the result of the last operation (load/inc/dec/ - add/sub) was zero. - - C = CARRY. Set if the add produced a carry, or if the subtraction - produced a borrow. Also holds bits after a logical shift. - *------------------------------------------------------------------------------ - */ -enum eCpuFlagMasks { - FLAGS_CARRY = 0x01, // 0: C - FLAGS_ZERO = 0x02, // 1: Z - FLAGS_IRQ = 0x04, // 2: I - FLAGS_DEC = 0x08, // 3: D - FLAGS_BRK = 0x10, // 4: B (Clear if interrupt vectoring, set if BRK or PHP) - FLAGS_UNUSED = 0x20, // 5: Unused flag (always set). - FLAGS_OVERFLOW = 0x40, // 6: V - FLAGS_SIGN = 0x80 // 7: N -}; - -enum eLogicOps { - LOGOP_OR, - LOGOP_AND, - LOGOP_EOR -}; - -class MKCpu -{ - public: - - MKCpu(); - MKCpu(Memory *pmem); - ~MKCpu(); - - Regs *ExecOpcode(unsigned short memaddr); - Regs *GetRegs(); - - protected: - - private: - - struct Regs mReg; // CPU registers - Memory *mpMem; // pointer to memory object - bool mLocalMem; // true - memory locally allocated - - void InitCpu(); - void SetFlags(unsigned char reg); // set CPU flags ZERO and SIGN based on Acc, X or Y - unsigned char ShiftLeft(unsigned char arg8); // Arithmetic Shift Left, set Carry flag - unsigned char ShiftRight(unsigned char arg8); // Logical Shift Right, update flags NZC. - unsigned char RotateLeft(unsigned char arg8); // Rotate left, Carry to bit 0, bit 7 to Carry, update flags N and Z. - unsigned char RotateRight(unsigned char arg8); // Rotate left, Carry to bit 7, bit 0 to Carry, update flags N and Z. - unsigned short GetArg16(unsigned char offs); // Get 2-byte argument, add offset, increase PC. - void LogicOpAcc(unsigned short addr, int logop); // Perform logical bitwise operation between memory location and Acc. - // Result in Acc. Set flags. - unsigned short ComputeRelJump(unsigned char offs); // Compute new PC based on relative offset. - unsigned char Conv2Bcd(unsigned short v); // Convert number to BCD representation. - unsigned short Bcd2Num(unsigned char v); // Convert BCD code to number. - bool CheckFlag(unsigned char flag); // Return true if given CPU status flag is set, false otherwise. - void SetFlag(bool set, unsigned char flag); // Set or unset processor status flag. - unsigned char AddWithCarry(unsigned char mem8); // Add With Carry, update flags and Acc. - unsigned char SubWithCarry(unsigned char mem8); // Subtract With Carry, update flags and Acc. - unsigned short GetAddrWithMode(int mode); // Get address of the byte argument with specified addr. mode -}; - -} // namespace MKBasic - -#endif +#ifndef MKCPU_H +#define MKCPU_H + +#include +#include +#include +#include "system.h" +#include "Memory.h" + +using namespace std; + +namespace MKBasic { + +#define DISS_BUF_SIZE 60 // disassembled instruction buffer size + +struct Regs { + unsigned char Acc; // 8-bit accumulator + unsigned short Acc16; // 16-bit accumulator + unsigned char IndX; // 8-bit index register X + unsigned char IndY; // 8-bit index register Y + unsigned short Ptr16; // general purpose 16-bit register + unsigned short PtrAddr; // cpu code counter (PC) - current read/write address + unsigned char PtrStack; // 8-bit stack pointer (0-255). + unsigned char Flags; // CPU flags + bool SoftIrq; // true when interrupted with BRK or trapped opcode + bool LastRTS; // true if RTS encountered and stack empty. + unsigned short LastAddr; // PC at the time of previous op-code + string LastInstr; // instruction and argument executed in previous step + int LastOpCode; // op-code of last instruction + unsigned short LastArg; // argument to the last instruction + int LastAddrMode; // addressing mode of last instruction +}; + +/* + * Virtual CPU, 6502 addressing modes: + + +---------------------+--------------------------+ + | mode | assembler format | + +=====================+==========================+ + | Immediate | #aa | + | Absolute | aaaa | + | Zero Page | aa | Note: + | Implied | | + | Indirect Absolute | (aaaa) | aa = 2 hex digits + | Absolute Indexed,X | aaaa,X | as $FF + | Absolute Indexed,Y | aaaa,Y | + | Zero Page Indexed,X | aa,X | aaaa = 4 hex + | Zero Page Indexed,Y | aa,Y | digits as + | Indexed Indirect | (aa,X) | $FFFF + | Indirect Indexed | (aa),Y | + | Relative | aaaa | Can also be + | Accumulator | A | assembler labels + +---------------------+--------------------------+ + +Short notation: + +imm = #$00 +zp = $00 +zpx = $00,X +zpy = $00,Y +izx = ($00,X) +izy = ($00),Y +abs = $0000 +abx = $0000,X +aby = $0000,Y +ind = ($0000) +rel = $0000 (PC-relative) + +See: 6502AssemblyInOneStep.txt for details. + + */ +enum eAddrModes { + ADDRMODE_IMM = 0, + ADDRMODE_ABS, + ADDRMODE_ZP, + ADDRMODE_IMP, + ADDRMODE_IND, + ADDRMODE_ABX, + ADDRMODE_ABY, + ADDRMODE_ZPX, + ADDRMODE_ZPY, + ADDRMODE_IZX, + ADDRMODE_IZY, + ADDRMODE_REL, + ADDRMODE_ACC, + ADDRMODE_UND, // undetermined (for some illegal codes) + ADDRMODE_LENGTH // should be always last +}; +// assumed little-endian order of bytes (start with least significant) +// MEM - memory location from where the value is read/written, +// & - reference operator (e.g.: &addr means: value under addr memory location) +// PC - program counter (PC+1 means - next memory location after opcode) +enum eOpCodes { + OPCODE_BRK = 0x00, // software interrupt, no arguments ($00 : BRK) + + /* full compatibility with 65C02 (illegal opcodes not supported, will be used for extended functions */ + OPCODE_ORA_IZX = 0x01, // bitwise OR with Accumulator, Indexed Indirect ($01 arg : ORA (arg,X) ;arg=0..$FF), MEM=&(arg+X) + OPCODE_ILL_02 = 0x02, // illegal opcode + OPCODE_ILL_03 = 0x03, // illegal opcode + OPCODE_ILL_04 = 0x04, // illegal opcode + OPCODE_ORA_ZP = 0x05, // bitwise OR with Accumulator, Zero Page ($05 arg : ORA arg ;arg=0..$FF), MEM=arg + OPCODE_ASL_ZP = 0x06, // Arithmetic Shift Left, Zero Page ($06 arg : ASL arg ;arg=0..$FF), MEM=arg + OPCODE_ILL_07 = 0x07, // illegal opcode + OPCODE_PHP = 0x08, // PusH Processor status on Stack, Implied ($08 : PHP) + OPCODE_ORA_IMM = 0x09, // bitwise OR with Accumulator, Immediate ($09 arg : ORA #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_ASL = 0x0A, // Arithmetic Shift Left, Accumulator ($0A : ASL) + OPCODE_ILL_0B = 0x0B, // illegal opcode + OPCODE_ILL_0C = 0x0C, // illegal opcode + OPCODE_ORA_ABS = 0x0D, // bitwise OR with Accumulator, Absolute ($0D addrlo addrhi : ORA addr ;addr=0..$FFFF), MEM=addr + OPCODE_ASL_ABS = 0x0E, // Arithmetic Shift Left, Absolute ($0E addrlo addrhi : ASL addr ;addr=0..$FFFF), MEM=addr + OPCODE_ILL_0F = 0x0F, // illegal opcode + OPCODE_BPL_REL = 0x10, // Branch on PLus, Relative ($10 signoffs : BPL signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + OPCODE_ORA_IZY = 0x11, // bitwise OR with Accumulator, Indirect Indexed ($11 arg : ORA (arg),Y ;arg=0..$FF), MEM=&arg+Y + OPCODE_ILL_12 = 0x12, // illegal opcode + OPCODE_ILL_13 = 0x13, // illegal opcode + OPCODE_ILL_14 = 0x14, // illegal opcode + OPCODE_ORA_ZPX = 0x15, // bitwise OR with Accumulator, Zero Page Indexed, X ($15 arg : ORA arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ASL_ZPX = 0x16, // Arithmetic Shift Left, Zero Page Indexed, X ($16 arg : ASL arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ILL_17 = 0x17, // illegal opcode + OPCODE_CLC = 0x18, // CLear Carry, Implied ($18 : CLC) + OPCODE_ORA_ABY = 0x19, // bitwise OR with Accumulator, Absolute Indexed, Y ($19 addrlo addrhi : ORA addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_ILL_1A = 0x1A, // illegal opcode + OPCODE_ILL_1B = 0x1B, // illegal opcode + OPCODE_ILL_1C = 0x1C, // illegal opcode + OPCODE_ORA_ABX = 0x1D, // bitwise OR with Accumulator, Absolute Indexed, X ($1D addrlo addrhi : ORA addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ASL_ABX = 0x1E, // Arithmetic Shift Left, Absolute Indexed, X ($1E addrlo addrhi : ASL addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ILL_1F = 0x1F, // illegal opcode + OPCODE_JSR_ABS = 0x20, // Jump to SubRoutine, Absolute ($20 addrlo addrhi : JSR addr ;addr=0..$FFFF), MEM=addr + OPCODE_AND_IZX = 0x21, // bitwise AND with accumulator, Indexed Indirect ($21 arg : AND (arg,X) ;arg=0..$FF), MEM=&(arg+X) + OPCODE_ILL_22 = 0x22, // illegal opcode + OPCODE_ILL_23 = 0x23, // illegal opcode + OPCODE_BIT_ZP = 0x24, // test BITs, Zero Page ($24 arg : BIT arg ;arg=0..$FF), MEM=arg + OPCODE_AND_ZP = 0x25, // bitwise AND with accumulator, Zero Page ($25 arg : AND arg ;arg=0..$FF), MEM=arg + OPCODE_ROL_ZP = 0x26, // ROtate Left, Zero Page ($26 arg : ROL arg ;arg=0..$FF), MEM=arg + OPCODE_ILL_27 = 0x27, // illegal opcode + OPCODE_PLP = 0x28, // PuLl Processor status, Implied ($28 : PLP) + OPCODE_AND_IMM = 0x29, // bitwise AND with accumulator, Immediate ($29 arg : AND #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_ROL = 0x2A, // ROtate Left, Accumulator ($2A : ROL) + OPCODE_ILL_2B = 0x2B, // illegal opcode + OPCODE_BIT_ABS = 0x2C, // test BITs, Absolute ($2C addrlo addrhi : BIT addr ;addr=0..$FFFF), MEM=addr + OPCODE_AND_ABS = 0x2D, // bitwise AND with accumulator, Absolute ($2D addrlo addrhi : AND addr ;addr=0..$FFFF), MEM=addr + OPCODE_ROL_ABS = 0x2E, // ROtate Left, Absolute ($2E addrlo addrhi : ROL addr ;addr=0..$FFFF), MEM=addr + OPCODE_ILL_2F = 0x2F, // illegal opcode + OPCODE_BMI_REL = 0x30, // Branch on MInus, Relative ($30 signoffs : BMI signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + OPCODE_AND_IZY = 0x31, // bitwise AND with accumulator, Indirect Indexed ($31 arg : AND (arg),Y ;arg=0..$FF), MEM=&arg+Y + OPCODE_ILL_32 = 0x32, // illegal opcode + OPCODE_ILL_33 = 0x33, // illegal opcode + OPCODE_ILL_34 = 0x34, // illegal opcode + OPCODE_AND_ZPX = 0x35, // bitwise AND with accumulator, Zero Page Indexed, X ($35 arg : AND arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ROL_ZPX = 0x36, // ROtate Left, Zero Page Indexed, X ($36 arg : ROL arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ILL_37 = 0x37, // illegal opcode + OPCODE_SEC = 0x38, // SEt Carry, Implied ($38 : SEC) + OPCODE_AND_ABY = 0x39, // bitwise AND with accumulator, Absolute Indexed, Y ($39 addrlo addrhi : AND addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_ILL_3A = 0x3A, // illegal opcode + OPCODE_ILL_3B = 0x3B, // illegal opcode + OPCODE_ILL_3C = 0x3C, // illegal opcode + OPCODE_AND_ABX = 0x3D, // bitwise AND with accumulator, Absolute Indexed, X ($3D addrlo addrhi : AND addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ROL_ABX = 0x3E, // ROtate Left, Absolute Indexed, X ($3E addrlo addrhi : ROL addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ILL_3F = 0x3F, // illegal opcode + OPCODE_RTI = 0x40, // ReTurn from Interrupt, Implied ($40 : RTI) + OPCODE_EOR_IZX = 0x41, // bitwise Exclusive OR, Indexed Indirect ($41 arg : EOR (arg,X) ;arg=0..$FF), MEM=&(arg+X) + OPCODE_ILL_42 = 0x42, // illegal opcode + OPCODE_ILL_43 = 0x43, // illegal opcode + OPCODE_ILL_44 = 0x44, // illegal opcode + OPCODE_EOR_ZP = 0x45, // bitwise Exclusive OR, Zero Page ($45 arg : EOR arg ;arg=0..$FF), MEM=arg + OPCODE_LSR_ZP = 0x46, // Logical Shift Right, Zero Page ($46 arg : LSR arg ;arg=0..$FF), MEM=arg + OPCODE_ILL_47 = 0x47, // illegal opcode + OPCODE_PHA = 0x48, // PusH Accumulator, Implied ($48 : PHA) + OPCODE_EOR_IMM = 0x49, // bitwise Exclusive OR, Immediate ($49 arg : EOR #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_LSR = 0x4A, // Logical Shift Right, Accumulator ($4A : LSR) + OPCODE_ILL_4B = 0x4B, // illegal opcode + OPCODE_JMP_ABS = 0x4C, // JuMP, Absolute ($4C addrlo addrhi : JMP addr ;addr=0..$FFFF), MEM=addr + OPCODE_EOR_ABS = 0x4D, // bitwise Exclusive OR, Absolute ($4D addrlo addrhi : EOR addr ;addr=0..$FFFF), MEM=addr + OPCODE_LSR_ABS = 0x4E, // Logical Shift Right, Absolute ($4E addrlo addrhi : LSR addr ;addr=0..$FFFF), MEM=addr + OPCODE_ILL_4F = 0x4F, // illegal opcode + OPCODE_BVC_REL = 0x50, // Branch on oVerflow Clear, Relative ($50 signoffs : BVC signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + OPCODE_EOR_IZY = 0x51, // bitwise Exclusive OR, Indirect Indexed ($51 arg : EOR (arg),Y ;arg=0..$FF), MEM=&arg+Y + OPCODE_ILL_52 = 0x52, // illegal opcode + OPCODE_ILL_53 = 0x53, // illegal opcode + OPCODE_ILL_54 = 0x54, // illegal opcode + OPCODE_EOR_ZPX = 0x55, // bitwise Exclusive OR, Zero Page Indexed, X ($55 arg : EOR arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_LSR_ZPX = 0x56, // Logical Shift Right, Zero Page Indexed, X ($56 arg : LSR arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ILL_57 = 0x57, // illegal opcode + OPCODE_CLI = 0x58, // CLear Interrupt, Implied ($58 : CLI) + OPCODE_EOR_ABY = 0x59, // bitwise Exclusive OR, Absolute Indexed, Y ($59 addrlo addrhi : EOR addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_ILL_5A = 0x5A, // illegal opcode + OPCODE_ILL_5B = 0x5B, // illegal opcode + OPCODE_ILL_5C = 0x5C, // illegal opcode + OPCODE_EOR_ABX = 0x5D, // bitwise Exclusive OR, Absolute Indexed, X ($5D addrlo addrhi : EOR addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_LSR_ABX = 0x5E, // Logical Shift Right, Absolute Indexed, X ($5E addrlo addrhi : LSR addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ILL_5F = 0x5F, // illegal opcode + OPCODE_RTS = 0x60, // ReTurn from Subroutine, Implied ($60 : RTS) + OPCODE_ADC_IZX = 0x61, // ADd with Carry, Indexed Indirect ($61 arg : ADC (arg,X) ;arg=0..$FF), MEM=&(arg+X) + OPCODE_ILL_62 = 0x62, // illegal opcode + OPCODE_ILL_63 = 0x63, // illegal opcode + OPCODE_ILL_64 = 0x64, // illegal opcode + OPCODE_ADC_ZP = 0x65, // ADd with Carry, Zero Page ($65 arg : ADC arg ;arg=0..$FF), MEM=arg + OPCODE_ROR_ZP = 0x66, // ROtate Right, Zero Page ($66 arg : ROR arg ;arg=0..$FF), MEM=arg + OPCODE_ILL_67 = 0x67, // illegal opcode + OPCODE_PLA = 0x68, // PuLl Accumulator, Implied ($68 : PLA) + OPCODE_ADC_IMM = 0x69, // ADd with Carry, Immediate ($69 arg : ADC #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_ROR = 0x6A, // ROtate Right, Accumulator ($6A : ROR) + OPCODE_ILL_6B = 0x6B, // illegal opcode + OPCODE_JMP_IND = 0x6C, // JuMP, Indirect Absolute ($6C addrlo addrhi : JMP (addr) ;addr=0..FFFF), MEM=&addr + OPCODE_ADC_ABS = 0x6D, // ADd with Carry, Absolute ($6D addrlo addrhi : ADC addr ;addr=0..$FFFF), MEM=addr + OPCODE_ROR_ABS = 0x6E, // ROtate Right, Absolute ($6E addrlo addrhi : ROR addr ;addr=0..$FFFF), MEM=addr + OPCODE_ILL_6F = 0x6F, // illegal opcode + OPCODE_BVS_REL = 0x70, // Branch on oVerflow Set, Relative ($70 signoffs : BVS signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + OPCODE_ADC_IZY = 0x71, // ADd with Carry, Indirect Indexed ($71 arg : ADC (arg),Y ;arg=0..$FF), MEM=&arg+Y + OPCODE_ILL_72 = 0x72, // illegal opcode + OPCODE_ILL_73 = 0x73, // illegal opcode + OPCODE_ILL_74 = 0x74, // illegal opcode + OPCODE_ADC_ZPX = 0x75, // ADd with Carry, Zero Page Indexed, X ($75 arg : ADC arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ROR_ZPX = 0x76, // ROtate Right, Zero Page Indexed, X ($76 arg : ROR arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ILL_77 = 0x77, // illegal opcode + OPCODE_SEI = 0x78, // SEt Interrupt, Implied ($78 : SEI) + OPCODE_ADC_ABY = 0x79, // ADd with Carry, Absolute Indexed, Y ($79 addrlo addrhi : ADC addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_ILL_7A = 0x7A, // illegal opcode + OPCODE_ILL_7B = 0x7B, // illegal opcode + OPCODE_ILL_7C = 0x7C, // illegal opcode + OPCODE_ADC_ABX = 0x7D, // ADd with Carry, Absolute Indexed, X ($7D addrlo addrhi : ADC addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ROR_ABX = 0x7E, // ROtate Right, Absolute Indexed, X ($7E addrlo addrhi : ROR addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ILL_7F = 0x7F, // illegal opcode + OPCODE_ILL_80 = 0x80, // illegal opcode + OPCODE_STA_IZX = 0x81, // STore Accumulator, Indexed Indirect ($81 arg : STA (arg,X) ;arg=0..$FF), MEM=&(arg+X) + OPCODE_ILL_82 = 0x82, // illegal opcode + OPCODE_ILL_83 = 0x83, // illegal opcode + OPCODE_STY_ZP = 0x84, // STore Y register, Zero Page ($84 arg : STY arg ;arg=0..$FF), MEM=arg + OPCODE_STA_ZP = 0x85, // STore Accumulator, Zero Page ($85 arg : STA arg ;arg=0..$FF), MEM=arg + OPCODE_STX_ZP = 0x86, // STore X register, Zero Page ($86 arg : STX arg ;arg=0..$FF), MEM=arg + OPCODE_ILL_87 = 0x87, // illegal opcode + OPCODE_DEY = 0x88, // DEcrement Y, Implied ($88 : DEY) + OPCODE_ILL_89 = 0x89, // illegal opcode + OPCODE_TXA = 0x8A, // Transfer X to A, Implied ($8A : TXA) + OPCODE_ILL_8B = 0x8B, // illegal opcode + OPCODE_STY_ABS = 0x8C, // STore Y register, Absolute ($8C addrlo addrhi : STY addr ;addr=0..$FFFF), MEM=addr + OPCODE_STA_ABS = 0x8D, // STore Accumulator, Absolute ($8D addrlo addrhi : STA addr ;addr=0..$FFFF), MEM=addr + OPCODE_STX_ABS = 0x8E, // STore X register, Absolute ($8E addrlo addrhi : STX addr ;addr=0..$FFFF), MEM=addr + OPCODE_ILL_8F = 0x8F, // illegal opcode + OPCODE_BCC_REL = 0x90, // Branch on Carry Clear, Relative ($90 signoffs : BCC signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + OPCODE_STA_IZY = 0x91, // STore Accumulator, Indirect Indexed ($91 arg : STA (arg),Y ;arg=0..$FF), MEM=&arg+Y + OPCODE_ILL_92 = 0x92, // illegal opcode + OPCODE_ILL_93 = 0x93, // illegal opcode + OPCODE_STY_ZPX = 0x94, // STore Y register, Zero Page Indexed, X ($94 arg : STY arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_STA_ZPX = 0x95, // STore Accumulator, Zero Page Indexed, X ($95 arg : STA arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_STX_ZPY = 0x96, // STore X register, Zero Page Indexed, Y ($96 arg : STX arg,Y ;arg=0..$FF), MEM=arg+Y + OPCODE_ILL_97 = 0x97, // illegal opcode + OPCODE_TYA = 0x98, // Transfer Y to A, Implied ($98 : TYA) + OPCODE_STA_ABY = 0x99, // STore Accumulator, Absolute Indexed, Y ($99 addrlo addrhi : STA addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_TXS = 0x9A, // Transfer X to Stack ptr, Implied ($9A : TXS) + OPCODE_ILL_9B = 0x9B, // illegal opcode + OPCODE_ILL_9C = 0x9C, // illegal opcode + OPCODE_STA_ABX = 0x9D, // STore Accumulator, Absolute Indexed, X ($9D addrlo addrhi : STA addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ILL_9E = 0x9E, // illegal opcode + OPCODE_ILL_9F = 0x9F, // illegal opcode + OPCODE_LDY_IMM = 0xA0, // LoaD Y register, Immediate ($A0 arg : LDY #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_LDA_IZX = 0xA1, // LoaD Accumulator, Indexed Indirect ($A1 arg : LDA (arg,X) ;arg=0..$FF), MEM=&(arg+X) + OPCODE_LDX_IMM = 0xA2, // LoaD X register, Immediate ($A2 arg : LDX #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_ILL_A3 = 0xA3, // illegal opcode + OPCODE_LDY_ZP = 0xA4, // LoaD Y register, Zero Page ($A4 arg : LDY arg ;arg=0..$FF), MEM=arg + OPCODE_LDA_ZP = 0xA5, // LoaD Accumulator, Zero Page ($A5 arg : LDA arg ;arg=0..$FF), MEM=arg + OPCODE_LDX_ZP = 0xA6, // LoaD X register, Zero Page ($A6 arg : LDX arg ;arg=0..$FF), MEM=arg + OPCODE_ILL_A7 = 0xA7, // illegal opcode + OPCODE_TAY = 0xA8, // Transfer A to Y, Implied ($A8 : TAY) + OPCODE_LDA_IMM = 0xA9, // LoaD Accumulator, Immediate ($A9 arg : LDA #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_TAX = 0xAA, // Transfer A to X, Implied ($AA : TAX) + OPCODE_ILL_AB = 0xAB, // illegal opcode + OPCODE_LDY_ABS = 0xAC, // LoaD Y register, Absolute ($AC addrlo addrhi : LDY addr ;addr=0..$FFFF), MEM=addr + OPCODE_LDA_ABS = 0xAD, // LoaD Accumulator, Absolute ($AD addrlo addrhi : LDA addr ;addr=0..$FFFF), MEM=addr + OPCODE_LDX_ABS = 0xAE, // LoaD X register, Absolute ($AE addrlo addrhi : LDX addr ;addr=0..$FFFF), MEM=addr + OPCODE_ILL_AF = 0xAF, // illegal opcode + OPCODE_BCS_REL = 0xB0, // Branch on Carry Set, Relative ($B0 signoffs : BCS signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + OPCODE_LDA_IZY = 0xB1, // LoaD Accumulator, Indirect Indexed ($B1 arg : LDA (arg),Y ;arg=0..$FF), MEM=&arg+Y + OPCODE_ILL_B2 = 0xB2, // illegal opcode + OPCODE_ILL_B3 = 0xB3, // illegal opcode + OPCODE_LDY_ZPX = 0xB4, // LoaD Y register, Zero Page Indexed, X ($B4 arg : LDY arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_LDA_ZPX = 0xB5, // LoaD Accumulator, Zero Page Indexed, X ($B5 arg : LDA arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_LDX_ZPY = 0xB6, // LoaD X register, Zero Page Indexed, Y ($B6 arg : LDX arg,Y ;arg=0..$FF), MEM=arg+Y + OPCODE_ILL_B7 = 0xB7, // illegal opcode + OPCODE_CLV = 0xB8, // CLear oVerflow, Implied ($B8 : CLV) + OPCODE_LDA_ABY = 0xB9, // LoaD Accumulator, Absolute Indexed, Y ($B9 addrlo addrhi : LDA addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_TSX = 0xBA, // Transfer Stack ptr to X, Implied ($BA : TSX) + OPCODE_ILL_BB = 0xBB, // illegal opcode + OPCODE_LDY_ABX = 0xBC, // LoaD Y register, Absolute Indexed, X ($BC addrlo addrhi : LDY addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_LDA_ABX = 0xBD, // LoaD Accumulator, Absolute Indexed, X ($BD addrlo addrhi : LDA addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_LDX_ABY = 0xBE, // LoaD X register, Absolute Indexed, Y ($BE addrlo addrhi : LDX addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_ILL_BF = 0xBF, // illegal opcode + OPCODE_CPY_IMM = 0xC0, // ComPare Y register, Immediate ($C0 arg : CPY #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_CMP_IZX = 0xC1, // CoMPare accumulator, Indexed Indirect ($A1 arg : LDA (arg,X) ;arg=0..$FF), MEM=&(arg+X) + OPCODE_ILL_C2 = 0xC2, // illegal opcode + OPCODE_ILL_C3 = 0xC3, // illegal opcode + OPCODE_CPY_ZP = 0xC4, // ComPare Y register, Zero Page ($C4 arg : CPY arg ;arg=0..$FF), MEM=arg + OPCODE_CMP_ZP = 0xC5, // CoMPare accumulator, Zero Page ($C5 arg : CMP arg ;arg=0..$FF), MEM=arg + OPCODE_DEC_ZP = 0xC6, // DECrement memory, Zero Page ($C6 arg : DEC arg ;arg=0..$FF), MEM=arg + OPCODE_ILL_C7 = 0xC7, // illegal opcode + OPCODE_INY = 0xC8, // INcrement Y, Implied ($C8 : INY)OPCODE_INY = 0xC8, // INcrement Y, Implied ($C8 : INY) + OPCODE_CMP_IMM = 0xC9, // CoMPare accumulator, Immediate ($C9 arg : CMP #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_DEX = 0xCA, // DEcrement X, Implied ($CA : DEX) + OPCODE_ILL_CB = 0xCB, // illegal opcode + OPCODE_CPY_ABS = 0xCC, // ComPare Y register, Absolute ($CC addrlo addrhi : CPY addr ;addr=0..$FFFF), MEM=addr + OPCODE_CMP_ABS = 0xCD, // CoMPare accumulator, Absolute ($CD addrlo addrhi : CMP addr ;addr=0..$FFFF), MEM=addr + OPCODE_DEC_ABS = 0xCE, // DECrement memory, Absolute ($CE addrlo addrhi : CMP addr ;addr=0..$FFFF), MEM=addr + OPCODE_ILL_CF = 0xCF, // illegal opcode + OPCODE_BNE_REL = 0xD0, // Branch on Not Equal, Relative ($D0 signoffs : BNE signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + OPCODE_CMP_IZY = 0xD1, // CoMPare accumulator, Indirect Indexed ($D1 arg : CMP (arg),Y ;arg=0..$FF), MEM=&arg+Y + OPCODE_ILL_D2 = 0xD2, // illegal opcode + OPCODE_ILL_D3 = 0xD3, // illegal opcode + OPCODE_ILL_D4 = 0xD4, // illegal opcode + OPCODE_CMP_ZPX = 0xD5, // CoMPare accumulator, Zero Page Indexed, X ($D5 arg : CMP arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_DEC_ZPX = 0xD6, // DECrement memory, Zero Page Indexed, X ($D6 arg : DEC arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ILL_D7 = 0xD7, // illegal opcode + OPCODE_CLD = 0xD8, // CLear Decimal, Implied ($D8 : CLD) + OPCODE_CMP_ABY = 0xD9, // CoMPare accumulator, Absolute Indexed, Y ($D9 addrlo addrhi : CMP addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_ILL_DA = 0xDA, // illegal opcode + OPCODE_ILL_DB = 0xDB, // illegal opcode + OPCODE_ILL_DC = 0xDC, // illegal opcode + OPCODE_CMP_ABX = 0xDD, // CoMPare accumulator, Absolute Indexed, X ($DD addrlo addrhi : CMP addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_DEC_ABX = 0xDE, // DECrement memory, Absolute Indexed, X ($DE addrlo addrhi : DEC addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ILL_DF = 0xDF, // illegal opcode + OPCODE_CPX_IMM = 0xE0, // ComPare X register, Immediate ($E0 arg : CPX #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_SBC_IZX = 0xE1, // SuBtract with Carry, Indexed Indirect ($E1 arg : SBC (arg,X) ;arg=0..$FF), MEM=&(arg+X) + OPCODE_ILL_E2 = 0xE2, // illegal opcode + OPCODE_ILL_E3 = 0xE3, // illegal opcode + OPCODE_CPX_ZP = 0xE4, // ComPare X register, Zero Page ($E4 arg : CPX arg ;arg=0..$FF), MEM=arg + OPCODE_SBC_ZP = 0xE5, // SuBtract with Carry, Zero Page ($E5 arg : SBC arg ;arg=0..$FF), MEM=arg + OPCODE_INC_ZP = 0xE6, // INCrement memory, Zero Page ($E6 arg : INC arg ;arg=0..$FF), MEM=arg + OPCODE_ILL_E7 = 0xE7, // illegal opcode + OPCODE_INX = 0xE8, // INcrement X, Implied ($E8 : INX) + OPCODE_SBC_IMM = 0xE9, // SuBtract with Carry, Immediate ($E9 arg : SBC #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_NOP = 0xEA, // NO oPeration, Implied ($EA : NOP) + OPCODE_ILL_EB = 0xEB, // illegal opcode + OPCODE_CPX_ABS = 0xEC, // ComPare X register, Absolute ($EC addrlo addrhi : CPX addr ;addr=0..$FFFF), MEM=addr + OPCODE_SBC_ABS = 0xED, // SuBtract with Carry, Absolute ($ED addrlo addrhi : SBC addr ;addr=0..$FFFF), MEM=addr + OPCODE_INC_ABS = 0xEE, // INCrement memory, Absolute ($EE addrlo addrhi : INC addr ;addr=0..$FFFF), MEM=addr + OPCODE_ILL_EF = 0xEF, // illegal opcode + OPCODE_BEQ_REL = 0xF0, // Branch on EQual, Relative ($F0 signoffs : BEQ signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + OPCODE_SBC_IZY = 0xF1, // SuBtract with Carry, Indirect Indexed ($F1 arg : SBC (arg),Y ;arg=0..$FF), MEM=&arg+Y + OPCODE_ILL_F2 = 0xF2, // illegal opcode + OPCODE_ILL_F3 = 0xF3, // illegal opcode + OPCODE_ILL_F4 = 0xF4, // illegal opcode + OPCODE_SBC_ZPX = 0xF5, // SuBtract with Carry, Zero Page Indexed, X ($F5 arg : SBC arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_INC_ZPX = 0xF6, // INCrement memory, Zero Page Indexed, X ($F6 arg : INC arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ILL_F7 = 0xF7, // illegal opcode + OPCODE_SED = 0xF8, // SEt Decimal, Implied ($F8 : SED) + OPCODE_SBC_ABY = 0xF9, // SuBtract with Carry, Absolute Indexed, Y ($F9 addrlo addrhi : SBC addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_ILL_FA = 0xFA, // illegal opcode + OPCODE_ILL_FB = 0xFB, // illegal opcode + OPCODE_ILL_FC = 0xFC, // illegal opcode + OPCODE_SBC_ABX = 0xFD, // SuBtract with Carry, Absolute Indexed, X ($FD addrlo addrhi : SBC addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_INC_ABX = 0xFE, // INCrement memory, Absolute Indexed, X ($FE addrlo addrhi : INC addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ILL_FF = 0xFF // illegal opcode +}; + +struct OpCode { + int code; // the byte value of the opcode + int addrmode; // addressing mode (see eAddrModes) + int time; // # of cycles + string amf; // assembler mnemonic +}; + +typedef map OpCodesMap; + +/* + *------------------------------------------------------------------------------ + bit -> 7 0 + +---+---+---+---+---+---+---+---+ + | N | V | | B | D | I | Z | C | <-- flag, 0/1 = reset/set + +---+---+---+---+---+---+---+---+ + + + N = NEGATIVE. Set if bit 7 of the accumulator is set. + + V = OVERFLOW. Set if the addition of two like-signed numbers or the + subtraction of two unlike-signed numbers produces a result + greater than +127 or less than -128. + + B = BRK COMMAND. Set if an interrupt caused by a BRK, reset if + caused by an external interrupt. + + D = DECIMAL MODE. Set if decimal mode active. + + I = IRQ DISABLE. Set if maskable interrupts are disabled. + + Z = ZERO. Set if the result of the last operation (load/inc/dec/ + add/sub) was zero. + + C = CARRY. Set if the add produced a carry, or if the subtraction + produced a borrow. Also holds bits after a logical shift. + *------------------------------------------------------------------------------ + */ +enum eCpuFlagMasks { + FLAGS_CARRY = 0x01, // 0: C + FLAGS_ZERO = 0x02, // 1: Z + FLAGS_IRQ = 0x04, // 2: I + FLAGS_DEC = 0x08, // 3: D + FLAGS_BRK = 0x10, // 4: B (Clear if interrupt vectoring, set if BRK or PHP) + FLAGS_UNUSED = 0x20, // 5: Unused flag (always set). + FLAGS_OVERFLOW = 0x40, // 6: V + FLAGS_SIGN = 0x80 // 7: N +}; + +enum eLogicOps { + LOGOP_OR, + LOGOP_AND, + LOGOP_EOR +}; + +class MKCpu +{ + public: + + MKCpu(); + MKCpu(Memory *pmem); + ~MKCpu(); + + Regs *ExecOpcode(unsigned short memaddr); + Regs *GetRegs(); + queue GetExecHistory(); + unsigned short Disassemble(unsigned short addr, + char *instrbuf); // Disassemble instruction in memory, return next instruction addr. + + protected: + + private: + + struct Regs mReg; // CPU registers + Memory *mpMem; // pointer to memory object + bool mLocalMem; // true - memory locally allocated + OpCodesMap mOpCodesMap; // hash table of all opcodes + int mAddrModesLen[ADDRMODE_LENGTH]; // array of instructions lengths per addressing mode + string mArgFmtTbl[ADDRMODE_LENGTH]; // array of instructions assembly formats per addressing mode + queue mExecHistory; // history of last 20 op-codes with arguments and registers statuses + + + void InitCpu(); + void SetFlags(unsigned char reg); // set CPU flags ZERO and SIGN based on Acc, X or Y + unsigned char ShiftLeft(unsigned char arg8); // Arithmetic Shift Left, set Carry flag + unsigned char ShiftRight(unsigned char arg8); // Logical Shift Right, update flags NZC. + unsigned char RotateLeft(unsigned char arg8); // Rotate left, Carry to bit 0, bit 7 to Carry, update flags N and Z. + unsigned char RotateRight(unsigned char arg8); // Rotate left, Carry to bit 7, bit 0 to Carry, update flags N and Z. + unsigned short GetArg16(unsigned char offs); // Get 2-byte argument, add offset, increase PC. + void LogicOpAcc(unsigned short addr, int logop); // Perform logical bitwise operation between memory location and Acc. + // Result in Acc. Set flags. + unsigned short ComputeRelJump(unsigned char offs); // Compute new PC based on relative offset. + unsigned short ComputeRelJump(unsigned short addr, + unsigned char offs); // Compute new address after branch based on relative offset. + unsigned char Conv2Bcd(unsigned short v); // Convert number to BCD representation. + unsigned short Bcd2Num(unsigned char v); // Convert BCD code to number. + bool CheckFlag(unsigned char flag); // Return true if given CPU status flag is set, false otherwise. + void SetFlag(bool set, unsigned char flag); // Set or unset processor status flag. + unsigned char AddWithCarry(unsigned char mem8); // Add With Carry, update flags and Acc. + unsigned char SubWithCarry(unsigned char mem8); // Subtract With Carry, update flags and Acc. + unsigned short GetAddrWithMode(int mode); // Get address of the byte argument with specified addr. mode + unsigned short GetArgWithMode(unsigned short opcaddr, + int mode); // Get argument from address with specified addr. mode + unsigned short Disassemble(); // Disassemble instruction and argument per addressing mode + void Add2History(string s); // add entry to op-codes execute history +}; + +} // namespace MKBasic + +#endif diff --git a/MKGenException.cpp b/MKGenException.cpp index 2ab9ac3..0686d2f 100644 --- a/MKGenException.cpp +++ b/MKGenException.cpp @@ -1,20 +1,20 @@ -#include "MKGenException.h" - -namespace MKBasic { - -MKGenException::MKGenException() -{ - msCause = "Ouch!"; -} - -MKGenException::MKGenException(string cause) -{ - msCause = cause; -} - -string MKGenException::GetCause() -{ - return msCause; -} - -} // namespace MKBasic +#include "MKGenException.h" + +namespace MKBasic { + +MKGenException::MKGenException() +{ + msCause = "Ouch!"; +} + +MKGenException::MKGenException(string cause) +{ + msCause = cause; +} + +string MKGenException::GetCause() +{ + return msCause; +} + +} // namespace MKBasic diff --git a/MKGenException.h b/MKGenException.h index ce10000..ae53913 100644 --- a/MKGenException.h +++ b/MKGenException.h @@ -1,23 +1,24 @@ -#ifndef MKGENEXCEPTION_H -#define MKGENEXCEPTION_H - -#include -#include - -using namespace std; - -namespace MKBasic { - -class MKGenException : public exception { - public: - MKGenException(); - MKGenException(string cause); - string GetCause(); - - private: - string msCause; -}; - -} // namespace MKBasic - -#endif +#ifndef MKGENEXCEPTION_H +#define MKGENEXCEPTION_H + +#include +#include + +using namespace std; + +namespace MKBasic { + +class MKGenException : public exception { + public: + MKGenException(); + MKGenException(string cause); + ~MKGenException() throw() {}; + string GetCause(); + + private: + string msCause; +}; + +} // namespace MKBasic + +#endif diff --git a/Makefile.win b/Makefile.win new file mode 100644 index 0000000..29fd844 --- /dev/null +++ b/Makefile.win @@ -0,0 +1,46 @@ +# Project: MKBasic +# Makefile created by Dev-C++ 5.11 + +CPP = g++.exe -D__DEBUG__ +CC = gcc.exe -D__DEBUG__ +WINDRES = windres.exe +OBJ = main.o VMachine.o MKBasic.o MKCpu.o Memory.o Display.o MKGenException.o +LINKOBJ = main.o VMachine.o MKBasic.o MKCpu.o Memory.o Display.o MKGenException.o +LIBS = -L"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib32" -L"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib32" -static-libgcc -m32 -g3 +INCS = -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include" +CXXINCS = -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include/c++" +BIN = MKBasic.exe +CXXFLAGS = $(CXXINCS) -m32 -std=c++11 -Wall -Wextra -pedantic -g3 +CFLAGS = $(INCS) -m32 -std=c++11 -Wall -Wextra -pedantic -g3 +RM = rm.exe -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before $(BIN) all-after + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +$(BIN): $(OBJ) + $(CPP) $(LINKOBJ) -o $(BIN) $(LIBS) + +main.o: main.cpp + $(CPP) -c main.cpp -o main.o $(CXXFLAGS) + +VMachine.o: VMachine.cpp + $(CPP) -c VMachine.cpp -o VMachine.o $(CXXFLAGS) + +MKBasic.o: MKBasic.cpp + $(CPP) -c MKBasic.cpp -o MKBasic.o $(CXXFLAGS) + +MKCpu.o: MKCpu.cpp + $(CPP) -c MKCpu.cpp -o MKCpu.o $(CXXFLAGS) + +Memory.o: Memory.cpp + $(CPP) -c Memory.cpp -o Memory.o $(CXXFLAGS) + +Display.o: Display.cpp + $(CPP) -c Display.cpp -o Display.o $(CXXFLAGS) + +MKGenException.o: MKGenException.cpp + $(CPP) -c MKGenException.cpp -o MKGenException.o $(CXXFLAGS) diff --git a/Memory.cpp b/Memory.cpp index b9c56d0..2ea11f7 100644 --- a/Memory.cpp +++ b/Memory.cpp @@ -1,310 +1,463 @@ -#include "Memory.h" -#include -#include - -//#define DBG 1 -#if defined (DBG) -#include -using namespace std; -#endif - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ - -namespace MKBasic { - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -Memory::Memory() -{ - Initialize(); -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -Memory::~Memory() -{ -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void Memory::Initialize() -{ - unsigned short addr = 0; - for (int i=0; i < 0xFFFF; i++) { - m8bitMem[addr++] = 0; - } - mCharIOAddr = CHARIO_ADDR; - mCharIOActive = false; - mIOEcho = false; - mInBufDataBegin = mInBufDataEnd = 0; - mOutBufDataBegin = mOutBufDataEnd = 0; - mROMBegin = ROM_BEGIN; - mROMEnd = ROM_END; - mROMActive = false; -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void Memory::EnableROM() -{ - mROMActive = true; -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void Memory::EnableROM(unsigned short start, unsigned short end) -{ - if (mROMEnd > mROMBegin) { - mROMBegin = start; - mROMEnd = end; - } - EnableROM(); -} - -/* - *-------------------------------------------------------------------- - * Method: ReadCharKb() - * Purpose: If char I/O active, read character from console - * (non-blocking) and put in an input FIFO buffer. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -unsigned char Memory::ReadCharKb() -{ - unsigned char ret = 0; - if (mCharIOActive) { - int c; - putchar('?'); - while(!kbhit()); - c = getch(); - if (mIOEcho) putchar(c); - mCharIOBufIn[mInBufDataEnd] = c; - mInBufDataEnd++; - if (mInBufDataEnd >= CHARIO_BUF_SIZE) mInBufDataEnd = 0; - ret = c; - } - return ret; -} - -/* - *-------------------------------------------------------------------- - * Method: GetCharIn() - * Purpose: Return character from the emulated character I/O FIFO - * input buffer or -1 if FIFO empty or char I/O not active. - * Arguments: n/a - * Returns: character - *-------------------------------------------------------------------- - */ -char Memory::GetCharIn() -{ - char ret = -1; - if (mCharIOActive) { - if (mInBufDataEnd != mInBufDataBegin) { - ret = mCharIOBufIn[mInBufDataBegin]; - mInBufDataBegin++; - if (mInBufDataBegin >= CHARIO_BUF_SIZE) mInBufDataBegin = 0; - } - } - return ret; -} - -/* - *-------------------------------------------------------------------- - * Method: GetCharOut() - * Purpose: Return character from the emulated character I/O FIFO - * output buffer or -1 if FIFO empty or char I/O not - * active. - * Arguments: n/a - * Returns: character - *-------------------------------------------------------------------- - */ -char Memory::GetCharOut() -{ - char ret = -1; - if (mCharIOActive) { - if (mOutBufDataEnd != mOutBufDataBegin) { - ret = mCharIOBufOut[mOutBufDataBegin]; - mOutBufDataBegin++; - if (mOutBufDataBegin >= CHARIO_BUF_SIZE) mOutBufDataBegin = 0; - } - } - return ret; -} - -/* - *-------------------------------------------------------------------- - * Method: PutCharIO() - * Purpose: Put character in the output char I/O FIFO buffer. - * Arguments: c - character - * Returns: n/a - *-------------------------------------------------------------------- - */ -void Memory::PutCharIO(char c) -{ - if (mCharIOActive) { - mCharIOBufOut[mOutBufDataEnd] = c; - mOutBufDataEnd++; - if (mOutBufDataEnd >= CHARIO_BUF_SIZE) mOutBufDataEnd = 0; - } -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -unsigned char Memory::Peek8bit(unsigned short addr) -{ - if (mCharIOActive && addr == mCharIOAddr) { -#if defined (DBG) - cout << "DBG: Peek8bit($" << hex << addr << ") BEFORE ReadCharKb()" << endl; - cout << "DBG: m8bitMem[$" << hex << addr << "] = $" << hex << (unsigned short)m8bitMem[addr] << endl; - for (unsigned int a = 0xFFF0; a < 0x10000; a++) { - cout << "DBG: m8bitMem[$" << hex << a << "] = $" << hex << (unsigned short)m8bitMem[a] << endl; - } -#endif - m8bitMem[addr] = ReadCharKb(); -#if defined (DBG) - cout << "************************" << endl; - cout << "DBG: Peek8bit($" << hex << addr << ") AFTER ReadCharKb()" << endl; - cout << "DBG: m8bitMem[$" << hex << addr << "] = $" << hex << (unsigned short)m8bitMem[addr] << endl; - for (unsigned int a = 0xFFF0; a < 0x10000; a++) { - cout << "DBG: m8bitMem[$" << hex << a << "] = $" << hex << (unsigned short)m8bitMem[a] << endl; - } -#endif - } - - return m8bitMem[addr]; -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -unsigned short Memory::Peek16bit(unsigned short addr) -{ - unsigned short ret = 0; - - if (mCharIOActive && addr == mCharIOAddr) { -#if defined (DBG) - cout << "DBG: Peek16bit(" << addr << ")" << endl; -#endif - m8bitMem[addr] = ReadCharKb(); - } - - ret = m8bitMem[addr++]; - ret += m8bitMem[addr] * 256; - - return ret; -} - -/* - *-------------------------------------------------------------------- - * Method: Poke8bit() - * Purpose: Write byte to specified memory location. - * If the memory location is mapped to character I/O, - * write value to output buffer and memory location. - * If the memory location is protected (ROM), do not - * write the value. - * Arguments: addr - (0x0000..0xffff) memory address, - * val - value (0x00..0xff) - * Returns: n/a - *-------------------------------------------------------------------- - */ -void Memory::Poke8bit(unsigned short addr, unsigned char val) -{ - if (mCharIOActive && addr == mCharIOAddr) - PutCharIO(val); - if (!mROMActive || (addr < ROM_BEGIN || addr > ROM_END)) { - m8bitMem[addr] = val; - } -} - -/* - *-------------------------------------------------------------------- - * Method: SetCharIO() - * Purpose: Activates and sets an address of basic character I/O - * emulation (console). - * Arguments: addr - address of I/O area (0x0000..0xFFFF) - * Returns: n/a - *-------------------------------------------------------------------- - */ -void Memory::SetCharIO(unsigned short addr, bool echo) -{ - mCharIOAddr = addr; - mCharIOActive = true; - mIOEcho = echo; -} - -/* - *-------------------------------------------------------------------- - * Method: DisableCharIO() - * Purpose: Deactivates basic character I/O emulation (console). - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void Memory::DisableCharIO() -{ - mCharIOActive = false; -} - -/* - *-------------------------------------------------------------------- - * Method: GetCharIOAddr() - * Purpose: Returns current address of basic character I/O area. - * Arguments: n/a - * Returns: address of I/O area - *-------------------------------------------------------------------- - */ -unsigned short Memory::GetCharIOAddr() -{ - return mCharIOAddr; -} - -} // namespace MKBasic + +#include "Memory.h" + +#include +#include +#if defined(WINDOWS) +#include +#endif + +//#define DBG 1 +#if defined (DBG) +#include +using namespace std; +#endif + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ + +namespace MKBasic { + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +Memory::Memory() +{ + Initialize(); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +Memory::~Memory() +{ +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void Memory::Initialize() +{ + unsigned short addr = 0; + for (int i=0; i < 0xFFFF; i++) { + m8bitMem[addr++] = 0; + } + mCharIOAddr = CHARIO_ADDR; + mCharIOActive = false; + mIOEcho = false; + mInBufDataBegin = mInBufDataEnd = 0; + mOutBufDataBegin = mOutBufDataEnd = 0; + mROMBegin = ROM_BEGIN; + mROMEnd = ROM_END; + mROMActive = false; +} + +#if defined(LINUX) +#include +#include +#include + +struct termios orig_termios; + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void reset_terminal_mode() +{ + tcsetattr(0, TCSANOW, &orig_termios); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void Memory::set_conio_terminal_mode() +{ + struct termios new_termios; + + /* take two copies - one for now, one for later */ + tcgetattr(0, &orig_termios); + memcpy(&new_termios, &orig_termios, sizeof(new_termios)); + + /* register cleanup handler, and set the new terminal mode */ + atexit(reset_terminal_mode); + cfmakeraw(&new_termios); + tcsetattr(0, TCSANOW, &new_termios); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +int Memory::kbhit() +{ + struct timeval tv = { 0L, 0L }; + fd_set fds; + FD_ZERO(&fds); + FD_SET(0, &fds); + return select(1, &fds, NULL, NULL, &tv); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +int Memory::getch() +{ + int r; + unsigned char c; + if ((r = read(0, &c, sizeof(c))) < 0) { + return r; + } else { + return c; + } +} +#endif + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void Memory::EnableROM() +{ + mROMActive = true; +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void Memory::DisableROM() +{ + mROMActive = false; +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void Memory::SetROM(unsigned short start, unsigned short end) +{ + if (mROMEnd > mROMBegin) { + mROMBegin = start; + mROMEnd = end; + } +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void Memory::EnableROM(unsigned short start, unsigned short end) +{ + SetROM(start,end); + EnableROM(); +} + +/* + *-------------------------------------------------------------------- + * Method: ReadCharKb() + * Purpose: If char I/O active, read character from console + * (non-blocking) and put in an input FIFO buffer. + * Arguments: nonblock - if true, works in non-blocking mode + * Returns: n/a + *-------------------------------------------------------------------- + */ +unsigned char Memory::ReadCharKb(bool nonblock) +{ + unsigned char ret = 0; + if (mCharIOActive) { +#if defined(LINUX) + set_conio_terminal_mode(); +#endif + static int c = ' '; + putchar('\n'); + if (mIOEcho && isprint(c)) putchar(c); + else putchar(' '); + fputs("<-Character Input (CTRL-Y to BREAK) ?\r",stdout); + fflush(stdout); + if (!nonblock) while(!kbhit()); + else c = 0; + c = getch(); +#if defined(LINUX) + if (c == 3) { // capture CTRL-C in CONIO mode + reset_terminal_mode(); + kill(getpid(),SIGINT); + } +#endif + fputs(" \r",stdout); + fflush(stdout); + mCharIOBufIn[mInBufDataEnd] = c; + mInBufDataEnd++; + if (mInBufDataEnd >= CHARIO_BUF_SIZE) mInBufDataEnd = 0; + ret = c; +#if defined(LINUX) + reset_terminal_mode(); +#endif + } + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: GetCharIn() + * Purpose: Return character from the emulated character I/O FIFO + * input buffer or -1 if FIFO empty or char I/O not active. + * Arguments: n/a + * Returns: character + *-------------------------------------------------------------------- + */ +char Memory::GetCharIn() +{ + char ret = -1; + if (mCharIOActive) { + if (mInBufDataEnd != mInBufDataBegin) { + ret = mCharIOBufIn[mInBufDataBegin]; + mInBufDataBegin++; + if (mInBufDataBegin >= CHARIO_BUF_SIZE) mInBufDataBegin = 0; + } + } + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: GetCharOut() + * Purpose: Return character from the emulated character I/O FIFO + * output buffer or -1 if FIFO empty or char I/O not + * active. + * Arguments: n/a + * Returns: character + *-------------------------------------------------------------------- + */ +char Memory::GetCharOut() +{ + char ret = -1; + if (mCharIOActive) { + if (mOutBufDataEnd != mOutBufDataBegin) { + ret = mCharIOBufOut[mOutBufDataBegin]; + mOutBufDataBegin++; + if (mOutBufDataBegin >= CHARIO_BUF_SIZE) mOutBufDataBegin = 0; + } + } + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: PutCharIO() + * Purpose: Put character in the output char I/O FIFO buffer. + * Arguments: c - character + * Returns: n/a + *-------------------------------------------------------------------- + */ +void Memory::PutCharIO(char c) +{ + if (mCharIOActive) { + mCharIOBufOut[mOutBufDataEnd] = c; + mOutBufDataEnd++; + if (mOutBufDataEnd >= CHARIO_BUF_SIZE) mOutBufDataEnd = 0; + } +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +unsigned char Memory::Peek8bit(unsigned short addr) +{ + if (mCharIOActive && addr == mCharIOAddr) { + m8bitMem[addr] = ReadCharKb(false); // blocking mode input + } else if (mCharIOActive && addr == mCharIOAddr+1) { + m8bitMem[addr] = ReadCharKb(true); // non-blocking mode input + } + + return m8bitMem[addr]; +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +unsigned short Memory::Peek16bit(unsigned short addr) +{ + unsigned short ret = 0; + + if (mCharIOActive && addr == mCharIOAddr) { + m8bitMem[addr] = ReadCharKb(false); // blocking mode input + } else if (mCharIOActive && addr == mCharIOAddr+1) { + m8bitMem[addr] = ReadCharKb(true); // non-blocking mode input + } + + ret = m8bitMem[addr++]; + ret += m8bitMem[addr] * 256; + + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: Poke8bit() + * Purpose: Write byte to specified memory location. + * If the memory location is mapped to character I/O, + * write value to output buffer and memory location. + * If the memory location is protected (ROM), do not + * write the value. + * Arguments: addr - (0x0000..0xffff) memory address, + * val - value (0x00..0xff) + * Returns: n/a + *-------------------------------------------------------------------- + */ +void Memory::Poke8bit(unsigned short addr, unsigned char val) +{ + if (mCharIOActive && addr == mCharIOAddr) + PutCharIO(val); + if (!mROMActive || (addr < mROMBegin || addr > mROMEnd)) { + m8bitMem[addr] = val; + } +} + +/* + *-------------------------------------------------------------------- + * Method: SetCharIO() + * Purpose: Activates and sets an address of basic character I/O + * emulation (console). + * Arguments: addr - address of I/O area (0x0000..0xFFFF) + * Returns: n/a + *-------------------------------------------------------------------- + */ +void Memory::SetCharIO(unsigned short addr, bool echo) +{ + mCharIOAddr = addr; + mCharIOActive = true; + mIOEcho = echo; +} + +/* + *-------------------------------------------------------------------- + * Method: DisableCharIO() + * Purpose: Deactivates basic character I/O emulation (console). + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void Memory::DisableCharIO() +{ + mCharIOActive = false; +} + +/* + *-------------------------------------------------------------------- + * Method: GetCharIOAddr() + * Purpose: Returns current address of basic character I/O area. + * Arguments: n/a + * Returns: address of I/O area + *-------------------------------------------------------------------- + */ +unsigned short Memory::GetCharIOAddr() +{ + return mCharIOAddr; +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +unsigned short Memory::GetROMBegin() +{ + return mROMBegin; +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +unsigned short Memory::GetROMEnd() +{ + return mROMEnd; +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +bool Memory::IsROMEnabled() +{ + return mROMActive; +} + +} // namespace MKBasic diff --git a/Memory.h b/Memory.h index e75533c..2151a63 100644 --- a/Memory.h +++ b/Memory.h @@ -1,55 +1,77 @@ -#ifndef MEMORY_H -#define MEMORY_H - -#define MAX_8BIT_ADDR 0xFFFF -#define CHARIO_ADDR 0xE000 -#define CHARIO_BUF_SIZE 256 -#define ROM_BEGIN 0xD000 -#define ROM_END 0xDFFF - -namespace MKBasic { - -class Memory -{ - public: - - Memory(); - ~Memory(); - - void Initialize(); - unsigned char Peek8bit(unsigned short addr); - unsigned short Peek16bit(unsigned short addr); - void Poke8bit(unsigned short addr, unsigned char val); - void SetCharIO(unsigned short addr, bool echo); - void DisableCharIO(); - unsigned short GetCharIOAddr(); - char GetCharIn(); - char GetCharOut(); - void EnableROM(); - void EnableROM(unsigned short start, unsigned short end); - - protected: - - private: - - unsigned char m8bitMem[MAX_8BIT_ADDR+1]; - char mCharIOBufIn[CHARIO_BUF_SIZE]; - char mCharIOBufOut[CHARIO_BUF_SIZE]; - unsigned int mInBufDataBegin; - unsigned int mInBufDataEnd; - unsigned int mOutBufDataBegin; - unsigned int mOutBufDataEnd; - unsigned short mCharIOAddr; - bool mCharIOActive; - bool mIOEcho; - unsigned short mROMBegin; - unsigned short mROMEnd; - bool mROMActive; - - unsigned char ReadCharKb(); - void PutCharIO(char c); -}; - -} // namespace MKBasic - -#endif +#ifndef MEMORY_H +#define MEMORY_H + +#include "system.h" + +#if defined(LINUX) +#include +#include +#include +#endif + +#define MAX_8BIT_ADDR 0xFFFF +#define CHARIO_ADDR 0xE000 +#define CHARIO_BUF_SIZE 256 +#define ROM_BEGIN 0xD000 +#define ROM_END 0xDFFF +#define MIN_ROM_BEGIN 0x0200 + +namespace MKBasic { + +class Memory +{ + public: + + Memory(); + ~Memory(); + + void Initialize(); + unsigned char Peek8bit(unsigned short addr); + unsigned short Peek16bit(unsigned short addr); + void Poke8bit(unsigned short addr, unsigned char val); + void SetCharIO(unsigned short addr, bool echo); + void DisableCharIO(); + unsigned short GetCharIOAddr(); + char GetCharIn(); + char GetCharOut(); + void EnableROM(); + void DisableROM(); + void SetROM(unsigned short start, unsigned short end); + void EnableROM(unsigned short start, unsigned short end); + unsigned short GetROMBegin(); + unsigned short GetROMEnd(); + bool IsROMEnabled(); + + protected: + + private: + + unsigned char m8bitMem[MAX_8BIT_ADDR+1]; + char mCharIOBufIn[CHARIO_BUF_SIZE]; + char mCharIOBufOut[CHARIO_BUF_SIZE]; + unsigned int mInBufDataBegin; + unsigned int mInBufDataEnd; + unsigned int mOutBufDataBegin; + unsigned int mOutBufDataEnd; + unsigned short mCharIOAddr; + bool mCharIOActive; + bool mIOEcho; + unsigned short mROMBegin; + unsigned short mROMEnd; + bool mROMActive; + + unsigned char ReadCharKb(bool nonblock); + void PutCharIO(char c); + +#if defined(LINUX) + + void set_conio_terminal_mode(); + int kbhit(); + int getch(); + +#endif +}; + +} // namespace MKBasic + +#endif diff --git a/Notes.txt b/Notes.txt index b2d55fc..103a6cc 100644 --- a/Notes.txt +++ b/Notes.txt @@ -1,25 +1,25 @@ - -http://visual6502.org/wiki/index.php?title=6502DecimalMode - - -NV-BDIZC - -Tests for ADC -00 + 00 and C=0 gives 00 and N=0 V=0 Z=1 C=0 (simulate) -79 + 00 and C=1 gives 80 and N=1 V=1 Z=0 C=0 (simulate) -24 + 56 and C=0 gives 80 and N=1 V=1 Z=0 C=0 (simulate) -93 + 82 and C=0 gives 75 and N=0 V=1 Z=0 C=1 (simulate) -89 + 76 and C=0 gives 65 and N=0 V=0 Z=0 C=1 (simulate) -89 + 76 and C=1 gives 66 and N=0 V=0 Z=1 C=1 (simulate) -80 + f0 and C=0 gives d0 and N=0 V=1 Z=0 C=1 (simulate) -80 + fa and C=0 gives e0 and N=1 V=0 Z=0 C=1 (simulate) -2f + 4f and C=0 gives 74 and N=0 V=0 Z=0 C=0 (simulate) -6f + 00 and C=1 gives 76 and N=0 V=0 Z=0 C=0 (simulate) -Tests for SBC -00 - 00 and C=0 gives 99 and N=1 V=0 Z=0 C=0 (simulate) -00 - 00 and C=1 gives 00 and N=0 V=0 Z=1 C=1 (simulate) -00 - 01 and C=1 gives 99 and N=1 V=0 Z=0 C=0 (simulate) -0a - 00 and C=1 gives 0a and N=0 V=0 Z=0 C=1 (simulate) -0b - 00 and C=0 gives 0a and N=0 V=0 Z=0 C=1 (simulate) -9a - 00 and C=1 gives 9a and N=1 V=0 Z=0 C=1 (simulate) + +http://visual6502.org/wiki/index.php?title=6502DecimalMode + + +NV-BDIZC + +Tests for ADC +00 + 00 and C=0 gives 00 and N=0 V=0 Z=1 C=0 (simulate) +79 + 00 and C=1 gives 80 and N=1 V=1 Z=0 C=0 (simulate) +24 + 56 and C=0 gives 80 and N=1 V=1 Z=0 C=0 (simulate) +93 + 82 and C=0 gives 75 and N=0 V=1 Z=0 C=1 (simulate) +89 + 76 and C=0 gives 65 and N=0 V=0 Z=0 C=1 (simulate) +89 + 76 and C=1 gives 66 and N=0 V=0 Z=1 C=1 (simulate) +80 + f0 and C=0 gives d0 and N=0 V=1 Z=0 C=1 (simulate) +80 + fa and C=0 gives e0 and N=1 V=0 Z=0 C=1 (simulate) +2f + 4f and C=0 gives 74 and N=0 V=0 Z=0 C=0 (simulate) +6f + 00 and C=1 gives 76 and N=0 V=0 Z=0 C=0 (simulate) +Tests for SBC +00 - 00 and C=0 gives 99 and N=1 V=0 Z=0 C=0 (simulate) +00 - 00 and C=1 gives 00 and N=0 V=0 Z=1 C=1 (simulate) +00 - 01 and C=1 gives 99 and N=1 V=0 Z=0 C=0 (simulate) +0a - 00 and C=1 gives 0a and N=0 V=0 Z=0 C=1 (simulate) +0b - 00 and C=0 gives 0a and N=0 V=0 Z=0 C=1 (simulate) +9a - 00 and C=1 gives 9a and N=1 V=0 Z=0 C=1 (simulate) 9b - 00 and C=0 gives 9a and N=1 V=0 Z=0 C=1 (simulate) \ No newline at end of file diff --git a/ReadMe.txt b/ReadMe.txt index 13c82ec..8a2d3b2 100644 --- a/ReadMe.txt +++ b/ReadMe.txt @@ -1,62 +1,262 @@ - -Project: MKBasic -Author: Copyright (C) Marek Karcz 2016. All rights reserved. -Purpose: -MOS 6502 emulator, Virtual CPU/Machine and potentially retro-style 8-bit computer emulator, -MOS-6502-compatible virtual computer featuring BASIC interpreter, machine code monitor etc. - -Memory images extensions: .RAM, .ROM - -Format of the memory definition file: - -; comment -ADDR -address -data -ORG -address - -Where: -ADDR - label indicating that starting address will follow in next - line -ORG - label indicating that the address counter will change to the - value provided in next line -address - decimal or hexadecimal (prefix $) address in memory - -E.g: -ADDR -$200 - -or - -ADDR -512 - -changes the default start address (256) to 512. - -ORG -49152 - -moves address counter to address 49152, following data will be -loaded from that address forward - -data - the multi-line stream of decimal of hexadecimal ($xx) values - of size unsigned char (byte: 0-255) separated with spaces - or commas. - -E.g.: -$00 $00 $00 $00 -$00 $00 $00 $00 - -or - -$00,$00,$00,$00 - -or - -0 0 0 0 - -or - -0,0,0,0 -0 0 0 0 \ No newline at end of file + +Project: MKBasic (VM6502). + +Author: Copyright (C) Marek Karcz 2016. All rights reserved. + Free for personal and non-commercial use. + Code can be distributed and included in derivative work under + condition that the original copyright notice is preserved. + For use in commercial product, please contact me to obtain + permission and discuss possible fees, at: makarcz@yahoo.com + This software is provided with no warranty. + +Purpose: + +MOS 6502 emulator, Virtual CPU/Machine and potentially retro-style 8-bit +computer emulator. +MOS-6502-compatible virtual computer featuring BASIC interpreter, machine code +monitor, input/output device emulation etc. +Program works in DOS/shell console (text mode) only. +Makefile are included to build under Windows 32/64 (mingw compiler required) +and under Linux Ubuntu or Ubuntu based. + +To build under Windows 32/64: + +* Install MINGW64 under C:\mingw-w64\x86_64-5.3.0 folder. +* Run mingw terminal. +* Change current directory to that of this project. +* Run: makeming.bat + +To build under Linux: + +* Make sure C++11 compliant version of GCC compiler is installed. +* Change current directory to that of this project. +* Run: make clean all + +Program passed following tests: + +* 6502 functional test by Klaus Dormann +* AllSuiteA.asm from project hmc-6502 + +1. Credits/attributions: + +Parts of this project is based on or contains 3-rd party work: + +- Tiny Basic. +- Enhanced Basic by Lee Davison. +- Microchess by Peter Jennings (http://www.benlo.com/microchess/index.html). +- 6502 functional test by Klaus Dormann. +- All Suite test from project hmc-6502. + +2. Format of the memory image definition file. + +Program can load raw binary image of MOS 6502 opcodes. +Binary image is always loaded from address $0000 and can be up to 64 kB long, +so the code must be properly located inside that image. +Depending on your favorite 6502 assembler, you may need to use proper command +line arguments or configuration to achieve properly formatted binary file. +E.g.: if using CL65 from CC65 package, create configuration file that defines +memory segments that your 6502 code uses, then all of the segments (except the +last one) must have attribute 'fill' set to 'yes' so the unsused areas are +filled with 0-s. +Two CFG files, one for microchess and one for All Suite from hmc-6502 project +are supplied with this project and assembler source code adapted to be +compiled with CL65. +Other assemblers may need a different approach or may not be able to generate +binary images that are required for this emulator. + +Program can also load memory image definition file (plain text), which is +a format developed especially for this project. + +The format of the plain text memory image definition file is described below: + +; comments +ADDR +address +data +ORG +address +data +IOADDR +address +ROMBEGIN +address +ROMEND +address +ENROM +ENIO +EXEC +address + +Where: +ADDR - label indicating that starting and run address will follow in + the next line +ORG - label indicating that the address counter will change to the + value provided in next line +IOADDR - label indicating that character I/O emulation trap address will + follow in the next line +ROMBEGIN - label indicating that the emulated read-only memory start address + will follow in the next line +ROMEND - label indicating that the emulated read-only memory end address + will follow in the next line +ENROM - enable read-only memory emulation +ENIO - enable character I/O emulation +EXEC - label indicating that the auto-execute address will follow + in the next line + + +address - decimal or hexadecimal (prefix $) address in memory + +E.g: +ADDR +$0200 + +or + +ADDR +512 + +changes the default start address (256) to 512. + +ORG +49152 + +moves address counter to address 49152, following data will be +loaded from that address forward + +data - the multi-line stream of decimal of hexadecimal ($xx) values + of size unsigned char (byte: 0-255) separated with spaces + or commas. + +E.g.: +$00 $00 $00 $00 +$00 $00 $00 $00 + +or + +$00,$00,$00,$00 + +or + +0 0 0 0 + +or + +0,0,0,0 +0 0 0 0 + +Each described above element of the memory image definition file is optional. + +3. Character I/O emulation. + +Emulator has ability to simulate a 80x25 text output display device and +rudimentary character I/O functions. The emulation is implemented by the means +of trapping memory locations defined to be designated I/O emulation addresses. +The default memory location is $E000 and also by default, the character I/O +is disabled. It can be enabled from the debug console with 'I' command: + +I hexaddr + +E.g.: + +I E000 + +or + +I FE00 + +or by putting optional statements in the memory image dedinition file: + +ENIO + +or + +IOADDR +address +ENIO + +Where: + +address - decimal or hexadecimal (with prefix '$') address in memory + $0000 - $FFFF. + +The same address is used for both, input and output operations. + +Reading from IOADDR inside the 6502 code invokes a blocking character +input function from user's DOS/shell session. +After user enters the character, the memory location contains the character +code and also emulated CPU Acc register contains the same code. + +Reading from IOADDR+1 inside 6502 code invokes a non-blocking character +input function from user's DOS/shell session. +This function is different than blocking one in one respect. +This function will return value 0 in the memory location and Acc register +if there was no key pressed by the user (no character waiting in buffer). +If there was a key typed, the function will act as the blocking counterpart. + +Writing to IOADDR inside the 6502 code will result in character code +being put in the IOADDR memory location and also written to the character +output buffer of the emulated display device. That character is not +immediately transferred to the user's DOS/shell session. It is written to the +emulated display's text memory instead. Depending on the mode in which +emulator is currently working (continuous or step-by-step code execution), +the emulated display device contents may or may not be updated on the user's +screen in real time fashion. Remember that this is a DOS/shell console +application. The user's console is shared among various functions of the +program. In step-by-step mode, if the character I/O emulation is enabled, the +current contents of the emulated display device can be displayed with +corresponding debug console command: 'T'. + +4. ROM (read-only memory) emulation. + +This facility provides very basic means for memory mapping of the read-only +area. This may be required by some 6502 programs that check for non-writable +memory to establish the bounds of memory that can be used for data and code. +One good example is Tiny Basic. +By default the ROM emulation is disabled and the memory range of ROM is +defined as $D000 - $DFFF. +ROM emulation can be enabled (and the memory range defined) using debug +console's command 'K': + +K [rombegin] [romend] - to enable + +or + +K - to disable + +The ROM emulation can also be defined and enabled in the memory image +definition file with following statements: + +ROMBEGIN +address +ROMEND +address +ENROM + +5. Additional comments and remarks. + +IOADDR is permitted to be located in the emulated ROM memory range. +The writing to IOADDR is trapped first before checking ROM range and writing +to it is permitted when character I/O emulation and ROM are enabled at the +same time. It is a good idea in fact to put the IOADDR inside ROM range, +otherwise memory scanning routines like the one in Tiny Basic may trigger +unexpected character input because of the reading from IOADDR during the scan. +If you experience unexpected character input prompt while emulating +6502 code, this may be the case. Reconfigure your IOADDR to be inside ROM in +such case and try again. + +6. Warranty and License Agreement. + +This software is provided with No Warranty. +I (The Author) will not be held responsible for any damage to computer +systems, data or user's health resulting from using this software. +Please use responsibly. +This software is provided in hope that it will be be useful and free of +charge for non-commercial and educational use. +Distribution of this software in non-commercial and educational derivative +work is permitted under condition that original copyright notices and +comments are preserved. Some 3-rd party work included with this project +may require separate application for permission from their respective +authors/copyright owners. + + + diff --git a/TestBCD.65s b/TestBCD.65s index b0f3f22..8cad2ed 100644 --- a/TestBCD.65s +++ b/TestBCD.65s @@ -1,291 +1,291 @@ -; Verify decimal mode behavior -; Written by Bruce Clark. This code is public domain. -; -; Returns: -; ERROR = 0 if the test passed -; ERROR = 1 if the test failed -; -; This routine requires 17 bytes of RAM -- 1 byte each for: -; AR, CF, DA, DNVZC, ERROR, HA, HNVZC, N1, N1H, N1L, N2, N2L, NF, VF, and ZF -; and 2 bytes for N2H -; -; Variables: -; N1 and N2 are the two numbers to be added or subtracted -; N1H, N1L, N2H, and N2L are the upper 4 bits and lower 4 bits of N1 and N2 -; DA and DNVZC are the actual accumulator and flag results in decimal mode -; HA and HNVZC are the accumulator and flag results when N1 and N2 are -; added or subtracted using binary arithmetic -; AR, NF, VF, ZF, and CF are the predicted decimal mode accumulator and -; flag results, calculated using binary arithmetic -; -; This program takes approximately 1 minute at 1 MHz (a few seconds more on -; a 65C02 than a 6502 or 65816) -; - *=$0300 - -AR: .DB 0 -CF: .DB 0 -DA: .DB 0 -DNVZC: .DB 0 -ERROR: .DB 0 -HA: .DB 0 -HNVZC: .DB 0 -N1: .DB 0 -N1H: .DB 0 -N1L: .DB 0 -N2: .DB 0 -N2L: .DB 0 -NF: .DB 0 -VF: .DB 0 -ZF: .DB 0 -N2H: .DB 0,0 - - *=$0400 - -TEST: LDY #1 ; initialize Y (used to loop through carry flag values) - STY ERROR ; store 1 in ERROR until the test passes - LDA #0 ; initialize N1 and N2 - STA N1 - STA N2 -LOOP1: LDA N2 ; N2L = N2 & $0F - AND #$0F ; [1] see text - STA N2L - LDA N2 ; N2H = N2 & $F0 - AND #$F0 ; [2] see text - STA N2H - ORA #$0F ; N2H+1 = (N2 & $F0) + $0F - STA N2H+1 -LOOP2: LDA N1 ; N1L = N1 & $0F - AND #$0F ; [3] see text - STA N1L - LDA N1 ; N1H = N1 & $F0 - AND #$F0 ; [4] see text - STA N1H - JSR ADD - JSR A6502 - JSR COMPARE - BNE DONE - JSR SUB - JSR S6502 - JSR COMPARE - BNE DONE - INC N1 ; [5] see text - BNE LOOP2 ; loop through all 256 values of N1 - INC N2 ; [6] see text - BNE LOOP1 ; loop through all 256 values of N2 - DEY - BPL LOOP1 ; loop through both values of the carry flag - LDA #0 ; test passed, so store 0 in ERROR - STA ERROR -DONE: RTS - BRK - -; Calculate the actual decimal mode accumulator and flags, the accumulator -; and flag results when N1 is added to N2 using binary arithmetic, the -; predicted accumulator result, the predicted carry flag, and the predicted -; V flag -; -ADD: SED ; decimal mode - CPY #1 ; set carry if Y = 1, clear carry if Y = 0 - LDA N1 - ADC N2 - STA DA ; actual accumulator result in decimal mode - PHP - PLA - STA DNVZC ; actual flags result in decimal mode - CLD ; binary mode - CPY #1 ; set carry if Y = 1, clear carry if Y = 0 - LDA N1 - ADC N2 - STA HA ; accumulator result of N1+N2 using binary arithmetic - - PHP - PLA - STA HNVZC ; flags result of N1+N2 using binary arithmetic - CPY #1 - LDA N1L - ADC N2L - CMP #$0A - LDX #0 - BCC A1 - INX - ADC #5 ; add 6 (carry is set) - AND #$0F - SEC -A1: ORA N1H -; -; if N1L + N2L < $0A, then add N2 & $F0 -; if N1L + N2L >= $0A, then add (N2 & $F0) + $0F + 1 (carry is set) -; - ADC N2H,X - PHP - BCS A2 - CMP #$A0 - BCC A3 -A2: ADC #$5F ; add $60 (carry is set) - SEC -A3: STA AR ; predicted accumulator result - PHP - PLA - STA CF ; predicted carry result - PLA -; -; note that all 8 bits of the P register are stored in VF -; - STA VF ; predicted V flags - RTS - -; Calculate the actual decimal mode accumulator and flags, and the -; accumulator and flag results when N2 is subtracted from N1 using binary -; arithmetic -; -SUB: SED ; decimal mode - CPY #1 ; set carry if Y = 1, clear carry if Y = 0 - LDA N1 - SBC N2 - STA DA ; actual accumulator result in decimal mode - PHP - PLA - STA DNVZC ; actual flags result in decimal mode - CLD ; binary mode - CPY #1 ; set carry if Y = 1, clear carry if Y = 0 - LDA N1 - SBC N2 - STA HA ; accumulator result of N1-N2 using binary arithmetic - - PHP - PLA - STA HNVZC ; flags result of N1-N2 using binary arithmetic - RTS - -; Calculate the predicted SBC accumulator result for the 6502 and 65816 - -; -SUB1: CPY #1 ; set carry if Y = 1, clear carry if Y = 0 - LDA N1L - SBC N2L - LDX #0 - BCS S11 - INX - SBC #5 ; subtract 6 (carry is clear) - AND #$0F - CLC -S11: ORA N1H -; -; if N1L - N2L >= 0, then subtract N2 & $F0 -; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear) -; - SBC N2H,X - BCS S12 - SBC #$5F ; subtract $60 (carry is clear) -S12: STA AR - RTS - -; Calculate the predicted SBC accumulator result for the 6502 and 65C02 - -; -SUB2: CPY #1 ; set carry if Y = 1, clear carry if Y = 0 - LDA N1L - SBC N2L - LDX #0 - BCS S21 - INX - AND #$0F - CLC -S21: ORA N1H -; -; if N1L - N2L >= 0, then subtract N2 & $F0 -; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear) -; - SBC N2H,X - BCS S22 - SBC #$5F ; subtract $60 (carry is clear) -S22: CPX #0 - BEQ S23 - SBC #6 -S23: STA AR ; predicted accumulator result - RTS - -; Compare accumulator actual results to predicted results -; -; Return: -; Z flag = 1 (BEQ branch) if same -; Z flag = 0 (BNE branch) if different -; -COMPARE: - LDA DA - CMP AR - BNE C1 - LDA DNVZC ; [7] see text - EOR NF - AND #$80 ; mask off N flag - BNE C1 - LDA DNVZC ; [8] see text - EOR VF - AND #$40 ; mask off V flag - BNE C1 ; [9] see text - LDA DNVZC - EOR ZF ; mask off Z flag - AND #2 - BNE C1 ; [10] see text - LDA DNVZC - EOR CF - AND #1 ; mask off C flag -C1: RTS - -; These routines store the predicted values for ADC and SBC for the 6502, -; 65C02, and 65816 in AR, CF, NF, VF, and ZF - -A6502: LDA VF -; -; since all 8 bits of the P register were stored in VF, bit 7 of VF contains -; the N flag for NF -; - STA NF - LDA HNVZC - STA ZF - RTS - -S6502: JSR SUB1 - LDA HNVZC - STA NF - STA VF - STA ZF - STA CF - RTS - -A65C02: LDA AR - PHP - PLA - STA NF - STA ZF - RTS - -S65C02: JSR SUB2 - LDA AR - PHP - PLA - STA NF - STA ZF - LDA HNVZC - STA VF - STA CF - RTS - -A65816: LDA AR - PHP - PLA - STA NF - STA ZF - RTS - -S65816: JSR SUB1 - LDA AR - PHP - PLA - STA NF - STA ZF - LDA HNVZC - STA VF - STA CF - RTS +; Verify decimal mode behavior +; Written by Bruce Clark. This code is public domain. +; +; Returns: +; ERROR = 0 if the test passed +; ERROR = 1 if the test failed +; +; This routine requires 17 bytes of RAM -- 1 byte each for: +; AR, CF, DA, DNVZC, ERROR, HA, HNVZC, N1, N1H, N1L, N2, N2L, NF, VF, and ZF +; and 2 bytes for N2H +; +; Variables: +; N1 and N2 are the two numbers to be added or subtracted +; N1H, N1L, N2H, and N2L are the upper 4 bits and lower 4 bits of N1 and N2 +; DA and DNVZC are the actual accumulator and flag results in decimal mode +; HA and HNVZC are the accumulator and flag results when N1 and N2 are +; added or subtracted using binary arithmetic +; AR, NF, VF, ZF, and CF are the predicted decimal mode accumulator and +; flag results, calculated using binary arithmetic +; +; This program takes approximately 1 minute at 1 MHz (a few seconds more on +; a 65C02 than a 6502 or 65816) +; + *=$0300 + +AR: .DB 0 +CF: .DB 0 +DA: .DB 0 +DNVZC: .DB 0 +ERROR: .DB 0 +HA: .DB 0 +HNVZC: .DB 0 +N1: .DB 0 +N1H: .DB 0 +N1L: .DB 0 +N2: .DB 0 +N2L: .DB 0 +NF: .DB 0 +VF: .DB 0 +ZF: .DB 0 +N2H: .DB 0,0 + + *=$0400 + +TEST: LDY #1 ; initialize Y (used to loop through carry flag values) + STY ERROR ; store 1 in ERROR until the test passes + LDA #0 ; initialize N1 and N2 + STA N1 + STA N2 +LOOP1: LDA N2 ; N2L = N2 & $0F + AND #$0F ; [1] see text + STA N2L + LDA N2 ; N2H = N2 & $F0 + AND #$F0 ; [2] see text + STA N2H + ORA #$0F ; N2H+1 = (N2 & $F0) + $0F + STA N2H+1 +LOOP2: LDA N1 ; N1L = N1 & $0F + AND #$0F ; [3] see text + STA N1L + LDA N1 ; N1H = N1 & $F0 + AND #$F0 ; [4] see text + STA N1H + JSR ADD + JSR A6502 + JSR COMPARE + BNE DONE + JSR SUB + JSR S6502 + JSR COMPARE + BNE DONE + INC N1 ; [5] see text + BNE LOOP2 ; loop through all 256 values of N1 + INC N2 ; [6] see text + BNE LOOP1 ; loop through all 256 values of N2 + DEY + BPL LOOP1 ; loop through both values of the carry flag + LDA #0 ; test passed, so store 0 in ERROR + STA ERROR +DONE: RTS + BRK + +; Calculate the actual decimal mode accumulator and flags, the accumulator +; and flag results when N1 is added to N2 using binary arithmetic, the +; predicted accumulator result, the predicted carry flag, and the predicted +; V flag +; +ADD: SED ; decimal mode + CPY #1 ; set carry if Y = 1, clear carry if Y = 0 + LDA N1 + ADC N2 + STA DA ; actual accumulator result in decimal mode + PHP + PLA + STA DNVZC ; actual flags result in decimal mode + CLD ; binary mode + CPY #1 ; set carry if Y = 1, clear carry if Y = 0 + LDA N1 + ADC N2 + STA HA ; accumulator result of N1+N2 using binary arithmetic + + PHP + PLA + STA HNVZC ; flags result of N1+N2 using binary arithmetic + CPY #1 + LDA N1L + ADC N2L + CMP #$0A + LDX #0 + BCC A1 + INX + ADC #5 ; add 6 (carry is set) + AND #$0F + SEC +A1: ORA N1H +; +; if N1L + N2L < $0A, then add N2 & $F0 +; if N1L + N2L >= $0A, then add (N2 & $F0) + $0F + 1 (carry is set) +; + ADC N2H,X + PHP + BCS A2 + CMP #$A0 + BCC A3 +A2: ADC #$5F ; add $60 (carry is set) + SEC +A3: STA AR ; predicted accumulator result + PHP + PLA + STA CF ; predicted carry result + PLA +; +; note that all 8 bits of the P register are stored in VF +; + STA VF ; predicted V flags + RTS + +; Calculate the actual decimal mode accumulator and flags, and the +; accumulator and flag results when N2 is subtracted from N1 using binary +; arithmetic +; +SUB: SED ; decimal mode + CPY #1 ; set carry if Y = 1, clear carry if Y = 0 + LDA N1 + SBC N2 + STA DA ; actual accumulator result in decimal mode + PHP + PLA + STA DNVZC ; actual flags result in decimal mode + CLD ; binary mode + CPY #1 ; set carry if Y = 1, clear carry if Y = 0 + LDA N1 + SBC N2 + STA HA ; accumulator result of N1-N2 using binary arithmetic + + PHP + PLA + STA HNVZC ; flags result of N1-N2 using binary arithmetic + RTS + +; Calculate the predicted SBC accumulator result for the 6502 and 65816 + +; +SUB1: CPY #1 ; set carry if Y = 1, clear carry if Y = 0 + LDA N1L + SBC N2L + LDX #0 + BCS S11 + INX + SBC #5 ; subtract 6 (carry is clear) + AND #$0F + CLC +S11: ORA N1H +; +; if N1L - N2L >= 0, then subtract N2 & $F0 +; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear) +; + SBC N2H,X + BCS S12 + SBC #$5F ; subtract $60 (carry is clear) +S12: STA AR + RTS + +; Calculate the predicted SBC accumulator result for the 6502 and 65C02 + +; +SUB2: CPY #1 ; set carry if Y = 1, clear carry if Y = 0 + LDA N1L + SBC N2L + LDX #0 + BCS S21 + INX + AND #$0F + CLC +S21: ORA N1H +; +; if N1L - N2L >= 0, then subtract N2 & $F0 +; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear) +; + SBC N2H,X + BCS S22 + SBC #$5F ; subtract $60 (carry is clear) +S22: CPX #0 + BEQ S23 + SBC #6 +S23: STA AR ; predicted accumulator result + RTS + +; Compare accumulator actual results to predicted results +; +; Return: +; Z flag = 1 (BEQ branch) if same +; Z flag = 0 (BNE branch) if different +; +COMPARE: + LDA DA + CMP AR + BNE C1 + LDA DNVZC ; [7] see text + EOR NF + AND #$80 ; mask off N flag + BNE C1 + LDA DNVZC ; [8] see text + EOR VF + AND #$40 ; mask off V flag + BNE C1 ; [9] see text + LDA DNVZC + EOR ZF ; mask off Z flag + AND #2 + BNE C1 ; [10] see text + LDA DNVZC + EOR CF + AND #1 ; mask off C flag +C1: RTS + +; These routines store the predicted values for ADC and SBC for the 6502, +; 65C02, and 65816 in AR, CF, NF, VF, and ZF + +A6502: LDA VF +; +; since all 8 bits of the P register were stored in VF, bit 7 of VF contains +; the N flag for NF +; + STA NF + LDA HNVZC + STA ZF + RTS + +S6502: JSR SUB1 + LDA HNVZC + STA NF + STA VF + STA ZF + STA CF + RTS + +A65C02: LDA AR + PHP + PLA + STA NF + STA ZF + RTS + +S65C02: JSR SUB2 + LDA AR + PHP + PLA + STA NF + STA ZF + LDA HNVZC + STA VF + STA CF + RTS + +A65816: LDA AR + PHP + PLA + STA NF + STA ZF + RTS + +S65816: JSR SUB1 + LDA AR + PHP + PLA + STA NF + STA ZF + LDA HNVZC + STA VF + STA CF + RTS diff --git a/VMachine.cpp b/VMachine.cpp index 73c7f13..944585e 100644 --- a/VMachine.cpp +++ b/VMachine.cpp @@ -1,579 +1,943 @@ -#include -#include -#include -#include -#include "VMachine.h" -#include "MKGenException.h" - -using namespace std; - -namespace MKBasic { - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ - -/* - *-------------------------------------------------------------------- - * Method: VMachine() - * Purpose: Default class constructor. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -VMachine::VMachine() -{ - InitVM(); -} - -/* - *-------------------------------------------------------------------- - * Method: VMachine() - * Purpose: Custom class constructor. - * Arguments: romfname - name of the ROM definition file - * ramfname - name of the RAM definition file - * Returns: n/a - *-------------------------------------------------------------------- - */ -VMachine::VMachine(string romfname, string ramfname) -{ - InitVM(); - LoadROM(romfname); - LoadRAM(ramfname); -} - -/* - *-------------------------------------------------------------------- - * Method: ~VMachine() - * Purpose: Class destructor. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -VMachine::~VMachine() -{ - delete mpDisp; - delete mpCPU; - delete mpROM; - delete mpRAM; -} - -/* - *-------------------------------------------------------------------- - * Method: InitVM() - * Purpose: Initialize class. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void VMachine::InitVM() -{ - mpRAM = new Memory(); - mRunAddr = 0x200; - mCharIOAddr = CHARIO_ADDR; - mCharIOActive = mCharIO = false; - if (NULL == mpRAM) { - throw MKGenException("Unable to initialize VM (RAM)."); - } - mpROM = new Memory(); - if (NULL == mpROM) { - throw MKGenException("Unable to initialize VM (ROM)."); - } - mpCPU = new MKCpu(mpRAM); - if (NULL == mpCPU) { - throw MKGenException("Unable to initialize VM (CPU)."); - } - mpDisp = new Display(); - if (NULL == mpDisp) { - throw MKGenException("Unable to initialize VM (Display)."); - } -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void VMachine::ClearScreen() -{ - HANDLE hStdOut; - CONSOLE_SCREEN_BUFFER_INFO csbi; - DWORD count; - DWORD cellCount; - COORD homeCoords = { 0, 0 }; - - hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); - if (hStdOut == INVALID_HANDLE_VALUE) return; - - /* Get the number of cells in the current buffer */ - if (!GetConsoleScreenBufferInfo( hStdOut, &csbi )) return; - cellCount = csbi.dwSize.X *csbi.dwSize.Y; - - /* Fill the entire buffer with spaces */ - if (!FillConsoleOutputCharacter( - hStdOut, - (TCHAR) ' ', - cellCount, - homeCoords, - &count - )) return; - - /* Fill the entire buffer with the current colors and attributes */ - if (!FillConsoleOutputAttribute( - hStdOut, - csbi.wAttributes, - cellCount, - homeCoords, - &count - )) return; - - /* Move the cursor home */ - SetConsoleCursorPosition( hStdOut, homeCoords ); -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void VMachine::ScrHome() -{ - HANDLE hStdOut; - COORD homeCoords = { 0, 0 }; - - hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); - if (hStdOut == INVALID_HANDLE_VALUE) return; - - /* Move the cursor home */ - SetConsoleCursorPosition( hStdOut, homeCoords ); -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void VMachine::ShowDisp() -{ - if (mCharIOActive) { -#if defined (WINDOWS) - //ClearScreen(); - ScrHome(); -#elif defined (LINUX) - system("clear"); -#endif - mpDisp->ShowScr(); - } -} - -/* - *-------------------------------------------------------------------- - * Method: Run() - * Purpose: Run VM until software break instruction. - * Arguments: n/a - * Returns: Pointer to CPU registers and flags. - *-------------------------------------------------------------------- - */ -Regs *VMachine::Run() -{ - Regs *cpureg = NULL; - -#if defined (WINDOWS) - ClearScreen(); -#elif defined (LINUX) - system("clear"); -#endif - ShowDisp(); - while (true) { - cpureg = Step(); - if (mCharIO) { - ShowDisp(); - } - if (cpureg->SoftIrq) - break; - } - - ShowDisp(); - - return cpureg; -} - -/* - *-------------------------------------------------------------------- - * Method: Run() - * Purpose: Run VM from specified address until software break - * instruction. - * Arguments: addr - start execution address - * Returns: Pointer to CPU registers and flags. - *-------------------------------------------------------------------- - */ -Regs *VMachine::Run(unsigned short addr) -{ - mRunAddr = addr; - return Run(); -} - -/* - *-------------------------------------------------------------------- - * Method: Exec() - * Purpose: Run VM from current address until last RTS. - * NOTE: Stack must be empty! - * Arguments: n/a - * Returns: Pointer to CPU registers and flags. - *-------------------------------------------------------------------- - */ -Regs *VMachine::Exec() -{ - Regs *cpureg = NULL; - -#if defined (WINDOWS) - ClearScreen(); -#elif defined (LINUX) - system("clear"); -#endif - ShowDisp(); - while (true) { - cpureg = Step(); - if (mCharIO) { - ShowDisp(); - } - if (cpureg->LastRTS) break; - } - - ShowDisp(); - - return cpureg; -} - -/* - *-------------------------------------------------------------------- - * Method: Exec() - * Purpose: Run VM from specified address until RTS. - * Arguments: addr - start execution address - * Returns: Pointer to CPU registers and flags. - *-------------------------------------------------------------------- - */ -Regs *VMachine::Exec(unsigned short addr) -{ - mRunAddr = addr; - return Exec(); -} - -/* - *-------------------------------------------------------------------- - * Method: Step() - * Purpose: Execute single opcode. - * Arguments: n/a - * Returns: Pointer to CPU registers and flags. - *-------------------------------------------------------------------- - */ -Regs *VMachine::Step() -{ - unsigned short addr = mRunAddr; - Regs *cpureg = NULL; - - cpureg = mpCPU->ExecOpcode(addr); - addr = cpureg->PtrAddr; - mRunAddr = addr; - - if (mCharIOActive) { - char c = -1; - mCharIO = false; - while ((c = mpRAM->GetCharOut()) != -1) { - mpDisp->PutChar(c); - mCharIO = true; - } - } - - return cpureg; -} - -/* - *-------------------------------------------------------------------- - * Method: Step() - * Purpose: Execute single opcode. - * Arguments: addr (unsigned short) - opcode address - * Returns: Pointer to CPU registers and flags. - *-------------------------------------------------------------------- - */ -Regs *VMachine::Step(unsigned short addr) -{ - mRunAddr = addr; - return Step(); -} - -/* - *-------------------------------------------------------------------- - * Method: LoadROM() - * Purpose: Load data from memory definition file to the memory. - * Arguments: romfname - name of the ROM file definition - * Returns: n/a - *-------------------------------------------------------------------- - */ -void VMachine::LoadROM(string romfname) -{ - LoadMEM(romfname, mpROM); -} - -/* - *-------------------------------------------------------------------- - * Method: LoadRAM() - * Purpose: Load data from memory definition file to the memory. - * Arguments: ramfname - name of the RAM file definition - * Returns: n/a - *-------------------------------------------------------------------- - */ -void VMachine::LoadRAM(string ramfname) -{ - LoadMEM(ramfname, mpRAM); - mpRAM->EnableROM(); -} - -/* - *-------------------------------------------------------------------- - * Method: LoadMEM() - * Purpose: Load data from memory definition file to the memory. - * Arguments: memfname - name of memory definition file - * pmem - pointer to memory object - * Returns: n/a - * Details: - * Format of the memory definition file: - * ; comment - * ADDR - * address - * data - * ORG - * address - * - * Where: - * ADDR - label indicating that starting address will follow in next - * line - * ORG - label indicating that the address counter will change to the - * value provided in next line - * address - decimal or hexadecimal (prefix $) address in memory - * E.g: - * ADDR - * $200 - * - * or - * - * ADDR - * 512 - * - * changes the default start address (256) to 512. - * - * ORG - * 49152 - * - * moves address counter to address 49152, following data will be - * loaded from that address forward - * - * data - the multi-line stream of decimal of hexadecimal ($xx) values - * of size unsigned char (byte: 0-255) separated with spaces - * or commas. - * E.g.: - * $00 $00 $00 $00 - * $00 $00 $00 $00 - * - * or - * - * $00,$00,$00,$00 - * - * or - * - * 0 0 0 0 - * - * or - * - * 0,0,0,0 - * 0 0 0 0 - *-------------------------------------------------------------------- - */ -void VMachine::LoadMEM(string memfname, Memory *pmem) -{ - FILE *fp = NULL; - char line[256] = "\0"; - unsigned short addr = 0x200; - unsigned int nAddr; - Memory *pm = pmem; - - if ((fp = fopen(memfname.c_str(), "r")) != NULL) { - fgets(line, 256, fp); - if (0 == strcmp(line, "ADDR")) { - line[0] = '\0'; - fgets(line, 256, fp); - if (*line == '$') { - sscanf(line+1, "%04x", &nAddr); - addr = nAddr; - } else { - addr = (unsigned short) atoi(line); - } - mRunAddr = addr; - } - while (0 == feof(fp) && 0 == ferror(fp)) - { - line[0] = '\0'; - fgets(line, 256, fp); - if (0 == strncmp(line, "ORG", 3)) { - line[0] = '\0'; - fgets(line, 256, fp); - if (*line == '$') { - sscanf(line+1, "%04x", &nAddr); - addr = nAddr; - } else { - addr = (unsigned short) atoi(line); - } - continue; - } - if (';' == *line) continue; // skip comment lines - char *s = strtok (line, " ,"); - while (NULL != s) { - unsigned int nVal; - if (*s == '$') { - sscanf(s+1, "%02x", &nVal); - pm->Poke8bit(addr++, (unsigned short)nVal); - } else { - pm->Poke8bit(addr++, (unsigned short)atoi(s)); - } - s = strtok(NULL, " ,"); - } - } - } - else { - cout << "WARNING: Unable to open memory definition file: " << memfname << endl; - cout << "Press [ENTER]..."; - getchar(); - //throw MKGenException("Unable to open memory definition file: " + memfname); - } -} - -/* - *-------------------------------------------------------------------- - * Method: MemPeek8bit() - * Purpose: Read value from specified RAM address. - * Arguments: addr - RAM address (0..0xFFFF) - * Returns: unsigned short - value read from specified RAM address - *-------------------------------------------------------------------- - */ -unsigned short VMachine::MemPeek8bit(unsigned short addr) -{ - unsigned short ret = 0; - - ret = (unsigned short)mpRAM->Peek8bit(addr); - - return ret; -} - -/* - *-------------------------------------------------------------------- - * Method: MemPoke8bit() - * Purpose: Write value to specified RAM address. - * Arguments: addr - RAM address (0..0xFFFF) - * v - 8-bit byte value - * Returns: n/a - *-------------------------------------------------------------------- - */ -void VMachine::MemPoke8bit(unsigned short addr, unsigned char v) -{ - mpRAM->Poke8bit(addr, v); -} - -/* - *-------------------------------------------------------------------- - * Method: GetRegs() - * Purpose: Return pointer to CPU status register. - * Arguments: n/a - * Returns: pointer to status register - *-------------------------------------------------------------------- - */ -Regs *VMachine::GetRegs() -{ - return mpCPU->GetRegs(); -} - -/* - *-------------------------------------------------------------------- - * Method: SetCharIO() - * Purpose: Activates and sets an address of basic character I/O - * emulation (console). - * Arguments: addr - address of I/O area (0x0000..0xFFFF) - * Returns: n/a - *-------------------------------------------------------------------- - */ -void VMachine::SetCharIO(unsigned short addr, bool echo) -{ - mCharIOAddr = addr; - mCharIOActive = true; - mpRAM->SetCharIO(addr, echo); - mpDisp->ClrScr(); -} - -/* - *-------------------------------------------------------------------- - * Method: DisableCharIO() - * Purpose: Deactivates basic character I/O emulation (console). - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void VMachine::DisableCharIO() -{ - mCharIOActive = false; - mpRAM->DisableCharIO(); -} - -/* - *-------------------------------------------------------------------- - * Method: GetCharIOAddr() - * Purpose: Returns current address of basic character I/O area. - * Arguments: n/a - * Returns: address of I/O area - *-------------------------------------------------------------------- - */ -unsigned short VMachine::GetCharIOAddr() -{ - return mCharIOAddr; -} - -/* - *-------------------------------------------------------------------- - * Method: GetCharIOActive() - * Purpose: Returns status of character I/O emulation. - * Arguments: n/a - * Returns: true if I/O emulation active - *-------------------------------------------------------------------- - */ -bool VMachine::GetCharIOActive() -{ - return mCharIOActive; -} - -/* - *-------------------------------------------------------------------- - * Method: ShowIO() - * Purpose: Show contents of emulated char I/O. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void VMachine::ShowIO() -{ - if (mCharIOActive) - mpDisp->ShowScr(); -} - -} // namespace MKBasic + +#include +#include +#include +#include "system.h" +#include "VMachine.h" +#include "MKGenException.h" + +#if defined(WINDOWS) +#include +#endif + +using namespace std; + +namespace MKBasic { + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ + +/* + *-------------------------------------------------------------------- + * Method: VMachine() + * Purpose: Default class constructor. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +VMachine::VMachine() +{ + InitVM(); +} + +/* + *-------------------------------------------------------------------- + * Method: VMachine() + * Purpose: Custom class constructor. + * Arguments: romfname - name of the ROM definition file + * ramfname - name of the RAM definition file + * Returns: n/a + *-------------------------------------------------------------------- + */ +VMachine::VMachine(string romfname, string ramfname) +{ + InitVM(); + LoadROM(romfname); + LoadRAM(ramfname); +} + +/* + *-------------------------------------------------------------------- + * Method: ~VMachine() + * Purpose: Class destructor. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +VMachine::~VMachine() +{ + delete mpDisp; + delete mpCPU; + delete mpROM; + delete mpRAM; +} + +/* + *-------------------------------------------------------------------- + * Method: InitVM() + * Purpose: Initialize class. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::InitVM() +{ + mOpInterrupt = false; + mpRAM = new Memory(); + + mAutoExec = false; + mCharIOAddr = CHARIO_ADDR; + mCharIOActive = mCharIO = false; + if (NULL == mpRAM) { + throw MKGenException("Unable to initialize VM (RAM)."); + } + mRunAddr = mpRAM->Peek16bit(0xFFFC); // address under RESET vector + mpROM = new Memory(); + if (NULL == mpROM) { + throw MKGenException("Unable to initialize VM (ROM)."); + } + mpCPU = new MKCpu(mpRAM); + if (NULL == mpCPU) { + throw MKGenException("Unable to initialize VM (CPU)."); + } + mpDisp = new Display(); + if (NULL == mpDisp) { + throw MKGenException("Unable to initialize VM (Display)."); + } +} + +#if defined(WINDOWS) + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::ClearScreen() +{ + HANDLE hStdOut; + CONSOLE_SCREEN_BUFFER_INFO csbi; + DWORD count; + DWORD cellCount; + COORD homeCoords = { 0, 0 }; + + hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); + if (hStdOut == INVALID_HANDLE_VALUE) return; + + /* Get the number of cells in the current buffer */ + if (!GetConsoleScreenBufferInfo( hStdOut, &csbi )) return; + cellCount = csbi.dwSize.X *csbi.dwSize.Y; + + /* Fill the entire buffer with spaces */ + if (!FillConsoleOutputCharacter( + hStdOut, + (TCHAR) ' ', + cellCount, + homeCoords, + &count + )) return; + + /* Fill the entire buffer with the current colors and attributes */ + if (!FillConsoleOutputAttribute( + hStdOut, + csbi.wAttributes, + cellCount, + homeCoords, + &count + )) return; + + /* Move the cursor home */ + SetConsoleCursorPosition( hStdOut, homeCoords ); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::ScrHome() +{ + HANDLE hStdOut; + COORD homeCoords = { 0, 0 }; + + hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); + if (hStdOut == INVALID_HANDLE_VALUE) return; + + /* Move the cursor home */ + SetConsoleCursorPosition( hStdOut, homeCoords ); +} + +#endif + +#if defined(LINUX) + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::ClearScreen() +{ + system("clear"); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::ScrHome() +{ + cout << "\033[1;1H"; +} + +#endif + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::ShowDisp() +{ + if (mCharIOActive) { + ScrHome(); + mpDisp->ShowScr(); + } +} + +/* + *-------------------------------------------------------------------- + * Method: Run() + * Purpose: Run VM until software break instruction. + * Arguments: n/a + * Returns: Pointer to CPU registers and flags. + *-------------------------------------------------------------------- + */ +Regs *VMachine::Run() +{ + Regs *cpureg = NULL; + + mOpInterrupt = false; + ClearScreen(); + ShowDisp(); + while (true) { + cpureg = Step(); + if (mCharIO) { + ShowDisp(); + } + if (cpureg->SoftIrq || mOpInterrupt) + break; + } + + ShowDisp(); + + return cpureg; +} + +/* + *-------------------------------------------------------------------- + * Method: Run() + * Purpose: Run VM from specified address until software break + * instruction. + * Arguments: addr - start execution address + * Returns: Pointer to CPU registers and flags. + *-------------------------------------------------------------------- + */ +Regs *VMachine::Run(unsigned short addr) +{ + mRunAddr = addr; + return Run(); +} + +/* + *-------------------------------------------------------------------- + * Method: Exec() + * Purpose: Run VM from current address until last RTS. + * NOTE: Stack must be empty! + * Arguments: n/a + * Returns: Pointer to CPU registers and flags. + *-------------------------------------------------------------------- + */ +Regs *VMachine::Exec() +{ + Regs *cpureg = NULL; + + mOpInterrupt = false; + ClearScreen(); + ShowDisp(); + while (true) { + cpureg = Step(); + if (mCharIO) { + ShowDisp(); + } + if (cpureg->LastRTS || mOpInterrupt) break; + } + + ShowDisp(); + + return cpureg; +} + +/* + *-------------------------------------------------------------------- + * Method: Exec() + * Purpose: Run VM from specified address until RTS. + * Arguments: addr - start execution address + * Returns: Pointer to CPU registers and flags. + *-------------------------------------------------------------------- + */ +Regs *VMachine::Exec(unsigned short addr) +{ + mRunAddr = addr; + return Exec(); +} + +/* + *-------------------------------------------------------------------- + * Method: Step() + * Purpose: Execute single opcode. + * Arguments: n/a + * Returns: Pointer to CPU registers and flags. + *-------------------------------------------------------------------- + */ +Regs *VMachine::Step() +{ + unsigned short addr = mRunAddr; + Regs *cpureg = NULL; + + cpureg = mpCPU->ExecOpcode(addr); + addr = cpureg->PtrAddr; + mRunAddr = addr; + + if (mCharIOActive && !mOpInterrupt) { + char c = -1; + mCharIO = false; + while ((c = mpRAM->GetCharOut()) != -1) { + mOpInterrupt = (c == OPINTERRUPT); + if (!mOpInterrupt) { + mpDisp->PutChar(c); + mCharIO = true; + } + } + } + + return cpureg; +} + +/* + *-------------------------------------------------------------------- + * Method: Step() + * Purpose: Execute single opcode. + * Arguments: addr (unsigned short) - opcode address + * Returns: Pointer to CPU registers and flags. + *-------------------------------------------------------------------- + */ +Regs *VMachine::Step(unsigned short addr) +{ + mRunAddr = addr; + return Step(); +} + +/* + *-------------------------------------------------------------------- + * Method: LoadROM() + * Purpose: Load data from memory definition file to the memory. + * Arguments: romfname - name of the ROM file definition + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::LoadROM(string romfname) +{ + LoadMEM(romfname, mpROM); +} + +/* + *-------------------------------------------------------------------- + * Method: LoadRAM() + * Purpose: Load data from memory definition file to the memory. + * Arguments: ramfname - name of the RAM file definition + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::LoadRAM(string ramfname) +{ + LoadMEM(ramfname, mpRAM); + //mpRAM->EnableROM(); +} + +/* + *-------------------------------------------------------------------- + * Method: LoadRAMBin() + * Purpose: Load data from binary image file to the memory. + * Arguments: ramfname - name of the RAM file definition + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::LoadRAMBin(string ramfname) +{ + FILE *fp = NULL; + unsigned short addr = 0x0000; + int n = 0; + Memory *pm = mpRAM; + + if ((fp = fopen(ramfname.c_str(), "rb")) != NULL) { + while (0 == feof(fp) && 0 == ferror(fp)) { + unsigned char val = fgetc(fp); + pm->Poke8bit(addr, val); + addr++; n++; + } + fclose(fp); + if (n <= 0xFFFF) { + cout << "WARNING: Unexpected EOF." << endl; + } + } + else { + cout << "WARNING: Unable to open memory image file: " << ramfname << endl; + cout << "Press [ENTER]..."; + getchar(); + } +} + +/* + *-------------------------------------------------------------------- + * Method: LoadMEM() + * Purpose: Load data from memory definition file to the memory. + * Arguments: memfname - name of memory definition file + * pmem - pointer to memory object + * Returns: n/a + * Details: + * Format of the memory definition file: + * [; comment] + * [ADDR + * address] + * [data] + * [ORG + * address] + * [data] + * [IOADDR + * address] + * [ROMBEGIN + * address] + * [ROMEND + * address] + * [ENIO] + * [ENROM] + * [EXEC + * addrress] + * + * Where: + * [] - optional token + * ADDR - label indicating that starting address will follow in next + * line, it also defines run address + * ORG - label indicating that the address counter will change to the + * value provided in next line + * IOADDR - label indicating that char IO trap address will be defined + * in the next line + * ROMBEGIN - label indicating that ROM begin address will be defined + * in the next line + * ROMEND - label indicating that ROM end address will be defined + * in the next line + * ENIO - label enabling char IO emulation + * ENROM - label enabling ROM emulation + * EXEC - label enabling auto-execute of code, address follows in the + * next line + * address - decimal or hexadecimal (prefix $) address in memory + * E.g: + * ADDR + * $200 + * + * or + * + * ADDR + * 512 + * + * changes the default start address (256) to 512. + * + * ORG + * 49152 + * + * moves address counter to address 49152, following data will be + * loaded from that address forward + * + * data - the multi-line stream of decimal of hexadecimal ($xx) values + * of size unsigned char (byte: 0-255) separated with spaces + * or commas. + * E.g.: + * $00 $00 $00 $00 + * $00 $00 $00 $00 + * + * or + * + * $00,$00,$00,$00 + * + * or + * + * 0 0 0 0 + * + * or + * + * 0,0,0,0 + * 0 0 0 0 + *-------------------------------------------------------------------- + */ +void VMachine::LoadMEM(string memfname, Memory *pmem) +{ + FILE *fp = NULL; + char line[256] = "\0"; + int lc = 0, errc = 0; + unsigned short addr = 0, rombegin = 0, romend = 0; + unsigned int nAddr; + bool enrom = false, enio = false, runset = false; + bool ioset = false, execset = false, rombegset = false; + bool romendset = false; + Memory *pm = pmem; + + if ((fp = fopen(memfname.c_str(), "r")) != NULL) { + while (0 == feof(fp) && 0 == ferror(fp)) + { + line[0] = '\0'; + fgets(line, 256, fp); + lc++; + // change run address (can be done only once) + if (0 == strncmp(line, "ADDR", 4)) { + line[0] = '\0'; + fgets(line, 256, fp); + lc++; + if (!runset) { + if (*line == '$') { + sscanf(line+1, "%04x", &nAddr); + addr = nAddr; + } else { + addr = (unsigned short) atoi(line); + } + mRunAddr = addr; + runset = true; + } else { + errc++; + cout << "LINE #" << dec << lc << " WARNING: Run address was already set. Ignoring..." << endl; + } + continue; + } + // change address counter + if (0 == strncmp(line, "ORG", 3)) { + line[0] = '\0'; + fgets(line, 256, fp); + lc++; + if (*line == '$') { + sscanf(line+1, "%04x", &nAddr); + addr = nAddr; + } else { + addr = (unsigned short) atoi(line); + } + continue; + } + // define I/O emulation address (once) + if (0 == strncmp(line, "IOADDR", 6)) { + line[0] = '\0'; + fgets(line, 256, fp); + lc++; + if (!ioset) { + if (*line == '$') { + sscanf(line+1, "%04x", &nAddr); + mCharIOAddr = nAddr; + } else { + mCharIOAddr = (unsigned short) atoi(line); + } + ioset = true; + } else { + errc++; + cout << "LINE #" << dec << lc << " WARNING: I/O address was already set. Ignoring..." << endl; + } + continue; + } + // enable character I/O emulation + if (0 == strncmp(line, "ENIO", 4)) { + enio = true; + continue; + } + // enable ROM emulation + if (0 == strncmp(line, "ENROM", 5)) { + enrom = true; + continue; + } + // auto execute from address + if (0 == strncmp(line, "EXEC", 4)) { + mAutoExec = true; + line[0] = '\0'; + fgets(line, 256, fp); + lc++; + if (!execset) { + if (*line == '$') { + sscanf(line+1, "%04x", &nAddr); + mRunAddr = nAddr; + } else { + mRunAddr = (unsigned short) atoi(line); + } + execset = true; + } else { + errc++; + cout << "LINE #" << dec << lc << " WARNING: auto-exec address was already set. Ignoring..." << endl; + } + continue; + } + // define ROM begin address + if (0 == strncmp(line, "ROMBEGIN", 8)) { + line[0] = '\0'; + fgets(line, 256, fp); + lc++; + if (!rombegset) { + if (*line == '$') { + sscanf(line+1, "%04x", &nAddr); + rombegin = nAddr; + } else { + rombegin = (unsigned short) atoi(line); + } + rombegset = true; + } else { + errc++; + cout << "LINE #" << dec << lc << " WARNING: ROM-begin address was already set. Ignoring..." << endl; + } + continue; + } + // define ROM end address + if (0 == strncmp(line, "ROMEND", 6)) { + line[0] = '\0'; + fgets(line, 256, fp); + lc++; + if (!romendset) { + if (*line == '$') { + sscanf(line+1, "%04x", &nAddr); + romend = nAddr; + } else { + romend = (unsigned short) atoi(line); + } + romendset = true; + } else { + errc++; + cout << "LINE #" << dec << lc << " WARNING: ROM-end address was already set. Ignoring..." << endl; + } + continue; + } + if (';' == *line) continue; // skip comment lines + char *s = strtok (line, " ,"); + while (NULL != s) { + unsigned int nVal; + if (*s == '$') { + sscanf(s+1, "%02x", &nVal); + pm->Poke8bit(addr++, (unsigned short)nVal); + } else { + pm->Poke8bit(addr++, (unsigned short)atoi(s)); + } + s = strtok(NULL, " ,"); + } + } + fclose(fp); + if (rombegin > MIN_ROM_BEGIN && romend > rombegin) { + if (enrom) + pm->EnableROM(rombegin, romend); + else + pm->SetROM(rombegin, romend); + } else { + if (enrom) pm->EnableROM(); + } + if (enio) { + SetCharIO(mCharIOAddr, false); + } + } + else { + cout << "WARNING: Unable to open memory definition file: " << memfname << endl; + errc++; + } + if (errc) { + cout << "Found " << dec << errc << ((errc > 1) ? " problems." : " problem.") << endl; + cout << "Press [ENTER] to continue..."; + getchar(); + } +} + +/* + *-------------------------------------------------------------------- + * Method: MemPeek8bit() + * Purpose: Read value from specified RAM address. + * Arguments: addr - RAM address (0..0xFFFF) + * Returns: unsigned short - value read from specified RAM address + *-------------------------------------------------------------------- + */ +unsigned short VMachine::MemPeek8bit(unsigned short addr) +{ + unsigned short ret = 0; + + ret = (unsigned short)mpRAM->Peek8bit(addr); + + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: MemPoke8bit() + * Purpose: Write value to specified RAM address. + * Arguments: addr - RAM address (0..0xFFFF) + * v - 8-bit byte value + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::MemPoke8bit(unsigned short addr, unsigned char v) +{ + mpRAM->Poke8bit(addr, v); +} + +/* + *-------------------------------------------------------------------- + * Method: GetRegs() + * Purpose: Return pointer to CPU status register. + * Arguments: n/a + * Returns: pointer to status register + *-------------------------------------------------------------------- + */ +Regs *VMachine::GetRegs() +{ + return mpCPU->GetRegs(); +} + +/* + *-------------------------------------------------------------------- + * Method: SetCharIO() + * Purpose: Activates and sets an address of basic character I/O + * emulation (console). + * Arguments: addr - address of I/O area (0x0000..0xFFFF) + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::SetCharIO(unsigned short addr, bool echo) +{ + mCharIOAddr = addr; + mCharIOActive = true; + mpRAM->SetCharIO(addr, echo); + mpDisp->ClrScr(); +} + +/* + *-------------------------------------------------------------------- + * Method: DisableCharIO() + * Purpose: Deactivates basic character I/O emulation (console). + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::DisableCharIO() +{ + mCharIOActive = false; + mpRAM->DisableCharIO(); +} + +/* + *-------------------------------------------------------------------- + * Method: GetCharIOAddr() + * Purpose: Returns current address of basic character I/O area. + * Arguments: n/a + * Returns: address of I/O area + *-------------------------------------------------------------------- + */ +unsigned short VMachine::GetCharIOAddr() +{ + return mCharIOAddr; +} + +/* + *-------------------------------------------------------------------- + * Method: GetCharIOActive() + * Purpose: Returns status of character I/O emulation. + * Arguments: n/a + * Returns: true if I/O emulation active + *-------------------------------------------------------------------- + */ +bool VMachine::GetCharIOActive() +{ + return mCharIOActive; +} + +/* + *-------------------------------------------------------------------- + * Method: ShowIO() + * Purpose: Show contents of emulated char I/O. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::ShowIO() +{ + if (mCharIOActive) + mpDisp->ShowScr(); +} + +/* + *-------------------------------------------------------------------- + * Method: IsAutoExec() + * Purpose: Return status of auto-execute flag. + * Arguments: n/a + * Returns: bool - true if auto-exec flag is enabled. + *-------------------------------------------------------------------- + */ +bool VMachine::IsAutoExec() +{ + return mAutoExec; +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::EnableROM() +{ + mpRAM->EnableROM(); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::DisableROM() +{ + mpRAM->DisableROM(); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::SetROM(unsigned short start, unsigned short end) +{ + mpRAM->SetROM(start, end); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::EnableROM(unsigned short start, unsigned short end) +{ + mpRAM->EnableROM(start, end); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +unsigned short VMachine::GetROMBegin() +{ + return mpRAM->GetROMBegin(); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +unsigned short VMachine::GetROMEnd() +{ + return mpRAM->GetROMEnd(); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +bool VMachine::IsROMEnabled() +{ + return mpRAM->IsROMEnabled(); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +unsigned short VMachine::GetRunAddr() +{ + return mRunAddr; +} + +/* + *-------------------------------------------------------------------- + * Method: SetOpInterrupt() + * Purpose: Set the flag indicating operator interrupt. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::SetOpInterrupt() +{ + mOpInterrupt = true; +} + +/* + *-------------------------------------------------------------------- + * Method: GetExecHistory() + * Purpose: Return history of executed opcodes (last 20). + * Arguments: n/a + * Returns: queue + *-------------------------------------------------------------------- + */ +queue VMachine::GetExecHistory() +{ + return mpCPU->GetExecHistory(); +} + +/* + *-------------------------------------------------------------------- + * Method: Disassemble() + * Purpose: Disassemble code in memory. Return next instruction + * address. + * Arguments: addr - address in memory + * buf - character buffer for disassembled instruction + * Returns: unsigned short - address of next instruction + *-------------------------------------------------------------------- + */ +unsigned short VMachine::Disassemble(unsigned short addr, char *buf) +{ + return mpCPU->Disassemble(addr, buf); +} + +} // namespace MKBasic diff --git a/VMachine.h b/VMachine.h index d18d793..8281a34 100644 --- a/VMachine.h +++ b/VMachine.h @@ -1,65 +1,84 @@ -#ifndef VMACHINE_H -#define VMACHINE_H - -#include -#include "MKCpu.h" -#include "Memory.h" -#include "Display.h" - -#define WINDOWS 1 -#if defined (WINDOWS) -#include -#endif -#define IOREFRESH 32 - -using namespace std; - -namespace MKBasic { - -class VMachine -{ - public: - VMachine(); - VMachine(string romfname, string ramfname); - ~VMachine(); - - void InitVM(); - Regs *Run(); - Regs *Run(unsigned short addr); - Regs *Exec(); - Regs *Exec(unsigned short addr); - Regs *Step(); - Regs *Step(unsigned short addr); - void LoadROM(string romfname); - void LoadRAM(string ramfname); - unsigned short MemPeek8bit(unsigned short addr); - void MemPoke8bit(unsigned short addr, unsigned char v); - Regs *GetRegs(); - void SetCharIO(unsigned short addr, bool echo); - void DisableCharIO(); - unsigned short GetCharIOAddr(); - bool GetCharIOActive(); - void ShowIO(); - void ClearScreen(); - void ScrHome(); - - protected: - - private: - - MKCpu *mpCPU; - Memory *mpROM; - Memory *mpRAM; - Display *mpDisp; - unsigned short mRunAddr; - unsigned short mCharIOAddr; - bool mCharIOActive; - bool mCharIO; - - void LoadMEM(string memfname, Memory *pmem); - void ShowDisp(); -}; - -} // namespace MKBasic - -#endif +#ifndef VMACHINE_H +#define VMACHINE_H + +#include +#include +#include "system.h" +#include "MKCpu.h" +#include "Memory.h" +#include "Display.h" + +//#define WINDOWS 1 +#if defined (WINDOWS) +#include +#endif + +#define IOREFRESH 32 +#define OPINTERRUPT 25 // operator interrupt code (CTRL-Y) + +using namespace std; + +namespace MKBasic { + +class VMachine +{ + public: + VMachine(); + VMachine(string romfname, string ramfname); + ~VMachine(); + + void InitVM(); + Regs *Run(); + Regs *Run(unsigned short addr); + Regs *Exec(); + Regs *Exec(unsigned short addr); + Regs *Step(); + Regs *Step(unsigned short addr); + void LoadROM(string romfname); + void LoadRAM(string ramfname); + void LoadRAMBin(string ramfname); + unsigned short MemPeek8bit(unsigned short addr); + void MemPoke8bit(unsigned short addr, unsigned char v); + Regs *GetRegs(); + void SetCharIO(unsigned short addr, bool echo); + void DisableCharIO(); + unsigned short GetCharIOAddr(); + bool GetCharIOActive(); + void ShowIO(); + void ClearScreen(); + void ScrHome(); + bool IsAutoExec(); + void EnableROM(); + void DisableROM(); + void SetROM(unsigned short start, unsigned short end); + void EnableROM(unsigned short start, unsigned short end); + unsigned short GetROMBegin(); + unsigned short GetROMEnd(); + bool IsROMEnabled(); + unsigned short GetRunAddr(); + void SetOpInterrupt(); + queue GetExecHistory(); + unsigned short Disassemble(unsigned short addr, char *buf); + + protected: + + private: + + MKCpu *mpCPU; + Memory *mpROM; + Memory *mpRAM; + Display *mpDisp; + unsigned short mRunAddr; + unsigned short mCharIOAddr; + bool mCharIOActive; + bool mCharIO; + bool mOpInterrupt; // operator interrupt from console + bool mAutoExec; + + void LoadMEM(string memfname, Memory *pmem); + void ShowDisp(); +}; + +} // namespace MKBasic + +#endif diff --git a/bcd.c b/bcd.c index 9dc76eb..e9bd058 100644 --- a/bcd.c +++ b/bcd.c @@ -1,56 +1,56 @@ - -#include -#include -#include - - -unsigned char conv2bcd(unsigned short v) -{ - unsigned char arg8 = 0; - arg8 = (unsigned char)((v/10) << 4); - arg8 |= ((unsigned char)(v - (v/10)*10)) & 0x0F; - return arg8; -} - -char *conv24bitbin(unsigned char v) -{ - static char retbuf[5]; - int i=3; - - memset(retbuf, '0', 4); - retbuf[4]=0; - if (v == 0) return retbuf; - while (v > 0 && i >= 0) { - int r = v % 2; - retbuf[i] = ((r==0) ? '0' : '1'); - v = v/2; - i--; - } - - return retbuf; -} - -/* run this program using the console pauser or add your own getch, system("pause") or input loop */ - -int main(int argc, char *argv[]) -{ - unsigned short v = 0; - - for (v = 0; v < 100; v++) { - unsigned char cv = conv2bcd(v), hinyb, lonyb; - hinyb = (cv & 0xF0) >> 4; - lonyb = cv & 0x0F; - char buf_hinyb[5], buf_lonyb[5]; - strcpy(buf_hinyb, conv24bitbin(hinyb)); - strcpy(buf_lonyb, conv24bitbin(lonyb)); - printf("%d (dec) \t= %4s(%d) %4s(%d) (BCD, dec:%d)\n", v, - buf_hinyb, - hinyb, - buf_lonyb, - lonyb, - cv); - } - - return 0; -} - + +#include +#include +#include + + +unsigned char conv2bcd(unsigned short v) +{ + unsigned char arg8 = 0; + arg8 = (unsigned char)((v/10) << 4); + arg8 |= ((unsigned char)(v - (v/10)*10)) & 0x0F; + return arg8; +} + +char *conv24bitbin(unsigned char v) +{ + static char retbuf[5]; + int i=3; + + memset(retbuf, '0', 4); + retbuf[4]=0; + if (v == 0) return retbuf; + while (v > 0 && i >= 0) { + int r = v % 2; + retbuf[i] = ((r==0) ? '0' : '1'); + v = v/2; + i--; + } + + return retbuf; +} + +/* run this program using the console pauser or add your own getch, system("pause") or input loop */ + +int main(int argc, char *argv[]) +{ + unsigned short v = 0; + + for (v = 0; v < 100; v++) { + unsigned char cv = conv2bcd(v), hinyb, lonyb; + hinyb = (cv & 0xF0) >> 4; + lonyb = cv & 0x0F; + char buf_hinyb[5], buf_lonyb[5]; + strcpy(buf_hinyb, conv24bitbin(hinyb)); + strcpy(buf_lonyb, conv24bitbin(lonyb)); + printf("%d (dec) \t= %4s(%d) %4s(%d) (BCD, dec:%d)\n", v, + buf_hinyb, + hinyb, + buf_lonyb, + lonyb, + cv); + } + + return 0; +} + diff --git a/bin2hex.c b/bin2hex.c new file mode 100644 index 0000000..5d5cd5f --- /dev/null +++ b/bin2hex.c @@ -0,0 +1,187 @@ +/* + *---------------------------------------------------------------------------- + * File: bin2hex.c + * + * Author: Marek Karcz + * + * Date created: 3/8/2016 + * + * Purpose: Convert binary file to memory image definition (plain text) file. + *---------------------------------------------------------------------------- + */ + +#include +#include +#include +#include + +const int DEBUG = 0; +const char *hdr1 = "; Created with BIN2HEX (C) Marek Karcz 2016. All rights reserved.\n"; + +char g_szInputFileName[256] = {0}; +char g_szHexFileName[256] = {0}; +int g_nStartAddr = 2048; /* $0800 */ +int g_nExecAddr = 2048; /* $0800 */ +int g_nSuppressAutoExec = 1; +int g_nSuppressAllZeroRows = 0; + +void ScanArgs(int argc, char *argv[]); +void ConvertFile(void); + +void Usage(char *prgn) +{ + printf("\nProgram: %s\n Convert binary file to memory image definition for MKBASIC (VM65) emulator.\n\n", prgn); + printf("Copyright: Marek Karcz 2016. All rights reserved.\n"); + printf("Free for personal and educational use.\n\n"); + printf("Usage:\n\n"); + printf(" %s -f input_fname -o output_fname [-w load_addr] [-x exec_addr] [-s] [-z]\n\n", prgn); + printf("Where:\n\n"); + printf(" input_fname - binary file name\n"); + printf(" output_fname - output file name\n"); + printf(" load_addr - starting address to load data (default: %d)\n", g_nStartAddr); + printf(" exec_addr - address to auto-execute code from (default: %d)\n", g_nExecAddr); + printf(" -s - suppress auto-execute statement in output\n"); + printf(" -z - suppress data blocks with 0-s only\n"); + printf("\n"); +} + +/* + * bin2hex -f InputFile -o OutputFile -w StartAddr + */ +void ScanArgs(int argc, char *argv[]) +{ + int n = 1; + + while (n < argc) + { + if (strcmp(argv[n], "-f") == 0) + { + n++; + strcpy(g_szInputFileName,argv[n]); + } + else if (strcmp(argv[n],"-o") == 0) + { + n++; + strcpy(g_szHexFileName,argv[n]); + } + else if (strcmp(argv[n],"-w") == 0) + { + n++; + g_nStartAddr = atoi(argv[n]); + g_nExecAddr = g_nStartAddr; + g_nSuppressAutoExec = 0; + } + else if (strcmp(argv[n],"-x") == 0) + { + n++; + g_nExecAddr = atoi(argv[n]); + g_nSuppressAutoExec = 0; + } + else if (strcmp(argv[n],"-s") == 0) + { + g_nSuppressAutoExec = 1; + } + else if (strcmp(argv[n],"-z") == 0) + { + g_nSuppressAllZeroRows = 1; + } + + n++; + } +} + +void ConvertFile(void) +{ + FILE *fpi = NULL; + FILE *fpo = NULL; + unsigned char bt[17]; + char hex[80]; + int i, addr, allzero, prev_allzero; + + addr = g_nStartAddr; + printf("Processing...\n"); + printf("Start address: $%04x\n", addr); + if (NULL != (fpi = fopen(g_szInputFileName,"rb"))) + { + if (NULL != (fpo = fopen(g_szHexFileName,"w"))) + { + time_t t = time(NULL); + struct tm *tm = localtime(&t); + char s[64] = {0}; + strftime(s, sizeof(s), "; %c\n", tm); + + fputs(hdr1, fpo); + fputs(s, fpo); + sprintf(hex, "ADDR\n$%04x\nORG\n$%04x\n", g_nExecAddr, addr); + if (DEBUG) printf("Adding line:\n%s\n", hex); + fputs(hex,fpo); + prev_allzero = 1; + while(0 == feof(fpi) && addr <= 0xFFFF) + { + memset(bt, 0, 17); + memset(hex, 0, 80); + if (DEBUG) printf("Reading input file..."); + fread(bt, sizeof(char), 16, fpi); + if (DEBUG) printf("done.\n"); + if (DEBUG) printf("Preparing hex string...\n"); + allzero = 1; + for(i=0; i<16; i++) + { + if (DEBUG) printf("Code: %d\n", bt[i]); + if (*hex == 0) sprintf(hex, "$%02x", bt[i]); + else sprintf(hex, "%s $%02x", hex, bt[i]); + if (allzero && bt[i] > 0) + allzero = 0; + } + if (g_nSuppressAllZeroRows && prev_allzero && 0 == allzero) { + char buff[20]; + sprintf (buff, "ORG\n$%04x\n", addr); + fputs(buff, fpo); + } + if (0 == g_nSuppressAllZeroRows + || + (g_nSuppressAllZeroRows && 0 == allzero) + ) + { + sprintf(hex, "%s\n", hex); + if (DEBUG) printf("Adding line: %s", hex); + fputs(hex, fpo); + } + addr += 16; + prev_allzero = allzero; + } + if (0 == g_nSuppressAutoExec) + { + memset(hex, 80, sizeof(char)); + sprintf(hex, "EXEC\n$%04x\n", g_nExecAddr); + if (DEBUG) printf("Adding line: %s", hex); + fputs(hex, fpo); + } + fclose(fpi); + fclose(fpo); + printf("Done.\n"); + printf("End address: $%04x\n", (addr <= 0xFFFF) ? addr : 0xFFFF); + printf("Run address: $%04x\n", g_nExecAddr); + } + else + printf("ERROR: Unable to create output file.\n"); + } + else + printf("ERROR: Unable to open input file.\n"); +} + +int main(int argc, char *argv[]) +{ + if (argc == 1) + Usage(argv[0]); + else { + ScanArgs(argc, argv); + if (*g_szInputFileName == 0 || *g_szHexFileName == 0) + Usage(argv[0]); + else + ConvertFile(); + } + return 0; +} + + diff --git a/dummy.ram b/dummy.ram index 9ce490e..43eaabb 100644 --- a/dummy.ram +++ b/dummy.ram @@ -1,315 +1,315 @@ -; -; test program #1 -; address: $0200 -; load Acc with value 12 -; write Acc to address $c000 (49152) -; -; nop -; nop -; lda #$0c -; sta $c000 -; brk -; -$EA $EA $A9 $0c $8D $00 $c0 $00 $00 -; -; test program #2 -; address: $0400 -; copy 0-terminated string from -; address $d000 to $0200 -; "Hello World!" -; -; ORG=$0400 -; hello: -; ldx #0 -; loop: -; lda $d000,x -; beq $06 ;branch to end (+6) if A=0 -; sta $0200,x -; inx -; bne $f5 ; branch to loop (-11) if X<>0 -; end: -; brk -ORG -$0400 -$A2 $00 -$BD $00 $d0 -$F0 $06 -$9D $00 $02 -$E8 -$D0 $F5 -$00 $00 -; data -; address: $d000 -ORG -$D000 -;DEC: 53248 -; "Hello World!" -72 101 108 108 111 32 87 111 114 108 100 33 0 -; -; test program #3 - copy Hello World! string to $0300 -; using different assembly instructions -; address: $0500 -; -; ORG=$0500 ;dec: 1280 -; hello: -; lda #0 -; sta $05 -; ldx $05 -; loop: -; lda $d000,x -; sta $0300,x -; beq end ;(+6) -; inx -; beq end ;(+3) -; jmp loop -; end: -; brk -ORG -$0500 -;DEC: 1280 -$A9 $00 -$85 $05 -$A6 $05 -$BD $00 $d0 -$9D $00 $03 -$F0 $06 -$E8 -$F0 $03 -$4C $06 $05 -$00 $00 -; -; test program #4 -; left-shift memory location $05 at zero page, -; then location $06 using zero page indexed addressing, -; then memory location $c001 (outside zero page) using absolute addressing -; then location $c002 using indexed absolute addressing -; and finally left-shift Acc. -; stop after each step for debugging -; exit loop when Acc=0 -; -; start: -; lda #$ff -; ldx #$01 -; sta $05 -; sta $05,x -; sta $c000,x -; inx -; sta $c000,x -; ldx #$01 -; loop2: -; brk -; asl $05 -; asl $05,x -; asl $c001 -; asl $c001,x -; asl -; bne loop2 ;(-15 or $f1) -; brk -ORG -$0600 -$A9 $FF -$A2 $01 -$85 $05 -$95 $05 -$9D $00 $C0 -$E8 -$9D $00 $C0 -$A2 $01 -$00 $00 -$06 $05 -$16 $05 -$0E $01 $C0 -$1E $01 $C0 -$0A -$D0 $F1 -$00 $00 -; -; test program #5 -; Test ORA opcode with various arguments and addressing modes. -; At each break, the contents of Acc should equal $AA. -; -; start: -; lda #$aa ;%10101010 -; sta $05 -; sta $aa -; lda #$00 -; tax -; ora ($05,x) -; brk -; lda #$00 -; ora $05 -; brk -; lda #$00 -; ora #$aa -; brk -; lda #$00 -; ora $0005 -; brk -; lda #$05 -; sta $06 -; lda #$00 -; sta $07 -; tay -; ora ($06),y -; brk -; lda #$00 -; tax -; ora $05,x -; brk -; lda #$00 -; tay -; ora $0005,y -; brk -; lda #$00 -; tax -; ora $0005,x -; brk -ORG -$0700 -$A9 $AA -$85 $05 -$85 $AA -$A9 $00 -$AA -$01 $05 -$00 $00 -$A9 $00 -$05 $05 -$00 $00 -$A9 $00 -$09 $AA -$00 $00 -$A9 $00 -$0D $05 $00 -$00 $00 -$A9 $05 -$85 $06 -$A9 $00 -$85 $07 -$A8 -$11 $06 -$00 $00 -$A9 $00 -$AA -$15 $05 -$00 $00 -$A9 $00 -$A8 -$19 $05 $00 -$00 $00 -$A9 $00 -$AA -$1D $05 $00 -$00 $00 -; -; test program #6 -; Test JSR opcode. -; After each break examine memory at $c000 and $c001. -; After 1-st break, $c000 should equal $dd. -; Return address-1 ($0802) should be on stack. -; After 2-nd break, PC counter should be at $0805. -; After 3-rd break, $c000 should equal $ee. -; Return address-1 ($0807) should be on stack. -; After 4-th break, PC counter should be at $080a. -; -; start: -; jsr sub1 -; brk -; jsr sub2 -; brk -; brk -; brk -; sub1: -; lda #$dd -; sta $c000 -; brk -; rts -; sub2: -; lda #$ee -; sta $c000 -; brk -; rts -; -ORG -$0800 -$20 $0B $08 -$00 $00 -$20 $13 $08 -$00 -$00 -$00 -$A9 $DD -$8D $00 $C0 -$00 $00 -$60 -$A9 $EE -$8D $00 $C0 -$00 $00 -$60 -; -; test program #7 -; Test ADC opcode. -; Expected results: -; First break: Acc=$01, Carry=1 -; 2-nd break: Acc=$02, Carry=1 -; 3-rd break: Acc=$22, Carry=0 -; 4-th break: Acc=$23, Carry=0 -; -; start: -; clc -; lda #$ff -; adc #$02 -; brk -; sec -; lda #$ff -; adc #$02 -; brk -; clc -; lda #$20 -; adc #$02 -; brk -; sec -; lda #$20 -; adc #$02 -; brk -; -ORG -$0900 -$18 -$A9 $FF -$69 $02 -$00 $00 -$38 -$A9 $FF -$69 $02 -$00 $00 -$18 -$A9 $20 -$69 $02 -$00 $00 -$38 -$A9 $20 -$69 $02 -$00 $00 -; -; test program #8 -; Test ROR opcode. -; -; start: -; sec -; lda #$00 -; loop: -; ror -; brk -; bcc loop ;(-5 -> $FB) -; brk -; -ORG -$0920 -$38 -$A9 $00 -$6A -$00 $00 -$90 $FB -$00 $00 +; +; test program #1 +; address: $0200 +; load Acc with value 12 +; write Acc to address $c000 (49152) +; +; nop +; nop +; lda #$0c +; sta $c000 +; brk +; +$EA $EA $A9 $0c $8D $00 $c0 $00 $00 +; +; test program #2 +; address: $0400 +; copy 0-terminated string from +; address $d000 to $0200 +; "Hello World!" +; +; ORG=$0400 +; hello: +; ldx #0 +; loop: +; lda $d000,x +; beq $06 ;branch to end (+6) if A=0 +; sta $0200,x +; inx +; bne $f5 ; branch to loop (-11) if X<>0 +; end: +; brk +ORG +$0400 +$A2 $00 +$BD $00 $d0 +$F0 $06 +$9D $00 $02 +$E8 +$D0 $F5 +$00 $00 +; data +; address: $d000 +ORG +$D000 +;DEC: 53248 +; "Hello World!" +72 101 108 108 111 32 87 111 114 108 100 33 0 +; +; test program #3 - copy Hello World! string to $0300 +; using different assembly instructions +; address: $0500 +; +; ORG=$0500 ;dec: 1280 +; hello: +; lda #0 +; sta $05 +; ldx $05 +; loop: +; lda $d000,x +; sta $0300,x +; beq end ;(+6) +; inx +; beq end ;(+3) +; jmp loop +; end: +; brk +ORG +$0500 +;DEC: 1280 +$A9 $00 +$85 $05 +$A6 $05 +$BD $00 $d0 +$9D $00 $03 +$F0 $06 +$E8 +$F0 $03 +$4C $06 $05 +$00 $00 +; +; test program #4 +; left-shift memory location $05 at zero page, +; then location $06 using zero page indexed addressing, +; then memory location $c001 (outside zero page) using absolute addressing +; then location $c002 using indexed absolute addressing +; and finally left-shift Acc. +; stop after each step for debugging +; exit loop when Acc=0 +; +; start: +; lda #$ff +; ldx #$01 +; sta $05 +; sta $05,x +; sta $c000,x +; inx +; sta $c000,x +; ldx #$01 +; loop2: +; brk +; asl $05 +; asl $05,x +; asl $c001 +; asl $c001,x +; asl +; bne loop2 ;(-15 or $f1) +; brk +ORG +$0600 +$A9 $FF +$A2 $01 +$85 $05 +$95 $05 +$9D $00 $C0 +$E8 +$9D $00 $C0 +$A2 $01 +$00 $00 +$06 $05 +$16 $05 +$0E $01 $C0 +$1E $01 $C0 +$0A +$D0 $F1 +$00 $00 +; +; test program #5 +; Test ORA opcode with various arguments and addressing modes. +; At each break, the contents of Acc should equal $AA. +; +; start: +; lda #$aa ;%10101010 +; sta $05 +; sta $aa +; lda #$00 +; tax +; ora ($05,x) +; brk +; lda #$00 +; ora $05 +; brk +; lda #$00 +; ora #$aa +; brk +; lda #$00 +; ora $0005 +; brk +; lda #$05 +; sta $06 +; lda #$00 +; sta $07 +; tay +; ora ($06),y +; brk +; lda #$00 +; tax +; ora $05,x +; brk +; lda #$00 +; tay +; ora $0005,y +; brk +; lda #$00 +; tax +; ora $0005,x +; brk +ORG +$0700 +$A9 $AA +$85 $05 +$85 $AA +$A9 $00 +$AA +$01 $05 +$00 $00 +$A9 $00 +$05 $05 +$00 $00 +$A9 $00 +$09 $AA +$00 $00 +$A9 $00 +$0D $05 $00 +$00 $00 +$A9 $05 +$85 $06 +$A9 $00 +$85 $07 +$A8 +$11 $06 +$00 $00 +$A9 $00 +$AA +$15 $05 +$00 $00 +$A9 $00 +$A8 +$19 $05 $00 +$00 $00 +$A9 $00 +$AA +$1D $05 $00 +$00 $00 +; +; test program #6 +; Test JSR opcode. +; After each break examine memory at $c000 and $c001. +; After 1-st break, $c000 should equal $dd. +; Return address-1 ($0802) should be on stack. +; After 2-nd break, PC counter should be at $0805. +; After 3-rd break, $c000 should equal $ee. +; Return address-1 ($0807) should be on stack. +; After 4-th break, PC counter should be at $080a. +; +; start: +; jsr sub1 +; brk +; jsr sub2 +; brk +; brk +; brk +; sub1: +; lda #$dd +; sta $c000 +; brk +; rts +; sub2: +; lda #$ee +; sta $c000 +; brk +; rts +; +ORG +$0800 +$20 $0B $08 +$00 $00 +$20 $13 $08 +$00 +$00 +$00 +$A9 $DD +$8D $00 $C0 +$00 $00 +$60 +$A9 $EE +$8D $00 $C0 +$00 $00 +$60 +; +; test program #7 +; Test ADC opcode. +; Expected results: +; First break: Acc=$01, Carry=1 +; 2-nd break: Acc=$02, Carry=1 +; 3-rd break: Acc=$22, Carry=0 +; 4-th break: Acc=$23, Carry=0 +; +; start: +; clc +; lda #$ff +; adc #$02 +; brk +; sec +; lda #$ff +; adc #$02 +; brk +; clc +; lda #$20 +; adc #$02 +; brk +; sec +; lda #$20 +; adc #$02 +; brk +; +ORG +$0900 +$18 +$A9 $FF +$69 $02 +$00 $00 +$38 +$A9 $FF +$69 $02 +$00 $00 +$18 +$A9 $20 +$69 $02 +$00 $00 +$38 +$A9 $20 +$69 $02 +$00 $00 +; +; test program #8 +; Test ROR opcode. +; +; start: +; sec +; lda #$00 +; loop: +; ror +; brk +; bcc loop ;(-5 -> $FB) +; brk +; +ORG +$0920 +$38 +$A9 $00 +$6A +$00 $00 +$90 $FB +$00 $00 ; \ No newline at end of file diff --git a/dummy.rom b/dummy.rom index 9ce490e..43eaabb 100644 --- a/dummy.rom +++ b/dummy.rom @@ -1,315 +1,315 @@ -; -; test program #1 -; address: $0200 -; load Acc with value 12 -; write Acc to address $c000 (49152) -; -; nop -; nop -; lda #$0c -; sta $c000 -; brk -; -$EA $EA $A9 $0c $8D $00 $c0 $00 $00 -; -; test program #2 -; address: $0400 -; copy 0-terminated string from -; address $d000 to $0200 -; "Hello World!" -; -; ORG=$0400 -; hello: -; ldx #0 -; loop: -; lda $d000,x -; beq $06 ;branch to end (+6) if A=0 -; sta $0200,x -; inx -; bne $f5 ; branch to loop (-11) if X<>0 -; end: -; brk -ORG -$0400 -$A2 $00 -$BD $00 $d0 -$F0 $06 -$9D $00 $02 -$E8 -$D0 $F5 -$00 $00 -; data -; address: $d000 -ORG -$D000 -;DEC: 53248 -; "Hello World!" -72 101 108 108 111 32 87 111 114 108 100 33 0 -; -; test program #3 - copy Hello World! string to $0300 -; using different assembly instructions -; address: $0500 -; -; ORG=$0500 ;dec: 1280 -; hello: -; lda #0 -; sta $05 -; ldx $05 -; loop: -; lda $d000,x -; sta $0300,x -; beq end ;(+6) -; inx -; beq end ;(+3) -; jmp loop -; end: -; brk -ORG -$0500 -;DEC: 1280 -$A9 $00 -$85 $05 -$A6 $05 -$BD $00 $d0 -$9D $00 $03 -$F0 $06 -$E8 -$F0 $03 -$4C $06 $05 -$00 $00 -; -; test program #4 -; left-shift memory location $05 at zero page, -; then location $06 using zero page indexed addressing, -; then memory location $c001 (outside zero page) using absolute addressing -; then location $c002 using indexed absolute addressing -; and finally left-shift Acc. -; stop after each step for debugging -; exit loop when Acc=0 -; -; start: -; lda #$ff -; ldx #$01 -; sta $05 -; sta $05,x -; sta $c000,x -; inx -; sta $c000,x -; ldx #$01 -; loop2: -; brk -; asl $05 -; asl $05,x -; asl $c001 -; asl $c001,x -; asl -; bne loop2 ;(-15 or $f1) -; brk -ORG -$0600 -$A9 $FF -$A2 $01 -$85 $05 -$95 $05 -$9D $00 $C0 -$E8 -$9D $00 $C0 -$A2 $01 -$00 $00 -$06 $05 -$16 $05 -$0E $01 $C0 -$1E $01 $C0 -$0A -$D0 $F1 -$00 $00 -; -; test program #5 -; Test ORA opcode with various arguments and addressing modes. -; At each break, the contents of Acc should equal $AA. -; -; start: -; lda #$aa ;%10101010 -; sta $05 -; sta $aa -; lda #$00 -; tax -; ora ($05,x) -; brk -; lda #$00 -; ora $05 -; brk -; lda #$00 -; ora #$aa -; brk -; lda #$00 -; ora $0005 -; brk -; lda #$05 -; sta $06 -; lda #$00 -; sta $07 -; tay -; ora ($06),y -; brk -; lda #$00 -; tax -; ora $05,x -; brk -; lda #$00 -; tay -; ora $0005,y -; brk -; lda #$00 -; tax -; ora $0005,x -; brk -ORG -$0700 -$A9 $AA -$85 $05 -$85 $AA -$A9 $00 -$AA -$01 $05 -$00 $00 -$A9 $00 -$05 $05 -$00 $00 -$A9 $00 -$09 $AA -$00 $00 -$A9 $00 -$0D $05 $00 -$00 $00 -$A9 $05 -$85 $06 -$A9 $00 -$85 $07 -$A8 -$11 $06 -$00 $00 -$A9 $00 -$AA -$15 $05 -$00 $00 -$A9 $00 -$A8 -$19 $05 $00 -$00 $00 -$A9 $00 -$AA -$1D $05 $00 -$00 $00 -; -; test program #6 -; Test JSR opcode. -; After each break examine memory at $c000 and $c001. -; After 1-st break, $c000 should equal $dd. -; Return address-1 ($0802) should be on stack. -; After 2-nd break, PC counter should be at $0805. -; After 3-rd break, $c000 should equal $ee. -; Return address-1 ($0807) should be on stack. -; After 4-th break, PC counter should be at $080a. -; -; start: -; jsr sub1 -; brk -; jsr sub2 -; brk -; brk -; brk -; sub1: -; lda #$dd -; sta $c000 -; brk -; rts -; sub2: -; lda #$ee -; sta $c000 -; brk -; rts -; -ORG -$0800 -$20 $0B $08 -$00 $00 -$20 $13 $08 -$00 -$00 -$00 -$A9 $DD -$8D $00 $C0 -$00 $00 -$60 -$A9 $EE -$8D $00 $C0 -$00 $00 -$60 -; -; test program #7 -; Test ADC opcode. -; Expected results: -; First break: Acc=$01, Carry=1 -; 2-nd break: Acc=$02, Carry=1 -; 3-rd break: Acc=$22, Carry=0 -; 4-th break: Acc=$23, Carry=0 -; -; start: -; clc -; lda #$ff -; adc #$02 -; brk -; sec -; lda #$ff -; adc #$02 -; brk -; clc -; lda #$20 -; adc #$02 -; brk -; sec -; lda #$20 -; adc #$02 -; brk -; -ORG -$0900 -$18 -$A9 $FF -$69 $02 -$00 $00 -$38 -$A9 $FF -$69 $02 -$00 $00 -$18 -$A9 $20 -$69 $02 -$00 $00 -$38 -$A9 $20 -$69 $02 -$00 $00 -; -; test program #8 -; Test ROR opcode. -; -; start: -; sec -; lda #$00 -; loop: -; ror -; brk -; bcc loop ;(-5 -> $FB) -; brk -; -ORG -$0920 -$38 -$A9 $00 -$6A -$00 $00 -$90 $FB -$00 $00 +; +; test program #1 +; address: $0200 +; load Acc with value 12 +; write Acc to address $c000 (49152) +; +; nop +; nop +; lda #$0c +; sta $c000 +; brk +; +$EA $EA $A9 $0c $8D $00 $c0 $00 $00 +; +; test program #2 +; address: $0400 +; copy 0-terminated string from +; address $d000 to $0200 +; "Hello World!" +; +; ORG=$0400 +; hello: +; ldx #0 +; loop: +; lda $d000,x +; beq $06 ;branch to end (+6) if A=0 +; sta $0200,x +; inx +; bne $f5 ; branch to loop (-11) if X<>0 +; end: +; brk +ORG +$0400 +$A2 $00 +$BD $00 $d0 +$F0 $06 +$9D $00 $02 +$E8 +$D0 $F5 +$00 $00 +; data +; address: $d000 +ORG +$D000 +;DEC: 53248 +; "Hello World!" +72 101 108 108 111 32 87 111 114 108 100 33 0 +; +; test program #3 - copy Hello World! string to $0300 +; using different assembly instructions +; address: $0500 +; +; ORG=$0500 ;dec: 1280 +; hello: +; lda #0 +; sta $05 +; ldx $05 +; loop: +; lda $d000,x +; sta $0300,x +; beq end ;(+6) +; inx +; beq end ;(+3) +; jmp loop +; end: +; brk +ORG +$0500 +;DEC: 1280 +$A9 $00 +$85 $05 +$A6 $05 +$BD $00 $d0 +$9D $00 $03 +$F0 $06 +$E8 +$F0 $03 +$4C $06 $05 +$00 $00 +; +; test program #4 +; left-shift memory location $05 at zero page, +; then location $06 using zero page indexed addressing, +; then memory location $c001 (outside zero page) using absolute addressing +; then location $c002 using indexed absolute addressing +; and finally left-shift Acc. +; stop after each step for debugging +; exit loop when Acc=0 +; +; start: +; lda #$ff +; ldx #$01 +; sta $05 +; sta $05,x +; sta $c000,x +; inx +; sta $c000,x +; ldx #$01 +; loop2: +; brk +; asl $05 +; asl $05,x +; asl $c001 +; asl $c001,x +; asl +; bne loop2 ;(-15 or $f1) +; brk +ORG +$0600 +$A9 $FF +$A2 $01 +$85 $05 +$95 $05 +$9D $00 $C0 +$E8 +$9D $00 $C0 +$A2 $01 +$00 $00 +$06 $05 +$16 $05 +$0E $01 $C0 +$1E $01 $C0 +$0A +$D0 $F1 +$00 $00 +; +; test program #5 +; Test ORA opcode with various arguments and addressing modes. +; At each break, the contents of Acc should equal $AA. +; +; start: +; lda #$aa ;%10101010 +; sta $05 +; sta $aa +; lda #$00 +; tax +; ora ($05,x) +; brk +; lda #$00 +; ora $05 +; brk +; lda #$00 +; ora #$aa +; brk +; lda #$00 +; ora $0005 +; brk +; lda #$05 +; sta $06 +; lda #$00 +; sta $07 +; tay +; ora ($06),y +; brk +; lda #$00 +; tax +; ora $05,x +; brk +; lda #$00 +; tay +; ora $0005,y +; brk +; lda #$00 +; tax +; ora $0005,x +; brk +ORG +$0700 +$A9 $AA +$85 $05 +$85 $AA +$A9 $00 +$AA +$01 $05 +$00 $00 +$A9 $00 +$05 $05 +$00 $00 +$A9 $00 +$09 $AA +$00 $00 +$A9 $00 +$0D $05 $00 +$00 $00 +$A9 $05 +$85 $06 +$A9 $00 +$85 $07 +$A8 +$11 $06 +$00 $00 +$A9 $00 +$AA +$15 $05 +$00 $00 +$A9 $00 +$A8 +$19 $05 $00 +$00 $00 +$A9 $00 +$AA +$1D $05 $00 +$00 $00 +; +; test program #6 +; Test JSR opcode. +; After each break examine memory at $c000 and $c001. +; After 1-st break, $c000 should equal $dd. +; Return address-1 ($0802) should be on stack. +; After 2-nd break, PC counter should be at $0805. +; After 3-rd break, $c000 should equal $ee. +; Return address-1 ($0807) should be on stack. +; After 4-th break, PC counter should be at $080a. +; +; start: +; jsr sub1 +; brk +; jsr sub2 +; brk +; brk +; brk +; sub1: +; lda #$dd +; sta $c000 +; brk +; rts +; sub2: +; lda #$ee +; sta $c000 +; brk +; rts +; +ORG +$0800 +$20 $0B $08 +$00 $00 +$20 $13 $08 +$00 +$00 +$00 +$A9 $DD +$8D $00 $C0 +$00 $00 +$60 +$A9 $EE +$8D $00 $C0 +$00 $00 +$60 +; +; test program #7 +; Test ADC opcode. +; Expected results: +; First break: Acc=$01, Carry=1 +; 2-nd break: Acc=$02, Carry=1 +; 3-rd break: Acc=$22, Carry=0 +; 4-th break: Acc=$23, Carry=0 +; +; start: +; clc +; lda #$ff +; adc #$02 +; brk +; sec +; lda #$ff +; adc #$02 +; brk +; clc +; lda #$20 +; adc #$02 +; brk +; sec +; lda #$20 +; adc #$02 +; brk +; +ORG +$0900 +$18 +$A9 $FF +$69 $02 +$00 $00 +$38 +$A9 $FF +$69 $02 +$00 $00 +$18 +$A9 $20 +$69 $02 +$00 $00 +$38 +$A9 $20 +$69 $02 +$00 $00 +; +; test program #8 +; Test ROR opcode. +; +; start: +; sec +; lda #$00 +; loop: +; ror +; brk +; bcc loop ;(-5 -> $FB) +; brk +; +ORG +$0920 +$38 +$A9 $00 +$6A +$00 $00 +$90 $FB +$00 $00 ; \ No newline at end of file diff --git a/eh_basic.asm b/eh_basic.asm new file mode 100644 index 0000000..b8796ad --- /dev/null +++ b/eh_basic.asm @@ -0,0 +1,8723 @@ +; The code below was copied and adapted from Lee Davison’s +; code of EhBasic to be ran in MKBASIC (VM65) 6502 emulator. +; Original comments and credits follow: +; +; Enhanced BASIC to assemble under 6502 simulator, $ver 2.22 + +; $E7E1 $E7CF $E7C6 $E7D3 $E7D1 $E7D5 $E7CF $E81E $E825 + +; 2.00 new revision numbers start here +; 2.01 fixed LCASE$() and UCASE$() +; 2.02 new get value routine done +; 2.03 changed RND() to galoise method +; 2.04 fixed SPC() +; 2.05 new get value routine fixed +; 2.06 changed USR() code +; 2.07 fixed STR$() +; 2.08 changed INPUT and READ to remove need for $00 start to input buffer +; 2.09 fixed RND() +; 2.10 integrated missed changes from an earlier version +; 2.20 added ELSE to IF .. THEN and fixed IF .. GOTO to cause error +; 2.21 fixed IF .. THEN RETURN to not cause error +; 2.22 fixed RND() breaking the get byte routine + +; zero page use .. + +LAB_WARM = $00 ; BASIC warm start entry point +Wrmjpl = LAB_WARM+1; BASIC warm start vector jump low byte +Wrmjph = LAB_WARM+2; BASIC warm start vector jump high byte + +Usrjmp = $0A ; USR function JMP address +Usrjpl = Usrjmp+1 ; USR function JMP vector low byte +Usrjph = Usrjmp+2 ; USR function JMP vector high byte +Nullct = $0D ; nulls output after each line +TPos = $0E ; BASIC terminal position byte +TWidth = $0F ; BASIC terminal width byte +Iclim = $10 ; input column limit +Itempl = $11 ; temporary integer low byte +Itemph = Itempl+1 ; temporary integer high byte + +nums_1 = Itempl ; number to bin/hex string convert MSB +nums_2 = nums_1+1 ; number to bin/hex string convert +nums_3 = nums_1+2 ; number to bin/hex string convert LSB + +Srchc = $5B ; search character +Temp3 = Srchc ; temp byte used in number routines +Scnquo = $5C ; scan-between-quotes flag +Asrch = Scnquo ; alt search character + +XOAw_l = Srchc ; eXclusive OR, OR and AND word low byte +XOAw_h = Scnquo ; eXclusive OR, OR and AND word high byte + +Ibptr = $5D ; input buffer pointer +Dimcnt = Ibptr ; # of dimensions +Tindx = Ibptr ; token index + +Defdim = $5E ; default DIM flag +Dtypef = $5F ; data type flag, $FF=string, $00=numeric +Oquote = $60 ; open quote flag (b7) (Flag: DATA scan; LIST quote; memory) +Gclctd = $60 ; garbage collected flag +Sufnxf = $61 ; subscript/FNX flag, 1xxx xxx = FN(0xxx xxx) +Imode = $62 ; input mode flag, $00=INPUT, $80=READ + +Cflag = $63 ; comparison evaluation flag + +TabSiz = $64 ; TAB step size (was input flag) + +next_s = $65 ; next descriptor stack address + + ; these two bytes form a word pointer to the item + ; currently on top of the descriptor stack +last_sl = $66 ; last descriptor stack address low byte +last_sh = $67 ; last descriptor stack address high byte (always $00) + +des_sk = $68 ; descriptor stack start address (temp strings) + +; = $70 ; End of descriptor stack + +ut1_pl = $71 ; utility pointer 1 low byte +ut1_ph = ut1_pl+1 ; utility pointer 1 high byte +ut2_pl = $73 ; utility pointer 2 low byte +ut2_ph = ut2_pl+1 ; utility pointer 2 high byte + +Temp_2 = ut1_pl ; temp byte for block move + +FACt_1 = $75 ; FAC temp mantissa1 +FACt_2 = FACt_1+1 ; FAC temp mantissa2 +FACt_3 = FACt_2+1 ; FAC temp mantissa3 + +dims_l = FACt_2 ; array dimension size low byte +dims_h = FACt_3 ; array dimension size high byte + +TempB = $78 ; temp page 0 byte + +Smeml = $79 ; start of mem low byte (Start-of-Basic) +Smemh = Smeml+1 ; start of mem high byte (Start-of-Basic) +Svarl = $7B ; start of vars low byte (Start-of-Variables) +Svarh = Svarl+1 ; start of vars high byte (Start-of-Variables) +Sarryl = $7D ; var mem end low byte (Start-of-Arrays) +Sarryh = Sarryl+1 ; var mem end high byte (Start-of-Arrays) +Earryl = $7F ; array mem end low byte (End-of-Arrays) +Earryh = Earryl+1 ; array mem end high byte (End-of-Arrays) +Sstorl = $81 ; string storage low byte (String storage (moving down)) +Sstorh = Sstorl+1 ; string storage high byte (String storage (moving down)) +Sutill = $83 ; string utility ptr low byte +Sutilh = Sutill+1 ; string utility ptr high byte +Ememl = $85 ; end of mem low byte (Limit-of-memory) +Ememh = Ememl+1 ; end of mem high byte (Limit-of-memory) +Clinel = $87 ; current line low byte (Basic line number) +Clineh = Clinel+1 ; current line high byte (Basic line number) +Blinel = $89 ; break line low byte (Previous Basic line number) +Blineh = Blinel+1 ; break line high byte (Previous Basic line number) + +Cpntrl = $8B ; continue pointer low byte +Cpntrh = Cpntrl+1 ; continue pointer high byte + +Dlinel = $8D ; current DATA line low byte +Dlineh = Dlinel+1 ; current DATA line high byte + +Dptrl = $8F ; DATA pointer low byte +Dptrh = Dptrl+1 ; DATA pointer high byte + +Rdptrl = $91 ; read pointer low byte +Rdptrh = Rdptrl+1 ; read pointer high byte + +Varnm1 = $93 ; current var name 1st byte +Varnm2 = Varnm1+1 ; current var name 2nd byte + +Cvaral = $95 ; current var address low byte +Cvarah = Cvaral+1 ; current var address high byte + +Frnxtl = $97 ; var pointer for FOR/NEXT low byte +Frnxth = Frnxtl+1 ; var pointer for FOR/NEXT high byte + +Tidx1 = Frnxtl ; temp line index + +Lvarpl = Frnxtl ; let var pointer low byte +Lvarph = Frnxth ; let var pointer high byte + +prstk = $99 ; precedence stacked flag + +comp_f = $9B ; compare function flag, bits 0,1 and 2 used + ; bit 2 set if > + ; bit 1 set if = + ; bit 0 set if < + +func_l = $9C ; function pointer low byte +func_h = func_l+1 ; function pointer high byte + +garb_l = func_l ; garbage collection working pointer low byte +garb_h = func_h ; garbage collection working pointer high byte + +des_2l = $9E ; string descriptor_2 pointer low byte +des_2h = des_2l+1 ; string descriptor_2 pointer high byte + +g_step = $A0 ; garbage collect step size + +Fnxjmp = $A1 ; jump vector for functions +Fnxjpl = Fnxjmp+1 ; functions jump vector low byte +Fnxjph = Fnxjmp+2 ; functions jump vector high byte + +g_indx = Fnxjpl ; garbage collect temp index + +FAC2_r = $A3 ; FAC2 rounding byte + +Adatal = $A4 ; array data pointer low byte +Adatah = Adatal+1 ; array data pointer high byte + +Nbendl = Adatal ; new block end pointer low byte +Nbendh = Adatah ; new block end pointer high byte + +Obendl = $A6 ; old block end pointer low byte +Obendh = Obendl+1 ; old block end pointer high byte + +numexp = $A8 ; string to float number exponent count +expcnt = $A9 ; string to float exponent count + +numbit = numexp ; bit count for array element calculations + +numdpf = $AA ; string to float decimal point flag +expneg = $AB ; string to float eval exponent -ve flag + +Astrtl = numdpf ; array start pointer low byte +Astrth = expneg ; array start pointer high byte + +Histrl = numdpf ; highest string low byte +Histrh = expneg ; highest string high byte + +Baslnl = numdpf ; BASIC search line pointer low byte +Baslnh = expneg ; BASIC search line pointer high byte + +Fvar_l = numdpf ; find/found variable pointer low byte +Fvar_h = expneg ; find/found variable pointer high byte + +Ostrtl = numdpf ; old block start pointer low byte +Ostrth = expneg ; old block start pointer high byte + +Vrschl = numdpf ; variable search pointer low byte +Vrschh = expneg ; variable search pointer high byte + +FAC1_e = $AC ; FAC1 exponent +FAC1_1 = FAC1_e+1 ; FAC1 mantissa1 +FAC1_2 = FAC1_e+2 ; FAC1 mantissa2 +FAC1_3 = FAC1_e+3 ; FAC1 mantissa3 +FAC1_s = FAC1_e+4 ; FAC1 sign (b7) + +str_ln = FAC1_e ; string length +str_pl = FAC1_1 ; string pointer low byte +str_ph = FAC1_2 ; string pointer high byte + +des_pl = FAC1_2 ; string descriptor pointer low byte +des_ph = FAC1_3 ; string descriptor pointer high byte + +mids_l = FAC1_3 ; MID$ string temp length byte + +negnum = $B1 ; string to float eval -ve flag +numcon = $B1 ; series evaluation constant count + +FAC1_o = $B2 ; FAC1 overflow byte + +FAC2_e = $B3 ; FAC2 exponent +FAC2_1 = FAC2_e+1 ; FAC2 mantissa1 +FAC2_2 = FAC2_e+2 ; FAC2 mantissa2 +FAC2_3 = FAC2_e+3 ; FAC2 mantissa3 +FAC2_s = FAC2_e+4 ; FAC2 sign (b7) + +FAC_sc = $B8 ; FAC sign comparison, Acc#1 vs #2 +FAC1_r = $B9 ; FAC1 rounding byte + +ssptr_l = FAC_sc ; string start pointer low byte +ssptr_h = FAC1_r ; string start pointer high byte + +sdescr = FAC_sc ; string descriptor pointer + +csidx = $BA ; line crunch save index +Asptl = csidx ; array size/pointer low byte +Aspth = $BB ; array size/pointer high byte + +Btmpl = Asptl ; BASIC pointer temp low byte +Btmph = Aspth ; BASIC pointer temp low byte + +Cptrl = Asptl ; BASIC pointer temp low byte +Cptrh = Aspth ; BASIC pointer temp low byte + +Sendl = Asptl ; BASIC pointer temp low byte +Sendh = Aspth ; BASIC pointer temp low byte + +LAB_IGBY = $BC ; get next BASIC byte subroutine + +LAB_GBYT = $C2 ; get current BASIC byte subroutine +Bpntrl = $C3 ; BASIC execute (get byte) pointer low byte +Bpntrh = Bpntrl+1 ; BASIC execute (get byte) pointer high byte + +; = $D7 ; end of get BASIC char subroutine + +Rbyte4 = $D8 ; extra PRNG byte +Rbyte1 = Rbyte4+1 ; most significant PRNG byte +Rbyte2 = Rbyte4+2 ; middle PRNG byte +Rbyte3 = Rbyte4+3 ; least significant PRNG byte + +NmiBase = $DC ; NMI handler enabled/setup/triggered flags + ; bit function + ; === ======== + ; 7 interrupt enabled + ; 6 interrupt setup + ; 5 interrupt happened +; = $DD ; NMI handler addr low byte +; = $DE ; NMI handler addr high byte +IrqBase = $DF ; IRQ handler enabled/setup/triggered flags +; = $E0 ; IRQ handler addr low byte +; = $E1 ; IRQ handler addr high byte + +; = $DE ; unused +; = $DF ; unused +; = $E0 ; unused +; = $E1 ; unused +; = $E2 ; unused +; = $E3 ; unused +; = $E4 ; unused +; = $E5 ; unused +; = $E6 ; unused +; = $E7 ; unused +; = $E8 ; unused +; = $E9 ; unused +; = $EA ; unused +; = $EB ; unused +; = $EC ; unused +; = $ED ; unused +; = $EE ; unused + +Decss = $EF ; number to decimal string start +Decssp1 = Decss+1 ; number to decimal string start + +; = $FF ; decimal string end + +; token values needed for BASIC + +; primary command tokens (can start a statement) + +TK_END = $80 ; END token +TK_FOR = TK_END+1 ; FOR token +TK_NEXT = TK_FOR+1 ; NEXT token +TK_DATA = TK_NEXT+1 ; DATA token +TK_INPUT = TK_DATA+1 ; INPUT token +TK_DIM = TK_INPUT+1 ; DIM token +TK_READ = TK_DIM+1 ; READ token +TK_LET = TK_READ+1 ; LET token +TK_DEC = TK_LET+1 ; DEC token +TK_GOTO = TK_DEC+1 ; GOTO token +TK_RUN = TK_GOTO+1 ; RUN token +TK_IF = TK_RUN+1 ; IF token +TK_RESTORE = TK_IF+1 ; RESTORE token +TK_GOSUB = TK_RESTORE+1 ; GOSUB token +TK_RETIRQ = TK_GOSUB+1 ; RETIRQ token +TK_RETNMI = TK_RETIRQ+1 ; RETNMI token +TK_RETURN = TK_RETNMI+1 ; RETURN token +TK_REM = TK_RETURN+1 ; REM token +TK_STOP = TK_REM+1 ; STOP token +TK_ON = TK_STOP+1 ; ON token +TK_NULL = TK_ON+1 ; NULL token +TK_INC = TK_NULL+1 ; INC token +TK_WAIT = TK_INC+1 ; WAIT token +TK_LOAD = TK_WAIT+1 ; LOAD token +TK_SAVE = TK_LOAD+1 ; SAVE token +TK_DEF = TK_SAVE+1 ; DEF token +TK_POKE = TK_DEF+1 ; POKE token +TK_DOKE = TK_POKE+1 ; DOKE token +TK_CALL = TK_DOKE+1 ; CALL token +TK_DO = TK_CALL+1 ; DO token +TK_LOOP = TK_DO+1 ; LOOP token +TK_PRINT = TK_LOOP+1 ; PRINT token +TK_CONT = TK_PRINT+1 ; CONT token +TK_LIST = TK_CONT+1 ; LIST token +TK_CLEAR = TK_LIST+1 ; CLEAR token +TK_NEW = TK_CLEAR+1 ; NEW token +TK_WIDTH = TK_NEW+1 ; WIDTH token +TK_GET = TK_WIDTH+1 ; GET token +TK_SWAP = TK_GET+1 ; SWAP token +TK_BITSET = TK_SWAP+1 ; BITSET token +TK_BITCLR = TK_BITSET+1 ; BITCLR token +TK_IRQ = TK_BITCLR+1 ; IRQ token +TK_NMI = TK_IRQ+1 ; NMI token + +; secondary command tokens, can't start a statement + +TK_TAB = TK_NMI+1 ; TAB token +TK_ELSE = TK_TAB+1 ; ELSE token +TK_TO = TK_ELSE+1 ; TO token +TK_FN = TK_TO+1 ; FN token +TK_SPC = TK_FN+1 ; SPC token +TK_THEN = TK_SPC+1 ; THEN token +TK_NOT = TK_THEN+1 ; NOT token +TK_STEP = TK_NOT+1 ; STEP token +TK_UNTIL = TK_STEP+1 ; UNTIL token +TK_WHILE = TK_UNTIL+1 ; WHILE token +TK_OFF = TK_WHILE+1 ; OFF token + +; opperator tokens + +TK_PLUS = TK_OFF+1 ; + token +TK_MINUS = TK_PLUS+1 ; - token +TK_MUL = TK_MINUS+1 ; * token +TK_DIV = TK_MUL+1 ; / token +TK_POWER = TK_DIV+1 ; ^ token +TK_AND = TK_POWER+1 ; AND token +TK_EOR = TK_AND+1 ; EOR token +TK_OR = TK_EOR+1 ; OR token +TK_RSHIFT = TK_OR+1 ; RSHIFT token +TK_LSHIFT = TK_RSHIFT+1 ; LSHIFT token +TK_GT = TK_LSHIFT+1 ; > token +TK_EQUAL = TK_GT+1 ; = token +TK_LT = TK_EQUAL+1 ; < token + +; functions tokens + +TK_SGN = TK_LT+1 ; SGN token +TK_INT = TK_SGN+1 ; INT token +TK_ABS = TK_INT+1 ; ABS token +TK_USR = TK_ABS+1 ; USR token +TK_FRE = TK_USR+1 ; FRE token +TK_POS = TK_FRE+1 ; POS token +TK_SQR = TK_POS+1 ; SQR token +TK_RND = TK_SQR+1 ; RND token +TK_LOG = TK_RND+1 ; LOG token +TK_EXP = TK_LOG+1 ; EXP token +TK_COS = TK_EXP+1 ; COS token +TK_SIN = TK_COS+1 ; SIN token +TK_TAN = TK_SIN+1 ; TAN token +TK_ATN = TK_TAN+1 ; ATN token +TK_PEEK = TK_ATN+1 ; PEEK token +TK_DEEK = TK_PEEK+1 ; DEEK token +TK_SADD = TK_DEEK+1 ; SADD token +TK_LEN = TK_SADD+1 ; LEN token +TK_STRS = TK_LEN+1 ; STR$ token +TK_VAL = TK_STRS+1 ; VAL token +TK_ASC = TK_VAL+1 ; ASC token +TK_UCASES = TK_ASC+1 ; UCASE$ token +TK_LCASES = TK_UCASES+1 ; LCASE$ token +TK_CHRS = TK_LCASES+1 ; CHR$ token +TK_HEXS = TK_CHRS+1 ; HEX$ token +TK_BINS = TK_HEXS+1 ; BIN$ token +TK_BITTST = TK_BINS+1 ; BITTST token +TK_MAX = TK_BITTST+1 ; MAX token +TK_MIN = TK_MAX+1 ; MIN token +TK_PI = TK_MIN+1 ; PI token +TK_TWOPI = TK_PI+1 ; TWOPI token +TK_VPTR = TK_TWOPI+1 ; VARPTR token +TK_LEFTS = TK_VPTR+1 ; LEFT$ token +TK_RIGHTS = TK_LEFTS+1 ; RIGHT$ token +TK_MIDS = TK_RIGHTS+1 ; MID$ token + +; offsets from a base of X or Y + +PLUS_0 = $00 ; X or Y plus 0 +PLUS_1 = $01 ; X or Y plus 1 +PLUS_2 = $02 ; X or Y plus 2 +PLUS_3 = $03 ; X or Y plus 3 + +LAB_STAK = $0100 ; stack bottom, no offset + +LAB_SKFE = LAB_STAK+$FE + ; flushed stack address +LAB_SKFF = LAB_STAK+$FF + ; flushed stack address + +ccflag = $0200 ; BASIC CTRL-C flag, 00 = enabled, 01 = dis +ccbyte = ccflag+1 ; BASIC CTRL-C byte +ccnull = ccbyte+1 ; BASIC CTRL-C byte timeout + +VEC_CC = ccnull+1 ; ctrl c check vector + +VEC_IN = VEC_CC+2 ; input vector +VEC_OUT = VEC_IN+2 ; output vector +VEC_LD = VEC_OUT+2 ; load vector +VEC_SV = VEC_LD+2 ; save vector + +; Ibuffs can now be anywhere in RAM, ensure that the max length is < $80 + +IRQ_vec = VEC_SV+2 + +Ibuffs = IRQ_vec+$14 ; start of input buffer after IRQ/NMI code +Ibuffe = Ibuffs+$47 ; end of input buffer + + .ORG $FFC0 + +; I/O routines for MKBASIC (V65) emulator. + +CHRIN + LDA $FFE1 ; Read from char IO address, non-blocking + BEQ ECHRIN ; if null, assume no character in buffer + CMP #'a' ; < 'a'? + BCC DCHRIN ; yes, done + CMP #'{' ; >= '{'? + BCS DCHRIN ; yes, done + AND #$5F ; no, convert to upper case +DCHRIN + SEC ; These is character waiting, set CARRY flag + RTS +ECHRIN + CLC ; no character in buffer, clear CARRY + RTS + +CHROUT + STA $FFE0 ; write to char IO address + AND #$FF ; set flags + RTS + + +Ram_base = $0300 ; start of user RAM (set as needed, should be page aligned) +Ram_top = $C000 ; end of user RAM+1 (set as needed, should be page aligned) + +; This start can be changed to suit your system + + *= $C000 + +; BASIC cold start entry point + +; new page 2 initialisation, copy block to ccflag on + +LAB_COLD + CLD + LDY #PG2_TABE-PG2_TABS-1 + ; byte count-1 +LAB_2D13 + LDA PG2_TABS,Y ; get byte + STA ccflag,Y ; store in page 2 + DEY ; decrement count + BPL LAB_2D13 ; loop if not done + + LDX #$FF ; set byte + STX Ibuffs + STX Clineh ; set current line high byte (set immediate mode) + TXS ; reset stack pointer + + LDA #$4C ; code for JMP + STA Fnxjmp ; save for jump vector for functions + +; copy block from LAB_2CEE to $00BC - $00D3 + + LDX #StrTab-LAB_2CEE ; set byte count +LAB_2D4E + LDA LAB_2CEE-1,X ; get byte from table + STA LAB_IGBY-1,X ; save byte in page zero + DEX ; decrement count + BNE LAB_2D4E ; loop if not all done + +; copy block from StrTab to $0000 - $0012 + +LAB_GMEM + LDX #EndTab-StrTab-1 ; set byte count-1 +TabLoop + LDA StrTab,X ; get byte from table + STA PLUS_0,X ; save byte in page zero + DEX ; decrement count + BPL TabLoop ; loop if not all done + +; set-up start values + + LDA #$00 ; clear A + STA NmiBase ; clear NMI handler enabled flag + STA IrqBase ; clear IRQ handler enabled flag + STA FAC1_o ; clear FAC1 overflow byte + STA last_sh ; clear descriptor stack top item pointer high byte + + LDA #$0E ; set default tab size + STA TabSiz ; save it + LDA #$03 ; set garbage collect step size for descriptor stack + STA g_step ; save it + LDX #des_sk ; descriptor stack start + STX next_s ; set descriptor stack pointer + JSR LAB_CRLF ; print CR/LF + LDA #LAB_MSZM ; point to memory size message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + JSR LAB_INLN ; print "? " and get BASIC input + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; get last byte back + + BNE LAB_2DAA ; branch if not null (user typed something) + + LDY #$00 ; else clear Y + ; character was null so get memory size the hard way + ; we get here with Y=0 and Itempl/h = Ram_base +LAB_2D93 + INC Itempl ; increment temporary integer low byte + BNE LAB_2D99 ; branch if no overflow + + INC Itemph ; increment temporary integer high byte + LDA Itemph ; get high byte + CMP #>Ram_top ; compare with top of RAM+1 + BEQ LAB_2DB6 ; branch if match (end of user RAM) + +LAB_2D99 + LDA #$55 ; set test byte + STA (Itempl),Y ; save via temporary integer + CMP (Itempl),Y ; compare via temporary integer + BNE LAB_2DB6 ; branch if fail + + ASL ; shift test byte left (now $AA) + STA (Itempl),Y ; save via temporary integer + CMP (Itempl),Y ; compare via temporary integer + BEQ LAB_2D93 ; if ok go do next byte + + BNE LAB_2DB6 ; branch if fail + +LAB_2DAA + JSR LAB_2887 ; get FAC1 from string + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_GMEM ; if too large go try again + + JSR LAB_F2FU ; save integer part of FAC1 in temporary integer + ; (no range check) + +LAB_2DB6 + LDA Itempl ; get temporary integer low byte + LDY Itemph ; get temporary integer high byte + CPY #Ram_top ; compare with top of RAM high byte +; BCC MEM_OK ; branch if < RAM top + +; BNE LAB_GMEM ; if too large go try again + ; else was = so compare low bytes +; CMP #Ram_base ; set start addr high byte + STY Smeml ; save start of mem low byte + STX Smemh ; save start of mem high byte + +; this line is only needed if Ram_base is not $xx00 + +; LDY #$00 ; clear Y + TYA ; clear A + STA (Smeml),Y ; clear first byte + INC Smeml ; increment start of mem low byte + +; these two lines are only needed if Ram_base is $xxFF + +; BNE LAB_2E05 ; branch if no rollover + +; INC Smemh ; increment start of mem high byte +LAB_2E05 + JSR LAB_CRLF ; print CR/LF + JSR LAB_1463 ; do "NEW" and "CLEAR" + LDA Ememl ; get end of mem low byte + SEC ; set carry for subtract + SBC Smeml ; subtract start of mem low byte + TAX ; copy to X + LDA Ememh ; get end of mem high byte + SBC Smemh ; subtract start of mem high byte + JSR LAB_295E ; print XA as unsigned integer (bytes free) + LDA #LAB_SMSG ; point to sign-on message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + LDA #LAB_1274 ; warm start vector high byte + STA Wrmjpl ; save warm start vector low byte + STY Wrmjph ; save warm start vector high byte + JMP (Wrmjpl) ; go do warm start + +; open up space in memory +; move (Ostrtl)-(Obendl) to new block ending at (Nbendl) + +; Nbendl,Nbendh - new block end address (A/Y) +; Obendl,Obendh - old block end address +; Ostrtl,Ostrth - old block start address + +; returns with .. + +; Nbendl,Nbendh - new block start address (high byte - $100) +; Obendl,Obendh - old block start address (high byte - $100) +; Ostrtl,Ostrth - old block start address (unchanged) + +LAB_11CF + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + STA Earryl ; save new array mem end low byte + STY Earryh ; save new array mem end high byte + +; open up space in memory +; move (Ostrtl)-(Obendl) to new block ending at (Nbendl) +; don't set array end + +LAB_11D6 + SEC ; set carry for subtract + LDA Obendl ; get block end low byte + SBC Ostrtl ; subtract block start low byte + TAY ; copy MOD(block length/$100) byte to Y + LDA Obendh ; get block end high byte + SBC Ostrth ; subtract block start high byte + TAX ; copy block length high byte to X + INX ; +1 to allow for count=0 exit + TYA ; copy block length low byte to A + BEQ LAB_120A ; branch if length low byte=0 + + ; block is (X-1)*256+Y bytes, do the Y bytes first + + SEC ; set carry for add + 1, two's complement + EOR #$FF ; invert low byte for subtract + ADC Obendl ; add block end low byte + + STA Obendl ; save corrected old block end low byte + BCS LAB_11F3 ; branch if no underflow + + DEC Obendh ; else decrement block end high byte + SEC ; set carry for add + 1, two's complement +LAB_11F3 + TYA ; get MOD(block length/$100) byte + EOR #$FF ; invert low byte for subtract + ADC Nbendl ; add destination end low byte + STA Nbendl ; save modified new block end low byte + BCS LAB_1203 ; branch if no underflow + + DEC Nbendh ; else decrement block end high byte + BCC LAB_1203 ; branch always + +LAB_11FF + LDA (Obendl),Y ; get byte from source + STA (Nbendl),Y ; copy byte to destination +LAB_1203 + DEY ; decrement index + BNE LAB_11FF ; loop until Y=0 + + ; now do Y=0 indexed byte + LDA (Obendl),Y ; get byte from source + STA (Nbendl),Y ; save byte to destination +LAB_120A + DEC Obendh ; decrement source pointer high byte + DEC Nbendh ; decrement destination pointer high byte + DEX ; decrement block count + BNE LAB_1203 ; loop until count = $0 + + RTS + +; check room on stack for A bytes +; stack too deep? do OM error + +LAB_1212 + STA TempB ; save result in temp byte + TSX ; copy stack + CPX TempB ; compare new "limit" with stack + BCC LAB_OMER ; if stack < limit do "Out of memory" error then warm start + + RTS + +; check available memory, "Out of memory" error if no room +; addr to check is in AY (low/high) + +LAB_121F + CPY Sstorh ; compare bottom of string mem high byte + BCC LAB_124B ; if less then exit (is ok) + + BNE LAB_1229 ; skip next test if greater (tested <) + + ; high byte was =, now do low byte + CMP Sstorl ; compare with bottom of string mem low byte + BCC LAB_124B ; if less then exit (is ok) + + ; addr is > string storage ptr (oops!) +LAB_1229 + PHA ; push addr low byte + LDX #$08 ; set index to save Adatal to expneg inclusive + TYA ; copy addr high byte (to push on stack) + + ; save misc numeric work area +LAB_122D + PHA ; push byte + LDA Adatal-1,X ; get byte from Adatal to expneg ( ,$00 not pushed) + DEX ; decrement index + BPL LAB_122D ; loop until all done + + JSR LAB_GARB ; garbage collection routine + + ; restore misc numeric work area + LDX #$00 ; clear the index to restore bytes +LAB_1238 + PLA ; pop byte + STA Adatal,X ; save byte to Adatal to expneg + INX ; increment index + CPX #$08 ; compare with end + 1 + BMI LAB_1238 ; loop if more to do + + PLA ; pop addr high byte + TAY ; copy back to Y + PLA ; pop addr low byte + CPY Sstorh ; compare bottom of string mem high byte + BCC LAB_124B ; if less then exit (is ok) + + BNE LAB_OMER ; if greater do "Out of memory" error then warm start + + ; high byte was =, now do low byte + CMP Sstorl ; compare with bottom of string mem low byte + BCS LAB_OMER ; if >= do "Out of memory" error then warm start + + ; ok exit, carry clear +LAB_124B + RTS + +; do "Out of memory" error then warm start + +LAB_OMER + LDX #$0C ; error code $0C ("Out of memory" error) + +; do error #X, then warm start + +LAB_XERR + JSR LAB_CRLF ; print CR/LF + + LDA LAB_BAER,X ; get error message pointer low byte + LDY LAB_BAER+1,X ; get error message pointer high byte + JSR LAB_18C3 ; print null terminated string from memory + + JSR LAB_1491 ; flush stack and clear continue flag + LDA #LAB_EMSG ; point to " Error" high addr +LAB_1269 + JSR LAB_18C3 ; print null terminated string from memory + LDY Clineh ; get current line high byte + INY ; increment it + BEQ LAB_1274 ; go do warm start (was immediate mode) + + ; else print line number + JSR LAB_2953 ; print " in line [LINE #]" + +; BASIC warm start entry point +; wait for Basic command + +LAB_1274 + ; clear ON IRQ/NMI bytes + LDA #$00 ; clear A + STA IrqBase ; clear enabled byte + STA NmiBase ; clear enabled byte + LDA #LAB_RMSG ; point to "Ready" message high byte + + JSR LAB_18C3 ; go do print string + CLC + +; wait for Basic command (no "Ready") + +LAB_127D + JSR LAB_1357 ; call for BASIC input +LAB_1280 + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_127D ; loop while null + +; got to interpret input line now .. + + LDX #$FF ; current line to null value + STX Clineh ; set current line high byte + BCC LAB_1295 ; branch if numeric character (handle new BASIC line) + + ; no line number .. immediate mode + JSR LAB_13A6 ; crunch keywords into Basic tokens + JMP LAB_15F6 ; go scan and interpret code + +; handle new BASIC line + +LAB_1295 + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_13A6 ; crunch keywords into Basic tokens + STY Ibptr ; save index pointer to end of crunched line + JSR LAB_SSLN ; search BASIC for temp integer line number + BCC LAB_12E6 ; branch if not found + + ; aroooogah! line # already exists! delete it + LDY #$01 ; set index to next line pointer high byte + LDA (Baslnl),Y ; get next line pointer high byte + STA ut1_ph ; save it + LDA Svarl ; get start of vars low byte + STA ut1_pl ; save it + LDA Baslnh ; get found line pointer high byte + STA ut2_ph ; save it + LDA Baslnl ; get found line pointer low byte + DEY ; decrement index + SBC (Baslnl),Y ; subtract next line pointer low byte + CLC ; clear carry for add + ADC Svarl ; add start of vars low byte + STA Svarl ; save new start of vars low byte + STA ut2_pl ; save destination pointer low byte + LDA Svarh ; get start of vars high byte + ADC #$FF ; -1 + carry + STA Svarh ; save start of vars high byte + SBC Baslnh ; subtract found line pointer high byte + TAX ; copy to block count + SEC ; set carry for subtract + LDA Baslnl ; get found line pointer low byte + SBC Svarl ; subtract start of vars low byte + TAY ; copy to bytes in first block count + BCS LAB_12D0 ; branch if overflow + + INX ; increment block count (correct for =0 loop exit) + DEC ut2_ph ; decrement destination high byte +LAB_12D0 + CLC ; clear carry for add + ADC ut1_pl ; add source pointer low byte + BCC LAB_12D8 ; branch if no overflow + + DEC ut1_ph ; else decrement source pointer high byte + CLC ; clear carry + + ; close up memory to delete old line +LAB_12D8 + LDA (ut1_pl),Y ; get byte from source + STA (ut2_pl),Y ; copy to destination + INY ; increment index + BNE LAB_12D8 ; while <> 0 do this block + + INC ut1_ph ; increment source pointer high byte + INC ut2_ph ; increment destination pointer high byte + DEX ; decrement block count + BNE LAB_12D8 ; loop until all done + + ; got new line in buffer and no existing same # +LAB_12E6 + LDA Ibuffs ; get byte from start of input buffer + BEQ LAB_1319 ; if null line just go flush stack/vars and exit + + ; got new line and it isn't empty line + LDA Ememl ; get end of mem low byte + LDY Ememh ; get end of mem high byte + STA Sstorl ; set bottom of string space low byte + STY Sstorh ; set bottom of string space high byte + LDA Svarl ; get start of vars low byte (end of BASIC) + STA Obendl ; save old block end low byte + LDY Svarh ; get start of vars high byte (end of BASIC) + STY Obendh ; save old block end high byte + ADC Ibptr ; add input buffer pointer (also buffer length) + BCC LAB_1301 ; branch if no overflow from add + + INY ; else increment high byte +LAB_1301 + STA Nbendl ; save new block end low byte (move to, low byte) + STY Nbendh ; save new block end high byte + JSR LAB_11CF ; open up space in memory + ; old start pointer Ostrtl,Ostrth set by the find line call + LDA Earryl ; get array mem end low byte + LDY Earryh ; get array mem end high byte + STA Svarl ; save start of vars low byte + STY Svarh ; save start of vars high byte + LDY Ibptr ; get input buffer pointer (also buffer length) + DEY ; adjust for loop type +LAB_1311 + LDA Ibuffs-4,Y ; get byte from crunched line + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + CPY #$03 ; compare with first byte-1 + BNE LAB_1311 ; continue while count <> 3 + + LDA Itemph ; get line # high byte + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + LDA Itempl ; get line # low byte + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + LDA #$FF ; set byte to allow chain rebuild. if you didn't set this + ; byte then a zero already here would stop the chain rebuild + ; as it would think it was the [EOT] marker. + STA (Baslnl),Y ; save it to program memory + +LAB_1319 + JSR LAB_1477 ; reset execution to start, clear vars and flush stack + LDX Smeml ; get start of mem low byte + LDA Smemh ; get start of mem high byte + LDY #$01 ; index to high byte of next line pointer +LAB_1325 + STX ut1_pl ; set line start pointer low byte + STA ut1_ph ; set line start pointer high byte + LDA (ut1_pl),Y ; get it + BEQ LAB_133E ; exit if end of program + +; rebuild chaining of Basic lines + + LDY #$04 ; point to first code byte of line + ; there is always 1 byte + [EOL] as null entries are deleted +LAB_1330 + INY ; next code byte + LDA (ut1_pl),Y ; get byte + BNE LAB_1330 ; loop if not [EOL] + + SEC ; set carry for add + 1 + TYA ; copy end index + ADC ut1_pl ; add to line start pointer low byte + TAX ; copy to X + LDY #$00 ; clear index, point to this line's next line pointer + STA (ut1_pl),Y ; set next line pointer low byte + TYA ; clear A + ADC ut1_ph ; add line start pointer high byte + carry + INY ; increment index to high byte + STA (ut1_pl),Y ; save next line pointer low byte + BCC LAB_1325 ; go do next line, branch always, carry clear + + +LAB_133E + JMP LAB_127D ; else we just wait for Basic command, no "Ready" + +; print "? " and get BASIC input + +LAB_INLN + JSR LAB_18E3 ; print "?" character + JSR LAB_18E0 ; print " " + BNE LAB_1357 ; call for BASIC input and return + +; receive line from keyboard + + ; $08 as delete key (BACKSPACE on standard keyboard) +LAB_134B + JSR LAB_PRNA ; go print the character + DEX ; decrement the buffer counter (delete) + .byte $2C ; make LDX into BIT abs + +; call for BASIC input (main entry point) + +LAB_1357 + LDX #$00 ; clear BASIC line buffer pointer +LAB_1359 + JSR V_INPT ; call scan input device + BCC LAB_1359 ; loop if no byte + + BEQ LAB_1359 ; loop until valid input (ignore NULLs) + + CMP #$07 ; compare with [BELL] + BEQ LAB_1378 ; branch if [BELL] + + CMP #$0D ; compare with [CR] + BEQ LAB_1384 ; do CR/LF exit if [CR] + + CPX #$00 ; compare pointer with $00 + BNE LAB_1374 ; branch if not empty + +; next two lines ignore any non print character and [SPACE] if input buffer empty + + CMP #$21 ; compare with [SP]+1 + BCC LAB_1359 ; if < ignore character + +LAB_1374 + CMP #$08 ; compare with [BACKSPACE] (delete last character) + BEQ LAB_134B ; go delete last character + +LAB_1378 + CPX #Ibuffe-Ibuffs ; compare character count with max + BCS LAB_138E ; skip store and do [BELL] if buffer full + + STA Ibuffs,X ; else store in buffer + INX ; increment pointer +LAB_137F + JSR LAB_PRNA ; go print the character + BNE LAB_1359 ; always loop for next character + +LAB_1384 + JMP LAB_1866 ; do CR/LF exit to BASIC + +; announce buffer full + +LAB_138E + LDA #$07 ; [BELL] character into A + BNE LAB_137F ; go print the [BELL] but ignore input character + ; branch always + +; crunch keywords into Basic tokens +; position independent buffer version .. +; faster, dictionary search version .... + +LAB_13A6 + LDY #$FF ; set save index (makes for easy math later) + + SEC ; set carry for subtract + LDA Bpntrl ; get basic execute pointer low byte + SBC #= go save byte then continue crunching + + CMP #'<' ; compare with "<" + BCS LAB_13CC ; if >= go crunch now + + CMP #'0' ; compare with "0" + BCS LAB_13EC ; if >= go save byte then continue crunching + + STA Scnquo ; save buffer byte as search character + CMP #$22 ; is it quote character? + BEQ LAB_1410 ; branch if so (copy quoted string) + + CMP #'*' ; compare with "*" + BCC LAB_13EC ; if < go save byte then continue crunching + + ; else crunch now +LAB_13CC + BIT Oquote ; get open quote/DATA token flag + BVS LAB_13EC ; branch if b6 of Oquote set (was DATA) + ; go save byte then continue crunching + + STX TempB ; save buffer read index + STY csidx ; copy buffer save index + LDY #TAB_1STC ; get keyword first character table high address + STY ut2_ph ; save pointer high byte + LDY #$00 ; clear table pointer + +LAB_13D0 + CMP (ut2_pl),Y ; compare with keyword first character table byte + BEQ LAB_13D1 ; go do word_table_chr if match + + BCC LAB_13EA ; if < keyword first character table byte go restore + ; Y and save to crunched + + INY ; else increment pointer + BNE LAB_13D0 ; and loop (branch always) + +; have matched first character of some keyword + +LAB_13D1 + TYA ; copy matching index + ASL ; *2 (bytes per pointer) + TAX ; copy to new index + LDA TAB_CHRT,X ; get keyword table pointer low byte + STA ut2_pl ; save pointer low byte + LDA TAB_CHRT+1,X ; get keyword table pointer high byte + STA ut2_ph ; save pointer high byte + + LDY #$FF ; clear table pointer (make -1 for start) + + LDX TempB ; restore buffer read index + +LAB_13D6 + INY ; next table byte + LDA (ut2_pl),Y ; get byte from table +LAB_13D8 + BMI LAB_13EA ; all bytes matched so go save token + + INX ; next buffer byte + CMP Ibuffs,X ; compare with byte from input buffer + BEQ LAB_13D6 ; go compare next if match + + BNE LAB_1417 ; branch if >< (not found keyword) + +LAB_13EA + LDY csidx ; restore save index + + ; save crunched to output +LAB_13EC + INX ; increment buffer index (to next input byte) + INY ; increment save index (to next output byte) + STA Ibuffs,Y ; save byte to output + CMP #$00 ; set the flags, set carry + BEQ LAB_142A ; do exit if was null [EOL] + + ; A holds token or byte here + SBC #':' ; subtract ":" (carry set by CMP #00) + BEQ LAB_13FF ; branch if it was ":" (is now $00) + + ; A now holds token-$3A + CMP #TK_DATA-$3A ; compare with DATA token - $3A + BNE LAB_1401 ; branch if not DATA + + ; token was : or DATA +LAB_13FF + STA Oquote ; save token-$3A (clear for ":", TK_DATA-$3A for DATA) +LAB_1401 + EOR #TK_REM-$3A ; effectively subtract REM token offset + BNE LAB_13AC ; If wasn't REM then go crunch rest of line + + STA Asrch ; else was REM so set search for [EOL] + + ; loop for REM, "..." etc. +LAB_1408 + LDA Ibuffs,X ; get byte from input buffer + BEQ LAB_13EC ; branch if null [EOL] + + CMP Asrch ; compare with stored character + BEQ LAB_13EC ; branch if match (end quote) + + ; entry for copy string in quotes, don't crunch +LAB_1410 + INY ; increment buffer save index + STA Ibuffs,Y ; save byte to output + INX ; increment buffer read index + BNE LAB_1408 ; loop while <> 0 (should never be 0!) + + ; not found keyword this go +LAB_1417 + LDX TempB ; compare has failed, restore buffer index (start byte!) + + ; now find the end of this word in the table +LAB_141B + LDA (ut2_pl),Y ; get table byte + PHP ; save status + INY ; increment table index + PLP ; restore byte status + BPL LAB_141B ; if not end of keyword go do next + + LDA (ut2_pl),Y ; get byte from keyword table + BNE LAB_13D8 ; go test next word if not zero byte (end of table) + + ; reached end of table with no match + LDA Ibuffs,X ; restore byte from input buffer + BPL LAB_13EA ; branch always (all bytes in buffer are $00-$7F) + ; go save byte in output and continue crunching + + ; reached [EOL] +LAB_142A + INY ; increment pointer + INY ; increment pointer (makes it next line pointer high byte) + STA Ibuffs,Y ; save [EOL] (marks [EOT] in immediate mode) + INY ; adjust for line copy + INY ; adjust for line copy + INY ; adjust for line copy + DEC Bpntrl ; allow for increment (change if buffer starts at $xxFF) + RTS + +; search Basic for temp integer line number from start of mem + +LAB_SSLN + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search Basic for temp integer line number from AX +; returns carry set if found +; returns Baslnl/Baslnh pointer to found or next higher (not found) line + +; old 541 new 507 + +LAB_SHLN + LDY #$01 ; set index + STA Baslnl ; save low byte as current + STX Baslnh ; save high byte as current + LDA (Baslnl),Y ; get pointer high byte from addr + BEQ LAB_145F ; pointer was zero so we're done, do 'not found' exit + + LDY #$03 ; set index to line # high byte + LDA (Baslnl),Y ; get line # high byte + DEY ; decrement index (point to low byte) + CMP Itemph ; compare with temporary integer high byte + BNE LAB_1455 ; if <> skip low byte check + + LDA (Baslnl),Y ; get line # low byte + CMP Itempl ; compare with temporary integer low byte +LAB_1455 + BCS LAB_145E ; else if temp < this line, exit (passed line#) + +LAB_1456 + DEY ; decrement index to next line ptr high byte + LDA (Baslnl),Y ; get next line pointer high byte + TAX ; copy to X + DEY ; decrement index to next line ptr low byte + LDA (Baslnl),Y ; get next line pointer low byte + BCC LAB_SHLN ; go search for line # in temp (Itempl/Itemph) from AX + ; (carry always clear) + +LAB_145E + BEQ LAB_1460 ; exit if temp = found line #, carry is set + +LAB_145F + CLC ; clear found flag +LAB_1460 + RTS + +; perform NEW + +LAB_NEW + BNE LAB_1460 ; exit if not end of statement (to do syntax error) + +LAB_1463 + LDA #$00 ; clear A + TAY ; clear Y + STA (Smeml),Y ; clear first line, next line pointer, low byte + INY ; increment index + STA (Smeml),Y ; clear first line, next line pointer, high byte + CLC ; clear carry + LDA Smeml ; get start of mem low byte + ADC #$02 ; calculate end of BASIC low byte + STA Svarl ; save start of vars low byte + LDA Smemh ; get start of mem high byte + ADC #$00 ; add any carry + STA Svarh ; save start of vars high byte + +; reset execution to start, clear vars and flush stack + +LAB_1477 + CLC ; clear carry + LDA Smeml ; get start of mem low byte + ADC #$FF ; -1 + STA Bpntrl ; save BASIC execute pointer low byte + LDA Smemh ; get start of mem high byte + ADC #$FF ; -1+carry + STA Bpntrh ; save BASIC execute pointer high byte + +; "CLEAR" command gets here + +LAB_147A + LDA Ememl ; get end of mem low byte + LDY Ememh ; get end of mem high byte + STA Sstorl ; set bottom of string space low byte + STY Sstorh ; set bottom of string space high byte + LDA Svarl ; get start of vars low byte + LDY Svarh ; get start of vars high byte + STA Sarryl ; save var mem end low byte + STY Sarryh ; save var mem end high byte + STA Earryl ; save array mem end low byte + STY Earryh ; save array mem end high byte + JSR LAB_161A ; perform RESTORE command + +; flush stack and clear continue flag + +LAB_1491 + LDX #des_sk ; set descriptor stack pointer + STX next_s ; save descriptor stack pointer + PLA ; pull return address low byte + TAX ; copy return address low byte + PLA ; pull return address high byte + STX LAB_SKFE ; save to cleared stack + STA LAB_SKFF ; save to cleared stack + LDX #$FD ; new stack pointer + TXS ; reset stack + LDA #$00 ; clear byte + STA Cpntrh ; clear continue pointer high byte + STA Sufnxf ; clear subscript/FNX flag +LAB_14A6 + RTS + +; perform CLEAR + +LAB_CLEAR + BEQ LAB_147A ; if no following token go do "CLEAR" + + ; else there was a following token (go do syntax error) + RTS + +; perform LIST [n][-m] +; bigger, faster version (a _lot_ faster) + +LAB_LIST + BCC LAB_14BD ; branch if next character numeric (LIST n..) + + BEQ LAB_14BD ; branch if next character [NULL] (LIST) + + CMP #TK_MINUS ; compare with token for - + BNE LAB_14A6 ; exit if not - (LIST -m) + + ; LIST [[n][-m]] + ; this bit sets the n , if present, as the start and end +LAB_14BD + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SSLN ; search BASIC for temp integer line number + ; (pointer in Baslnl/Baslnh) + JSR LAB_GBYT ; scan memory + BEQ LAB_14D4 ; branch if no more characters + + ; this bit checks the - is present + CMP #TK_MINUS ; compare with token for - + BNE LAB_1460 ; return if not "-" (will be Syntax error) + + ; LIST [n]-m + ; the - was there so set m as the end value + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GFPN ; get fixed-point number into temp integer + BNE LAB_1460 ; exit if not ok + +LAB_14D4 + LDA Itempl ; get temporary integer low byte + ORA Itemph ; OR temporary integer high byte + BNE LAB_14E2 ; branch if start set + + LDA #$FF ; set for -1 + STA Itempl ; set temporary integer low byte + STA Itemph ; set temporary integer high byte +LAB_14E2 + LDY #$01 ; set index for line + STY Oquote ; clear open quote flag + JSR LAB_CRLF ; print CR/LF + LDA (Baslnl),Y ; get next line pointer high byte + ; pointer initially set by search at LAB_14BD + BEQ LAB_152B ; if null all done so exit + JSR LAB_1629 ; do CRTL-C check vector + + INY ; increment index for line + LDA (Baslnl),Y ; get line # low byte + TAX ; copy to X + INY ; increment index + LDA (Baslnl),Y ; get line # high byte + CMP Itemph ; compare with temporary integer high byte + BNE LAB_14FF ; branch if no high byte match + + CPX Itempl ; compare with temporary integer low byte + BEQ LAB_1501 ; branch if = last line to do (< will pass next branch) + +LAB_14FF ; else .. + BCS LAB_152B ; if greater all done so exit + +LAB_1501 + STY Tidx1 ; save index for line + JSR LAB_295E ; print XA as unsigned integer + LDA #$20 ; space is the next character +LAB_1508 + LDY Tidx1 ; get index for line + AND #$7F ; mask top out bit of character +LAB_150C + JSR LAB_PRNA ; go print the character + CMP #$22 ; was it " character + BNE LAB_1519 ; branch if not + + ; we are either entering or leaving a pair of quotes + LDA Oquote ; get open quote flag + EOR #$FF ; toggle it + STA Oquote ; save it back +LAB_1519 + INY ; increment index + LDA (Baslnl),Y ; get next byte + BNE LAB_152E ; branch if not [EOL] (go print character) + TAY ; else clear index + LDA (Baslnl),Y ; get next line pointer low byte + TAX ; copy to X + INY ; increment index + LDA (Baslnl),Y ; get next line pointer high byte + STX Baslnl ; set pointer to line low byte + STA Baslnh ; set pointer to line high byte + BNE LAB_14E2 ; go do next line if not [EOT] + ; else .. +LAB_152B + RTS + +LAB_152E + BPL LAB_150C ; just go print it if not token byte + + ; else was token byte so uncrunch it (maybe) + BIT Oquote ; test the open quote flag + BMI LAB_150C ; just go print character if open quote set + + LDX #>LAB_KEYT ; get table address high byte + ASL ; *2 + ASL ; *4 + BCC LAB_152F ; branch if no carry + + INX ; else increment high byte + CLC ; clear carry for add +LAB_152F + ADC #LAB_159F ; set return address high byte + STA ut1_pl ; save return address low byte + STY ut1_ph ; save return address high byte + JMP LAB_1B66 ; round FAC1 and put on stack (returns to next instruction) + +LAB_159F + LDA #LAB_259C ; set 1 pointer high addr + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + JSR LAB_GBYT ; scan memory + CMP #TK_STEP ; compare with STEP token + BNE LAB_15B3 ; jump if not "STEP" + + ;.was step so .. + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch +LAB_15B3 + JSR LAB_27CA ; return A=FF,C=1/-ve A=01,C=0/+ve + STA FAC1_s ; set FAC1 sign (b7) + ; this is +1 for +ve step and -1 for -ve step, in NEXT we + ; compare the FOR value and the TO value and return +1 if + ; FOR > TO, 0 if FOR = TO and -1 if FOR < TO. the value + ; here (+/-1) is then compared to that result and if they + ; are the same (+ve and FOR > TO or -ve and FOR < TO) then + ; the loop is done + JSR LAB_1B5B ; push sign, round FAC1 and put on stack + LDA Frnxth ; get var pointer for FOR/NEXT high byte + PHA ; push on stack + LDA Frnxtl ; get var pointer for FOR/NEXT low byte + PHA ; push on stack + LDA #TK_FOR ; get FOR token + PHA ; push on stack + +; interpreter inner loop + +LAB_15C2 + JSR LAB_1629 ; do CRTL-C check vector + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + + LDX Clineh ; continue line is $FFxx for immediate mode + ; ($00xx for RUN from immediate mode) + INX ; increment it (now $00 if immediate mode) + BEQ LAB_15D1 ; branch if null (immediate mode) + + STA Cpntrl ; save continue pointer low byte + STY Cpntrh ; save continue pointer high byte +LAB_15D1 + LDY #$00 ; clear index + LDA (Bpntrl),Y ; get next byte + BEQ LAB_15DC ; branch if null [EOL] + + CMP #':' ; compare with ":" + BEQ LAB_15F6 ; branch if = (statement separator) + +LAB_15D9 + JMP LAB_SNER ; else syntax error then warm start + + ; have reached [EOL] +LAB_15DC + LDY #$02 ; set index + LDA (Bpntrl),Y ; get next line pointer high byte + CLC ; clear carry for no "BREAK" message + BEQ LAB_1651 ; if null go to immediate mode (was immediate or [EOT] + ; marker) + + INY ; increment index + LDA (Bpntrl),Y ; get line # low byte + STA Clinel ; save current line low byte + INY ; increment index + LDA (Bpntrl),Y ; get line # high byte + STA Clineh ; save current line high byte + TYA ; A now = 4 + ADC Bpntrl ; add BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + BCC LAB_15F6 ; branch if no overflow + + INC Bpntrh ; else increment BASIC execute pointer high byte +LAB_15F6 + JSR LAB_IGBY ; increment and scan memory + +LAB_15F9 + JSR LAB_15FF ; go interpret BASIC code from (Bpntrl) + +LAB_15FC + JMP LAB_15C2 ; loop + +; interpret BASIC code from (Bpntrl) + +LAB_15FF + BEQ LAB_1628 ; exit if zero [EOL] + +LAB_1602 + ASL ; *2 bytes per vector and normalise token + BCS LAB_1609 ; branch if was token + + JMP LAB_LET ; else go do implied LET + +LAB_1609 + CMP #[TK_TAB-$80]*2 ; compare normalised token * 2 with TAB + BCS LAB_15D9 ; branch if A>=TAB (do syntax error then warm start) + ; only tokens before TAB can start a line + TAY ; copy to index + LDA LAB_CTBL+1,Y ; get vector high byte + PHA ; onto stack + LDA LAB_CTBL,Y ; get vector low byte + PHA ; onto stack + JMP LAB_IGBY ; jump to increment and scan memory + ; then "return" to vector + +; CTRL-C check jump. this is called as a subroutine but exits back via a jump if a +; key press is detected. + +LAB_1629 + JMP (VEC_CC) ; ctrl c check vector + +; if there was a key press it gets back here .. + +LAB_1636 + CMP #$03 ; compare with CTRL-C + +; perform STOP + +LAB_STOP + BCS LAB_163B ; branch if token follows STOP + ; else just END +; END + +LAB_END + CLC ; clear the carry, indicate a normal program end +LAB_163B + BNE LAB_167A ; if wasn't CTRL-C or there is a following byte return + + LDA Bpntrh ; get the BASIC execute pointer high byte + EOR #>Ibuffs ; compare with buffer address high byte (Cb unchanged) + BEQ LAB_164F ; branch if the BASIC pointer is in the input buffer + ; (can't continue in immediate mode) + + ; else .. + EOR #>Ibuffs ; correct the bits + LDY Bpntrl ; get BASIC execute pointer low byte + STY Cpntrl ; save continue pointer low byte + STA Cpntrh ; save continue pointer high byte +LAB_1647 + LDA Clinel ; get current line low byte + LDY Clineh ; get current line high byte + STA Blinel ; save break line low byte + STY Blineh ; save break line high byte +LAB_164F + PLA ; pull return address low + PLA ; pull return address high +LAB_1651 + BCC LAB_165E ; if was program end just do warm start + + ; else .. + LDA #LAB_BMSG ; point to "Break" high byte + JMP LAB_1269 ; print "Break" and do warm start + +LAB_165E + JMP LAB_1274 ; go do warm start + +; perform RESTORE + +LAB_RESTORE + BNE LAB_RESTOREn ; branch if next character not null (RESTORE n) + +LAB_161A + SEC ; set carry for subtract + LDA Smeml ; get start of mem low byte + SBC #$01 ; -1 + LDY Smemh ; get start of mem high byte + BCS LAB_1624 ; branch if no underflow + +LAB_uflow + DEY ; else decrement high byte +LAB_1624 + STA Dptrl ; save DATA pointer low byte + STY Dptrh ; save DATA pointer high byte +LAB_1628 + RTS + + ; is RESTORE n +LAB_RESTOREn + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SNBL ; scan for next BASIC line + LDA Clineh ; get current line high byte + CMP Itemph ; compare with temporary integer high byte + BCS LAB_reset_search ; branch if >= (start search from beginning) + + TYA ; else copy line index to A + SEC ; set carry (+1) + ADC Bpntrl ; add BASIC execute pointer low byte + LDX Bpntrh ; get BASIC execute pointer high byte + BCC LAB_go_search ; branch if no overflow to high byte + + INX ; increment high byte + BCS LAB_go_search ; branch always (can never be carry clear) + +; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml) + +LAB_reset_search + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search for line # in temp (Itempl/Itemph) from (AX) + +LAB_go_search + + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCS LAB_line_found ; if carry set go set pointer + + JMP LAB_16F7 ; else go do "Undefined statement" error + +LAB_line_found + ; carry already set for subtract + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 + LDY Baslnh ; get pointer high byte + BCS LAB_1624 ; branch if no underflow (save DATA pointer and return) + + BCC LAB_uflow ; else decrement high byte then save DATA pointer and + ; return (branch always) + +; perform NULL + +LAB_NULL + JSR LAB_GTBY ; get byte parameter + STX Nullct ; save new NULL count +LAB_167A + RTS + +; perform CONT + +LAB_CONT + BNE LAB_167A ; if following byte exit to do syntax error + + LDY Cpntrh ; get continue pointer high byte + BNE LAB_166C ; go do continue if we can + + LDX #$1E ; error code $1E ("Can't continue" error) + JMP LAB_XERR ; do error #X, then warm start + + ; we can continue so .. +LAB_166C + LDA #TK_ON ; set token for ON + JSR LAB_IRQ ; set IRQ flags + LDA #TK_ON ; set token for ON + JSR LAB_NMI ; set NMI flags + + STY Bpntrh ; save BASIC execute pointer high byte + LDA Cpntrl ; get continue pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA Blinel ; get break line low byte + LDY Blineh ; get break line high byte + STA Clinel ; set current line low byte + STY Clineh ; set current line high byte + RTS + +; perform RUN + +LAB_RUN + BNE LAB_1696 ; branch if RUN n + JMP LAB_1477 ; reset execution to start, clear variables, flush stack and + ; return + +; does RUN n + +LAB_1696 + JSR LAB_147A ; go do "CLEAR" + BEQ LAB_16B0 ; get n and do GOTO n (branch always as CLEAR sets Z=1) + +; perform DO + +LAB_DO + LDA #$05 ; need 5 bytes for DO + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_DO ; token for DO + PHA ; push on stack + JSR LAB_GBYT ; scan memory + JMP LAB_15C2 ; go do interpreter inner loop + +; perform GOSUB + +LAB_GOSUB + LDA #$05 ; need 5 bytes for GOSUB + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_GOSUB ; token for GOSUB + PHA ; push on stack +LAB_16B0 + JSR LAB_GBYT ; scan memory + JSR LAB_GOTO ; perform GOTO n + JMP LAB_15C2 ; go do interpreter inner loop + ; (can't RTS, we used the stack!) + +; perform GOTO + +LAB_GOTO + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SNBL ; scan for next BASIC line + LDA Clineh ; get current line high byte + CMP Itemph ; compare with temporary integer high byte + BCS LAB_16D0 ; branch if >= (start search from beginning) + + TYA ; else copy line index to A + SEC ; set carry (+1) + ADC Bpntrl ; add BASIC execute pointer low byte + LDX Bpntrh ; get BASIC execute pointer high byte + BCC LAB_16D4 ; branch if no overflow to high byte + + INX ; increment high byte + BCS LAB_16D4 ; branch always (can never be carry) + +; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml) + +LAB_16D0 + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search for line # in temp (Itempl/Itemph) from (AX) + +LAB_16D4 + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCC LAB_16F7 ; if carry clear go do "Undefined statement" error + ; (unspecified statement) + + ; carry already set for subtract + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 + STA Bpntrl ; save BASIC execute pointer low byte + LDA Baslnh ; get pointer high byte + SBC #$00 ; subtract carry + STA Bpntrh ; save BASIC execute pointer high byte +LAB_16E5 + RTS + +LAB_DONOK + LDX #$22 ; error code $22 ("LOOP without DO" error) + JMP LAB_XERR ; do error #X, then warm start + +; perform LOOP + +LAB_LOOP + TAY ; save following token + TSX ; copy stack pointer + LDA LAB_STAK+3,X ; get token byte from stack + CMP #TK_DO ; compare with DO token + BNE LAB_DONOK ; branch if no matching DO + + INX ; dump calling routine return address + INX ; dump calling routine return address + TXS ; correct stack + TYA ; get saved following token back + BEQ LoopAlways ; if no following token loop forever + ; (stack pointer in X) + + CMP #':' ; could be ':' + BEQ LoopAlways ; if :... loop forever + + SBC #TK_UNTIL ; subtract token for UNTIL, we know carry is set here + TAX ; copy to X (if it was UNTIL then Y will be correct) + BEQ DoRest ; branch if was UNTIL + + DEX ; decrement result + BNE LAB_16FC ; if not WHILE go do syntax error and warm start + ; only if the token was WHILE will this fail + + DEX ; set invert result byte +DoRest + STX Frnxth ; save invert result byte + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVEX ; evaluate expression + LDA FAC1_e ; get FAC1 exponent + BEQ DoCmp ; if =0 go do straight compare + + LDA #$FF ; else set all bits +DoCmp + TSX ; copy stack pointer + EOR Frnxth ; EOR with invert byte + BNE LoopDone ; if <> 0 clear stack and back to interpreter loop + + ; loop condition wasn't met so do it again +LoopAlways + LDA LAB_STAK+2,X ; get current line low byte + STA Clinel ; save current line low byte + LDA LAB_STAK+3,X ; get current line high byte + STA Clineh ; save current line high byte + LDA LAB_STAK+4,X ; get BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA LAB_STAK+5,X ; get BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + JMP LAB_15C2 ; go do interpreter inner loop + + ; clear stack and back to interpreter loop +LoopDone + INX ; dump DO token + INX ; dump current line low byte + INX ; dump current line high byte + INX ; dump BASIC execute pointer low byte + INX ; dump BASIC execute pointer high byte + TXS ; correct stack + JMP LAB_DATA ; go perform DATA (find : or [EOL]) + +; do the return without gosub error + +LAB_16F4 + LDX #$04 ; error code $04 ("RETURN without GOSUB" error) + .byte $2C ; makes next line BIT LAB_0EA2 + +LAB_16F7 ; do undefined statement error + LDX #$0E ; error code $0E ("Undefined statement" error) + JMP LAB_XERR ; do error #X, then warm start + +; perform RETURN + +LAB_RETURN + BNE LAB_16E5 ; exit if following token (to allow syntax error) + +LAB_16E8 + PLA ; dump calling routine return address + PLA ; dump calling routine return address + PLA ; pull token + CMP #TK_GOSUB ; compare with GOSUB token + BNE LAB_16F4 ; branch if no matching GOSUB + +LAB_16FF + PLA ; pull current line low byte + STA Clinel ; save current line low byte + PLA ; pull current line high byte + STA Clineh ; save current line high byte + PLA ; pull BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + PLA ; pull BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte + + ; now do the DATA statement as we could be returning into + ; the middle of an ON GOSUB n,m,p,q line + ; (the return address used by the DATA statement is the one + ; pushed before the GOSUB was executed!) + +; perform DATA + +LAB_DATA + JSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL]) + + ; set BASIC execute pointer +LAB_170F + TYA ; copy index to A + CLC ; clear carry for add + ADC Bpntrl ; add BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + BCC LAB_1719 ; skip next if no carry + + INC Bpntrh ; else increment BASIC execute pointer high byte +LAB_1719 + RTS + +LAB_16FC + JMP LAB_SNER ; do syntax error then warm start + +; scan for next BASIC statement ([:] or [EOL]) +; returns Y as index to [:] or [EOL] + +LAB_SNBS + LDX #':' ; set look for character = ":" + .byte $2C ; makes next line BIT $00A2 + +; scan for next BASIC line +; returns Y as index to [EOL] + +LAB_SNBL + LDX #$00 ; set alt search character = [EOL] + LDY #$00 ; set search character = [EOL] + STY Asrch ; store search character +LAB_1725 + TXA ; get alt search character + EOR Asrch ; toggle search character, effectively swap with $00 + STA Asrch ; save swapped search character +LAB_172D + LDA (Bpntrl),Y ; get next byte + BEQ LAB_1719 ; exit if null [EOL] + + CMP Asrch ; compare with search character + BEQ LAB_1719 ; exit if found + + INY ; increment index + CMP #$22 ; compare current character with open quote + BNE LAB_172D ; if not open quote go get next character + + BEQ LAB_1725 ; if found go swap search character for alt search character + +; perform IF + +LAB_IF + JSR LAB_EVEX ; evaluate the expression + JSR LAB_GBYT ; scan memory + CMP #TK_THEN ; compare with THEN token + BEQ LAB_174B ; if it was THEN go do IF + + ; wasn't IF .. THEN so must be IF .. GOTO + CMP #TK_GOTO ; compare with GOTO token + BNE LAB_16FC ; if it wasn't GOTO go do syntax error + + LDX Bpntrl ; save the basic pointer low byte + LDY Bpntrh ; save the basic pointer high byte + JSR LAB_IGBY ; increment and scan memory + BCS LAB_16FC ; if not numeric go do syntax error + + STX Bpntrl ; restore the basic pointer low byte + STY Bpntrh ; restore the basic pointer high byte +LAB_174B + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_174E ; if the result was zero go look for an ELSE + + JSR LAB_IGBY ; else increment and scan memory + BCS LAB_174D ; if not numeric go do var or keyword + +LAB_174C + JMP LAB_GOTO ; else was numeric so do GOTO n + + ; is var or keyword +LAB_174D + CMP #TK_RETURN ; compare the byte with the token for RETURN + BNE LAB_174G ; if it wasn't RETURN go interpret BASIC code from (Bpntrl) + ; and return to this code to process any following code + + JMP LAB_1602 ; else it was RETURN so interpret BASIC code from (Bpntrl) + ; but don't return here + +LAB_174G + JSR LAB_15FF ; interpret BASIC code from (Bpntrl) + +; the IF was executed and there may be a following ELSE so the code needs to return +; here to check and ignore the ELSE if present + + LDY #$00 ; clear the index + LDA (Bpntrl),Y ; get the next BASIC byte + CMP #TK_ELSE ; compare it with the token for ELSE + BEQ LAB_DATA ; if ELSE ignore the following statement + +; there was no ELSE so continue execution of IF THEN [: ]. any +; following ELSE will, correctly, cause a syntax error + + RTS ; else return to the interpreter inner loop + +; perform ELSE after IF + +LAB_174E + LDY #$00 ; clear the BASIC byte index + LDX #$01 ; clear the nesting depth +LAB_1750 + INY ; increment the BASIC byte index + LDA (Bpntrl),Y ; get the next BASIC byte + BEQ LAB_1753 ; if EOL go add the pointer and return + + CMP #TK_IF ; compare the byte with the token for IF + BNE LAB_1752 ; if not IF token skip the depth increment + + INX ; else increment the nesting depth .. + BNE LAB_1750 ; .. and continue looking + +LAB_1752 + CMP #TK_ELSE ; compare the byte with the token for ELSE + BNE LAB_1750 ; if not ELSE token continue looking + + DEX ; was ELSE so decrement the nesting depth + BNE LAB_1750 ; loop if still nested + + INY ; increment the BASIC byte index past the ELSE + +; found the matching ELSE, now do <{n|statement}> + +LAB_1753 + TYA ; else copy line index to A + CLC ; clear carry for add + ADC Bpntrl ; add the BASIC execute pointer low byte + STA Bpntrl ; save the BASIC execute pointer low byte + BCC LAB_1754 ; branch if no overflow to high byte + + INC Bpntrh ; else increment the BASIC execute pointer high byte +LAB_1754 + JSR LAB_GBYT ; scan memory + BCC LAB_174C ; if numeric do GOTO n + ; the code will return to the interpreter loop at the + ; tail end of the GOTO + + JMP LAB_15FF ; interpret BASIC code from (Bpntrl) + ; the code will return to the interpreter loop at the + ; tail end of the + +; perform REM, skip (rest of) line + +LAB_REM + JSR LAB_SNBL ; scan for next BASIC line + JMP LAB_170F ; go set BASIC execute pointer and return, branch always + +LAB_16FD + JMP LAB_SNER ; do syntax error then warm start + +; perform ON + +LAB_ON + CMP #TK_IRQ ; was it IRQ token ? + BNE LAB_NOIN ; if not go check NMI + + JMP LAB_SIRQ ; else go set-up IRQ + +LAB_NOIN + CMP #TK_NMI ; was it NMI token ? + BNE LAB_NONM ; if not go do normal ON command + + JMP LAB_SNMI ; else go set-up NMI + +LAB_NONM + JSR LAB_GTBY ; get byte parameter + PHA ; push GOTO/GOSUB token + CMP #TK_GOSUB ; compare with GOSUB token + BEQ LAB_176B ; branch if GOSUB + + CMP #TK_GOTO ; compare with GOTO token +LAB_1767 + BNE LAB_16FD ; if not GOTO do syntax error then warm start + + +; next character was GOTO or GOSUB + +LAB_176B + DEC FAC1_3 ; decrement index (byte value) + BNE LAB_1773 ; branch if not zero + + PLA ; pull GOTO/GOSUB token + JMP LAB_1602 ; go execute it + +LAB_1773 + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GFPN ; get fixed-point number into temp integer (skip this n) + ; (we could LDX #',' and JSR LAB_SNBL+2, then we + ; just BNE LAB_176B for the loop. should be quicker .. + ; no we can't, what if we meet a colon or [EOL]?) + CMP #$2C ; compare next character with "," + BEQ LAB_176B ; loop if "," + +LAB_177E + PLA ; else pull keyword token (run out of options) + ; also dump +/-1 pointer low byte and exit +LAB_177F + RTS + +; takes n * 106 + 11 cycles where n is the number of digits + +; get fixed-point number into temp integer + +LAB_GFPN + LDX #$00 ; clear reg + STX Itempl ; clear temporary integer low byte +LAB_1785 + STX Itemph ; save temporary integer high byte + BCS LAB_177F ; return if carry set, end of scan, character was + ; not 0-9 + + CPX #$19 ; compare high byte with $19 + TAY ; ensure Zb = 0 if the branch is taken + BCS LAB_1767 ; branch if >=, makes max line # 63999 because next + ; bit does *$0A, = 64000, compare at target will fail + ; and do syntax error + + SBC #'0'-1 ; subtract "0", $2F + carry, from byte + TAY ; copy binary digit + LDA Itempl ; get temporary integer low byte + ASL ; *2 low byte + ROL Itemph ; *2 high byte + ASL ; *2 low byte + ROL Itemph ; *2 high byte, *4 + ADC Itempl ; + low byte, *5 + STA Itempl ; save it + TXA ; get high byte copy to A + ADC Itemph ; + high byte, *5 + ASL Itempl ; *2 low byte, *10d + ROL ; *2 high byte, *10d + TAX ; copy high byte back to X + TYA ; get binary digit back + ADC Itempl ; add number low byte + STA Itempl ; save number low byte + BCC LAB_17B3 ; if no overflow to high byte get next character + + INX ; else increment high byte +LAB_17B3 + JSR LAB_IGBY ; increment and scan memory + JMP LAB_1785 ; loop for next character + +; perform DEC + +LAB_DEC + LDA #LAB_259C ; set +/-1 pointer high byte (both the same) + JSR LAB_246C ; add (AY) to FAC1 + JSR LAB_PFAC ; pack FAC1 into variable (Lvarpl) + + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BNE LAB_177E ; exit if not "," (either end or error) + + ; was "," so another INCR variable to do + JSR LAB_IGBY ; increment and scan memory + JMP LAB_17B7 ; go do next var + +IncrErr + JMP LAB_1ABC ; do "Type mismatch" error then warm start + +; perform LET + +LAB_LET + JSR LAB_GVAR ; get var address + STA Lvarpl ; save var address low byte + STY Lvarph ; save var address high byte + LDA #TK_EQUAL ; get = token + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; push data type flag + JSR LAB_EVEX ; evaluate expression + PLA ; pop data type flag + ROL ; set carry if type = string + JSR LAB_CKTM ; type match check, set C for string + BNE LAB_17D5 ; branch if string + + JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return + +; string LET + +LAB_17D5 + LDY #$02 ; set index to pointer high byte + LDA (des_pl),Y ; get string pointer high byte + CMP Sstorh ; compare bottom of string space high byte + BCC LAB_17F4 ; if less assign value and exit (was in program memory) + + BNE LAB_17E6 ; branch if > + ; else was equal so compare low bytes + DEY ; decrement index + LDA (des_pl),Y ; get pointer low byte + CMP Sstorl ; compare bottom of string space low byte + BCC LAB_17F4 ; if less assign value and exit (was in program memory) + + ; pointer was >= to bottom of string space pointer +LAB_17E6 + LDY des_ph ; get descriptor pointer high byte + CPY Svarh ; compare start of vars high byte + BCC LAB_17F4 ; branch if less (descriptor is on stack) + + BNE LAB_17FB ; branch if greater (descriptor is not on stack) + + ; else high bytes were equal so .. + LDA des_pl ; get descriptor pointer low byte + CMP Svarl ; compare start of vars low byte + BCS LAB_17FB ; branch if >= (descriptor is not on stack) + +LAB_17F4 + LDA des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + JMP LAB_1811 ; clean stack, copy descriptor to variable and return + + ; make space and copy string +LAB_17FB + LDY #$00 ; index to length + LDA (des_pl),Y ; get string length + JSR LAB_209C ; copy string + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + STA ssptr_l ; save descriptor pointer low byte + STY ssptr_h ; save descriptor pointer high byte + JSR LAB_228A ; copy string from descriptor (sdescr) to (Sutill) + LDA #FAC1_e ; get descriptor pointer high byte + + ; clean stack and assign value to string variable +LAB_1811 + STA des_2l ; save descriptor_2 pointer low byte + STY des_2h ; save descriptor_2 pointer high byte + JSR LAB_22EB ; clean descriptor stack, YA = pointer + LDY #$00 ; index to length + LDA (des_2l),Y ; get string length + STA (Lvarpl),Y ; copy to let string variable + INY ; index to string pointer low byte + LDA (des_2l),Y ; get string pointer low byte + STA (Lvarpl),Y ; copy to let string variable + INY ; index to string pointer high byte + LDA (des_2l),Y ; get string pointer high byte + STA (Lvarpl),Y ; copy to let string variable + RTS + +; perform GET + +LAB_GET + JSR LAB_GVAR ; get var address + STA Lvarpl ; save var address low byte + STY Lvarph ; save var address high byte + JSR INGET ; get input byte + LDX Dtypef ; get data type flag, $FF=string, $00=numeric + BMI LAB_GETS ; go get string character + + ; was numeric get + TAY ; copy character to Y + JSR LAB_1FD0 ; convert Y to byte in FAC1 + JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return + +LAB_GETS + PHA ; save character + LDA #$01 ; string is single byte + BCS LAB_IsByte ; branch if byte received + + PLA ; string is null +LAB_IsByte + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + BEQ LAB_NoSt ; skip store if null string + + PLA ; get character back + LDY #$00 ; clear index + STA (str_pl),Y ; save byte in string (byte IS string!) +LAB_NoSt + JSR LAB_RTST ; check for space on descriptor stack then put address + ; and length on descriptor stack and update stack pointers + + JMP LAB_17D5 ; do string LET and return + +; perform PRINT + +LAB_1829 + JSR LAB_18C6 ; print string from Sutill/Sutilh +LAB_182C + JSR LAB_GBYT ; scan memory + +; PRINT + +LAB_PRINT + BEQ LAB_CRLF ; if nothing following just print CR/LF + +LAB_1831 + CMP #TK_TAB ; compare with TAB( token + BEQ LAB_18A2 ; go do TAB/SPC + + CMP #TK_SPC ; compare with SPC( token + BEQ LAB_18A2 ; go do TAB/SPC + + CMP #',' ; compare with "," + BEQ LAB_188B ; go do move to next TAB mark + + CMP #';' ; compare with ";" + BEQ LAB_18BD ; if ";" continue with PRINT processing + + JSR LAB_EVEX ; evaluate expression + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BMI LAB_1829 ; branch if string + + JSR LAB_296E ; convert FAC1 to string + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + LDY #$00 ; clear index + +; don't check fit if terminal width byte is zero + + LDA TWidth ; get terminal width byte + BEQ LAB_185E ; skip check if zero + + SEC ; set carry for subtract + SBC TPos ; subtract terminal position + SBC (des_pl),Y ; subtract string length + BCS LAB_185E ; branch if less than terminal width + + JSR LAB_CRLF ; else print CR/LF +LAB_185E + JSR LAB_18C6 ; print string from Sutill/Sutilh + BEQ LAB_182C ; always go continue processing line + +; CR/LF return to BASIC from BASIC input handler + +LAB_1866 + LDA #$00 ; clear byte + STA Ibuffs,X ; null terminate input + LDX #Ibuffs ; set Y to buffer start-1 high byte + +; print CR/LF + +LAB_CRLF + LDA #$0D ; load [CR] + JSR LAB_PRNA ; go print the character + LDA #$0A ; load [LF] + BNE LAB_PRNA ; go print the character and return, branch always + +LAB_188B + LDA TPos ; get terminal position + CMP Iclim ; compare with input column limit + BCC LAB_1897 ; branch if less + + JSR LAB_CRLF ; else print CR/LF (next line) + BNE LAB_18BD ; continue with PRINT processing (branch always) + +LAB_1897 + SEC ; set carry for subtract +LAB_1898 + SBC TabSiz ; subtract TAB size + BCS LAB_1898 ; loop if result was +ve + + EOR #$FF ; complement it + ADC #$01 ; +1 (twos complement) + BNE LAB_18B6 ; always print A spaces (result is never $00) + + ; do TAB/SPC +LAB_18A2 + PHA ; save token + JSR LAB_SGBY ; scan and get byte parameter + CMP #$29 ; is next character ) + BNE LAB_1910 ; if not do syntax error then warm start + + PLA ; get token back + CMP #TK_TAB ; was it TAB ? + BNE LAB_18B7 ; if not go do SPC + + ; calculate TAB offset + TXA ; copy integer value to A + SBC TPos ; subtract terminal position + BCC LAB_18BD ; branch if result was < 0 (can't TAB backwards) + + ; print A spaces +LAB_18B6 + TAX ; copy result to X +LAB_18B7 + TXA ; set flags on size for SPC + BEQ LAB_18BD ; branch if result was = $0, already here + + ; print X spaces +LAB_18BA + JSR LAB_18E0 ; print " " + DEX ; decrement count + BNE LAB_18BA ; loop if not all done + + ; continue with PRINT processing +LAB_18BD + JSR LAB_IGBY ; increment and scan memory + BNE LAB_1831 ; if more to print go do it + + RTS + +; print null terminated string from memory + +LAB_18C3 + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + +; print string from Sutill/Sutilh + +LAB_18C6 + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=$71=pointer low byte, + ; Y=$72=pointer high byte + LDY #$00 ; reset index + TAX ; copy length to X + BEQ LAB_188C ; exit (RTS) if null string + +LAB_18CD + + LDA (ut1_pl),Y ; get next byte + JSR LAB_PRNA ; go print the character + INY ; increment index + DEX ; decrement count + BNE LAB_18CD ; loop if not done yet + + RTS + + ; Print single format character +; print " " + +LAB_18E0 + LDA #$20 ; load " " + .byte $2C ; change next line to BIT LAB_3FA9 + +; print "?" character + +LAB_18E3 + LDA #$3F ; load "?" character + +; print character in A +; now includes the null handler +; also includes infinite line length code +; note! some routines expect this one to exit with Zb=0 + +LAB_PRNA + CMP #' ' ; compare with " " + BCC LAB_18F9 ; branch if less (non printing) + + ; else printable character + PHA ; save the character + +; don't check fit if terminal width byte is zero + + LDA TWidth ; get terminal width + BNE LAB_18F0 ; branch if not zero (not infinite length) + +; is "infinite line" so check TAB position + + LDA TPos ; get position + SBC TabSiz ; subtract TAB size, carry set by CMP #$20 above + BNE LAB_18F7 ; skip reset if different + + STA TPos ; else reset position + BEQ LAB_18F7 ; go print character + +LAB_18F0 + CMP TPos ; compare with terminal character position + BNE LAB_18F7 ; branch if not at end of line + + JSR LAB_CRLF ; else print CR/LF +LAB_18F7 + INC TPos ; increment terminal position + PLA ; get character back +LAB_18F9 + JSR V_OUTP ; output byte via output vector + CMP #$0D ; compare with [CR] + BNE LAB_188A ; branch if not [CR] + + ; else print nullct nulls after the [CR] + STX TempB ; save buffer index + LDX Nullct ; get null count + BEQ LAB_1886 ; branch if no nulls + + LDA #$00 ; load [NULL] +LAB_1880 + JSR LAB_PRNA ; go print the character + DEX ; decrement count + BNE LAB_1880 ; loop if not all done + + LDA #$0D ; restore the character (and set the flags) +LAB_1886 + STX TPos ; clear terminal position (X always = zero when we get here) + LDX TempB ; restore buffer index +LAB_188A + AND #$FF ; set the flags +LAB_188C + RTS + +; handle bad input data + +LAB_1904 + LDA Imode ; get input mode flag, $00=INPUT, $00=READ + BPL LAB_1913 ; branch if INPUT (go do redo) + + LDA Dlinel ; get current DATA line low byte + LDY Dlineh ; get current DATA line high byte + STA Clinel ; save current line low byte + STY Clineh ; save current line high byte +LAB_1910 + JMP LAB_SNER ; do syntax error then warm start + + ; mode was INPUT +LAB_1913 + LDA #LAB_REDO ; point to redo message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + LDA Cpntrl ; get continue pointer low byte + LDY Cpntrh ; get continue pointer high byte + STA Bpntrl ; save BASIC execute pointer low byte + STY Bpntrh ; save BASIC execute pointer high byte + RTS + +; perform INPUT + +LAB_INPUT + CMP #$22 ; compare next byte with open quote + BNE LAB_1934 ; branch if no prompt string + + JSR LAB_1BC1 ; print "..." string + LDA #$3B ; load A with ";" + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + JSR LAB_18C6 ; print string from Sutill/Sutilh + + ; done with prompt, now get data +LAB_1934 + JSR LAB_CKRN ; check not Direct, back here if ok + JSR LAB_INLN ; print "? " and get BASIC input + LDA #$00 ; set mode = INPUT + CMP Ibuffs ; test first byte in buffer + BNE LAB_1953 ; branch if not null input + + CLC ; was null input so clear carry to exit program + JMP LAB_1647 ; go do BREAK exit + +; perform READ + +LAB_READ + LDX Dptrl ; get DATA pointer low byte + LDY Dptrh ; get DATA pointer high byte + LDA #$80 ; set mode = READ + +LAB_1953 + STA Imode ; set input mode flag, $00=INPUT, $80=READ + STX Rdptrl ; save READ pointer low byte + STY Rdptrh ; save READ pointer high byte + + ; READ or INPUT next variable from list +LAB_195B + JSR LAB_GVAR ; get (var) address + STA Lvarpl ; save address low byte + STY Lvarph ; save address high byte + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + STA Itempl ; save as temporary integer low byte + STY Itemph ; save as temporary integer high byte + LDX Rdptrl ; get READ pointer low byte + LDY Rdptrh ; get READ pointer high byte + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BNE LAB_1988 ; branch if not null + + ; pointer was to null entry + BIT Imode ; test input mode flag, $00=INPUT, $80=READ + BMI LAB_19DD ; branch if READ + + ; mode was INPUT + JSR LAB_18E3 ; print "?" character (double ? for extended input) + JSR LAB_INLN ; print "? " and get BASIC input + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte +LAB_1985 + JSR LAB_GBYT ; scan memory +LAB_1988 + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BPL LAB_19B0 ; branch if numeric + + ; else get string + STA Srchc ; save search character + CMP #$22 ; was it " ? + BEQ LAB_1999 ; branch if so + + LDA #':' ; else search character is ":" + STA Srchc ; set new search character + LDA #',' ; other search character is "," + CLC ; clear carry for add +LAB_1999 + STA Asrch ; set second search character + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + + ADC #$00 ; c is =1 if we came via the BEQ LAB_1999, else =0 + BCC LAB_19A4 ; branch if no execute pointer low byte rollover + + INY ; else increment high byte +LAB_19A4 + JSR LAB_20B4 ; print Srchc or Asrch terminated string to Sutill/Sutilh + JSR LAB_23F3 ; restore BASIC execute pointer from temp (Btmpl/Btmph) + JSR LAB_17D5 ; go do string LET + JMP LAB_19B6 ; go check string terminator + + ; get numeric INPUT +LAB_19B0 + JSR LAB_2887 ; get FAC1 from string + JSR LAB_PFAC ; pack FAC1 into (Lvarpl) +LAB_19B6 + JSR LAB_GBYT ; scan memory + BEQ LAB_19C5 ; branch if null (last entry) + + CMP #',' ; else compare with "," + BEQ LAB_19C2 ; branch if "," + + JMP LAB_1904 ; else go handle bad input data + + ; got good input data +LAB_19C2 + JSR LAB_IGBY ; increment and scan memory +LAB_19C5 + LDA Bpntrl ; get BASIC execute pointer low byte (temp READ/INPUT ptr) + LDY Bpntrh ; get BASIC execute pointer high byte (temp READ/INPUT ptr) + STA Rdptrl ; save for now + STY Rdptrh ; save for now + LDA Itempl ; get temporary integer low byte (temp BASIC execute ptr) + LDY Itemph ; get temporary integer high byte (temp BASIC execute ptr) + STA Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_1A03 ; if null go do extra ignored message + + JSR LAB_1C01 ; else scan for "," , else do syntax error then warm start + JMP LAB_195B ; go INPUT next variable from list + + ; find next DATA statement or do "Out of DATA" error +LAB_19DD + JSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL]) + INY ; increment index + TAX ; copy character ([:] or [EOL]) + BNE LAB_19F6 ; branch if [:] + + LDX #$06 ; set for "Out of DATA" error + INY ; increment index, now points to next line pointer high byte + LDA (Bpntrl),Y ; get next line pointer high byte + BEQ LAB_1A54 ; branch if end (eventually does error X) + + INY ; increment index + LDA (Bpntrl),Y ; get next line # low byte + STA Dlinel ; save current DATA line low byte + INY ; increment index + LDA (Bpntrl),Y ; get next line # high byte + INY ; increment index + STA Dlineh ; save current DATA line high byte +LAB_19F6 + LDA (Bpntrl),Y ; get byte + INY ; increment index + TAX ; copy to X + JSR LAB_170F ; set BASIC execute pointer + CPX #TK_DATA ; compare with "DATA" token + BEQ LAB_1985 ; was "DATA" so go do next READ + + BNE LAB_19DD ; go find next statement if not "DATA" + +; end of INPUT/READ routine + +LAB_1A03 + LDA Rdptrl ; get temp READ pointer low byte + LDY Rdptrh ; get temp READ pointer high byte + LDX Imode ; get input mode flag, $00=INPUT, $80=READ + BPL LAB_1A0E ; branch if INPUT + + JMP LAB_1624 ; save AY as DATA pointer and return + + ; we were getting INPUT +LAB_1A0E + LDY #$00 ; clear index + LDA (Rdptrl),Y ; get next byte + BNE LAB_1A1B ; error if not end of INPUT + + RTS + + ; user typed too much +LAB_1A1B + LDA #LAB_IMSG ; point to extra ignored message (high addr) + JMP LAB_18C3 ; print null terminated string from memory and return + +; search the stack for FOR activity +; exit with z=1 if FOR else exit with z=0 + +LAB_11A1 + TSX ; copy stack pointer + INX ; +1 pass return address + INX ; +2 pass return address + INX ; +3 pass calling routine return address + INX ; +4 pass calling routine return address +LAB_11A6 + LDA LAB_STAK+1,X ; get token byte from stack + CMP #TK_FOR ; is it FOR token + BNE LAB_11CE ; exit if not FOR token + + ; was FOR token + LDA Frnxth ; get var pointer for FOR/NEXT high byte + BNE LAB_11BB ; branch if not null + + LDA LAB_STAK+2,X ; get FOR variable pointer low byte + STA Frnxtl ; save var pointer for FOR/NEXT low byte + LDA LAB_STAK+3,X ; get FOR variable pointer high byte + STA Frnxth ; save var pointer for FOR/NEXT high byte +LAB_11BB + CMP LAB_STAK+3,X ; compare var pointer with stacked var pointer (high byte) + BNE LAB_11C7 ; branch if no match + + LDA Frnxtl ; get var pointer for FOR/NEXT low byte + CMP LAB_STAK+2,X ; compare var pointer with stacked var pointer (low byte) + BEQ LAB_11CE ; exit if match found + +LAB_11C7 + TXA ; copy index + CLC ; clear carry for add + ADC #$10 ; add FOR stack use size + TAX ; copy back to index + BNE LAB_11A6 ; loop if not at start of stack + +LAB_11CE + RTS + +; perform NEXT + +LAB_NEXT + BNE LAB_1A46 ; branch if NEXT var + + LDY #$00 ; else clear Y + BEQ LAB_1A49 ; branch always (no variable to search for) + +; NEXT var + +LAB_1A46 + JSR LAB_GVAR ; get variable address +LAB_1A49 + STA Frnxtl ; store variable pointer low byte + STY Frnxth ; store variable pointer high byte + ; (both cleared if no variable defined) + JSR LAB_11A1 ; search the stack for FOR activity + BEQ LAB_1A56 ; branch if found + + LDX #$00 ; else set error $00 ("NEXT without FOR" error) +LAB_1A54 + BEQ LAB_1ABE ; do error #X, then warm start + +LAB_1A56 + TXS ; set stack pointer, X set by search, dumps return addresses + + TXA ; copy stack pointer + SEC ; set carry for subtract + SBC #$F7 ; point to TO var + STA ut2_pl ; save pointer to TO var for compare + ADC #$FB ; point to STEP var + + LDY #>LAB_STAK ; point to stack page high byte + JSR LAB_UFAC ; unpack memory (STEP value) into FAC1 + TSX ; get stack pointer back + LDA LAB_STAK+8,X ; get step sign + STA FAC1_s ; save FAC1 sign (b7) + LDA Frnxtl ; get FOR variable pointer low byte + LDY Frnxth ; get FOR variable pointer high byte + JSR LAB_246C ; add (FOR variable) to FAC1 + JSR LAB_PFAC ; pack FAC1 into (FOR variable) + LDY #>LAB_STAK ; point to stack page high byte + JSR LAB_27FA ; compare FAC1 with (Y,ut2_pl) (TO value) + TSX ; get stack pointer back + CMP LAB_STAK+8,X ; compare step sign + BEQ LAB_1A9B ; branch if = (loop complete) + + ; loop back and do it all again + LDA LAB_STAK+$0D,X ; get FOR line low byte + STA Clinel ; save current line low byte + LDA LAB_STAK+$0E,X ; get FOR line high byte + STA Clineh ; save current line high byte + LDA LAB_STAK+$10,X ; get BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA LAB_STAK+$0F,X ; get BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte +LAB_1A98 + JMP LAB_15C2 ; go do interpreter inner loop + + ; loop complete so carry on +LAB_1A9B + TXA ; stack copy to A + ADC #$0F ; add $10 ($0F+carry) to dump FOR structure + TAX ; copy back to index + TXS ; copy to stack pointer + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BNE LAB_1A98 ; branch if not "," (go do interpreter inner loop) + + ; was "," so another NEXT variable to do + JSR LAB_IGBY ; else increment and scan memory + JSR LAB_1A46 ; do NEXT (var) + +; evaluate expression and check is numeric, else do type mismatch + +LAB_EVNM + JSR LAB_EVEX ; evaluate expression + +; check if source is numeric, else do type mismatch + +LAB_CTNM + CLC ; destination is numeric + .byte $24 ; makes next line BIT $38 + +; check if source is string, else do type mismatch + +LAB_CTST + SEC ; required type is string + +; type match check, set C for string, clear C for numeric + +LAB_CKTM + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BMI LAB_1ABA ; branch if data type is string + + ; else data type was numeric + BCS LAB_1ABC ; if required type is string do type mismatch error +LAB_1AB9 + RTS + + ; data type was string, now check required type +LAB_1ABA + BCS LAB_1AB9 ; exit if required type is string + + ; else do type mismatch error +LAB_1ABC + LDX #$18 ; error code $18 ("Type mismatch" error) +LAB_1ABE + JMP LAB_XERR ; do error #X, then warm start + +; evaluate expression + +LAB_EVEX + LDX Bpntrl ; get BASIC execute pointer low byte + BNE LAB_1AC7 ; skip next if not zero + + DEC Bpntrh ; else decrement BASIC execute pointer high byte +LAB_1AC7 + DEC Bpntrl ; decrement BASIC execute pointer low byte + +LAB_EVEZ + LDA #$00 ; set null precedence (flag done) +LAB_1ACC + PHA ; push precedence byte + LDA #$02 ; 2 bytes + JSR LAB_1212 ; check room on stack for A bytes + JSR LAB_GVAL ; get value from line + LDA #$00 ; clear A + STA comp_f ; clear compare function flag +LAB_1ADB + JSR LAB_GBYT ; scan memory +LAB_1ADE + SEC ; set carry for subtract + SBC #TK_GT ; subtract token for > (lowest comparison function) + BCC LAB_1AFA ; branch if < TK_GT + + CMP #$03 ; compare with ">" to "<" tokens + BCS LAB_1AFA ; branch if >= TK_SGN (highest evaluation function +1) + + ; was token for > = or < (A = 0, 1 or 2) + CMP #$01 ; compare with token for = + ROL ; *2, b0 = carry (=1 if token was = or <) + ; (A = 0, 3 or 5) + EOR #$01 ; toggle b0 + ; (A = 1, 2 or 4. 1 if >, 2 if =, 4 if <) + EOR comp_f ; EOR with compare function flag bits + CMP comp_f ; compare with compare function flag + BCC LAB_1B53 ; if <(comp_f) do syntax error then warm start + ; was more than one <, = or >) + + STA comp_f ; save new compare function flag + JSR LAB_IGBY ; increment and scan memory + JMP LAB_1ADE ; go do next character + + ; token is < ">" or > "<" tokens +LAB_1AFA + LDX comp_f ; get compare function flag + BNE LAB_1B2A ; branch if compare function + + BCS LAB_1B78 ; go do functions + + ; else was < TK_GT so is operator or lower + ADC #TK_GT-TK_PLUS ; add # of operators (+, -, *, /, ^, AND, OR or EOR) + BCC LAB_1B78 ; branch if < + operator + + ; carry was set so token was +, -, *, /, ^, AND, OR or EOR + BNE LAB_1B0B ; branch if not + token + + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BPL LAB_1B0B ; branch if not string + + ; will only be $00 if type is string and token was + + JMP LAB_224D ; add strings, string 1 is in descriptor des_pl, string 2 + ; is in line, and return + +LAB_1B0B + STA ut1_pl ; save it + ASL ; *2 + ADC ut1_pl ; *3 + TAY ; copy to index +LAB_1B13 + PLA ; pull previous precedence + CMP LAB_OPPT,Y ; compare with precedence byte + BCS LAB_1B7D ; branch if A >= + + JSR LAB_CTNM ; check if source is numeric, else do type mismatch +LAB_1B1C + PHA ; save precedence +LAB_1B1D + JSR LAB_1B43 ; get vector, execute function then continue evaluation + PLA ; restore precedence + LDY prstk ; get precedence stacked flag + BPL LAB_1B3C ; branch if stacked values + + TAX ; copy precedence (set flags) + BEQ LAB_1B9D ; exit if done + + BNE LAB_1B86 ; else pop FAC2 and return, branch always + +LAB_1B2A + ROL Dtypef ; shift data type flag into Cb + TXA ; copy compare function flag + STA Dtypef ; clear data type flag, X is 0xxx xxxx + ROL ; shift data type into compare function byte b0 + LDX Bpntrl ; get BASIC execute pointer low byte + BNE LAB_1B34 ; branch if no underflow + + DEC Bpntrh ; else decrement BASIC execute pointer high byte +LAB_1B34 + DEC Bpntrl ; decrement BASIC execute pointer low byte +TK_LT_PLUS = TK_LT-TK_PLUS + LDY #TK_LT_PLUS*3 ; set offset to last operator entry + STA comp_f ; save new compare function flag + BNE LAB_1B13 ; branch always + +LAB_1B3C + CMP LAB_OPPT,Y ;.compare with stacked function precedence + BCS LAB_1B86 ; branch if A >=, pop FAC2 and return + + BCC LAB_1B1C ; branch always + +;.get vector, execute function then continue evaluation + +LAB_1B43 + LDA LAB_OPPT+2,Y ; get function vector high byte + PHA ; onto stack + LDA LAB_OPPT+1,Y ; get function vector low byte + PHA ; onto stack + ; now push sign, round FAC1 and put on stack + JSR LAB_1B5B ; function will return here, then the next RTS will call + ; the function + LDA comp_f ; get compare function flag + PHA ; push compare evaluation byte + LDA LAB_OPPT,Y ; get precedence byte + JMP LAB_1ACC ; continue evaluating expression + +LAB_1B53 + JMP LAB_SNER ; do syntax error then warm start + +; push sign, round FAC1 and put on stack + +LAB_1B5B + PLA ; get return addr low byte + STA ut1_pl ; save it + INC ut1_pl ; increment it (was ret-1 pushed? yes!) + ; note! no check is made on the high byte! if the calling + ; routine assembles to a page edge then this all goes + ; horribly wrong !!! + PLA ; get return addr high byte + STA ut1_ph ; save it + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; push sign + +; round FAC1 and put on stack + +LAB_1B66 + JSR LAB_27BA ; round FAC1 + LDA FAC1_3 ; get FAC1 mantissa3 + PHA ; push on stack + LDA FAC1_2 ; get FAC1 mantissa2 + PHA ; push on stack + LDA FAC1_1 ; get FAC1 mantissa1 + PHA ; push on stack + LDA FAC1_e ; get FAC1 exponent + PHA ; push on stack + JMP (ut1_pl) ; return, sort of + +; do functions + +LAB_1B78 + LDY #$FF ; flag function + PLA ; pull precedence byte +LAB_1B7B + BEQ LAB_1B9D ; exit if done + +LAB_1B7D + CMP #$64 ; compare previous precedence with $64 + BEQ LAB_1B84 ; branch if was $64 (< function) + + JSR LAB_CTNM ; check if source is numeric, else do type mismatch +LAB_1B84 + STY prstk ; save precedence stacked flag + + ; pop FAC2 and return +LAB_1B86 + PLA ; pop byte + LSR ; shift out comparison evaluation lowest bit + STA Cflag ; save comparison evaluation flag + PLA ; pop exponent + STA FAC2_e ; save FAC2 exponent + PLA ; pop mantissa1 + STA FAC2_1 ; save FAC2 mantissa1 + PLA ; pop mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + PLA ; pop mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + PLA ; pop sign + STA FAC2_s ; save FAC2 sign (b7) + EOR FAC1_s ; EOR FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) +LAB_1B9D + LDA FAC1_e ; get FAC1 exponent + RTS + +; print "..." string to string util area + +LAB_1BC1 + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + ADC #$00 ; add carry to low byte + BCC LAB_1BCA ; branch if no overflow + + INY ; increment high byte +LAB_1BCA + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + JMP LAB_23F3 ; restore BASIC execute pointer from temp and return + +; get value from line + +LAB_GVAL + JSR LAB_IGBY ; increment and scan memory + BCS LAB_1BAC ; branch if not numeric character + + ; else numeric string found (e.g. 123) +LAB_1BA9 + JMP LAB_2887 ; get FAC1 from string and return + +; get value from line .. continued + + ; wasn't a number so .. +LAB_1BAC + TAX ; set the flags + BMI LAB_1BD0 ; if -ve go test token values + + ; else it is either a string, number, variable or () + CMP #'$' ; compare with "$" + BEQ LAB_1BA9 ; branch if "$", hex number + + CMP #'%' ; else compare with "%" + BEQ LAB_1BA9 ; branch if "%", binary number + + CMP #'.' ; compare with "." + BEQ LAB_1BA9 ; if so get FAC1 from string and return (e.g. was .123) + + ; it wasn't any sort of number so .. + CMP #$22 ; compare with " + BEQ LAB_1BC1 ; branch if open quote + + ; wasn't any sort of number so .. + +; evaluate expression within parentheses + + CMP #'(' ; compare with "(" + BNE LAB_1C18 ; if not "(" get (var), return value in FAC1 and $ flag + +LAB_1BF7 + JSR LAB_EVEZ ; evaluate expression, no decrement + +; all the 'scan for' routines return the character after the sought character + +; scan for ")" , else do syntax error then warm start + +LAB_1BFB + LDA #$29 ; load A with ")" + +; scan for CHR$(A) , else do syntax error then warm start + +LAB_SCCA + LDY #$00 ; clear index + CMP (Bpntrl),Y ; check next byte is = A + BNE LAB_SNER ; if not do syntax error then warm start + + JMP LAB_IGBY ; increment and scan memory then return + +; scan for "(" , else do syntax error then warm start + +LAB_1BFE + LDA #$28 ; load A with "(" + BNE LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + ; (branch always) + +; scan for "," , else do syntax error then warm start + +LAB_1C01 + LDA #$2C ; load A with "," + BNE LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + ; (branch always) + +; syntax error then warm start + +LAB_SNER + LDX #$02 ; error code $02 ("Syntax" error) + JMP LAB_XERR ; do error #X, then warm start + +; get value from line .. continued +; do tokens + +LAB_1BD0 + CMP #TK_MINUS ; compare with token for - + BEQ LAB_1C11 ; branch if - token (do set-up for functions) + + ; wasn't -n so .. + CMP #TK_PLUS ; compare with token for + + BEQ LAB_GVAL ; branch if + token (+n = n so ignore leading +) + + CMP #TK_NOT ; compare with token for NOT + BNE LAB_1BE7 ; branch if not token for NOT + + ; was NOT token +TK_EQUAL_PLUS = TK_EQUAL-TK_PLUS + LDY #TK_EQUAL_PLUS*3 ; offset to NOT function + BNE LAB_1C13 ; do set-up for function then execute (branch always) + +; do = compare + +LAB_EQUAL + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_3 ; get FAC1 mantissa3 + EOR #$FF ; invert it + TAY ; copy it + LDA FAC1_2 ; get FAC1 mantissa2 + EOR #$FF ; invert it + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; get value from line .. continued + + ; wasn't +, -, or NOT so .. +LAB_1BE7 + CMP #TK_FN ; compare with token for FN + BNE LAB_1BEE ; branch if not token for FN + + JMP LAB_201E ; go evaluate FNx + +; get value from line .. continued + + ; wasn't +, -, NOT or FN so .. +LAB_1BEE + SBC #TK_SGN ; subtract with token for SGN + BCS LAB_1C27 ; if a function token go do it + + JMP LAB_SNER ; else do syntax error + +; set-up for functions + +LAB_1C11 +TK_GT_PLUS = TK_GT-TK_PLUS + LDY #TK_GT_PLUS*3 ; set offset from base to > operator +LAB_1C13 + PLA ; dump return address low byte + PLA ; dump return address high byte + JMP LAB_1B1D ; execute function then continue evaluation + +; variable name set-up +; get (var), return value in FAC_1 and $ flag + +LAB_1C18 + JSR LAB_GVAR ; get (var) address + STA FAC1_2 ; save address low byte in FAC1 mantissa2 + STY FAC1_3 ; save address high byte in FAC1 mantissa3 + LDX Dtypef ; get data type flag, $FF=string, $00=numeric + BMI LAB_1C25 ; if string then return (does RTS) + +LAB_1C24 + JMP LAB_UFAC ; unpack memory (AY) into FAC1 + +LAB_1C25 + RTS + +; get value from line .. continued +; only functions left so .. + +; set up function references + +; new for V2.0+ this replaces a lot of IF .. THEN .. ELSEIF .. THEN .. that was needed +; to process function calls. now the function vector is computed and pushed on the stack +; and the preprocess offset is read. if the preprocess offset is non zero then the vector +; is calculated and the routine called, if not this routine just does RTS. whichever +; happens the RTS at the end of this routine, or the end of the preprocess routine, calls +; the function code + +; this also removes some less than elegant code that was used to bypass type checking +; for functions that returned strings + +LAB_1C27 + ASL ; *2 (2 bytes per function address) + TAY ; copy to index + + LDA LAB_FTBM,Y ; get function jump vector high byte + PHA ; push functions jump vector high byte + LDA LAB_FTBL,Y ; get function jump vector low byte + PHA ; push functions jump vector low byte + + LDA LAB_FTPM,Y ; get function pre process vector high byte + BEQ LAB_1C56 ; skip pre process if null vector + + PHA ; push functions pre process vector high byte + LDA LAB_FTPL,Y ; get function pre process vector low byte + PHA ; push functions pre process vector low byte + +LAB_1C56 + RTS ; do function, or pre process, call + +; process string expression in parenthesis + +LAB_PPFS + JSR LAB_1BF7 ; process expression in parenthesis + JMP LAB_CTST ; check if source is string then do function, + ; else do type mismatch + +; process numeric expression in parenthesis + +LAB_PPFN + JSR LAB_1BF7 ; process expression in parenthesis + JMP LAB_CTNM ; check if source is numeric then do function, + ; else do type mismatch + +; set numeric data type and increment BASIC execute pointer + +LAB_PPBI + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + JMP LAB_IGBY ; increment and scan memory then do function + +; process string for LEFT$, RIGHT$ or MID$ + +LAB_LRMS + JSR LAB_EVEZ ; evaluate (should be string) expression + JSR LAB_1C01 ; scan for ",", else do syntax error then warm start + JSR LAB_CTST ; check if source is string, else do type mismatch + + PLA ; get function jump vector low byte + TAX ; save functions jump vector low byte + PLA ; get function jump vector high byte + TAY ; save functions jump vector high byte + LDA des_ph ; get descriptor pointer high byte + PHA ; push string pointer high byte + LDA des_pl ; get descriptor pointer low byte + PHA ; push string pointer low byte + TYA ; get function jump vector high byte back + PHA ; save functions jump vector high byte + TXA ; get function jump vector low byte back + PHA ; save functions jump vector low byte + JSR LAB_GTBY ; get byte parameter + TXA ; copy byte parameter to A + RTS ; go do function + +; process numeric expression(s) for BIN$ or HEX$ + +LAB_BHSS + JSR LAB_EVEZ ; process expression + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_BHER ; branch if n>=2^24 (is too big) + + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDX #$02 ; 3 bytes to do +LAB_CFAC + LDA FAC1_1,X ; get byte from FAC1 + STA nums_1,X ; save byte to temp + DEX ; decrement index + BPL LAB_CFAC ; copy FAC1 mantissa to temp + + JSR LAB_GBYT ; get next BASIC byte + LDX #$00 ; set default to no leading "0"s + CMP #')' ; compare with close bracket + BEQ LAB_1C54 ; if ")" go do rest of function + + JSR LAB_SCGB ; scan for "," and get byte + JSR LAB_GBYT ; get last byte back + CMP #')' ; is next character ) + BNE LAB_BHER ; if not ")" go do error + +LAB_1C54 + RTS ; else do function + +LAB_BHER + JMP LAB_FCER ; do function call error then warm start + +; perform EOR + +; added operator format is the same as AND or OR, precedence is the same as OR + +; this bit worked first time but it took a while to sort out the operator table +; pointers and offsets afterwards! + +LAB_EOR + JSR GetFirst ; get first integer expression (no sign check) + EOR XOAw_l ; EOR with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + EOR XOAw_h ; EOR with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform OR + +LAB_OR + JSR GetFirst ; get first integer expression (no sign check) + ORA XOAw_l ; OR with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + ORA XOAw_h ; OR with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform AND + +LAB_AND + JSR GetFirst ; get first integer expression (no sign check) + AND XOAw_l ; AND with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + AND XOAw_h ; AND with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; get first value for OR, AND or EOR + +GetFirst + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_2 ; get FAC1 mantissa2 + STA XOAw_h ; save it + LDA FAC1_3 ; get FAC1 mantissa3 + STA XOAw_l ; save it + JSR LAB_279B ; copy FAC2 to FAC1 (get 2nd value in expression) + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_3 ; get FAC1 mantissa3 +LAB_1C95 + RTS + +; perform comparisons + +; do < compare + +LAB_LTHAN + JSR LAB_CKTM ; type match check, set C for string + BCS LAB_1CAE ; branch if string + + ; do numeric < compare + LDA FAC2_s ; get FAC2 sign (b7) + ORA #$7F ; set all non sign bits + AND FAC2_1 ; and FAC2 mantissa1 (AND in sign bit) + STA FAC2_1 ; save FAC2 mantissa1 + LDA #FAC2_e ; set pointer high byte to FAC2 + JSR LAB_27F8 ; compare FAC1 with FAC2 (AY) + TAX ; copy result + JMP LAB_1CE1 ; go evaluate result + + ; do string < compare +LAB_1CAE + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + DEC comp_f ; clear < bit in compare function flag + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=pointer low byte, + ; Y=pointer high byte + STA str_ln ; save length + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + LDA FAC2_2 ; get descriptor pointer low byte + LDY FAC2_3 ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=pointer low byte, + ; Y=pointer high byte + STX FAC2_2 ; save string pointer low byte + STY FAC2_3 ; save string pointer high byte + TAX ; copy length + SEC ; set carry for subtract + SBC str_ln ; subtract string 1 length + BEQ LAB_1CD6 ; branch if str 1 length = string 2 length + + LDA #$01 ; set str 1 length > string 2 length + BCC LAB_1CD6 ; branch if so + + LDX str_ln ; get string 1 length + LDA #$FF ; set str 1 length < string 2 length +LAB_1CD6 + STA FAC1_s ; save length compare + LDY #$FF ; set index + INX ; adjust for loop +LAB_1CDB + INY ; increment index + DEX ; decrement count + BNE LAB_1CE6 ; branch if still bytes to do + + LDX FAC1_s ; get length compare back +LAB_1CE1 + BMI LAB_1CF2 ; branch if str 1 < str 2 + + CLC ; flag str 1 <= str 2 + BCC LAB_1CF2 ; go evaluate result + +LAB_1CE6 + LDA (FAC2_2),Y ; get string 2 byte + CMP (FAC1_1),Y ; compare with string 1 byte + BEQ LAB_1CDB ; loop if bytes = + + LDX #$FF ; set str 1 < string 2 + BCS LAB_1CF2 ; branch if so + + LDX #$01 ; set str 1 > string 2 +LAB_1CF2 + INX ; x = 0, 1 or 2 + TXA ; copy to A + ROL ; *2 (1, 2 or 4) + AND Cflag ; AND with comparison evaluation flag + BEQ LAB_1CFB ; branch if 0 (compare is false) + + LDA #$FF ; else set result true +LAB_1CFB + JMP LAB_27DB ; save A as integer byte and return + +LAB_1CFE + JSR LAB_1C01 ; scan for ",", else do syntax error then warm start + +; perform DIM + +LAB_DIM + TAX ; copy "DIM" flag to X + JSR LAB_1D10 ; search for variable + JSR LAB_GBYT ; scan memory + BNE LAB_1CFE ; scan for "," and loop if not null + + RTS + +; perform << (left shift) + +LAB_LSHIFT + JSR GetPair ; get integer expression and byte (no sign check) + LDA FAC1_2 ; get expression high byte + LDX TempB ; get shift count + BEQ NoShift ; branch if zero + + CPX #$10 ; compare bit count with 16d + BCS TooBig ; branch if >= + +Ls_loop + ASL FAC1_3 ; shift low byte + ROL ; shift high byte + DEX ; decrement bit count + BNE Ls_loop ; loop if shift not complete + + LDY FAC1_3 ; get expression low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform >> (right shift) + +LAB_RSHIFT + JSR GetPair ; get integer expression and byte (no sign check) + LDA FAC1_2 ; get expression high byte + LDX TempB ; get shift count + BEQ NoShift ; branch if zero + + CPX #$10 ; compare bit count with 16d + BCS TooBig ; branch if >= + +Rs_loop + LSR ; shift high byte + ROR FAC1_3 ; shift low byte + DEX ; decrement bit count + BNE Rs_loop ; loop if shift not complete + +NoShift + LDY FAC1_3 ; get expression low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +TooBig + LDA #$00 ; clear high byte + TAY ; copy to low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +GetPair + JSR LAB_EVBY ; evaluate byte expression, result in X + STX TempB ; save it + JSR LAB_279B ; copy FAC2 to FAC1 (get 2nd value in expression) + JMP LAB_EVIR ; evaluate integer expression (no sign check) + +; search for variable + +; return pointer to variable in Cvaral/Cvarah + +LAB_GVAR + LDX #$00 ; set DIM flag = $00 + JSR LAB_GBYT ; scan memory (1st character) +LAB_1D10 + STX Defdim ; save DIM flag +LAB_1D12 + STA Varnm1 ; save 1st character + AND #$7F ; clear FN flag bit + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCS LAB_1D1F ; branch if ok + + JMP LAB_SNER ; else syntax error then warm start + + ; was variable name so .. +LAB_1D1F + LDX #$00 ; clear 2nd character temp + STX Dtypef ; clear data type flag, $FF=string, $00=numeric + JSR LAB_IGBY ; increment and scan memory (2nd character) + BCC LAB_1D2D ; branch if character = "0"-"9" (ok) + + ; 2nd character wasn't "0" to "9" so .. + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCC LAB_1D38 ; branch if <"A" or >"Z" (go check if string) + +LAB_1D2D + TAX ; copy 2nd character + + ; ignore further (valid) characters in the variable name +LAB_1D2E + JSR LAB_IGBY ; increment and scan memory (3rd character) + BCC LAB_1D2E ; loop if character = "0"-"9" (ignore) + + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCS LAB_1D2E ; loop if character = "A"-"Z" (ignore) + + ; check if string variable +LAB_1D38 + CMP #'$' ; compare with "$" + BNE LAB_1D47 ; branch if not string + +; to introduce a new variable type (% suffix for integers say) then this branch +; will need to go to that check and then that branch, if it fails, go to LAB_1D47 + + ; type is string + LDA #$FF ; set data type = string + STA Dtypef ; set data type flag, $FF=string, $00=numeric + TXA ; get 2nd character back + ORA #$80 ; set top bit (indicate string var) + TAX ; copy back to 2nd character temp + JSR LAB_IGBY ; increment and scan memory + +; after we have determined the variable type we need to come back here to determine +; if it's an array of type. this would plug in a%(b[,c[,d]])) integer arrays nicely + + +LAB_1D47 ; gets here with character after var name in A + STX Varnm2 ; save 2nd character + ORA Sufnxf ; or with subscript/FNX flag (or FN name) + CMP #'(' ; compare with "(" + BNE LAB_1D53 ; branch if not "(" + + JMP LAB_1E17 ; go find, or make, array + +; either find or create var +; var name (1st two characters only!) is in Varnm1,Varnm2 + + ; variable name wasn't var(... so look for plain var +LAB_1D53 + LDA #$00 ; clear A + STA Sufnxf ; clear subscript/FNX flag + LDA Svarl ; get start of vars low byte + LDX Svarh ; get start of vars high byte + LDY #$00 ; clear index +LAB_1D5D + STX Vrschh ; save search address high byte +LAB_1D5F + STA Vrschl ; save search address low byte + CPX Sarryh ; compare high address with var space end + BNE LAB_1D69 ; skip next compare if <> + + ; high addresses were = so compare low addresses + CMP Sarryl ; compare low address with var space end + BEQ LAB_1D8B ; if not found go make new var + +LAB_1D69 + LDA Varnm1 ; get 1st character of var to find + CMP (Vrschl),Y ; compare with variable name 1st character + BNE LAB_1D77 ; branch if no match + + ; 1st characters match so compare 2nd characters + LDA Varnm2 ; get 2nd character of var to find + INY ; index to point to variable name 2nd character + CMP (Vrschl),Y ; compare with variable name 2nd character + BEQ LAB_1DD7 ; branch if match (found var) + + DEY ; else decrement index (now = $00) +LAB_1D77 + CLC ; clear carry for add + LDA Vrschl ; get search address low byte + ADC #$06 ; +6 (offset to next var name) + BCC LAB_1D5F ; loop if no overflow to high byte + + INX ; else increment high byte + BNE LAB_1D5D ; loop always (RAM doesn't extend to $FFFF !) + +; check byte, return C=0 if<"A" or >"Z" or "a" to "z" + +LAB_CASC + CMP #'a' ; compare with "a" + BCS LAB_1D83 ; go check <"z"+1 + +; check byte, return C=0 if<"A" or >"Z" + +LAB_1D82 + CMP #'A' ; compare with "A" + BCC LAB_1D8A ; exit if less + + ; carry is set + SBC #$5B ; subtract "Z"+1 + SEC ; set carry + SBC #$A5 ; subtract $A5 (restore byte) + ; carry clear if byte>$5A +LAB_1D8A + RTS + +LAB_1D83 + SBC #$7B ; subtract "z"+1 + SEC ; set carry + SBC #$85 ; subtract $85 (restore byte) + ; carry clear if byte>$7A + RTS + + ; reached end of variable mem without match + ; .. so create new variable +LAB_1D8B + PLA ; pop return address low byte + PHA ; push return address low byte +LAB_1C18p2 = LAB_1C18+2 + CMP #LAB_1D96 ; high byte point to $00,$00 + RTS + + ; create new numeric variable +LAB_1D98 + LDA Sarryl ; get var mem end low byte + LDY Sarryh ; get var mem end high byte + STA Ostrtl ; save old block start low byte + STY Ostrth ; save old block start high byte + LDA Earryl ; get array mem end low byte + LDY Earryh ; get array mem end high byte + STA Obendl ; save old block end low byte + STY Obendh ; save old block end high byte + CLC ; clear carry for add + ADC #$06 ; +6 (space for one var) + BCC LAB_1DAE ; branch if no overflow to high byte + + INY ; else increment high byte +LAB_1DAE + STA Nbendl ; set new block end low byte + STY Nbendh ; set new block end high byte + JSR LAB_11CF ; open up space in memory + LDA Nbendl ; get new start low byte + LDY Nbendh ; get new start high byte (-$100) + INY ; correct high byte + STA Sarryl ; save new var mem end low byte + STY Sarryh ; save new var mem end high byte + LDY #$00 ; clear index + LDA Varnm1 ; get var name 1st character + STA (Vrschl),Y ; save var name 1st character + INY ; increment index + LDA Varnm2 ; get var name 2nd character + STA (Vrschl),Y ; save var name 2nd character + LDA #$00 ; clear A + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + + ; found a match for var ((Vrschl) = ptr) +LAB_1DD7 + LDA Vrschl ; get var address low byte + CLC ; clear carry for add + ADC #$02 ; +2 (offset past var name bytes) + LDY Vrschh ; get var address high byte + BCC LAB_1DE1 ; branch if no overflow from add + + INY ; else increment high byte +LAB_1DE1 + STA Cvaral ; save current var address low byte + STY Cvarah ; save current var address high byte + RTS + +; set-up array pointer (Adatal/h) to first element in array +; set Adatal,Adatah to Astrtl,Astrth+2*Dimcnt+#$05 + +LAB_1DE6 + LDA Dimcnt ; get # of dimensions (1, 2 or 3) + ASL ; *2 (also clears the carry !) + ADC #$05 ; +5 (result is 7, 9 or 11 here) + ADC Astrtl ; add array start pointer low byte + LDY Astrth ; get array pointer high byte + BCC LAB_1DF2 ; branch if no overflow + + INY ; else increment high byte +LAB_1DF2 + STA Adatal ; save array data pointer low byte + STY Adatah ; save array data pointer high byte + RTS + +; evaluate integer expression + +LAB_EVIN + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + +; evaluate integer expression (no check) + +LAB_EVPI + LDA FAC1_s ; get FAC1 sign (b7) + BMI LAB_1E12 ; do function call error if -ve + +; evaluate integer expression (no sign check) + +LAB_EVIR + LDA FAC1_e ; get FAC1 exponent + CMP #$90 ; compare with exponent = 2^16 (n>2^15) + BCC LAB_1E14 ; branch if n<2^16 (is ok) + + LDA #LAB_1DF7 ; set pointer high byte to -32768 + JSR LAB_27F8 ; compare FAC1 with (AY) +LAB_1E12 + BNE LAB_FCER ; if <> do function call error then warm start + +LAB_1E14 + JMP LAB_2831 ; convert FAC1 floating-to-fixed and return + +; find or make array + +LAB_1E17 + LDA Defdim ; get DIM flag + PHA ; push it + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; push it + LDY #$00 ; clear dimensions count + +; now get the array dimension(s) and stack it (them) before the data type and DIM flag + +LAB_1E1F + TYA ; copy dimensions count + PHA ; save it + LDA Varnm2 ; get array name 2nd byte + PHA ; save it + LDA Varnm1 ; get array name 1st byte + PHA ; save it + JSR LAB_EVIN ; evaluate integer expression + PLA ; pull array name 1st byte + STA Varnm1 ; restore array name 1st byte + PLA ; pull array name 2nd byte + STA Varnm2 ; restore array name 2nd byte + PLA ; pull dimensions count + TAY ; restore it + TSX ; copy stack pointer + LDA LAB_STAK+2,X ; get DIM flag + PHA ; push it + LDA LAB_STAK+1,X ; get data type flag + PHA ; push it + LDA FAC1_2 ; get this dimension size high byte + STA LAB_STAK+2,X ; stack before flag bytes + LDA FAC1_3 ; get this dimension size low byte + STA LAB_STAK+1,X ; stack before flag bytes + INY ; increment dimensions count + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BEQ LAB_1E1F ; if found go do next dimension + + STY Dimcnt ; store dimensions count + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + PLA ; pull data type flag + STA Dtypef ; restore data type flag, $FF=string, $00=numeric + PLA ; pull DIM flag + STA Defdim ; restore DIM flag + LDX Sarryl ; get array mem start low byte + LDA Sarryh ; get array mem start high byte + +; now check to see if we are at the end of array memory (we would be if there were +; no arrays). + +LAB_1E5C + STX Astrtl ; save as array start pointer low byte + STA Astrth ; save as array start pointer high byte + CMP Earryh ; compare with array mem end high byte + BNE LAB_1E68 ; branch if not reached array mem end + + CPX Earryl ; else compare with array mem end low byte + BEQ LAB_1EA1 ; go build array if not found + + ; search for array +LAB_1E68 + LDY #$00 ; clear index + LDA (Astrtl),Y ; get array name first byte + INY ; increment index to second name byte + CMP Varnm1 ; compare with this array name first byte + BNE LAB_1E77 ; branch if no match + + LDA Varnm2 ; else get this array name second byte + CMP (Astrtl),Y ; compare with array name second byte + BEQ LAB_1E8D ; array found so branch + + ; no match +LAB_1E77 + INY ; increment index + LDA (Astrtl),Y ; get array size low byte + CLC ; clear carry for add + ADC Astrtl ; add array start pointer low byte + TAX ; copy low byte to X + INY ; increment index + LDA (Astrtl),Y ; get array size high byte + ADC Astrth ; add array mem pointer high byte + BCC LAB_1E5C ; if no overflow go check next array + +; do array bounds error + +LAB_1E85 + LDX #$10 ; error code $10 ("Array bounds" error) + .byte $2C ; makes next bit BIT LAB_08A2 + +; do function call error + +LAB_FCER + LDX #$08 ; error code $08 ("Function call" error) +LAB_1E8A + JMP LAB_XERR ; do error #X, then warm start + + ; found array, are we trying to dimension it? +LAB_1E8D + LDX #$12 ; set error $12 ("Double dimension" error) + LDA Defdim ; get DIM flag + BNE LAB_1E8A ; if we are trying to dimension it do error #X, then warm + ; start + +; found the array and we're not dimensioning it so we must find an element in it + + JSR LAB_1DE6 ; set-up array pointer (Adatal/h) to first element in array + ; (Astrtl,Astrth points to start of array) + LDA Dimcnt ; get dimensions count + LDY #$04 ; set index to array's # of dimensions + CMP (Astrtl),Y ; compare with no of dimensions + BNE LAB_1E85 ; if wrong do array bounds error, could do "Wrong + ; dimensions" error here .. if we want a different + ; error message + + JMP LAB_1F28 ; found array so go get element + ; (could jump to LAB_1F28 as all LAB_1F24 does is take + ; Dimcnt and save it at (Astrtl),Y which is already the + ; same or we would have taken the BNE) + + ; array not found, so build it +LAB_1EA1 + JSR LAB_1DE6 ; set-up array pointer (Adatal/h) to first element in array + ; (Astrtl,Astrth points to start of array) + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + LDY #$00 ; clear Y (don't need to clear A) + STY Aspth ; clear array data size high byte + LDA Varnm1 ; get variable name 1st byte + STA (Astrtl),Y ; save array name 1st byte + INY ; increment index + LDA Varnm2 ; get variable name 2nd byte + STA (Astrtl),Y ; save array name 2nd byte + LDA Dimcnt ; get dimensions count + LDY #$04 ; index to dimension count + STY Asptl ; set array data size low byte (four bytes per element) + STA (Astrtl),Y ; set array's dimensions count + + ; now calculate the size of the data space for the array + CLC ; clear carry for add (clear on subsequent loops) +LAB_1EC0 + LDX #$0B ; set default dimension value low byte + LDA #$00 ; set default dimension value high byte + BIT Defdim ; test default DIM flag + BVC LAB_1ED0 ; branch if b6 of Defdim is clear + + PLA ; else pull dimension value low byte + ADC #$01 ; +1 (allow for zeroeth element) + TAX ; copy low byte to X + PLA ; pull dimension value high byte + ADC #$00 ; add carry from low byte + +LAB_1ED0 + INY ; index to dimension value high byte + STA (Astrtl),Y ; save dimension value high byte + INY ; index to dimension value high byte + TXA ; get dimension value low byte + STA (Astrtl),Y ; save dimension value low byte + JSR LAB_1F7C ; does XY = (Astrtl),Y * (Asptl) + STX Asptl ; save array data size low byte + STA Aspth ; save array data size high byte + LDY ut1_pl ; restore index (saved by subroutine) + DEC Dimcnt ; decrement dimensions count + BNE LAB_1EC0 ; loop while not = 0 + + ADC Adatah ; add size high byte to first element high byte + ; (carry is always clear here) + BCS LAB_1F45 ; if overflow go do "Out of memory" error + + STA Adatah ; save end of array high byte + TAY ; copy end high byte to Y + TXA ; get array size low byte + ADC Adatal ; add array start low byte + BCC LAB_1EF3 ; branch if no carry + + INY ; else increment end of array high byte + BEQ LAB_1F45 ; if overflow go do "Out of memory" error + + ; set-up mostly complete, now zero the array +LAB_1EF3 + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + STA Earryl ; save array mem end low byte + STY Earryh ; save array mem end high byte + LDA #$00 ; clear byte for array clear + INC Aspth ; increment array size high byte (now block count) + LDY Asptl ; get array size low byte (now index to block) + BEQ LAB_1F07 ; branch if low byte = $00 + +LAB_1F02 + DEY ; decrement index (do 0 to n-1) + STA (Adatal),Y ; zero byte + BNE LAB_1F02 ; loop until this block done + +LAB_1F07 + DEC Adatah ; decrement array pointer high byte + DEC Aspth ; decrement block count high byte + BNE LAB_1F02 ; loop until all blocks done + + INC Adatah ; correct for last loop + SEC ; set carry for subtract + LDY #$02 ; index to array size low byte + LDA Earryl ; get array mem end low byte + SBC Astrtl ; subtract array start low byte + STA (Astrtl),Y ; save array size low byte + INY ; index to array size high byte + LDA Earryh ; get array mem end high byte + SBC Astrth ; subtract array start high byte + STA (Astrtl),Y ; save array size high byte + LDA Defdim ; get default DIM flag + BNE LAB_1F7B ; exit (RET) if this was a DIM command + + ; else, find element + INY ; index to # of dimensions + +LAB_1F24 + LDA (Astrtl),Y ; get array's dimension count + STA Dimcnt ; save it + +; we have found, or built, the array. now we need to find the element + +LAB_1F28 + LDA #$00 ; clear byte + STA Asptl ; clear array data pointer low byte +LAB_1F2C + STA Aspth ; save array data pointer high byte + INY ; increment index (point to array bound high byte) + PLA ; pull array index low byte + TAX ; copy to X + STA FAC1_2 ; save index low byte to FAC1 mantissa2 + PLA ; pull array index high byte + STA FAC1_3 ; save index high byte to FAC1 mantissa3 + CMP (Astrtl),Y ; compare with array bound high byte + BCC LAB_1F48 ; branch if within bounds + + BNE LAB_1F42 ; if outside bounds do array bounds error + + ; else high byte was = so test low bytes + INY ; index to array bound low byte + TXA ; get array index low byte + CMP (Astrtl),Y ; compare with array bound low byte + BCC LAB_1F49 ; branch if within bounds + +LAB_1F42 + JMP LAB_1E85 ; else do array bounds error + +LAB_1F45 + JMP LAB_OMER ; do "Out of memory" error then warm start + +LAB_1F48 + INY ; index to array bound low byte +LAB_1F49 + LDA Aspth ; get array data pointer high byte + ORA Asptl ; OR with array data pointer low byte + BEQ LAB_1F5A ; branch if array data pointer = null (skip multiply) + + JSR LAB_1F7C ; does XY = (Astrtl),Y * (Asptl) + TXA ; get result low byte + ADC FAC1_2 ; add index low byte from FAC1 mantissa2 + TAX ; save result low byte + TYA ; get result high byte + LDY ut1_pl ; restore index +LAB_1F5A + ADC FAC1_3 ; add index high byte from FAC1 mantissa3 + STX Asptl ; save array data pointer low byte + DEC Dimcnt ; decrement dimensions count + BNE LAB_1F2C ; loop if dimensions still to do + + ASL Asptl ; array data pointer low byte * 2 + ROL ; array data pointer high byte * 2 + ASL Asptl ; array data pointer low byte * 4 + ROL ; array data pointer high byte * 4 + TAY ; copy high byte + LDA Asptl ; get low byte + ADC Adatal ; add array data start pointer low byte + STA Cvaral ; save as current var address low byte + TYA ; get high byte back + ADC Adatah ; add array data start pointer high byte + STA Cvarah ; save as current var address high byte + TAY ; copy high byte to Y + LDA Cvaral ; get current var address low byte +LAB_1F7B + RTS + +; does XY = (Astrtl),Y * (Asptl) + +LAB_1F7C + STY ut1_pl ; save index + LDA (Astrtl),Y ; get dimension size low byte + STA dims_l ; save dimension size low byte + DEY ; decrement index + LDA (Astrtl),Y ; get dimension size high byte + STA dims_h ; save dimension size high byte + + LDA #$10 ; count = $10 (16 bit multiply) + STA numbit ; save bit count + LDX #$00 ; clear result low byte + LDY #$00 ; clear result high byte +LAB_1F8F + TXA ; get result low byte + ASL ; *2 + TAX ; save result low byte + TYA ; get result high byte + ROL ; *2 + TAY ; save result high byte + BCS LAB_1F45 ; if overflow go do "Out of memory" error + + ASL Asptl ; shift multiplier low byte + ROL Aspth ; shift multiplier high byte + BCC LAB_1FA8 ; skip add if no carry + + CLC ; else clear carry for add + TXA ; get result low byte + ADC dims_l ; add dimension size low byte + TAX ; save result low byte + TYA ; get result high byte + ADC dims_h ; add dimension size high byte + TAY ; save result high byte + BCS LAB_1F45 ; if overflow go do "Out of memory" error + +LAB_1FA8 + DEC numbit ; decrement bit count + BNE LAB_1F8F ; loop until all done + + RTS + +; perform FRE() + +LAB_FRE + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + BPL LAB_1FB4 ; branch if numeric + + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=$71=pointer low byte, + ; Y=$72=pointer high byte + + ; FRE(n) was numeric so do this +LAB_1FB4 + JSR LAB_GARB ; go do garbage collection + SEC ; set carry for subtract + LDA Sstorl ; get bottom of string space low byte + SBC Earryl ; subtract array mem end low byte + TAY ; copy result to Y + LDA Sstorh ; get bottom of string space high byte + SBC Earryh ; subtract array mem end high byte + +; save and convert integer AY to FAC1 + +LAB_AYFC + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + STA FAC1_1 ; save FAC1 mantissa1 + STY FAC1_2 ; save FAC1 mantissa2 + LDX #$90 ; set exponent=2^16 (integer) + JMP LAB_27E3 ; set exp=X, clear FAC1_3, normalise and return + +; perform POS() + +LAB_POS + LDY TPos ; get terminal position + +; convert Y to byte in FAC1 + +LAB_1FD0 + LDA #$00 ; clear high byte + BEQ LAB_AYFC ; always save and convert integer AY to FAC1 and return + +; check not Direct (used by DEF and INPUT) + +LAB_CKRN + LDX Clineh ; get current line high byte + INX ; increment it + BNE LAB_1F7B ; return if can continue not direct mode + + ; else do illegal direct error +LAB_1FD9 + LDX #$16 ; error code $16 ("Illegal direct" error) +LAB_1FDB + JMP LAB_XERR ; go do error #X, then warm start + +; perform DEF + +LAB_DEF + JSR LAB_200B ; check FNx syntax + STA func_l ; save function pointer low byte + STY func_h ; save function pointer high byte + JSR LAB_CKRN ; check not Direct (back here if ok) + JSR LAB_1BFE ; scan for "(" , else do syntax error then warm start + LDA #$80 ; set flag for FNx + STA Sufnxf ; save subscript/FNx flag + JSR LAB_GVAR ; get (var) address + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + LDA #TK_EQUAL ; get = token + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + LDA Cvarah ; get current var address high byte + PHA ; push it + LDA Cvaral ; get current var address low byte + PHA ; push it + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push it + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push it + JSR LAB_DATA ; go perform DATA + JMP LAB_207A ; put execute pointer and variable pointer into function + ; and return + +; check FNx syntax + +LAB_200B + LDA #TK_FN ; get FN" token + JSR LAB_SCCA ; scan for CHR$(A) , else do syntax error then warm start + ; return character after A + ORA #$80 ; set FN flag bit + STA Sufnxf ; save FN flag so array variable test fails + JSR LAB_1D12 ; search for FN variable + JMP LAB_CTNM ; check if source is numeric and return, else do type + ; mismatch + + ; Evaluate FNx +LAB_201E + JSR LAB_200B ; check FNx syntax + PHA ; push function pointer low byte + TYA ; copy function pointer high byte + PHA ; push function pointer high byte + JSR LAB_1BFE ; scan for "(", else do syntax error then warm start + JSR LAB_EVEX ; evaluate expression + JSR LAB_1BFB ; scan for ")", else do syntax error then warm start + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + PLA ; pop function pointer high byte + STA func_h ; restore it + PLA ; pop function pointer low byte + STA func_l ; restore it + LDX #$20 ; error code $20 ("Undefined function" error) + LDY #$03 ; index to variable pointer high byte + LDA (func_l),Y ; get variable pointer high byte + BEQ LAB_1FDB ; if zero go do undefined function error + + STA Cvarah ; save variable address high byte + DEY ; index to variable address low byte + LDA (func_l),Y ; get variable address low byte + STA Cvaral ; save variable address low byte + TAX ; copy address low byte + + ; now stack the function variable value before use + INY ; index to mantissa_3 +LAB_2043 + LDA (Cvaral),Y ; get byte from variable + PHA ; stack it + DEY ; decrement index + BPL LAB_2043 ; loop until variable stacked + + LDY Cvarah ; get variable address high byte + JSR LAB_2778 ; pack FAC1 (function expression value) into (XY) + ; (function variable), return Y=0, always + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push it + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push it + LDA (func_l),Y ; get function execute pointer low byte + STA Bpntrl ; save as BASIC execute pointer low byte + INY ; index to high byte + LDA (func_l),Y ; get function execute pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + LDA Cvarah ; get variable address high byte + PHA ; push it + LDA Cvaral ; get variable address low byte + PHA ; push it + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + PLA ; pull variable address low byte + STA func_l ; save variable address low byte + PLA ; pull variable address high byte + STA func_h ; save variable address high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_2074 ; branch if null (should be [EOL] marker) + + JMP LAB_SNER ; else syntax error then warm start + +; restore Bpntrl,Bpntrh and function variable from stack + +LAB_2074 + PLA ; pull BASIC execute pointer low byte + STA Bpntrl ; restore BASIC execute pointer low byte + PLA ; pull BASIC execute pointer high byte + STA Bpntrh ; restore BASIC execute pointer high byte + +; put execute pointer and variable pointer into function + +LAB_207A + LDY #$00 ; clear index + PLA ; pull BASIC execute pointer low byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull BASIC execute pointer high byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull current var address low byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull current var address high byte + STA (func_l),Y ; save to function + RTS + +; perform STR$() + +LAB_STRS + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + JSR LAB_296E ; convert FAC1 to string + LDA #Decssp1 ; set result string high pointer + BEQ LAB_20AE ; print null terminated string to Sutill/Sutilh + +; Do string vector +; copy des_pl/h to des_2l/h and make string space A bytes long + +LAB_209C + LDX des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + STX des_2l ; save descriptor pointer low byte + STY des_2h ; save descriptor pointer high byte + +; make string space A bytes long +; A=length, X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + +LAB_MSSP + JSR LAB_2115 ; make space in string memory for string A long + ; return X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + STA str_ln ; save length + RTS + +; Scan, set up string +; print " terminated string to Sutill/Sutilh + +LAB_20AE + LDX #$22 ; set terminator to " + STX Srchc ; set search character (terminator 1) + STX Asrch ; set terminator 2 + +; print [Srchc] or [Asrch] terminated string to Sutill/Sutilh +; source is AY + +LAB_20B4 + STA ssptr_l ; store string start low byte + STY ssptr_h ; store string start high byte + STA str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + LDY #$FF ; set length to -1 +LAB_20BE + INY ; increment length + LDA (ssptr_l),Y ; get byte from string + BEQ LAB_20CF ; exit loop if null byte [EOS] + + CMP Srchc ; compare with search character (terminator 1) + BEQ LAB_20CB ; branch if terminator + + CMP Asrch ; compare with terminator 2 + BNE LAB_20BE ; loop if not terminator 2 + +LAB_20CB + CMP #$22 ; compare with " + BEQ LAB_20D0 ; branch if " (carry set if = !) + +LAB_20CF + CLC ; clear carry for add (only if [EOL] terminated string) +LAB_20D0 + STY str_ln ; save length in FAC1 exponent + TYA ; copy length to A + ADC ssptr_l ; add string start low byte + STA Sendl ; save string end low byte + LDX ssptr_h ; get string start high byte + BCC LAB_20DC ; branch if no low byte overflow + + INX ; else increment high byte +LAB_20DC + STX Sendh ; save string end high byte + LDA ssptr_h ; get string start high byte + CMP #>Ram_base ; compare with start of program memory + BCS LAB_RTST ; branch if not in utility area + + ; string in utility area, move to string memory + TYA ; copy length to A + JSR LAB_209C ; copy des_pl/h to des_2l/h and make string space A bytes + ; long + LDX ssptr_l ; get string start low byte + LDY ssptr_h ; get string start high byte + JSR LAB_2298 ; store string A bytes long from XY to (Sutill) + +; check for space on descriptor stack then .. +; put string address and length on descriptor stack and update stack pointers + +LAB_RTST + LDX next_s ; get string stack pointer + CPX #des_sk+$09 ; compare with max+1 + BNE LAB_20F8 ; branch if space on string stack + + ; else do string too complex error + LDX #$1C ; error code $1C ("String too complex" error) +LAB_20F5 + JMP LAB_XERR ; do error #X, then warm start + +; put string address and length on descriptor stack and update stack pointers + +LAB_20F8 + LDA str_ln ; get string length + STA PLUS_0,X ; put on string stack + LDA str_pl ; get string pointer low byte + STA PLUS_1,X ; put on string stack + LDA str_ph ; get string pointer high byte + STA PLUS_2,X ; put on string stack + LDY #$00 ; clear Y + STX des_pl ; save string descriptor pointer low byte + STY des_ph ; save string descriptor pointer high byte (always $00) + DEY ; Y = $FF + STY Dtypef ; save data type flag, $FF=string + STX last_sl ; save old stack pointer (current top item) + INX ; update stack pointer + INX ; update stack pointer + INX ; update stack pointer + STX next_s ; save new top item value + RTS + +; Build descriptor +; make space in string memory for string A long +; return X=Sutill=ptr low byte, Y=Sutill=ptr high byte + +LAB_2115 + LSR Gclctd ; clear garbage collected flag (b7) + + ; make space for string A long +LAB_2117 + PHA ; save string length + EOR #$FF ; complement it + SEC ; set carry for subtract (twos comp add) + ADC Sstorl ; add bottom of string space low byte (subtract length) + LDY Sstorh ; get bottom of string space high byte + BCS LAB_2122 ; skip decrement if no underflow + + DEY ; decrement bottom of string space high byte +LAB_2122 + CPY Earryh ; compare with array mem end high byte + BCC LAB_2137 ; do out of memory error if less + + BNE LAB_212C ; if not = skip next test + + CMP Earryl ; compare with array mem end low byte + BCC LAB_2137 ; do out of memory error if less + +LAB_212C + STA Sstorl ; save bottom of string space low byte + STY Sstorh ; save bottom of string space high byte + STA Sutill ; save string utility ptr low byte + STY Sutilh ; save string utility ptr high byte + TAX ; copy low byte to X + PLA ; get string length back + RTS + +LAB_2137 + LDX #$0C ; error code $0C ("Out of memory" error) + LDA Gclctd ; get garbage collected flag + BMI LAB_20F5 ; if set then do error code X + + JSR LAB_GARB ; else go do garbage collection + LDA #$80 ; flag for garbage collected + STA Gclctd ; set garbage collected flag + PLA ; pull length + BNE LAB_2117 ; go try again (loop always, length should never be = $00) + +; garbage collection routine + +LAB_GARB + LDX Ememl ; get end of mem low byte + LDA Ememh ; get end of mem high byte + +; re-run routine from last ending + +LAB_214B + STX Sstorl ; set string storage low byte + STA Sstorh ; set string storage high byte + LDY #$00 ; clear index + STY garb_h ; clear working pointer high byte (flag no strings to move) + LDA Earryl ; get array mem end low byte + LDX Earryh ; get array mem end high byte + STA Histrl ; save as highest string low byte + STX Histrh ; save as highest string high byte + LDA #des_sk ; set descriptor stack pointer + STA ut1_pl ; save descriptor stack pointer low byte + STY ut1_ph ; save descriptor stack pointer high byte ($00) +LAB_2161 + CMP next_s ; compare with descriptor stack pointer + BEQ LAB_216A ; branch if = + + JSR LAB_21D7 ; go garbage collect descriptor stack + BEQ LAB_2161 ; loop always + + ; done stacked strings, now do string vars +LAB_216A + ASL g_step ; set step size = $06 + LDA Svarl ; get start of vars low byte + LDX Svarh ; get start of vars high byte + STA ut1_pl ; save as pointer low byte + STX ut1_ph ; save as pointer high byte +LAB_2176 + CPX Sarryh ; compare start of arrays high byte + BNE LAB_217E ; branch if no high byte match + + CMP Sarryl ; else compare start of arrays low byte + BEQ LAB_2183 ; branch if = var mem end + +LAB_217E + JSR LAB_21D1 ; go garbage collect strings + BEQ LAB_2176 ; loop always + + ; done string vars, now do string arrays +LAB_2183 + STA Nbendl ; save start of arrays low byte as working pointer + STX Nbendh ; save start of arrays high byte as working pointer + LDA #$04 ; set step size + STA g_step ; save step size +LAB_218B + LDA Nbendl ; get pointer low byte + LDX Nbendh ; get pointer high byte +LAB_218F + CPX Earryh ; compare with array mem end high byte + BNE LAB_219A ; branch if not at end + + CMP Earryl ; else compare with array mem end low byte + BEQ LAB_2216 ; tidy up and exit if at end + +LAB_219A + STA ut1_pl ; save pointer low byte + STX ut1_ph ; save pointer high byte + LDY #$02 ; set index + LDA (ut1_pl),Y ; get array size low byte + ADC Nbendl ; add start of this array low byte + STA Nbendl ; save start of next array low byte + INY ; increment index + LDA (ut1_pl),Y ; get array size high byte + ADC Nbendh ; add start of this array high byte + STA Nbendh ; save start of next array high byte + LDY #$01 ; set index + LDA (ut1_pl),Y ; get name second byte + BPL LAB_218B ; skip if not string array + +; was string array so .. + + LDY #$04 ; set index + LDA (ut1_pl),Y ; get # of dimensions + ASL ; *2 + ADC #$05 ; +5 (array header size) + JSR LAB_2208 ; go set up for first element +LAB_21C4 + CPX Nbendh ; compare with start of next array high byte + BNE LAB_21CC ; branch if <> (go do this array) + + CMP Nbendl ; else compare element pointer low byte with next array + ; low byte + BEQ LAB_218F ; if equal then go do next array + +LAB_21CC + JSR LAB_21D7 ; go defrag array strings + BEQ LAB_21C4 ; go do next array string (loop always) + +; defrag string variables +; enter with XA = variable pointer +; return with XA = next variable pointer + +LAB_21D1 + INY ; increment index (Y was $00) + LDA (ut1_pl),Y ; get var name byte 2 + BPL LAB_2206 ; if not string, step pointer to next var and return + + INY ; else increment index +LAB_21D7 + LDA (ut1_pl),Y ; get string length + BEQ LAB_2206 ; if null, step pointer to next string and return + + INY ; else increment index + LDA (ut1_pl),Y ; get string pointer low byte + TAX ; copy to X + INY ; increment index + LDA (ut1_pl),Y ; get string pointer high byte + CMP Sstorh ; compare bottom of string space high byte + BCC LAB_21EC ; branch if less + + BNE LAB_2206 ; if greater, step pointer to next string and return + + ; high bytes were = so compare low bytes + CPX Sstorl ; compare bottom of string space low byte + BCS LAB_2206 ; if >=, step pointer to next string and return + + ; string pointer is < string storage pointer (pos in mem) +LAB_21EC + CMP Histrh ; compare to highest string high byte + BCC LAB_2207 ; if <, step pointer to next string and return + + BNE LAB_21F6 ; if > update pointers, step to next and return + + ; high bytes were = so compare low bytes + CPX Histrl ; compare to highest string low byte + BCC LAB_2207 ; if <, step pointer to next string and return + + ; string is in string memory space +LAB_21F6 + STX Histrl ; save as new highest string low byte + STA Histrh ; save as new highest string high byte + LDA ut1_pl ; get start of vars(descriptors) low byte + LDX ut1_ph ; get start of vars(descriptors) high byte + STA garb_l ; save as working pointer low byte + STX garb_h ; save as working pointer high byte + DEY ; decrement index DIFFERS + DEY ; decrement index (should point to descriptor start) + STY g_indx ; save index pointer + + ; step pointer to next string +LAB_2206 + CLC ; clear carry for add +LAB_2207 + LDA g_step ; get step size +LAB_2208 + ADC ut1_pl ; add pointer low byte + STA ut1_pl ; save pointer low byte + BCC LAB_2211 ; branch if no overflow + + INC ut1_ph ; else increment high byte +LAB_2211 + LDX ut1_ph ; get pointer high byte + LDY #$00 ; clear Y + RTS + +; search complete, now either exit or set-up and move string + +LAB_2216 + DEC g_step ; decrement step size (now $03 for descriptor stack) + LDX garb_h ; get string to move high byte + BEQ LAB_2211 ; exit if nothing to move + + LDY g_indx ; get index byte back (points to descriptor) + CLC ; clear carry for add + LDA (garb_l),Y ; get string length + ADC Histrl ; add highest string low byte + STA Obendl ; save old block end low pointer + LDA Histrh ; get highest string high byte + ADC #$00 ; add any carry + STA Obendh ; save old block end high byte + LDA Sstorl ; get bottom of string space low byte + LDX Sstorh ; get bottom of string space high byte + STA Nbendl ; save new block end low byte + STX Nbendh ; save new block end high byte + JSR LAB_11D6 ; open up space in memory, don't set array end + LDY g_indx ; get index byte + INY ; point to descriptor low byte + LDA Nbendl ; get string pointer low byte + STA (garb_l),Y ; save new string pointer low byte + TAX ; copy string pointer low byte + INC Nbendh ; correct high byte (move sets high byte -1) + LDA Nbendh ; get new string pointer high byte + INY ; point to descriptor high byte + STA (garb_l),Y ; save new string pointer high byte + JMP LAB_214B ; re-run routine from last ending + ; (but don't collect this string) + +; concatenate +; add strings, string 1 is in descriptor des_pl, string 2 is in line + +LAB_224D + LDA des_ph ; get descriptor pointer high byte + PHA ; put on stack + LDA des_pl ; get descriptor pointer low byte + PHA ; put on stack + JSR LAB_GVAL ; get value from line + JSR LAB_CTST ; check if source is string, else do type mismatch + PLA ; get descriptor pointer low byte back + STA ssptr_l ; set pointer low byte + PLA ; get descriptor pointer high byte back + STA ssptr_h ; set pointer high byte + LDY #$00 ; clear index + LDA (ssptr_l),Y ; get length_1 from descriptor + CLC ; clear carry for add + ADC (des_pl),Y ; add length_2 + BCC LAB_226D ; branch if no overflow + + LDX #$1A ; else set error code $1A ("String too long" error) + JMP LAB_XERR ; do error #X, then warm start + +LAB_226D + JSR LAB_209C ; copy des_pl/h to des_2l/h and make string space A bytes + ; long + JSR LAB_228A ; copy string from descriptor (sdescr) to (Sutill) + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, ut1_pl = pointer low byte, + ; ut1_ph = pointer high byte + JSR LAB_229C ; store string A bytes long from (ut1_pl) to (Sutill) + LDA ssptr_l ;.set descriptor pointer low byte + LDY ssptr_h ;.set descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=ut1_pl=pointer low byte, + ; Y=ut1_ph=pointer high byte + JSR LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + JMP LAB_1ADB ;.continue evaluation + +; copy string from descriptor (sdescr) to (Sutill) + +LAB_228A + LDY #$00 ; clear index + LDA (sdescr),Y ; get string length + PHA ; save on stack + INY ; increment index + LDA (sdescr),Y ; get source string pointer low byte + TAX ; copy to X + INY ; increment index + LDA (sdescr),Y ; get source string pointer high byte + TAY ; copy to Y + PLA ; get length back + +; store string A bytes long from YX to (Sutill) + +LAB_2298 + STX ut1_pl ; save source string pointer low byte + STY ut1_ph ; save source string pointer high byte + +; store string A bytes long from (ut1_pl) to (Sutill) + +LAB_229C + TAX ; copy length to index (don't count with Y) + BEQ LAB_22B2 ; branch if = $0 (null string) no need to add zero length + + LDY #$00 ; zero pointer (copy forward) +LAB_22A0 + LDA (ut1_pl),Y ; get source byte + STA (Sutill),Y ; save destination byte + + INY ; increment index + DEX ; decrement counter + BNE LAB_22A0 ; loop while <> 0 + + TYA ; restore length from Y +LAB_22A9 + CLC ; clear carry for add + ADC Sutill ; add string utility ptr low byte + STA Sutill ; save string utility ptr low byte + BCC LAB_22B2 ; branch if no carry + + INC Sutilh ; else increment string utility ptr high byte +LAB_22B2 + RTS + +; evaluate string + +LAB_EVST + JSR LAB_CTST ; check if source is string, else do type mismatch + +; pop string off descriptor stack, or from top of string space +; returns with A = length, X=pointer low byte, Y=pointer high byte + +LAB_22B6 + LDA des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + +; pop (YA) descriptor off stack or from top of string space +; returns with A = length, X=ut1_pl=pointer low byte, Y=ut1_ph=pointer high byte + +LAB_22BA + STA ut1_pl ; save descriptor pointer low byte + STY ut1_ph ; save descriptor pointer high byte + JSR LAB_22EB ; clean descriptor stack, YA = pointer + PHP ; save status flags + LDY #$00 ; clear index + LDA (ut1_pl),Y ; get length from string descriptor + PHA ; put on stack + INY ; increment index + LDA (ut1_pl),Y ; get string pointer low byte from descriptor + TAX ; copy to X + INY ; increment index + LDA (ut1_pl),Y ; get string pointer high byte from descriptor + TAY ; copy to Y + PLA ; get string length back + PLP ; restore status + BNE LAB_22E6 ; branch if pointer <> last_sl,last_sh + + CPY Sstorh ; compare bottom of string space high byte + BNE LAB_22E6 ; branch if <> + + CPX Sstorl ; else compare bottom of string space low byte + BNE LAB_22E6 ; branch if <> + + PHA ; save string length + CLC ; clear carry for add + ADC Sstorl ; add bottom of string space low byte + STA Sstorl ; save bottom of string space low byte + BCC LAB_22E5 ; skip increment if no overflow + + INC Sstorh ; increment bottom of string space high byte +LAB_22E5 + PLA ; restore string length +LAB_22E6 + STX ut1_pl ; save string pointer low byte + STY ut1_ph ; save string pointer high byte + RTS + +; clean descriptor stack, YA = pointer +; checks if AY is on the descriptor stack, if so does a stack discard + +LAB_22EB + CPY last_sh ; compare pointer high byte + BNE LAB_22FB ; exit if <> + + CMP last_sl ; compare pointer low byte + BNE LAB_22FB ; exit if <> + + STA next_s ; save descriptor stack pointer + SBC #$03 ; -3 + STA last_sl ; save low byte -3 + LDY #$00 ; clear high byte +LAB_22FB + RTS + +; perform CHR$() + +LAB_CHRS + JSR LAB_EVBY ; evaluate byte expression, result in X + TXA ; copy to A + PHA ; save character + LDA #$01 ; string is single byte + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + PLA ; get character back + LDY #$00 ; clear index + STA (str_pl),Y ; save byte in string (byte IS string!) + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform LEFT$() + +LAB_LEFT + PHA ; push byte parameter + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + CMP (des_2l),Y ; compare byte parameter with string length + TYA ; clear A + BEQ LAB_2316 ; go do string copy (branch always) + +; perform RIGHT$() + +LAB_RIGHT + PHA ; push byte parameter + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + CLC ; clear carry for add-1 + SBC (des_2l),Y ; subtract string length + EOR #$FF ; invert it (A=LEN(expression$)-l) + +LAB_2316 + BCC LAB_231C ; branch if string length > byte parameter + + LDA (des_2l),Y ; else make parameter = length + TAX ; copy to byte parameter copy + TYA ; clear string start offset +LAB_231C + PHA ; save string start offset +LAB_231D + TXA ; copy byte parameter (or string length if <) +LAB_231E + PHA ; save string length + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=ut1_pl=pointer low byte, + ; Y=ut1_ph=pointer high byte + PLA ; get string length back + TAY ; copy length to Y + PLA ; get string start offset back + CLC ; clear carry for add + ADC ut1_pl ; add start offset to string start pointer low byte + STA ut1_pl ; save string start pointer low byte + BCC LAB_2335 ; branch if no overflow + + INC ut1_ph ; else increment string start pointer high byte +LAB_2335 + TYA ; copy length to A + JSR LAB_229C ; store string A bytes long from (ut1_pl) to (Sutill) + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform MID$() + +LAB_MIDS + PHA ; push byte parameter + LDA #$FF ; set default length = 255 + STA mids_l ; save default length + JSR LAB_GBYT ; scan memory + CMP #')' ; compare with ")" + BEQ LAB_2358 ; branch if = ")" (skip second byte get) + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_GTBY ; get byte parameter (use copy in mids_l) +LAB_2358 + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + DEX ; decrement start index + TXA ; copy to A + PHA ; save string start offset + CLC ; clear carry for sub-1 + LDX #$00 ; clear output string length + SBC (des_2l),Y ; subtract string length + BCS LAB_231D ; if start>string length go do null string + + EOR #$FF ; complement -length + CMP mids_l ; compare byte parameter + BCC LAB_231E ; if length>remaining string go do RIGHT$ + + LDA mids_l ; get length byte + BCS LAB_231E ; go do string copy (branch always) + +; pull string data and byte parameter from stack +; return pointer in des_2l/h, byte in A (and X), Y=0 + +LAB_236F + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + PLA ; pull return address low byte (return address) + STA Fnxjpl ; save functions jump vector low byte + PLA ; pull return address high byte (return address) + STA Fnxjph ; save functions jump vector high byte + PLA ; pull byte parameter + TAX ; copy byte parameter to X + PLA ; pull string pointer low byte + STA des_2l ; save it + PLA ; pull string pointer high byte + STA des_2h ; save it + LDY #$00 ; clear index + TXA ; copy byte parameter + BEQ LAB_23A8 ; if null do function call error then warm start + + INC Fnxjpl ; increment function jump vector low byte + ; (JSR pushes return addr-1. this is all very nice + ; but will go tits up if either call is on a page + ; boundary!) + JMP (Fnxjpl) ; in effect, RTS + +; perform LCASE$() + +LAB_LCASE + JSR LAB_EVST ; evaluate string + STA str_ln ; set string length + TAY ; copy length to Y + BEQ NoString ; branch if null string + + JSR LAB_MSSP ; make string space A bytes long A=length, + ; X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + TAY ; get string length back + +LC_loop + DEY ; decrement index + LDA (ut1_pl),Y ; get byte from string + JSR LAB_1D82 ; is character "A" to "Z" + BCC NoUcase ; branch if not upper case alpha + + ORA #$20 ; convert upper to lower case +NoUcase + STA (Sutill),Y ; save byte back to string + TYA ; test index + BNE LC_loop ; loop if not all done + + BEQ NoString ; tidy up and exit, branch always + +; perform UCASE$() + +LAB_UCASE + JSR LAB_EVST ; evaluate string + STA str_ln ; set string length + TAY ; copy length to Y + BEQ NoString ; branch if null string + + JSR LAB_MSSP ; make string space A bytes long A=length, + ; X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + TAY ; get string length back + +UC_loop + DEY ; decrement index + LDA (ut1_pl),Y ; get byte from string + JSR LAB_CASC ; is character "a" to "z" (or "A" to "Z") + BCC NoLcase ; branch if not alpha + + AND #$DF ; convert lower to upper case +NoLcase + STA (Sutill),Y ; save byte back to string + TYA ; test index + BNE UC_loop ; loop if not all done + +NoString + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform SADD() + +LAB_SADD + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GVAR ; get var address + + JSR LAB_1BFB ; scan for ")", else do syntax error then warm start + JSR LAB_CTST ; check if source is string, else do type mismatch + + LDY #$02 ; index to string pointer high byte + LDA (Cvaral),Y ; get string pointer high byte + TAX ; copy string pointer high byte to X + DEY ; index to string pointer low byte + LDA (Cvaral),Y ; get string pointer low byte + TAY ; copy string pointer low byte to Y + TXA ; copy string pointer high byte to A + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform LEN() + +LAB_LENS + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; evaluate string, get length in Y + +LAB_ESGL + JSR LAB_EVST ; evaluate string + TAY ; copy length to Y + RTS + +; perform ASC() + +LAB_ASC + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + BEQ LAB_23A8 ; if null do function call error then warm start + + LDY #$00 ; set index to first character + LDA (ut1_pl),Y ; get byte + TAY ; copy to Y + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; do function call error then warm start + +LAB_23A8 + JMP LAB_FCER ; do function call error then warm start + +; scan and get byte parameter + +LAB_SGBY + JSR LAB_IGBY ; increment and scan memory + +; get byte parameter + +LAB_GTBY + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + +; evaluate byte expression, result in X + +LAB_EVBY + JSR LAB_EVPI ; evaluate integer expression (no check) + + LDY FAC1_2 ; get FAC1 mantissa2 + BNE LAB_23A8 ; if top byte <> 0 do function call error then warm start + + LDX FAC1_3 ; get FAC1 mantissa3 + JMP LAB_GBYT ; scan memory and return + +; perform VAL() + +LAB_VAL + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + BNE LAB_23C5 ; branch if not null string + + ; string was null so set result = $00 + JMP LAB_24F1 ; clear FAC1 exponent and sign and return + +LAB_23C5 + LDX Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + STX Btmpl ; save BASIC execute pointer low byte + STY Btmph ; save BASIC execute pointer high byte + LDX ut1_pl ; get string pointer low byte + STX Bpntrl ; save as BASIC execute pointer low byte + CLC ; clear carry + ADC ut1_pl ; add string length + STA ut2_pl ; save string end low byte + LDA ut1_ph ; get string pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + ADC #$00 ; add carry to high byte + STA ut2_ph ; save string end high byte + LDY #$00 ; set index to $00 + LDA (ut2_pl),Y ; get string end +1 byte + PHA ; push it + TYA ; clear A + STA (ut2_pl),Y ; terminate string with $00 + JSR LAB_GBYT ; scan memory + JSR LAB_2887 ; get FAC1 from string + PLA ; restore string end +1 byte + LDY #$00 ; set index to zero + STA (ut2_pl),Y ; put string end byte back + +; restore BASIC execute pointer from temp (Btmpl/Btmph) + +LAB_23F3 + LDX Btmpl ; get BASIC execute pointer low byte back + LDY Btmph ; get BASIC execute pointer high byte back + STX Bpntrl ; save BASIC execute pointer low byte + STY Bpntrh ; save BASIC execute pointer high byte + RTS + +; get two parameters for POKE or WAIT + +LAB_GADB + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + +; scan for "," and get byte, else do Syntax error then warm start + +LAB_SCGB + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + LDA Itemph ; save temporary integer high byte + PHA ; on stack + LDA Itempl ; save temporary integer low byte + PHA ; on stack + JSR LAB_GTBY ; get byte parameter + PLA ; pull low byte + STA Itempl ; restore temporary integer low byte + PLA ; pull high byte + STA Itemph ; restore temporary integer high byte + RTS + +; convert float to fixed routine. accepts any value that fits in 24 bits, +ve or +; -ve and converts it into a right truncated integer in Itempl and Itemph + +; save unsigned 16 bit integer part of FAC1 in temporary integer + +LAB_F2FX + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_23A8 ; if >= do function call error then warm start + +LAB_F2FU + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDA FAC1_2 ; get FAC1 mantissa2 + LDY FAC1_3 ; get FAC1 mantissa3 + STY Itempl ; save temporary integer low byte + STA Itemph ; save temporary integer high byte + RTS + +; perform PEEK() + +LAB_PEEK + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + LDX #$00 ; clear index + LDA (Itempl,X) ; get byte via temporary integer (addr) + TAY ; copy byte to Y + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; perform POKE + +LAB_POKE + JSR LAB_GADB ; get two parameters for POKE or WAIT + TXA ; copy byte argument to A + LDX #$00 ; clear index + STA (Itempl,X) ; save byte via temporary integer (addr) + RTS + +; perform DEEK() + +LAB_DEEK + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + LDX #$00 ; clear index + LDA (Itempl,X) ; PEEK low byte + TAY ; copy to Y + INC Itempl ; increment pointer low byte + BNE Deekh ; skip high increment if no rollover + + INC Itemph ; increment pointer high byte +Deekh + LDA (Itempl,X) ; PEEK high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform DOKE + +LAB_DOKE + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + + STY Frnxtl ; save pointer low byte (float to fixed returns word in AY) + STA Frnxth ; save pointer high byte + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + + TYA ; copy value low byte (float to fixed returns word in AY) + LDX #$00 ; clear index + STA (Frnxtl,X) ; POKE low byte + INC Frnxtl ; increment pointer low byte + BNE Dokeh ; skip high increment if no rollover + + INC Frnxth ; increment pointer high byte +Dokeh + LDA Itemph ; get value high byte + STA (Frnxtl,X) ; POKE high byte + JMP LAB_GBYT ; scan memory and return + +; perform SWAP + +LAB_SWAP + JSR LAB_GVAR ; get var1 address + STA Lvarpl ; save var1 address low byte + STY Lvarph ; save var1 address high byte + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; save data type flag + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_GVAR ; get var2 address (pointer in Cvaral/h) + PLA ; pull var1 data type flag + EOR Dtypef ; compare with var2 data type + BPL SwapErr ; exit if not both the same type + + LDY #$03 ; four bytes to swap (either value or descriptor+1) +SwapLp + LDA (Lvarpl),Y ; get byte from var1 + TAX ; save var1 byte + LDA (Cvaral),Y ; get byte from var2 + STA (Lvarpl),Y ; save byte to var1 + TXA ; restore var1 byte + STA (Cvaral),Y ; save byte to var2 + DEY ; decrement index + BPL SwapLp ; loop until done + + RTS + +SwapErr + JMP LAB_1ABC ; do "Type mismatch" error then warm start + +; perform CALL + +LAB_CALL + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + LDA #>CallExit ; set return address high byte + PHA ; put on stack + LDA #8 shifts) + BCC LAB_24A8 ;.go subtract mantissas + +; add 0.5 to FAC1 + +LAB_244E + LDA #LAB_2A96 ; set 0.5 pointer high byte + +; add (AY) to FAC1 + +LAB_246C + JSR LAB_264D ; unpack memory (AY) into FAC2 + +; add FAC2 to FAC1 + +LAB_ADD + BNE LAB_2474 ; branch if FAC1 was not zero + +; copy FAC2 to FAC1 + +LAB_279B + LDA FAC2_s ; get FAC2 sign (b7) + +; save FAC1 sign and copy ABS(FAC2) to FAC1 + +LAB_279D + STA FAC1_s ; save FAC1 sign (b7) + LDX #$04 ; 4 bytes to copy +LAB_27A1 + LDA FAC1_o,X ; get byte from FAC2,X + STA FAC1_e-1,X ; save byte at FAC1,X + DEX ; decrement count + BNE LAB_27A1 ; loop if not all done + + STX FAC1_r ; clear FAC1 rounding byte + RTS + + ; FAC1 is non zero +LAB_2474 + LDX FAC1_r ; get FAC1 rounding byte + STX FAC2_r ; save as FAC2 rounding byte + LDX #FAC2_e ; set index to FAC2 exponent addr + LDA FAC2_e ; get FAC2 exponent +LAB_247C + TAY ; copy exponent + BEQ LAB_244D ; exit if zero + + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent + BEQ LAB_24A8 ; branch if = (go add mantissa) + + BCC LAB_2498 ; branch if < + + ; FAC2>FAC1 + STY FAC1_e ; save FAC1 exponent + LDY FAC2_s ; get FAC2 sign (b7) + STY FAC1_s ; save FAC1 sign (b7) + EOR #$FF ; complement A + ADC #$00 ; +1 (twos complement, carry is set) + LDY #$00 ; clear Y + STY FAC2_r ; clear FAC2 rounding byte + LDX #FAC1_e ; set index to FAC1 exponent addr + BNE LAB_249C ; branch always + +LAB_2498 + LDY #$00 ; clear Y + STY FAC1_r ; clear FAC1 rounding byte +LAB_249C + CMP #$F9 ; compare exponent diff with $F9 + BMI LAB_2467 ; branch if range $79-$F8 + + TAY ; copy exponent difference to Y + LDA FAC1_r ; get FAC1 rounding byte + LSR PLUS_1,X ; shift FAC? mantissa1 + JSR LAB_2592 ; shift FACX Y times right + + ; exponents are equal now do mantissa subtract +LAB_24A8 + BIT FAC_sc ; test sign compare (FAC1 EOR FAC2) + BPL LAB_24F8 ; if = add FAC2 mantissa to FAC1 mantissa and return + + LDY #FAC1_e ; set index to FAC1 exponent addr + CPX #FAC2_e ; compare X to FAC2 exponent addr + BEQ LAB_24B4 ; branch if = + + LDY #FAC2_e ; else set index to FAC2 exponent addr + + ; subtract smaller from bigger (take sign of bigger) +LAB_24B4 + SEC ; set carry for subtract + EOR #$FF ; ones complement A + ADC FAC2_r ; add FAC2 rounding byte + STA FAC1_r ; save FAC1 rounding byte + LDA PLUS_3,Y ; get FACY mantissa3 + SBC PLUS_3,X ; subtract FACX mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + LDA PLUS_2,Y ; get FACY mantissa2 + SBC PLUS_2,X ; subtract FACX mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA PLUS_1,Y ; get FACY mantissa1 + SBC PLUS_1,X ; subtract FACX mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + +; do ABS and normalise FAC1 + +LAB_24D0 + BCS LAB_24D5 ; branch if number is +ve + + JSR LAB_2537 ; negate FAC1 + +; normalise FAC1 + +LAB_24D5 + LDY #$00 ; clear Y + TYA ; clear A + CLC ; clear carry for add +LAB_24D9 + LDX FAC1_1 ; get FAC1 mantissa1 + BNE LAB_251B ; if not zero normalise FAC1 + + LDX FAC1_2 ; get FAC1 mantissa2 + STX FAC1_1 ; save FAC1 mantissa1 + LDX FAC1_3 ; get FAC1 mantissa3 + STX FAC1_2 ; save FAC1 mantissa2 + LDX FAC1_r ; get FAC1 rounding byte + STX FAC1_3 ; save FAC1 mantissa3 + STY FAC1_r ; clear FAC1 rounding byte + ADC #$08 ; add x to exponent offset + CMP #$18 ; compare with $18 (max offset, all bits would be =0) + BNE LAB_24D9 ; loop if not max + +; clear FAC1 exponent and sign + +LAB_24F1 + LDA #$00 ; clear A +LAB_24F3 + STA FAC1_e ; set FAC1 exponent + +; save FAC1 sign + +LAB_24F5 + STA FAC1_s ; save FAC1 sign (b7) + RTS + +; add FAC2 mantissa to FAC1 mantissa + +LAB_24F8 + ADC FAC2_r ; add FAC2 rounding byte + STA FAC1_r ; save FAC1 rounding byte + LDA FAC1_3 ; get FAC1 mantissa3 + ADC FAC2_3 ; add FAC2 mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_2 ; get FAC1 mantissa2 + ADC FAC2_2 ; add FAC2 mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_1 ; get FAC1 mantissa1 + ADC FAC2_1 ; add FAC2 mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + BCS LAB_252A ; if carry then normalise FAC1 for C=1 + + RTS ; else just exit + +LAB_2511 + ADC #$01 ; add 1 to exponent offset + ASL FAC1_r ; shift FAC1 rounding byte + ROL FAC1_3 ; shift FAC1 mantissa3 + ROL FAC1_2 ; shift FAC1 mantissa2 + ROL FAC1_1 ; shift FAC1 mantissa1 + +; normalise FAC1 + +LAB_251B + BPL LAB_2511 ; loop if not normalised + + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent + BCS LAB_24F1 ; branch if underflow (set result = $0) + + EOR #$FF ; complement exponent + ADC #$01 ; +1 (twos complement) + STA FAC1_e ; save FAC1 exponent + +; test and normalise FAC1 for C=0/1 + +LAB_2528 + BCC LAB_2536 ; exit if no overflow + +; normalise FAC1 for C=1 + +LAB_252A + INC FAC1_e ; increment FAC1 exponent + BEQ LAB_2564 ; if zero do overflow error and warm start + + ROR FAC1_1 ; shift FAC1 mantissa1 + ROR FAC1_2 ; shift FAC1 mantissa2 + ROR FAC1_3 ; shift FAC1 mantissa3 + ROR FAC1_r ; shift FAC1 rounding byte +LAB_2536 + RTS + +; negate FAC1 + +LAB_2537 + LDA FAC1_s ; get FAC1 sign (b7) + EOR #$FF ; complement it + STA FAC1_s ; save FAC1 sign (b7) + +; twos complement FAC1 mantissa + +LAB_253D + LDA FAC1_1 ; get FAC1 mantissa1 + EOR #$FF ; complement it + STA FAC1_1 ; save FAC1 mantissa1 + LDA FAC1_2 ; get FAC1 mantissa2 + EOR #$FF ; complement it + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_3 ; get FAC1 mantissa3 + EOR #$FF ; complement it + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_r ; get FAC1 rounding byte + EOR #$FF ; complement it + STA FAC1_r ; save FAC1 rounding byte + INC FAC1_r ; increment FAC1 rounding byte + BNE LAB_2563 ; exit if no overflow + +; increment FAC1 mantissa + +LAB_2559 + INC FAC1_3 ; increment FAC1 mantissa3 + BNE LAB_2563 ; finished if no rollover + + INC FAC1_2 ; increment FAC1 mantissa2 + BNE LAB_2563 ; finished if no rollover + + INC FAC1_1 ; increment FAC1 mantissa1 +LAB_2563 + RTS + +; do overflow error (overflow exit) + +LAB_2564 + LDX #$0A ; error code $0A ("Overflow" error) + JMP LAB_XERR ; do error #X, then warm start + +; shift FCAtemp << A+8 times + +LAB_2569 + LDX #FACt_1-1 ; set offset to FACtemp +LAB_256B + LDY PLUS_3,X ; get FACX mantissa3 + STY FAC1_r ; save as FAC1 rounding byte + LDY PLUS_2,X ; get FACX mantissa2 + STY PLUS_3,X ; save FACX mantissa3 + LDY PLUS_1,X ; get FACX mantissa1 + STY PLUS_2,X ; save FACX mantissa2 + LDY FAC1_o ; get FAC1 overflow byte + STY PLUS_1,X ; save FACX mantissa1 + +; shift FACX -A times right (> 8 shifts) + +LAB_257B + ADC #$08 ; add 8 to shift count + BMI LAB_256B ; go do 8 shift if still -ve + + BEQ LAB_256B ; go do 8 shift if zero + + SBC #$08 ; else subtract 8 again + TAY ; save count to Y + LDA FAC1_r ; get FAC1 rounding byte + BCS LAB_259A ;. + +LAB_2588 + ASL PLUS_1,X ; shift FACX mantissa1 + BCC LAB_258E ; branch if +ve + + INC PLUS_1,X ; this sets b7 eventually +LAB_258E + ROR PLUS_1,X ; shift FACX mantissa1 (correct for ASL) + ROR PLUS_1,X ; shift FACX mantissa1 (put carry in b7) + +; shift FACX Y times right + +LAB_2592 + ROR PLUS_2,X ; shift FACX mantissa2 + ROR PLUS_3,X ; shift FACX mantissa3 + ROR ; shift FACX rounding byte + INY ; increment exponent diff + BNE LAB_2588 ; branch if range adjust not complete + +LAB_259A + CLC ; just clear it + RTS + +; perform LOG() + +LAB_LOG + JSR LAB_27CA ; test sign and zero + BEQ LAB_25C4 ; if zero do function call error then warm start + + BPL LAB_25C7 ; skip error if +ve + +LAB_25C4 + JMP LAB_FCER ; do function call error then warm start (-ve) + +LAB_25C7 + LDA FAC1_e ; get FAC1 exponent + SBC #$7F ; normalise it + PHA ; save it + LDA #$80 ; set exponent to zero + STA FAC1_e ; save FAC1 exponent + LDA #LAB_25AD ; set 1/root2 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 (1/root2) + LDA #LAB_25B1 ; set root2 pointer high byte + JSR LAB_26CA ; convert AY and do (AY)/FAC1 (root2/(x+(1/root2))) + LDA #LAB_259C ; set 1 pointer high byte + JSR LAB_2455 ; subtract (AY) from FAC1 ((root2/(x+(1/root2)))-1) + LDA #LAB_25A0 ; set pointer high byte to counter + JSR LAB_2B6E ; ^2 then series evaluation + LDA #LAB_25B5 ; set -0.5 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + PLA ; restore FAC1 exponent + JSR LAB_2912 ; evaluate new ASCII digit + LDA #LAB_25B9 ; set LOG(2) pointer high byte + +; do convert AY, FCA1*(AY) + +LAB_25FB + JSR LAB_264D ; unpack memory (AY) into FAC2 +LAB_MULTIPLY + BEQ LAB_264C ; exit if zero + + JSR LAB_2673 ; test and adjust accumulators + LDA #$00 ; clear A + STA FACt_1 ; clear temp mantissa1 + STA FACt_2 ; clear temp mantissa2 + STA FACt_3 ; clear temp mantissa3 + LDA FAC1_r ; get FAC1 rounding byte + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_3 ; get FAC1 mantissa3 + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_2 ; get FAC1 mantissa2 + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_1 ; get FAC1 mantissa1 + JSR LAB_2627 ; go do shift/add FAC2 + JMP LAB_273C ; copy temp to FAC1, normalise and return + +LAB_2622 + BNE LAB_2627 ; branch if byte <> zero + + JMP LAB_2569 ; shift FCAtemp << A+8 times + + ; else do shift and add +LAB_2627 + LSR ; shift byte + ORA #$80 ; set top bit (mark for 8 times) +LAB_262A + TAY ; copy result + BCC LAB_2640 ; skip next if bit was zero + + CLC ; clear carry for add + LDA FACt_3 ; get temp mantissa3 + ADC FAC2_3 ; add FAC2 mantissa3 + STA FACt_3 ; save temp mantissa3 + LDA FACt_2 ; get temp mantissa2 + ADC FAC2_2 ; add FAC2 mantissa2 + STA FACt_2 ; save temp mantissa2 + LDA FACt_1 ; get temp mantissa1 + ADC FAC2_1 ; add FAC2 mantissa1 + STA FACt_1 ; save temp mantissa1 +LAB_2640 + ROR FACt_1 ; shift temp mantissa1 + ROR FACt_2 ; shift temp mantissa2 + ROR FACt_3 ; shift temp mantissa3 + ROR FAC1_r ; shift temp rounding byte + TYA ; get byte back + LSR ; shift byte + BNE LAB_262A ; loop if all bits not done + +LAB_264C + RTS + +; unpack memory (AY) into FAC2 + +LAB_264D + STA ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; 4 bytes to get (0-3) + LDA (ut1_pl),Y ; get mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + DEY ; decrement index + LDA (ut1_pl),Y ; get mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + DEY ; decrement index + LDA (ut1_pl),Y ; get mantissa1+sign + STA FAC2_s ; save FAC2 sign (b7) + EOR FAC1_s ; EOR with FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + LDA FAC2_s ; recover FAC2 sign (b7) + ORA #$80 ; set 1xxx xxx (set normal bit) + STA FAC2_1 ; save FAC2 mantissa1 + DEY ; decrement index + LDA (ut1_pl),Y ; get exponent byte + STA FAC2_e ; save FAC2 exponent + LDA FAC1_e ; get FAC1 exponent + RTS + +; test and adjust accumulators + +LAB_2673 + LDA FAC2_e ; get FAC2 exponent +LAB_2675 + BEQ LAB_2696 ; branch if FAC2 = $00 (handle underflow) + + CLC ; clear carry for add + ADC FAC1_e ; add FAC1 exponent + BCC LAB_2680 ; branch if sum of exponents <$0100 + + BMI LAB_269B ; do overflow error + + CLC ; clear carry for the add + .byte $2C ; makes next line BIT $1410 +LAB_2680 + BPL LAB_2696 ; if +ve go handle underflow + + ADC #$80 ; adjust exponent + STA FAC1_e ; save FAC1 exponent + BNE LAB_268B ; branch if not zero + + JMP LAB_24F5 ; save FAC1 sign and return + +LAB_268B + LDA FAC_sc ; get sign compare (FAC1 EOR FAC2) + STA FAC1_s ; save FAC1 sign (b7) +LAB_268F + RTS + +; handle overflow and underflow + +LAB_2690 + LDA FAC1_s ; get FAC1 sign (b7) + BPL LAB_269B ; do overflow error + + ; handle underflow +LAB_2696 + PLA ; pop return address low byte + PLA ; pop return address high byte + JMP LAB_24F1 ; clear FAC1 exponent and sign and return + +; multiply by 10 + +LAB_269E + JSR LAB_27AB ; round and copy FAC1 to FAC2 + TAX ; copy exponent (set the flags) + BEQ LAB_268F ; exit if zero + + CLC ; clear carry for add + ADC #$02 ; add two to exponent (*4) + BCS LAB_269B ; do overflow error if > $FF + + LDX #$00 ; clear byte + STX FAC_sc ; clear sign compare (FAC1 EOR FAC2) + JSR LAB_247C ; add FAC2 to FAC1 (*5) + INC FAC1_e ; increment FAC1 exponent (*10) + BNE LAB_268F ; if non zero just do RTS + +LAB_269B + JMP LAB_2564 ; do overflow error and warm start + +; divide by 10 + +LAB_26B9 + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #LAB_26B5 ; set pointer to 10d high addr + LDX #$00 ; clear sign + +; divide by (AY) (X=sign) + +LAB_26C2 + STX FAC_sc ; save sign compare (FAC1 EOR FAC2) + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + JMP LAB_DIVIDE ; do FAC2/FAC1 + + ; Perform divide-by +; convert AY and do (AY)/FAC1 + +LAB_26CA + JSR LAB_264D ; unpack memory (AY) into FAC2 + + ; Perform divide-into +LAB_DIVIDE + BEQ LAB_2737 ; if zero go do /0 error + + JSR LAB_27BA ; round FAC1 + LDA #$00 ; clear A + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent (2s complement) + STA FAC1_e ; save FAC1 exponent + JSR LAB_2673 ; test and adjust accumulators + INC FAC1_e ; increment FAC1 exponent + BEQ LAB_269B ; if zero do overflow error + + LDX #$FF ; set index for pre increment + LDA #$01 ; set bit to flag byte save +LAB_26E4 + LDY FAC2_1 ; get FAC2 mantissa1 + CPY FAC1_1 ; compare FAC1 mantissa1 + BNE LAB_26F4 ; branch if <> + + LDY FAC2_2 ; get FAC2 mantissa2 + CPY FAC1_2 ; compare FAC1 mantissa2 + BNE LAB_26F4 ; branch if <> + + LDY FAC2_3 ; get FAC2 mantissa3 + CPY FAC1_3 ; compare FAC1 mantissa3 +LAB_26F4 + PHP ; save FAC2-FAC1 compare status + ROL ; shift the result byte + BCC LAB_2702 ; if no carry skip the byte save + + LDY #$01 ; set bit to flag byte save + INX ; else increment the index to FACt + CPX #$02 ; compare with the index to FACt_3 + BMI LAB_2701 ; if not last byte just go save it + + BNE LAB_272B ; if all done go save FAC1 rounding byte, normalise and + ; return + + LDY #$40 ; set bit to flag byte save for the rounding byte +LAB_2701 + STA FACt_1,X ; write result byte to FACt_1 + index + TYA ; copy the next save byte flag +LAB_2702 + PLP ; restore FAC2-FAC1 compare status + BCC LAB_2704 ; if FAC2 < FAC1 then skip the subtract + + TAY ; save FAC2-FAC1 compare status + LDA FAC2_3 ; get FAC2 mantissa3 + SBC FAC1_3 ; subtract FAC1 mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + LDA FAC2_2 ; get FAC2 mantissa2 + SBC FAC1_2 ; subtract FAC1 mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + LDA FAC2_1 ; get FAC2 mantissa1 + SBC FAC1_1 ; subtract FAC1 mantissa1 + STA FAC2_1 ; save FAC2 mantissa1 + TYA ; restore FAC2-FAC1 compare status + + ; FAC2 = FAC2*2 +LAB_2704 + ASL FAC2_3 ; shift FAC2 mantissa3 + ROL FAC2_2 ; shift FAC2 mantissa2 + ROL FAC2_1 ; shift FAC2 mantissa1 + BCS LAB_26F4 ; loop with no compare + + BMI LAB_26E4 ; loop with compare + + BPL LAB_26F4 ; loop always with no compare + +; do A<<6, save as FAC1 rounding byte, normalise and return + +LAB_272B + LSR ; shift b1 - b0 .. + ROR ; .. + ROR ; .. to b7 - b6 + STA FAC1_r ; save FAC1 rounding byte + PLP ; dump FAC2-FAC1 compare status + JMP LAB_273C ; copy temp to FAC1, normalise and return + +; do "Divide by zero" error + +LAB_2737 + LDX #$14 ; error code $14 ("Divide by zero" error) + JMP LAB_XERR ; do error #X, then warm start + +; copy temp to FAC1 and normalise + +LAB_273C + LDA FACt_1 ; get temp mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + LDA FACt_2 ; get temp mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA FACt_3 ; get temp mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + JMP LAB_24D5 ; normalise FAC1 and return + +; unpack memory (AY) into FAC1 + +LAB_UFAC + STA ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; 4 bytes to do + LDA (ut1_pl),Y ; get last byte + STA FAC1_3 ; save FAC1 mantissa3 + DEY ; decrement index + LDA (ut1_pl),Y ; get last-1 byte + STA FAC1_2 ; save FAC1 mantissa2 + DEY ; decrement index + LDA (ut1_pl),Y ; get second byte + STA FAC1_s ; save FAC1 sign (b7) + ORA #$80 ; set 1xxx xxxx (add normal bit) + STA FAC1_1 ; save FAC1 mantissa1 + DEY ; decrement index + LDA (ut1_pl),Y ; get first byte (exponent) + STA FAC1_e ; save FAC1 exponent + STY FAC1_r ; clear FAC1 rounding byte + RTS + +; pack FAC1 into Adatal + +LAB_276E + LDX #Adatal ; set pointer high byte + BEQ LAB_2778 ; pack FAC1 into (XY) and return + +; pack FAC1 into (Lvarpl) + +LAB_PFAC + LDX Lvarpl ; get destination pointer low byte + LDY Lvarph ; get destination pointer high byte + +; pack FAC1 into (XY) + +LAB_2778 + JSR LAB_27BA ; round FAC1 + STX ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; set index + LDA FAC1_3 ; get FAC1 mantissa3 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_2 ; get FAC1 mantissa2 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_s ; get FAC1 sign (b7) + ORA #$7F ; set bits x111 1111 + AND FAC1_1 ; AND in FAC1 mantissa1 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_e ; get FAC1 exponent + STA (ut1_pl),Y ; store in destination + STY FAC1_r ; clear FAC1 rounding byte + RTS + +; round and copy FAC1 to FAC2 + +LAB_27AB + JSR LAB_27BA ; round FAC1 + +; copy FAC1 to FAC2 + +LAB_27AE + LDX #$05 ; 5 bytes to copy +LAB_27B0 + LDA FAC1_e-1,X ; get byte from FAC1,X + STA FAC1_o,X ; save byte at FAC2,X + DEX ; decrement count + BNE LAB_27B0 ; loop if not all done + + STX FAC1_r ; clear FAC1 rounding byte +LAB_27B9 + RTS + +; round FAC1 + +LAB_27BA + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_27B9 ; exit if zero + + ASL FAC1_r ; shift FAC1 rounding byte + BCC LAB_27B9 ; exit if no overflow + +; round FAC1 (no check) + +LAB_27C2 + JSR LAB_2559 ; increment FAC1 mantissa + BNE LAB_27B9 ; branch if no overflow + + JMP LAB_252A ; normalise FAC1 for C=1 and return + +; get FAC1 sign +; return A=FF,C=1/-ve A=01,C=0/+ve + +LAB_27CA + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_27D7 ; exit if zero (already correct SGN(0)=0) + +; return A=FF,C=1/-ve A=01,C=0/+ve +; no = 0 check + +LAB_27CE + LDA FAC1_s ; else get FAC1 sign (b7) + +; return A=FF,C=1/-ve A=01,C=0/+ve +; no = 0 check, sign in A + +LAB_27D0 + ROL ; move sign bit to carry + LDA #$FF ; set byte for -ve result + BCS LAB_27D7 ; return if sign was set (-ve) + + LDA #$01 ; else set byte for +ve result +LAB_27D7 + RTS + +; perform SGN() + +LAB_SGN + JSR LAB_27CA ; get FAC1 sign + ; return A=$FF/-ve A=$01/+ve +; save A as integer byte + +LAB_27DB + STA FAC1_1 ; save FAC1 mantissa1 + LDA #$00 ; clear A + STA FAC1_2 ; clear FAC1 mantissa2 + LDX #$88 ; set exponent + +; set exp=X, clearFAC1 mantissa3 and normalise + +LAB_27E3 + LDA FAC1_1 ; get FAC1 mantissa1 + EOR #$FF ; complement it + ROL ; sign bit into carry + +; set exp=X, clearFAC1 mantissa3 and normalise + +LAB_STFA + LDA #$00 ; clear A + STA FAC1_3 ; clear FAC1 mantissa3 + STX FAC1_e ; set FAC1 exponent + STA FAC1_r ; clear FAC1 rounding byte + STA FAC1_s ; clear FAC1 sign (b7) + JMP LAB_24D0 ; do ABS and normalise FAC1 + +; perform ABS() + +LAB_ABS + LSR FAC1_s ; clear FAC1 sign (put zero in b7) + RTS + +; compare FAC1 with (AY) +; returns A=$00 if FAC1 = (AY) +; returns A=$01 if FAC1 > (AY) +; returns A=$FF if FAC1 < (AY) + +LAB_27F8 + STA ut2_pl ; save pointer low byte +LAB_27FA + STY ut2_ph ; save pointer high byte + LDY #$00 ; clear index + LDA (ut2_pl),Y ; get exponent + INY ; increment index + TAX ; copy (AY) exponent to X + BEQ LAB_27CA ; branch if (AY) exponent=0 and get FAC1 sign + ; A=FF,C=1/-ve A=01,C=0/+ve + + LDA (ut2_pl),Y ; get (AY) mantissa1 (with sign) + EOR FAC1_s ; EOR FAC1 sign (b7) + BMI LAB_27CE ; if signs <> do return A=FF,C=1/-ve + ; A=01,C=0/+ve and return + + CPX FAC1_e ; compare (AY) exponent with FAC1 exponent + BNE LAB_2828 ; branch if different + + LDA (ut2_pl),Y ; get (AY) mantissa1 (with sign) + ORA #$80 ; normalise top bit + CMP FAC1_1 ; compare with FAC1 mantissa1 + BNE LAB_2828 ; branch if different + + INY ; increment index + LDA (ut2_pl),Y ; get mantissa2 + CMP FAC1_2 ; compare with FAC1 mantissa2 + BNE LAB_2828 ; branch if different + + INY ; increment index + LDA #$7F ; set for 1/2 value rounding byte + CMP FAC1_r ; compare with FAC1 rounding byte (set carry) + LDA (ut2_pl),Y ; get mantissa3 + SBC FAC1_3 ; subtract FAC1 mantissa3 + BEQ LAB_2850 ; exit if mantissa3 equal + +; gets here if number <> FAC1 + +LAB_2828 + LDA FAC1_s ; get FAC1 sign (b7) + BCC LAB_282E ; branch if FAC1 > (AY) + + EOR #$FF ; else toggle FAC1 sign +LAB_282E + JMP LAB_27D0 ; return A=FF,C=1/-ve A=01,C=0/+ve + +; convert FAC1 floating-to-fixed + +LAB_2831 + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_287F ; if zero go clear FAC1 and return + + SEC ; set carry for subtract + SBC #$98 ; subtract maximum integer range exponent + BIT FAC1_s ; test FAC1 sign (b7) + BPL LAB_2845 ; branch if FAC1 +ve + + ; FAC1 was -ve + TAX ; copy subtracted exponent + LDA #$FF ; overflow for -ve number + STA FAC1_o ; set FAC1 overflow byte + JSR LAB_253D ; twos complement FAC1 mantissa + TXA ; restore subtracted exponent +LAB_2845 + LDX #FAC1_e ; set index to FAC1 + CMP #$F9 ; compare exponent result + BPL LAB_2851 ; if < 8 shifts shift FAC1 A times right and return + + JSR LAB_257B ; shift FAC1 A times right (> 8 shifts) + STY FAC1_o ; clear FAC1 overflow byte +LAB_2850 + RTS + +; shift FAC1 A times right + +LAB_2851 + TAY ; copy shift count + LDA FAC1_s ; get FAC1 sign (b7) + AND #$80 ; mask sign bit only (x000 0000) + LSR FAC1_1 ; shift FAC1 mantissa1 + ORA FAC1_1 ; OR sign in b7 FAC1 mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + JSR LAB_2592 ; shift FAC1 Y times right + STY FAC1_o ; clear FAC1 overflow byte + RTS + +; perform INT() + +LAB_INT + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with max int + BCS LAB_2886 ; exit if >= (already int, too big for fractional part!) + + JSR LAB_2831 ; convert FAC1 floating-to-fixed + STY FAC1_r ; save FAC1 rounding byte + LDA FAC1_s ; get FAC1 sign (b7) + STY FAC1_s ; save FAC1 sign (b7) + EOR #$80 ; toggle FAC1 sign + ROL ; shift into carry + LDA #$98 ; set new exponent + STA FAC1_e ; save FAC1 exponent + LDA FAC1_3 ; get FAC1 mantissa3 + STA Temp3 ; save for EXP() function + JMP LAB_24D0 ; do ABS and normalise FAC1 + +; clear FAC1 and return + +LAB_287F + STA FAC1_1 ; clear FAC1 mantissa1 + STA FAC1_2 ; clear FAC1 mantissa2 + STA FAC1_3 ; clear FAC1 mantissa3 + TAY ; clear Y +LAB_2886 + RTS + +; get FAC1 from string +; this routine now handles hex and binary values from strings +; starting with "$" and "%" respectively + +LAB_2887 + LDY #$00 ; clear Y + STY Dtypef ; clear data type flag, $FF=string, $00=numeric + LDX #$09 ; set index +LAB_288B + STY numexp,X ; clear byte + DEX ; decrement index + BPL LAB_288B ; loop until numexp to negnum (and FAC1) = $00 + + BCC LAB_28FE ; branch if 1st character numeric + +; get FAC1 from string .. first character wasn't numeric + + CMP #'-' ; else compare with "-" + BNE LAB_289A ; branch if not "-" + + STX negnum ; set flag for -ve number (X = $FF) + BEQ LAB_289C ; branch always (go scan and check for hex/bin) + +; get FAC1 from string .. first character wasn't numeric or - + +LAB_289A + CMP #'+' ; else compare with "+" + BNE LAB_289D ; branch if not "+" (go check for hex/bin) + +; was "+" or "-" to start, so get next character + +LAB_289C + JSR LAB_IGBY ; increment and scan memory + BCC LAB_28FE ; branch if numeric character + +; code here for hex and binary numbers + +LAB_289D + CMP #'$' ; else compare with "$" + BNE LAB_NHEX ; branch if not "$" + + JMP LAB_CHEX ; branch if "$" + +LAB_NHEX + CMP #'%' ; else compare with "%" + BNE LAB_28A3 ; branch if not "%" (continue original code) + + JMP LAB_CBIN ; branch if "%" + +LAB_289E + JSR LAB_IGBY ; increment and scan memory (ignore + or get next number) +LAB_28A1 + BCC LAB_28FE ; branch if numeric character + +; get FAC1 from string .. character wasn't numeric, -, +, hex or binary + +LAB_28A3 + CMP #'.' ; else compare with "." + BEQ LAB_28D5 ; branch if "." + +; get FAC1 from string .. character wasn't numeric, -, + or . + + CMP #'E' ; else compare with "E" + BNE LAB_28DB ; branch if not "E" + + ; was "E" so evaluate exponential part + JSR LAB_IGBY ; increment and scan memory + BCC LAB_28C7 ; branch if numeric character + + CMP #TK_MINUS ; else compare with token for - + BEQ LAB_28C2 ; branch if token for - + + CMP #'-' ; else compare with "-" + BEQ LAB_28C2 ; branch if "-" + + CMP #TK_PLUS ; else compare with token for + + BEQ LAB_28C4 ; branch if token for + + + CMP #'+' ; else compare with "+" + BEQ LAB_28C4 ; branch if "+" + + BNE LAB_28C9 ; branch always + +LAB_28C2 + ROR expneg ; set exponent -ve flag (C, which=1, into b7) +LAB_28C4 + JSR LAB_IGBY ; increment and scan memory +LAB_28C7 + BCC LAB_2925 ; branch if numeric character + +LAB_28C9 + BIT expneg ; test exponent -ve flag + BPL LAB_28DB ; if +ve go evaluate exponent + + ; else do exponent = -exponent + LDA #$00 ; clear result + SEC ; set carry for subtract + SBC expcnt ; subtract exponent byte + JMP LAB_28DD ; go evaluate exponent + +LAB_28D5 + ROR numdpf ; set decimal point flag + BIT numdpf ; test decimal point flag + BVC LAB_289E ; branch if only one decimal point so far + + ; evaluate exponent +LAB_28DB + LDA expcnt ; get exponent count byte +LAB_28DD + SEC ; set carry for subtract + SBC numexp ; subtract numerator exponent + STA expcnt ; save exponent count byte + BEQ LAB_28F6 ; branch if no adjustment + + BPL LAB_28EF ; else if +ve go do FAC1*10^expcnt + + ; else go do FAC1/10^(0-expcnt) +LAB_28E6 + JSR LAB_26B9 ; divide by 10 + INC expcnt ; increment exponent count byte + BNE LAB_28E6 ; loop until all done + + BEQ LAB_28F6 ; branch always + +LAB_28EF + JSR LAB_269E ; multiply by 10 + DEC expcnt ; decrement exponent count byte + BNE LAB_28EF ; loop until all done + +LAB_28F6 + LDA negnum ; get -ve flag + BMI LAB_28FB ; if -ve do - FAC1 and return + + RTS + +; do - FAC1 and return + +LAB_28FB + JMP LAB_GTHAN ; do - FAC1 and return + +; do unsigned FAC1*10+number + +LAB_28FE + PHA ; save character + BIT numdpf ; test decimal point flag + BPL LAB_2905 ; skip exponent increment if not set + + INC numexp ; else increment number exponent +LAB_2905 + JSR LAB_269E ; multiply FAC1 by 10 + PLA ; restore character + AND #$0F ; convert to binary + JSR LAB_2912 ; evaluate new ASCII digit + JMP LAB_289E ; go do next character + +; evaluate new ASCII digit + +LAB_2912 + PHA ; save digit + JSR LAB_27AB ; round and copy FAC1 to FAC2 + PLA ; restore digit + JSR LAB_27DB ; save A as integer byte + LDA FAC2_s ; get FAC2 sign (b7) + EOR FAC1_s ; toggle with FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + LDX FAC1_e ; get FAC1 exponent + JMP LAB_ADD ; add FAC2 to FAC1 and return + +; evaluate next character of exponential part of number + +LAB_2925 + LDA expcnt ; get exponent count byte + CMP #$0A ; compare with 10 decimal + BCC LAB_2934 ; branch if less + + LDA #$64 ; make all -ve exponents = -100 decimal (causes underflow) + BIT expneg ; test exponent -ve flag + BMI LAB_2942 ; branch if -ve + + JMP LAB_2564 ; else do overflow error + +LAB_2934 + ASL ; * 2 + ASL ; * 4 + ADC expcnt ; * 5 + ASL ; * 10 + LDY #$00 ; set index + ADC (Bpntrl),Y ; add character (will be $30 too much!) + SBC #'0'-1 ; convert character to binary +LAB_2942 + STA expcnt ; save exponent count byte + JMP LAB_28C4 ; go get next character + +; print " in line [LINE #]" + +LAB_2953 + LDA #LAB_LMSG ; point to " in line " message high byte + JSR LAB_18C3 ; print null terminated string from memory + + ; print Basic line # + LDA Clineh ; get current line high byte + LDX Clinel ; get current line low byte + +; print XA as unsigned integer + +LAB_295E + STA FAC1_1 ; save low byte as FAC1 mantissa1 + STX FAC1_2 ; save high byte as FAC1 mantissa2 + LDX #$90 ; set exponent to 16d bits + SEC ; set integer is +ve flag + JSR LAB_STFA ; set exp=X, clearFAC1 mantissa3 and normalise + LDY #$00 ; clear index + TYA ; clear A + JSR LAB_297B ; convert FAC1 to string, skip sign character save + JMP LAB_18C3 ; print null terminated string from memory and return + +; convert FAC1 to ASCII string result in (AY) +; not any more, moved scratchpad to page 0 + +LAB_296E + LDY #$01 ; set index = 1 + LDA #$20 ; character = " " (assume +ve) + BIT FAC1_s ; test FAC1 sign (b7) + BPL LAB_2978 ; branch if +ve + + LDA #$2D ; else character = "-" +LAB_2978 + STA Decss,Y ; save leading character (" " or "-") +LAB_297B + STA FAC1_s ; clear FAC1 sign (b7) + STY Sendl ; save index + INY ; increment index + LDX FAC1_e ; get FAC1 exponent + BNE LAB_2989 ; branch if FAC1<>0 + + ; exponent was $00 so FAC1 is 0 + LDA #'0' ; set character = "0" + JMP LAB_2A89 ; save last character, [EOT] and exit + + ; FAC1 is some non zero value +LAB_2989 + LDA #$00 ; clear (number exponent count) + CPX #$81 ; compare FAC1 exponent with $81 (>1.00000) + + BCS LAB_299A ; branch if FAC1=>1 + + ; FAC1<1 + LDA #LAB_294F ; set pointer high byte to 1,000,000 + JSR LAB_25FB ; do convert AY, FCA1*(AY) + LDA #$FA ; set number exponent count (-6) +LAB_299A + STA numexp ; save number exponent count +LAB_299C + LDA #LAB_294B ; set pointer high byte to 999999.4375 + JSR LAB_27F8 ; compare FAC1 with (AY) + BEQ LAB_29C3 ; exit if FAC1 = (AY) + + BPL LAB_29B9 ; go do /10 if FAC1 > (AY) + + ; FAC1 < (AY) +LAB_29A7 + LDA #LAB_2947 ; set pointer high byte to 99999.9375 + JSR LAB_27F8 ; compare FAC1 with (AY) + BEQ LAB_29B2 ; branch if FAC1 = (AY) (allow decimal places) + + BPL LAB_29C0 ; branch if FAC1 > (AY) (no decimal places) + + ; FAC1 <= (AY) +LAB_29B2 + JSR LAB_269E ; multiply by 10 + DEC numexp ; decrement number exponent count + BNE LAB_29A7 ; go test again (branch always) + +LAB_29B9 + JSR LAB_26B9 ; divide by 10 + INC numexp ; increment number exponent count + BNE LAB_299C ; go test again (branch always) + +; now we have just the digits to do + +LAB_29C0 + JSR LAB_244E ; add 0.5 to FAC1 (round FAC1) +LAB_29C3 + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDX #$01 ; set default digits before dp = 1 + LDA numexp ; get number exponent count + CLC ; clear carry for add + ADC #$07 ; up to 6 digits before point + BMI LAB_29D8 ; if -ve then 1 digit before dp + + CMP #$08 ; A>=8 if n>=1E6 + BCS LAB_29D9 ; branch if >= $08 + + ; carry is clear + ADC #$FF ; take 1 from digit count + TAX ; copy to A + LDA #$02 ;.set exponent adjust +LAB_29D8 + SEC ; set carry for subtract +LAB_29D9 + SBC #$02 ; -2 + STA expcnt ;.save exponent adjust + STX numexp ; save digits before dp count + TXA ; copy to A + BEQ LAB_29E4 ; branch if no digits before dp + + BPL LAB_29F7 ; branch if digits before dp + +LAB_29E4 + LDY Sendl ; get output string index + LDA #$2E ; character "." + INY ; increment index + STA Decss,Y ; save to output string + TXA ;. + BEQ LAB_29F5 ;. + + LDA #'0' ; character "0" + INY ; increment index + STA Decss,Y ; save to output string +LAB_29F5 + STY Sendl ; save output string index +LAB_29F7 + LDY #$00 ; clear index (point to 100,000) + LDX #$80 ; +LAB_29FB + LDA FAC1_3 ; get FAC1 mantissa3 + CLC ; clear carry for add + ADC LAB_2A9C,Y ; add -ve LSB + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_2 ; get FAC1 mantissa2 + ADC LAB_2A9B,Y ; add -ve NMSB + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_1 ; get FAC1 mantissa1 + ADC LAB_2A9A,Y ; add -ve MSB + STA FAC1_1 ; save FAC1 mantissa1 + INX ; + BCS LAB_2A18 ; + + BPL LAB_29FB ; not -ve so try again + + BMI LAB_2A1A ; + +LAB_2A18 + BMI LAB_29FB ; + +LAB_2A1A + TXA ; + BCC LAB_2A21 ; + + EOR #$FF ; + ADC #$0A ; +LAB_2A21 + ADC #'0'-1 ; add "0"-1 to result + INY ; increment index .. + INY ; .. to next less .. + INY ; .. power of ten + STY Cvaral ; save as current var address low byte + LDY Sendl ; get output string index + INY ; increment output string index + TAX ; copy character to X + AND #$7F ; mask out top bit + STA Decss,Y ; save to output string + DEC numexp ; decrement # of characters before the dp + BNE LAB_2A3B ; branch if still characters to do + + ; else output the point + LDA #$2E ; character "." + INY ; increment output string index + STA Decss,Y ; save to output string +LAB_2A3B + STY Sendl ; save output string index + LDY Cvaral ; get current var address low byte + TXA ; get character back + EOR #$FF ; + AND #$80 ; + TAX ; + CPY #$12 ; compare index with max + BNE LAB_29FB ; loop if not max + + ; now remove trailing zeroes + LDY Sendl ; get output string index +LAB_2A4B + LDA Decss,Y ; get character from output string + DEY ; decrement output string index + CMP #'0' ; compare with "0" + BEQ LAB_2A4B ; loop until non "0" character found + + CMP #'.' ; compare with "." + BEQ LAB_2A58 ; branch if was dp + + ; restore last character + INY ; increment output string index +LAB_2A58 + LDA #$2B ; character "+" + LDX expcnt ; get exponent count + BEQ LAB_2A8C ; if zero go set null terminator and exit + + ; exponent isn't zero so write exponent + BPL LAB_2A68 ; branch if exponent count +ve + + LDA #$00 ; clear A + SEC ; set carry for subtract + SBC expcnt ; subtract exponent count adjust (convert -ve to +ve) + TAX ; copy exponent count to X + LDA #'-' ; character "-" +LAB_2A68 + STA Decss+2,Y ; save to output string + LDA #$45 ; character "E" + STA Decss+1,Y ; save exponent sign to output string + TXA ; get exponent count back + LDX #'0'-1 ; one less than "0" character + SEC ; set carry for subtract +LAB_2A74 + INX ; increment 10's character + SBC #$0A ;.subtract 10 from exponent count + BCS LAB_2A74 ; loop while still >= 0 + + ADC #':' ; add character ":" ($30+$0A, result is 10 less that value) + STA Decss+4,Y ; save to output string + TXA ; copy 10's character + STA Decss+3,Y ; save to output string + LDA #$00 ; set null terminator + STA Decss+5,Y ; save to output string + BEQ LAB_2A91 ; go set string pointer (AY) and exit (branch always) + + ; save last character, [EOT] and exit +LAB_2A89 + STA Decss,Y ; save last character to output string + + ; set null terminator and exit +LAB_2A8C + LDA #$00 ; set null terminator + STA Decss+1,Y ; save after last character + + ; set string pointer (AY) and exit +LAB_2A91 + LDA #Decssp1 ; set result string high pointer + RTS + +; perform power function + +LAB_POWER + BEQ LAB_EXP ; go do EXP() + + LDA FAC2_e ; get FAC2 exponent + BNE LAB_2ABF ; branch if FAC2<>0 + + JMP LAB_24F3 ; clear FAC1 exponent and sign and return + +LAB_2ABF + LDX #func_l ; set destination pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) + LDA FAC2_s ; get FAC2 sign (b7) + BPL LAB_2AD9 ; branch if FAC2>0 + + ; else FAC2 is -ve and can only be raised to an + ; integer power which gives an x +j0 result + JSR LAB_INT ; perform INT + LDA #func_l ; set source pointer high byte + JSR LAB_27F8 ; compare FAC1 with (AY) + BNE LAB_2AD9 ; branch if FAC1 <> (AY) to allow Function Call error + ; this will leave FAC1 -ve and cause a Function Call + ; error when LOG() is called + + TYA ; clear sign b7 + LDY Temp3 ; save mantissa 3 from INT() function as sign in Y + ; for possible later negation, b0 +LAB_2AD9 + JSR LAB_279D ; save FAC1 sign and copy ABS(FAC2) to FAC1 + TYA ; copy sign back .. + PHA ; .. and save it + JSR LAB_LOG ; do LOG(n) + LDA #garb_l ; set pointer high byte + JSR LAB_25FB ; do convert AY, FCA1*(AY) (square the value) + JSR LAB_EXP ; go do EXP(n) + PLA ; pull sign from stack + LSR ; b0 is to be tested, shift to Cb + BCC LAB_2AF9 ; if no bit then exit + + ; Perform negation +; do - FAC1 + +LAB_GTHAN + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_2AF9 ; exit if FAC1_e = $00 + + LDA FAC1_s ; get FAC1 sign (b7) + EOR #$FF ; complement it + STA FAC1_s ; save FAC1 sign (b7) +LAB_2AF9 + RTS + +; perform EXP() (x^e) + +LAB_EXP + LDA #LAB_2AFA ; set 1.443 pointer high byte + JSR LAB_25FB ; do convert AY, FCA1*(AY) + LDA FAC1_r ; get FAC1 rounding byte + ADC #$50 ; +$50/$100 + BCC LAB_2B2B ; skip rounding if no carry + + JSR LAB_27C2 ; round FAC1 (no check) +LAB_2B2B + STA FAC2_r ; save FAC2 rounding byte + JSR LAB_27AE ; copy FAC1 to FAC2 + LDA FAC1_e ; get FAC1 exponent + CMP #$88 ; compare with EXP limit (256d) + BCC LAB_2B39 ; branch if less + +LAB_2B36 + JSR LAB_2690 ; handle overflow and underflow +LAB_2B39 + JSR LAB_INT ; perform INT + LDA Temp3 ; get mantissa 3 from INT() function + CLC ; clear carry for add + ADC #$81 ; normalise +1 + BEQ LAB_2B36 ; if $00 go handle overflow + + SEC ; set carry for subtract + SBC #$01 ; now correct for exponent + PHA ; save FAC2 exponent + + ; swap FAC1 and FAC2 + LDX #$04 ; 4 bytes to do +LAB_2B49 + LDA FAC2_e,X ; get FAC2,X + LDY FAC1_e,X ; get FAC1,X + STA FAC1_e,X ; save FAC1,X + STY FAC2_e,X ; save FAC2,X + DEX ; decrement count/index + BPL LAB_2B49 ; loop if not all done + + LDA FAC2_r ; get FAC2 rounding byte + STA FAC1_r ; save as FAC1 rounding byte + JSR LAB_SUBTRACT ; perform subtraction, FAC2 from FAC1 + JSR LAB_GTHAN ; do - FAC1 + LDA #LAB_2AFE ; set counter pointer high byte + JSR LAB_2B84 ; go do series evaluation + LDA #$00 ; clear A + STA FAC_sc ; clear sign compare (FAC1 EOR FAC2) + PLA ;.get saved FAC2 exponent + JMP LAB_2675 ; test and adjust accumulators and return + +; ^2 then series evaluation + +LAB_2B6E + STA Cptrl ; save count pointer low byte + STY Cptrh ; save count pointer high byte + JSR LAB_276E ; pack FAC1 into Adatal + LDA #Adatal ; pointer to original # high byte + JMP LAB_25FB ; do convert AY, FCA1*(AY) and return + +; series evaluation + +LAB_2B84 + STA Cptrl ; save count pointer low byte + STY Cptrh ; save count pointer high byte +LAB_2B88 + LDX #numexp ; set pointer high byte to partial @ numexp + DEC numcon ; decrement constants count + BNE LAB_2B9B ; loop until all done + + RTS + +; RND(n), 32 bit Galoise version. make n=0 for 19th next number in sequence or n<>0 +; to get 19th next number in sequence after seed n. This version of the PRNG uses +; the Galois method and a sample of 65536 bytes produced gives the following values. + +; Entropy = 7.997442 bits per byte +; Optimum compression would reduce these 65536 bytes by 0 percent + +; Chi square distribution for 65536 samples is 232.01, and +; randomly would exceed this value 75.00 percent of the time + +; Arithmetic mean value of data bytes is 127.6724, 127.5 would be random +; Monte Carlo value for Pi is 3.122871269, error 0.60 percent +; Serial correlation coefficient is -0.000370, totally uncorrelated would be 0.0 + +LAB_RND + LDA FAC1_e ; get FAC1 exponent + BEQ NextPRN ; do next random # if zero + + ; else get seed into random number store + LDX #Rbyte4 ; set PRNG pointer low byte + LDY #$00 ; set PRNG pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) +NextPRN + LDX #$AF ; set EOR byte + LDY #$13 ; do this nineteen times +LoopPRN + ASL Rbyte1 ; shift PRNG most significant byte + ROL Rbyte2 ; shift PRNG middle byte + ROL Rbyte3 ; shift PRNG least significant byte + ROL Rbyte4 ; shift PRNG extra byte + BCC Ninc1 ; branch if bit 32 clear + + TXA ; set EOR byte + EOR Rbyte1 ; EOR PRNG extra byte + STA Rbyte1 ; save new PRNG extra byte +Ninc1 + DEY ; decrement loop count + BNE LoopPRN ; loop if not all done + + LDX #$02 ; three bytes to copy +CopyPRNG + LDA Rbyte1,X ; get PRNG byte + STA FAC1_1,X ; save FAC1 byte + DEX + BPL CopyPRNG ; loop if not complete + + LDA #$80 ; set the exponent + STA FAC1_e ; save FAC1 exponent + + ASL ; clear A + STA FAC1_s ; save FAC1 sign + + JMP LAB_24D5 ; normalise FAC1 and return + +; perform COS() + +LAB_COS + LDA #LAB_2C78 ; set (pi/2) pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + +; perform SIN() + +LAB_SIN + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #LAB_2C7C ; set (2*pi) pointer high byte + LDX FAC2_s ; get FAC2 sign (b7) + JSR LAB_26C2 ; divide by (AY) (X=sign) + JSR LAB_27AB ; round and copy FAC1 to FAC2 + JSR LAB_INT ; perform INT + LDA #$00 ; clear byte + STA FAC_sc ; clear sign compare (FAC1 EOR FAC2) + JSR LAB_SUBTRACT ; perform subtraction, FAC2 from FAC1 + LDA #LAB_2C80 ; set 0.25 pointer high byte + JSR LAB_2455 ; perform subtraction, (AY) from FAC1 + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; save FAC1 sign + BPL LAB_2C35 ; branch if +ve + + ; FAC1 sign was -ve + JSR LAB_244E ; add 0.5 to FAC1 + LDA FAC1_s ; get FAC1 sign (b7) + BMI LAB_2C38 ; branch if -ve + + LDA Cflag ; get comparison evaluation flag + EOR #$FF ; toggle flag + STA Cflag ; save comparison evaluation flag +LAB_2C35 + JSR LAB_GTHAN ; do - FAC1 +LAB_2C38 + LDA #LAB_2C80 ; set 0.25 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + PLA ; restore FAC1 sign + BPL LAB_2C45 ; branch if was +ve + + ; else correct FAC1 + JSR LAB_GTHAN ; do - FAC1 +LAB_2C45 + LDA #LAB_2C84 ; set pointer high byte to counter + JMP LAB_2B6E ; ^2 then series evaluation and return + +; perform TAN() + +LAB_TAN + JSR LAB_276E ; pack FAC1 into Adatal + LDA #$00 ; clear byte + STA Cflag ; clear comparison evaluation flag + JSR LAB_SIN ; go do SIN(n) + LDX #func_l ; set sin(n) pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) + LDA #Adatal ; set n pointer high addr + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + LDA #$00 ; clear byte + STA FAC1_s ; clear FAC1 sign (b7) + LDA Cflag ; get comparison evaluation flag + JSR LAB_2C74 ; save flag and go do series evaluation + + LDA #func_l ; set sin(n) pointer high byte + JMP LAB_26CA ; convert AY and do (AY)/FAC1 + +LAB_2C74 + PHA ; save comparison evaluation flag + JMP LAB_2C35 ; go do series evaluation + +; perform USR() + +LAB_USR + JSR Usrjmp ; call user code + JMP LAB_1BFB ; scan for ")", else do syntax error then warm start + +; perform ATN() + +LAB_ATN + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; save sign + BPL LAB_2CA1 ; branch if +ve + + JSR LAB_GTHAN ; else do - FAC1 +LAB_2CA1 + LDA FAC1_e ; get FAC1 exponent + PHA ; push exponent + CMP #$81 ; compare with 1 + BCC LAB_2CAF ; branch if FAC1<1 + + LDA #LAB_259C ; set 1 pointer high byte + JSR LAB_26CA ; convert AY and do (AY)/FAC1 +LAB_2CAF + LDA #LAB_2CC9 ; set pointer high byte to counter + JSR LAB_2B6E ; ^2 then series evaluation + PLA ; restore old FAC1 exponent + CMP #$81 ; compare with 1 + BCC LAB_2CC2 ; branch if FAC1<1 + + LDA #LAB_2C78 ; set (pi/2) pointer high byte + JSR LAB_2455 ; perform subtraction, (AY) from FAC1 +LAB_2CC2 + PLA ; restore FAC1 sign + BPL LAB_2D04 ; exit if was +ve + + JMP LAB_GTHAN ; else do - FAC1 and return + +; perform BITSET + +LAB_BITSET + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + LDA #$00 ; clear A + SEC ; set the carry +S_Bits + ROL ; shift bit + DEX ; decrement bit number + BPL S_Bits ; loop if still +ve + + INX ; make X = $00 + ORA (Itempl,X) ; or with byte via temporary integer (addr) + STA (Itempl,X) ; save byte via temporary integer (addr) +LAB_2D04 + RTS + +; perform BITCLR + +LAB_BITCLR + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + LDA #$FF ; set A +S_Bitc + ROL ; shift bit + DEX ; decrement bit number + BPL S_Bitc ; loop if still +ve + + INX ; make X = $00 + AND (Itempl,X) ; and with byte via temporary integer (addr) + STA (Itempl,X) ; save byte via temporary integer (addr) + RTS + +FCError + JMP LAB_FCER ; do function call error then warm start + +; perform BITTST() + +LAB_BTST + JSR LAB_IGBY ; increment BASIC pointer + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + JSR LAB_GBYT ; get next BASIC byte + CMP #')' ; is next character ")" + BEQ TST_OK ; if ")" go do rest of function + + JMP LAB_SNER ; do syntax error then warm start + +TST_OK + JSR LAB_IGBY ; update BASIC execute pointer (to character past ")") + LDA #$00 ; clear A + SEC ; set the carry +T_Bits + ROL ; shift bit + DEX ; decrement bit number + BPL T_Bits ; loop if still +ve + + INX ; make X = $00 + AND (Itempl,X) ; AND with byte via temporary integer (addr) + BEQ LAB_NOTT ; branch if zero (already correct) + + LDA #$FF ; set for -1 result +LAB_NOTT + JMP LAB_27DB ; go do SGN tail + +; perform BIN$() + +LAB_BINS + CPX #$19 ; max + 1 + BCS BinFErr ; exit if too big ( > or = ) + + STX TempB ; save # of characters ($00 = leading zero remove) + LDA #$18 ; need A byte long space + JSR LAB_MSSP ; make string space A bytes long + LDY #$17 ; set index + LDX #$18 ; character count +NextB1 + LSR nums_1 ; shift highest byte + ROR nums_2 ; shift middle byte + ROR nums_3 ; shift lowest byte bit 0 to carry + TXA ; load with "0"/2 + ROL ; shift in carry + STA (str_pl),Y ; save to temp string + index + DEY ; decrement index + BPL NextB1 ; loop if not done + + LDA TempB ; get # of characters + BEQ EndBHS ; branch if truncate + + TAX ; copy length to X + SEC ; set carry for add ! + EOR #$FF ; 1's complement + ADC #$18 ; add 24d + BEQ GoPr2 ; if zero print whole string + + BNE GoPr1 ; else go make output string + +; this is the exit code and is also used by HEX$() +; truncate string to remove leading "0"s + +EndBHS + TAY ; clear index (A=0, X=length here) +NextB2 + LDA (str_pl),Y ; get character from string + CMP #'0' ; compare with "0" + BNE GoPr ; if not "0" then go print string from here + + DEX ; decrement character count + BEQ GoPr3 ; if zero then end of string so go print it + + INY ; else increment index + BPL NextB2 ; loop always + +; make fixed length output string - ignore overflows! + +GoPr3 + INX ; need at least 1 character +GoPr + TYA ; copy result +GoPr1 + CLC ; clear carry for add + ADC str_pl ; add low address + STA str_pl ; save low address + LDA #$00 ; do high byte + ADC str_ph ; add high address + STA str_ph ; save high address +GoPr2 + STX str_ln ; X holds string length + JSR LAB_IGBY ; update BASIC execute pointer (to character past ")") + JMP LAB_RTST ; check for space on descriptor stack then put address + ; and length on descriptor stack and update stack pointers + +BinFErr + JMP LAB_FCER ; do function call error then warm start + +; perform HEX$() + +LAB_HEXS + CPX #$07 ; max + 1 + BCS BinFErr ; exit if too big ( > or = ) + + STX TempB ; save # of characters + + LDA #$06 ; need 6 bytes for string + JSR LAB_MSSP ; make string space A bytes long + LDY #$05 ; set string index + + SED ; need decimal mode for nibble convert + LDA nums_3 ; get lowest byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + LDA nums_2 ; get middle byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + LDA nums_1 ; get highest byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + CLD ; back to binary + + LDX #$06 ; character count + LDA TempB ; get # of characters + BEQ EndBHS ; branch if truncate + + TAX ; copy length to X + SEC ; set carry for add ! + EOR #$FF ; 1's complement + ADC #$06 ; add 6d + BEQ GoPr2 ; if zero print whole string + + BNE GoPr1 ; else go make output string (branch always) + +; convert A to ASCII hex byte and output .. note set decimal mode before calling + +LAB_A2HX + TAX ; save byte + AND #$0F ; mask off top bits + JSR LAB_AL2X ; convert low nibble to ASCII and output + TXA ; get byte back + LSR ; /2 shift high nibble to low nibble + LSR ; /4 + LSR ; /8 + LSR ; /16 +LAB_AL2X + CMP #$0A ; set carry for +1 if >9 + ADC #'0' ; add ASCII "0" + STA (str_pl),Y ; save to temp string + DEY ; decrement counter + RTS + +LAB_NLTO + STA FAC1_e ; save FAC1 exponent + LDA #$00 ; clear sign compare +LAB_MLTE + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + TXA ; restore character + JSR LAB_2912 ; evaluate new ASCII digit + +; gets here if the first character was "$" for hex +; get hex number + +LAB_CHEX + JSR LAB_IGBY ; increment and scan memory + BCC LAB_ISHN ; branch if numeric character + + ORA #$20 ; case convert, allow "A" to "F" and "a" to "f" + SBC #'a' ; subtract "a" (carry set here) + CMP #$06 ; compare normalised with $06 (max+1) + BCS LAB_EXCH ; exit if >"f" or <"0" + + ADC #$0A ; convert to nibble +LAB_ISHN + AND #$0F ; convert to binary + TAX ; save nibble + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_MLTE ; skip multiply if zero + + ADC #$04 ; add four to exponent (*16 - carry clear here) + BCC LAB_NLTO ; if no overflow do evaluate digit + +LAB_MLTO + JMP LAB_2564 ; do overflow error and warm start + +LAB_NXCH + TAX ; save bit + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_MLBT ; skip multiply if zero + + INC FAC1_e ; increment FAC1 exponent (*2) + BEQ LAB_MLTO ; do overflow error if = $00 + + LDA #$00 ; clear sign compare +LAB_MLBT + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + TXA ; restore bit + JSR LAB_2912 ; evaluate new ASCII digit + +; gets here if the first character was "%" for binary +; get binary number + +LAB_CBIN + JSR LAB_IGBY ; increment and scan memory + EOR #'0' ; convert "0" to 0 etc. + CMP #$02 ; compare with max+1 + BCC LAB_NXCH ; branch exit if < 2 + +LAB_EXCH + JMP LAB_28F6 ; evaluate -ve flag and return + +; ctrl-c check routine. includes limited "life" byte save for INGET routine +; now also the code that checks to see if an interrupt has occurred + +CTRLC + LDA ccflag ; get [CTRL-C] check flag + BNE LAB_FBA2 ; exit if inhibited + + JSR V_INPT ; scan input device + BCC LAB_FBA0 ; exit if buffer empty + + STA ccbyte ; save received byte + LDX #$20 ; "life" timer for bytes + STX ccnull ; set countdown + JMP LAB_1636 ; return to BASIC + +LAB_FBA0 + LDX ccnull ; get countdown byte + BEQ LAB_FBA2 ; exit if finished + + DEC ccnull ; else decrement countdown +LAB_FBA2 + LDX #NmiBase ; set pointer to NMI values + JSR LAB_CKIN ; go check interrupt + LDX #IrqBase ; set pointer to IRQ values + JSR LAB_CKIN ; go check interrupt +LAB_CRTS + RTS + +; check whichever interrupt is indexed by X + +LAB_CKIN + LDA PLUS_0,X ; get interrupt flag byte + BPL LAB_CRTS ; branch if interrupt not enabled + +; we disable the interrupt here and make two new commands RETIRQ and RETNMI to +; automatically enable the interrupt when we exit + + ASL ; move happened bit to setup bit + AND #$40 ; mask happened bits + BEQ LAB_CRTS ; if no interrupt then exit + + STA PLUS_0,X ; save interrupt flag byte + + TXA ; copy index .. + TAY ; .. to Y + + PLA ; dump return address low byte, call from CTRL-C + PLA ; dump return address high byte + + LDA #$05 ; need 5 bytes for GOSUB + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_GOSUB ; token for GOSUB + PHA ; push on stack + + LDA PLUS_1,Y ; get interrupt code pointer low byte + STA Bpntrl ; save as BASIC execute pointer low byte + LDA PLUS_2,Y ; get interrupt code pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + + JMP LAB_15C2 ; go do interpreter inner loop + ; can't RTS, we used the stack! the RTS from the ctrl-c + ; check will be taken when the RETIRQ/RETNMI/RETURN is + ; executed at the end of the subroutine + +; get byte from input device, no waiting +; returns with carry set if byte in A + +INGET + JSR V_INPT ; call scan input device + BCS LAB_FB95 ; if byte go reset timer + + LDA ccnull ; get countdown + BEQ LAB_FB96 ; exit if empty + + LDA ccbyte ; get last received byte + SEC ; flag we got a byte +LAB_FB95 + LDX #$00 ; clear X + STX ccnull ; clear timer because we got a byte +LAB_FB96 + RTS + +; these routines only enable the interrupts if the set-up flag is set +; if not they have no effect + +; perform IRQ {ON|OFF|CLEAR} + +LAB_IRQ + LDX #IrqBase ; set pointer to IRQ values + .byte $2C ; make next line BIT abs. + +; perform NMI {ON|OFF|CLEAR} + +LAB_NMI + LDX #NmiBase ; set pointer to NMI values + CMP #TK_ON ; compare with token for ON + BEQ LAB_INON ; go turn on interrupt + + CMP #TK_OFF ; compare with token for OFF + BEQ LAB_IOFF ; go turn off interrupt + + EOR #TK_CLEAR ; compare with token for CLEAR, A = $00 if = TK_CLEAR + BEQ LAB_INEX ; go clear interrupt flags and return + + JMP LAB_SNER ; do syntax error then warm start + +LAB_IOFF + LDA #$7F ; clear A + AND PLUS_0,X ; AND with interrupt setup flag + BPL LAB_INEX ; go clear interrupt enabled flag and return + +LAB_INON + LDA PLUS_0,X ; get interrupt setup flag + ASL ; Shift bit to enabled flag + ORA PLUS_0,X ; OR with flag byte +LAB_INEX + STA PLUS_0,X ; save interrupt flag byte + JMP LAB_IGBY ; update BASIC execute pointer and return + +; these routines set up the pointers and flags for the interrupt routines +; note that the interrupts are also enabled by these commands + +; perform ON IRQ + +LAB_SIRQ + CLI ; enable interrupts + LDX #IrqBase ; set pointer to IRQ values + .byte $2C ; make next line BIT abs. + +; perform ON NMI + +LAB_SNMI + LDX #NmiBase ; set pointer to NMI values + + STX TempB ; save interrupt pointer + JSR LAB_IGBY ; increment and scan memory (past token) + JSR LAB_GFPN ; get fixed-point number into temp integer + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCS LAB_LFND ; if carry set go set-up interrupt + + JMP LAB_16F7 ; else go do "Undefined statement" error and warm start + +LAB_LFND + LDX TempB ; get interrupt pointer + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 (carry already set for subtract) + STA PLUS_1,X ; save as interrupt pointer low byte + LDA Baslnh ; get pointer high byte + SBC #$00 ; subtract carry + STA PLUS_2,X ; save as interrupt pointer high byte + + LDA #$C0 ; set interrupt enabled/setup bits + STA PLUS_0,X ; set interrupt flags +LAB_IRTS + RTS + +; return from IRQ service, restores the enabled flag. + +; perform RETIRQ + +LAB_RETIRQ + BNE LAB_IRTS ; exit if following token (to allow syntax error) + + LDA IrqBase ; get interrupt flags + ASL ; copy setup to enabled (b7) + ORA IrqBase ; OR in setup flag + STA IrqBase ; save enabled flag + JMP LAB_16E8 ; go do rest of RETURN + +; return from NMI service, restores the enabled flag. + +; perform RETNMI + +LAB_RETNMI + BNE LAB_IRTS ; exit if following token (to allow syntax error) + + LDA NmiBase ; get set-up flag + ASL ; copy setup to enabled (b7) + ORA NmiBase ; OR in setup flag + STA NmiBase ; save enabled flag + JMP LAB_16E8 ; go do rest of RETURN + +; MAX() MIN() pre process + +LAB_MMPP + JSR LAB_EVEZ ; process expression + JMP LAB_CTNM ; check if source is numeric, else do type mismatch + +; perform MAX() + +LAB_MAX + JSR LAB_PHFA ; push FAC1, evaluate expression, + ; pull FAC2 and compare with FAC1 + BPL LAB_MAX ; branch if no swap to do + + LDA FAC2_1 ; get FAC2 mantissa1 + ORA #$80 ; set top bit (clear sign from compare) + STA FAC2_1 ; save FAC2 mantissa1 + JSR LAB_279B ; copy FAC2 to FAC1 + BEQ LAB_MAX ; go do next (branch always) + +; perform MIN() + +LAB_MIN + JSR LAB_PHFA ; push FAC1, evaluate expression, + ; pull FAC2 and compare with FAC1 + BMI LAB_MIN ; branch if no swap to do + + BEQ LAB_MIN ; branch if no swap to do + + LDA FAC2_1 ; get FAC2 mantissa1 + ORA #$80 ; set top bit (clear sign from compare) + STA FAC2_1 ; save FAC2 mantissa1 + JSR LAB_279B ; copy FAC2 to FAC1 + BEQ LAB_MIN ; go do next (branch always) + +; exit routine. don't bother returning to the loop code +; check for correct exit, else so syntax error + +LAB_MMEC + CMP #')' ; is it end of function? + BNE LAB_MMSE ; if not do MAX MIN syntax error + + PLA ; dump return address low byte + PLA ; dump return address high byte + JMP LAB_IGBY ; update BASIC execute pointer (to chr past ")") + +LAB_MMSE + JMP LAB_SNER ; do syntax error then warm start + +; check for next, evaluate and return or exit +; this is the routine that does most of the work + +LAB_PHFA + JSR LAB_GBYT ; get next BASIC byte + CMP #',' ; is there more ? + BNE LAB_MMEC ; if not go do end check + + ; push FAC1 + JSR LAB_27BA ; round FAC1 + LDA FAC1_s ; get FAC1 sign + ORA #$7F ; set all non sign bits + AND FAC1_1 ; AND FAC1 mantissa1 (AND in sign bit) + PHA ; push on stack + LDA FAC1_2 ; get FAC1 mantissa2 + PHA ; push on stack + LDA FAC1_3 ; get FAC1 mantissa3 + PHA ; push on stack + LDA FAC1_e ; get FAC1 exponent + PHA ; push on stack + + JSR LAB_IGBY ; scan and get next BASIC byte (after ",") + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + + ; pop FAC2 (MAX/MIN expression so far) + PLA ; pop exponent + STA FAC2_e ; save FAC2 exponent + PLA ; pop mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + PLA ; pop mantissa1 + STA FAC2_2 ; save FAC2 mantissa2 + PLA ; pop sign/mantissa1 + STA FAC2_1 ; save FAC2 sign/mantissa1 + STA FAC2_s ; save FAC2 sign + + ; compare FAC1 with (packed) FAC2 + LDA #FAC2_e ; set pointer high byte to FAC2 + JMP LAB_27F8 ; compare FAC1 with FAC2 (AY) and return + ; returns A=$00 if FAC1 = (AY) + ; returns A=$01 if FAC1 > (AY) + ; returns A=$FF if FAC1 < (AY) + +; perform WIDTH + +LAB_WDTH + CMP #',' ; is next byte "," + BEQ LAB_TBSZ ; if so do tab size + + JSR LAB_GTBY ; get byte parameter + TXA ; copy width to A + BEQ LAB_NSTT ; branch if set for infinite line + + CPX #$10 ; else make min width = 16d + BCC TabErr ; if less do function call error and exit + +; this next compare ensures that we can't exit WIDTH via an error leaving the +; tab size greater than the line length. + + CPX TabSiz ; compare with tab size + BCS LAB_NSTT ; branch if >= tab size + + STX TabSiz ; else make tab size = terminal width +LAB_NSTT + STX TWidth ; set the terminal width + JSR LAB_GBYT ; get BASIC byte back + BEQ WExit ; exit if no following + + CMP #',' ; else is it "," + BNE LAB_MMSE ; if not do syntax error + +LAB_TBSZ + JSR LAB_SGBY ; scan and get byte parameter + TXA ; copy TAB size + BMI TabErr ; if >127 do function call error and exit + + CPX #$01 ; compare with min-1 + BCC TabErr ; if <=1 do function call error and exit + + LDA TWidth ; set flags for width + BEQ LAB_SVTB ; skip check if infinite line + + CPX TWidth ; compare TAB with width + BEQ LAB_SVTB ; ok if = + + BCS TabErr ; branch if too big + +LAB_SVTB + STX TabSiz ; save TAB size + +; calculate tab column limit from TAB size. The Iclim is set to the last tab +; position on a line that still has at least one whole tab width between it +; and the end of the line. + +WExit + LDA TWidth ; get width + BEQ LAB_SULP ; branch if infinite line + + CMP TabSiz ; compare with tab size + BCS LAB_WDLP ; branch if >= tab size + + STA TabSiz ; else make tab size = terminal width +LAB_SULP + SEC ; set carry for subtract +LAB_WDLP + SBC TabSiz ; subtract tab size + BCS LAB_WDLP ; loop while no borrow + + ADC TabSiz ; add tab size back + CLC ; clear carry for add + ADC TabSiz ; add tab size back again + STA Iclim ; save for now + LDA TWidth ; get width back + SEC ; set carry for subtract + SBC Iclim ; subtract remainder + STA Iclim ; save tab column limit +LAB_NOSQ + RTS + +TabErr + JMP LAB_FCER ; do function call error then warm start + +; perform SQR() + +LAB_SQR + LDA FAC1_s ; get FAC1 sign + BMI TabErr ; if -ve do function call error + + LDA FAC1_e ; get exponent + BEQ LAB_NOSQ ; if zero just return + + ; else do root + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #$00 ; clear A + + STA FACt_3 ; clear remainder + STA FACt_2 ; .. + STA FACt_1 ; .. + STA TempB ; .. + + STA FAC1_3 ; clear root + STA FAC1_2 ; .. + STA FAC1_1 ; .. + + LDX #$18 ; 24 pairs of bits to do + LDA FAC2_e ; get exponent + LSR ; check odd/even + BCS LAB_SQE2 ; if odd only 1 shift first time + +LAB_SQE1 + ASL FAC2_3 ; shift highest bit of number .. + ROL FAC2_2 ; .. + ROL FAC2_1 ; .. + ROL FACt_3 ; .. into remainder + ROL FACt_2 ; .. + ROL FACt_1 ; .. + ROL TempB ; .. never overflows +LAB_SQE2 + ASL FAC2_3 ; shift highest bit of number .. + ROL FAC2_2 ; .. + ROL FAC2_1 ; .. + ROL FACt_3 ; .. into remainder + ROL FACt_2 ; .. + ROL FACt_1 ; .. + ROL TempB ; .. never overflows + + ASL FAC1_3 ; root = root * 2 + ROL FAC1_2 ; .. + ROL FAC1_1 ; .. never overflows + + LDA FAC1_3 ; get root low byte + ROL ; *2 + STA Temp3 ; save partial low byte + LDA FAC1_2 ; get root low mid byte + ROL ; *2 + STA Temp3+1 ; save partial low mid byte + LDA FAC1_1 ; get root high mid byte + ROL ; *2 + STA Temp3+2 ; save partial high mid byte + LDA #$00 ; get root high byte (always $00) + ROL ; *2 + STA Temp3+3 ; save partial high byte + + ; carry clear for subtract +1 + LDA FACt_3 ; get remainder low byte + SBC Temp3 ; subtract partial low byte + STA Temp3 ; save partial low byte + + LDA FACt_2 ; get remainder low mid byte + SBC Temp3+1 ; subtract partial low mid byte + STA Temp3+1 ; save partial low mid byte + + LDA FACt_1 ; get remainder high mid byte + SBC Temp3+2 ; subtract partial high mid byte + TAY ; copy partial high mid byte + + LDA TempB ; get remainder high byte + SBC Temp3+3 ; subtract partial high byte + BCC LAB_SQNS ; skip sub if remainder smaller + + STA TempB ; save remainder high byte + + STY FACt_1 ; save remainder high mid byte + + LDA Temp3+1 ; get remainder low mid byte + STA FACt_2 ; save remainder low mid byte + + LDA Temp3 ; get partial low byte + STA FACt_3 ; save remainder low byte + + INC FAC1_3 ; increment root low byte (never any rollover) +LAB_SQNS + DEX ; decrement bit pair count + BNE LAB_SQE1 ; loop if not all done + + SEC ; set carry for subtract + LDA FAC2_e ; get exponent + SBC #$80 ; normalise + ROR ; /2 and re-bias to $80 + ADC #$00 ; add bit zero back in (allow for half shift) + STA FAC1_e ; save it + JMP LAB_24D5 ; normalise FAC1 and return + +; perform VARPTR() + +LAB_VARPTR + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GVAR ; get var address + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + LDY Cvaral ; get var address low byte + LDA Cvarah ; get var address high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform PI + +LAB_PI + LDA #LAB_2C7C ; set (2*pi) pointer high byte + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + DEC FAC1_e ; make result = PI + RTS + +; perform TWOPI + +LAB_TWOPI + LDA #LAB_2C7C ; set (2*pi) pointer high byte + JMP LAB_UFAC ; unpack memory (AY) into FAC1 and return + +; system dependant i/o vectors +; these are in RAM and are set by the monitor at start-up + +V_INPT + JMP (VEC_IN) ; non halting scan input device +V_OUTP + JMP (VEC_OUT) ; send byte to output device +V_LOAD + JMP (VEC_LD) ; load BASIC program +V_SAVE + JMP (VEC_SV) ; save BASIC program + +; The rest are tables messages and code for RAM + +; the rest of the code is tables and BASIC start-up code + +PG2_TABS + .byte $FF ; ctrl-c flag - $00 = enabled + .byte $00 ; ctrl-c byte - GET needs this + .byte $00 ; ctrl-c byte timeout - GET needs this + .word CTRLC ; ctrl c check vector + .word CHRIN ; non halting key input - monitor to set this + .word CHROUT ; output vector - monitor to set this +; .word xxxx ; load vector - monitor to set this +; .word xxxx ; save vector - monitor to set this +PG2_TABE + +; character get subroutine for zero page + +; For a 1.8432MHz 6502 including the JSR and RTS +; fastest (>=":") = 29 cycles = 15.7uS +; slowest (<":") = 40 cycles = 21.7uS +; space skip = +21 cycles = +11.4uS +; inc across page = +4 cycles = +2.2uS + +; the target address for the LDA at LAB_2CF4 becomes the BASIC execute pointer once the +; block is copied to it's destination, any non zero page address will do at assembly +; time, to assemble a three byte instruction. + +; page 0 initialisation table from $BC +; increment and scan memory + +LAB_2CEE + INC Bpntrl ; increment BASIC execute pointer low byte + BNE LAB_2CF4 ; branch if no carry + ; else + INC Bpntrh ; increment BASIC execute pointer high byte + +; page 0 initialisation table from $C2 +; scan memory + +LAB_2CF4 + LDA $FFFF ; get byte to scan (addr set by call routine) + CMP #TK_ELSE ; compare with the token for ELSE + BEQ LAB_2D05 ; exit if ELSE, not numeric, carry set + + CMP #':' ; compare with ":" + BCS LAB_2D05 ; exit if >= ":", not numeric, carry set + + CMP #' ' ; compare with " " + BEQ LAB_2CEE ; if " " go do next + + SEC ; set carry for SBC + SBC #'0' ; subtract "0" + SEC ; set carry for SBC + SBC #$D0 ; subtract -"0" + ; clear carry if byte = "0"-"9" +LAB_2D05 + RTS + +; page zero initialisation table $00-$12 inclusive + +StrTab + .byte $4C ; JMP opcode + .word LAB_COLD ; initial warm start vector (cold start) + + .byte $00 ; these bytes are not used by BASIC + .word $0000 ; + .word $0000 ; + .word $0000 ; + + .byte $4C ; JMP opcode + .word LAB_FCER ; initial user function vector ("Function call" error) + .byte $00 ; default NULL count + .byte $00 ; clear terminal position + .byte $00 ; default terminal width byte + .byte $F2 ; default limit for TAB = 14 + .word Ram_base ; start of user RAM +EndTab + +LAB_MSZM + .byte $0D,$0A,"Memory size ",$00 + +LAB_SMSG + .byte " Bytes free",$0D,$0A,$0A + .byte "Enhanced BASIC 2.22",$0A,$00 + +; numeric constants and series + + ; constants and series for LOG(n) +LAB_25A0 + .byte $02 ; counter + .byte $80,$19,$56,$62 ; 0.59898 + .byte $80,$76,$22,$F3 ; 0.96147 +;## .byte $80,$76,$22,$F1 ; 0.96147 + .byte $82,$38,$AA,$40 ; 2.88539 +;## .byte $82,$38,$AA,$45 ; 2.88539 + +LAB_25AD + .byte $80,$35,$04,$F3 ; 0.70711 1/root 2 +LAB_25B1 + .byte $81,$35,$04,$F3 ; 1.41421 root 2 +LAB_25B5 + .byte $80,$80,$00,$00 ; -0.5 +LAB_25B9 + .byte $80,$31,$72,$18 ; 0.69315 LOG(2) + + ; numeric PRINT constants +LAB_2947 + .byte $91,$43,$4F,$F8 ; 99999.9375 (max value with at least one decimal) +LAB_294B + .byte $94,$74,$23,$F7 ; 999999.4375 (max value before scientific notation) +LAB_294F + .byte $94,$74,$24,$00 ; 1000000 + + ; EXP(n) constants and series +LAB_2AFA + .byte $81,$38,$AA,$3B ; 1.4427 (1/LOG base 2 e) +LAB_2AFE + .byte $06 ; counter + .byte $74,$63,$90,$8C ; 2.17023e-4 + .byte $77,$23,$0C,$AB ; 0.00124 + .byte $7A,$1E,$94,$00 ; 0.00968 + .byte $7C,$63,$42,$80 ; 0.05548 + .byte $7E,$75,$FE,$D0 ; 0.24023 + .byte $80,$31,$72,$15 ; 0.69315 + .byte $81,$00,$00,$00 ; 1.00000 + +;## .byte $07 ; counter +;## .byte $74,$94,$2E,$40 ; -1/7! (-1/5040) +;## .byte $77,$2E,$4F,$70 ; 1/6! ( 1/720) +;## .byte $7A,$88,$02,$6E ; -1/5! (-1/120) +;## .byte $7C,$2A,$A0,$E6 ; 1/4! ( 1/24) +;## .byte $7E,$AA,$AA,$50 ; -1/3! (-1/6) +;## .byte $7F,$7F,$FF,$FF ; 1/2! ( 1/2) +;## .byte $81,$80,$00,$00 ; -1/1! (-1/1) +;## .byte $81,$00,$00,$00 ; 1/0! ( 1/1) + + ; trigonometric constants and series +LAB_2C78 + .byte $81,$49,$0F,$DB ; 1.570796371 (pi/2) as floating # +LAB_2C84 + .byte $04 ; counter + .byte $86,$1E,$D7,$FB ; 39.7109 +;## .byte $86,$1E,$D7,$BA ; 39.7109 + .byte $87,$99,$26,$65 ;-76.575 +;## .byte $87,$99,$26,$64 ;-76.575 + .byte $87,$23,$34,$58 ; 81.6022 + .byte $86,$A5,$5D,$E1 ;-41.3417 +;## .byte $86,$A5,$5D,$E0 ;-41.3417 +LAB_2C7C + .byte $83,$49,$0F,$DB ; 6.28319 (2*pi) as floating # +;## .byte $83,$49,$0F,$DA ; 6.28319 (2*pi) as floating # + +LAB_2CC9 + .byte $08 ; counter + .byte $78,$3A,$C5,$37 ; 0.00285 + .byte $7B,$83,$A2,$5C ;-0.0160686 + .byte $7C,$2E,$DD,$4D ; 0.0426915 + .byte $7D,$99,$B0,$1E ;-0.0750429 + .byte $7D,$59,$ED,$24 ; 0.106409 + .byte $7E,$91,$72,$00 ;-0.142036 + .byte $7E,$4C,$B9,$73 ; 0.199926 + .byte $7F,$AA,$AA,$53 ;-0.333331 + +;## .byte $08 ; counter +;## .byte $78,$3B,$D7,$4A ; 1/17 +;## .byte $7B,$84,$6E,$02 ;-1/15 +;## .byte $7C,$2F,$C1,$FE ; 1/13 +;## .byte $7D,$9A,$31,$74 ;-1/11 +;## .byte $7D,$5A,$3D,$84 ; 1/9 +;## .byte $7E,$91,$7F,$C8 ;-1/7 +;## .byte $7E,$4C,$BB,$E4 ; 1/5 +;## .byte $7F,$AA,$AA,$6C ;-1/3 + +LAB_1D96 = *+1 ; $00,$00 used for undefined variables +LAB_259C + .byte $81,$00,$00,$00 ; 1.000000, used for INC +LAB_2AFD + .byte $81,$80,$00,$00 ; -1.00000, used for DEC. must be on the same page as +1.00 + + ; misc constants +LAB_1DF7 + .byte $90 ;-32768 (uses first three bytes from 0.5) +LAB_2A96 + .byte $80,$00,$00,$00 ; 0.5 +LAB_2C80 + .byte $7F,$00,$00,$00 ; 0.25 +LAB_26B5 + .byte $84,$20,$00,$00 ; 10.0000 divide by 10 constant + +; This table is used in converting numbers to ASCII. + +LAB_2A9A +LAB_2A9B = LAB_2A9A+1 +LAB_2A9C = LAB_2A9B+1 + .byte $FE,$79,$60 ; -100000 + .byte $00,$27,$10 ; 10000 + .byte $FF,$FC,$18 ; -1000 + .byte $00,$00,$64 ; 100 + .byte $FF,$FF,$F6 ; -10 + .byte $00,$00,$01 ; 1 + +LAB_CTBL + .word LAB_END-1 ; END + .word LAB_FOR-1 ; FOR + .word LAB_NEXT-1 ; NEXT + .word LAB_DATA-1 ; DATA + .word LAB_INPUT-1 ; INPUT + .word LAB_DIM-1 ; DIM + .word LAB_READ-1 ; READ + .word LAB_LET-1 ; LET + .word LAB_DEC-1 ; DEC new command + .word LAB_GOTO-1 ; GOTO + .word LAB_RUN-1 ; RUN + .word LAB_IF-1 ; IF + .word LAB_RESTORE-1 ; RESTORE modified command + .word LAB_GOSUB-1 ; GOSUB + .word LAB_RETIRQ-1 ; RETIRQ new command + .word LAB_RETNMI-1 ; RETNMI new command + .word LAB_RETURN-1 ; RETURN + .word LAB_REM-1 ; REM + .word LAB_STOP-1 ; STOP + .word LAB_ON-1 ; ON modified command + .word LAB_NULL-1 ; NULL modified command + .word LAB_INC-1 ; INC new command + .word LAB_WAIT-1 ; WAIT + .word V_LOAD-1 ; LOAD + .word V_SAVE-1 ; SAVE + .word LAB_DEF-1 ; DEF + .word LAB_POKE-1 ; POKE + .word LAB_DOKE-1 ; DOKE new command + .word LAB_CALL-1 ; CALL new command + .word LAB_DO-1 ; DO new command + .word LAB_LOOP-1 ; LOOP new command + .word LAB_PRINT-1 ; PRINT + .word LAB_CONT-1 ; CONT + .word LAB_LIST-1 ; LIST + .word LAB_CLEAR-1 ; CLEAR + .word LAB_NEW-1 ; NEW + .word LAB_WDTH-1 ; WIDTH new command + .word LAB_GET-1 ; GET new command + .word LAB_SWAP-1 ; SWAP new command + .word LAB_BITSET-1 ; BITSET new command + .word LAB_BITCLR-1 ; BITCLR new command + .word LAB_IRQ-1 ; IRQ new command + .word LAB_NMI-1 ; NMI new command + +; function pre process routine table + +LAB_FTPL +LAB_FTPM = LAB_FTPL+$01 + .word LAB_PPFN-1 ; SGN(n) process numeric expression in () + .word LAB_PPFN-1 ; INT(n) " + .word LAB_PPFN-1 ; ABS(n) " + .word LAB_EVEZ-1 ; USR(x) process any expression + .word LAB_1BF7-1 ; FRE(x) " + .word LAB_1BF7-1 ; POS(x) " + .word LAB_PPFN-1 ; SQR(n) process numeric expression in () + .word LAB_PPFN-1 ; RND(n) " + .word LAB_PPFN-1 ; LOG(n) " + .word LAB_PPFN-1 ; EXP(n) " + .word LAB_PPFN-1 ; COS(n) " + .word LAB_PPFN-1 ; SIN(n) " + .word LAB_PPFN-1 ; TAN(n) " + .word LAB_PPFN-1 ; ATN(n) " + .word LAB_PPFN-1 ; PEEK(n) " + .word LAB_PPFN-1 ; DEEK(n) " + .word $0000 ; SADD() none + .word LAB_PPFS-1 ; LEN($) process string expression in () + .word LAB_PPFN-1 ; STR$(n) process numeric expression in () + .word LAB_PPFS-1 ; VAL($) process string expression in () + .word LAB_PPFS-1 ; ASC($) " + .word LAB_PPFS-1 ; UCASE$($) " + .word LAB_PPFS-1 ; LCASE$($) " + .word LAB_PPFN-1 ; CHR$(n) process numeric expression in () + .word LAB_BHSS-1 ; HEX$(n) " + .word LAB_BHSS-1 ; BIN$(n) " + .word $0000 ; BITTST() none + .word LAB_MMPP-1 ; MAX() process numeric expression + .word LAB_MMPP-1 ; MIN() " + .word LAB_PPBI-1 ; PI advance pointer + .word LAB_PPBI-1 ; TWOPI " + .word $0000 ; VARPTR() none + .word LAB_LRMS-1 ; LEFT$() process string expression + .word LAB_LRMS-1 ; RIGHT$() " + .word LAB_LRMS-1 ; MID$() " + +; action addresses for functions + +LAB_FTBL +LAB_FTBM = LAB_FTBL+$01 + .word LAB_SGN-1 ; SGN() + .word LAB_INT-1 ; INT() + .word LAB_ABS-1 ; ABS() + .word LAB_USR-1 ; USR() + .word LAB_FRE-1 ; FRE() + .word LAB_POS-1 ; POS() + .word LAB_SQR-1 ; SQR() + .word LAB_RND-1 ; RND() modified function + .word LAB_LOG-1 ; LOG() + .word LAB_EXP-1 ; EXP() + .word LAB_COS-1 ; COS() + .word LAB_SIN-1 ; SIN() + .word LAB_TAN-1 ; TAN() + .word LAB_ATN-1 ; ATN() + .word LAB_PEEK-1 ; PEEK() + .word LAB_DEEK-1 ; DEEK() new function + .word LAB_SADD-1 ; SADD() new function + .word LAB_LENS-1 ; LEN() + .word LAB_STRS-1 ; STR$() + .word LAB_VAL-1 ; VAL() + .word LAB_ASC-1 ; ASC() + .word LAB_UCASE-1 ; UCASE$() new function + .word LAB_LCASE-1 ; LCASE$() new function + .word LAB_CHRS-1 ; CHR$() + .word LAB_HEXS-1 ; HEX$() new function + .word LAB_BINS-1 ; BIN$() new function + .word LAB_BTST-1 ; BITTST() new function + .word LAB_MAX-1 ; MAX() new function + .word LAB_MIN-1 ; MIN() new function + .word LAB_PI-1 ; PI new function + .word LAB_TWOPI-1 ; TWOPI new function + .word LAB_VARPTR-1 ; VARPTR() new function + .word LAB_LEFT-1 ; LEFT$() + .word LAB_RIGHT-1 ; RIGHT$() + .word LAB_MIDS-1 ; MID$() + +; hierarchy and action addresses for operator + +LAB_OPPT + .byte $79 ; + + .word LAB_ADD-1 + .byte $79 ; - + .word LAB_SUBTRACT-1 + .byte $7B ; * + .word LAB_MULTIPLY-1 + .byte $7B ; / + .word LAB_DIVIDE-1 + .byte $7F ; ^ + .word LAB_POWER-1 + .byte $50 ; AND + .word LAB_AND-1 + .byte $46 ; EOR new operator + .word LAB_EOR-1 + .byte $46 ; OR + .word LAB_OR-1 + .byte $56 ; >> new operator + .word LAB_RSHIFT-1 + .byte $56 ; << new operator + .word LAB_LSHIFT-1 + .byte $7D ; > + .word LAB_GTHAN-1 + .byte $5A ; = + .word LAB_EQUAL-1 + .byte $64 ; < + .word LAB_LTHAN-1 + +; keywords start with .. +; this is the first character table and must be in alphabetic order + +TAB_1STC + .byte "*" + .byte "+" + .byte "-" + .byte "/" + .byte "<" + .byte "=" + .byte ">" + .byte "?" + .byte "A" + .byte "B" + .byte "C" + .byte "D" + .byte "E" + .byte "F" + .byte "G" + .byte "H" + .byte "I" + .byte "L" + .byte "M" + .byte "N" + .byte "O" + .byte "P" + .byte "R" + .byte "S" + .byte "T" + .byte "U" + .byte "V" + .byte "W" + .byte "^" + .byte $00 ; table terminator + +; pointers to keyword tables + +TAB_CHRT + .word TAB_STAR ; table for "*" + .word TAB_PLUS ; table for "+" + .word TAB_MNUS ; table for "-" + .word TAB_SLAS ; table for "/" + .word TAB_LESS ; table for "<" + .word TAB_EQUL ; table for "=" + .word TAB_MORE ; table for ">" + .word TAB_QEST ; table for "?" + .word TAB_ASCA ; table for "A" + .word TAB_ASCB ; table for "B" + .word TAB_ASCC ; table for "C" + .word TAB_ASCD ; table for "D" + .word TAB_ASCE ; table for "E" + .word TAB_ASCF ; table for "F" + .word TAB_ASCG ; table for "G" + .word TAB_ASCH ; table for "H" + .word TAB_ASCI ; table for "I" + .word TAB_ASCL ; table for "L" + .word TAB_ASCM ; table for "M" + .word TAB_ASCN ; table for "N" + .word TAB_ASCO ; table for "O" + .word TAB_ASCP ; table for "P" + .word TAB_ASCR ; table for "R" + .word TAB_ASCS ; table for "S" + .word TAB_ASCT ; table for "T" + .word TAB_ASCU ; table for "U" + .word TAB_ASCV ; table for "V" + .word TAB_ASCW ; table for "W" + .word TAB_POWR ; table for "^" + +; tables for each start character, note if a longer keyword with the same start +; letters as a shorter one exists then it must come first, else the list is in +; alphabetical order as follows .. + +; [keyword,token +; [keyword,token]] +; end marker (#$00) + +TAB_STAR + .byte TK_MUL,$00 ; * +TAB_PLUS + .byte TK_PLUS,$00 ; + +TAB_MNUS + .byte TK_MINUS,$00 ; - +TAB_SLAS + .byte TK_DIV,$00 ; / +TAB_LESS +LBB_LSHIFT + .byte "<",TK_LSHIFT ; << note - "<<" must come before "<" + .byte TK_LT ; < + .byte $00 +TAB_EQUL + .byte TK_EQUAL,$00 ; = +TAB_MORE +LBB_RSHIFT + .byte ">",TK_RSHIFT ; >> note - ">>" must come before ">" + .byte TK_GT ; > + .byte $00 +TAB_QEST + .byte TK_PRINT,$00 ; ? +TAB_ASCA +LBB_ABS + .byte "BS(",TK_ABS ; ABS( +LBB_AND + .byte "ND",TK_AND ; AND +LBB_ASC + .byte "SC(",TK_ASC ; ASC( +LBB_ATN + .byte "TN(",TK_ATN ; ATN( + .byte $00 +TAB_ASCB +LBB_BINS + .byte "IN$(",TK_BINS ; BIN$( +LBB_BITCLR + .byte "ITCLR",TK_BITCLR ; BITCLR +LBB_BITSET + .byte "ITSET",TK_BITSET ; BITSET +LBB_BITTST + .byte "ITTST(",TK_BITTST + ; BITTST( + .byte $00 +TAB_ASCC +LBB_CALL + .byte "ALL",TK_CALL ; CALL +LBB_CHRS + .byte "HR$(",TK_CHRS ; CHR$( +LBB_CLEAR + .byte "LEAR",TK_CLEAR ; CLEAR +LBB_CONT + .byte "ONT",TK_CONT ; CONT +LBB_COS + .byte "OS(",TK_COS ; COS( + .byte $00 +TAB_ASCD +LBB_DATA + .byte "ATA",TK_DATA ; DATA +LBB_DEC + .byte "EC",TK_DEC ; DEC +LBB_DEEK + .byte "EEK(",TK_DEEK ; DEEK( +LBB_DEF + .byte "EF",TK_DEF ; DEF +LBB_DIM + .byte "IM",TK_DIM ; DIM +LBB_DOKE + .byte "OKE",TK_DOKE ; DOKE note - "DOKE" must come before "DO" +LBB_DO + .byte "O",TK_DO ; DO + .byte $00 +TAB_ASCE +LBB_ELSE + .byte "LSE",TK_ELSE ; ELSE +LBB_END + .byte "ND",TK_END ; END +LBB_EOR + .byte "OR",TK_EOR ; EOR +LBB_EXP + .byte "XP(",TK_EXP ; EXP( + .byte $00 +TAB_ASCF +LBB_FN + .byte "N",TK_FN ; FN +LBB_FOR + .byte "OR",TK_FOR ; FOR +LBB_FRE + .byte "RE(",TK_FRE ; FRE( + .byte $00 +TAB_ASCG +LBB_GET + .byte "ET",TK_GET ; GET +LBB_GOSUB + .byte "OSUB",TK_GOSUB ; GOSUB +LBB_GOTO + .byte "OTO",TK_GOTO ; GOTO + .byte $00 +TAB_ASCH +LBB_HEXS + .byte "EX$(",TK_HEXS ; HEX$( + .byte $00 +TAB_ASCI +LBB_IF + .byte "F",TK_IF ; IF +LBB_INC + .byte "NC",TK_INC ; INC +LBB_INPUT + .byte "NPUT",TK_INPUT ; INPUT +LBB_INT + .byte "NT(",TK_INT ; INT( +LBB_IRQ + .byte "RQ",TK_IRQ ; IRQ + .byte $00 +TAB_ASCL +LBB_LCASES + .byte "CASE$(",TK_LCASES + ; LCASE$( +LBB_LEFTS + .byte "EFT$(",TK_LEFTS ; LEFT$( +LBB_LEN + .byte "EN(",TK_LEN ; LEN( +LBB_LET + .byte "ET",TK_LET ; LET +LBB_LIST + .byte "IST",TK_LIST ; LIST +LBB_LOAD + .byte "OAD",TK_LOAD ; LOAD +LBB_LOG + .byte "OG(",TK_LOG ; LOG( +LBB_LOOP + .byte "OOP",TK_LOOP ; LOOP + .byte $00 +TAB_ASCM +LBB_MAX + .byte "AX(",TK_MAX ; MAX( +LBB_MIDS + .byte "ID$(",TK_MIDS ; MID$( +LBB_MIN + .byte "IN(",TK_MIN ; MIN( + .byte $00 +TAB_ASCN +LBB_NEW + .byte "EW",TK_NEW ; NEW +LBB_NEXT + .byte "EXT",TK_NEXT ; NEXT +LBB_NMI + .byte "MI",TK_NMI ; NMI +LBB_NOT + .byte "OT",TK_NOT ; NOT +LBB_NULL + .byte "ULL",TK_NULL ; NULL + .byte $00 +TAB_ASCO +LBB_OFF + .byte "FF",TK_OFF ; OFF +LBB_ON + .byte "N",TK_ON ; ON +LBB_OR + .byte "R",TK_OR ; OR + .byte $00 +TAB_ASCP +LBB_PEEK + .byte "EEK(",TK_PEEK ; PEEK( +LBB_PI + .byte "I",TK_PI ; PI +LBB_POKE + .byte "OKE",TK_POKE ; POKE +LBB_POS + .byte "OS(",TK_POS ; POS( +LBB_PRINT + .byte "RINT",TK_PRINT ; PRINT + .byte $00 +TAB_ASCR +LBB_READ + .byte "EAD",TK_READ ; READ +LBB_REM + .byte "EM",TK_REM ; REM +LBB_RESTORE + .byte "ESTORE",TK_RESTORE + ; RESTORE +LBB_RETIRQ + .byte "ETIRQ",TK_RETIRQ ; RETIRQ +LBB_RETNMI + .byte "ETNMI",TK_RETNMI ; RETNMI +LBB_RETURN + .byte "ETURN",TK_RETURN ; RETURN +LBB_RIGHTS + .byte "IGHT$(",TK_RIGHTS + ; RIGHT$( +LBB_RND + .byte "ND(",TK_RND ; RND( +LBB_RUN + .byte "UN",TK_RUN ; RUN + .byte $00 +TAB_ASCS +LBB_SADD + .byte "ADD(",TK_SADD ; SADD( +LBB_SAVE + .byte "AVE",TK_SAVE ; SAVE +LBB_SGN + .byte "GN(",TK_SGN ; SGN( +LBB_SIN + .byte "IN(",TK_SIN ; SIN( +LBB_SPC + .byte "PC(",TK_SPC ; SPC( +LBB_SQR + .byte "QR(",TK_SQR ; SQR( +LBB_STEP + .byte "TEP",TK_STEP ; STEP +LBB_STOP + .byte "TOP",TK_STOP ; STOP +LBB_STRS + .byte "TR$(",TK_STRS ; STR$( +LBB_SWAP + .byte "WAP",TK_SWAP ; SWAP + .byte $00 +TAB_ASCT +LBB_TAB + .byte "AB(",TK_TAB ; TAB( +LBB_TAN + .byte "AN(",TK_TAN ; TAN( +LBB_THEN + .byte "HEN",TK_THEN ; THEN +LBB_TO + .byte "O",TK_TO ; TO +LBB_TWOPI + .byte "WOPI",TK_TWOPI ; TWOPI + .byte $00 +TAB_ASCU +LBB_UCASES + .byte "CASE$(",TK_UCASES + ; UCASE$( +LBB_UNTIL + .byte "NTIL",TK_UNTIL ; UNTIL +LBB_USR + .byte "SR(",TK_USR ; USR( + .byte $00 +TAB_ASCV +LBB_VAL + .byte "AL(",TK_VAL ; VAL( +LBB_VPTR + .byte "ARPTR(",TK_VPTR ; VARPTR( + .byte $00 +TAB_ASCW +LBB_WAIT + .byte "AIT",TK_WAIT ; WAIT +LBB_WHILE + .byte "HILE",TK_WHILE ; WHILE +LBB_WIDTH + .byte "IDTH",TK_WIDTH ; WIDTH + .byte $00 +TAB_POWR + .byte TK_POWER,$00 ; ^ + +; new decode table for LIST +; Table is .. +; byte - keyword length, keyword first character +; word - pointer to rest of keyword from dictionary + +; note if length is 1 then the pointer is ignored + +LAB_KEYT + .byte 3,'E' + .word LBB_END ; END + .byte 3,'F' + .word LBB_FOR ; FOR + .byte 4,'N' + .word LBB_NEXT ; NEXT + .byte 4,'D' + .word LBB_DATA ; DATA + .byte 5,'I' + .word LBB_INPUT ; INPUT + .byte 3,'D' + .word LBB_DIM ; DIM + .byte 4,'R' + .word LBB_READ ; READ + .byte 3,'L' + .word LBB_LET ; LET + .byte 3,'D' + .word LBB_DEC ; DEC + .byte 4,'G' + .word LBB_GOTO ; GOTO + .byte 3,'R' + .word LBB_RUN ; RUN + .byte 2,'I' + .word LBB_IF ; IF + .byte 7,'R' + .word LBB_RESTORE ; RESTORE + .byte 5,'G' + .word LBB_GOSUB ; GOSUB + .byte 6,'R' + .word LBB_RETIRQ ; RETIRQ + .byte 6,'R' + .word LBB_RETNMI ; RETNMI + .byte 6,'R' + .word LBB_RETURN ; RETURN + .byte 3,'R' + .word LBB_REM ; REM + .byte 4,'S' + .word LBB_STOP ; STOP + .byte 2,'O' + .word LBB_ON ; ON + .byte 4,'N' + .word LBB_NULL ; NULL + .byte 3,'I' + .word LBB_INC ; INC + .byte 4,'W' + .word LBB_WAIT ; WAIT + .byte 4,'L' + .word LBB_LOAD ; LOAD + .byte 4,'S' + .word LBB_SAVE ; SAVE + .byte 3,'D' + .word LBB_DEF ; DEF + .byte 4,'P' + .word LBB_POKE ; POKE + .byte 4,'D' + .word LBB_DOKE ; DOKE + .byte 4,'C' + .word LBB_CALL ; CALL + .byte 2,'D' + .word LBB_DO ; DO + .byte 4,'L' + .word LBB_LOOP ; LOOP + .byte 5,'P' + .word LBB_PRINT ; PRINT + .byte 4,'C' + .word LBB_CONT ; CONT + .byte 4,'L' + .word LBB_LIST ; LIST + .byte 5,'C' + .word LBB_CLEAR ; CLEAR + .byte 3,'N' + .word LBB_NEW ; NEW + .byte 5,'W' + .word LBB_WIDTH ; WIDTH + .byte 3,'G' + .word LBB_GET ; GET + .byte 4,'S' + .word LBB_SWAP ; SWAP + .byte 6,'B' + .word LBB_BITSET ; BITSET + .byte 6,'B' + .word LBB_BITCLR ; BITCLR + .byte 3,'I' + .word LBB_IRQ ; IRQ + .byte 3,'N' + .word LBB_NMI ; NMI + +; secondary commands (can't start a statement) + + .byte 4,'T' + .word LBB_TAB ; TAB + .byte 4,'E' + .word LBB_ELSE ; ELSE + .byte 2,'T' + .word LBB_TO ; TO + .byte 2,'F' + .word LBB_FN ; FN + .byte 4,'S' + .word LBB_SPC ; SPC + .byte 4,'T' + .word LBB_THEN ; THEN + .byte 3,'N' + .word LBB_NOT ; NOT + .byte 4,'S' + .word LBB_STEP ; STEP + .byte 5,'U' + .word LBB_UNTIL ; UNTIL + .byte 5,'W' + .word LBB_WHILE ; WHILE + .byte 3,'O' + .word LBB_OFF ; OFF + +; opperators + + .byte 1,'+' + .word $0000 ; + + .byte 1,'-' + .word $0000 ; - + .byte 1,'*' + .word $0000 ; * + .byte 1,'/' + .word $0000 ; / + .byte 1,'^' + .word $0000 ; ^ + .byte 3,'A' + .word LBB_AND ; AND + .byte 3,'E' + .word LBB_EOR ; EOR + .byte 2,'O' + .word LBB_OR ; OR + .byte 2,'>' + .word LBB_RSHIFT ; >> + .byte 2,'<' + .word LBB_LSHIFT ; << + .byte 1,'>' + .word $0000 ; > + .byte 1,'=' + .word $0000 ; = + .byte 1,'<' + .word $0000 ; < + +; functions + + .byte 4,'S' ; + .word LBB_SGN ; SGN + .byte 4,'I' ; + .word LBB_INT ; INT + .byte 4,'A' ; + .word LBB_ABS ; ABS + .byte 4,'U' ; + .word LBB_USR ; USR + .byte 4,'F' ; + .word LBB_FRE ; FRE + .byte 4,'P' ; + .word LBB_POS ; POS + .byte 4,'S' ; + .word LBB_SQR ; SQR + .byte 4,'R' ; + .word LBB_RND ; RND + .byte 4,'L' ; + .word LBB_LOG ; LOG + .byte 4,'E' ; + .word LBB_EXP ; EXP + .byte 4,'C' ; + .word LBB_COS ; COS + .byte 4,'S' ; + .word LBB_SIN ; SIN + .byte 4,'T' ; + .word LBB_TAN ; TAN + .byte 4,'A' ; + .word LBB_ATN ; ATN + .byte 5,'P' ; + .word LBB_PEEK ; PEEK + .byte 5,'D' ; + .word LBB_DEEK ; DEEK + .byte 5,'S' ; + .word LBB_SADD ; SADD + .byte 4,'L' ; + .word LBB_LEN ; LEN + .byte 5,'S' ; + .word LBB_STRS ; STR$ + .byte 4,'V' ; + .word LBB_VAL ; VAL + .byte 4,'A' ; + .word LBB_ASC ; ASC + .byte 7,'U' ; + .word LBB_UCASES ; UCASE$ + .byte 7,'L' ; + .word LBB_LCASES ; LCASE$ + .byte 5,'C' ; + .word LBB_CHRS ; CHR$ + .byte 5,'H' ; + .word LBB_HEXS ; HEX$ + .byte 5,'B' ; + .word LBB_BINS ; BIN$ + .byte 7,'B' ; + .word LBB_BITTST ; BITTST + .byte 4,'M' ; + .word LBB_MAX ; MAX + .byte 4,'M' ; + .word LBB_MIN ; MIN + .byte 2,'P' ; + .word LBB_PI ; PI + .byte 5,'T' ; + .word LBB_TWOPI ; TWOPI + .byte 7,'V' ; + .word LBB_VPTR ; VARPTR + .byte 6,'L' ; + .word LBB_LEFTS ; LEFT$ + .byte 7,'R' ; + .word LBB_RIGHTS ; RIGHT$ + .byte 5,'M' ; + .word LBB_MIDS ; MID$ + +; BASIC messages, mostly error messages + +LAB_BAER + .word ERR_NF ;$00 NEXT without FOR + .word ERR_SN ;$02 syntax + .word ERR_RG ;$04 RETURN without GOSUB + .word ERR_OD ;$06 out of data + .word ERR_FC ;$08 function call + .word ERR_OV ;$0A overflow + .word ERR_OM ;$0C out of memory + .word ERR_US ;$0E undefined statement + .word ERR_BS ;$10 array bounds + .word ERR_DD ;$12 double dimension array + .word ERR_D0 ;$14 divide by 0 + .word ERR_ID ;$16 illegal direct + .word ERR_TM ;$18 type mismatch + .word ERR_LS ;$1A long string + .word ERR_ST ;$1C string too complex + .word ERR_CN ;$1E continue error + .word ERR_UF ;$20 undefined function + .word ERR_LD ;$22 LOOP without DO + +; I may implement these two errors to force definition of variables and +; dimensioning of arrays before use. + +; .word ERR_UV ;$24 undefined variable + +; the above error has been tested and works (see code and comments below LAB_1D8B) + +; .word ERR_UA ;$26 undimensioned array + +ERR_NF .byte "NEXT without FOR",$00 +ERR_SN .byte "Syntax",$00 +ERR_RG .byte "RETURN without GOSUB",$00 +ERR_OD .byte "Out of DATA",$00 +ERR_FC .byte "Function call",$00 +ERR_OV .byte "Overflow",$00 +ERR_OM .byte "Out of memory",$00 +ERR_US .byte "Undefined statement",$00 +ERR_BS .byte "Array bounds",$00 +ERR_DD .byte "Double dimension",$00 +ERR_D0 .byte "Divide by zero",$00 +ERR_ID .byte "Illegal direct",$00 +ERR_TM .byte "Type mismatch",$00 +ERR_LS .byte "String too long",$00 +ERR_ST .byte "String too complex",$00 +ERR_CN .byte "Can't continue",$00 +ERR_UF .byte "Undefined function",$00 +ERR_LD .byte "LOOP without DO",$00 + +;ERR_UV .byte "Undefined variable",$00 + +; the above error has been tested and works (see code and comments below LAB_1D8B) + +;ERR_UA .byte "Undimensioned array",$00 + +LAB_BMSG .byte $0D,$0A,"Break",$00 +LAB_EMSG .byte " Error",$00 +LAB_LMSG .byte " in line ",$00 +LAB_RMSG .byte $0D,$0A,"Ready",$0D,$0A,$00 + +LAB_IMSG .byte " Extra ignored",$0D,$0A,$00 +LAB_REDO .byte " Redo from start",$0D,$0A,$00 + +AA_end_basic diff --git a/eh_basic_kow.asm b/eh_basic_kow.asm new file mode 100644 index 0000000..382b368 --- /dev/null +++ b/eh_basic_kow.asm @@ -0,0 +1,8724 @@ + +; The code below was copied and adapted from Lee Davison’s +; code of EhBasic to be ran in Michal Kowalski's 6502 emulator. +; Original comments and credits follow: +; +; Enhanced BASIC to assemble under 6502 simulator, $ver 2.22 + +; $E7E1 $E7CF $E7C6 $E7D3 $E7D1 $E7D5 $E7CF $E81E $E825 + +; 2.00 new revision numbers start here +; 2.01 fixed LCASE$() and UCASE$() +; 2.02 new get value routine done +; 2.03 changed RND() to galoise method +; 2.04 fixed SPC() +; 2.05 new get value routine fixed +; 2.06 changed USR() code +; 2.07 fixed STR$() +; 2.08 changed INPUT and READ to remove need for $00 start to input buffer +; 2.09 fixed RND() +; 2.10 integrated missed changes from an earlier version +; 2.20 added ELSE to IF .. THEN and fixed IF .. GOTO to cause error +; 2.21 fixed IF .. THEN RETURN to not cause error +; 2.22 fixed RND() breaking the get byte routine + +; zero page use .. + +LAB_WARM = $00 ; BASIC warm start entry point +Wrmjpl = LAB_WARM+1; BASIC warm start vector jump low byte +Wrmjph = LAB_WARM+2; BASIC warm start vector jump high byte + +Usrjmp = $0A ; USR function JMP address +Usrjpl = Usrjmp+1 ; USR function JMP vector low byte +Usrjph = Usrjmp+2 ; USR function JMP vector high byte +Nullct = $0D ; nulls output after each line +TPos = $0E ; BASIC terminal position byte +TWidth = $0F ; BASIC terminal width byte +Iclim = $10 ; input column limit +Itempl = $11 ; temporary integer low byte +Itemph = Itempl+1 ; temporary integer high byte + +nums_1 = Itempl ; number to bin/hex string convert MSB +nums_2 = nums_1+1 ; number to bin/hex string convert +nums_3 = nums_1+2 ; number to bin/hex string convert LSB + +Srchc = $5B ; search character +Temp3 = Srchc ; temp byte used in number routines +Scnquo = $5C ; scan-between-quotes flag +Asrch = Scnquo ; alt search character + +XOAw_l = Srchc ; eXclusive OR, OR and AND word low byte +XOAw_h = Scnquo ; eXclusive OR, OR and AND word high byte + +Ibptr = $5D ; input buffer pointer +Dimcnt = Ibptr ; # of dimensions +Tindx = Ibptr ; token index + +Defdim = $5E ; default DIM flag +Dtypef = $5F ; data type flag, $FF=string, $00=numeric +Oquote = $60 ; open quote flag (b7) (Flag: DATA scan; LIST quote; memory) +Gclctd = $60 ; garbage collected flag +Sufnxf = $61 ; subscript/FNX flag, 1xxx xxx = FN(0xxx xxx) +Imode = $62 ; input mode flag, $00=INPUT, $80=READ + +Cflag = $63 ; comparison evaluation flag + +TabSiz = $64 ; TAB step size (was input flag) + +next_s = $65 ; next descriptor stack address + + ; these two bytes form a word pointer to the item + ; currently on top of the descriptor stack +last_sl = $66 ; last descriptor stack address low byte +last_sh = $67 ; last descriptor stack address high byte (always $00) + +des_sk = $68 ; descriptor stack start address (temp strings) + +; = $70 ; End of descriptor stack + +ut1_pl = $71 ; utility pointer 1 low byte +ut1_ph = ut1_pl+1 ; utility pointer 1 high byte +ut2_pl = $73 ; utility pointer 2 low byte +ut2_ph = ut2_pl+1 ; utility pointer 2 high byte + +Temp_2 = ut1_pl ; temp byte for block move + +FACt_1 = $75 ; FAC temp mantissa1 +FACt_2 = FACt_1+1 ; FAC temp mantissa2 +FACt_3 = FACt_2+1 ; FAC temp mantissa3 + +dims_l = FACt_2 ; array dimension size low byte +dims_h = FACt_3 ; array dimension size high byte + +TempB = $78 ; temp page 0 byte + +Smeml = $79 ; start of mem low byte (Start-of-Basic) +Smemh = Smeml+1 ; start of mem high byte (Start-of-Basic) +Svarl = $7B ; start of vars low byte (Start-of-Variables) +Svarh = Svarl+1 ; start of vars high byte (Start-of-Variables) +Sarryl = $7D ; var mem end low byte (Start-of-Arrays) +Sarryh = Sarryl+1 ; var mem end high byte (Start-of-Arrays) +Earryl = $7F ; array mem end low byte (End-of-Arrays) +Earryh = Earryl+1 ; array mem end high byte (End-of-Arrays) +Sstorl = $81 ; string storage low byte (String storage (moving down)) +Sstorh = Sstorl+1 ; string storage high byte (String storage (moving down)) +Sutill = $83 ; string utility ptr low byte +Sutilh = Sutill+1 ; string utility ptr high byte +Ememl = $85 ; end of mem low byte (Limit-of-memory) +Ememh = Ememl+1 ; end of mem high byte (Limit-of-memory) +Clinel = $87 ; current line low byte (Basic line number) +Clineh = Clinel+1 ; current line high byte (Basic line number) +Blinel = $89 ; break line low byte (Previous Basic line number) +Blineh = Blinel+1 ; break line high byte (Previous Basic line number) + +Cpntrl = $8B ; continue pointer low byte +Cpntrh = Cpntrl+1 ; continue pointer high byte + +Dlinel = $8D ; current DATA line low byte +Dlineh = Dlinel+1 ; current DATA line high byte + +Dptrl = $8F ; DATA pointer low byte +Dptrh = Dptrl+1 ; DATA pointer high byte + +Rdptrl = $91 ; read pointer low byte +Rdptrh = Rdptrl+1 ; read pointer high byte + +Varnm1 = $93 ; current var name 1st byte +Varnm2 = Varnm1+1 ; current var name 2nd byte + +Cvaral = $95 ; current var address low byte +Cvarah = Cvaral+1 ; current var address high byte + +Frnxtl = $97 ; var pointer for FOR/NEXT low byte +Frnxth = Frnxtl+1 ; var pointer for FOR/NEXT high byte + +Tidx1 = Frnxtl ; temp line index + +Lvarpl = Frnxtl ; let var pointer low byte +Lvarph = Frnxth ; let var pointer high byte + +prstk = $99 ; precedence stacked flag + +comp_f = $9B ; compare function flag, bits 0,1 and 2 used + ; bit 2 set if > + ; bit 1 set if = + ; bit 0 set if < + +func_l = $9C ; function pointer low byte +func_h = func_l+1 ; function pointer high byte + +garb_l = func_l ; garbage collection working pointer low byte +garb_h = func_h ; garbage collection working pointer high byte + +des_2l = $9E ; string descriptor_2 pointer low byte +des_2h = des_2l+1 ; string descriptor_2 pointer high byte + +g_step = $A0 ; garbage collect step size + +Fnxjmp = $A1 ; jump vector for functions +Fnxjpl = Fnxjmp+1 ; functions jump vector low byte +Fnxjph = Fnxjmp+2 ; functions jump vector high byte + +g_indx = Fnxjpl ; garbage collect temp index + +FAC2_r = $A3 ; FAC2 rounding byte + +Adatal = $A4 ; array data pointer low byte +Adatah = Adatal+1 ; array data pointer high byte + +Nbendl = Adatal ; new block end pointer low byte +Nbendh = Adatah ; new block end pointer high byte + +Obendl = $A6 ; old block end pointer low byte +Obendh = Obendl+1 ; old block end pointer high byte + +numexp = $A8 ; string to float number exponent count +expcnt = $A9 ; string to float exponent count + +numbit = numexp ; bit count for array element calculations + +numdpf = $AA ; string to float decimal point flag +expneg = $AB ; string to float eval exponent -ve flag + +Astrtl = numdpf ; array start pointer low byte +Astrth = expneg ; array start pointer high byte + +Histrl = numdpf ; highest string low byte +Histrh = expneg ; highest string high byte + +Baslnl = numdpf ; BASIC search line pointer low byte +Baslnh = expneg ; BASIC search line pointer high byte + +Fvar_l = numdpf ; find/found variable pointer low byte +Fvar_h = expneg ; find/found variable pointer high byte + +Ostrtl = numdpf ; old block start pointer low byte +Ostrth = expneg ; old block start pointer high byte + +Vrschl = numdpf ; variable search pointer low byte +Vrschh = expneg ; variable search pointer high byte + +FAC1_e = $AC ; FAC1 exponent +FAC1_1 = FAC1_e+1 ; FAC1 mantissa1 +FAC1_2 = FAC1_e+2 ; FAC1 mantissa2 +FAC1_3 = FAC1_e+3 ; FAC1 mantissa3 +FAC1_s = FAC1_e+4 ; FAC1 sign (b7) + +str_ln = FAC1_e ; string length +str_pl = FAC1_1 ; string pointer low byte +str_ph = FAC1_2 ; string pointer high byte + +des_pl = FAC1_2 ; string descriptor pointer low byte +des_ph = FAC1_3 ; string descriptor pointer high byte + +mids_l = FAC1_3 ; MID$ string temp length byte + +negnum = $B1 ; string to float eval -ve flag +numcon = $B1 ; series evaluation constant count + +FAC1_o = $B2 ; FAC1 overflow byte + +FAC2_e = $B3 ; FAC2 exponent +FAC2_1 = FAC2_e+1 ; FAC2 mantissa1 +FAC2_2 = FAC2_e+2 ; FAC2 mantissa2 +FAC2_3 = FAC2_e+3 ; FAC2 mantissa3 +FAC2_s = FAC2_e+4 ; FAC2 sign (b7) + +FAC_sc = $B8 ; FAC sign comparison, Acc#1 vs #2 +FAC1_r = $B9 ; FAC1 rounding byte + +ssptr_l = FAC_sc ; string start pointer low byte +ssptr_h = FAC1_r ; string start pointer high byte + +sdescr = FAC_sc ; string descriptor pointer + +csidx = $BA ; line crunch save index +Asptl = csidx ; array size/pointer low byte +Aspth = $BB ; array size/pointer high byte + +Btmpl = Asptl ; BASIC pointer temp low byte +Btmph = Aspth ; BASIC pointer temp low byte + +Cptrl = Asptl ; BASIC pointer temp low byte +Cptrh = Aspth ; BASIC pointer temp low byte + +Sendl = Asptl ; BASIC pointer temp low byte +Sendh = Aspth ; BASIC pointer temp low byte + +LAB_IGBY = $BC ; get next BASIC byte subroutine + +LAB_GBYT = $C2 ; get current BASIC byte subroutine +Bpntrl = $C3 ; BASIC execute (get byte) pointer low byte +Bpntrh = Bpntrl+1 ; BASIC execute (get byte) pointer high byte + +; = $D7 ; end of get BASIC char subroutine + +Rbyte4 = $D8 ; extra PRNG byte +Rbyte1 = Rbyte4+1 ; most significant PRNG byte +Rbyte2 = Rbyte4+2 ; middle PRNG byte +Rbyte3 = Rbyte4+3 ; least significant PRNG byte + +NmiBase = $DC ; NMI handler enabled/setup/triggered flags + ; bit function + ; === ======== + ; 7 interrupt enabled + ; 6 interrupt setup + ; 5 interrupt happened +; = $DD ; NMI handler addr low byte +; = $DE ; NMI handler addr high byte +IrqBase = $DF ; IRQ handler enabled/setup/triggered flags +; = $E0 ; IRQ handler addr low byte +; = $E1 ; IRQ handler addr high byte + +; = $DE ; unused +; = $DF ; unused +; = $E0 ; unused +; = $E1 ; unused +; = $E2 ; unused +; = $E3 ; unused +; = $E4 ; unused +; = $E5 ; unused +; = $E6 ; unused +; = $E7 ; unused +; = $E8 ; unused +; = $E9 ; unused +; = $EA ; unused +; = $EB ; unused +; = $EC ; unused +; = $ED ; unused +; = $EE ; unused + +Decss = $EF ; number to decimal string start +Decssp1 = Decss+1 ; number to decimal string start + +; = $FF ; decimal string end + +; token values needed for BASIC + +; primary command tokens (can start a statement) + +TK_END = $80 ; END token +TK_FOR = TK_END+1 ; FOR token +TK_NEXT = TK_FOR+1 ; NEXT token +TK_DATA = TK_NEXT+1 ; DATA token +TK_INPUT = TK_DATA+1 ; INPUT token +TK_DIM = TK_INPUT+1 ; DIM token +TK_READ = TK_DIM+1 ; READ token +TK_LET = TK_READ+1 ; LET token +TK_DEC = TK_LET+1 ; DEC token +TK_GOTO = TK_DEC+1 ; GOTO token +TK_RUN = TK_GOTO+1 ; RUN token +TK_IF = TK_RUN+1 ; IF token +TK_RESTORE = TK_IF+1 ; RESTORE token +TK_GOSUB = TK_RESTORE+1 ; GOSUB token +TK_RETIRQ = TK_GOSUB+1 ; RETIRQ token +TK_RETNMI = TK_RETIRQ+1 ; RETNMI token +TK_RETURN = TK_RETNMI+1 ; RETURN token +TK_REM = TK_RETURN+1 ; REM token +TK_STOP = TK_REM+1 ; STOP token +TK_ON = TK_STOP+1 ; ON token +TK_NULL = TK_ON+1 ; NULL token +TK_INC = TK_NULL+1 ; INC token +TK_WAIT = TK_INC+1 ; WAIT token +TK_LOAD = TK_WAIT+1 ; LOAD token +TK_SAVE = TK_LOAD+1 ; SAVE token +TK_DEF = TK_SAVE+1 ; DEF token +TK_POKE = TK_DEF+1 ; POKE token +TK_DOKE = TK_POKE+1 ; DOKE token +TK_CALL = TK_DOKE+1 ; CALL token +TK_DO = TK_CALL+1 ; DO token +TK_LOOP = TK_DO+1 ; LOOP token +TK_PRINT = TK_LOOP+1 ; PRINT token +TK_CONT = TK_PRINT+1 ; CONT token +TK_LIST = TK_CONT+1 ; LIST token +TK_CLEAR = TK_LIST+1 ; CLEAR token +TK_NEW = TK_CLEAR+1 ; NEW token +TK_WIDTH = TK_NEW+1 ; WIDTH token +TK_GET = TK_WIDTH+1 ; GET token +TK_SWAP = TK_GET+1 ; SWAP token +TK_BITSET = TK_SWAP+1 ; BITSET token +TK_BITCLR = TK_BITSET+1 ; BITCLR token +TK_IRQ = TK_BITCLR+1 ; IRQ token +TK_NMI = TK_IRQ+1 ; NMI token + +; secondary command tokens, can't start a statement + +TK_TAB = TK_NMI+1 ; TAB token +TK_ELSE = TK_TAB+1 ; ELSE token +TK_TO = TK_ELSE+1 ; TO token +TK_FN = TK_TO+1 ; FN token +TK_SPC = TK_FN+1 ; SPC token +TK_THEN = TK_SPC+1 ; THEN token +TK_NOT = TK_THEN+1 ; NOT token +TK_STEP = TK_NOT+1 ; STEP token +TK_UNTIL = TK_STEP+1 ; UNTIL token +TK_WHILE = TK_UNTIL+1 ; WHILE token +TK_OFF = TK_WHILE+1 ; OFF token + +; opperator tokens + +TK_PLUS = TK_OFF+1 ; + token +TK_MINUS = TK_PLUS+1 ; - token +TK_MUL = TK_MINUS+1 ; * token +TK_DIV = TK_MUL+1 ; / token +TK_POWER = TK_DIV+1 ; ^ token +TK_AND = TK_POWER+1 ; AND token +TK_EOR = TK_AND+1 ; EOR token +TK_OR = TK_EOR+1 ; OR token +TK_RSHIFT = TK_OR+1 ; RSHIFT token +TK_LSHIFT = TK_RSHIFT+1 ; LSHIFT token +TK_GT = TK_LSHIFT+1 ; > token +TK_EQUAL = TK_GT+1 ; = token +TK_LT = TK_EQUAL+1 ; < token + +; functions tokens + +TK_SGN = TK_LT+1 ; SGN token +TK_INT = TK_SGN+1 ; INT token +TK_ABS = TK_INT+1 ; ABS token +TK_USR = TK_ABS+1 ; USR token +TK_FRE = TK_USR+1 ; FRE token +TK_POS = TK_FRE+1 ; POS token +TK_SQR = TK_POS+1 ; SQR token +TK_RND = TK_SQR+1 ; RND token +TK_LOG = TK_RND+1 ; LOG token +TK_EXP = TK_LOG+1 ; EXP token +TK_COS = TK_EXP+1 ; COS token +TK_SIN = TK_COS+1 ; SIN token +TK_TAN = TK_SIN+1 ; TAN token +TK_ATN = TK_TAN+1 ; ATN token +TK_PEEK = TK_ATN+1 ; PEEK token +TK_DEEK = TK_PEEK+1 ; DEEK token +TK_SADD = TK_DEEK+1 ; SADD token +TK_LEN = TK_SADD+1 ; LEN token +TK_STRS = TK_LEN+1 ; STR$ token +TK_VAL = TK_STRS+1 ; VAL token +TK_ASC = TK_VAL+1 ; ASC token +TK_UCASES = TK_ASC+1 ; UCASE$ token +TK_LCASES = TK_UCASES+1 ; LCASE$ token +TK_CHRS = TK_LCASES+1 ; CHR$ token +TK_HEXS = TK_CHRS+1 ; HEX$ token +TK_BINS = TK_HEXS+1 ; BIN$ token +TK_BITTST = TK_BINS+1 ; BITTST token +TK_MAX = TK_BITTST+1 ; MAX token +TK_MIN = TK_MAX+1 ; MIN token +TK_PI = TK_MIN+1 ; PI token +TK_TWOPI = TK_PI+1 ; TWOPI token +TK_VPTR = TK_TWOPI+1 ; VARPTR token +TK_LEFTS = TK_VPTR+1 ; LEFT$ token +TK_RIGHTS = TK_LEFTS+1 ; RIGHT$ token +TK_MIDS = TK_RIGHTS+1 ; MID$ token + +; offsets from a base of X or Y + +PLUS_0 = $00 ; X or Y plus 0 +PLUS_1 = $01 ; X or Y plus 1 +PLUS_2 = $02 ; X or Y plus 2 +PLUS_3 = $03 ; X or Y plus 3 + +LAB_STAK = $0100 ; stack bottom, no offset + +LAB_SKFE = LAB_STAK+$FE + ; flushed stack address +LAB_SKFF = LAB_STAK+$FF + ; flushed stack address + +ccflag = $0200 ; BASIC CTRL-C flag, 00 = enabled, 01 = dis +ccbyte = ccflag+1 ; BASIC CTRL-C byte +ccnull = ccbyte+1 ; BASIC CTRL-C byte timeout + +VEC_CC = ccnull+1 ; ctrl c check vector + +VEC_IN = VEC_CC+2 ; input vector +VEC_OUT = VEC_IN+2 ; output vector +VEC_LD = VEC_OUT+2 ; load vector +VEC_SV = VEC_LD+2 ; save vector + +; Ibuffs can now be anywhere in RAM, ensure that the max length is < $80 + +IRQ_vec = VEC_SV+2 + +Ibuffs = IRQ_vec+$14 ; start of input buffer after IRQ/NMI code +Ibuffe = Ibuffs+$47 ; end of input buffer + + .ORG $FFC0 + +; I/O routines for Michal Kowalski's 6502 emulator. + +CHRIN + LDA $E004 ; Read from char IO address, non-blocking + BEQ ECHRIN ; if null, assume no character in buffer + CMP #'a' ; < 'a'? + BCC DCHRIN ; yes, done + CMP #'{' ; >= '{'? + BCS DCHRIN ; yes, done + AND #$5F ; no, convert to upper case +DCHRIN + SEC ; These is character waiting, set CARRY flag + RTS +ECHRIN + CLC ; no character in buffer, clear CARRY + RTS + +CHROUT + STA $E001 ; write to char IO address + AND #$FF ; set flags + RTS + + +Ram_base = $0300 ; start of user RAM (set as needed, should be page aligned) +Ram_top = $C000 ; end of user RAM+1 (set as needed, should be page aligned) + +; This start can be changed to suit your system + + *= $C000 + +; BASIC cold start entry point + +; new page 2 initialisation, copy block to ccflag on + +LAB_COLD + CLD + LDY #PG2_TABE-PG2_TABS-1 + ; byte count-1 +LAB_2D13 + LDA PG2_TABS,Y ; get byte + STA ccflag,Y ; store in page 2 + DEY ; decrement count + BPL LAB_2D13 ; loop if not done + + LDX #$FF ; set byte + STX Ibuffs + STX Clineh ; set current line high byte (set immediate mode) + TXS ; reset stack pointer + + LDA #$4C ; code for JMP + STA Fnxjmp ; save for jump vector for functions + +; copy block from LAB_2CEE to $00BC - $00D3 + + LDX #StrTab-LAB_2CEE ; set byte count +LAB_2D4E + LDA LAB_2CEE-1,X ; get byte from table + STA LAB_IGBY-1,X ; save byte in page zero + DEX ; decrement count + BNE LAB_2D4E ; loop if not all done + +; copy block from StrTab to $0000 - $0012 + +LAB_GMEM + LDX #EndTab-StrTab-1 ; set byte count-1 +TabLoop + LDA StrTab,X ; get byte from table + STA PLUS_0,X ; save byte in page zero + DEX ; decrement count + BPL TabLoop ; loop if not all done + +; set-up start values + + LDA #$00 ; clear A + STA NmiBase ; clear NMI handler enabled flag + STA IrqBase ; clear IRQ handler enabled flag + STA FAC1_o ; clear FAC1 overflow byte + STA last_sh ; clear descriptor stack top item pointer high byte + + LDA #$0E ; set default tab size + STA TabSiz ; save it + LDA #$03 ; set garbage collect step size for descriptor stack + STA g_step ; save it + LDX #des_sk ; descriptor stack start + STX next_s ; set descriptor stack pointer + JSR LAB_CRLF ; print CR/LF + LDA #LAB_MSZM ; point to memory size message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + JSR LAB_INLN ; print "? " and get BASIC input + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; get last byte back + + BNE LAB_2DAA ; branch if not null (user typed something) + + LDY #$00 ; else clear Y + ; character was null so get memory size the hard way + ; we get here with Y=0 and Itempl/h = Ram_base +LAB_2D93 + INC Itempl ; increment temporary integer low byte + BNE LAB_2D99 ; branch if no overflow + + INC Itemph ; increment temporary integer high byte + LDA Itemph ; get high byte + CMP #>Ram_top ; compare with top of RAM+1 + BEQ LAB_2DB6 ; branch if match (end of user RAM) + +LAB_2D99 + LDA #$55 ; set test byte + STA (Itempl),Y ; save via temporary integer + CMP (Itempl),Y ; compare via temporary integer + BNE LAB_2DB6 ; branch if fail + + ASL ; shift test byte left (now $AA) + STA (Itempl),Y ; save via temporary integer + CMP (Itempl),Y ; compare via temporary integer + BEQ LAB_2D93 ; if ok go do next byte + + BNE LAB_2DB6 ; branch if fail + +LAB_2DAA + JSR LAB_2887 ; get FAC1 from string + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_GMEM ; if too large go try again + + JSR LAB_F2FU ; save integer part of FAC1 in temporary integer + ; (no range check) + +LAB_2DB6 + LDA Itempl ; get temporary integer low byte + LDY Itemph ; get temporary integer high byte + CPY #Ram_top ; compare with top of RAM high byte +; BCC MEM_OK ; branch if < RAM top + +; BNE LAB_GMEM ; if too large go try again + ; else was = so compare low bytes +; CMP #Ram_base ; set start addr high byte + STY Smeml ; save start of mem low byte + STX Smemh ; save start of mem high byte + +; this line is only needed if Ram_base is not $xx00 + +; LDY #$00 ; clear Y + TYA ; clear A + STA (Smeml),Y ; clear first byte + INC Smeml ; increment start of mem low byte + +; these two lines are only needed if Ram_base is $xxFF + +; BNE LAB_2E05 ; branch if no rollover + +; INC Smemh ; increment start of mem high byte +LAB_2E05 + JSR LAB_CRLF ; print CR/LF + JSR LAB_1463 ; do "NEW" and "CLEAR" + LDA Ememl ; get end of mem low byte + SEC ; set carry for subtract + SBC Smeml ; subtract start of mem low byte + TAX ; copy to X + LDA Ememh ; get end of mem high byte + SBC Smemh ; subtract start of mem high byte + JSR LAB_295E ; print XA as unsigned integer (bytes free) + LDA #LAB_SMSG ; point to sign-on message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + LDA #LAB_1274 ; warm start vector high byte + STA Wrmjpl ; save warm start vector low byte + STY Wrmjph ; save warm start vector high byte + JMP (Wrmjpl) ; go do warm start + +; open up space in memory +; move (Ostrtl)-(Obendl) to new block ending at (Nbendl) + +; Nbendl,Nbendh - new block end address (A/Y) +; Obendl,Obendh - old block end address +; Ostrtl,Ostrth - old block start address + +; returns with .. + +; Nbendl,Nbendh - new block start address (high byte - $100) +; Obendl,Obendh - old block start address (high byte - $100) +; Ostrtl,Ostrth - old block start address (unchanged) + +LAB_11CF + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + STA Earryl ; save new array mem end low byte + STY Earryh ; save new array mem end high byte + +; open up space in memory +; move (Ostrtl)-(Obendl) to new block ending at (Nbendl) +; don't set array end + +LAB_11D6 + SEC ; set carry for subtract + LDA Obendl ; get block end low byte + SBC Ostrtl ; subtract block start low byte + TAY ; copy MOD(block length/$100) byte to Y + LDA Obendh ; get block end high byte + SBC Ostrth ; subtract block start high byte + TAX ; copy block length high byte to X + INX ; +1 to allow for count=0 exit + TYA ; copy block length low byte to A + BEQ LAB_120A ; branch if length low byte=0 + + ; block is (X-1)*256+Y bytes, do the Y bytes first + + SEC ; set carry for add + 1, two's complement + EOR #$FF ; invert low byte for subtract + ADC Obendl ; add block end low byte + + STA Obendl ; save corrected old block end low byte + BCS LAB_11F3 ; branch if no underflow + + DEC Obendh ; else decrement block end high byte + SEC ; set carry for add + 1, two's complement +LAB_11F3 + TYA ; get MOD(block length/$100) byte + EOR #$FF ; invert low byte for subtract + ADC Nbendl ; add destination end low byte + STA Nbendl ; save modified new block end low byte + BCS LAB_1203 ; branch if no underflow + + DEC Nbendh ; else decrement block end high byte + BCC LAB_1203 ; branch always + +LAB_11FF + LDA (Obendl),Y ; get byte from source + STA (Nbendl),Y ; copy byte to destination +LAB_1203 + DEY ; decrement index + BNE LAB_11FF ; loop until Y=0 + + ; now do Y=0 indexed byte + LDA (Obendl),Y ; get byte from source + STA (Nbendl),Y ; save byte to destination +LAB_120A + DEC Obendh ; decrement source pointer high byte + DEC Nbendh ; decrement destination pointer high byte + DEX ; decrement block count + BNE LAB_1203 ; loop until count = $0 + + RTS + +; check room on stack for A bytes +; stack too deep? do OM error + +LAB_1212 + STA TempB ; save result in temp byte + TSX ; copy stack + CPX TempB ; compare new "limit" with stack + BCC LAB_OMER ; if stack < limit do "Out of memory" error then warm start + + RTS + +; check available memory, "Out of memory" error if no room +; addr to check is in AY (low/high) + +LAB_121F + CPY Sstorh ; compare bottom of string mem high byte + BCC LAB_124B ; if less then exit (is ok) + + BNE LAB_1229 ; skip next test if greater (tested <) + + ; high byte was =, now do low byte + CMP Sstorl ; compare with bottom of string mem low byte + BCC LAB_124B ; if less then exit (is ok) + + ; addr is > string storage ptr (oops!) +LAB_1229 + PHA ; push addr low byte + LDX #$08 ; set index to save Adatal to expneg inclusive + TYA ; copy addr high byte (to push on stack) + + ; save misc numeric work area +LAB_122D + PHA ; push byte + LDA Adatal-1,X ; get byte from Adatal to expneg ( ,$00 not pushed) + DEX ; decrement index + BPL LAB_122D ; loop until all done + + JSR LAB_GARB ; garbage collection routine + + ; restore misc numeric work area + LDX #$00 ; clear the index to restore bytes +LAB_1238 + PLA ; pop byte + STA Adatal,X ; save byte to Adatal to expneg + INX ; increment index + CPX #$08 ; compare with end + 1 + BMI LAB_1238 ; loop if more to do + + PLA ; pop addr high byte + TAY ; copy back to Y + PLA ; pop addr low byte + CPY Sstorh ; compare bottom of string mem high byte + BCC LAB_124B ; if less then exit (is ok) + + BNE LAB_OMER ; if greater do "Out of memory" error then warm start + + ; high byte was =, now do low byte + CMP Sstorl ; compare with bottom of string mem low byte + BCS LAB_OMER ; if >= do "Out of memory" error then warm start + + ; ok exit, carry clear +LAB_124B + RTS + +; do "Out of memory" error then warm start + +LAB_OMER + LDX #$0C ; error code $0C ("Out of memory" error) + +; do error #X, then warm start + +LAB_XERR + JSR LAB_CRLF ; print CR/LF + + LDA LAB_BAER,X ; get error message pointer low byte + LDY LAB_BAER+1,X ; get error message pointer high byte + JSR LAB_18C3 ; print null terminated string from memory + + JSR LAB_1491 ; flush stack and clear continue flag + LDA #LAB_EMSG ; point to " Error" high addr +LAB_1269 + JSR LAB_18C3 ; print null terminated string from memory + LDY Clineh ; get current line high byte + INY ; increment it + BEQ LAB_1274 ; go do warm start (was immediate mode) + + ; else print line number + JSR LAB_2953 ; print " in line [LINE #]" + +; BASIC warm start entry point +; wait for Basic command + +LAB_1274 + ; clear ON IRQ/NMI bytes + LDA #$00 ; clear A + STA IrqBase ; clear enabled byte + STA NmiBase ; clear enabled byte + LDA #LAB_RMSG ; point to "Ready" message high byte + + JSR LAB_18C3 ; go do print string + CLC + +; wait for Basic command (no "Ready") + +LAB_127D + JSR LAB_1357 ; call for BASIC input +LAB_1280 + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_127D ; loop while null + +; got to interpret input line now .. + + LDX #$FF ; current line to null value + STX Clineh ; set current line high byte + BCC LAB_1295 ; branch if numeric character (handle new BASIC line) + + ; no line number .. immediate mode + JSR LAB_13A6 ; crunch keywords into Basic tokens + JMP LAB_15F6 ; go scan and interpret code + +; handle new BASIC line + +LAB_1295 + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_13A6 ; crunch keywords into Basic tokens + STY Ibptr ; save index pointer to end of crunched line + JSR LAB_SSLN ; search BASIC for temp integer line number + BCC LAB_12E6 ; branch if not found + + ; aroooogah! line # already exists! delete it + LDY #$01 ; set index to next line pointer high byte + LDA (Baslnl),Y ; get next line pointer high byte + STA ut1_ph ; save it + LDA Svarl ; get start of vars low byte + STA ut1_pl ; save it + LDA Baslnh ; get found line pointer high byte + STA ut2_ph ; save it + LDA Baslnl ; get found line pointer low byte + DEY ; decrement index + SBC (Baslnl),Y ; subtract next line pointer low byte + CLC ; clear carry for add + ADC Svarl ; add start of vars low byte + STA Svarl ; save new start of vars low byte + STA ut2_pl ; save destination pointer low byte + LDA Svarh ; get start of vars high byte + ADC #$FF ; -1 + carry + STA Svarh ; save start of vars high byte + SBC Baslnh ; subtract found line pointer high byte + TAX ; copy to block count + SEC ; set carry for subtract + LDA Baslnl ; get found line pointer low byte + SBC Svarl ; subtract start of vars low byte + TAY ; copy to bytes in first block count + BCS LAB_12D0 ; branch if overflow + + INX ; increment block count (correct for =0 loop exit) + DEC ut2_ph ; decrement destination high byte +LAB_12D0 + CLC ; clear carry for add + ADC ut1_pl ; add source pointer low byte + BCC LAB_12D8 ; branch if no overflow + + DEC ut1_ph ; else decrement source pointer high byte + CLC ; clear carry + + ; close up memory to delete old line +LAB_12D8 + LDA (ut1_pl),Y ; get byte from source + STA (ut2_pl),Y ; copy to destination + INY ; increment index + BNE LAB_12D8 ; while <> 0 do this block + + INC ut1_ph ; increment source pointer high byte + INC ut2_ph ; increment destination pointer high byte + DEX ; decrement block count + BNE LAB_12D8 ; loop until all done + + ; got new line in buffer and no existing same # +LAB_12E6 + LDA Ibuffs ; get byte from start of input buffer + BEQ LAB_1319 ; if null line just go flush stack/vars and exit + + ; got new line and it isn't empty line + LDA Ememl ; get end of mem low byte + LDY Ememh ; get end of mem high byte + STA Sstorl ; set bottom of string space low byte + STY Sstorh ; set bottom of string space high byte + LDA Svarl ; get start of vars low byte (end of BASIC) + STA Obendl ; save old block end low byte + LDY Svarh ; get start of vars high byte (end of BASIC) + STY Obendh ; save old block end high byte + ADC Ibptr ; add input buffer pointer (also buffer length) + BCC LAB_1301 ; branch if no overflow from add + + INY ; else increment high byte +LAB_1301 + STA Nbendl ; save new block end low byte (move to, low byte) + STY Nbendh ; save new block end high byte + JSR LAB_11CF ; open up space in memory + ; old start pointer Ostrtl,Ostrth set by the find line call + LDA Earryl ; get array mem end low byte + LDY Earryh ; get array mem end high byte + STA Svarl ; save start of vars low byte + STY Svarh ; save start of vars high byte + LDY Ibptr ; get input buffer pointer (also buffer length) + DEY ; adjust for loop type +LAB_1311 + LDA Ibuffs-4,Y ; get byte from crunched line + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + CPY #$03 ; compare with first byte-1 + BNE LAB_1311 ; continue while count <> 3 + + LDA Itemph ; get line # high byte + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + LDA Itempl ; get line # low byte + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + LDA #$FF ; set byte to allow chain rebuild. if you didn't set this + ; byte then a zero already here would stop the chain rebuild + ; as it would think it was the [EOT] marker. + STA (Baslnl),Y ; save it to program memory + +LAB_1319 + JSR LAB_1477 ; reset execution to start, clear vars and flush stack + LDX Smeml ; get start of mem low byte + LDA Smemh ; get start of mem high byte + LDY #$01 ; index to high byte of next line pointer +LAB_1325 + STX ut1_pl ; set line start pointer low byte + STA ut1_ph ; set line start pointer high byte + LDA (ut1_pl),Y ; get it + BEQ LAB_133E ; exit if end of program + +; rebuild chaining of Basic lines + + LDY #$04 ; point to first code byte of line + ; there is always 1 byte + [EOL] as null entries are deleted +LAB_1330 + INY ; next code byte + LDA (ut1_pl),Y ; get byte + BNE LAB_1330 ; loop if not [EOL] + + SEC ; set carry for add + 1 + TYA ; copy end index + ADC ut1_pl ; add to line start pointer low byte + TAX ; copy to X + LDY #$00 ; clear index, point to this line's next line pointer + STA (ut1_pl),Y ; set next line pointer low byte + TYA ; clear A + ADC ut1_ph ; add line start pointer high byte + carry + INY ; increment index to high byte + STA (ut1_pl),Y ; save next line pointer low byte + BCC LAB_1325 ; go do next line, branch always, carry clear + + +LAB_133E + JMP LAB_127D ; else we just wait for Basic command, no "Ready" + +; print "? " and get BASIC input + +LAB_INLN + JSR LAB_18E3 ; print "?" character + JSR LAB_18E0 ; print " " + BNE LAB_1357 ; call for BASIC input and return + +; receive line from keyboard + + ; $08 as delete key (BACKSPACE on standard keyboard) +LAB_134B + JSR LAB_PRNA ; go print the character + DEX ; decrement the buffer counter (delete) + .byte $2C ; make LDX into BIT abs + +; call for BASIC input (main entry point) + +LAB_1357 + LDX #$00 ; clear BASIC line buffer pointer +LAB_1359 + JSR V_INPT ; call scan input device + BCC LAB_1359 ; loop if no byte + + BEQ LAB_1359 ; loop until valid input (ignore NULLs) + + CMP #$07 ; compare with [BELL] + BEQ LAB_1378 ; branch if [BELL] + + CMP #$0D ; compare with [CR] + BEQ LAB_1384 ; do CR/LF exit if [CR] + + CPX #$00 ; compare pointer with $00 + BNE LAB_1374 ; branch if not empty + +; next two lines ignore any non print character and [SPACE] if input buffer empty + + CMP #$21 ; compare with [SP]+1 + BCC LAB_1359 ; if < ignore character + +LAB_1374 + CMP #$08 ; compare with [BACKSPACE] (delete last character) + BEQ LAB_134B ; go delete last character + +LAB_1378 + CPX #Ibuffe-Ibuffs ; compare character count with max + BCS LAB_138E ; skip store and do [BELL] if buffer full + + STA Ibuffs,X ; else store in buffer + INX ; increment pointer +LAB_137F + JSR LAB_PRNA ; go print the character + BNE LAB_1359 ; always loop for next character + +LAB_1384 + JMP LAB_1866 ; do CR/LF exit to BASIC + +; announce buffer full + +LAB_138E + LDA #$07 ; [BELL] character into A + BNE LAB_137F ; go print the [BELL] but ignore input character + ; branch always + +; crunch keywords into Basic tokens +; position independent buffer version .. +; faster, dictionary search version .... + +LAB_13A6 + LDY #$FF ; set save index (makes for easy math later) + + SEC ; set carry for subtract + LDA Bpntrl ; get basic execute pointer low byte + SBC #= go save byte then continue crunching + + CMP #'<' ; compare with "<" + BCS LAB_13CC ; if >= go crunch now + + CMP #'0' ; compare with "0" + BCS LAB_13EC ; if >= go save byte then continue crunching + + STA Scnquo ; save buffer byte as search character + CMP #$22 ; is it quote character? + BEQ LAB_1410 ; branch if so (copy quoted string) + + CMP #'*' ; compare with "*" + BCC LAB_13EC ; if < go save byte then continue crunching + + ; else crunch now +LAB_13CC + BIT Oquote ; get open quote/DATA token flag + BVS LAB_13EC ; branch if b6 of Oquote set (was DATA) + ; go save byte then continue crunching + + STX TempB ; save buffer read index + STY csidx ; copy buffer save index + LDY #TAB_1STC ; get keyword first character table high address + STY ut2_ph ; save pointer high byte + LDY #$00 ; clear table pointer + +LAB_13D0 + CMP (ut2_pl),Y ; compare with keyword first character table byte + BEQ LAB_13D1 ; go do word_table_chr if match + + BCC LAB_13EA ; if < keyword first character table byte go restore + ; Y and save to crunched + + INY ; else increment pointer + BNE LAB_13D0 ; and loop (branch always) + +; have matched first character of some keyword + +LAB_13D1 + TYA ; copy matching index + ASL ; *2 (bytes per pointer) + TAX ; copy to new index + LDA TAB_CHRT,X ; get keyword table pointer low byte + STA ut2_pl ; save pointer low byte + LDA TAB_CHRT+1,X ; get keyword table pointer high byte + STA ut2_ph ; save pointer high byte + + LDY #$FF ; clear table pointer (make -1 for start) + + LDX TempB ; restore buffer read index + +LAB_13D6 + INY ; next table byte + LDA (ut2_pl),Y ; get byte from table +LAB_13D8 + BMI LAB_13EA ; all bytes matched so go save token + + INX ; next buffer byte + CMP Ibuffs,X ; compare with byte from input buffer + BEQ LAB_13D6 ; go compare next if match + + BNE LAB_1417 ; branch if >< (not found keyword) + +LAB_13EA + LDY csidx ; restore save index + + ; save crunched to output +LAB_13EC + INX ; increment buffer index (to next input byte) + INY ; increment save index (to next output byte) + STA Ibuffs,Y ; save byte to output + CMP #$00 ; set the flags, set carry + BEQ LAB_142A ; do exit if was null [EOL] + + ; A holds token or byte here + SBC #':' ; subtract ":" (carry set by CMP #00) + BEQ LAB_13FF ; branch if it was ":" (is now $00) + + ; A now holds token-$3A + CMP #TK_DATA-$3A ; compare with DATA token - $3A + BNE LAB_1401 ; branch if not DATA + + ; token was : or DATA +LAB_13FF + STA Oquote ; save token-$3A (clear for ":", TK_DATA-$3A for DATA) +LAB_1401 + EOR #TK_REM-$3A ; effectively subtract REM token offset + BNE LAB_13AC ; If wasn't REM then go crunch rest of line + + STA Asrch ; else was REM so set search for [EOL] + + ; loop for REM, "..." etc. +LAB_1408 + LDA Ibuffs,X ; get byte from input buffer + BEQ LAB_13EC ; branch if null [EOL] + + CMP Asrch ; compare with stored character + BEQ LAB_13EC ; branch if match (end quote) + + ; entry for copy string in quotes, don't crunch +LAB_1410 + INY ; increment buffer save index + STA Ibuffs,Y ; save byte to output + INX ; increment buffer read index + BNE LAB_1408 ; loop while <> 0 (should never be 0!) + + ; not found keyword this go +LAB_1417 + LDX TempB ; compare has failed, restore buffer index (start byte!) + + ; now find the end of this word in the table +LAB_141B + LDA (ut2_pl),Y ; get table byte + PHP ; save status + INY ; increment table index + PLP ; restore byte status + BPL LAB_141B ; if not end of keyword go do next + + LDA (ut2_pl),Y ; get byte from keyword table + BNE LAB_13D8 ; go test next word if not zero byte (end of table) + + ; reached end of table with no match + LDA Ibuffs,X ; restore byte from input buffer + BPL LAB_13EA ; branch always (all bytes in buffer are $00-$7F) + ; go save byte in output and continue crunching + + ; reached [EOL] +LAB_142A + INY ; increment pointer + INY ; increment pointer (makes it next line pointer high byte) + STA Ibuffs,Y ; save [EOL] (marks [EOT] in immediate mode) + INY ; adjust for line copy + INY ; adjust for line copy + INY ; adjust for line copy + DEC Bpntrl ; allow for increment (change if buffer starts at $xxFF) + RTS + +; search Basic for temp integer line number from start of mem + +LAB_SSLN + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search Basic for temp integer line number from AX +; returns carry set if found +; returns Baslnl/Baslnh pointer to found or next higher (not found) line + +; old 541 new 507 + +LAB_SHLN + LDY #$01 ; set index + STA Baslnl ; save low byte as current + STX Baslnh ; save high byte as current + LDA (Baslnl),Y ; get pointer high byte from addr + BEQ LAB_145F ; pointer was zero so we're done, do 'not found' exit + + LDY #$03 ; set index to line # high byte + LDA (Baslnl),Y ; get line # high byte + DEY ; decrement index (point to low byte) + CMP Itemph ; compare with temporary integer high byte + BNE LAB_1455 ; if <> skip low byte check + + LDA (Baslnl),Y ; get line # low byte + CMP Itempl ; compare with temporary integer low byte +LAB_1455 + BCS LAB_145E ; else if temp < this line, exit (passed line#) + +LAB_1456 + DEY ; decrement index to next line ptr high byte + LDA (Baslnl),Y ; get next line pointer high byte + TAX ; copy to X + DEY ; decrement index to next line ptr low byte + LDA (Baslnl),Y ; get next line pointer low byte + BCC LAB_SHLN ; go search for line # in temp (Itempl/Itemph) from AX + ; (carry always clear) + +LAB_145E + BEQ LAB_1460 ; exit if temp = found line #, carry is set + +LAB_145F + CLC ; clear found flag +LAB_1460 + RTS + +; perform NEW + +LAB_NEW + BNE LAB_1460 ; exit if not end of statement (to do syntax error) + +LAB_1463 + LDA #$00 ; clear A + TAY ; clear Y + STA (Smeml),Y ; clear first line, next line pointer, low byte + INY ; increment index + STA (Smeml),Y ; clear first line, next line pointer, high byte + CLC ; clear carry + LDA Smeml ; get start of mem low byte + ADC #$02 ; calculate end of BASIC low byte + STA Svarl ; save start of vars low byte + LDA Smemh ; get start of mem high byte + ADC #$00 ; add any carry + STA Svarh ; save start of vars high byte + +; reset execution to start, clear vars and flush stack + +LAB_1477 + CLC ; clear carry + LDA Smeml ; get start of mem low byte + ADC #$FF ; -1 + STA Bpntrl ; save BASIC execute pointer low byte + LDA Smemh ; get start of mem high byte + ADC #$FF ; -1+carry + STA Bpntrh ; save BASIC execute pointer high byte + +; "CLEAR" command gets here + +LAB_147A + LDA Ememl ; get end of mem low byte + LDY Ememh ; get end of mem high byte + STA Sstorl ; set bottom of string space low byte + STY Sstorh ; set bottom of string space high byte + LDA Svarl ; get start of vars low byte + LDY Svarh ; get start of vars high byte + STA Sarryl ; save var mem end low byte + STY Sarryh ; save var mem end high byte + STA Earryl ; save array mem end low byte + STY Earryh ; save array mem end high byte + JSR LAB_161A ; perform RESTORE command + +; flush stack and clear continue flag + +LAB_1491 + LDX #des_sk ; set descriptor stack pointer + STX next_s ; save descriptor stack pointer + PLA ; pull return address low byte + TAX ; copy return address low byte + PLA ; pull return address high byte + STX LAB_SKFE ; save to cleared stack + STA LAB_SKFF ; save to cleared stack + LDX #$FD ; new stack pointer + TXS ; reset stack + LDA #$00 ; clear byte + STA Cpntrh ; clear continue pointer high byte + STA Sufnxf ; clear subscript/FNX flag +LAB_14A6 + RTS + +; perform CLEAR + +LAB_CLEAR + BEQ LAB_147A ; if no following token go do "CLEAR" + + ; else there was a following token (go do syntax error) + RTS + +; perform LIST [n][-m] +; bigger, faster version (a _lot_ faster) + +LAB_LIST + BCC LAB_14BD ; branch if next character numeric (LIST n..) + + BEQ LAB_14BD ; branch if next character [NULL] (LIST) + + CMP #TK_MINUS ; compare with token for - + BNE LAB_14A6 ; exit if not - (LIST -m) + + ; LIST [[n][-m]] + ; this bit sets the n , if present, as the start and end +LAB_14BD + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SSLN ; search BASIC for temp integer line number + ; (pointer in Baslnl/Baslnh) + JSR LAB_GBYT ; scan memory + BEQ LAB_14D4 ; branch if no more characters + + ; this bit checks the - is present + CMP #TK_MINUS ; compare with token for - + BNE LAB_1460 ; return if not "-" (will be Syntax error) + + ; LIST [n]-m + ; the - was there so set m as the end value + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GFPN ; get fixed-point number into temp integer + BNE LAB_1460 ; exit if not ok + +LAB_14D4 + LDA Itempl ; get temporary integer low byte + ORA Itemph ; OR temporary integer high byte + BNE LAB_14E2 ; branch if start set + + LDA #$FF ; set for -1 + STA Itempl ; set temporary integer low byte + STA Itemph ; set temporary integer high byte +LAB_14E2 + LDY #$01 ; set index for line + STY Oquote ; clear open quote flag + JSR LAB_CRLF ; print CR/LF + LDA (Baslnl),Y ; get next line pointer high byte + ; pointer initially set by search at LAB_14BD + BEQ LAB_152B ; if null all done so exit + JSR LAB_1629 ; do CRTL-C check vector + + INY ; increment index for line + LDA (Baslnl),Y ; get line # low byte + TAX ; copy to X + INY ; increment index + LDA (Baslnl),Y ; get line # high byte + CMP Itemph ; compare with temporary integer high byte + BNE LAB_14FF ; branch if no high byte match + + CPX Itempl ; compare with temporary integer low byte + BEQ LAB_1501 ; branch if = last line to do (< will pass next branch) + +LAB_14FF ; else .. + BCS LAB_152B ; if greater all done so exit + +LAB_1501 + STY Tidx1 ; save index for line + JSR LAB_295E ; print XA as unsigned integer + LDA #$20 ; space is the next character +LAB_1508 + LDY Tidx1 ; get index for line + AND #$7F ; mask top out bit of character +LAB_150C + JSR LAB_PRNA ; go print the character + CMP #$22 ; was it " character + BNE LAB_1519 ; branch if not + + ; we are either entering or leaving a pair of quotes + LDA Oquote ; get open quote flag + EOR #$FF ; toggle it + STA Oquote ; save it back +LAB_1519 + INY ; increment index + LDA (Baslnl),Y ; get next byte + BNE LAB_152E ; branch if not [EOL] (go print character) + TAY ; else clear index + LDA (Baslnl),Y ; get next line pointer low byte + TAX ; copy to X + INY ; increment index + LDA (Baslnl),Y ; get next line pointer high byte + STX Baslnl ; set pointer to line low byte + STA Baslnh ; set pointer to line high byte + BNE LAB_14E2 ; go do next line if not [EOT] + ; else .. +LAB_152B + RTS + +LAB_152E + BPL LAB_150C ; just go print it if not token byte + + ; else was token byte so uncrunch it (maybe) + BIT Oquote ; test the open quote flag + BMI LAB_150C ; just go print character if open quote set + + LDX #>LAB_KEYT ; get table address high byte + ASL ; *2 + ASL ; *4 + BCC LAB_152F ; branch if no carry + + INX ; else increment high byte + CLC ; clear carry for add +LAB_152F + ADC #LAB_159F ; set return address high byte + STA ut1_pl ; save return address low byte + STY ut1_ph ; save return address high byte + JMP LAB_1B66 ; round FAC1 and put on stack (returns to next instruction) + +LAB_159F + LDA #LAB_259C ; set 1 pointer high addr + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + JSR LAB_GBYT ; scan memory + CMP #TK_STEP ; compare with STEP token + BNE LAB_15B3 ; jump if not "STEP" + + ;.was step so .. + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch +LAB_15B3 + JSR LAB_27CA ; return A=FF,C=1/-ve A=01,C=0/+ve + STA FAC1_s ; set FAC1 sign (b7) + ; this is +1 for +ve step and -1 for -ve step, in NEXT we + ; compare the FOR value and the TO value and return +1 if + ; FOR > TO, 0 if FOR = TO and -1 if FOR < TO. the value + ; here (+/-1) is then compared to that result and if they + ; are the same (+ve and FOR > TO or -ve and FOR < TO) then + ; the loop is done + JSR LAB_1B5B ; push sign, round FAC1 and put on stack + LDA Frnxth ; get var pointer for FOR/NEXT high byte + PHA ; push on stack + LDA Frnxtl ; get var pointer for FOR/NEXT low byte + PHA ; push on stack + LDA #TK_FOR ; get FOR token + PHA ; push on stack + +; interpreter inner loop + +LAB_15C2 + JSR LAB_1629 ; do CRTL-C check vector + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + + LDX Clineh ; continue line is $FFxx for immediate mode + ; ($00xx for RUN from immediate mode) + INX ; increment it (now $00 if immediate mode) + BEQ LAB_15D1 ; branch if null (immediate mode) + + STA Cpntrl ; save continue pointer low byte + STY Cpntrh ; save continue pointer high byte +LAB_15D1 + LDY #$00 ; clear index + LDA (Bpntrl),Y ; get next byte + BEQ LAB_15DC ; branch if null [EOL] + + CMP #':' ; compare with ":" + BEQ LAB_15F6 ; branch if = (statement separator) + +LAB_15D9 + JMP LAB_SNER ; else syntax error then warm start + + ; have reached [EOL] +LAB_15DC + LDY #$02 ; set index + LDA (Bpntrl),Y ; get next line pointer high byte + CLC ; clear carry for no "BREAK" message + BEQ LAB_1651 ; if null go to immediate mode (was immediate or [EOT] + ; marker) + + INY ; increment index + LDA (Bpntrl),Y ; get line # low byte + STA Clinel ; save current line low byte + INY ; increment index + LDA (Bpntrl),Y ; get line # high byte + STA Clineh ; save current line high byte + TYA ; A now = 4 + ADC Bpntrl ; add BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + BCC LAB_15F6 ; branch if no overflow + + INC Bpntrh ; else increment BASIC execute pointer high byte +LAB_15F6 + JSR LAB_IGBY ; increment and scan memory + +LAB_15F9 + JSR LAB_15FF ; go interpret BASIC code from (Bpntrl) + +LAB_15FC + JMP LAB_15C2 ; loop + +; interpret BASIC code from (Bpntrl) + +LAB_15FF + BEQ LAB_1628 ; exit if zero [EOL] + +LAB_1602 + ASL ; *2 bytes per vector and normalise token + BCS LAB_1609 ; branch if was token + + JMP LAB_LET ; else go do implied LET + +LAB_1609 + CMP #[TK_TAB-$80]*2 ; compare normalised token * 2 with TAB + BCS LAB_15D9 ; branch if A>=TAB (do syntax error then warm start) + ; only tokens before TAB can start a line + TAY ; copy to index + LDA LAB_CTBL+1,Y ; get vector high byte + PHA ; onto stack + LDA LAB_CTBL,Y ; get vector low byte + PHA ; onto stack + JMP LAB_IGBY ; jump to increment and scan memory + ; then "return" to vector + +; CTRL-C check jump. this is called as a subroutine but exits back via a jump if a +; key press is detected. + +LAB_1629 + JMP (VEC_CC) ; ctrl c check vector + +; if there was a key press it gets back here .. + +LAB_1636 + CMP #$03 ; compare with CTRL-C + +; perform STOP + +LAB_STOP + BCS LAB_163B ; branch if token follows STOP + ; else just END +; END + +LAB_END + CLC ; clear the carry, indicate a normal program end +LAB_163B + BNE LAB_167A ; if wasn't CTRL-C or there is a following byte return + + LDA Bpntrh ; get the BASIC execute pointer high byte + EOR #>Ibuffs ; compare with buffer address high byte (Cb unchanged) + BEQ LAB_164F ; branch if the BASIC pointer is in the input buffer + ; (can't continue in immediate mode) + + ; else .. + EOR #>Ibuffs ; correct the bits + LDY Bpntrl ; get BASIC execute pointer low byte + STY Cpntrl ; save continue pointer low byte + STA Cpntrh ; save continue pointer high byte +LAB_1647 + LDA Clinel ; get current line low byte + LDY Clineh ; get current line high byte + STA Blinel ; save break line low byte + STY Blineh ; save break line high byte +LAB_164F + PLA ; pull return address low + PLA ; pull return address high +LAB_1651 + BCC LAB_165E ; if was program end just do warm start + + ; else .. + LDA #LAB_BMSG ; point to "Break" high byte + JMP LAB_1269 ; print "Break" and do warm start + +LAB_165E + JMP LAB_1274 ; go do warm start + +; perform RESTORE + +LAB_RESTORE + BNE LAB_RESTOREn ; branch if next character not null (RESTORE n) + +LAB_161A + SEC ; set carry for subtract + LDA Smeml ; get start of mem low byte + SBC #$01 ; -1 + LDY Smemh ; get start of mem high byte + BCS LAB_1624 ; branch if no underflow + +LAB_uflow + DEY ; else decrement high byte +LAB_1624 + STA Dptrl ; save DATA pointer low byte + STY Dptrh ; save DATA pointer high byte +LAB_1628 + RTS + + ; is RESTORE n +LAB_RESTOREn + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SNBL ; scan for next BASIC line + LDA Clineh ; get current line high byte + CMP Itemph ; compare with temporary integer high byte + BCS LAB_reset_search ; branch if >= (start search from beginning) + + TYA ; else copy line index to A + SEC ; set carry (+1) + ADC Bpntrl ; add BASIC execute pointer low byte + LDX Bpntrh ; get BASIC execute pointer high byte + BCC LAB_go_search ; branch if no overflow to high byte + + INX ; increment high byte + BCS LAB_go_search ; branch always (can never be carry clear) + +; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml) + +LAB_reset_search + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search for line # in temp (Itempl/Itemph) from (AX) + +LAB_go_search + + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCS LAB_line_found ; if carry set go set pointer + + JMP LAB_16F7 ; else go do "Undefined statement" error + +LAB_line_found + ; carry already set for subtract + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 + LDY Baslnh ; get pointer high byte + BCS LAB_1624 ; branch if no underflow (save DATA pointer and return) + + BCC LAB_uflow ; else decrement high byte then save DATA pointer and + ; return (branch always) + +; perform NULL + +LAB_NULL + JSR LAB_GTBY ; get byte parameter + STX Nullct ; save new NULL count +LAB_167A + RTS + +; perform CONT + +LAB_CONT + BNE LAB_167A ; if following byte exit to do syntax error + + LDY Cpntrh ; get continue pointer high byte + BNE LAB_166C ; go do continue if we can + + LDX #$1E ; error code $1E ("Can't continue" error) + JMP LAB_XERR ; do error #X, then warm start + + ; we can continue so .. +LAB_166C + LDA #TK_ON ; set token for ON + JSR LAB_IRQ ; set IRQ flags + LDA #TK_ON ; set token for ON + JSR LAB_NMI ; set NMI flags + + STY Bpntrh ; save BASIC execute pointer high byte + LDA Cpntrl ; get continue pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA Blinel ; get break line low byte + LDY Blineh ; get break line high byte + STA Clinel ; set current line low byte + STY Clineh ; set current line high byte + RTS + +; perform RUN + +LAB_RUN + BNE LAB_1696 ; branch if RUN n + JMP LAB_1477 ; reset execution to start, clear variables, flush stack and + ; return + +; does RUN n + +LAB_1696 + JSR LAB_147A ; go do "CLEAR" + BEQ LAB_16B0 ; get n and do GOTO n (branch always as CLEAR sets Z=1) + +; perform DO + +LAB_DO + LDA #$05 ; need 5 bytes for DO + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_DO ; token for DO + PHA ; push on stack + JSR LAB_GBYT ; scan memory + JMP LAB_15C2 ; go do interpreter inner loop + +; perform GOSUB + +LAB_GOSUB + LDA #$05 ; need 5 bytes for GOSUB + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_GOSUB ; token for GOSUB + PHA ; push on stack +LAB_16B0 + JSR LAB_GBYT ; scan memory + JSR LAB_GOTO ; perform GOTO n + JMP LAB_15C2 ; go do interpreter inner loop + ; (can't RTS, we used the stack!) + +; perform GOTO + +LAB_GOTO + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SNBL ; scan for next BASIC line + LDA Clineh ; get current line high byte + CMP Itemph ; compare with temporary integer high byte + BCS LAB_16D0 ; branch if >= (start search from beginning) + + TYA ; else copy line index to A + SEC ; set carry (+1) + ADC Bpntrl ; add BASIC execute pointer low byte + LDX Bpntrh ; get BASIC execute pointer high byte + BCC LAB_16D4 ; branch if no overflow to high byte + + INX ; increment high byte + BCS LAB_16D4 ; branch always (can never be carry) + +; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml) + +LAB_16D0 + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search for line # in temp (Itempl/Itemph) from (AX) + +LAB_16D4 + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCC LAB_16F7 ; if carry clear go do "Undefined statement" error + ; (unspecified statement) + + ; carry already set for subtract + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 + STA Bpntrl ; save BASIC execute pointer low byte + LDA Baslnh ; get pointer high byte + SBC #$00 ; subtract carry + STA Bpntrh ; save BASIC execute pointer high byte +LAB_16E5 + RTS + +LAB_DONOK + LDX #$22 ; error code $22 ("LOOP without DO" error) + JMP LAB_XERR ; do error #X, then warm start + +; perform LOOP + +LAB_LOOP + TAY ; save following token + TSX ; copy stack pointer + LDA LAB_STAK+3,X ; get token byte from stack + CMP #TK_DO ; compare with DO token + BNE LAB_DONOK ; branch if no matching DO + + INX ; dump calling routine return address + INX ; dump calling routine return address + TXS ; correct stack + TYA ; get saved following token back + BEQ LoopAlways ; if no following token loop forever + ; (stack pointer in X) + + CMP #':' ; could be ':' + BEQ LoopAlways ; if :... loop forever + + SBC #TK_UNTIL ; subtract token for UNTIL, we know carry is set here + TAX ; copy to X (if it was UNTIL then Y will be correct) + BEQ DoRest ; branch if was UNTIL + + DEX ; decrement result + BNE LAB_16FC ; if not WHILE go do syntax error and warm start + ; only if the token was WHILE will this fail + + DEX ; set invert result byte +DoRest + STX Frnxth ; save invert result byte + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVEX ; evaluate expression + LDA FAC1_e ; get FAC1 exponent + BEQ DoCmp ; if =0 go do straight compare + + LDA #$FF ; else set all bits +DoCmp + TSX ; copy stack pointer + EOR Frnxth ; EOR with invert byte + BNE LoopDone ; if <> 0 clear stack and back to interpreter loop + + ; loop condition wasn't met so do it again +LoopAlways + LDA LAB_STAK+2,X ; get current line low byte + STA Clinel ; save current line low byte + LDA LAB_STAK+3,X ; get current line high byte + STA Clineh ; save current line high byte + LDA LAB_STAK+4,X ; get BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA LAB_STAK+5,X ; get BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + JMP LAB_15C2 ; go do interpreter inner loop + + ; clear stack and back to interpreter loop +LoopDone + INX ; dump DO token + INX ; dump current line low byte + INX ; dump current line high byte + INX ; dump BASIC execute pointer low byte + INX ; dump BASIC execute pointer high byte + TXS ; correct stack + JMP LAB_DATA ; go perform DATA (find : or [EOL]) + +; do the return without gosub error + +LAB_16F4 + LDX #$04 ; error code $04 ("RETURN without GOSUB" error) + .byte $2C ; makes next line BIT LAB_0EA2 + +LAB_16F7 ; do undefined statement error + LDX #$0E ; error code $0E ("Undefined statement" error) + JMP LAB_XERR ; do error #X, then warm start + +; perform RETURN + +LAB_RETURN + BNE LAB_16E5 ; exit if following token (to allow syntax error) + +LAB_16E8 + PLA ; dump calling routine return address + PLA ; dump calling routine return address + PLA ; pull token + CMP #TK_GOSUB ; compare with GOSUB token + BNE LAB_16F4 ; branch if no matching GOSUB + +LAB_16FF + PLA ; pull current line low byte + STA Clinel ; save current line low byte + PLA ; pull current line high byte + STA Clineh ; save current line high byte + PLA ; pull BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + PLA ; pull BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte + + ; now do the DATA statement as we could be returning into + ; the middle of an ON GOSUB n,m,p,q line + ; (the return address used by the DATA statement is the one + ; pushed before the GOSUB was executed!) + +; perform DATA + +LAB_DATA + JSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL]) + + ; set BASIC execute pointer +LAB_170F + TYA ; copy index to A + CLC ; clear carry for add + ADC Bpntrl ; add BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + BCC LAB_1719 ; skip next if no carry + + INC Bpntrh ; else increment BASIC execute pointer high byte +LAB_1719 + RTS + +LAB_16FC + JMP LAB_SNER ; do syntax error then warm start + +; scan for next BASIC statement ([:] or [EOL]) +; returns Y as index to [:] or [EOL] + +LAB_SNBS + LDX #':' ; set look for character = ":" + .byte $2C ; makes next line BIT $00A2 + +; scan for next BASIC line +; returns Y as index to [EOL] + +LAB_SNBL + LDX #$00 ; set alt search character = [EOL] + LDY #$00 ; set search character = [EOL] + STY Asrch ; store search character +LAB_1725 + TXA ; get alt search character + EOR Asrch ; toggle search character, effectively swap with $00 + STA Asrch ; save swapped search character +LAB_172D + LDA (Bpntrl),Y ; get next byte + BEQ LAB_1719 ; exit if null [EOL] + + CMP Asrch ; compare with search character + BEQ LAB_1719 ; exit if found + + INY ; increment index + CMP #$22 ; compare current character with open quote + BNE LAB_172D ; if not open quote go get next character + + BEQ LAB_1725 ; if found go swap search character for alt search character + +; perform IF + +LAB_IF + JSR LAB_EVEX ; evaluate the expression + JSR LAB_GBYT ; scan memory + CMP #TK_THEN ; compare with THEN token + BEQ LAB_174B ; if it was THEN go do IF + + ; wasn't IF .. THEN so must be IF .. GOTO + CMP #TK_GOTO ; compare with GOTO token + BNE LAB_16FC ; if it wasn't GOTO go do syntax error + + LDX Bpntrl ; save the basic pointer low byte + LDY Bpntrh ; save the basic pointer high byte + JSR LAB_IGBY ; increment and scan memory + BCS LAB_16FC ; if not numeric go do syntax error + + STX Bpntrl ; restore the basic pointer low byte + STY Bpntrh ; restore the basic pointer high byte +LAB_174B + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_174E ; if the result was zero go look for an ELSE + + JSR LAB_IGBY ; else increment and scan memory + BCS LAB_174D ; if not numeric go do var or keyword + +LAB_174C + JMP LAB_GOTO ; else was numeric so do GOTO n + + ; is var or keyword +LAB_174D + CMP #TK_RETURN ; compare the byte with the token for RETURN + BNE LAB_174G ; if it wasn't RETURN go interpret BASIC code from (Bpntrl) + ; and return to this code to process any following code + + JMP LAB_1602 ; else it was RETURN so interpret BASIC code from (Bpntrl) + ; but don't return here + +LAB_174G + JSR LAB_15FF ; interpret BASIC code from (Bpntrl) + +; the IF was executed and there may be a following ELSE so the code needs to return +; here to check and ignore the ELSE if present + + LDY #$00 ; clear the index + LDA (Bpntrl),Y ; get the next BASIC byte + CMP #TK_ELSE ; compare it with the token for ELSE + BEQ LAB_DATA ; if ELSE ignore the following statement + +; there was no ELSE so continue execution of IF THEN [: ]. any +; following ELSE will, correctly, cause a syntax error + + RTS ; else return to the interpreter inner loop + +; perform ELSE after IF + +LAB_174E + LDY #$00 ; clear the BASIC byte index + LDX #$01 ; clear the nesting depth +LAB_1750 + INY ; increment the BASIC byte index + LDA (Bpntrl),Y ; get the next BASIC byte + BEQ LAB_1753 ; if EOL go add the pointer and return + + CMP #TK_IF ; compare the byte with the token for IF + BNE LAB_1752 ; if not IF token skip the depth increment + + INX ; else increment the nesting depth .. + BNE LAB_1750 ; .. and continue looking + +LAB_1752 + CMP #TK_ELSE ; compare the byte with the token for ELSE + BNE LAB_1750 ; if not ELSE token continue looking + + DEX ; was ELSE so decrement the nesting depth + BNE LAB_1750 ; loop if still nested + + INY ; increment the BASIC byte index past the ELSE + +; found the matching ELSE, now do <{n|statement}> + +LAB_1753 + TYA ; else copy line index to A + CLC ; clear carry for add + ADC Bpntrl ; add the BASIC execute pointer low byte + STA Bpntrl ; save the BASIC execute pointer low byte + BCC LAB_1754 ; branch if no overflow to high byte + + INC Bpntrh ; else increment the BASIC execute pointer high byte +LAB_1754 + JSR LAB_GBYT ; scan memory + BCC LAB_174C ; if numeric do GOTO n + ; the code will return to the interpreter loop at the + ; tail end of the GOTO + + JMP LAB_15FF ; interpret BASIC code from (Bpntrl) + ; the code will return to the interpreter loop at the + ; tail end of the + +; perform REM, skip (rest of) line + +LAB_REM + JSR LAB_SNBL ; scan for next BASIC line + JMP LAB_170F ; go set BASIC execute pointer and return, branch always + +LAB_16FD + JMP LAB_SNER ; do syntax error then warm start + +; perform ON + +LAB_ON + CMP #TK_IRQ ; was it IRQ token ? + BNE LAB_NOIN ; if not go check NMI + + JMP LAB_SIRQ ; else go set-up IRQ + +LAB_NOIN + CMP #TK_NMI ; was it NMI token ? + BNE LAB_NONM ; if not go do normal ON command + + JMP LAB_SNMI ; else go set-up NMI + +LAB_NONM + JSR LAB_GTBY ; get byte parameter + PHA ; push GOTO/GOSUB token + CMP #TK_GOSUB ; compare with GOSUB token + BEQ LAB_176B ; branch if GOSUB + + CMP #TK_GOTO ; compare with GOTO token +LAB_1767 + BNE LAB_16FD ; if not GOTO do syntax error then warm start + + +; next character was GOTO or GOSUB + +LAB_176B + DEC FAC1_3 ; decrement index (byte value) + BNE LAB_1773 ; branch if not zero + + PLA ; pull GOTO/GOSUB token + JMP LAB_1602 ; go execute it + +LAB_1773 + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GFPN ; get fixed-point number into temp integer (skip this n) + ; (we could LDX #',' and JSR LAB_SNBL+2, then we + ; just BNE LAB_176B for the loop. should be quicker .. + ; no we can't, what if we meet a colon or [EOL]?) + CMP #$2C ; compare next character with "," + BEQ LAB_176B ; loop if "," + +LAB_177E + PLA ; else pull keyword token (run out of options) + ; also dump +/-1 pointer low byte and exit +LAB_177F + RTS + +; takes n * 106 + 11 cycles where n is the number of digits + +; get fixed-point number into temp integer + +LAB_GFPN + LDX #$00 ; clear reg + STX Itempl ; clear temporary integer low byte +LAB_1785 + STX Itemph ; save temporary integer high byte + BCS LAB_177F ; return if carry set, end of scan, character was + ; not 0-9 + + CPX #$19 ; compare high byte with $19 + TAY ; ensure Zb = 0 if the branch is taken + BCS LAB_1767 ; branch if >=, makes max line # 63999 because next + ; bit does *$0A, = 64000, compare at target will fail + ; and do syntax error + + SBC #'0'-1 ; subtract "0", $2F + carry, from byte + TAY ; copy binary digit + LDA Itempl ; get temporary integer low byte + ASL ; *2 low byte + ROL Itemph ; *2 high byte + ASL ; *2 low byte + ROL Itemph ; *2 high byte, *4 + ADC Itempl ; + low byte, *5 + STA Itempl ; save it + TXA ; get high byte copy to A + ADC Itemph ; + high byte, *5 + ASL Itempl ; *2 low byte, *10d + ROL ; *2 high byte, *10d + TAX ; copy high byte back to X + TYA ; get binary digit back + ADC Itempl ; add number low byte + STA Itempl ; save number low byte + BCC LAB_17B3 ; if no overflow to high byte get next character + + INX ; else increment high byte +LAB_17B3 + JSR LAB_IGBY ; increment and scan memory + JMP LAB_1785 ; loop for next character + +; perform DEC + +LAB_DEC + LDA #LAB_259C ; set +/-1 pointer high byte (both the same) + JSR LAB_246C ; add (AY) to FAC1 + JSR LAB_PFAC ; pack FAC1 into variable (Lvarpl) + + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BNE LAB_177E ; exit if not "," (either end or error) + + ; was "," so another INCR variable to do + JSR LAB_IGBY ; increment and scan memory + JMP LAB_17B7 ; go do next var + +IncrErr + JMP LAB_1ABC ; do "Type mismatch" error then warm start + +; perform LET + +LAB_LET + JSR LAB_GVAR ; get var address + STA Lvarpl ; save var address low byte + STY Lvarph ; save var address high byte + LDA #TK_EQUAL ; get = token + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; push data type flag + JSR LAB_EVEX ; evaluate expression + PLA ; pop data type flag + ROL ; set carry if type = string + JSR LAB_CKTM ; type match check, set C for string + BNE LAB_17D5 ; branch if string + + JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return + +; string LET + +LAB_17D5 + LDY #$02 ; set index to pointer high byte + LDA (des_pl),Y ; get string pointer high byte + CMP Sstorh ; compare bottom of string space high byte + BCC LAB_17F4 ; if less assign value and exit (was in program memory) + + BNE LAB_17E6 ; branch if > + ; else was equal so compare low bytes + DEY ; decrement index + LDA (des_pl),Y ; get pointer low byte + CMP Sstorl ; compare bottom of string space low byte + BCC LAB_17F4 ; if less assign value and exit (was in program memory) + + ; pointer was >= to bottom of string space pointer +LAB_17E6 + LDY des_ph ; get descriptor pointer high byte + CPY Svarh ; compare start of vars high byte + BCC LAB_17F4 ; branch if less (descriptor is on stack) + + BNE LAB_17FB ; branch if greater (descriptor is not on stack) + + ; else high bytes were equal so .. + LDA des_pl ; get descriptor pointer low byte + CMP Svarl ; compare start of vars low byte + BCS LAB_17FB ; branch if >= (descriptor is not on stack) + +LAB_17F4 + LDA des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + JMP LAB_1811 ; clean stack, copy descriptor to variable and return + + ; make space and copy string +LAB_17FB + LDY #$00 ; index to length + LDA (des_pl),Y ; get string length + JSR LAB_209C ; copy string + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + STA ssptr_l ; save descriptor pointer low byte + STY ssptr_h ; save descriptor pointer high byte + JSR LAB_228A ; copy string from descriptor (sdescr) to (Sutill) + LDA #FAC1_e ; get descriptor pointer high byte + + ; clean stack and assign value to string variable +LAB_1811 + STA des_2l ; save descriptor_2 pointer low byte + STY des_2h ; save descriptor_2 pointer high byte + JSR LAB_22EB ; clean descriptor stack, YA = pointer + LDY #$00 ; index to length + LDA (des_2l),Y ; get string length + STA (Lvarpl),Y ; copy to let string variable + INY ; index to string pointer low byte + LDA (des_2l),Y ; get string pointer low byte + STA (Lvarpl),Y ; copy to let string variable + INY ; index to string pointer high byte + LDA (des_2l),Y ; get string pointer high byte + STA (Lvarpl),Y ; copy to let string variable + RTS + +; perform GET + +LAB_GET + JSR LAB_GVAR ; get var address + STA Lvarpl ; save var address low byte + STY Lvarph ; save var address high byte + JSR INGET ; get input byte + LDX Dtypef ; get data type flag, $FF=string, $00=numeric + BMI LAB_GETS ; go get string character + + ; was numeric get + TAY ; copy character to Y + JSR LAB_1FD0 ; convert Y to byte in FAC1 + JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return + +LAB_GETS + PHA ; save character + LDA #$01 ; string is single byte + BCS LAB_IsByte ; branch if byte received + + PLA ; string is null +LAB_IsByte + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + BEQ LAB_NoSt ; skip store if null string + + PLA ; get character back + LDY #$00 ; clear index + STA (str_pl),Y ; save byte in string (byte IS string!) +LAB_NoSt + JSR LAB_RTST ; check for space on descriptor stack then put address + ; and length on descriptor stack and update stack pointers + + JMP LAB_17D5 ; do string LET and return + +; perform PRINT + +LAB_1829 + JSR LAB_18C6 ; print string from Sutill/Sutilh +LAB_182C + JSR LAB_GBYT ; scan memory + +; PRINT + +LAB_PRINT + BEQ LAB_CRLF ; if nothing following just print CR/LF + +LAB_1831 + CMP #TK_TAB ; compare with TAB( token + BEQ LAB_18A2 ; go do TAB/SPC + + CMP #TK_SPC ; compare with SPC( token + BEQ LAB_18A2 ; go do TAB/SPC + + CMP #',' ; compare with "," + BEQ LAB_188B ; go do move to next TAB mark + + CMP #';' ; compare with ";" + BEQ LAB_18BD ; if ";" continue with PRINT processing + + JSR LAB_EVEX ; evaluate expression + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BMI LAB_1829 ; branch if string + + JSR LAB_296E ; convert FAC1 to string + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + LDY #$00 ; clear index + +; don't check fit if terminal width byte is zero + + LDA TWidth ; get terminal width byte + BEQ LAB_185E ; skip check if zero + + SEC ; set carry for subtract + SBC TPos ; subtract terminal position + SBC (des_pl),Y ; subtract string length + BCS LAB_185E ; branch if less than terminal width + + JSR LAB_CRLF ; else print CR/LF +LAB_185E + JSR LAB_18C6 ; print string from Sutill/Sutilh + BEQ LAB_182C ; always go continue processing line + +; CR/LF return to BASIC from BASIC input handler + +LAB_1866 + LDA #$00 ; clear byte + STA Ibuffs,X ; null terminate input + LDX #Ibuffs ; set Y to buffer start-1 high byte + +; print CR/LF + +LAB_CRLF + LDA #$0D ; load [CR] + JSR LAB_PRNA ; go print the character + LDA #$0A ; load [LF] + BNE LAB_PRNA ; go print the character and return, branch always + +LAB_188B + LDA TPos ; get terminal position + CMP Iclim ; compare with input column limit + BCC LAB_1897 ; branch if less + + JSR LAB_CRLF ; else print CR/LF (next line) + BNE LAB_18BD ; continue with PRINT processing (branch always) + +LAB_1897 + SEC ; set carry for subtract +LAB_1898 + SBC TabSiz ; subtract TAB size + BCS LAB_1898 ; loop if result was +ve + + EOR #$FF ; complement it + ADC #$01 ; +1 (twos complement) + BNE LAB_18B6 ; always print A spaces (result is never $00) + + ; do TAB/SPC +LAB_18A2 + PHA ; save token + JSR LAB_SGBY ; scan and get byte parameter + CMP #$29 ; is next character ) + BNE LAB_1910 ; if not do syntax error then warm start + + PLA ; get token back + CMP #TK_TAB ; was it TAB ? + BNE LAB_18B7 ; if not go do SPC + + ; calculate TAB offset + TXA ; copy integer value to A + SBC TPos ; subtract terminal position + BCC LAB_18BD ; branch if result was < 0 (can't TAB backwards) + + ; print A spaces +LAB_18B6 + TAX ; copy result to X +LAB_18B7 + TXA ; set flags on size for SPC + BEQ LAB_18BD ; branch if result was = $0, already here + + ; print X spaces +LAB_18BA + JSR LAB_18E0 ; print " " + DEX ; decrement count + BNE LAB_18BA ; loop if not all done + + ; continue with PRINT processing +LAB_18BD + JSR LAB_IGBY ; increment and scan memory + BNE LAB_1831 ; if more to print go do it + + RTS + +; print null terminated string from memory + +LAB_18C3 + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + +; print string from Sutill/Sutilh + +LAB_18C6 + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=$71=pointer low byte, + ; Y=$72=pointer high byte + LDY #$00 ; reset index + TAX ; copy length to X + BEQ LAB_188C ; exit (RTS) if null string + +LAB_18CD + + LDA (ut1_pl),Y ; get next byte + JSR LAB_PRNA ; go print the character + INY ; increment index + DEX ; decrement count + BNE LAB_18CD ; loop if not done yet + + RTS + + ; Print single format character +; print " " + +LAB_18E0 + LDA #$20 ; load " " + .byte $2C ; change next line to BIT LAB_3FA9 + +; print "?" character + +LAB_18E3 + LDA #$3F ; load "?" character + +; print character in A +; now includes the null handler +; also includes infinite line length code +; note! some routines expect this one to exit with Zb=0 + +LAB_PRNA + CMP #' ' ; compare with " " + BCC LAB_18F9 ; branch if less (non printing) + + ; else printable character + PHA ; save the character + +; don't check fit if terminal width byte is zero + + LDA TWidth ; get terminal width + BNE LAB_18F0 ; branch if not zero (not infinite length) + +; is "infinite line" so check TAB position + + LDA TPos ; get position + SBC TabSiz ; subtract TAB size, carry set by CMP #$20 above + BNE LAB_18F7 ; skip reset if different + + STA TPos ; else reset position + BEQ LAB_18F7 ; go print character + +LAB_18F0 + CMP TPos ; compare with terminal character position + BNE LAB_18F7 ; branch if not at end of line + + JSR LAB_CRLF ; else print CR/LF +LAB_18F7 + INC TPos ; increment terminal position + PLA ; get character back +LAB_18F9 + JSR V_OUTP ; output byte via output vector + CMP #$0D ; compare with [CR] + BNE LAB_188A ; branch if not [CR] + + ; else print nullct nulls after the [CR] + STX TempB ; save buffer index + LDX Nullct ; get null count + BEQ LAB_1886 ; branch if no nulls + + LDA #$00 ; load [NULL] +LAB_1880 + JSR LAB_PRNA ; go print the character + DEX ; decrement count + BNE LAB_1880 ; loop if not all done + + LDA #$0D ; restore the character (and set the flags) +LAB_1886 + STX TPos ; clear terminal position (X always = zero when we get here) + LDX TempB ; restore buffer index +LAB_188A + AND #$FF ; set the flags +LAB_188C + RTS + +; handle bad input data + +LAB_1904 + LDA Imode ; get input mode flag, $00=INPUT, $00=READ + BPL LAB_1913 ; branch if INPUT (go do redo) + + LDA Dlinel ; get current DATA line low byte + LDY Dlineh ; get current DATA line high byte + STA Clinel ; save current line low byte + STY Clineh ; save current line high byte +LAB_1910 + JMP LAB_SNER ; do syntax error then warm start + + ; mode was INPUT +LAB_1913 + LDA #LAB_REDO ; point to redo message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + LDA Cpntrl ; get continue pointer low byte + LDY Cpntrh ; get continue pointer high byte + STA Bpntrl ; save BASIC execute pointer low byte + STY Bpntrh ; save BASIC execute pointer high byte + RTS + +; perform INPUT + +LAB_INPUT + CMP #$22 ; compare next byte with open quote + BNE LAB_1934 ; branch if no prompt string + + JSR LAB_1BC1 ; print "..." string + LDA #$3B ; load A with ";" + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + JSR LAB_18C6 ; print string from Sutill/Sutilh + + ; done with prompt, now get data +LAB_1934 + JSR LAB_CKRN ; check not Direct, back here if ok + JSR LAB_INLN ; print "? " and get BASIC input + LDA #$00 ; set mode = INPUT + CMP Ibuffs ; test first byte in buffer + BNE LAB_1953 ; branch if not null input + + CLC ; was null input so clear carry to exit program + JMP LAB_1647 ; go do BREAK exit + +; perform READ + +LAB_READ + LDX Dptrl ; get DATA pointer low byte + LDY Dptrh ; get DATA pointer high byte + LDA #$80 ; set mode = READ + +LAB_1953 + STA Imode ; set input mode flag, $00=INPUT, $80=READ + STX Rdptrl ; save READ pointer low byte + STY Rdptrh ; save READ pointer high byte + + ; READ or INPUT next variable from list +LAB_195B + JSR LAB_GVAR ; get (var) address + STA Lvarpl ; save address low byte + STY Lvarph ; save address high byte + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + STA Itempl ; save as temporary integer low byte + STY Itemph ; save as temporary integer high byte + LDX Rdptrl ; get READ pointer low byte + LDY Rdptrh ; get READ pointer high byte + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BNE LAB_1988 ; branch if not null + + ; pointer was to null entry + BIT Imode ; test input mode flag, $00=INPUT, $80=READ + BMI LAB_19DD ; branch if READ + + ; mode was INPUT + JSR LAB_18E3 ; print "?" character (double ? for extended input) + JSR LAB_INLN ; print "? " and get BASIC input + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte +LAB_1985 + JSR LAB_GBYT ; scan memory +LAB_1988 + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BPL LAB_19B0 ; branch if numeric + + ; else get string + STA Srchc ; save search character + CMP #$22 ; was it " ? + BEQ LAB_1999 ; branch if so + + LDA #':' ; else search character is ":" + STA Srchc ; set new search character + LDA #',' ; other search character is "," + CLC ; clear carry for add +LAB_1999 + STA Asrch ; set second search character + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + + ADC #$00 ; c is =1 if we came via the BEQ LAB_1999, else =0 + BCC LAB_19A4 ; branch if no execute pointer low byte rollover + + INY ; else increment high byte +LAB_19A4 + JSR LAB_20B4 ; print Srchc or Asrch terminated string to Sutill/Sutilh + JSR LAB_23F3 ; restore BASIC execute pointer from temp (Btmpl/Btmph) + JSR LAB_17D5 ; go do string LET + JMP LAB_19B6 ; go check string terminator + + ; get numeric INPUT +LAB_19B0 + JSR LAB_2887 ; get FAC1 from string + JSR LAB_PFAC ; pack FAC1 into (Lvarpl) +LAB_19B6 + JSR LAB_GBYT ; scan memory + BEQ LAB_19C5 ; branch if null (last entry) + + CMP #',' ; else compare with "," + BEQ LAB_19C2 ; branch if "," + + JMP LAB_1904 ; else go handle bad input data + + ; got good input data +LAB_19C2 + JSR LAB_IGBY ; increment and scan memory +LAB_19C5 + LDA Bpntrl ; get BASIC execute pointer low byte (temp READ/INPUT ptr) + LDY Bpntrh ; get BASIC execute pointer high byte (temp READ/INPUT ptr) + STA Rdptrl ; save for now + STY Rdptrh ; save for now + LDA Itempl ; get temporary integer low byte (temp BASIC execute ptr) + LDY Itemph ; get temporary integer high byte (temp BASIC execute ptr) + STA Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_1A03 ; if null go do extra ignored message + + JSR LAB_1C01 ; else scan for "," , else do syntax error then warm start + JMP LAB_195B ; go INPUT next variable from list + + ; find next DATA statement or do "Out of DATA" error +LAB_19DD + JSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL]) + INY ; increment index + TAX ; copy character ([:] or [EOL]) + BNE LAB_19F6 ; branch if [:] + + LDX #$06 ; set for "Out of DATA" error + INY ; increment index, now points to next line pointer high byte + LDA (Bpntrl),Y ; get next line pointer high byte + BEQ LAB_1A54 ; branch if end (eventually does error X) + + INY ; increment index + LDA (Bpntrl),Y ; get next line # low byte + STA Dlinel ; save current DATA line low byte + INY ; increment index + LDA (Bpntrl),Y ; get next line # high byte + INY ; increment index + STA Dlineh ; save current DATA line high byte +LAB_19F6 + LDA (Bpntrl),Y ; get byte + INY ; increment index + TAX ; copy to X + JSR LAB_170F ; set BASIC execute pointer + CPX #TK_DATA ; compare with "DATA" token + BEQ LAB_1985 ; was "DATA" so go do next READ + + BNE LAB_19DD ; go find next statement if not "DATA" + +; end of INPUT/READ routine + +LAB_1A03 + LDA Rdptrl ; get temp READ pointer low byte + LDY Rdptrh ; get temp READ pointer high byte + LDX Imode ; get input mode flag, $00=INPUT, $80=READ + BPL LAB_1A0E ; branch if INPUT + + JMP LAB_1624 ; save AY as DATA pointer and return + + ; we were getting INPUT +LAB_1A0E + LDY #$00 ; clear index + LDA (Rdptrl),Y ; get next byte + BNE LAB_1A1B ; error if not end of INPUT + + RTS + + ; user typed too much +LAB_1A1B + LDA #LAB_IMSG ; point to extra ignored message (high addr) + JMP LAB_18C3 ; print null terminated string from memory and return + +; search the stack for FOR activity +; exit with z=1 if FOR else exit with z=0 + +LAB_11A1 + TSX ; copy stack pointer + INX ; +1 pass return address + INX ; +2 pass return address + INX ; +3 pass calling routine return address + INX ; +4 pass calling routine return address +LAB_11A6 + LDA LAB_STAK+1,X ; get token byte from stack + CMP #TK_FOR ; is it FOR token + BNE LAB_11CE ; exit if not FOR token + + ; was FOR token + LDA Frnxth ; get var pointer for FOR/NEXT high byte + BNE LAB_11BB ; branch if not null + + LDA LAB_STAK+2,X ; get FOR variable pointer low byte + STA Frnxtl ; save var pointer for FOR/NEXT low byte + LDA LAB_STAK+3,X ; get FOR variable pointer high byte + STA Frnxth ; save var pointer for FOR/NEXT high byte +LAB_11BB + CMP LAB_STAK+3,X ; compare var pointer with stacked var pointer (high byte) + BNE LAB_11C7 ; branch if no match + + LDA Frnxtl ; get var pointer for FOR/NEXT low byte + CMP LAB_STAK+2,X ; compare var pointer with stacked var pointer (low byte) + BEQ LAB_11CE ; exit if match found + +LAB_11C7 + TXA ; copy index + CLC ; clear carry for add + ADC #$10 ; add FOR stack use size + TAX ; copy back to index + BNE LAB_11A6 ; loop if not at start of stack + +LAB_11CE + RTS + +; perform NEXT + +LAB_NEXT + BNE LAB_1A46 ; branch if NEXT var + + LDY #$00 ; else clear Y + BEQ LAB_1A49 ; branch always (no variable to search for) + +; NEXT var + +LAB_1A46 + JSR LAB_GVAR ; get variable address +LAB_1A49 + STA Frnxtl ; store variable pointer low byte + STY Frnxth ; store variable pointer high byte + ; (both cleared if no variable defined) + JSR LAB_11A1 ; search the stack for FOR activity + BEQ LAB_1A56 ; branch if found + + LDX #$00 ; else set error $00 ("NEXT without FOR" error) +LAB_1A54 + BEQ LAB_1ABE ; do error #X, then warm start + +LAB_1A56 + TXS ; set stack pointer, X set by search, dumps return addresses + + TXA ; copy stack pointer + SEC ; set carry for subtract + SBC #$F7 ; point to TO var + STA ut2_pl ; save pointer to TO var for compare + ADC #$FB ; point to STEP var + + LDY #>LAB_STAK ; point to stack page high byte + JSR LAB_UFAC ; unpack memory (STEP value) into FAC1 + TSX ; get stack pointer back + LDA LAB_STAK+8,X ; get step sign + STA FAC1_s ; save FAC1 sign (b7) + LDA Frnxtl ; get FOR variable pointer low byte + LDY Frnxth ; get FOR variable pointer high byte + JSR LAB_246C ; add (FOR variable) to FAC1 + JSR LAB_PFAC ; pack FAC1 into (FOR variable) + LDY #>LAB_STAK ; point to stack page high byte + JSR LAB_27FA ; compare FAC1 with (Y,ut2_pl) (TO value) + TSX ; get stack pointer back + CMP LAB_STAK+8,X ; compare step sign + BEQ LAB_1A9B ; branch if = (loop complete) + + ; loop back and do it all again + LDA LAB_STAK+$0D,X ; get FOR line low byte + STA Clinel ; save current line low byte + LDA LAB_STAK+$0E,X ; get FOR line high byte + STA Clineh ; save current line high byte + LDA LAB_STAK+$10,X ; get BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA LAB_STAK+$0F,X ; get BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte +LAB_1A98 + JMP LAB_15C2 ; go do interpreter inner loop + + ; loop complete so carry on +LAB_1A9B + TXA ; stack copy to A + ADC #$0F ; add $10 ($0F+carry) to dump FOR structure + TAX ; copy back to index + TXS ; copy to stack pointer + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BNE LAB_1A98 ; branch if not "," (go do interpreter inner loop) + + ; was "," so another NEXT variable to do + JSR LAB_IGBY ; else increment and scan memory + JSR LAB_1A46 ; do NEXT (var) + +; evaluate expression and check is numeric, else do type mismatch + +LAB_EVNM + JSR LAB_EVEX ; evaluate expression + +; check if source is numeric, else do type mismatch + +LAB_CTNM + CLC ; destination is numeric + .byte $24 ; makes next line BIT $38 + +; check if source is string, else do type mismatch + +LAB_CTST + SEC ; required type is string + +; type match check, set C for string, clear C for numeric + +LAB_CKTM + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BMI LAB_1ABA ; branch if data type is string + + ; else data type was numeric + BCS LAB_1ABC ; if required type is string do type mismatch error +LAB_1AB9 + RTS + + ; data type was string, now check required type +LAB_1ABA + BCS LAB_1AB9 ; exit if required type is string + + ; else do type mismatch error +LAB_1ABC + LDX #$18 ; error code $18 ("Type mismatch" error) +LAB_1ABE + JMP LAB_XERR ; do error #X, then warm start + +; evaluate expression + +LAB_EVEX + LDX Bpntrl ; get BASIC execute pointer low byte + BNE LAB_1AC7 ; skip next if not zero + + DEC Bpntrh ; else decrement BASIC execute pointer high byte +LAB_1AC7 + DEC Bpntrl ; decrement BASIC execute pointer low byte + +LAB_EVEZ + LDA #$00 ; set null precedence (flag done) +LAB_1ACC + PHA ; push precedence byte + LDA #$02 ; 2 bytes + JSR LAB_1212 ; check room on stack for A bytes + JSR LAB_GVAL ; get value from line + LDA #$00 ; clear A + STA comp_f ; clear compare function flag +LAB_1ADB + JSR LAB_GBYT ; scan memory +LAB_1ADE + SEC ; set carry for subtract + SBC #TK_GT ; subtract token for > (lowest comparison function) + BCC LAB_1AFA ; branch if < TK_GT + + CMP #$03 ; compare with ">" to "<" tokens + BCS LAB_1AFA ; branch if >= TK_SGN (highest evaluation function +1) + + ; was token for > = or < (A = 0, 1 or 2) + CMP #$01 ; compare with token for = + ROL ; *2, b0 = carry (=1 if token was = or <) + ; (A = 0, 3 or 5) + EOR #$01 ; toggle b0 + ; (A = 1, 2 or 4. 1 if >, 2 if =, 4 if <) + EOR comp_f ; EOR with compare function flag bits + CMP comp_f ; compare with compare function flag + BCC LAB_1B53 ; if <(comp_f) do syntax error then warm start + ; was more than one <, = or >) + + STA comp_f ; save new compare function flag + JSR LAB_IGBY ; increment and scan memory + JMP LAB_1ADE ; go do next character + + ; token is < ">" or > "<" tokens +LAB_1AFA + LDX comp_f ; get compare function flag + BNE LAB_1B2A ; branch if compare function + + BCS LAB_1B78 ; go do functions + + ; else was < TK_GT so is operator or lower + ADC #TK_GT-TK_PLUS ; add # of operators (+, -, *, /, ^, AND, OR or EOR) + BCC LAB_1B78 ; branch if < + operator + + ; carry was set so token was +, -, *, /, ^, AND, OR or EOR + BNE LAB_1B0B ; branch if not + token + + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BPL LAB_1B0B ; branch if not string + + ; will only be $00 if type is string and token was + + JMP LAB_224D ; add strings, string 1 is in descriptor des_pl, string 2 + ; is in line, and return + +LAB_1B0B + STA ut1_pl ; save it + ASL ; *2 + ADC ut1_pl ; *3 + TAY ; copy to index +LAB_1B13 + PLA ; pull previous precedence + CMP LAB_OPPT,Y ; compare with precedence byte + BCS LAB_1B7D ; branch if A >= + + JSR LAB_CTNM ; check if source is numeric, else do type mismatch +LAB_1B1C + PHA ; save precedence +LAB_1B1D + JSR LAB_1B43 ; get vector, execute function then continue evaluation + PLA ; restore precedence + LDY prstk ; get precedence stacked flag + BPL LAB_1B3C ; branch if stacked values + + TAX ; copy precedence (set flags) + BEQ LAB_1B9D ; exit if done + + BNE LAB_1B86 ; else pop FAC2 and return, branch always + +LAB_1B2A + ROL Dtypef ; shift data type flag into Cb + TXA ; copy compare function flag + STA Dtypef ; clear data type flag, X is 0xxx xxxx + ROL ; shift data type into compare function byte b0 + LDX Bpntrl ; get BASIC execute pointer low byte + BNE LAB_1B34 ; branch if no underflow + + DEC Bpntrh ; else decrement BASIC execute pointer high byte +LAB_1B34 + DEC Bpntrl ; decrement BASIC execute pointer low byte +TK_LT_PLUS = TK_LT-TK_PLUS + LDY #TK_LT_PLUS*3 ; set offset to last operator entry + STA comp_f ; save new compare function flag + BNE LAB_1B13 ; branch always + +LAB_1B3C + CMP LAB_OPPT,Y ;.compare with stacked function precedence + BCS LAB_1B86 ; branch if A >=, pop FAC2 and return + + BCC LAB_1B1C ; branch always + +;.get vector, execute function then continue evaluation + +LAB_1B43 + LDA LAB_OPPT+2,Y ; get function vector high byte + PHA ; onto stack + LDA LAB_OPPT+1,Y ; get function vector low byte + PHA ; onto stack + ; now push sign, round FAC1 and put on stack + JSR LAB_1B5B ; function will return here, then the next RTS will call + ; the function + LDA comp_f ; get compare function flag + PHA ; push compare evaluation byte + LDA LAB_OPPT,Y ; get precedence byte + JMP LAB_1ACC ; continue evaluating expression + +LAB_1B53 + JMP LAB_SNER ; do syntax error then warm start + +; push sign, round FAC1 and put on stack + +LAB_1B5B + PLA ; get return addr low byte + STA ut1_pl ; save it + INC ut1_pl ; increment it (was ret-1 pushed? yes!) + ; note! no check is made on the high byte! if the calling + ; routine assembles to a page edge then this all goes + ; horribly wrong !!! + PLA ; get return addr high byte + STA ut1_ph ; save it + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; push sign + +; round FAC1 and put on stack + +LAB_1B66 + JSR LAB_27BA ; round FAC1 + LDA FAC1_3 ; get FAC1 mantissa3 + PHA ; push on stack + LDA FAC1_2 ; get FAC1 mantissa2 + PHA ; push on stack + LDA FAC1_1 ; get FAC1 mantissa1 + PHA ; push on stack + LDA FAC1_e ; get FAC1 exponent + PHA ; push on stack + JMP (ut1_pl) ; return, sort of + +; do functions + +LAB_1B78 + LDY #$FF ; flag function + PLA ; pull precedence byte +LAB_1B7B + BEQ LAB_1B9D ; exit if done + +LAB_1B7D + CMP #$64 ; compare previous precedence with $64 + BEQ LAB_1B84 ; branch if was $64 (< function) + + JSR LAB_CTNM ; check if source is numeric, else do type mismatch +LAB_1B84 + STY prstk ; save precedence stacked flag + + ; pop FAC2 and return +LAB_1B86 + PLA ; pop byte + LSR ; shift out comparison evaluation lowest bit + STA Cflag ; save comparison evaluation flag + PLA ; pop exponent + STA FAC2_e ; save FAC2 exponent + PLA ; pop mantissa1 + STA FAC2_1 ; save FAC2 mantissa1 + PLA ; pop mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + PLA ; pop mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + PLA ; pop sign + STA FAC2_s ; save FAC2 sign (b7) + EOR FAC1_s ; EOR FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) +LAB_1B9D + LDA FAC1_e ; get FAC1 exponent + RTS + +; print "..." string to string util area + +LAB_1BC1 + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + ADC #$00 ; add carry to low byte + BCC LAB_1BCA ; branch if no overflow + + INY ; increment high byte +LAB_1BCA + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + JMP LAB_23F3 ; restore BASIC execute pointer from temp and return + +; get value from line + +LAB_GVAL + JSR LAB_IGBY ; increment and scan memory + BCS LAB_1BAC ; branch if not numeric character + + ; else numeric string found (e.g. 123) +LAB_1BA9 + JMP LAB_2887 ; get FAC1 from string and return + +; get value from line .. continued + + ; wasn't a number so .. +LAB_1BAC + TAX ; set the flags + BMI LAB_1BD0 ; if -ve go test token values + + ; else it is either a string, number, variable or () + CMP #'$' ; compare with "$" + BEQ LAB_1BA9 ; branch if "$", hex number + + CMP #'%' ; else compare with "%" + BEQ LAB_1BA9 ; branch if "%", binary number + + CMP #'.' ; compare with "." + BEQ LAB_1BA9 ; if so get FAC1 from string and return (e.g. was .123) + + ; it wasn't any sort of number so .. + CMP #$22 ; compare with " + BEQ LAB_1BC1 ; branch if open quote + + ; wasn't any sort of number so .. + +; evaluate expression within parentheses + + CMP #'(' ; compare with "(" + BNE LAB_1C18 ; if not "(" get (var), return value in FAC1 and $ flag + +LAB_1BF7 + JSR LAB_EVEZ ; evaluate expression, no decrement + +; all the 'scan for' routines return the character after the sought character + +; scan for ")" , else do syntax error then warm start + +LAB_1BFB + LDA #$29 ; load A with ")" + +; scan for CHR$(A) , else do syntax error then warm start + +LAB_SCCA + LDY #$00 ; clear index + CMP (Bpntrl),Y ; check next byte is = A + BNE LAB_SNER ; if not do syntax error then warm start + + JMP LAB_IGBY ; increment and scan memory then return + +; scan for "(" , else do syntax error then warm start + +LAB_1BFE + LDA #$28 ; load A with "(" + BNE LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + ; (branch always) + +; scan for "," , else do syntax error then warm start + +LAB_1C01 + LDA #$2C ; load A with "," + BNE LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + ; (branch always) + +; syntax error then warm start + +LAB_SNER + LDX #$02 ; error code $02 ("Syntax" error) + JMP LAB_XERR ; do error #X, then warm start + +; get value from line .. continued +; do tokens + +LAB_1BD0 + CMP #TK_MINUS ; compare with token for - + BEQ LAB_1C11 ; branch if - token (do set-up for functions) + + ; wasn't -n so .. + CMP #TK_PLUS ; compare with token for + + BEQ LAB_GVAL ; branch if + token (+n = n so ignore leading +) + + CMP #TK_NOT ; compare with token for NOT + BNE LAB_1BE7 ; branch if not token for NOT + + ; was NOT token +TK_EQUAL_PLUS = TK_EQUAL-TK_PLUS + LDY #TK_EQUAL_PLUS*3 ; offset to NOT function + BNE LAB_1C13 ; do set-up for function then execute (branch always) + +; do = compare + +LAB_EQUAL + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_3 ; get FAC1 mantissa3 + EOR #$FF ; invert it + TAY ; copy it + LDA FAC1_2 ; get FAC1 mantissa2 + EOR #$FF ; invert it + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; get value from line .. continued + + ; wasn't +, -, or NOT so .. +LAB_1BE7 + CMP #TK_FN ; compare with token for FN + BNE LAB_1BEE ; branch if not token for FN + + JMP LAB_201E ; go evaluate FNx + +; get value from line .. continued + + ; wasn't +, -, NOT or FN so .. +LAB_1BEE + SBC #TK_SGN ; subtract with token for SGN + BCS LAB_1C27 ; if a function token go do it + + JMP LAB_SNER ; else do syntax error + +; set-up for functions + +LAB_1C11 +TK_GT_PLUS = TK_GT-TK_PLUS + LDY #TK_GT_PLUS*3 ; set offset from base to > operator +LAB_1C13 + PLA ; dump return address low byte + PLA ; dump return address high byte + JMP LAB_1B1D ; execute function then continue evaluation + +; variable name set-up +; get (var), return value in FAC_1 and $ flag + +LAB_1C18 + JSR LAB_GVAR ; get (var) address + STA FAC1_2 ; save address low byte in FAC1 mantissa2 + STY FAC1_3 ; save address high byte in FAC1 mantissa3 + LDX Dtypef ; get data type flag, $FF=string, $00=numeric + BMI LAB_1C25 ; if string then return (does RTS) + +LAB_1C24 + JMP LAB_UFAC ; unpack memory (AY) into FAC1 + +LAB_1C25 + RTS + +; get value from line .. continued +; only functions left so .. + +; set up function references + +; new for V2.0+ this replaces a lot of IF .. THEN .. ELSEIF .. THEN .. that was needed +; to process function calls. now the function vector is computed and pushed on the stack +; and the preprocess offset is read. if the preprocess offset is non zero then the vector +; is calculated and the routine called, if not this routine just does RTS. whichever +; happens the RTS at the end of this routine, or the end of the preprocess routine, calls +; the function code + +; this also removes some less than elegant code that was used to bypass type checking +; for functions that returned strings + +LAB_1C27 + ASL ; *2 (2 bytes per function address) + TAY ; copy to index + + LDA LAB_FTBM,Y ; get function jump vector high byte + PHA ; push functions jump vector high byte + LDA LAB_FTBL,Y ; get function jump vector low byte + PHA ; push functions jump vector low byte + + LDA LAB_FTPM,Y ; get function pre process vector high byte + BEQ LAB_1C56 ; skip pre process if null vector + + PHA ; push functions pre process vector high byte + LDA LAB_FTPL,Y ; get function pre process vector low byte + PHA ; push functions pre process vector low byte + +LAB_1C56 + RTS ; do function, or pre process, call + +; process string expression in parenthesis + +LAB_PPFS + JSR LAB_1BF7 ; process expression in parenthesis + JMP LAB_CTST ; check if source is string then do function, + ; else do type mismatch + +; process numeric expression in parenthesis + +LAB_PPFN + JSR LAB_1BF7 ; process expression in parenthesis + JMP LAB_CTNM ; check if source is numeric then do function, + ; else do type mismatch + +; set numeric data type and increment BASIC execute pointer + +LAB_PPBI + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + JMP LAB_IGBY ; increment and scan memory then do function + +; process string for LEFT$, RIGHT$ or MID$ + +LAB_LRMS + JSR LAB_EVEZ ; evaluate (should be string) expression + JSR LAB_1C01 ; scan for ",", else do syntax error then warm start + JSR LAB_CTST ; check if source is string, else do type mismatch + + PLA ; get function jump vector low byte + TAX ; save functions jump vector low byte + PLA ; get function jump vector high byte + TAY ; save functions jump vector high byte + LDA des_ph ; get descriptor pointer high byte + PHA ; push string pointer high byte + LDA des_pl ; get descriptor pointer low byte + PHA ; push string pointer low byte + TYA ; get function jump vector high byte back + PHA ; save functions jump vector high byte + TXA ; get function jump vector low byte back + PHA ; save functions jump vector low byte + JSR LAB_GTBY ; get byte parameter + TXA ; copy byte parameter to A + RTS ; go do function + +; process numeric expression(s) for BIN$ or HEX$ + +LAB_BHSS + JSR LAB_EVEZ ; process expression + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_BHER ; branch if n>=2^24 (is too big) + + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDX #$02 ; 3 bytes to do +LAB_CFAC + LDA FAC1_1,X ; get byte from FAC1 + STA nums_1,X ; save byte to temp + DEX ; decrement index + BPL LAB_CFAC ; copy FAC1 mantissa to temp + + JSR LAB_GBYT ; get next BASIC byte + LDX #$00 ; set default to no leading "0"s + CMP #')' ; compare with close bracket + BEQ LAB_1C54 ; if ")" go do rest of function + + JSR LAB_SCGB ; scan for "," and get byte + JSR LAB_GBYT ; get last byte back + CMP #')' ; is next character ) + BNE LAB_BHER ; if not ")" go do error + +LAB_1C54 + RTS ; else do function + +LAB_BHER + JMP LAB_FCER ; do function call error then warm start + +; perform EOR + +; added operator format is the same as AND or OR, precedence is the same as OR + +; this bit worked first time but it took a while to sort out the operator table +; pointers and offsets afterwards! + +LAB_EOR + JSR GetFirst ; get first integer expression (no sign check) + EOR XOAw_l ; EOR with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + EOR XOAw_h ; EOR with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform OR + +LAB_OR + JSR GetFirst ; get first integer expression (no sign check) + ORA XOAw_l ; OR with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + ORA XOAw_h ; OR with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform AND + +LAB_AND + JSR GetFirst ; get first integer expression (no sign check) + AND XOAw_l ; AND with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + AND XOAw_h ; AND with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; get first value for OR, AND or EOR + +GetFirst + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_2 ; get FAC1 mantissa2 + STA XOAw_h ; save it + LDA FAC1_3 ; get FAC1 mantissa3 + STA XOAw_l ; save it + JSR LAB_279B ; copy FAC2 to FAC1 (get 2nd value in expression) + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_3 ; get FAC1 mantissa3 +LAB_1C95 + RTS + +; perform comparisons + +; do < compare + +LAB_LTHAN + JSR LAB_CKTM ; type match check, set C for string + BCS LAB_1CAE ; branch if string + + ; do numeric < compare + LDA FAC2_s ; get FAC2 sign (b7) + ORA #$7F ; set all non sign bits + AND FAC2_1 ; and FAC2 mantissa1 (AND in sign bit) + STA FAC2_1 ; save FAC2 mantissa1 + LDA #FAC2_e ; set pointer high byte to FAC2 + JSR LAB_27F8 ; compare FAC1 with FAC2 (AY) + TAX ; copy result + JMP LAB_1CE1 ; go evaluate result + + ; do string < compare +LAB_1CAE + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + DEC comp_f ; clear < bit in compare function flag + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=pointer low byte, + ; Y=pointer high byte + STA str_ln ; save length + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + LDA FAC2_2 ; get descriptor pointer low byte + LDY FAC2_3 ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=pointer low byte, + ; Y=pointer high byte + STX FAC2_2 ; save string pointer low byte + STY FAC2_3 ; save string pointer high byte + TAX ; copy length + SEC ; set carry for subtract + SBC str_ln ; subtract string 1 length + BEQ LAB_1CD6 ; branch if str 1 length = string 2 length + + LDA #$01 ; set str 1 length > string 2 length + BCC LAB_1CD6 ; branch if so + + LDX str_ln ; get string 1 length + LDA #$FF ; set str 1 length < string 2 length +LAB_1CD6 + STA FAC1_s ; save length compare + LDY #$FF ; set index + INX ; adjust for loop +LAB_1CDB + INY ; increment index + DEX ; decrement count + BNE LAB_1CE6 ; branch if still bytes to do + + LDX FAC1_s ; get length compare back +LAB_1CE1 + BMI LAB_1CF2 ; branch if str 1 < str 2 + + CLC ; flag str 1 <= str 2 + BCC LAB_1CF2 ; go evaluate result + +LAB_1CE6 + LDA (FAC2_2),Y ; get string 2 byte + CMP (FAC1_1),Y ; compare with string 1 byte + BEQ LAB_1CDB ; loop if bytes = + + LDX #$FF ; set str 1 < string 2 + BCS LAB_1CF2 ; branch if so + + LDX #$01 ; set str 1 > string 2 +LAB_1CF2 + INX ; x = 0, 1 or 2 + TXA ; copy to A + ROL ; *2 (1, 2 or 4) + AND Cflag ; AND with comparison evaluation flag + BEQ LAB_1CFB ; branch if 0 (compare is false) + + LDA #$FF ; else set result true +LAB_1CFB + JMP LAB_27DB ; save A as integer byte and return + +LAB_1CFE + JSR LAB_1C01 ; scan for ",", else do syntax error then warm start + +; perform DIM + +LAB_DIM + TAX ; copy "DIM" flag to X + JSR LAB_1D10 ; search for variable + JSR LAB_GBYT ; scan memory + BNE LAB_1CFE ; scan for "," and loop if not null + + RTS + +; perform << (left shift) + +LAB_LSHIFT + JSR GetPair ; get integer expression and byte (no sign check) + LDA FAC1_2 ; get expression high byte + LDX TempB ; get shift count + BEQ NoShift ; branch if zero + + CPX #$10 ; compare bit count with 16d + BCS TooBig ; branch if >= + +Ls_loop + ASL FAC1_3 ; shift low byte + ROL ; shift high byte + DEX ; decrement bit count + BNE Ls_loop ; loop if shift not complete + + LDY FAC1_3 ; get expression low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform >> (right shift) + +LAB_RSHIFT + JSR GetPair ; get integer expression and byte (no sign check) + LDA FAC1_2 ; get expression high byte + LDX TempB ; get shift count + BEQ NoShift ; branch if zero + + CPX #$10 ; compare bit count with 16d + BCS TooBig ; branch if >= + +Rs_loop + LSR ; shift high byte + ROR FAC1_3 ; shift low byte + DEX ; decrement bit count + BNE Rs_loop ; loop if shift not complete + +NoShift + LDY FAC1_3 ; get expression low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +TooBig + LDA #$00 ; clear high byte + TAY ; copy to low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +GetPair + JSR LAB_EVBY ; evaluate byte expression, result in X + STX TempB ; save it + JSR LAB_279B ; copy FAC2 to FAC1 (get 2nd value in expression) + JMP LAB_EVIR ; evaluate integer expression (no sign check) + +; search for variable + +; return pointer to variable in Cvaral/Cvarah + +LAB_GVAR + LDX #$00 ; set DIM flag = $00 + JSR LAB_GBYT ; scan memory (1st character) +LAB_1D10 + STX Defdim ; save DIM flag +LAB_1D12 + STA Varnm1 ; save 1st character + AND #$7F ; clear FN flag bit + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCS LAB_1D1F ; branch if ok + + JMP LAB_SNER ; else syntax error then warm start + + ; was variable name so .. +LAB_1D1F + LDX #$00 ; clear 2nd character temp + STX Dtypef ; clear data type flag, $FF=string, $00=numeric + JSR LAB_IGBY ; increment and scan memory (2nd character) + BCC LAB_1D2D ; branch if character = "0"-"9" (ok) + + ; 2nd character wasn't "0" to "9" so .. + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCC LAB_1D38 ; branch if <"A" or >"Z" (go check if string) + +LAB_1D2D + TAX ; copy 2nd character + + ; ignore further (valid) characters in the variable name +LAB_1D2E + JSR LAB_IGBY ; increment and scan memory (3rd character) + BCC LAB_1D2E ; loop if character = "0"-"9" (ignore) + + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCS LAB_1D2E ; loop if character = "A"-"Z" (ignore) + + ; check if string variable +LAB_1D38 + CMP #'$' ; compare with "$" + BNE LAB_1D47 ; branch if not string + +; to introduce a new variable type (% suffix for integers say) then this branch +; will need to go to that check and then that branch, if it fails, go to LAB_1D47 + + ; type is string + LDA #$FF ; set data type = string + STA Dtypef ; set data type flag, $FF=string, $00=numeric + TXA ; get 2nd character back + ORA #$80 ; set top bit (indicate string var) + TAX ; copy back to 2nd character temp + JSR LAB_IGBY ; increment and scan memory + +; after we have determined the variable type we need to come back here to determine +; if it's an array of type. this would plug in a%(b[,c[,d]])) integer arrays nicely + + +LAB_1D47 ; gets here with character after var name in A + STX Varnm2 ; save 2nd character + ORA Sufnxf ; or with subscript/FNX flag (or FN name) + CMP #'(' ; compare with "(" + BNE LAB_1D53 ; branch if not "(" + + JMP LAB_1E17 ; go find, or make, array + +; either find or create var +; var name (1st two characters only!) is in Varnm1,Varnm2 + + ; variable name wasn't var(... so look for plain var +LAB_1D53 + LDA #$00 ; clear A + STA Sufnxf ; clear subscript/FNX flag + LDA Svarl ; get start of vars low byte + LDX Svarh ; get start of vars high byte + LDY #$00 ; clear index +LAB_1D5D + STX Vrschh ; save search address high byte +LAB_1D5F + STA Vrschl ; save search address low byte + CPX Sarryh ; compare high address with var space end + BNE LAB_1D69 ; skip next compare if <> + + ; high addresses were = so compare low addresses + CMP Sarryl ; compare low address with var space end + BEQ LAB_1D8B ; if not found go make new var + +LAB_1D69 + LDA Varnm1 ; get 1st character of var to find + CMP (Vrschl),Y ; compare with variable name 1st character + BNE LAB_1D77 ; branch if no match + + ; 1st characters match so compare 2nd characters + LDA Varnm2 ; get 2nd character of var to find + INY ; index to point to variable name 2nd character + CMP (Vrschl),Y ; compare with variable name 2nd character + BEQ LAB_1DD7 ; branch if match (found var) + + DEY ; else decrement index (now = $00) +LAB_1D77 + CLC ; clear carry for add + LDA Vrschl ; get search address low byte + ADC #$06 ; +6 (offset to next var name) + BCC LAB_1D5F ; loop if no overflow to high byte + + INX ; else increment high byte + BNE LAB_1D5D ; loop always (RAM doesn't extend to $FFFF !) + +; check byte, return C=0 if<"A" or >"Z" or "a" to "z" + +LAB_CASC + CMP #'a' ; compare with "a" + BCS LAB_1D83 ; go check <"z"+1 + +; check byte, return C=0 if<"A" or >"Z" + +LAB_1D82 + CMP #'A' ; compare with "A" + BCC LAB_1D8A ; exit if less + + ; carry is set + SBC #$5B ; subtract "Z"+1 + SEC ; set carry + SBC #$A5 ; subtract $A5 (restore byte) + ; carry clear if byte>$5A +LAB_1D8A + RTS + +LAB_1D83 + SBC #$7B ; subtract "z"+1 + SEC ; set carry + SBC #$85 ; subtract $85 (restore byte) + ; carry clear if byte>$7A + RTS + + ; reached end of variable mem without match + ; .. so create new variable +LAB_1D8B + PLA ; pop return address low byte + PHA ; push return address low byte +LAB_1C18p2 = LAB_1C18+2 + CMP #LAB_1D96 ; high byte point to $00,$00 + RTS + + ; create new numeric variable +LAB_1D98 + LDA Sarryl ; get var mem end low byte + LDY Sarryh ; get var mem end high byte + STA Ostrtl ; save old block start low byte + STY Ostrth ; save old block start high byte + LDA Earryl ; get array mem end low byte + LDY Earryh ; get array mem end high byte + STA Obendl ; save old block end low byte + STY Obendh ; save old block end high byte + CLC ; clear carry for add + ADC #$06 ; +6 (space for one var) + BCC LAB_1DAE ; branch if no overflow to high byte + + INY ; else increment high byte +LAB_1DAE + STA Nbendl ; set new block end low byte + STY Nbendh ; set new block end high byte + JSR LAB_11CF ; open up space in memory + LDA Nbendl ; get new start low byte + LDY Nbendh ; get new start high byte (-$100) + INY ; correct high byte + STA Sarryl ; save new var mem end low byte + STY Sarryh ; save new var mem end high byte + LDY #$00 ; clear index + LDA Varnm1 ; get var name 1st character + STA (Vrschl),Y ; save var name 1st character + INY ; increment index + LDA Varnm2 ; get var name 2nd character + STA (Vrschl),Y ; save var name 2nd character + LDA #$00 ; clear A + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + + ; found a match for var ((Vrschl) = ptr) +LAB_1DD7 + LDA Vrschl ; get var address low byte + CLC ; clear carry for add + ADC #$02 ; +2 (offset past var name bytes) + LDY Vrschh ; get var address high byte + BCC LAB_1DE1 ; branch if no overflow from add + + INY ; else increment high byte +LAB_1DE1 + STA Cvaral ; save current var address low byte + STY Cvarah ; save current var address high byte + RTS + +; set-up array pointer (Adatal/h) to first element in array +; set Adatal,Adatah to Astrtl,Astrth+2*Dimcnt+#$05 + +LAB_1DE6 + LDA Dimcnt ; get # of dimensions (1, 2 or 3) + ASL ; *2 (also clears the carry !) + ADC #$05 ; +5 (result is 7, 9 or 11 here) + ADC Astrtl ; add array start pointer low byte + LDY Astrth ; get array pointer high byte + BCC LAB_1DF2 ; branch if no overflow + + INY ; else increment high byte +LAB_1DF2 + STA Adatal ; save array data pointer low byte + STY Adatah ; save array data pointer high byte + RTS + +; evaluate integer expression + +LAB_EVIN + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + +; evaluate integer expression (no check) + +LAB_EVPI + LDA FAC1_s ; get FAC1 sign (b7) + BMI LAB_1E12 ; do function call error if -ve + +; evaluate integer expression (no sign check) + +LAB_EVIR + LDA FAC1_e ; get FAC1 exponent + CMP #$90 ; compare with exponent = 2^16 (n>2^15) + BCC LAB_1E14 ; branch if n<2^16 (is ok) + + LDA #LAB_1DF7 ; set pointer high byte to -32768 + JSR LAB_27F8 ; compare FAC1 with (AY) +LAB_1E12 + BNE LAB_FCER ; if <> do function call error then warm start + +LAB_1E14 + JMP LAB_2831 ; convert FAC1 floating-to-fixed and return + +; find or make array + +LAB_1E17 + LDA Defdim ; get DIM flag + PHA ; push it + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; push it + LDY #$00 ; clear dimensions count + +; now get the array dimension(s) and stack it (them) before the data type and DIM flag + +LAB_1E1F + TYA ; copy dimensions count + PHA ; save it + LDA Varnm2 ; get array name 2nd byte + PHA ; save it + LDA Varnm1 ; get array name 1st byte + PHA ; save it + JSR LAB_EVIN ; evaluate integer expression + PLA ; pull array name 1st byte + STA Varnm1 ; restore array name 1st byte + PLA ; pull array name 2nd byte + STA Varnm2 ; restore array name 2nd byte + PLA ; pull dimensions count + TAY ; restore it + TSX ; copy stack pointer + LDA LAB_STAK+2,X ; get DIM flag + PHA ; push it + LDA LAB_STAK+1,X ; get data type flag + PHA ; push it + LDA FAC1_2 ; get this dimension size high byte + STA LAB_STAK+2,X ; stack before flag bytes + LDA FAC1_3 ; get this dimension size low byte + STA LAB_STAK+1,X ; stack before flag bytes + INY ; increment dimensions count + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BEQ LAB_1E1F ; if found go do next dimension + + STY Dimcnt ; store dimensions count + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + PLA ; pull data type flag + STA Dtypef ; restore data type flag, $FF=string, $00=numeric + PLA ; pull DIM flag + STA Defdim ; restore DIM flag + LDX Sarryl ; get array mem start low byte + LDA Sarryh ; get array mem start high byte + +; now check to see if we are at the end of array memory (we would be if there were +; no arrays). + +LAB_1E5C + STX Astrtl ; save as array start pointer low byte + STA Astrth ; save as array start pointer high byte + CMP Earryh ; compare with array mem end high byte + BNE LAB_1E68 ; branch if not reached array mem end + + CPX Earryl ; else compare with array mem end low byte + BEQ LAB_1EA1 ; go build array if not found + + ; search for array +LAB_1E68 + LDY #$00 ; clear index + LDA (Astrtl),Y ; get array name first byte + INY ; increment index to second name byte + CMP Varnm1 ; compare with this array name first byte + BNE LAB_1E77 ; branch if no match + + LDA Varnm2 ; else get this array name second byte + CMP (Astrtl),Y ; compare with array name second byte + BEQ LAB_1E8D ; array found so branch + + ; no match +LAB_1E77 + INY ; increment index + LDA (Astrtl),Y ; get array size low byte + CLC ; clear carry for add + ADC Astrtl ; add array start pointer low byte + TAX ; copy low byte to X + INY ; increment index + LDA (Astrtl),Y ; get array size high byte + ADC Astrth ; add array mem pointer high byte + BCC LAB_1E5C ; if no overflow go check next array + +; do array bounds error + +LAB_1E85 + LDX #$10 ; error code $10 ("Array bounds" error) + .byte $2C ; makes next bit BIT LAB_08A2 + +; do function call error + +LAB_FCER + LDX #$08 ; error code $08 ("Function call" error) +LAB_1E8A + JMP LAB_XERR ; do error #X, then warm start + + ; found array, are we trying to dimension it? +LAB_1E8D + LDX #$12 ; set error $12 ("Double dimension" error) + LDA Defdim ; get DIM flag + BNE LAB_1E8A ; if we are trying to dimension it do error #X, then warm + ; start + +; found the array and we're not dimensioning it so we must find an element in it + + JSR LAB_1DE6 ; set-up array pointer (Adatal/h) to first element in array + ; (Astrtl,Astrth points to start of array) + LDA Dimcnt ; get dimensions count + LDY #$04 ; set index to array's # of dimensions + CMP (Astrtl),Y ; compare with no of dimensions + BNE LAB_1E85 ; if wrong do array bounds error, could do "Wrong + ; dimensions" error here .. if we want a different + ; error message + + JMP LAB_1F28 ; found array so go get element + ; (could jump to LAB_1F28 as all LAB_1F24 does is take + ; Dimcnt and save it at (Astrtl),Y which is already the + ; same or we would have taken the BNE) + + ; array not found, so build it +LAB_1EA1 + JSR LAB_1DE6 ; set-up array pointer (Adatal/h) to first element in array + ; (Astrtl,Astrth points to start of array) + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + LDY #$00 ; clear Y (don't need to clear A) + STY Aspth ; clear array data size high byte + LDA Varnm1 ; get variable name 1st byte + STA (Astrtl),Y ; save array name 1st byte + INY ; increment index + LDA Varnm2 ; get variable name 2nd byte + STA (Astrtl),Y ; save array name 2nd byte + LDA Dimcnt ; get dimensions count + LDY #$04 ; index to dimension count + STY Asptl ; set array data size low byte (four bytes per element) + STA (Astrtl),Y ; set array's dimensions count + + ; now calculate the size of the data space for the array + CLC ; clear carry for add (clear on subsequent loops) +LAB_1EC0 + LDX #$0B ; set default dimension value low byte + LDA #$00 ; set default dimension value high byte + BIT Defdim ; test default DIM flag + BVC LAB_1ED0 ; branch if b6 of Defdim is clear + + PLA ; else pull dimension value low byte + ADC #$01 ; +1 (allow for zeroeth element) + TAX ; copy low byte to X + PLA ; pull dimension value high byte + ADC #$00 ; add carry from low byte + +LAB_1ED0 + INY ; index to dimension value high byte + STA (Astrtl),Y ; save dimension value high byte + INY ; index to dimension value high byte + TXA ; get dimension value low byte + STA (Astrtl),Y ; save dimension value low byte + JSR LAB_1F7C ; does XY = (Astrtl),Y * (Asptl) + STX Asptl ; save array data size low byte + STA Aspth ; save array data size high byte + LDY ut1_pl ; restore index (saved by subroutine) + DEC Dimcnt ; decrement dimensions count + BNE LAB_1EC0 ; loop while not = 0 + + ADC Adatah ; add size high byte to first element high byte + ; (carry is always clear here) + BCS LAB_1F45 ; if overflow go do "Out of memory" error + + STA Adatah ; save end of array high byte + TAY ; copy end high byte to Y + TXA ; get array size low byte + ADC Adatal ; add array start low byte + BCC LAB_1EF3 ; branch if no carry + + INY ; else increment end of array high byte + BEQ LAB_1F45 ; if overflow go do "Out of memory" error + + ; set-up mostly complete, now zero the array +LAB_1EF3 + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + STA Earryl ; save array mem end low byte + STY Earryh ; save array mem end high byte + LDA #$00 ; clear byte for array clear + INC Aspth ; increment array size high byte (now block count) + LDY Asptl ; get array size low byte (now index to block) + BEQ LAB_1F07 ; branch if low byte = $00 + +LAB_1F02 + DEY ; decrement index (do 0 to n-1) + STA (Adatal),Y ; zero byte + BNE LAB_1F02 ; loop until this block done + +LAB_1F07 + DEC Adatah ; decrement array pointer high byte + DEC Aspth ; decrement block count high byte + BNE LAB_1F02 ; loop until all blocks done + + INC Adatah ; correct for last loop + SEC ; set carry for subtract + LDY #$02 ; index to array size low byte + LDA Earryl ; get array mem end low byte + SBC Astrtl ; subtract array start low byte + STA (Astrtl),Y ; save array size low byte + INY ; index to array size high byte + LDA Earryh ; get array mem end high byte + SBC Astrth ; subtract array start high byte + STA (Astrtl),Y ; save array size high byte + LDA Defdim ; get default DIM flag + BNE LAB_1F7B ; exit (RET) if this was a DIM command + + ; else, find element + INY ; index to # of dimensions + +LAB_1F24 + LDA (Astrtl),Y ; get array's dimension count + STA Dimcnt ; save it + +; we have found, or built, the array. now we need to find the element + +LAB_1F28 + LDA #$00 ; clear byte + STA Asptl ; clear array data pointer low byte +LAB_1F2C + STA Aspth ; save array data pointer high byte + INY ; increment index (point to array bound high byte) + PLA ; pull array index low byte + TAX ; copy to X + STA FAC1_2 ; save index low byte to FAC1 mantissa2 + PLA ; pull array index high byte + STA FAC1_3 ; save index high byte to FAC1 mantissa3 + CMP (Astrtl),Y ; compare with array bound high byte + BCC LAB_1F48 ; branch if within bounds + + BNE LAB_1F42 ; if outside bounds do array bounds error + + ; else high byte was = so test low bytes + INY ; index to array bound low byte + TXA ; get array index low byte + CMP (Astrtl),Y ; compare with array bound low byte + BCC LAB_1F49 ; branch if within bounds + +LAB_1F42 + JMP LAB_1E85 ; else do array bounds error + +LAB_1F45 + JMP LAB_OMER ; do "Out of memory" error then warm start + +LAB_1F48 + INY ; index to array bound low byte +LAB_1F49 + LDA Aspth ; get array data pointer high byte + ORA Asptl ; OR with array data pointer low byte + BEQ LAB_1F5A ; branch if array data pointer = null (skip multiply) + + JSR LAB_1F7C ; does XY = (Astrtl),Y * (Asptl) + TXA ; get result low byte + ADC FAC1_2 ; add index low byte from FAC1 mantissa2 + TAX ; save result low byte + TYA ; get result high byte + LDY ut1_pl ; restore index +LAB_1F5A + ADC FAC1_3 ; add index high byte from FAC1 mantissa3 + STX Asptl ; save array data pointer low byte + DEC Dimcnt ; decrement dimensions count + BNE LAB_1F2C ; loop if dimensions still to do + + ASL Asptl ; array data pointer low byte * 2 + ROL ; array data pointer high byte * 2 + ASL Asptl ; array data pointer low byte * 4 + ROL ; array data pointer high byte * 4 + TAY ; copy high byte + LDA Asptl ; get low byte + ADC Adatal ; add array data start pointer low byte + STA Cvaral ; save as current var address low byte + TYA ; get high byte back + ADC Adatah ; add array data start pointer high byte + STA Cvarah ; save as current var address high byte + TAY ; copy high byte to Y + LDA Cvaral ; get current var address low byte +LAB_1F7B + RTS + +; does XY = (Astrtl),Y * (Asptl) + +LAB_1F7C + STY ut1_pl ; save index + LDA (Astrtl),Y ; get dimension size low byte + STA dims_l ; save dimension size low byte + DEY ; decrement index + LDA (Astrtl),Y ; get dimension size high byte + STA dims_h ; save dimension size high byte + + LDA #$10 ; count = $10 (16 bit multiply) + STA numbit ; save bit count + LDX #$00 ; clear result low byte + LDY #$00 ; clear result high byte +LAB_1F8F + TXA ; get result low byte + ASL ; *2 + TAX ; save result low byte + TYA ; get result high byte + ROL ; *2 + TAY ; save result high byte + BCS LAB_1F45 ; if overflow go do "Out of memory" error + + ASL Asptl ; shift multiplier low byte + ROL Aspth ; shift multiplier high byte + BCC LAB_1FA8 ; skip add if no carry + + CLC ; else clear carry for add + TXA ; get result low byte + ADC dims_l ; add dimension size low byte + TAX ; save result low byte + TYA ; get result high byte + ADC dims_h ; add dimension size high byte + TAY ; save result high byte + BCS LAB_1F45 ; if overflow go do "Out of memory" error + +LAB_1FA8 + DEC numbit ; decrement bit count + BNE LAB_1F8F ; loop until all done + + RTS + +; perform FRE() + +LAB_FRE + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + BPL LAB_1FB4 ; branch if numeric + + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=$71=pointer low byte, + ; Y=$72=pointer high byte + + ; FRE(n) was numeric so do this +LAB_1FB4 + JSR LAB_GARB ; go do garbage collection + SEC ; set carry for subtract + LDA Sstorl ; get bottom of string space low byte + SBC Earryl ; subtract array mem end low byte + TAY ; copy result to Y + LDA Sstorh ; get bottom of string space high byte + SBC Earryh ; subtract array mem end high byte + +; save and convert integer AY to FAC1 + +LAB_AYFC + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + STA FAC1_1 ; save FAC1 mantissa1 + STY FAC1_2 ; save FAC1 mantissa2 + LDX #$90 ; set exponent=2^16 (integer) + JMP LAB_27E3 ; set exp=X, clear FAC1_3, normalise and return + +; perform POS() + +LAB_POS + LDY TPos ; get terminal position + +; convert Y to byte in FAC1 + +LAB_1FD0 + LDA #$00 ; clear high byte + BEQ LAB_AYFC ; always save and convert integer AY to FAC1 and return + +; check not Direct (used by DEF and INPUT) + +LAB_CKRN + LDX Clineh ; get current line high byte + INX ; increment it + BNE LAB_1F7B ; return if can continue not direct mode + + ; else do illegal direct error +LAB_1FD9 + LDX #$16 ; error code $16 ("Illegal direct" error) +LAB_1FDB + JMP LAB_XERR ; go do error #X, then warm start + +; perform DEF + +LAB_DEF + JSR LAB_200B ; check FNx syntax + STA func_l ; save function pointer low byte + STY func_h ; save function pointer high byte + JSR LAB_CKRN ; check not Direct (back here if ok) + JSR LAB_1BFE ; scan for "(" , else do syntax error then warm start + LDA #$80 ; set flag for FNx + STA Sufnxf ; save subscript/FNx flag + JSR LAB_GVAR ; get (var) address + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + LDA #TK_EQUAL ; get = token + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + LDA Cvarah ; get current var address high byte + PHA ; push it + LDA Cvaral ; get current var address low byte + PHA ; push it + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push it + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push it + JSR LAB_DATA ; go perform DATA + JMP LAB_207A ; put execute pointer and variable pointer into function + ; and return + +; check FNx syntax + +LAB_200B + LDA #TK_FN ; get FN" token + JSR LAB_SCCA ; scan for CHR$(A) , else do syntax error then warm start + ; return character after A + ORA #$80 ; set FN flag bit + STA Sufnxf ; save FN flag so array variable test fails + JSR LAB_1D12 ; search for FN variable + JMP LAB_CTNM ; check if source is numeric and return, else do type + ; mismatch + + ; Evaluate FNx +LAB_201E + JSR LAB_200B ; check FNx syntax + PHA ; push function pointer low byte + TYA ; copy function pointer high byte + PHA ; push function pointer high byte + JSR LAB_1BFE ; scan for "(", else do syntax error then warm start + JSR LAB_EVEX ; evaluate expression + JSR LAB_1BFB ; scan for ")", else do syntax error then warm start + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + PLA ; pop function pointer high byte + STA func_h ; restore it + PLA ; pop function pointer low byte + STA func_l ; restore it + LDX #$20 ; error code $20 ("Undefined function" error) + LDY #$03 ; index to variable pointer high byte + LDA (func_l),Y ; get variable pointer high byte + BEQ LAB_1FDB ; if zero go do undefined function error + + STA Cvarah ; save variable address high byte + DEY ; index to variable address low byte + LDA (func_l),Y ; get variable address low byte + STA Cvaral ; save variable address low byte + TAX ; copy address low byte + + ; now stack the function variable value before use + INY ; index to mantissa_3 +LAB_2043 + LDA (Cvaral),Y ; get byte from variable + PHA ; stack it + DEY ; decrement index + BPL LAB_2043 ; loop until variable stacked + + LDY Cvarah ; get variable address high byte + JSR LAB_2778 ; pack FAC1 (function expression value) into (XY) + ; (function variable), return Y=0, always + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push it + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push it + LDA (func_l),Y ; get function execute pointer low byte + STA Bpntrl ; save as BASIC execute pointer low byte + INY ; index to high byte + LDA (func_l),Y ; get function execute pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + LDA Cvarah ; get variable address high byte + PHA ; push it + LDA Cvaral ; get variable address low byte + PHA ; push it + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + PLA ; pull variable address low byte + STA func_l ; save variable address low byte + PLA ; pull variable address high byte + STA func_h ; save variable address high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_2074 ; branch if null (should be [EOL] marker) + + JMP LAB_SNER ; else syntax error then warm start + +; restore Bpntrl,Bpntrh and function variable from stack + +LAB_2074 + PLA ; pull BASIC execute pointer low byte + STA Bpntrl ; restore BASIC execute pointer low byte + PLA ; pull BASIC execute pointer high byte + STA Bpntrh ; restore BASIC execute pointer high byte + +; put execute pointer and variable pointer into function + +LAB_207A + LDY #$00 ; clear index + PLA ; pull BASIC execute pointer low byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull BASIC execute pointer high byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull current var address low byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull current var address high byte + STA (func_l),Y ; save to function + RTS + +; perform STR$() + +LAB_STRS + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + JSR LAB_296E ; convert FAC1 to string + LDA #Decssp1 ; set result string high pointer + BEQ LAB_20AE ; print null terminated string to Sutill/Sutilh + +; Do string vector +; copy des_pl/h to des_2l/h and make string space A bytes long + +LAB_209C + LDX des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + STX des_2l ; save descriptor pointer low byte + STY des_2h ; save descriptor pointer high byte + +; make string space A bytes long +; A=length, X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + +LAB_MSSP + JSR LAB_2115 ; make space in string memory for string A long + ; return X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + STA str_ln ; save length + RTS + +; Scan, set up string +; print " terminated string to Sutill/Sutilh + +LAB_20AE + LDX #$22 ; set terminator to " + STX Srchc ; set search character (terminator 1) + STX Asrch ; set terminator 2 + +; print [Srchc] or [Asrch] terminated string to Sutill/Sutilh +; source is AY + +LAB_20B4 + STA ssptr_l ; store string start low byte + STY ssptr_h ; store string start high byte + STA str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + LDY #$FF ; set length to -1 +LAB_20BE + INY ; increment length + LDA (ssptr_l),Y ; get byte from string + BEQ LAB_20CF ; exit loop if null byte [EOS] + + CMP Srchc ; compare with search character (terminator 1) + BEQ LAB_20CB ; branch if terminator + + CMP Asrch ; compare with terminator 2 + BNE LAB_20BE ; loop if not terminator 2 + +LAB_20CB + CMP #$22 ; compare with " + BEQ LAB_20D0 ; branch if " (carry set if = !) + +LAB_20CF + CLC ; clear carry for add (only if [EOL] terminated string) +LAB_20D0 + STY str_ln ; save length in FAC1 exponent + TYA ; copy length to A + ADC ssptr_l ; add string start low byte + STA Sendl ; save string end low byte + LDX ssptr_h ; get string start high byte + BCC LAB_20DC ; branch if no low byte overflow + + INX ; else increment high byte +LAB_20DC + STX Sendh ; save string end high byte + LDA ssptr_h ; get string start high byte + CMP #>Ram_base ; compare with start of program memory + BCS LAB_RTST ; branch if not in utility area + + ; string in utility area, move to string memory + TYA ; copy length to A + JSR LAB_209C ; copy des_pl/h to des_2l/h and make string space A bytes + ; long + LDX ssptr_l ; get string start low byte + LDY ssptr_h ; get string start high byte + JSR LAB_2298 ; store string A bytes long from XY to (Sutill) + +; check for space on descriptor stack then .. +; put string address and length on descriptor stack and update stack pointers + +LAB_RTST + LDX next_s ; get string stack pointer + CPX #des_sk+$09 ; compare with max+1 + BNE LAB_20F8 ; branch if space on string stack + + ; else do string too complex error + LDX #$1C ; error code $1C ("String too complex" error) +LAB_20F5 + JMP LAB_XERR ; do error #X, then warm start + +; put string address and length on descriptor stack and update stack pointers + +LAB_20F8 + LDA str_ln ; get string length + STA PLUS_0,X ; put on string stack + LDA str_pl ; get string pointer low byte + STA PLUS_1,X ; put on string stack + LDA str_ph ; get string pointer high byte + STA PLUS_2,X ; put on string stack + LDY #$00 ; clear Y + STX des_pl ; save string descriptor pointer low byte + STY des_ph ; save string descriptor pointer high byte (always $00) + DEY ; Y = $FF + STY Dtypef ; save data type flag, $FF=string + STX last_sl ; save old stack pointer (current top item) + INX ; update stack pointer + INX ; update stack pointer + INX ; update stack pointer + STX next_s ; save new top item value + RTS + +; Build descriptor +; make space in string memory for string A long +; return X=Sutill=ptr low byte, Y=Sutill=ptr high byte + +LAB_2115 + LSR Gclctd ; clear garbage collected flag (b7) + + ; make space for string A long +LAB_2117 + PHA ; save string length + EOR #$FF ; complement it + SEC ; set carry for subtract (twos comp add) + ADC Sstorl ; add bottom of string space low byte (subtract length) + LDY Sstorh ; get bottom of string space high byte + BCS LAB_2122 ; skip decrement if no underflow + + DEY ; decrement bottom of string space high byte +LAB_2122 + CPY Earryh ; compare with array mem end high byte + BCC LAB_2137 ; do out of memory error if less + + BNE LAB_212C ; if not = skip next test + + CMP Earryl ; compare with array mem end low byte + BCC LAB_2137 ; do out of memory error if less + +LAB_212C + STA Sstorl ; save bottom of string space low byte + STY Sstorh ; save bottom of string space high byte + STA Sutill ; save string utility ptr low byte + STY Sutilh ; save string utility ptr high byte + TAX ; copy low byte to X + PLA ; get string length back + RTS + +LAB_2137 + LDX #$0C ; error code $0C ("Out of memory" error) + LDA Gclctd ; get garbage collected flag + BMI LAB_20F5 ; if set then do error code X + + JSR LAB_GARB ; else go do garbage collection + LDA #$80 ; flag for garbage collected + STA Gclctd ; set garbage collected flag + PLA ; pull length + BNE LAB_2117 ; go try again (loop always, length should never be = $00) + +; garbage collection routine + +LAB_GARB + LDX Ememl ; get end of mem low byte + LDA Ememh ; get end of mem high byte + +; re-run routine from last ending + +LAB_214B + STX Sstorl ; set string storage low byte + STA Sstorh ; set string storage high byte + LDY #$00 ; clear index + STY garb_h ; clear working pointer high byte (flag no strings to move) + LDA Earryl ; get array mem end low byte + LDX Earryh ; get array mem end high byte + STA Histrl ; save as highest string low byte + STX Histrh ; save as highest string high byte + LDA #des_sk ; set descriptor stack pointer + STA ut1_pl ; save descriptor stack pointer low byte + STY ut1_ph ; save descriptor stack pointer high byte ($00) +LAB_2161 + CMP next_s ; compare with descriptor stack pointer + BEQ LAB_216A ; branch if = + + JSR LAB_21D7 ; go garbage collect descriptor stack + BEQ LAB_2161 ; loop always + + ; done stacked strings, now do string vars +LAB_216A + ASL g_step ; set step size = $06 + LDA Svarl ; get start of vars low byte + LDX Svarh ; get start of vars high byte + STA ut1_pl ; save as pointer low byte + STX ut1_ph ; save as pointer high byte +LAB_2176 + CPX Sarryh ; compare start of arrays high byte + BNE LAB_217E ; branch if no high byte match + + CMP Sarryl ; else compare start of arrays low byte + BEQ LAB_2183 ; branch if = var mem end + +LAB_217E + JSR LAB_21D1 ; go garbage collect strings + BEQ LAB_2176 ; loop always + + ; done string vars, now do string arrays +LAB_2183 + STA Nbendl ; save start of arrays low byte as working pointer + STX Nbendh ; save start of arrays high byte as working pointer + LDA #$04 ; set step size + STA g_step ; save step size +LAB_218B + LDA Nbendl ; get pointer low byte + LDX Nbendh ; get pointer high byte +LAB_218F + CPX Earryh ; compare with array mem end high byte + BNE LAB_219A ; branch if not at end + + CMP Earryl ; else compare with array mem end low byte + BEQ LAB_2216 ; tidy up and exit if at end + +LAB_219A + STA ut1_pl ; save pointer low byte + STX ut1_ph ; save pointer high byte + LDY #$02 ; set index + LDA (ut1_pl),Y ; get array size low byte + ADC Nbendl ; add start of this array low byte + STA Nbendl ; save start of next array low byte + INY ; increment index + LDA (ut1_pl),Y ; get array size high byte + ADC Nbendh ; add start of this array high byte + STA Nbendh ; save start of next array high byte + LDY #$01 ; set index + LDA (ut1_pl),Y ; get name second byte + BPL LAB_218B ; skip if not string array + +; was string array so .. + + LDY #$04 ; set index + LDA (ut1_pl),Y ; get # of dimensions + ASL ; *2 + ADC #$05 ; +5 (array header size) + JSR LAB_2208 ; go set up for first element +LAB_21C4 + CPX Nbendh ; compare with start of next array high byte + BNE LAB_21CC ; branch if <> (go do this array) + + CMP Nbendl ; else compare element pointer low byte with next array + ; low byte + BEQ LAB_218F ; if equal then go do next array + +LAB_21CC + JSR LAB_21D7 ; go defrag array strings + BEQ LAB_21C4 ; go do next array string (loop always) + +; defrag string variables +; enter with XA = variable pointer +; return with XA = next variable pointer + +LAB_21D1 + INY ; increment index (Y was $00) + LDA (ut1_pl),Y ; get var name byte 2 + BPL LAB_2206 ; if not string, step pointer to next var and return + + INY ; else increment index +LAB_21D7 + LDA (ut1_pl),Y ; get string length + BEQ LAB_2206 ; if null, step pointer to next string and return + + INY ; else increment index + LDA (ut1_pl),Y ; get string pointer low byte + TAX ; copy to X + INY ; increment index + LDA (ut1_pl),Y ; get string pointer high byte + CMP Sstorh ; compare bottom of string space high byte + BCC LAB_21EC ; branch if less + + BNE LAB_2206 ; if greater, step pointer to next string and return + + ; high bytes were = so compare low bytes + CPX Sstorl ; compare bottom of string space low byte + BCS LAB_2206 ; if >=, step pointer to next string and return + + ; string pointer is < string storage pointer (pos in mem) +LAB_21EC + CMP Histrh ; compare to highest string high byte + BCC LAB_2207 ; if <, step pointer to next string and return + + BNE LAB_21F6 ; if > update pointers, step to next and return + + ; high bytes were = so compare low bytes + CPX Histrl ; compare to highest string low byte + BCC LAB_2207 ; if <, step pointer to next string and return + + ; string is in string memory space +LAB_21F6 + STX Histrl ; save as new highest string low byte + STA Histrh ; save as new highest string high byte + LDA ut1_pl ; get start of vars(descriptors) low byte + LDX ut1_ph ; get start of vars(descriptors) high byte + STA garb_l ; save as working pointer low byte + STX garb_h ; save as working pointer high byte + DEY ; decrement index DIFFERS + DEY ; decrement index (should point to descriptor start) + STY g_indx ; save index pointer + + ; step pointer to next string +LAB_2206 + CLC ; clear carry for add +LAB_2207 + LDA g_step ; get step size +LAB_2208 + ADC ut1_pl ; add pointer low byte + STA ut1_pl ; save pointer low byte + BCC LAB_2211 ; branch if no overflow + + INC ut1_ph ; else increment high byte +LAB_2211 + LDX ut1_ph ; get pointer high byte + LDY #$00 ; clear Y + RTS + +; search complete, now either exit or set-up and move string + +LAB_2216 + DEC g_step ; decrement step size (now $03 for descriptor stack) + LDX garb_h ; get string to move high byte + BEQ LAB_2211 ; exit if nothing to move + + LDY g_indx ; get index byte back (points to descriptor) + CLC ; clear carry for add + LDA (garb_l),Y ; get string length + ADC Histrl ; add highest string low byte + STA Obendl ; save old block end low pointer + LDA Histrh ; get highest string high byte + ADC #$00 ; add any carry + STA Obendh ; save old block end high byte + LDA Sstorl ; get bottom of string space low byte + LDX Sstorh ; get bottom of string space high byte + STA Nbendl ; save new block end low byte + STX Nbendh ; save new block end high byte + JSR LAB_11D6 ; open up space in memory, don't set array end + LDY g_indx ; get index byte + INY ; point to descriptor low byte + LDA Nbendl ; get string pointer low byte + STA (garb_l),Y ; save new string pointer low byte + TAX ; copy string pointer low byte + INC Nbendh ; correct high byte (move sets high byte -1) + LDA Nbendh ; get new string pointer high byte + INY ; point to descriptor high byte + STA (garb_l),Y ; save new string pointer high byte + JMP LAB_214B ; re-run routine from last ending + ; (but don't collect this string) + +; concatenate +; add strings, string 1 is in descriptor des_pl, string 2 is in line + +LAB_224D + LDA des_ph ; get descriptor pointer high byte + PHA ; put on stack + LDA des_pl ; get descriptor pointer low byte + PHA ; put on stack + JSR LAB_GVAL ; get value from line + JSR LAB_CTST ; check if source is string, else do type mismatch + PLA ; get descriptor pointer low byte back + STA ssptr_l ; set pointer low byte + PLA ; get descriptor pointer high byte back + STA ssptr_h ; set pointer high byte + LDY #$00 ; clear index + LDA (ssptr_l),Y ; get length_1 from descriptor + CLC ; clear carry for add + ADC (des_pl),Y ; add length_2 + BCC LAB_226D ; branch if no overflow + + LDX #$1A ; else set error code $1A ("String too long" error) + JMP LAB_XERR ; do error #X, then warm start + +LAB_226D + JSR LAB_209C ; copy des_pl/h to des_2l/h and make string space A bytes + ; long + JSR LAB_228A ; copy string from descriptor (sdescr) to (Sutill) + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, ut1_pl = pointer low byte, + ; ut1_ph = pointer high byte + JSR LAB_229C ; store string A bytes long from (ut1_pl) to (Sutill) + LDA ssptr_l ;.set descriptor pointer low byte + LDY ssptr_h ;.set descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=ut1_pl=pointer low byte, + ; Y=ut1_ph=pointer high byte + JSR LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + JMP LAB_1ADB ;.continue evaluation + +; copy string from descriptor (sdescr) to (Sutill) + +LAB_228A + LDY #$00 ; clear index + LDA (sdescr),Y ; get string length + PHA ; save on stack + INY ; increment index + LDA (sdescr),Y ; get source string pointer low byte + TAX ; copy to X + INY ; increment index + LDA (sdescr),Y ; get source string pointer high byte + TAY ; copy to Y + PLA ; get length back + +; store string A bytes long from YX to (Sutill) + +LAB_2298 + STX ut1_pl ; save source string pointer low byte + STY ut1_ph ; save source string pointer high byte + +; store string A bytes long from (ut1_pl) to (Sutill) + +LAB_229C + TAX ; copy length to index (don't count with Y) + BEQ LAB_22B2 ; branch if = $0 (null string) no need to add zero length + + LDY #$00 ; zero pointer (copy forward) +LAB_22A0 + LDA (ut1_pl),Y ; get source byte + STA (Sutill),Y ; save destination byte + + INY ; increment index + DEX ; decrement counter + BNE LAB_22A0 ; loop while <> 0 + + TYA ; restore length from Y +LAB_22A9 + CLC ; clear carry for add + ADC Sutill ; add string utility ptr low byte + STA Sutill ; save string utility ptr low byte + BCC LAB_22B2 ; branch if no carry + + INC Sutilh ; else increment string utility ptr high byte +LAB_22B2 + RTS + +; evaluate string + +LAB_EVST + JSR LAB_CTST ; check if source is string, else do type mismatch + +; pop string off descriptor stack, or from top of string space +; returns with A = length, X=pointer low byte, Y=pointer high byte + +LAB_22B6 + LDA des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + +; pop (YA) descriptor off stack or from top of string space +; returns with A = length, X=ut1_pl=pointer low byte, Y=ut1_ph=pointer high byte + +LAB_22BA + STA ut1_pl ; save descriptor pointer low byte + STY ut1_ph ; save descriptor pointer high byte + JSR LAB_22EB ; clean descriptor stack, YA = pointer + PHP ; save status flags + LDY #$00 ; clear index + LDA (ut1_pl),Y ; get length from string descriptor + PHA ; put on stack + INY ; increment index + LDA (ut1_pl),Y ; get string pointer low byte from descriptor + TAX ; copy to X + INY ; increment index + LDA (ut1_pl),Y ; get string pointer high byte from descriptor + TAY ; copy to Y + PLA ; get string length back + PLP ; restore status + BNE LAB_22E6 ; branch if pointer <> last_sl,last_sh + + CPY Sstorh ; compare bottom of string space high byte + BNE LAB_22E6 ; branch if <> + + CPX Sstorl ; else compare bottom of string space low byte + BNE LAB_22E6 ; branch if <> + + PHA ; save string length + CLC ; clear carry for add + ADC Sstorl ; add bottom of string space low byte + STA Sstorl ; save bottom of string space low byte + BCC LAB_22E5 ; skip increment if no overflow + + INC Sstorh ; increment bottom of string space high byte +LAB_22E5 + PLA ; restore string length +LAB_22E6 + STX ut1_pl ; save string pointer low byte + STY ut1_ph ; save string pointer high byte + RTS + +; clean descriptor stack, YA = pointer +; checks if AY is on the descriptor stack, if so does a stack discard + +LAB_22EB + CPY last_sh ; compare pointer high byte + BNE LAB_22FB ; exit if <> + + CMP last_sl ; compare pointer low byte + BNE LAB_22FB ; exit if <> + + STA next_s ; save descriptor stack pointer + SBC #$03 ; -3 + STA last_sl ; save low byte -3 + LDY #$00 ; clear high byte +LAB_22FB + RTS + +; perform CHR$() + +LAB_CHRS + JSR LAB_EVBY ; evaluate byte expression, result in X + TXA ; copy to A + PHA ; save character + LDA #$01 ; string is single byte + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + PLA ; get character back + LDY #$00 ; clear index + STA (str_pl),Y ; save byte in string (byte IS string!) + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform LEFT$() + +LAB_LEFT + PHA ; push byte parameter + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + CMP (des_2l),Y ; compare byte parameter with string length + TYA ; clear A + BEQ LAB_2316 ; go do string copy (branch always) + +; perform RIGHT$() + +LAB_RIGHT + PHA ; push byte parameter + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + CLC ; clear carry for add-1 + SBC (des_2l),Y ; subtract string length + EOR #$FF ; invert it (A=LEN(expression$)-l) + +LAB_2316 + BCC LAB_231C ; branch if string length > byte parameter + + LDA (des_2l),Y ; else make parameter = length + TAX ; copy to byte parameter copy + TYA ; clear string start offset +LAB_231C + PHA ; save string start offset +LAB_231D + TXA ; copy byte parameter (or string length if <) +LAB_231E + PHA ; save string length + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=ut1_pl=pointer low byte, + ; Y=ut1_ph=pointer high byte + PLA ; get string length back + TAY ; copy length to Y + PLA ; get string start offset back + CLC ; clear carry for add + ADC ut1_pl ; add start offset to string start pointer low byte + STA ut1_pl ; save string start pointer low byte + BCC LAB_2335 ; branch if no overflow + + INC ut1_ph ; else increment string start pointer high byte +LAB_2335 + TYA ; copy length to A + JSR LAB_229C ; store string A bytes long from (ut1_pl) to (Sutill) + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform MID$() + +LAB_MIDS + PHA ; push byte parameter + LDA #$FF ; set default length = 255 + STA mids_l ; save default length + JSR LAB_GBYT ; scan memory + CMP #')' ; compare with ")" + BEQ LAB_2358 ; branch if = ")" (skip second byte get) + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_GTBY ; get byte parameter (use copy in mids_l) +LAB_2358 + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + DEX ; decrement start index + TXA ; copy to A + PHA ; save string start offset + CLC ; clear carry for sub-1 + LDX #$00 ; clear output string length + SBC (des_2l),Y ; subtract string length + BCS LAB_231D ; if start>string length go do null string + + EOR #$FF ; complement -length + CMP mids_l ; compare byte parameter + BCC LAB_231E ; if length>remaining string go do RIGHT$ + + LDA mids_l ; get length byte + BCS LAB_231E ; go do string copy (branch always) + +; pull string data and byte parameter from stack +; return pointer in des_2l/h, byte in A (and X), Y=0 + +LAB_236F + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + PLA ; pull return address low byte (return address) + STA Fnxjpl ; save functions jump vector low byte + PLA ; pull return address high byte (return address) + STA Fnxjph ; save functions jump vector high byte + PLA ; pull byte parameter + TAX ; copy byte parameter to X + PLA ; pull string pointer low byte + STA des_2l ; save it + PLA ; pull string pointer high byte + STA des_2h ; save it + LDY #$00 ; clear index + TXA ; copy byte parameter + BEQ LAB_23A8 ; if null do function call error then warm start + + INC Fnxjpl ; increment function jump vector low byte + ; (JSR pushes return addr-1. this is all very nice + ; but will go tits up if either call is on a page + ; boundary!) + JMP (Fnxjpl) ; in effect, RTS + +; perform LCASE$() + +LAB_LCASE + JSR LAB_EVST ; evaluate string + STA str_ln ; set string length + TAY ; copy length to Y + BEQ NoString ; branch if null string + + JSR LAB_MSSP ; make string space A bytes long A=length, + ; X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + TAY ; get string length back + +LC_loop + DEY ; decrement index + LDA (ut1_pl),Y ; get byte from string + JSR LAB_1D82 ; is character "A" to "Z" + BCC NoUcase ; branch if not upper case alpha + + ORA #$20 ; convert upper to lower case +NoUcase + STA (Sutill),Y ; save byte back to string + TYA ; test index + BNE LC_loop ; loop if not all done + + BEQ NoString ; tidy up and exit, branch always + +; perform UCASE$() + +LAB_UCASE + JSR LAB_EVST ; evaluate string + STA str_ln ; set string length + TAY ; copy length to Y + BEQ NoString ; branch if null string + + JSR LAB_MSSP ; make string space A bytes long A=length, + ; X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + TAY ; get string length back + +UC_loop + DEY ; decrement index + LDA (ut1_pl),Y ; get byte from string + JSR LAB_CASC ; is character "a" to "z" (or "A" to "Z") + BCC NoLcase ; branch if not alpha + + AND #$DF ; convert lower to upper case +NoLcase + STA (Sutill),Y ; save byte back to string + TYA ; test index + BNE UC_loop ; loop if not all done + +NoString + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform SADD() + +LAB_SADD + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GVAR ; get var address + + JSR LAB_1BFB ; scan for ")", else do syntax error then warm start + JSR LAB_CTST ; check if source is string, else do type mismatch + + LDY #$02 ; index to string pointer high byte + LDA (Cvaral),Y ; get string pointer high byte + TAX ; copy string pointer high byte to X + DEY ; index to string pointer low byte + LDA (Cvaral),Y ; get string pointer low byte + TAY ; copy string pointer low byte to Y + TXA ; copy string pointer high byte to A + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform LEN() + +LAB_LENS + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; evaluate string, get length in Y + +LAB_ESGL + JSR LAB_EVST ; evaluate string + TAY ; copy length to Y + RTS + +; perform ASC() + +LAB_ASC + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + BEQ LAB_23A8 ; if null do function call error then warm start + + LDY #$00 ; set index to first character + LDA (ut1_pl),Y ; get byte + TAY ; copy to Y + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; do function call error then warm start + +LAB_23A8 + JMP LAB_FCER ; do function call error then warm start + +; scan and get byte parameter + +LAB_SGBY + JSR LAB_IGBY ; increment and scan memory + +; get byte parameter + +LAB_GTBY + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + +; evaluate byte expression, result in X + +LAB_EVBY + JSR LAB_EVPI ; evaluate integer expression (no check) + + LDY FAC1_2 ; get FAC1 mantissa2 + BNE LAB_23A8 ; if top byte <> 0 do function call error then warm start + + LDX FAC1_3 ; get FAC1 mantissa3 + JMP LAB_GBYT ; scan memory and return + +; perform VAL() + +LAB_VAL + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + BNE LAB_23C5 ; branch if not null string + + ; string was null so set result = $00 + JMP LAB_24F1 ; clear FAC1 exponent and sign and return + +LAB_23C5 + LDX Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + STX Btmpl ; save BASIC execute pointer low byte + STY Btmph ; save BASIC execute pointer high byte + LDX ut1_pl ; get string pointer low byte + STX Bpntrl ; save as BASIC execute pointer low byte + CLC ; clear carry + ADC ut1_pl ; add string length + STA ut2_pl ; save string end low byte + LDA ut1_ph ; get string pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + ADC #$00 ; add carry to high byte + STA ut2_ph ; save string end high byte + LDY #$00 ; set index to $00 + LDA (ut2_pl),Y ; get string end +1 byte + PHA ; push it + TYA ; clear A + STA (ut2_pl),Y ; terminate string with $00 + JSR LAB_GBYT ; scan memory + JSR LAB_2887 ; get FAC1 from string + PLA ; restore string end +1 byte + LDY #$00 ; set index to zero + STA (ut2_pl),Y ; put string end byte back + +; restore BASIC execute pointer from temp (Btmpl/Btmph) + +LAB_23F3 + LDX Btmpl ; get BASIC execute pointer low byte back + LDY Btmph ; get BASIC execute pointer high byte back + STX Bpntrl ; save BASIC execute pointer low byte + STY Bpntrh ; save BASIC execute pointer high byte + RTS + +; get two parameters for POKE or WAIT + +LAB_GADB + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + +; scan for "," and get byte, else do Syntax error then warm start + +LAB_SCGB + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + LDA Itemph ; save temporary integer high byte + PHA ; on stack + LDA Itempl ; save temporary integer low byte + PHA ; on stack + JSR LAB_GTBY ; get byte parameter + PLA ; pull low byte + STA Itempl ; restore temporary integer low byte + PLA ; pull high byte + STA Itemph ; restore temporary integer high byte + RTS + +; convert float to fixed routine. accepts any value that fits in 24 bits, +ve or +; -ve and converts it into a right truncated integer in Itempl and Itemph + +; save unsigned 16 bit integer part of FAC1 in temporary integer + +LAB_F2FX + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_23A8 ; if >= do function call error then warm start + +LAB_F2FU + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDA FAC1_2 ; get FAC1 mantissa2 + LDY FAC1_3 ; get FAC1 mantissa3 + STY Itempl ; save temporary integer low byte + STA Itemph ; save temporary integer high byte + RTS + +; perform PEEK() + +LAB_PEEK + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + LDX #$00 ; clear index + LDA (Itempl,X) ; get byte via temporary integer (addr) + TAY ; copy byte to Y + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; perform POKE + +LAB_POKE + JSR LAB_GADB ; get two parameters for POKE or WAIT + TXA ; copy byte argument to A + LDX #$00 ; clear index + STA (Itempl,X) ; save byte via temporary integer (addr) + RTS + +; perform DEEK() + +LAB_DEEK + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + LDX #$00 ; clear index + LDA (Itempl,X) ; PEEK low byte + TAY ; copy to Y + INC Itempl ; increment pointer low byte + BNE Deekh ; skip high increment if no rollover + + INC Itemph ; increment pointer high byte +Deekh + LDA (Itempl,X) ; PEEK high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform DOKE + +LAB_DOKE + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + + STY Frnxtl ; save pointer low byte (float to fixed returns word in AY) + STA Frnxth ; save pointer high byte + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + + TYA ; copy value low byte (float to fixed returns word in AY) + LDX #$00 ; clear index + STA (Frnxtl,X) ; POKE low byte + INC Frnxtl ; increment pointer low byte + BNE Dokeh ; skip high increment if no rollover + + INC Frnxth ; increment pointer high byte +Dokeh + LDA Itemph ; get value high byte + STA (Frnxtl,X) ; POKE high byte + JMP LAB_GBYT ; scan memory and return + +; perform SWAP + +LAB_SWAP + JSR LAB_GVAR ; get var1 address + STA Lvarpl ; save var1 address low byte + STY Lvarph ; save var1 address high byte + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; save data type flag + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_GVAR ; get var2 address (pointer in Cvaral/h) + PLA ; pull var1 data type flag + EOR Dtypef ; compare with var2 data type + BPL SwapErr ; exit if not both the same type + + LDY #$03 ; four bytes to swap (either value or descriptor+1) +SwapLp + LDA (Lvarpl),Y ; get byte from var1 + TAX ; save var1 byte + LDA (Cvaral),Y ; get byte from var2 + STA (Lvarpl),Y ; save byte to var1 + TXA ; restore var1 byte + STA (Cvaral),Y ; save byte to var2 + DEY ; decrement index + BPL SwapLp ; loop until done + + RTS + +SwapErr + JMP LAB_1ABC ; do "Type mismatch" error then warm start + +; perform CALL + +LAB_CALL + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + LDA #>CallExit ; set return address high byte + PHA ; put on stack + LDA #8 shifts) + BCC LAB_24A8 ;.go subtract mantissas + +; add 0.5 to FAC1 + +LAB_244E + LDA #LAB_2A96 ; set 0.5 pointer high byte + +; add (AY) to FAC1 + +LAB_246C + JSR LAB_264D ; unpack memory (AY) into FAC2 + +; add FAC2 to FAC1 + +LAB_ADD + BNE LAB_2474 ; branch if FAC1 was not zero + +; copy FAC2 to FAC1 + +LAB_279B + LDA FAC2_s ; get FAC2 sign (b7) + +; save FAC1 sign and copy ABS(FAC2) to FAC1 + +LAB_279D + STA FAC1_s ; save FAC1 sign (b7) + LDX #$04 ; 4 bytes to copy +LAB_27A1 + LDA FAC1_o,X ; get byte from FAC2,X + STA FAC1_e-1,X ; save byte at FAC1,X + DEX ; decrement count + BNE LAB_27A1 ; loop if not all done + + STX FAC1_r ; clear FAC1 rounding byte + RTS + + ; FAC1 is non zero +LAB_2474 + LDX FAC1_r ; get FAC1 rounding byte + STX FAC2_r ; save as FAC2 rounding byte + LDX #FAC2_e ; set index to FAC2 exponent addr + LDA FAC2_e ; get FAC2 exponent +LAB_247C + TAY ; copy exponent + BEQ LAB_244D ; exit if zero + + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent + BEQ LAB_24A8 ; branch if = (go add mantissa) + + BCC LAB_2498 ; branch if < + + ; FAC2>FAC1 + STY FAC1_e ; save FAC1 exponent + LDY FAC2_s ; get FAC2 sign (b7) + STY FAC1_s ; save FAC1 sign (b7) + EOR #$FF ; complement A + ADC #$00 ; +1 (twos complement, carry is set) + LDY #$00 ; clear Y + STY FAC2_r ; clear FAC2 rounding byte + LDX #FAC1_e ; set index to FAC1 exponent addr + BNE LAB_249C ; branch always + +LAB_2498 + LDY #$00 ; clear Y + STY FAC1_r ; clear FAC1 rounding byte +LAB_249C + CMP #$F9 ; compare exponent diff with $F9 + BMI LAB_2467 ; branch if range $79-$F8 + + TAY ; copy exponent difference to Y + LDA FAC1_r ; get FAC1 rounding byte + LSR PLUS_1,X ; shift FAC? mantissa1 + JSR LAB_2592 ; shift FACX Y times right + + ; exponents are equal now do mantissa subtract +LAB_24A8 + BIT FAC_sc ; test sign compare (FAC1 EOR FAC2) + BPL LAB_24F8 ; if = add FAC2 mantissa to FAC1 mantissa and return + + LDY #FAC1_e ; set index to FAC1 exponent addr + CPX #FAC2_e ; compare X to FAC2 exponent addr + BEQ LAB_24B4 ; branch if = + + LDY #FAC2_e ; else set index to FAC2 exponent addr + + ; subtract smaller from bigger (take sign of bigger) +LAB_24B4 + SEC ; set carry for subtract + EOR #$FF ; ones complement A + ADC FAC2_r ; add FAC2 rounding byte + STA FAC1_r ; save FAC1 rounding byte + LDA PLUS_3,Y ; get FACY mantissa3 + SBC PLUS_3,X ; subtract FACX mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + LDA PLUS_2,Y ; get FACY mantissa2 + SBC PLUS_2,X ; subtract FACX mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA PLUS_1,Y ; get FACY mantissa1 + SBC PLUS_1,X ; subtract FACX mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + +; do ABS and normalise FAC1 + +LAB_24D0 + BCS LAB_24D5 ; branch if number is +ve + + JSR LAB_2537 ; negate FAC1 + +; normalise FAC1 + +LAB_24D5 + LDY #$00 ; clear Y + TYA ; clear A + CLC ; clear carry for add +LAB_24D9 + LDX FAC1_1 ; get FAC1 mantissa1 + BNE LAB_251B ; if not zero normalise FAC1 + + LDX FAC1_2 ; get FAC1 mantissa2 + STX FAC1_1 ; save FAC1 mantissa1 + LDX FAC1_3 ; get FAC1 mantissa3 + STX FAC1_2 ; save FAC1 mantissa2 + LDX FAC1_r ; get FAC1 rounding byte + STX FAC1_3 ; save FAC1 mantissa3 + STY FAC1_r ; clear FAC1 rounding byte + ADC #$08 ; add x to exponent offset + CMP #$18 ; compare with $18 (max offset, all bits would be =0) + BNE LAB_24D9 ; loop if not max + +; clear FAC1 exponent and sign + +LAB_24F1 + LDA #$00 ; clear A +LAB_24F3 + STA FAC1_e ; set FAC1 exponent + +; save FAC1 sign + +LAB_24F5 + STA FAC1_s ; save FAC1 sign (b7) + RTS + +; add FAC2 mantissa to FAC1 mantissa + +LAB_24F8 + ADC FAC2_r ; add FAC2 rounding byte + STA FAC1_r ; save FAC1 rounding byte + LDA FAC1_3 ; get FAC1 mantissa3 + ADC FAC2_3 ; add FAC2 mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_2 ; get FAC1 mantissa2 + ADC FAC2_2 ; add FAC2 mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_1 ; get FAC1 mantissa1 + ADC FAC2_1 ; add FAC2 mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + BCS LAB_252A ; if carry then normalise FAC1 for C=1 + + RTS ; else just exit + +LAB_2511 + ADC #$01 ; add 1 to exponent offset + ASL FAC1_r ; shift FAC1 rounding byte + ROL FAC1_3 ; shift FAC1 mantissa3 + ROL FAC1_2 ; shift FAC1 mantissa2 + ROL FAC1_1 ; shift FAC1 mantissa1 + +; normalise FAC1 + +LAB_251B + BPL LAB_2511 ; loop if not normalised + + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent + BCS LAB_24F1 ; branch if underflow (set result = $0) + + EOR #$FF ; complement exponent + ADC #$01 ; +1 (twos complement) + STA FAC1_e ; save FAC1 exponent + +; test and normalise FAC1 for C=0/1 + +LAB_2528 + BCC LAB_2536 ; exit if no overflow + +; normalise FAC1 for C=1 + +LAB_252A + INC FAC1_e ; increment FAC1 exponent + BEQ LAB_2564 ; if zero do overflow error and warm start + + ROR FAC1_1 ; shift FAC1 mantissa1 + ROR FAC1_2 ; shift FAC1 mantissa2 + ROR FAC1_3 ; shift FAC1 mantissa3 + ROR FAC1_r ; shift FAC1 rounding byte +LAB_2536 + RTS + +; negate FAC1 + +LAB_2537 + LDA FAC1_s ; get FAC1 sign (b7) + EOR #$FF ; complement it + STA FAC1_s ; save FAC1 sign (b7) + +; twos complement FAC1 mantissa + +LAB_253D + LDA FAC1_1 ; get FAC1 mantissa1 + EOR #$FF ; complement it + STA FAC1_1 ; save FAC1 mantissa1 + LDA FAC1_2 ; get FAC1 mantissa2 + EOR #$FF ; complement it + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_3 ; get FAC1 mantissa3 + EOR #$FF ; complement it + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_r ; get FAC1 rounding byte + EOR #$FF ; complement it + STA FAC1_r ; save FAC1 rounding byte + INC FAC1_r ; increment FAC1 rounding byte + BNE LAB_2563 ; exit if no overflow + +; increment FAC1 mantissa + +LAB_2559 + INC FAC1_3 ; increment FAC1 mantissa3 + BNE LAB_2563 ; finished if no rollover + + INC FAC1_2 ; increment FAC1 mantissa2 + BNE LAB_2563 ; finished if no rollover + + INC FAC1_1 ; increment FAC1 mantissa1 +LAB_2563 + RTS + +; do overflow error (overflow exit) + +LAB_2564 + LDX #$0A ; error code $0A ("Overflow" error) + JMP LAB_XERR ; do error #X, then warm start + +; shift FCAtemp << A+8 times + +LAB_2569 + LDX #FACt_1-1 ; set offset to FACtemp +LAB_256B + LDY PLUS_3,X ; get FACX mantissa3 + STY FAC1_r ; save as FAC1 rounding byte + LDY PLUS_2,X ; get FACX mantissa2 + STY PLUS_3,X ; save FACX mantissa3 + LDY PLUS_1,X ; get FACX mantissa1 + STY PLUS_2,X ; save FACX mantissa2 + LDY FAC1_o ; get FAC1 overflow byte + STY PLUS_1,X ; save FACX mantissa1 + +; shift FACX -A times right (> 8 shifts) + +LAB_257B + ADC #$08 ; add 8 to shift count + BMI LAB_256B ; go do 8 shift if still -ve + + BEQ LAB_256B ; go do 8 shift if zero + + SBC #$08 ; else subtract 8 again + TAY ; save count to Y + LDA FAC1_r ; get FAC1 rounding byte + BCS LAB_259A ;. + +LAB_2588 + ASL PLUS_1,X ; shift FACX mantissa1 + BCC LAB_258E ; branch if +ve + + INC PLUS_1,X ; this sets b7 eventually +LAB_258E + ROR PLUS_1,X ; shift FACX mantissa1 (correct for ASL) + ROR PLUS_1,X ; shift FACX mantissa1 (put carry in b7) + +; shift FACX Y times right + +LAB_2592 + ROR PLUS_2,X ; shift FACX mantissa2 + ROR PLUS_3,X ; shift FACX mantissa3 + ROR ; shift FACX rounding byte + INY ; increment exponent diff + BNE LAB_2588 ; branch if range adjust not complete + +LAB_259A + CLC ; just clear it + RTS + +; perform LOG() + +LAB_LOG + JSR LAB_27CA ; test sign and zero + BEQ LAB_25C4 ; if zero do function call error then warm start + + BPL LAB_25C7 ; skip error if +ve + +LAB_25C4 + JMP LAB_FCER ; do function call error then warm start (-ve) + +LAB_25C7 + LDA FAC1_e ; get FAC1 exponent + SBC #$7F ; normalise it + PHA ; save it + LDA #$80 ; set exponent to zero + STA FAC1_e ; save FAC1 exponent + LDA #LAB_25AD ; set 1/root2 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 (1/root2) + LDA #LAB_25B1 ; set root2 pointer high byte + JSR LAB_26CA ; convert AY and do (AY)/FAC1 (root2/(x+(1/root2))) + LDA #LAB_259C ; set 1 pointer high byte + JSR LAB_2455 ; subtract (AY) from FAC1 ((root2/(x+(1/root2)))-1) + LDA #LAB_25A0 ; set pointer high byte to counter + JSR LAB_2B6E ; ^2 then series evaluation + LDA #LAB_25B5 ; set -0.5 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + PLA ; restore FAC1 exponent + JSR LAB_2912 ; evaluate new ASCII digit + LDA #LAB_25B9 ; set LOG(2) pointer high byte + +; do convert AY, FCA1*(AY) + +LAB_25FB + JSR LAB_264D ; unpack memory (AY) into FAC2 +LAB_MULTIPLY + BEQ LAB_264C ; exit if zero + + JSR LAB_2673 ; test and adjust accumulators + LDA #$00 ; clear A + STA FACt_1 ; clear temp mantissa1 + STA FACt_2 ; clear temp mantissa2 + STA FACt_3 ; clear temp mantissa3 + LDA FAC1_r ; get FAC1 rounding byte + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_3 ; get FAC1 mantissa3 + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_2 ; get FAC1 mantissa2 + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_1 ; get FAC1 mantissa1 + JSR LAB_2627 ; go do shift/add FAC2 + JMP LAB_273C ; copy temp to FAC1, normalise and return + +LAB_2622 + BNE LAB_2627 ; branch if byte <> zero + + JMP LAB_2569 ; shift FCAtemp << A+8 times + + ; else do shift and add +LAB_2627 + LSR ; shift byte + ORA #$80 ; set top bit (mark for 8 times) +LAB_262A + TAY ; copy result + BCC LAB_2640 ; skip next if bit was zero + + CLC ; clear carry for add + LDA FACt_3 ; get temp mantissa3 + ADC FAC2_3 ; add FAC2 mantissa3 + STA FACt_3 ; save temp mantissa3 + LDA FACt_2 ; get temp mantissa2 + ADC FAC2_2 ; add FAC2 mantissa2 + STA FACt_2 ; save temp mantissa2 + LDA FACt_1 ; get temp mantissa1 + ADC FAC2_1 ; add FAC2 mantissa1 + STA FACt_1 ; save temp mantissa1 +LAB_2640 + ROR FACt_1 ; shift temp mantissa1 + ROR FACt_2 ; shift temp mantissa2 + ROR FACt_3 ; shift temp mantissa3 + ROR FAC1_r ; shift temp rounding byte + TYA ; get byte back + LSR ; shift byte + BNE LAB_262A ; loop if all bits not done + +LAB_264C + RTS + +; unpack memory (AY) into FAC2 + +LAB_264D + STA ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; 4 bytes to get (0-3) + LDA (ut1_pl),Y ; get mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + DEY ; decrement index + LDA (ut1_pl),Y ; get mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + DEY ; decrement index + LDA (ut1_pl),Y ; get mantissa1+sign + STA FAC2_s ; save FAC2 sign (b7) + EOR FAC1_s ; EOR with FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + LDA FAC2_s ; recover FAC2 sign (b7) + ORA #$80 ; set 1xxx xxx (set normal bit) + STA FAC2_1 ; save FAC2 mantissa1 + DEY ; decrement index + LDA (ut1_pl),Y ; get exponent byte + STA FAC2_e ; save FAC2 exponent + LDA FAC1_e ; get FAC1 exponent + RTS + +; test and adjust accumulators + +LAB_2673 + LDA FAC2_e ; get FAC2 exponent +LAB_2675 + BEQ LAB_2696 ; branch if FAC2 = $00 (handle underflow) + + CLC ; clear carry for add + ADC FAC1_e ; add FAC1 exponent + BCC LAB_2680 ; branch if sum of exponents <$0100 + + BMI LAB_269B ; do overflow error + + CLC ; clear carry for the add + .byte $2C ; makes next line BIT $1410 +LAB_2680 + BPL LAB_2696 ; if +ve go handle underflow + + ADC #$80 ; adjust exponent + STA FAC1_e ; save FAC1 exponent + BNE LAB_268B ; branch if not zero + + JMP LAB_24F5 ; save FAC1 sign and return + +LAB_268B + LDA FAC_sc ; get sign compare (FAC1 EOR FAC2) + STA FAC1_s ; save FAC1 sign (b7) +LAB_268F + RTS + +; handle overflow and underflow + +LAB_2690 + LDA FAC1_s ; get FAC1 sign (b7) + BPL LAB_269B ; do overflow error + + ; handle underflow +LAB_2696 + PLA ; pop return address low byte + PLA ; pop return address high byte + JMP LAB_24F1 ; clear FAC1 exponent and sign and return + +; multiply by 10 + +LAB_269E + JSR LAB_27AB ; round and copy FAC1 to FAC2 + TAX ; copy exponent (set the flags) + BEQ LAB_268F ; exit if zero + + CLC ; clear carry for add + ADC #$02 ; add two to exponent (*4) + BCS LAB_269B ; do overflow error if > $FF + + LDX #$00 ; clear byte + STX FAC_sc ; clear sign compare (FAC1 EOR FAC2) + JSR LAB_247C ; add FAC2 to FAC1 (*5) + INC FAC1_e ; increment FAC1 exponent (*10) + BNE LAB_268F ; if non zero just do RTS + +LAB_269B + JMP LAB_2564 ; do overflow error and warm start + +; divide by 10 + +LAB_26B9 + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #LAB_26B5 ; set pointer to 10d high addr + LDX #$00 ; clear sign + +; divide by (AY) (X=sign) + +LAB_26C2 + STX FAC_sc ; save sign compare (FAC1 EOR FAC2) + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + JMP LAB_DIVIDE ; do FAC2/FAC1 + + ; Perform divide-by +; convert AY and do (AY)/FAC1 + +LAB_26CA + JSR LAB_264D ; unpack memory (AY) into FAC2 + + ; Perform divide-into +LAB_DIVIDE + BEQ LAB_2737 ; if zero go do /0 error + + JSR LAB_27BA ; round FAC1 + LDA #$00 ; clear A + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent (2s complement) + STA FAC1_e ; save FAC1 exponent + JSR LAB_2673 ; test and adjust accumulators + INC FAC1_e ; increment FAC1 exponent + BEQ LAB_269B ; if zero do overflow error + + LDX #$FF ; set index for pre increment + LDA #$01 ; set bit to flag byte save +LAB_26E4 + LDY FAC2_1 ; get FAC2 mantissa1 + CPY FAC1_1 ; compare FAC1 mantissa1 + BNE LAB_26F4 ; branch if <> + + LDY FAC2_2 ; get FAC2 mantissa2 + CPY FAC1_2 ; compare FAC1 mantissa2 + BNE LAB_26F4 ; branch if <> + + LDY FAC2_3 ; get FAC2 mantissa3 + CPY FAC1_3 ; compare FAC1 mantissa3 +LAB_26F4 + PHP ; save FAC2-FAC1 compare status + ROL ; shift the result byte + BCC LAB_2702 ; if no carry skip the byte save + + LDY #$01 ; set bit to flag byte save + INX ; else increment the index to FACt + CPX #$02 ; compare with the index to FACt_3 + BMI LAB_2701 ; if not last byte just go save it + + BNE LAB_272B ; if all done go save FAC1 rounding byte, normalise and + ; return + + LDY #$40 ; set bit to flag byte save for the rounding byte +LAB_2701 + STA FACt_1,X ; write result byte to FACt_1 + index + TYA ; copy the next save byte flag +LAB_2702 + PLP ; restore FAC2-FAC1 compare status + BCC LAB_2704 ; if FAC2 < FAC1 then skip the subtract + + TAY ; save FAC2-FAC1 compare status + LDA FAC2_3 ; get FAC2 mantissa3 + SBC FAC1_3 ; subtract FAC1 mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + LDA FAC2_2 ; get FAC2 mantissa2 + SBC FAC1_2 ; subtract FAC1 mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + LDA FAC2_1 ; get FAC2 mantissa1 + SBC FAC1_1 ; subtract FAC1 mantissa1 + STA FAC2_1 ; save FAC2 mantissa1 + TYA ; restore FAC2-FAC1 compare status + + ; FAC2 = FAC2*2 +LAB_2704 + ASL FAC2_3 ; shift FAC2 mantissa3 + ROL FAC2_2 ; shift FAC2 mantissa2 + ROL FAC2_1 ; shift FAC2 mantissa1 + BCS LAB_26F4 ; loop with no compare + + BMI LAB_26E4 ; loop with compare + + BPL LAB_26F4 ; loop always with no compare + +; do A<<6, save as FAC1 rounding byte, normalise and return + +LAB_272B + LSR ; shift b1 - b0 .. + ROR ; .. + ROR ; .. to b7 - b6 + STA FAC1_r ; save FAC1 rounding byte + PLP ; dump FAC2-FAC1 compare status + JMP LAB_273C ; copy temp to FAC1, normalise and return + +; do "Divide by zero" error + +LAB_2737 + LDX #$14 ; error code $14 ("Divide by zero" error) + JMP LAB_XERR ; do error #X, then warm start + +; copy temp to FAC1 and normalise + +LAB_273C + LDA FACt_1 ; get temp mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + LDA FACt_2 ; get temp mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA FACt_3 ; get temp mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + JMP LAB_24D5 ; normalise FAC1 and return + +; unpack memory (AY) into FAC1 + +LAB_UFAC + STA ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; 4 bytes to do + LDA (ut1_pl),Y ; get last byte + STA FAC1_3 ; save FAC1 mantissa3 + DEY ; decrement index + LDA (ut1_pl),Y ; get last-1 byte + STA FAC1_2 ; save FAC1 mantissa2 + DEY ; decrement index + LDA (ut1_pl),Y ; get second byte + STA FAC1_s ; save FAC1 sign (b7) + ORA #$80 ; set 1xxx xxxx (add normal bit) + STA FAC1_1 ; save FAC1 mantissa1 + DEY ; decrement index + LDA (ut1_pl),Y ; get first byte (exponent) + STA FAC1_e ; save FAC1 exponent + STY FAC1_r ; clear FAC1 rounding byte + RTS + +; pack FAC1 into Adatal + +LAB_276E + LDX #Adatal ; set pointer high byte + BEQ LAB_2778 ; pack FAC1 into (XY) and return + +; pack FAC1 into (Lvarpl) + +LAB_PFAC + LDX Lvarpl ; get destination pointer low byte + LDY Lvarph ; get destination pointer high byte + +; pack FAC1 into (XY) + +LAB_2778 + JSR LAB_27BA ; round FAC1 + STX ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; set index + LDA FAC1_3 ; get FAC1 mantissa3 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_2 ; get FAC1 mantissa2 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_s ; get FAC1 sign (b7) + ORA #$7F ; set bits x111 1111 + AND FAC1_1 ; AND in FAC1 mantissa1 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_e ; get FAC1 exponent + STA (ut1_pl),Y ; store in destination + STY FAC1_r ; clear FAC1 rounding byte + RTS + +; round and copy FAC1 to FAC2 + +LAB_27AB + JSR LAB_27BA ; round FAC1 + +; copy FAC1 to FAC2 + +LAB_27AE + LDX #$05 ; 5 bytes to copy +LAB_27B0 + LDA FAC1_e-1,X ; get byte from FAC1,X + STA FAC1_o,X ; save byte at FAC2,X + DEX ; decrement count + BNE LAB_27B0 ; loop if not all done + + STX FAC1_r ; clear FAC1 rounding byte +LAB_27B9 + RTS + +; round FAC1 + +LAB_27BA + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_27B9 ; exit if zero + + ASL FAC1_r ; shift FAC1 rounding byte + BCC LAB_27B9 ; exit if no overflow + +; round FAC1 (no check) + +LAB_27C2 + JSR LAB_2559 ; increment FAC1 mantissa + BNE LAB_27B9 ; branch if no overflow + + JMP LAB_252A ; normalise FAC1 for C=1 and return + +; get FAC1 sign +; return A=FF,C=1/-ve A=01,C=0/+ve + +LAB_27CA + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_27D7 ; exit if zero (already correct SGN(0)=0) + +; return A=FF,C=1/-ve A=01,C=0/+ve +; no = 0 check + +LAB_27CE + LDA FAC1_s ; else get FAC1 sign (b7) + +; return A=FF,C=1/-ve A=01,C=0/+ve +; no = 0 check, sign in A + +LAB_27D0 + ROL ; move sign bit to carry + LDA #$FF ; set byte for -ve result + BCS LAB_27D7 ; return if sign was set (-ve) + + LDA #$01 ; else set byte for +ve result +LAB_27D7 + RTS + +; perform SGN() + +LAB_SGN + JSR LAB_27CA ; get FAC1 sign + ; return A=$FF/-ve A=$01/+ve +; save A as integer byte + +LAB_27DB + STA FAC1_1 ; save FAC1 mantissa1 + LDA #$00 ; clear A + STA FAC1_2 ; clear FAC1 mantissa2 + LDX #$88 ; set exponent + +; set exp=X, clearFAC1 mantissa3 and normalise + +LAB_27E3 + LDA FAC1_1 ; get FAC1 mantissa1 + EOR #$FF ; complement it + ROL ; sign bit into carry + +; set exp=X, clearFAC1 mantissa3 and normalise + +LAB_STFA + LDA #$00 ; clear A + STA FAC1_3 ; clear FAC1 mantissa3 + STX FAC1_e ; set FAC1 exponent + STA FAC1_r ; clear FAC1 rounding byte + STA FAC1_s ; clear FAC1 sign (b7) + JMP LAB_24D0 ; do ABS and normalise FAC1 + +; perform ABS() + +LAB_ABS + LSR FAC1_s ; clear FAC1 sign (put zero in b7) + RTS + +; compare FAC1 with (AY) +; returns A=$00 if FAC1 = (AY) +; returns A=$01 if FAC1 > (AY) +; returns A=$FF if FAC1 < (AY) + +LAB_27F8 + STA ut2_pl ; save pointer low byte +LAB_27FA + STY ut2_ph ; save pointer high byte + LDY #$00 ; clear index + LDA (ut2_pl),Y ; get exponent + INY ; increment index + TAX ; copy (AY) exponent to X + BEQ LAB_27CA ; branch if (AY) exponent=0 and get FAC1 sign + ; A=FF,C=1/-ve A=01,C=0/+ve + + LDA (ut2_pl),Y ; get (AY) mantissa1 (with sign) + EOR FAC1_s ; EOR FAC1 sign (b7) + BMI LAB_27CE ; if signs <> do return A=FF,C=1/-ve + ; A=01,C=0/+ve and return + + CPX FAC1_e ; compare (AY) exponent with FAC1 exponent + BNE LAB_2828 ; branch if different + + LDA (ut2_pl),Y ; get (AY) mantissa1 (with sign) + ORA #$80 ; normalise top bit + CMP FAC1_1 ; compare with FAC1 mantissa1 + BNE LAB_2828 ; branch if different + + INY ; increment index + LDA (ut2_pl),Y ; get mantissa2 + CMP FAC1_2 ; compare with FAC1 mantissa2 + BNE LAB_2828 ; branch if different + + INY ; increment index + LDA #$7F ; set for 1/2 value rounding byte + CMP FAC1_r ; compare with FAC1 rounding byte (set carry) + LDA (ut2_pl),Y ; get mantissa3 + SBC FAC1_3 ; subtract FAC1 mantissa3 + BEQ LAB_2850 ; exit if mantissa3 equal + +; gets here if number <> FAC1 + +LAB_2828 + LDA FAC1_s ; get FAC1 sign (b7) + BCC LAB_282E ; branch if FAC1 > (AY) + + EOR #$FF ; else toggle FAC1 sign +LAB_282E + JMP LAB_27D0 ; return A=FF,C=1/-ve A=01,C=0/+ve + +; convert FAC1 floating-to-fixed + +LAB_2831 + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_287F ; if zero go clear FAC1 and return + + SEC ; set carry for subtract + SBC #$98 ; subtract maximum integer range exponent + BIT FAC1_s ; test FAC1 sign (b7) + BPL LAB_2845 ; branch if FAC1 +ve + + ; FAC1 was -ve + TAX ; copy subtracted exponent + LDA #$FF ; overflow for -ve number + STA FAC1_o ; set FAC1 overflow byte + JSR LAB_253D ; twos complement FAC1 mantissa + TXA ; restore subtracted exponent +LAB_2845 + LDX #FAC1_e ; set index to FAC1 + CMP #$F9 ; compare exponent result + BPL LAB_2851 ; if < 8 shifts shift FAC1 A times right and return + + JSR LAB_257B ; shift FAC1 A times right (> 8 shifts) + STY FAC1_o ; clear FAC1 overflow byte +LAB_2850 + RTS + +; shift FAC1 A times right + +LAB_2851 + TAY ; copy shift count + LDA FAC1_s ; get FAC1 sign (b7) + AND #$80 ; mask sign bit only (x000 0000) + LSR FAC1_1 ; shift FAC1 mantissa1 + ORA FAC1_1 ; OR sign in b7 FAC1 mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + JSR LAB_2592 ; shift FAC1 Y times right + STY FAC1_o ; clear FAC1 overflow byte + RTS + +; perform INT() + +LAB_INT + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with max int + BCS LAB_2886 ; exit if >= (already int, too big for fractional part!) + + JSR LAB_2831 ; convert FAC1 floating-to-fixed + STY FAC1_r ; save FAC1 rounding byte + LDA FAC1_s ; get FAC1 sign (b7) + STY FAC1_s ; save FAC1 sign (b7) + EOR #$80 ; toggle FAC1 sign + ROL ; shift into carry + LDA #$98 ; set new exponent + STA FAC1_e ; save FAC1 exponent + LDA FAC1_3 ; get FAC1 mantissa3 + STA Temp3 ; save for EXP() function + JMP LAB_24D0 ; do ABS and normalise FAC1 + +; clear FAC1 and return + +LAB_287F + STA FAC1_1 ; clear FAC1 mantissa1 + STA FAC1_2 ; clear FAC1 mantissa2 + STA FAC1_3 ; clear FAC1 mantissa3 + TAY ; clear Y +LAB_2886 + RTS + +; get FAC1 from string +; this routine now handles hex and binary values from strings +; starting with "$" and "%" respectively + +LAB_2887 + LDY #$00 ; clear Y + STY Dtypef ; clear data type flag, $FF=string, $00=numeric + LDX #$09 ; set index +LAB_288B + STY numexp,X ; clear byte + DEX ; decrement index + BPL LAB_288B ; loop until numexp to negnum (and FAC1) = $00 + + BCC LAB_28FE ; branch if 1st character numeric + +; get FAC1 from string .. first character wasn't numeric + + CMP #'-' ; else compare with "-" + BNE LAB_289A ; branch if not "-" + + STX negnum ; set flag for -ve number (X = $FF) + BEQ LAB_289C ; branch always (go scan and check for hex/bin) + +; get FAC1 from string .. first character wasn't numeric or - + +LAB_289A + CMP #'+' ; else compare with "+" + BNE LAB_289D ; branch if not "+" (go check for hex/bin) + +; was "+" or "-" to start, so get next character + +LAB_289C + JSR LAB_IGBY ; increment and scan memory + BCC LAB_28FE ; branch if numeric character + +; code here for hex and binary numbers + +LAB_289D + CMP #'$' ; else compare with "$" + BNE LAB_NHEX ; branch if not "$" + + JMP LAB_CHEX ; branch if "$" + +LAB_NHEX + CMP #'%' ; else compare with "%" + BNE LAB_28A3 ; branch if not "%" (continue original code) + + JMP LAB_CBIN ; branch if "%" + +LAB_289E + JSR LAB_IGBY ; increment and scan memory (ignore + or get next number) +LAB_28A1 + BCC LAB_28FE ; branch if numeric character + +; get FAC1 from string .. character wasn't numeric, -, +, hex or binary + +LAB_28A3 + CMP #'.' ; else compare with "." + BEQ LAB_28D5 ; branch if "." + +; get FAC1 from string .. character wasn't numeric, -, + or . + + CMP #'E' ; else compare with "E" + BNE LAB_28DB ; branch if not "E" + + ; was "E" so evaluate exponential part + JSR LAB_IGBY ; increment and scan memory + BCC LAB_28C7 ; branch if numeric character + + CMP #TK_MINUS ; else compare with token for - + BEQ LAB_28C2 ; branch if token for - + + CMP #'-' ; else compare with "-" + BEQ LAB_28C2 ; branch if "-" + + CMP #TK_PLUS ; else compare with token for + + BEQ LAB_28C4 ; branch if token for + + + CMP #'+' ; else compare with "+" + BEQ LAB_28C4 ; branch if "+" + + BNE LAB_28C9 ; branch always + +LAB_28C2 + ROR expneg ; set exponent -ve flag (C, which=1, into b7) +LAB_28C4 + JSR LAB_IGBY ; increment and scan memory +LAB_28C7 + BCC LAB_2925 ; branch if numeric character + +LAB_28C9 + BIT expneg ; test exponent -ve flag + BPL LAB_28DB ; if +ve go evaluate exponent + + ; else do exponent = -exponent + LDA #$00 ; clear result + SEC ; set carry for subtract + SBC expcnt ; subtract exponent byte + JMP LAB_28DD ; go evaluate exponent + +LAB_28D5 + ROR numdpf ; set decimal point flag + BIT numdpf ; test decimal point flag + BVC LAB_289E ; branch if only one decimal point so far + + ; evaluate exponent +LAB_28DB + LDA expcnt ; get exponent count byte +LAB_28DD + SEC ; set carry for subtract + SBC numexp ; subtract numerator exponent + STA expcnt ; save exponent count byte + BEQ LAB_28F6 ; branch if no adjustment + + BPL LAB_28EF ; else if +ve go do FAC1*10^expcnt + + ; else go do FAC1/10^(0-expcnt) +LAB_28E6 + JSR LAB_26B9 ; divide by 10 + INC expcnt ; increment exponent count byte + BNE LAB_28E6 ; loop until all done + + BEQ LAB_28F6 ; branch always + +LAB_28EF + JSR LAB_269E ; multiply by 10 + DEC expcnt ; decrement exponent count byte + BNE LAB_28EF ; loop until all done + +LAB_28F6 + LDA negnum ; get -ve flag + BMI LAB_28FB ; if -ve do - FAC1 and return + + RTS + +; do - FAC1 and return + +LAB_28FB + JMP LAB_GTHAN ; do - FAC1 and return + +; do unsigned FAC1*10+number + +LAB_28FE + PHA ; save character + BIT numdpf ; test decimal point flag + BPL LAB_2905 ; skip exponent increment if not set + + INC numexp ; else increment number exponent +LAB_2905 + JSR LAB_269E ; multiply FAC1 by 10 + PLA ; restore character + AND #$0F ; convert to binary + JSR LAB_2912 ; evaluate new ASCII digit + JMP LAB_289E ; go do next character + +; evaluate new ASCII digit + +LAB_2912 + PHA ; save digit + JSR LAB_27AB ; round and copy FAC1 to FAC2 + PLA ; restore digit + JSR LAB_27DB ; save A as integer byte + LDA FAC2_s ; get FAC2 sign (b7) + EOR FAC1_s ; toggle with FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + LDX FAC1_e ; get FAC1 exponent + JMP LAB_ADD ; add FAC2 to FAC1 and return + +; evaluate next character of exponential part of number + +LAB_2925 + LDA expcnt ; get exponent count byte + CMP #$0A ; compare with 10 decimal + BCC LAB_2934 ; branch if less + + LDA #$64 ; make all -ve exponents = -100 decimal (causes underflow) + BIT expneg ; test exponent -ve flag + BMI LAB_2942 ; branch if -ve + + JMP LAB_2564 ; else do overflow error + +LAB_2934 + ASL ; * 2 + ASL ; * 4 + ADC expcnt ; * 5 + ASL ; * 10 + LDY #$00 ; set index + ADC (Bpntrl),Y ; add character (will be $30 too much!) + SBC #'0'-1 ; convert character to binary +LAB_2942 + STA expcnt ; save exponent count byte + JMP LAB_28C4 ; go get next character + +; print " in line [LINE #]" + +LAB_2953 + LDA #LAB_LMSG ; point to " in line " message high byte + JSR LAB_18C3 ; print null terminated string from memory + + ; print Basic line # + LDA Clineh ; get current line high byte + LDX Clinel ; get current line low byte + +; print XA as unsigned integer + +LAB_295E + STA FAC1_1 ; save low byte as FAC1 mantissa1 + STX FAC1_2 ; save high byte as FAC1 mantissa2 + LDX #$90 ; set exponent to 16d bits + SEC ; set integer is +ve flag + JSR LAB_STFA ; set exp=X, clearFAC1 mantissa3 and normalise + LDY #$00 ; clear index + TYA ; clear A + JSR LAB_297B ; convert FAC1 to string, skip sign character save + JMP LAB_18C3 ; print null terminated string from memory and return + +; convert FAC1 to ASCII string result in (AY) +; not any more, moved scratchpad to page 0 + +LAB_296E + LDY #$01 ; set index = 1 + LDA #$20 ; character = " " (assume +ve) + BIT FAC1_s ; test FAC1 sign (b7) + BPL LAB_2978 ; branch if +ve + + LDA #$2D ; else character = "-" +LAB_2978 + STA Decss,Y ; save leading character (" " or "-") +LAB_297B + STA FAC1_s ; clear FAC1 sign (b7) + STY Sendl ; save index + INY ; increment index + LDX FAC1_e ; get FAC1 exponent + BNE LAB_2989 ; branch if FAC1<>0 + + ; exponent was $00 so FAC1 is 0 + LDA #'0' ; set character = "0" + JMP LAB_2A89 ; save last character, [EOT] and exit + + ; FAC1 is some non zero value +LAB_2989 + LDA #$00 ; clear (number exponent count) + CPX #$81 ; compare FAC1 exponent with $81 (>1.00000) + + BCS LAB_299A ; branch if FAC1=>1 + + ; FAC1<1 + LDA #LAB_294F ; set pointer high byte to 1,000,000 + JSR LAB_25FB ; do convert AY, FCA1*(AY) + LDA #$FA ; set number exponent count (-6) +LAB_299A + STA numexp ; save number exponent count +LAB_299C + LDA #LAB_294B ; set pointer high byte to 999999.4375 + JSR LAB_27F8 ; compare FAC1 with (AY) + BEQ LAB_29C3 ; exit if FAC1 = (AY) + + BPL LAB_29B9 ; go do /10 if FAC1 > (AY) + + ; FAC1 < (AY) +LAB_29A7 + LDA #LAB_2947 ; set pointer high byte to 99999.9375 + JSR LAB_27F8 ; compare FAC1 with (AY) + BEQ LAB_29B2 ; branch if FAC1 = (AY) (allow decimal places) + + BPL LAB_29C0 ; branch if FAC1 > (AY) (no decimal places) + + ; FAC1 <= (AY) +LAB_29B2 + JSR LAB_269E ; multiply by 10 + DEC numexp ; decrement number exponent count + BNE LAB_29A7 ; go test again (branch always) + +LAB_29B9 + JSR LAB_26B9 ; divide by 10 + INC numexp ; increment number exponent count + BNE LAB_299C ; go test again (branch always) + +; now we have just the digits to do + +LAB_29C0 + JSR LAB_244E ; add 0.5 to FAC1 (round FAC1) +LAB_29C3 + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDX #$01 ; set default digits before dp = 1 + LDA numexp ; get number exponent count + CLC ; clear carry for add + ADC #$07 ; up to 6 digits before point + BMI LAB_29D8 ; if -ve then 1 digit before dp + + CMP #$08 ; A>=8 if n>=1E6 + BCS LAB_29D9 ; branch if >= $08 + + ; carry is clear + ADC #$FF ; take 1 from digit count + TAX ; copy to A + LDA #$02 ;.set exponent adjust +LAB_29D8 + SEC ; set carry for subtract +LAB_29D9 + SBC #$02 ; -2 + STA expcnt ;.save exponent adjust + STX numexp ; save digits before dp count + TXA ; copy to A + BEQ LAB_29E4 ; branch if no digits before dp + + BPL LAB_29F7 ; branch if digits before dp + +LAB_29E4 + LDY Sendl ; get output string index + LDA #$2E ; character "." + INY ; increment index + STA Decss,Y ; save to output string + TXA ;. + BEQ LAB_29F5 ;. + + LDA #'0' ; character "0" + INY ; increment index + STA Decss,Y ; save to output string +LAB_29F5 + STY Sendl ; save output string index +LAB_29F7 + LDY #$00 ; clear index (point to 100,000) + LDX #$80 ; +LAB_29FB + LDA FAC1_3 ; get FAC1 mantissa3 + CLC ; clear carry for add + ADC LAB_2A9C,Y ; add -ve LSB + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_2 ; get FAC1 mantissa2 + ADC LAB_2A9B,Y ; add -ve NMSB + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_1 ; get FAC1 mantissa1 + ADC LAB_2A9A,Y ; add -ve MSB + STA FAC1_1 ; save FAC1 mantissa1 + INX ; + BCS LAB_2A18 ; + + BPL LAB_29FB ; not -ve so try again + + BMI LAB_2A1A ; + +LAB_2A18 + BMI LAB_29FB ; + +LAB_2A1A + TXA ; + BCC LAB_2A21 ; + + EOR #$FF ; + ADC #$0A ; +LAB_2A21 + ADC #'0'-1 ; add "0"-1 to result + INY ; increment index .. + INY ; .. to next less .. + INY ; .. power of ten + STY Cvaral ; save as current var address low byte + LDY Sendl ; get output string index + INY ; increment output string index + TAX ; copy character to X + AND #$7F ; mask out top bit + STA Decss,Y ; save to output string + DEC numexp ; decrement # of characters before the dp + BNE LAB_2A3B ; branch if still characters to do + + ; else output the point + LDA #$2E ; character "." + INY ; increment output string index + STA Decss,Y ; save to output string +LAB_2A3B + STY Sendl ; save output string index + LDY Cvaral ; get current var address low byte + TXA ; get character back + EOR #$FF ; + AND #$80 ; + TAX ; + CPY #$12 ; compare index with max + BNE LAB_29FB ; loop if not max + + ; now remove trailing zeroes + LDY Sendl ; get output string index +LAB_2A4B + LDA Decss,Y ; get character from output string + DEY ; decrement output string index + CMP #'0' ; compare with "0" + BEQ LAB_2A4B ; loop until non "0" character found + + CMP #'.' ; compare with "." + BEQ LAB_2A58 ; branch if was dp + + ; restore last character + INY ; increment output string index +LAB_2A58 + LDA #$2B ; character "+" + LDX expcnt ; get exponent count + BEQ LAB_2A8C ; if zero go set null terminator and exit + + ; exponent isn't zero so write exponent + BPL LAB_2A68 ; branch if exponent count +ve + + LDA #$00 ; clear A + SEC ; set carry for subtract + SBC expcnt ; subtract exponent count adjust (convert -ve to +ve) + TAX ; copy exponent count to X + LDA #'-' ; character "-" +LAB_2A68 + STA Decss+2,Y ; save to output string + LDA #$45 ; character "E" + STA Decss+1,Y ; save exponent sign to output string + TXA ; get exponent count back + LDX #'0'-1 ; one less than "0" character + SEC ; set carry for subtract +LAB_2A74 + INX ; increment 10's character + SBC #$0A ;.subtract 10 from exponent count + BCS LAB_2A74 ; loop while still >= 0 + + ADC #':' ; add character ":" ($30+$0A, result is 10 less that value) + STA Decss+4,Y ; save to output string + TXA ; copy 10's character + STA Decss+3,Y ; save to output string + LDA #$00 ; set null terminator + STA Decss+5,Y ; save to output string + BEQ LAB_2A91 ; go set string pointer (AY) and exit (branch always) + + ; save last character, [EOT] and exit +LAB_2A89 + STA Decss,Y ; save last character to output string + + ; set null terminator and exit +LAB_2A8C + LDA #$00 ; set null terminator + STA Decss+1,Y ; save after last character + + ; set string pointer (AY) and exit +LAB_2A91 + LDA #Decssp1 ; set result string high pointer + RTS + +; perform power function + +LAB_POWER + BEQ LAB_EXP ; go do EXP() + + LDA FAC2_e ; get FAC2 exponent + BNE LAB_2ABF ; branch if FAC2<>0 + + JMP LAB_24F3 ; clear FAC1 exponent and sign and return + +LAB_2ABF + LDX #func_l ; set destination pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) + LDA FAC2_s ; get FAC2 sign (b7) + BPL LAB_2AD9 ; branch if FAC2>0 + + ; else FAC2 is -ve and can only be raised to an + ; integer power which gives an x +j0 result + JSR LAB_INT ; perform INT + LDA #func_l ; set source pointer high byte + JSR LAB_27F8 ; compare FAC1 with (AY) + BNE LAB_2AD9 ; branch if FAC1 <> (AY) to allow Function Call error + ; this will leave FAC1 -ve and cause a Function Call + ; error when LOG() is called + + TYA ; clear sign b7 + LDY Temp3 ; save mantissa 3 from INT() function as sign in Y + ; for possible later negation, b0 +LAB_2AD9 + JSR LAB_279D ; save FAC1 sign and copy ABS(FAC2) to FAC1 + TYA ; copy sign back .. + PHA ; .. and save it + JSR LAB_LOG ; do LOG(n) + LDA #garb_l ; set pointer high byte + JSR LAB_25FB ; do convert AY, FCA1*(AY) (square the value) + JSR LAB_EXP ; go do EXP(n) + PLA ; pull sign from stack + LSR ; b0 is to be tested, shift to Cb + BCC LAB_2AF9 ; if no bit then exit + + ; Perform negation +; do - FAC1 + +LAB_GTHAN + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_2AF9 ; exit if FAC1_e = $00 + + LDA FAC1_s ; get FAC1 sign (b7) + EOR #$FF ; complement it + STA FAC1_s ; save FAC1 sign (b7) +LAB_2AF9 + RTS + +; perform EXP() (x^e) + +LAB_EXP + LDA #LAB_2AFA ; set 1.443 pointer high byte + JSR LAB_25FB ; do convert AY, FCA1*(AY) + LDA FAC1_r ; get FAC1 rounding byte + ADC #$50 ; +$50/$100 + BCC LAB_2B2B ; skip rounding if no carry + + JSR LAB_27C2 ; round FAC1 (no check) +LAB_2B2B + STA FAC2_r ; save FAC2 rounding byte + JSR LAB_27AE ; copy FAC1 to FAC2 + LDA FAC1_e ; get FAC1 exponent + CMP #$88 ; compare with EXP limit (256d) + BCC LAB_2B39 ; branch if less + +LAB_2B36 + JSR LAB_2690 ; handle overflow and underflow +LAB_2B39 + JSR LAB_INT ; perform INT + LDA Temp3 ; get mantissa 3 from INT() function + CLC ; clear carry for add + ADC #$81 ; normalise +1 + BEQ LAB_2B36 ; if $00 go handle overflow + + SEC ; set carry for subtract + SBC #$01 ; now correct for exponent + PHA ; save FAC2 exponent + + ; swap FAC1 and FAC2 + LDX #$04 ; 4 bytes to do +LAB_2B49 + LDA FAC2_e,X ; get FAC2,X + LDY FAC1_e,X ; get FAC1,X + STA FAC1_e,X ; save FAC1,X + STY FAC2_e,X ; save FAC2,X + DEX ; decrement count/index + BPL LAB_2B49 ; loop if not all done + + LDA FAC2_r ; get FAC2 rounding byte + STA FAC1_r ; save as FAC1 rounding byte + JSR LAB_SUBTRACT ; perform subtraction, FAC2 from FAC1 + JSR LAB_GTHAN ; do - FAC1 + LDA #LAB_2AFE ; set counter pointer high byte + JSR LAB_2B84 ; go do series evaluation + LDA #$00 ; clear A + STA FAC_sc ; clear sign compare (FAC1 EOR FAC2) + PLA ;.get saved FAC2 exponent + JMP LAB_2675 ; test and adjust accumulators and return + +; ^2 then series evaluation + +LAB_2B6E + STA Cptrl ; save count pointer low byte + STY Cptrh ; save count pointer high byte + JSR LAB_276E ; pack FAC1 into Adatal + LDA #Adatal ; pointer to original # high byte + JMP LAB_25FB ; do convert AY, FCA1*(AY) and return + +; series evaluation + +LAB_2B84 + STA Cptrl ; save count pointer low byte + STY Cptrh ; save count pointer high byte +LAB_2B88 + LDX #numexp ; set pointer high byte to partial @ numexp + DEC numcon ; decrement constants count + BNE LAB_2B9B ; loop until all done + + RTS + +; RND(n), 32 bit Galoise version. make n=0 for 19th next number in sequence or n<>0 +; to get 19th next number in sequence after seed n. This version of the PRNG uses +; the Galois method and a sample of 65536 bytes produced gives the following values. + +; Entropy = 7.997442 bits per byte +; Optimum compression would reduce these 65536 bytes by 0 percent + +; Chi square distribution for 65536 samples is 232.01, and +; randomly would exceed this value 75.00 percent of the time + +; Arithmetic mean value of data bytes is 127.6724, 127.5 would be random +; Monte Carlo value for Pi is 3.122871269, error 0.60 percent +; Serial correlation coefficient is -0.000370, totally uncorrelated would be 0.0 + +LAB_RND + LDA FAC1_e ; get FAC1 exponent + BEQ NextPRN ; do next random # if zero + + ; else get seed into random number store + LDX #Rbyte4 ; set PRNG pointer low byte + LDY #$00 ; set PRNG pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) +NextPRN + LDX #$AF ; set EOR byte + LDY #$13 ; do this nineteen times +LoopPRN + ASL Rbyte1 ; shift PRNG most significant byte + ROL Rbyte2 ; shift PRNG middle byte + ROL Rbyte3 ; shift PRNG least significant byte + ROL Rbyte4 ; shift PRNG extra byte + BCC Ninc1 ; branch if bit 32 clear + + TXA ; set EOR byte + EOR Rbyte1 ; EOR PRNG extra byte + STA Rbyte1 ; save new PRNG extra byte +Ninc1 + DEY ; decrement loop count + BNE LoopPRN ; loop if not all done + + LDX #$02 ; three bytes to copy +CopyPRNG + LDA Rbyte1,X ; get PRNG byte + STA FAC1_1,X ; save FAC1 byte + DEX + BPL CopyPRNG ; loop if not complete + + LDA #$80 ; set the exponent + STA FAC1_e ; save FAC1 exponent + + ASL ; clear A + STA FAC1_s ; save FAC1 sign + + JMP LAB_24D5 ; normalise FAC1 and return + +; perform COS() + +LAB_COS + LDA #LAB_2C78 ; set (pi/2) pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + +; perform SIN() + +LAB_SIN + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #LAB_2C7C ; set (2*pi) pointer high byte + LDX FAC2_s ; get FAC2 sign (b7) + JSR LAB_26C2 ; divide by (AY) (X=sign) + JSR LAB_27AB ; round and copy FAC1 to FAC2 + JSR LAB_INT ; perform INT + LDA #$00 ; clear byte + STA FAC_sc ; clear sign compare (FAC1 EOR FAC2) + JSR LAB_SUBTRACT ; perform subtraction, FAC2 from FAC1 + LDA #LAB_2C80 ; set 0.25 pointer high byte + JSR LAB_2455 ; perform subtraction, (AY) from FAC1 + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; save FAC1 sign + BPL LAB_2C35 ; branch if +ve + + ; FAC1 sign was -ve + JSR LAB_244E ; add 0.5 to FAC1 + LDA FAC1_s ; get FAC1 sign (b7) + BMI LAB_2C38 ; branch if -ve + + LDA Cflag ; get comparison evaluation flag + EOR #$FF ; toggle flag + STA Cflag ; save comparison evaluation flag +LAB_2C35 + JSR LAB_GTHAN ; do - FAC1 +LAB_2C38 + LDA #LAB_2C80 ; set 0.25 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + PLA ; restore FAC1 sign + BPL LAB_2C45 ; branch if was +ve + + ; else correct FAC1 + JSR LAB_GTHAN ; do - FAC1 +LAB_2C45 + LDA #LAB_2C84 ; set pointer high byte to counter + JMP LAB_2B6E ; ^2 then series evaluation and return + +; perform TAN() + +LAB_TAN + JSR LAB_276E ; pack FAC1 into Adatal + LDA #$00 ; clear byte + STA Cflag ; clear comparison evaluation flag + JSR LAB_SIN ; go do SIN(n) + LDX #func_l ; set sin(n) pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) + LDA #Adatal ; set n pointer high addr + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + LDA #$00 ; clear byte + STA FAC1_s ; clear FAC1 sign (b7) + LDA Cflag ; get comparison evaluation flag + JSR LAB_2C74 ; save flag and go do series evaluation + + LDA #func_l ; set sin(n) pointer high byte + JMP LAB_26CA ; convert AY and do (AY)/FAC1 + +LAB_2C74 + PHA ; save comparison evaluation flag + JMP LAB_2C35 ; go do series evaluation + +; perform USR() + +LAB_USR + JSR Usrjmp ; call user code + JMP LAB_1BFB ; scan for ")", else do syntax error then warm start + +; perform ATN() + +LAB_ATN + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; save sign + BPL LAB_2CA1 ; branch if +ve + + JSR LAB_GTHAN ; else do - FAC1 +LAB_2CA1 + LDA FAC1_e ; get FAC1 exponent + PHA ; push exponent + CMP #$81 ; compare with 1 + BCC LAB_2CAF ; branch if FAC1<1 + + LDA #LAB_259C ; set 1 pointer high byte + JSR LAB_26CA ; convert AY and do (AY)/FAC1 +LAB_2CAF + LDA #LAB_2CC9 ; set pointer high byte to counter + JSR LAB_2B6E ; ^2 then series evaluation + PLA ; restore old FAC1 exponent + CMP #$81 ; compare with 1 + BCC LAB_2CC2 ; branch if FAC1<1 + + LDA #LAB_2C78 ; set (pi/2) pointer high byte + JSR LAB_2455 ; perform subtraction, (AY) from FAC1 +LAB_2CC2 + PLA ; restore FAC1 sign + BPL LAB_2D04 ; exit if was +ve + + JMP LAB_GTHAN ; else do - FAC1 and return + +; perform BITSET + +LAB_BITSET + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + LDA #$00 ; clear A + SEC ; set the carry +S_Bits + ROL ; shift bit + DEX ; decrement bit number + BPL S_Bits ; loop if still +ve + + INX ; make X = $00 + ORA (Itempl,X) ; or with byte via temporary integer (addr) + STA (Itempl,X) ; save byte via temporary integer (addr) +LAB_2D04 + RTS + +; perform BITCLR + +LAB_BITCLR + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + LDA #$FF ; set A +S_Bitc + ROL ; shift bit + DEX ; decrement bit number + BPL S_Bitc ; loop if still +ve + + INX ; make X = $00 + AND (Itempl,X) ; and with byte via temporary integer (addr) + STA (Itempl,X) ; save byte via temporary integer (addr) + RTS + +FCError + JMP LAB_FCER ; do function call error then warm start + +; perform BITTST() + +LAB_BTST + JSR LAB_IGBY ; increment BASIC pointer + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + JSR LAB_GBYT ; get next BASIC byte + CMP #')' ; is next character ")" + BEQ TST_OK ; if ")" go do rest of function + + JMP LAB_SNER ; do syntax error then warm start + +TST_OK + JSR LAB_IGBY ; update BASIC execute pointer (to character past ")") + LDA #$00 ; clear A + SEC ; set the carry +T_Bits + ROL ; shift bit + DEX ; decrement bit number + BPL T_Bits ; loop if still +ve + + INX ; make X = $00 + AND (Itempl,X) ; AND with byte via temporary integer (addr) + BEQ LAB_NOTT ; branch if zero (already correct) + + LDA #$FF ; set for -1 result +LAB_NOTT + JMP LAB_27DB ; go do SGN tail + +; perform BIN$() + +LAB_BINS + CPX #$19 ; max + 1 + BCS BinFErr ; exit if too big ( > or = ) + + STX TempB ; save # of characters ($00 = leading zero remove) + LDA #$18 ; need A byte long space + JSR LAB_MSSP ; make string space A bytes long + LDY #$17 ; set index + LDX #$18 ; character count +NextB1 + LSR nums_1 ; shift highest byte + ROR nums_2 ; shift middle byte + ROR nums_3 ; shift lowest byte bit 0 to carry + TXA ; load with "0"/2 + ROL ; shift in carry + STA (str_pl),Y ; save to temp string + index + DEY ; decrement index + BPL NextB1 ; loop if not done + + LDA TempB ; get # of characters + BEQ EndBHS ; branch if truncate + + TAX ; copy length to X + SEC ; set carry for add ! + EOR #$FF ; 1's complement + ADC #$18 ; add 24d + BEQ GoPr2 ; if zero print whole string + + BNE GoPr1 ; else go make output string + +; this is the exit code and is also used by HEX$() +; truncate string to remove leading "0"s + +EndBHS + TAY ; clear index (A=0, X=length here) +NextB2 + LDA (str_pl),Y ; get character from string + CMP #'0' ; compare with "0" + BNE GoPr ; if not "0" then go print string from here + + DEX ; decrement character count + BEQ GoPr3 ; if zero then end of string so go print it + + INY ; else increment index + BPL NextB2 ; loop always + +; make fixed length output string - ignore overflows! + +GoPr3 + INX ; need at least 1 character +GoPr + TYA ; copy result +GoPr1 + CLC ; clear carry for add + ADC str_pl ; add low address + STA str_pl ; save low address + LDA #$00 ; do high byte + ADC str_ph ; add high address + STA str_ph ; save high address +GoPr2 + STX str_ln ; X holds string length + JSR LAB_IGBY ; update BASIC execute pointer (to character past ")") + JMP LAB_RTST ; check for space on descriptor stack then put address + ; and length on descriptor stack and update stack pointers + +BinFErr + JMP LAB_FCER ; do function call error then warm start + +; perform HEX$() + +LAB_HEXS + CPX #$07 ; max + 1 + BCS BinFErr ; exit if too big ( > or = ) + + STX TempB ; save # of characters + + LDA #$06 ; need 6 bytes for string + JSR LAB_MSSP ; make string space A bytes long + LDY #$05 ; set string index + + SED ; need decimal mode for nibble convert + LDA nums_3 ; get lowest byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + LDA nums_2 ; get middle byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + LDA nums_1 ; get highest byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + CLD ; back to binary + + LDX #$06 ; character count + LDA TempB ; get # of characters + BEQ EndBHS ; branch if truncate + + TAX ; copy length to X + SEC ; set carry for add ! + EOR #$FF ; 1's complement + ADC #$06 ; add 6d + BEQ GoPr2 ; if zero print whole string + + BNE GoPr1 ; else go make output string (branch always) + +; convert A to ASCII hex byte and output .. note set decimal mode before calling + +LAB_A2HX + TAX ; save byte + AND #$0F ; mask off top bits + JSR LAB_AL2X ; convert low nibble to ASCII and output + TXA ; get byte back + LSR ; /2 shift high nibble to low nibble + LSR ; /4 + LSR ; /8 + LSR ; /16 +LAB_AL2X + CMP #$0A ; set carry for +1 if >9 + ADC #'0' ; add ASCII "0" + STA (str_pl),Y ; save to temp string + DEY ; decrement counter + RTS + +LAB_NLTO + STA FAC1_e ; save FAC1 exponent + LDA #$00 ; clear sign compare +LAB_MLTE + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + TXA ; restore character + JSR LAB_2912 ; evaluate new ASCII digit + +; gets here if the first character was "$" for hex +; get hex number + +LAB_CHEX + JSR LAB_IGBY ; increment and scan memory + BCC LAB_ISHN ; branch if numeric character + + ORA #$20 ; case convert, allow "A" to "F" and "a" to "f" + SBC #'a' ; subtract "a" (carry set here) + CMP #$06 ; compare normalised with $06 (max+1) + BCS LAB_EXCH ; exit if >"f" or <"0" + + ADC #$0A ; convert to nibble +LAB_ISHN + AND #$0F ; convert to binary + TAX ; save nibble + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_MLTE ; skip multiply if zero + + ADC #$04 ; add four to exponent (*16 - carry clear here) + BCC LAB_NLTO ; if no overflow do evaluate digit + +LAB_MLTO + JMP LAB_2564 ; do overflow error and warm start + +LAB_NXCH + TAX ; save bit + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_MLBT ; skip multiply if zero + + INC FAC1_e ; increment FAC1 exponent (*2) + BEQ LAB_MLTO ; do overflow error if = $00 + + LDA #$00 ; clear sign compare +LAB_MLBT + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + TXA ; restore bit + JSR LAB_2912 ; evaluate new ASCII digit + +; gets here if the first character was "%" for binary +; get binary number + +LAB_CBIN + JSR LAB_IGBY ; increment and scan memory + EOR #'0' ; convert "0" to 0 etc. + CMP #$02 ; compare with max+1 + BCC LAB_NXCH ; branch exit if < 2 + +LAB_EXCH + JMP LAB_28F6 ; evaluate -ve flag and return + +; ctrl-c check routine. includes limited "life" byte save for INGET routine +; now also the code that checks to see if an interrupt has occurred + +CTRLC + LDA ccflag ; get [CTRL-C] check flag + BNE LAB_FBA2 ; exit if inhibited + + JSR V_INPT ; scan input device + BCC LAB_FBA0 ; exit if buffer empty + + STA ccbyte ; save received byte + LDX #$20 ; "life" timer for bytes + STX ccnull ; set countdown + JMP LAB_1636 ; return to BASIC + +LAB_FBA0 + LDX ccnull ; get countdown byte + BEQ LAB_FBA2 ; exit if finished + + DEC ccnull ; else decrement countdown +LAB_FBA2 + LDX #NmiBase ; set pointer to NMI values + JSR LAB_CKIN ; go check interrupt + LDX #IrqBase ; set pointer to IRQ values + JSR LAB_CKIN ; go check interrupt +LAB_CRTS + RTS + +; check whichever interrupt is indexed by X + +LAB_CKIN + LDA PLUS_0,X ; get interrupt flag byte + BPL LAB_CRTS ; branch if interrupt not enabled + +; we disable the interrupt here and make two new commands RETIRQ and RETNMI to +; automatically enable the interrupt when we exit + + ASL ; move happened bit to setup bit + AND #$40 ; mask happened bits + BEQ LAB_CRTS ; if no interrupt then exit + + STA PLUS_0,X ; save interrupt flag byte + + TXA ; copy index .. + TAY ; .. to Y + + PLA ; dump return address low byte, call from CTRL-C + PLA ; dump return address high byte + + LDA #$05 ; need 5 bytes for GOSUB + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_GOSUB ; token for GOSUB + PHA ; push on stack + + LDA PLUS_1,Y ; get interrupt code pointer low byte + STA Bpntrl ; save as BASIC execute pointer low byte + LDA PLUS_2,Y ; get interrupt code pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + + JMP LAB_15C2 ; go do interpreter inner loop + ; can't RTS, we used the stack! the RTS from the ctrl-c + ; check will be taken when the RETIRQ/RETNMI/RETURN is + ; executed at the end of the subroutine + +; get byte from input device, no waiting +; returns with carry set if byte in A + +INGET + JSR V_INPT ; call scan input device + BCS LAB_FB95 ; if byte go reset timer + + LDA ccnull ; get countdown + BEQ LAB_FB96 ; exit if empty + + LDA ccbyte ; get last received byte + SEC ; flag we got a byte +LAB_FB95 + LDX #$00 ; clear X + STX ccnull ; clear timer because we got a byte +LAB_FB96 + RTS + +; these routines only enable the interrupts if the set-up flag is set +; if not they have no effect + +; perform IRQ {ON|OFF|CLEAR} + +LAB_IRQ + LDX #IrqBase ; set pointer to IRQ values + .byte $2C ; make next line BIT abs. + +; perform NMI {ON|OFF|CLEAR} + +LAB_NMI + LDX #NmiBase ; set pointer to NMI values + CMP #TK_ON ; compare with token for ON + BEQ LAB_INON ; go turn on interrupt + + CMP #TK_OFF ; compare with token for OFF + BEQ LAB_IOFF ; go turn off interrupt + + EOR #TK_CLEAR ; compare with token for CLEAR, A = $00 if = TK_CLEAR + BEQ LAB_INEX ; go clear interrupt flags and return + + JMP LAB_SNER ; do syntax error then warm start + +LAB_IOFF + LDA #$7F ; clear A + AND PLUS_0,X ; AND with interrupt setup flag + BPL LAB_INEX ; go clear interrupt enabled flag and return + +LAB_INON + LDA PLUS_0,X ; get interrupt setup flag + ASL ; Shift bit to enabled flag + ORA PLUS_0,X ; OR with flag byte +LAB_INEX + STA PLUS_0,X ; save interrupt flag byte + JMP LAB_IGBY ; update BASIC execute pointer and return + +; these routines set up the pointers and flags for the interrupt routines +; note that the interrupts are also enabled by these commands + +; perform ON IRQ + +LAB_SIRQ + CLI ; enable interrupts + LDX #IrqBase ; set pointer to IRQ values + .byte $2C ; make next line BIT abs. + +; perform ON NMI + +LAB_SNMI + LDX #NmiBase ; set pointer to NMI values + + STX TempB ; save interrupt pointer + JSR LAB_IGBY ; increment and scan memory (past token) + JSR LAB_GFPN ; get fixed-point number into temp integer + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCS LAB_LFND ; if carry set go set-up interrupt + + JMP LAB_16F7 ; else go do "Undefined statement" error and warm start + +LAB_LFND + LDX TempB ; get interrupt pointer + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 (carry already set for subtract) + STA PLUS_1,X ; save as interrupt pointer low byte + LDA Baslnh ; get pointer high byte + SBC #$00 ; subtract carry + STA PLUS_2,X ; save as interrupt pointer high byte + + LDA #$C0 ; set interrupt enabled/setup bits + STA PLUS_0,X ; set interrupt flags +LAB_IRTS + RTS + +; return from IRQ service, restores the enabled flag. + +; perform RETIRQ + +LAB_RETIRQ + BNE LAB_IRTS ; exit if following token (to allow syntax error) + + LDA IrqBase ; get interrupt flags + ASL ; copy setup to enabled (b7) + ORA IrqBase ; OR in setup flag + STA IrqBase ; save enabled flag + JMP LAB_16E8 ; go do rest of RETURN + +; return from NMI service, restores the enabled flag. + +; perform RETNMI + +LAB_RETNMI + BNE LAB_IRTS ; exit if following token (to allow syntax error) + + LDA NmiBase ; get set-up flag + ASL ; copy setup to enabled (b7) + ORA NmiBase ; OR in setup flag + STA NmiBase ; save enabled flag + JMP LAB_16E8 ; go do rest of RETURN + +; MAX() MIN() pre process + +LAB_MMPP + JSR LAB_EVEZ ; process expression + JMP LAB_CTNM ; check if source is numeric, else do type mismatch + +; perform MAX() + +LAB_MAX + JSR LAB_PHFA ; push FAC1, evaluate expression, + ; pull FAC2 and compare with FAC1 + BPL LAB_MAX ; branch if no swap to do + + LDA FAC2_1 ; get FAC2 mantissa1 + ORA #$80 ; set top bit (clear sign from compare) + STA FAC2_1 ; save FAC2 mantissa1 + JSR LAB_279B ; copy FAC2 to FAC1 + BEQ LAB_MAX ; go do next (branch always) + +; perform MIN() + +LAB_MIN + JSR LAB_PHFA ; push FAC1, evaluate expression, + ; pull FAC2 and compare with FAC1 + BMI LAB_MIN ; branch if no swap to do + + BEQ LAB_MIN ; branch if no swap to do + + LDA FAC2_1 ; get FAC2 mantissa1 + ORA #$80 ; set top bit (clear sign from compare) + STA FAC2_1 ; save FAC2 mantissa1 + JSR LAB_279B ; copy FAC2 to FAC1 + BEQ LAB_MIN ; go do next (branch always) + +; exit routine. don't bother returning to the loop code +; check for correct exit, else so syntax error + +LAB_MMEC + CMP #')' ; is it end of function? + BNE LAB_MMSE ; if not do MAX MIN syntax error + + PLA ; dump return address low byte + PLA ; dump return address high byte + JMP LAB_IGBY ; update BASIC execute pointer (to chr past ")") + +LAB_MMSE + JMP LAB_SNER ; do syntax error then warm start + +; check for next, evaluate and return or exit +; this is the routine that does most of the work + +LAB_PHFA + JSR LAB_GBYT ; get next BASIC byte + CMP #',' ; is there more ? + BNE LAB_MMEC ; if not go do end check + + ; push FAC1 + JSR LAB_27BA ; round FAC1 + LDA FAC1_s ; get FAC1 sign + ORA #$7F ; set all non sign bits + AND FAC1_1 ; AND FAC1 mantissa1 (AND in sign bit) + PHA ; push on stack + LDA FAC1_2 ; get FAC1 mantissa2 + PHA ; push on stack + LDA FAC1_3 ; get FAC1 mantissa3 + PHA ; push on stack + LDA FAC1_e ; get FAC1 exponent + PHA ; push on stack + + JSR LAB_IGBY ; scan and get next BASIC byte (after ",") + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + + ; pop FAC2 (MAX/MIN expression so far) + PLA ; pop exponent + STA FAC2_e ; save FAC2 exponent + PLA ; pop mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + PLA ; pop mantissa1 + STA FAC2_2 ; save FAC2 mantissa2 + PLA ; pop sign/mantissa1 + STA FAC2_1 ; save FAC2 sign/mantissa1 + STA FAC2_s ; save FAC2 sign + + ; compare FAC1 with (packed) FAC2 + LDA #FAC2_e ; set pointer high byte to FAC2 + JMP LAB_27F8 ; compare FAC1 with FAC2 (AY) and return + ; returns A=$00 if FAC1 = (AY) + ; returns A=$01 if FAC1 > (AY) + ; returns A=$FF if FAC1 < (AY) + +; perform WIDTH + +LAB_WDTH + CMP #',' ; is next byte "," + BEQ LAB_TBSZ ; if so do tab size + + JSR LAB_GTBY ; get byte parameter + TXA ; copy width to A + BEQ LAB_NSTT ; branch if set for infinite line + + CPX #$10 ; else make min width = 16d + BCC TabErr ; if less do function call error and exit + +; this next compare ensures that we can't exit WIDTH via an error leaving the +; tab size greater than the line length. + + CPX TabSiz ; compare with tab size + BCS LAB_NSTT ; branch if >= tab size + + STX TabSiz ; else make tab size = terminal width +LAB_NSTT + STX TWidth ; set the terminal width + JSR LAB_GBYT ; get BASIC byte back + BEQ WExit ; exit if no following + + CMP #',' ; else is it "," + BNE LAB_MMSE ; if not do syntax error + +LAB_TBSZ + JSR LAB_SGBY ; scan and get byte parameter + TXA ; copy TAB size + BMI TabErr ; if >127 do function call error and exit + + CPX #$01 ; compare with min-1 + BCC TabErr ; if <=1 do function call error and exit + + LDA TWidth ; set flags for width + BEQ LAB_SVTB ; skip check if infinite line + + CPX TWidth ; compare TAB with width + BEQ LAB_SVTB ; ok if = + + BCS TabErr ; branch if too big + +LAB_SVTB + STX TabSiz ; save TAB size + +; calculate tab column limit from TAB size. The Iclim is set to the last tab +; position on a line that still has at least one whole tab width between it +; and the end of the line. + +WExit + LDA TWidth ; get width + BEQ LAB_SULP ; branch if infinite line + + CMP TabSiz ; compare with tab size + BCS LAB_WDLP ; branch if >= tab size + + STA TabSiz ; else make tab size = terminal width +LAB_SULP + SEC ; set carry for subtract +LAB_WDLP + SBC TabSiz ; subtract tab size + BCS LAB_WDLP ; loop while no borrow + + ADC TabSiz ; add tab size back + CLC ; clear carry for add + ADC TabSiz ; add tab size back again + STA Iclim ; save for now + LDA TWidth ; get width back + SEC ; set carry for subtract + SBC Iclim ; subtract remainder + STA Iclim ; save tab column limit +LAB_NOSQ + RTS + +TabErr + JMP LAB_FCER ; do function call error then warm start + +; perform SQR() + +LAB_SQR + LDA FAC1_s ; get FAC1 sign + BMI TabErr ; if -ve do function call error + + LDA FAC1_e ; get exponent + BEQ LAB_NOSQ ; if zero just return + + ; else do root + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #$00 ; clear A + + STA FACt_3 ; clear remainder + STA FACt_2 ; .. + STA FACt_1 ; .. + STA TempB ; .. + + STA FAC1_3 ; clear root + STA FAC1_2 ; .. + STA FAC1_1 ; .. + + LDX #$18 ; 24 pairs of bits to do + LDA FAC2_e ; get exponent + LSR ; check odd/even + BCS LAB_SQE2 ; if odd only 1 shift first time + +LAB_SQE1 + ASL FAC2_3 ; shift highest bit of number .. + ROL FAC2_2 ; .. + ROL FAC2_1 ; .. + ROL FACt_3 ; .. into remainder + ROL FACt_2 ; .. + ROL FACt_1 ; .. + ROL TempB ; .. never overflows +LAB_SQE2 + ASL FAC2_3 ; shift highest bit of number .. + ROL FAC2_2 ; .. + ROL FAC2_1 ; .. + ROL FACt_3 ; .. into remainder + ROL FACt_2 ; .. + ROL FACt_1 ; .. + ROL TempB ; .. never overflows + + ASL FAC1_3 ; root = root * 2 + ROL FAC1_2 ; .. + ROL FAC1_1 ; .. never overflows + + LDA FAC1_3 ; get root low byte + ROL ; *2 + STA Temp3 ; save partial low byte + LDA FAC1_2 ; get root low mid byte + ROL ; *2 + STA Temp3+1 ; save partial low mid byte + LDA FAC1_1 ; get root high mid byte + ROL ; *2 + STA Temp3+2 ; save partial high mid byte + LDA #$00 ; get root high byte (always $00) + ROL ; *2 + STA Temp3+3 ; save partial high byte + + ; carry clear for subtract +1 + LDA FACt_3 ; get remainder low byte + SBC Temp3 ; subtract partial low byte + STA Temp3 ; save partial low byte + + LDA FACt_2 ; get remainder low mid byte + SBC Temp3+1 ; subtract partial low mid byte + STA Temp3+1 ; save partial low mid byte + + LDA FACt_1 ; get remainder high mid byte + SBC Temp3+2 ; subtract partial high mid byte + TAY ; copy partial high mid byte + + LDA TempB ; get remainder high byte + SBC Temp3+3 ; subtract partial high byte + BCC LAB_SQNS ; skip sub if remainder smaller + + STA TempB ; save remainder high byte + + STY FACt_1 ; save remainder high mid byte + + LDA Temp3+1 ; get remainder low mid byte + STA FACt_2 ; save remainder low mid byte + + LDA Temp3 ; get partial low byte + STA FACt_3 ; save remainder low byte + + INC FAC1_3 ; increment root low byte (never any rollover) +LAB_SQNS + DEX ; decrement bit pair count + BNE LAB_SQE1 ; loop if not all done + + SEC ; set carry for subtract + LDA FAC2_e ; get exponent + SBC #$80 ; normalise + ROR ; /2 and re-bias to $80 + ADC #$00 ; add bit zero back in (allow for half shift) + STA FAC1_e ; save it + JMP LAB_24D5 ; normalise FAC1 and return + +; perform VARPTR() + +LAB_VARPTR + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GVAR ; get var address + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + LDY Cvaral ; get var address low byte + LDA Cvarah ; get var address high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform PI + +LAB_PI + LDA #LAB_2C7C ; set (2*pi) pointer high byte + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + DEC FAC1_e ; make result = PI + RTS + +; perform TWOPI + +LAB_TWOPI + LDA #LAB_2C7C ; set (2*pi) pointer high byte + JMP LAB_UFAC ; unpack memory (AY) into FAC1 and return + +; system dependant i/o vectors +; these are in RAM and are set by the monitor at start-up + +V_INPT + JMP (VEC_IN) ; non halting scan input device +V_OUTP + JMP (VEC_OUT) ; send byte to output device +V_LOAD + JMP (VEC_LD) ; load BASIC program +V_SAVE + JMP (VEC_SV) ; save BASIC program + +; The rest are tables messages and code for RAM + +; the rest of the code is tables and BASIC start-up code + +PG2_TABS + .byte $FF ; ctrl-c flag - $00 = enabled + .byte $00 ; ctrl-c byte - GET needs this + .byte $00 ; ctrl-c byte timeout - GET needs this + .word CTRLC ; ctrl c check vector + .word CHRIN ; non halting key input - monitor to set this + .word CHROUT ; output vector - monitor to set this +; .word xxxx ; load vector - monitor to set this +; .word xxxx ; save vector - monitor to set this +PG2_TABE + +; character get subroutine for zero page + +; For a 1.8432MHz 6502 including the JSR and RTS +; fastest (>=":") = 29 cycles = 15.7uS +; slowest (<":") = 40 cycles = 21.7uS +; space skip = +21 cycles = +11.4uS +; inc across page = +4 cycles = +2.2uS + +; the target address for the LDA at LAB_2CF4 becomes the BASIC execute pointer once the +; block is copied to it's destination, any non zero page address will do at assembly +; time, to assemble a three byte instruction. + +; page 0 initialisation table from $BC +; increment and scan memory + +LAB_2CEE + INC Bpntrl ; increment BASIC execute pointer low byte + BNE LAB_2CF4 ; branch if no carry + ; else + INC Bpntrh ; increment BASIC execute pointer high byte + +; page 0 initialisation table from $C2 +; scan memory + +LAB_2CF4 + LDA $FFFF ; get byte to scan (addr set by call routine) + CMP #TK_ELSE ; compare with the token for ELSE + BEQ LAB_2D05 ; exit if ELSE, not numeric, carry set + + CMP #':' ; compare with ":" + BCS LAB_2D05 ; exit if >= ":", not numeric, carry set + + CMP #' ' ; compare with " " + BEQ LAB_2CEE ; if " " go do next + + SEC ; set carry for SBC + SBC #'0' ; subtract "0" + SEC ; set carry for SBC + SBC #$D0 ; subtract -"0" + ; clear carry if byte = "0"-"9" +LAB_2D05 + RTS + +; page zero initialisation table $00-$12 inclusive + +StrTab + .byte $4C ; JMP opcode + .word LAB_COLD ; initial warm start vector (cold start) + + .byte $00 ; these bytes are not used by BASIC + .word $0000 ; + .word $0000 ; + .word $0000 ; + + .byte $4C ; JMP opcode + .word LAB_FCER ; initial user function vector ("Function call" error) + .byte $00 ; default NULL count + .byte $00 ; clear terminal position + .byte $00 ; default terminal width byte + .byte $F2 ; default limit for TAB = 14 + .word Ram_base ; start of user RAM +EndTab + +LAB_MSZM + .byte $0D,$0A,"Memory size ",$00 + +LAB_SMSG + .byte " Bytes free",$0D,$0A,$0A + .byte "Enhanced BASIC 2.22",$0A,$00 + +; numeric constants and series + + ; constants and series for LOG(n) +LAB_25A0 + .byte $02 ; counter + .byte $80,$19,$56,$62 ; 0.59898 + .byte $80,$76,$22,$F3 ; 0.96147 +;## .byte $80,$76,$22,$F1 ; 0.96147 + .byte $82,$38,$AA,$40 ; 2.88539 +;## .byte $82,$38,$AA,$45 ; 2.88539 + +LAB_25AD + .byte $80,$35,$04,$F3 ; 0.70711 1/root 2 +LAB_25B1 + .byte $81,$35,$04,$F3 ; 1.41421 root 2 +LAB_25B5 + .byte $80,$80,$00,$00 ; -0.5 +LAB_25B9 + .byte $80,$31,$72,$18 ; 0.69315 LOG(2) + + ; numeric PRINT constants +LAB_2947 + .byte $91,$43,$4F,$F8 ; 99999.9375 (max value with at least one decimal) +LAB_294B + .byte $94,$74,$23,$F7 ; 999999.4375 (max value before scientific notation) +LAB_294F + .byte $94,$74,$24,$00 ; 1000000 + + ; EXP(n) constants and series +LAB_2AFA + .byte $81,$38,$AA,$3B ; 1.4427 (1/LOG base 2 e) +LAB_2AFE + .byte $06 ; counter + .byte $74,$63,$90,$8C ; 2.17023e-4 + .byte $77,$23,$0C,$AB ; 0.00124 + .byte $7A,$1E,$94,$00 ; 0.00968 + .byte $7C,$63,$42,$80 ; 0.05548 + .byte $7E,$75,$FE,$D0 ; 0.24023 + .byte $80,$31,$72,$15 ; 0.69315 + .byte $81,$00,$00,$00 ; 1.00000 + +;## .byte $07 ; counter +;## .byte $74,$94,$2E,$40 ; -1/7! (-1/5040) +;## .byte $77,$2E,$4F,$70 ; 1/6! ( 1/720) +;## .byte $7A,$88,$02,$6E ; -1/5! (-1/120) +;## .byte $7C,$2A,$A0,$E6 ; 1/4! ( 1/24) +;## .byte $7E,$AA,$AA,$50 ; -1/3! (-1/6) +;## .byte $7F,$7F,$FF,$FF ; 1/2! ( 1/2) +;## .byte $81,$80,$00,$00 ; -1/1! (-1/1) +;## .byte $81,$00,$00,$00 ; 1/0! ( 1/1) + + ; trigonometric constants and series +LAB_2C78 + .byte $81,$49,$0F,$DB ; 1.570796371 (pi/2) as floating # +LAB_2C84 + .byte $04 ; counter + .byte $86,$1E,$D7,$FB ; 39.7109 +;## .byte $86,$1E,$D7,$BA ; 39.7109 + .byte $87,$99,$26,$65 ;-76.575 +;## .byte $87,$99,$26,$64 ;-76.575 + .byte $87,$23,$34,$58 ; 81.6022 + .byte $86,$A5,$5D,$E1 ;-41.3417 +;## .byte $86,$A5,$5D,$E0 ;-41.3417 +LAB_2C7C + .byte $83,$49,$0F,$DB ; 6.28319 (2*pi) as floating # +;## .byte $83,$49,$0F,$DA ; 6.28319 (2*pi) as floating # + +LAB_2CC9 + .byte $08 ; counter + .byte $78,$3A,$C5,$37 ; 0.00285 + .byte $7B,$83,$A2,$5C ;-0.0160686 + .byte $7C,$2E,$DD,$4D ; 0.0426915 + .byte $7D,$99,$B0,$1E ;-0.0750429 + .byte $7D,$59,$ED,$24 ; 0.106409 + .byte $7E,$91,$72,$00 ;-0.142036 + .byte $7E,$4C,$B9,$73 ; 0.199926 + .byte $7F,$AA,$AA,$53 ;-0.333331 + +;## .byte $08 ; counter +;## .byte $78,$3B,$D7,$4A ; 1/17 +;## .byte $7B,$84,$6E,$02 ;-1/15 +;## .byte $7C,$2F,$C1,$FE ; 1/13 +;## .byte $7D,$9A,$31,$74 ;-1/11 +;## .byte $7D,$5A,$3D,$84 ; 1/9 +;## .byte $7E,$91,$7F,$C8 ;-1/7 +;## .byte $7E,$4C,$BB,$E4 ; 1/5 +;## .byte $7F,$AA,$AA,$6C ;-1/3 + +LAB_1D96 = *+1 ; $00,$00 used for undefined variables +LAB_259C + .byte $81,$00,$00,$00 ; 1.000000, used for INC +LAB_2AFD + .byte $81,$80,$00,$00 ; -1.00000, used for DEC. must be on the same page as +1.00 + + ; misc constants +LAB_1DF7 + .byte $90 ;-32768 (uses first three bytes from 0.5) +LAB_2A96 + .byte $80,$00,$00,$00 ; 0.5 +LAB_2C80 + .byte $7F,$00,$00,$00 ; 0.25 +LAB_26B5 + .byte $84,$20,$00,$00 ; 10.0000 divide by 10 constant + +; This table is used in converting numbers to ASCII. + +LAB_2A9A +LAB_2A9B = LAB_2A9A+1 +LAB_2A9C = LAB_2A9B+1 + .byte $FE,$79,$60 ; -100000 + .byte $00,$27,$10 ; 10000 + .byte $FF,$FC,$18 ; -1000 + .byte $00,$00,$64 ; 100 + .byte $FF,$FF,$F6 ; -10 + .byte $00,$00,$01 ; 1 + +LAB_CTBL + .word LAB_END-1 ; END + .word LAB_FOR-1 ; FOR + .word LAB_NEXT-1 ; NEXT + .word LAB_DATA-1 ; DATA + .word LAB_INPUT-1 ; INPUT + .word LAB_DIM-1 ; DIM + .word LAB_READ-1 ; READ + .word LAB_LET-1 ; LET + .word LAB_DEC-1 ; DEC new command + .word LAB_GOTO-1 ; GOTO + .word LAB_RUN-1 ; RUN + .word LAB_IF-1 ; IF + .word LAB_RESTORE-1 ; RESTORE modified command + .word LAB_GOSUB-1 ; GOSUB + .word LAB_RETIRQ-1 ; RETIRQ new command + .word LAB_RETNMI-1 ; RETNMI new command + .word LAB_RETURN-1 ; RETURN + .word LAB_REM-1 ; REM + .word LAB_STOP-1 ; STOP + .word LAB_ON-1 ; ON modified command + .word LAB_NULL-1 ; NULL modified command + .word LAB_INC-1 ; INC new command + .word LAB_WAIT-1 ; WAIT + .word V_LOAD-1 ; LOAD + .word V_SAVE-1 ; SAVE + .word LAB_DEF-1 ; DEF + .word LAB_POKE-1 ; POKE + .word LAB_DOKE-1 ; DOKE new command + .word LAB_CALL-1 ; CALL new command + .word LAB_DO-1 ; DO new command + .word LAB_LOOP-1 ; LOOP new command + .word LAB_PRINT-1 ; PRINT + .word LAB_CONT-1 ; CONT + .word LAB_LIST-1 ; LIST + .word LAB_CLEAR-1 ; CLEAR + .word LAB_NEW-1 ; NEW + .word LAB_WDTH-1 ; WIDTH new command + .word LAB_GET-1 ; GET new command + .word LAB_SWAP-1 ; SWAP new command + .word LAB_BITSET-1 ; BITSET new command + .word LAB_BITCLR-1 ; BITCLR new command + .word LAB_IRQ-1 ; IRQ new command + .word LAB_NMI-1 ; NMI new command + +; function pre process routine table + +LAB_FTPL +LAB_FTPM = LAB_FTPL+$01 + .word LAB_PPFN-1 ; SGN(n) process numeric expression in () + .word LAB_PPFN-1 ; INT(n) " + .word LAB_PPFN-1 ; ABS(n) " + .word LAB_EVEZ-1 ; USR(x) process any expression + .word LAB_1BF7-1 ; FRE(x) " + .word LAB_1BF7-1 ; POS(x) " + .word LAB_PPFN-1 ; SQR(n) process numeric expression in () + .word LAB_PPFN-1 ; RND(n) " + .word LAB_PPFN-1 ; LOG(n) " + .word LAB_PPFN-1 ; EXP(n) " + .word LAB_PPFN-1 ; COS(n) " + .word LAB_PPFN-1 ; SIN(n) " + .word LAB_PPFN-1 ; TAN(n) " + .word LAB_PPFN-1 ; ATN(n) " + .word LAB_PPFN-1 ; PEEK(n) " + .word LAB_PPFN-1 ; DEEK(n) " + .word $0000 ; SADD() none + .word LAB_PPFS-1 ; LEN($) process string expression in () + .word LAB_PPFN-1 ; STR$(n) process numeric expression in () + .word LAB_PPFS-1 ; VAL($) process string expression in () + .word LAB_PPFS-1 ; ASC($) " + .word LAB_PPFS-1 ; UCASE$($) " + .word LAB_PPFS-1 ; LCASE$($) " + .word LAB_PPFN-1 ; CHR$(n) process numeric expression in () + .word LAB_BHSS-1 ; HEX$(n) " + .word LAB_BHSS-1 ; BIN$(n) " + .word $0000 ; BITTST() none + .word LAB_MMPP-1 ; MAX() process numeric expression + .word LAB_MMPP-1 ; MIN() " + .word LAB_PPBI-1 ; PI advance pointer + .word LAB_PPBI-1 ; TWOPI " + .word $0000 ; VARPTR() none + .word LAB_LRMS-1 ; LEFT$() process string expression + .word LAB_LRMS-1 ; RIGHT$() " + .word LAB_LRMS-1 ; MID$() " + +; action addresses for functions + +LAB_FTBL +LAB_FTBM = LAB_FTBL+$01 + .word LAB_SGN-1 ; SGN() + .word LAB_INT-1 ; INT() + .word LAB_ABS-1 ; ABS() + .word LAB_USR-1 ; USR() + .word LAB_FRE-1 ; FRE() + .word LAB_POS-1 ; POS() + .word LAB_SQR-1 ; SQR() + .word LAB_RND-1 ; RND() modified function + .word LAB_LOG-1 ; LOG() + .word LAB_EXP-1 ; EXP() + .word LAB_COS-1 ; COS() + .word LAB_SIN-1 ; SIN() + .word LAB_TAN-1 ; TAN() + .word LAB_ATN-1 ; ATN() + .word LAB_PEEK-1 ; PEEK() + .word LAB_DEEK-1 ; DEEK() new function + .word LAB_SADD-1 ; SADD() new function + .word LAB_LENS-1 ; LEN() + .word LAB_STRS-1 ; STR$() + .word LAB_VAL-1 ; VAL() + .word LAB_ASC-1 ; ASC() + .word LAB_UCASE-1 ; UCASE$() new function + .word LAB_LCASE-1 ; LCASE$() new function + .word LAB_CHRS-1 ; CHR$() + .word LAB_HEXS-1 ; HEX$() new function + .word LAB_BINS-1 ; BIN$() new function + .word LAB_BTST-1 ; BITTST() new function + .word LAB_MAX-1 ; MAX() new function + .word LAB_MIN-1 ; MIN() new function + .word LAB_PI-1 ; PI new function + .word LAB_TWOPI-1 ; TWOPI new function + .word LAB_VARPTR-1 ; VARPTR() new function + .word LAB_LEFT-1 ; LEFT$() + .word LAB_RIGHT-1 ; RIGHT$() + .word LAB_MIDS-1 ; MID$() + +; hierarchy and action addresses for operator + +LAB_OPPT + .byte $79 ; + + .word LAB_ADD-1 + .byte $79 ; - + .word LAB_SUBTRACT-1 + .byte $7B ; * + .word LAB_MULTIPLY-1 + .byte $7B ; / + .word LAB_DIVIDE-1 + .byte $7F ; ^ + .word LAB_POWER-1 + .byte $50 ; AND + .word LAB_AND-1 + .byte $46 ; EOR new operator + .word LAB_EOR-1 + .byte $46 ; OR + .word LAB_OR-1 + .byte $56 ; >> new operator + .word LAB_RSHIFT-1 + .byte $56 ; << new operator + .word LAB_LSHIFT-1 + .byte $7D ; > + .word LAB_GTHAN-1 + .byte $5A ; = + .word LAB_EQUAL-1 + .byte $64 ; < + .word LAB_LTHAN-1 + +; keywords start with .. +; this is the first character table and must be in alphabetic order + +TAB_1STC + .byte "*" + .byte "+" + .byte "-" + .byte "/" + .byte "<" + .byte "=" + .byte ">" + .byte "?" + .byte "A" + .byte "B" + .byte "C" + .byte "D" + .byte "E" + .byte "F" + .byte "G" + .byte "H" + .byte "I" + .byte "L" + .byte "M" + .byte "N" + .byte "O" + .byte "P" + .byte "R" + .byte "S" + .byte "T" + .byte "U" + .byte "V" + .byte "W" + .byte "^" + .byte $00 ; table terminator + +; pointers to keyword tables + +TAB_CHRT + .word TAB_STAR ; table for "*" + .word TAB_PLUS ; table for "+" + .word TAB_MNUS ; table for "-" + .word TAB_SLAS ; table for "/" + .word TAB_LESS ; table for "<" + .word TAB_EQUL ; table for "=" + .word TAB_MORE ; table for ">" + .word TAB_QEST ; table for "?" + .word TAB_ASCA ; table for "A" + .word TAB_ASCB ; table for "B" + .word TAB_ASCC ; table for "C" + .word TAB_ASCD ; table for "D" + .word TAB_ASCE ; table for "E" + .word TAB_ASCF ; table for "F" + .word TAB_ASCG ; table for "G" + .word TAB_ASCH ; table for "H" + .word TAB_ASCI ; table for "I" + .word TAB_ASCL ; table for "L" + .word TAB_ASCM ; table for "M" + .word TAB_ASCN ; table for "N" + .word TAB_ASCO ; table for "O" + .word TAB_ASCP ; table for "P" + .word TAB_ASCR ; table for "R" + .word TAB_ASCS ; table for "S" + .word TAB_ASCT ; table for "T" + .word TAB_ASCU ; table for "U" + .word TAB_ASCV ; table for "V" + .word TAB_ASCW ; table for "W" + .word TAB_POWR ; table for "^" + +; tables for each start character, note if a longer keyword with the same start +; letters as a shorter one exists then it must come first, else the list is in +; alphabetical order as follows .. + +; [keyword,token +; [keyword,token]] +; end marker (#$00) + +TAB_STAR + .byte TK_MUL,$00 ; * +TAB_PLUS + .byte TK_PLUS,$00 ; + +TAB_MNUS + .byte TK_MINUS,$00 ; - +TAB_SLAS + .byte TK_DIV,$00 ; / +TAB_LESS +LBB_LSHIFT + .byte "<",TK_LSHIFT ; << note - "<<" must come before "<" + .byte TK_LT ; < + .byte $00 +TAB_EQUL + .byte TK_EQUAL,$00 ; = +TAB_MORE +LBB_RSHIFT + .byte ">",TK_RSHIFT ; >> note - ">>" must come before ">" + .byte TK_GT ; > + .byte $00 +TAB_QEST + .byte TK_PRINT,$00 ; ? +TAB_ASCA +LBB_ABS + .byte "BS(",TK_ABS ; ABS( +LBB_AND + .byte "ND",TK_AND ; AND +LBB_ASC + .byte "SC(",TK_ASC ; ASC( +LBB_ATN + .byte "TN(",TK_ATN ; ATN( + .byte $00 +TAB_ASCB +LBB_BINS + .byte "IN$(",TK_BINS ; BIN$( +LBB_BITCLR + .byte "ITCLR",TK_BITCLR ; BITCLR +LBB_BITSET + .byte "ITSET",TK_BITSET ; BITSET +LBB_BITTST + .byte "ITTST(",TK_BITTST + ; BITTST( + .byte $00 +TAB_ASCC +LBB_CALL + .byte "ALL",TK_CALL ; CALL +LBB_CHRS + .byte "HR$(",TK_CHRS ; CHR$( +LBB_CLEAR + .byte "LEAR",TK_CLEAR ; CLEAR +LBB_CONT + .byte "ONT",TK_CONT ; CONT +LBB_COS + .byte "OS(",TK_COS ; COS( + .byte $00 +TAB_ASCD +LBB_DATA + .byte "ATA",TK_DATA ; DATA +LBB_DEC + .byte "EC",TK_DEC ; DEC +LBB_DEEK + .byte "EEK(",TK_DEEK ; DEEK( +LBB_DEF + .byte "EF",TK_DEF ; DEF +LBB_DIM + .byte "IM",TK_DIM ; DIM +LBB_DOKE + .byte "OKE",TK_DOKE ; DOKE note - "DOKE" must come before "DO" +LBB_DO + .byte "O",TK_DO ; DO + .byte $00 +TAB_ASCE +LBB_ELSE + .byte "LSE",TK_ELSE ; ELSE +LBB_END + .byte "ND",TK_END ; END +LBB_EOR + .byte "OR",TK_EOR ; EOR +LBB_EXP + .byte "XP(",TK_EXP ; EXP( + .byte $00 +TAB_ASCF +LBB_FN + .byte "N",TK_FN ; FN +LBB_FOR + .byte "OR",TK_FOR ; FOR +LBB_FRE + .byte "RE(",TK_FRE ; FRE( + .byte $00 +TAB_ASCG +LBB_GET + .byte "ET",TK_GET ; GET +LBB_GOSUB + .byte "OSUB",TK_GOSUB ; GOSUB +LBB_GOTO + .byte "OTO",TK_GOTO ; GOTO + .byte $00 +TAB_ASCH +LBB_HEXS + .byte "EX$(",TK_HEXS ; HEX$( + .byte $00 +TAB_ASCI +LBB_IF + .byte "F",TK_IF ; IF +LBB_INC + .byte "NC",TK_INC ; INC +LBB_INPUT + .byte "NPUT",TK_INPUT ; INPUT +LBB_INT + .byte "NT(",TK_INT ; INT( +LBB_IRQ + .byte "RQ",TK_IRQ ; IRQ + .byte $00 +TAB_ASCL +LBB_LCASES + .byte "CASE$(",TK_LCASES + ; LCASE$( +LBB_LEFTS + .byte "EFT$(",TK_LEFTS ; LEFT$( +LBB_LEN + .byte "EN(",TK_LEN ; LEN( +LBB_LET + .byte "ET",TK_LET ; LET +LBB_LIST + .byte "IST",TK_LIST ; LIST +LBB_LOAD + .byte "OAD",TK_LOAD ; LOAD +LBB_LOG + .byte "OG(",TK_LOG ; LOG( +LBB_LOOP + .byte "OOP",TK_LOOP ; LOOP + .byte $00 +TAB_ASCM +LBB_MAX + .byte "AX(",TK_MAX ; MAX( +LBB_MIDS + .byte "ID$(",TK_MIDS ; MID$( +LBB_MIN + .byte "IN(",TK_MIN ; MIN( + .byte $00 +TAB_ASCN +LBB_NEW + .byte "EW",TK_NEW ; NEW +LBB_NEXT + .byte "EXT",TK_NEXT ; NEXT +LBB_NMI + .byte "MI",TK_NMI ; NMI +LBB_NOT + .byte "OT",TK_NOT ; NOT +LBB_NULL + .byte "ULL",TK_NULL ; NULL + .byte $00 +TAB_ASCO +LBB_OFF + .byte "FF",TK_OFF ; OFF +LBB_ON + .byte "N",TK_ON ; ON +LBB_OR + .byte "R",TK_OR ; OR + .byte $00 +TAB_ASCP +LBB_PEEK + .byte "EEK(",TK_PEEK ; PEEK( +LBB_PI + .byte "I",TK_PI ; PI +LBB_POKE + .byte "OKE",TK_POKE ; POKE +LBB_POS + .byte "OS(",TK_POS ; POS( +LBB_PRINT + .byte "RINT",TK_PRINT ; PRINT + .byte $00 +TAB_ASCR +LBB_READ + .byte "EAD",TK_READ ; READ +LBB_REM + .byte "EM",TK_REM ; REM +LBB_RESTORE + .byte "ESTORE",TK_RESTORE + ; RESTORE +LBB_RETIRQ + .byte "ETIRQ",TK_RETIRQ ; RETIRQ +LBB_RETNMI + .byte "ETNMI",TK_RETNMI ; RETNMI +LBB_RETURN + .byte "ETURN",TK_RETURN ; RETURN +LBB_RIGHTS + .byte "IGHT$(",TK_RIGHTS + ; RIGHT$( +LBB_RND + .byte "ND(",TK_RND ; RND( +LBB_RUN + .byte "UN",TK_RUN ; RUN + .byte $00 +TAB_ASCS +LBB_SADD + .byte "ADD(",TK_SADD ; SADD( +LBB_SAVE + .byte "AVE",TK_SAVE ; SAVE +LBB_SGN + .byte "GN(",TK_SGN ; SGN( +LBB_SIN + .byte "IN(",TK_SIN ; SIN( +LBB_SPC + .byte "PC(",TK_SPC ; SPC( +LBB_SQR + .byte "QR(",TK_SQR ; SQR( +LBB_STEP + .byte "TEP",TK_STEP ; STEP +LBB_STOP + .byte "TOP",TK_STOP ; STOP +LBB_STRS + .byte "TR$(",TK_STRS ; STR$( +LBB_SWAP + .byte "WAP",TK_SWAP ; SWAP + .byte $00 +TAB_ASCT +LBB_TAB + .byte "AB(",TK_TAB ; TAB( +LBB_TAN + .byte "AN(",TK_TAN ; TAN( +LBB_THEN + .byte "HEN",TK_THEN ; THEN +LBB_TO + .byte "O",TK_TO ; TO +LBB_TWOPI + .byte "WOPI",TK_TWOPI ; TWOPI + .byte $00 +TAB_ASCU +LBB_UCASES + .byte "CASE$(",TK_UCASES + ; UCASE$( +LBB_UNTIL + .byte "NTIL",TK_UNTIL ; UNTIL +LBB_USR + .byte "SR(",TK_USR ; USR( + .byte $00 +TAB_ASCV +LBB_VAL + .byte "AL(",TK_VAL ; VAL( +LBB_VPTR + .byte "ARPTR(",TK_VPTR ; VARPTR( + .byte $00 +TAB_ASCW +LBB_WAIT + .byte "AIT",TK_WAIT ; WAIT +LBB_WHILE + .byte "HILE",TK_WHILE ; WHILE +LBB_WIDTH + .byte "IDTH",TK_WIDTH ; WIDTH + .byte $00 +TAB_POWR + .byte TK_POWER,$00 ; ^ + +; new decode table for LIST +; Table is .. +; byte - keyword length, keyword first character +; word - pointer to rest of keyword from dictionary + +; note if length is 1 then the pointer is ignored + +LAB_KEYT + .byte 3,'E' + .word LBB_END ; END + .byte 3,'F' + .word LBB_FOR ; FOR + .byte 4,'N' + .word LBB_NEXT ; NEXT + .byte 4,'D' + .word LBB_DATA ; DATA + .byte 5,'I' + .word LBB_INPUT ; INPUT + .byte 3,'D' + .word LBB_DIM ; DIM + .byte 4,'R' + .word LBB_READ ; READ + .byte 3,'L' + .word LBB_LET ; LET + .byte 3,'D' + .word LBB_DEC ; DEC + .byte 4,'G' + .word LBB_GOTO ; GOTO + .byte 3,'R' + .word LBB_RUN ; RUN + .byte 2,'I' + .word LBB_IF ; IF + .byte 7,'R' + .word LBB_RESTORE ; RESTORE + .byte 5,'G' + .word LBB_GOSUB ; GOSUB + .byte 6,'R' + .word LBB_RETIRQ ; RETIRQ + .byte 6,'R' + .word LBB_RETNMI ; RETNMI + .byte 6,'R' + .word LBB_RETURN ; RETURN + .byte 3,'R' + .word LBB_REM ; REM + .byte 4,'S' + .word LBB_STOP ; STOP + .byte 2,'O' + .word LBB_ON ; ON + .byte 4,'N' + .word LBB_NULL ; NULL + .byte 3,'I' + .word LBB_INC ; INC + .byte 4,'W' + .word LBB_WAIT ; WAIT + .byte 4,'L' + .word LBB_LOAD ; LOAD + .byte 4,'S' + .word LBB_SAVE ; SAVE + .byte 3,'D' + .word LBB_DEF ; DEF + .byte 4,'P' + .word LBB_POKE ; POKE + .byte 4,'D' + .word LBB_DOKE ; DOKE + .byte 4,'C' + .word LBB_CALL ; CALL + .byte 2,'D' + .word LBB_DO ; DO + .byte 4,'L' + .word LBB_LOOP ; LOOP + .byte 5,'P' + .word LBB_PRINT ; PRINT + .byte 4,'C' + .word LBB_CONT ; CONT + .byte 4,'L' + .word LBB_LIST ; LIST + .byte 5,'C' + .word LBB_CLEAR ; CLEAR + .byte 3,'N' + .word LBB_NEW ; NEW + .byte 5,'W' + .word LBB_WIDTH ; WIDTH + .byte 3,'G' + .word LBB_GET ; GET + .byte 4,'S' + .word LBB_SWAP ; SWAP + .byte 6,'B' + .word LBB_BITSET ; BITSET + .byte 6,'B' + .word LBB_BITCLR ; BITCLR + .byte 3,'I' + .word LBB_IRQ ; IRQ + .byte 3,'N' + .word LBB_NMI ; NMI + +; secondary commands (can't start a statement) + + .byte 4,'T' + .word LBB_TAB ; TAB + .byte 4,'E' + .word LBB_ELSE ; ELSE + .byte 2,'T' + .word LBB_TO ; TO + .byte 2,'F' + .word LBB_FN ; FN + .byte 4,'S' + .word LBB_SPC ; SPC + .byte 4,'T' + .word LBB_THEN ; THEN + .byte 3,'N' + .word LBB_NOT ; NOT + .byte 4,'S' + .word LBB_STEP ; STEP + .byte 5,'U' + .word LBB_UNTIL ; UNTIL + .byte 5,'W' + .word LBB_WHILE ; WHILE + .byte 3,'O' + .word LBB_OFF ; OFF + +; opperators + + .byte 1,'+' + .word $0000 ; + + .byte 1,'-' + .word $0000 ; - + .byte 1,'*' + .word $0000 ; * + .byte 1,'/' + .word $0000 ; / + .byte 1,'^' + .word $0000 ; ^ + .byte 3,'A' + .word LBB_AND ; AND + .byte 3,'E' + .word LBB_EOR ; EOR + .byte 2,'O' + .word LBB_OR ; OR + .byte 2,'>' + .word LBB_RSHIFT ; >> + .byte 2,'<' + .word LBB_LSHIFT ; << + .byte 1,'>' + .word $0000 ; > + .byte 1,'=' + .word $0000 ; = + .byte 1,'<' + .word $0000 ; < + +; functions + + .byte 4,'S' ; + .word LBB_SGN ; SGN + .byte 4,'I' ; + .word LBB_INT ; INT + .byte 4,'A' ; + .word LBB_ABS ; ABS + .byte 4,'U' ; + .word LBB_USR ; USR + .byte 4,'F' ; + .word LBB_FRE ; FRE + .byte 4,'P' ; + .word LBB_POS ; POS + .byte 4,'S' ; + .word LBB_SQR ; SQR + .byte 4,'R' ; + .word LBB_RND ; RND + .byte 4,'L' ; + .word LBB_LOG ; LOG + .byte 4,'E' ; + .word LBB_EXP ; EXP + .byte 4,'C' ; + .word LBB_COS ; COS + .byte 4,'S' ; + .word LBB_SIN ; SIN + .byte 4,'T' ; + .word LBB_TAN ; TAN + .byte 4,'A' ; + .word LBB_ATN ; ATN + .byte 5,'P' ; + .word LBB_PEEK ; PEEK + .byte 5,'D' ; + .word LBB_DEEK ; DEEK + .byte 5,'S' ; + .word LBB_SADD ; SADD + .byte 4,'L' ; + .word LBB_LEN ; LEN + .byte 5,'S' ; + .word LBB_STRS ; STR$ + .byte 4,'V' ; + .word LBB_VAL ; VAL + .byte 4,'A' ; + .word LBB_ASC ; ASC + .byte 7,'U' ; + .word LBB_UCASES ; UCASE$ + .byte 7,'L' ; + .word LBB_LCASES ; LCASE$ + .byte 5,'C' ; + .word LBB_CHRS ; CHR$ + .byte 5,'H' ; + .word LBB_HEXS ; HEX$ + .byte 5,'B' ; + .word LBB_BINS ; BIN$ + .byte 7,'B' ; + .word LBB_BITTST ; BITTST + .byte 4,'M' ; + .word LBB_MAX ; MAX + .byte 4,'M' ; + .word LBB_MIN ; MIN + .byte 2,'P' ; + .word LBB_PI ; PI + .byte 5,'T' ; + .word LBB_TWOPI ; TWOPI + .byte 7,'V' ; + .word LBB_VPTR ; VARPTR + .byte 6,'L' ; + .word LBB_LEFTS ; LEFT$ + .byte 7,'R' ; + .word LBB_RIGHTS ; RIGHT$ + .byte 5,'M' ; + .word LBB_MIDS ; MID$ + +; BASIC messages, mostly error messages + +LAB_BAER + .word ERR_NF ;$00 NEXT without FOR + .word ERR_SN ;$02 syntax + .word ERR_RG ;$04 RETURN without GOSUB + .word ERR_OD ;$06 out of data + .word ERR_FC ;$08 function call + .word ERR_OV ;$0A overflow + .word ERR_OM ;$0C out of memory + .word ERR_US ;$0E undefined statement + .word ERR_BS ;$10 array bounds + .word ERR_DD ;$12 double dimension array + .word ERR_D0 ;$14 divide by 0 + .word ERR_ID ;$16 illegal direct + .word ERR_TM ;$18 type mismatch + .word ERR_LS ;$1A long string + .word ERR_ST ;$1C string too complex + .word ERR_CN ;$1E continue error + .word ERR_UF ;$20 undefined function + .word ERR_LD ;$22 LOOP without DO + +; I may implement these two errors to force definition of variables and +; dimensioning of arrays before use. + +; .word ERR_UV ;$24 undefined variable + +; the above error has been tested and works (see code and comments below LAB_1D8B) + +; .word ERR_UA ;$26 undimensioned array + +ERR_NF .byte "NEXT without FOR",$00 +ERR_SN .byte "Syntax",$00 +ERR_RG .byte "RETURN without GOSUB",$00 +ERR_OD .byte "Out of DATA",$00 +ERR_FC .byte "Function call",$00 +ERR_OV .byte "Overflow",$00 +ERR_OM .byte "Out of memory",$00 +ERR_US .byte "Undefined statement",$00 +ERR_BS .byte "Array bounds",$00 +ERR_DD .byte "Double dimension",$00 +ERR_D0 .byte "Divide by zero",$00 +ERR_ID .byte "Illegal direct",$00 +ERR_TM .byte "Type mismatch",$00 +ERR_LS .byte "String too long",$00 +ERR_ST .byte "String too complex",$00 +ERR_CN .byte "Can't continue",$00 +ERR_UF .byte "Undefined function",$00 +ERR_LD .byte "LOOP without DO",$00 + +;ERR_UV .byte "Undefined variable",$00 + +; the above error has been tested and works (see code and comments below LAB_1D8B) + +;ERR_UA .byte "Undimensioned array",$00 + +LAB_BMSG .byte $0D,$0A,"Break",$00 +LAB_EMSG .byte " Error",$00 +LAB_LMSG .byte " in line ",$00 +LAB_RMSG .byte $0D,$0A,"Ready",$0D,$0A,$00 + +LAB_IMSG .byte " Extra ignored",$0D,$0A,$00 +LAB_REDO .byte " Redo from start",$0D,$0A,$00 + +AA_end_basic diff --git a/ehbas.dat b/ehbas.dat new file mode 100644 index 0000000..df282a4 --- /dev/null +++ b/ehbas.dat @@ -0,0 +1,2064 @@ +; Program disassembly from $C000 to $FFDF 3/4/2016 +; EhBasic image for MKBASIC 6502 simulator. +; +ORG +$C000 +; Char IO +IOADDR +$FFE0 +; ROM +ROMBEGIN +$FFC0 +ROMEND +$FFDF +; Enable char IO and ROM +ENIO +ENROM +; Auto-execute +EXEC +$C000 +; Data/Code +$D8, $A0, $08, $B9, $FB, $E0, $99, $00 +$02, $88, $10, $F7, $A2, $FF, $8E, $21 +$02, $86, $88, $9A, $A9, $4C, $85, $A1 +$A2, $1C, $BD, $03, $E1, $95, $BB, $CA +$D0, $F8, $A2, $12, $BD, $20, $E1, $95 +$00, $CA, $10, $F8, $A9, $00, $85, $DC +$85, $DF, $85, $B2, $85, $67, $A9, $0E +$85, $64, $A9, $03, $85, $A0, $A2, $68 +$86, $65, $20, $97, $C8, $A9, $33, $A0 +$E1, $20, $D8, $C8, $20, $45, $C2, $86 +$C3, $84, $C4, $20, $C2, $00, $D0, $1F +$A0, $00, $E6, $11, $D0, $08, $E6, $12 +$A5, $12, $C9, $C0, $F0, $1D, $A9, $55 +$91, $11, $D1, $11, $D0, $15, $0A, $91 +$11, $D1, $11, $F0, $E5, $D0, $0C, $20 +$AB, $D9, $A5, $AC, $C9, $98, $B0, $A2 +$20, $FC, $D4, $A5, $11, $A4, $12, $C0 +$01, $90, $97, $85, $85, $84, $86, $85 +$81, $84, $82, $A0, $00, $A2, $03, $84 +$79, $86, $7A, $98, $91, $79, $E6, $79 +$20, $97, $C8, $20, $55, $C3, $A5, $85 +$38, $E5, $79, $AA, $A5, $86, $E5, $7A +$20, $87, $DA, $A9, $42, $A0, $E1, $20 +$D8, $C8, $A9, $5E, $A0, $C1, $85, $01 +$84, $02, $6C, $01, $00, $20, $0F, $C1 +$85, $7F, $84, $80, $38, $A5, $A6, $E5 +$AA, $A8, $A5, $A7, $E5, $AB, $AA, $E8 +$98, $F0, $24, $38, $49, $FF, $65, $A6 +$85, $A6, $B0, $03, $C6, $A7, $38, $98 +$49, $FF, $65, $A4, $85, $A4, $B0, $08 +$C6, $A5, $90, $04, $B1, $A6, $91, $A4 +$88, $D0, $F9, $B1, $A6, $91, $A4, $C6 +$A7, $C6, $A5, $CA, $D0, $F2, $60, $85 +$78, $BA, $E4, $78, $90, $30, $60, $C4 +$82, $90, $2A, $D0, $04, $C5, $81, $90 +$24, $48, $A2, $08, $98, $48, $B5, $A3 +$CA, $10, $FA, $20, $E4, $D1, $A2, $00 +$68, $95, $A4, $E8, $E0, $08, $30, $F8 +$68, $A8, $68, $C4, $82, $90, $06, $D0 +$05, $C5, $81, $B0, $01, $60, $A2, $0C +$20, $97, $C8, $BD, $B2, $E6, $BC, $B3 +$E6, $20, $D8, $C8, $20, $8E, $C3, $A9 +$EF, $A0, $E7, $20, $D8, $C8, $A4, $88 +$C8, $F0, $03, $20, $7C, $DA, $A9, $00 +$85, $DF, $85, $DC, $A9, $00, $A0, $E8 +$20, $D8, $C8, $18, $20, $52, $C2, $86 +$C3, $84, $C4, $20, $C2, $00, $F0, $F4 +$A2, $FF, $86, $88, $90, $06, $20, $83 +$C2, $4C, $F8, $C4, $20, $5A, $C7, $20 +$83, $C2, $84, $5D, $20, $29, $C3, $90 +$44, $A0, $01, $B1, $AA, $85, $72, $A5 +$7B, $85, $71, $A5, $AB, $85, $74, $A5 +$AA, $88, $F1, $AA, $18, $65, $7B, $85 +$7B, $85, $73, $A5, $7C, $69, $FF, $85 +$7C, $E5, $AB, $AA, $38, $A5, $AA, $E5 +$7B, $A8, $B0, $03, $E8, $C6, $74, $18 +$65, $71, $90, $03, $C6, $72, $18, $B1 +$71, $91, $73, $C8, $D0, $F9, $E6, $72 +$E6, $74, $CA, $D0, $F2, $AD, $21, $02 +$F0, $3F, $A5, $85, $A4, $86, $85, $81 +$84, $82, $A5, $7B, $85, $A6, $A4, $7C +$84, $A7, $65, $5D, $90, $01, $C8, $85 +$A4, $84, $A5, $20, $C5, $C0, $A5, $7F +$A4, $80, $85, $7B, $84, $7C, $A4, $5D +$88, $B9, $1D, $02, $91, $AA, $88, $C0 +$03, $D0, $F6, $A5, $12, $91, $AA, $88 +$A5, $11, $91, $AA, $88, $A9, $FF, $91 +$AA, $20, $6A, $C3, $A6, $79, $A5, $7A +$A0, $01, $86, $71, $85, $72, $B1, $71 +$F0, $18, $A0, $04, $C8, $B1, $71, $D0 +$FB, $38, $98, $65, $71, $AA, $A0, $00 +$91, $71, $98, $65, $72, $C8, $91, $71 +$90, $E0, $4C, $6C, $C1, $20, $F0, $C8 +$20, $ED, $C8, $D0, $05, $20, $F2, $C8 +$CA, $2C, $A2, $00, $20, $EF, $E0, $90 +$FB, $F0, $F9, $C9, $07, $F0, $10, $C9 +$0D, $F0, $19, $E0, $00, $D0, $04, $C9 +$21, $90, $E9, $C9, $08, $F0, $DE, $E0 +$47, $B0, $0C, $9D, $21, $02, $E8, $20 +$F2, $C8, $D0, $D8, $4C, $8E, $C8, $A9 +$07, $D0, $F4, $A0, $FF, $38, $A5, $C3 +$E9, $21, $AA, $86, $60, $BD, $21, $02 +$F0, $51, $C9, $5F, $B0, $4D, $C9, $3C +$B0, $0E, $C9, $30, $B0, $45, $85, $5C +$C9, $22, $F0, $61, $C9, $2A, $90, $3B +$24, $60, $70, $37, $86, $78, $84, $BA +$A0, $19, $84, $73, $A0, $E3, $84, $74 +$A0, $00, $D1, $73, $F0, $05, $90, $21 +$C8, $D0, $F7, $98, $0A, $AA, $BD, $37 +$E3, $85, $73, $BD, $38, $E3, $85, $74 +$A0, $FF, $A6, $78, $C8, $B1, $73, $30 +$08, $E8, $DD, $21, $02, $F0, $F5, $D0 +$2B, $A4, $BA, $E8, $C8, $99, $21, $02 +$C9, $00, $F0, $32, $E9, $3A, $F0, $04 +$C9, $49, $D0, $02, $85, $60, $49, $57 +$D0, $93, $85, $5C, $BD, $21, $02, $F0 +$E2, $C5, $5C, $F0, $DE, $C8, $99, $21 +$02, $E8, $D0, $F0, $A6, $78, $B1, $73 +$08, $C8, $28, $10, $F9, $B1, $73, $D0 +$BE, $BD, $21, $02, $10, $C3, $C8, $C8 +$99, $21, $02, $C8, $C8, $C8, $C6, $C3 +$60, $A5, $79, $A6, $7A, $A0, $01, $85 +$AA, $86, $AB, $B1, $AA, $F0, $1A, $A0 +$03, $B1, $AA, $88, $C5, $12, $D0, $04 +$B1, $AA, $C5, $11, $B0, $09, $88, $B1 +$AA, $AA, $88, $B1, $AA, $90, $DE, $F0 +$01, $18, $60, $D0, $FD, $A9, $00, $A8 +$91, $79, $C8, $91, $79, $18, $A5, $79 +$69, $02, $85, $7B, $A5, $7A, $69, $00 +$85, $7C, $18, $A5, $79, $69, $FF, $85 +$C3, $A5, $7A, $69, $FF, $85, $C4, $A5 +$85, $A4, $86, $85, $81, $84, $82, $A5 +$7B, $A4, $7C, $85, $7D, $84, $7E, $85 +$7F, $84, $80, $20, $49, $C5, $A2, $68 +$86, $65, $68, $AA, $68, $8E, $FE, $01 +$8D, $FF, $01, $A2, $FD, $9A, $A9, $00 +$85, $8C, $85, $61, $60, $F0, $D0, $60 +$90, $06, $F0, $04, $C9, $B7, $D0, $F4 +$20, $5A, $C7, $20, $29, $C3, $20, $C2 +$00, $F0, $0C, $C9, $B7, $D0, $93, $20 +$BC, $00, $20, $5A, $C7, $D0, $8B, $A5 +$11, $05, $12, $D0, $06, $A9, $FF, $85 +$11, $85, $12, $A0, $01, $84, $60, $20 +$97, $C8, $B1, $AA, $F0, $3E, $20, $19 +$C5, $C8, $B1, $AA, $AA, $C8, $B1, $AA +$C5, $12, $D0, $04, $E4, $11, $F0, $02 +$B0, $2A, $84, $97, $20, $87, $DA, $A9 +$20, $A4, $97, $29, $7F, $20, $F2, $C8 +$C9, $22, $D0, $06, $A5, $60, $49, $FF +$85, $60, $C8, $B1, $AA, $D0, $0E, $A8 +$B1, $AA, $AA, $C8, $B1, $AA, $86, $AA +$85, $AB, $D0, $B7, $60, $10, $DE, $24 +$60, $30, $DA, $A2, $E5, $0A, $0A, $90 +$02, $E8, $18, $69, $1A, $90, $01, $E8 +$85, $73, $86, $74, $84, $97, $A0, $00 +$B1, $73, $AA, $C8, $B1, $73, $CA, $F0 +$B8, $20, $F2, $C8, $C8, $B1, $73, $48 +$C8, $B1, $73, $A0, $00, $85, $74, $68 +$85, $73, $B1, $73, $CA, $F0, $A2, $20 +$F2, $C8, $C8, $D0, $F5, $A9, $80, $85 +$61, $20, $B9, $C7, $68, $68, $A9, $10 +$20, $07, $C1, $20, $A2, $C6, $18, $98 +$65, $C3, $48, $A5, $C4, $69, $00, $48 +$A5, $88, $48, $A5, $87, $48, $A9, $AD +$20, $F6, $CB, $20, $D5, $CA, $20, $D2 +$CA, $A5, $B0, $09, $7F, $25, $AD, $85 +$AD, $A9, $9C, $A0, $C4, $85, $71, $84 +$72, $4C, $89, $CB, $A9, $E9, $A0, $E1 +$20, $82, $D8, $20, $C2, $00, $C9, $B2 +$D0, $06, $20, $BC, $00, $20, $D2, $CA +$20, $EE, $D8, $85, $B0, $20, $7E, $CB +$A5, $98, $48, $A5, $97, $48, $A9, $81 +$48, $20, $19, $C5, $A5, $C3, $A4, $C4 +$A6, $88, $E8, $F0, $04, $85, $8B, $84 +$8C, $A0, $00, $B1, $C3, $F0, $07, $C9 +$3A, $F0, $1D, $4C, $07, $CC, $A0, $02 +$B1, $C3, $18, $F0, $56, $C8, $B1, $C3 +$85, $87, $C8, $B1, $C3, $85, $88, $98 +$65, $C3, $85, $C3, $90, $02, $E6, $C4 +$20, $BC, $00, $20, $01, $C5, $4C, $C1 +$C4, $F0, $54, $0A, $B0, $03, $4C, $B9 +$C7, $C9, $56, $B0, $CE, $A8, $B9, $11 +$E2, $48, $B9, $10, $E2, $48, $4C, $BC +$00, $6C, $03, $02, $C9, $03, $B0, $01 +$18, $D0, $67, $A5, $C4, $49, $02, $F0 +$10, $49, $02, $A4, $C3, $84, $8B, $85 +$8C, $A5, $87, $A4, $88, $85, $89, $84 +$8A, $68, $68, $90, $07, $A9, $E7, $A0 +$E7, $4C, $53, $C1, $4C, $5E, $C1, $D0 +$0F, $38, $A5, $79, $E9, $01, $A4, $7A +$B0, $01, $88, $85, $8F, $84, $90, $60 +$20, $5A, $C7, $20, $A5, $C6, $A5, $88 +$C5, $12, $B0, $0B, $98, $38, $65, $C3 +$A6, $C4, $90, $07, $E8, $B0, $04, $A5 +$79, $A6, $7A, $20, $2D, $C3, $B0, $03 +$4C, $77, $C6, $A5, $AA, $E9, $01, $A4 +$AB, $B0, $D0, $90, $CD, $20, $91, $D4 +$86, $0D, $60, $D0, $FD, $A4, $8C, $D0 +$05, $A2, $1E, $4C, $40, $C1, $A9, $93 +$20, $19, $DF, $A9, $93, $20, $1C, $DF +$84, $C4, $A5, $8B, $85, $C3, $A5, $89 +$A4, $8A, $85, $87, $84, $88, $60, $D0 +$03, $4C, $6A, $C3, $20, $77, $C3, $F0 +$2E, $A9, $05, $20, $07, $C1, $A5, $C4 +$48, $A5, $C3, $48, $A5, $88, $48, $A5 +$87, $48, $A9, $9D, $48, $20, $C2, $00 +$4C, $C1, $C4, $A9, $05, $20, $07, $C1 +$A5, $C4, $48, $A5, $C3, $48, $A5, $88 +$48, $A5, $87, $48, $A9, $8D, $48, $20 +$C2, $00, $20, $F0, $C5, $4C, $C1, $C4 +$20, $5A, $C7, $20, $A5, $C6, $A5, $88 +$C5, $12, $B0, $0B, $98, $38, $65, $C3 +$A6, $C4, $90, $07, $E8, $B0, $04, $A5 +$79, $A6, $7A, $20, $2D, $C3, $90, $67 +$A5, $AA, $E9, $01, $85, $C3, $A5, $AB +$E9, $00, $85, $C4, $60, $A2, $22, $4C +$40, $C1, $A8, $BA, $BD, $03, $01, $C9 +$9D, $D0, $F2, $E8, $E8, $9A, $98, $F0 +$20, $C9, $3A, $F0, $1C, $E9, $B3, $AA +$F0, $04, $CA, $D0, $62, $CA, $86, $98 +$20, $BC, $00, $20, $E6, $CA, $A5, $AC +$F0, $02, $A9, $FF, $BA, $45, $98, $D0 +$1A, $BD, $02, $01, $85, $87, $BD, $03 +$01, $85, $88, $BD, $04, $01, $85, $C3 +$BD, $05, $01, $85, $C4, $20, $C2, $00 +$4C, $C1, $C4, $E8, $E8, $E8, $E8, $E8 +$9A, $4C, $91, $C6, $A2, $04, $2C, $A2 +$0E, $4C, $40, $C1, $D0, $9E, $68, $68 +$68, $C9, $8D, $D0, $EF, $68, $85, $87 +$68, $85, $88, $68, $85, $C3, $68, $85 +$C4, $20, $A2, $C6, $98, $18, $65, $C3 +$85, $C3, $90, $02, $E6, $C4, $60, $4C +$07, $CC, $A2, $3A, $2C, $A2, $00, $A0 +$00, $84, $5C, $8A, $45, $5C, $85, $5C +$B1, $C3, $F0, $EA, $C5, $5C, $F0, $E6 +$C8, $C9, $22, $D0, $F3, $F0, $EC, $20 +$E6, $CA, $20, $C2, $00, $C9, $B0, $F0 +$11, $C9, $89, $D0, $D2, $A6, $C3, $A4 +$C4, $20, $BC, $00, $B0, $C9, $86, $C3 +$84, $C4, $A5, $AC, $F0, $1B, $20, $BC +$00, $B0, $03, $4C, $F0, $C5, $C9, $90 +$D0, $03, $4C, $03, $C5, $20, $01, $C5 +$A0, $00, $B1, $C3, $C9, $AC, $F0, $99 +$60, $A0, $00, $A2, $01, $C8, $B1, $C3 +$F0, $0F, $C9, $8B, $D0, $03, $E8, $D0 +$F4, $C9, $AC, $D0, $F0, $CA, $D0, $ED +$C8, $98, $18, $65, $C3, $85, $C3, $90 +$02, $E6, $C4, $20, $C2, $00, $90, $C3 +$4C, $01, $C5, $20, $A5, $C6, $4C, $94 +$C6, $4C, $07, $CC, $C9, $A9, $D0, $03 +$4C, $3D, $DF, $C9, $AA, $D0, $03, $4C +$41, $DF, $20, $91, $D4, $48, $C9, $8D +$F0, $04, $C9, $89, $D0, $E3, $C6, $AF +$D0, $04, $68, $4C, $03, $C5, $20, $BC +$00, $20, $5A, $C7, $C9, $2C, $F0, $EE +$68, $60, $A2, $00, $86, $11, $86, $12 +$B0, $F7, $E0, $19, $A8, $B0, $DD, $E9 +$2F, $A8, $A5, $11, $0A, $26, $12, $0A +$26, $12, $65, $11, $85, $11, $8A, $65 +$12, $06, $11, $2A, $AA, $98, $65, $11 +$85, $11, $90, $01, $E8, $20, $BC, $00 +$4C, $5E, $C7, $A9, $ED, $2C, $A9, $E9 +$48, $20, $AF, $CD, $A6, $5F, $30, $1E +$85, $97, $84, $98, $20, $82, $D8, $68 +$48, $A0, $E1, $20, $C3, $D5, $20, $A8 +$D8, $20, $C2, $00, $C9, $2C, $D0, $A8 +$20, $BC, $00, $4C, $91, $C7, $4C, $E1 +$CA, $20, $AF, $CD, $85, $97, $84, $98 +$A9, $C1, $20, $F6, $CB, $A5, $5F, $48 +$20, $E6, $CA, $68, $2A, $20, $D8, $CA +$D0, $03, $4C, $A8, $D8, $A0, $02, $B1 +$AE, $C5, $82, $90, $17, $D0, $07, $88 +$B1, $AE, $C5, $81, $90, $0E, $A4, $AF +$C4, $7C, $90, $08, $D0, $0D, $A5, $AE +$C5, $7B, $B0, $07, $A5, $AE, $A4, $AF +$4C, $11, $C8, $A0, $00, $B1, $AE, $20 +$37, $D1, $A5, $9E, $A4, $9F, $85, $B8 +$84, $B9, $20, $16, $D3, $A9, $AC, $A0 +$00, $85, $9E, $84, $9F, $20, $78, $D3 +$A0, $00, $B1, $9E, $91, $97, $C8, $B1 +$9E, $91, $97, $C8, $B1, $9E, $91, $97 +$60, $20, $AF, $CD, $85, $97, $84, $98 +$20, $05, $DF, $A6, $5F, $30, $07, $A8 +$20, $6B, $D0, $4C, $A8, $D8, $48, $A9 +$01, $B0, $01, $68, $20, $3F, $D1, $F0 +$05, $68, $A0, $00, $91, $AD, $20, $8A +$D1, $4C, $D5, $C7, $20, $DB, $C8, $20 +$C2, $00, $F0, $3B, $C9, $AB, $F0, $56 +$C9, $AF, $F0, $52, $C9, $2C, $F0, $38 +$C9, $3B, $F0, $66, $20, $E6, $CA, $24 +$5F, $30, $E1, $20, $9A, $DA, $20, $49 +$D1, $A0, $00, $A5, $0F, $F0, $0A, $38 +$E5, $0E, $F1, $AE, $B0, $03, $20, $97 +$C8, $20, $DB, $C8, $F0, $C9, $A9, $00 +$9D, $21, $02, $A2, $21, $A0, $02, $A9 +$0D, $20, $F2, $C8, $A9, $0A, $D0, $52 +$A5, $0E, $C5, $10, $90, $05, $20, $97 +$C8, $D0, $27, $38, $E5, $64, $B0, $FC +$49, $FF, $69, $01, $D0, $12, $48, $20 +$8E, $D4, $C9, $29, $D0, $7B, $68, $C9 +$AB, $D0, $06, $8A, $E5, $0E, $90, $0A +$AA, $8A, $F0, $06, $20, $ED, $C8, $CA +$D0, $FA, $20, $BC, $00, $D0, $85, $60 +$20, $49, $D1, $20, $43, $D3, $A0, $00 +$AA, $F0, $49, $B1, $71, $20, $F2, $C8 +$C8, $CA, $D0, $F7, $60, $A9, $20, $2C +$A9, $3F, $C9, $20, $90, $19, $48, $A5 +$0F, $D0, $0A, $A5, $0E, $E5, $64, $D0 +$0B, $85, $0E, $F0, $07, $C5, $0E, $D0 +$03, $20, $97, $C8, $E6, $0E, $68, $20 +$F2, $E0, $C9, $0D, $D0, $14, $86, $78 +$A6, $0D, $F0, $0A, $A9, $00, $20, $F2 +$C8, $CA, $D0, $FA, $A9, $0D, $86, $0E +$A6, $78, $29, $FF, $60, $A5, $62, $10 +$0B, $A5, $8D, $A4, $8E, $85, $87, $84 +$88, $4C, $07, $CC, $A9, $1B, $A0, $E8 +$20, $D8, $C8, $A5, $8B, $A4, $8C, $85 +$C3, $84, $C4, $60, $C9, $22, $D0, $0B +$20, $C3, $CB, $A9, $3B, $20, $F6, $CB +$20, $DB, $C8, $20, $6F, $D0, $20, $45 +$C2, $A9, $00, $CD, $21, $02, $D0, $0A +$18, $4C, $31, $C5, $A6, $8F, $A4, $90 +$A9, $80, $85, $62, $86, $91, $84, $92 +$20, $AF, $CD, $85, $97, $84, $98, $A5 +$C3, $A4, $C4, $85, $11, $84, $12, $A6 +$91, $A4, $92, $86, $C3, $84, $C4, $20 +$C2, $00, $D0, $11, $24, $62, $30, $65 +$20, $F0, $C8, $20, $45, $C2, $86, $C3 +$84, $C4, $20, $C2, $00, $24, $5F, $10 +$24, $85, $5B, $C9, $22, $F0, $07, $A9 +$3A, $85, $5B, $A9, $2C, $18, $85, $5C +$A5, $C3, $A4, $C4, $69, $00, $90, $01 +$C8, $20, $4F, $D1, $20, $D4, $D4, $20 +$D5, $C7, $4C, $D3, $C9, $20, $AB, $D9 +$20, $A8, $D8, $20, $C2, $00, $F0, $0A +$C9, $2C, $F0, $03, $4C, $2D, $C9, $20 +$BC, $00, $A5, $C3, $A4, $C4, $85, $91 +$84, $92, $A5, $11, $A4, $12, $85, $C3 +$84, $C4, $20, $C2, $00, $F0, $2C, $20 +$03, $CC, $4C, $78, $C9, $20, $A2, $C6 +$C8, $AA, $D0, $12, $A2, $06, $C8, $B1 +$C3, $F0, $73, $C8, $B1, $C3, $85, $8D +$C8, $B1, $C3, $C8, $85, $8E, $B1, $C3 +$C8, $AA, $20, $94, $C6, $E0, $83, $F0 +$81, $D0, $DA, $A5, $91, $A4, $92, $A6 +$62, $10, $03, $4C, $53, $C5, $A0, $00 +$B1, $91, $D0, $01, $60, $A9, $0A, $A0 +$E8, $4C, $D8, $C8, $BA, $E8, $E8, $E8 +$E8, $BD, $01, $01, $C9, $81, $D0, $21 +$A5, $98, $D0, $0A, $BD, $02, $01, $85 +$97, $BD, $03, $01, $85, $98, $DD, $03 +$01, $D0, $07, $A5, $97, $DD, $02, $01 +$F0, $07, $8A, $18, $69, $10, $AA, $D0 +$D8, $60, $D0, $04, $A0, $00, $F0, $03 +$20, $AF, $CD, $85, $97, $84, $98, $20 +$3C, $CA, $F0, $04, $A2, $00, $F0, $63 +$9A, $8A, $38, $E9, $F7, $85, $73, $69 +$FB, $A0, $01, $20, $82, $D8, $BA, $BD +$08, $01, $85, $B0, $A5, $97, $A4, $98 +$20, $C3, $D5, $20, $A8, $D8, $A0, $01 +$20, $1E, $D9, $BA, $DD, $08, $01, $F0 +$17, $BD, $0D, $01, $85, $87, $BD, $0E +$01, $85, $88, $BD, $10, $01, $85, $C3 +$BD, $0F, $01, $85, $C4, $4C, $C1, $C4 +$8A, $69, $0F, $AA, $9A, $20, $C2, $00 +$C9, $2C, $D0, $F1, $20, $BC, $00, $20 +$70, $CA, $20, $E6, $CA, $18, $24, $38 +$24, $5F, $30, $03, $B0, $03, $60, $B0 +$FD, $A2, $18, $4C, $40, $C1, $A6, $C3 +$D0, $02, $C6, $C4, $C6, $C3, $A9, $00 +$48, $A9, $02, $20, $07, $C1, $20, $D2 +$CB, $A9, $00, $85, $9B, $20, $C2, $00 +$38, $E9, $C0, $90, $17, $C9, $03, $B0 +$13, $C9, $01, $2A, $49, $01, $45, $9B +$C5, $9B, $90, $67, $85, $9B, $20, $BC +$00, $4C, $00, $CB, $A6, $9B, $D0, $2C +$B0, $79, $69, $0A, $90, $75, $D0, $07 +$24, $5F, $10, $03, $4C, $D9, $D2, $85 +$71, $0A, $65, $71, $A8, $68, $D9, $F2 +$E2, $B0, $65, $20, $D5, $CA, $48, $20 +$67, $CB, $68, $A4, $99, $10, $19, $AA +$F0, $76, $D0, $5D, $26, $5F, $8A, $85 +$5F, $2A, $A6, $C3, $D0, $02, $C6, $C4 +$C6, $C3, $A0, $24, $85, $9B, $D0, $D5 +$D9, $F2, $E2, $B0, $44, $90, $D7, $B9 +$F4, $E2, $48, $B9, $F3, $E2, $48, $20 +$7E, $CB, $A5, $9B, $48, $B9, $F2, $E2 +$4C, $F0, $CA, $4C, $07, $CC, $68, $85 +$71, $E6, $71, $68, $85, $72, $A5, $B0 +$48, $20, $DE, $D8, $A5, $AF, $48, $A5 +$AE, $48, $A5, $AD, $48, $A5, $AC, $48 +$6C, $71, $00, $A0, $FF, $68, $F0, $20 +$C9, $64, $F0, $03, $20, $D5, $CA, $84 +$99, $68, $4A, $85, $63, $68, $85, $B3 +$68, $85, $B4, $68, $85, $B5, $68, $85 +$B6, $68, $85, $B7, $45, $B0, $85, $B8 +$A5, $AC, $60, $A5, $C3, $A4, $C4, $69 +$00, $90, $01, $C8, $20, $49, $D1, $4C +$D4, $D4, $20, $BC, $00, $B0, $03, $4C +$AB, $D9, $AA, $30, $2F, $C9, $24, $F0 +$F6, $C9, $25, $F0, $F2, $C9, $2E, $F0 +$EE, $C9, $22, $F0, $D6, $C9, $28, $D0 +$4F, $20, $EE, $CA, $A9, $29, $A0, $00 +$D1, $C3, $D0, $0B, $4C, $BC, $00, $A9 +$28, $D0, $F3, $A9, $2C, $D0, $EF, $A2 +$02, $4C, $40, $C1, $C9, $B7, $F0, $29 +$C9, $B6, $F0, $BE, $C9, $B1, $D0, $13 +$A0, $21, $D0, $1F, $20, $AB, $CE, $A5 +$AF, $49, $FF, $A8, $A5, $AE, $49, $FF +$4C, $5E, $D0, $C9, $AE, $D0, $03, $4C +$B9, $D0, $E9, $C3, $B0, $19, $4C, $07 +$CC, $A0, $1E, $68, $68, $4C, $3F, $CB +$20, $AF, $CD, $85, $AE, $84, $AF, $A6 +$5F, $30, $03, $4C, $82, $D8, $60, $0A +$A8, $B9, $AD, $E2, $48, $B9, $AC, $E2 +$48, $B9, $67, $E2, $F0, $05, $48, $B9 +$66, $E2, $48, $60, $20, $F1, $CB, $4C +$D7, $CA, $20, $F1, $CB, $4C, $D5, $CA +$46, $5F, $4C, $BC, $00, $20, $EE, $CA +$20, $03, $CC, $20, $D7, $CA, $68, $AA +$68, $A8, $A5, $AF, $48, $A5, $AE, $48 +$98, $48, $8A, $48, $20, $91, $D4, $8A +$60, $20, $EE, $CA, $20, $D5, $CA, $A5 +$AC, $C9, $98, $B0, $20, $20, $55, $D9 +$A2, $02, $B5, $AD, $95, $11, $CA, $10 +$F9, $20, $C2, $00, $A2, $00, $C9, $29 +$F0, $0A, $20, $E3, $D4, $20, $C2, $00 +$C9, $29, $D0, $01, $60, $4C, $2E, $CF +$20, $E7, $CC, $45, $5B, $A8, $A5, $AE +$45, $5C, $4C, $5E, $D0, $20, $E7, $CC +$05, $5B, $A8, $A5, $AE, $05, $5C, $4C +$5E, $D0, $20, $E7, $CC, $25, $5B, $A8 +$A5, $AE, $25, $5C, $4C, $5E, $D0, $20 +$AB, $CE, $A5, $AE, $85, $5C, $A5, $AF +$85, $5B, $20, $C8, $D5, $20, $AB, $CE +$A5, $AF, $60, $20, $D8, $CA, $B0, $13 +$A5, $B7, $09, $7F, $25, $B4, $85, $B4 +$A9, $B3, $A0, $00, $20, $1C, $D9, $AA +$4C, $44, $CD, $46, $5F, $C6, $9B, $20 +$43, $D3, $85, $AC, $86, $AD, $84, $AE +$A5, $B5, $A4, $B6, $20, $47, $D3, $86 +$B5, $84, $B6, $AA, $38, $E5, $AC, $F0 +$08, $A9, $01, $90, $04, $A6, $AC, $A9 +$FF, $85, $B0, $A0, $FF, $E8, $C8, $CA +$D0, $07, $A6, $B0, $30, $0F, $18, $90 +$0C, $B1, $B5, $D1, $AD, $F0, $EF, $A2 +$FF, $B0, $02, $A2, $01, $E8, $8A, $2A +$25, $63, $F0, $02, $A9, $FF, $4C, $FF +$D8, $20, $03, $CC, $AA, $20, $B4, $CD +$20, $C2, $00, $D0, $F4, $60, $20, $A4 +$CD, $A5, $AE, $A6, $78, $F0, $22, $E0 +$10, $B0, $23, $06, $AF, $2A, $CA, $D0 +$FA, $A4, $AF, $4C, $5E, $D0, $20, $A4 +$CD, $A5, $AE, $A6, $78, $F0, $0A, $E0 +$10, $B0, $0B, $4A, $66, $AF, $CA, $D0 +$FA, $A4, $AF, $4C, $5E, $D0, $A9, $00 +$A8, $4C, $5E, $D0, $20, $94, $D4, $86 +$78, $20, $C8, $D5, $4C, $AB, $CE, $A2 +$00, $20, $C2, $00, $86, $5E, $85, $93 +$29, $7F, $20, $23, $CE, $B0, $03, $4C +$07, $CC, $A2, $00, $86, $5F, $20, $BC +$00, $90, $05, $20, $23, $CE, $90, $0B +$AA, $20, $BC, $00, $90, $FB, $20, $23 +$CE, $B0, $F6, $C9, $24, $D0, $0B, $A9 +$FF, $85, $5F, $8A, $09, $80, $AA, $20 +$BC, $00, $86, $94, $05, $61, $C9, $28 +$D0, $03, $4C, $BD, $CE, $A9, $00, $85 +$61, $A5, $7B, $A6, $7C, $A0, $00, $86 +$AB, $85, $AA, $E4, $7E, $D0, $04, $C5 +$7D, $F0, $2C, $A5, $93, $D1, $AA, $D0 +$08, $A5, $94, $C8, $D1, $AA, $F0, $69 +$88, $18, $A5, $AA, $69, $06, $90, $E1 +$E8, $D0, $DC, $C9, $61, $B0, $0A, $C9 +$41, $90, $05, $E9, $5B, $38, $E9, $A5 +$60, $E9, $7B, $38, $E9, $85, $60, $68 +$48, $C9, $42, $D0, $05, $A9, $EA, $A0 +$E1, $60, $A5, $7D, $A4, $7E, $85, $AA +$84, $AB, $A5, $7F, $A4, $80, $85, $A6 +$84, $A7, $18, $69, $06, $90, $01, $C8 +$85, $A4, $84, $A5, $20, $C5, $C0, $A5 +$A4, $A4, $A5, $C8, $85, $7D, $84, $7E +$A0, $00, $A5, $93, $91, $AA, $C8, $A5 +$94, $91, $AA, $A9, $00, $C8, $91, $AA +$C8, $91, $AA, $C8, $91, $AA, $C8, $91 +$AA, $A5, $AA, $18, $69, $02, $A4, $AB +$90, $01, $C8, $85, $95, $84, $96, $60 +$A5, $5D, $0A, $69, $05, $65, $AA, $A4 +$AB, $90, $01, $C8, $85, $A4, $84, $A5 +$60, $20, $BC, $00, $20, $D2, $CA, $A5 +$B0, $30, $0D, $A5, $AC, $C9, $90, $90 +$09, $A9, $F1, $A0, $E1, $20, $1C, $D9 +$D0, $74, $4C, $55, $D9, $A5, $5E, $48 +$A5, $5F, $48, $A0, $00, $98, $48, $A5 +$94, $48, $A5, $93, $48, $20, $A1, $CE +$68, $85, $93, $68, $85, $94, $68, $A8 +$BA, $BD, $02, $01, $48, $BD, $01, $01 +$48, $A5, $AE, $9D, $02, $01, $A5, $AF +$9D, $01, $01, $C8, $20, $C2, $00, $C9 +$2C, $F0, $D2, $84, $5D, $20, $F4, $CB +$68, $85, $5F, $68, $85, $5E, $A6, $7D +$A5, $7E, $86, $AA, $85, $AB, $C5, $80 +$D0, $04, $E4, $7F, $F0, $39, $A0, $00 +$B1, $AA, $C8, $C5, $93, $D0, $06, $A5 +$94, $D1, $AA, $F0, $16, $C8, $B1, $AA +$18, $65, $AA, $AA, $C8, $B1, $AA, $65 +$AB, $90, $D7, $A2, $10, $2C, $A2, $08 +$4C, $40, $C1, $A2, $12, $A5, $5E, $D0 +$F7, $20, $90, $CE, $A5, $5D, $A0, $04 +$D1, $AA, $D0, $E7, $4C, $CA, $CF, $20 +$90, $CE, $20, $0F, $C1, $A0, $00, $84 +$BB, $A5, $93, $91, $AA, $C8, $A5, $94 +$91, $AA, $A5, $5D, $A0, $04, $84, $BA +$91, $AA, $18, $A2, $0B, $A9, $00, $24 +$5E, $50, $07, $68, $69, $01, $AA, $68 +$69, $00, $C8, $91, $AA, $C8, $8A, $91 +$AA, $20, $19, $D0, $86, $BA, $85, $BB +$A4, $71, $C6, $5D, $D0, $DD, $65, $A5 +$B0, $5D, $85, $A5, $A8, $8A, $65, $A4 +$90, $03, $C8, $F0, $52, $20, $0F, $C1 +$85, $7F, $84, $80, $A9, $00, $E6, $BB +$A4, $BA, $F0, $05, $88, $91, $A4, $D0 +$FB, $C6, $A5, $C6, $BB, $D0, $F5, $E6 +$A5, $38, $A0, $02, $A5, $7F, $E5, $AA +$91, $AA, $C8, $A5, $80, $E5, $AB, $91 +$AA, $A5, $5E, $D0, $53, $C8, $B1, $AA +$85, $5D, $A9, $00, $85, $BA, $85, $BB +$C8, $68, $AA, $85, $AE, $68, $85, $AF +$D1, $AA, $90, $0E, $D0, $06, $C8, $8A +$D1, $AA, $90, $07, $4C, $2B, $CF, $4C +$3E, $C1, $C8, $A5, $BB, $05, $BA, $F0 +$0A, $20, $19, $D0, $8A, $65, $AE, $AA +$98, $A4, $71, $65, $AF, $86, $BA, $C6 +$5D, $D0, $CB, $06, $BA, $2A, $06, $BA +$2A, $A8, $A5, $BA, $65, $A4, $85, $95 +$98, $65, $A5, $85, $96, $A8, $A5, $95 +$60, $84, $71, $B1, $AA, $85, $76, $88 +$B1, $AA, $85, $77, $A9, $10, $85, $A8 +$A2, $00, $A0, $00, $8A, $0A, $AA, $98 +$2A, $A8, $B0, $B3, $06, $BA, $26, $BB +$90, $0B, $18, $8A, $65, $76, $AA, $98 +$65, $77, $A8, $B0, $A2, $C6, $A8, $D0 +$E3, $60, $A5, $5F, $10, $03, $20, $43 +$D3, $20, $E4, $D1, $38, $A5, $81, $E5 +$7F, $A8, $A5, $82, $E5, $80, $46, $5F +$85, $AD, $84, $AE, $A2, $90, $4C, $07 +$D9, $A4, $0E, $A9, $00, $F0, $EF, $A6 +$88, $E8, $D0, $A4, $A2, $16, $4C, $40 +$C1, $20, $AA, $D0, $85, $9C, $84, $9D +$20, $6F, $D0, $20, $FF, $CB, $A9, $80 +$85, $61, $20, $AF, $CD, $20, $D5, $CA +$20, $F4, $CB, $A9, $C1, $20, $F6, $CB +$A5, $96, $48, $A5, $95, $48, $A5, $C4 +$48, $A5, $C3, $48, $20, $91, $C6, $4C +$19, $D1, $A9, $AE, $20, $F6, $CB, $09 +$80, $85, $61, $20, $B6, $CD, $4C, $D5 +$CA, $20, $AA, $D0, $48, $98, $48, $20 +$FF, $CB, $20, $E6, $CA, $20, $F4, $CB +$20, $D5, $CA, $68, $85, $9D, $68, $85 +$9C, $A2, $20, $A0, $03, $B1, $9C, $F0 +$9D, $85, $96, $88, $B1, $9C, $85, $95 +$AA, $C8, $B1, $95, $48, $88, $10, $FA +$A4, $96, $20, $AC, $D8, $A5, $C4, $48 +$A5, $C3, $48, $B1, $9C, $85, $C3, $C8 +$B1, $9C, $85, $C4, $A5, $96, $48, $A5 +$95, $48, $20, $D2, $CA, $68, $85, $9C +$68, $85, $9D, $20, $C2, $00, $F0, $03 +$4C, $07, $CC, $68, $85, $C3, $68, $85 +$C4, $A0, $00, $68, $91, $9C, $C8, $68 +$91, $9C, $C8, $68, $91, $9C, $C8, $68 +$91, $9C, $60, $20, $D5, $CA, $20, $9A +$DA, $A9, $F0, $A0, $00, $F0, $12, $A6 +$AE, $A4, $AF, $86, $9E, $84, $9F, $20 +$B2, $D1, $86, $AD, $84, $AE, $85, $AC +$60, $A2, $22, $86, $5B, $86, $5C, $85 +$B8, $84, $B9, $85, $AD, $84, $AE, $A0 +$FF, $C8, $B1, $B8, $F0, $0C, $C5, $5B +$F0, $04, $C5, $5C, $D0, $F3, $C9, $22 +$F0, $01, $18, $84, $AC, $98, $65, $B8 +$85, $BA, $A6, $B9, $90, $01, $E8, $86 +$BB, $A5, $B9, $C9, $03, $B0, $0B, $98 +$20, $37, $D1, $A6, $B8, $A4, $B9, $20 +$24, $D3, $A6, $65, $E0, $71, $D0, $05 +$A2, $1C, $4C, $40, $C1, $A5, $AC, $95 +$00, $A5, $AD, $95, $01, $A5, $AE, $95 +$02, $A0, $00, $86, $AE, $84, $AF, $88 +$84, $5F, $86, $66, $E8, $E8, $E8, $86 +$65, $60, $46, $60, $48, $49, $FF, $38 +$65, $81, $A4, $82, $B0, $01, $88, $C4 +$80, $90, $11, $D0, $04, $C5, $7F, $90 +$0B, $85, $81, $84, $82, $85, $83, $84 +$84, $AA, $68, $60, $A2, $0C, $A5, $60 +$30, $B8, $20, $E4, $D1, $A9, $80, $85 +$60, $68, $D0, $D0, $A6, $85, $A5, $86 +$86, $81, $85, $82, $A0, $00, $84, $9D +$A5, $7F, $A6, $80, $85, $AA, $86, $AB +$A9, $68, $85, $71, $84, $72, $C5, $65 +$F0, $05, $20, $68, $D2, $F0, $F7, $06 +$A0, $A5, $7B, $A6, $7C, $85, $71, $86 +$72, $E4, $7E, $D0, $04, $C5, $7D, $F0 +$05, $20, $62, $D2, $F0, $F3, $85, $A4 +$86, $A5, $A9, $04, $85, $A0, $A5, $A4 +$A6, $A5, $E4, $80, $D0, $04, $C5, $7F +$F0, $75, $85, $71, $86, $72, $A0, $02 +$B1, $71, $65, $A4, $85, $A4, $C8, $B1 +$71, $65, $A5, $85, $A5, $A0, $01, $B1 +$71, $10, $DB, $A0, $04, $B1, $71, $0A +$69, $05, $20, $9A, $D2, $E4, $A5, $D0 +$04, $C5, $A4, $F0, $CD, $20, $68, $D2 +$F0, $F3, $C8, $B1, $71, $10, $30, $C8 +$B1, $71, $F0, $2B, $C8, $B1, $71, $AA +$C8, $B1, $71, $C5, $82, $90, $06, $D0 +$1E, $E4, $81, $B0, $1A, $C5, $AB, $90 +$17, $D0, $04, $E4, $AA, $90, $11, $86 +$AA, $85, $AB, $A5, $71, $A6, $72, $85 +$9C, $86, $9D, $88, $88, $84, $A2, $18 +$A5, $A0, $65, $71, $85, $71, $90, $02 +$E6, $72, $A6, $72, $A0, $00, $60, $C6 +$A0, $A6, $9D, $F0, $F5, $A4, $A2, $18 +$B1, $9C, $65, $AA, $85, $A6, $A5, $AB +$69, $00, $85, $A7, $A5, $81, $A6, $82 +$85, $A4, $86, $A5, $20, $CC, $C0, $A4 +$A2, $C8, $A5, $A4, $91, $9C, $AA, $E6 +$A5, $A5, $A5, $C8, $91, $9C, $4C, $E8 +$D1, $A5, $AF, $48, $A5, $AE, $48, $20 +$D2, $CB, $20, $D7, $CA, $68, $85, $B8 +$68, $85, $B9, $A0, $00, $B1, $B8, $18 +$71, $AE, $90, $05, $A2, $1A, $4C, $40 +$C1, $20, $37, $D1, $20, $16, $D3, $A5 +$9E, $A4, $9F, $20, $47, $D3, $20, $28 +$D3, $A5, $B8, $A4, $B9, $20, $47, $D3 +$20, $8A, $D1, $4C, $FD, $CA, $A0, $00 +$B1, $B8, $48, $C8, $B1, $B8, $AA, $C8 +$B1, $B8, $A8, $68, $86, $71, $84, $72 +$AA, $F0, $14, $A0, $00, $B1, $71, $91 +$83, $C8, $CA, $D0, $F8, $98, $18, $65 +$83, $85, $83, $90, $02, $E6, $84, $60 +$20, $D7, $CA, $A5, $AE, $A4, $AF, $85 +$71, $84, $72, $20, $78, $D3, $08, $A0 +$00, $B1, $71, $48, $C8, $B1, $71, $AA +$C8, $B1, $71, $A8, $68, $28, $D0, $13 +$C4, $82, $D0, $0F, $E4, $81, $D0, $0B +$48, $18, $65, $81, $85, $81, $90, $02 +$E6, $82, $68, $86, $71, $84, $72, $60 +$C4, $67, $D0, $0C, $C5, $66, $D0, $08 +$85, $65, $E9, $03, $85, $66, $A0, $00 +$60, $20, $94, $D4, $8A, $48, $A9, $01 +$20, $3F, $D1, $68, $A0, $00, $91, $AD +$4C, $8A, $D1, $48, $20, $FC, $D3, $D1 +$9E, $98, $F0, $09, $48, $20, $FC, $D3 +$18, $F1, $9E, $49, $FF, $90, $04, $B1 +$9E, $AA, $98, $48, $8A, $48, $20, $3F +$D1, $A5, $9E, $A4, $9F, $20, $47, $D3 +$68, $A8, $68, $18, $65, $71, $85, $71 +$90, $02, $E6, $72, $98, $20, $28, $D3 +$4C, $8A, $D1, $48, $A9, $FF, $85, $AF +$20, $C2, $00, $C9, $29, $F0, $06, $20 +$03, $CC, $20, $91, $D4, $20, $FC, $D3 +$CA, $8A, $48, $18, $A2, $00, $F1, $9E +$B0, $C2, $49, $FF, $C5, $AF, $90, $BD +$A5, $AF, $B0, $B9, $20, $F4, $CB, $68 +$85, $A2, $68, $85, $A3, $68, $AA, $68 +$85, $9E, $68, $85, $9F, $A0, $00, $8A +$F0, $79, $E6, $A2, $6C, $A2, $00, $20 +$40, $D3, $85, $AC, $A8, $F0, $38, $20 +$3F, $D1, $86, $AD, $84, $AE, $A8, $88 +$B1, $71, $20, $27, $CE, $90, $02, $09 +$20, $91, $83, $98, $D0, $F1, $F0, $1F +$20, $40, $D3, $85, $AC, $A8, $F0, $17 +$20, $3F, $D1, $86, $AD, $84, $AE, $A8 +$88, $B1, $71, $20, $23, $CE, $90, $02 +$29, $DF, $91, $83, $98, $D0, $F1, $4C +$8A, $D1, $20, $BC, $00, $20, $AF, $CD +$20, $F4, $CB, $20, $D7, $CA, $A0, $02 +$B1, $95, $AA, $88, $B1, $95, $A8, $8A +$4C, $5E, $D0, $20, $79, $D4, $4C, $6B +$D0, $20, $40, $D3, $A8, $60, $20, $79 +$D4, $F0, $08, $A0, $00, $B1, $71, $A8 +$4C, $6B, $D0, $4C, $2E, $CF, $20, $BC +$00, $20, $D2, $CA, $20, $A7, $CE, $A4 +$AE, $D0, $F0, $A6, $AF, $4C, $C2, $00 +$20, $79, $D4, $D0, $03, $4C, $55, $D6 +$A6, $C3, $A4, $C4, $86, $BA, $84, $BB +$A6, $71, $86, $C3, $18, $65, $71, $85 +$73, $A5, $72, $85, $C4, $69, $00, $85 +$74, $A0, $00, $B1, $73, $48, $98, $91 +$73, $20, $C2, $00, $20, $AB, $D9, $68 +$A0, $00, $91, $73, $A6, $BA, $A4, $BB +$86, $C3, $84, $C4, $60, $20, $D2, $CA +$20, $F6, $D4, $20, $03, $CC, $A5, $12 +$48, $A5, $11, $48, $20, $91, $D4, $68 +$85, $11, $68, $85, $12, $60, $A5, $AC +$C9, $98, $B0, $8F, $20, $55, $D9, $A5 +$AE, $A4, $AF, $84, $11, $85, $12, $60 +$20, $F6, $D4, $A2, $00, $A1, $11, $A8 +$4C, $6B, $D0, $20, $DD, $D4, $8A, $A2 +$00, $81, $11, $60, $20, $F6, $D4, $A2 +$00, $A1, $11, $A8, $E6, $11, $D0, $02 +$E6, $12, $A1, $11, $4C, $5E, $D0, $20 +$D2, $CA, $20, $F6, $D4, $84, $97, $85 +$98, $20, $03, $CC, $20, $D2, $CA, $20 +$F6, $D4, $98, $A2, $00, $81, $97, $E6 +$97, $D0, $02, $E6, $98, $A5, $12, $81 +$97, $4C, $C2, $00, $20, $AF, $CD, $85 +$97, $84, $98, $A5, $5F, $48, $20, $03 +$CC, $20, $AF, $CD, $68, $45, $5F, $10 +$10, $A0, $03, $B1, $97, $AA, $B1, $95 +$91, $97, $8A, $91, $95, $88, $10, $F3 +$60, $4C, $E1, $CA, $20, $D2, $CA, $20 +$F6, $D4, $A9, $D5, $48, $A9, $8A, $48 +$6C, $11, $00, $4C, $C2, $00, $20, $DD +$D4, $86, $97, $A2, $00, $20, $C2, $00 +$F0, $03, $20, $E3, $D4, $86, $98, $B1 +$11, $45, $98, $25, $97, $F0, $F8, $60 +$20, $90, $D7, $A5, $B0, $49, $FF, $85 +$B0, $45, $B7, $85, $B8, $A5, $AC, $4C +$C6, $D5, $20, $DF, $D6, $90, $4D, $A9 +$F2, $A0, $E1, $20, $90, $D7, $D0, $10 +$A5, $B7, $85, $B0, $A2, $04, $B5, $B2 +$95, $AB, $CA, $D0, $F9, $86, $B9, $60 +$A6, $B9, $86, $A3, $A2, $B3, $A5, $B3 +$A8, $F0, $C4, $38, $E5, $AC, $F0, $24 +$90, $12, $84, $AC, $A4, $B7, $84, $B0 +$49, $FF, $69, $00, $A0, $00, $84, $A3 +$A2, $AC, $D0, $04, $A0, $00, $84, $B9 +$C9, $F9, $30, $B6, $A8, $A5, $B9, $56 +$01, $20, $F6, $D6, $24, $B8, $10, $4C +$A0, $AC, $E0, $B3, $F0, $02, $A0, $B3 +$38, $49, $FF, $65, $A3, $85, $B9, $B9 +$03, $00, $F5, $03, $85, $AF, $B9, $02 +$00, $F5, $02, $85, $AE, $B9, $01, $00 +$F5, $01, $85, $AD, $B0, $03, $20, $9B +$D6, $A0, $00, $98, $18, $A6, $AD, $D0 +$3E, $A6, $AE, $86, $AD, $A6, $AF, $86 +$AE, $A6, $B9, $86, $AF, $84, $B9, $69 +$08, $C9, $18, $D0, $E8, $A9, $00, $85 +$AC, $85, $B0, $60, $65, $A3, $85, $B9 +$A5, $AF, $65, $B6, $85, $AF, $A5, $AE +$65, $B5, $85, $AE, $A5, $AD, $65, $B4 +$85, $AD, $B0, $1A, $60, $69, $01, $06 +$B9, $26, $AF, $26, $AE, $26, $AD, $10 +$F4, $38, $E5, $AC, $B0, $CF, $49, $FF +$69, $01, $85, $AC, $90, $0C, $E6, $AC +$F0, $36, $66, $AD, $66, $AE, $66, $AF +$66, $B9, $60, $A5, $B0, $49, $FF, $85 +$B0, $A5, $AD, $49, $FF, $85, $AD, $A5 +$AE, $49, $FF, $85, $AE, $A5, $AF, $49 +$FF, $85, $AF, $A5, $B9, $49, $FF, $85 +$B9, $E6, $B9, $D0, $0A, $E6, $AF, $D0 +$06, $E6, $AE, $D0, $02, $E6, $AD, $60 +$A2, $0A, $4C, $40, $C1, $A2, $74, $B4 +$03, $84, $B9, $B4, $02, $94, $03, $B4 +$01, $94, $02, $A4, $B2, $94, $01, $69 +$08, $30, $EC, $F0, $EA, $E9, $08, $A8 +$A5, $B9, $B0, $12, $16, $01, $90, $02 +$F6, $01, $76, $01, $76, $01, $76, $02 +$76, $03, $6A, $C8, $D0, $EE, $18, $60 +$20, $EE, $D8, $F0, $02, $10, $03, $4C +$2E, $CF, $A5, $AC, $E9, $7F, $48, $A9 +$80, $85, $AC, $A9, $72, $A0, $E1, $20 +$C3, $D5, $A9, $76, $A0, $E1, $20, $06 +$D8, $A9, $E9, $A0, $E1, $20, $A8, $D5 +$A9, $65, $A0, $E1, $20, $56, $DC, $A9 +$7A, $A0, $E1, $20, $C3, $D5, $68, $20 +$4A, $DA, $A9, $7E, $A0, $E1, $20, $90 +$D7, $F0, $4C, $20, $B6, $D7, $A9, $00 +$85, $75, $85, $76, $85, $77, $A5, $B9 +$20, $65, $D7, $A5, $AF, $20, $65, $D7 +$A5, $AE, $20, $65, $D7, $A5, $AD, $20 +$6A, $D7, $4C, $73, $D8, $D0, $03, $4C +$CD, $D6, $4A, $09, $80, $A8, $90, $13 +$18, $A5, $77, $65, $B6, $85, $77, $A5 +$76, $65, $B5, $85, $76, $A5, $75, $65 +$B4, $85, $75, $66, $75, $66, $76, $66 +$77, $66, $B9, $98, $4A, $D0, $DE, $60 +$85, $71, $84, $72, $A0, $03, $B1, $71 +$85, $B6, $88, $B1, $71, $85, $B5, $88 +$B1, $71, $85, $B7, $45, $B0, $85, $B8 +$A5, $B7, $09, $80, $85, $B4, $88, $B1 +$71, $85, $B3, $A5, $AC, $60, $A5, $B3 +$F0, $1D, $18, $65, $AC, $90, $04, $30 +$31, $18, $2C, $10, $12, $69, $80, $85 +$AC, $D0, $03, $4C, $59, $D6, $A5, $B8 +$85, $B0, $60, $A5, $B0, $10, $1B, $68 +$68, $4C, $55, $D6, $20, $CF, $D8, $AA +$F0, $F0, $18, $69, $02, $B0, $0B, $A2 +$00, $86, $B8, $20, $E0, $D5, $E6, $AC +$D0, $E0, $4C, $C8, $D6, $20, $CF, $D8 +$A9, $FA, $A0, $E1, $A2, $00, $86, $B8 +$20, $82, $D8, $4C, $09, $D8, $20, $90 +$D7, $F0, $63, $20, $DE, $D8, $A9, $00 +$38, $E5, $AC, $85, $AC, $20, $B6, $D7 +$E6, $AC, $F0, $D6, $A2, $FF, $A9, $01 +$A4, $B4, $C4, $AD, $D0, $0A, $A4, $B5 +$C4, $AE, $D0, $04, $A4, $B6, $C4, $AF +$08, $2A, $90, $0E, $A0, $01, $E8, $E0 +$02, $30, $04, $D0, $28, $A0, $40, $95 +$75, $98, $28, $90, $14, $A8, $A5, $B6 +$E5, $AF, $85, $B6, $A5, $B5, $E5, $AE +$85, $B5, $A5, $B4, $E5, $AD, $85, $B4 +$98, $06, $B6, $26, $B5, $26, $B4, $B0 +$CF, $30, $BD, $10, $CB, $4A, $6A, $6A +$85, $B9, $28, $4C, $73, $D8, $A2, $14 +$4C, $40, $C1, $A5, $75, $85, $AD, $A5 +$76, $85, $AE, $A5, $77, $85, $AF, $4C +$39, $D6, $85, $71, $84, $72, $A0, $03 +$B1, $71, $85, $AF, $88, $B1, $71, $85 +$AE, $88, $B1, $71, $85, $B0, $09, $80 +$85, $AD, $88, $B1, $71, $85, $AC, $84 +$B9, $60, $A2, $A4, $A0, $00, $F0, $04 +$A6, $97, $A4, $98, $20, $DE, $D8, $86 +$71, $84, $72, $A0, $03, $A5, $AF, $91 +$71, $88, $A5, $AE, $91, $71, $88, $A5 +$B0, $09, $7F, $25, $AD, $91, $71, $88 +$A5, $AC, $91, $71, $84, $B9, $60, $20 +$DE, $D8, $A2, $05, $B5, $AB, $95, $B2 +$CA, $D0, $F9, $86, $B9, $60, $A5, $AC +$F0, $FB, $06, $B9, $90, $F7, $20, $BD +$D6, $D0, $F2, $4C, $8E, $D6, $A5, $AC +$F0, $09, $A5, $B0, $2A, $A9, $FF, $B0 +$02, $A9, $01, $60, $20, $EE, $D8, $85 +$AD, $A9, $00, $85, $AE, $A2, $88, $A5 +$AD, $49, $FF, $2A, $A9, $00, $85, $AF +$86, $AC, $85, $B9, $85, $B0, $4C, $34 +$D6, $46, $B0, $60, $85, $73, $84, $74 +$A0, $00, $B1, $73, $C8, $AA, $F0, $C6 +$B1, $73, $45, $B0, $30, $C4, $E4, $AC +$D0, $1A, $B1, $73, $09, $80, $C5, $AD +$D0, $12, $C8, $B1, $73, $C5, $AE, $D0 +$0B, $C8, $A9, $7F, $C5, $B9, $B1, $73 +$E5, $AF, $F0, $28, $A5, $B0, $90, $02 +$49, $FF, $4C, $F4, $D8, $A5, $AC, $F0 +$4A, $38, $E9, $98, $24, $B0, $10, $09 +$AA, $A9, $FF, $85, $B2, $20, $A1, $D6 +$8A, $A2, $AC, $C9, $F9, $10, $06, $20 +$DF, $D6, $84, $B2, $60, $A8, $A5, $B0 +$29, $80, $46, $AD, $05, $AD, $85, $AD +$20, $F6, $D6, $84, $B2, $60, $A5, $AC +$C9, $98, $B0, $1E, $20, $55, $D9, $84 +$B9, $A5, $B0, $84, $B0, $49, $80, $2A +$A9, $98, $85, $AC, $A5, $AF, $85, $5B +$4C, $34, $D6, $85, $AD, $85, $AE, $85 +$AF, $A8, $60, $A0, $00, $84, $5F, $A2 +$09, $94, $A8, $CA, $10, $FB, $90, $7F +$C9, $2D, $D0, $04, $86, $B1, $F0, $04 +$C9, $2B, $D0, $05, $20, $BC, $00, $90 +$6E, $C9, $24, $D0, $03, $4C, $73, $DE +$C9, $25, $D0, $08, $4C, $A1, $DE, $20 +$BC, $00, $90, $5B, $C9, $2E, $F0, $2E +$C9, $45, $D0, $30, $20, $BC, $00, $90 +$17, $C9, $B7, $F0, $0E, $C9, $2D, $F0 +$0A, $C9, $B6, $F0, $08, $C9, $2B, $F0 +$04, $D0, $07, $66, $AB, $20, $BC, $00 +$90, $5B, $24, $AB, $10, $0E, $A9, $00 +$38, $E5, $A9, $4C, $16, $DA, $66, $AA +$24, $AA, $50, $C3, $A5, $A9, $38, $E5 +$A8, $85, $A9, $F0, $12, $10, $09, $20 +$F5, $D7, $E6, $A9, $D0, $F9, $F0, $07 +$20, $DC, $D7, $C6, $A9, $D0, $F9, $A5 +$B1, $30, $01, $60, $4C, $F9, $DB, $48 +$24, $AA, $10, $02, $E6, $A8, $20, $DC +$D7, $68, $29, $0F, $20, $4A, $DA, $4C +$D7, $D9, $48, $20, $CF, $D8, $68, $20 +$FF, $D8, $A5, $B7, $45, $B0, $85, $B8 +$A6, $AC, $4C, $C6, $D5, $A5, $A9, $C9 +$0A, $90, $09, $A9, $64, $24, $AB, $30 +$0E, $4C, $C8, $D6, $0A, $0A, $65, $A9 +$0A, $A0, $00, $71, $C3, $E9, $2F, $85 +$A9, $4C, $FD, $D9, $A9, $F6, $A0, $E7 +$20, $D8, $C8, $A5, $88, $A6, $87, $85 +$AD, $86, $AE, $A2, $90, $38, $20, $0C +$D9, $A0, $00, $98, $20, $A7, $DA, $4C +$D8, $C8, $A0, $01, $A9, $20, $24, $B0 +$10, $02, $A9, $2D, $99, $EF, $00, $85 +$B0, $84, $BA, $C8, $A6, $AC, $D0, $05 +$A9, $30, $4C, $B3, $DB, $A9, $00, $E0 +$81, $B0, $09, $A9, $8A, $A0, $E1, $20 +$3E, $D7, $A9, $FA, $85, $A8, $A9, $86 +$A0, $E1, $20, $1C, $D9, $F0, $1E, $10 +$12, $A9, $82, $A0, $E1, $20, $1C, $D9 +$F0, $02, $10, $0E, $20, $DC, $D7, $C6 +$A8, $D0, $EE, $20, $F5, $D7, $E6, $A8 +$D0, $DC, $20, $BF, $D5, $20, $55, $D9 +$A2, $01, $A5, $A8, $18, $69, $07, $30 +$09, $C9, $08, $B0, $06, $69, $FF, $AA +$A9, $02, $38, $E9, $02, $85, $A9, $86 +$A8, $8A, $F0, $02, $10, $13, $A4, $BA +$A9, $2E, $C8, $99, $EF, $00, $8A, $F0 +$06, $A9, $30, $C8, $99, $EF, $00, $84 +$BA, $A0, $00, $A2, $80, $A5, $AF, $18 +$79, $00, $E2, $85, $AF, $A5, $AE, $79 +$FF, $E1, $85, $AE, $A5, $AD, $79, $FE +$E1, $85, $AD, $E8, $B0, $04, $10, $E5 +$30, $02, $30, $E1, $8A, $90, $04, $49 +$FF, $69, $0A, $69, $2F, $C8, $C8, $C8 +$84, $95, $A4, $BA, $C8, $AA, $29, $7F +$99, $EF, $00, $C6, $A8, $D0, $06, $A9 +$2E, $C8, $99, $EF, $00, $84, $BA, $A4 +$95, $8A, $49, $FF, $29, $80, $AA, $C0 +$12, $D0, $B2, $A4, $BA, $B9, $EF, $00 +$88, $C9, $30, $F0, $F8, $C9, $2E, $F0 +$01, $C8, $A9, $2B, $A6, $A9, $F0, $2E +$10, $08, $A9, $00, $38, $E5, $A9, $AA +$A9, $2D, $99, $F1, $00, $A9, $45, $99 +$F0, $00, $8A, $A2, $2F, $38, $E8, $E9 +$0A, $B0, $FB, $69, $3A, $99, $F3, $00 +$8A, $99, $F2, $00, $A9, $00, $99, $F4 +$00, $F0, $08, $99, $EF, $00, $A9, $00 +$99, $F0, $00, $A9, $F0, $A0, $00, $60 +$F0, $42, $A5, $B3, $D0, $03, $4C, $57 +$D6, $A2, $9C, $A0, $00, $20, $AC, $D8 +$A5, $B7, $10, $0F, $20, $86, $D9, $A9 +$9C, $A0, $00, $20, $1C, $D9, $D0, $03 +$98, $A4, $5B, $20, $CA, $D5, $98, $48 +$20, $00, $D7, $A9, $9C, $A0, $00, $20 +$3E, $D7, $20, $04, $DC, $68, $4A, $90 +$0A, $A5, $AC, $F0, $06, $A5, $B0, $49 +$FF, $85, $B0, $60, $A9, $8E, $A0, $E1 +$20, $3E, $D7, $A5, $B9, $69, $50, $90 +$03, $20, $E6, $D8, $85, $A3, $20, $D2 +$D8, $A5, $AC, $C9, $88, $90, $03, $20 +$D3, $D7, $20, $86, $D9, $A5, $5B, $18 +$69, $81, $F0, $F3, $38, $E9, $01, $48 +$A2, $04, $B5, $B3, $B4, $AC, $95, $AC +$94, $B3, $CA, $10, $F5, $A5, $A3, $85 +$B9, $20, $AB, $D5, $20, $F9, $DB, $A9 +$92, $A0, $E1, $20, $6C, $DC, $A9, $00 +$85, $B8, $68, $4C, $B8, $D7, $85, $BA +$84, $BB, $20, $A2, $D8, $A9, $A4, $20 +$3E, $D7, $20, $70, $DC, $A9, $A4, $A0 +$00, $4C, $3E, $D7, $85, $BA, $84, $BB +$A2, $A8, $20, $A4, $D8, $B1, $BA, $85 +$B1, $A4, $BA, $C8, $98, $D0, $02, $E6 +$BB, $85, $BA, $A4, $BB, $20, $3E, $D7 +$A5, $BA, $A4, $BB, $18, $69, $04, $90 +$01, $C8, $85, $BA, $84, $BB, $20, $C3 +$D5, $A9, $A8, $A0, $00, $C6, $B1, $D0 +$E4, $60, $A5, $AC, $F0, $07, $A2, $D8 +$A0, $00, $20, $AC, $D8, $A2, $AF, $A0 +$13, $06, $D9, $26, $DA, $26, $DB, $26 +$D8, $90, $05, $8A, $45, $D9, $85, $D9 +$88, $D0, $EE, $A2, $02, $B5, $D9, $95 +$AD, $CA, $10, $F9, $A9, $80, $85, $AC +$0A, $85, $B0, $4C, $39, $D6, $A9, $AF +$A0, $E1, $20, $C3, $D5, $20, $CF, $D8 +$A9, $C4, $A0, $E1, $A6, $B7, $20, $FE +$D7, $20, $CF, $D8, $20, $86, $D9, $A9 +$00, $85, $B8, $20, $AB, $D5, $A9, $F6 +$A0, $E1, $20, $A8, $D5, $A5, $B0, $48 +$10, $0D, $20, $BF, $D5, $A5, $B0, $30 +$09, $A5, $63, $49, $FF, $85, $63, $20 +$F9, $DB, $A9, $F6, $A0, $E1, $20, $C3 +$D5, $68, $10, $03, $20, $F9, $DB, $A9 +$B3, $A0, $E1, $4C, $56, $DC, $20, $A2 +$D8, $A9, $00, $85, $63, $20, $DD, $DC +$A2, $9C, $A0, $00, $20, $AC, $D8, $A9 +$A4, $A0, $00, $20, $82, $D8, $A9, $00 +$85, $B0, $A5, $63, $20, $4E, $DD, $A9 +$9C, $A0, $00, $4C, $06, $D8, $48, $4C +$0F, $DD, $20, $0A, $00, $4C, $F4, $CB +$A5, $B0, $48, $10, $03, $20, $F9, $DB +$A5, $AC, $48, $C9, $81, $90, $07, $A9 +$E9, $A0, $E1, $20, $06, $D8, $A9, $C8 +$A0, $E1, $20, $56, $DC, $68, $C9, $81 +$90, $07, $A9, $AF, $A0, $E1, $20, $A8 +$D5, $68, $10, $16, $4C, $F9, $DB, $20 +$DD, $D4, $E0, $08, $B0, $20, $A9, $00 +$38, $2A, $CA, $10, $FC, $E8, $01, $11 +$81, $11, $60, $20, $DD, $D4, $E0, $08 +$B0, $0C, $A9, $FF, $2A, $CA, $10, $FC +$E8, $21, $11, $81, $11, $60, $4C, $2E +$CF, $20, $BC, $00, $20, $DD, $D4, $E0 +$08, $B0, $F3, $20, $C2, $00, $C9, $29 +$F0, $03, $4C, $07, $CC, $20, $BC, $00 +$A9, $00, $38, $2A, $CA, $10, $FC, $E8 +$21, $11, $F0, $02, $A9, $FF, $4C, $FF +$D8, $E0, $19, $B0, $48, $86, $78, $A9 +$18, $20, $3F, $D1, $A0, $17, $A2, $18 +$46, $11, $66, $12, $66, $13, $8A, $2A +$91, $AD, $88, $10, $F3, $A5, $78, $F0 +$0A, $AA, $38, $49, $FF, $69, $18, $F0 +$1C, $D0, $0F, $A8, $B1, $AD, $C9, $30 +$D0, $07, $CA, $F0, $03, $C8, $10, $F4 +$E8, $98, $18, $65, $AD, $85, $AD, $A9 +$00, $65, $AE, $85, $AE, $86, $AC, $20 +$BC, $00, $4C, $8A, $D1, $4C, $2E, $CF +$E0, $07, $B0, $F9, $86, $78, $A9, $06 +$20, $3F, $D1, $A0, $05, $F8, $A5, $13 +$20, $56, $DE, $A5, $12, $20, $56, $DE +$A5, $11, $20, $56, $DE, $D8, $A2, $06 +$A5, $78, $F0, $B7, $AA, $38, $49, $FF +$69, $06, $F0, $C9, $D0, $BC, $AA, $29 +$0F, $20, $61, $DE, $8A, $4A, $4A, $4A +$4A, $C9, $0A, $69, $30, $91, $AD, $88 +$60, $85, $AC, $A9, $00, $85, $B8, $8A +$20, $4A, $DA, $20, $BC, $00, $90, $0A +$09, $20, $E9, $61, $C9, $06, $B0, $2A +$69, $0A, $29, $0F, $AA, $A5, $AC, $F0 +$E4, $69, $04, $90, $DC, $4C, $C8, $D6 +$AA, $A5, $AC, $F0, $06, $E6, $AC, $F0 +$F4, $A9, $00, $85, $B8, $8A, $20, $4A +$DA, $20, $BC, $00, $49, $30, $C9, $02 +$90, $E6, $4C, $2F, $DA, $AD, $00, $02 +$D0, $18, $20, $EF, $E0, $90, $0B, $8D +$01, $02, $A2, $20, $8E, $02, $02, $4C +$1C, $C5, $AE, $02, $02, $F0, $03, $CE +$02, $02, $A2, $DC, $20, $D5, $DE, $A2 +$DF, $20, $D5, $DE, $60, $B5, $00, $10 +$FB, $0A, $29, $40, $F0, $F6, $95, $00 +$8A, $A8, $68, $68, $A9, $05, $20, $07 +$C1, $A5, $C4, $48, $A5, $C3, $48, $A5 +$88, $48, $A5, $87, $48, $A9, $8D, $48 +$B9, $01, $00, $85, $C3, $B9, $02, $00 +$85, $C4, $4C, $C1, $C4, $20, $EF, $E0 +$B0, $09, $AD, $02, $02, $F0, $09, $AD +$01, $02, $38, $A2, $00, $8E, $02, $02 +$60, $A2, $DF, $2C, $A2, $DC, $C9, $93 +$F0, $11, $C9, $B5, $F0, $07, $49, $A2 +$F0, $0E, $4C, $07, $CC, $A9, $7F, $35 +$00, $10, $05, $B5, $00, $0A, $15, $00 +$95, $00, $4C, $BC, $00, $58, $A2, $DF +$2C, $A2, $DC, $86, $78, $20, $BC, $00 +$20, $5A, $C7, $A5, $79, $A6, $7A, $20 +$2D, $C3, $B0, $03, $4C, $77, $C6, $A6 +$78, $A5, $AA, $E9, $01, $95, $01, $A5 +$AB, $E9, $00, $95, $02, $A9, $C0, $95 +$00, $60, $D0, $FD, $A5, $DF, $0A, $05 +$DF, $85, $DF, $4C, $7E, $C6, $D0, $F1 +$A5, $DC, $0A, $05, $DC, $85, $DC, $4C +$7E, $C6, $20, $EE, $CA, $4C, $D5, $CA +$20, $B6, $DF, $10, $FB, $A5, $B4, $09 +$80, $85, $B4, $20, $C8, $D5, $F0, $F0 +$20, $B6, $DF, $30, $FB, $F0, $F9, $A5 +$B4, $09, $80, $85, $B4, $20, $C8, $D5 +$F0, $EE, $C9, $29, $D0, $05, $68, $68 +$4C, $BC, $00, $4C, $07, $CC, $20, $C2 +$00, $C9, $2C, $D0, $ED, $20, $DE, $D8 +$A5, $B0, $09, $7F, $25, $AD, $48, $A5 +$AE, $48, $A5, $AF, $48, $A5, $AC, $48 +$20, $BC, $00, $20, $D2, $CA, $68, $85 +$B3, $68, $85, $B6, $68, $85, $B5, $68 +$85, $B4, $85, $B7, $A9, $B3, $A0, $00 +$4C, $1C, $D9, $C9, $2C, $F0, $1B, $20 +$91, $D4, $8A, $F0, $0A, $E0, $10, $90 +$45, $E4, $64, $B0, $02, $86, $64, $86 +$0F, $20, $C2, $00, $F0, $1A, $C9, $2C +$D0, $A9, $20, $8E, $D4, $8A, $30, $2E +$E0, $01, $90, $2A, $A5, $0F, $F0, $06 +$E4, $0F, $F0, $02, $B0, $20, $86, $64 +$A5, $0F, $F0, $06, $C5, $64, $B0, $03 +$85, $64, $38, $E5, $64, $B0, $FC, $65 +$64, $18, $65, $64, $85, $10, $A5, $0F +$38, $E5, $10, $85, $10, $60, $4C, $2E +$CF, $A5, $B0, $30, $F9, $A5, $AC, $F0 +$F4, $20, $CF, $D8, $A9, $00, $85, $77 +$85, $76, $85, $75, $85, $78, $85, $AF +$85, $AE, $85, $AD, $A2, $18, $A5, $B3 +$4A, $B0, $0E, $06, $B6, $26, $B5, $26 +$B4, $26, $77, $26, $76, $26, $75, $26 +$78, $06, $B6, $26, $B5, $26, $B4, $26 +$77, $26, $76, $26, $75, $26, $78, $06 +$AF, $26, $AE, $26, $AD, $A5, $AF, $2A +$85, $5B, $A5, $AE, $2A, $85, $5C, $A5 +$AD, $2A, $85, $5D, $A9, $00, $2A, $85 +$5E, $A5, $77, $E5, $5B, $85, $5B, $A5 +$76, $E5, $5C, $85, $5C, $A5, $75, $E5 +$5D, $A8, $A5, $78, $E5, $5E, $90, $0E +$85, $78, $84, $75, $A5, $5C, $85, $76 +$A5, $5B, $85, $77, $E6, $AF, $CA, $D0 +$A2, $38, $A5, $B3, $E9, $80, $6A, $69 +$00, $85, $AC, $4C, $39, $D6, $20, $BC +$00, $20, $AF, $CD, $20, $F4, $CB, $A4 +$95, $A5, $96, $4C, $5E, $D0, $A9, $C4 +$A0, $E1, $20, $82, $D8, $C6, $AC, $60 +$A9, $C4, $A0, $E1, $4C, $82, $D8, $6C +$05, $02, $6C, $07, $02, $6C, $09, $02 +$6C, $0B, $02, $FF, $00, $00, $AD, $DE +$C0, $FF, $D3, $FF, $E6, $C3, $D0, $02 +$E6, $C4, $AD, $FF, $FF, $C9, $AC, $F0 +$0E, $C9, $3A, $B0, $0A, $C9, $20, $F0 +$EB, $38, $E9, $30, $38, $E9, $D0, $60 +$4C, $00, $C0, $00, $00, $00, $00, $00 +$00, $00, $4C, $2E, $CF, $00, $00, $00 +$F2, $00, $03, $0D, $0A, $4D, $65, $6D +$6F, $72, $79, $20, $73, $69, $7A, $65 +$20, $00, $20, $42, $79, $74, $65, $73 +$20, $66, $72, $65, $65, $0D, $0A, $0A +$45, $6E, $68, $61, $6E, $63, $65, $64 +$20, $42, $41, $53, $49, $43, $20, $32 +$2E, $32, $32, $0A, $00, $02, $80, $19 +$56, $62, $80, $76, $22, $F3, $82, $38 +$AA, $40, $80, $35, $04, $F3, $81, $35 +$04, $F3, $80, $80, $00, $00, $80, $31 +$72, $18, $91, $43, $4F, $F8, $94, $74 +$23, $F7, $94, $74, $24, $00, $81, $38 +$AA, $3B, $06, $74, $63, $90, $8C, $77 +$23, $0C, $AB, $7A, $1E, $94, $00, $7C +$63, $42, $80, $7E, $75, $FE, $D0, $80 +$31, $72, $15, $81, $00, $00, $00, $81 +$49, $0F, $DB, $04, $86, $1E, $D7, $FB +$87, $99, $26, $65, $87, $23, $34, $58 +$86, $A5, $5D, $E1, $83, $49, $0F, $DB +$08, $78, $3A, $C5, $37, $7B, $83, $A2 +$5C, $7C, $2E, $DD, $4D, $7D, $99, $B0 +$1E, $7D, $59, $ED, $24, $7E, $91, $72 +$00, $7E, $4C, $B9, $73, $7F, $AA, $AA +$53, $81, $00, $00, $00, $81, $80, $00 +$00, $90, $80, $00, $00, $00, $7F, $00 +$00, $00, $84, $20, $00, $00, $FE, $79 +$60, $00, $27, $10, $FF, $FC, $18, $00 +$00, $64, $FF, $FF, $F6, $00, $00, $01 +$1F, $C5, $5C, $C4, $69, $CA, $90, $C6 +$4B, $C9, $63, $CD, $6B, $C9, $B8, $C7 +$8A, $C7, $EF, $C5, $AE, $C5, $BE, $C6 +$46, $C5, $D2, $C5, $69, $DF, $75, $DF +$7B, $C6, $22, $C7, $1D, $C5, $2B, $C7 +$84, $C5, $8D, $C7, $8D, $D5, $F4, $E0 +$F7, $E0, $78, $D0, $12, $D5, $2E, $D5 +$7B, $D5, $B8, $C5, $21, $C6, $59, $C8 +$8A, $C5, $A7, $C3, $A4, $C3, $52, $C3 +$EA, $DF, $28, $C8, $53, $D5, $86, $DD +$9A, $DD, $18, $DF, $1B, $DF, $69, $CC +$69, $CC, $69, $CC, $ED, $CA, $F0, $CB +$F0, $CB, $69, $CC, $69, $CC, $69, $CC +$69, $CC, $69, $CC, $69, $CC, $69, $CC +$69, $CC, $69, $CC, $69, $CC, $00, $00 +$63, $CC, $69, $CC, $63, $CC, $63, $CC +$63, $CC, $63, $CC, $69, $CC, $90, $CC +$90, $CC, $00, $00, $81, $DF, $81, $DF +$6F, $CC, $6F, $CC, $00, $00, $74, $CC +$74, $CC, $74, $CC, $FB, $D8, $85, $D9 +$18, $D9, $51, $DD, $49, $D0, $68, $D0 +$40, $E0, $A1, $DC, $FF, $D6, $03, $DC +$D5, $DC, $DC, $DC, $25, $DD, $57, $DD +$07, $D5, $1B, $D5, $59, $D4, $72, $D4 +$2A, $D1, $9F, $D4, $7D, $D4, $37, $D4 +$16, $D4, $88, $D3, $27, $DE, $D8, $DD +$B0, $DD, $87, $DF, $97, $DF, $DD, $E0 +$E7, $E0, $CD, $E0, $9A, $D3, $A3, $D3 +$D2, $D3, $79, $C5, $D5, $79, $AA, $D5 +$7B, $40, $D7, $7B, $08, $D8, $7F, $BF +$DB, $50, $D9, $CC, $46, $BF, $CC, $46 +$CC, $CC, $56, $85, $CD, $56, $6D, $CD +$7D, $F8, $DB, $5A, $1B, $CC, $64, $FA +$CC, $2A, $2B, $2D, $2F, $3C, $3D, $3E +$3F, $41, $42, $43, $44, $45, $46, $47 +$48, $49, $4C, $4D, $4E, $4F, $50, $52 +$53, $54, $55, $56, $57, $5E, $00, $71 +$E3, $73, $E3, $75, $E3, $77, $E3, $79 +$E3, $7D, $E3, $7F, $E3, $83, $E3, $85 +$E3, $95, $E3, $AE, $E3, $C5, $E3, $DE +$E3, $ED, $E3, $F7, $E3, $04, $E4, $0A +$E4, $1C, $E4, $41, $E4, $4F, $E4, $61 +$E4, $69, $E4, $7E, $E4, $AD, $E4, $D8 +$E4, $EC, $E4, $FD, $E4, $09, $E5, $18 +$E5, $B8, $00, $B6, $00, $B7, $00, $B9 +$00, $3C, $BF, $C2, $00, $C1, $00, $3E +$BE, $C0, $00, $9F, $00, $42, $53, $28 +$C5, $4E, $44, $BB, $53, $43, $28, $D7 +$54, $4E, $28, $D0, $00, $49, $4E, $24 +$28, $DC, $49, $54, $43, $4C, $52, $A8 +$49, $54, $53, $45, $54, $A7, $49, $54 +$54, $53, $54, $28, $DD, $00, $41, $4C +$4C, $9C, $48, $52, $24, $28, $DA, $4C +$45, $41, $52, $A2, $4F, $4E, $54, $A0 +$4F, $53, $28, $CD, $00, $41, $54, $41 +$83, $45, $43, $88, $45, $45, $4B, $28 +$D2, $45, $46, $99, $49, $4D, $85, $4F +$4B, $45, $9B, $4F, $9D, $00, $4C, $53 +$45, $AC, $4E, $44, $80, $4F, $52, $BC +$58, $50, $28, $CC, $00, $4E, $AE, $4F +$52, $81, $52, $45, $28, $C7, $00, $45 +$54, $A5, $4F, $53, $55, $42, $8D, $4F +$54, $4F, $89, $00, $45, $58, $24, $28 +$DB, $00, $46, $8B, $4E, $43, $95, $4E +$50, $55, $54, $84, $4E, $54, $28, $C4 +$52, $51, $A9, $00, $43, $41, $53, $45 +$24, $28, $D9, $45, $46, $54, $24, $28 +$E3, $45, $4E, $28, $D4, $45, $54, $87 +$49, $53, $54, $A1, $4F, $41, $44, $97 +$4F, $47, $28, $CB, $4F, $4F, $50, $9E +$00, $41, $58, $28, $DE, $49, $44, $24 +$28, $E5, $49, $4E, $28, $DF, $00, $45 +$57, $A3, $45, $58, $54, $82, $4D, $49 +$AA, $4F, $54, $B1, $55, $4C, $4C, $94 +$00, $46, $46, $B5, $4E, $93, $52, $BD +$00, $45, $45, $4B, $28, $D1, $49, $E0 +$4F, $4B, $45, $9A, $4F, $53, $28, $C8 +$52, $49, $4E, $54, $9F, $00, $45, $41 +$44, $86, $45, $4D, $91, $45, $53, $54 +$4F, $52, $45, $8C, $45, $54, $49, $52 +$51, $8E, $45, $54, $4E, $4D, $49, $8F +$45, $54, $55, $52, $4E, $90, $49, $47 +$48, $54, $24, $28, $E4, $4E, $44, $28 +$CA, $55, $4E, $8A, $00, $41, $44, $44 +$28, $D3, $41, $56, $45, $98, $47, $4E +$28, $C3, $49, $4E, $28, $CE, $50, $43 +$28, $AF, $51, $52, $28, $C9, $54, $45 +$50, $B2, $54, $4F, $50, $92, $54, $52 +$24, $28, $D5, $57, $41, $50, $A6, $00 +$41, $42, $28, $AB, $41, $4E, $28, $CF +$48, $45, $4E, $B0, $4F, $AD, $57, $4F +$50, $49, $E1, $00, $43, $41, $53, $45 +$24, $28, $D8, $4E, $54, $49, $4C, $B3 +$53, $52, $28, $C6, $00, $41, $4C, $28 +$D6, $41, $52, $50, $54, $52, $28, $E2 +$00, $41, $49, $54, $96, $48, $49, $4C +$45, $B4, $49, $44, $54, $48, $A4, $00 +$BA, $00, $03, $45, $E2, $E3, $03, $46 +$EF, $E3, $04, $4E, $52, $E4, $04, $44 +$C5, $E3, $05, $49, $0F, $E4, $03, $44 +$D4, $E3, $04, $52, $7E, $E4, $03, $4C +$2D, $E4, $03, $44, $C9, $E3, $04, $47 +$FF, $E3, $03, $52, $A9, $E4, $02, $49 +$0A, $E4, $07, $52, $85, $E4, $05, $47 +$FA, $E3, $06, $52, $8C, $E4, $06, $52 +$92, $E4, $06, $52, $98, $E4, $03, $52 +$82, $E4, $04, $53, $CA, $E4, $02, $4F +$64, $E4, $04, $4E, $5C, $E4, $03, $49 +$0C, $E4, $04, $57, $09, $E5, $04, $4C +$34, $E4, $04, $53, $B2, $E4, $03, $44 +$D1, $E3, $04, $50, $70, $E4, $04, $44 +$D7, $E3, $04, $43, $AE, $E3, $02, $44 +$DB, $E3, $04, $4C, $3C, $E4, $05, $50 +$78, $E4, $04, $43, $BC, $E3, $04, $4C +$30, $E4, $05, $43, $B7, $E3, $03, $4E +$4F, $E4, $05, $57, $12, $E5, $03, $47 +$F7, $E3, $04, $53, $D3, $E4, $06, $42 +$A0, $E3, $06, $42, $9A, $E3, $03, $49 +$18, $E4, $03, $4E, $56, $E4, $04, $54 +$D8, $E4, $04, $45, $DE, $E3, $02, $54 +$E4, $E4, $02, $46, $ED, $E3, $04, $53 +$BE, $E4, $04, $54, $E0, $E4, $03, $4E +$59, $E4, $04, $53, $C6, $E4, $05, $55 +$F3, $E4, $05, $57, $0D, $E5, $03, $4F +$61, $E4, $01, $2B, $00, $00, $01, $2D +$00, $00, $01, $2A, $00, $00, $01, $2F +$00, $00, $01, $5E, $00, $00, $03, $41 +$89, $E3, $03, $45, $E5, $E3, $02, $4F +$66, $E4, $02, $3E, $7F, $E3, $02, $3C +$79, $E3, $01, $3E, $00, $00, $01, $3D +$00, $00, $01, $3C, $00, $00, $04, $53 +$B6, $E4, $04, $49, $14, $E4, $04, $41 +$85, $E3, $04, $55, $F8, $E4, $04, $46 +$F2, $E3, $04, $50, $74, $E4, $04, $53 +$C2, $E4, $04, $52, $A5, $E4, $04, $4C +$38, $E4, $04, $45, $E8, $E3, $04, $43 +$C0, $E3, $04, $53, $BA, $E4, $04, $54 +$DC, $E4, $04, $41, $90, $E3, $05, $50 +$69, $E4, $05, $44, $CC, $E3, $05, $53 +$AD, $E4, $04, $4C, $29, $E4, $05, $53 +$CE, $E4, $04, $56, $FD, $E4, $04, $41 +$8C, $E3, $07, $55, $EC, $E4, $07, $4C +$1C, $E4, $05, $43, $B2, $E3, $05, $48 +$04, $E4, $05, $42, $95, $E3, $07, $42 +$A6, $E3, $04, $4D, $41, $E4, $04, $4D +$4A, $E4, $02, $50, $6E, $E4, $05, $54 +$E6, $E4, $07, $56, $01, $E5, $06, $4C +$23, $E4, $07, $52, $9E, $E4, $05, $4D +$45, $E4, $D6, $E6, $E7, $E6, $EE, $E6 +$03, $E7, $0F, $E7, $1D, $E7, $26, $E7 +$34, $E7, $48, $E7, $55, $E7, $66, $E7 +$75, $E7, $84, $E7, $92, $E7, $A2, $E7 +$B5, $E7, $C4, $E7, $D7, $E7, $4E, $45 +$58, $54, $20, $77, $69, $74, $68, $6F +$75, $74, $20, $46, $4F, $52, $00, $53 +$79, $6E, $74, $61, $78, $00, $52, $45 +$54, $55, $52, $4E, $20, $77, $69, $74 +$68, $6F, $75, $74, $20, $47, $4F, $53 +$55, $42, $00, $4F, $75, $74, $20, $6F +$66, $20, $44, $41, $54, $41, $00, $46 +$75, $6E, $63, $74, $69, $6F, $6E, $20 +$63, $61, $6C, $6C, $00, $4F, $76, $65 +$72, $66, $6C, $6F, $77, $00, $4F, $75 +$74, $20, $6F, $66, $20, $6D, $65, $6D +$6F, $72, $79, $00, $55, $6E, $64, $65 +$66, $69, $6E, $65, $64, $20, $73, $74 +$61, $74, $65, $6D, $65, $6E, $74, $00 +$41, $72, $72, $61, $79, $20, $62, $6F +$75, $6E, $64, $73, $00, $44, $6F, $75 +$62, $6C, $65, $20, $64, $69, $6D, $65 +$6E, $73, $69, $6F, $6E, $00, $44, $69 +$76, $69, $64, $65, $20, $62, $79, $20 +$7A, $65, $72, $6F, $00, $49, $6C, $6C +$65, $67, $61, $6C, $20, $64, $69, $72 +$65, $63, $74, $00, $54, $79, $70, $65 +$20, $6D, $69, $73, $6D, $61, $74, $63 +$68, $00, $53, $74, $72, $69, $6E, $67 +$20, $74, $6F, $6F, $20, $6C, $6F, $6E +$67, $00, $53, $74, $72, $69, $6E, $67 +$20, $74, $6F, $6F, $20, $63, $6F, $6D +$70, $6C, $65, $78, $00, $43, $61, $6E +$27, $74, $20, $63, $6F, $6E, $74, $69 +$6E, $75, $65, $00, $55, $6E, $64, $65 +$66, $69, $6E, $65, $64, $20, $66, $75 +$6E, $63, $74, $69, $6F, $6E, $00, $4C +$4F, $4F, $50, $20, $77, $69, $74, $68 +$6F, $75, $74, $20, $44, $4F, $00, $0D +$0A, $42, $72, $65, $61, $6B, $00, $20 +$45, $72, $72, $6F, $72, $00, $20, $69 +$6E, $20, $6C, $69, $6E, $65, $20, $00 +$0D, $0A, $52, $65, $61, $64, $79, $0D +$0A, $00, $20, $45, $78, $74, $72, $61 +$20, $69, $67, $6E, $6F, $72, $65, $64 +$0D, $0A, $00, $20, $52, $65, $64, $6F +$20, $66, $72, $6F, $6D, $20, $73, $74 +$61, $72, $74, $0D, $0A, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$AD, $E1, $FF, $F0, $0C, $C9, $61, $90 +$06, $C9, $7B, $B0, $02, $29, $5F, $38 +$60, $18, $60, $8D, $E0, $FF, $29, $FF +$60, $00, $00, $00, $00, $00, $00, $00 diff --git a/hello_world.bas b/hello_world.bas index 00635af..eb77a7f 100644 --- a/hello_world.bas +++ b/hello_world.bas @@ -1,5 +1,5 @@ -10 LET A=1 -20 PR A;") HELLO WORLD FROM MKHBC!" -30 LET A=A+1 -40 IF A=0 THEN END -50 GOTO 20 +10 LET A=0 +20 PR A;") HELLO WORLD FROM MKHBC!" +30 LET A=A+1 +40 IF A>100 THEN END +50 GOTO 20 diff --git a/main.cpp b/main.cpp index 9c5c7ed..01bd0a3 100644 --- a/main.cpp +++ b/main.cpp @@ -1,333 +1,695 @@ -#include -#include -#include -#include "MKCpu.h" -#include "Memory.h" -#include "Display.h" -#include "VMachine.h" -#include "MKGenException.h" - -using namespace std; -using namespace MKBasic; - -/* - *-------------------------------------------------------------------- - * Method: ShowHelp() - * Purpose: Display commands help. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void ShowHelp() -{ - cout << "Virtual Machine/CPU emulator/Debugger Command Reference." << endl << endl; - cout << "S - step" << endl; - cout << " Executes single opcode at current address." << endl; - cout << "C - continue" << endl; - cout << " Continues code execution from current address until BRK." << endl; - cout << "D - dump memory" << endl; - cout << " Usage: D [startaddr] [endaddr]" << endl; - cout << " Where: startaddr,endaddr - memory addr. in hexadecimal format [0000..FFFF]." << endl; - cout << " Dumps contents of memory, hexadecimal and ASCII formats." << endl; - cout << "G - go/continue from new address until BRK" << endl; - cout << " Usage: G [address]" << endl; - cout << " Where: address - memory addr. in hexadecimal format [0000.FFFF]." << endl; - cout << " Executes code at provided address, interrupted by BRK opcode." << endl; - cout << "X - execute code from new address until RTS" << endl; - cout << " Usage: X [address]" << endl; - cout << " Where: address - memory addr. in hexadecimal format [0000.FFFF]." << endl; - cout << " Executes code at provided address, until RTS (last one)." << endl; - cout << "Q - quit" << endl; - cout << " Exits from the emulator/debugger." << endl; - cout << "A - set address for next step" << endl; - cout << " Usage: A [address]" << endl; - cout << " Where: address - memory addr. in hexadecimal format [0000.FFFF]." << endl; - cout << " Sets current address to a new value." << endl; - cout << "N - go number of steps" << endl; - cout << " Usage: N [steps]" << endl; - cout << " Where: steps - number of steps in decimal format" << endl; - cout << " Execute number of opcodes provided in steps argument starting" << endl; - cout << " from current address." << endl; - cout << "W - write to memory" << endl; - cout << " Usage: W [address] [hexval] [hexval] ... 100" << endl; - cout << " Where: address - memory addr. in hexadecimal format [0000.FFFF]," << endl; - cout << " hexval - byte value in hexadecimal format [00.FF]." << endl; - cout << " Writes provided values to memory starting at specified address." << endl; - cout << "I - toggle char I/O emulation" << endl; - cout << " Usage: I [address]" << endl; - cout << " Where: address - memory addr. in hexadecimal format [0000.FFFF]," << endl; - cout << " Toggles basic character I/O emulation. When enabled, all writes" << endl; - cout << " to the specified memory address also writes a character code to" << endl; - cout << " to a virtual console. All reads from specified memory address" << endl; - cout << " are interpreted as console character input." << endl; - cout << "R - regs" << endl; - cout << " Displays CPU registers and flags." << endl; - cout << "T - show I/O console" << endl; - cout << " Displays/prints the contents of the virtual console screen." << endl; - cout << " Note that in run mode (commands X, G or C), virtual screen is" << endl; - cout << " displayed automatically in real-time if I/O emulation is enabled." << endl; - cout << "E - toggle I/O local echo" << endl; - cout << " Toggles local echo on/off when I/O emulation is enabled." << endl; - cout << "B - blank (clear) screen" << endl; - cout << " Clears the screen, useful when after exiting I/O emulation" << endl; - cout << " your screen is messed up." << endl; - cout << "NOTE:" << endl; - cout << " If no arguments provided, each command will prompt user to enter" << endl; - cout << " missing data." << endl; - cout << endl; -} - -/* - *-------------------------------------------------------------------- - * Method: PromptNewAddress() - * Purpose: Prompt user to enter 16-bit address (hex) in console. - * Arguments: prompt - prompt text - * Returns: unsigned int - address entered by user - *-------------------------------------------------------------------- - */ -unsigned int PromptNewAddress(string prompt) -{ - unsigned int newaddr = 0x10000; - - while (newaddr > 0xFFFF) { - cout << prompt; - cin >> hex >> newaddr; - } - - return newaddr; -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void ShowRegs(Regs *preg, VMachine *pvm, unsigned short ioaddr, bool ioecho) -{ - cout << "Registers:" << endl; - cout << " Acc: $" << hex << (unsigned short)preg->Acc << "\t(%" << bitset<8>((int)preg->Acc) << ")" << endl; - cout << " X: $" << hex << (unsigned short)preg->IndX << endl; - cout << " Y: $" << hex << (unsigned short)preg->IndY << endl; - cout << " Addr: $" << hex << preg->PtrAddr << endl; - cout << " Acc16: $" << hex << preg->Acc16 << endl; - cout << " Ptr16: $" << hex << preg->Ptr16 << endl; - cout << " Stack: $" << hex << (unsigned short)preg->PtrStack << endl; - cout << " Flags: NV-BDIZC" << endl; - cout << " " << bitset<8>((int)preg->Flags) << endl; - cout << endl << "I/O status: " << (pvm->GetCharIOActive() ? "enabled" : "disabled") << ", "; - cout << " at: $" << hex << ioaddr << ", "; - cout << " local echo: " << (ioecho ? "ON" : "OFF") << "." << endl; - // cout << "-------------------------------------------------------------------------------" << endl; -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void ShowMenu() -{ - cout << "---------------------------------------------------------------------------" << endl; - cout << "S - step | C - continue, D - dump memory | G - go/continue from new address" << endl; - cout << "Q - quit | A - set address for next step | N - go number of steps" << endl; - cout << "H - help | I - toggle char I/O emulation | W - write to memory" << endl; - cout << "R - regs | T - show I/O console | E - toggle I/O local echo" << endl; - cout << " | X - execute from new address | B - blank (clear) screen" << endl; - cout << "---------------------------------------------------------------------------" << endl; -} - - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -#define RUNSTEPS(step,nsteps,brk,preg,stct,pvm,lrts) \ - brk = preg->SoftIrq; \ - lrts = preg->LastRTS; \ - while(step && nsteps > 1 && !brk && !lrts) { \ - cout << "addr: $" << hex << preg->PtrAddr << ", step: " << dec << stct << "\r"; \ - preg = pvm->Step(); \ - brk = preg->SoftIrq; \ - nsteps--; \ - stct++; \ - } - -/* run this program using the console pauser or add your own getch, system("pause") or input loop */ - -int main(int argc, char** argv) { - string romfile("dummy.rom"), ramfile("dummy.ram"); - if (argc > 1) { - ramfile = argv[1]; - } - try { - cout << endl; - VMachine *pvm = new VMachine(romfile, ramfile); - pvm->ClearScreen(); - cout << "Welcome to Virtual Machine/CPU Emulator (6502)/Debugger." << endl; - cout << "Copyright (C) by Marek Karcz 2016. All rights reserved." << endl; - string cmd; - bool runvm = false, step = false, brk = false, execaddr = false, stop = true; - bool ioecho = false, lrts = false, execvm = false; - unsigned int newaddr = 0x10000, ioaddr = 0xE000, tmpaddr = 0x0000; - int nsteps = 0; - while (true) { - Regs *preg = pvm->GetRegs(); - if (runvm) { - int stct = 1; - if (execaddr) { - preg = ((step) ? pvm->Step(newaddr) : pvm->Run(newaddr)); - RUNSTEPS(step,nsteps,brk,preg,stct,pvm,lrts); - execaddr = false; - newaddr = 0x10000; - } else { - preg = ((step) ? pvm->Step() : pvm->Run()); - RUNSTEPS(step,nsteps,brk,preg,stct,pvm,lrts); - } - if (step) - cout << "\rExecuted " << dec << stct << ((stct == 1) ? " step." : " steps.") << " " << endl; - nsteps = 0; - runvm = step = false; - } else if (execvm) { - preg = (execaddr ? pvm->Exec(newaddr) : pvm->Exec()); - execvm = false; - brk = preg->SoftIrq; - lrts = preg->LastRTS; - } - if (brk || stop || lrts) { - cout << endl; - if (brk) { - cout << "BRK at " << hex << preg->PtrAddr << endl; - brk = stop = lrts = false; - } else if (lrts) { - cout << "FINISHED at " << hex << ((newaddr > 0xFFFF) ? preg->PtrAddr : newaddr) << endl; - brk = stop = lrts = false; - } else if (stop) { - cout << "STOPPED at " << hex << ((newaddr > 0xFFFF) ? preg->PtrAddr : newaddr) << endl; - brk = stop = lrts = false; - } - ShowRegs(preg,pvm,ioaddr,ioecho); - } - ShowMenu(); - cout << "> "; - cin >> cmd; - char c = tolower(cmd.c_str()[0]); - if (c == 'h') { - ShowHelp(); - } else if (c == 'b') { - pvm->ClearScreen(); - } else if (c == 'r') { - stop = true; - } else if (c == 'e') { - if (pvm->GetCharIOActive()) { - ioecho = !ioecho; - cout << "I/O echo is " << (ioecho ? "activated." : "deactivated.") << endl; - pvm->SetCharIO(ioaddr, ioecho); - } else { - cout << "ERROR: I/O is deactivated." << endl; - } - } else if (c == 't') { - if (pvm->GetCharIOActive()) { - pvm->ShowIO(); - } else { - cout << "ERROR: I/O is deactivated." << endl; - } - } else if (c == 'i') { - if (pvm->GetCharIOActive()) { - pvm->DisableCharIO(); - cout << "I/O deactivated." << endl; - } else { - ioaddr = PromptNewAddress("Address (0..FFFF): "); - cout << " [" << hex << ioaddr << "]" << endl; - pvm->SetCharIO(ioaddr, ioecho); - cout << "I/O activated." << endl; - } - } else if (c == 'w') { - tmpaddr = PromptNewAddress("Address (0..FFFF): "); - cout << " [" << hex << tmpaddr << "]" << endl; - cout << "Enter hex bytes [00..FF] values separated with NL or spaces, end with [100]:" << endl; - unsigned short v = 0; - while (true) { - cin >> hex >> v; - cout << " " << hex << v; - if (v > 0xFF) break; - pvm->MemPoke8bit(tmpaddr++, v & 0xFF); - }; - cout << endl; - } else if (c == 'a') { - execaddr = stop = true; - newaddr = PromptNewAddress("Address (0..FFFF): "); - cout << " [" << hex << newaddr << "]" << endl; - } else if (c == 's') { - runvm = step = stop = true; - } else if (c == 'n') { - nsteps = 0; - while (nsteps < 1) { - cout << "# of steps [n>1]: "; - cin >> dec >> nsteps; - } - cout << " [" << dec << nsteps << "]" << endl; - runvm = step = stop = true; - } else if (c == 'c') { - runvm = true; - } else if (c == 'g') { - runvm = true; - execaddr = true; - newaddr = PromptNewAddress("Address (0..FFFF): "); - cout << " [" << hex << newaddr << "]" << endl; - } else if (c == 'x') { - execvm = true; - execaddr = true; - newaddr = PromptNewAddress("Address (0..FFFF): "); - cout << " [" << hex << newaddr << "]" << endl; - } else if (c == 'q') { - break; - } else if (c == 'd') { - unsigned int addrbeg = 0x10000, addrend = 0x10000; - cout << "Enter address range (0..0xFFFF)..." << endl; - addrbeg = PromptNewAddress("Start address (0..FFFF): "); - cout << " [" << hex << addrbeg << "]" << endl; - addrend = PromptNewAddress("End address (0..FFFF): "); - cout << " [" << hex << addrend << "]" << endl; - cout << endl; - for (unsigned int addr = addrbeg; addr <= addrend; addr+=16) { - cout << "\t|"; - for (unsigned int j=0; j < 16; j++) { - unsigned int hv = (unsigned int)pvm->MemPeek8bit(addr+j); - if (hv < 16) { - cout << 0; - } - cout << hex << hv << " "; - } - cout << "|"; - for (int j=0; j < 16; j++) { - char cc = (char)pvm->MemPeek8bit(addr+j); - if (isprint(cc)) - cout << cc; - else - cout << "?"; - } - cout << '\r'; - cout << hex << addr; - cout << endl; - } - } - } - } - catch (MKGenException& ex) { - cout << "ERROR: " << ex.GetCause() << endl; - } - catch (...) { - cout << "ERROR: Fatal." << endl; - } - return 0; -} +#include +#include +#include +#include +#include +#include "system.h" +#include "MKCpu.h" +#include "Memory.h" +#include "Display.h" +#include "VMachine.h" +#include "MKGenException.h" + +using namespace std; +using namespace MKBasic; + +#define ANIM_DELAY 250 + +const bool ClsIfDirty = true; + +VMachine *pvm = NULL; +Regs *preg = NULL; +bool ioecho = false, opbrk = false; +int g_stackdisp_lines = 1; + +bool ShowRegs(Regs *preg, VMachine *pvm, bool ioecho, bool showiostat); +void ShowHelp(); + +#if defined(LINUX) + +#include + +void trap_signal(int signum); + +/* + *-------------------------------------------------------------------- + * Method: trap_signal() + * Purpose: handle signal + * Arguments: signum - signal # + * Returns: n/a + *-------------------------------------------------------------------- + */ +void trap_signal(int signum) +{ + cout << "Signal caught: " << dec << signum << endl; + if (NULL != pvm && NULL != preg) { + pvm->SetOpInterrupt(); + opbrk = true; + } + //exit(signum); + return; +} + +#endif + +#if defined(WINDOWS) +#include + +BOOL CtrlHandler(DWORD fdwCtrlType); + +/* + *-------------------------------------------------------------------- + * Method: CtrlHandler() + * Purpose: handle signal + * Arguments: fdwCtrlType - event type + * Returns: BOOL - TRUE if event handled, FALSE if needs further + * processing. + *-------------------------------------------------------------------- + */ +BOOL CtrlHandler(DWORD fdwCtrlType) +{ + switch( fdwCtrlType ) + { + case CTRL_C_EVENT: + //Beep( 750, 300 ); + if (NULL != pvm && NULL != preg) { + pvm->SetOpInterrupt(); + opbrk = true; + } + return TRUE; + + + case CTRL_CLOSE_EVENT: + //Beep( 600, 200 ); + cout << "Ctrl-Close event" << endl; + return TRUE ; + + case CTRL_BREAK_EVENT: + //Beep( 900, 200 ); + if (NULL != pvm && NULL != preg) { + pvm->SetOpInterrupt(); + opbrk = true; + } + return TRUE; + + case CTRL_LOGOFF_EVENT: + //Beep( 1000, 200 ); + cout << "Ctrl-Logoff event" << endl; + return FALSE; + + case CTRL_SHUTDOWN_EVENT: + Beep( 750, 500 ); + cout << "Ctrl-Shutdown event" << endl; + return FALSE; + + default: + return FALSE; + } +} + +#endif + +/* + *-------------------------------------------------------------------- + * Method: PromptNewAddress() + * Purpose: Prompt user to enter 16-bit address (hex) in console. + * Arguments: prompt - prompt text + * Returns: unsigned int - address entered by user + *-------------------------------------------------------------------- + */ +unsigned int PromptNewAddress(string prompt) +{ + unsigned int newaddr = 0x10000; + + while (newaddr > 0xFFFF) { + cout << prompt; + cin >> hex >> newaddr; + } + + return newaddr; +} + +/* + *-------------------------------------------------------------------- + * Thank you stackoverflow.com. + * http://stackoverflow.com/questions/111928/ + * is-there-a-printf-converter-to-print-in-binary-format + *-------------------------------------------------------------------- + */ +#define BYTETOBINARYPATTERN "%d%d%d%d%d%d%d%d" +#define BYTETOBINARY(byte) \ + (byte & 0x80 ? 1 : 0), \ + (byte & 0x40 ? 1 : 0), \ + (byte & 0x20 ? 1 : 0), \ + (byte & 0x10 ? 1 : 0), \ + (byte & 0x08 ? 1 : 0), \ + (byte & 0x04 ? 1 : 0), \ + (byte & 0x02 ? 1 : 0), \ + (byte & 0x01 ? 1 : 0) + +/* + *-------------------------------------------------------------------- + * Method: ShowRegs() + * Purpose: Display status of CPU registers on DOS console. + * Arguments: preg - pointer to registers structure + * pvm - pointer to VM + * ioaddr - address setup for char I/O emulation + * ioecho - local I/O echo flag + * showiostat - if true, I/O emulation status is shown + * Returns: boolean - true if the stack pointer was longer than + * 15 (the screen must be cleared). + *-------------------------------------------------------------------- + */ +bool ShowRegs(Regs *preg, VMachine *pvm, bool ioecho, bool showiostat) +{ + bool ret = false; + char sBuf[80] = {0}; + + sprintf(sBuf, "| PC: $%04x | Acc: $%02x (" BYTETOBINARYPATTERN ") | X: $%02x | Y: $%02x |", + preg->PtrAddr, preg->Acc, BYTETOBINARY(preg->Acc), preg->IndX, preg->IndY); + cout << "*-------------*-----------------------*----------*----------*" << endl; + cout << sBuf << endl; + cout << "*-------------*-----------------------*----------*----------*" << endl; + cout << "| NV-BDIZC |" << endl; + cout << "| " << bitset<8>((int)preg->Flags) << " |"; + cout << " Last instr.: " << preg->LastInstr << " " << endl; + cout << "*-------------*" << endl; + //cout << "Last instr.: " << preg->LastInstr << " " << endl; + cout << endl; + /* + cout << "Registers:" << endl; + cout << " Acc: $" << hex << (unsigned short)preg->Acc << "\t(%" << bitset<8>((int)preg->Acc) << ")" << endl; + cout << " X: $" << hex << (unsigned short)preg->IndX << " " << endl; + cout << " Y: $" << hex << (unsigned short)preg->IndY << " " << endl; + cout << " PC: $" << hex << preg->PtrAddr << " " << endl; + //cout << " Acc16: $" << hex << preg->Acc16 << " " << endl; + //cout << " Ptr16: $" << hex << preg->Ptr16 << " " << endl; + */ + cout << "Stack: $" << hex << (unsigned short)preg->PtrStack << " " << endl; + cout << " \r"; + // display stack contents + cout << " ["; + int j = 0, stacklines = 1; + for (unsigned int addr = 0x0101 + preg->PtrStack; addr < 0x0200; addr++) { + unsigned int hv = (unsigned int)pvm->MemPeek8bit(addr); + if (hv < 16) { + cout << 0; + } + cout << hex << hv << " "; + j++; + if (j > 15) { + cout << "]" << endl; + cout << " ["; + j=0; + stacklines++; + } + } + cout << "] " << endl; + ret = (stacklines < g_stackdisp_lines); + g_stackdisp_lines = stacklines; + // end display stack contents + + if (showiostat) { + cout << endl << "I/O status: " << (pvm->GetCharIOActive() ? "enabled" : "disabled") << ", "; + cout << " at: $" << hex << pvm->GetCharIOAddr() << ", "; + cout << " local echo: " << (ioecho ? "ON" : "OFF") << "." << endl; + cout << "ROM: " << ((pvm->IsROMEnabled()) ? "enabled." : "disabled.") << " "; + cout << "Range: $" << hex << pvm->GetROMBegin() << " - $" << hex << pvm->GetROMEnd() << "." << endl; + } + cout << " \r"; + // cout << "-------------------------------------------------------------------------------" << endl; + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void ShowMenu() +{ + cout << "------------------------------------+----------------------------------------" << endl; + cout << " C - continue, S - step | A - set address for next step" << endl; + cout << " G - go/cont. from new address | N - go number of steps" << endl; + cout << " I - toggle char I/O emulation | X - execute from new address" << endl; + cout << " T - show I/O console | B - blank (clear) screen" << endl; + cout << " E - toggle I/O local echo | F - toggle registers animation" << endl; + cout << " J - set animation delay | M - dump memory, W - write memory" << endl; + cout << " K - toggle ROM emulation | R - show registers" << endl; + cout << " L - load memory image | O - display op-codes history" << endl; + cout << " D - disassemble code in memory | Q - quit, H - help" << endl; + cout << "------------------------------------+----------------------------------------" << endl; +} + + +/* + *-------------------------------------------------------------------- + * Method: RUNSTEPS() - macro + * Purpose: Execute multiple steps of CPU emulation. + * Arguments: + * step - boolean flag, true if step by step mode + * nsteps - # if steps + * brk - current status of break flag + * preg - pointer to CPU registers + * stct - step counter + * pvm - pointer to VM + * lrts - status of last RTS flag + * anim - boolean flag, true - registers animation mode + * delay - delay for anim mode + * enrom - rom enabled/disabled flag + * rombegin - begin address of emulated ROM + * romend - end address of emulated ROM + * + * Returns: n/a + *-------------------------------------------------------------------- + */ +#define RUNSTEPS(step,nsteps,brk,preg,stct,pvm,lrts,anim,delay) \ +{ \ + bool cls = false; \ + brk = preg->SoftIrq; \ + lrts = preg->LastRTS; \ + while(step && nsteps > 1 && !brk && !lrts) { \ + cout << "addr: $" << hex << preg->PtrAddr << ", step: " << dec << stct; \ + cout << " \r"; \ + preg = pvm->Step(); \ + if (anim) { \ + if (cls & ClsIfDirty) { pvm->ClearScreen(); cls = false; } \ + pvm->ScrHome(); \ + cls = ShowRegs(preg,pvm,false,false); \ + cout << endl; \ + this_thread::sleep_for(chrono::milliseconds(delay)); \ + } \ + brk = preg->SoftIrq; \ + nsteps--; \ + stct++; \ + } \ +} + +/* run this program using the console pauser or add your own getch, system("pause") or input loop */ + +int main(int argc, char** argv) { +#if defined(LINUX) + signal(SIGINT, trap_signal); + signal(SIGTERM, trap_signal); +#endif +#if defined(WINDOWS) + SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ); +#endif + string romfile("dummy.rom"), ramfile("dummy.ram"); + if (argc > 1) { + ramfile = argv[1]; + } + try { + cout << endl; + pvm = new VMachine(romfile, ramfile); + pvm->ClearScreen(); + cout << "Virtual Machine/CPU Emulator (MOS 6502) and Debugger." << endl; + cout << "Copyright (C) by Marek Karcz 2016. All rights reserved." << endl; + string cmd; + bool runvm = false, step = false, brk = false, execaddr = false, stop = true; + bool lrts = false, execvm = false, anim = false, enrom = pvm->IsROMEnabled(); + unsigned int newaddr = pvm->GetRunAddr(), ioaddr = pvm->GetCharIOAddr(), tmpaddr = 0x0000; + unsigned int rombegin = pvm->GetROMBegin(), romend = pvm->GetROMEnd(), delay = ANIM_DELAY; + int nsteps = 0; + if (pvm->IsAutoExec()) { + execvm = true; + } + if (newaddr == 0) newaddr = 0x10000; + while (true) { + preg = pvm->GetRegs(); + if (runvm) { + if (anim) pvm->ClearScreen(); + int stct = 1; + if (execaddr) { + preg = ((step) ? pvm->Step(newaddr) : pvm->Run(newaddr)); + RUNSTEPS(step,nsteps,brk,preg,stct,pvm,lrts,anim,delay); + execaddr = false; + } else { + preg = ((step) ? pvm->Step() : pvm->Run()); + RUNSTEPS(step,nsteps,brk,preg,stct,pvm,lrts,anim,delay); + } + if (step) + cout << "\rExecuted " << dec << stct << ((stct == 1) ? " step." : " steps.") << " " << endl; + nsteps = 0; + runvm = step = false; + newaddr = 0x10000; + } else if (execvm) { + preg = (execaddr ? pvm->Exec(newaddr) : pvm->Exec()); + execvm = false; + execaddr = false; + brk = preg->SoftIrq; + lrts = preg->LastRTS; + newaddr = 0x10000; + } + if (brk || opbrk || stop || lrts) { + cout << endl; + if (opbrk) { + cout << "Interrupted at " << hex << preg->PtrAddr << endl; + opbrk = brk = stop = lrts = false; + } else if (brk) { + cout << "BRK at " << hex << preg->PtrAddr << endl; + opbrk = brk = stop = lrts = false; + } else if (lrts) { + cout << "FINISHED at " << hex << ((newaddr > 0xFFFF) ? preg->PtrAddr : newaddr) << endl; + opbrk = brk = stop = lrts = false; + } else if (stop) { + cout << "STOPPED at " << hex << ((newaddr > 0xFFFF) ? preg->PtrAddr : newaddr) << endl; + opbrk = brk = stop = lrts = false; + } + ShowRegs(preg,pvm,ioecho,true); + } + ShowMenu(); + cout << "> "; + cin >> cmd; + char c = tolower(cmd.c_str()[0]); + if (c == 'h') { // display help + ShowHelp(); + } else if (c == 'o') { + queue exechist(pvm->GetExecHistory()); + cout << "PC : INSTR ACC | X | Y | PS | SP" << endl; + cout << "------------------------------------+-----+-----+-----+-----" << endl; + while (exechist.size()) { + cout << exechist.front() << endl; + exechist.pop(); + } + } else if (c == 'l') { // load memory image + char typ = 0; + while (tolower(typ) != 'b' && tolower(typ) != 'd') { + cout << "Type (B - binary/D - definition): "; + cin >> typ; + } + cout << " [" << ((tolower(typ) == 'b') ? "binary" : "definition") << "]" << endl; + string name; + cout << "Memory Image File Name: "; + cin >> name; + cout << " [" << name << "]" << endl; + if (typ == 'b') pvm->LoadRAMBin(name); + else { + pvm->LoadRAM(name); + if (pvm->IsAutoExec()) execvm = true; + if (newaddr == 0) newaddr = 0x10000; + } + } else if (c == 'k') { // toggle ROM emulation + if (!enrom) { + enrom = true; + do { + rombegin = PromptNewAddress("ROM begin (0200..FFFF): "); + } while (rombegin < 0x0200); + cout << " [" << hex << rombegin << "]" << endl; + do { + romend = PromptNewAddress("ROM end (ROMBEGIN+1..FFFF): "); + } while (romend <= rombegin); + cout << " [" << hex << romend << "]" << endl; + pvm->EnableROM(rombegin, romend); + cout << "ROM activated." << endl; + } else { + enrom = false; + pvm->DisableROM(); + cout << "ROM deactivated." << endl; + } + } else if (c == 'j') { // set registers animation delay + cout << "Delay [ms]: "; + cin >> dec >> delay; + cout << " [" << dec << delay << "]" << endl; + } else if (c == 'f') { // toggle registers animation in step mode + anim = !anim; + cout << "Registers status animation " << ((anim) ? "enabled." : "disabled.") << endl; + } else if (c == 'b') { // clear screen + pvm->ClearScreen(); + } else if (c == 'r') { // show registers + stop = true; + } else if (c == 'e') { // toggle local echo for I/O console + if (pvm->GetCharIOActive()) { + ioecho = !ioecho; + cout << "I/O echo is " << (ioecho ? "activated." : "deactivated.") << endl; + pvm->SetCharIO(ioaddr, ioecho); + } else { + cout << "ERROR: I/O is deactivated." << endl; + } + } else if (c == 't') { // show I/O console + if (pvm->GetCharIOActive()) { + pvm->ShowIO(); + } else { + cout << "ERROR: I/O is deactivated." << endl; + } + } else if (c == 'i') { // toggle I/O + if (pvm->GetCharIOActive()) { + pvm->DisableCharIO(); + cout << "I/O deactivated." << endl; + } else { + ioaddr = PromptNewAddress("Address (0..FFFF): "); + cout << " [" << hex << ioaddr << "]" << endl; + pvm->SetCharIO(ioaddr, ioecho); + cout << "I/O activated." << endl; + } + } else if (c == 'w') { // write to memory + tmpaddr = PromptNewAddress("Address (0..FFFF): "); + cout << " [" << hex << tmpaddr << "]" << endl; + cout << "Enter hex bytes [00..FF] values separated with NL or spaces, end with [100]:" << endl; + unsigned short v = 0; + while (true) { + cin >> hex >> v; + cout << " " << hex << v; + if (v > 0xFF) break; + pvm->MemPoke8bit(tmpaddr++, v & 0xFF); + }; + cout << endl; + } else if (c == 'a') { // change run address + execaddr = stop = true; + newaddr = PromptNewAddress("Address (0..FFFF): "); + cout << " [" << hex << newaddr << "]" << endl; + } else if (c == 's') { + runvm = step = stop = true; + } else if (c == 'n') { // execute # of steps + nsteps = 0; + while (nsteps < 1) { + cout << "# of steps [n>1]: "; + cin >> dec >> nsteps; + } + cout << " [" << dec << nsteps << "]" << endl; + runvm = step = stop = true; + } else if (c == 'c') { // continue running code + runvm = true; + } else if (c == 'g') { // run from new address until BRK + runvm = true; + execaddr = true; + newaddr = PromptNewAddress("Address (0..FFFF): "); + cout << " [" << hex << newaddr << "]" << endl; + } else if (c == 'x') { // execute code at address + execvm = true; + execaddr = true; + newaddr = PromptNewAddress("Address (0..FFFF): "); + cout << " [" << hex << newaddr << "]" << endl; + } else if (c == 'q') { // quit + break; + } else if (c == 'd') { // disassemble code in memory + unsigned int addrbeg = 0x10000, addrend = 0x10000; + cout << "Enter address range (0..0xFFFF)..." << endl; + addrbeg = PromptNewAddress("Start address (0..FFFF): "); + cout << " [" << hex << addrbeg << "]" << endl; + addrend = PromptNewAddress("End address (0..FFFF): "); + cout << " [" << hex << addrend << "]" << endl; + cout << endl; + for (unsigned int addr = addrbeg; addr <= addrend;) { + char instrbuf[DISS_BUF_SIZE]; + addr = pvm->Disassemble((unsigned short)addr, instrbuf); + cout << instrbuf << endl; + } + } else if (c == 'm') { // dump memory + unsigned int addrbeg = 0x10000, addrend = 0x10000; + cout << "Enter address range (0..0xFFFF)..." << endl; + addrbeg = PromptNewAddress("Start address (0..FFFF): "); + cout << " [" << hex << addrbeg << "]" << endl; + addrend = PromptNewAddress("End address (0..FFFF): "); + cout << " [" << hex << addrend << "]" << endl; + cout << endl; + for (unsigned int addr = addrbeg; addr <= addrend; addr+=16) { + cout << "\t|"; + for (unsigned int j=0; j < 16; j++) { + unsigned int hv = (unsigned int)pvm->MemPeek8bit(addr+j); + if (hv < 16) { + cout << 0; + } + cout << hex << hv << " "; + } + cout << "|"; + for (int j=0; j < 16; j++) { + char cc = (char)pvm->MemPeek8bit(addr+j); + if (isprint(cc)) + cout << cc; + else + cout << "?"; + } + cout << '\r'; + cout << hex << addr; + cout << endl; + } + } + } + } + catch (MKGenException& ex) { + cout << ex.GetCause() << endl; + } + catch (...) { + cout << "ERROR: Fatal." << endl; + } + return 0; +} + +/* + *-------------------------------------------------------------------- + * Method: ShowHel2p() + * Purpose: Display commands help. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void ShowHelp() +{ + cout << R"(Debugger Console Command Reference. + +S - step + Executes single opcode at current address. +C - continue + Continues code execution from current address until BRK. +M - dump memory + Usage: M [startaddr] [endaddr] + Where: startaddr,endaddr - memory addr. in hexadecimal format [0000..FFFF]. + Dumps contents of memory, hexadecimal and ASCII formats." +G - go/continue from new address until BRK + Usage: G [address] + Where: address - memory addr. in hexadecimal format [0000.FFFF]. + Executes code at provided address, interrupted by BRK opcode. +X - execute code from new address until RTS + Usage: X [address] + Where: address - memory addr. in hexadecimal format [0000.FFFF]. + Executes code at provided address, until RTS (last one). +Q - quit + Exits from the emulator/debugger. +A - set address for next step + Usage: A [address] + Where: address - memory addr. in hexadecimal format [0000.FFFF]. + Sets current address to a new value. +N - go number of steps + Usage: N [steps] + Where: steps - number of steps in decimal format + Execute number of opcodes provided in steps argument starting + from current address. +W - write to memory + Usage: W [address] [hexval] [hexval] ... 100 + Where: address - memory addr. in hexadecimal format [0000.FFFF], + hexval - byte value in hexadecimal format [00.FF]. + Writes provided values to memory starting at specified address. +I - toggle char I/O emulation + Usage: I [address] + Where: address - memory addr. in hexadecimal format [0000.FFFF], + Toggles basic character I/O emulation. When enabled, all writes + to the specified memory address also writes a character code to + to a virtual console. All reads from specified memory address + are interpreted as console character input. +R - show registers + Displays CPU registers, flags and stack. +T - show I/O console + Displays/prints the contents of the virtual console screen. + Note that in run mode (commands X, G or C), virtual screen is + displayed automatically in real-time if I/O emulation is enabled. +E - toggle I/O local echo + Toggles local echo on/off when I/O emulation is enabled. +B - blank (clear) screen + Clears the screen, useful when after exiting I/O emulation or + registers animation (long stack) your screen is messed up. +F - toggle registers animation mode + When in multi-step debug mode (command: N), displaying registers + can be suppressed or, when animation mode is enabled - they will + be continuously displayed after each executed step. +J - set registers status animation delay + Usage: J [delay] + Where: delay - time of delay in milliseconds, + Sets the time added at the end of each execution step in multi + step mode (command: N). The default value is 250 ms. +K - toggle ROM emulation + Usage: K [rombegin] [romend] - to enable, + K - to disable, + (OR just use 'K' in both cases and be prompted for arguments.) + Where: + rombegin - hexadecimal address [0200..FFFF], + romend - hexadecimal address [rombegin+1..FFFF]. + Enable/disable ROM emulation and define address range to which the ROM + (read-only memory) will be mapped. Default range: $D000-$DFFF. +L - load memory image + Usage: L [image_type] [image_name] + Where: + image_type - B (binary) OR D (definition), + image_name - name of the image file. + This function allows to load new memory image from either binary + image file or the ASCII definition file. The binary image is always + loaded from address 0x0000 and can be up to 64kB long. The definition + file format is a plain text file that can contain following keywords + and data: + + ADDR This keyword defines the run address of the executable code. + It is optional, but if exists, it must be the 1-st keyword + in the definition file. + Address in decimal or hexadecimal ($xxxx) format must follow + in the next line. + + ORG Changes the current address counter. The line that follows + sets the new address in decimal or hexadecimal format. + Data that follows will be put in memory starting from that + address. This keyword is optional and can be used multiple + times in the definition file. + + IOADDR Defines the address of the character I/O emulation. The + next line sets the address of I/O emulation in decimal or + hexadecimal format. If the I/O emulation is enabled + (see ENIO keyword), then any character written to this + address will be sent to the virtual console. The reading + from that address will invoke character input from the + emulated console. That input procedure is of blocking + type. To invoke non-blocking character procedure, reading + should be performed from IOADDR+1. + + ROMBEGIN Defines the address in memory where the beginning of the + Read Only memory is mapped. The next line that follows this + keyword sets the address in decimal or hexadecimal format. + + ROMEND Defines the address in memory where the end of the Read + Only Memory is mapped. The next line that follows this + keyword sets the address in decimal or hexadecimal format. + + ENIO Putting this keyword in memory definition file enables + rudimentary character I/O emulation and virtual console + emulation. + + ENROM Putting this keyword in memory definition file enables + emulation of Read Only Memory, in range of addresses + defined by ROMBEGIN and ROMEND keywords. + + EXEC Define starting address of code which will be automatically + executed after the memory image is loaded. + The next line that follows this keyword sets the address + in decimal or hexadecimal format. + +O - display op-codes history + Show the history of last executed op-codes/instructions, full with + disassembled mnemonic and argument. +D - diassemble code in memory + Usage: D [startaddr] [endaddr] + Where: startaddr,endaddr - hexadecimal address [0000..FFFF]. + Attempt to disassemble code in specified address range and display + the results (print) on the screen in symbolic form. + +NOTE: + 1. If no arguments provided, each command will prompt user to enter + missing data. + 2. It is possible to exit from running program to debugger console + by pressing CTRL-C or CTRL-Pause/Break, which will generate + a "Operator Interrupt". However in the character input mode + use CTRL-Y combination or CTRL-Break (DOS), CTRL-C (Linux). + You may need to press ENTER after that in input mode (DOS) +)"; + cout << endl; +} \ No newline at end of file diff --git a/makefile b/makefile new file mode 100644 index 0000000..d8d1adb --- /dev/null +++ b/makefile @@ -0,0 +1,49 @@ +# Project: MKBasic + +CPP = g++ -D__DEBUG__ -DLINUX +CC = gcc -D__DEBUG__ +OBJ = main.o VMachine.o MKBasic.o MKCpu.o Memory.o Display.o MKGenException.o +LINKOBJ = main.o VMachine.o MKBasic.o MKCpu.o Memory.o Display.o MKGenException.o +BIN = mkbasic +LIBS = -static-libgcc -m32 -g3 -ltermcap +CLIBS = -static-libgcc -m32 -g3 +INCS = +CXXINCS = +CXXFLAGS = $(CXXINCS) -m32 -std=c++0x -Wall -pedantic -g3 +#CFLAGS = $(INCS) -m32 -std=c++0x -Wall -pedantic -g3 +CFLAGS = $(INCS) -m32 -Wall -pedantic -g3 +RM = rm -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before $(BIN) bin2hex all-after + +clean: clean-custom + ${RM} $(OBJ) $(BIN) bin2hex + +$(BIN): $(OBJ) + $(CPP) $(LINKOBJ) -o $(BIN) $(LIBS) + +main.o: main.cpp + $(CPP) -c main.cpp -o main.o $(CXXFLAGS) + +VMachine.o: VMachine.cpp + $(CPP) -c VMachine.cpp -o VMachine.o $(CXXFLAGS) + +MKBasic.o: MKBasic.cpp + $(CPP) -c MKBasic.cpp -o MKBasic.o $(CXXFLAGS) + +MKCpu.o: MKCpu.cpp + $(CPP) -c MKCpu.cpp -o MKCpu.o $(CXXFLAGS) + +Memory.o: Memory.cpp + $(CPP) -c Memory.cpp -o Memory.o $(CXXFLAGS) + +Display.o: Display.cpp + $(CPP) -c Display.cpp -o Display.o $(CXXFLAGS) + +bin2hex: bin2hex.c + $(CC) bin2hex.c -o bin2hex $(CFLAGS) $(CLIBS) + +MKGenException.o: MKGenException.cpp + $(CPP) -c MKGenException.cpp -o MKGenException.o $(CXXFLAGS) diff --git a/makefile.mingw b/makefile.mingw new file mode 100644 index 0000000..a35382d --- /dev/null +++ b/makefile.mingw @@ -0,0 +1,58 @@ +# Project: MKBasic +# Makefile created by Dev-C++ 5.11 +# and modified for standalone MINGW compiler installation. + +CPP = g++.exe -D__DEBUG__ +CC = gcc.exe -D__DEBUG__ +WINDRES = windres.exe +OBJ = main.o VMachine.o MKBasic.o MKCpu.o Memory.o Display.o MKGenException.o +OBJ2 = bin2hex.o +LINKOBJ = main.o VMachine.o MKBasic.o MKCpu.o Memory.o Display.o MKGenException.o +LINKOBJ2 = bin2hex.o +LIBS = -L"C:\mingw-w64\x86_64-5.3.0\mingw64\x86_64-w64-mingw32/lib" -L"C:\mingw-w64\x86_64-5.3.0\mingw64\x86_64-w64-mingw32/lib" -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic +INCS = -I"C:\mingw-w64\x86_64-5.3.0\mingw64/include" -I"C:\mingw-w64\x86_64-5.3.0\mingw64\x86_64-w64-mingw32/include" -I"C:\mingw-w64\x86_64-5.3.0\mingw64\lib\gcc\x86_64-w64-mingw32\5.3.0/include" +CXXINCS = -I"C:\mingw-w64\x86_64-5.3.0\mingw64/include" -I"C:\mingw-w64\x86_64-5.3.0\mingw64\x86_64-w64-mingw32/include" -I"C:\mingw-w64\x86_64-5.3.0\mingw64\lib\gcc\x86_64-w64-mingw32\5.3.0/include" +BIN = mkbasic.exe +BIN2 = bin2hex.exe +CXXFLAGS = $(CXXINCS) -std=c++11 -Wall -Wextra -pedantic -g3 +CFLAGS = $(INCS) -std=c++11 -Wall -Wextra -pedantic -g3 +CXXFLAGS2 = $(CXXINCS) +CFLAGS2 = $(INCS) +RM = del /f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before $(BIN) $(BIN2) all-after + +clean: clean-custom + ${RM} $(OBJ) $(OBJ2) $(BIN) $(BIN2) + +$(BIN): $(OBJ) + $(CPP) $(LINKOBJ) -o $(BIN) $(LIBS) + +main.o: main.cpp + $(CPP) -c main.cpp -o main.o $(CXXFLAGS) + +VMachine.o: VMachine.cpp + $(CPP) -c VMachine.cpp -o VMachine.o $(CXXFLAGS) + +MKBasic.o: MKBasic.cpp + $(CPP) -c MKBasic.cpp -o MKBasic.o $(CXXFLAGS) + +MKCpu.o: MKCpu.cpp + $(CPP) -c MKCpu.cpp -o MKCpu.o $(CXXFLAGS) + +Memory.o: Memory.cpp + $(CPP) -c Memory.cpp -o Memory.o $(CXXFLAGS) + +Display.o: Display.cpp + $(CPP) -c Display.cpp -o Display.o $(CXXFLAGS) + +MKGenException.o: MKGenException.cpp + $(CPP) -c MKGenException.cpp -o MKGenException.o $(CXXFLAGS) + +$(BIN2): $(OBJ2) + $(CC) $(LINKOBJ2) -o $(BIN2) $(LIBS) + +bin2hex.o: bin2hex.c + $(CC) -c bin2hex.c -o bin2hex.o $(CFLAGS2) diff --git a/makeming.bat b/makeming.bat new file mode 100644 index 0000000..7f2ab63 --- /dev/null +++ b/makeming.bat @@ -0,0 +1,4 @@ +rem to make project on win64 with mingw +rem run in mingw console + +mingw32-make -f makefile.mingw clean all \ No newline at end of file diff --git a/microchess.asm b/microchess.asm new file mode 100644 index 0000000..0ee1a6e --- /dev/null +++ b/microchess.asm @@ -0,0 +1,1051 @@ +;*********************************************************************** +; +; MicroChess (c) 1996-2002 Peter Jennings, peterj@benlo.com +; +;*********************************************************************** +; Daryl Rictor: +; I have been given permission to distribute this program by the +; author and copyright holder, Peter Jennings. Please get his +; permission if you wish to re-distribute a modified copy of +; this file to others. He specifically requested that his +; copyright notice be included in the source and binary images. +; Thanks! +; +; Marek Karcz: +; I have been given permission to distribute this program by the +; original author Peter Jennings under condition that I include +; link to his website in attribution. +; Here it is: http://www.benlo.com/microchess/index.html +; I did not bother to contact Daryl Rictor to ask permission to +; distribute his modifications to this software because according to +; the copyright notice on the web page of his project, permission is +; already given for personal non-commercial use: +; http://sbc.rictor.org/avr65c02.html +; http://sbc.rictor.org/download/AVR65C02.zip, readme.txt +; If this is incorrect or I misunderstood the author's intention, +; please note that I acted with no malicious intent and will remove +; this file from my project if I receive such request. +; +; To build this program with CL65: +; +; cl65 -C microchess.cfg -l --start-addr 1024 -t none -o microchess.bin +; microchess.asm +; +; Binary image microchess.bin can be loaded to emulator with 'L' +; command in debug console. Start emulator: mkbasic, then issue +; command in debug console: +; L B MICROCHESS.BIN +; +; Memory image definition file can be generated which can be loaded +; to emulator via command line argument and automatically executed. +; To create that file, build microchess.bin image, then execute: +; +; bin2hex -f microchess.bin -o microchess.dat -w 0 -x 1024 -z +; +; and add following lines at the end of microchess.dat file: +; +; IOADDR +; $E000 +; ENIO +; +; Instructions to play: +; +; Load the game to emulator and auto-execute with command: +; mkbasic microchess.dat +; then perform following steps: +; 1. Press 'C' to setup board. +; 2. Enter your move: 4 digits - BBEE, BB - piece coordinates, +; EE - destination coordinates and press ENTER +; 3. After board is updated, press 'P' to make program make the move. +; 4. Repeat steps 2 and 3 until the game is finished. +; +; +; 1/14/2012 +; Modified Daryl Rictor's port to run on MKHBC-8-R1 homebrew +; computer under MKHBCOS (derivative of M.O.S. by Scott + Chidester). +; +; 3/11/2016 +; Adapted to run in MKBASIC (V65) emulator. +; +; 3/12/2016 +; Modified UI behavior: +; - chess board is only printed after move, not after each +; keystroke +; - copyright banner is only printed once at the start +; of the program +; +; 6551 I/O Port Addresses +; +;ACIADat = $7F70 +;ACIAsta = $7F71 +;ACIACmd = $7F72 +;ACIACtl = $7F73 + +; M.O.S. API defines (kernal) - OK for emulator, no changes + +.define mos_StrPtr $E0 +.define tmp_zpgPt $F6 + +; jumps, originally for M.O.S., now modified for emulator + +.define mos_CallGetCh $FFED +.define mos_CallPutCh $FFF0 +.define mos_CallPuts $FFF3 + + +; +; page zero variables +; +BOARD = $50 +BK = $60 +PIECE = $B0 +SQUARE = $B1 +SP2 = $B2 +SP1 = $B3 +incHEK = $B4 +STATE = $B5 +MOVEN = $B6 +REV = $B7 +OMOVE = $2C +WCAP0 = $2D +COUNT = $2E +BCAP2 = $2E +WCAP2 = $2F +BCAP1 = $20 +WCAP1 = $21 +BCAP0 = $22 +MOB = $23 +MAXC = $24 +CC = $25 +PCAP = $26 +BMOB = $23 +BMAXC = $24 +BMCC = $25 ; was bcc (TASS doesn't like it as a label) +BMAXP = $26 +XMAXC = $28 +WMOB = $2B +WMAXC = $3C +WCC = $3D +WMAXP = $3E +PMOB = $3F +PMAXC = $40 +PCC = $41 +PCP = $42 +OLDKY = $43 +BESTP = $4B +BESTV = $4A +BESTM = $49 +DIS1 = $4B +DIS2 = $4A +DIS3 = $49 +temp = $4C + +; +; +; + +.segment "BEGN" + + .ORG $0000 + +.segment "CODE" + + .ORG $0400 ; load into RAM @ $1000-$15FF + + lda #$00 ; REVERSE TOGGLE + sta REV + jmp CHESS + +PAINT: .byte $FF ; set this flag if board needs painting + ; unset otherwise +PRNBANN: + .byte $FF ; set this flag to print copyright banner + + ;jsr Init_6551 +CHESS: cld ; INITIALIZE + ldx #$FF ; TWO STACKS + txs + ldx #$C8 + stx SP2 +; +; ROUTINES TO LIGHT LED +; DISPLAY and GET KEY +; FROM KEYBOARD +; +OUT: jsr POUT ; DISPLAY and + jsr KIN ; GET INPUT *** my routine waits for a keypress + cmp #$43 ; [C] + bne NOSET ; SET UP + lda #$FF ; set PAINT flag + sta PAINT ; board needs to be diplayed + ldx #$1F ; BOARD +WHSET: lda SETW,X ; FROM + sta BOARD,X ; SETW + dex + bpl WHSET + ldx #$1B ; *ADDED + stx OMOVE ; INITS TO $FF + lda #$CC ; DISPLAY CCC + bne CLDSP +; +NOSET: cmp #$45 ; [E] + bne NOREV ; REVERSE + lda #$FF + sta PAINT + jsr REVERSE ; BOARD IS + sec + lda #$01 + sbc REV + sta REV ; TOGGLE REV FLAG + lda #$EE ; IS + bne CLDSP +; +NOREV: cmp #$40 ; [P] + bne NOGO ; PLAY CHESS + lda #$FF + sta PAINT + jsr GO +CLDSP: sta DIS1 ; DISPLAY + sta DIS2 ; ACROSS + sta DIS3 ; DISPLAY + bne CHESS +; +NOGO: cmp #$0D ; [Enter] + bne NOMV ; MOVE MAN + pha + lda #$FF + sta PAINT + pla + jsr MOVE ; AS ENTERED + jmp DISP +NOMV: cmp #$41 ; [Q] ***Added to allow game exit*** + beq DONE ; quit the game, exit back to system. + pha + lda #$00 + sta PAINT + pla + jmp INPUT ; process move +DONE: rts +;jmp $FF00 ; *** MUST set this to YOUR OS starting address +; +; THE ROUTINE JANUS DIRECTS THE +; ANALYSIS BY DETERMINING WHAT +; SHOULD OCCUR AFTER EACH MOVE +; GENERATED BY GNM +; +; +; +JANUS: ldx STATE + bmi NOCOUNT +; +; THIS ROUTINE COUNTS OCCURRENCES +; IT DEPENDS UPON STATE TO INdex +; THE CORRECT COUNTERS +; +COUNTS: lda PIECE + beq OVER ; IF STATE=8 + cpx #$08 ; DO NOT COUNT + bne OVER ; BLK MAX CAP + cmp BMAXP ; MOVES FOR + beq XRT ; WHITE +; +OVER: inc MOB,X ; MOBILITY + cmp #$01 ; + QUEEN + bne NOQ ; FOR TWO + inc MOB,X +; +NOQ: bvc NOCAP + ldy #$0F ; CALCULATE + lda SQUARE ; POINTS +ELOOP: cmp BK,Y ; CAPTURED + beq FOUN ; BY THIS + dey ; MOVE + bpl ELOOP +FOUN: lda POINTS,Y + cmp MAXC,X + bcc LESS ; SAVE IF + sty PCAP,X ; BEST THIS + sta MAXC,X ; STATE +; +LESS: clc + php ; ADD TO + adc CC,X ; CAPTURE + sta CC,X ; COUNTS + plp +; +NOCAP: cpx #$04 + beq ON4 + bmi TREE ;(=00 ONLY) +XRT: rts +; +; GENERATE FURTHER MOVES FOR COUNT +; and ANALYSIS +; +ON4: lda XMAXC ; SAVE ACTUAL + sta WCAP0 ; CAPTURE + lda #$00 ; STATE=0 + sta STATE + jsr MOVE ; GENERATE + jsr REVERSE ; IMMEDIATE + jsr GNMZ ; REPLY MOVES + jsr REVERSE +; + lda #$08 ; STATE=8 + sta STATE ; GENERATE +; jsr OHM ; CONTINUATION + jsr UMOVE ; MOVES +; + jmp STRATGY ; FINAL EVALUATION +NOCOUNT:cpx #$F9 + bne TREE +; +; DETERMINE IF THE KING CAN BE +; TAKEN, USED BY CHKCHK +; + lda BK ; IS KING + cmp SQUARE ; IN CHECK? + bne RETJ ; SET incHEK=0 + lda #$00 ; IF IT IS + sta incHEK +RETJ: rts +; +; IF A PIECE HAS BEEN CAPTURED BY +; A TRIAL MOVE, GENERATE REPLIES & +; EVALUATE THE EXCHANGE GAIN/LOSS +; +TREE: bvc RETJ ; NO CAP + ldy #$07 ; (PIECES) + lda SQUARE +LOOPX: cmp BK,Y + beq FOUNX + dey + beq RETJ ; (KING) + bpl LOOPX ; SAVE +FOUNX: lda POINTS,Y ; BEST CAP + cmp BCAP0,X ; AT THIS + bcc NOMAX ; LEVEL + sta BCAP0,X +NOMAX: dec STATE + lda #$FB ; IF STATE=FB + cmp STATE ; TIME TO TURN + beq UPTREE ; AROUND + jsr GENRM ; GENERATE FURTHER +UPTREE: inc STATE ; CAPTURES + rts +; +; THE PLAYER'S MOVE IS INPUT +; +INPUT: cmp #$08 ; NOT A LEGAL + bcs ERROR ; SQUARE # + jsr DISMV +DISP: ldx #$1F +SEARCH: lda BOARD,X + cmp DIS2 + beq HERE ; DISPLAY + dex ; PIECE AT + bpl SEARCH ; FROM +HERE: stx DIS1 ; SQUARE + stx PIECE +ERROR: jmp CHESS +; +; GENERATE ALL MOVES FOR ONE +; SIDE, CALL JANUS AFTER EACH +; ONE FOR NEXT STE? +; +; +GNMZ: ldx #$10 ; CLEAR +GNMX: lda #$00 ; COUNTERS +CLEAR: sta COUNT,X + dex + bpl CLEAR +; +GNM: lda #$10 ; SET UP + sta PIECE ; PIECE +NEWP: dec PIECE ; NEW PIECE + bpl NEX ; ALL DONE? + rts ; #NAME? +; +NEX: jsr RESET ; READY + ldy PIECE ; GET PIECE + ldx #$08 + stx MOVEN ; COMMON staRT + cpy #$08 ; WHAT IS IT? + bpl PAWN ; PAWN + cpy #$06 + bpl KNIGHT ; KNIGHT + cpy #$04 + bpl BISHOP ; BISHOP + cpy #$01 + beq QUEEN ; QUEEN + bpl ROOK ; ROOK +; +KING: jsr SNGMV ; MUST BE KING! + bne KING ; MOVES + beq NEWP ; 8 TO 1 +QUEEN: jsr LINE + bne QUEEN ; MOVES + beq NEWP ; 8 TO 1 +; +ROOK: ldx #$04 + stx MOVEN ; MOVES +AGNR: jsr LINE ; 4 TO 1 + bne AGNR + beq NEWP +; +BISHOP: jsr LINE + lda MOVEN ; MOVES + cmp #$04 ; 8 TO 5 + bne BISHOP + beq NEWP +; +KNIGHT: ldx #$10 + stx MOVEN ; MOVES +AGNN: jsr SNGMV ; 16 TO 9 + lda MOVEN + cmp #$08 + bne AGNN + beq NEWP +; +PAWN: ldx #$06 + stx MOVEN +P1: jsr CMOVE ; RIGHT CAP? + bvc P2 + bmi P2 + jsr JANUS ; YES +P2: jsr RESET + dec MOVEN ; LEFT CAP? + lda MOVEN + cmp #$05 + beq P1 +P3: jsr CMOVE ; AHEAD + bvs NEWP ; ILLEGAL + bmi NEWP + jsr JANUS + lda SQUARE ; GETS TO + and #$F0 ; 3RD RANK? + cmp #$20 + beq P3 ; DO DOUBLE + jmp NEWP +; +; CALCULATE SINGLE STEP MOVES +; FOR K,N +; +SNGMV: jsr CMOVE ; CALC MOVE + bmi ILL1 ; -IF LEGAL + jsr JANUS ; -EVALUATE +ILL1: jsr RESET + dec MOVEN + rts +; +; CALCULATE ALL MOVES DOWN A +; STRAIGHT LINE FOR Q,B,R +; +LINE: jsr CMOVE ; CALC MOVE + bcc OVL ; NO CHK + bvc LINE ; NOCAP +OVL: bmi ILL ; RETURN + php + jsr JANUS ; EVALUATE POSN + plp + bvc LINE ; NOT A CAP +ILL: jsr RESET ; LINE STOPPED + dec MOVEN ; NEXT DIR + rts +; +; EXCHANGE SIDES FOR REPLY +; ANALYSIS +; +REVERSE:ldx #$0F +ETC: sec + ldy BK,X ; SUBTRACT + lda #$77 ; POSITION + sbc BOARD,X ; FROM 77 + sta BK,X + sty BOARD,X ; and + sec + lda #$77 ; EXCHANGE + sbc BOARD,X ; PIECES + sta BOARD,X + dex + bpl ETC + rts +; +; CMOVE CALCULATES THE TO SQUARE +; USING SQUARE and THE MOVE +; TABLE FLAGS SET AS FOLLOWS: +; N#NAME? MOVE +; V#NAME? (LEGAL UNLESS IN CR) +; C#NAME? BECAUSE OF CHECK +; [MY &THANKS TO JIM BUTTERFIELD +; WHO WROTE THIS MORE EFFICIENT +; VERSION OF CMOVE) +; +CMOVE: lda SQUARE ; GET SQUARE + ldx MOVEN ; MOVE POINTER + clc + adc MOVEX,X ; MOVE LIST + sta SQUARE ; NEW POS'N + and #$88 + bne ILLEGAL ; OFF BOARD + lda SQUARE +; + ldx #$20 +LOOP: dex ; IS TO + bmi NO ; SQUARE + cmp BOARD,X ; OCCUPIED? + bne LOOP +; + cpx #$10 ; BY SELF? + bmi ILLEGAL +; + lda #$7F ; MUST BE CAP! + adc #$01 ; SET V FLAG + bvs SPX ; (jmp) +; +NO: clv ; NO CAPTURE +; +SPX: lda STATE ; SHOULD WE + bmi RETL ; DO THE + cmp #$08 ; CHECK CHECK? + bpl RETL +; +; CHKCHK REVERSES SIDES +; and LOOKS FOR A KING +; CAPTURE TO INDICATE +; ILLEGAL MOVE BECAUSE OF +; CHECK SincE THIS IS +; TIME CONSUMING, IT IS NOT +; ALWAYS DONE +; +CHKCHK: pha ; STATE #392 + php + lda #$F9 + sta STATE ; GENERATE + sta incHEK ; ALL REPLY + jsr MOVE ; MOVES TO + jsr REVERSE ; SEE IF KING + jsr GNM ; IS IN + jsr RUM ; CHECK + plp + pla + sta STATE + lda incHEK + bmi RETL ; NO - SAFE + sec ; YES - IN CHK + lda #$FF + rts +; +RETL: clc ; LEGAL + lda #$00 ; RETURN + rts +; +ILLEGAL:lda #$FF + clc ; ILLEGAL + clv ; RETURN + rts +; +; REPLACE PIECE ON CORRECT SQUARE +; +RESET: ldx PIECE ; GET LOGAT + lda BOARD,X ; FOR PIECE + sta SQUARE ; FROM BOARD + rts +; +; +; +GENRM: jsr MOVE ; MAKE MOVE +GENR2: jsr REVERSE ; REVERSE BOARD + jsr GNM ; GENERATE MOVES +RUM: jsr REVERSE ; REVERSE BACK +; +; ROUTINE TO UNMAKE A MOVE MADE BY +; MOVE +; +UMOVE: tsx ; UNMAKE MOVE + stx SP1 + ldx SP2 ; EXCHANGE + txs ; STACKS + pla ; MOVEN + sta MOVEN + pla ; CAPTURED + sta PIECE ; PIECE + tax + pla ; FROM SQUARE + sta BOARD,X + pla ; PIECE + tax + pla ; TO SOUARE + sta SQUARE + sta BOARD,X + jmp STRV +; +; THIS ROUTINE MOVES PIECE +; TO SQUARE, PARAMETERS +; ARE SAVED IN A staCK TO UNMAKE +; THE MOVE LATER +; +MOVE: tsx + stx SP1 ; SWITCH + ldx SP2 ; STACKS + txs + lda SQUARE + pha ; TO SQUARE + tay + ldx #$1F +CHECK: cmp BOARD,X ; CHECK FOR + beq TAKE ; CAPTURE + dex + bpl CHECK +TAKE: lda #$CC + sta BOARD,X + txa ; CAPTURED + pha ; PIECE + ldx PIECE + lda BOARD,X + sty BOARD,X ; FROM + pha ; SQUARE + txa + pha ; PIECE + lda MOVEN + pha ; MOVEN +STRV: tsx + stx SP2 ; SWITCH + ldx SP1 ; STACKS + txs ; BACK + rts +; +; CONTINUATION OF SUB STRATGY +; -CHECKS FOR CHECK OR CHECKMATE +; and ASSIGNS VALUE TO MOVE +; +CKMATE: ldy BMAXC ; CAN BLK CAP + cpx POINTS ; MY KING? + bne NOCHEK + lda #$00 ; GULP! + beq RETV ; DUMB MOVE! +; +NOCHEK: ldx BMOB ; IS BLACK + bne RETV ; UNABLE TO + ldx WMAXP ; MOVE and + bne RETV ; KING IN CH? + lda #$FF ; YES! MATE +; +RETV: ldx #$04 ; RESTORE + stx STATE ; STATE=4 +; +; THE VALUE OF THE MOVE (IN ACCU) +; IS COMPARED TO THE BEST MOVE and +; REPLACES IT IF IT IS BETTER +; +PUSH: cmp BESTV ; IS THIS BEST + bcc RETP ; MOVE SO FAR? + beq RETP + sta BESTV ; YES! + lda PIECE ; SAVE IT + sta BESTP + lda SQUARE + sta BESTM ; FLASH DISPLAY +RETP: lda #'.' ; print ... instead of flashing disp + jmp syschout ; print . and return +; +; MAIN PROGRAM TO PLAY CHESS +; PLAY FROM OPENING OR THINK +; +GO: ldx OMOVE ; OPENING? + bmi NOOPEN ; -NO *ADD CHANGE FROM bpl + lda DIS3 ; -YES WAS + cmp OPNING,X ; OPPONENT'S + bne END ; MOVE OK? + dex + lda OPNING,X ; GET NEXT + sta DIS1 ; CANNED + dex ; OPENING MOVE + lda OPNING,X + sta DIS3 ; DISPLAY IT + dex + stx OMOVE ; MOVE IT + bne MV2 ; (jmp) +; +END: lda #$FF ; *ADD - STOP CANNED MOVES + sta OMOVE ; FLAG OPENING +NOOPEN: ldx #$0C ; FINISHED + stx STATE ; STATE=C + stx BESTV ; CLEAR BESTV + ldx #$14 ; GENERATE P + jsr GNMX ; MOVES +; + ldx #$04 ; STATE=4 + stx STATE ; GENERATE and + jsr GNMZ ; TEST AVAILABLE +; +; MOVES +; + ldx BESTV ; GET BEST MOVE + cpx #$0F ; IF NONE + bcc MATE ; OH OH! +; +MV2: ldx BESTP ; MOVE + lda BOARD,X ; THE + sta BESTV ; BEST + stx PIECE ; MOVE + lda BESTM + sta SQUARE ; and DISPLAY + jsr MOVE ; IT + jmp CHESS +; +MATE: lda #$FF ; RESIGN + rts ; OR staLEMATE +; +; SUBROUTINE TO ENTER THE +; PLAYER'S MOVE +; +DISMV: ldx #$04 ; ROTATE +Drol: asl DIS3 ; KEY + rol DIS2 ; INTO + dex ; DISPLAY + bne Drol ; + ora DIS3 + sta DIS3 + sta SQUARE + rts +; +; THE FOLLOWING SUBROUTINE ASSIGNS +; A VALUE TO THE MOVE UNDER +; CONSIDERATION and RETURNS IT IN +; THE ACCUMULATOR +; + +STRATGY:clc + lda #$80 + adc WMOB ; PARAMETERS + adc WMAXC ; WITH WHEIGHT + adc WCC ; OF O25 + adc WCAP1 + adc WCAP2 + sec + sbc PMAXC + sbc PCC + sbc BCAP0 + sbc BCAP1 + sbc BCAP2 + sbc PMOB + sbc BMOB + bcs POS ; UNDERFLOW + lda #$00 ; PREVENTION +POS: lsr + clc ; ************** + adc #$40 + adc WMAXC ; PARAMETERS + adc WCC ; WITH WEIGHT + sec ; OF 05 + sbc BMAXC + lsr ; ************** + clc + adc #$90 + adc WCAP0 ; PARAMETERS + adc WCAP0 ; WITH WEIGHT + adc WCAP0 ; OF 10 + adc WCAP0 + adc WCAP1 + sec ; [UNDER OR OVER- + sbc BMAXC ; FLOW MAY OCCUR + sbc BMAXC ; FROM THIS + sbc BMCC ; secTION] + sbc BMCC + sbc BCAP1 + ldx SQUARE ; *************** + cpx #$33 + beq POSN ; POSITION + cpx #$34 ; BONUS FOR + beq POSN ; MOVE TO + cpx #$22 ; CENTRE + beq POSN ; OR + cpx #$25 ; OUT OF + beq POSN ; BACK RANK + ldx PIECE + beq NOPOSN + ldy BOARD,X + cpy #$10 + bpl NOPOSN +POSN: clc + adc #$02 +NOPOSN: jmp CKMATE ; CONTINUE + + +;----------------------------------------------------------------- +; The following routines were added to allow text-based board +; DISPLAY over a standard RS-232 port. +; +POUT: lda PAINT + bne POUT0 + rts ; return if PAINT flag = 0 +POUT0: jsr POUT9 ; print CRLF + jsr POUT13 ; print copyright + jsr POUT10 ; print column labels + ldy #$00 ; init board location + jsr POUT5 ; print board horz edge +POUT1: lda #'|' ; print vert edge + jsr syschout ; PRINT ONE ASCII CHR - SPACE + ldx #$1F +POUT2: tya ; scan the pieces for a location match + cmp BOARD,X ; match found? + beq POUT4 ; yes; print the piece's color and type + dex ; no + bpl POUT2 ; if not the last piece, try again + tya ; empty square + and #$01 ; odd or even column? + sta temp ; save it + tya ; is the row odd or even + lsr ; shift column right 4 spaces + lsr ; + lsr ; + lsr ; + and #$01 ; strip LSB + clc ; + adc temp ; combine row & col to determine square color + and #$01 ; is board square white or blk? + bne POUT25 ; white, print space + lda #'*' ; black, print * + + .byte $2c ; used to skip over lda #$20 + ;jmp POUT25A + +POUT25: lda #$20 ; ASCII space +POUT25A:jsr syschout ; PRINT ONE ASCII CHR - SPACE + jsr syschout ; PRINT ONE ASCII CHR - SPACE +POUT3: iny ; + tya ; get row number + and #$08 ; have we completed the row? + beq POUT1 ; no, do next column + lda #'|' ; yes, put the right edge on + jsr syschout ; PRINT ONE ASCII CHR - | + jsr POUT12 ; print row number + jsr POUT9 ; print CRLF + jsr POUT5 ; print bottom edge of board + clc ; + tya ; + adc #$08 ; point y to beginning of next row + tay ; + cpy #$80 ; was that the last row? + beq POUT8 ; yes, print the LED values + bne POUT1 ; no, do new row + +POUT4: lda REV ; print piece's color & type + beq POUT41 ; + lda cpl+16,X ; + bne POUT42 ; +POUT41: lda cpl,x ; +POUT42: jsr syschout ; + lda cph,x ; + jsr syschout ; + bne POUT3 ; branch always + +POUT5: txa ; print "-----...-----" + pha + ldx #$19 + lda #'-' +POUT6: jsr syschout ; PRINT ONE ASCII CHR - "-" + dex + bne POUT6 + pla + tax + jsr POUT9 + rts + +POUT8: jsr POUT10 ; + lda BESTP + jsr syshexout ; PRINT 1 BYTE AS 2 HEX CHRS + lda #$20 + jsr syschout ; PRINT ONE ASCII CHR - SPACE + lda BESTV + jsr syshexout ; PRINT 1 BYTE AS 2 HEX CHRS + lda #$20 + jsr syschout ; PRINT ONE ASCII CHR - SPACE + lda DIS3 + jsr syshexout ; PRINT 1 BYTE AS 2 HEX CHRS + +POUT9: lda #$0D + jsr syschout ; PRINT ONE ASCII CHR - CR + lda #$0A + jsr syschout ; PRINT ONE ASCII CHR - LF + rts + +POUT10: ldx #$00 ; print the column labels +POUT11: lda #$20 ; 00 01 02 03 ... 07 + jsr syschout + txa + jsr syshexout + inx + cpx #$08 + bne POUT11 + beq POUT9 +POUT12: tya + and #$70 + jsr syshexout + rts + +; print banner only once, preserve registers A, X, Y +POUT13: stx tmp_zpgPt + sta tmp_zpgPt+1 + sty tmp_zpgPt+2 + lda PRNBANN + beq NOPRNBANN + lda #banner + sta mos_StrPtr+1 + jsr mos_CallPuts +NOPRNBANN: + lda #$00 + sta PRNBANN + ldx tmp_zpgPt + lda tmp_zpgPt+1 + ldy tmp_zpgPt+2 + rts + +; ldx #$00 ; Print the copyright banner +;POUT14: lda banner,x +; beq POUT15 +; jsr syschout +; inx +; bne POUT14 +;POUT15: rts + +KIN: lda #'?' + jsr syschout ; PRINT ONE ASCII CHR - ? + jsr syskin ; GET A KEYSTROKE FROM SYSTEM + jsr syschout ; echo entered character + and #$4F ; MASK 0-7, and ALpha'S + rts +; +; 6551 I/O Support Routines +; +; +;Init_6551 lda #$1F ; 19.2K/8/1 +; sta ACIActl ; control reg +; lda #$0B ; N parity/echo off/rx int off/ dtr active low +; sta ACIAcmd ; command reg +; rts ; done +; +; input chr from ACIA1 (waiting) +; +syskin: + jsr mos_CallGetCh + rts + + ;lda ACIAsta ; Serial port status + ;and #$08 ; is recvr full + ;beq syskin ; no char to get + ;lda ACIAdat ; get chr + ;rts ; +; +; output to OutPut Port +; +syschout: ; MKHBCOS: must preserve X, Y and A + stx tmp_zpgPt + sta tmp_zpgPt+1 + ;sty tmp_zpgPt+2 + jsr mos_CallPutCh + ldx tmp_zpgPt + lda tmp_zpgPt+1 + ;ldy tmp_zpgPt+2 + rts +; pha ; save registers +;ACIA_Out1 lda ACIAsta ; serial port status +; and #$10 ; is tx buffer empty +; beq ACIA_Out1 ; no +; pla ; get chr +; sta ACIAdat ; put character to Port +; rts ; done + +syshexout: pha ; prints AA hex digits + lsr ; MOVE UPPER NIBBLE TO LOWER + lsr ; + lsr ; + lsr ; + jsr PrintDig ; + pla ; +PrintDig: + sty tmp_zpgPt+2 + and #$0F ; + tay ; + lda Hexdigdata,Y ; + ldy tmp_zpgPt+2 ; + jmp syschout ; + +Hexdigdata: .byte "0123456789ABCDEF" +banner: .byte "MicroChess (c) 1996-2002 Peter Jennings, peterj@benlo.com" + .byte $0d, $0a, $00 +cpl: .byte "WWWWWWWWWWWWWWWWBBBBBBBBBBBBBBBBWWWWWWWWWWWWWWWW" +cph: .byte "KQCCBBRRPPPPPPPPKQCCBBRRPPPPPPPP" + .byte $00 +; +; end of added code +; +; BLOCK DATA + +.segment "DATA" + + .ORG $0A20 + +SETW: .byte $03, $04, $00, $07, $02, $05, $01, $06 + .byte $10, $17, $11, $16, $12, $15, $14, $13 + .byte $73, $74, $70, $77, $72, $75, $71, $76 + .byte $60, $67, $61, $66, $62, $65, $64, $63 + +MOVEX: .byte $00, $F0, $FF, $01, $10, $11, $0F, $EF, $F1 + .byte $DF, $E1, $EE, $F2, $12, $0E, $1F, $21 + +POINTS: .byte $0B, $0A, $06, $06, $04, $04, $04, $04 + .byte $02, $02, $02, $02, $02, $02, $02, $02 + +OPNING: .byte $99, $25, $0B, $25, $01, $00, $33, $25 + .byte $07, $36, $34, $0D, $34, $34, $0E, $52 + .byte $25, $0D, $45, $35, $04, $55, $22, $06 + .byte $43, $33, $0F, $CC + +.segment "KERN" + + .ORG $FE00 + +CHRIN: lda $E000 + rts + +CHROUT: sta $E000 + rts + +; this function was shamelessly ripped :-) from M.O.S. code (c) by Scott Chidester + +STROUT: + ldy #0 ; Non-indexed variant starts at zero, of course + lda mos_StrPtr+1 ; Save StrPtr so it isn't modified + pha +PutsLoop: + lda (mos_StrPtr),y ; Get the next char in the string + beq PutsDone ; Zero means end of string + jsr CHROUT ; Otherwise put the char + + ; Update string pointer + iny ; increment StrPtr-lo + bne PutsLoop ; No rollover? Loop back for next character + inc mos_StrPtr+1 ; StrPtr-lo rolled over--carry hi byte + jmp PutsLoop ; Now loop back + +PutsDone: + pla + sta mos_StrPtr+1 ; Restore StrPtr + rts + +.segment "VECT" + + .ORG $FFED + + jmp CHRIN + jmp CHROUT + jmp STROUT + +; +; +; end of file +; diff --git a/microchess.bin b/microchess.bin new file mode 100644 index 0000000000000000000000000000000000000000..da73a58ccd07bc5825add5dff27d95eed9845e9c GIT binary patch literal 65526 zcmeIz|8Emz90%}gdw0EdY&!-*jl?}{D_LcmWgBB8D*Ga)?P@rP1`WR)%t~i;Oa}6c zM1J5JGDBDlP3HUsFS~{#E@@%ifVgD-Fr*E}iwTK@7`vDf6BJK~`yyfWxo(kUf5Lb_ z*FN_=pXa$x?|I!lDZ`*Z00PgdfX*lrVHaB{{Hzv+)tj-)v=bes|A zukCf;t{G&{Z;97HO`4u6BJ)hhM${?jx!y%*x+Xsrvhe}E6yIdcm}i6&2{ z43^FrlcgsYoJ%>mGv?potd+HD&>pY4k=7qir%eah!{1BG86jCgHaXSGv@{(u9a(WM z))h-qAyw3wctcivtcyzWMpCrNB*2d(RUtM$C5Y`)yx1_sij`9~(*p^#T=5PlpEA zm~JJcC6z8Mr3Cec@Hrt-=ij6Se>vzj)@COUx|ObC9n8k+j7@q$sZ-a)(y@@bo^0i; z9Q2(@gmUGB6^Sl-`=MA;3o0q=Rdum+aVpCPw}i6B0vA+hoG$iMWNYM=$g7dfk(XQZ zZTa?mRi5M<^1JfYNxRO3JUwmJaBIGXHU}g1%g1IKpofbEX#T6 zs*qir{tWVRt{0DHo6sud^ROK6r#mv z^F+cvo8i!3s?!ObL_ar&e1iEy@e=ZuU?p-1o}nJ$;?yZ~t1+fcnA~Kk%WzCSv1U)! zyJ&4>2LkHzdOdAsjenz;=v6ZPajlDdB^2{&q5oS!t5r&8>TX)eDpQ;=K%>9Yjr`F3 zZOGS0J92DRnL9l{DzIjW{+*JeJ9CCSD$w08u!&i1Ze(88chLmobL%#Idt~xwp?D23 z3)Z+Cuog&0gy`vcU-`vrDPd%uK4Jg1#-`@&EjwCwws&;CzWa?gd%BMv>5NAD`$=uL zk8Inyv!%Y#?{6ehR~A|F2Z{-MZw-HchV ziEGRM`uo?J2M;UCDmRz7d7h=kzFfZamUwMUlh@hOT-w}Rw$EF-dprAf72nxZerpwa zVM!2x00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa z0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV= z5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHaf zKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_ z009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz z00bZa0SG_<0uX=z1Rwwb2tZ)935+s1`7HfjV6>S)Drc4ucJZb$dv7LOx)@bvzhW--hzhK0rd0E?(w" +00080A 1 48 pha +00080B 1 A2 19 ldx #$19 +00080D 1 A9 2D lda #'-' +00080F 1 20 8F 08 POUT6: jsr syschout ; PRINT ONE ASCII CHR - "-" +000812 1 CA dex +000813 1 D0 FA bne POUT6 +000815 1 68 pla +000816 1 AA tax +000817 1 20 37 08 jsr POUT9 +00081A 1 60 rts +00081B 1 +00081B 1 20 42 08 POUT8: jsr POUT10 ; +00081E 1 A5 4B lda BESTP +000820 1 20 9B 08 jsr syshexout ; PRINT 1 BYTE AS 2 HEX CHRS +000823 1 A9 20 lda #$20 +000825 1 20 8F 08 jsr syschout ; PRINT ONE ASCII CHR - SPACE +000828 1 A5 4A lda BESTV +00082A 1 20 9B 08 jsr syshexout ; PRINT 1 BYTE AS 2 HEX CHRS +00082D 1 A9 20 lda #$20 +00082F 1 20 8F 08 jsr syschout ; PRINT ONE ASCII CHR - SPACE +000832 1 A5 49 lda DIS3 +000834 1 20 9B 08 jsr syshexout ; PRINT 1 BYTE AS 2 HEX CHRS +000837 1 +000837 1 A9 0D POUT9: lda #$0D +000839 1 20 8F 08 jsr syschout ; PRINT ONE ASCII CHR - CR +00083C 1 A9 0A lda #$0A +00083E 1 20 8F 08 jsr syschout ; PRINT ONE ASCII CHR - LF +000841 1 60 rts +000842 1 +000842 1 A2 00 POUT10: ldx #$00 ; print the column labels +000844 1 A9 20 POUT11: lda #$20 ; 00 01 02 03 ... 07 +000846 1 20 8F 08 jsr syschout +000849 1 8A txa +00084A 1 20 9B 08 jsr syshexout +00084D 1 E8 inx +00084E 1 E0 08 cpx #$08 +000850 1 D0 F2 bne POUT11 +000852 1 F0 E3 beq POUT9 +000854 1 98 POUT12: tya +000855 1 29 70 and #$70 +000857 1 20 9B 08 jsr syshexout +00085A 1 60 rts +00085B 1 +00085B 1 ; print banner only once, preserve registers A, X, Y +00085B 1 86 F6 POUT13: stx tmp_zpgPt +00085D 1 85 F7 sta tmp_zpgPt+1 +00085F 1 84 F8 sty tmp_zpgPt+2 +000861 1 AD 08 04 lda PRNBANN +000864 1 F0 0B beq NOPRNBANN +000866 1 A9 C1 lda #banner +00086C 1 85 E1 sta mos_StrPtr+1 +00086E 1 20 F3 FF jsr mos_CallPuts +000871 1 NOPRNBANN: +000871 1 A9 00 lda #$00 +000873 1 8D 08 04 sta PRNBANN +000876 1 A6 F6 ldx tmp_zpgPt +000878 1 A5 F7 lda tmp_zpgPt+1 +00087A 1 A4 F8 ldy tmp_zpgPt+2 +00087C 1 60 rts +00087D 1 +00087D 1 ; ldx #$00 ; Print the copyright banner +00087D 1 ;POUT14: lda banner,x +00087D 1 ; beq POUT15 +00087D 1 ; jsr syschout +00087D 1 ; inx +00087D 1 ; bne POUT14 +00087D 1 ;POUT15: rts +00087D 1 +00087D 1 A9 3F KIN: lda #'?' +00087F 1 20 8F 08 jsr syschout ; PRINT ONE ASCII CHR - ? +000882 1 20 8B 08 jsr syskin ; GET A KEYSTROKE FROM SYSTEM +000885 1 20 8F 08 jsr syschout ; echo entered character +000888 1 29 4F and #$4F ; MASK 0-7, and ALpha'S +00088A 1 60 rts +00088B 1 ; +00088B 1 ; 6551 I/O Support Routines +00088B 1 ; +00088B 1 ; +00088B 1 ;Init_6551 lda #$1F ; 19.2K/8/1 +00088B 1 ; sta ACIActl ; control reg +00088B 1 ; lda #$0B ; N parity/echo off/rx int off/ dtr active low +00088B 1 ; sta ACIAcmd ; command reg +00088B 1 ; rts ; done +00088B 1 ; +00088B 1 ; input chr from ACIA1 (waiting) +00088B 1 ; +00088B 1 syskin: +00088B 1 20 ED FF jsr mos_CallGetCh +00088E 1 60 rts +00088F 1 +00088F 1 ;lda ACIAsta ; Serial port status +00088F 1 ;and #$08 ; is recvr full +00088F 1 ;beq syskin ; no char to get +00088F 1 ;lda ACIAdat ; get chr +00088F 1 ;rts ; +00088F 1 ; +00088F 1 ; output to OutPut Port +00088F 1 ; +00088F 1 syschout: ; MKHBCOS: must preserve X, Y and A +00088F 1 86 F6 stx tmp_zpgPt +000891 1 85 F7 sta tmp_zpgPt+1 +000893 1 ;sty tmp_zpgPt+2 +000893 1 20 F0 FF jsr mos_CallPutCh +000896 1 A6 F6 ldx tmp_zpgPt +000898 1 A5 F7 lda tmp_zpgPt+1 +00089A 1 ;ldy tmp_zpgPt+2 +00089A 1 60 rts +00089B 1 ; pha ; save registers +00089B 1 ;ACIA_Out1 lda ACIAsta ; serial port status +00089B 1 ; and #$10 ; is tx buffer empty +00089B 1 ; beq ACIA_Out1 ; no +00089B 1 ; pla ; get chr +00089B 1 ; sta ACIAdat ; put character to Port +00089B 1 ; rts ; done +00089B 1 +00089B 1 48 syshexout: pha ; prints AA hex digits +00089C 1 4A lsr ; MOVE UPPER NIBBLE TO LOWER +00089D 1 4A lsr ; +00089E 1 4A lsr ; +00089F 1 4A lsr ; +0008A0 1 20 A4 08 jsr PrintDig ; +0008A3 1 68 pla ; +0008A4 1 PrintDig: +0008A4 1 84 F8 sty tmp_zpgPt+2 +0008A6 1 29 0F and #$0F ; +0008A8 1 A8 tay ; +0008A9 1 B9 B1 08 lda Hexdigdata,Y ; +0008AC 1 A4 F8 ldy tmp_zpgPt+2 ; +0008AE 1 4C 8F 08 jmp syschout ; +0008B1 1 +0008B1 1 30 31 32 33 Hexdigdata: .byte "0123456789ABCDEF" +0008B5 1 34 35 36 37 +0008B9 1 38 39 41 42 +0008C1 1 4D 69 63 72 banner: .byte "MicroChess (c) 1996-2002 Peter Jennings, peterj@benlo.com" +0008C5 1 6F 43 68 65 +0008C9 1 73 73 20 28 +0008FA 1 0D 0A 00 .byte $0d, $0a, $00 +0008FD 1 57 57 57 57 cpl: .byte "WWWWWWWWWWWWWWWWBBBBBBBBBBBBBBBBWWWWWWWWWWWWWWWW" +000901 1 57 57 57 57 +000905 1 57 57 57 57 +00092D 1 4B 51 43 43 cph: .byte "KQCCBBRRPPPPPPPPKQCCBBRRPPPPPPPP" +000931 1 42 42 52 52 +000935 1 50 50 50 50 +00094D 1 00 .byte $00 +00094E 1 ; +00094E 1 ; end of added code +00094E 1 ; +00094E 1 ; BLOCK DATA +00094E 1 +00094E 1 .segment "DATA" +00094E 1 +00094E 1 .ORG $0A20 +000A20 1 +000A20 1 03 04 00 07 SETW: .byte $03, $04, $00, $07, $02, $05, $01, $06 +000A24 1 02 05 01 06 +000A28 1 10 17 11 16 .byte $10, $17, $11, $16, $12, $15, $14, $13 +000A2C 1 12 15 14 13 +000A30 1 73 74 70 77 .byte $73, $74, $70, $77, $72, $75, $71, $76 +000A34 1 72 75 71 76 +000A38 1 60 67 61 66 .byte $60, $67, $61, $66, $62, $65, $64, $63 +000A3C 1 62 65 64 63 +000A40 1 +000A40 1 00 F0 FF 01 MOVEX: .byte $00, $F0, $FF, $01, $10, $11, $0F, $EF, $F1 +000A44 1 10 11 0F EF +000A48 1 F1 +000A49 1 DF E1 EE F2 .byte $DF, $E1, $EE, $F2, $12, $0E, $1F, $21 +000A4D 1 12 0E 1F 21 +000A51 1 +000A51 1 0B 0A 06 06 POINTS: .byte $0B, $0A, $06, $06, $04, $04, $04, $04 +000A55 1 04 04 04 04 +000A59 1 02 02 02 02 .byte $02, $02, $02, $02, $02, $02, $02, $02 +000A5D 1 02 02 02 02 +000A61 1 +000A61 1 99 25 0B 25 OPNING: .byte $99, $25, $0B, $25, $01, $00, $33, $25 +000A65 1 01 00 33 25 +000A69 1 07 36 34 0D .byte $07, $36, $34, $0D, $34, $34, $0E, $52 +000A6D 1 34 34 0E 52 +000A71 1 25 0D 45 35 .byte $25, $0D, $45, $35, $04, $55, $22, $06 +000A75 1 04 55 22 06 +000A79 1 43 33 0F CC .byte $43, $33, $0F, $CC +000A7D 1 +000A7D 1 .segment "KERN" +000A7D 1 +000A7D 1 .ORG $FE00 +00FE00 1 +00FE00 1 AD 00 E0 CHRIN: lda $E000 +00FE03 1 60 rts +00FE04 1 +00FE04 1 8D 00 E0 CHROUT: sta $E000 +00FE07 1 60 rts +00FE08 1 +00FE08 1 ; this function was shamelessly ripped :-) from M.O.S. code (c) by Scott Chidester +00FE08 1 +00FE08 1 STROUT: +00FE08 1 A0 00 ldy #0 ; Non-indexed variant starts at zero, of course +00FE0A 1 A5 E1 lda mos_StrPtr+1 ; Save StrPtr so it isn't modified +00FE0C 1 48 pha +00FE0D 1 PutsLoop: +00FE0D 1 B1 E0 lda (mos_StrPtr),y ; Get the next char in the string +00FE0F 1 F0 0B beq PutsDone ; Zero means end of string +00FE11 1 20 04 FE jsr CHROUT ; Otherwise put the char +00FE14 1 +00FE14 1 ; Update string pointer +00FE14 1 C8 iny ; increment StrPtr-lo +00FE15 1 D0 F6 bne PutsLoop ; No rollover? Loop back for next character +00FE17 1 E6 E1 inc mos_StrPtr+1 ; StrPtr-lo rolled over--carry hi byte +00FE19 1 4C 0D FE jmp PutsLoop ; Now loop back +00FE1C 1 +00FE1C 1 PutsDone: +00FE1C 1 68 pla +00FE1D 1 85 E1 sta mos_StrPtr+1 ; Restore StrPtr +00FE1F 1 60 rts +00FE20 1 +00FE20 1 .segment "VECT" +00FE20 1 +00FE20 1 .ORG $FFED +00FFED 1 +00FFED 1 4C 00 FE jmp CHRIN +00FFF0 1 4C 04 FE jmp CHROUT +00FFF3 1 4C 08 FE jmp STROUT +00FFF6 1 +00FFF6 1 ; +00FFF6 1 ; +00FFF6 1 ; end of file +00FFF6 1 ; +00FFF6 1 diff --git a/microchess.o b/microchess.o new file mode 100644 index 0000000000000000000000000000000000000000..f69541f5af9ad6ccb4083b679ae61100ea0108c8 GIT binary patch literal 11613 zcmb7~dvsG(zQ?mq&N)e|NPUblSMP8XaM>$xOYwng=|~$g^bwL{+5*npSu2Pc%N+%V z#~trnx#KGpc?c?%0zM#+LO`?y(w5e00YO?pB8rOmC~6gXXaISM(!0<8ezVrBHGjBn zm&xb*-TU|Z?bkUcX|d{WlP6r{a=FIKSB`v5kgr_%`m=oPy}{+WBj4o`Qva5`lN?DF zNnWkHT>miyaWYi>XqqqmYn&=RGCdpqDl+*bd@nhFj`EsEhY<0(2;FD27S%;;sZa~=Bo zkm;A{$&&TliB~u?a{jB?nL&u^1_WA-s(?1rgb;xZDpR}4fDoMrW*#w_UmZUgj z6NYq=^P96nLWt@X1O_%^$UFl=L|V~N|0WijA`7;QtDFn(ZZh#U`Wwj1E^)2X?z*WWiD74J9MTke4`t_8Z99 zNpYRC&>>{<2Qk3$E;4os8;~Nc(<)wGwGhHOgN6eJgs{%45wv^*LRjb2#UvjZ5F&YA z^jB988T$!yN|DwDl>CDUAp#F;&Lp+L9thF>h^8J?=g9P<@E4JZCp2|^M#$~6;Ty^H zlkhs3oCEJ7V{zb5k)V;aFKFrxzK-1SA_h*8$(N9S zp4`41JCGtXD^Sl(T5;vIkO?8aUdaS9vI;BdT%+M|$%Z8SWu&!MO+>rK10mw;aCZI4 z)XSK;O>SS0{xUN23JSW(u2MB*^6t|qec2nu+~^ilXTWab$BdNTe!yh+w%SdX-hW5AOJgs@L&&NnAv zkOe2<-K6yc5@zWT!a9W;sl(`sy48bU05 z2BkI9e%7si|2Rh$EK)-W59zICq32L&mJT6qSd0$44y((M))EAkm=I#eQUo-Sk!47X zFUL0ZB}c44`=&T%7$K7@;r~jWS_N;DwF%UTkc;ZE0-GGM8g-LvScg27WF4}0ty_Jl z*<{x`vP?Aqp5kMx2!k#`BXZ#x%ArgtFk9NE1S6V4+GIiI( zH2zLb+J$&QPTfsUw(P+?67OOjDY9TM<}r}$d=KmQl6miQJ!Hve7}xtb53ZZ@CSwO# zpNxG0zlpTIR9=3Igb>zOXgFX%2&)GTg$9JMzDC1%6GGhZ4aTlM1jfF_{gomUhjAvG z$butSqfU-EioHl4!`yqx$akpMFT?)h*h3c?Il(pmz&x_wDa5y&1|w$>SAX8Ez7RE# zsh{9&GWIikBN@4XJnK#k<5u5OTx zWc@s}Zy=Y>hp&DLj4jaB*VHDmdLi4N1{=t=&*I=1vZlPE8#bgOIIN-k>CJiNj>7$tVVx)jT%7o zC-)`MZSi@lj~7u7g_rX7edZ?6?IA)!1_kyH;}0fj3*auA(-ntoaHLdU)$oe+;jpWkT;3MsbU$qT>AbIpn<>l`i5F))D z8>*AZ9Y}DInYZ9`$@)(C0c5%h-X!bahW{;@-UY9b$=&e1WPA_2PS&L1Q{?s!boC)w zMlSpi{$euo5e_PsjO}MUnfMsKfs7r%2A7kGPk2F*u}=|SN+v&pA4S6*A-g%I^$ z>CP7fF_KT}QE1 z?Z*^lMFK`%G49m#wN8$UD3m=2OjI58rmy@X) zc$)jn1Ahk@O=5?xC8KNM|D7DM4&(H^jP{Xa&w4|Bautz1ub}@rvgcKJ zi|lEDA4>K#V%~R>JsaQ$kPRC#PmN4&f_IT+DeglP+9x$5eQ8zdbr+J+H;^}kjCRnI(Jl03bSvr)A*0*iuO&yk$$4xC2a-KI z=*gb9;0KXCJ29_8WKSpRT4a3};v32Cw-G;_%bi-3nn>o5Wqcp*gm2&UhktUHQ?eaAqX%zOtwlI;2(J}(2FCF_pE=br!t z89NCdAnSgBFFQq^CeM&(!TfWeAp89YA3YBS$o!ueN2Y&OwNISh_vQr3qlBM9vUjW5W<>| zhFiT5!g>k~IbI0SZ-HtMbqm2sPlH}^%`@;F&w>w=nMLq7lIdFbO=M!R>HM3gXeKjt z@CMnwM0u@G4unWAMSz=ZUxt96y%55B9t{h;5TgABGz`gs5Y~&?2ndmWNi~Qra?T2D zbV=M)pFHuEruxMCHJMxmKZLXrYEkkCAw*X_64R?q^C%eq}7_O03niX2*@R^*RlZ+BGQia$KOyL!bK)K;H@mT zs1uSq4k6}j<;HC@e~o>C5QpAGNB4FN?IqJYO!Y0}1etjY+w&z^w-b5!oyeO?T3y)z zAVlPC1lGKxI>c!*wg-u4$j8(0XUX;Nn$F{2^Xd>Hvlj&}B9rf#m&yRKg^ay#{)^+g z$>cutd&$@bSiwQk`cQf8WG{qB?#B#VdCH>-mn`KD-Q_)8w=5)^02{N-rxORiY~zd4Qqja~?`Y9%_(l7UqSSm1@w3x*XAulG2g z1^P`l-*PMEh}(*aDSe~-zoQ&8Y2viih@IlAj#5saZrwmRG2a?SdE0Hb452J6C@7?~ z?C1>2=rpS=D<@B$L^=7s>4USeQ~x3MKS#3lp6KNJDW?pbI0aHXK=xVVQIG!IH6F{^ zFV`B+AZKagZPisd0%x2{Or5XAE)r|Z|3-a%4LH>jmA^je9?;hyjJ92+KT+Xt;qkr75T?oJ;lyGeBOpS2is8RyEfE0(Z+pfL!C?7P^W(z z>Rj7~Iv2GgKerwEW;^mF)j8-AgRtlQk{eLI`SpeIZCQ?l*Bo{j(q7=zNE^R zRQXFfkUyvc`4@E{UwV}qL!V^=JE|2=QHh)*P142Z0qhtAA&$TjH zxX8qN@CV6~_Yv3l0ouFC%!lw7k=94bYx)HUvGV`|(w~5*$*(_!KS%~XLt>u`5Tg1Z zMvQ%-9)02<8Try_zg5 z9*|Ei)D*Z>@-Q~^C@W?<5j~rr*E7i-Q#4Jqio%F8g12R`+RQO zXB(lwsPemwVt+-Yt=`9~_c8jY(u!fuTcPtdT%QqrV5;FO@mEwBc2TLE>d@(v{ucGv z;b3u5Fz60dRqD2UbC;I}jbNz4Uuldhk?*>EjWc|KQ5CjqmW%etmp@$L*Mp(aA#HR> za?DuW*$8JGTOSn)`i;_{T~%q66$Ps*Ji(CK8dJSj=rS# z$xSh82)fL6gK3f#*8&9{6%43iC*Flt8(Mzie!shR@Q_5ake|?A8&;H z&U)>laY3^@SUS3-(kw2mC<)odT~&U6P!ESf<+|LR(MCmZv|MtaH0alhMhC;rTTqin z?Q^E6*@c=tTrUj-hPgvy18ynY{z{*^YQ}q{^N%hH=+4x&U`SqEwMA=;Vym?W&3rN7>%#|2=(T^^}=2WOvB+ z2hETjloNIPgQMJI#umzJu2P=Pv?=$y?NEh0=8B*UbYM6~UZCD@lY3uPIczw9wwqPY zF!f%j-fvRfg*SVg;KG}WR3mc`F+xS$G|WA5>iv*~QdXcwVe;hYG*d?WdD3LBJ#EtD8KWlMms=8j@ZL%H-8*5%1i2gG(xBX_upHZz`y=7C zXU>=&m@;Lm5~HR}j_SV9D8CsFjVh`vau-)r=#KFI-X9LxMWf|aTNMcC#s1Mjz1$xT L>SO)BO4t7ZZ=1@N literal 0 HcmV?d00001 diff --git a/numbers.bas b/numbers.bas new file mode 100644 index 0000000..1aee208 --- /dev/null +++ b/numbers.bas @@ -0,0 +1,10 @@ +10 LET A=0 +15 LET B=0 +20 PRINT A;" "; +30 LET A=A+1 +32 LET B=B+1 +35 IF B>9 THEN GOTO 60 +40 IF A>1000 THEN END +50 GOTO 20 +60 PRINT +70 GOTO 15 diff --git a/system.h b/system.h new file mode 100644 index 0000000..b9aebea --- /dev/null +++ b/system.h @@ -0,0 +1,3 @@ +#if !defined(LINUX) +#define WINDOWS +#endif diff --git a/t_adc_bcd_01.65s b/t_adc_bcd_01.65s index 6266710..17a2233 100644 --- a/t_adc_bcd_01.65s +++ b/t_adc_bcd_01.65s @@ -1,99 +1,99 @@ -; ADC, test decimal mode. -; -; NV-BDIZC -; ??1110?? -; -; The results I got on Rockwell 6502 AP -; -; 00 + 00 and C=0 gives 00 and N=0 V=0 Z=1 C=0 (3A) -; 79 + 00 and C=1 gives 80 and N=1 V=1 Z=0 C=0 (F8) -; 24 + 56 and C=0 gives 80 and N=1 V=1 Z=0 C=0 (F8) -; 93 + 82 and C=0 gives 75 and N=0 V=1 Z=0 C=1 (79) -; 89 + 76 and C=0 gives 65 and N=0 V=0 Z=0 C=1 (39) -; 89 + 76 and C=1 gives 66 and N=0 V=0 Z=0 C=1 (39) -; 80 + f0 and C=0 gives d0 and N=1 V=1 Z=0 C=1 (F9) -; 80 + fa and C=0 gives e0 and N=1 V=0 Z=0 C=1 (B9) -; 2f + 4f and C=0 gives 74 and N=0 V=0 Z=0 C=0 (38) -; 6f + 00 and C=1 gives 76 and N=0 V=0 Z=0 C=0 (38) - -RES=$0300 - - *=$0200 - - SED - CLC - LDA #$00 - ADC #$00 - STA RES - PHP - PLA - STA RES+1 - SEC - LDA #$79 - ADC #$00 - STA RES+2 - PHP - PLA - STA RES+3 - CLC - LDA #$24 - ADC #$56 - STA RES+4 - PHP - PLA - STA RES+5 - CLC - LDA #$93 - ADC #$82 - STA RES+6 - PHP - PLA - STA RES+7 - CLC - LDA #$89 - ADC #$76 - STA RES+8 - PHP - PLA - STA RES+9 - SEC - LDA #$89 - ADC #$76 - STA RES+10 - PHP - PLA - STA RES+11 - CLC - LDA #$80 - ADC #$F0 - STA RES+12 - PHP - PLA - STA RES+13 - CLC - LDA #$80 - ADC #$FA - STA RES+14 - PHP - PLA - STA RES+15 - CLC - LDA #$2F - ADC #$4F - STA RES+16 - PHP - PLA - STA RES+17 - SEC - LDA #$6F - ADC #$00 - STA RES+18 - PHP - PLA - STA RES+19 - BRK - - *=$0300 - - .DS 20 +; ADC, test decimal mode. +; +; NV-BDIZC +; ??1110?? +; +; The results I got on Rockwell 6502 AP +; +; 00 + 00 and C=0 gives 00 and N=0 V=0 Z=1 C=0 (3A) +; 79 + 00 and C=1 gives 80 and N=1 V=1 Z=0 C=0 (F8) +; 24 + 56 and C=0 gives 80 and N=1 V=1 Z=0 C=0 (F8) +; 93 + 82 and C=0 gives 75 and N=0 V=1 Z=0 C=1 (79) +; 89 + 76 and C=0 gives 65 and N=0 V=0 Z=0 C=1 (39) +; 89 + 76 and C=1 gives 66 and N=0 V=0 Z=0 C=1 (39) +; 80 + f0 and C=0 gives d0 and N=1 V=1 Z=0 C=1 (F9) +; 80 + fa and C=0 gives e0 and N=1 V=0 Z=0 C=1 (B9) +; 2f + 4f and C=0 gives 74 and N=0 V=0 Z=0 C=0 (38) +; 6f + 00 and C=1 gives 76 and N=0 V=0 Z=0 C=0 (38) + +RES=$0300 + + *=$0200 + + SED + CLC + LDA #$00 + ADC #$00 + STA RES + PHP + PLA + STA RES+1 + SEC + LDA #$79 + ADC #$00 + STA RES+2 + PHP + PLA + STA RES+3 + CLC + LDA #$24 + ADC #$56 + STA RES+4 + PHP + PLA + STA RES+5 + CLC + LDA #$93 + ADC #$82 + STA RES+6 + PHP + PLA + STA RES+7 + CLC + LDA #$89 + ADC #$76 + STA RES+8 + PHP + PLA + STA RES+9 + SEC + LDA #$89 + ADC #$76 + STA RES+10 + PHP + PLA + STA RES+11 + CLC + LDA #$80 + ADC #$F0 + STA RES+12 + PHP + PLA + STA RES+13 + CLC + LDA #$80 + ADC #$FA + STA RES+14 + PHP + PLA + STA RES+15 + CLC + LDA #$2F + ADC #$4F + STA RES+16 + PHP + PLA + STA RES+17 + SEC + LDA #$6F + ADC #$00 + STA RES+18 + PHP + PLA + STA RES+19 + BRK + + *=$0300 + + .DS 20 \ No newline at end of file diff --git a/t_adc_bcd_01.dat b/t_adc_bcd_01.dat index 52375ca..bb09293 100644 --- a/t_adc_bcd_01.dat +++ b/t_adc_bcd_01.dat @@ -1,36 +1,36 @@ -; Test ADC BCD mode. -ORG -$0200 -$F8 $18 $A9 $00 $69 $00 $8D $00 -$03 $08 $68 $8D $01 $03 $38 $A9 -$79 $69 $00 $8D $02 $03 $08 $68 -$8D $03 $03 $18 $A9 $24 $69 $56 -$8D $04 $03 $08 $68 $8D $05 $03 -$18 $A9 $93 $69 $82 $8D $06 $03 -$08 $68 $8D $07 $03 $18 $A9 $89 -$69 $76 $8D $08 $03 $08 $68 $8D -$09 $03 $38 $A9 $89 $69 $76 $8D -$0A $03 $08 $68 $8D $0B $03 $18 -$A9 $80 $69 $F0 $8D $0C $03 $08 -$68 $8D $0D $03 $18 $A9 $80 $69 -$FA $8D $0E $03 $08 $68 $8D $0F -$03 $18 $A9 $2F $69 $4F $8D $10 -$03 $08 $68 $8D $11 $03 $38 $A9 -$6F $69 $00 $8D $12 $03 $08 $68 -$8D $13 $03 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 - +; Test ADC BCD mode. +ORG +$0200 +$F8 $18 $A9 $00 $69 $00 $8D $00 +$03 $08 $68 $8D $01 $03 $38 $A9 +$79 $69 $00 $8D $02 $03 $08 $68 +$8D $03 $03 $18 $A9 $24 $69 $56 +$8D $04 $03 $08 $68 $8D $05 $03 +$18 $A9 $93 $69 $82 $8D $06 $03 +$08 $68 $8D $07 $03 $18 $A9 $89 +$69 $76 $8D $08 $03 $08 $68 $8D +$09 $03 $38 $A9 $89 $69 $76 $8D +$0A $03 $08 $68 $8D $0B $03 $18 +$A9 $80 $69 $F0 $8D $0C $03 $08 +$68 $8D $0D $03 $18 $A9 $80 $69 +$FA $8D $0E $03 $08 $68 $8D $0F +$03 $18 $A9 $2F $69 $4F $8D $10 +$03 $08 $68 $8D $11 $03 $38 $A9 +$6F $69 $00 $8D $12 $03 $08 $68 +$8D $13 $03 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 + diff --git a/t_sbc_bcd_01.65s b/t_sbc_bcd_01.65s index e78c36c..c164095 100644 --- a/t_sbc_bcd_01.65s +++ b/t_sbc_bcd_01.65s @@ -1,85 +1,85 @@ -; SBC, test decimal mode. -; -; NV-BDIZC -; ??1110?? -; -; Expected results (I got on Rockwell 6502 AP): -; 00 - 00 and C=0 gives 99 and N=1 V=0 Z=0 C=0 (B8) -; 00 - 00 and C=1 gives 00 and N=0 V=0 Z=1 C=1 (3B) -; 00 - 01 and C=1 gives 99 and N=1 V=0 Z=0 C=0 (B8) -; 0a - 00 and C=1 gives 0a and N=0 V=0 Z=0 C=1 (39) -; 0b - 00 and C=0 gives 0a and N=0 V=0 Z=0 C=1 (39) -; 9a - 00 and C=1 gives 9a and N=1 V=0 Z=0 C=1 (B9) -; 9b - 00 and C=0 gives 9a and N=1 V=0 Z=0 C=1 (B9) -; - - *=$0200 - - SED - CLC - LDA #$00 - SBC #$00 - STA SBT1A - PHP - PLA - STA SBT1F - SEC - LDA #$00 - SBC #$00 - STA SBT2A - PHP - PLA - STA SBT2F - SEC - LDA #$00 - SBC #$01 - STA SBT3A - PHP - PLA - STA SBT3F - SEC - LDA #$0A - SBC #$00 - STA SBT4A - PHP - PLA - STA SBT4F - CLC - LDA #$0B - SBC #$00 - STA SBT5A - PHP - PLA - STA SBT5F - SEC - LDA #$9A - SBC #$00 - STA SBT6A - PHP - PLA - STA SBT6F - CLC - LDA #$9B - SBC #$00 - STA SBT7A - PHP - PLA - STA SBT7F - BRK - - *=$0300 - -SBT1A: .DB 0 -SBT1F: .DB 0 -SBT2A: .DB 0 -SBT2F: .DB 0 -SBT3A: .DB 0 -SBT3F: .DB 0 -SBT4A: .DB 0 -SBT4F: .DB 0 -SBT5A: .DB 0 -SBT5F: .DB 0 -SBT6A: .DB 0 -SBT6F: .DB 0 -SBT7A: .DB 0 +; SBC, test decimal mode. +; +; NV-BDIZC +; ??1110?? +; +; Expected results (I got on Rockwell 6502 AP): +; 00 - 00 and C=0 gives 99 and N=1 V=0 Z=0 C=0 (B8) +; 00 - 00 and C=1 gives 00 and N=0 V=0 Z=1 C=1 (3B) +; 00 - 01 and C=1 gives 99 and N=1 V=0 Z=0 C=0 (B8) +; 0a - 00 and C=1 gives 0a and N=0 V=0 Z=0 C=1 (39) +; 0b - 00 and C=0 gives 0a and N=0 V=0 Z=0 C=1 (39) +; 9a - 00 and C=1 gives 9a and N=1 V=0 Z=0 C=1 (B9) +; 9b - 00 and C=0 gives 9a and N=1 V=0 Z=0 C=1 (B9) +; + + *=$0200 + + SED + CLC + LDA #$00 + SBC #$00 + STA SBT1A + PHP + PLA + STA SBT1F + SEC + LDA #$00 + SBC #$00 + STA SBT2A + PHP + PLA + STA SBT2F + SEC + LDA #$00 + SBC #$01 + STA SBT3A + PHP + PLA + STA SBT3F + SEC + LDA #$0A + SBC #$00 + STA SBT4A + PHP + PLA + STA SBT4F + CLC + LDA #$0B + SBC #$00 + STA SBT5A + PHP + PLA + STA SBT5F + SEC + LDA #$9A + SBC #$00 + STA SBT6A + PHP + PLA + STA SBT6F + CLC + LDA #$9B + SBC #$00 + STA SBT7A + PHP + PLA + STA SBT7F + BRK + + *=$0300 + +SBT1A: .DB 0 +SBT1F: .DB 0 +SBT2A: .DB 0 +SBT2F: .DB 0 +SBT3A: .DB 0 +SBT3F: .DB 0 +SBT4A: .DB 0 +SBT4F: .DB 0 +SBT5A: .DB 0 +SBT5F: .DB 0 +SBT6A: .DB 0 +SBT6F: .DB 0 +SBT7A: .DB 0 SBT7F: .DB 0 \ No newline at end of file diff --git a/t_sbc_bcd_01.dat b/t_sbc_bcd_01.dat index 941c928..5ab2019 100644 --- a/t_sbc_bcd_01.dat +++ b/t_sbc_bcd_01.dat @@ -1,36 +1,36 @@ -; Test BCD mode. -ORG -$0200 -$F8 $18 $A9 $00 $E9 $00 $8D $00 -$03 $08 $68 $8D $01 $03 $38 $A9 -$00 $E9 $00 $8D $02 $03 $08 $68 -$8D $03 $03 $38 $A9 $00 $E9 $01 -$8D $04 $03 $08 $68 $8D $05 $03 -$38 $A9 $0A $E9 $00 $8D $06 $03 -$08 $68 $8D $07 $03 $18 $A9 $0B -$E9 $00 $8D $08 $03 $08 $68 $8D -$09 $03 $38 $A9 $9A $E9 $00 $8D -$0A $03 $08 $68 $8D $0B $03 $18 -$A9 $9B $E9 $00 $8D $0C $03 $08 -$68 $8D $0D $03 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 - +; Test BCD mode. +ORG +$0200 +$F8 $18 $A9 $00 $E9 $00 $8D $00 +$03 $08 $68 $8D $01 $03 $38 $A9 +$00 $E9 $00 $8D $02 $03 $08 $68 +$8D $03 $03 $38 $A9 $00 $E9 $01 +$8D $04 $03 $08 $68 $8D $05 $03 +$38 $A9 $0A $E9 $00 $8D $06 $03 +$08 $68 $8D $07 $03 $18 $A9 $0B +$E9 $00 $8D $08 $03 $08 $68 $8D +$09 $03 $38 $A9 $9A $E9 $00 $8D +$0A $03 $08 $68 $8D $0B $03 $18 +$A9 $9B $E9 $00 $8D $0C $03 $08 +$68 $8D $0D $03 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 + diff --git a/tall.bin b/tall.bin new file mode 100644 index 0000000000000000000000000000000000000000..1a307cf9bab753276952d51b6500c5fbb70e3861 GIT binary patch literal 65536 zcmeIz{clrM7zglkPP?slY|swS`GeYy@v=p*+h9WCOV@1*IK~*ehiz*RhDUYDrl_BVqDiu_tW;l6ef;Opgr!`Yg zm8wnl$bRCogZiv~D^?hUx=1QnLa<5{zmE>YTOaA z&Ed#fvyD{M*lgp?IYu(^!5rhA#qYkHOdMRCsyd|Wqe)My>a!uwAQPjtBF#kB)i&8m z*Yl^SdCXY8$|n7y00!b;5d7WrB$QeGWDD*aR^19Y>jvJ%U@bA4+obo2$~ z<#f05aayPfxUx`OMz-OA7D0Ttl%wyM&7_jviOKK@h%Px^Ilj|y_CRdt-E zRK4z9;pMmZ_!Ie&F&Wedb<`#6b=^SSa;dJD(J>X{^qT78G^D!qn1G*GHC5}$Oc~M% zP1GU7x^AZRvPIXebeD<G7xAdD63J{`$QN#Jkz`Sti>!yZKE0!mOEDS0po)ZS6)Gvtx#9plre9v$~9z*^@HU*xT6qQm>V7-iPC?oWoY^Nb&kd+>q7I4Vm}6pZ^x%GHYk)8CA_`y_(Ny!Rw6w&AFT!o}%+=5vNP4 zhSSnl8UIU1ui971FJt;ecTu(M)^$%u)4BWPwc%^@z1&Jnf0cfa+jRW~jdX3D+9rcm zFkS5IvAA#$rY}~`xrhlh$mxtqaJp09xqA5s1@*m)$q%Vg22WIGMGZ6fv0z5mDV7fM ztlK%p>4lkMW4mm!n`+LSW!%Y<;o)!%`;PI9FlNbSyVu9 zBIjCj(_|Ja*DSq|qSyQeZ!QtSf4kz7T=y0;=D<_;R z-d<!fB5)xu-Ds8hxaXYXLDTt%5|z0< z&|_^)8_rtB^jc9yiRjMC%W-$qjP6^0InF_N;<(|q#QMQuU zhJ3;dCt=2PLM4UustpH9sdXiFtkjtyt07(HWR(3o#Vdb$Hc0>D-+DH5`enchq|2S| z^674BlI8`|GSf4i;LJksdfF>8t}9-_SSq*QywU$fus#GJ009U<00Izz00bZa0SG_< z0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb z2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$## zAOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;| zfB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U< p00Izz00bZa0SG_<0uX=z1Rwwb2tWV=|D{0azntvJUMP01 + .byte LBL027 + .byte JUMP02 + .byte JUMP03 + .byte JUMP04 + .byte JUMP05 + + ; NOTE: The original comment below is obsolete now, since I found the jump + ; addresses locations and put them in this table. Now assembler will + ; take care of the reallocation. + ; START OF ORIGINAL COMMENT + ; This appears to be a table of + ; execution addresses to jump to ML routines + ; that handle the the IL instructions. + ; You cannot add code to or relocate this program + ; without updating these + ; END OF ORIGINAL COMMENT + + ;.byte $9F,$17, $42,$1B, $3F,$1B, $7A,$17, $FC,$18, $95,$17, $9F,$17, $9F,$17 + .byte LBL067 + .byte LBL132 + .byte JUMP06 + .byte JUMP07 + .byte LBL035 + .byte LBL097 + .byte LBL067 + .byte LBL067 + + ;.byte $BD,$1A, $C1,$1A, $8A,$1A, $9B,$1A, $E9,$1A, $61,$17, $51,$17, $41,$1A + .byte JUMP08 + .byte JUMP09 + .byte JUMP10 + .byte JUMP11 + .byte JUMP12 + .byte JUMP13 + .byte JUMP14 + .byte LBL071 + + ;.byte $52,$1A, $4F,$1A, $62,$1A, $E7,$19, $CD,$16, $06,$17, $9F,$17, $15,$18 + .byte JUMP15 + .byte JUMP16 + .byte JUMP17 + .byte JUMP18 + .byte JUMP19 + .byte JUMP20 + .byte LBL067 + .byte JUMP21 + + ;.byte $A7,$17, $B7,$16, $BF,$16, $83,$18, $A1,$16, $9F,$17, $9F,$17, $A8,$18 + .byte JUMP22 + .byte JUMP23 + .byte LBL047 + .byte LBL081 + .byte LBL013 + .byte LBL067 + .byte LBL067 + .byte JUMP24 + + ;.byte $4F,$1B, $4D,$1B, $07,$19, $AA,$14, $37,$17, $BD,$14, $1B,$1B, $B1,$1A + .byte JUMP25 + .byte JUMP26 + .byte JUMP27 + .byte MEM_T2 + .byte JUMP28 + .byte WARM_S + .byte JUMP29 + .byte JUMP30 + + .byte $20,$41, $54,$20 ; No idea ???? + + .byte $80 ; No idea + +LBL002: .byte ILTBL ;$1B ; $1B - hi byte of IL address + +; +;Begin Cold Start +; +; +; +; Load start of free ram ($1C00) into locations $0020 and $0022 +; The memory between $1000 and $1Bff (3 kB) is free for assembler programs +; that can be loaded and used simultaneously with TB. +; $1C00 to the end of writable memory is the BASIC memory space. +; +COLD_S: lda #$00 ; Load accumulator with lo byte of lower and upper prg memory limits + sta $20 ; Store in $20 + sta $22 ; Store in $22 + lda #$1C ; Load accumulator with hi byte of lower and upper prg memory limits + sta $21 ; Store in $21 + sta $23 ; Store in $23 + ; NOTE: $22,$23 vector will be updated by routine below to be the upper RAM limit for TB. +; +; +; Begin test for free ram +; As a result, memory locations $20,$21 will contain lo,hi byte order address of lower RAM boundary +; and $22,$23 upper RAM boundary respectively. +; + + ldy #$01 ; Load register Y with $01 +MEM_T: lda (C_22),Y ; Load accumulator With the contents of a byte of memory + tax ; Save it to X + eor #$FF ; Next 4 instuctions test to see if this memeory location + sta (C_22),Y ; is ram by trying to write something new to it - new value + cmp (C_22),Y ; gets created by XORing the old value with $FF - store the + php ; result of the test on the stack to look at later + txa ; Retrieve the old memory value + sta (C_22),Y ; Put it back where it came from + inc $22 ; Increment $22 (for next memory location) + bne SKP_PI ; Goto $14A6 if we don't need to increment page + inc $23 ; Increment $23 (for next memory page) +SKP_PI: plp ; Now look at the result of the memory test + beq MEM_T ; Go test the next mempry location if the last one was ram + dey ; If last memory location did not test as ram, decrement Y (should be $00 now) +MEM_T2: cld ; Make sure we're not in decimal mode + lda $20 ; Load up the low-order by of the start of free ram + adc SSS ; Add to the spare stack size + sta $24 ; Store the result in $0024 + tya ; Retrieve Y + adc $21 ; And add it to the high order byte of the start of free ram (this does not look right) + sta $25 ; Store the result in $0025 + tya ; Retrieve Y again + sta (C_20),Y ; Store A in the first byte of program memory + iny ; Increment Y + sta (C_20),Y ; Store A in the second byte of program memory +; +;Begin Warm Start; +; +WARM_S: lda $22 + sta $C6 + sta $26 + lda $23 + sta $C7 + sta $27 + jsr LBL001 ; Go print CR, LF and pad charachters +LBL014: lda LBL002 + sta $2A + lda LBL003 + sta $2B + lda #$80 + sta $C1 + lda #$30 + sta $C0 + ldx #$00 + stx $BE + stx $C2 + dex + txs +LBL006: cld + jsr LBL004 ; Go read a byte from the TBIL table + jsr LBL005 + jmp LBL006 +; +; +; + .byte $83 ; No idea about this + .byte $65 ; No idea about this +; +; +; Routine to service the TBIL Instructions +; +LBL005: cmp #$30 ; + bcs LBL011 ; If it's $30 or higher, it's a Branch or Jump - go handle it + cmp #$08 ; + bcc LBL007 ; If it's less than $08 it's a stack exchange - go handle it + asl ; Multiply the OP code by 2 + tax ; Transfer it to X +LBL022: lda SR_V_H,X ; Get the hi byte of the OP Code handling routine + pha ; and save it on the stack + lda SR_V_L,X ; Get the lo byte + pha ; and save it on the stack + php ; save the processor status too + rti ; now go execute the OP Code handling routine +; +; +; Routine to handle the stack exchange +; +LBL007: adc $C1 + tax + lda (C_C1),Y + pha + lda $00,X + sta (C_C1),Y + pla + sta $00,X + rts +; +; +; +LBL015: jsr LBL001 ; Go print CR, LF and pad charachters + lda #$21 ; Load an ASCII DC2 + jsr OUT_V ; Go print it + lda $2A ; Load the current TBIL pointer (lo) + sec ; Set the carry flag + sbc LBL002 ; Subtract the TBIL table origin (lo) + tax ; Move the difference to X + lda $2B ; Load the current TBIL pointer (hi) + sbc LBL003 ; Subtract the TBIL table origin (hi) + jsr LBL010 + lda $BE + beq LBL012 + lda #$7E + sta $2A + lda #$20 + sta $2B + jsr LBL013 + ldx $28 + lda $29 + jsr LBL010 +LBL012: lda #$07 ; ASCII Bell + jsr OUT_V ; Go ring Bell + jsr LBL001 ; Go print CR, LF and pad charachters +LBL060: lda $26 + sta $C6 + lda $27 + sta $C7 + jmp LBL014 +; +; +; +LBL115: ldx #$7C +LBL048: cpx $C1 +LBL019: bcc LBL015 + ldx $C1 + inc $C1 + inc $C1 + clc + rts +; +; +; +JUMP01: dec $BD +LBL027: lda $BD + beq LBL015 +LBL017: lda $BC + sta $2A + lda $BD + sta $2B + rts +; +; Branch handling routine +; +LBL011: cmp #$40 ; + bcs LBL016 ; If it's not a Jump, go to branch handler + pha + jsr LBL004 ; Go read a byte from the TBIL table + adc LBL002 + sta $BC + pla + pha + and #$07 + adc LBL003 + sta $BD + pla + and #$08 + bne LBL017 + lda $BC + ldx $2A + sta $2A + stx $BC + lda $BD + ldx $2B + sta $2B + stx $BD +LBL126: lda $C6 + sbc #$01 + sta $C6 + bcs LBL018 + dec $C7 +LBL018: cmp $24 + lda $C7 + sbc $25 + bcc LBL019 + lda $BC + sta (C_C6),Y + iny + lda $BD + sta (C_C6),Y + rts +; +;Branch handler +; +LBL016: pha + lsr + lsr + lsr + lsr + and #$0E + tax + pla + cmp #$60 + and #$1F + bcs LBL020 + ora #$E0 +LBL020: clc + beq LBL021 + adc $2A + sta $BC + tya + adc $2B +LBL021: sta $BD + JMP LBL022 +; +; +; +JUMP02: lda $2C + sta $B8 + lda $2D + sta $B9 +LBL025: jsr LBL023 + jsr LBL024 + eor (C_2A),Y + tax + jsr LBL004 ; Go read a byte from the TBIL table + txa + beq LBL025 + asl + beq LBL026 + lda $B8 + sta $2C + lda $B9 + sta $2D +LBL028: jmp LBL027 +JUMP05: jsr LBL023 + cmp #$0D + bne LBL028 +LBL026: rts +; +; +; +JUMP03: jsr LBL023 + cmp #$5B + bcs LBL028 + cmp #$41 + bcc LBL028 + asl + jsr LBL029 +LBL024: ldy #$00 + lda (C_2C),Y + inc $2C + bne LBL030 + inc $2D +LBL030: cmp #$0D + clc + rts +; +; + +LBL031: jsr LBL024 +LBL023: lda (C_2C),Y + cmp #$20 + beq LBL031 + cmp #$3A + clc + bpl LBL032 + cmp #$30 +LBL032: rts +; +; +; +JUMP04: jsr LBL023 + bcc LBL028 + sty $BC + sty $BD +LBL033: lda $BC + ldx $BD + asl $BC + rol $BD + asl $BC + rol $BD + clc + adc $BC + sta $BC + txa + adc $BD + asl $BC + rol + sta $BD + jsr LBL024 + and #$0F + adc $BC + sta $BC + tya + adc $BD + sta $BD + jsr LBL023 + bcs LBL033 + jmp LBL034 +LBL061: jsr LBL035 + lda $BC + ora $BD + beq LBL036 +LBL065: lda $20 + sta $2C + lda $21 + sta $2D +LBL040: jsr LBL037 + beq LBL038 + lda $28 + cmp $BC + lda $29 + sbc $BD + bcs LBL038 +LBL039: jsr LBL024 + bne LBL039 + jmp LBL040 +LBL038: lda $28 + eor $BC + bne LBL041 + lda $29 + eor $BD +LBL041: rts +; +; +; +LBL043: jsr LBL042 +LBL013: jsr LBL004 ; Entry point for TBIL PC (print literal) - Go read a byte from the TBIL table + bpl LBL043 ; +LBL042: inc $BF + bmi LBL044 + jmp OUT_V ; Go print it +LBL044: dec $BF +LBL045: rts +; +; +; +LBL046: cmp #$22 + beq LBL045 + jsr LBL042 +JUMP23: jsr LBL024 + bne LBL046 +LBL036: jmp LBL015 +LBL047: lda #$20 + jsr LBL042 + lda $BF + and #$87 + bmi LBL045 + bne LBL047 + rts +; +; +; +JUMP19: ldx #$7B + jsr LBL048 + inc $C1 + inc $C1 + inc $C1 + sec + lda $03,X + sbc $00,X + sta $00,X + lda $04,X + sbc $01,X + bvc LBL052 + eor #$80 + ora #$01 +LBL052: bmi LBL053 + bne LBL054 + ora $00,X + beq LBL049 +LBL054: lsr $02,X +LBL049: lsr $02,X +LBL053: lsr $02,X + bcc LBL050 +LBL004: ldy #$00 ; Read a byte from the TBIL Table + lda (C_2A),Y ; + inc $2A ; Increment TBIL Table pointer as required + bne LBL051 ; + inc $2B ; +LBL051: ora #$00 ; Check for $00 and set the 'Z' flag acordingly +LBL050: rts ; Return +; +; +; +JUMP20: lda $BE + beq LBL055 +LBL056: jsr LBL024 + bne LBL056 + jsr LBL037 + beq LBL057 +LBL062: jsr LBL058 + jsr BREAK + bcs LBL059 + lda $C4 + sta $2A + lda $C5 + sta $2B + rts +; +; +; +LBL059: lda LBL002 + sta $2A + lda LBL003 + sta $2B +LBL057: jmp LBL015 +LBL055: sta $BF + jmp LBL060 +JUMP28: lda $20 + sta $2C + lda $21 + sta $2D + jsr LBL037 + beq LBL057 + lda $2A + sta $C4 + lda $2B + sta $C5 +LBL058: lda #$01 + sta $BE + rts +; +; +; +JUMP14: jsr LBL061 + beq LBL062 +LBL066: lda $BC + sta $28 + lda $BD + sta $29 + jmp LBL015 +JUMP13: jsr LBL063 + jsr LBL064 + jsr LBL065 + bne LBL066 + rts +; +; +; +LBL037: jsr LBL024 + sta $28 + jsr LBL024 + sta $29 + ora $28 + rts +; +; +; +JUMP07: jsr LBL035 + jsr LBL034 +LBL034: lda $BD +LBL131: jsr LBL029 + lda $BC +LBL029: ldx $C1 + dex + sta $00,X + stx $C1 + cpx $C0 + bne LBL067 +LBL068: jmp LBL015 +LBL097: ldx $C1 + cpx #$80 + bpl LBL068 + lda $00,X + inc $C1 +LBL067: rts +; +; +; +LBL010: sta $BD + stx $BC + jmp LBL069 +JUMP22: ldx $C1 ; entry point to TBIL PN (print number) + lda $01,X + bpl LBL070 + jsr LBL071 + lda #$2D + jsr LBL042 +LBL070: jsr LBL035 +LBL069: lda #$1F + sta $B8 + sta $BA + lda #$2A + sta $B9 + sta $BB + ldx $BC + ldy $BD + sec +LBL072: inc $B8 + txa + sbc #$10 + tax + tya + sbc #$27 + tay + bcs LBL072 +LBL073: dec $B9 + txa + adc #$E8 + tax + tya + adc #$03 + tay + bcc LBL073 + txa +LBL074: sec + inc $BA + sbc #$64 + bcs LBL074 + dey + bpl LBL074 +LBL075: dec $BB + adc #$0A + bcc LBL075 + ora #$30 + sta $BC + lda #$20 + sta $BD + ldx #$FB +LBL199: stx $C3 + lda $BD,X + ora $BD + cmp #$20 + beq LBL076 + ldy #$30 + sty $BD + ora $BD + jsr LBL042 +LBL076: ldx $C3 + inx + bne LBL199 + rts +; +; +; +JUMP21: lda $2D + pha + lda $2C + pha + lda $20 + sta $2C + lda $21 + sta $2D + lda $24 + ldx $25 + jsr LBL077 + beq LBL078 + jsr LBL077 +LBL078: lda $2C + sec + sbc $B6 + lda $2D + sbc $B7 + bcs LBL079 + jsr LBL037 + beq LBL079 + ldx $28 + lda $29 + jsr LBL010 + lda #$20 +LBL080: jsr LBL042 + jsr BREAK + bcs LBL079 + jsr LBL024 + bne LBL080 + jsr LBL081 + jmp LBL078 +LBL077: sta $B6 + inc $B6 + bne LBL082 + inx +LBL082: stx $B7 + ldy $C1 + cpy #$80 + beq LBL083 + jsr LBL061 +LBL099: lda $2C + ldx $2D + sec + sbc #$02 + bcs LBL084 + dex +LBL084: sta $2C + jmp LBL085 +LBL079: pla + sta $2C + pla + sta $2D +LBL083: rts +LBL081: lda $BF + bmi LBL083 +; +; +; Routine to handle CR, LF and pad characters in the ouput +; +LBL001: lda #$0D ; Load up a CR + jsr OUT_V ; Go print it + lda PCC ; Load the pad character code + and #$7F ; Test to see - + sta $BF ; how many pad charachters to print + beq LBL086 ; Skip if 0 +LBL088: jsr LBL087 ; Go print pad charcter + dec $BF ; One less + bne LBL088 ; Loop until 0 +LBL086: lda #$0A ; Load up a LF + jmp LBL089 ; Go print it +; +; +; +LBL092: ldy TMC +LBL091: sty $BF + bcs LBL090 +JUMP24: lda #$30 ; Entry pont for TBIL GL (get input line) + sta $2C + sta $C0 + sty $2D + jsr LBL034 +LBL090: eor $80 + sta $80 + jsr IN_V + ldy #$00 + ldx $C0 + and #$7F + beq LBL090 + cmp #$7F + beq LBL090 + cmp #$13 + beq LBL091 + cmp #$0A + beq LBL092 + cmp LSC + beq LBL093 + cmp BSC + bne LBL094 + cpx #$30 + bne LBL095 +LBL093: ldx $2C + sty $BF + lda #$0D +LBL094: cpx $C1 + bmi LBL096 + lda #$07 + jsr LBL042 + jmp LBL090 +LBL096: sta $00,X + inx + inx +LBL095: dex + stx $C0 + cmp #$0D + bne LBL090 + jsr LBL081 +LBL035: jsr LBL097 + sta $BC + jsr LBL097 + sta $BD + rts +; +; +; +JUMP27: jsr LBL098 + jsr LBL061 + php + jsr LBL099 + sta $B8 + stx $B9 + lda $BC + sta $B6 + lda $BD + sta $B7 + ldx #$00 + plp + bne LBL100 + jsr LBL037 + dex + dex +LBL101: dex + jsr LBL024 + bne LBL101 +LBL100: sty $28 + sty $29 + jsr LBL098 + lda #$0D + cmp (C_2C),Y + beq LBL102 + inx + inx + inx +LBL103: inx + iny + cmp (C_2C),Y + bne LBL103 + lda $B6 + sta $28 + lda $B7 + sta $29 +LBL102: lda $B8 + sta $BC + lda $B9 + sta $BD + clc + ldy #$00 + txa + beq LBL104 + bpl LBL105 + adc $2E + sta $B8 + lda $2F + sbc #$00 + sta $B9 +LBL109: lda (C_2E),Y + sta (C_B8),Y + ldx $2E + cpx $24 + bne LBL106 + lda $2F + cmp $25 + beq LBL107 +LBL106: inx + stx $2E + bne LBL108 + inc $2F +LBL108: inc $B8 + bne LBL109 + inc $B9 + bne LBL109 +LBL105: adc $24 + sta $B8 + sta $2E + tya + adc $25 + sta $B9 + sta $2F + lda $2E + sbc $C6 + lda $2F + sbc $C7 + bcc LBL110 + dec $2A + jmp LBL015 +LBL110: lda (C_24),Y + sta (C_2E),Y + ldx $24 + bne LBL111 + dec $25 +LBL111: dec $24 + ldx $2E + bne LBL112 + dec $2F +LBL112: dex + stx $2E + cpx $BC + bne LBL110 + ldx $2F + cpx $BD + bne LBL110 +LBL107: lda $B8 + sta $24 + lda $B9 + sta $25 +LBL104: lda $28 + ora $29 + beq LBL113 + lda $28 + sta (C_BC),Y + iny + lda $29 + sta (C_BC),Y +LBL114: iny + sty $B6 + jsr LBL024 + php + ldy $B6 + sta (C_BC),Y + plp + bne LBL114 +LBL113: jmp LBL014 +JUMP18: jsr LBL115 + lda $03,X + and #$80 + beq LBL116 + lda #$FF +LBL116: sta $BC + sta $BD + pha + adc $02,X + sta $02,X + pla + pha + adc $03,X + sta $03,X + pla + eor $01,X + sta $BB + bpl LBL117 + jsr LBL118 +LBL117: ldy #$11 + lda $00,X + ora $01,X + bne LBL119 + jmp LBL015 +LBL119: sec + lda $BC + sbc $00,X + pha + lda $BD + sbc $01,X + pha + eor $BD + bmi LBL120 + pla + sta $BD + pla + sta $BC + sec + jmp LBL121 +LBL120: pla + pla + clc +LBL121: rol $02,X + rol $03,X + rol $BC + rol $BD + dey + bne LBL119 + lda $BB + bpl LBL122 +LBL071: ldx $C1 +LBL118: sec + tya + sbc $00,X + sta $00,X + tya + sbc $01,X + sta $01,X +LBL122: rts +; +; +; +JUMP16: jsr LBL071 +JUMP15: jsr LBL115 + lda $00,X + adc $02,X + sta $02,X + lda $01,X + adc $03,X + sta $03,X + rts +; +; +; +JUMP17: jsr LBL115 + ldy #$10 + lda $02,X + sta $BC + lda $03,X + sta $BD +LBL124: asl $02,X + rol $03,X + rol $BC + rol $BD + bcc LBL123 + clc + lda $02,X + adc $00,X + sta $02,X + lda $03,X + adc $01,X + sta $03,X +LBL123: dey + bne LBL124 + rts +; +; +; +JUMP10: jsr LBL097 + tax + lda $00,X + ldy $01,X + dec $C1 + ldx $C1 + sty $00,X + jmp LBL029 +JUMP11: ldx #$7D + jsr LBL048 + lda $01,X + pha + lda $00,X + pha + jsr LBL097 + tax + pla + sta $00,X + pla + sta $01,X + rts +JUMP30: jsr LBL063 + lda $BC + sta $2A + lda $BD + sta $2B + rts +; +; +; +JUMP08: ldx #$2C ; Entry point to Save Basic Pointer SB + bne LBL125 +JUMP09: ldx #$2E +LBL125: lda $00,X + cmp #$80 + bcs LBL098 + lda $01,X + bne LBL098 + lda $2C + sta $2E + lda $2D + sta $2F + rts +; +; +; +LBL098: lda $2C + ldy $2E + sty $2C + sta $2E + lda $2D + ldy $2F + sty $2D + sta $2F + ldy #$00 + rts +; +; +; +JUMP12: lda $28 + sta $BC + lda $29 + sta $BD + jsr LBL126 + lda $C6 + sta $26 + lda $C7 +LBL064: sta $27 +LBL129: rts +; +; +; +LBL063: lda (C_C6),Y + sta $BC + jsr LBL127 + lda (C_C6),Y + sta $BD +LBL127: inc $C6 + bne LBL128 + inc $C7 +LBL128: lda $22 + cmp $C6 + lda $23 + sbc $C7 + bcs LBL129 + jmp LBL015 +JUMP29: jsr LBL130 + sta $BC + tya + jmp LBL131 +LBL130: jsr LBL035 + lda $BC + sta $B6 + jsr LBL035 + lda $BD + sta $B7 + ldy $BC + jsr LBL035 + ldx $B7 + lda $B6 + clc + jmp (C_00BC) +JUMP06: jsr LBL132 +LBL132: jsr LBL004 ; Go read a byte from the TBIL Table + jmp LBL029 +LBL085: stx $2D + cpx #$00 + rts +; +; +; +JUMP26: ldy #$02 +JUMP25: sty $BC + ldy #$29 + sty $BD + ldy #$00 + lda (C_BC),Y + cmp #$08 + bne LBL133 + jmp LBL117 +LBL133: rts +; +; +; Subroutine to decide which pad character to print +; +LBL089: jsr OUT_V ; Entry point with a charater to print first +LBL087: lda #$FF ; Normal entry point - Set pad to $FF + bit PCC ; Check if the pad flag is on + bmi LBL134 ; Skip it if not + lda #$00 ; set pad to $00 +LBL134: jmp OUT_V ; Go print it + + +; +; TBIL Tables +; +ILTBL: .byte $24, $3A, $91, $27, $10, $E1, $59, $C5, $2A, $56, $10, $11, $2C, $8B, $4C + .byte $45, $D4, $A0, $80, $BD, $30, $BC, $E0, $13, $1D, $94, $47, $CF, $88, $54 + .byte $CF, $30, $BC, $E0, $10, $11, $16, $80, $53, $55, $C2, $30, $BC, $E0, $14 + .byte $16, $90, $50, $D2, $83, $49, $4E, $D4, $E5, $71, $88, $BB, $E1, $1D, $8F + .byte $A2, $21, $58, $6F, $83, $AC, $22, $55, $83, $BA, $24, $93, $E0, $23, $1D + .byte $30, $BC, $20, $48, $91, $49, $C6, $30, $BC, $31, $34, $30, $BC, $84, $54 + .byte $48, $45, $CE, $1C, $1D, $38, $0D, $9A, $49, $4E, $50, $55, $D4, $A0, $10 + .byte $E7, $24, $3F, $20, $91, $27, $E1, $59, $81, $AC, $30, $BC, $13, $11, $82 + .byte $AC, $4D, $E0, $1D, $89, $52, $45, $54, $55, $52, $CE, $E0, $15, $1D, $85 + .byte $45, $4E, $C4, $E0, $2D, $98, $4C, $49, $53, $D4, $EC, $24, $00, $00, $00 + .byte $00, $0A, $80, $1F, $24, $93, $23, $1D, $30, $BC, $E1, $50, $80, $AC, $59 + .byte $85, $52, $55, $CE, $38, $0A, $86, $43, $4C, $45, $41, $D2, $2B, $84, $52 + .byte $45, $CD, $1D, $A0, $80, $BD, $38, $14, $85, $AD, $30, $D3, $17, $64, $81 + .byte $AB, $30, $D3, $85, $AB, $30, $D3, $18, $5A, $85, $AD, $30, $D3, $19, $54 + .byte $2F, $30, $E2, $85, $AA, $30, $E2, $1A, $5A, $85, $AF, $30, $E2, $1B, $54 + .byte $2F, $98, $52, $4E, $C4, $0A, $80, $80, $12, $0A, $09, $29, $1A, $0A, $1A + .byte $85, $18, $13, $09, $80, $12, $01, $0B, $31, $30, $61, $72, $0B, $04, $02 + .byte $03, $05, $03, $1B, $1A, $19, $0B, $09, $06, $0A, $00, $00, $1C, $17, $2F + .byte $8F, $55, $53, $D2, $80, $A8, $30, $BC, $31, $2A, $31, $2A, $80, $A9, $2E + .byte $2F, $A2, $12, $2F, $C1, $2F, $80, $A8, $30, $BC, $80, $A9, $2F, $83, $AC + .byte $38, $BC, $0B, $2F, $80, $A8, $52, $2F, $84, $BD, $09, $02, $2F, $8E, $BC + .byte $84, $BD, $09, $93, $2F, $84, $BE, $09, $05, $2F, $09, $91, $2F, $80, $BE + .byte $84, $BD, $09, $06, $2F, $84, $BC, $09, $95, $2F, $09, $04, $2F, $00, $00 + .byte $00 +; +; End of Tiny Basic + + +;.segment "MAIN" + + .org $0CF0 ; Address of main program + +; Code needs work below here, BIOS must be changed for MKHBC-8-R2 + +;FBLK: +; +; Set some symbols +; +;ACIARW = $1200 ; Base address of ACIA +;ACIAST = ACIARW+$01 ; ACIA status register +;ACIACM = ACIARW+$02 ; ACIA commnad register +;ACIACN = ACIARW+$03 ; ACIA control register + + +; +; Begin base system initialization +; +; jmp main ; no 6522 on MKHBC-8-R1 +;-------------------- +; sta ACIAST ; Do a soft reset on the ACIA +; lda #$0B ; Set it up for : +; sta ACIACM ; no echo, no parity, RTS low, No IRQ, DTR low +; lda #$1A ; and : +; sta ACIACN ; 2400, 8 bits, 1 stop bit, external Rx clock +;-------------------- + +main: + jsr CLRSC ; Go clear the screen + ldy #$00 ; Offset for welcome message and prompt + jsr SNDMSG ; Go print it +ST_LP: JSR RCCHR ; Go get a character from the console + cmp #$43 ; Check for 'C' + BNE IS_WRM ; If not branch to next check + jmp COLD_S ; Otherwise cold-start Tiny Basic +IS_WRM: cmp #$57 ; Check for 'W' + BNE PRMPT ; If not, branch to re-prompt them + jmp WARM_S ; Otherwise warm-start Tiny Basic +PRMPT: ldx #$2F ; Offset of prompt + jsr SNDMSG ; Go print the prompt + jmp ST_LP ; Go get the response + +;.segment "MESG" + + .org $0E00 ; Address of message area +MBLK: + +; +; The message block begins at $1E00 and is at most 256 bytes long. +; Messages terminate with an FF. +; + .byte "MKHBC-8-R2 TINY BASIC 6502 PORT" + .byte $0D, $0A ;, $0A + .byte "Version: 1.0.3, 2/20/2016" + .byte $0D, $0A ;, $0A + .byte "(NOTE: Use UPPER CASE.)" + .byte $0D, $0A ;, $0A + .byte "Boot ([C]old/[W]arm)? " + .byte $07, $FF + +;.segment "SUBR" + + .org $0F00 ;address of subroutine area + +SBLK: +; +; Begin BIOS subroutines +; + +; M.O.S. API defines. + +StrPtr = $E0 + +; Kernel jump table + +GetCh = $FFED +PutCh = $FFF0 +Gets = $FFF3 +Puts = $FFF6 + + +;SNDCHR = PutCh +;RCCHR = GetCh + + +; +; Clear the screen +; +ESC = $1b + +; 2-BYTE PEEK USR FUNCTION +; For TINY BASIC IL ASSEMBLER VERSION 0 + +TwoBytePeek: + + STX $C3 ;($C2=00) + LDA ($C2),Y ;GET MSB + PHA ;SAVE IT + INY + LDA ($C2),Y ;GET LSB + TAX + PLA + TAY ;Y=MSB + TXA + RTS + + +;ClrScrCode: + +; .BYTE ESC,"[2J",0 ;clear screen sequence (ANSI). + +;ClearScreen: + +; lda #ClrScrCode +; sta StrPtr+1 +; jsr Puts +; rts + +CLRSC: ldx #$19 ; Load X - we're going tp print 25 lines + lda #$0D ; CR + jsr SNDCHR ; Send a carriage retuen + lda #$0A ; LF +CSLP: jsr SNDCHR ; Send the line feed + dex ; One less to do + bne CSLP ; Go send another untill we're done + rts ; Return + +; +; Print a message. +; This sub expects the messsage offset from MBLK in X. +; +SNDMSG: lda MBLK,y ; Get a character from teh message block + cmp #$FF ; Look for end of message marker + beq EXSM ; Finish up if it is + jsr SNDCHR ; Otherwise send the character + iny ; Increment the pointer + jmp SNDMSG ; Go get next character +EXSM: rts ; Return + +; +; Get a character from the ACIA +; Runs into SNDCHR to provide echo +; +RCCHR: ;lda ACIAST ; Read the ACAI status to (for OMS-02) + ;and #$08 ; Check if there is character in the receiver (for OMS-02) + ;beq RCCHR ; Loop util we get one (for OMS-02) + ;lda ACIARW ; Load it into the accumulator (for OMS-02) + LDA $E000 ; Check if a character typed (for emulator) + BEQ RCCHR ; Loop until we get one (for emulator) + +;RCCHR: jsr GetCh +; jsr SNDCHR ; echo character to the console +; rts + +; +;Send a character to the ACIA +; +SNDCHR: sta $FE ; Save the character to be printed + cmp #$FF ; Check for a bunch of characters + BEQ EXSC ; that we don't want to print to + cmp #$00 ; the terminal and discard them to + BEQ EXSC ; clean up the output + cmp #$91 ; + BEQ EXSC ; + cmp #$93 ; + BEQ EXSC ; + cmp #$80 ; + BEQ EXSC ; + jmp SCLP ; VM6502 emulator, comment for MKHBC-8-R2 + jsr PutCh ; MKHBC-8-R2 + lda $fe + rts +SCLP: ;lda ACIAST ; Check ACIA Status (don't need for emulator) + ;and #$10 ; See if transmiter it busy (don't need for emulator) + ;beq SCLP ; Wait for it (don't need for emulator) + lda $FE ; Restore the character + ;sta ACIARW ; Transmit it (for OMS-02) + STA $E000 ; Transmit it (for emulator) +EXSC: rts ; Return + +; .org $1FFC ; Address of reset vector (for 6507 not required for emulator) +;RSVEC +; .byte $F0, $1C ; Reset vector + +; .org $3000 ; Address of last byte of EPROM +;EOROM: + +;--------------------------- END ---------------------------------------------------------------------- diff --git a/tb.dat b/tb.dat new file mode 100644 index 0000000..45d7737 --- /dev/null +++ b/tb.dat @@ -0,0 +1,398 @@ +ADDR +$0CF0 +; Program disassembly from $0400 to $1000 2/20/2016 +; Tiny Basic port for VM6502 emulator. +; Exec address: $0CF0 +ORG +$0400 +; Enable ROM and IO emulation. +ENROM +ENIO +; Set char IO address +IOADDR +$E000 +; Code/Data +$4C, $85, $04, $4C, $BD, $04, $4C, $2C +$0F, $4C, $31, $0F, $EA, $18, $60, $5F +$18, $80, $00, $20, $86, $C3, $90, $05 +$86, $C3, $91, $C2, $60, $B1, $C2, $A0 +$00, $60, $62, $05, $64, $05, $D8, $05 +$05, $06, $33, $06, $FD, $05, $9F, $07 +$42, $0B, $3F, $0B, $7A, $07, $FC, $08 +$95, $07, $9F, $07, $9F, $07, $BD, $0A +$C1, $0A, $8A, $0A, $9B, $0A, $E9, $0A +$61, $07, $51, $07, $41, $0A, $52, $0A +$4F, $0A, $62, $0A, $E7, $09, $CD, $06 +$06, $07, $9F, $07, $15, $08, $A7, $07 +$B7, $06, $BF, $06, $83, $08, $A1, $06 +$9F, $07, $9F, $07, $A8, $08, $4F, $0B +$4D, $0B, $07, $09, $AA, $04, $37, $07 +$BD, $04, $1B, $0B, $B1, $0A, $20, $41 +$54, $20, $80, $70, $0B, $A9, $00, $85 +$20, $85, $22, $A9, $1C, $85, $21, $85 +$23, $A0, $01, $B1, $22, $AA, $49, $FF +$91, $22, $D1, $22, $08, $8A, $91, $22 +$E6, $22, $D0, $02, $E6, $23, $28, $F0 +$EA, $88, $D8, $A5, $20, $6D, $13, $04 +$85, $24, $98, $65, $21, $85, $25, $98 +$91, $20, $C8, $91, $20, $A5, $22, $85 +$C6, $85, $26, $A5, $23, $85, $C7, $85 +$27, $20, $87, $08, $AD, $83, $04, $85 +$2A, $AD, $84, $04, $85, $2B, $A9, $80 +$85, $C1, $A9, $30, $85, $C0, $A2, $00 +$86, $BE, $86, $C2, $CA, $9A, $D8, $20 +$F9, $06, $20, $F2, $04, $4C, $E6, $04 +$83, $65, $C9, $30, $B0, $7B, $C9, $08 +$90, $0C, $0A, $AA, $BD, $1F, $04, $48 +$BD, $1E, $04, $48, $08, $40, $65, $C1 +$AA, $B1, $C1, $48, $B5, $00, $91, $C1 +$68, $95, $00, $60, $20, $87, $08, $A9 +$21, $20, $09, $04, $A5, $2A, $38, $ED +$83, $04, $AA, $A5, $2B, $ED, $84, $04 +$20, $A0, $07, $A5, $BE, $F0, $12, $A9 +$7E, $85, $2A, $A9, $20, $85, $2B, $20 +$A1, $06, $A6, $28, $A5, $29, $20, $A0 +$07, $A9, $07, $20, $09, $04, $20, $87 +$08, $A5, $26, $85, $C6, $A5, $27, $85 +$C7, $4C, $CC, $04, $A2, $7C, $E4, $C1 +$90, $BA, $A6, $C1, $E6, $C1, $E6, $C1 +$18, $60, $C6, $BD, $A5, $BD, $F0, $AC +$A5, $BC, $85, $2A, $A5, $BD, $85, $2B +$60, $C9, $40, $B0, $43, $48, $20, $F9 +$06, $6D, $83, $04, $85, $BC, $68, $48 +$29, $07, $6D, $84, $04, $85, $BD, $68 +$29, $08, $D0, $DC, $A5, $BC, $A6, $2A +$85, $2A, $86, $BC, $A5, $BD, $A6, $2B +$85, $2B, $86, $BD, $A5, $C6, $E9, $01 +$85, $C6, $B0, $02, $C6, $C7, $C5, $24 +$A5, $C7, $E5, $25, $90, $AA, $A5, $BC +$91, $C6, $C8, $A5, $BD, $91, $C6, $60 +$48, $4A, $4A, $4A, $4A, $29, $0E, $AA +$68, $C9, $60, $29, $1F, $B0, $02, $09 +$E0, $18, $F0, $07, $65, $2A, $85, $BC +$98, $65, $2B, $85, $BD, $4C, $FC, $04 +$A5, $2C, $85, $B8, $A5, $2D, $85, $B9 +$20, $25, $06, $20, $14, $06, $51, $2A +$AA, $20, $F9, $06, $8A, $F0, $F1, $0A +$F0, $12, $A5, $B8, $85, $2C, $A5, $B9 +$85, $2D, $4C, $64, $05, $20, $25, $06 +$C9, $0D, $D0, $F6, $60, $20, $25, $06 +$C9, $5B, $B0, $EE, $C9, $41, $90, $EA +$0A, $20, $87, $07, $A0, $00, $B1, $2C +$E6, $2C, $D0, $02, $E6, $2D, $C9, $0D +$18, $60, $20, $14, $06, $B1, $2C, $C9 +$20, $F0, $F7, $C9, $3A, $18, $10, $02 +$C9, $30, $60, $20, $25, $06, $90, $C2 +$84, $BC, $84, $BD, $A5, $BC, $A6, $BD +$06, $BC, $26, $BD, $06, $BC, $26, $BD +$18, $65, $BC, $85, $BC, $8A, $65, $BD +$06, $BC, $2A, $85, $BD, $20, $14, $06 +$29, $0F, $65, $BC, $85, $BC, $98, $65 +$BD, $85, $BD, $20, $25, $06, $B0, $D4 +$4C, $80, $07, $20, $FC, $08, $A5, $BC +$05, $BD, $F0, $48, $A5, $20, $85, $2C +$A5, $21, $85, $2D, $20, $6D, $07, $F0 +$12, $A5, $28, $C5, $BC, $A5, $29, $E5 +$BD, $B0, $08, $20, $14, $06, $D0, $FB +$4C, $7C, $06, $A5, $28, $45, $BC, $D0 +$04, $A5, $29, $45, $BD, $60, $20, $A6 +$06, $20, $F9, $06, $10, $F8, $E6, $BF +$30, $03, $4C, $09, $04, $C6, $BF, $60 +$C9, $22, $F0, $FB, $20, $A6, $06, $20 +$14, $06, $D0, $F4, $4C, $14, $05, $A9 +$20, $20, $A6, $06, $A5, $BF, $29, $87 +$30, $E5, $D0, $F3, $60, $A2, $7B, $20 +$56, $05, $E6, $C1, $E6, $C1, $E6, $C1 +$38, $B5, $03, $F5, $00, $95, $00, $B5 +$04, $F5, $01, $50, $04, $49, $80, $09 +$01, $30, $0A, $D0, $04, $15, $00, $F0 +$02, $56, $02, $56, $02, $56, $02, $90 +$0C, $A0, $00, $B1, $2A, $E6, $2A, $D0 +$02, $E6, $2B, $09, $00, $60, $A5, $BE +$F0, $28, $20, $14, $06, $D0, $FB, $20 +$6D, $07, $F0, $1B, $20, $4C, $07, $20 +$0C, $04, $B0, $09, $A5, $C4, $85, $2A +$A5, $C5, $85, $2B, $60, $AD, $83, $04 +$85, $2A, $AD, $84, $04, $85, $2B, $4C +$14, $05, $85, $BF, $4C, $49, $05, $A5 +$20, $85, $2C, $A5, $21, $85, $2D, $20 +$6D, $07, $F0, $EB, $A5, $2A, $85, $C4 +$A5, $2B, $85, $C5, $A9, $01, $85, $BE +$60, $20, $6B, $06, $F0, $BE, $A5, $BC +$85, $28, $A5, $BD, $85, $29, $4C, $14 +$05, $20, $FD, $0A, $20, $FA, $0A, $20 +$74, $06, $D0, $EA, $60, $20, $14, $06 +$85, $28, $20, $14, $06, $85, $29, $05 +$28, $60, $20, $FC, $08, $20, $80, $07 +$A5, $BD, $20, $87, $07, $A5, $BC, $A6 +$C1, $CA, $95, $00, $86, $C1, $E4, $C0 +$D0, $0D, $4C, $14, $05, $A6, $C1, $E0 +$80, $10, $F7, $B5, $00, $E6, $C1, $60 +$85, $BD, $86, $BC, $4C, $B8, $07, $A6 +$C1, $B5, $01, $10, $08, $20, $41, $0A +$A9, $2D, $20, $A6, $06, $20, $FC, $08 +$A9, $1F, $85, $B8, $85, $BA, $A9, $2A +$85, $B9, $85, $BB, $A6, $BC, $A4, $BD +$38, $E6, $B8, $8A, $E9, $10, $AA, $98 +$E9, $27, $A8, $B0, $F4, $C6, $B9, $8A +$69, $E8, $AA, $98, $69, $03, $A8, $90 +$F4, $8A, $38, $E6, $BA, $E9, $64, $B0 +$F9, $88, $10, $F6, $C6, $BB, $69, $0A +$90, $FA, $09, $30, $85, $BC, $A9, $20 +$85, $BD, $A2, $FB, $86, $C3, $B5, $BD +$05, $BD, $C9, $20, $F0, $09, $A0, $30 +$84, $BD, $05, $BD, $20, $A6, $06, $A6 +$C3, $E8, $D0, $E8, $60, $A5, $2D, $48 +$A5, $2C, $48, $A5, $20, $85, $2C, $A5 +$21, $85, $2D, $A5, $24, $A6, $25, $20 +$5B, $08, $F0, $03, $20, $5B, $08, $A5 +$2C, $38, $E5, $B6, $A5, $2D, $E5, $B7 +$B0, $42, $20, $6D, $07, $F0, $3D, $A6 +$28, $A5, $29, $20, $A0, $07, $A9, $20 +$20, $A6, $06, $20, $0C, $04, $B0, $2C +$20, $14, $06, $D0, $F3, $20, $83, $08 +$4C, $2F, $08, $85, $B6, $E6, $B6, $D0 +$01, $E8, $86, $B7, $A4, $C1, $C0, $80 +$F0, $18, $20, $6B, $06, $A5, $2C, $A6 +$2D, $38, $E9, $02, $B0, $01, $CA, $85 +$2C, $4C, $48, $0B, $68, $85, $2C, $68 +$85, $2D, $60, $A5, $BF, $30, $FB, $A9 +$0D, $20, $09, $04, $AD, $11, $04, $29 +$7F, $85, $BF, $F0, $07, $20, $64, $0B +$C6, $BF, $D0, $F9, $A9, $0A, $4C, $61 +$0B, $AC, $12, $04, $84, $BF, $B0, $0B +$A9, $30, $85, $2C, $85, $C0, $84, $2D +$20, $80, $07, $45, $80, $85, $80, $20 +$06, $04, $A0, $00, $A6, $C0, $29, $7F +$F0, $F1, $C9, $7F, $F0, $ED, $C9, $13 +$F0, $DA, $C9, $0A, $F0, $D3, $CD, $10 +$04, $F0, $09, $CD, $0F, $04, $D0, $0A +$E0, $30, $D0, $16, $A6, $2C, $84, $BF +$A9, $0D, $E4, $C1, $30, $08, $A9, $07 +$20, $A6, $06, $4C, $B3, $08, $95, $00 +$E8, $E8, $CA, $86, $C0, $C9, $0D, $D0 +$BA, $20, $83, $08, $20, $95, $07, $85 +$BC, $20, $95, $07, $85, $BD, $60, $20 +$D6, $0A, $20, $6B, $06, $08, $20, $6D +$08, $85, $B8, $86, $B9, $A5, $BC, $85 +$B6, $A5, $BD, $85, $B7, $A2, $00, $28 +$D0, $0B, $20, $6D, $07, $CA, $CA, $CA +$20, $14, $06, $D0, $FA, $84, $28, $84 +$29, $20, $D6, $0A, $A9, $0D, $D1, $2C +$F0, $11, $E8, $E8, $E8, $E8, $C8, $D1 +$2C, $D0, $FA, $A5, $B6, $85, $28, $A5 +$B7, $85, $29, $A5, $B8, $85, $BC, $A5 +$B9, $85, $BD, $18, $A0, $00, $8A, $F0 +$6E, $10, $29, $65, $2E, $85, $B8, $A5 +$2F, $E9, $00, $85, $B9, $B1, $2E, $91 +$B8, $A6, $2E, $E4, $24, $D0, $06, $A5 +$2F, $C5, $25, $F0, $4A, $E8, $86, $2E +$D0, $02, $E6, $2F, $E6, $B8, $D0, $E5 +$E6, $B9, $D0, $E1, $65, $24, $85, $B8 +$85, $2E, $98, $65, $25, $85, $B9, $85 +$2F, $A5, $2E, $E5, $C6, $A5, $2F, $E5 +$C7, $90, $05, $C6, $2A, $4C, $14, $05 +$B1, $24, $91, $2E, $A6, $24, $D0, $02 +$C6, $25, $C6, $24, $A6, $2E, $D0, $02 +$C6, $2F, $CA, $86, $2E, $E4, $BC, $D0 +$E7, $A6, $2F, $E4, $BD, $D0, $E1, $A5 +$B8, $85, $24, $A5, $B9, $85, $25, $A5 +$28, $05, $29, $F0, $17, $A5, $28, $91 +$BC, $C8, $A5, $29, $91, $BC, $C8, $84 +$B6, $20, $14, $06, $08, $A4, $B6, $91 +$BC, $28, $D0, $F2, $4C, $CC, $04, $20 +$54, $05, $B5, $03, $29, $80, $F0, $02 +$A9, $FF, $85, $BC, $85, $BD, $48, $75 +$02, $95, $02, $68, $48, $75, $03, $95 +$03, $68, $55, $01, $85, $BB, $10, $03 +$20, $43, $0A, $A0, $11, $B5, $00, $15 +$01, $D0, $03, $4C, $14, $05, $38, $A5 +$BC, $F5, $00, $48, $A5, $BD, $F5, $01 +$48, $45, $BD, $30, $0A, $68, $85, $BD +$68, $85, $BC, $38, $4C, $32, $0A, $68 +$68, $18, $36, $02, $36, $03, $26, $BC +$26, $BD, $88, $D0, $D9, $A5, $BB, $10 +$0D, $A6, $C1, $38, $98, $F5, $00, $95 +$00, $98, $F5, $01, $95, $01, $60, $20 +$41, $0A, $20, $54, $05, $B5, $00, $75 +$02, $95, $02, $B5, $01, $75, $03, $95 +$03, $60, $20, $54, $05, $A0, $10, $B5 +$02, $85, $BC, $B5, $03, $85, $BD, $16 +$02, $36, $03, $26, $BC, $26, $BD, $90 +$0D, $18, $B5, $02, $75, $00, $95, $02 +$B5, $03, $75, $01, $95, $03, $88, $D0 +$E6, $60, $20, $95, $07, $AA, $B5, $00 +$B4, $01, $C6, $C1, $A6, $C1, $94, $00 +$4C, $87, $07, $A2, $7D, $20, $56, $05 +$B5, $01, $48, $B5, $00, $48, $20, $95 +$07, $AA, $68, $95, $00, $68, $95, $01 +$60, $20, $FD, $0A, $A5, $BC, $85, $2A +$A5, $BD, $85, $2B, $60, $A2, $2C, $D0 +$02, $A2, $2E, $B5, $00, $C9, $80, $B0 +$0D, $B5, $01, $D0, $09, $A5, $2C, $85 +$2E, $A5, $2D, $85, $2F, $60, $A5, $2C +$A4, $2E, $84, $2C, $85, $2E, $A5, $2D +$A4, $2F, $84, $2D, $85, $2F, $A0, $00 +$60, $A5, $28, $85, $BC, $A5, $29, $85 +$BD, $20, $9C, $05, $A5, $C6, $85, $26 +$A5, $C7, $85, $27, $60, $B1, $C6, $85 +$BC, $20, $08, $0B, $B1, $C6, $85, $BD +$E6, $C6, $D0, $02, $E6, $C7, $A5, $22 +$C5, $C6, $A5, $23, $E5, $C7, $B0, $E4 +$4C, $14, $05, $20, $24, $0B, $85, $BC +$98, $4C, $82, $07, $20, $FC, $08, $A5 +$BC, $85, $B6, $20, $FC, $08, $A5, $BD +$85, $B7, $A4, $BC, $20, $FC, $08, $A6 +$B7, $A5, $B6, $18, $6C, $BC, $00, $20 +$42, $0B, $20, $F9, $06, $4C, $87, $07 +$86, $2D, $E0, $00, $60, $A0, $02, $84 +$BC, $A0, $29, $84, $BD, $A0, $00, $B1 +$BC, $C9, $08, $D0, $03, $4C, $0B, $0A +$60, $20, $09, $04, $A9, $FF, $2C, $11 +$04, $30, $02, $A9, $00, $4C, $09, $04 +$24, $3A, $91, $27, $10, $E1, $59, $C5 +$2A, $56, $10, $11, $2C, $8B, $4C, $45 +$D4, $A0, $80, $BD, $30, $BC, $E0, $13 +$1D, $94, $47, $CF, $88, $54, $CF, $30 +$BC, $E0, $10, $11, $16, $80, $53, $55 +$C2, $30, $BC, $E0, $14, $16, $90, $50 +$D2, $83, $49, $4E, $D4, $E5, $71, $88 +$BB, $E1, $1D, $8F, $A2, $21, $58, $6F +$83, $AC, $22, $55, $83, $BA, $24, $93 +$E0, $23, $1D, $30, $BC, $20, $48, $91 +$49, $C6, $30, $BC, $31, $34, $30, $BC +$84, $54, $48, $45, $CE, $1C, $1D, $38 +$0D, $9A, $49, $4E, $50, $55, $D4, $A0 +$10, $E7, $24, $3F, $20, $91, $27, $E1 +$59, $81, $AC, $30, $BC, $13, $11, $82 +$AC, $4D, $E0, $1D, $89, $52, $45, $54 +$55, $52, $CE, $E0, $15, $1D, $85, $45 +$4E, $C4, $E0, $2D, $98, $4C, $49, $53 +$D4, $EC, $24, $00, $00, $00, $00, $0A +$80, $1F, $24, $93, $23, $1D, $30, $BC +$E1, $50, $80, $AC, $59, $85, $52, $55 +$CE, $38, $0A, $86, $43, $4C, $45, $41 +$D2, $2B, $84, $52, $45, $CD, $1D, $A0 +$80, $BD, $38, $14, $85, $AD, $30, $D3 +$17, $64, $81, $AB, $30, $D3, $85, $AB +$30, $D3, $18, $5A, $85, $AD, $30, $D3 +$19, $54, $2F, $30, $E2, $85, $AA, $30 +$E2, $1A, $5A, $85, $AF, $30, $E2, $1B +$54, $2F, $98, $52, $4E, $C4, $0A, $80 +$80, $12, $0A, $09, $29, $1A, $0A, $1A +$85, $18, $13, $09, $80, $12, $01, $0B +$31, $30, $61, $72, $0B, $04, $02, $03 +$05, $03, $1B, $1A, $19, $0B, $09, $06 +$0A, $00, $00, $1C, $17, $2F, $8F, $55 +$53, $D2, $80, $A8, $30, $BC, $31, $2A +$31, $2A, $80, $A9, $2E, $2F, $A2, $12 +$2F, $C1, $2F, $80, $A8, $30, $BC, $80 +$A9, $2F, $83, $AC, $38, $BC, $0B, $2F +$80, $A8, $52, $2F, $84, $BD, $09, $02 +$2F, $8E, $BC, $84, $BD, $09, $93, $2F +$84, $BE, $09, $05, $2F, $09, $91, $2F +$80, $BE, $84, $BD, $09, $06, $2F, $84 +$BC, $09, $95, $2F, $09, $04, $2F, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$20, $0D, $0F, $A0, $00, $20, $1D, $0F +$20, $2C, $0F, $C9, $43, $D0, $03, $4C +$85, $04, $C9, $57, $D0, $03, $4C, $BD +$04, $A2, $2F, $20, $1D, $0F, $4C, $F8 +$0C, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$4D, $4B, $48, $42, $43, $2D, $38, $2D +$52, $32, $20, $54, $49, $4E, $59, $20 +$42, $41, $53, $49, $43, $20, $36, $35 +$30, $32, $20, $50, $4F, $52, $54, $0D +$0A, $56, $65, $72, $73, $69, $6F, $6E +$3A, $20, $31, $2E, $30, $2E, $33, $2C +$20, $32, $2F, $32, $30, $2F, $32, $30 +$31, $36, $0D, $0A, $28, $4E, $4F, $54 +$45, $3A, $20, $55, $73, $65, $20, $55 +$50, $50, $45, $52, $20, $43, $41, $53 +$45, $2E, $29, $0D, $0A, $42, $6F, $6F +$74, $20, $28, $5B, $43, $5D, $6F, $6C +$64, $2F, $5B, $57, $5D, $61, $72, $6D +$29, $3F, $20, $07, $FF, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$86, $C3, $B1, $C2, $48, $C8, $B1, $C2 +$AA, $68, $A8, $8A, $60, $A2, $19, $A9 +$0D, $20, $31, $0F, $A9, $0A, $20, $31 +$0F, $CA, $D0, $FA, $60, $B9, $00, $0E +$C9, $FF, $F0, $07, $20, $31, $0F, $C8 +$4C, $1D, $0F, $60, $AD, $00, $E0, $F0 +$FB, $85, $FE, $C9, $FF, $F0, $1E, $C9 +$00, $F0, $1A, $C9, $91, $F0, $16, $C9 +$93, $F0, $12, $C9, $80, $F0, $0E, $4C +$50, $0F, $20, $F0, $FF, $A5, $FE, $60 +$A5, $FE, $8D, $00, $E0, $60, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 diff --git a/tbe.dat b/tbe.dat new file mode 100644 index 0000000..1669f0b --- /dev/null +++ b/tbe.dat @@ -0,0 +1,423 @@ +ADDR +$0CF0 +; Program disassembly from $0400 to $1000 2/20/2016 +; Tiny Basic port for VM6502 emulator. +; Exec address: $0CF0 +;------------------------------------------------------ +ORG +$0400 +;------------------------------------------------------ +; Character I/O emulation address. +;------------------------------------------------------ +IOADDR +$E000 +;------------------------------------------------------ +; Enable character I/O emulation. +;------------------------------------------------------ +ENIO +;------------------------------------------------------ +; Begin of ROM. +;------------------------------------------------------ +ROMBEGIN +$DF00 +;------------------------------------------------------ +; End of ROM. +;------------------------------------------------------ +ROMEND +$FFFF +;------------------------------------------------------ +; Enable ROM (protected read-only memory) emulation. +;------------------------------------------------------ +ENROM +;------------------------------------------------------ +; Auto-execute code from address. +;------------------------------------------------------ +EXEC +$0CF0 +;------------------------------------------------------ +; Code/Data +;------------------------------------------------------ +$4C, $85, $04, $4C, $BD, $04, $4C, $2C +$0F, $4C, $31, $0F, $EA, $18, $60, $5F +$18, $80, $00, $20, $86, $C3, $90, $05 +$86, $C3, $91, $C2, $60, $B1, $C2, $A0 +$00, $60, $62, $05, $64, $05, $D8, $05 +$05, $06, $33, $06, $FD, $05, $9F, $07 +$42, $0B, $3F, $0B, $7A, $07, $FC, $08 +$95, $07, $9F, $07, $9F, $07, $BD, $0A +$C1, $0A, $8A, $0A, $9B, $0A, $E9, $0A +$61, $07, $51, $07, $41, $0A, $52, $0A +$4F, $0A, $62, $0A, $E7, $09, $CD, $06 +$06, $07, $9F, $07, $15, $08, $A7, $07 +$B7, $06, $BF, $06, $83, $08, $A1, $06 +$9F, $07, $9F, $07, $A8, $08, $4F, $0B +$4D, $0B, $07, $09, $AA, $04, $37, $07 +$BD, $04, $1B, $0B, $B1, $0A, $20, $41 +$54, $20, $80, $70, $0B, $A9, $00, $85 +$20, $85, $22, $A9, $1C, $85, $21, $85 +$23, $A0, $01, $B1, $22, $AA, $49, $FF +$91, $22, $D1, $22, $08, $8A, $91, $22 +$E6, $22, $D0, $02, $E6, $23, $28, $F0 +$EA, $88, $D8, $A5, $20, $6D, $13, $04 +$85, $24, $98, $65, $21, $85, $25, $98 +$91, $20, $C8, $91, $20, $A5, $22, $85 +$C6, $85, $26, $A5, $23, $85, $C7, $85 +$27, $20, $87, $08, $AD, $83, $04, $85 +$2A, $AD, $84, $04, $85, $2B, $A9, $80 +$85, $C1, $A9, $30, $85, $C0, $A2, $00 +$86, $BE, $86, $C2, $CA, $9A, $D8, $20 +$F9, $06, $20, $F2, $04, $4C, $E6, $04 +$83, $65, $C9, $30, $B0, $7B, $C9, $08 +$90, $0C, $0A, $AA, $BD, $1F, $04, $48 +$BD, $1E, $04, $48, $08, $40, $65, $C1 +$AA, $B1, $C1, $48, $B5, $00, $91, $C1 +$68, $95, $00, $60, $20, $87, $08, $A9 +$21, $20, $09, $04, $A5, $2A, $38, $ED +$83, $04, $AA, $A5, $2B, $ED, $84, $04 +$20, $A0, $07, $A5, $BE, $F0, $12, $A9 +$7E, $85, $2A, $A9, $20, $85, $2B, $20 +$A1, $06, $A6, $28, $A5, $29, $20, $A0 +$07, $A9, $07, $20, $09, $04, $20, $87 +$08, $A5, $26, $85, $C6, $A5, $27, $85 +$C7, $4C, $CC, $04, $A2, $7C, $E4, $C1 +$90, $BA, $A6, $C1, $E6, $C1, $E6, $C1 +$18, $60, $C6, $BD, $A5, $BD, $F0, $AC +$A5, $BC, $85, $2A, $A5, $BD, $85, $2B +$60, $C9, $40, $B0, $43, $48, $20, $F9 +$06, $6D, $83, $04, $85, $BC, $68, $48 +$29, $07, $6D, $84, $04, $85, $BD, $68 +$29, $08, $D0, $DC, $A5, $BC, $A6, $2A +$85, $2A, $86, $BC, $A5, $BD, $A6, $2B +$85, $2B, $86, $BD, $A5, $C6, $E9, $01 +$85, $C6, $B0, $02, $C6, $C7, $C5, $24 +$A5, $C7, $E5, $25, $90, $AA, $A5, $BC +$91, $C6, $C8, $A5, $BD, $91, $C6, $60 +$48, $4A, $4A, $4A, $4A, $29, $0E, $AA +$68, $C9, $60, $29, $1F, $B0, $02, $09 +$E0, $18, $F0, $07, $65, $2A, $85, $BC +$98, $65, $2B, $85, $BD, $4C, $FC, $04 +$A5, $2C, $85, $B8, $A5, $2D, $85, $B9 +$20, $25, $06, $20, $14, $06, $51, $2A +$AA, $20, $F9, $06, $8A, $F0, $F1, $0A +$F0, $12, $A5, $B8, $85, $2C, $A5, $B9 +$85, $2D, $4C, $64, $05, $20, $25, $06 +$C9, $0D, $D0, $F6, $60, $20, $25, $06 +$C9, $5B, $B0, $EE, $C9, $41, $90, $EA +$0A, $20, $87, $07, $A0, $00, $B1, $2C +$E6, $2C, $D0, $02, $E6, $2D, $C9, $0D +$18, $60, $20, $14, $06, $B1, $2C, $C9 +$20, $F0, $F7, $C9, $3A, $18, $10, $02 +$C9, $30, $60, $20, $25, $06, $90, $C2 +$84, $BC, $84, $BD, $A5, $BC, $A6, $BD +$06, $BC, $26, $BD, $06, $BC, $26, $BD +$18, $65, $BC, $85, $BC, $8A, $65, $BD +$06, $BC, $2A, $85, $BD, $20, $14, $06 +$29, $0F, $65, $BC, $85, $BC, $98, $65 +$BD, $85, $BD, $20, $25, $06, $B0, $D4 +$4C, $80, $07, $20, $FC, $08, $A5, $BC +$05, $BD, $F0, $48, $A5, $20, $85, $2C +$A5, $21, $85, $2D, $20, $6D, $07, $F0 +$12, $A5, $28, $C5, $BC, $A5, $29, $E5 +$BD, $B0, $08, $20, $14, $06, $D0, $FB +$4C, $7C, $06, $A5, $28, $45, $BC, $D0 +$04, $A5, $29, $45, $BD, $60, $20, $A6 +$06, $20, $F9, $06, $10, $F8, $E6, $BF +$30, $03, $4C, $09, $04, $C6, $BF, $60 +$C9, $22, $F0, $FB, $20, $A6, $06, $20 +$14, $06, $D0, $F4, $4C, $14, $05, $A9 +$20, $20, $A6, $06, $A5, $BF, $29, $87 +$30, $E5, $D0, $F3, $60, $A2, $7B, $20 +$56, $05, $E6, $C1, $E6, $C1, $E6, $C1 +$38, $B5, $03, $F5, $00, $95, $00, $B5 +$04, $F5, $01, $50, $04, $49, $80, $09 +$01, $30, $0A, $D0, $04, $15, $00, $F0 +$02, $56, $02, $56, $02, $56, $02, $90 +$0C, $A0, $00, $B1, $2A, $E6, $2A, $D0 +$02, $E6, $2B, $09, $00, $60, $A5, $BE +$F0, $28, $20, $14, $06, $D0, $FB, $20 +$6D, $07, $F0, $1B, $20, $4C, $07, $20 +$0C, $04, $B0, $09, $A5, $C4, $85, $2A +$A5, $C5, $85, $2B, $60, $AD, $83, $04 +$85, $2A, $AD, $84, $04, $85, $2B, $4C +$14, $05, $85, $BF, $4C, $49, $05, $A5 +$20, $85, $2C, $A5, $21, $85, $2D, $20 +$6D, $07, $F0, $EB, $A5, $2A, $85, $C4 +$A5, $2B, $85, $C5, $A9, $01, $85, $BE +$60, $20, $6B, $06, $F0, $BE, $A5, $BC +$85, $28, $A5, $BD, $85, $29, $4C, $14 +$05, $20, $FD, $0A, $20, $FA, $0A, $20 +$74, $06, $D0, $EA, $60, $20, $14, $06 +$85, $28, $20, $14, $06, $85, $29, $05 +$28, $60, $20, $FC, $08, $20, $80, $07 +$A5, $BD, $20, $87, $07, $A5, $BC, $A6 +$C1, $CA, $95, $00, $86, $C1, $E4, $C0 +$D0, $0D, $4C, $14, $05, $A6, $C1, $E0 +$80, $10, $F7, $B5, $00, $E6, $C1, $60 +$85, $BD, $86, $BC, $4C, $B8, $07, $A6 +$C1, $B5, $01, $10, $08, $20, $41, $0A +$A9, $2D, $20, $A6, $06, $20, $FC, $08 +$A9, $1F, $85, $B8, $85, $BA, $A9, $2A +$85, $B9, $85, $BB, $A6, $BC, $A4, $BD +$38, $E6, $B8, $8A, $E9, $10, $AA, $98 +$E9, $27, $A8, $B0, $F4, $C6, $B9, $8A +$69, $E8, $AA, $98, $69, $03, $A8, $90 +$F4, $8A, $38, $E6, $BA, $E9, $64, $B0 +$F9, $88, $10, $F6, $C6, $BB, $69, $0A +$90, $FA, $09, $30, $85, $BC, $A9, $20 +$85, $BD, $A2, $FB, $86, $C3, $B5, $BD +$05, $BD, $C9, $20, $F0, $09, $A0, $30 +$84, $BD, $05, $BD, $20, $A6, $06, $A6 +$C3, $E8, $D0, $E8, $60, $A5, $2D, $48 +$A5, $2C, $48, $A5, $20, $85, $2C, $A5 +$21, $85, $2D, $A5, $24, $A6, $25, $20 +$5B, $08, $F0, $03, $20, $5B, $08, $A5 +$2C, $38, $E5, $B6, $A5, $2D, $E5, $B7 +$B0, $42, $20, $6D, $07, $F0, $3D, $A6 +$28, $A5, $29, $20, $A0, $07, $A9, $20 +$20, $A6, $06, $20, $0C, $04, $B0, $2C +$20, $14, $06, $D0, $F3, $20, $83, $08 +$4C, $2F, $08, $85, $B6, $E6, $B6, $D0 +$01, $E8, $86, $B7, $A4, $C1, $C0, $80 +$F0, $18, $20, $6B, $06, $A5, $2C, $A6 +$2D, $38, $E9, $02, $B0, $01, $CA, $85 +$2C, $4C, $48, $0B, $68, $85, $2C, $68 +$85, $2D, $60, $A5, $BF, $30, $FB, $A9 +$0D, $20, $09, $04, $AD, $11, $04, $29 +$7F, $85, $BF, $F0, $07, $20, $64, $0B +$C6, $BF, $D0, $F9, $A9, $0A, $4C, $61 +$0B, $AC, $12, $04, $84, $BF, $B0, $0B +$A9, $30, $85, $2C, $85, $C0, $84, $2D +$20, $80, $07, $45, $80, $85, $80, $20 +$06, $04, $A0, $00, $A6, $C0, $29, $7F +$F0, $F1, $C9, $7F, $F0, $ED, $C9, $13 +$F0, $DA, $C9, $0A, $F0, $D3, $CD, $10 +$04, $F0, $09, $CD, $0F, $04, $D0, $0A +$E0, $30, $D0, $16, $A6, $2C, $84, $BF +$A9, $0D, $E4, $C1, $30, $08, $A9, $07 +$20, $A6, $06, $4C, $B3, $08, $95, $00 +$E8, $E8, $CA, $86, $C0, $C9, $0D, $D0 +$BA, $20, $83, $08, $20, $95, $07, $85 +$BC, $20, $95, $07, $85, $BD, $60, $20 +$D6, $0A, $20, $6B, $06, $08, $20, $6D +$08, $85, $B8, $86, $B9, $A5, $BC, $85 +$B6, $A5, $BD, $85, $B7, $A2, $00, $28 +$D0, $0B, $20, $6D, $07, $CA, $CA, $CA +$20, $14, $06, $D0, $FA, $84, $28, $84 +$29, $20, $D6, $0A, $A9, $0D, $D1, $2C +$F0, $11, $E8, $E8, $E8, $E8, $C8, $D1 +$2C, $D0, $FA, $A5, $B6, $85, $28, $A5 +$B7, $85, $29, $A5, $B8, $85, $BC, $A5 +$B9, $85, $BD, $18, $A0, $00, $8A, $F0 +$6E, $10, $29, $65, $2E, $85, $B8, $A5 +$2F, $E9, $00, $85, $B9, $B1, $2E, $91 +$B8, $A6, $2E, $E4, $24, $D0, $06, $A5 +$2F, $C5, $25, $F0, $4A, $E8, $86, $2E +$D0, $02, $E6, $2F, $E6, $B8, $D0, $E5 +$E6, $B9, $D0, $E1, $65, $24, $85, $B8 +$85, $2E, $98, $65, $25, $85, $B9, $85 +$2F, $A5, $2E, $E5, $C6, $A5, $2F, $E5 +$C7, $90, $05, $C6, $2A, $4C, $14, $05 +$B1, $24, $91, $2E, $A6, $24, $D0, $02 +$C6, $25, $C6, $24, $A6, $2E, $D0, $02 +$C6, $2F, $CA, $86, $2E, $E4, $BC, $D0 +$E7, $A6, $2F, $E4, $BD, $D0, $E1, $A5 +$B8, $85, $24, $A5, $B9, $85, $25, $A5 +$28, $05, $29, $F0, $17, $A5, $28, $91 +$BC, $C8, $A5, $29, $91, $BC, $C8, $84 +$B6, $20, $14, $06, $08, $A4, $B6, $91 +$BC, $28, $D0, $F2, $4C, $CC, $04, $20 +$54, $05, $B5, $03, $29, $80, $F0, $02 +$A9, $FF, $85, $BC, $85, $BD, $48, $75 +$02, $95, $02, $68, $48, $75, $03, $95 +$03, $68, $55, $01, $85, $BB, $10, $03 +$20, $43, $0A, $A0, $11, $B5, $00, $15 +$01, $D0, $03, $4C, $14, $05, $38, $A5 +$BC, $F5, $00, $48, $A5, $BD, $F5, $01 +$48, $45, $BD, $30, $0A, $68, $85, $BD +$68, $85, $BC, $38, $4C, $32, $0A, $68 +$68, $18, $36, $02, $36, $03, $26, $BC +$26, $BD, $88, $D0, $D9, $A5, $BB, $10 +$0D, $A6, $C1, $38, $98, $F5, $00, $95 +$00, $98, $F5, $01, $95, $01, $60, $20 +$41, $0A, $20, $54, $05, $B5, $00, $75 +$02, $95, $02, $B5, $01, $75, $03, $95 +$03, $60, $20, $54, $05, $A0, $10, $B5 +$02, $85, $BC, $B5, $03, $85, $BD, $16 +$02, $36, $03, $26, $BC, $26, $BD, $90 +$0D, $18, $B5, $02, $75, $00, $95, $02 +$B5, $03, $75, $01, $95, $03, $88, $D0 +$E6, $60, $20, $95, $07, $AA, $B5, $00 +$B4, $01, $C6, $C1, $A6, $C1, $94, $00 +$4C, $87, $07, $A2, $7D, $20, $56, $05 +$B5, $01, $48, $B5, $00, $48, $20, $95 +$07, $AA, $68, $95, $00, $68, $95, $01 +$60, $20, $FD, $0A, $A5, $BC, $85, $2A +$A5, $BD, $85, $2B, $60, $A2, $2C, $D0 +$02, $A2, $2E, $B5, $00, $C9, $80, $B0 +$0D, $B5, $01, $D0, $09, $A5, $2C, $85 +$2E, $A5, $2D, $85, $2F, $60, $A5, $2C +$A4, $2E, $84, $2C, $85, $2E, $A5, $2D +$A4, $2F, $84, $2D, $85, $2F, $A0, $00 +$60, $A5, $28, $85, $BC, $A5, $29, $85 +$BD, $20, $9C, $05, $A5, $C6, $85, $26 +$A5, $C7, $85, $27, $60, $B1, $C6, $85 +$BC, $20, $08, $0B, $B1, $C6, $85, $BD +$E6, $C6, $D0, $02, $E6, $C7, $A5, $22 +$C5, $C6, $A5, $23, $E5, $C7, $B0, $E4 +$4C, $14, $05, $20, $24, $0B, $85, $BC +$98, $4C, $82, $07, $20, $FC, $08, $A5 +$BC, $85, $B6, $20, $FC, $08, $A5, $BD +$85, $B7, $A4, $BC, $20, $FC, $08, $A6 +$B7, $A5, $B6, $18, $6C, $BC, $00, $20 +$42, $0B, $20, $F9, $06, $4C, $87, $07 +$86, $2D, $E0, $00, $60, $A0, $02, $84 +$BC, $A0, $29, $84, $BD, $A0, $00, $B1 +$BC, $C9, $08, $D0, $03, $4C, $0B, $0A +$60, $20, $09, $04, $A9, $FF, $2C, $11 +$04, $30, $02, $A9, $00, $4C, $09, $04 +$24, $3A, $91, $27, $10, $E1, $59, $C5 +$2A, $56, $10, $11, $2C, $8B, $4C, $45 +$D4, $A0, $80, $BD, $30, $BC, $E0, $13 +$1D, $94, $47, $CF, $88, $54, $CF, $30 +$BC, $E0, $10, $11, $16, $80, $53, $55 +$C2, $30, $BC, $E0, $14, $16, $90, $50 +$D2, $83, $49, $4E, $D4, $E5, $71, $88 +$BB, $E1, $1D, $8F, $A2, $21, $58, $6F +$83, $AC, $22, $55, $83, $BA, $24, $93 +$E0, $23, $1D, $30, $BC, $20, $48, $91 +$49, $C6, $30, $BC, $31, $34, $30, $BC +$84, $54, $48, $45, $CE, $1C, $1D, $38 +$0D, $9A, $49, $4E, $50, $55, $D4, $A0 +$10, $E7, $24, $3F, $20, $91, $27, $E1 +$59, $81, $AC, $30, $BC, $13, $11, $82 +$AC, $4D, $E0, $1D, $89, $52, $45, $54 +$55, $52, $CE, $E0, $15, $1D, $85, $45 +$4E, $C4, $E0, $2D, $98, $4C, $49, $53 +$D4, $EC, $24, $00, $00, $00, $00, $0A +$80, $1F, $24, $93, $23, $1D, $30, $BC +$E1, $50, $80, $AC, $59, $85, $52, $55 +$CE, $38, $0A, $86, $43, $4C, $45, $41 +$D2, $2B, $84, $52, $45, $CD, $1D, $A0 +$80, $BD, $38, $14, $85, $AD, $30, $D3 +$17, $64, $81, $AB, $30, $D3, $85, $AB +$30, $D3, $18, $5A, $85, $AD, $30, $D3 +$19, $54, $2F, $30, $E2, $85, $AA, $30 +$E2, $1A, $5A, $85, $AF, $30, $E2, $1B +$54, $2F, $98, $52, $4E, $C4, $0A, $80 +$80, $12, $0A, $09, $29, $1A, $0A, $1A +$85, $18, $13, $09, $80, $12, $01, $0B +$31, $30, $61, $72, $0B, $04, $02, $03 +$05, $03, $1B, $1A, $19, $0B, $09, $06 +$0A, $00, $00, $1C, $17, $2F, $8F, $55 +$53, $D2, $80, $A8, $30, $BC, $31, $2A +$31, $2A, $80, $A9, $2E, $2F, $A2, $12 +$2F, $C1, $2F, $80, $A8, $30, $BC, $80 +$A9, $2F, $83, $AC, $38, $BC, $0B, $2F +$80, $A8, $52, $2F, $84, $BD, $09, $02 +$2F, $8E, $BC, $84, $BD, $09, $93, $2F +$84, $BE, $09, $05, $2F, $09, $91, $2F +$80, $BE, $84, $BD, $09, $06, $2F, $84 +$BC, $09, $95, $2F, $09, $04, $2F, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$20, $0D, $0F, $A0, $00, $20, $1D, $0F +$20, $2C, $0F, $C9, $43, $D0, $03, $4C +$85, $04, $C9, $57, $D0, $03, $4C, $BD +$04, $A2, $2F, $20, $1D, $0F, $4C, $F8 +$0C, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$4D, $4B, $48, $42, $43, $2D, $38, $2D +$52, $32, $20, $54, $49, $4E, $59, $20 +$42, $41, $53, $49, $43, $20, $36, $35 +$30, $32, $20, $50, $4F, $52, $54, $0D +$0A, $56, $65, $72, $73, $69, $6F, $6E +$3A, $20, $31, $2E, $30, $2E, $33, $2C +$20, $32, $2F, $32, $30, $2F, $32, $30 +$31, $36, $0D, $0A, $28, $4E, $4F, $54 +$45, $3A, $20, $55, $73, $65, $20, $55 +$50, $50, $45, $52, $20, $43, $41, $53 +$45, $2E, $29, $0D, $0A, $42, $6F, $6F +$74, $20, $28, $5B, $43, $5D, $6F, $6C +$64, $2F, $5B, $57, $5D, $61, $72, $6D +$29, $3F, $20, $07, $FF, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$86, $C3, $B1, $C2, $48, $C8, $B1, $C2 +$AA, $68, $A8, $8A, $60, $A2, $19, $A9 +$0D, $20, $31, $0F, $A9, $0A, $20, $31 +$0F, $CA, $D0, $FA, $60, $B9, $00, $0E +$C9, $FF, $F0, $07, $20, $31, $0F, $C8 +$4C, $1D, $0F, $60, $AD, $00, $E0, $F0 +$FB, $85, $FE, $C9, $FF, $F0, $1E, $C9 +$00, $F0, $1A, $C9, $91, $F0, $16, $C9 +$93, $F0, $12, $C9, $80, $F0, $0E, $4C +$50, $0F, $20, $F0, $FF, $A5, $FE, $60 +$A5, $FE, $8D, $00, $E0, $60, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 diff --git a/test_char_io_01.65s b/test_char_io_01.65s index 343d122..18a4bd6 100644 --- a/test_char_io_01.65s +++ b/test_char_io_01.65s @@ -1,50 +1,50 @@ -; Basic test of char I/O emulation - - .ORG $0200 - -CHRGET = $E000 -PUTCH = $E000 -TXTBUF = $0400 -CR = $0D -NL = $0A - -START: LDX #$00 -PR1: LDA PROMPT,X ;print prompt - BEQ L0 - STA PUTCH - INX - BNE PR1 -L0: LDX #$00 -GETTXT: LDA CHRGET ;get text from input - BEQ GETTXT - CMP #CR - BEQ L1 - CMP #NL - BEQ L1 - STA PUTCH ;echo char - STA TXTBUF,X ;store char - INX - BNE GETTXT -L1: LDA #NL ; add line break - STA TXTBUF,X - STA PUTCH - INX - LDA #CR - STA TXTBUF,X - STA PUTCH - INX - LDA #$00 ; add null - STA TXTBUF,X - TAX -PRINT: LDA TXTBUF,X ; print to output - BEQ L2 - STA PUTCH - INX - BNE PRINT -L2: BRK - NOP - JMP START -PROMPT: .DB "Enter text:",0 - - +; Basic test of char I/O emulation + + .ORG $0200 + +CHRGET = $E000 +PUTCH = $E000 +TXTBUF = $0400 +CR = $0D +NL = $0A + +START: LDX #$00 +PR1: LDA PROMPT,X ;print prompt + BEQ L0 + STA PUTCH + INX + BNE PR1 +L0: LDX #$00 +GETTXT: LDA CHRGET ;get text from input + BEQ GETTXT + CMP #CR + BEQ L1 + CMP #NL + BEQ L1 + STA PUTCH ;echo char + STA TXTBUF,X ;store char + INX + BNE GETTXT +L1: LDA #NL ; add line break + STA TXTBUF,X + STA PUTCH + INX + LDA #CR + STA TXTBUF,X + STA PUTCH + INX + LDA #$00 ; add null + STA TXTBUF,X + TAX +PRINT: LDA TXTBUF,X ; print to output + BEQ L2 + STA PUTCH + INX + BNE PRINT +L2: BRK + NOP + JMP START +PROMPT: .DB "Enter text:",0 + + \ No newline at end of file diff --git a/test_char_io_01.dat b/test_char_io_01.dat index 7fdc22b..8767d98 100644 --- a/test_char_io_01.dat +++ b/test_char_io_01.dat @@ -1,15 +1,15 @@ -; I/O test for MKBASIC VM. -ORG -$0200 -$A2 $00 $BD $4E $02 $F0 $06 $8D -$00 $E0 $E8 $D0 $F5 $A2 $00 $AD -$00 $E0 $F0 $FB $C9 $0D $F0 $0D -$C9 $0A $F0 $09 $8D $00 $E0 $9D -$00 $04 $E8 $D0 $EA $A9 $0A $9D -$00 $04 $8D $00 $E0 $E8 $A9 $0D -$9D $00 $04 $8D $00 $E0 $E8 $A9 -$00 $9D $00 $04 $AA $BD $00 $04 -$F0 $06 $8D $00 $E0 $E8 $D0 $F5 -$00 $00 $EA $4C $00 $02 $45 $6E -$74 $65 $72 $20 $74 $65 $78 $74 -$3A $00 $00 $00 $00 $00 $00 $00 +; I/O test for MKBASIC VM. +ORG +$0200 +$A2 $00 $BD $4E $02 $F0 $06 $8D +$00 $E0 $E8 $D0 $F5 $A2 $00 $AD +$00 $E0 $F0 $FB $C9 $0D $F0 $0D +$C9 $0A $F0 $09 $8D $00 $E0 $9D +$00 $04 $E8 $D0 $EA $A9 $0A $9D +$00 $04 $8D $00 $E0 $E8 $A9 $0D +$9D $00 $04 $8D $00 $E0 $E8 $A9 +$00 $9D $00 $04 $AA $BD $00 $04 +$F0 $06 $8D $00 $E0 $E8 $D0 $F5 +$00 $00 $EA $4C $00 $02 $45 $6E +$74 $65 $72 $20 $74 $65 $78 $74 +$3A $00 $00 $00 $00 $00 $00 $00 diff --git a/testall.asm b/testall.asm index 197a441..a221200 100644 --- a/testall.asm +++ b/testall.asm @@ -1,925 +1,954 @@ - .ORG $4000 -start: -; EXPECTED FINAL RESULTS: $0210 = FF -; (any other number will be the -; test that failed) - -; initialize: - LDA #$00 - STA $0210 - ; store each test's expected - LDA #$55 - STA $0200 - LDA #$AA - STA $0201 - LDA #$FF - STA $0202 - LDA #$6E - STA $0203 - LDA #$42 - STA $0204 - LDA #$33 - STA $0205 - LDA #$9D - STA $0206 - LDA #$7F - STA $0207 - LDA #$A5 - STA $0208 - LDA #$1F - STA $0209 - LDA #$CE - STA $020A - LDA #$29 - STA $020B - LDA #$42 - STA $020C - LDA #$6C - STA $020D - LDA #$42 - STA $020E - - -; expected result: $022A = 0x55 -test00: - LDA #85 - LDX #42 - LDY #115 - STA $81 - LDA #$01 - STA $61 - LDA #$7E - LDA $81 - STA $0910 - LDA #$7E - LDA $0910 - STA $56,X - LDA #$7E - LDA $56,X - STY $60 - STA ($60),Y - LDA #$7E - LDA ($60),Y - STA $07ff,X - LDA #$7E - LDA $07ff,X - STA $07ff,Y - LDA #$7E - LDA $07ff,Y - STA ($36,X) - LDA #$7E - LDA ($36,X) - STX $50 - LDX $60 - LDY $50 - STX $0913 - LDX #$22 - LDX $0913 - STY $0914 - LDY #$99 - LDY $0914 - STY $2D,X - STX $77,Y - LDY #$99 - LDY $2D,X - LDX #$22 - LDX $77,Y - LDY #$99 - LDY $08A0,X - LDX #$22 - LDX $08A1,Y - STA $0200,X - -; CHECK test00: - LDA $022A - CMP $0200 - BEQ test00pass - JMP theend -test00pass: - LDA #$FE - STA $0210 - - -; expected result: $A9 = 0xAA -test01: - ; imm - LDA #85 - AND #83 - ORA #56 - EOR #17 - - ; zpg - STA $99 - LDA #185 - STA $10 - LDA #231 - STA $11 - LDA #57 - STA $12 - LDA $99 - AND $10 - ORA $11 - EOR $12 - - ; zpx - LDX #16 - STA $99 - LDA #188 - STA $20 - LDA #49 - STA $21 - LDA #23 - STA $22 - LDA $99 - AND $10,X - ORA $11,X - EOR $12,X - - ; abs - STA $99 - LDA #111 - STA $0110 - LDA #60 - STA $0111 - LDA #39 - STA $0112 - LDA $99 - AND $0110 - ORA $0111 - EOR $0112 - - ; abx - STA $99 - LDA #138 - STA $0120 - LDA #71 - STA $0121 - LDA #143 - STA $0122 - LDA $99 - AND $0110,X - ORA $0111,X - EOR $0112,X - - ; aby - LDY #32 - STA $99 - LDA #115 - STA $0130 - LDA #42 - STA $0131 - LDA #241 - STA $0132 - LDA $99 - AND $0110,Y - ORA $0111,Y - EOR $0112,Y - - ; idx - STA $99 - LDA #112 - STA $30 - LDA #$01 - STA $31 - LDA #113 - STA $32 - LDA #$01 - STA $33 - LDA #114 - STA $34 - LDA #$01 - STA $35 - LDA #197 - STA $0170 - LDA #124 - STA $0171 - LDA #161 - STA $0172 - LDA $99 - AND ($20,X) - ORA ($22,X) - EOR ($24,X) - - ; idy - STA $99 - LDA #96 - STA $40 - LDA #$01 - STA $41 - LDA #97 - STA $42 - LDA #$01 - STA $43 - LDA #98 - STA $44 - LDA #$01 - STA $45 - LDA #55 - STA $0250 - LDA #35 - STA $0251 - LDA #157 - STA $0252 - LDA $99 - LDY #$F0 - AND ($40),Y - ORA ($42),Y - EOR ($44),Y - - STA $A9 - -; CHECK test01 - LDA $A9 - CMP $0201 - BEQ test02 - LDA #$01 - STA $0210 - JMP theend - - -; expected result: $71 = 0xFF -test02: - LDA #$FF - LDX #$00 - - STA $90 - INC $90 - INC $90 - LDA $90 - LDX $90 - - STA $90,X - INC $90,X - LDA $90,X - LDX $91 - - STA $0190,X - INC $0192 - LDA $0190,X - LDX $0192 - - STA $0190,X - INC $0190,X - LDA $0190,X - LDX $0193 - - STA $0170,X - DEC $0170,X - LDA $0170,X - LDX $0174 - - STA $0170,X - DEC $0173 - LDA $0170,X - LDX $0173 - - STA $70,X - DEC $70,X - LDA $70,X - LDX $72 - - STA $70,X - DEC $71 - DEC $71 - -; CHECK test02 - LDA $71 - CMP $0202 - BEQ test03 - LDA #$02 - STA $0210 - JMP theend - - -; expected result: $01DD = 0x6E -test03: - LDA #$4B - LSR - ASL - - STA $50 - ASL $50 - ASL $50 - LSR $50 - LDA $50 - - LDX $50 - ORA #$C9 - STA $60 - ASL $4C,X - LSR $4C,X - LSR $4C,X - LDA $4C,X - - LDX $60 - ORA #$41 - STA $012E - LSR $0100,X - LSR $0100,X - ASL $0100,X - LDA $0100,X - - LDX $012E - ORA #$81 - STA $0100,X - LSR $0136 - LSR $0136 - ASL $0136 - LDA $0100,X - - ; rol & ror - - ROL - ROL - ROR - STA $70 - - LDX $70 - ORA #$03 - STA $0C,X - ROL $C0 - ROR $C0 - ROR $C0 - LDA $0C,X - - LDX $C0 - STA $D0 - ROL $75,X - ROL $75,X - ROR $75,X - LDA $D0 - - LDX $D0 - STA $0100,X - ROL $01B7 - ROL $01B7 - ROL $01B7 - ROR $01B7 - LDA $0100,X - - LDX $01B7 - STA $01DD - ROL $0100,X - ROR $0100,X - ROR $0100,X - -; CHECK test03 - LDA $01DD - CMP $0203 - BEQ test04 - LDA #$03 - STA $0210 - JMP theend - - -; expected result: $40 = 0x42 -test04: - LDA #$E8 ;originally:#$7C - STA $20 - LDA #$42 ;originally:#$02 - STA $21 - LDA #$00 - ORA #$03 - JMP jump1 - ORA #$FF ; not done -jump1: - ORA #$30 - JSR subr - ORA #$42 - JMP ($0020) - ORA #$FF ; not done -subr: - STA $30 - LDX $30 - LDA #$00 - RTS -final: - STA $0D,X - -; CHECK test04 - LDA $40 - CMP $0204 - BEQ test05 - LDA #$04 - STA $0210 - JMP theend - - -; expected result: $40 = 0x33 -test05: - LDA #$35 - - TAX - DEX - DEX - INX - TXA - - TAY - DEY - DEY - INY - TYA - - TAX - LDA #$20 - TXS - LDX #$10 - TSX - TXA - - STA $40 - -; CHECK test05 - LDA $40 - CMP $0205 - BEQ test06 - LDA #$05 - STA $0210 - JMP theend - - -; expected result: $30 = 9D -test06: - -; RESET TO CARRY FLAG = 0 - ROL - - LDA #$6A - STA $50 - LDA #$6B - STA $51 - LDA #$A1 - STA $60 - LDA #$A2 - STA $61 - - LDA #$FF - ADC #$FF - ADC #$FF - SBC #$AE - - STA $40 - LDX $40 - ADC $00,X - SBC $01,X - - ADC $60 - SBC $61 - - STA $0120 - LDA #$4D - STA $0121 - LDA #$23 - ADC $0120 - SBC $0121 - - STA $F0 - LDX $F0 - LDA #$64 - STA $0124 - LDA #$62 - STA $0125 - LDA #$26 - ADC $0100,X - SBC $0101,X - - STA $F1 - LDY $F1 - LDA #$E5 - STA $0128 - LDA #$E9 - STA $0129 - LDA #$34 - ADC $0100,Y - SBC $0101,Y - - STA $F2 - LDX $F2 - LDA #$20 - STA $70 - LDA #$01 - STA $71 - LDA #$24 - STA $72 - LDA #$01 - STA $73 - ADC ($41,X) - SBC ($3F,X) - - STA $F3 - LDY $F3 - LDA #$DA - STA $80 - LDA #$00 - STA $81 - LDA #$DC - STA $82 - LDA #$00 - STA $83 - LDA #$AA - ADC ($80),Y - SBC ($82),Y - STA $30 - -; CHECK test06 - LDA $30 - CMP $0206 - BEQ test07 - LDA #$06 - STA $0210 - JMP theend - - -; expected result: $15 = 0x7F -test07: - ; prepare memory - LDA #$00 - STA $34 - LDA #$FF - STA $0130 - LDA #$99 - STA $019D - LDA #$DB - STA $0199 - LDA #$2F - STA $32 - LDA #$32 - STA $4F - LDA #$30 - STA $33 - LDA #$70 - STA $AF - LDA #$18 - STA $30 - - ; imm - CMP #$18 - BEQ beq1 ; taken - AND #$00 ; not done -beq1: - ; zpg - ORA #$01 - CMP $30 - BNE bne1 ; taken - AND #$00 ; not done -bne1: - ; abs - LDX #$00 - CMP $0130 - BEQ beq2 ; not taken - STA $40 - LDX $40 -beq2: - ; zpx - CMP $27,X - BNE bne2 ; not taken - ORA #$84 - STA $41 - LDX $41 -bne2: - ; abx - AND #$DB - CMP $0100,X - BEQ beq3 ; taken - AND #$00 ; not done -beq3: - ; aby - STA $42 - LDY $42 - AND #$00 - CMP $0100,Y - BNE bne3 ; taken - ORA #$0F ; not done -bne3: - ; idx - STA $43 - LDX $43 - ORA #$24 - CMP ($40,X) - BEQ beq4 ; not taken - ORA #$7F -beq4: - ; idy - STA $44 - LDY $44 - EOR #$0F - CMP ($33),Y - BNE bne4 ; not taken - LDA $44 - STA $15 -bne4: - -; CHECK test07 - LDA $15 - CMP $0207 - BEQ test08 - LDA #$07 - STA $0210 - JMP theend - - -; expected result: $42 = 0xA5 -test08: - ; prepare memory - LDA #$A5 - STA $20 - STA $0120 - LDA #$5A - STA $21 - - ; cpx imm... - LDX #$A5 - CPX #$A5 - BEQ b1 ; taken - LDX #$01 ; not done -b1: - ; cpx zpg... - CPX $20 - BEQ b2 ; taken - LDX #$02 ; not done -b2: - ; cpx abs... - CPX $0120 - BEQ b3 ; taken - LDX #$03 ; not done -b3: - ; cpy imm... - STX $30 - LDY $30 - CPY #$A5 - BEQ b4 ; taken - LDY #$04 ; not done -b4: - ; cpy zpg... - CPY $20 - BEQ b5 ; taken - LDY #$05 ; not done -b5: - ; cpy abs... - CPY $0120 - BEQ b6 ; taken - LDY #$06 ; not done -b6: - ; bit zpg... - STY $31 - LDA $31 - BIT $20 - BNE b7 ; taken - LDA #$07 ; not done -b7: - ; bit abs... - BIT $0120 - BNE b8 ; taken - LDA #$08 ; not done -b8: - BIT $21 - BNE b9 ; not taken - STA $42 -b9: - -; CHECK test08 - LDA $42 - CMP $0208 - BEQ test09 - LDA #$08 - STA $0210 - JMP theend - - -; expected result: $80 = 0x1F -test09: - ; prepare memory - LDA #$54 - STA $32 - LDA #$B3 - STA $A1 - LDA #$87 - STA $43 - - ; BPL - LDX #$A1 - BPL bpl1 ; not taken - LDX #$32 -bpl1: - LDY $00,X - BPL bpl2 ; taken - LDA #$05 ; not done - LDX $A1 ; not done -bpl2: - - ; BMI - BMI bmi1 ; not taken - SBC #$03 -bmi1: - BMI bmi2 ; taken - LDA #$41 ; not done -bmi2: - - ; BVC - EOR #$30 - STA $32 - ADC $00,X - BVC bvc1 ; not taken - LDA #$03 -bvc1: - STA $54 - LDX $00,Y - ADC $51,X - BVC bvc2 ; taken - LDA #$E5 ; not done -bvc2: - - ; BVS - ADC $40,X - BVS bvs1 ; not taken - STA $0001,Y - ADC $55 -bvs1: - BVS bvs2 ; taken - LDA #$00 -bvs2: - - ; BCC - ADC #$F0 - BCC bcc1 ; not taken - STA $60 - ADC $43 -bcc1: - BCC bcc2 ; taken - LDA #$FF -bcc2: - - ; BCS - ADC $54 - BCS bcs1 ; not taken - ADC #$87 - LDX $60 -bcs1: - BCS bcs2 ; taken - LDA #$00 ; not done -bcs2: - STA $73,X - -; CHECK test09 - LDA $80 - CMP $0209 - BEQ test10 - LDA #$09 - STA $0210 - JMP theend - - -; expected result: $30 = 0xCE -test10: - -; RESET TO CARRY = 0 & OVERFLOW = 0 - ADC #$00 - - LDA #$99 - ADC #$87 - CLC - NOP - BCC t10bcc1 ; taken - ADC #$60 ; not done - ADC #$93 ; not done -t10bcc1: - SEC - NOP - BCC t10bcc2 ; not taken - CLV -t10bcc2: - BVC t10bvc1 ; taken - LDA #$00 ; not done -t10bvc1: - ADC #$AD - NOP - STA $30 - -; CHECK test10 - LDA $30 - CMP $020A - BEQ test11 - LDA #$0A - STA $0210 - JMP theend - - -; expected result: $30 = 0x29 -test11: - -; RESET TO CARRY = 0 & ZERO = 0 - ADC #$01 - - LDA #$27 - ADC #$01 - SEC - PHP - CLC - PLP - ADC #$00 - PHA - LDA #$00 - PLA - STA $30 - -; CHECK test11 - LDA $30 - CMP $020B - BEQ test12 - LDA #$0B - STA $0210 - JMP theend - - -; expected result: $33 = 0x42 -test12: - CLC - LDA #$42 - BCC runstuff - STA $33 - BCS t12end -runstuff: - LDA #$45 - PHA - LDA #$61 - PHA - SEC - PHP - CLC - RTI -t12end: - -; CHECK test12 - LDA $33 - CMP $020C - BEQ test13 - LDA #$0C - STA $0210 - JMP theend - - -; expected result: $21 = 0x6C (simulator) -; $21 = 0x0C (ours) -test13: - -; RESET TO CARRY = 0 & ZERO = 0 - ADC #$01 - - SEI - SED - PHP - PLA - STA $20 - CLI - CLD - PHP - PLA - ADC $20 - STA $21 - -; CHECK test13 - LDA $21 - CMP $020D - BEQ test14 - LDA #$0D - STA $0210 - JMP theend - - -; expect result: $60 = 0x42 -test14: - ; !!! NOTICE: BRK doesn't work in this - ; simulator, so commented instructions - ; are what should be executed... - ;JMP pass_intrp - LDA #$41 - STA $60 - ;RTI - ;pass_intrp: - ;LDA #$FF - ;STA $60 - ;BRK (two bytes) - INC $60 - -; CHECK test14 - LDA $60 - CMP $020E - BEQ suiteafinal - LDA #$0E - STA $0210 - JMP theend - -suiteafinal: - ; IF $0210 == 0xFE, INCREMENT - ; (checking that it didn't - ; happen to wander off and - ; not run our instructions - ; to say which tests failed...) - LDA #$FE - CMP $0210 - BNE theend - INC $0210 -theend: - BRK - ;JMP theend \ No newline at end of file +; Testing 6502 opcodes. +; Copied and adapted from AllSuiteA.asm from project hmc-6502: +; https://code.google.com/archive/p/hmc-6502/ +; EXPECTED FINAL RESULTS: $0210 = FF +; (any other number will be the test that failed) +; To build with cl65: +; cl65 -C testall_cl65.cfg -l --start-addr 16384 -t none -o tall.bin testall.asm +; then load to simulator from debug console with 'L B TALL.BIN' +; and execute with 'X 4000'. + + .segment "CODE1" + + .segment "CODE2" + + .ORG $4000 + +start: +; initialize: + LDA #$00 + STA $0210 + ; store each test's expected + LDA #$55 + STA $0200 + LDA #$AA + STA $0201 + LDA #$FF + STA $0202 + LDA #$6E + STA $0203 + LDA #$42 + STA $0204 + LDA #$33 + STA $0205 + LDA #$9D + STA $0206 + LDA #$7F + STA $0207 + LDA #$A5 + STA $0208 + LDA #$1F + STA $0209 + LDA #$CE + STA $020A + LDA #$29 + STA $020B + LDA #$42 + STA $020C + LDA #$6C + STA $020D + LDA #$42 + STA $020E + + +; expected result: $022A = 0x55 +test00: + LDA #85 + LDX #42 + LDY #115 + STA $81 + LDA #$01 + STA $61 + LDA #$7E + LDA $81 + STA $0910 + LDA #$7E + LDA $0910 + STA $56,X + LDA #$7E + LDA $56,X + STY $60 + STA ($60),Y + LDA #$7E + LDA ($60),Y + STA $07ff,X + LDA #$7E + LDA $07ff,X + STA $07ff,Y + LDA #$7E + LDA $07ff,Y + STA ($36,X) + LDA #$7E + LDA ($36,X) + STX $50 + LDX $60 + LDY $50 + STX $0913 + LDX #$22 + LDX $0913 + STY $0914 + LDY #$99 + LDY $0914 + STY $2D,X + STX $77,Y + LDY #$99 + LDY $2D,X + LDX #$22 + LDX $77,Y + LDY #$99 + LDY $08A0,X + LDX #$22 + LDX $08A1,Y + STA $0200,X + +; CHECK test00: + LDA $022A + CMP $0200 + BEQ test00pass + JMP theend +test00pass: + LDA #$FE + STA $0210 + + +; expected result: $A9 = 0xAA +test01: + ; imm + LDA #85 + AND #83 + ORA #56 + EOR #17 + + ; zpg + STA $99 + LDA #185 + STA $10 + LDA #231 + STA $11 + LDA #57 + STA $12 + LDA $99 + AND $10 + ORA $11 + EOR $12 + + ; zpx + LDX #16 + STA $99 + LDA #188 + STA $20 + LDA #49 + STA $21 + LDA #23 + STA $22 + LDA $99 + AND $10,X + ORA $11,X + EOR $12,X + + ; abs + STA $99 + LDA #111 + STA $0110 + LDA #60 + STA $0111 + LDA #39 + STA $0112 + LDA $99 + AND $0110 + ORA $0111 + EOR $0112 + + ; abx + STA $99 + LDA #138 + STA $0120 + LDA #71 + STA $0121 + LDA #143 + STA $0122 + LDA $99 + AND $0110,X + ORA $0111,X + EOR $0112,X + + ; aby + LDY #32 + STA $99 + LDA #115 + STA $0130 + LDA #42 + STA $0131 + LDA #241 + STA $0132 + LDA $99 + AND $0110,Y + ORA $0111,Y + EOR $0112,Y + + ; idx + STA $99 + LDA #112 + STA $30 + LDA #$01 + STA $31 + LDA #113 + STA $32 + LDA #$01 + STA $33 + LDA #114 + STA $34 + LDA #$01 + STA $35 + LDA #197 + STA $0170 + LDA #124 + STA $0171 + LDA #161 + STA $0172 + LDA $99 + AND ($20,X) + ORA ($22,X) + EOR ($24,X) + + ; idy + STA $99 + LDA #96 + STA $40 + LDA #$01 + STA $41 + LDA #97 + STA $42 + LDA #$01 + STA $43 + LDA #98 + STA $44 + LDA #$01 + STA $45 + LDA #55 + STA $0250 + LDA #35 + STA $0251 + LDA #157 + STA $0252 + LDA $99 + LDY #$F0 + AND ($40),Y + ORA ($42),Y + EOR ($44),Y + + STA $A9 + +; CHECK test01 + LDA $A9 + CMP $0201 + BEQ test02 + LDA #$01 + STA $0210 + JMP theend + + +; expected result: $71 = 0xFF +test02: + LDA #$FF + LDX #$00 + + STA $90 + INC $90 + INC $90 + LDA $90 + LDX $90 + + STA $90,X + INC $90,X + LDA $90,X + LDX $91 + + STA $0190,X + INC $0192 + LDA $0190,X + LDX $0192 + + STA $0190,X + INC $0190,X + LDA $0190,X + LDX $0193 + + STA $0170,X + DEC $0170,X + LDA $0170,X + LDX $0174 + + STA $0170,X + DEC $0173 + LDA $0170,X + LDX $0173 + + STA $70,X + DEC $70,X + LDA $70,X + LDX $72 + + STA $70,X + DEC $71 + DEC $71 + +; CHECK test02 + LDA $71 + CMP $0202 + BEQ test03 + LDA #$02 + STA $0210 + JMP theend + + +; expected result: $01DD = 0x6E +test03: + LDA #$4B + LSR + ASL + + STA $50 + ASL $50 + ASL $50 + LSR $50 + LDA $50 + + LDX $50 + ORA #$C9 + STA $60 + ASL $4C,X + LSR $4C,X + LSR $4C,X + LDA $4C,X + + LDX $60 + ORA #$41 + STA $012E + LSR $0100,X + LSR $0100,X + ASL $0100,X + LDA $0100,X + + LDX $012E + ORA #$81 + STA $0100,X + LSR $0136 + LSR $0136 + ASL $0136 + LDA $0100,X + + ; rol & ror + + ROL + ROL + ROR + STA $70 + + LDX $70 + ORA #$03 + STA $0C,X + ROL $C0 + ROR $C0 + ROR $C0 + LDA $0C,X + + LDX $C0 + STA $D0 + ROL $75,X + ROL $75,X + ROR $75,X + LDA $D0 + + LDX $D0 + STA $0100,X + ROL $01B7 + ROL $01B7 + ROL $01B7 + ROR $01B7 + LDA $0100,X + + LDX $01B7 + STA $01DD + ROL $0100,X + ROR $0100,X + ROR $0100,X + +; CHECK test03 + LDA $01DD + CMP $0203 + BEQ test04 + LDA #$03 + STA $0210 + JMP theend + + +; expected result: $40 = 0x42 +test04: + LDA #$E8 ;originally:#$7C + STA $20 + LDA #$42 ;originally:#$02 + STA $21 + LDA #$00 + ORA #$03 + JMP jump1 + ORA #$FF ; not done +jump1: + ORA #$30 + JSR subr + ORA #$42 + JMP ($0020) + ORA #$FF ; not done +subr: + STA $30 + LDX $30 + LDA #$00 + RTS +final: + STA $0D,X + +; CHECK test04 + LDA $40 + CMP $0204 + BEQ test05 + LDA #$04 + STA $0210 + JMP theend + + +; expected result: $40 = 0x33 +test05: + LDA #$35 + + TAX + DEX + DEX + INX + TXA + + TAY + DEY + DEY + INY + TYA + + TAX + LDA #$20 + TXS + LDX #$10 + TSX + TXA + + STA $40 + +; CHECK test05 + LDA $40 + CMP $0205 + BEQ test06 + LDA #$05 + STA $0210 + JMP theend + + +; expected result: $30 = 9D +test06: + +; RESET TO CARRY FLAG = 0 + ROL + + LDA #$6A + STA $50 + LDA #$6B + STA $51 + LDA #$A1 + STA $60 + LDA #$A2 + STA $61 + + LDA #$FF + ADC #$FF + ADC #$FF + SBC #$AE + + STA $40 + LDX $40 + ADC $00,X + SBC $01,X + + ADC $60 + SBC $61 + + STA $0120 + LDA #$4D + STA $0121 + LDA #$23 + ADC $0120 + SBC $0121 + + STA $F0 + LDX $F0 + LDA #$64 + STA $0124 + LDA #$62 + STA $0125 + LDA #$26 + ADC $0100,X + SBC $0101,X + + STA $F1 + LDY $F1 + LDA #$E5 + STA $0128 + LDA #$E9 + STA $0129 + LDA #$34 + ADC $0100,Y + SBC $0101,Y + + STA $F2 + LDX $F2 + LDA #$20 + STA $70 + LDA #$01 + STA $71 + LDA #$24 + STA $72 + LDA #$01 + STA $73 + ADC ($41,X) + SBC ($3F,X) + + STA $F3 + LDY $F3 + LDA #$DA + STA $80 + LDA #$00 + STA $81 + LDA #$DC + STA $82 + LDA #$00 + STA $83 + LDA #$AA + ADC ($80),Y + SBC ($82),Y + STA $30 + +; CHECK test06 + LDA $30 + CMP $0206 + BEQ test07 + LDA #$06 + STA $0210 + JMP theend + + +; expected result: $15 = 0x7F +test07: + ; prepare memory + LDA #$00 + STA $34 + LDA #$FF + STA $0130 + LDA #$99 + STA $019D + LDA #$DB + STA $0199 + LDA #$2F + STA $32 + LDA #$32 + STA $4F + LDA #$30 + STA $33 + LDA #$70 + STA $AF + LDA #$18 + STA $30 + + ; imm + CMP #$18 + BEQ beq1 ; taken + AND #$00 ; not done +beq1: + ; zpg + ORA #$01 + CMP $30 + BNE bne1 ; taken + AND #$00 ; not done +bne1: + ; abs + LDX #$00 + CMP $0130 + BEQ beq2 ; not taken + STA $40 + LDX $40 +beq2: + ; zpx + CMP $27,X + BNE bne2 ; not taken + ORA #$84 + STA $41 + LDX $41 +bne2: + ; abx + AND #$DB + CMP $0100,X + BEQ beq3 ; taken + AND #$00 ; not done +beq3: + ; aby + STA $42 + LDY $42 + AND #$00 + CMP $0100,Y + BNE bne3 ; taken + ORA #$0F ; not done +bne3: + ; idx + STA $43 + LDX $43 + ORA #$24 + CMP ($40,X) + BEQ beq4 ; not taken + ORA #$7F +beq4: + ; idy + STA $44 + LDY $44 + EOR #$0F + CMP ($33),Y + BNE bne4 ; not taken + LDA $44 + STA $15 +bne4: + +; CHECK test07 + LDA $15 + CMP $0207 + BEQ test08 + LDA #$07 + STA $0210 + JMP theend + + +; expected result: $42 = 0xA5 +test08: + ; prepare memory + LDA #$A5 + STA $20 + STA $0120 + LDA #$5A + STA $21 + + ; cpx imm... + LDX #$A5 + CPX #$A5 + BEQ b1 ; taken + LDX #$01 ; not done +b1: + ; cpx zpg... + CPX $20 + BEQ b2 ; taken + LDX #$02 ; not done +b2: + ; cpx abs... + CPX $0120 + BEQ b3 ; taken + LDX #$03 ; not done +b3: + ; cpy imm... + STX $30 + LDY $30 + CPY #$A5 + BEQ b4 ; taken + LDY #$04 ; not done +b4: + ; cpy zpg... + CPY $20 + BEQ b5 ; taken + LDY #$05 ; not done +b5: + ; cpy abs... + CPY $0120 + BEQ b6 ; taken + LDY #$06 ; not done +b6: + ; bit zpg... + STY $31 + LDA $31 + BIT $20 + BNE b7 ; taken + LDA #$07 ; not done +b7: + ; bit abs... + BIT $0120 + BNE b8 ; taken + LDA #$08 ; not done +b8: + BIT $21 + BNE b9 ; not taken + STA $42 +b9: + +; CHECK test08 + LDA $42 + CMP $0208 + BEQ test09 + LDA #$08 + STA $0210 + JMP theend + + +; expected result: $80 = 0x1F +test09: + ; prepare memory + LDA #$54 + STA $32 + LDA #$B3 + STA $A1 + LDA #$87 + STA $43 + + ; BPL + LDX #$A1 + BPL bpl1 ; not taken + LDX #$32 +bpl1: + LDY $00,X + BPL bpl2 ; taken + LDA #$05 ; not done + LDX $A1 ; not done +bpl2: + + ; BMI + BMI bmi1 ; not taken + SBC #$03 +bmi1: + BMI bmi2 ; taken + LDA #$41 ; not done +bmi2: + + ; BVC + EOR #$30 + STA $32 + ADC $00,X + BVC bvc1 ; not taken + LDA #$03 +bvc1: + STA $54 + LDX $00,Y + ADC $51,X + BVC bvc2 ; taken + LDA #$E5 ; not done +bvc2: + + ; BVS + ADC $40,X + BVS bvs1 ; not taken + STA $0001,Y + ADC $55 +bvs1: + BVS bvs2 ; taken + LDA #$00 +bvs2: + + ; BCC + ADC #$F0 + BCC bcc1 ; not taken + STA $60 + ADC $43 +bcc1: + BCC bcc2 ; taken + LDA #$FF +bcc2: + + ; BCS + ADC $54 + BCS bcs1 ; not taken + ADC #$87 + LDX $60 +bcs1: + BCS bcs2 ; taken + LDA #$00 ; not done +bcs2: + STA $73,X + +; CHECK test09 + LDA $80 + CMP $0209 + BEQ test10 + LDA #$09 + STA $0210 + JMP theend + + +; expected result: $30 = 0xCE +test10: + +; RESET TO CARRY = 0 & OVERFLOW = 0 + ADC #$00 + + LDA #$99 + ADC #$87 + CLC + NOP + BCC t10bcc1 ; taken + ADC #$60 ; not done + ADC #$93 ; not done +t10bcc1: + SEC + NOP + BCC t10bcc2 ; not taken + CLV +t10bcc2: + BVC t10bvc1 ; taken + LDA #$00 ; not done +t10bvc1: + ADC #$AD + NOP + STA $30 + +; CHECK test10 + LDA $30 + CMP $020A + BEQ test11 + LDA #$0A + STA $0210 + JMP theend + + +; expected result: $30 = 0x29 +test11: + +; RESET TO CARRY = 0 & ZERO = 0 + ADC #$01 + + LDA #$27 + ADC #$01 + SEC + PHP + CLC + PLP + ADC #$00 + PHA + LDA #$00 + PLA + STA $30 + +; CHECK test11 + LDA $30 + CMP $020B + BEQ test12 + LDA #$0B + STA $0210 + JMP theend + + +; expected result: $33 = 0x42 +test12: + CLC + LDA #$42 + BCC runstuff + STA $33 + BCS t12end +runstuff: + LDA #$45 + PHA + LDA #$61 + PHA + SEC + PHP + CLC + RTI +t12end: + +; CHECK test12 + LDA $33 + CMP $020C + BEQ test13 + LDA #$0C + STA $0210 + JMP theend + + +; expected result: $21 = 0x6C (simulator) +; $21 = 0x0C (ours) +test13: + +; RESET TO CARRY = 0 & ZERO = 0 + ADC #$01 + + SEI + SED + PHP + PLA + STA $20 + CLI + CLD + PHP + PLA + ADC $20 + STA $21 + +; CHECK test13 + LDA $21 + CMP $020D + BEQ test14 + LDA #$0D + STA $0210 + JMP theend + + +; expect result: $60 = 0x42 +test14: + ; !!! NOTICE: BRK doesn't work in this + ; simulator, so commented instructions + ; are what should be executed... + ;JMP pass_intrp + LDA #$41 + STA $60 + ;RTI + ;pass_intrp: + ;LDA #$FF + ;STA $60 + ;BRK (two bytes) + INC $60 + +; CHECK test14 + LDA $60 + CMP $020E + BEQ suiteafinal + LDA #$0E + STA $0210 + JMP theend + +suiteafinal: + ; IF $0210 == 0xFE, INCREMENT + ; (checking that it didn't + ; happen to wander off and + ; not run our instructions + ; to say which tests failed...) + LDA #$FE + CMP $0210 + BNE theend + INC $0210 +theend: + BRK + BRK + ;JMP theend + LDX #$FF + TXS + RTS + + .segment "KERN" + + .ORG $FF00 + + RTI + + .segment "VECT" + + .ORG $FFFA + + .BYTE $00,$FF,$00,$FF,$00,$FF + +;-------------------------- END \ No newline at end of file diff --git a/testall.dat b/testall.dat index 29cafa8..69896ee 100644 --- a/testall.dat +++ b/testall.dat @@ -1,195 +1,195 @@ -; Test 6502 emulation. -ORG -$4000 -$A9 $00 $8D $10 $02 $A9 $55 $8D -$00 $02 $A9 $AA $8D $01 $02 $A9 -$FF $8D $02 $02 $A9 $6E $8D $03 -$02 $A9 $42 $8D $04 $02 $A9 $33 -$8D $05 $02 $A9 $9D $8D $06 $02 -$A9 $7F $8D $07 $02 $A9 $A5 $8D -$08 $02 $A9 $1F $8D $09 $02 $A9 -$CE $8D $0A $02 $A9 $29 $8D $0B -$02 $A9 $42 $8D $0C $02 $A9 $6C -$8D $0D $02 $A9 $42 $8D $0E $02 -$A9 $55 $A2 $2A $A0 $73 $85 $81 -$A9 $01 $85 $61 $A9 $7E $A5 $81 -$8D $10 $09 $A9 $7E $AD $10 $09 -$95 $56 $A9 $7E $B5 $56 $84 $60 -$91 $60 $A9 $7E $B1 $60 $9D $FF -$07 $A9 $7E $BD $FF $07 $99 $FF -$07 $A9 $7E $B9 $FF $07 $81 $36 -$A9 $7E $A1 $36 $86 $50 $A6 $60 -$A4 $50 $8E $13 $09 $A2 $22 $AE -$13 $09 $8C $14 $09 $A0 $99 $AC -$14 $09 $94 $2D $96 $77 $A0 $99 -$B4 $2D $A2 $22 $B6 $77 $A0 $99 -$BC $A0 $08 $A2 $22 $BE $A1 $08 -$9D $00 $02 $AD $2A $02 $CD $00 -$02 $F0 $03 $4C $C0 $45 $A9 $FE -$8D $10 $02 $A9 $55 $29 $53 $09 -$38 $49 $11 $85 $99 $A9 $B9 $85 -$10 $A9 $E7 $85 $11 $A9 $39 $85 -$12 $A5 $99 $25 $10 $05 $11 $45 -$12 $A2 $10 $85 $99 $A9 $BC $85 -$20 $A9 $31 $85 $21 $A9 $17 $85 -$22 $A5 $99 $35 $10 $15 $11 $55 -$12 $85 $99 $A9 $6F $8D $10 $01 -$A9 $3C $8D $11 $01 $A9 $27 $8D -$12 $01 $A5 $99 $2D $10 $01 $0D -$11 $01 $4D $12 $01 $85 $99 $A9 -$8A $8D $20 $01 $A9 $47 $8D $21 -$01 $A9 $8F $8D $22 $01 $A5 $99 -$3D $10 $01 $1D $11 $01 $5D $12 -$01 $A0 $20 $85 $99 $A9 $73 $8D -$30 $01 $A9 $2A $8D $31 $01 $A9 -$F1 $8D $32 $01 $A5 $99 $39 $10 -$01 $19 $11 $01 $59 $12 $01 $85 -$99 $A9 $70 $85 $30 $A9 $01 $85 -$31 $A9 $71 $85 $32 $A9 $01 $85 -$33 $A9 $72 $85 $34 $A9 $01 $85 -$35 $A9 $C5 $8D $70 $01 $A9 $7C -$8D $71 $01 $A9 $A1 $8D $72 $01 -$A5 $99 $21 $20 $01 $22 $41 $24 -$85 $99 $A9 $60 $85 $40 $A9 $01 -$85 $41 $A9 $61 $85 $42 $A9 $01 -$85 $43 $A9 $62 $85 $44 $A9 $01 -$85 $45 $A9 $37 $8D $50 $02 $A9 -$23 $8D $51 $02 $A9 $9D $8D $52 -$02 $A5 $99 $A0 $F0 $31 $40 $11 -$42 $51 $44 $85 $A9 $A5 $A9 $CD -$01 $02 $F0 $08 $A9 $01 $8D $10 -$02 $4C $C0 $45 $A9 $FF $A2 $00 -$85 $90 $E6 $90 $E6 $90 $A5 $90 -$A6 $90 $95 $90 $F6 $90 $B5 $90 -$A6 $91 $9D $90 $01 $EE $92 $01 -$BD $90 $01 $AE $92 $01 $9D $90 -$01 $FE $90 $01 $BD $90 $01 $AE -$93 $01 $9D $70 $01 $DE $70 $01 -$BD $70 $01 $AE $74 $01 $9D $70 -$01 $CE $73 $01 $BD $70 $01 $AE -$73 $01 $95 $70 $D6 $70 $B5 $70 -$A6 $72 $95 $70 $C6 $71 $C6 $71 -$A5 $71 $CD $02 $02 $F0 $08 $A9 -$02 $8D $10 $02 $4C $C0 $45 $A9 -$4B $4A $0A $85 $50 $06 $50 $06 -$50 $46 $50 $A5 $50 $A6 $50 $09 -$C9 $85 $60 $16 $4C $56 $4C $56 -$4C $B5 $4C $A6 $60 $09 $41 $8D -$2E $01 $5E $00 $01 $5E $00 $01 -$1E $00 $01 $BD $00 $01 $AE $2E -$01 $09 $81 $9D $00 $01 $4E $36 -$01 $4E $36 $01 $0E $36 $01 $BD -$00 $01 $2A $2A $6A $85 $70 $A6 -$70 $09 $03 $95 $0C $26 $C0 $66 -$C0 $66 $C0 $B5 $0C $A6 $C0 $85 -$D0 $36 $75 $36 $75 $76 $75 $A5 -$D0 $A6 $D0 $9D $00 $01 $2E $B7 -$01 $2E $B7 $01 $2E $B7 $01 $6E -$B7 $01 $BD $00 $01 $AE $B7 $01 -$8D $DD $01 $3E $00 $01 $7E $00 -$01 $7E $00 $01 $AD $DD $01 $CD -$03 $02 $F0 $08 $A9 $03 $8D $10 -$02 $4C $C0 $45 $A9 $E8 $85 $20 -$A9 $42 $85 $21 $A9 $00 $09 $03 -$4C $D5 $42 $09 $FF $09 $30 $20 -$E1 $42 $09 $42 $6C $20 $00 $09 -$FF $85 $30 $A6 $30 $A9 $00 $60 -$95 $0D $A5 $40 $CD $04 $02 $F0 -$08 $A9 $04 $8D $10 $02 $4C $C0 -$45 $A9 $35 $AA $CA $CA $E8 $8A -$A8 $88 $88 $C8 $98 $AA $A9 $20 -$9A $A2 $10 $BA $8A $85 $40 $A5 -$40 $CD $05 $02 $F0 $08 $A9 $05 -$8D $10 $02 $4C $C0 $45 $2A $A9 -$6A $85 $50 $A9 $6B $85 $51 $A9 -$A1 $85 $60 $A9 $A2 $85 $61 $A9 -$FF $69 $FF $69 $FF $E9 $AE $85 -$40 $A6 $40 $75 $00 $F5 $01 $65 -$60 $E5 $61 $8D $20 $01 $A9 $4D -$8D $21 $01 $A9 $23 $6D $20 $01 -$ED $21 $01 $85 $F0 $A6 $F0 $A9 -$64 $8D $24 $01 $A9 $62 $8D $25 -$01 $A9 $26 $7D $00 $01 $FD $01 -$01 $85 $F1 $A4 $F1 $A9 $E5 $8D -$28 $01 $A9 $E9 $8D $29 $01 $A9 -$34 $79 $00 $01 $F9 $01 $01 $85 -$F2 $A6 $F2 $A9 $20 $85 $70 $A9 -$01 $85 $71 $A9 $24 $85 $72 $A9 -$01 $85 $73 $61 $41 $E1 $3F $85 -$F3 $A4 $F3 $A9 $DA $85 $80 $A9 -$00 $85 $81 $A9 $DC $85 $82 $A9 -$00 $85 $83 $A9 $AA $71 $80 $F1 -$82 $85 $30 $A5 $30 $CD $06 $02 -$F0 $08 $A9 $06 $8D $10 $02 $4C -$C0 $45 $A9 $00 $85 $34 $A9 $FF -$8D $30 $01 $A9 $99 $8D $9D $01 -$A9 $DB $8D $99 $01 $A9 $2F $85 -$32 $A9 $32 $85 $4F $A9 $30 $85 -$33 $A9 $70 $85 $AF $A9 $18 $85 -$30 $C9 $18 $F0 $02 $29 $00 $09 -$01 $C5 $30 $D0 $02 $29 $00 $A2 -$00 $CD $30 $01 $F0 $04 $85 $40 -$A6 $40 $D5 $27 $D0 $06 $09 $84 -$85 $41 $A6 $41 $29 $DB $DD $00 -$01 $F0 $02 $29 $00 $85 $42 $A4 -$42 $29 $00 $D9 $00 $01 $D0 $02 -$09 $0F $85 $43 $A6 $43 $09 $24 -$C1 $40 $F0 $02 $09 $7F $85 $44 -$A4 $44 $49 $0F $D1 $33 $D0 $04 -$A5 $44 $85 $15 $A5 $15 $CD $07 -$02 $F0 $08 $A9 $07 $8D $10 $02 -$4C $C0 $45 $A9 $A5 $85 $20 $8D -$20 $01 $A9 $5A $85 $21 $A2 $A5 -$E0 $A5 $F0 $02 $A2 $01 $E4 $20 -$F0 $02 $A2 $02 $EC $20 $01 $F0 -$02 $A2 $03 $86 $30 $A4 $30 $C0 -$A5 $F0 $02 $A0 $04 $C4 $20 $F0 -$02 $A0 $05 $CC $20 $01 $F0 $02 -$A0 $06 $84 $31 $A5 $31 $24 $20 -$D0 $02 $A9 $07 $2C $20 $01 $D0 -$02 $A9 $08 $24 $21 $D0 $02 $85 -$42 $A5 $42 $CD $08 $02 $F0 $08 -$A9 $08 $8D $10 $02 $4C $C0 $45 -$A9 $54 $85 $32 $A9 $B3 $85 $A1 -$A9 $87 $85 $43 $A2 $A1 $10 $02 -$A2 $32 $B4 $00 $10 $04 $A9 $05 -$A6 $A1 $30 $02 $E9 $03 $30 $02 -$A9 $41 $49 $30 $85 $32 $75 $00 -$50 $02 $A9 $03 $85 $54 $B6 $00 -$75 $51 $50 $02 $A9 $E5 $75 $40 -$70 $05 $99 $01 $00 $65 $55 $70 -$02 $A9 $00 $69 $F0 $90 $04 $85 -$60 $65 $43 $90 $02 $A9 $FF $65 -$54 $B0 $04 $69 $87 $A6 $60 $B0 -$02 $A9 $00 $95 $73 $A5 $80 $CD -$09 $02 $F0 $08 $A9 $09 $8D $10 -$02 $4C $C0 $45 $69 $00 $A9 $99 -$69 $87 $18 $EA $90 $04 $69 $60 -$69 $93 $38 $EA $90 $01 $B8 $50 -$02 $A9 $00 $69 $AD $EA $85 $30 -$A5 $30 $CD $0A $02 $F0 $08 $A9 -$0A $8D $10 $02 $4C $C0 $45 $69 -$01 $A9 $27 $69 $01 $38 $08 $18 -$28 $69 $00 $48 $A9 $00 $68 $85 -$30 $A5 $30 $CD $0B $02 $F0 $08 -$A9 $0B $8D $10 $02 $4C $C0 $45 -$18 $A9 $42 $90 $04 $85 $33 $B0 -$0A $A9 $45 $48 $A9 $61 $48 $38 -$08 $18 $40 $A5 $33 $CD $0C $02 -$F0 $08 $A9 $0C $8D $10 $02 $4C -$C0 $45 $69 $01 $78 $F8 $08 $68 -$85 $20 $58 $D8 $08 $68 $65 $20 -$85 $21 $A5 $21 $CD $0D $02 $F0 -$08 $A9 $0D $8D $10 $02 $4C $C0 -$45 $A9 $41 $85 $60 $E6 $60 $A5 -$60 $CD $0E $02 $F0 $08 $A9 $0E -$8D $10 $02 $4C $C0 $45 $A9 $FE -$CD $10 $02 $D0 $03 $EE $10 $02 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 +; Test 6502 emulation. +ORG +$4000 +$A9 $00 $8D $10 $02 $A9 $55 $8D +$00 $02 $A9 $AA $8D $01 $02 $A9 +$FF $8D $02 $02 $A9 $6E $8D $03 +$02 $A9 $42 $8D $04 $02 $A9 $33 +$8D $05 $02 $A9 $9D $8D $06 $02 +$A9 $7F $8D $07 $02 $A9 $A5 $8D +$08 $02 $A9 $1F $8D $09 $02 $A9 +$CE $8D $0A $02 $A9 $29 $8D $0B +$02 $A9 $42 $8D $0C $02 $A9 $6C +$8D $0D $02 $A9 $42 $8D $0E $02 +$A9 $55 $A2 $2A $A0 $73 $85 $81 +$A9 $01 $85 $61 $A9 $7E $A5 $81 +$8D $10 $09 $A9 $7E $AD $10 $09 +$95 $56 $A9 $7E $B5 $56 $84 $60 +$91 $60 $A9 $7E $B1 $60 $9D $FF +$07 $A9 $7E $BD $FF $07 $99 $FF +$07 $A9 $7E $B9 $FF $07 $81 $36 +$A9 $7E $A1 $36 $86 $50 $A6 $60 +$A4 $50 $8E $13 $09 $A2 $22 $AE +$13 $09 $8C $14 $09 $A0 $99 $AC +$14 $09 $94 $2D $96 $77 $A0 $99 +$B4 $2D $A2 $22 $B6 $77 $A0 $99 +$BC $A0 $08 $A2 $22 $BE $A1 $08 +$9D $00 $02 $AD $2A $02 $CD $00 +$02 $F0 $03 $4C $C0 $45 $A9 $FE +$8D $10 $02 $A9 $55 $29 $53 $09 +$38 $49 $11 $85 $99 $A9 $B9 $85 +$10 $A9 $E7 $85 $11 $A9 $39 $85 +$12 $A5 $99 $25 $10 $05 $11 $45 +$12 $A2 $10 $85 $99 $A9 $BC $85 +$20 $A9 $31 $85 $21 $A9 $17 $85 +$22 $A5 $99 $35 $10 $15 $11 $55 +$12 $85 $99 $A9 $6F $8D $10 $01 +$A9 $3C $8D $11 $01 $A9 $27 $8D +$12 $01 $A5 $99 $2D $10 $01 $0D +$11 $01 $4D $12 $01 $85 $99 $A9 +$8A $8D $20 $01 $A9 $47 $8D $21 +$01 $A9 $8F $8D $22 $01 $A5 $99 +$3D $10 $01 $1D $11 $01 $5D $12 +$01 $A0 $20 $85 $99 $A9 $73 $8D +$30 $01 $A9 $2A $8D $31 $01 $A9 +$F1 $8D $32 $01 $A5 $99 $39 $10 +$01 $19 $11 $01 $59 $12 $01 $85 +$99 $A9 $70 $85 $30 $A9 $01 $85 +$31 $A9 $71 $85 $32 $A9 $01 $85 +$33 $A9 $72 $85 $34 $A9 $01 $85 +$35 $A9 $C5 $8D $70 $01 $A9 $7C +$8D $71 $01 $A9 $A1 $8D $72 $01 +$A5 $99 $21 $20 $01 $22 $41 $24 +$85 $99 $A9 $60 $85 $40 $A9 $01 +$85 $41 $A9 $61 $85 $42 $A9 $01 +$85 $43 $A9 $62 $85 $44 $A9 $01 +$85 $45 $A9 $37 $8D $50 $02 $A9 +$23 $8D $51 $02 $A9 $9D $8D $52 +$02 $A5 $99 $A0 $F0 $31 $40 $11 +$42 $51 $44 $85 $A9 $A5 $A9 $CD +$01 $02 $F0 $08 $A9 $01 $8D $10 +$02 $4C $C0 $45 $A9 $FF $A2 $00 +$85 $90 $E6 $90 $E6 $90 $A5 $90 +$A6 $90 $95 $90 $F6 $90 $B5 $90 +$A6 $91 $9D $90 $01 $EE $92 $01 +$BD $90 $01 $AE $92 $01 $9D $90 +$01 $FE $90 $01 $BD $90 $01 $AE +$93 $01 $9D $70 $01 $DE $70 $01 +$BD $70 $01 $AE $74 $01 $9D $70 +$01 $CE $73 $01 $BD $70 $01 $AE +$73 $01 $95 $70 $D6 $70 $B5 $70 +$A6 $72 $95 $70 $C6 $71 $C6 $71 +$A5 $71 $CD $02 $02 $F0 $08 $A9 +$02 $8D $10 $02 $4C $C0 $45 $A9 +$4B $4A $0A $85 $50 $06 $50 $06 +$50 $46 $50 $A5 $50 $A6 $50 $09 +$C9 $85 $60 $16 $4C $56 $4C $56 +$4C $B5 $4C $A6 $60 $09 $41 $8D +$2E $01 $5E $00 $01 $5E $00 $01 +$1E $00 $01 $BD $00 $01 $AE $2E +$01 $09 $81 $9D $00 $01 $4E $36 +$01 $4E $36 $01 $0E $36 $01 $BD +$00 $01 $2A $2A $6A $85 $70 $A6 +$70 $09 $03 $95 $0C $26 $C0 $66 +$C0 $66 $C0 $B5 $0C $A6 $C0 $85 +$D0 $36 $75 $36 $75 $76 $75 $A5 +$D0 $A6 $D0 $9D $00 $01 $2E $B7 +$01 $2E $B7 $01 $2E $B7 $01 $6E +$B7 $01 $BD $00 $01 $AE $B7 $01 +$8D $DD $01 $3E $00 $01 $7E $00 +$01 $7E $00 $01 $AD $DD $01 $CD +$03 $02 $F0 $08 $A9 $03 $8D $10 +$02 $4C $C0 $45 $A9 $E8 $85 $20 +$A9 $42 $85 $21 $A9 $00 $09 $03 +$4C $D5 $42 $09 $FF $09 $30 $20 +$E1 $42 $09 $42 $6C $20 $00 $09 +$FF $85 $30 $A6 $30 $A9 $00 $60 +$95 $0D $A5 $40 $CD $04 $02 $F0 +$08 $A9 $04 $8D $10 $02 $4C $C0 +$45 $A9 $35 $AA $CA $CA $E8 $8A +$A8 $88 $88 $C8 $98 $AA $A9 $20 +$9A $A2 $10 $BA $8A $85 $40 $A5 +$40 $CD $05 $02 $F0 $08 $A9 $05 +$8D $10 $02 $4C $C0 $45 $2A $A9 +$6A $85 $50 $A9 $6B $85 $51 $A9 +$A1 $85 $60 $A9 $A2 $85 $61 $A9 +$FF $69 $FF $69 $FF $E9 $AE $85 +$40 $A6 $40 $75 $00 $F5 $01 $65 +$60 $E5 $61 $8D $20 $01 $A9 $4D +$8D $21 $01 $A9 $23 $6D $20 $01 +$ED $21 $01 $85 $F0 $A6 $F0 $A9 +$64 $8D $24 $01 $A9 $62 $8D $25 +$01 $A9 $26 $7D $00 $01 $FD $01 +$01 $85 $F1 $A4 $F1 $A9 $E5 $8D +$28 $01 $A9 $E9 $8D $29 $01 $A9 +$34 $79 $00 $01 $F9 $01 $01 $85 +$F2 $A6 $F2 $A9 $20 $85 $70 $A9 +$01 $85 $71 $A9 $24 $85 $72 $A9 +$01 $85 $73 $61 $41 $E1 $3F $85 +$F3 $A4 $F3 $A9 $DA $85 $80 $A9 +$00 $85 $81 $A9 $DC $85 $82 $A9 +$00 $85 $83 $A9 $AA $71 $80 $F1 +$82 $85 $30 $A5 $30 $CD $06 $02 +$F0 $08 $A9 $06 $8D $10 $02 $4C +$C0 $45 $A9 $00 $85 $34 $A9 $FF +$8D $30 $01 $A9 $99 $8D $9D $01 +$A9 $DB $8D $99 $01 $A9 $2F $85 +$32 $A9 $32 $85 $4F $A9 $30 $85 +$33 $A9 $70 $85 $AF $A9 $18 $85 +$30 $C9 $18 $F0 $02 $29 $00 $09 +$01 $C5 $30 $D0 $02 $29 $00 $A2 +$00 $CD $30 $01 $F0 $04 $85 $40 +$A6 $40 $D5 $27 $D0 $06 $09 $84 +$85 $41 $A6 $41 $29 $DB $DD $00 +$01 $F0 $02 $29 $00 $85 $42 $A4 +$42 $29 $00 $D9 $00 $01 $D0 $02 +$09 $0F $85 $43 $A6 $43 $09 $24 +$C1 $40 $F0 $02 $09 $7F $85 $44 +$A4 $44 $49 $0F $D1 $33 $D0 $04 +$A5 $44 $85 $15 $A5 $15 $CD $07 +$02 $F0 $08 $A9 $07 $8D $10 $02 +$4C $C0 $45 $A9 $A5 $85 $20 $8D +$20 $01 $A9 $5A $85 $21 $A2 $A5 +$E0 $A5 $F0 $02 $A2 $01 $E4 $20 +$F0 $02 $A2 $02 $EC $20 $01 $F0 +$02 $A2 $03 $86 $30 $A4 $30 $C0 +$A5 $F0 $02 $A0 $04 $C4 $20 $F0 +$02 $A0 $05 $CC $20 $01 $F0 $02 +$A0 $06 $84 $31 $A5 $31 $24 $20 +$D0 $02 $A9 $07 $2C $20 $01 $D0 +$02 $A9 $08 $24 $21 $D0 $02 $85 +$42 $A5 $42 $CD $08 $02 $F0 $08 +$A9 $08 $8D $10 $02 $4C $C0 $45 +$A9 $54 $85 $32 $A9 $B3 $85 $A1 +$A9 $87 $85 $43 $A2 $A1 $10 $02 +$A2 $32 $B4 $00 $10 $04 $A9 $05 +$A6 $A1 $30 $02 $E9 $03 $30 $02 +$A9 $41 $49 $30 $85 $32 $75 $00 +$50 $02 $A9 $03 $85 $54 $B6 $00 +$75 $51 $50 $02 $A9 $E5 $75 $40 +$70 $05 $99 $01 $00 $65 $55 $70 +$02 $A9 $00 $69 $F0 $90 $04 $85 +$60 $65 $43 $90 $02 $A9 $FF $65 +$54 $B0 $04 $69 $87 $A6 $60 $B0 +$02 $A9 $00 $95 $73 $A5 $80 $CD +$09 $02 $F0 $08 $A9 $09 $8D $10 +$02 $4C $C0 $45 $69 $00 $A9 $99 +$69 $87 $18 $EA $90 $04 $69 $60 +$69 $93 $38 $EA $90 $01 $B8 $50 +$02 $A9 $00 $69 $AD $EA $85 $30 +$A5 $30 $CD $0A $02 $F0 $08 $A9 +$0A $8D $10 $02 $4C $C0 $45 $69 +$01 $A9 $27 $69 $01 $38 $08 $18 +$28 $69 $00 $48 $A9 $00 $68 $85 +$30 $A5 $30 $CD $0B $02 $F0 $08 +$A9 $0B $8D $10 $02 $4C $C0 $45 +$18 $A9 $42 $90 $04 $85 $33 $B0 +$0A $A9 $45 $48 $A9 $61 $48 $38 +$08 $18 $40 $A5 $33 $CD $0C $02 +$F0 $08 $A9 $0C $8D $10 $02 $4C +$C0 $45 $69 $01 $78 $F8 $08 $68 +$85 $20 $58 $D8 $08 $68 $65 $20 +$85 $21 $A5 $21 $CD $0D $02 $F0 +$08 $A9 $0D $8D $10 $02 $4C $C0 +$45 $A9 $41 $85 $60 $E6 $60 $A5 +$60 $CD $0E $02 $F0 $08 $A9 $0E +$8D $10 $02 $4C $C0 $45 $A9 $FE +$CD $10 $02 $D0 $03 $EE $10 $02 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 diff --git a/testall.lst b/testall.lst new file mode 100644 index 0000000..2e7075f --- /dev/null +++ b/testall.lst @@ -0,0 +1,960 @@ +ca65 V2.13.2 - (C) Copyright 1998-2005 Ullrich von Bassewitz +Main file : testall.asm +Current file: testall.asm + +000000r 1 ; Testing 6502 opcodes. +000000r 1 ; Copied and adapted from AllSuiteA.asm from project hmc-6502: +000000r 1 ; https://code.google.com/archive/p/hmc-6502/ +000000r 1 ; EXPECTED FINAL RESULTS: $0210 = FF +000000r 1 ; (any other number will be the test that failed) +000000r 1 ; To build with cl65: +000000r 1 ; cl65 -C testall_cl65.cfg -l --start-addr 16384 -t none -o tall.bin testall.asm +000000r 1 ; then load to simulator from debug console with 'L B TALL.BIN' +000000r 1 ; and execute with 'X 4000'. +000000r 1 +000000r 1 .segment "CODE1" +000000r 1 +000000r 1 .segment "CODE2" +000000r 1 +000000r 1 .ORG $4000 +004000 1 +004000 1 start: +004000 1 ; initialize: +004000 1 A9 00 LDA #$00 +004002 1 8D 10 02 STA $0210 +004005 1 ; store each test's expected +004005 1 A9 55 LDA #$55 +004007 1 8D 00 02 STA $0200 +00400A 1 A9 AA LDA #$AA +00400C 1 8D 01 02 STA $0201 +00400F 1 A9 FF LDA #$FF +004011 1 8D 02 02 STA $0202 +004014 1 A9 6E LDA #$6E +004016 1 8D 03 02 STA $0203 +004019 1 A9 42 LDA #$42 +00401B 1 8D 04 02 STA $0204 +00401E 1 A9 33 LDA #$33 +004020 1 8D 05 02 STA $0205 +004023 1 A9 9D LDA #$9D +004025 1 8D 06 02 STA $0206 +004028 1 A9 7F LDA #$7F +00402A 1 8D 07 02 STA $0207 +00402D 1 A9 A5 LDA #$A5 +00402F 1 8D 08 02 STA $0208 +004032 1 A9 1F LDA #$1F +004034 1 8D 09 02 STA $0209 +004037 1 A9 CE LDA #$CE +004039 1 8D 0A 02 STA $020A +00403C 1 A9 29 LDA #$29 +00403E 1 8D 0B 02 STA $020B +004041 1 A9 42 LDA #$42 +004043 1 8D 0C 02 STA $020C +004046 1 A9 6C LDA #$6C +004048 1 8D 0D 02 STA $020D +00404B 1 A9 42 LDA #$42 +00404D 1 8D 0E 02 STA $020E +004050 1 +004050 1 +004050 1 ; expected result: $022A = 0x55 +004050 1 test00: +004050 1 A9 55 LDA #85 +004052 1 A2 2A LDX #42 +004054 1 A0 73 LDY #115 +004056 1 85 81 STA $81 +004058 1 A9 01 LDA #$01 +00405A 1 85 61 STA $61 +00405C 1 A9 7E LDA #$7E +00405E 1 A5 81 LDA $81 +004060 1 8D 10 09 STA $0910 +004063 1 A9 7E LDA #$7E +004065 1 AD 10 09 LDA $0910 +004068 1 95 56 STA $56,X +00406A 1 A9 7E LDA #$7E +00406C 1 B5 56 LDA $56,X +00406E 1 84 60 STY $60 +004070 1 91 60 STA ($60),Y +004072 1 A9 7E LDA #$7E +004074 1 B1 60 LDA ($60),Y +004076 1 9D FF 07 STA $07ff,X +004079 1 A9 7E LDA #$7E +00407B 1 BD FF 07 LDA $07ff,X +00407E 1 99 FF 07 STA $07ff,Y +004081 1 A9 7E LDA #$7E +004083 1 B9 FF 07 LDA $07ff,Y +004086 1 81 36 STA ($36,X) +004088 1 A9 7E LDA #$7E +00408A 1 A1 36 LDA ($36,X) +00408C 1 86 50 STX $50 +00408E 1 A6 60 LDX $60 +004090 1 A4 50 LDY $50 +004092 1 8E 13 09 STX $0913 +004095 1 A2 22 LDX #$22 +004097 1 AE 13 09 LDX $0913 +00409A 1 8C 14 09 STY $0914 +00409D 1 A0 99 LDY #$99 +00409F 1 AC 14 09 LDY $0914 +0040A2 1 94 2D STY $2D,X +0040A4 1 96 77 STX $77,Y +0040A6 1 A0 99 LDY #$99 +0040A8 1 B4 2D LDY $2D,X +0040AA 1 A2 22 LDX #$22 +0040AC 1 B6 77 LDX $77,Y +0040AE 1 A0 99 LDY #$99 +0040B0 1 BC A0 08 LDY $08A0,X +0040B3 1 A2 22 LDX #$22 +0040B5 1 BE A1 08 LDX $08A1,Y +0040B8 1 9D 00 02 STA $0200,X +0040BB 1 +0040BB 1 ; CHECK test00: +0040BB 1 AD 2A 02 LDA $022A +0040BE 1 CD 00 02 CMP $0200 +0040C1 1 F0 03 BEQ test00pass +0040C3 1 4C C0 45 JMP theend +0040C6 1 test00pass: +0040C6 1 A9 FE LDA #$FE +0040C8 1 8D 10 02 STA $0210 +0040CB 1 +0040CB 1 +0040CB 1 ; expected result: $A9 = 0xAA +0040CB 1 test01: +0040CB 1 ; imm +0040CB 1 A9 55 LDA #85 +0040CD 1 29 53 AND #83 +0040CF 1 09 38 ORA #56 +0040D1 1 49 11 EOR #17 +0040D3 1 +0040D3 1 ; zpg +0040D3 1 85 99 STA $99 +0040D5 1 A9 B9 LDA #185 +0040D7 1 85 10 STA $10 +0040D9 1 A9 E7 LDA #231 +0040DB 1 85 11 STA $11 +0040DD 1 A9 39 LDA #57 +0040DF 1 85 12 STA $12 +0040E1 1 A5 99 LDA $99 +0040E3 1 25 10 AND $10 +0040E5 1 05 11 ORA $11 +0040E7 1 45 12 EOR $12 +0040E9 1 +0040E9 1 ; zpx +0040E9 1 A2 10 LDX #16 +0040EB 1 85 99 STA $99 +0040ED 1 A9 BC LDA #188 +0040EF 1 85 20 STA $20 +0040F1 1 A9 31 LDA #49 +0040F3 1 85 21 STA $21 +0040F5 1 A9 17 LDA #23 +0040F7 1 85 22 STA $22 +0040F9 1 A5 99 LDA $99 +0040FB 1 35 10 AND $10,X +0040FD 1 15 11 ORA $11,X +0040FF 1 55 12 EOR $12,X +004101 1 +004101 1 ; abs +004101 1 85 99 STA $99 +004103 1 A9 6F LDA #111 +004105 1 8D 10 01 STA $0110 +004108 1 A9 3C LDA #60 +00410A 1 8D 11 01 STA $0111 +00410D 1 A9 27 LDA #39 +00410F 1 8D 12 01 STA $0112 +004112 1 A5 99 LDA $99 +004114 1 2D 10 01 AND $0110 +004117 1 0D 11 01 ORA $0111 +00411A 1 4D 12 01 EOR $0112 +00411D 1 +00411D 1 ; abx +00411D 1 85 99 STA $99 +00411F 1 A9 8A LDA #138 +004121 1 8D 20 01 STA $0120 +004124 1 A9 47 LDA #71 +004126 1 8D 21 01 STA $0121 +004129 1 A9 8F LDA #143 +00412B 1 8D 22 01 STA $0122 +00412E 1 A5 99 LDA $99 +004130 1 3D 10 01 AND $0110,X +004133 1 1D 11 01 ORA $0111,X +004136 1 5D 12 01 EOR $0112,X +004139 1 +004139 1 ; aby +004139 1 A0 20 LDY #32 +00413B 1 85 99 STA $99 +00413D 1 A9 73 LDA #115 +00413F 1 8D 30 01 STA $0130 +004142 1 A9 2A LDA #42 +004144 1 8D 31 01 STA $0131 +004147 1 A9 F1 LDA #241 +004149 1 8D 32 01 STA $0132 +00414C 1 A5 99 LDA $99 +00414E 1 39 10 01 AND $0110,Y +004151 1 19 11 01 ORA $0111,Y +004154 1 59 12 01 EOR $0112,Y +004157 1 +004157 1 ; idx +004157 1 85 99 STA $99 +004159 1 A9 70 LDA #112 +00415B 1 85 30 STA $30 +00415D 1 A9 01 LDA #$01 +00415F 1 85 31 STA $31 +004161 1 A9 71 LDA #113 +004163 1 85 32 STA $32 +004165 1 A9 01 LDA #$01 +004167 1 85 33 STA $33 +004169 1 A9 72 LDA #114 +00416B 1 85 34 STA $34 +00416D 1 A9 01 LDA #$01 +00416F 1 85 35 STA $35 +004171 1 A9 C5 LDA #197 +004173 1 8D 70 01 STA $0170 +004176 1 A9 7C LDA #124 +004178 1 8D 71 01 STA $0171 +00417B 1 A9 A1 LDA #161 +00417D 1 8D 72 01 STA $0172 +004180 1 A5 99 LDA $99 +004182 1 21 20 AND ($20,X) +004184 1 01 22 ORA ($22,X) +004186 1 41 24 EOR ($24,X) +004188 1 +004188 1 ; idy +004188 1 85 99 STA $99 +00418A 1 A9 60 LDA #96 +00418C 1 85 40 STA $40 +00418E 1 A9 01 LDA #$01 +004190 1 85 41 STA $41 +004192 1 A9 61 LDA #97 +004194 1 85 42 STA $42 +004196 1 A9 01 LDA #$01 +004198 1 85 43 STA $43 +00419A 1 A9 62 LDA #98 +00419C 1 85 44 STA $44 +00419E 1 A9 01 LDA #$01 +0041A0 1 85 45 STA $45 +0041A2 1 A9 37 LDA #55 +0041A4 1 8D 50 02 STA $0250 +0041A7 1 A9 23 LDA #35 +0041A9 1 8D 51 02 STA $0251 +0041AC 1 A9 9D LDA #157 +0041AE 1 8D 52 02 STA $0252 +0041B1 1 A5 99 LDA $99 +0041B3 1 A0 F0 LDY #$F0 +0041B5 1 31 40 AND ($40),Y +0041B7 1 11 42 ORA ($42),Y +0041B9 1 51 44 EOR ($44),Y +0041BB 1 +0041BB 1 85 A9 STA $A9 +0041BD 1 +0041BD 1 ; CHECK test01 +0041BD 1 A5 A9 LDA $A9 +0041BF 1 CD 01 02 CMP $0201 +0041C2 1 F0 08 BEQ test02 +0041C4 1 A9 01 LDA #$01 +0041C6 1 8D 10 02 STA $0210 +0041C9 1 4C C0 45 JMP theend +0041CC 1 +0041CC 1 +0041CC 1 ; expected result: $71 = 0xFF +0041CC 1 test02: +0041CC 1 A9 FF LDA #$FF +0041CE 1 A2 00 LDX #$00 +0041D0 1 +0041D0 1 85 90 STA $90 +0041D2 1 E6 90 INC $90 +0041D4 1 E6 90 INC $90 +0041D6 1 A5 90 LDA $90 +0041D8 1 A6 90 LDX $90 +0041DA 1 +0041DA 1 95 90 STA $90,X +0041DC 1 F6 90 INC $90,X +0041DE 1 B5 90 LDA $90,X +0041E0 1 A6 91 LDX $91 +0041E2 1 +0041E2 1 9D 90 01 STA $0190,X +0041E5 1 EE 92 01 INC $0192 +0041E8 1 BD 90 01 LDA $0190,X +0041EB 1 AE 92 01 LDX $0192 +0041EE 1 +0041EE 1 9D 90 01 STA $0190,X +0041F1 1 FE 90 01 INC $0190,X +0041F4 1 BD 90 01 LDA $0190,X +0041F7 1 AE 93 01 LDX $0193 +0041FA 1 +0041FA 1 9D 70 01 STA $0170,X +0041FD 1 DE 70 01 DEC $0170,X +004200 1 BD 70 01 LDA $0170,X +004203 1 AE 74 01 LDX $0174 +004206 1 +004206 1 9D 70 01 STA $0170,X +004209 1 CE 73 01 DEC $0173 +00420C 1 BD 70 01 LDA $0170,X +00420F 1 AE 73 01 LDX $0173 +004212 1 +004212 1 95 70 STA $70,X +004214 1 D6 70 DEC $70,X +004216 1 B5 70 LDA $70,X +004218 1 A6 72 LDX $72 +00421A 1 +00421A 1 95 70 STA $70,X +00421C 1 C6 71 DEC $71 +00421E 1 C6 71 DEC $71 +004220 1 +004220 1 ; CHECK test02 +004220 1 A5 71 LDA $71 +004222 1 CD 02 02 CMP $0202 +004225 1 F0 08 BEQ test03 +004227 1 A9 02 LDA #$02 +004229 1 8D 10 02 STA $0210 +00422C 1 4C C0 45 JMP theend +00422F 1 +00422F 1 +00422F 1 ; expected result: $01DD = 0x6E +00422F 1 test03: +00422F 1 A9 4B LDA #$4B +004231 1 4A LSR +004232 1 0A ASL +004233 1 +004233 1 85 50 STA $50 +004235 1 06 50 ASL $50 +004237 1 06 50 ASL $50 +004239 1 46 50 LSR $50 +00423B 1 A5 50 LDA $50 +00423D 1 +00423D 1 A6 50 LDX $50 +00423F 1 09 C9 ORA #$C9 +004241 1 85 60 STA $60 +004243 1 16 4C ASL $4C,X +004245 1 56 4C LSR $4C,X +004247 1 56 4C LSR $4C,X +004249 1 B5 4C LDA $4C,X +00424B 1 +00424B 1 A6 60 LDX $60 +00424D 1 09 41 ORA #$41 +00424F 1 8D 2E 01 STA $012E +004252 1 5E 00 01 LSR $0100,X +004255 1 5E 00 01 LSR $0100,X +004258 1 1E 00 01 ASL $0100,X +00425B 1 BD 00 01 LDA $0100,X +00425E 1 +00425E 1 AE 2E 01 LDX $012E +004261 1 09 81 ORA #$81 +004263 1 9D 00 01 STA $0100,X +004266 1 4E 36 01 LSR $0136 +004269 1 4E 36 01 LSR $0136 +00426C 1 0E 36 01 ASL $0136 +00426F 1 BD 00 01 LDA $0100,X +004272 1 +004272 1 ; rol & ror +004272 1 +004272 1 2A ROL +004273 1 2A ROL +004274 1 6A ROR +004275 1 85 70 STA $70 +004277 1 +004277 1 A6 70 LDX $70 +004279 1 09 03 ORA #$03 +00427B 1 95 0C STA $0C,X +00427D 1 26 C0 ROL $C0 +00427F 1 66 C0 ROR $C0 +004281 1 66 C0 ROR $C0 +004283 1 B5 0C LDA $0C,X +004285 1 +004285 1 A6 C0 LDX $C0 +004287 1 85 D0 STA $D0 +004289 1 36 75 ROL $75,X +00428B 1 36 75 ROL $75,X +00428D 1 76 75 ROR $75,X +00428F 1 A5 D0 LDA $D0 +004291 1 +004291 1 A6 D0 LDX $D0 +004293 1 9D 00 01 STA $0100,X +004296 1 2E B7 01 ROL $01B7 +004299 1 2E B7 01 ROL $01B7 +00429C 1 2E B7 01 ROL $01B7 +00429F 1 6E B7 01 ROR $01B7 +0042A2 1 BD 00 01 LDA $0100,X +0042A5 1 +0042A5 1 AE B7 01 LDX $01B7 +0042A8 1 8D DD 01 STA $01DD +0042AB 1 3E 00 01 ROL $0100,X +0042AE 1 7E 00 01 ROR $0100,X +0042B1 1 7E 00 01 ROR $0100,X +0042B4 1 +0042B4 1 ; CHECK test03 +0042B4 1 AD DD 01 LDA $01DD +0042B7 1 CD 03 02 CMP $0203 +0042BA 1 F0 08 BEQ test04 +0042BC 1 A9 03 LDA #$03 +0042BE 1 8D 10 02 STA $0210 +0042C1 1 4C C0 45 JMP theend +0042C4 1 +0042C4 1 +0042C4 1 ; expected result: $40 = 0x42 +0042C4 1 test04: +0042C4 1 A9 E8 LDA #$E8 ;originally:#$7C +0042C6 1 85 20 STA $20 +0042C8 1 A9 42 LDA #$42 ;originally:#$02 +0042CA 1 85 21 STA $21 +0042CC 1 A9 00 LDA #$00 +0042CE 1 09 03 ORA #$03 +0042D0 1 4C D5 42 JMP jump1 +0042D3 1 09 FF ORA #$FF ; not done +0042D5 1 jump1: +0042D5 1 09 30 ORA #$30 +0042D7 1 20 E1 42 JSR subr +0042DA 1 09 42 ORA #$42 +0042DC 1 6C 20 00 JMP ($0020) +0042DF 1 09 FF ORA #$FF ; not done +0042E1 1 subr: +0042E1 1 85 30 STA $30 +0042E3 1 A6 30 LDX $30 +0042E5 1 A9 00 LDA #$00 +0042E7 1 60 RTS +0042E8 1 final: +0042E8 1 95 0D STA $0D,X +0042EA 1 +0042EA 1 ; CHECK test04 +0042EA 1 A5 40 LDA $40 +0042EC 1 CD 04 02 CMP $0204 +0042EF 1 F0 08 BEQ test05 +0042F1 1 A9 04 LDA #$04 +0042F3 1 8D 10 02 STA $0210 +0042F6 1 4C C0 45 JMP theend +0042F9 1 +0042F9 1 +0042F9 1 ; expected result: $40 = 0x33 +0042F9 1 test05: +0042F9 1 A9 35 LDA #$35 +0042FB 1 +0042FB 1 AA TAX +0042FC 1 CA DEX +0042FD 1 CA DEX +0042FE 1 E8 INX +0042FF 1 8A TXA +004300 1 +004300 1 A8 TAY +004301 1 88 DEY +004302 1 88 DEY +004303 1 C8 INY +004304 1 98 TYA +004305 1 +004305 1 AA TAX +004306 1 A9 20 LDA #$20 +004308 1 9A TXS +004309 1 A2 10 LDX #$10 +00430B 1 BA TSX +00430C 1 8A TXA +00430D 1 +00430D 1 85 40 STA $40 +00430F 1 +00430F 1 ; CHECK test05 +00430F 1 A5 40 LDA $40 +004311 1 CD 05 02 CMP $0205 +004314 1 F0 08 BEQ test06 +004316 1 A9 05 LDA #$05 +004318 1 8D 10 02 STA $0210 +00431B 1 4C C0 45 JMP theend +00431E 1 +00431E 1 +00431E 1 ; expected result: $30 = 9D +00431E 1 test06: +00431E 1 +00431E 1 ; RESET TO CARRY FLAG = 0 +00431E 1 2A ROL +00431F 1 +00431F 1 A9 6A LDA #$6A +004321 1 85 50 STA $50 +004323 1 A9 6B LDA #$6B +004325 1 85 51 STA $51 +004327 1 A9 A1 LDA #$A1 +004329 1 85 60 STA $60 +00432B 1 A9 A2 LDA #$A2 +00432D 1 85 61 STA $61 +00432F 1 +00432F 1 A9 FF LDA #$FF +004331 1 69 FF ADC #$FF +004333 1 69 FF ADC #$FF +004335 1 E9 AE SBC #$AE +004337 1 +004337 1 85 40 STA $40 +004339 1 A6 40 LDX $40 +00433B 1 75 00 ADC $00,X +00433D 1 F5 01 SBC $01,X +00433F 1 +00433F 1 65 60 ADC $60 +004341 1 E5 61 SBC $61 +004343 1 +004343 1 8D 20 01 STA $0120 +004346 1 A9 4D LDA #$4D +004348 1 8D 21 01 STA $0121 +00434B 1 A9 23 LDA #$23 +00434D 1 6D 20 01 ADC $0120 +004350 1 ED 21 01 SBC $0121 +004353 1 +004353 1 85 F0 STA $F0 +004355 1 A6 F0 LDX $F0 +004357 1 A9 64 LDA #$64 +004359 1 8D 24 01 STA $0124 +00435C 1 A9 62 LDA #$62 +00435E 1 8D 25 01 STA $0125 +004361 1 A9 26 LDA #$26 +004363 1 7D 00 01 ADC $0100,X +004366 1 FD 01 01 SBC $0101,X +004369 1 +004369 1 85 F1 STA $F1 +00436B 1 A4 F1 LDY $F1 +00436D 1 A9 E5 LDA #$E5 +00436F 1 8D 28 01 STA $0128 +004372 1 A9 E9 LDA #$E9 +004374 1 8D 29 01 STA $0129 +004377 1 A9 34 LDA #$34 +004379 1 79 00 01 ADC $0100,Y +00437C 1 F9 01 01 SBC $0101,Y +00437F 1 +00437F 1 85 F2 STA $F2 +004381 1 A6 F2 LDX $F2 +004383 1 A9 20 LDA #$20 +004385 1 85 70 STA $70 +004387 1 A9 01 LDA #$01 +004389 1 85 71 STA $71 +00438B 1 A9 24 LDA #$24 +00438D 1 85 72 STA $72 +00438F 1 A9 01 LDA #$01 +004391 1 85 73 STA $73 +004393 1 61 41 ADC ($41,X) +004395 1 E1 3F SBC ($3F,X) +004397 1 +004397 1 85 F3 STA $F3 +004399 1 A4 F3 LDY $F3 +00439B 1 A9 DA LDA #$DA +00439D 1 85 80 STA $80 +00439F 1 A9 00 LDA #$00 +0043A1 1 85 81 STA $81 +0043A3 1 A9 DC LDA #$DC +0043A5 1 85 82 STA $82 +0043A7 1 A9 00 LDA #$00 +0043A9 1 85 83 STA $83 +0043AB 1 A9 AA LDA #$AA +0043AD 1 71 80 ADC ($80),Y +0043AF 1 F1 82 SBC ($82),Y +0043B1 1 85 30 STA $30 +0043B3 1 +0043B3 1 ; CHECK test06 +0043B3 1 A5 30 LDA $30 +0043B5 1 CD 06 02 CMP $0206 +0043B8 1 F0 08 BEQ test07 +0043BA 1 A9 06 LDA #$06 +0043BC 1 8D 10 02 STA $0210 +0043BF 1 4C C0 45 JMP theend +0043C2 1 +0043C2 1 +0043C2 1 ; expected result: $15 = 0x7F +0043C2 1 test07: +0043C2 1 ; prepare memory +0043C2 1 A9 00 LDA #$00 +0043C4 1 85 34 STA $34 +0043C6 1 A9 FF LDA #$FF +0043C8 1 8D 30 01 STA $0130 +0043CB 1 A9 99 LDA #$99 +0043CD 1 8D 9D 01 STA $019D +0043D0 1 A9 DB LDA #$DB +0043D2 1 8D 99 01 STA $0199 +0043D5 1 A9 2F LDA #$2F +0043D7 1 85 32 STA $32 +0043D9 1 A9 32 LDA #$32 +0043DB 1 85 4F STA $4F +0043DD 1 A9 30 LDA #$30 +0043DF 1 85 33 STA $33 +0043E1 1 A9 70 LDA #$70 +0043E3 1 85 AF STA $AF +0043E5 1 A9 18 LDA #$18 +0043E7 1 85 30 STA $30 +0043E9 1 +0043E9 1 ; imm +0043E9 1 C9 18 CMP #$18 +0043EB 1 F0 02 BEQ beq1 ; taken +0043ED 1 29 00 AND #$00 ; not done +0043EF 1 beq1: +0043EF 1 ; zpg +0043EF 1 09 01 ORA #$01 +0043F1 1 C5 30 CMP $30 +0043F3 1 D0 02 BNE bne1 ; taken +0043F5 1 29 00 AND #$00 ; not done +0043F7 1 bne1: +0043F7 1 ; abs +0043F7 1 A2 00 LDX #$00 +0043F9 1 CD 30 01 CMP $0130 +0043FC 1 F0 04 BEQ beq2 ; not taken +0043FE 1 85 40 STA $40 +004400 1 A6 40 LDX $40 +004402 1 beq2: +004402 1 ; zpx +004402 1 D5 27 CMP $27,X +004404 1 D0 06 BNE bne2 ; not taken +004406 1 09 84 ORA #$84 +004408 1 85 41 STA $41 +00440A 1 A6 41 LDX $41 +00440C 1 bne2: +00440C 1 ; abx +00440C 1 29 DB AND #$DB +00440E 1 DD 00 01 CMP $0100,X +004411 1 F0 02 BEQ beq3 ; taken +004413 1 29 00 AND #$00 ; not done +004415 1 beq3: +004415 1 ; aby +004415 1 85 42 STA $42 +004417 1 A4 42 LDY $42 +004419 1 29 00 AND #$00 +00441B 1 D9 00 01 CMP $0100,Y +00441E 1 D0 02 BNE bne3 ; taken +004420 1 09 0F ORA #$0F ; not done +004422 1 bne3: +004422 1 ; idx +004422 1 85 43 STA $43 +004424 1 A6 43 LDX $43 +004426 1 09 24 ORA #$24 +004428 1 C1 40 CMP ($40,X) +00442A 1 F0 02 BEQ beq4 ; not taken +00442C 1 09 7F ORA #$7F +00442E 1 beq4: +00442E 1 ; idy +00442E 1 85 44 STA $44 +004430 1 A4 44 LDY $44 +004432 1 49 0F EOR #$0F +004434 1 D1 33 CMP ($33),Y +004436 1 D0 04 BNE bne4 ; not taken +004438 1 A5 44 LDA $44 +00443A 1 85 15 STA $15 +00443C 1 bne4: +00443C 1 +00443C 1 ; CHECK test07 +00443C 1 A5 15 LDA $15 +00443E 1 CD 07 02 CMP $0207 +004441 1 F0 08 BEQ test08 +004443 1 A9 07 LDA #$07 +004445 1 8D 10 02 STA $0210 +004448 1 4C C0 45 JMP theend +00444B 1 +00444B 1 +00444B 1 ; expected result: $42 = 0xA5 +00444B 1 test08: +00444B 1 ; prepare memory +00444B 1 A9 A5 LDA #$A5 +00444D 1 85 20 STA $20 +00444F 1 8D 20 01 STA $0120 +004452 1 A9 5A LDA #$5A +004454 1 85 21 STA $21 +004456 1 +004456 1 ; cpx imm... +004456 1 A2 A5 LDX #$A5 +004458 1 E0 A5 CPX #$A5 +00445A 1 F0 02 BEQ b1 ; taken +00445C 1 A2 01 LDX #$01 ; not done +00445E 1 b1: +00445E 1 ; cpx zpg... +00445E 1 E4 20 CPX $20 +004460 1 F0 02 BEQ b2 ; taken +004462 1 A2 02 LDX #$02 ; not done +004464 1 b2: +004464 1 ; cpx abs... +004464 1 EC 20 01 CPX $0120 +004467 1 F0 02 BEQ b3 ; taken +004469 1 A2 03 LDX #$03 ; not done +00446B 1 b3: +00446B 1 ; cpy imm... +00446B 1 86 30 STX $30 +00446D 1 A4 30 LDY $30 +00446F 1 C0 A5 CPY #$A5 +004471 1 F0 02 BEQ b4 ; taken +004473 1 A0 04 LDY #$04 ; not done +004475 1 b4: +004475 1 ; cpy zpg... +004475 1 C4 20 CPY $20 +004477 1 F0 02 BEQ b5 ; taken +004479 1 A0 05 LDY #$05 ; not done +00447B 1 b5: +00447B 1 ; cpy abs... +00447B 1 CC 20 01 CPY $0120 +00447E 1 F0 02 BEQ b6 ; taken +004480 1 A0 06 LDY #$06 ; not done +004482 1 b6: +004482 1 ; bit zpg... +004482 1 84 31 STY $31 +004484 1 A5 31 LDA $31 +004486 1 24 20 BIT $20 +004488 1 D0 02 BNE b7 ; taken +00448A 1 A9 07 LDA #$07 ; not done +00448C 1 b7: +00448C 1 ; bit abs... +00448C 1 2C 20 01 BIT $0120 +00448F 1 D0 02 BNE b8 ; taken +004491 1 A9 08 LDA #$08 ; not done +004493 1 b8: +004493 1 24 21 BIT $21 +004495 1 D0 02 BNE b9 ; not taken +004497 1 85 42 STA $42 +004499 1 b9: +004499 1 +004499 1 ; CHECK test08 +004499 1 A5 42 LDA $42 +00449B 1 CD 08 02 CMP $0208 +00449E 1 F0 08 BEQ test09 +0044A0 1 A9 08 LDA #$08 +0044A2 1 8D 10 02 STA $0210 +0044A5 1 4C C0 45 JMP theend +0044A8 1 +0044A8 1 +0044A8 1 ; expected result: $80 = 0x1F +0044A8 1 test09: +0044A8 1 ; prepare memory +0044A8 1 A9 54 LDA #$54 +0044AA 1 85 32 STA $32 +0044AC 1 A9 B3 LDA #$B3 +0044AE 1 85 A1 STA $A1 +0044B0 1 A9 87 LDA #$87 +0044B2 1 85 43 STA $43 +0044B4 1 +0044B4 1 ; BPL +0044B4 1 A2 A1 LDX #$A1 +0044B6 1 10 02 BPL bpl1 ; not taken +0044B8 1 A2 32 LDX #$32 +0044BA 1 bpl1: +0044BA 1 B4 00 LDY $00,X +0044BC 1 10 04 BPL bpl2 ; taken +0044BE 1 A9 05 LDA #$05 ; not done +0044C0 1 A6 A1 LDX $A1 ; not done +0044C2 1 bpl2: +0044C2 1 +0044C2 1 ; BMI +0044C2 1 30 02 BMI bmi1 ; not taken +0044C4 1 E9 03 SBC #$03 +0044C6 1 bmi1: +0044C6 1 30 02 BMI bmi2 ; taken +0044C8 1 A9 41 LDA #$41 ; not done +0044CA 1 bmi2: +0044CA 1 +0044CA 1 ; BVC +0044CA 1 49 30 EOR #$30 +0044CC 1 85 32 STA $32 +0044CE 1 75 00 ADC $00,X +0044D0 1 50 02 BVC bvc1 ; not taken +0044D2 1 A9 03 LDA #$03 +0044D4 1 bvc1: +0044D4 1 85 54 STA $54 +0044D6 1 B6 00 LDX $00,Y +0044D8 1 75 51 ADC $51,X +0044DA 1 50 02 BVC bvc2 ; taken +0044DC 1 A9 E5 LDA #$E5 ; not done +0044DE 1 bvc2: +0044DE 1 +0044DE 1 ; BVS +0044DE 1 75 40 ADC $40,X +0044E0 1 70 05 BVS bvs1 ; not taken +0044E2 1 99 01 00 STA $0001,Y +0044E5 1 65 55 ADC $55 +0044E7 1 bvs1: +0044E7 1 70 02 BVS bvs2 ; taken +0044E9 1 A9 00 LDA #$00 +0044EB 1 bvs2: +0044EB 1 +0044EB 1 ; BCC +0044EB 1 69 F0 ADC #$F0 +0044ED 1 90 04 BCC bcc1 ; not taken +0044EF 1 85 60 STA $60 +0044F1 1 65 43 ADC $43 +0044F3 1 bcc1: +0044F3 1 90 02 BCC bcc2 ; taken +0044F5 1 A9 FF LDA #$FF +0044F7 1 bcc2: +0044F7 1 +0044F7 1 ; BCS +0044F7 1 65 54 ADC $54 +0044F9 1 B0 04 BCS bcs1 ; not taken +0044FB 1 69 87 ADC #$87 +0044FD 1 A6 60 LDX $60 +0044FF 1 bcs1: +0044FF 1 B0 02 BCS bcs2 ; taken +004501 1 A9 00 LDA #$00 ; not done +004503 1 bcs2: +004503 1 95 73 STA $73,X +004505 1 +004505 1 ; CHECK test09 +004505 1 A5 80 LDA $80 +004507 1 CD 09 02 CMP $0209 +00450A 1 F0 08 BEQ test10 +00450C 1 A9 09 LDA #$09 +00450E 1 8D 10 02 STA $0210 +004511 1 4C C0 45 JMP theend +004514 1 +004514 1 +004514 1 ; expected result: $30 = 0xCE +004514 1 test10: +004514 1 +004514 1 ; RESET TO CARRY = 0 & OVERFLOW = 0 +004514 1 69 00 ADC #$00 +004516 1 +004516 1 A9 99 LDA #$99 +004518 1 69 87 ADC #$87 +00451A 1 18 CLC +00451B 1 EA NOP +00451C 1 90 04 BCC t10bcc1 ; taken +00451E 1 69 60 ADC #$60 ; not done +004520 1 69 93 ADC #$93 ; not done +004522 1 t10bcc1: +004522 1 38 SEC +004523 1 EA NOP +004524 1 90 01 BCC t10bcc2 ; not taken +004526 1 B8 CLV +004527 1 t10bcc2: +004527 1 50 02 BVC t10bvc1 ; taken +004529 1 A9 00 LDA #$00 ; not done +00452B 1 t10bvc1: +00452B 1 69 AD ADC #$AD +00452D 1 EA NOP +00452E 1 85 30 STA $30 +004530 1 +004530 1 ; CHECK test10 +004530 1 A5 30 LDA $30 +004532 1 CD 0A 02 CMP $020A +004535 1 F0 08 BEQ test11 +004537 1 A9 0A LDA #$0A +004539 1 8D 10 02 STA $0210 +00453C 1 4C C0 45 JMP theend +00453F 1 +00453F 1 +00453F 1 ; expected result: $30 = 0x29 +00453F 1 test11: +00453F 1 +00453F 1 ; RESET TO CARRY = 0 & ZERO = 0 +00453F 1 69 01 ADC #$01 +004541 1 +004541 1 A9 27 LDA #$27 +004543 1 69 01 ADC #$01 +004545 1 38 SEC +004546 1 08 PHP +004547 1 18 CLC +004548 1 28 PLP +004549 1 69 00 ADC #$00 +00454B 1 48 PHA +00454C 1 A9 00 LDA #$00 +00454E 1 68 PLA +00454F 1 85 30 STA $30 +004551 1 +004551 1 ; CHECK test11 +004551 1 A5 30 LDA $30 +004553 1 CD 0B 02 CMP $020B +004556 1 F0 08 BEQ test12 +004558 1 A9 0B LDA #$0B +00455A 1 8D 10 02 STA $0210 +00455D 1 4C C0 45 JMP theend +004560 1 +004560 1 +004560 1 ; expected result: $33 = 0x42 +004560 1 test12: +004560 1 18 CLC +004561 1 A9 42 LDA #$42 +004563 1 90 04 BCC runstuff +004565 1 85 33 STA $33 +004567 1 B0 0A BCS t12end +004569 1 runstuff: +004569 1 A9 45 LDA #$45 +00456B 1 48 PHA +00456C 1 A9 61 LDA #$61 +00456E 1 48 PHA +00456F 1 38 SEC +004570 1 08 PHP +004571 1 18 CLC +004572 1 40 RTI +004573 1 t12end: +004573 1 +004573 1 ; CHECK test12 +004573 1 A5 33 LDA $33 +004575 1 CD 0C 02 CMP $020C +004578 1 F0 08 BEQ test13 +00457A 1 A9 0C LDA #$0C +00457C 1 8D 10 02 STA $0210 +00457F 1 4C C0 45 JMP theend +004582 1 +004582 1 +004582 1 ; expected result: $21 = 0x6C (simulator) +004582 1 ; $21 = 0x0C (ours) +004582 1 test13: +004582 1 +004582 1 ; RESET TO CARRY = 0 & ZERO = 0 +004582 1 69 01 ADC #$01 +004584 1 +004584 1 78 SEI +004585 1 F8 SED +004586 1 08 PHP +004587 1 68 PLA +004588 1 85 20 STA $20 +00458A 1 58 CLI +00458B 1 D8 CLD +00458C 1 08 PHP +00458D 1 68 PLA +00458E 1 65 20 ADC $20 +004590 1 85 21 STA $21 +004592 1 +004592 1 ; CHECK test13 +004592 1 A5 21 LDA $21 +004594 1 CD 0D 02 CMP $020D +004597 1 F0 08 BEQ test14 +004599 1 A9 0D LDA #$0D +00459B 1 8D 10 02 STA $0210 +00459E 1 4C C0 45 JMP theend +0045A1 1 +0045A1 1 +0045A1 1 ; expect result: $60 = 0x42 +0045A1 1 test14: +0045A1 1 ; !!! NOTICE: BRK doesn't work in this +0045A1 1 ; simulator, so commented instructions +0045A1 1 ; are what should be executed... +0045A1 1 ;JMP pass_intrp +0045A1 1 A9 41 LDA #$41 +0045A3 1 85 60 STA $60 +0045A5 1 ;RTI +0045A5 1 ;pass_intrp: +0045A5 1 ;LDA #$FF +0045A5 1 ;STA $60 +0045A5 1 ;BRK (two bytes) +0045A5 1 E6 60 INC $60 +0045A7 1 +0045A7 1 ; CHECK test14 +0045A7 1 A5 60 LDA $60 +0045A9 1 CD 0E 02 CMP $020E +0045AC 1 F0 08 BEQ suiteafinal +0045AE 1 A9 0E LDA #$0E +0045B0 1 8D 10 02 STA $0210 +0045B3 1 4C C0 45 JMP theend +0045B6 1 +0045B6 1 suiteafinal: +0045B6 1 ; IF $0210 == 0xFE, INCREMENT +0045B6 1 ; (checking that it didn't +0045B6 1 ; happen to wander off and +0045B6 1 ; not run our instructions +0045B6 1 ; to say which tests failed...) +0045B6 1 A9 FE LDA #$FE +0045B8 1 CD 10 02 CMP $0210 +0045BB 1 D0 03 BNE theend +0045BD 1 EE 10 02 INC $0210 +0045C0 1 theend: +0045C0 1 00 BRK +0045C1 1 00 BRK +0045C2 1 ;JMP theend +0045C2 1 A2 FF LDX #$FF +0045C4 1 9A TXS +0045C5 1 60 RTS +0045C6 1 +0045C6 1 .segment "KERN" +0045C6 1 +0045C6 1 .ORG $FF00 +00FF00 1 +00FF00 1 40 RTI +00FF01 1 +00FF01 1 .segment "VECT" +00FF01 1 +00FF01 1 .ORG $FFFA +00FFFA 1 +00FFFA 1 00 FF 00 FF .BYTE $00,$FF,$00,$FF,$00,$FF +00FFFE 1 00 FF +010000 1 +010000 1 ;-------------------------- END +010000 1 diff --git a/testall.o b/testall.o new file mode 100644 index 0000000000000000000000000000000000000000..3aa76535e5bd529fa8d97252c41aa97b8d28500c GIT binary patch literal 11227 zcmYk?33yahmIv^6ZYoQK#X`GVdU{$5L?v`fCt(q1T1^5`Y@;j!Z9CIW5)5M$Fc6|W zJ>5!x3$i>6OMn2;5K{%0C4hh|8e|bSeW5Bsa+gLyf}>pX*zA?x!G&j{X56G z-s|&!DW!7GFBrc*S)}iuKOfT7E2pP<#k*~TauV@9Ka21ES)B8;IM>Ev`}2Ob-kb5o z&W_V(XR?>6x^zd(4e4Ge4sd^wxHT10Rx!V_#lgV6(H0$L71Q1pmjd_KwkXOf=3i{F z1-QSlMWw7_{?!&o0{6GJn53*?ZnDKZ;NEPD0c8~vw#9D1?O=<^$||O#E!G0}7F$eF zRxzDy@de=CYKy7LD&{s@i~#p`TTD|{F`aGkX5ePnVo+Jdbg{*K!2O*qrYozM-`ipa zaPP3iR>~@-t1adM_Ybz%T3N+p+Tw8FX4zsJWfhZ+N#J&~#kR^SrdR94=W{Tqzbo-2 zDqTR`zuCcZp#R<0DuMZ@^C(jQiUp<_dx7i#f3R0n|Y4pAwmBNwtc35Urr8fJLj+JjB#0 z=3(@Ljr~}(N@f2i&mNapNUlN0CWCov*$qF;}`^M{|lXF1}-bHmK^6P129P%1^>v-fLnmhq{JDRUKPwQV~Kh=|w z*HAM>?BU*|dMfH+YNjF2qS{5?ftu;aZ>0JqVXlN%0#4JF=?bKa}hU*1^L~40SddJKDB@jrP zSNtsz$U}Ah76?SY$}OmAz^SKDH-dq%AP^J9!2Q%+jD`+^K+F>C@DgD|l3e*1(3f&6wk7TO5{`RfWSTrUWuZWXo&Q@xs7Qu7+lP)^-7I76l&5VIBoU8uVb z4OxOf% z`5n}K7tgFr5QvGP;UCo9hlWvtK+Jn+SVY}sG>jGm64{R<)zA*_<49pDA0Y2Yb3a7h ziRuHKr{)vng;XCzojCw9LN01j$eH3{fHJ@^x>d#Q`P0i=Xi>W?_ybm?U zIZyQ$sOM920{NZPJ&6a_Um*~43JteV_e(SkPzc1F#uaL*dj<^y6#|Kz#SS&J?kfz$ zY1TPB;vCxUYvg%!z0f98l^cN6F<1Fkk zOAttHH9E=!fqXj0UqB#DbNvMb(l`%$j1dGAo~`eqg)V3(?Y)kfi%|o9SEfQ z6}up1^y50_bloE6G+K}6Ihs~CuugYIP#;BiMw!!yVNPR9?Y#H5R|FDYrtF(9jhf}k z{@FxPcLfGQ3V{?f+5zuN5`maCn0S!>X{}29byd>WLA@SF=ucBNFsCUSnbZ3=F{hC? znA2zza~j-?>+h!eEz}F?ueRWk70@ADnbRTLnA3IJnbYVF?ni?=alKsXzGM4US3w|; z@4{DsBM9X2-TndsxoMBTfIyn|`U?o8G3IZIK!W>l)k<3Xo2d&{vM!&%rw;N{cnFW6j7Exuk8kE zy&#aT=lul)()AmE0fCH+`wIx9>4Lv00%^SHcOVe=5*CgM0=eh1KY~D>zv3?-kmtYi z7ZAvbAN@TLNbLWxkfabu{3m|LQ*)J{JnCM{XXgOiab(Sj*5tHgss=oFw~_tDc8_+R(@X%;nJ7LflF~A&_`& z65hAeyo`+l)O`g5A%#E+>g<5`zC|D=f{7k<>0%sZ&k}0j>7{VWGPq;~e6f+Pgu7P3 zd8^^lHPEcZb;5N1I;_{fj`a}Tv>xkIHbA|JkAOy+nA6y1++ngpAn~{ONT}I@3nWu_ ztN%z4NWnJ$ksy#RyLsfjn0$)rcX8?d)WlGKn(BS151{5f)E80RjCvt8`%$l_`hC=k zsQD1}7Fzldb6WZ_b9&|g@fr&`A)8 zIfsT~>VA!eTLpob^Jut@{_`7rb31}SuEwz-fR!erI|~9a zSI}^Vy5FH8LlB7h9u3{;|NP*e34#3Zqkkp@qJP2}zNOKt%&EDC9m7<&pk7AJ*noYB z3e}YX`w|{S%{bIMQ9T~@(bP=fJk=WYa#}Poka%TEEPM)qLVX-HGdNH6Ow`9yGYj>lbkuB|e=NOFjeH!{b1NK_F%+8V*x;85(K?ftclJ_yg4|aD;4X8d1-tdL`=ps9A-2 zCe^D^??%mQsFzW_2KANHtVO*&)$35tq`Nn;PU9Qx4Tz!{n~*y+*o1zeJ2rDa+WZ#h zX~q`L)B5e0cWCTwTUVKaK;kd&xYZyNoaISn4e1v=5K$MKDrL*rj?e;Pc2{uikJ68rU`4X2sY2hO1XI=cTX z_U}fUzry|j8ac;#s=r45OB%VroW{Pj^D0##koZNu2&lP)1Ef;-G6q5lffQWvUjzum z{Dg@J)mL%JFmlR@kg-&QdJ&Q&n%xR}6@-S^)%>AfYg8fqI z@0a-pKp@S_IY7+{45ZOcD^c%2n^&=)>ea~eXk;C88hafVOj8IXzCIa0zo^-ON1jIA zjTi_i1X8fc4tPJm5Qy1=i9u9v#U-<;*@pTWs<)%Qh?=)ipG5Tz)O*wVU8pajq1|{S ziq`KzJ)5q57j=h*V#ov3>_eVRqwjHln)w0ur)NGyJ&9(1%sMp(kmu3|4x>Ml>LYv} zwBjiG9oqj>?nljMydKrZFh7XCew_2P;tS*hX#W%3kD8OnPtuAr$a84fS>(yI=Bs4; zw`6e;NXa=IU@$E^&kIoV4G!$k(u>IBwCWQ215{teeucE;3i95x>U-`_%@5eGg_d09 z1EH&~aerFcg8oS~IyS|=77OXBaVhpSr>Gf^+@aMPc{z=|i21QJHrduyP$7``loWgq zQ8P8gzITJvorZysLLddM9q_(~5J>54OgPlcL0&^k=OUj(+s{j}|L}0O23E~aX`A?C zdVrQLz%3Ng(uK%p(Oxfe{uR#GVP5ElMOg3uD%KS>4cNz_rBR$~1wFeMb9xCLStgAv zV@_ks@kG)U0*SBSBc!Gg8>druB?dwYffTIrA0YxMU5^Q&W+U?3Y3U}`X|FeM)U-EY z`zF|VGc0`z{SNKB1?y%j*Xfhnu&%fB7HMQBa~gXGchE{9koYd%GBvxgaVzTX@oyP{ z6zuhH8G*EK=8^VeGLKfh&#wlmKfqDC(N!Pf%IVa6jQM=p_W<|(1nWh#??J5hIt0@W z!}dpD&QTaS#_Q48aokC3g+St8@Ybn0feW>!?n(dF5lF!)|JD&m>3K{D{aYND{{8|? z`xZWV5$a1gQkXt^8S9^1VgGmR{~nh7z<#QKMBaf$t}>^wYdCQmg+SshyhUoprrLKx z8|qf3+P_GK6apz2mzsEqc<%%RVy0pum+EP$c#Y9hGnvy!HFFx9gDbRE2qZo?wO!&R zkw(otT%av=Yy2Z2kb?RCkr0Tf$HX-nd)1#nAk7VSLXznDh~I!foW-g3#pNu4^-Hm1 z3!T3V>xIh`CjMhle&YXSI!YYLc`dQl%ggRdv1=*be}UX!FCZ-&Qm^yY68Q}Yz5GVz zzhQo}r}yiAr`4E}@-aojhj%S1AJKYfQO_RXA=zECx^>M?_LfJFN$y%+`uCEQL{nyF zIw&hDFHafsWJ$@$Cs4=&*`OQfp8QnBh_b9ec}4N)n>s!Yj+YqrI0Z&QitMs<@jf?yib^sN$Zg_)b;qt>1-?y8^{!!@a%AhI`wLDD|QdrC#*x zP%nCRXd)_4MCD#IG_f``u{JcZHnbe~mz9}1CMz>hrP)?*2YZDqlASiXVr2Q4iebZ2 z#$;vtk17ifC#!p_@`}