From 52cd458e768b8afb729ba4b3acec4832e35a19fc Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Fri, 7 Jan 2022 14:06:15 -0800 Subject: [PATCH 01/34] Add PS2INFO - Replaced kbdinfo with more comprehensive ps2info - Started process of clarifying licensing --- Doc/ROM Applications.pdf | Bin 193894 -> 193895 bytes Doc/RomWBW Applications.pdf | Bin 229562 -> 229563 bytes Doc/RomWBW Architecture.pdf | Bin 447508 -> 447508 bytes Doc/RomWBW Disk Catalog.pdf | Bin 134794 -> 134793 bytes Doc/RomWBW Getting Started.pdf | Bin 271719 -> 277975 bytes ReadMe.md | 46 +- ReadMe.txt | 46 +- Source/Apps/Test/Build.cmd | 2 +- Source/Apps/Test/Clean.cmd | 2 +- Source/Apps/Test/Makefile | 2 +- Source/Apps/Test/kbdinfo/Build.cmd | 10 - Source/Apps/Test/kbdinfo/mseinfo.asm | 896 ------------------ Source/Apps/Test/ps2info/Build.cmd | 10 + .../Apps/Test/{kbdinfo => ps2info}/Clean.cmd | 0 .../Apps/Test/{kbdinfo => ps2info}/Makefile | 2 +- .../kbdinfo.asm => ps2info/ps2info.asm} | 640 +++++++++++-- Source/Apps/VGM/Tunes/filthy01.vgm | Bin 0 -> 27392 bytes Source/Doc/GettingStarted.md | 97 +- Source/Images/fd_zsdos.txt | 2 +- 19 files changed, 733 insertions(+), 1022 deletions(-) delete mode 100644 Source/Apps/Test/kbdinfo/Build.cmd delete mode 100644 Source/Apps/Test/kbdinfo/mseinfo.asm create mode 100644 Source/Apps/Test/ps2info/Build.cmd rename Source/Apps/Test/{kbdinfo => ps2info}/Clean.cmd (100%) rename Source/Apps/Test/{kbdinfo => ps2info}/Makefile (56%) rename Source/Apps/Test/{kbdinfo/kbdinfo.asm => ps2info/ps2info.asm} (53%) create mode 100644 Source/Apps/VGM/Tunes/filthy01.vgm diff --git a/Doc/ROM Applications.pdf b/Doc/ROM Applications.pdf index bdf95a31d360f324385c2a2582337d4ca9f002be..b1533de561942db48a49ad84e44d78774af6fa38 100644 GIT binary patch delta 10156 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 delta 11961 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 diff --git a/Doc/RomWBW Architecture.pdf b/Doc/RomWBW Architecture.pdf index 7e5baed75c8e50777c9abc4207a8892c6f2dc079..cf4ad4077501fb2046602066eb21cddad764e8d2 100644 GIT binary patch delta 600 zcmbQTLVC&y=?Qi9r}J(b2)KU#)fE}U?U(lBnqH~A8?#6*^TJ4x$Q|omNp!58GBNSX zduySmM@$1aF9bZ<+a4|>nA4CDdC@hsQpjL~xr9aIc0NtRHRV^|cTIfq$+gH#uX}Ux zydA%GBv)JykAG^X`%*Y`exi78=~qR89UUhFTE2y00 zbM&j)^|mX!(t`MJFO24IzjO8(!!gfCCnj4ORp~!7+-G?7&sx7FyZ-EX`+cjKp=Ngs zTYS;-;_o-s&Qq7#VE7`2Ay?{Ty>R#39KriNf?>voIBNMWFj#NVo1xi|9l%$yO6BIM zpQX<4#3w~C9Dh`Q`~5t=<`%8>r|-zmbBhbzHPyWMcHVT+3@86ED~XL8w<+`=PnPva zl)Gr3_T?Arskp@X=EfWU#7&Ud^l?G1OPbx*!zbOZPP;O{Hhj~Rl`+|xhn=_o&)1RD zZcn+Bx~}lO@%OK3+i%$|a`~-(Cbjl{SUqF@)NR){OER%!@tasACmAMLnwpuJnx~p1 zHS6ST*U4eL-GMIAF7}lXh?#(x8Hic7i+yD^o6BuvU}#`$Xl86~VlmxOn@OC<2uWmn z)g(46M`veOM@s{96JrBIQ#V&P3nvQ;Cu3&|H#buw10xGdLpM7G8$wE^f4|Ho3jhWM B02}}S delta 600 zcmbQTLVC&y=?Qi9{`pr71dhJ{DN?+JzbyTay?F$e_5^_d*DnngItO#YU*&bpzS@<4 zUgg}hTvZ{>vNzxF{dvTBNKD`w?>>pn`5Y`ydikath+b|e_~rMra%ZWZpF)ca*U#=Q zj@(hTUwwz%Ed84K+pk!L#vWO>>)ESVhk`)$X2D(Y2}-YK9AMLX#96;<{s-SXC*I#} zkIa~CX7|H0gPB_?{rn{VAXa5NJ5GHe=L=@LHh&1y>Q6GY&;S2)k{{+rDNL|r)17luMe|crnT=}?OX|yEh71ibGGTt*tw&4mucVeFy-Q_ zn@=Z8hWVWSv;0-P@f-O*W#+5bOC|gGgX4m&L$`UK&b!8|aYatIT>sUzTT+!)b5k4^ zo)-C=-1%<4(@AdIDQ_o5)a!cqP5!tb=ZZ^7UaRxQiDF0RJFn9zUFmW3aK&`~|3^2; z)i_*UZufjvR{W0m-0!pR?oHd0ZlHgBd+cZNuZy-RY?fqV$>L8-F*Z(2OExk$OH4LM zO=;H2*{+krc)J5#qFwAOBM>tIF*6XeY!~~=YBrbK(9p=h!qCjv(8OT6qc)Q`j}el{ z_Nqy2R*uf*My8HN1||k>hR%kLZmw>ohDI*NjwWUXu4Zmd=EfFw3O0n4O#gnFO%?$8 CZvSim diff --git a/Doc/RomWBW Disk Catalog.pdf b/Doc/RomWBW Disk Catalog.pdf index 93265d75bbe47c0a6bcd4f24328ccee2f99e5d1b..b9cc152b188cd2efe025292aa6ab4e2ae4659c02 100644 GIT binary patch delta 5385 zcmai&du-lS8OM2Fck4R_HeHd0%i7FJG{DYt?q@*d?brmILJ61!7+DRB#URp^0cMi& zh9F^JWDDb{tl5PTjd4pViUvlYAsM6!x=iHq2eX@o37SwY>(+7m9~84q?>L(1eTU+-VG{@a(mt-gHE*x}a4mz;9uid}!Z=`W8~n|kN3 zUEWwadq(Tlj(?qU)rV^~zIxBvi+(?FXyg2|%-5DyhjwoLrup@{yBga!??2&tr)_)o zoj>pB{Kn!-^NZ{6Uj4?|FTK0(z)xPhMPK>Jo~QR-vF5i6o_*=bw+{TZ`P84+UsyPH z;=ZOkPuPCWPyg99Hl_de4_5c>UACm_jLU!b_@kGf_tm#s)~vtQ4PSES;d$q`Ex7mf zN1lG?iSCErdd1qp1o<~xvdw+^M3TJ3s=t#^PjtB+RA_LJoJ?{tw*kU=GFJ-&00F;XT6)ZeWz#m z-b-#A?O!zS%K5dfi?>Z#*_ic%{nyu)U%lkzffbj&wrX_zho`R?oLhP7-IJdi|ETYg zuKzs$#ySc6Q**{8o=eSI(q=n2N=Z}q5 z&T1vOq+K2vtF&C;CoYlJDlighqg3GgOtL!DAs~b?C6^ zt=ck2Sx3Tl>%Gpqi(DB0Lj|Fj(M~zT0)2o`;XbEvr$kOl4t$^yrt{o_euVQ@Hkhye{!X0^|~1;HILRwvz>N>YOUoe7ynZb1 z6`cox=odyO6}e@WNHlV5qBscF_{1}ZFbb3KTRIxRlaAk`7Vf7F-BsxoLMGLFW4Y-d zDB7?E1Rix1kEm1|l}Nh9Rqi&7g21EbaLe;3I+U+)HyT`rb@Vrp9H*?PYuqe}SEDmV zp><4-2v%5zv%w?bys|2f6a+6+(8U$tT#CXuI6|4K)s_xPC&Np`KnB$pRK@R+L=|S9tm{}+oF90 z^d=VSvYjJfg;yc3D+s0$+fkAeHDY_r6V8wDZhO3XSTm?%|Y%E`M6g2e*!xD)3GGrD4`urH;Q+h+j5jK-*r@rs8t zdY+{+(&KH`TM%MEGXCoYtzqvc76hA8I2f{;srgj-fQDZ_-CD>Wc^_M=5J;~qOX z)mxcZ&l$2Fbly@BVhLr;TS^QtgIg9NX0p*q9f{To=OXrVL^8qT z`b=0M=qd5XBjF$MXe#e+hJ{ST0+!(_ z%XA_TEZ=2tJ$4%$8y)dMgc4VU3nJOv0D_OW=uP4k3|R~;bELiE9R)IceV7;o$Sf~a z$lS3$dHlpc7@W=Rvt)iq2l15xGVy+Z%p%3T1;IKwmT;W8X+ba2(P8Zi=C~9bWu|EE_492$9g@4gyR~Q4t#_=t RVMPu2NL1_SSajLq+Na80pL+lR delta 6311 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 Y4UY=-SuFug0LwXALR)*b!yJkK2mY>~h5!Hn delta 45384 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≺eI&g(aMBT2AxpN;IrTzc*D67nOU(^ ze;>8R``4ryeV$Q;ahru346AxpeE*_rlP*e}dZO~JTd{xDDt46V;a?2!jZtT{)cS+8A4~0aVZ-^`s(EmvRmoaPvh39-ym;fF z6UuI$_VAX6-!Ax|XC!rVTl>;O&A|8FyZb4bJ?d|VhtJM+NREoBr)zUH?3TH=x0b+t z{D=xstiG_j>qY_i2Y1asj0aKkrp+-wl+UQSO}gJZRaE8nFc3Vx zSFt&SrFLKTlKwj?1BM}PvHaDxX;g5kHeuh17O59}_ah9SOuy6T7bcOz2l1QoR#5+i?^fblJysw$BEqTM`WDDDSxJvOAeCJAj zpi^#^$yoCSdcAjIsozY044?{!68u;&m&5X0WCa@NAs%q`2 z%Z22I8q=2^ulJ_71iu-D9~Fk|$@gx$by%?fc86F~7S~W?>UDp$WBx<#Er-J13oKNp zE*x>z)%Pth<;q&P6~?ZqoOAfyA;Gec(7{x{A5iew)f+#lOkS7M*j}-Sw%dcZcP>5B ze*S`;!X7cy(ERd{%uvmXciGwn4_T0(2AXUHaaKp3ypx-XsG;+mnW~94*S>$l+x{bs zcGoLG+a})wLzgcH)#c|paQSyPAR}|~Z2dX3^73zK%QI&rj9N2Dx$g>xxFf12RIcq5 z)Rx9)`*XkA-SO6}Uib3~RLhff86O5-s9N`rhlxi#Zajqu{FQ z@O`^;#b@_XEg$ptLn77(1P}JwJMdL!?c8(5*#2SHU|v$HVT) zoPJbte>6R8mO4)0Tx@ySDo2Tcv+fKP=f^k3Ca^ZM`;=lW)x_t6=REJo>UodiAI9d_ z@3Y69FWHuLxS~Hr{PEQg9VbVXfecE2tf*{rMnc~`G1gZ}0*=0BNelW_V~%fk>ucr0 zp2W%MsL)vRo|-+JVeg2w-*)bIc|Nn08vFpGAV|BcPnTh6Z&Pwl+nC7AsmU&e<^#cqaPxQ*vhec-AT^Y{C?8Q}$f`B6n=2=H&<6d0yxUnth<#9j8yMw2LB+RTnpV@o#*kS2iW7%VeCRFgX zagkpv{Y3R=59%z=_@v}SkK{k`dR>^Y_jJ+gnC!H-6M@slo!wjvh^Nxen(KG-Pd*ko zsi*am=)01#mx@Q})IX^c=J@0~sG8EVY-)L#&}h&xpr!6g#vcggj=cV?E$&l(KpVBusbK{(C@!(H621hS^LR-v|k0E zi!Whl?w0s*x8v-*4r9HM$1ZI4FZHz0OzUs*K~_a$4-ac_gq{_hAOz^og(8EF*7Rk( zux$~@x^-~vuD|iQPoWDB%l@yhD-Xyq`~G+$nk-pU)T=Bps&{$b4U@I3BW2fwC`8*- zwlFVa8A1%hW0|qd7+bdR#TYwTCX5)ynk`LN-Kp=zKb?^QyIL7QJd$ZpKab$R$-;j9A#fhR1Hyk0`n2dNAy1|7FG=^Jn&bzA1U$ii9nnyG}bex8aF)p3CEo*Q@@0 z&6L02Hy-k|a;xJxlU)W43piG@IisswikW{Rclo9G%6kud z;g~*tOC??L!yTsU*$Lf_3U$BF${k!Q=ycqb7Jg!qpc&eaaT4cOB1($xPPIW&ArtCMqwZ_JuKKlj$N9m7^lY0-GC@5pJL zy6x>#>A;4VU7F4dIwWLVbScXAI55TMo5!OEyDlkle|vm^|EAd|2d_Eu^^~}#j!&8{ z**n*5&*Im=osa){Ye3Jhx0bgJ9(lFyxe~u{^WQ}VU09Omxy*de?xsnHyDhI8bEw&a zIXlz49zFB>vk{i3ZT{Vz`g;D56@$IU|Gu>8h_*L3j=k;}aQIh4joLF_q^5+Q-uHRh zgH9{7#-JY6RyNfY*y;|q9(ZuMPXAG-{v7$P%g(PF@~!3vigQ=j~#TV)MCoAb4g(<8+Eqc`mxvAYA!zQoP&b98Sb{qTb7sBepW!jhi+3Y zhWC3l|6tzA9ap!GH#IzQJ2C5(E%$Bz0`IK1j_zUAZ)#oK);k71ik=ZT_RddZRxNpU z_Q*}`nDqs`en(uv**1=i!W}ovx)Rm(>UM{v9b*a%eT$u)E=?P}b9?OU==Omt0xKV# zoP9q3RQ#Nqhc9O}o4s>#jqj2+W)$z}KHIs@!;F;O|2#iX<5J?$dd~~;+b>(myG}Tj zY3pCFa92I|>BSvC^vo}C3(lx-9B}QNb6(QZ33>0cs_DAvAML3&t66bfnoE}Fn<=~bKAlGW_WrWdo(Dy_{TpVkuQPMf>L{0I zQ(o4(-l*uOAA-scAK8yz?|q|H?t|sGwuXCK^{?WdPPdhNp4wQO_5R6sr+#b@#E%4IR$@6wTGBvJMacxP>++9`k&iG$g^l|^wH(ujvzK={8 zUDD^5<`3E(O8)rOlF&;DwuYg3AF^}f{`@0#+h3JNZ#Zo{Se$Ss(<$4(e7bk&Z^iRl z7d|(bZ%&_gAp47DAF54i-S1?`q;rdRzq{A7SxokrKIvbrz3}wT(0QL(FAll&p#74- z3k@rJyjHoi?D=BCd+VL_V%@+ku_hC@Ah6ZukC%J; zPYYfcb>Yjq1D9vEZMY@QHZF9=Kkd1LO^!{j{9E3(dzL?LH3|uC`BS$XQ^(Oqw*K&; z%NM(@=br0cC*^{7P0u4Uc5VLN*!JtARa<@$K4|EH*|xO%4f4iSO!Vzr_3ZAze}nq2 z2>L-dv!Pwu&7^&kXN`W}GPYml@oD$?n(I5vJf`WBkm`AU#?lL^Ykx^N@3&=X^OUXM zPdV1+*nqii?}MUUdliSzOpko>_G7@<+bcU)>(2@<&uj>UX4F?D26~wi8LSV)s-SKfUt(UYE0VDK*l^RbTgd!ZmzND#z2eKw(|Wl~5q_$7v{Q)9 zqR&}%qUx6KjDBZtR?#gCJG*Di`3->i`-uRZSKCWj^pQ>dp&LDS$nMg&z zUGO5foX4&kUsnvQ>3O_H%kKuxcUzOY^XCe=K`9y0TeD*wr&ZfjvS7{leGR9d zG5Bq(vUA_$cj@D}xSX@=J{-+I*yz~K;K$#Lo0vUAZw%P_#4qo7w#%`qX}quh;gJoW zT+LhPl4A78@zngTiydk^m$GE|qla_Otn2%I+8}FTbaYyNUY+A{X}u5q)5fX7ye(DV zopig?*)RHGr)`TX-40ljR-wnP%f>;s2M2F#TFKxNw7=xSr6G;0)qno?;@+o&zrMe- z#^$2quf95Cd@waItozJPi{jqQ@YjS^%l~+J$%2c~B_-b{{Wx>|!9%B0Q+Hi^oo(~$ zdZ6LF8|yre_dU5}&A{tVCN}VjZmk`)**&cC7UvDAH%pc|XIlOINB8U4yT`V#J$|Zc z{PNq?-(K6d+vQMykNn)JXA3j?$Jx&A9Prn$kb->^3K}@x&KUfDRc41Y_mK7LMhzNh zZTangc2(~idwf*uI{|-wG5X&#N#SG8UhLCiWA85Bb8K0+_O}i`w5{-`{hyzzI%vhx zg*%?jY`H0Wq1Wf(%M$K|`*pZ-!urLaa#v@0p5q&YzRFG8p4zbUg?8PaRm|y|9zD0B zWpQ!x-RmpAT6ulcr6no#yL|C3#l`!`=Fq;q7v^@pGOu8h&)wUHe;%EjYCeDD%%r(9 ze?Rrh#Jr}PTV@@MSf3g8l`Z)MckiF&!>`>PU*}S2%YerR`ZNp(nLb~8r&gQ(P4T9A z?v&53SMq>;&HCX(U)wjjk&)@uUoP%EWRFwT zdN*HQ$jP2#+CHe&kLgA3_ZBx^d(0?_YOox4*T` z5La$vx}U9bt?`=2GyBiYb;^EwZR?T|Ke_d~GcMjdaN|gauz)`n9sIn`_z?{@ubg=8 zUe{mVdUR}5u2$`N$A)KJ7&*~*=#Xx0)Ap^un!f+!BE=j(<>7>ar!nrwtDNb2U{l1Fv{p05JQ#fRP^fL;n!3Y}onPP)>auF|h^?>N zyzqGI6OiZBH_#>if_}pZhneoViL(xs_?`Cgp0>Sjt#y|hb&hQAHM-NfliRZgrM`aC zRP!t|xYIA2Cw6JM;KZ|wH@c<$ThRPu!16n&^51BkBe{5XXidT(0BHAKQCch z9iL`8ZQGQ=k)daoHyL`zR`b_XbK`59ue_hrRD1ukH>VvpY)vb_ZPt9(-yW{d_$$VB zYwHi%4W{rP-Mdd&@chldj@KOrY(4Yr_9nsMYQ<~o_GOGRq?``dHSoLCVW+E;WBzX) zUrsyNU7Ix1eOl;DL$@v;YAkWB@09V)pMOU^I#Yh`m3pC*Jq!b9Z3&pM{Xpt+{{^-m zV(UGrcCX9!MT-X&{q=RfwK*eO-gn5joN!(juyEb|cbl(1PSH-Bw0fhdbECb-zWX(? zdiA3rowEG?D2$n(_FKu5&R%qH^1|)Z)v5JfI=CnLrgqr2ukd*< zu5HQYkuEd)cx|wi`+B$Qoi0NjjhQs=Pv>`OF9z=U_m1tNmzK3{Lo zfGvH`z8HA;^SjzfW6#z|dsQ>%z;ADcwf8!lQSM;tyGI7ZRbFBC>)Ef#uRko$+IqKH zwO)1KI=P+nFZbm|A^m!*gO$HCo^7*vV3Q_>*%^(8^sLyfLQ$k+^tYCXjK=2=wl#$8 zHJ|*mdi$rn9xm!`ShzpyStVP!{wEIA5Okh+KvU?&Ig8iFEA7}P|*biVW?_pr8}eg|VjJup0fL0y?l?nmKF zCU+m@*~ABBbuMsi_I^0Uy}(s>UMM-swP>c4FDZR$gWl48`#$k~cl!@w;c88ov0*sQP#Z?j!_X#+!yGKW&psvm! zJ)G7_&ki&?=?xJIbjo8%uW2+o>E%oK;_?|~V|_u5B|UCIsZa6YhlUjT6zP#)`s<{} z8ycPT{9iZJONlExstAkrA5M?v^0t%E^&Wurkc z1A4l=mXvoEr(4COck=HQkr)-1j6JHN7Ig$fs(5LE?fFG&?&{0eCH$%)6kq3@yGycK zD!S4t$|ZRrb@GZxm8LX$36VxGk**$@l<}8H>!R1%(I!8dQdUKrl*Sg*zSN$AVcpt5E(n*V%o!#)Xw4Bwx<3pKh5eHHG$xfG?9N$bfSn>);cl~ zT0vU?H99qi(~_c%897`S`C0vr^fLxODdal6aP?{1$$_y z^88AgAFn(Hljf(q;*yx`YY@)g<675H1|Uq<@F@G+>^|2P<(h>?cfpIK`&@hPQY2Cv z^RbNCVGE^N-{d|jyJ zfGN(;=f13=l;n~y^9CXC5f|XiQ(#&ABs!!Qg~GWc}Ya?km-Ts!IW-mWp1Li@*J5)D0XI^8php4cFIgUq zPuJwASU;2+F~}BL0-&adL3;lvx8MoDAZ&*kK^2QL1)Pls zR-}YLAs!!^g!P4-MfhhTJjTa`TpgR_miP=G6_Jn}mFTAf2I*m@rVIuolHIX`8Jpwl z5t5}VYiJ@s$xxR8%>*d!i*QImbZj*Fz<}~+!S;mn5b{$%&gLh0H_i)3pK!H7?Ug57 zBf@5lH? z#6|j!jROfF3fn5U2;1u4BCeu`UfQ~!Akh!A5_CnJTQ!wkLA`|%7zlk4SEmw~rbh|) zgd(o44fV=ToVq16Nsn38an!52FKbyJ0)=bRU|S@d(xeU!X$;>SfLj*E^O z53*&a(kB7D@&lDR*_oCBT0o??=k_#}j$hhJz04Nj$Sckj@1RL<8K;B*v)0MpvD_E4 z)+s9|wE^8a>AAK>ZbSC1vcaV`5O36W7Z$wY>Qp0W7}?z9)yr6X;}pTCg^3STk51I%ZX2&5cCZQmQt{a4=9I1_%KvY z)>{5HiQJN`wW2k}8R^MtNybeX4YSrubqo~s^u^MwL!S^4_B`$!6A3lHy2jj zfRiAug#iN_;#s# zcwms$!hjhYq+$_rOCoMk;I9BMV}n#;LxEt%207@JhUdwQRZGE>38IEHWTI|WAd%Z) zgQDmR%)-={Tt$@IAdT$hk0*1M<3_m)nX^>LK^cV1SuV9Kw;^+u>M1B~$h=U9n24k^ zK_fS`3NH#cZxQ#!K{W>}3lv;y)oyjCzea(56hpB(fwZm6f#1Si)n+xw= zbFGAhPdG1p+z%QzD$i zM&Z^Qu5qYrV%s zsendlBR?Hc?216kE&X(6QQbp{j(Nv*6l%TW>QqN(Wn@3z&mg!KV*z)(<9zUK5Y2n8 zx6tt;SKEd6BjTluWAfvLhR@J$?0d1@{nBw5%udb8Hept!zB4amieVM$!j3?0Li@TC%{wP1y5- z^J__3c0dT zH^~;oB!8R1Bx^{MoRl*mZXha^gH4q*VAwy1-6iS-U3rIksHr3?QIk}o2){Eyi&}Gu z`yxa&chSG2<}MXB!f=wBG|9fJNzzaDbCqOXT#~)7xvC0zo)sJn!W_=Q+ege&D8qM( zNOk_rO;Coe4i3>3%*MUb9UNL#sDjM4 z)}ljte{rm1eP<|q`B!ARZdG!KtY9_?9UUF?A@D=VKTVv*N&JsiYbLRm8ip_AV9QW2 z15x7?426O4NgRh}HnzD~rH5*+B{Q~%>5%{+>0mXC=Sf;z4MQ0(I1Cg_tg=O5wzB!) z+hi0HtyX6xafp3qtrq!n3b9tpTWJEdTBDBmV(PxgAF7G5;qNHE#V{AewHU-GT*bmH z#IaE$L470!F^Z=#M4Jo-Qk{wF%oC+Y!9>kK!OWz16a}*qjiH8_wZ!?QV4|lk!fd7D zWES(>R70_78U-_x{38XkkRVkJvuH_zl!EEV{scMH)AH+>${p~gtWRMssHOy)y9;FJVH<^inQ^DYM5tU29L=C5c zA;iHgao3hAxviR5JCkrYc0gXQo}4p zMwwU;=?ab99BSD}u20q6${R^;P7SkwGzP}g`x3b-3q1p!)+i=v?8if$Gb^!J_-89q zdVrSkPG%jdo{@mczOxp!&zSwDLym)nc0>6ywGt&Vg4_f|;z0jz)Y>jJCR=0h*D4iBSvHPOPb~hG|(YXd#gDvX|*-a8Lm% zdRwPOrASKbhz%p&s67(EbTkJM%oxdele(Q%j41Z8H1Fhhp*LYeJ0VbB2R1u90Ne(YmFf)$v82K=Y zC%a<1QXP%eq-`#2p;+iZU&)#}^F68Q2K{ z4&F#Cr$%hCFs?WpC}tjgcJPvg)c4%dxDu_~hBrZFnr2m?qj9ZtQ;1tRjV z%*sOblTyRvpJHXZEw80&siLoe} z!;V0h1BMG$Exi@Uc#7DUP7cA5iMFy@lujn+XzJNn#k`6NhN8-}ht% z8D!>>l4SZ~KpJKd%UhS>AnJkmT}(qvn4ub`ghqmBhKY`lc41;!vqj8fl_AFeEI31C zYy^NLHKcBciqR}g%zLWa;W&^c+F}$BZPe|`9KKTZfY_bM#*m1P@dGU20?jROm5~o9 zcE($TRw4(FcEo`H05VauRj*~%&WZ?+VL!O99uVmP9Fx*!1~5iGtY9jm9<029BrxqL z#DKU;sa9%$@jT=CAbe$<9IKh#rC20c`jIG55+zo%g~=;HVKA1}3W;N8huy>wZ4nRR z)Dy9YcLwcYHU!R0xCt0OjzV+60tZkHLp!lbxcz{DiJ4mp1|7uoH6tQuMcS3Bdvu0) z(G5}3o?2t*dh*3`XZX14m>Ll^NzhT7fWYYa045$1sL>-$!^{z;nI%a{K;Vp0UO{Xi z9Ub(;KNAl~)kw&e6go6?Xlz3$L9rP<#4`?c50uxZ1dwDbSZr4KIyCpJTH5C%u{Al{ zhw`;&y_HcY2(IR>8U$ACCwr4R!JExaUHx6i2%{P3M&kZGplE;VhX(HY?) zjRamCEm#O==`Bn$0wiZo{*@A~GvbC1rBKiipT@iBK?IAkMPgcpUM<|uX4|0}Kif`E z>obfeUe{64M7&&y&N9OYreROf#9NKx653CQB>8Eg0i)d$pa46l@!+nLCZSn1%Nq*3rC1G~maAuMq6Cg`3x->nuwob?NGz*yNt2l!&VyLaSQ)|B$>?Y z5R+c~>XC{#_<3@s&&~)TF-NC8anvQgh@m=DSvW{EiIM50#CVM5MEI(9-5g10=olfS zDJ(K`9zc$vXdwn)*-1h%(_0>4DIIMh;x{rb3t)2Qql_7lFB4;TuooF5Fgx_I4Ga;| zkJPFn!O1vtX1uXdnHXY`aem3@A2YO#sv%*Tl~oNm4`3X4vz|#d0Ebn*3a|z^PvPnF zBGQmK0Wl++Of5A!BMD2-*q~(`JTq=NQWHU6@%u$Y#L6r(8Zz<(vsh|76p!491AIy~ z5cA2%F)|)>cmTwoI4?q~mYy93Wa1)prm~P^>0m8sAvEK07$v~yi-3&b76NhFB9oJK z%07|KrI{zi`N1Zk^XxEzj21>;#Nsq!UVNP=?r_B-qcakv>V`O`V(ke@=uqoPY%guO z(bvM54xDGv#Msc;ObZ-3Ge_oVXQ8|)u%Bnb7W9SsQ%{7nqbG;QnZ$CdEiyVA8PkpQ z8=ZecXPn)tk)SUe1T~Dbqch=viPu?0_Q%N<8J!L6dg68s!)jPd3JLn+$c8~Ies4`e zB3pekKF&rju?;&X?en2u#jh6}J_ z)Y6f@tSzyb%ybS5#Gs{mCg{vF-WgIY%!#cpIm{Mg?*yT*p7CpNMsBat#r=ouD02dZ&N^C+l6FiMzzqMEWi=GNnuF-eh8JeD zjX66-as(Th?red%WMJ_A)iCsBZd>5SgN|Kdi_AgHUtvEwW8^BX98R$?3#s*gwr1U5)f$XyQ8c{W#6_-0` z9B?QU;Vz2|tmN7lg&4_hTI(ZiE52`6BY|+!97GV!WYm$&QV`4f7`Zwta+~yeLOU^T zh81-xXci)I!Xy)|C>KG?jFtZcG00Mx=*R#mIQp^#VhZM@40$UgC~0ne;GjK&vq@hCsa*hashc zu0#g7u|#V^T;*Ug0XSe1pTMYzL7tT+28nN4Wy9-Zl$qX!r=s*B6WlqZ0;ri7c;==Q z<^gp^wL>#HK7x(3&^w1*S|+iw=ouFLD9%tI&0H_Rx7j&pKkm%IL z)<)ysJ30k5!_27G6B-|n%0$YS)w{-xh{tajij++0+DQ}Erh_$*?_h1;0Y@-_f#yzp zAR-K{siU#IzP&*g)Ui{5=KpUJu0cI9)DuWdo{$(-eS{O_7y8VpNt3|fAgBKWz&K=; diff --git a/ReadMe.md b/ReadMe.md index 897958ea..ef48fca1 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -3,7 +3,7 @@ author: "Wayne Warthen (mailto:wwarthen@gmail.com)" classoption: - oneside colorlinks: true -date: 08 Dec 2021 +date: 03 Jan 2022 documentclass: book fontfamily: helvet fontsize: 12pt @@ -44,7 +44,7 @@ toc-depth: 1 ## Z80/Z180 System Software Version 3.1 Pre-release -08 Dec 2021 +03 Jan 2022 Wayne Warthen @@ -1357,6 +1357,48 @@ applications are no longer provided. Contributions of all kinds to RomWBW are very welcome. +# Licensing + +RomWBW 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. + +RomWBW 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 RomWBW. If not, see . + +Portions of RomWBW were created by, contributed by, or derived from the +work of others. It is believed that these works are being used in +accordance with the intentions and/or licensing of their creators. + +If anyone feels their work is being used outside of it’s intended +licensing, please notify: + + Wayne Warthen + wwarthen@gmail.com + +RomWBW is an aggregate work. It is composed of many individual, +standalone programs that are distributed as a whole to function as a +cohesive system. Each program may have it’s own licensing which may be +different from other programs within the aggregate. + +In some cases, a single program (e.g., CP/M Operating System) is +composed of multiple components with different licenses. It is believed +that in all such cases the licenses are compatible with GPL version 3. + +RomWBW encourages code contributions from others. Contributors may +assert their own copyright in their contributions by annotating the +contributed source code appropriately. Contributors are further +encouraged to submit their contributions via the RomWBW source code +control system to ensure their contributions are clearly documented. + +All contributions to RomWBW are subject to this license. + # Getting Assistance The best way to get assistance with RomWBW or any aspect of the diff --git a/ReadMe.txt b/ReadMe.txt index 2bc55874..22459a57 100644 --- a/ReadMe.txt +++ b/ReadMe.txt @@ -1,6 +1,6 @@ RomWBW Getting Started Wayne Warthen (mailto:wwarthen@gmail.com) -08 Dec 2021 +03 Jan 2022 @@ -17,7 +17,7 @@ RomWBW Z80/Z180 System Software Version 3.1 Pre-release -08 Dec 2021 +03 Jan 2022 Wayne Warthen wwarthen@gmail.com @@ -1360,6 +1360,48 @@ applications are no longer provided. Contributions of all kinds to RomWBW are very welcome. +Licensing + +RomWBW 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. + +RomWBW 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 RomWBW. If not, see https://www.gnu.org/licenses/. + +Portions of RomWBW were created by, contributed by, or derived from the +work of others. It is believed that these works are being used in +accordance with the intentions and/or licensing of their creators. + +If anyone feels their work is being used outside of it’s intended +licensing, please notify: + + Wayne Warthen + wwarthen@gmail.com + +RomWBW is an aggregate work. It is composed of many individual, +standalone programs that are distributed as a whole to function as a +cohesive system. Each program may have it’s own licensing which may be +different from other programs within the aggregate. + +In some cases, a single program (e.g., CP/M Operating System) is +composed of multiple components with different licenses. It is believed +that in all such cases the licenses are compatible with GPL version 3. + +RomWBW encourages code contributions from others. Contributors may +assert their own copyright in their contributions by annotating the +contributed source code appropriately. Contributors are further +encouraged to submit their contributions via the RomWBW source code +control system to ensure their contributions are clearly documented. + +All contributions to RomWBW are subject to this license. + Getting Assistance The best way to get assistance with RomWBW or any aspect of the diff --git a/Source/Apps/Test/Build.cmd b/Source/Apps/Test/Build.cmd index 139ea0c9..fb322d6b 100644 --- a/Source/Apps/Test/Build.cmd +++ b/Source/Apps/Test/Build.cmd @@ -21,7 +21,7 @@ pushd I2C && call Build || exit /b & popd pushd rzsz && call Build || exit /b & popd pushd vdctest && call Build || exit /b & popd pushd kbdtest && call Build || exit /b & popd -pushd kbdinfo && call Build || exit /b & popd +pushd ps2info && call Build || exit /b & popd goto :eof diff --git a/Source/Apps/Test/Clean.cmd b/Source/Apps/Test/Clean.cmd index 3cb2cdfa..9e1f36d9 100644 --- a/Source/Apps/Test/Clean.cmd +++ b/Source/Apps/Test/Clean.cmd @@ -16,4 +16,4 @@ pushd I2C && call Clean || exit /b 1 & popd pushd rzsz && call Clean || exit /b 1 & popd pushd vdctest && call Clean || exit /b 1 & popd pushd kbdtest && call Clean || exit /b 1 & popd -pushd kbdinfo && call Clean || exit /b 1 & popd +pushd ps2info && call Clean || exit /b 1 & popd diff --git a/Source/Apps/Test/Makefile b/Source/Apps/Test/Makefile index 3c844c01..aed32df2 100644 --- a/Source/Apps/Test/Makefile +++ b/Source/Apps/Test/Makefile @@ -1,5 +1,5 @@ OBJECTS = -SUBDIRS = DMAmon I2C inttest ppidetst ramtest tstdskng rzsz vdctest kbdtest kbdinfo +SUBDIRS = DMAmon I2C inttest ppidetst ramtest tstdskng rzsz vdctest kbdtest ps2info DEST = ../../../Binary/Apps/Test TOOLS =../../../Tools diff --git a/Source/Apps/Test/kbdinfo/Build.cmd b/Source/Apps/Test/kbdinfo/Build.cmd deleted file mode 100644 index 1f9866d6..00000000 --- a/Source/Apps/Test/kbdinfo/Build.cmd +++ /dev/null @@ -1,10 +0,0 @@ -@echo off -setlocal - -set TOOLS=../../../../Tools -set PATH=%TOOLS%\tasm32;%PATH% -set TASMTABS=%TOOLS%\tasm32 - -tasm -t180 -g3 -fFF kbdinfo.asm kbdinfo.com kbdinfo.lst || exit /b - -copy /Y kbdinfo.com ..\..\..\..\Binary\Apps\Test\ || exit /b diff --git a/Source/Apps/Test/kbdinfo/mseinfo.asm b/Source/Apps/Test/kbdinfo/mseinfo.asm deleted file mode 100644 index 506aeacf..00000000 --- a/Source/Apps/Test/kbdinfo/mseinfo.asm +++ /dev/null @@ -1,896 +0,0 @@ -; -;======================================================================= -; Mouse Information Utility (MSEINFO) -;======================================================================= -; -; Simple utility that attempts to determine the status of the mouse you -; have attached to an 8242 keyboard controller. -; -; Based on Wayne Warthen's KBDINFO program, Thanks to his great work -; on RomWBW and support to the Retrobrewcomputers community at large -; -; Additional help from these websites -; https://isdaman.com/alsos/hardware/mouse/ps2interface.htm -; -; Second PS/2 write data port info from -; https://wiki.osdev.org/%228042%22_PS/2_Controller#Second_PS.2F2_Port -; -; PS/2 Mouse initialization code in C -; http://bos.asmhackers.net/docs/mouse/snippet_2/mouse.inc -; -;======================================================================= -; -; Mouse controller port addresses (adjust as needed) -; -iocmd .equ $E3 ; keyboard controller command port address -iodat .equ $E2 ; keyboard controller data port address -; -; General operational equates (should not requre adjustment) -; -stksiz .equ $40 ; Working stack size -; -timeout .equ $00 ; Controller timeout constant -; -restart .equ $0000 ; CP/M restart vector -bdos .equ $0005 ; BDOS invocation vector -; -;======================================================================= -; - .org $100 ; standard CP/M executable -; -; - ; setup stack (save old value) - ld (stksav),sp ; save stack - ld sp,stack ; set new stack -; - call crlf - ld de,str_banner ; banner - call prtstr -; - call main ; do the real work -; -exit: - call crlf2 - ld de,str_exit - call prtstr - ;call crlf - - ; clean up and return to command processor - call crlf ; formatting - ld sp,(stksav) ; restore stack - jp restart ; return to CP/M via restart -; -; -;======================================================================= -; Main Program -;======================================================================= -; -main: -; -; Display active mouse controller port addresses -; - call crlf2 - ld de,str_cmdport - call prtstr - ld a,iocmd - call prthex - call crlf - ld de,str_dataport - call prtstr - ld a,iodat - call prthex -; -; Attempt self-test command on mouse controller -; -; Mouse controller should respond with an 0x55 on data port -; after being sent a 0xAA on the command port. -; - call crlf2 - ld de,str_ctrl_test - call prtstr - ld a,$aa ; self-test command - call put_cmd_dbg - jp c,err_ctlr_io ; handle controller error - call get_data_dbg - jp c,err_ctlr_io ; handle controller error - cp $55 ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr -; -; Send 0xA8 Mouse Enable command to 8242 controller -; - call crlf2 - ld de,str_enable_mouse - call prtstr - - ld a,$a8 ; Send Mouse Enable command to 8242 - call put_cmd_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for self-test status - jp c,err_ctlr_io ; handle controller error - cp $AA ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - - call get_data_dbg ; Read Mouse for Mouse ID - jp c,err_ctlr_io ; handle controller error - cp $00 ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - - - -; -; Disable translation on keyboard controller to get raw scan codes! Enable Mouse -; -; call crlf2 -; ld de,str_trans_off -; call prtstr -; ld a,$60 ; write to command register 0 -; call put_cmd_dbg -; jp c,err_ctlr_io ; handle controller error -; ld a,$00 ; xlat disabled, mouse enabled, no ints -; call put_cmd_dbg -; jp c,err_ctlr_io ; handle controller error - -; Attempt four reset commands on mouse controller -; - call crlf2 - ld de,str_mse_init - call prtstr - -; Reset Pass #1 - ld a,$ff ; Send Mouse Reset command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - call get_data_dbg ; Read Mouse for self-test status - jp c,err_ctlr_io ; handle controller error - cp $AA ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - - call get_data_dbg ; Read Mouse for Mouse ID - jp c,err_ctlr_io ; handle controller error - cp $00 ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - -; Reset Pass #2 - ld a,$ff ; Send Mouse Reset command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - call get_data_dbg ; Read Mouse for self-test status - jp c,err_ctlr_io ; handle controller error - cp $AA ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - - call get_data_dbg ; Read Mouse for Mouse ID - jp c,err_ctlr_io ; handle controller error - cp $00 ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - -; Reset Pass #3 - ld a,$ff ; Send Mouse Reset command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - call get_data_dbg ; Read Mouse for self-test status - jp c,err_ctlr_io ; handle controller error - cp $AA ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - - call get_data_dbg ; Read Mouse for Mouse ID - jp c,err_ctlr_io ; handle controller error - cp $00 ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - -; Reset Pass #4 - ld a,$ff ; Send Mouse Reset command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - call get_data_dbg ; Read Mouse for self-test status - jp c,err_ctlr_io ; handle controller error - cp $AA ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - - call get_data_dbg ; Read Mouse for Mouse ID - jp c,err_ctlr_io ; handle controller error - cp $00 ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - -; Begin setting mouse parameters, Request Microsoft Scrolling Mouse Mode - - ld a,$f3 ; Send Set Sample Rate command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - ld a,$c8 ; Send Decimal 200 command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - ld a,$f3 ; Send Set Sample Rate command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - ld a,$64 ; Send Decimal 100 command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - ld a,$f3 ; Send Set Sample Rate command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - ld a,$50 ; Send Decimal 80 command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - ld a,$f2 ; Send Read Device Type command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - call get_data_dbg ; Read Mouse for Mouse ID - jp c,err_ctlr_io ; handle controller error - cp $03 ; detect MS Intellimouse/Microsoft Scrolling Mouse - jp z,Intellimouse - cp $00 ; expected value? ($00 if Regular PS/2 Mouse) - jp z,ReadMouseID -Intellimouse: - call crlf - ld de,str_intellimouse_ok - call prtstr -ReadMouseID: - jp nz,err_ctlr_test ; handle self-test error - call crlf - - ld a,$f3 ; Send Set Sample Rate command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - ld a,$0a ; Send Decimal 10 command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - ld a,$f2 ; Send Read Device Type command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - call get_data_dbg ; Read Mouse for Mouse ID - jp c,err_ctlr_io ; handle controller error - cp $03 ; detect MS Intellimouse/Microsoft Scrolling Mouse - jp z,Intellimouse2 - cp $00 ; expected value? ($00 if Regular PS/2 Mouse) - jp z,ReadMouseID2 -Intellimouse2: - call crlf - ld de,str_intellimouse_ok - call prtstr -ReadMouseID2: - jp nz,err_ctlr_test ; handle self-test error - call crlf - - ld a,$e8 ; Send Set Resolution command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - ld a,$03 ; Send 8 Counts/mm command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - ld a,$e6 ; Send Set Scaling 1:1 command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - ld a,$f3 ; Send Set Sample Rate command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - ld a,$28 ; Send Decimal 40 command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - - ld a,$f4 ; Send Enable command - call put_data_dbg - jp c,err_ctlr_io ; handle controller error - - call get_data_dbg ; Read Mouse for Acknowledge - jp c,err_ctlr_io ; handle controller error - cp $fa ; expected value? - jp nz,err_ctlr_test ; handle self-test error - call crlf - ld de,str_ctrl_test_ok - call prtstr - -; Initialization Complete - -ReadMousePackets: - -; call check_read -; jp nz, ReadMousePackets - - call get_data_dbg ; Read Mouse for self-test status - jp c,err_ctlr_io ; handle controller error - call crlf - - call get_data_dbg ; Read Mouse for Mouse ID - jp c,err_ctlr_io ; handle controller error - call crlf - - call get_data_dbg ; Read Mouse for Mouse ID - jp c,err_ctlr_io ; handle controller error - call crlf - - call crlf - - jp ReadMousePackets - -; -done: - ret - -; -;======================================================================= -; Mouse Controller I/O Routines -;======================================================================= -; -wait_write: -; -; Wait for mouse controller to be ready for a write -; A=0 indicates success (ZF set) -; - ld b,timeout ; setup timeout constant -wait_write1: - in a,(iocmd) ; get status - ld c,a ; save status - and $02 ; isolate input buf status bit - ret z ; 0 means ready, all done - call delay ; wait a bit - djnz wait_write1 ; loop until counter exhausted - ld de,str_timeout_write ; write timeout message - call crlf - call prtstr - ld a,c ; recover last status value - call prthex - or $ff ; signal error - ret -; -wait_read: -; -; Wait for mouse controller to be ready to read a byte -; A=0 indicates success (ZF set) -; - ld b,timeout ; setup timeout constant -wait_read1: - in a,(iocmd) ; get status - ld c,a ; save status - and $01 ; isolate input buf status bit - xor $01 ; invert so 0 means ready - ret z ; if 0, all done - call delay ; wait a bit - djnz wait_read1 ; loop until counter exhausted - ld de,str_timeout_read ; write timeout message - call crlf - call prtstr - ld a,c ; recover last status value - call prthex - or $ff ; signal error - ret -; -check_read: -; -; Check for data ready to read -; A=0 indicates data available (ZF set) -; - in a,(iocmd) ; get status - and $01 ; isolate input buf status bit - xor $01 ; invert so 0 means ready - ret -; -put_cmd: -; -; Put a cmd byte from A to the mouse interface with timeout -; CF set indicates timeout error -; - ld e,a ; save incoming value - call wait_write ; wait for controller ready - jr z,put_cmd1 ; if ready, move on - scf ; else, signal timeout error - ret ; and bail out -put_cmd1: - ld a,e ; recover value to write - out (iocmd),a ; write it - or a ; clear CF for success - ret -; -put_cmd_dbg: - call put_cmd - ret c - push af - call crlf - ld de,str_put_cmd - call prtstr - call prthex - pop af - ret -; -put_data: -; -; Put a data byte from A to the mouse interface with timeout -; CF set indicates timeout error -; -; note: direct data to second PS/2 port, send $d4 to 8242 command register -; different than keyboard which uses first PS/2 port - - push af ; save contents of a - ld e,a ; save incoming value - call wait_write ; wait for controller ready - jr z,put_data0 ; if ready, move on - scf ; else, signal timeout error - ret ; and bail out -put_data0: - ld a,$d4 ; direct to second PS/2 port for mouse - out (iocmd),a ; send second port command to 8242 - pop af - -; rest of put_data is the same as for PS/2 keyboard - - ld e,a ; save incoming value - call wait_write ; wait for controller ready - jr z,put_data1 ; if ready, move on - scf ; else, signal timeout error - ret ; and bail out -put_data1: - ld a,e ; recover value to write - out (iodat),a ; write it - or a ; clear CF for success - ret -; -put_data_dbg: - call put_data - ret c - push af - call crlf - ld de,str_put_data - call prtstr - call prthex - pop af - ret - -; -; Get a data byte from the mouse interface to A with timeout -; CF set indicates timeout error -; -get_data: -; - call wait_read ; wait for byte to be ready - jr z,get_data1 ; if ready, move on - scf ; else signal timeout error - ret ; and bail out -get_data1: - in a,(iodat) ; get data byte - or a ; clear CF for success - ret -; -get_data_dbg: - call get_data - ret c - push af - call crlf - ld de,str_get_data - call prtstr - call prthex - pop af - ret -; -; Error Handlers -; -err_ctlr_io: - ld de,str_err_ctrl_io - jr err_ret -; -err_ctlr_test: - ld de,str_err_ctrl_test - jr err_ret -; -err_mse_reset: - ld de,str_err_mse_reset - jr err_ret -; -err_ret: - call crlf2 - call prtstr - or $ff ; signal error - ret -; -;======================================================================= -; Utility Routines -;======================================================================= -; -; -; Print character in A without destroying any registers -; -prtchr: - push bc ; save registers - push de - push hl - ld e,a ; character to print in E - ld c,$02 ; BDOS function to output a character - call bdos ; do it - pop hl ; restore registers - pop de - pop bc - ret -; -prtdot: -; - ; shortcut to print a dot preserving all regs - push af ; save af - ld a,'.' ; load dot char - call prtchr ; print it - pop af ; restore af - ret ; done -; -; Print a zero terminated string at (de) without destroying any registers -; -prtstr: - push af - push de -; -prtstr1: - ld a,(de) ; get next char - or a - jr z,prtstr2 - call prtchr - inc de - jr prtstr1 -; -prtstr2: - pop de ; restore registers - pop af - ret -; -; Print the value in A in hex without destroying any registers -; -prthex: - push af ; save AF - push de ; save DE - call hexascii ; convert value in A to hex chars in DE - ld a,d ; get the high order hex char - call prtchr ; print it - ld a,e ; get the low order hex char - call prtchr ; print it - pop de ; restore DE - pop af ; restore AF - ret ; done -; -; print the hex word value in hl -; -prthexword: - push af - ld a,h - call prthex - ld a,l - call prthex - pop af - ret -; -; print the hex dword value in de:hl -; -prthex32: - push bc - push de - pop bc - call prthexword - push hl - pop bc - call prthexword - pop bc - ret -; -; Convert binary value in A to ascii hex characters in DE -; -hexascii: - ld d,a ; save A in D - call hexconv ; convert low nibble of A to hex - ld e,a ; save it in E - ld a,d ; get original value back - rlca ; rotate high order nibble to low bits - rlca - rlca - rlca - call hexconv ; convert nibble - ld d,a ; save it in D - ret ; done -; -; Convert low nibble of A to ascii hex -; -hexconv: - and $0F ; low nibble only - add a,$90 - daa - adc a,$40 - daa - ret -; -; Print value of A or HL in decimal with leading zero suppression -; Use prtdecb for A or prtdecw for HL -; -prtdecb: - push hl - ld h,0 - ld l,a - call prtdecw ; print it - pop hl - ret -; -prtdecw: - push af - push bc - push de - push hl - call prtdec0 - pop hl - pop de - pop bc - pop af - ret -; -prtdec0: - ld e,'0' - ld bc,-10000 - call prtdec1 - ld bc,-1000 - call prtdec1 - ld bc,-100 - call prtdec1 - ld c,-10 - call prtdec1 - ld e,0 - ld c,-1 -prtdec1: - ld a,'0' - 1 -prtdec2: - inc a - add hl,bc - jr c,prtdec2 - sbc hl,bc - cp e - ret z - ld e,0 - call prtchr - ret -; -; Start a new line -; -crlf2: - call crlf ; two of them -crlf: - push af ; preserve AF - ld a,13 ; - call prtchr ; print it - ld a,10 ; - call prtchr ; print it - pop af ; restore AF - ret -; -; Brief delay -; -delay: - push bc - ld b,0 -delay1: - ex (sp),hl - ex (sp),hl - ex (sp),hl - ex (sp),hl - ex (sp),hl - ex (sp),hl - ex (sp),hl - ex (sp),hl - djnz delay1 - pop bc - ret -; -;======================================================================= -; Constants -;======================================================================= -; -str_banner .db "Mouse Information, v0.1",0 -str_exit .db "Done, Thank you for using MSEINFO!",0 -str_cmdport .db "Mouse Controller Command Port: 0x",0 -str_dataport .db "Mouse Controller Data Port: 0x",0 -str_timeout_write .db "Mouse Controller Write Timeout, Status: 0x",0 -str_timeout_read .db "Mouse Controller Read Timeout, Status: 0x",0 -str_err_ctrl_io .db "Mouse Controller I/O Failure",0 -str_err_ctrl_test .db "Mouse Controller Self-Test Failed",0 -str_put_cmd .db "Sent Command 0x",0 -str_put_data .db "Sent Data 0x",0 -str_get_data .db "Got Data 0x",0 -str_ctrl_test .db "Attempting Controller Self-Test",0 -str_mse_init .db "Attempting Mouse Initialization",0 -str_enable_mouse .db "Enabling Mouse in 8242 Controller",0 -str_ctrl_test_ok .db "Controller Self-Test OK",0 -str_intellimouse_ok .db "MS Intellimouse OK",0 -str_trans_off .db "Disabling Controller Translation",0 -str_mse_reset .db "Attempting Mouse Reset",0 -str_mse_reset_ok .db "Mouse Reset OK",0 -str_err_mse_reset .db "Mouse Reset Failed",0 -; -;======================================================================= -; Working data -;======================================================================= -; -stksav .dw 0 ; stack pointer saved at start - .fill stksiz,0 ; stack -stack .equ $ ; stack top -; -workbuf .fill 8 -workbuf_len .db 0 -; -;======================================================================= -; - .end - diff --git a/Source/Apps/Test/ps2info/Build.cmd b/Source/Apps/Test/ps2info/Build.cmd new file mode 100644 index 00000000..965883ce --- /dev/null +++ b/Source/Apps/Test/ps2info/Build.cmd @@ -0,0 +1,10 @@ +@echo off +setlocal + +set TOOLS=../../../../Tools +set PATH=%TOOLS%\tasm32;%PATH% +set TASMTABS=%TOOLS%\tasm32 + +tasm -t180 -g3 -fFF ps2info.asm ps2info.com ps2info.lst || exit /b + +copy /Y ps2info.com ..\..\..\..\Binary\Apps\Test\ || exit /b diff --git a/Source/Apps/Test/kbdinfo/Clean.cmd b/Source/Apps/Test/ps2info/Clean.cmd similarity index 100% rename from Source/Apps/Test/kbdinfo/Clean.cmd rename to Source/Apps/Test/ps2info/Clean.cmd diff --git a/Source/Apps/Test/kbdinfo/Makefile b/Source/Apps/Test/ps2info/Makefile similarity index 56% rename from Source/Apps/Test/kbdinfo/Makefile rename to Source/Apps/Test/ps2info/Makefile index 3525056d..33330b47 100644 --- a/Source/Apps/Test/kbdinfo/Makefile +++ b/Source/Apps/Test/ps2info/Makefile @@ -1,4 +1,4 @@ -OBJECTS = kbdinfo.com +OBJECTS = ps2info.com DEST = ../../../../Binary/Apps/Test TOOLS =../../../../Tools diff --git a/Source/Apps/Test/kbdinfo/kbdinfo.asm b/Source/Apps/Test/ps2info/ps2info.asm similarity index 53% rename from Source/Apps/Test/kbdinfo/kbdinfo.asm rename to Source/Apps/Test/ps2info/ps2info.asm index 151db818..8a517a22 100644 --- a/Source/Apps/Test/kbdinfo/kbdinfo.asm +++ b/Source/Apps/Test/ps2info/ps2info.asm @@ -1,17 +1,17 @@ ; ;======================================================================= -; Keyboard Information Utility (KBDINFO) +; PS/2 Keyboard/Mouse Information Utility (PS2INFO) ;======================================================================= ; -; Simple utility that attempts to determine the type of keyboard you -; have attached to an 8242 keyboard controller. +; Simple utility that performs simple tests of an 8242 PS/2 controller, +; keyboard, and mouse. ; ;======================================================================= ; -; Keyboard controller port addresses (adjust as needed) +; PS/2 Keyboard/Mouse controller port addresses (adjust as needed) ; -iocmd .equ $E3 ; keyboard controller command port address -iodat .equ $E2 ; keyboard controller data port address +iocmd .equ $E3 ; PS/2 controller command port address +iodat .equ $E2 ; PS/2 controller data port address ; cpumhz .equ 8 ; for time delay calculations (not critical) ; @@ -39,10 +39,6 @@ bdos .equ $0005 ; BDOS invocation vector call prtstr ; call main ; do the real work - jr z,exit ; completed all tests - ld de,str_run_failed - call crlf2 - call prtstr ; exit: call crlf2 @@ -61,7 +57,7 @@ exit: ; main: ; -; Display active keyboard controller port addresses +; Display active controller port addresses ; call crlf2 ld de,str_cmdport @@ -73,16 +69,66 @@ main: call prtstr ld a,iodat call prthex +; + call test_ctlr + jr z,main0 ; continue if ctlr OK + ld de,str_kbd_failed + call crlf2 + call prtstr + jr mainz ; bail out if ctlr fails +; +main0: + call test_kbd + jr z,main1 ; completed all tests, continue + ld de,str_kbd_failed + call crlf2 + call prtstr +; +main1: + call test_mse + jr z,main2 ; completed all tests, continue + ld de,str_mse_failed + call crlf2 + call prtstr +; +main2: + call test_kbdmse +; +mainz: + xor a + ret +; +; Test 8242 PS/2 Controller +; +test_ctlr: + call crlf2 + ld de,str_ctlr + call prtstr +; + call ctlr_test + ret nz +; + call ctlr_test_p1 + ;ret nz +; + call ctlr_test_p2 + ;ret nz +; + ret +; +; Test Keyboard +; +test_kbd: ; ; First, we attempt to contact the controller and keyboard, then -; print the keyboard identity and scan codes scupported +; print the keyboard identity and scan codes supported ; ; Run test series with translation off call crlf2 ld de,str_basic call prtstr ; - call do_basic + call test_kbd_basic ret nz ; ; We make two passes through the test series with different controller @@ -94,29 +140,78 @@ main: ld de,str_trans_off call prtstr ; - ld a,$20 ; xlat disabled, mouse disabled, no ints + ld a,$20 ; kbd enabled, xlat disabled, mouse disabled, no ints ld (ctlr_cfgval),a - call do_tests + call test_kbd_keys ; ; Run test series with translation on call crlf2 ld de,str_trans_on call prtstr ; - ld a,$60 ; xlat enabled, mouse disabled, no ints + ld a,$60 ; kbd enabled, xlat enabled, mouse disabled, no ints ld (ctlr_cfgval),a - call do_tests - + call test_kbd_keys +; + ret +; +; Test Mouse +; +test_mse: + call crlf2 + ld de,str_basic_mse + call prtstr +; + ld a,$10 ; kbd disabled, mse enabled, no ints + call ctlr_setup + ret nz +; + call mse_reset + ret nz +; + call mse_ident + ret nz +; + call mse_stream + ret nz +; + call mse_echo +; xor a ; signal success ret ; -; Perform basic keyboard tests, display keyboard identity, and -; inventory the supported scan code sets. +; Test Everything ; -do_basic: - call ctlr_test +test_kbdmse: + call crlf2 + ld de,str_kbdmse + call prtstr +; + ld a,$00 ; kbd enabled, mse enabled, no ints + call ctlr_setup ret nz ; + call kbd_reset + ret nz +; + ld a,2 + call kbd_setsc +; + call mse_reset + ret nz +; + call mse_stream + ret nz +; + call kbdmse_echo +; + xor a ; signal success + ret +; +; Perform basic keyboard tests, display keyboard identity, and +; inventory the supported scan code sets. +; +test_kbd_basic: ld a,$20 ; Xlat off for this checking call ctlr_setup ret nz @@ -129,7 +224,7 @@ do_basic: ; ld b,3 ; Loop control, 3 scan code sets ld c,1 ; Current scan code number -do_basic1: +test_kbd_basic1: ld a,c ; Scan code set to A push bc call kbd_setsc ; Attempt to set it @@ -142,12 +237,12 @@ do_basic1: call prtdecb pop af ; restore result ld de,str_sc_ok - jr z,do_basic2 + jr z,test_kbd_basic2 ld de,str_sc_fail -do_basic2: +test_kbd_basic2: call prtstr inc c - djnz do_basic1 + djnz test_kbd_basic1 ; xor a ; signal success ret @@ -156,10 +251,7 @@ do_basic2: ; desired controller setup value should be placed in ctlr_cfgval ; prior to invoking this routine. ; -do_tests: - call ctlr_test - ret nz -; +test_kbd_keys: ld a,(ctlr_cfgval) call ctlr_setup ret nz @@ -177,19 +269,19 @@ do_tests: call kbd_dispsc ;ret nz ; - call kbd_showkeys + call kbd_echo ;ret nz ; xor a ; signal success ret ; ;======================================================================= -; Keyboard/Controller Test Routines +; Controller/Keyboard/Mouse Test Routines ;======================================================================= ; -; Attempt self-test command on keyboard controller +; Attempt self-test command on PS/2 controller ; -; Keyboard controller should respond with an 0x55 on data port +; PS/2 controller should respond with an 0x55 on data port ; after being sent a 0xAA on the command port. ; ctlr_test: @@ -209,9 +301,47 @@ ctlr_test: xor a ret ; -; Keyboard controller setup +; Attempt self-test of first port of controller +; +ctlr_test_p1: + call crlf2 + ld de,str_ctlr_test_p1 + call prtstr + ld a,$ab ; self-test first port + call put_cmd_dbg + jp c,err_ctlr_to ; handle controller error + call get_data_dbg + jp c,err_ctlr_to ; handle controller error + cp $00 ; expected value? + jp nz,err_ctlr_test_p1 ; handle self-test error + call crlf + ld de,str_ctlr_test_p1_ok + call prtstr + xor a + ret +; +; Attempt self-test of second port of controller ; -; Set keyboard controller command register to value in A +ctlr_test_p2: + call crlf2 + ld de,str_ctlr_test_p2 + call prtstr + ld a,$a9 ; self-test second port + call put_cmd_dbg + jp c,err_ctlr_to ; handle controller error + call get_data_dbg + jp c,err_ctlr_to ; handle controller error + cp $00 ; expected value? + jp nz,err_ctlr_test_p2 ; handle self-test error + call crlf + ld de,str_ctlr_test_p2_ok + call prtstr + xor a + ret +; +; PS/2 controller setup +; +; Set controller command register to value in A ; ctlr_setup: push af ; save incoming value @@ -243,7 +373,7 @@ kbd_reset: jp nz,err_kbd_reset call get_data_dbg jp c,err_ctlr_to ; handle controller error - cp $AA ; Success? + cp $aa ; Success? jp nz,err_kbd_reset call crlf ld de,str_kbd_reset_ok @@ -313,7 +443,7 @@ kbd_ident4: xor a ret ; -; Display active scan code set being used +; Display keyboard active scan code set being used ; kbd_dispsc: call crlf2 @@ -344,7 +474,7 @@ kbd_dispsc: xor a ret ; -; Set active scan code set to value in A +; Set keyboard active scan code set to value in A ; kbd_setsc: ld (kbd_setsc_val),a ; Save incoming value @@ -371,10 +501,9 @@ kbd_setsc: ; kbd_setsc_val .db 0 ; -; ; Read and display raw scan codes ; -kbd_showkeys: +kbd_echo: call crlf2 ld de,str_disp_scan_codes call prtstr @@ -384,7 +513,7 @@ read_loop: call bdos cp $1B ; Escape key? ret z - call check_read + call check_read_kbd jr nz,read_loop call get_data jp c,err_ctlr_to ; handle controller error @@ -399,13 +528,255 @@ read_loop: call prtchr jr read_loop ; +; Reset Mouse +; +mse_reset: + call crlf2 + ld de,str_mse_reset + call prtstr + ld a,$f2 ; Identify mouse command + call put_data_mse_dbg + jp c,err_ctlr_to ; handle controller error + call get_data_dbg + jp c,err_ctlr_to ; handle controller error + cp $fa ; Is it an ack as expected? + jp nz,err_mse_reset + call crlf + ld de,str_mse_reset_ok + call prtstr + xor a + ret +; +; Identify Mouse +; +mse_ident: + call crlf2 + ld de,str_mse_ident + call prtstr + ld a,$f2 ; Identify mouse command + call put_data_mse_dbg + jp c,err_ctlr_to ; handle controller error + call get_data_dbg + jp c,err_ctlr_to ; handle controller error + cp $fa ; Is it an ack as expected? + jp nz,err_mse_ident + call get_data_dbg + jp c,err_ctlr_to ; handle controller error + push af + call crlf + ld de,str_mse_ident_disp + call prtstr + pop af + call prtdecb + xor a + ret +; +; Enable mouse packet streaming +; +mse_stream: + call crlf2 + ld de,str_mse_stream + call prtstr + ld a,$f4 ; Stream packets cmd + call put_data_mse_dbg + jp c,err_ctlr_to ; handle controller error + call get_data_dbg + jp c,err_ctlr_to ; handle controller error + cp $FA ; Is it an ack as expected? + jp nz,err_mse_stream + xor a + ret +; +; Read and display raw mouse packets +; +mse_echo: + call crlf2 + ld de,str_disp_mse_pkts + call prtstr + call mse_track_disp ; show mouse status + xor a + ld (msebuflen),a +mse_echo1: + ld c,$06 ; BDOS direct console I/O + ld e,$FF ; Subfunction = read + call bdos + cp $1B ; Escape key? + ret z + call check_read_mse + jr nz,mse_echo1 + call get_data + jp c,err_ctlr_to ; handle controller error + push af + ld a,(msebuflen) ; current bytes in buf + ld hl,msebuf ; start of buf + call addhla ; point to next buf pos + pop af + ld (hl),a ; save byte in buf + ld a,(msebuflen) + inc a + ld (msebuflen),a ; inc buf len + cp 3 ; got 3 bytes? + jr nz,mse_echo1 ; if not, get some more + call mse_track + call mse_track_disp + jr mse_echo1 ; and loop +; +; Read and display data from keyboard and mouse +; +kbdmse_echo: + call crlf2 + ld de,str_disp_kbdmse + call prtstr + xor a + ld (msebuflen),a + call kbdmse_track_disp +; +kbdmse_echo1: + ; Check for user abort + ld c,$06 ; BDOS direct console I/O + ld e,$FF ; Subfunction = read + call bdos + cp $1B ; Escape key? + ret z +; + call kbdmse_echo2 + call kbdmse_echo3 + jr kbdmse_echo1 +; +kbdmse_echo2: + ; Check & handle keyboard data + call check_read_kbd + ret nz + call get_data + ld (kbd_byte),a + call kbdmse_track_disp + ret +; +kbdmse_echo3: + ; Check & handle mouse data + call check_read_mse + ret nz + call get_data + jp c,err_ctlr_to ; handle controller error + push af + ld a,(msebuflen) ; current bytes in buf + ld hl,msebuf ; start of buf + call addhla ; point to next buf pos + pop af + ld (hl),a ; save byte in buf + ld a,(msebuflen) + inc a + ld (msebuflen),a ; inc buf len + cp 3 ; full packet? + ret nz ; if not, loop + call mse_track + call kbdmse_track_disp + ret +; +; Update mouse tracking stuff +; This routine assumes that msebuf has been filled with a complete +; 3 byte mouse packet. +; +mse_track: + ; Buttons... + ld a,(msebuf) + ld (mse_stat),a +; + ; X Coordinate + ld a,(msebuf+1) + ld e,a + ld d,0 + ld a,(msebuf) + and %00010000 ; sign bit + jr z,mse_track_x + ld d,$ff ; sign extend +mse_track_x: + ld hl,(mse_x) + add hl,de + ld (mse_x),hl ; save result +; + ; Y Coordinate + ld a,(msebuf+2) + ld e,a + ld d,0 + ld a,(msebuf) + and %00100000 ; sign bit + jr z,mse_track_y + ld d,$ff ; sign extend +mse_track_y: + ld hl,(mse_y) + add hl,de + ld (mse_y),hl ; save result +; + ; Reset mouse buffer + xor a + ld (msebuflen),a + ret +; +; Display current mouse tracking info (buttons and coordinates) +; +mse_track_disp: + ld a,13 ; CR only + call prtchr + ld de,str_msestat1 ; "L=" + call prtstr + ld a,(mse_stat) + and %00000001 + call updown + ld de,str_msestat2 ; ", M=" + call prtstr + ld a,(mse_stat) + and %00000100 + call updown + ld de,str_msestat3 ; ", R=" + call prtstr + ld a,(mse_stat) + and %00000010 + call updown +; + ld de,str_msestat4 ; ", X=" + call prtstr + ld hl,(mse_x) ; save result + call prthexword +; + ld de,str_msestat5 ; ", Y=" + call prtstr + ld hl,(mse_y) ; save result + call prthexword +; + ret +; +updown: + jr nz,updown1 + ld de,str_up + jr updown2 +updown1: + ld de,str_down +updown2: + call prtstr + ret +; +; Display all keyboard and mouse tracking +; +kbdmse_track_disp: + call mse_track_disp + ld a,' ' + call prtchr + ld a,'[' + call prtchr + ld a,(kbd_byte) + call prthex + ld a,']' + call prtchr + ret +; ;======================================================================= -; Keyboard Controller I/O Routines +; PS/2 Controller I/O Routines ;======================================================================= ; wait_write: ; -; Wait for keyboard controller to be ready for a write +; Wait for controller to be ready for a write ; A=0 indicates success (ZF set) ; ld a,(timeout) ; setup timeout constant @@ -427,7 +798,7 @@ wait_write1: ; wait_read: ; -; Wait for keyboard controller to be ready to read a byte +; Wait for controller to be ready to read a byte ; A=0 indicates success (ZF set) ; ld a,(timeout) ; setup timeout constant @@ -458,9 +829,29 @@ check_read: xor $01 ; invert so 0 means ready ret ; +check_read_kbd: +; +; Check for keyboard data ready to read +; A=0 indicates data available (ZF set) +; + in a,(iocmd) ; get status + and %00100001 ; isolate input buf status bit + cp %00000001 ; data ready, not mouse + ret +; +check_read_mse: +; +; Check for mouse data ready to read +; A=0 indicates data available (ZF set) +; + in a,(iocmd) ; get status + and %00100001 ; isolate input buf status bit + cp %00100001 ; data ready, is mouse + ret +; put_cmd: ; -; Put a cmd byte from A to the keyboard interface with timeout +; Put a cmd byte from A to the controller with timeout ; CF set indicates timeout error ; ld e,a ; save incoming value @@ -484,18 +875,12 @@ put_cmd_dbg: call prtstr call prthex -; ld de,str_prefix ; " " -; call prtstr -; call prthex -; ld de,str_cmdout ; "->(CMD)" -; call prtstr - pop af ret ; put_data: ; -; Put a data byte from A to the keyboard interface with timeout +; Put a data byte from A to the controller interface with timeout ; CF set indicates timeout error ; ld e,a ; save incoming value @@ -519,17 +904,41 @@ put_data_dbg: call prtstr call prthex -; ld de,str_prefix ; " " -; call prtstr -; call prthex -; ld de,str_dataout ; "->(DATA)" -; call prtstr - pop af ret +; +put_data_mse: +; +; Put a data byte from A to the mouse interface with timeout +; CF set indicates timeout error +; + ld e,a ; save incoming value + push de + + ld a,$d4 ; mouse channel prefix + call put_cmd + pop de + ret c + + ld a,e ; recover value + call put_data + ret +; +put_data_mse_dbg: + ld e,a ; save incoming value + push de + + ld a,$d4 ; mouse channel prefix + call put_cmd_dbg + pop de + ret c + + ld a,e ; recover value + call put_data_dbg + ret ; -; Get a data byte from the keyboard interface to A with timeout +; Get a data byte from the controller interface to A with timeout ; CF set indicates timeout error ; get_data: @@ -552,10 +961,6 @@ get_data_dbg: call prtstr call prthex -; ld de,str_datain ; " (DATA)->" -; call prtstr -; call prthex - pop af ret ; @@ -569,6 +974,14 @@ err_ctlr_test: ld de,str_err_ctlr_test jr err_ret ; +err_ctlr_test_p1: + ld de,str_err_ctlr_test_p1 + jr err_ret +; +err_ctlr_test_p2: + ld de,str_err_ctlr_test_p2 + jr err_ret +; err_kbd_reset: ld de,str_err_kbd_reset jr err_ret @@ -585,6 +998,18 @@ err_kbd_ident: ld de,str_err_kbd_ident jr err_ret ; +err_mse_reset: + ld de,str_err_mse_reset + jr err_ret +; +err_mse_ident: + ld de,str_err_mse_ident + jr err_ret +; +err_mse_stream: + ld de,str_err_mse_stream + jr err_ret +; err_ret: call crlf2 call prtstr @@ -648,7 +1073,6 @@ prthexpre: call prtchr pop af ret - ; ; Print the value in A in hex without destroying any registers ; @@ -779,6 +1203,17 @@ crlf: pop af ; restore AF ret ; +; Add hl,a +; +; A register is destroyed! +; +addhla: + add a,l + ld l,a + ret nc + inc h + ret +; ; Delay ~10ms ; delay: @@ -804,30 +1239,36 @@ delay1: ; Constants ;======================================================================= ; -str_banner .db "Keyboard Information v0.2, 23-Dec-2021",0 -str_exit .db "Done, Thank you for using Keyboard Information!",0 -str_cmdport .db "Keyboard Controller Command Port: ",0 -str_dataport .db "Keyboard Controller Data Port: ",0 -;str_prefix .db " ",0 -;str_cmdout .db "->(CMD)",0 -;str_dataout .db "->(DATA)",0 -;str_datain .db " (DATA)->",0 -;str_timeout_write .db "Keyboard Controller Write Timeout, Status: ",0 -;str_timeout_read .db "Keyboard Controller Read Timeout, Status: ",0 -str_err_ctlr_to .db "Keyboard Controller I/O Timeout",0 -str_err_ctlr_test .db "Keyboard Controller Self-Test Failed",0 +str_banner .db "PS/2 Keyboard/Mouse Information v0.4, 7-Jan-2022",0 +str_exit .db "Done, Thank you for using PS/2 Keyboard/Mouse Information!",0 +str_cmdport .db "Controller Command Port: ",0 +str_dataport .db "Controller Data Port: ",0 +str_err_ctlr_to .db "Controller I/O Timeout",0 +str_err_ctlr_test .db "Controller Self-Test Failed",0 str_put_cmd .db " Sent Command ",0 str_put_data .db " Sent Data ",0 str_get_data .db " Got Data ",0 str_ctlr_test .db "Attempting Controller Self-Test",0 str_ctlr_test_ok .db "Controller Self-Test OK",0 +str_ctlr_test_p1 .db "Attempting Self-Test of First Controller Port",0 +str_ctlr_test_p1_ok .db "Controller First Port Self-Test OK",0 +str_err_ctlr_test_p1 .db "Controller First Port Self-Test Failed",0 +str_ctlr_test_p2 .db "Attempting Self-Test of Second Controller Port",0 +str_ctlr_test_p2_ok .db "Controller Second Port Self-Test OK",0 +str_err_ctlr_test_p2 .db "Controller Second Port Self-Test Failed",0 str_ctlr_setup .db "Performing Controller Setup",0 +str_ctlr .db "***** Basic 8242 PS/2 Controller Tests *****",0 str_basic .db "***** Basic Keyboard Checks and Scan Code Inventory *****",0 -str_trans_off .db "***** Testing with Scan Code Translation DISABLED *****",0 -str_trans_on .db "***** Testing with Scan Code Translation ENABLED *****",0 +str_trans_off .db "***** Testing Keyboard with Scan Code Translation DISABLED *****",0 +str_trans_on .db "***** Testing Keyboard with Scan Code Translation ENABLED *****",0 +str_basic_mse .db "***** Basic Mouse Tests *****",0 +str_kbdmse .db "***** Test All Devices Combined *****",0 str_kbd_reset .db "Attempting Keyboard Reset",0 str_kbd_reset_ok .db "Keyboard Reset OK",0 str_err_kbd_reset .db "Keyboard Reset Failed",0 +str_mse_reset .db "Attempting Mouse Reset",0 +str_mse_reset_ok .db "Mouse Reset OK",0 +str_err_mse_reset .db "Mouse Reset Failed",0 str_kbd_getsc .db "Requesting Active Scan Code Set from Keyboard",0 str_kbd_dispsc .db "Active Keyboard Scan Code Set is #",0 str_err_kbd_getsc .db "Error getting Active Keyboard Scan Code Set",0 @@ -835,18 +1276,42 @@ str_kbd_setsc .db "Setting Active Keyboard Scan Code Set to #",0 str_err_kbd_setsc .db "Error setting Active Keyboard Scan Code Set",0 str_kbd_ident .db "Keyboard Identification",0 str_kbd_ident_disp .db "Keyboard Identity: ",0 +str_mse_ident .db "Mouse Identification",0 +str_mse_ident_disp .db "Mouse Identity: ",0 +str_mse_stream .db "Enable Mouse Packet Streaming",0 +str_err_mse_stream .db "Error enabling Mouse Packet Streaming",0 +str_msestat1 .db "L=",0 +str_msestat2 .db ", M=",0 +str_msestat3 .db ", R=",0 +str_msestat4 .db ", X=",0 +str_msestat5 .db ", Y=",0 +str_up .db "UP",0 +str_down .db "DN",0 str_sc_tag .db "Scan Code Set #",0 str_sc_ok .db " IS supported",0 str_sc_fail .db " IS NOT supported",0 str_err_kbd_ident .db "Error performing Keyboard Identification",0 +str_err_mse_ident .db "Error performing Mouse Identification",0 str_disp_scan_codes .db "Displaying Raw Scan Codes",13,10 .db " Press keys on test keyboard to display scan codes",13,10 .db " Press on CP/M console to end",13,10,13,10,0 -str_run_failed .db "***** HARDWARE ERROR *****",13,10,13,10 +str_disp_mse_pkts .db "Displaying Mouse Packets",13,10 + .db " Move mouse and click mouse buttons",13,10 + .db " Press on CP/M console to end",13,10,13,10,0 +str_disp_kbdmse .db "Displaying Keyboard & Mouse Activity",13,10 + .db " Press keys on test keyboard to display scan codes",13,10 + .db " Move mouse and click mouse buttons",13,10 + .db " Press on CP/M console to end",13,10,13,10,0 +str_kbd_failed .db "***** KEYBOARD HARDWARE ERROR *****",13,10,13,10 .db "A basic hardware or configuration issue prevented",13,10 - .db "Keyboard Information from completing the full set",13,10 - .db "of tests. Check your hardware and verify the port",13,10 - .db "addresses being used for the keyboard controller",0 + .db "the completion of the full set of keyboard tests.",13,10 + .db "Check your hardware and verify the port",13,10 + .db "addresses being used for the controller",0 +str_mse_failed .db "***** MOUSE HARDWARE ERROR *****",13,10,13,10 + .db "A basic hardware or configuration issue prevented",13,10 + .db "the completion of the full set of mouse tests.",13,10 + .db "Check your hardware and verify the port",13,10 + .db "addresses being used for the controller",0 ; ;======================================================================= ; Working data @@ -859,6 +1324,15 @@ stack .equ $ ; stack top workbuf .fill 8 workbuf_len .db 0 ; +msebuf .fill 5,0 +msebuflen .db 0 +; +mse_stat .db 0 +mse_x .dw 0 +mse_y .dw 0 +; +kbd_byte .db 0 +; ctlr_cfgval .db 0 ; Value for controller cmd reg 0 ; cpuscl .db cpumhz - 2 diff --git a/Source/Apps/VGM/Tunes/filthy01.vgm b/Source/Apps/VGM/Tunes/filthy01.vgm new file mode 100644 index 0000000000000000000000000000000000000000..c161e1f32d7ec584b66d79bad954a92cbe315192 GIT binary patch literal 27392 zcmc&-|C3!sm4D3S3m{e0f?5iliuOEz~3!g2rS-{IagbkibAfG9>G0*hrN93wDKq{J689&*^je_U-#- zh?Z5$?(@C5-F^C;)8|{C(|z-~uiSUpf8SH9CFj&?|N6ZpHU760f4Bed1@hbe=YrZl zob&VZd*#otCI8Sl=|?x#)A_ah@>;q8|9?(BUC@S4J3h1UnT^k!db)BdTRBxvS54J3 zeA1hyvYYUA3;w)iD*YtB@JVl&%5K2d&G_@?sdNp#@JT!I-8q%sh%bE7)l=DOe67Ww zYp0U$CkK+Z>d91J_KO$m=|^jQ=}$i1NIR~nr%N&WwRbhr<@iqSsHeBy(MUgo@7q_` z(=XN<>D{$@x(=Uv@w<-i0eqVHy&m5iFRZ8Ey0DQxgzqi*th}U=-gF7jUjUppHqxKH z*hp`=s6YL|N9yVJ<&AW~UwYE#KUPn#?yRTFRyWe?F#jj;`_s2K($8o0^s~3u(>vBQ z(tK_`{pxx3^viP_>3zVffw=}TXD_~o@pO5)3x*Z(`SLs&PAB_ospqrV=}9eJl&t{O6GJYzv)lLli7{rbpD;W890$$ z-Py>Nt*&R_MD_{%{`Bqj?DJV811GXO*3`3nZX*LHGH@aTCo*s%11Be-IHKldjfUfe9d&% z2kYq$s>j<+Cp#SvBv1DyW69k7*KO{};*sP}`QF*u+=KahGYrdikdN=>6Gl@XdO-H_ zQ~F?)d$5pGi&)M_|5-rm-TZ`&G2EA1-#=)}QlggbSfN-g$|tqqTG!BN=nf>`?N0WS z8#2e@{A2`Sq&ImbnVr9+kC(gg_>%q|BaP(Mpn0WhUS{*6`7oLf=;&3hd5JbJ97+D% zNRFVxt41TK6`Ny_Fuy`*$^VPNf9mVo__Xz=&(4GX(r&yX>+r+m{6_MdK4|V7YVOz0 z1^1iTu8YBaO4NJ#f7oos$yHr=J_~~MZWBV#%m6UkN$opB935uXH;}%b6hPA*9UzPt z>?`s6;&jJiZFt`Cy9Xk%(?k+HL67QCvKkGGbm*Sk7MH9+!$NI%&Qn45qG7%^?8<*; z@*9u9dM~K;ra$;+Sa-7TFR?h|8QDpR#7}VZ;X19~)6Hb8p3DVPo5{F5Ii26FTrFgp zTqWeI$tnK0PPp34@JF_toEPr)gu4AoJZ6#8IU<>EA0>_;g6g)SM`dp)*<4R%V&$DQ~s21^%g5`Tl$k0!GQk{!b3zT~)bI(L!D zFdTFSUqry+M3-0}v8g9QCcg?$p$Pv0f1k<66B?HPQ z<2L^h4{M@iK-sBi8&^rAx{x0 z^x|v>34O0W`4$AhsME2NVoC)?2keBfHa}uaa8D-&lJ7N=M<_{j8SFnXl01w*p>HzV z2`@TFRL>9Ff(<2)prhe8j>U)m9W|1MxRf-nG#vyin1R?+LxQkjvfqt63|seNGAD;B zh&369*a>R{&Omaojz$_{0p-RVGE4@N?}G|T&LQ;Lue}tb1KR7v5DDv})qM%QXqE}< z2sr_?Ci4H(Cld;Nm>>rYq*!1M5JA?3ya)?P!3`}i1^b;rQV)~So9s(IAZGX=Wx6oK z7eSUOm($8}WQMU@mvVMLl?J@+rJd*oZ@(J2 zI8hC84&>Ji#u(aUuFlzs8I1Ae>2^*}V@%Wz7cx2ue;~$~&qW6y=mC$VyW{am;qm3b z>J2AokW-PsN#QXY-c$+Hh7-bLf;gZvPAHErhf5*W&KL_!N(O&m<*1LQBPSTH5TmWG@Wr zA#L3~;w%G=Bq2T%K}2BERG`F_PL(V$8#F2A*^x=JK@htmGKZ7x_2j%JMNv$Pa9J&; z*~C-e#p`G{w8ju29#ER!Y9tduQ_Mx9`IzeyqX%MplcQ*(g>1z$xB7_T1uw3?S}-5O zatiz>3B}(dv#!ygBnRu>)aNM z@TcQsuZvR|@tw(kjF4K;t#b4%#c6B!i%?bgj8-?eL?pk>jX4 z-Sb7V)0U~-^V{6>h57Gvmh0T}Tix^d`Og*p)zkD}r1B?b8%#jz%x!Rnxo2aP;KRZz zxwWIx`w;mGeX^M3`%SV$5PgUNXZxtRI&_f^T_h1n{+e-AA1{>n`XPX@&C+$+GJh!f zCLZqz=z_PV*92D=4ka98Au^e#p*8oUG8LI_k@c1E;6f22@?scQs(`teZrk~d^%NmV zq}Y;apunx7#L}GIpf6G{#@K_iV18n5$X%_IFZA&<*RB8vLJ1Albpg`1BG6nU3i#W| zIeswR$rRE%aE(8#OU42|RCd{?^ZSB$u1HywB-U-NAIP4CPuj_((iy*z@iAXnsyTTF zNP!*Lxx&lm6-wk{EC5jIe8BCapE0r4<__0fj5FpiQ9)7)!PXH>RG?v5A=%o%L?eRU54|A(%U;F%v<=vyLQ4DD@&R zJ2(H0NqL0vFeA9k&(X~+4>_a!6A?&SRZPi+Fu5V|@7H$qswf|Tuy zr$LHjy*M3Nj`HKkN*dlVcR=~;Xr63yBu?PB?P@)Xl}W=4*o4Hlx|3r8%qnJ}kTKa@ zzpany^RnXEqavY%6TDGnIUrFTWarw@mAh8WnrxQMW{;>)zokt!Yb3uAJ_D;y#Sn2R z^kJLR)DCpO;(F`FTo4o($=m0klGsEASsywM#01O?%66$=R?;}T&15QnQIF>KY70YB>AMLcDy0GuRr1ITOu-{3eOr9CLs*4}%wtGC z$5^(3`5P3#SkZ8z=?JAnPRBYV*^BIsMFf8<3nBd{=sU_hJX_Hk07L(7a%Dj_QqqzG zQzhMs#iKcr*uX6$a$iG|BF|r#c{Pu?g(y~Y!d9lVnwmV9ye?N2rHNu+X-Zq8fLv_S*l|s)=XfuUi6t>=l+njJI6b5nSR$tq@);)O21>4xtBZK`QbGOI9 zY%7-8D7fYcJT~rWt#4G;X#ie(mUu`Z%z@n^5jS>w?ULy|jvh?6u!j~EH$9L%k+gTg z=W}&w8)P`l5(%+Y*fNxiChY?UhcNhL13;x28r*mo%_n75W_%>0YD)~bP6P8LVW zymu8-A7J{TPsw`=49`p~TbMBM28kgC%sWCIEsJB{JD}EG3gfPR%QFdfB*A#;caN>h zx258^g{^)}5n(eQq6V5#sH=@Ll)J(;(3Y?vs*SV9v_qK=08Ge~40W|}j$m>`Ej3}f z+Bh4yBS!;G0~=gze8v%#Ie3PmB~~oVvmqv^tIlLZFA4-m)xUzQx^XF{3pNmTLMj9T zD4tr<9j^4=gu$ERL$R1#%e8cK8;TOaTLgUpmUvM;*$|Ti^+a?cX`w_z0v_mSB7~&PQ%#FqrK~J|(sK$~H zG$nm&e2O7J3UNl}Tv1e6(}+Ht14(9yfd(LEam^RR$cv&r#?0G8(f$3?#O3D+si4dyTTO*@NZ-J-KYik~ByfFqy zK`*&HziX3vlvP+~f?SfOn3IO9KrStOm8nidMB0dgQ57>4X)}faJ=|76GAXP`uep>4 z9HHce5iOLCEodNddAd`MM&ckUAV?r#=X{SaZ&U;lf6F;v9JJW!&PbYl3^E(1b*&G= zgCo-4!Q%-y$Fei`fdo&X>Zt}ctg8kR2VIZq&~ewmqYWHdoRmD`8hEyW4Y&C~VnWg2 z=?1pk>H~?&5IGZqlS`CTfAF;1Q9*86QAuWYVcOGuOkJPOyP0&8>mGKf!gIvshp;`8 zB%5rLOxS#%;B++UAlKkOIM4qV*Bm?lR;FPzGnZuI+xT$r88VF#7LSSafpcFE(v{_N zq@Fux$HAatA|bZoaG3LB?Q!MI$JVTvz)Z~Y6_cZuQ6tueeJo64fUW6xDWir5hkX4D z=QLVo)NrLqPe_<)EkbPv^bn&GOHWEdO*idaeUUaIj)a4(q&M##`f zAM8?i(ZE^;VV>|7kvJ@Y=W(vjqDF z1eonUEQ+Vrco|UzQiCs{qwNl2`Jfvsgn^QvByhtr2Cf?if@SDk zz?>0X(ruwmOt)^VT!NCqXmrJ*0R|y%Y4aPaF{1D~9$11hhFscMIYzw2(6h}?!Q&gE zCniGyCm43Ld6va|@WNK*r37S-L7dAnly+#8#txU0O7$&FA6V&8xdzsYvm)o=OaS-e z*d^;FFccBWCpRF-+u!KYbG>g`c?(MEPVB28DXcP0UTMsvC@CKu2RDe;Rz=4pK-h8= ziUaHalr}^O5E<)wREJKw28f3vQ5Yu(xP~p-;1VEg&}#{sw87;+W*os&{^tOkH+k^7 z!cU&4XN_H!QP4zb@)D+Ycmcv9W>v(43bKDJ~jpdLPqH98*sF<@00d};xirwQR;FwwjAyQFWCiP-I2@XDU z5SSxWPdMu!u>-r&5nDo$g6lK>df0-0Bcq7>CbAE38Gn>F^;TtAFJ`&Y)r$#utVoxs zdt3vP@>0L`3N_{$n5$;PLUDTp^@3}duMP9X?XjUU!uA1d6y~a8O>3-hxD5GXvs1F+ zI_+aKF;p}0)wTxU=Oq?3vXCOUb?FiW>~wTgZH#hr2J@uctPb6yOH{Q_%ABfwQg&AD zQ)R?V?DRVXT^0V#vwD(ZFBi5 zSskj-YHMA?D#Bro@PssEG;gMvmIOJwBJvuzWXC zx+~(j9N6U)ZxB!s;JPh88v^sl3EbsK!r(1xKC#P@J`9jEmIAX&)rx)@z%59=&0pMO z%uT~-hLt4|+5)>pEmj13BSpj_N+q@rC9js$CS@H zAeFrj>=Mu8w-PL9qv3gNh=LT7b*1Z39m-?XLZ^-`$~3G@1L$+wP?Tv{nMT7dZ78ZV z(~f|}<_Ktr^MoGp3RNQkX>m6dYZ!SRPv*?1Yxji}Ma&x%p6|!3l%wewH{yiGcEe@gUd zNAMmIa+Vt;DhyK#B}*zIU6ze)t#RXmnp{_zCu>e=F|GB?^H<}@BGC{+0*`&+B=qZk z!vvl)O^t1_p1{!e(AW_vF{E_ub}?H{Nc}agT~hy+rJ2U1>t3ho($TP3rF0sX-f}3d zF&glt-qwsPtuGq5P2yx_kB$azlh{!9=q*Q7=CJG_od-s6^X3S$$?1mB;0Y=`I!^zn zw2An{5L$V30P^G&9uj~`9z7yAcIfVaRP4|J+Vi1s=yE=az(a?QuAY~LLkAYIL!TC1 z(rxM*(_J`pK#UzaAbL(#9XbZY4jlvhn#2wrjA-G|%Sf9;2k6+LqoZeoPY%+dqak3W zIdnh>9lBK;xZjR9H04UjMk#9cX<`e-5Z%>CG9x}>T&ftj_in|f7c2FU(wN}-2<%yT zn?hk{XC743{1f*cQBjjUc;-#>OYGq)du(74qq4&h1YAS0JFz2)JiRA79jF#zxuWKb zL+k>HH+aD=QA#-ocX0Ynw%jb|(A147ZA-abBJ^v!kV!4Q*sPBy8|7jg+kMC78+f^* zc;_776QMk2{^(3M6M>`ZC^&M}1|+xIi}&Dxaurk3w@*&g$*z-~^_U^0o~_T@-4Nc^ zp}!SW5EK$M|8~9zBKMb)=jGv1LfIowJj!}Pkt=H9PE*1C$=c;<}QX z*TZp?;NV6nQc;O7WtddrrCcRt52WwkGcj=k(I5UX+@_dBr8vxO^0^3oIkzd@9gp36-$07J zlgz9{Ikg!GtV?YY1nyf4kIyo-S%P6a=FDNuh=D|SL6@<*?SYaxc0@uvPU(W-`(}nnd;Ci6Q_)Rp&6?VX|!l z3a}4x3eIi?SaKL$7?cUoRM9z=0<6cKTbiffCXxDVV7GA=2AuAT}MW1irqI!0QWCOfba-xEefy{fdD#qBUEc`^V)95q$-O6&SXuwT!9w=4> zM_NH#e^RQU8%QLEaKTOdK?wt)4T<0~%Cd+~lngi33sbQrgN`bS0&_96CY?9|hIon7 z_`(|rC36L0zsssIZDflRDE#t4M++HcT~x7o%!y!D43b1A3wDM;t%K=hCn)7gq1o+~ z);p+Na?_YV8X>F_`v>?KB;X@DNNAQ~WH$x?Rv!`prOx9Mz2(3TvRL8$s6+_mi`wPF z`wS;pG$LT(ogU6z)Fv{1OmLFLi7)kurEvGI1NJ@Y8mOvlh~9O;9>=E}I_Vmiap6$+ zt^=9hHBb}T;NEq>hBq}{rRuT8z3iankg&2DGPe|M!Klj2&gZ zOkG;fkY(p1tT+%{h0@nV z$cQS^o)f%~Sx{FIDqC51ijzWN=ygI705F$ zWT1vLOYSSNV?{a#sX>qr_7oMtO(>GZgw*>%ri<{9r^mAC1dCOYR&q3``aukkAT5sL z#T*4&xa45u6T-;7a*5?t4&i2~HEiR9?^4CnF+hMF4k?PI67y3ZY*}L240&#vR3OSL zTg8gUphF(uR?aLbDUqNUTi`%pV*0Q(y(Svby2rdUWQA(f!e;R*)JBBVJ$yN)y9(86 z0?bdz^~$3L3}`xcXK=kZ*{WA5E-)2}ErhDF)f)|HCNV|eNCoEg6rwm2^ zD<3Ols3an9MpevKY)E)~$nHW>T(MLOYWN3*MjGj=k$QR)KDXeraSH#~&=mgBA$+z> zAzs2iqx4BUzX6|{(RU5LA4J>3_-sPo$ET11XltaMczz>3tMOTje&0a*BltXq&l6Mm zAn&Q*AI}+SWPp_2jL#bU2BZv-vQ79rK9xU-Uijx{fKvvXGT@Zmg5Mj_3Y;?FlnGAw z=WH-vhWWD9XkUwO%$Gef)tx;twc)ORS-1GI8vY%r@8DmFy0P}v+P$@A?e5y3{F_mq zs(l@Q_tx&K-CygGCt2;wwXf9j+GVv2eR|OM%V@o<_Nm&U+BN9$>y96H{IcU$9j|o! zSBE|O44`}sQ0@lwui^J)wa?c20iz4Q`QO#GW%$1i{L1j;e)Reh`h2~17yfr??VqI2 IywZRF2mQwCp8x;= literal 0 HcmV?d00001 diff --git a/Source/Doc/GettingStarted.md b/Source/Doc/GettingStarted.md index 92ccc134..1c31f15b 100644 --- a/Source/Doc/GettingStarted.md +++ b/Source/Doc/GettingStarted.md @@ -1083,7 +1083,7 @@ through the normal startup process just like it was started from ROM. However, your ROM has not been updated and the next time you boot your system, it will revert to the system image contained in ROM. -# Upgrading via Flash Utility +## Upgrading via Flash Utility If you do not have easy access to a ROM programmer, it is usually possible to reprogram your system ROM using the FLASH utility from @@ -1128,7 +1128,7 @@ system and boot an operating system from ROM. Do not boot from a disk device yet. Review the boot messages to see if any issues have occurred. -# Upgrading via XModem Flash Updater +## Upgrading via XModem Flash Updater Similar to using the Flash utility, the system ROM can be updated or upgraded through the ROM based updater utility. This works by @@ -1143,7 +1143,7 @@ U (Begin Update). Then initiate the Xmodem transfer of the .img or More information can be found in the ROM Applications document. -# Post Update System Image and Application update process +## Post Upgrade System Image and Application Update Process Once you are satisfied that the ROM is working well, you will need to update the system images and RomWBW custom applications on your disk @@ -1214,23 +1214,22 @@ operating system on your disk. After this is done, you will need to use `SYSCOPY` to place the ZPM3 loader image on the boot tracks of all ZPM3 - boot disks/slices. The loader image is called `CPMLDR.SYS`. + boot disks/slices. The loader image is called `ZPMLDR.SYS`. You must then copy (at a minimum) `CPM3.SYS`, `ZCCP.COM`, `ZINSTAL.ZPM`, and `STARTZPM.COM` onto the disk/slice. Assuming you copied the ZPM3 boot files onto your RAM disk at A:, you would use: ``` - A>B:SYSCOPY C:=CPMLDR.SYS + A>B:SYSCOPY C:=ZPMLDR.SYS A>B:COPY CPM3.SYS C: A>B:COPY ZCCP.COM C: A>B:COPY ZINSTAL.ZPM C: A>B:COPY STARTZPM.COM C: ``` - You may be wondering if the references to `CPMLDR.SYS` and - `CPM3.SYS` are typos. They are not. ZPM3 uses the same loader - image as CPM3. The ZPM3 main system code file is called `CPM3.SYS` + You may be wondering if the reference to `CPM3.SYS` is a typo. + It is not. The ZPM3 main system code file is called `CPM3.SYS` which is the same name as CP/M 3 uses, but the file contents are not the same. @@ -1263,29 +1262,34 @@ images. * FAT.COM * TUNE.COM -# System Update +## System Update -If the system running ROMWBW utilizes the SST39SF040 Flash chip then it is possible to do a System Update in place of -a System Upgrade in some cases. +If the system running ROMWBW utilizes the SST39SF040 Flash chip then it +is possible to do a System Update in place of a System Upgrade in some +cases. -A System Update would involve only updating the BIOS, ROM applications and CP/M system. +A System Update would involve only updating the BIOS, ROM applications +and CP/M system. -A System Update may be more favorable than a System Upgrade in cases such as: +A System Update may be more favorable than a System Upgrade in cases +such as: - Overwriting of the ROM drive is not desired. - Space is unavailable to hold a full ROMWBW ROM. - To mimimize time taken to transfer and flash a full ROM. - Configuration changes are only minor and do not impact disk applications. -The ROMWBW build process generates a system upgrade file along with the normal ROM image and can be identified by the -extension ".upd". It will be 128Kb in size. In comparison the normal ROM image will have the extension ".rom" and be -512Kb or 1024Kb in size. +The ROMWBW build process generates a system upgrade file along with +the normal ROM image and can be identified by the extension ".upd". It +will be 128Kb in size. In comparison the normal ROM image will have +the extension ".rom" and be 512Kb or 1024Kb in size. -Transferring and flashing the System Update is accomplished in the same manner as described above in *Upgrading* with -the required difference being that the flash application needs to be directed to complete a partial flash using the -/p command line switch. +Transferring and flashing the System Update is accomplished in the +same manner as described above in *Upgrading* with the required +difference being that the flash application needs to be directed to +complete a partial flash using the /P command line switch. -`E>flash write rom.upd /p` +`E>FLASH WRITE ROM.UPD /P` # RomWBW Distribution @@ -1303,7 +1307,7 @@ directories are: | Application | Description | | ----------- | -------------------------------------------------------------- | -| Binary | The final output files of the build process are placed here. Most importantly, are the ROM images with the file names ending in ".rom". | +| Binary | The final output files of the build process are placed here. Most importantly, the ROM images with the file names ending in ".rom". | | Doc | Contains various detailed documentation including the operating systems, RomWBW architecture, etc. | | Source | Contains the source code files used to build the software and ROM images. | | Tools | Contains the MS Windows programs that are used by the build process or that may be useful in setting up your system. | @@ -1327,10 +1331,11 @@ these applications are no longer provided. driver. * Ed Brindley contributed some of the code that supports the RC2014 platform. -* Phil Summers contributed Forth and BASIC in ROM, the AY-3-8910 sound -driver as well as a long list of general code enhancements. +* Phil Summers contributed the Forth and BASIC adaptations in ROM, the +AY-3-8910 sound driver as well as a long list of general code +enhancements. * Phillip Stevens contributed support for FreeRTOS. -* Curt Mayer contributed the Linux / MacOS build process. +* Curt Mayer contributed the original Linux / MacOS build process. * UNA BIOS and FDISK80 are the products of John Coffman. * FLASH4 is a product of Will Sowerbutts. * CLRDIR is a product of Max Scane. @@ -1341,6 +1346,50 @@ the SN76489 sound driver. Contributions of all kinds to RomWBW are very welcome. +# Licensing + +RomWBW 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. + +RomWBW 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 RomWBW. If not, see . + +Portions of RomWBW were created by, contributed by, or derived from +the work of others. It is believed that these works are being used +in accordance with the intentions and/or licensing of their creators. + +If anyone feels their work is being used outside of it's intended +licensing, please notify: + +> Wayne Warthen +> wwarthen@gmail.com + +RomWBW is an aggregate work. It is composed of many individual, +standalone programs that are distributed as a whole to function as +a cohesive system. Each program may have it's own licensing which +may be different from other programs within the aggregate. + +In some cases, a single program (e.g., CP/M Operating System) is +composed of multiple components with different licenses. It is +believed that in all such cases the licenses are compatible with +GPL version 3. + +RomWBW encourages code contributions from others. Contributors +may assert their own copyright in their contributions by +annotating the contributed source code appropriately. Contributors +are further encouraged to submit their contributions via the RomWBW +source code control system to ensure their contributions are clearly +documented. + +All contributions to RomWBW are subject to this license. + # Getting Assistance The best way to get assistance with RomWBW or any aspect of the diff --git a/Source/Images/fd_zsdos.txt b/Source/Images/fd_zsdos.txt index 0d7c71ae..333d6526 100644 --- a/Source/Images/fd_zsdos.txt +++ b/Source/Images/fd_zsdos.txt @@ -47,7 +47,7 @@ d_cpm22/u0/XSUB.COM 0: # Add Tune sample files # ../../Binary/Apps/Tunes/*.pt? 3: -../../Binary/Apps/Tunes/*.mym 3: +#../../Binary/Apps/Tunes/*.mym 3: ../../Binary/Apps/Tunes/*.vgm 3: # # Add OS image From 79dc868e6eaee758bd4008bb37eb95d8d4a21dde Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Sat, 22 Jan 2022 14:40:17 -0800 Subject: [PATCH 02/34] Support MBC CTCDART Board --- Source/HBIOS/Config/MBC_std.asm | 2 ++ Source/HBIOS/cfg_mbc.asm | 4 ++-- Source/HBIOS/ctc.asm | 2 +- Source/HBIOS/std.asm | 24 ++++++++++++++++++++++++ Source/ver.inc | 2 +- Source/ver.lib | 2 +- 6 files changed, 31 insertions(+), 5 deletions(-) diff --git a/Source/HBIOS/Config/MBC_std.asm b/Source/HBIOS/Config/MBC_std.asm index 8d9fec06..ce2106b2 100644 --- a/Source/HBIOS/Config/MBC_std.asm +++ b/Source/HBIOS/Config/MBC_std.asm @@ -37,3 +37,5 @@ PPIDEENABLE .SET TRUE ; PPIDE: ENABLE PARALLEL PORT IDE DISK DRIVER (PPIDE.ASM) ; DSKYENABLE .SET FALSE ; ENABLES DSKY DSKYMODE .SET DSKYMODE_NG ; DSKY VERSION: DSKYMODE_[V1|NG] +; +CTCENABLE .SET FALSE ; ENABLE ZILOG CTC SUPPORT diff --git a/Source/HBIOS/cfg_mbc.asm b/Source/HBIOS/cfg_mbc.asm index ec23472c..ef403af0 100644 --- a/Source/HBIOS/cfg_mbc.asm +++ b/Source/HBIOS/cfg_mbc.asm @@ -49,7 +49,7 @@ CTCMODE .EQU CTCMODE_CTR ; CTC MODE: CTCMODE_[NONE|CTR|TIM16|TIM256] CTCPRE .EQU 256 ; PRESCALE CONSTANT (1-256) CTCPRECH .EQU 2 ; PRESCALE CHANNEL (0-3) CTCTIMCH .EQU 3 ; TIMER CHANNEL (0-3) -CTCOSC .EQU 614400 ; CTC CLOCK FREQUENCY +CTCOSC .EQU (4915200/8) ; CTC CLOCK FREQUENCY ; EIPCENABLE .EQU FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; @@ -120,7 +120,7 @@ Z2UENABLE .EQU FALSE ; Z2U: ENABLE Z280 UART SERIAL DRIVER (Z2U.ASM) ; ACIAENABLE .EQU FALSE ; ACIA: ENABLE MOTOROLA 6850 ACIA DRIVER (ACIA.ASM) ; -SIOENABLE .EQU FALSE ; SIO: ENABLE ZILOG SIO SERIAL DRIVER (SIO.ASM) +SIOENABLE .EQU TRUE ; SIO: ENABLE ZILOG SIO SERIAL DRIVER (SIO.ASM) SIODEBUG .EQU FALSE ; SIO: ENABLE DEBUG OUTPUT SIOBOOT .EQU 0 ; SIO: REBOOT ON RCV CHAR (0=DISABLED) SIOCNT .EQU 1 ; SIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP diff --git a/Source/HBIOS/ctc.asm b/Source/HBIOS/ctc.asm index d4c6b156..b7be79e6 100644 --- a/Source/HBIOS/ctc.asm +++ b/Source/HBIOS/ctc.asm @@ -101,7 +101,7 @@ CTC_PREINIT1: ; EACH CHANNEL. BELOW WE SET THE BASE VECTOR TO THE ; START OF THE IVT, SO THE FIRST FOUR ENTIRES OF THE ; IVT CORRESPOND TO CTC CHANNELS A-D. - LD A,0 + LD A,INT_CTC0A * 2 OUT (CTCBASE),A ; SETUP CTC BASE INT VECTOR ; ; IN ORDER TO DIVIDE THE CTC INPUT CLOCK DOWN TO THE diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index 500c4fea..630d8752 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -670,6 +670,28 @@ INT_SIO1 .EQU 14 ; ZILOG SIO 1, CHANNEL A & B ; Z80-BASED SYSTEMS + + #IF (PLATFORM == PLT_MBC) + +;INT_CTC0A .EQU 0 ; ZILOG CTC 0, CHANNEL A +;INT_CTC0B .EQU 1 ; ZILOG CTC 0, CHANNEL B +;INT_CTC0C .EQU 2 ; ZILOG CTC 0, CHANNEL C +;INT_CTC0D .EQU 3 ; ZILOG CTC 0, CHANNEL D +INT_UART0 .EQU 4 ; MBC UART 0 +INT_UART1 .EQU 5 ; MBC UART 1 +INT_SIO0 .EQU 8 ; ZILOG SIO 0, CHANNEL A & B +INT_SIO1 .EQU 9 ; ZILOG SIO 1, CHANNEL A & B +INT_CTC0A .EQU 12 ; ZILOG CTC 0, CHANNEL A +INT_CTC0B .EQU 13 ; ZILOG CTC 0, CHANNEL B +INT_CTC0C .EQU 14 ; ZILOG CTC 0, CHANNEL C +INT_CTC0D .EQU 15 ; ZILOG CTC 0, CHANNEL D +;INT_PIO0A .EQU 9 ; ZILOG PIO 0, CHANNEL A +;INT_PIO0B .EQU 10 ; ZILOG PIO 0, CHANNEL B +;INT_PIO1A .EQU 11 ; ZILOG PIO 1, CHANNEL A +;INT_PIO1B .EQU 12 ; ZILOG PIO 1, CHANNEL B + + #ELSE + INT_CTC0A .EQU 0 ; ZILOG CTC 0, CHANNEL A INT_CTC0B .EQU 1 ; ZILOG CTC 0, CHANNEL B INT_CTC0C .EQU 2 ; ZILOG CTC 0, CHANNEL C @@ -683,6 +705,8 @@ INT_PIO0B .EQU 10 ; ZILOG PIO 0, CHANNEL B INT_PIO1A .EQU 11 ; ZILOG PIO 1, CHANNEL A INT_PIO1B .EQU 12 ; ZILOG PIO 1, CHANNEL B + #ENDIF + #ENDIF #DEFINE IVT(INTX) HB_IVT+(INTX * 4)+1 diff --git a/Source/ver.inc b/Source/ver.inc index f14ca9b3..b3061a4a 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,4 +2,4 @@ #DEFINE RMN 1 #DEFINE RUP 1 #DEFINE RTP 0 -#DEFINE BIOSVER "3.1.1-pre.146" +#DEFINE BIOSVER "3.1.1-pre.147" diff --git a/Source/ver.lib b/Source/ver.lib index a22e049f..ade54c98 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 1 rup equ 1 rtp equ 0 biosver macro - db "3.1.1-pre.146" + db "3.1.1-pre.147" endm From 85adb811bbe39486e822715691325691065cf512 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Sat, 22 Jan 2022 17:15:07 -0800 Subject: [PATCH 03/34] Add CTC Hardware Detection --- Source/HBIOS/Config/MBC_std.asm | 2 - Source/HBIOS/cfg_mbc.asm | 2 +- Source/HBIOS/ctc.asm | 70 ++++++++++++++++++++++++++++----- Source/ver.inc | 2 +- Source/ver.lib | 2 +- 5 files changed, 64 insertions(+), 14 deletions(-) diff --git a/Source/HBIOS/Config/MBC_std.asm b/Source/HBIOS/Config/MBC_std.asm index ce2106b2..8d9fec06 100644 --- a/Source/HBIOS/Config/MBC_std.asm +++ b/Source/HBIOS/Config/MBC_std.asm @@ -37,5 +37,3 @@ PPIDEENABLE .SET TRUE ; PPIDE: ENABLE PARALLEL PORT IDE DISK DRIVER (PPIDE.ASM) ; DSKYENABLE .SET FALSE ; ENABLES DSKY DSKYMODE .SET DSKYMODE_NG ; DSKY VERSION: DSKYMODE_[V1|NG] -; -CTCENABLE .SET FALSE ; ENABLE ZILOG CTC SUPPORT diff --git a/Source/HBIOS/cfg_mbc.asm b/Source/HBIOS/cfg_mbc.asm index ef403af0..08547480 100644 --- a/Source/HBIOS/cfg_mbc.asm +++ b/Source/HBIOS/cfg_mbc.asm @@ -41,7 +41,7 @@ RTCIO .EQU $70 ; RTC LATCH REGISTER ADR KIOENABLE .EQU FALSE ; ENABLE ZILOG KIO SUPPORT KIOBASE .EQU $80 ; KIO BASE I/O ADDRESS ; -CTCENABLE .EQU FALSE ; ENABLE ZILOG CTC SUPPORT +CTCENABLE .EQU TRUE ; ENABLE ZILOG CTC SUPPORT CTCDEBUG .EQU FALSE ; ENABLE CTC DRIVER DEBUG OUTPUT CTCBASE .EQU $B0 ; CTC BASE I/O ADDRESS CTCTIMER .EQU TRUE ; ENABLE CTC PERIODIC TIMER diff --git a/Source/HBIOS/ctc.asm b/Source/HBIOS/ctc.asm index b7be79e6..9d0d69f7 100644 --- a/Source/HBIOS/ctc.asm +++ b/Source/HBIOS/ctc.asm @@ -19,17 +19,27 @@ CTC_TIMCFG .EQU %11010111 ; CTC TIMER CHANNEL CONFIG ; |+-------- COUNTER MODE ; +--------- INTERRUPT ENABLE ; -#IF (CTCTIMER) +#IF (INTMODE != 2) + .ECHO "*** WARNING: CTC TIMER DISABLED -- INTMODE 2 REQUIRED!!!\n" +#ENDIF +; +#IF (CTCTIMER & (INTMODE == 2)) +; + #IF (INT_CTC0A % 4) + + .ECHO INT_CTC0A + .ECHO "\n" + .ECHO (INT_CTC0A % 4) + .ECHO "\n" + + .ECHO "*** ERROR: CTC BASE VECTOR NOT /4 ALIGNED!!!\n" + !!! ; FORCE AN ASSEMBLY ERROR + #ENDIF ; ; ONLY IM2 IMPLEMENTED BELOW. I DON'T SEE ANY REASONABLE WAY TO ; IMPLEMENT AN IM1 TIMER BECAUSE THE CTC PROVIDES NO WAY TO ; DETERMINE IF IT WAS THE CAUSE OF AN INTERRUPT OR A WAY TO ; DETERMINE WHICH CHANNEL CAUSED AN INTERRUPT. -; - #IF (INTMODE != 2) - .ECHO "*** ERROR: CTC REQUIRES INTMODE 2!!!\n" - !!! ; FORCE AN ASSEMBLY ERROR - #ENDIF ; CTC_PREIO .EQU CTCBASE + CTCPRECH CTC_SCLIO .EQU CTCBASE + CTCTIMCH @@ -82,6 +92,9 @@ CTCTIVT .EQU INT_CTC0A + CTCTIMCH ; ; CTC_PREINIT: + CALL CTC_DETECT ; DO WE HAVE ONE? + LD (CTC_EXIST),A ; SAVE IT + RET NZ ; ABORT IF NONE ; ; RESET ALL CTC CHANNELS LD B,4 ; 4 CHANNELS @@ -92,7 +105,7 @@ CTC_PREINIT1: INC C ; NEXT CHANNEL PORT DJNZ CTC_PREINIT1 ; -#IF (CTCTIMER) +#IF (CTCTIMER & (INTMODE == 2)) ; SETUP TIMER INTERRUPT IVT SLOT LD HL,HB_TIMINT ; TIMER INT HANDLER ADR LD (IVT(CTCTIVT)),HL ; IVT ENTRY FOR TIMER CHANNEL @@ -136,9 +149,20 @@ CTC_PRTCFG: LD A,CTCBASE ; GET BASE PORT CALL PRTHEXBYTE ; PRINT BASE PORT ; -#IF (CTCTIMER) + LD A,(CTC_EXIST) ; IS IT THERE? + OR A ; 0 MEANS YES + JR Z,CTC_PRTCFG1 ; IF SO, CONTINUE +; + ; NOTIFY NO CTC HARDWARE + PRTS(" NOT PRESENT$") + OR $FF + RET +; +CTC_PRTCFG1: ; - PRTS(" MODE=$") ; FORMATTING +#IF (CTCTIMER & (INTMODE == 2)) +; + PRTS(" TIMER MODE=$") ; FORMATTING #IF (CTCMODE == CTCMODE_CTR) PRTS("CTR$") #ENDIF @@ -175,3 +199,31 @@ CTC_PRTCFG: ; XOR A RET +; +; +; +CTC_DETECT: + LD A,CTC_TIM256CFG + OUT (CTCBASE),A + XOR A + OUT (CTCBASE),A + ; CTC SHOULD NOW BE RUNNING WITH TIME CONSTANT 0 + LD A,CTC_TIM256CFG ; RESET + OUT (CTCBASE),A + IN A,(CTCBASE) ; SHOULD READ 0 NOW + CP 0 + JR NZ,CTC_NO + LD A,$FF ; TIME CONSTANT $FF + OUT (CTCBASE),A + IN A,(CTCBASE) ; SHOULD NOT BE 0 NOW + CP 0 + JR Z,CTC_NO + XOR A + RET +CTC_NO: + OR $FF + RET +; +; +; +CTC_EXIST .DB $FF diff --git a/Source/ver.inc b/Source/ver.inc index b3061a4a..1176d907 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,4 +2,4 @@ #DEFINE RMN 1 #DEFINE RUP 1 #DEFINE RTP 0 -#DEFINE BIOSVER "3.1.1-pre.147" +#DEFINE BIOSVER "3.1.1-pre.148" diff --git a/Source/ver.lib b/Source/ver.lib index ade54c98..496282d8 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 1 rup equ 1 rtp equ 0 biosver macro - db "3.1.1-pre.147" + db "3.1.1-pre.148" endm From 7b46b1a89bdd8e58a2a908db9e5b8f9b4d054140 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Sun, 23 Jan 2022 11:49:44 -0800 Subject: [PATCH 04/34] Update ZMRX/ZMTX Update ZMTX/ZMRX to version 1.1 --- Source/Images/Common/All/ZMRX.COM | Bin 29495 -> 31474 bytes Source/Images/Common/All/ZMTX.COM | Bin 22789 -> 24832 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Source/Images/Common/All/ZMRX.COM b/Source/Images/Common/All/ZMRX.COM index 6a5286af8ed4bf9e5d8da5eb4b43f1f71a0b8f4a..19f317b181de2df095e653f7a2a2dfb303137a25 100644 GIT binary patch literal 31474 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 M14A76|CkG5&pr3t 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 A8vpp0bJV7eCGT4{QfAKm-p^H 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

W!PGK>P2VYOno4Av5=0;|aXrmh@fy9Gdg( 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 P$J}yV_XdOI<9+WB(D;5{ delta 54299 zcmZVlWmH^E6E+Ip43+@`1b6q~4#8c5`{3?QaM(D(WpD}Z?!h4h5)UP#ZN{piJ`gO*c3uU@k}8ox1H^`1u2_I}L`f zcv0t6pIWvzpXbS<-teBL<9(mpbwo>Yd7@@3Z?6aedP&Jbba3?PJmm(ent)vS*N>rS$w!!s1#)Dy=M(Es84=kp13Ho+t%6+}uPbZ$HP@3XTbC!! z)`t|A+earD0GlGA)UVYmmzx=ir76uwb)w|-ts^UMF4UBJA1Jq<0AHSC+USD2Qd3oX z$x>VT)s?{t+LgOX)RSqP!Bm2du`sf=w>ztu;OMD!q+j2(Yu^OzE!>Am#54;O-P0}3 z<9C&|t$M4@K-S$R3t#r!^9osQc~g4T%3dolzAZ8XaL-@FeBnQc?mzkU4wv)O_dPc* zQT)6byf)~jm%B>SC(*@63qI10EXA|A1g-Pzd~D*;0T?d5Avr~c{&3Fh+Hqx13co@eK8&1k92inyCNR}t-$*+`X|rUmmP z=U#zwVJENS&N%?DbMB#sJh|AXG_bMj<6iIU@u24IWK6&*-xd1JEplsZ`QRAf3i6M-xrk|@P zSYe&F@c77goLvUzRsHPJw0K%p?@-G%O5YMN{o-U`J-@Q%I(7KCH|28Hl_2SJ(k7Bv zW%<=YrYFqf!~oPVB~IWWxrr4IeWJ#^o>7f8oZ(PMPR zdyJp^y8d!E37s9-`N3r5I3Msp#8XCULbU!?W#h%|c5rTLo*iF&#Paj9S7e?Oy8Z^H zh$A|po0*@t!mF-O(YdkiHVV`vY9+AkBbL{!tK!5vjN)SEKRw+JakT3Xd!Lhl@6`Qz zZ!yF*t)slI-^UcNUz4IKt`_v0F`#tSA0&w3;7J;`2*kW(QB0VXqs;1J&Y|()NolM86DC3P`xYI11sq?8Jx5Y@PT6_b`UVA>(J zG;BKKRy1PTy$vwh{cNvLU(W0bh=VPotY@cnw<9!TY0pdy9c+(uzML`t5py+-($O>z zFEN&gjFCk%CI4i?%0*iYM6~{AosoM;tYV64%?5qnL0DXs&0-Y9dgN zB#5D8Q8lm0CvvgmD8?;derPFZC^YNVwCZ;z9J$1P5DP|)3FJZ;RZ(?s{$98NO13E~ zDKr*u`c53XM_*2#GE%sKm}<#T{$6(<+Cka$gzza6F(#0Wfmu{sSQTbUK69Z<3c+e@ zI$#5t--98X(G3S|D9gZl7k_f&CL5xj9$IS9l#_F6Z59kgj5K0%BgpHbNy}I*fr(HQ zt6j;E=5@ic+;|dd9Z0AJwM?maX-FkYV4nWamLP5MUngN%Qz)n}c9>bYs-z<$c2kf| zZqWiHo3_t((nU*P7I7Os*K9FcPl-_%ZMtAyX_$ePP4!0rY9Qo^LzmEWiiX4WcZPxF?vD#6O2(KQvP z0j24fCadMrImt19=>MJ+H<*Y+FsjTB#(@zDzH(LUy!3#{88Qo!UL%$Q}SY~I^A;7G0x#v$6G!Ty`GAqRO(xXbzt(U;1 zh~oNRcz)@6hS-MItAod|QY`5+z&S8K)7~+EC~#)_1@qGi-Si%8g{W{m8Ps%w&=hR~ zbCZW#J1yCVZBT)heNr{;gF~&0HdAnWK|MgG#ONJeW}0_Sb26~iyQf~>m|xos53<}~6Q7ArbU*{27o5Eaq9 z4UW4%x%BfxRlmso2A)pKul3$pv^*@?tM_~rd}OQWO~z^hGgcx&199Kr@N%*8^6*k{ z^6|0qaZzx?{;+dF3s}jZnw*$WIQEbKlyJHDSUGukD7d&eS@}76D7bmpS$R334di&~ z`RyPuG@J_)n*D!OIoMhGdAKRKdAV7+cqzC!xmh_m`TsW|Dfc@l4~HUbLS%d{er{G? zE&&Qo4lY(s0Zs}o0Y2EweE-vHf$2?fsN-<)va|B=a#3*daI^CBQgHEcuyRA$@yJ0O zd{8Y;a~y6iRz8?d?64>BQE>6_vhwlqL8sWr;P{{?oR+v8FrV3BfpKxNa&U1|aB;D- za&bcQS;^t}p%GkW_?!YTPuY1WIQThXk^i5GIQahODx3h6j2or_i-DV+8#VT83nAQAWrtCR_+csPz-sK8!sgy!e=IBPpBypc4*~?w#pB1>nk8m{`4(3xc9({ z(~2Bcz@5&48t6p9xYF52mtvSMb1eRy!-+V^;;K)snI)FlPMVSM^;x@#L4Sh3&m{PY ziZ^?$tdq5DQIp4(ZULLi$IonNXLJ;5?Od42Uz!5VH84`D9)>1nnB^F-(&d%mpZd3* z%r|kRU(P-(rH>ky9P3%2OuN}!J_7r`E6i!f_Kw$%OEz2Mm50vFe;=LNA!lcH&V=mB z)g@RVRq#Yiv?#@yi>5C7Vnf3QPKXa{sn?TMzI^Uh%cnOMQ-`i=r*{3y&RLmFGtON2 zr8V=-NomG=C8ZozKu(s3taZ4D-ScP>#Zw#>@ynOUjY(i$izwW z!gkLFU)3D{&(h<^y#l$Ta){{rS=W{2B20T> z@$rE*r|=?+nup~#It>naM4+=v552=}#;Qq=<+svJkw#5s%-M3doqDOyAJlGNAP{h@ z39qXmtFtnSWh*>cK&?3(!egq$iT`+5imH}2=F5owuFO32%r0l71I6QxFLpPkU`*Ol z?fbKD4Fuh^8DV@vXyvd|Ft3j@Pu!wi$oaw3YG+eyimbYP0SVXZ5tx%uSvbv)TJE07 z%JmJB>pDZ;S~-R56~3+r+PK;6f46JlvtsZ%hMcgA?U%{^XIPC%+43m?9PyoP*Jh3y zDN>as{>95hd(WI_*qG$%C;rU!j87ZCrp}X7)y-N5Y2?@G=qcM02?g__70hx#F z*A$_&SUDGqItuYIWFXaY>h@|1wFiA!$+g4a*p-Aynaz5hbkVc!pdlRvv&=cIs&&Dv zE~&oKn!OVngFK0BwJx4ZS1iVS!EnLWbj|@|K`K?WA^Ahvh-@??DYL~YK~xIdEha&m z@9oxLJ6=44s(B%f%8kT^@KG841`m>)?X@)H=}<%``85~PH(+f?JB|$L&k)^n?M&^$ z>5O}{Xu|s+DD`?0F(a>m!sIFV=)Ak;<5!{k1LgPmzR8NRz6!{fUn(idG$~KH|H?rF z00M=sCo5)*0)-e^j#KBQDFT!!^6)2Lj3wr*HG=#=_Tp%1-_k%j#JI4kR2jQZ({^!^ zIizuJZAqDNcz~mQx@h*w_>mgTQ8mM{3g@{Tt9VMdm}dLg&Fev+2MK%@We7%p zpSK?AllRQX%>B4qQOVvzwei_)D0H<>7yXB|vqNhFj!4plET_96wCm+Z9;ZdUfut8^ zKTZAIrl)T2o0@7%$H&8`XHnxk`zB}Y-KltMU-rYy8(>mOV1@*vdyrm9ZuxOwRHtlt zdT;sYWbox-j8MP%^6E!Ad2bHW-(1K^(_!WlPlh<$OJR)|V z;}_M7QuMzydbL?~b6qV*l`D3p#&wR`hD`_L1+g)$M2pR)Z51plH`Envj!j=@mNcE` zDg{SxD*#5rc%?AmD>#Q6gZD5k;%fjC{c=l1s^qmQ7+9#Tte|Y@bLfwFw*& zAX=(jwUGe}x4#}X$j;}>X$tv-QmL7Sh$BZMN*7=;;^W-M2*Fw4gexRP3SizJ5Ac`8 zg4%GPvcVrl8uI%xKU&~?70Q*x@uWeALuAFs?=S4*vXrTiCM$kh#BaeOkf*vCzX(IZ z(vfDpmLuqcl*GfjIFF80)@n43nSg4Hsxzu|=yoDk%3Hhr2^6Gg$q7X^oJUgVBm;W8 z7-bRvE>%g`cA}ytR$Orco5xBB?|_T$cNX@S`Bcn2B=HYKru`6Y%B)^ zveSu~Oad|IC1Ur#P>p1wFz2eG=`H4c9ZZfa!HzBpT9)68DML`C$0-egLB+Mu=xtT` zU9}Hj|6v5h;ZzB5OHz>1+KQdpW;~kRdpKeh^i<`1RHQp^Kn2S(TFxZje2Lt+&T&x0py%LUav?Q;FObPZPAt$V? z*2A!5osbl?M$})0L~kdWkKlbm{*;8ql-tLe#KoR#eOc}S>Xd*>a%5JMQgATki4;|Ra0V*wEGsSgG-^v~P$+f62)g?P4ou9?E8o{@hiqqjN)p)fV(a?j210 zL#q5O7YQoiY<5%*nt-NAFqBrNJM-tTn$#XPzt2cHAGW|;f_(vh3YEYjyqd!IS3sm+ z=zgzBb|Y)k>}HKgk2^X#0zEIv*)UcXU4&yOyXKygnum zsF@)n;jy@ooou=M0Aa`5HppT2w%gfnLpilRDfCF%!w=kOK-L6OGq<{Hbzg`^~Iq0J> zJhpMWf`L!IoT{_N?qBiXqLd7R_T{J8c?Qy#$6 zbnLcOmKnUu-ANwfXq_x6;AC|^@#14eb~j!cVw%+LRkn`koapY<-PvV$CPIq$d;Q^F zsTZgN=VG)ODw3S@KD#++i3_FwXHQ?%^>?fErdhjdqb{;ysAr?_DYtSFVaL4c^70%A zywh>ysU?H_!8jf-Em^<0TYIr{b^86ol)t%4bUl3(5RBEaW7U4XjYPU=Um+h-tJq^E z*=^VE5skH~wOrReutht%XB*0%MBlojH3iCKa5b7^A|G$+J6JybagbFOUbt^9^jrxP zy(!b|u&?NSUKCrzD4P%Z$H%4(QCuuU34!uWHb=q0;`WG^z=e9Bua{ z=olb}oc+QW9iCqASin~~%U$jk^(P(DYMNgwCGI$);E5N8}EZQ4dp)%uK6M@GX;6^ZDoa{ozpjaN1l~m*K10% zM%M~w{rTa@B19}w=q(B6cN&e)%oInVPl1==yI9TF9z$2*fA0U zMPo4}E*wZi*r=;iQl`P3mvp&$n<&^Rh-dx2OIXrH*sA#KbTVa3c%DSWm?%;R(&uMHa;YQO2W9sSxA4LhD zP^(~T21ON2X8;o`=6Ri}0Riz3DD5we(Uz`nh&M(Y^X+3$-!%4j+2TI4-br%?6l5U+ z{z)^SUN!9tML#7&%(J+dA1?-(jP5Q5oU$$n$~%R}E?m1e2r-hB)D61`QFud*{5Yf} zipq%$ssoo-8(=>vkUS73au)&3$s9hkgd300fL>71QwpRm{~Yhxjeg?-X>u@ zt^$xhF9shYH6K!c0v)pZ0R*-MvGevgPHI$Z`#$R`ySj% z3o+;I3!@{gVM4g1Rw2dem0FksX}Ewwz8wYZk#pagB*2=aREo+B7`Q*HRYP3UnH5!3 z-(oI%%Xq`4&%%TSP)V4HTTJQH*fwy4JutYE+S4ed+S0O_#e~Q z+z^I;FcMaLZWOG45Muxak@%NU)nb3W8ms)hT?`yN98OTOX?1kg^08s2BLZ9`PN5rR z-mX5k#!Qd%X6gQ{pmk&}ehyZ40giMGb`Vec6E&PLh>IsZ=?@$ZJU^_h^uMh?ftU}= zf5Vs~0n4S9x-;82;kP6Sh1bwl@>>&%;n1#Rukh;PxZ=1i01zIS@;zNah=f0qF66gR zYFZk+FE9P(@*!+%rHUQs?df?q&L%CVu<@)Ckt$Yswok!tb&anNoHhp8YPT4Dc0+N3}?bR*l z9KZ9fjRu3Gu!N?F7OuwknEm@O1L|O$8?jfB*2>y#;3p3U`Isxyr`ExpiWPS4HAi1V z(R0l^@AY-($-Fdo8g!u@P>V)6^UP40a@e%X<`dR~Aie0zQN8GvdF-30`o!bN^ zdh=xP@N|3B?PHERPb)(GN#cm!#@YTkwjCl078Oq2De+$wBEgu9Xk0N=7FfRimcM-k zm-^YF1moa0X0zWq{VQ;o5NnsR{6+S9Yu_12Fi#m+z9 zMe=~%sKmS-1aTo0-u%4CpB>%ZtwifynKpQxiGz!y=H&d)Gs9 zeS7XZH%S@p)rmSagT2+o@4lk{eciIf_>NlS;dym`vU?MoaGGLHHO7GIefUE5%4rwP z4K((52GxdtAs=v6a2n{h{?K2yecIIWN@~!3d$Co;x_Gv4BQ&P8N#c*!10^oH0lQY( zD-OJuPxOiM_v1IB@)ymu`{sIAE5cSAP>~tZ3*1E{Jl>T2*3k|Suj&;RT6K1&`c@6>KSAnl$G>v_@c&MnWb#-dGo8UQH6%bob2Lo!CZ`}~cc|w6YI6de)=PFxO z2_4>7V`6|QMlz6?5H;qR7Dir3(o$REJt~S1!&WsrMdsUupbTA-%6EakM?mWks~@%Dum4W3gk*XM&cdp$U(Dm=ge|$6s$4P86_oYY z2;*?cx+jzGhG6R{YGcD9kcZpsca?*gBK?v>IkK(F%D#MDb5j0oTh*zYS-^Cx0|oYO zL#2U&1vW4Z#{F%MLX9d|z>OEK;E9G8PQs&|rB9SXM?V{+sf+)MNX^Dg0=IdL3gD5- z%2CBmNu4X?p`N-9gNXS_YrZE^QnrChy2WafW`LoP?;|w7N*MrdfdWFJ_fRo?nc`t^ z&HrUD!Kk43seK_5x^5x=hpoZGa?`@|ma#0s(k*{8sJr?0n*wb; zfk~!xAwmB%6ElikVK6aBQMo>YVrW}+j6E&Kq=DjnjATP0Y%7HZQ81&+hr#lI4fmes zyA&yqI!MVe`?DiNLB?blOoxbNBT}adGnr1*ZOpV4GaUw(zKgr*nAYs~b+@upoi{JE zl`w+|3Bx^o=0k>(u|E=1!Q5jO({l@1`r4U_8%@W+EYSad`5JIi34MkogQEy4mZCCy z6+^Wqs3~G-M7?ph`ycIuFrp4bvM^%7CP=1iYNdlHlrxL>tBdCo8c{L}_p66Cz+~t@ zVbCq7wF=sY3)@L`dEeOE7w#dLAA-}kIR8PA_P5x*h`!}a8(J~ge?saT^V5&bRR64^ z3mZM@Ao6cuP$A+M*=L2|=T~0|??02_J%5|P_6_GXmyFpmUQ^eR*mTBEqJw-3I>Q@4aIwQlB??l7hUs>(>09{2%- zjm0AX`}Uu@kPr%+6oo#_s$m+AKHZHCgq@xr1V_&ZBT@d}Dt!NDq+rw4gHUj=!&nU- z80Evqlb+26B2OoQ2g#%}3xROqxj4Ae;le=g0q6=ZR`+DxuOtmium3!Dj=$boX-sI3 z82PoTSI{8qZF@JTML+^hs$ZXZ->6axaP7@%cgM(u^htUZ8N*wIayF@OaXoI0H1AYp zSDnA$jg5f^aZXS6J*||o?ip~tomdGxwmkk~L$BI;c_@jgXnJ|L%O-C*9HrQ8+1K4$ z16nei7Rl{$0jKmUN#jXT|0VJVC1Ic`(^!8dpd+xN_w?l{Pyo)2#>w!-veU2*@9KwB zf_37`TFcBj-gBUFR^?w)D;CRh!*?61%GKUhRL_QB)Tx+wVd!}hHD`CO5TMO3rM#n zVeyI5`kUR!+w;hk?t>$u^sS65*d6!pvZpoYZ{8e;JC`W)*~7d8x08S}DG#-fqotpz zZ}2mp*@Dq~pfU2pVtPS>K(AS;8eZO7;OkFqO=xn&O4l6Qsc0o+Ng_6VQWd~ezl z%Z-7Gh2<-a9k1G~xvyByI+gc~|GgdE!_kgN*xT>e5IP?`A~<_b@41vT`~r+c3EVsN zE;}rQqg%dF6ra0Tw$%EFdL))ktYNdmA+~5BuU&iOk}jAX*q*iU4a-GA&5?DjH~w*6 z@=r6pD(^sJopuj7^=UYYZK;t&1TixHfR&$6%Fz*K3+gU=mk=`x#;n1&;r+UFvo@Sua)2rqvp3~k`Lrqb(bm7}pE18P#6F5Tfe6A!L&uhTW zb)qBt18F3O`g?hgoF5hDT^T6p&w*2*r5{9WIS&sI9yW3RE(4zAmW%#1V`Ad=j}9yf zu5EQqdyDRN{=cDI09T>xrR%;2(^z~JFGf{Bf#x*}cUaSKy*EepSuaraTreTv>xF_v zU&k1(8R7Ox07Z4gACbCC8UmEhxo~zR|6%EyiI!5w42QE zs9?C7^7WVVE6w5bn3bVVG1A}t+i#s@!XrAR2Wr%Zrt9T~52^u6E3yHKxs~TdGkH^& zB>q`hGJm-uy8(sI*581$_Jw7FpPl=yKLYgmzA}0*A61X;;5@%Y@=j z-RbATkxfOQYA(Fh=Lwr2?cmQOSDwpq+aORr#+G*&t+4g+Jkz$F4J7$F!=&*eHs`29 z?X!VC*UNrRZ#j3Zuxd~^>!?D-Kv*s3Q`){g{JOnL}z)d^wt!&jIfF~BZI9#%a za47q;;lNV|A1^Sgf=FQ2!}{ueu~X@mk+{J-7k#(z7^BzU`}uZ_Z6i6WNo!_5rWE^` zOhB|osz{W$!JRt7tlgpU+4rE3{)2St-LolQmwK-{3wfoXaYFy=_hE9+0oM;^I%r&v zLfI29fj7_NbG>x{oeMsS^Z+y6boi~A`_1vWRqL$2X#8joyC1=OCr$nAnAbXM^4b^I z^cNbDpYqiae`lfe?wHRvi1%1LLoaF=;Sl9?gphR7uolPt;DJUr%uXtdUqMH53a%>B8d4 z1$61c6pvt-U<8LHT1taf2r@1Uq4QC`+T_#DCo)auxP(5h` zmI~yRA=kq~SylfW3-U^lkO@Z3q+oCf_>9hQBDO7zBBXwShxmm7Ji@$Z7?%H!)`(|t zk^RPiu2;IL3XOuIs`ke1!k)zY&hFhvD-E_9iCaXnxcphQSw8=+u71Jdc^H2I|E|zI zjLAU7p^lbhRgZ_!8z0Nl1IHrx^ZCE0`HQ)JCY8qELe;osKyRRbpPsJ=!U0B@3TsHB zpSC~4I^CaeF7XBf-$j@EOAPB8`DXQ-3}Tp27B$~`2OnCzLOC8v@kOR)Jlqr~rhmdfHoZgIGxB{&$6 zq9vm3u*aA)3DT71BK)P4@`u&KO0biQNK|)KBw*Zy+!unDs&EYoj8Xbxxq2NbMzshS zwLyvM7nRMz!JL~&>NBehn)vt*#&U3;RUic;H`aSd#D6c(MaU7u?pJpc(2#PZ!PMYw zhv0bMmr}zhClaRI{P!$av)UkzFA`=jwk&K}fr2h6Dg-pS3v2d&CrS>YN@@uk(fXVo z+YHAHx17!z3&I1k>CH3+#SQ2Z6tcm@(d8Z?^(C>shKyrjzV39)J9oVlE-GZH%9!Xl zrZevMLpU%vVWFlEmO|rT%B4_$N&asydYhqe8r)Hy4`WIwwucKZ!BoKnykC-pU<%0$ zFs|aW#YnlK!gdR;-TPo~+1L^E7#QnOgRmVAI+_8b{(Qk=DxeTa4hDbu3FAt(xxhy= zQs4+!Z7BNHB?7V-f`{`j!B}A=|HNMqQdJT$8S+JxQZT_SrZN(Ap%0vDg_JPjLav#n zoDG{+5Cuj)NtK5E6Vr#n#Av%F7*ZU`Pp|g~SG%G=4WACfEcAP8>;QhXmtM)Yf42dq zp5FEc@{HV5rSu9}P*?gs8we|1SPq1qUK0dIlx`^p@`C5(5lC+U!7~B|`U(2&Zv*p; zw`7TRxv=EdKpw%FOXG#7rSe=F%*o>-{N^fV-`gGAY4B-8cx$J_j6| zuwQ?EPKW1x-m}uLdTjuR5?Y~zBx0}(;ww2z`o06k_CsjeBO06r0+W~%$p3P~=htBjn ztADqDti%9Dx&<7<`hvgBLG%lq_k(r4nd`b_Zxr)!{PGl2?!}B7 zO?b)f8CsSUV6~l(aKAdg+<{}Uhxe(LJVbnrAD|D@vPq=}4;<)J=@{N)rrg;)9kLs- zL$ANH>x@NwjErN0w7AaGMjdO2RQSmGRCo)YhOJBtjU!SPZ=6NB^(HZ$$&h$jjB=Ak zz8rnC6wsI%EOi4qpsY$+hz7m>=zMj~$|r^PKB5#2L54bOdc(JpTuC}h5=KIGeC;YF zOSi(j%y0d3x@SYVsx~y$)HDKC3x{Fkk`&gZjJD_ zbQP^FkgmDPf4|A#R^LTh1UU-sU%c5wKm7GGdzfryZtK1CSd!&?KQ2T(< z8@wJkn|K7^VN5GoGN^kv?Y;R65X$*TFxFW7N;~m_Ireh94-s?^4ErNha{~UQs%1}0 zk{lCo*!-qj-{Htno3NcmrrQqp?nW>(8gJpo^roV{_3!L-wQ!|&qHM*waX{_l59lLY z>5C0t{qvHxnBr85>#+N#fGc82+6uz2(osrc4H*_7-N9O~-FqX>xW_hkG;R>z!EUd> z;QmD~%}OAfrHK)!tcl6ojr1D5@#XZls1?kmA%xFZ^zXN7F^FAxisL*V%@JL%p}+CG zR$kwK?8W$Xqpx*C>b?2F!Meu#KkC(iH`!V{J!?BwE=-m0Y}DX=B2T=LmLlo?_Oj19 zVZ{dk4>In!*>LE$?Eg`iQKrY(?_?pSwP2-)P%@@7raimlhE z{7!fdI~R2R!$VC!5M-D??-OsezjAb1dVYEA`DhX#WH|aQ|1UdrV@gNWq1i0cI>ZbN z#>msu#p>!=NZ1A=6vFh9RVM^~f_HNIxAhiY z?fI;_yIqC5ox05#qmGte$LPrYSKIM(;P{i~82cx)U98;cJXC|^^S-CIWMqVtgd$1C z`*q4MHueZqS}Z2_)0_F!a^HVA40Z*+Y-!)DTPL!XsTnWV9xscrrTsFh@i;gkbnu3dDl&57m${)pGe(r2BOv#q zS)lZ>@YbRw*5k70IQ`;At~|qZ+kASjkf6<$@Px~NiWbk@@#wQCc3R4I=C3h+Lg zAw)tbqQN0^prmS&WY~RcK%!m-RVqqM8x1l>IIH{NLLOCOSn?xeQ>8KEGXzrs>qVCK z0?N@xX~)sF32)0G`&q=6!RU8E=H)5VVF5tkT=OQ-!S)}1P}r$ zjPDRG21J+QaLQ;*In?JA3R~OoaFmw5$v4HRDwvXR)-As#(Zt{9B~Fsi6@>>*$llFX z(}q;%w`98>C;h1snP>JCF~;B;?=@!LFg*%R~HzqUM_GLOQp1e;;k zJqbd9@}@jhIbW<#W^@8RG_3{!nbKCA!F#I!k#ftf2*`q9B|-!#iCo0(L2-B?Fi1sH zhxqc-WNsQf1!tRUS8&i@v4?H;Ukghi0cAxA_GN{7i_)q^@a!}g+;5vplP`q{gHe?K z;BJ3q3AXxw(}MD1j3E#OR@yfZWbooHcCB`dK**G!LSMvxEz@8u+f|nQeGu@o!`u1=P*O{NYL!V0W-gICQW5Od$?<=BsFL&W_OM$pNEfh7 z6H~&XBX~zy_kSFjo-?rkR^VOTuOb8~++?jT&AcOm`P26WgmV1sai>5F+Ek^+&5E% z3xoz9%_yXGAk~Z9exKipcMd`jr7WL1Xa55`)b1XxQom{HImfgr_2)lF{$GiJ^vk7j zH=Zx4mz_)XWm>9;%<2;BRf zC-nFFYz8Qa?T-An5wBA<{N#5Uz+>Pd|4C=(>iVMpxW7LSIcudne&Sm@X8+~u)XC;3 zd8PXV9|0D7#KfmShxz`4zpu@JyXVCQd`l7I!W2MHfS8rx(+4zMwz${f^Z`n$34PRICl9n}Hv zw>b|3yB;RX($$1k!!I;a3#10~`aU$(aRFd%2FE+;dS;zi=`caMgth~~Uwm!L%)svV z>FKaPw_#qwjjJTs!TjjijJXd>mNyQ|} z`|t5$bgMfp+1sf2H!Y8UiP0F+{GB!L?-ax0WY8Ld?jal79!QS#ysj-5A;XloLo7T-DF19$tb_{@Jt$+OKx9%xX8;s z-Nv#>+O(*i;o_F5t8sL2c2`9Bs74fq_9zB6BOG`lyWJk191IKtWwKHfC6xTDj?12Y zJmXcBKh;rLXgzOKXPvu|6nla`W^eh-BdB?C5(lcB4)4=`sYIdB!KvJ>Y)q7qe=nL= zQrpg;^0vwCYav18T0|7V=x@c==r-KRiBZhl2gRn1C#44)RZ@@2U&}$qjZF712OBjhkB%_*jKt7K z{;G&7H)~yD<$dT&cZV2iSn0KXM+QekpsLxp25Ib)qkjtj)z`kE;+XFEJmG4S9ZI^l z&V2X&9v&cB2U7CG3BO+iui9S0VpB%Y$@9Pu#3Vh)M!^Z=K>6He=0`u_TcyuSaiVg2 zCP7bM+`ewiz}-C}*bd9Q>8#22;q6?#KZ297!T9;yT6!hBrE!d_vD#ozYdx5N)Yf2l z7=ph^(}~E6-!vY6G}NxyO_|O+5yZCaN?VW9Y~j_XQx^F{h2s{7Iv+jz-2#8bkai^7 zmsANvHv9$K0D$kV5RnLbkt#~Jfao-H%Jkyr7t2!m}zaAq`eW<5 zZob_Z@&gP$*i9Tm2YFL2i_tg1J@_@qlPD{PFYjtL;&Yop*mp$6#>z73ojZ$KYuK^a zMDUAFHv7^W!~86xuSL+`KT5*dB5d@i2R!uP=iStNFnNi#IV10@T%*rX&kD5{;s&*g zgtoif$iP-U&OfGj8H{D0BjC3WuS@YI{}`5HaslNmF(dft1G`}FJj*NPRQpCg-846M zHJw?ZxGk$r^%h9?T5;Mu$>uK0f9a9gHBK>nz0L}4gBKj`0x=DH`d#}|tc{0!OXfoF zk*r504?IH$R8q!MmzIrxhqJ$LS%A)22Go`>dz3xtE-fExgIO#CED=NpTR&chz^6S+2H*@^n>kcbqUuPD%0*k*DL9d=1rP zB3s_YgeE!LIZjC&!A|gWK*NU_j3gScRM(ONAIW&LE~QZ|uDzb+PF5GBRfjvq_9}+wXW^9huji_GV#J)z0j)n|ErpI~%>7KoWKwad%vNy?cCc z@%7Iz>-5|s5HCeI!@calv%k&*`qblwdy%XmEw#TLbWSkGJw?|tj! z{TG6g!&k7Z7>r#+#OSgvQs}PLrgj>?*lm2}w6YZ;xNeR-K5B7L)7AC)6 z9>pN#r01X_tgX0Srs&FWYLJ8T2nZt|DMw4j64k(3h-R{sg9Z7)p=^vU@M*4Qf|R!4O%!3fT*;3`MWPd)hJ@wH#hRj%`CMDxvR=#)CmG+c3r>g=Ir z7*1qtNPe-56SujX>raZdWV2q%K3I_E{YZ@Hgvjf#7;}Rz(mhY%Xn+)CX$-s){xCQp zg$8nJDaIPiHcs_jdUys{|1=z=t=N$Frb|-=D-Usq@vC_zm99-$e< zAknOM4zm~w#pYdcvdW=HUD61Be#?DV66RNU`cxG;WFQ1;)*C0F#{z$bL-2kuuq?Rv z5`2Kh4|7QpGiE$j12J5E*9#p@0e1C`qG3TlUM&tM(jbf?Raq==!X73iW>-H%xPDVy zJl{^A2zkFAlAw-r$x0ppyHK1TngOB8*A=8>s5cr3MtW<+oQsJjMK2A-(d7gv6mn_$ z4#Z+gunUn>1m%M`f^-#FWiHf_!EzF_eDTC;sV?ja}4WeHXZrz8M`Y zaTKATOBzJ7emPQFxxAA^C{@xtMQRm=BZV%93y3yVnZmI@5ht=4K3Rc2@pe-+T2fFf z5eC)rV_|tmqJ|wF%*B8sn>U0Ony_?-Vj#6qI_1D1%GC?sqhCS!Q*7BU}!VtisAGrlG0K{vtyPhGbZh6!!&*piB+7i z>mj`Vlmh#Cb~yBbJE=OHB2|^*SUl>jP!OzQ#pD;1P#r2-4KKaReq0@j%fvYhr{vzA+&h~plXb?|6{b%4K+Y-k^V8+ zeC*Hy2wnPTbr3pqOoAef8pI9zVV@cg4v3#UEeymAxWn#|bsy_o$dO%#$nX*Mk+qJf zTcpoNK~pmn9G3*xv1%;!aB!2E>RzACM6UO=8ntSD@v%bT$cV@>`o`=(W*8`a+a2$p zdfMzuRw?e%#0zF!pM+oJlGUd+7|0#C^zpWfK# z21-9^xgsrcvya_ycZBrk7&UV{H+N;fofR{NaejzC{}qzfX_%(CG?pB*o@V-c6xjyE ztG*CzIh4NL|N8js`Cb_i60mRASL%7YdA;Tz`2W!L-GN+w?f)M)%8IhH$;=*aBP6Tr zm7Sd}gp7!HWMmV$Ga_W~Eh8%;NwW9eGc)^l-um=B&*yo*zklAH`?}7!&N;X4GhWy0 za=xv(fUVMLaJ(QEhV7K!zWS}N%WY{EY2p4erS)jv^RSBRvwKlSdoO+mj{L}%l^vSX z(_dLB=Lk_HvtFIWMSBhv)ycZm)$z~Nk#xqcH>IBO*}f7nQ{**vj~&WCHr3y}XW=-| zI_}V*NANTBb4fjA(5c(k(#c1GZ&q9PSLhvnonMurVnalwjUOGfzbuRIv$1kQ<;HLgpE*3{i)l)O=Q{ekZX_g@n7XMj*c5wR(@7WuQ|NoHCpn2K9ZTr zQW5jrQxLy`lKIt-*-5)~i8g7hI)k1*ai!&b(%H$H(pJ9O+VA~9EPamuTgQ2Pvt@>|ggDZX zcIY_VrJZ|I<&0(LyI;Yo^y@-Q+68p`I=2e6?MELb9U}CtDz+sEUW-oTJ8sgzenO*N ziBb#l&TqZ1|$9VHP1^B^aE0yb` zu_!B+)1(Y6mg{qCCe&rj#km3yXXsaMHL-_E^{d|uJ*lwY#|@RLSU<-NK0#7I9KgoL zveL#IAv&bh^wlMeqtcmW#nf?xxMD3a#f`WjB?%egs+S)+$ziDTidx1Rck|;$33W;P=lfu(fiwKo9U(eJ!5G1~$#8^~Hs@o>_kfs4OM9fY#Kd_W0J+ zH|qQV)a1AKLltr7Z7V&JgwYCoi=ERDp=r#dK?0Itt@N(hCE99Ta$jbmNX;!ujM;DI zY30v{aBM&DFWvPQREzR&_2D;0zhc; zfdEVfT;-kpTAyD9m_R=OYv;IIj5Ltuu$8uOVx=Vu(X^ z%Z|-!6Q?*e$xjgRc3eW{Q;gHmSFZpM_w=rqMElJ^{b4E|qV9nmmsP7;8;Yz^&%M*J z_~D|4ll_G%&$`iw&YzJVCJ>K|{xUQ$aQ^6F_o;8Ts?*0s$Ej$uEogT9enI%?pn28J z<(wrhHGB-$d2}#la~`LU%pP9}=r2Dpc(A6hYWrB+ zxGN`XvhH{B8oN-Zan61LXMzteux0(6g*hB+~`YE7SD}x?J+o?(;2b$8dNR#TqK?= zB5PAg9&v=6fcx7gHNsuyhWfufavOBlx^cQtlrhii_CzqoB}dfV=-9!I_197o(q}Np zrNcJOc5d(Cd}-;|ZwXHKU7a`+qkD6-dLQ*9h<%XHP3m>lw;xq*u{0pS^*nnNeqS*9 z=g-wA3lA;nRB$tJ^*m?arOYo>csD!aJkt zz$|(Z(W{={qTGYL^k@M!#bU@-# zNlpCQ^|ty4%hN5MuHugb_om$51ZKWXeY;}kM8#h5QS`^8;89S0z<6o@@w{!fXu<7> z(OP}>ug6mFMZ@s~^=9VmSaK&6#YVkCl1jDjl^&nDfdef|n9w`Zb0OF8I$29Ob?B3p zG($G>6ubI>7c+}1mFL6wy_p{Zh=U&fpr3hI^5w)}c5`jK(#Vqv?woyic6m12#@@ti z(4ePgcSq|jU6{Q_vB;LaYU`vvtMv{w=)@L+qY z6g$7J1qqk@t;_>qcNXH@Xz08Z^`Dq`yJR4_z_EM&w3*e|S0>ukVry_D-7U&x6_v^*=$ za<1Vl!=5TzOSBa|&U!voPMtMX+g8}7LtXnejYPLNj71xM^ z@|iwg!`zS~Z>4`w%EG$;AazcSs?;}3wq)|IGpQ^?A{GMMB9V=pI4CLATQpl_(dui9O4l<;dbIIneVkC<w}HDf zG0?~30f1Li)DG+ZWko;W+WeRpqxGy2BQf!^YM}ZYlE9Y=_@pyn1E2JF+4!xgQEb4E znyT|IGjUMbjUWY<$L54Dws%T9DKXdCEWvS%8Xj=~aX<4LeLfUI3-9nH#hsW8EJYT^ zdm``JQ~WuAP>k1B2RG{uO`NJ+v=kUn_92NaO_1;Hu50F3GO zGxcfvZ700>|KYlbM<^H~NJv`gSzRtws452K5nMEsIuTYe)tCRv}ZoX6>HvOqY1L~+#yHlUQI&oi$iTKk!KAt8b;2JLZ zj9IcCnZVklc4wZ5QCA^bhlq*iI*|KCNrTKyF(`x=gbBRS2^mrazsj|nt2r_&2%si4 zI1XdaGEL?l8UTK^$D+g>DQ8mPufVw&Q$36kc{|0#==5x)EK)_Ta&J6$zbSb8DRpr7 z$NN89=7*7JY?B27f3I%v{}U=N%mefO0P7p!|23{(F6cbNlwc)GD*>8Opr9-;E2S)jr)mT z=rJT%wiP>@YmO+<&@(T!&a=t0+f~Rz6rLPEPm9%!_u$vEx>0#&dy4SWJwh=uj^3;s zCBP|YkmS8%ADfeYFMN4smN7$FkIL+};aXOT(B@)i@AQV7mr=w0yM8SET#CpW6&T!Jg={_6^sy9kH^<=&g z!PntZk4f)ZQzvqK2=lFf4%y6v*6oi@%7?q&i??lidLs9W%C=YN%m^jji#pYbcMFYK z?>!-=z3jmsv1IA)CCZ&DFuX=HFz@42O(i>%*b;=iHc_+DGVVrv;{L#!zeqM{lxbW2 z!MVPDIyT+7@!+r7)2xEnE~mq?QEtxC+-C^Of-8smvpdsIDlR$Ict$J;p98|dkN&k1 z&rYiQOXDMV*5`XkEp|-L6fFES8XnOa+iuz^XXTCCcoiNQ#Mq9X)Dn-28x&;J9v`o^ z%sZ?jNfevb#WraNuBf`(^#naN+_?7)?!-n`>~C)@oO#|BcPx9LGr>JBeZ25w$gqgr z$o91MR|B3Adrb$$$!rTPwS#@u&)LLdSCL%mMW2Q<7w>9sqtoK@5$lOg_Ixe*7#$YN zTSXBg+B6eqv$K2m@Bdn&OoW2_(L zAGSQZHBm3}ZB+8}A|e|Z!R&cLllSOp(A?Fqj6RsG`@ z`xcVe+$HW;wGo0;+9t}pCk0=bRQmdsNl!{J9;vi+g=pxRAPs9$s~S;u37zdMsTIe| z1cq=xpZCNZiPfc_o{0EDXGl(oftP6EBZe4 zg0iX2D}Ziq#XF2qZfliX;(=gXHJygu3<;9+mg1ONv+m48YjTeD=O4;G5luG}I$F2c z#__)5YBRIOJIP~KtONV)DAu&nB{JzejzC5=K(fb}3rO}Z0WWBUdw>qG;vI?hoL1na z(A3+5r}-^ z6se16b0^&Oa=$-&D80R$MNbj++y0w^`?(yy3Z(RWnwMA~oAx*cnjd1@Mi}YtK9IsG zs1gXfCZJf?qU+=5DJejD%4N+VEos=qm(m9|uq@f49D2K6bSPySpxZNkh8(~S_gmpO zk_Mb>lIaX#vPf3z?uBXAFMbk8NJ|e-w%NL<$}C%(RJx}Ju*hY;!wOB!&*l)7yl)!N z-`(4|!oJ-8O^WrQb@5e-+#l9mKT-umQ%O8Z9o{KNft1#+Nz)`AAk0gU*3;u0fmC*g z^!@fjvJp=b-hRjR2VPsav6d{mOhHkyNFBy5m8HOMz<-Mdkn(*eLVf|si92O;p7%-# zvGX}P3YrOvP`*y=A%N|#Erv7<(Ac$JQ`VdDZ3C`aKhyvzBK2z^(=ciB1KaGP=J#nL z%42H4?BH~YP#h$!>Dfz3wwo;;e(%3J6q46dlsMBv!xKffU4ag4>0;c1VcJGSU zF!F-+k=FJT$qUHnPogM_JyJ$cn&ipADvDyS3q`TlB6B|o@a6U1`Qgx=(21uM=Mhv4 zDE4svMX{$H%^_+krunW6NU55)iM~P#qAA#bmCy1@2jJCPUCQTR+9@FeZd!FxdK<+b zn)Pxp76MI_0mGgEVAw+@vz9kf0t0zAc?SAqLj6n*u}S^f5)!Oa0ZU?2vzp$0B2KEd zZ6Xe+2?(Q2n7$5en_>=pmFe^Y42&F@Z3*$#de=Z!jUHWoB2Manc^2JEH|_7lVjrKM z`ZsW$|04a8LYr93wK|sj^Sf}u((((U0VD5}nf2D;%@?as+YUVB069TI!my$v;5|fe z@$ewvI!8z%MhyoK-kV1gfO9>eD{xl_bQyz>2YgO0T&W^wtFP4qSO+IxRAE&9jE;k- zXiUc-ot!GV*U{?-N>7jgN+3f$CnE>M_&mnTwNV=)B6Ixq08a zj(6vv_Bc`Egze22;7VohdY)0rtaTeFKyADzcXPFS-FfL~eP*ClbF})`&$A-^JwdFe zoFXJ2R)vt0^~Z&=9+T98-Uq$S@khe_z1t%)+4&i3^@#~|4`n2kEGj<8HT_ZmJK~WS z;gC<6QKWUr?cL9(rJU`ZKK*fJU2abW-DiC-()hS?*6FV*r-mIaAMR=Ctqh|)Q?ja?jJd1IcMF?hc#Mif_sC` zD>kOe)&_zFsKtL>g(E_WZR?^1{$v z=Yh^47uneSmz8%`B(w_9;Ozh>zz7zJWLp$=cqL(>FREI zaxNU9jCAg1W;#BKjWZihCARsZN?kSnQJgCCX@76SliKZjWyZJNEb2OgX~UdWD`Qs< z2)ZhdEle|RYpq$HSZ=T98D)ipQ<$4A|4gNR^5jL|DZE|pNkg7fyU){{D}-scO3=0a zvu0~+h-O4+McIlr@$em`PgRsbcf(PSXmaKJXG7#@{%sQEb)RG}{?P+Ut`)-j+pSSr zUb@M5KaAdvy-rQjtu%_i?)Jv8I`OSZ|IN?=ew{PE6fr8H#DzKM70JELZrz~k>&@E6 zkKP9V{M>O*Vr=r{cp*21ULCJQ-@)PId5oT1Das$DNb?~jLzb^eBW z1pzM4kR>05H(#!=J)K;0TXh(&`*8d1N}HT~{eJGo@nY)e+rNx>rJi^bpZ~xrBHEIm z;7zTTxkVL_u~}p9BDtXxrow&foqP7RQn$`xG{2J|V?$-w>+GT7LJ&(9wJLs=Z9w?A zrIlp|!z*4>6OuVE*1Q2?T zodzN?a5!FfMdUC3n50d5IC4OF8fPOvs2iVYRt3%jO1>@}`-o7G=(c<#PR1v5N{gq? zm!Ls%eQ*yk$@6(S#wwY(NK!M(HTb!oEyPZ+0`HqXzdXrDx=fP_ z;u~OfOMTVL^IIiKO9t<$<5-Tl9>mx0?XWoq{rd4~=hlw?6IIyZ&C2Yw`R;dklU_RTq*_c?LC>%nlRKZwR-Ijt_qocbW@DD$ zLBZY3*_|byv4hX!7zR|IHP3TZ?jdW9ZW)lbsAi{mhMo4~yh+iyqquK&DD3(RaiaM6 zo{9}7WJO2`e2r);@G&=B1&MIPRxDxlDS0~!Vh`qT5EMy)t4mv4Zf4;)Sa0tefO`FR+WyeZl!wHd*&$Pq5 z>Ot4ZN|+(H2KJ%Bb<%)7C4>~vrI3Rkr&R|v#xF{bz>jA@Fz}Y)3y~60`@*_yH9pHi z9I)-tjR(Ar0vVZ!tC{NYrF}(_|JsVO^tF;E{-@iKt?sV#2v&&nz^mDpkUL}8Oq2x< zeyb0AEEQnjiYj5-Yfdqss@`#ztHO4i#K&*1vVh$wOA65V zn#nk|%YM1mN)KbZ_C^k0y-XZ5^ojtu9Hk?dOk0{`!3KM+11Ch9>Ln(LqzE983ldg0 zCq5Rre>XhDnlp%@LD(!d`CWw6MA{Iy)U^zj;$LhJ|H7c@pmwKT__Fu#nf~6h^3Id}bI&?dY;N`@3AJa%L3tu| zV0WnFvu?A{3e8ZnI-0i@g;d>hU zi1`s~+8lmW<|n*(^j%6wa*Tl4(qm;_<9K>UThnc*2zqnc&$(@Ro)6Qmy&1-hFj$EUd~? z^f7F8C7kG${nJVXq3~NWy|^rl#`W)KT28x=Xcc~Ui2vTR{^yoe#Csj!#_Z9?;LMn;Kdf5SmeU_{2%V@;EI3*jhX3BfB$2P zE`sXsKP-YxH6T_Zk^lC37ZHTB9U*2&1USvVfz;7>;3jJ{VhF(x-&sK8Kst^Iqi!Fp z9c}3f>GfI%d7Wrt)-Z;{uV93l<119Hk^bO(dVEdw?39#ty`0F)j6)5MlZ&S9F!OFr z3$g7tK;%AkO8OJF2K28U~>mLxZRSTO5(_Ne>#(BVznaL&)ve$)NM zR?0%p6)X<;t8DT&tGgA($Tpiyd#|z;GM!bQG5h=KciqDWt`;D!Q^!uP0P>oU+c(ZN4}VM zYDQk9@uOVzGiFt*i`#u9%{i}hzYpbNCkxYQ9c5=%&@Ns0TPv?Q_SSuQUyspKt&pVd z+USy(v}3)Fm_MsW$w@FmGDf>YnXkwvd@C=~?XA=z2-{gtv=ND8vFe?luc5T_5gNc5 zOk8$35HV$JRTME`MVlk`frTZW8kW|$%187Tnt#>thBG@S%$`^v@n3D*A9-cXc!*6r zkIW2X=@y9Djw!Y6-&8OghgT&n6m7F*jp5F68n@bft)wB9RUe9DBu`l2=k{1JUBlz3 zzdFiK_iIuJ#%~gY^or5ww8v@$D=pue1oZI>;wk$&c@7TSTP*XnWOh$#H0x$+4E!t>RJq4K6qDdWwbdrdK2Hm2`py5_fwGsxoxr zH19reo2@&~z?}cMb0h4`EWRGNE;*%+w4Iu&DgC6zPeY| zIA^6E5$Fyx|8zwt8;5LNKj7={i1`$pE1987BUM?-5gpyt`_YZbb;Gwqm?AP5OZUoh z4P~35gr$73uEFa}MYX5TCs>-kJ@JZKue6L4`HC4c@QgiYG{b)c=huf6)m6_1+Olh- z+95h8tsieMIEgo_Ah+jyv2~9m7Uk3qHr5BTzzBkoqc!HYReq-HI< z$Yeinw6$J`yW823;Rn$^6VgoumH3eK=EZKsHoYpnlY(9R^zT^o{(K>_73!Bs_4?1~ z>h2fZNnN!2%i?sl)yl_O=N>LvUhS@#di7C$r39CD6%K8`G{YRuXxjcW9S#|>Uzc)+ z`V(GL$7`O*`HX5H^G6bfK1%Q_^gfiytiQa;E>fs7zQMs&k|Z? zQ}-NS>5v<`#NZajyC>Yw)k7?@oPS*3^8WRCDzLUFqw$)ioEJcY(w5<}VSKxk3|rGb zCQwKv_L$OF#}O+{SCpDE@_oHhJvjB^H6&Cg8Z#5c^4%!pbd7DtO&e#-*HvRp)gdfq z=4$#~_SUm^cOJ0eV@?FWf_=`=7?7_zxnGZLDl>hO~z2=+*a-Ku_7&%i!`p^xK*Uq<&__zR_1teGLh1vE; z-$-xsO{w^nXso$Y$lXkS{_Xh|rSYBA`dMsRlzSMxEdAYnNhOYJY8**diFLUvo?m*~ zO@iY~`BEk1#P?2U0FfVN?5%#kCSQ_J77PNjqL)(7SxHr1;*<|5j%A~@He>fZe+_V= z*P1|921yiTw8xhemqmtv)%De15C1BOf}=ek5+n{waTX?{YwYt_Ofof`G0CV~3Q@O} zG?U*q-XPCO$9PZj8!t-oFT5zpzwx3t|Hg}gV#EyOK{Y26=Lg0ED{oU_14$IYB zTV|d7o-aYUW-R>`RbdE`8XL`kk@L=e758uw`Y#9+A0Dwsl(uPN-y z`Wyy0SYmpGw;Bwc74IVmqY%$EdQ3~Pv_U0$5DRdh(!-U!`R>lZ3&K^8zmQ-$=_q~Q z-&SVKYLss!YPZ4CNMU{@tp+M}#<&Yy`khI^gx>k)i^7>EUCu%0pJQM}p-0(yK$dL^ zxs^_t?Mq3TV!mQhQ2=cE>`3Ak8~)SFcOOa5iGM$*RaHAU6PbF8OnR5yS*5imQ2KJ4 zRz=r)QT3*gLDC5U{%0|r;eW3!;phkeE9KB9Aras~t$_bQk|e+bM?0Z0{~s4W0zCh< z5EkI!y}0<9^MtOVg9lhW17d-fUx20V$s6b{#3KlsPD8{Hui)=PJeSeCDBS53z@55f zHdrn!MGo1qIN5UAA5L}ovTFz`5-z{a-aDGyeEx1m?o95c)~1XJR-Mi6t{vW%XH=lO zG(|G4_-*l{(K0z{Y24uH-DmAN_)H?DhmUKhCcdd?Th;El@k_*MSbZ?_p<*bzXXPSa z7TV>O?7jcfx#F2SvSMV-Vd1l0+VI-m{z})ZP_Ib0PVKnoj>Cw^FlXVhcEY-L=V4J6 zcchQ7_))j|M%#OO+FPnGIa-GMdq$0Wi`S5KRD|XI)3ayAd6ExyCp)L-mT2!SKW18< zAZd-_PpDnvmdBA~N*W9JxG8*6?*_&3r`fQCx3Z zSr)g7PyX_E&-w&Gw@m^{+QO>N(Xt+b*@^vUN8TU2kz127>xYN^W-pG#v!<&>1)m;% zwCVQoe6sCM>HFo8_mY`Y(d6;?M?GUBn!4Lpdd0GaSB@rU+s8L*qU+Zwi@;~+`HUSpt7KUayK3-rn`^f}{2a z_P0ex9X6Ci!_*hs&z8KOg$Ip2auf=xoS*)F{;k#OM&D31a$-$;aM5L*=GFsc<)$K=fKY!YXkSKZ`Ow7i z`?5^=zDQGF-{;*0Gh6S{Ax^HU&CIv+`)h7W3cZrFpQjDSl#t4)CHg8}URKBi{Nuyk z*7?4p&OK+>Q=|y%$K}f8QUmJD%S0*9ctga!Zp&eXikcba3w5?2Yu9&=kNXZE_#N6u zxt5j-DL?usHfrP@pd3>%{x)a6{$bF=RiD1T%xI7L5kp5>_b1oIUF4K?XdNV2Ru%_G zM+v;XE-Umt<{h&?^^mYr40EEDCP->0*l}C^aKzJe*V7?iu zIt>rQ*vOt8e}!%o^{TYdP9m?Q@j(h3Id&bRaOc)5_1v;X%z{#3O}r1qL&jA4x>PsO z2vDSh*rY+XY+Xo??WEjDgKPsSLS?k305nvK_+fN5MM9~ZCc2&;V=m@Rz&(gV23QAI zi4;k}<-_N84nl;a3iw&yL6HyoURrCO`PP)Qvho(c{#w5;uiseyLZH-LGRxI zp2GLOD14~oi&pxsEszbf)y6?x0N_OLeR$PMeOrios3R{Jp(8c0|CD9iX?gHY3jSKu9j#(Hi-2SQ1fEm z^{OYK*3zX43H}YqybE{KQ%v>v;Zw@8N1>+xV6$2NJ#ol$hXeq(5VJe7~gVH zT!R8As=>ThcOKC7&iQM<%U6KxNd)8z5yaZ`z8NLe2=HD6Yk|N}^nk3lyWAvS15%90 z{sIwbYP0!fglL9gPS62aCpIYu;XGcPwyB=l+e;2eIe_#ml@0?_grXY!Ko{GZYM>6- z0ObMCZxEw27?c_wXbs*%OofKw3AI-4-H=&}>37hw5; zVm+s@5O`BQ{UFN6@ZZ0qiL+L;iamKU@oh0uS+}!yB=@$>8rKN&ar6Ad0UPQ|AaV3w zFYn)9PgDwZv?9QRh@sb~1K&`=|NVx>IJq)23-F+hTQvRyJ0ZaHU#L)2B>*l;ECA>P z|8Zgi6!35h8Z-E=3ZRZ=G~iz;5FSkBhlYjD&;K_eu;b`0LT^AYIQr#|D7{Ea(MD&b z>}X=`cx7TWYsiN8V|yk<;X@01s~0E7)FI9*7#-uGnBQU;L&WBuCDCW3nkR&|32a7u z^>~I5zvV-zH0y5`QW>8tH1NLdUh36^<+Q_rWY?YXQe)NR+Bf=%EDg%Y{!A1$G(r0H zLFZFs)dbfd*?i_qK%4%TiCRA^Rx5iG3eh{E9(*cZHGP3ur}MCmG4ZWow-226dXpV% z3gaFf?~HeSI&!OAHd0D1`?T*iqcmzfn6NWkqdoQ{bl$BhUTm=_O2%w66y)6PFv>Q6Bo<*Zy#FF|wklYW#3-Wms1?6}j39$1HQxN~o^3b`lt;@Z`Qmm&MBCAnbUc zV{ynAJ@!#d-22e<$dyp(cu>l|Xm;pyDJUXsq(ZmB_K~4tE{DG3)29{s_^)hpJmGA2 ztstXK2fO8|Q_qvniM@jj)!rSPxGVcu3{>(={;vegaJ=F;7k5w~i0u!{PUrE46=3 z*gRv6*mIH7uOWEWa#BNW^~-BKtjh|S=n#2do7mNDV#CzdT1zLX`?$-jGT9y3*01z^ zJ`A~J=brr0V6$fLEp=~qt6y@_#(*G!UMZCwp5VF=vVEbY*fQpBs6a$!wNPk%;#B@o ze@&jnB2$v<+qU3o=e5$L+dQgl`Vkd(3rech?K0G6kK8_xn;w^R&TnwHhJSWLzQ8A~ z@U4x}pIvG#J104NWMU?yF>Bl3wV!%NBoDWM>|m)j1ZvEbBWA*njJQD7HrhKD#%l;(l(;bKG$Z1+XQRf=xOTPTUZK7AJZ>ubAqhoBa z<&gO`rmM7uL8>D+(;LeQMrVsj^M=TuvB&VYN{=iZ%+uQ)mgNhM10CJKiL^_U57@Q%fIkVyq-)T!5 za=alD$`GyWukT;lMT`f+DXH;gM_<5F|DaN@XV8|>U+mvFITu^6kw)NR;k&aglfE zPmH}E!pigos0GbUxt+?GP~?I)B1hyKV6#tVP(q|T6q+Du zNcTd4iUXJJNqxHU}~QeCi{%bR!)c{?v&iY+T+IUiG0EfIjs{mmS*u z8qEjv;06%jV#!eqhM!*DvuBFh=Hvu4h@m)NfXVX*B&2}R2Xw>hE(n(7CztjT5EQ;* zOLt=fq$nr?LTcWdqNp1{PzM=KHd2+S)e8_s`u&o-B)BDm56Y&KdLJB2cm;)b1$Thn7k7XF?#jo65_b~R z|GoqCMcn~Pq?pj0!Xx!aWq?{8y=f?r8xlxCtK#wTz$-+kH~k!f>+=Ktz4C$`Gk%|2 zkP7gkjw1efZo$io@`a`Rv*`Nw?VkWIipW`m&JdnVgXCbQ2*{O?_rI>}1bE?V+~Dw{ zHv+nbF2Ku&I?7;$b>D*}7bh7+2lGUt@dLRKe9aGy2zHBv642tSu0=s3m&u&>X-Q}c zxqQ$^lblum!`L_J5EaUAmw*_Q`yXrJJ0xfw-#{!7@9&#Bh))Q0xIzT$#6xe8Hn&dqW)^)`^n{&NpDH=uromrL%oFJdJ@u)V zFqo*L&3bPre(73y(q481V?|2JrDYKk|H>xu8#dj~dMmhYhsQ(|O@tq}lw0N<-~ZV^ zpOewQc=+8^l)I>{rOx^3%{=a58u#%cf|P{{ozbpD*l}TR-65{7E?z)_oAP+n2>F?* z=`&MkkXaoCLGAi*nby<%yVM5goX-lIJI6h8bI6W|Xe1s9Rk;T_Riy|yx{sdkj>Q%1 zm7bg*IUDJ17vvp`b}eZBSlO`j{w1~ve0rKR(L3^LyUvbt)FQ=2+w|rgWI|ehsd|i=evwMj+!vTt|>hU+xgxa@;l>g3r+3C(e?hl zA6SdE>*MRRi&|&4Mzs%v_7~P4F1U3p5R{!%P7>*#=B{?#cia+mKV7YLPjsaXzGqbT zwWTBdVCT$XtoxYD@%C5IN#*ppjTO@aha~q&)$!X#2ZRxw(JjwRC@5W;l5>zFv0F~> z4?Zofwn%JFbU{UJqw8m?pNn&(lovzt3GN%yMtkvnnJ9c*2PHA-c6M6Fd>}9~*sL-R z?{lg%s&t$EQ5`h@tNMch_vOhXPyMNn*Bd7K%Qi!e7UzHTKA1jWpNyQGG~USUJFiao z#Ou1{!gQYbz{@I=*`?|miH4*%@~vuq6K;w5fOCS5$&{y4qeL5vQLz}&_pOm!`DD@n~Ot$J6r?(u_w)pQ_!HR+pD zx?B=H5W_l<0ibIKuY!2h^r(2%x@MAnN23VETQ?|hQ%SSKF_EjAUatexR*Sk{V>D!7 zaKC2adTGYtBpcpF=>8u0IL-sfeDOolYhL)KNhY`1E8jw4X!oi+%-Ekr79 zhGo&i9gzzFwWz4o#Mu{7tEIE$r9sr{1T~_(xtoSBTBGzOLS-9n<(HEG2s6;bvjN8w z()!IkBTEuNu94i50A5qycExgRGJjYV>K>WKt~x$pU2vkHc3H| zr&X7d!STz`ltUtwfY{u$XEOo?*5ubW>)FJ-2wUBN3R|57(32`Jzobdv-t1H>eq<7_ z8b^(SSz39R_N1UUffQLE04I;~*7)9_!A{WI4QkZ$@e5!`l0}jONNsd<7$y>)U(VQC3F_Kx)Cam=v4n*W#D%K%iLl}!K zS%FN1g8fya{vB&KDRv%hB%^NyP6E>)1rB>uV=wX4O)xPa=#B>;uwY45|FJf!Z&p}# z8zDHK0I3koB&LaX`Dzf1K|m_QVDglNDsNg09 zJsSuW&f2N^SgTk{+Mpn>lw9K;$pEz`dawmcHK}!4#ZzQJ$r{FB;MdZwF+!Y9mB&N^ z1B(hm=&POai7mQC!4B8sK~7AZ_5DYf;UI;;Vvhwe83Bm5mJWmw8Y2m?VA&1A5zuCB z5{T9VKxVH->r=fbV1<{gX#iohkbrjVt3@ADP^zq1cca)!+7fim4a3ehZ87W%AF&vc zj8VUdJ$9bO!{IT2)kgXQSS^j;mxP2RQ&a@%mel;5V4CaSwgHnGfYmOkH{!hcX)Tu@ zA8bU3Ds)ZQ&N7Wm7KE+l4*Zf3zhrS#fg74is0LyPv28VMvb?uKmha335lxsUKj^2W z@FJo{3P-1$eVY3m8Z-G9{@a_Rw*UU_{Ofpv4=|#kjwe8f=l}jx@?8K&)c=o9CExE) zr2yXrx&{QHzPKL%|6Y7=!M_(L8sOjG&a8(2dA7mF6JttB9`oFa0iJvZ`9gfW|M`p! zXQV>UAwIr;3T@LM-xy<3ii=__>5wM`JVpLgGY+27_+nByuV1KR-a}3>*#P<#Oh9uX zzz05*tnlp&0M+3WytsOR_V`=k%tQsYg&4Z9Idm)g`qhtn!K!%$S467>q(*d=7 z(C89M0eVXTN903KV9TPvwP=EHND;7Xvj)P1l?otHcpdeaTL8+?6#p)R33Gh_gwOK@ zAdH1iF{)qz=#@$#$WnmHa#jeIGZBRl8%$pU3>hi}hG>+4rO{+1L?!#H7$% zg1O2e8dRe=aCjMH4^NgrBya^#!ephOz(P4FAX*9u!Z#}}h7bphA6BXW>grN3=07Sx zgN9|GLG;SsmRwZh0Rg-dXq61i2M)|y4&g&0!mwmD=&gD=WDd(#fno#Y5CQC31$v8C z0oH&7)er-$SOHyu5IitX9P?gwD!^-3_@fgdhJIB0xu?gwBA zF#e+d#4t`3bPFB9d(mUEm@SU0utOE*u@Usxy#aI$D3svqbRnpwXT>fMsi_2P2Y~2~xM~ zA$K%a*t8C!#x~#);4$Fg;du;?)q}xm1f}2yO`zGWM$oL%M@Rt{X#zC~!3Isg&A)gz z@nF0{&}L!-c%3%0AZ&C5Sb$$l%yS-WLLn|*HoAYK*$@K!a8o5H4YEg|3B+YVbk}%= z|Cs}T}?y=2XplR zS-@wg6i)mBQi|<>t+K8cq>jFU=xz;Pp-ZrG2jl{e^Z{942lNX*?gy!Jlzi7sdb<{JSr@o!KL{A3i!j=w<#u;ds>)ptYbFy=VWKKTyS zz-ki^ag|gLq=yF6PeLSB#XlfCH2B^WkbdulaL{05a5D?5{e(DRihgJsHk|<)f&qvZ z4R)Ue)eWpe?C|qJXc*3z0~zgypi#JM9;6J0p#hkF5#+u*0&$_i$BQ6$@F-Lb<17QU z))-U_v#dZQRTSfpAR4T-3WVkpP(2*K29Z_?O+r`E;HGs@{J|82fd-Fk0DT@BItQFG z4K>4fTR`JF13_r8*iTSN*erA%4K~~cZ4|Bni{|H`B{*&eXlCXi2{gEU7ia_*!8A4O zfr<#0pktW*0HnYyali`8&^XNX3sfn(0vv8(yhBjXb`|1AgJq6@v|tS)MuUluL9%}x z!UV|^klfgSsL^2jQ}6<-V4<_aN?Xt-%ytGI!60(L-any9*y0@2( zpquc(4)ha_LqjKp$9KVqzJbt5s(SZ8^jUV*s`EFQ^@^#Y88qqCW(G z8}QmCpw>NtYGGk4kYYWCR$*&wkdf^KT7WfiKs}77&?PiD5*H*T&L9>vcpeX(81_7e zmSHq}bkd5a=rm}sAOVnpvD|>euY!6CA@pfD;~FUP9vvNYZl4gS>oL&JAwHgqeQZ?^ zCOQ>(Dag=&``c8ZT}Bs11OI)YFrZbS@04f|AOG)drVlpy0K^AAe_;PxWrKsxjLIj8 zdR1|W(AlfHanVUZWcXOm6d#=q4UPiA4676f(4|pDO}~Sp z22)^4yRM=S!TeU}L{-(-&~KxG|Ho03u2nch=$9ZC{=e}FvJMX&&21d4=mh!y-uX*g zn>wpGJ3e#)A^~_3M!#OAMuL8T2J!P($&;b)qrtz*(61m(L4Jhb-?fY&5P$P}mz=K0@QY~U_xmGf#zQo z2!RLGx(f-;C`<)}=>&f-q)-nc;Nef*2p;h8r)~r&7y*RPpJ4;{b>{g1CT# zUpxR4E}-8R55NSGKPG@S5F!^QAW?;Y34hSrrl1kT1v(p52sDDYh%)y73On-{JFDw} z%X1wA#(=?2!48;*!C;(v{Ot=S4m5-%grziTB%HLJ;K59bXUNQ$K-K1{Qk6(ilSo1B zts)gQm1w0Ze}tsfREg9^lr(GsvxTsmEkH;h2~pK8YJcZj-h1~PC$(g~dFP#Tmvhg4 z?)P5vM&zuQP4M&PvUc+c@)Pxo16o8qS`4`8@9@mTz>DURj!?zGi(%CBDCUDA>Q@*8 zFZ#wMsEAS1nrsOXou(hzzLVK|KE?c1wDmNZg1?G*v>5&>;$B8#{wm^Oe_k;ax1y=K zHG{@X$p2OZ;~2r^fB%l@`-&M;Fg^eK&t&@1V#rpCHe->+kh2tR-qO6|-15qQVa07) zwb%dez(p&cKh3ShJ`^io+TwOkO{L|^69YFZ7H8%fjPY-6b)TH}w|oan^z7B{6RS3+ z?X=@aq~LPYPrci?a`QFrferqwd)x*O>Sn)iz5Ci4>GgRF;f496N{?zB(W^VGW^(WlzjyXOpCdMI_{f@iDzxtdzZiI13l1yR*tM5|& z6rUtBc2AWIx+1|O2a5c*!L`5EOt~qq*6wPzUvz}s4*br;C`NpbJ9(IPZ2I8L(lScf zy?funLH3(OfxOFS{c|fHnp?hc7W~elT*#lD5ghTV6Z5MVXKx>jswy&5d?AG_CmkRN_Z{Z;o85T^bs_qz9P4YB$Vrk%14L40kV zF}vE&=voZ#b9);2x9)S-Hh-LUfA`1VKfr1}eZRZloq6xZ+C8=Y$FF~YA^FH(@qoM5 z|KkJh>dS(KWPPmAPS!h^ZtuOjYxmwes#Xklrv9Ao;uNaH@B6O1LSDcAUAK2#KcFnb zuY1s4edcJ6W@T9)PBb%SZ8+fn_CdFM%OvR_>%)@{FZMru(7o61dB|OPBD`(SxgD|K zR33EinyPaDSzi6_hq3zKe8}xu*GHkvV!nEa5P#DlH$4TxWry5edHvl7vC4NIau=SN zO(GAnCK$!Ex6`*#oj?C!w|jk$*L@QC&phn*oUhl^iC>G<@2utPXzYfsSy}sEJkBxx z{9!k(w}z8QA8}W#?*+TvaGv|yA93$pHwpDmKjN--83fahy3K3aFx?+~)SY)Cz)5yx zh5y#06JxeZ%xZtyW1XD+&SP%#>3w9?t-14ttsZ2=3C)^6`xtIjME#qOxoh>})7YQ= zxciWw`<^@2-}boMHByy!%Cz){ALrc2M&?DUUOvnL{nZohhN-&tfBcp^)t~u&cbfmR z7XW|w`|jU-_9A~pPrAWxw~^j}ue_MKX?b>WI?m4J2WDG4JO<_hYz|@qvk+kG8^)NW z08@X*lWyA-JV=kp?BC(#>_c1nQlDO54F)%q7kqz+@Y9(04yJ_`Bm&$t}{`Tcx;{Pz8`^RtUHH|{*RG_!x!zXajQ`)8Mz$u)P*EG^9~ zEzitfHw!o7+Q0COyZq?(rrtFJfACp%#yJzqVI)hoohMM)kpH_MxU>9UKI=ZhLf-S7 zo8B@>*y6zQ?F%>0F5Wyh`$>QBRW@+dVfPNd_?)`{qW^vlK=!6P@mOkOd_~LtS)|0* zuk~o#o_805cE|H>YlkKbZSWHRiwlfPbP8zQ+E&PEudbImqXokB~1d&agbSx6ujz;Wx z(~ml|qcV7q@)Lu%zUcC8olrMh$e2BC^U9u%5mKyl^rm~~sY2HcS0Y^F2%sn#OE)$!8vK0k#!&CaJYTe0WE2!&qW=gvYSjKya$Jq#WL9`@6J<^ zmp1t8Fj45N&0>05jweeh|BaVi*&NurgsR1^)E<&%*keUc+Z=x2FL>E)cl&0R{f#f< zyNk%*{<5o@an1s5`{KfZo!1>)T3$HNX@nZlU-*5u@npeToH?*lG-&DELDF8T82IEB z@qnfOlULmI*^`2*2(~ZHUMK3dV>L@UeXS!rqmZKU zh)zZc&!!Z*)BGK;xs(Y{f4!$Gr$uMJ>ml_=ejJYrgP?`{4T~ z$849AH~T$!)BeR7Da3`_YYH}cyl38UH!$88f8;Lo&%OcgcfI9KSylPBf9$UCpL@%# z+j<1kt;Y4UZ-R^^KmFuZHxeZem4E(C7q1(j>5aQ8%D7R}kBkkLQl};o>(|<)E^TFt zL7LEl*H(FpwywqdHtQ@RuSy>vm9$yvz1!TeyYye7o#5^>4DF)U6*Y!oajvz6cfx!XK7l^6cg|L#6Ml#pi< zDT+B`HCU8Hk#H%%OV|OiP5?`*QZi=+tEm2lFdE)c3EvsXHlISgf zCOX4#GXbcosh43g?#hGX>us#Xe0@|7r(u=99 zrpX`TRYfipyh$L@CcM@#l5aI2l|l|U#6x0gN#!QTizp&W4OGDzXC$!Uh}ChNO6gr8 z=29wDutL%u1*^pUDp;)r752qash_}u|A53mOaKMe+<{QArVy@RrBv<}3_;ScG&1rL zr*V~>ZxB7NPZKJ zSJwtFDe?XEAOplSiX`7susG0J`7lk{p2kaab0jQA+H2u>X(4sc1~%-XkSL`ArKJ@+ zsMsYFTUAVHv#CWVIAtl4gcIZX`-!`Ghf!LE7D*`5s_8c?;zXKAA*?El?QPe@xw z5{NYXA4M_9ue6f`L`-#Ot4E$P5+-Qrr$218Bu~mNQk|qlxkqyhn;2XMH0F_JwzMt6 z#njq>V3P3>+OyFW*BTK4)6yRm!vuLylhEKbK_AU@6Nl6KHK7-wv}8%aqG@lMn6Jnv z5P>KBAF-bfu~{{i)fk!r$<)WhBszLUFbTT#V#;DNCusGrD3eKGvwT{x=G@6WrK2A1 zu0-SvtT5avX}W7pm(kD~2HdvMS&|HC><1H*pcuDZ;)nDCOM*wutrE3sw2u9c*w27r zaKLnBRcd_)#&t=v7;+vBtD4I+!J;{kAgyZnU&S_eE33*_Led1onM%T2H8DRpZ8WFi z7NcHZmBd5oC5J0Sw#NF|sweJ1?+)Q=dixobdi3z}OMH*{LqMEqC5YHbOD$z>Nc zNu?v+2z56{R}&(c@vwTqc*6fWiFNobFcUo1*cmOsb(Wjds3vUE9IWYiX(1$Z%!k@o z)D>~C+A$`@NPk^La(yP?3=1@Fw&vD@Su~+Rr%mJduO_K6tFD@RLz9z`Vv~4<6Qi7k zIrqA%bZ!q`siI{nC{bMLq)}kn5do{UL6Ur5?~Wc4rbaIiX;s{UmNJow{~%7an-!Se z9kAx{gOD>^ZBfSw-Vr#+Exn$Def*c?2}9~tb0j@t7q7(;vY^frn6V3F(NwFE?He*|80k1#k@qMA;_$F>SYJcu3;M(Wd&^hC=d3zS=8;UsmT zwVAp_8scHAh<+k-tcbQYeh^~|)Fh-uX2+O5ou3HAoFH*|q;pm3QK=4WI8{<3Jux?h zG#8RMH)2Odpi2cJC4D_=WUDy2*pz;#-UOZ%{!-B)us4fgg&KxVX=O=BJ3@PitxBp& zTVf_5@6!WfzK#Ivt!^K3ND<8(9d&CX3kmf~xi1?C4YetwRiuYT;8Gqk*3!=*=`sV0 zsdau5r?ek?&V01DK`Gz+qIX9=JQ3D6VFS|9v<1RN(`wZ0M~Y}*ABTn;=5jAhhcYp3 zCtX*KxeI4RjGCO@Ba*`rDn4f90PS`rG@NBxX4HMyG71`Fl2{%73T(u*o@d+)(eZhl z@fCLgFGRy71=gBN?xBN0hzY^;PEg$bv_=ybCNhPV_OhlWnjUJ_i18jf+0%e4(~q%1j_q5W%4Ezsa$9<;pUNR2|`t`!Uo2dK3a zp=qu<%4)`oA-W09PU^UX@n&}nXkaBSO>eHQ>r87nu1v@0codUo<55h}9$0M*G5Ls2 zAY$ym$lUbN2tZTh!z#%&?eIvb1)6AtrvZ#jYN(l zLRS`KK%MR)Fr|q?$zn};oEkzGA$Wh%>f?qw>!2QNf`4GP=r7r;7Cua)POqUYwG2o= z(h1~*Au5y1SU}n~Cekd4g|tqyXcIHxCXGsy!iPdHhKTgv__Z>zv3g16OdA~rRH`MR zKigCCLvuwJ3M55HjUg&2D(bMJB$?K%MgvXUg9wDXYc@v_RxhTaf!xBzhNz@BqYVrN z0A2W@J;ec-0h{Lm0=t1R)>03xZWv&Qs5}_QLQz2P1mfnQA2ms>%jb+&%QGO8c+jFU zAuL9GvqT#rvT&W|LQEWBh&et3Ls~-^v>1*M#>8WDJTgS3?XN)GTs4~93B)#;$oQ zn_@ zh+j9ET}6XlpB;SB&W4Fo;|IXgnnQp`*&^fuv?L*_EDj>sN{9$7)e#TGB&!xrx78%F z)JYt)lRfsfEDj>2doy5jw`TH4k~}lDIA}{#R-u5XBO_=lttD|aB-b}Pk$z>k7>Kd{ zAxvt{#x+;8+m(-iR$DzREpdm;A@V<#YN8gUCJ;A|=uL6~V!~Rpm|XjRXfqRxR2;y> z0vr8fz~++GHNn?}jH!L=c>;1VJELyMdS)dE}OhISJCNV8CWP(-C9QnROx5n%RG_ zLKZ{$I)p)d1Y?((o&fr63?Q^feK;O?BTqjLf~Z4k!v--~f+04od=qY3*I(nvRS*PGDAm5px7R41z$Ur>@Q&3t(J*EyV+aSDGWC3ah;^wVVl~*ablV zk1!y`Mjhx<_||ov|xnoAas)|48MNY#|^YY99I zUUTWK;s3}BV?<3zK!L|dKgVt-k?dJdB8jMhHD3hKndL4BswETBh*fMSro^DNMCu}1 zFtHvcIigmg9Z_5lxyNOR&0_R#VW_ zW+dTms&10vL``U$P%7g&sI8k;ZyjP8iC)wqxDTSU7M!--0Mw1}T`!OrOv@RyTO;(+8P&(lw|tCcua_yl;KRrOr9o{kxg2ZiG6{77 z?bd)LI!y+KI&Gxk#vs1w1ccuEqgt3Xp+^0EoBK zlW;L!pIt%htrdYXvN;mDhoyH+L2ZJot%s0;rgkO3OwAscx!M8@Vb+T#!Z8a>xQe3j zF5q&fw&-+=b%TqXmI{I7%y!MbSlRc47Sfi?|&lm#;2 @@ -1100,7 +1100,7 @@ through the normal startup process just like it was started from ROM. However, your ROM has not been updated and the next time you boot your system, it will revert to the system image contained in ROM. -# Upgrading via Flash Utility +## Upgrading via Flash Utility If you do not have easy access to a ROM programmer, it is usually possible to reprogram your system ROM using the FLASH utility from Will @@ -1142,7 +1142,7 @@ To confirm your ROM chip has been successfully updated, restart your system and boot an operating system from ROM. Do not boot from a disk device yet. Review the boot messages to see if any issues have occurred. -# Upgrading via XModem Flash Updater +## Upgrading via XModem Flash Updater Similar to using the Flash utility, the system ROM can be updated or upgraded through the ROM based updater utility. This works by by @@ -1157,7 +1157,7 @@ file. More information can be found in the ROM Applications document. -# Post Update System Image and Application update process +## Post Upgrade System Image and Application Update Process Once you are satisfied that the ROM is working well, you will need to update the system images and RomWBW custom applications on your disk @@ -1226,21 +1226,20 @@ system on your disk. After this is done, you will need to use `SYSCOPY` to place the ZPM3 loader image on the boot tracks of all ZPM3 boot disks/slices. The - loader image is called `CPMLDR.SYS`. You must then copy (at a + loader image is called `ZPMLDR.SYS`. You must then copy (at a minimum) `CPM3.SYS`, `ZCCP.COM`, `ZINSTAL.ZPM`, and `STARTZPM.COM` onto the disk/slice. Assuming you copied the ZPM3 boot files onto your RAM disk at A:, you would use: - A>B:SYSCOPY C:=CPMLDR.SYS + A>B:SYSCOPY C:=ZPMLDR.SYS A>B:COPY CPM3.SYS C: A>B:COPY ZCCP.COM C: A>B:COPY ZINSTAL.ZPM C: A>B:COPY STARTZPM.COM C: - You may be wondering if the references to `CPMLDR.SYS` and - `CPM3.SYS` are typos. They are not. ZPM3 uses the same loader image - as CPM3. The ZPM3 main system code file is called `CPM3.SYS` which - is the same name as CP/M 3 uses, but the file contents are not the + You may be wondering if the reference to `CPM3.SYS` is a typo. It is + not. The ZPM3 main system code file is called `CPM3.SYS` which is + the same name as CP/M 3 uses, but the file contents are not the same. Finally, if you have copies of any of the RomWBW custom applications on @@ -1272,7 +1271,7 @@ images. - FAT.COM - TUNE.COM -# System Update +## System Update If the system running ROMWBW utilizes the SST39SF040 Flash chip then it is possible to do a System Update in place of a System Upgrade in some @@ -1298,9 +1297,9 @@ extension “.rom†and be 512Kb or 1024Kb in size. Transferring and flashing the System Update is accomplished in the same manner as described above in *Upgrading* with the required difference being that the flash application needs to be directed to complete a -partial flash using the /p command line switch. +partial flash using the /P command line switch. -`E>flash write rom.upd /p` +`E>FLASH WRITE ROM.UPD /P` # RomWBW Distribution @@ -1317,12 +1316,12 @@ set of directories. Each of these directories has it’s own ReadMe.txt file describing the contents in detail. In summary, these directories are: -| Application | Description | -|-------------|-----------------------------------------------------------------------------------------------------------------------------------------| -| Binary | The final output files of the build process are placed here. Most importantly, are the ROM images with the file names ending in “.româ€. | -| Doc | Contains various detailed documentation including the operating systems, RomWBW architecture, etc. | -| Source | Contains the source code files used to build the software and ROM images. | -| Tools | Contains the MS Windows programs that are used by the build process or that may be useful in setting up your system. | +| Application | Description | +|-------------|-------------------------------------------------------------------------------------------------------------------------------------| +| Binary | The final output files of the build process are placed here. Most importantly, the ROM images with the file names ending in “.româ€. | +| Doc | Contains various detailed documentation including the operating systems, RomWBW architecture, etc. | +| Source | Contains the source code files used to build the software and ROM images. | +| Tools | Contains the MS Windows programs that are used by the build process or that may be useful in setting up your system. | # Acknowledgments @@ -1343,10 +1342,11 @@ applications are no longer provided. driver. - Ed Brindley contributed some of the code that supports the RC2014 platform. -- Phil Summers contributed Forth and BASIC in ROM, the AY-3-8910 sound - driver as well as a long list of general code enhancements. +- Phil Summers contributed the Forth and BASIC adaptations in ROM, the + AY-3-8910 sound driver as well as a long list of general code + enhancements. - Phillip Stevens contributed support for FreeRTOS. -- Curt Mayer contributed the Linux / MacOS build process. +- Curt Mayer contributed the original Linux / MacOS build process. - UNA BIOS and FDISK80 are the products of John Coffman. - FLASH4 is a product of Will Sowerbutts. - CLRDIR is a product of Max Scane. @@ -1379,8 +1379,8 @@ accordance with the intentions and/or licensing of their creators. If anyone feels their work is being used outside of it’s intended licensing, please notify: - Wayne Warthen - wwarthen@gmail.com +> Wayne Warthen +> wwarthen@gmail.com RomWBW is an aggregate work. It is composed of many individual, standalone programs that are distributed as a whole to function as a diff --git a/ReadMe.txt b/ReadMe.txt index 22459a57..ca05cffe 100644 --- a/ReadMe.txt +++ b/ReadMe.txt @@ -1,6 +1,6 @@ RomWBW Getting Started Wayne Warthen (mailto:wwarthen@gmail.com) -03 Jan 2022 +26 Jan 2022 @@ -17,7 +17,7 @@ RomWBW Z80/Z180 System Software Version 3.1 Pre-release -03 Jan 2022 +26 Jan 2022 Wayne Warthen wwarthen@gmail.com @@ -1154,7 +1154,7 @@ file. More information can be found in the ROM Applications document. -Post Update System Image and Application update process +Post Upgrade System Image and Application Update Process Once you are satisfied that the ROM is working well, you will need to update the system images and RomWBW custom applications on your disk @@ -1222,21 +1222,20 @@ system on your disk. After this is done, you will need to use SYSCOPY to place the ZPM3 loader image on the boot tracks of all ZPM3 boot disks/slices. The - loader image is called CPMLDR.SYS. You must then copy (at a minimum) + loader image is called ZPMLDR.SYS. You must then copy (at a minimum) CPM3.SYS, ZCCP.COM, ZINSTAL.ZPM, and STARTZPM.COM onto the disk/slice. Assuming you copied the ZPM3 boot files onto your RAM disk at A:, you would use: - A>B:SYSCOPY C:=CPMLDR.SYS + A>B:SYSCOPY C:=ZPMLDR.SYS A>B:COPY CPM3.SYS C: A>B:COPY ZCCP.COM C: A>B:COPY ZINSTAL.ZPM C: A>B:COPY STARTZPM.COM C: - You may be wondering if the references to CPMLDR.SYS and CPM3.SYS - are typos. They are not. ZPM3 uses the same loader image as CPM3. - The ZPM3 main system code file is called CPM3.SYS which is the same - name as CP/M 3 uses, but the file contents are not the same. + You may be wondering if the reference to CPM3.SYS is a typo. It is + not. The ZPM3 main system code file is called CPM3.SYS which is the + same name as CP/M 3 uses, but the file contents are not the same. Finally, if you have copies of any of the RomWBW custom applications on your hard disk, you need to update them with the latest copies. The @@ -1292,9 +1291,9 @@ extension “.rom†and be 512Kb or 1024Kb in size. Transferring and flashing the System Update is accomplished in the same manner as described above in Upgrading with the required difference being that the flash application needs to be directed to complete a -partial flash using the /p command line switch. +partial flash using the /P command line switch. -E>flash write rom.upd /p +E>FLASH WRITE ROM.UPD /P RomWBW Distribution @@ -1314,8 +1313,8 @@ are: Application Description ------------- ------------------------------------------------------------ Binary The final output files of the build process are placed here. - Most importantly, are the ROM images with the file names - ending in “.româ€. + Most importantly, the ROM images with the file names ending + in “.româ€. Doc Contains various detailed documentation including the operating systems, RomWBW architecture, etc. @@ -1346,10 +1345,11 @@ applications are no longer provided. driver. - Ed Brindley contributed some of the code that supports the RC2014 platform. -- Phil Summers contributed Forth and BASIC in ROM, the AY-3-8910 sound - driver as well as a long list of general code enhancements. +- Phil Summers contributed the Forth and BASIC adaptations in ROM, the + AY-3-8910 sound driver as well as a long list of general code + enhancements. - Phillip Stevens contributed support for FreeRTOS. -- Curt Mayer contributed the Linux / MacOS build process. +- Curt Mayer contributed the original Linux / MacOS build process. - UNA BIOS and FDISK80 are the products of John Coffman. - FLASH4 is a product of Will Sowerbutts. - CLRDIR is a product of Max Scane. @@ -1382,8 +1382,8 @@ accordance with the intentions and/or licensing of their creators. If anyone feels their work is being used outside of it’s intended licensing, please notify: - Wayne Warthen - wwarthen@gmail.com + Wayne Warthen + wwarthen@gmail.com RomWBW is an aggregate work. It is composed of many individual, standalone programs that are distributed as a whole to function as a diff --git a/Source/Apps/Test/cpuspd/cpuspd.asm b/Source/Apps/Test/cpuspd/cpuspd.asm index 4ce9e457..71a22684 100644 --- a/Source/Apps/Test/cpuspd/cpuspd.asm +++ b/Source/Apps/Test/cpuspd/cpuspd.asm @@ -10,8 +10,6 @@ ; #include "../../../HBIOS/hbios.inc" ; -cpumhz .equ 8 ; for time delay calculations (not critical) -; ; General operational equates (should not requre adjustment) ; stksiz .equ $40 ; Working stack size @@ -20,23 +18,6 @@ rtc_port .equ $70 ; RTC latch port adr ; restart .equ $0000 ; CP/M restart vector bdos .equ $0005 ; BDOS invocation vector -; -; primary hardware platforms -; -plt_sbc .equ 1 ; SBC ECB Z80 SBC -plt_zeta .equ 2 ; ZETA Z80 SBC -plt_zeta2 .equ 3 ; ZETA Z80 V2 SBC -plt_n8 .equ 4 ; N8 (HOME COMPUTER) Z180 SBC -plt_mk4 .equ 5 ; MARK IV -plt_una .equ 6 ; UNA BIOS -plt_rcz80 .equ 7 ; RC2014 W/ Z80 -plt_rcz180 .equ 8 ; RC2014 W/ Z180 -plt_ezz80 .equ 9 ; EASY Z80 -plt_scz180 .equ 10 ; SCZ180 -plt_dyno .equ 11 ; DYNO MICRO-ATX MOTHERBOARD -plt_rcz280 .equ 12 ; RC2014 W/ Z280 -plt_mbc .equ 13 ; MULTI BOARD COMPUTER - ; ;======================================================================= ; @@ -68,63 +49,84 @@ main: ; ; Get HBIOS platform ID ; -; - ; Get platform id from RomWBW HBIOS - ld b,BF_SYSVER ; HBIOS VER function 0xF1 - ld c,0 ; Required reserved value - rst 08 ; Do it, L := Platform ID - ld a,l ; Move to A -; - cp plt_sbc - jr set_spd - cp plt_mbc - jr set_spd - jp err_not_sup ; Platform not supported -; -set_spd: ; Use first char of FCB for speed selection ld a,($5D) cp ' ' jr z,show_spd and $5F ; make upper case - cp 'F' ; fast - jr z,set_fast - cp 'H' ; high - jr z,set_fast - cp 'S' ; slow - jr z,set_slow - cp 'L' ; low - jr z,set_slow + cp 'D' ; double + jr z,set_dbl + cp 'F' ; full + jr z,set_full + cp 'H' ; half + jr z,set_half jr usage ; -set_slow: - ld a,(HB_RTCVAL) - and ~%00001000 +set_half: + ld l,0 jr new_spd ; -set_fast: - ld a,(HB_RTCVAL) - or %00001000 +set_full: + ld l,1 + jr new_spd +; +set_dbl: + ld l,2 jr new_spd ; new_spd: - ld (HB_RTCVAL),a - out (rtc_port),a + ld b,BF_SYSSET + ld c,BF_SYSSET_CPUSPD + rst 08 + jp nz,err_not_sup call show_spd xor a ret ; show_spd: - ld a,(HB_RTCVAL) - and %00001000 + ld b,BF_SYSGET + ld c,BF_SYSGET_CPUSPD + rst 08 + jp nz,err_not_sup + push de + ld a,l + ld de,str_slow + cp 0 + jr z,show_spd1 + ld de,str_full + cp 1 + jr z,show_spd1 + ld de,str_dbl + cp 2 jr z,show_spd1 - ld de,str_fast - jr show_spd2 + jp err_invalid show_spd1: - ld de,str_slow -show_spd2: call crlf2 call prtstr + pop hl +; + ld a,h ; memory wait states + cp $FF + jr z,show_spd2 + call crlf + ld de,str_spacer + call prtstr + call prtdecb + ld de,str_memws + call prtstr +; +show_spd2: + ld a,l + cp $FF + jr z,show_spd3 + call crlf + ld de,str_spacer + call prtstr + call prtdecb + ld de,str_iows + call prtstr +; +show_spd3: ret ; usage: @@ -139,6 +141,9 @@ usage: err_not_sup: ld de,str_err_not_sup jr err_ret +err_invalid: + ld de,str_err_invalid + jr err_ret ; err_ret: call crlf2 @@ -346,36 +351,21 @@ addhla: inc h ret ; -; Delay ~10ms -; -delay: - push af - push de - ld de,625 ; 10000us/16us -delay0: - ld a,(cpuscl) -delay1: - dec a - jr nz,delay1 - dec de - ld a,d - or e - jp nz,delay0 - pop de - pop af - ret -; -; ; ;======================================================================= ; Constants ;======================================================================= ; -str_banner .db "RomWBW CPU Speed Selector v0.1, 25-Jan-2022",0 -str_slow .db " CPU speed is SLOW",0 -str_fast .db " CPU speed is FAST",0 -str_err_not_sup .db " ERROR: Platform not supported!",0 -str_usage .db " Usage: CPUSPD [F|S]",0 +str_banner .db "RomWBW CPU Speed Selector v0.2, 26-Jan-2022",0 +str_spacer .db " ",0 +str_slow .db " CPU speed is HALF",0 +str_full .db " CPU speed is FULL",0 +str_dbl .db " CPU speed is DOUBLE",0 +str_memws .db " Memory Wait State(s)",0 +str_iows .db " I/O Wait State(s)",0 +str_err_not_sup .db " ERROR: Platform or configuration not supported!",0 +str_err_invalid .db " ERROR: Invalid configuration!",0 +str_usage .db " Usage: CPUSPD [Half|Full|Double]",0 ; ;======================================================================= ; Working data @@ -385,8 +375,6 @@ stksav .dw 0 ; stack pointer saved at start .fill stksiz,0 ; stack stack .equ $ ; stack top ; -cpuscl .db cpumhz - 2 -; ;======================================================================= ; .end \ No newline at end of file diff --git a/Source/Doc/Architecture.md b/Source/Doc/Architecture.md index 859c712a..a761c02d 100644 --- a/Source/Doc/Architecture.md +++ b/Source/Doc/Architecture.md @@ -1959,6 +1959,23 @@ lookup. | D: BIOS Bank ID | E: User Bank ID +#### SYSGET Subfunction 0xF3 -- Get CPU Speed (CPUSPD) + +| _Entry Parameters_ +| BC: 0xF8F3 + +| _Returned Values_ +| A: Status (0=OK, else error) +| L: Clock Mult (0:Half, 1:Full, 2: Double) +| D: Memory Wait States +| E: I/O Wait States + +This function will return the running CPU speed attributes of a system. +Note that it is frequently impossible to tell if a system is capable +of dynamic speed changes. This function returns it's best guess. +If either of the wait state settings is unknown, the function will +return 0xFF. + ### Function 0xF9 -- System Set (SYSSET) | _Entry Parameters_ @@ -2002,6 +2019,26 @@ available along with the registers/information used as input. | _Returned Values_ | A: Status (0=OK, else error) +#### SYSSET Subfunction 0xF3 -- Set CPU Speed (CPUSPD) + +| _Entry Parameters_ +| BC: 0xF9F3 +| L: Clock Mult (0:Half, 1:Full, 2: Double) +| D: Memory Wait States +| E: I/O Wait States + +| _Returned Values_ +| A: Status (0=OK, else error) + +This function will modify the running CPU speed attributes of a system. +Note that it is frequently impossible to tell if a system is capable +of dynamic speed changes. This function makes the changes blindly. +You can specify 0xFF for either of the wait state settings to have them +left alone. + +In the case of the Z180, the SIO port buad rate is derived from the CPU +speed. So, when the speed is changed the baud rate will change. + ### Function 0xFA -- System Peek (SYSPEEK) | _Entry Parameters_ diff --git a/Source/HBIOS/API.txt b/Source/HBIOS/API.txt index 013ec895..aeae56e9 100644 --- a/Source/HBIOS/API.txt +++ b/Source/HBIOS/API.txt @@ -102,7 +102,7 @@ GET ($F8): DE=CPU Speed in KHz MEMINFO ($F1): - BC=Function/Subfunction A=Result + BC=FuSnction/Subfunction A=Result D=# ROM Banks E=# RAM Banks @@ -111,6 +111,13 @@ GET ($F8): D=BIOS Bank Id E=User Bank Id + CPUSPD ($F3): + BC=Function/Subfunction A=Result + L=Clock Mult (0:Half, 1:Full, 2: Double) + D=Memory Wait States + E=I/O Wait States + + SET ($F9): BC=Function/Subfunction A=Result @@ -127,6 +134,13 @@ SET ($F9): DE=Boot Volume (Disk Unit/Slice) L=Boot Bank Id + CPUSPD ($F3): + BC=Function/Subfunction A=Result + L=Clock Mult (0:Half, 1:Full, 2: Double) + D=Memory Wait States + E=I/O Wait States + + PEEK ($FA): B=Function A=Result D=Bank E=Byte Value diff --git a/Source/HBIOS/cfg_dyno.asm b/Source/HBIOS/cfg_dyno.asm index 5a4ce268..be14562c 100644 --- a/Source/HBIOS/cfg_dyno.asm +++ b/Source/HBIOS/cfg_dyno.asm @@ -13,6 +13,8 @@ ; #DEFINE PLATFORM_NAME "DYNO" ; +#INCLUDE "hbios.inc" +; PLATFORM .EQU PLT_DYNO ; PLT_[SBC|ZETA|ZETA2|N8|MK4|UNA|RCZ80|RCZ180|EZZ80|SCZ180|DYNO|RCZ280|MBC] CPUFAM .EQU CPU_Z180 ; CPU FAMILY: CPU_[Z80|Z180|Z280] BIOS .EQU BIOS_WBW ; HARDWARE BIOS: BIOS_[WBW|UNA] diff --git a/Source/HBIOS/cfg_ezz80.asm b/Source/HBIOS/cfg_ezz80.asm index 24713e83..d18bfb42 100644 --- a/Source/HBIOS/cfg_ezz80.asm +++ b/Source/HBIOS/cfg_ezz80.asm @@ -13,6 +13,8 @@ ; #DEFINE PLATFORM_NAME "EASYZ80" ; +#INCLUDE "hbios.inc" +; PLATFORM .EQU PLT_EZZ80 ; PLT_[SBC|ZETA|ZETA2|N8|MK4|UNA|RCZ80|RCZ180|EZZ80|SCZ180|DYNO|RCZ280|MBC] CPUFAM .EQU CPU_Z80 ; CPU FAMILY: CPU_[Z80|Z180|Z280] BIOS .EQU BIOS_WBW ; HARDWARE BIOS: BIOS_[WBW|UNA] diff --git a/Source/HBIOS/cfg_master.asm b/Source/HBIOS/cfg_master.asm index f527e76f..b666088c 100644 --- a/Source/HBIOS/cfg_master.asm +++ b/Source/HBIOS/cfg_master.asm @@ -10,6 +10,8 @@ ; #DEFINE PLATFORM_NAME "ROMWBW" ; +#INCLUDE "hbios.inc" +; PLATFORM .EQU PLT_SBC ; PLT_[SBC|ZETA|ZETA2|N8|MK4|UNA|RCZ80|RCZ180|EZZ80|SCZ180|DYNO|RCZ280|MBC] CPUFAM .EQU CPU_Z80 ; CPU FAMILY: CPU_[Z80|Z180|Z280] BIOS .EQU BIOS_WBW ; HARDWARE BIOS: BIOS_[WBW|UNA] diff --git a/Source/HBIOS/cfg_mbc.asm b/Source/HBIOS/cfg_mbc.asm index 08547480..74b64d92 100644 --- a/Source/HBIOS/cfg_mbc.asm +++ b/Source/HBIOS/cfg_mbc.asm @@ -13,6 +13,8 @@ ; #DEFINE PLATFORM_NAME "Multi Board Computer" ; +#INCLUDE "hbios.inc" +; PLATFORM .EQU PLT_MBC ; PLT_[SBC|ZETA|ZETA2|N8|MK4|UNA|RCZ80|RCZ180|EZZ80|SCZ180|DYNO|RCZ280|MBC] CPUFAM .EQU CPU_Z80 ; CPU FAMILY: CPU_[Z80|Z180|Z280] BIOS .EQU BIOS_WBW ; HARDWARE BIOS: BIOS_[WBW|UNA] diff --git a/Source/HBIOS/cfg_mk4.asm b/Source/HBIOS/cfg_mk4.asm index 157e1134..01aa44fb 100644 --- a/Source/HBIOS/cfg_mk4.asm +++ b/Source/HBIOS/cfg_mk4.asm @@ -13,6 +13,8 @@ ; #DEFINE PLATFORM_NAME "MARK IV" ; +#INCLUDE "hbios.inc" +; PLATFORM .EQU PLT_MK4 ; PLT_[SBC|ZETA|ZETA2|N8|MK4|UNA|RCZ80|RCZ180|EZZ80|SCZ180|DYNO|RCZ280|MBC] CPUFAM .EQU CPU_Z180 ; CPU FAMILY: CPU_[Z80|Z180|Z280] BIOS .EQU BIOS_WBW ; HARDWARE BIOS: BIOS_[WBW|UNA] diff --git a/Source/HBIOS/cfg_n8.asm b/Source/HBIOS/cfg_n8.asm index d9aa64c6..f4bcf1b2 100644 --- a/Source/HBIOS/cfg_n8.asm +++ b/Source/HBIOS/cfg_n8.asm @@ -13,6 +13,8 @@ ; #DEFINE PLATFORM_NAME "N8" ; +#INCLUDE "hbios.inc" +; PLATFORM .EQU PLT_N8 ; PLT_[SBC|ZETA|ZETA2|N8|MK4|UNA|RCZ80|RCZ180|EZZ80|SCZ180|DYNO|RCZ280|MBC] CPUFAM .EQU CPU_Z180 ; CPU FAMILY: CPU_[Z80|Z180|Z280] BIOS .EQU BIOS_WBW ; HARDWARE BIOS: BIOS_[WBW|UNA] diff --git a/Source/HBIOS/cfg_rcz180.asm b/Source/HBIOS/cfg_rcz180.asm index eaf2141d..2a5a8f25 100644 --- a/Source/HBIOS/cfg_rcz180.asm +++ b/Source/HBIOS/cfg_rcz180.asm @@ -13,6 +13,8 @@ ; #DEFINE PLATFORM_NAME "RC2014" ; +#INCLUDE "hbios.inc" +; PLATFORM .EQU PLT_RCZ180 ; PLT_[SBC|ZETA|ZETA2|N8|MK4|UNA|RCZ80|RCZ180|EZZ80|SCZ180|DYNO|RCZ280|MBC] CPUFAM .EQU CPU_Z180 ; CPU FAMILY: CPU_[Z80|Z180|Z280] BIOS .EQU BIOS_WBW ; HARDWARE BIOS: BIOS_[WBW|UNA] diff --git a/Source/HBIOS/cfg_rcz280.asm b/Source/HBIOS/cfg_rcz280.asm index 625f5e32..a13b1308 100644 --- a/Source/HBIOS/cfg_rcz280.asm +++ b/Source/HBIOS/cfg_rcz280.asm @@ -13,6 +13,8 @@ ; #DEFINE PLATFORM_NAME "RC2014" ; +#INCLUDE "hbios.inc" +; PLATFORM .EQU PLT_RCZ280 ; PLT_[SBC|ZETA|ZETA2|N8|MK4|UNA|RCZ80|RCZ180|EZZ80|SCZ180|DYNO|RCZ280|MBC] CPUFAM .EQU CPU_Z280 ; CPU FAMILY: CPU_[Z80|Z180|Z280] BIOS .EQU BIOS_WBW ; HARDWARE BIOS: BIOS_[WBW|UNA] diff --git a/Source/HBIOS/cfg_rcz80.asm b/Source/HBIOS/cfg_rcz80.asm index 4fbb3501..a6d411a2 100644 --- a/Source/HBIOS/cfg_rcz80.asm +++ b/Source/HBIOS/cfg_rcz80.asm @@ -13,6 +13,8 @@ ; #DEFINE PLATFORM_NAME "RC2014" ; +#INCLUDE "hbios.inc" +; PLATFORM .EQU PLT_RCZ80 ; PLT_[SBC|ZETA|ZETA2|N8|MK4|UNA|RCZ80|RCZ180|EZZ80|SCZ180|DYNO|RCZ280|MBC] CPUFAM .EQU CPU_Z80 ; CPU FAMILY: CPU_[Z80|Z180|Z280] BIOS .EQU BIOS_WBW ; HARDWARE BIOS: BIOS_[WBW|UNA] diff --git a/Source/HBIOS/cfg_sbc.asm b/Source/HBIOS/cfg_sbc.asm index 1fe35342..f71d5203 100644 --- a/Source/HBIOS/cfg_sbc.asm +++ b/Source/HBIOS/cfg_sbc.asm @@ -13,6 +13,8 @@ ; #DEFINE PLATFORM_NAME "SBC" ; +#INCLUDE "hbios.inc" +; PLATFORM .EQU PLT_SBC ; PLT_[SBC|ZETA|ZETA2|N8|MK4|UNA|RCZ80|RCZ180|EZZ80|SCZ180|DYNO|RCZ280|MBC] CPUFAM .EQU CPU_Z80 ; CPU FAMILY: CPU_[Z80|Z180|Z280] BIOS .EQU BIOS_WBW ; HARDWARE BIOS: BIOS_[WBW|UNA] diff --git a/Source/HBIOS/cfg_scz180.asm b/Source/HBIOS/cfg_scz180.asm index 82daba78..1698252b 100644 --- a/Source/HBIOS/cfg_scz180.asm +++ b/Source/HBIOS/cfg_scz180.asm @@ -13,6 +13,8 @@ ; #DEFINE PLATFORM_NAME "SCZ180" ; +#INCLUDE "hbios.inc" +; PLATFORM .EQU PLT_SCZ180 ; PLT_[SBC|ZETA|ZETA2|N8|MK4|UNA|RCZ80|RCZ180|EZZ80|SCZ180|DYNO|RCZ280|MBC] CPUFAM .EQU CPU_Z180 ; CPU FAMILY: CPU_[Z80|Z180|Z280] BIOS .EQU BIOS_WBW ; HARDWARE BIOS: BIOS_[WBW|UNA] diff --git a/Source/HBIOS/cfg_una.asm b/Source/HBIOS/cfg_una.asm index 33528538..408e0fb6 100644 --- a/Source/HBIOS/cfg_una.asm +++ b/Source/HBIOS/cfg_una.asm @@ -13,7 +13,9 @@ ; #DEFINE PLATFORM_NAME "UNA" ; -PLATFORM .EQU PLT_UNA ; PLT_[SBC|ZETA|ZETA2|N8|MK4|UNA|RCZ80|RCZ180|EZZ80|SCZ180|DYNO|RCZ280|MBC] +#INCLUDE "../UBIOS/ubios.inc" +; +;PLATFORM .EQU PLT_UNA ; PLT_[SBC|ZETA|ZETA2|N8|MK4|UNA|RCZ80|RCZ180|EZZ80|SCZ180|DYNO|RCZ280|MBC] BIOS .EQU BIOS_UNA ; HARDWARE BIOS: BIOS_[WBW|UNA] ; BOOT_TIMEOUT .EQU -1 ; AUTO BOOT TIMEOUT IN SECONDS, -1 TO DISABLE, 0 FOR IMMEDIATE diff --git a/Source/HBIOS/cfg_zeta.asm b/Source/HBIOS/cfg_zeta.asm index 8a2bb725..bcd7c7f4 100644 --- a/Source/HBIOS/cfg_zeta.asm +++ b/Source/HBIOS/cfg_zeta.asm @@ -13,6 +13,8 @@ ; #DEFINE PLATFORM_NAME "ZETA" ; +#INCLUDE "hbios.inc" +; PLATFORM .EQU PLT_ZETA ; PLT_[SBC|ZETA|ZETA2|N8|MK4|UNA|RCZ80|RCZ180|EZZ80|SCZ180|DYNO|RCZ280|MBC] CPUFAM .EQU CPU_Z80 ; CPU FAMILY: CPU_[Z80|Z180|Z280] BIOS .EQU BIOS_WBW ; BIOS_[WBW|UNA]: HARDWARE BIOS diff --git a/Source/HBIOS/cfg_zeta2.asm b/Source/HBIOS/cfg_zeta2.asm index 30983347..acff03b4 100644 --- a/Source/HBIOS/cfg_zeta2.asm +++ b/Source/HBIOS/cfg_zeta2.asm @@ -13,6 +13,8 @@ ; #DEFINE PLATFORM_NAME "ZETA V2" ; +#INCLUDE "hbios.inc" +; PLATFORM .EQU PLT_ZETA2 ; PLT_[SBC|ZETA|ZETA2|N8|MK4|UNA|RCZ80|RCZ180|EZZ80|SCZ180|DYNO|RCZ280|MBC] CPUFAM .EQU CPU_Z80 ; CPU FAMILY: CPU_[Z80|Z180|Z280] BIOS .EQU BIOS_WBW ; HARDWARE BIOS: BIOS_[WBW|UNA] diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index 198b6fcc..18f9a886 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -3714,6 +3714,8 @@ SYS_GET: JP Z,SYS_GETMEMINFO CP BF_SYSGET_BNKINFO JP Z,SYS_GETBNKINFO + CP BF_SYSGET_CPUSPD + JP Z,SYS_GETCPUSPD CALL SYSCHK LD A,ERR_NOFUNC ; SIGNAL ERROR OR A ; SET FLAGS @@ -3802,6 +3804,61 @@ SYS_GETBNKINFO: XOR A RET ; +; GET SYSTEM CPU SPEED ORMANCE ATTRIBUTES +; RETURNS: +; L: CLOCK MULT (0:HALF, 1:FULL, 2: DOUBLE) +; D: MEMORY WAIT STATES +; E: I/O WAIT STATES +; +SYS_GETCPUSPD: +; +#IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_MBC)) + LD A,(HB_RTCVAL) + BIT 3,A + LD L,0 ; ASSUME HALF SPEED + JR Z,SYS_GETCPUSPD1 + LD L,1 +SYS_GETCPUSPD1: + LD DE,$FFFF ; UNKNOWN WAIT STATES + XOR A + RET +#ENDIF +; +#IF (CPUFAM == CPU_Z180) + IN0 A,(Z180_CMR) ; GET CLOCK MULTIPLIER + RLCA ; ROTATE BIT TO BIT 0 + AND %00000001 ; ISOLATE IT + LD H,A ; SAVE IN H + IN0 A,(Z180_CCR) ; GET CLOCK CONTROL + RLCA ; ROTATE BIT TO BIT 0 + AND %00000001 ; ISOLATE IT + LD L,A ; SAVE IN L + XOR A ; CLEAR ACCUM + ADD A,H ; ADD IN CMR BIT + ADD A,L ; ADD IN CCR BIT + LD L,A ; SAVE RESULT IN L +; + ; DCNTL = MMII???? + IN0 A,(Z180_DCNTL) ; GET WAIT STATES + RLCA ; ROTATE MEM WS BITS + RLCA ; ... TO LOW BITS + PUSH AF ; SAVE FOR NOW + AND %00000011 ; ISOLATE BITS + LD D,A ; PUT IN D + POP AF ; RECOVER A + RLCA ; ROTATE I/O WS BITS + RLCA ; ... TO LOW BITS + AND %00000011 ; ISOLATE BITS + INC A ; ADD 1 FOR BUILT-IN WS + LD E,A ; PUT IN E +; + XOR A + RET +#ENDIF +; + OR $FF + RET +; ; GET SERIAL UNIT COUNT ; SYS_GETCIOCNT: @@ -3932,6 +3989,8 @@ SYS_SET: JR Z,SYS_SETSECS CP BF_SYSSET_BOOTINFO JR Z,SYS_SETBOOTINFO + CP BF_SYSSET_CPUSPD + JR Z,SYS_SETCPUSPD CALL SYSCHK LD A,ERR_NOFUNC ; SIGNAL ERROR OR A ; SET FLAGS @@ -3973,6 +4032,67 @@ SYS_SETSECS: XOR A RET ; +; SET SYSTEM CPU SPEED ATTRIBUTES +; ON ENTRY: +; L: CLOCK MULT (0:HALF, 1:FULL, 2: DOUBLE) +; D: MEMORY WAIT STATES +; E: I/O WAIT STATES +; +SYS_SETCPUSPD: +; +#IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_MBC)) +; +; WAIT STATE SETTINGS ARE IGNORED FOR Z80 +; + LD A,L ; CLK SPD TO ACCUM + LD C,%00000000 ; HALF SPEED + CP 0 + JR Z,SYS_SETCPUSPD1 + LD C,%00001000 ; FULL SPEED + CP 1 + JR Z,SYS_SETCPUSPD1 + JR SYS_SETCPUSPD_ERR ; SPD NOT SUPPORTED +SYS_SETCPUSPD1: + LD A,(HB_RTCVAL) + AND ~%00001000 ; CLEAR SPEED BIT + OR C ; IMPLEMENT NEW SPEED BIT + LD (HB_RTCVAL),A ; SAVE IN SHADOW REGISTER + OUT (RTCIO),A ; UPDATE HARDWARE REGISTER + XOR A + RET +#ENDIF +; +#IF (CPUFAM == CPU_Z180) + LD A,L ; CLK SPD TO ACCUM + LD B,0 ; B HAS BIT FOR CMR + LD C,0 ; C HAS BIT FOR CCR + CP 2 ; DOUBLE SPEED? + JR C,SYS_SETCPUSPD1 + LD B,%10000000 +SYS_SETCPUSPD1: + CP 1 + JR C,SYS_SETCPUSPD2 + LD C,%10000000 +SYS_SETCPUSPD2: +; + IN0 A,(Z180_CMR) + AND ~%10000000 + OR B + OUT0 (Z180_CMR),A +; + IN0 A,(Z180_CCR) + AND ~%10000000 + OR C + OUT0 (Z180_CCR),A +; + XOR A + RET +#ENDIF +; +SYS_SETCPUSPD_ERR: + OR $FF ; NOT SUPPORTED + RET +; ; RETURN A BYTE OF MEMORY FROM SPECIFIED BANK ; ENTRY: D=BANK ID, HL=ADDRESS ; RETURN: E=BYTE VALUE diff --git a/Source/HBIOS/hbios.inc b/Source/HBIOS/hbios.inc index 498d51c7..cd25559a 100644 --- a/Source/HBIOS/hbios.inc +++ b/Source/HBIOS/hbios.inc @@ -108,10 +108,12 @@ BF_SYSGET_BOOTINFO .EQU $E0 ; GET BOOT INFORMATION BF_SYSGET_CPUINFO .EQU $F0 ; GET CPU INFORMATION BF_SYSGET_MEMINFO .EQU $F1 ; GET MEMORY CAPACTITY INFO BF_SYSGET_BNKINFO .EQU $F2 ; GET BANK ASSIGNMENT INFO +BF_SYSGET_CPUSPD .EQU $F3 ; GET CLOCK SPEED & WAIT STATES ; BF_SYSSET_TIMER .EQU $D0 ; SET TIMER VALUE BF_SYSSET_SECS .EQU $D1 ; SET SECONDS VALUE BF_SYSSET_BOOTINFO .EQU $E0 ; SET BOOT INFORMATION +BF_SYSSET_CPUSPD .EQU $F3 ; SET CLOCK SPEED & WAIT STATES ; BF_SYSINT_INFO .EQU $00 ; GET INTERRUPT SYSTEM INFO BF_SYSINT_GET .EQU $10 ; GET INT VECTOR ADDRESS @@ -119,6 +121,22 @@ BF_SYSINT_SET .EQU $20 ; SET INT VECTOR ADDRESS ; CIO_CONSOLE .EQU $80 ; CIO UNIT NUM FOR CUR CON ; +; PRIMARY HARDWARE PLATFORMS +; +PLT_SBC .EQU 1 ; SBC ECB Z80 SBC +PLT_ZETA .EQU 2 ; ZETA Z80 SBC +PLT_ZETA2 .EQU 3 ; ZETA Z80 V2 SBC +PLT_N8 .EQU 4 ; N8 (HOME COMPUTER) Z180 SBC +PLT_MK4 .EQU 5 ; MARK IV +PLT_UNA .EQU 6 ; UNA BIOS +PLT_RCZ80 .EQU 7 ; RC2014 W/ Z80 +PLT_RCZ180 .EQU 8 ; RC2014 W/ Z180 +PLT_EZZ80 .EQU 9 ; EASY Z80 +PLT_SCZ180 .EQU 10 ; SCZ180 +PLT_DYNO .EQU 11 ; DYNO MICRO-ATX MOTHERBOARD +PLT_RCZ280 .EQU 12 ; RC2014 W/ Z280 +PLT_MBC .EQU 13 ; MULTI BOARD COMPUTER +; ; HBIOS GLOBAL ERROR RETURN VALUES ; ERR_NONE .EQU 0 ; SUCCESS diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index 630d8752..080677e3 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -42,22 +42,6 @@ DL_INFO .EQU 16 ; HBIOS DISPLAYS INFORMATIONAL MESSAGES DL_DETAIL .EQU 20 ; HBIOS DISPLAYS DETAILED DIAGNOSTIC MESSAGES DL_VERBOSE .EQU 24 ; HBIOS DISPLAYS ANYTHING IT KNOWS HOW TO ; -; PRIMARY HARDWARE PLATFORMS -; -PLT_SBC .EQU 1 ; SBC ECB Z80 SBC -PLT_ZETA .EQU 2 ; ZETA Z80 SBC -PLT_ZETA2 .EQU 3 ; ZETA Z80 V2 SBC -PLT_N8 .EQU 4 ; N8 (HOME COMPUTER) Z180 SBC -PLT_MK4 .EQU 5 ; MARK IV -PLT_UNA .EQU 6 ; UNA BIOS -PLT_RCZ80 .EQU 7 ; RC2014 W/ Z80 -PLT_RCZ180 .EQU 8 ; RC2014 W/ Z180 -PLT_EZZ80 .EQU 9 ; EASY Z80 -PLT_SCZ180 .EQU 10 ; SCZ180 -PLT_DYNO .EQU 11 ; DYNO MICRO-ATX MOTHERBOARD -PLT_RCZ280 .EQU 12 ; RC2014 W/ Z280 -PLT_MBC .EQU 13 ; MULTI BOARD COMPUTER -; ; CPU TYPES ; CPU_NONE .EQU 0 ; NO CPU TYPE DEFINED @@ -416,15 +400,6 @@ SPD_LOW .EQU 2 ; PLATFORM CAN CHANGE SPEED, STARTS LOW ; #INCLUDE "build.inc" ; INCLUDE USER CONFIG, ADD VARIANT, TIMESTAMP, & ROMSIZE ; -#IF (BIOS == BIOS_WBW) -#INCLUDE "hbios.inc" -#ENDIF -; -#IF (BIOS == BIOS_UNA) -#INCLUDE "../UBIOS/ubios.inc" -#ENDIF -; -; ; INCLUDE Z180 REGISTER DEFINITIONS ; #IF (BIOS == BIOS_WBW) @@ -713,16 +688,15 @@ INT_PIO1B .EQU 12 ; ZILOG PIO 1, CHANNEL B #DEFINE VEC(INTX) INTX*2 #ENDIF - +; ; SET DEFAULT CSIO SPEED (INTERNAL CLOCK, SLOW AS POSSIBLE) ; DIV 1280, 14KHZ @ 18MHZ CLK - +; #IF (BIOS == BIOS_WBW) #IF (CPUFAM == CPU_Z180) Z180_CNTR_DEF .EQU $06 ; DEFAULT VALUE FOR Z180 CSIO CONFIG #ENDIF #ENDIF - ; ; HELPER MACROS ; diff --git a/Source/ver.inc b/Source/ver.inc index 50edcccd..0f82f97b 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,4 +2,4 @@ #DEFINE RMN 1 #DEFINE RUP 1 #DEFINE RTP 0 -#DEFINE BIOSVER "3.1.1-pre.150" +#DEFINE BIOSVER "3.1.1-pre.151" diff --git a/Source/ver.lib b/Source/ver.lib index 091ba1e6..61894d78 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 1 rup equ 1 rtp equ 0 biosver macro - db "3.1.1-pre.150" + db "3.1.1-pre.151" endm From b6aa769f120668c0d4de7c8fdc4c73c6ad9cb00b Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Tue, 1 Feb 2022 17:42:31 -0800 Subject: [PATCH 07/34] Finalize CPUSPD The CPUSPD app is now considered stable and fully supported. I have added the application and the API's to the documentation. --- Doc/ROM Applications.pdf | Bin 193895 -> 193897 bytes Doc/RomWBW Applications.pdf | Bin 229563 -> 241325 bytes Doc/RomWBW Architecture.pdf | Bin 451133 -> 451481 bytes Doc/RomWBW Disk Catalog.pdf | Bin 134793 -> 134793 bytes Doc/RomWBW Getting Started.pdf | Bin 272619 -> 272620 bytes ReadMe.md | 4 +- ReadMe.txt | 4 +- Source/Apps/Build.cmd | 1 + Source/Apps/Clean.cmd | 1 + Source/Apps/Makefile | 2 +- Source/Apps/Test/Build.cmd | 1 - Source/Apps/Test/Clean.cmd | 1 - Source/Apps/Test/Makefile | 2 +- Source/Apps/Test/cpuspd/Makefile | 7 - Source/Apps/{Test => }/cpuspd/Build.cmd | 2 +- Source/Apps/{Test => }/cpuspd/Clean.cmd | 0 Source/Apps/cpuspd/Makefile | 7 + Source/Apps/{Test => }/cpuspd/cpuspd.asm | 227 ++++++++++++++-- Source/Doc/Applications.md | 70 ++++- Source/Doc/Architecture.md | 16 +- Source/Doc/GettingStarted.md | 3 +- Source/HBIOS/hbios.asm | 315 ++++++++++++++++++----- Source/Images/fd_bp.txt | 1 + Source/Images/fd_cpm22.txt | 1 + Source/Images/fd_cpm3.txt | 1 + Source/Images/fd_nzcom.txt | 1 + Source/Images/fd_zpm3.txt | 1 + Source/Images/fd_zsdos.txt | 1 + Source/Images/hd_bp.txt | 1 + Source/Images/hd_cpm22.txt | 1 + Source/Images/hd_cpm3.txt | 1 + Source/Images/hd_nzcom.txt | 1 + Source/Images/hd_zpm3.txt | 1 + Source/Images/hd_zsdos.txt | 1 + Source/RomDsk/Build.cmd | 2 +- Source/RomDsk/Makefile | 2 +- Source/ver.inc | 2 +- Source/ver.lib | 2 +- 38 files changed, 582 insertions(+), 101 deletions(-) delete mode 100644 Source/Apps/Test/cpuspd/Makefile rename Source/Apps/{Test => }/cpuspd/Build.cmd (71%) rename Source/Apps/{Test => }/cpuspd/Clean.cmd (100%) create mode 100644 Source/Apps/cpuspd/Makefile rename Source/Apps/{Test => }/cpuspd/cpuspd.asm (51%) diff --git a/Doc/ROM Applications.pdf b/Doc/ROM Applications.pdf index 62badcd653f20aefc5e0f14e0be67b3f3ffe85de..5d7c2dacdf8c3183bad07b8a7c328372f3460a03 100644 GIT binary patch delta 11921 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 diff --git a/Doc/RomWBW Applications.pdf b/Doc/RomWBW Applications.pdf index e1e22c70906cba88cce9e2243cae46b525d5280f..bb6a0000440b7909589057f3abefcf8149169fd5 100644 GIT binary patch delta 51252 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 B@&Et; delta 41231 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 diff --git a/Doc/RomWBW Architecture.pdf b/Doc/RomWBW Architecture.pdf index fcc7429803501b9db7cafbec21f8cdc3cb3630a6..8a8dd61e19b7a43b9c1be99ea980e4f5a3f8a2b7 100644 GIT binary patch delta 16198 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 D2QS4z delta 15895 zcmaib2{@Hq_jfqQoXnJYJ`~P8nCE#cDI`NE^E{+DrXm!Xj;Rb~O2}Mh86s2WC_^%a zNFgNO?Rnq-^YonaUf1Wk+;;0;Ywxvwd#$zC-uo`?4Oe43S9~zO$L#}@QGItm+AM+2 z0DIe+PzOTW!0q9-|6e=*Uxf^&mXk0zj$`0K*Trq8DcHhxl{pkQpy%C zqq0kk>B& zB+5E$1E(9kXf6!7C7m6x9uD(Lxt9MW@WRtUTS@Jh$o2T~ww(D1?iQ>8w`@MM1JH6JTalY^WXF*tjB zECz|S!P-Mn2s>=Jq)V-&3)y58$(u-yZ8G4O9QdWE<=6(L%Td4)@I*3Y2)^UW2d|GW znS#bIZ9cqE?L@KM*>~~g3zwVgjqMNe+N&p~BFpbqYpofbH6I6eadh7H(KyG+W+3p)cwM-q#`-8jTia$V|&KA z-*vpt3HJH^qE$n1zPK#p3Hkgja?q$S+B`j?n0~1^7=g1No@PrLXMwHzAUGZB*7n^h zOSC?5cEcum`-=3R>7UcOZpg`X2pl8PhMZ0swcA@T(6c#nl9Wl1X13HKSp< zAgK0`yX7W0U~hRe>(cETOT&#fGsP}l#19w6II7Q-?(poyX`8(4C_SjVceX3>O;-A} zYnz)XYUpHO-U)Nj=3(_Fmni7=x$!YOpc~RnB{>zmcc-}^KCe$}i zqm7n|^_GhCwf(Dy&-M@B;{qGg7|eeu7(4hH6< zi)L2O_It~_Fv6wzAJWgLHSaEGq0`(c{gVxEa!6Yxx36Pq7iy$yJGKidy=v3u{Y-pb zp04wG*-y!3=D76iQI(}+U?bj4ny*SWe$9CYqbH>`==eiHf?}m3kaP6Q^0#mK7V^sv z)(cKMT-CSAys?u#Tfb83kUVj1#?`kAJ0klPoNN#!!aDA5p#G}I_h-;=51GuuTKT=U zq?ZM=SpOCN8DBnyld&>wO$v%fzmJdt3c>vQS$gNM4_{mIkEh0FIrk1lleMt#$wp>C%sRf0_j zZ-s{FgY{GXpS9pMR&RInR6eCU#J0^!cfNcW=eKz<8mT!vNoQ}D!fBH9)j6}uxGVp% z8s2|1GUwD{PRNv`x}5E)C{>Qk$=+{s2+EJK zD%meD?H}v;U}@#x(Rk=rIX(3tUfpl__KlsQjg2ybC8rDo2@@~lElsT~P1rr_P^_^1 z2K9YuGp@DziLVJ|DB>OinBU`cEhE2&q2v1k>lUHYZII2U)o@z5RbITl((GWoCJnD- z$Gq{Z+ZCzs7GG=(WJlAG+n75#^tMvDqDC}Xhk$w?Z^v)Du0Ynv1gQ$Jy5JNjQ28MQ zrVc!4>@^-jz!kBA#?f`oDi0wdTMX*CN#f?L_bO~Jv)=Rh=6o_*E$trgFr%hi7q?@* zu}(t*&zRw}ICsMBM)RGC?5Kc0_@CHGHK(FpB%IZ7V7TBDHtg5usT#AB-N zRt&je63Cu?N{iss3le4@5lnK;w>IMTx|^V^{q?zRHWt}Lr=GZGei|=*n0nGv$umlF zFJz8UHk#LgJ%7!Zd+t*#b+jsX6c`omB|HFO@XYOk?0DzLRz%;Bj1+8s342RNetnC* zBbX_=Fn~O!z{O~dpf%RgAoB2Qw()Elh|SR29U{zn(3lrN3wd!}1)TMs4rd}4+9-Ap zvU8wB2E6AJ2eTdo$@7MP=iIdJy2*MFE~4DQg2mE?+2XCkO8UaZ+8|qzN)L>=X&-`i z0?$I8sd_@}bP7GlHFZ04v8+5e6D%P|fPxd>n{dzOQ-ocY<_IW#E#Td0&{qf*>t15~ zojWWEVj7Q}KCyPS&C!T6udx~HBmtZ*U9YdsIq1^UiP>rL`X+=RE=1g6sW8%bBs|OA z_4+jpj`@iJvxfnQu6sd`$v0l9*P~`Mw}t2Qh;i6AEd`0p?6Z>0BgW*g$11k00of6F z86AGnhxfwB2j-15Y1+>uga|&Yj)=Y(<(ni&f2Aw?HI1!2PT8}IlGy~S?DDh)!Z4vm z!)CyEy$j14nJE$(Ef(b+A#+CX0UKL~fLPKwCraN?dWlSasRRTxqu|?Fcg6tGINA&v zuINIKuoro;ftKRE5rN*K=h_Qhb6<$X;c3OFsiI%3qRx>8GnoT#N~N+`?_!(tyq+Bbm0?_U>f{OQbIt<9YAoJ=}B(e zT$VE{2KCnQ=->qU}LmZ*-k3%oGk^`rw1tK&B5Eo;sSiI<85K&ih@3f=Rg?WKLIF%p_8bj!8uOPPwR?~0B_8v` z;=^5|Y=!p*KGU2kTZp^9`x_-Nk>XzLGgv5k29IT0Z=AW1Y4!LQm$pOG6d^|z>_vto zu*!k+sE|;o6dH;ow8()GTnH>&3Wr4SyZO4fSkfve(AvA%x!XF?qM-eaUif?#$p|;Z&$N` zLvyBSJ6}7#VY{#6Vz?-}6|3ae*HN`sEx#d}Vb;ve^MUaL^^Isi%ijKY zl*+JQu^VnhPetGTd7I{>hF&j4U%FCG0cvn;G_T!)Mg$( z+5A4-smeTbD3QLtw7aTb3t7t2aGCs#*S)mLdA(;MsZNRRDH)^7sd~4XsbsF&%f@m{GrAnGPX+ip@^Tp z=gRY5VsyzM(EPE_dPRnU(bcyzPt{lsq>O(rWwm?&t=`Qj z{kS*Yk<> ze}2kYhnpFEM4um_m?2Ji{Uxl^wS$R%}d+JqDQ!9*yS_d|BOFK+V?ml6S{M0V$S+<&{CBt}UveJu_ zQWobn-ezqVu$+1Y9xHHZcfs~b4{u{r*jqbj58?C84vT3Wu^{`AiU%zhBwn*8;_o4J zHm2SD+b$$m%WT@p1q$!l`%VjbDR7ND4NLj|qPQvb-P)8-;*b#8xxVo22}AOyTf?IR zhYp3O=O20|JJdowzJ! z{7LT-eBLc+vL<=z)V`MSpr!;{leKJ9w;>+9x=^zhSMK?LbButa9!FW2 z4XkUUL;Qy<5;M+48cu+{yTje-8kctSTxzbkZ@q(0St_jXh!>kY;|#j=EyimIKih|u zjp_YZx~|h50KXaQ_4qU%4{B`*fw8K;eOXhPk}0OobIQ zlT_S8i#=UdSG?YUzL0T?wK+>)cQ7}L79TV4l`hFrW%0wfiLRR!YKhF*&LjdQ+iWm^ zLdf>%ZLf|zBRI#8|J3rN!IwVi?I}0$6SB2Q!#tMbd1F&9-iQF7UZ&ph z&NISk+^P#5-qW4(0|DX&=I-w9mE_EZE>2f|*tG=g$~b@%e?R-&wdR!iaZ9jh>~`jw zSNspM)xu39>qt?)F|7K96_Lajop!=53A45w%Fp*NI2y#>y2RhVe<$|YXgj|AFnHA6 zovO=Lc=)!X-}Q}C1lzGCTqj0Ar)Ap*mSR^rA=zn^8^6?3PT1USz4ME`x`pPlt(u4j zuW5nKEQ9S;^3@P3=-sN8CvwSEEs5uj%xL5|JUMMCXm)PrhY)7an4qzp)>HM|)N2Sy=8h9~ z)mp4V*kbkEhR2$c%p$EylFZ#<)c4u%F?a79#i-p=J~??3?*a+E6{Q{XOWTy!I7UUh zn^x`KFFSgVDDzorg?RRtca{^`vEkpIgQawJ%I>U(J{l$`fD2V6H>n@ut9u3M9NWyf zRY1DRbRWqR*(2jyEF^b?RI32mDaz{iab)M59#RY40Ov%|Gz`wgqZsd}%(H`4V^mdl z^kNQELUY+8pHpyDW9{T4vO5I0_yIE~K<4;;rqldo9ReyIfUR}{SX3pWa6yN_+YfP7 zST)|LY6m0QS*;jVJgY!F`+>OfPz7zz1=E;cE}>OhG;@$yqnN{9MxfcwkT7VgNTu{- zQIg3HTmpU^QoThpPye&9BRG<=nwfTLTDxhgZY|2Zv)W060%(Veq-px zo%2*5xn3B=9P)-9i%ABI**1$A#q>2&sG863@}6__#CK6yS2x!-WSdJe?17BWK2joU z&1R1b0~aS7WGl63^bAmhr<8%H1RRYa0j=+H&ijxhkot2%PsV$iCCIEqV`ke{+?y;B)#pNds-?6uqlxXBahjlVwr>V_X zK%x;(xBW#}LdO)Z>(M{0*0b}P1$gy%!zO>|3E*F=(#erIxr$h$l>lA`P(gKa$oET3 z00*;)($J(%%i4+REt+0ltrA5FY>5xKcSJV8fm0ru%xgEmKR)K@CwH`uoM6HNCa!Td zj1}Ko<5nw)Ag@26p}$FOdN!*?ip;q&y=yvT{H@pv%_#FS(F!rB`5tJ8-gI?TZHM79 zz%m^^9*BAvbfV-WBC}aCf7?NjisD$5EOJ0hJk(+nU}pdsulA`iFvJ2b5>8cI!%s^l z^AkTHCMTZ~x59JVIgBO6zgYMNE6Yi~OzNH4@2tl)4@Jwl8#~8!owtvdy^ZTX6<*>) zO#wDE6vGeYKTj)t-rn2Y*Xx?SH$NIm_*4QC6$OgKzh3=W6=DI(aeXK!M=PzyZ-IuQ z3C2tyQNkBZFbf%)z+?urg|)ye?C4`re(B3*=KL@ymLG|QN%kk%gI3e^$aa|!W8%{jGhDWO*xj=iD9YJsBOASXtxy3fTdjM5=d40c6BVbVe z(D>M&m`Z}XqRiSJW{?j6hpzqTh z&#%0p*?C2Oz^hyPv4*R7L-6jRPU^|(?t$7vrz#2QtZuI?I7rpE#aEnVEKj%eej1$t zdw4PLw{(k>i8&v;pC)en-ow|7oda8+`Y`rY)ymQ3z|_d}{O`E5feTpK#T%^`T&^vC zv-Y8=6uBmAFn<1K6Kn6r{zSg}oh_vJIYHQ$vtKBRUguZIrse)H>z8mIc+ewcI-Lre8Z)wyf7ygx^u*6es@N(Px_e7<9BG+Ogew#cS_W zaMVin;?v!Jw%-iLq#oWQRow_1ZTt4+3iFS_lf!orO zCFGUA7QJK=At@2o&wqbS%hiLzn5(AuKH@OfGt0tt|Db-NVem@rSncX|fq5eruh_B! zE!)($>8i>LQErFKzFJpo~(I6fi2(H9mat=W9dK41r%7 z?iv)ZC%jYQ+EHc_!^}ZebMUB(3!Uly7ONW1YSDXFP|}wy4P9#;p7m0tRo23<`)Q@4 zT{Afj13w^V2P3k&Z?1;){d(U{|6D2YtRwO(RJMEVx>(wt%P6z0xRaMlgNQVH_ODa( z4+t7MoY^D2o@Vo6?6Y?GpQ$vrofr>28(B0!OrdEWa#1g({bD98VL?|~i_H5W#UgP} zC6me{WKvuu3(q83T;gK+68kj!Mj8~(xgc(}6nuhZ3v}&-w7JsVqhjx$`=hnLG%vyl zhp~qODPeJ_8HbDK^#;UWbJ?u^`I+_Y8ayg%pvFabrddWbe)(Gox7j(J$!oS`i~luxBL4aEv0Lon^WHJVyoOAXD@b; z!Z$b-cc!g#ppARdo0jn4%<=h(8Mle(OGw2}M+=9Pp@#}@=4@_yhXu^zvoMHo-Imuw zA%Sab9*M8ZonEBljlBEhXH7g$MfWrX-3We}y1ak1xYcF%=0Ww?0yKNQ^nSrw)~xf; zfGj&fDAmUK+j<@CbvB{J{lm7>l+82A$-8k`6+F?-1W`hUM$sN#L&V!fPOg5oth9_n zFQ{@(;NQ=qBG#By@u zV?H04cX0oZiJk%nJI}e~i=cp+p7R1RvoT*RczjV$O8wS40>8PWIDhg%X^R=kVg0Vs zpAK)d7hn zqYu|oJ{CN?M}T!xYNv{v{GymKuy?z!ezaq!ra9Oy(JuR*ze|3on>2F=+pGGs0ZKv& zN)x@FUlwgf`+bFX(<~=*)U8+u1r`XYgM*}nYcEvt&3+F#2aSC2Rebalt{K!Un1kLF z9jLd7Dc@y?4C=JS`&PWc+T6Z4>+f$^bcMxGFS-K+T*L`IYW&slj=^Q_6-9=}ZR@rg zPgCdJ0<;+awVKhbay{xtf$1z}_Q8|8B`Km&sGy_8FF5j5`pc_SZBmOTJ>Qpl=UUy5 z6cg#~w0HJtqc}Y0HsIpj=&Ddt`+jFNAf)nXjBrj+FN=5s6aL7)@$}zuUAJQ;4UMA1`9tf-g_A-9P>;y^H4P0 zyxk1-g`piR^drS3)?eq4R?Cg?9u9%B$~A4W6Ksq|X8KRY4<4uf!P(K8SB*ziU)F?qowv z!S85h6gz87r<%&2%f1g&9h;-|lr8`Vdxe;P1F^Gin$jJrF;>sfXz^AIswk?z(9kz$ z-efS337{N`7R$ykCa~`}-g(Mqq!gFUc3Z`8wrY+BzZ~?+K3`2v=^elk7as<2G)(4H zXSarYH(x%*u66cti1ODGryNE8!o9`TaAnEO$P*0JP*%bC$#16C&kX2P1yqM<#jLBW zpR?c1r6^!CXo*tN(CrrrO?j?%3g)Z~q0G+#3*q(*53j4V8} zGRUm%#aR8CX3a!ttWF1@P`@K*0xMN-$Ib%Og>bm}C7LL>U5SOx{42uPMe;2Mqq8!4 zysgfbBK(GoRaf`z$fK_vm?U^;DJ`$0>sarUuNXp3WG zx>hTNLrgwM@a|R^>`oJ0~1<`swlD3TCQ=sOd=yf2&-3;E|uXAX`uY467tD1Ud@zF04vHF~_ z)3^2M&38WM(CfuC89Ozs`_NUyq{FCwaMRx6{M_PvmKeIn=8SBObC-pi8=pb&{shv0 zuM=}$K)ZYo$$IOC@ZK*)_fo^(ezp%}K5;pVbcNFzF{J*=QQq0DmRd&>6^)F3b-o93X zuqgeq9&Gl#zT=0b@$1_)0gC9x)cLTZX_d0C3dujJoE8z^9_1vRXKRkCCAeDpWKOOG zHa0xcKM>T?#;0%dZCymZsm+)qA@!Q_Bf&sH^><|0_PPGae$(`?d6~ zk^#r6S?%(h^t{dswsaTHTXZx@I=#J|n-c_K%<#3k;9t32_^8x@o;)c=sF5D`<`LdG z(`<>)!fjtjBYb6SP?W-F^8`~~ML?$cB5>{K8`Gv|e}Y4|~)FUltn+MeDZJ$WV%BGct@X~v2n zy0EX{$%8$;XYb~Rp3W81bHp^o-VtZNZ1h`ZP_EGT24CIBkNe_mlKtP(?e z-^*$etP}<+6a`u)YItSmjA`8K)+oKy$EBY2b?!uJy8|3L*%YvRtPsOK*I)AUy0O8*-`ar_T)joqGU}_TA@vS?5=UiYL$XLEPld zyMB{f)!dD%ucW#>KsdbYR})~ebmQlP$*!_{&*VV@rR~9wi?99zA9<`L4 zdC!y0l~euXG2vac|7vfB-7{}j( zE@e&fS1n#hYb<0iR<;E+)M?#RFSoRO-w%xhtLo}lW>pd6Y5n&S-L3bl=Th+mA;p?&>n9}Tmq;&M*b77_qg47zt z8GOQ41#gFd4J|`Hd(ONOcS1!LWrx5w;po6H9eyzggZ5K?$c}Dq#8C92d8}YFoJQht z{K-3+>g86+U=Nh(mTkeS~PG$jF=aSKI}iQ24-!i$q6%@OX6fR zWL(k$(Ckmt>|kjJNAq?B6YjclaC*4oqj;hZrxSALXy(!ya^G*{|%Ko*EOILA+5-Z8nxQl@n<4Kc%!^Ql_y#+iI)@p#^8bj9A|mqF;|B zXjy-XxX}e3p+K6`zVJ}7)8SSBU1$f~q%Uh3)td_kdc6oxp$FYkXB85;jLpHjsNHRB z*G~bl8))e6wn+wb3X1r*XxD$(F~NOc1E8- z)ekNkb5}fOWiv41>Y|IrtD?`V-C;>Od0GSbtN|wRIJ-Au@=Wfz)4=t*X*Byb$lj0= zU}b2h%>RzfjG_t!F1BB!MdyUjiWOegDI8ChP$|S*m(U3_7k!5H0`AKzsnA@GPP`KTIA zwXU{h=^enL2iiu1Hoglc(r?W(6Eu1BO_m_JiN^pUf$FE?^ihQAz>4S4}_5dX;C(~?$QDv$I=tfP#-flm7U{6$5b+5KdW z=1c@u@QYn8r6wht;k(&;Hgvg+T6nzNr*B7JS3M5g^>0*cyIg#XOxd7LK4k!s-fxo-n;Ko@(x)yNN-e^e4OPDsH zJ?HBQcxhU&|3cIlsps^NF1hCsf^N79| zQUgsK8db~Mcq|UZ!fTgXDAg!9k6DRFM8a^mTD5jc0T2ZOhOWKQb=*QC5Vf(rl#LV| zP#kbV{iluyBpi){6Rh7+3gh9}zz`^gC`IrvEP}{sfR0fxVy#dx9P$qh{!#!1haTTB9RK`{20%j-TZw|h zNDu;O*kddI1tkg&N01DHL?MYSLLm__;<-ivq9imV5>D(VC?pd52OmLnnDPuBaI8OQ z|1l1UCYdf220)$IU<{OWTnvoFcK|N|?n;Qj!odHE#D9Z;L69nqLE?yf0trK7VI)Xn zPzcgN0I&V`zT-}G5;fS(P%iyEMYJtQH8?b;6&~L42&X`_=4iNm9?aN_6#WD#%@w6KW(pat0fj{{?oe}>vIGJr7fx%a;z zM4+%p6baN=6q*PbKo&-dDi#g=928Fq7hoQdB?uG_Mml#mIFbk%Bn*YYkVGsFPVB%ye~AC0h5uVaKp2f7avFdU zNop|;MeGZJETA=sbtqE!aTvtE938+P5GDyRU|`IjxdK2Em?j*MI{!TgAdA5LIiLUK z!xBS{hQf&R$FVFFPwbfhBlce!0s{k|?V(Bh<2becTN!{42_uFd4MjnT_<(_7|Azwp zZwCPwNfsXqPR ziNy#gsWJ#)Atgo&0rZC_A!3k3bBsVEa70=IN+aPUc^-`fCX~28BnC@@APV|-6^8$B zxrRUkYaNM(C^V@hDAK|P$jWdMSu~1djX(Adg01yTOp14C`g(evUhaySKXdJ08V2-1Qs6SvO z|0k#5|5Gg^Fi;@TlQ7~?#Eyx9!BNE75d#D2F=AODib)0rB9_=c@E9PAl5_~iV2ENC zD5Ie$QW}CdeFJ0^e=`2LFZs|K$K+`NP3T7*T**6I%!5dEzL+ph-gv zgU0;>^?#AZ;$XOckiq}8Spm#I6Ne5G$e4dtD#s}ppkawiEO z2kieFemDX~?EOff`XkPS01ZjvT=3&%jMzE^hB!O{*?${%j6bkbfsvHU$7zAYVkDBJ z4uAvBO3DWml*Gyaiw;rl2bM56o_LuBh)9xR6b_VTL^%N9!;;c~@6Jg0(EnrV&`8XG zBI1ww57-cqgbr{Zfgynv10|gj44gRYA>qJ(@Fejq4EoOvcTaCG2jRUkc$7|lRh2{I65LtbO;1cu>ZsOUp|5{02&C`c)|%k z=O~q}RgtPH$}pTd7Nw!At_;IKRe^O3rvmKG5$YN^6_f(M-2a!wk{|e%(%Z+z%O}9g U-hmbJu%t%!)ap$6^$10Yvapa1{> diff --git a/Doc/RomWBW Disk Catalog.pdf b/Doc/RomWBW Disk Catalog.pdf index 5853df285d8d123146dd46b31f3eb6a7a7b2c1de..c5255721f4b15c8e09e9fcab555d2a9a2f971b42 100644 GIT binary patch delta 510 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 diff --git a/ReadMe.md b/ReadMe.md index 979af801..7d626167 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -3,7 +3,7 @@ author: "Wayne Warthen (mailto:wwarthen@gmail.com)" classoption: - oneside colorlinks: true -date: 26 Jan 2022 +date: 01 Feb 2022 documentclass: book fontfamily: helvet fontsize: 12pt @@ -44,7 +44,7 @@ toc-depth: 1 ## Z80/Z180 System Software Version 3.1 Pre-release -26 Jan 2022 +01 Feb 2022 Wayne Warthen diff --git a/ReadMe.txt b/ReadMe.txt index ca05cffe..b94fb4d5 100644 --- a/ReadMe.txt +++ b/ReadMe.txt @@ -1,6 +1,6 @@ RomWBW Getting Started Wayne Warthen (mailto:wwarthen@gmail.com) -26 Jan 2022 +01 Feb 2022 @@ -17,7 +17,7 @@ RomWBW Z80/Z180 System Software Version 3.1 Pre-release -26 Jan 2022 +01 Feb 2022 Wayne Warthen wwarthen@gmail.com diff --git a/Source/Apps/Build.cmd b/Source/Apps/Build.cmd index 0e27703a..cbcf8a01 100644 --- a/Source/Apps/Build.cmd +++ b/Source/Apps/Build.cmd @@ -35,6 +35,7 @@ pushd ZMP && call Build || exit /b & popd pushd ZMD && call Build || exit /b & popd pushd Dev && call Build || exit /b & popd pushd VGM && call Build || exit /b & popd +pushd cpuspd && call Build || exit /b & popd copy *.com %APPBIN%\ || exit /b diff --git a/Source/Apps/Clean.cmd b/Source/Apps/Clean.cmd index 0ee31190..198f461d 100644 --- a/Source/Apps/Clean.cmd +++ b/Source/Apps/Clean.cmd @@ -16,3 +16,4 @@ pushd ZMP && call Clean || exit /b 1 & popd pushd ZMD && call Clean || exit /b 1 & popd pushd Dev && call Clean || exit /b 1 & popd pushd VGM && call Clean || exit /b 1 & popd +pushd cpuspd && call Clean || exit /b 1 & popd diff --git a/Source/Apps/Makefile b/Source/Apps/Makefile index 51060be0..96d2411c 100644 --- a/Source/Apps/Makefile +++ b/Source/Apps/Makefile @@ -1,7 +1,7 @@ OBJECTS = sysgen.com survey.com \ syscopy.com assign.com format.com talk.com mode.com rtc.com \ timer.com rtchb.com -SUBDIRS = XM FDU FAT Tune Test ZMP ZMD Dev VGM +SUBDIRS = XM FDU FAT Tune Test ZMP ZMD Dev VGM cpuspd DEST = ../../Binary/Apps TOOLS =../../Tools diff --git a/Source/Apps/Test/Build.cmd b/Source/Apps/Test/Build.cmd index f8e126d4..fb322d6b 100644 --- a/Source/Apps/Test/Build.cmd +++ b/Source/Apps/Test/Build.cmd @@ -22,7 +22,6 @@ pushd rzsz && call Build || exit /b & popd pushd vdctest && call Build || exit /b & popd pushd kbdtest && call Build || exit /b & popd pushd ps2info && call Build || exit /b & popd -pushd cpuspd && call Build || exit /b & popd goto :eof diff --git a/Source/Apps/Test/Clean.cmd b/Source/Apps/Test/Clean.cmd index 7cedf243..9e1f36d9 100644 --- a/Source/Apps/Test/Clean.cmd +++ b/Source/Apps/Test/Clean.cmd @@ -17,4 +17,3 @@ pushd rzsz && call Clean || exit /b 1 & popd pushd vdctest && call Clean || exit /b 1 & popd pushd kbdtest && call Clean || exit /b 1 & popd pushd ps2info && call Clean || exit /b 1 & popd -pushd cpuspd && call Clean || exit /b 1 & popd diff --git a/Source/Apps/Test/Makefile b/Source/Apps/Test/Makefile index db9b6b34..aed32df2 100644 --- a/Source/Apps/Test/Makefile +++ b/Source/Apps/Test/Makefile @@ -1,5 +1,5 @@ OBJECTS = -SUBDIRS = DMAmon I2C inttest ppidetst ramtest tstdskng rzsz vdctest kbdtest ps2info cpuspd +SUBDIRS = DMAmon I2C inttest ppidetst ramtest tstdskng rzsz vdctest kbdtest ps2info DEST = ../../../Binary/Apps/Test TOOLS =../../../Tools diff --git a/Source/Apps/Test/cpuspd/Makefile b/Source/Apps/Test/cpuspd/Makefile deleted file mode 100644 index aedcb761..00000000 --- a/Source/Apps/Test/cpuspd/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -OBJECTS = cpuspd.com -DEST = ../../../../Binary/Apps/Test -TOOLS =../../../../Tools - -USETASM=1 - -include $(TOOLS)/Makefile.inc \ No newline at end of file diff --git a/Source/Apps/Test/cpuspd/Build.cmd b/Source/Apps/cpuspd/Build.cmd similarity index 71% rename from Source/Apps/Test/cpuspd/Build.cmd rename to Source/Apps/cpuspd/Build.cmd index c99af191..19b3439e 100644 --- a/Source/Apps/Test/cpuspd/Build.cmd +++ b/Source/Apps/cpuspd/Build.cmd @@ -7,4 +7,4 @@ set TASMTABS=%TOOLS%\tasm32 tasm -t180 -g3 -fFF cpuspd.asm cpuspd.com cpuspd.lst || exit /b -copy /Y cpuspd.com ..\..\..\..\Binary\Apps\Test\ || exit /b +copy /Y cpuspd.com ..\..\..\Binary\Apps\ || exit /b diff --git a/Source/Apps/Test/cpuspd/Clean.cmd b/Source/Apps/cpuspd/Clean.cmd similarity index 100% rename from Source/Apps/Test/cpuspd/Clean.cmd rename to Source/Apps/cpuspd/Clean.cmd diff --git a/Source/Apps/cpuspd/Makefile b/Source/Apps/cpuspd/Makefile new file mode 100644 index 00000000..c8025816 --- /dev/null +++ b/Source/Apps/cpuspd/Makefile @@ -0,0 +1,7 @@ +OBJECTS = cpuspd.com +DEST = ../../../Binary/Apps +TOOLS =../../../Tools + +USETASM=1 + +include $(TOOLS)/Makefile.inc \ No newline at end of file diff --git a/Source/Apps/Test/cpuspd/cpuspd.asm b/Source/Apps/cpuspd/cpuspd.asm similarity index 51% rename from Source/Apps/Test/cpuspd/cpuspd.asm rename to Source/Apps/cpuspd/cpuspd.asm index 71a22684..0aecb7f8 100644 --- a/Source/Apps/Test/cpuspd/cpuspd.asm +++ b/Source/Apps/cpuspd/cpuspd.asm @@ -8,12 +8,14 @@ ; ;======================================================================= ; -#include "../../../HBIOS/hbios.inc" +#include "../../HBIOS/hbios.inc" ; ; General operational equates (should not requre adjustment) ; stksiz .equ $40 ; Working stack size ; +cpumhz .equ 30 ; for time delay calculations (not critical) +; rtc_port .equ $70 ; RTC latch port adr ; restart .equ $0000 ; CP/M restart vector @@ -46,21 +48,64 @@ exit: ;======================================================================= ; main: -; -; Get HBIOS platform ID -; - ; Use first char of FCB for speed selection - ld a,($5D) - cp ' ' - jr z,show_spd - and $5F ; make upper case - cp 'D' ; double - jr z,set_dbl - cp 'F' ; full - jr z,set_full - cp 'H' ; half + ; skip to start of first parm + ld ix,$81 ; point to start of parm area (past len byte) + call nonblank ; skip to next non-blank char + jp z,show_spd ; no parms, show current settings +; +main1: + ; process options (if any) + cp '/' ; option prefix? + jr nz,main2 ; not an option, continue + call option ; process option + ret nz ; some options mean we are done (e.g., "/?") + inc ix ; skip option character + call nonblank ; skip whitespace + jr main1 ; continue option checking +; +main2: + ; parse speed string (half, full, double) + call getalpha ; extract speed ("HALF", "FULL", "DOUBLE") +; + call nonblank ; skip whitespace + jp z,set_spd ; if nothing else, set new speed + cp ',' ; parm separator + jp nz,err_parm ; invalid format, show usage and abort + inc ix ; pass separator + call nonblank ; skip whitespace + jp z,set_spd ; if nothing else, set new speed + call isnum ; start of parm? + jr c,main3 ; nope, try skipping this parm + call getnum ; get memory wait states + jp c,err_parm ; if overflow, show usage and abort + ld (ws_mem),a ; save memory wait states +; +main3: + call nonblank ; skip whitespace + jp z,set_spd ; if nothing else, set new speed + cp ',' ; parm separator + jp nz,err_parm ; invalid format, show usage and abort + inc ix ; pass separator + call nonblank ; skip whitespace + jp z,set_spd ; if nothing else, set new speed + call getnum ; get I/O wait states + jp c,err_parm ; if overflow, show usage and abort + ld (ws_io),a ; save memory wait states +; + call nonblank ; skip whitespace + jp nz,err_parm ; invalid format, show usage and abort + ; +; +set_spd: + ld a,(tmpstr) + cp 'H' jr z,set_half - jr usage + cp 'F' + jr z,set_full + cp 'D' + jr z,set_dbl + jp err_parm + ret ; set_half: ld l,0 @@ -75,8 +120,13 @@ set_dbl: jr new_spd ; new_spd: + call delay ld b,BF_SYSSET ld c,BF_SYSSET_CPUSPD + ld a,(ws_mem) + ld d,a + ld a,(ws_io) + ld e,a rst 08 jp nz,err_not_sup call show_spd @@ -129,6 +179,16 @@ show_spd2: show_spd3: ret ; +; Handle special options +; +option: +; + inc ix ; next char + ld a,(ix) ; get it + cp '?' ; is it a '?' as expected? + jp z,usage ; yes, display usage + jp err_parm ; anything else is an error + usage: call crlf2 ld de,str_usage @@ -138,6 +198,9 @@ usage: ; ; Error Handlers ; +err_parm: + ld de,str_err_parm + jr err_ret err_not_sup: ld de,str_err_not_sup jr err_ret @@ -327,6 +390,99 @@ prtdec2: call prtchr ret ; +; Get the next non-blank character from (HL). +; +nonblank: + ld a,(ix) ; load next character + or a ; string ends with a null + ret z ; if null, return pointing to null + cp ' ' ; check for blank + ret nz ; return if not blank + inc ix ; if blank, increment character pointer + jr nonblank ; and loop +; +; Get alpha chars and save in tmpstr +; Length of string returned in A +; +getalpha: +; + ld hl,tmpstr ; location to save chars + ld b,8 ; length counter (tmpstr max chars) + ld c,0 ; init character counter +; +getalpha1: + ld a,(ix) ; get active char + call ucase ; lower case -> uppper case, if needed + cp 'A' ; check for start of alpha range + jr c,getalpha2 ; not alpha, get out + cp 'Z' + 1 ; check for end of alpha range + jr nc,getalpha2 ; not alpha, get out + ; handle alpha char + ld (hl),a ; save it + inc c ; bump char count + inc hl ; inc string pointer + inc ix ; increment buffer ptr + djnz getalpha1 ; if space, loop for more chars +; +getalpha2: ; non-alpha, clean up and return + ld (hl),0 ; terminate string + ld a,c ; string length to A + or a ; set flags + ret ; and return +; +; Determine if byte in A is a numeric '0'-'9' +; Return with CF clear if it is numeric +; +isnum: + cp '0' + jr c,isnum1 ; too low + cp '9' + 1 + jr nc,isnum1 ; too high + or a ; clear CF + ret +isnum1: + or a ; clear CF + ccf ; set CF + ret + +; +; Get numeric chars and convert to number returned in A +; Carry flag set on overflow +; +getnum: + ld c,0 ; C is working register +getnum1: + ld a,(ix) ; get the active char + cp '0' ; compare to ascii '0' + jr c,getnum2 ; abort if below + cp '9' + 1 ; compare to ascii '9' + jr nc,getnum2 ; abort if above +; + ; valid digit, add new digit to C + ld a,c ; get working value to A + rlca ; multiply by 10 + ret c ; overflow, return with carry set + rlca ; ... + ret c ; overflow, return with carry set + add a,c ; ... + ret c ; overflow, return with carry set + rlca ; ... + ret c ; overflow, return with carry set + ld c,a ; back to C + ld a,(ix) ; get new digit + sub '0' ; make binary + add a,c ; add in working value + ret c ; overflow, return with carry set + ld c,a ; back to C +; + inc ix ; bump to next char + jr getnum1 ; loop +; +getnum2: ; return result + ld a,c ; return result in A + or a ; with flags set, CF is cleared + ret +; ; Start a new line ; crlf2: @@ -340,6 +496,16 @@ crlf: pop af ; restore AF ret ; +; Convert character in A to uppercase +; +ucase: + cp 'a' ; if below 'a' + ret c ; ... do nothing and return + cp 'z' + 1 ; if above 'z' + ret nc ; ... do nothing and return + res 5,a ; clear bit 5 to make lower case -> upper case + ret ; and return +; ; Add hl,a ; ; A register is destroyed! @@ -351,21 +517,41 @@ addhla: inc h ret ; +; Delay ~10ms +; +delay: + push af + push de + ld de,625 ; 10000us/16us +delay0: + ld a,cpumhz - 2 +delay1: + dec a + jr nz,delay1 + dec de + ld a,d + or e + jp nz,delay0 + pop de + pop af + ret +; ; ;======================================================================= ; Constants ;======================================================================= ; -str_banner .db "RomWBW CPU Speed Selector v0.2, 26-Jan-2022",0 +str_banner .db "RomWBW CPU Speed Selector v0.4, 31-Jan-2022",0 str_spacer .db " ",0 str_slow .db " CPU speed is HALF",0 str_full .db " CPU speed is FULL",0 str_dbl .db " CPU speed is DOUBLE",0 str_memws .db " Memory Wait State(s)",0 str_iows .db " I/O Wait State(s)",0 +str_err_parm .db " Parameter error (CPUSPD /? for usage)",0 str_err_not_sup .db " ERROR: Platform or configuration not supported!",0 str_err_invalid .db " ERROR: Invalid configuration!",0 -str_usage .db " Usage: CPUSPD [Half|Full|Double]",0 +str_usage .db " Usage: CPUSPD [(Half|Full|Double)[,[,]]]",0 ; ;======================================================================= ; Working data @@ -374,6 +560,13 @@ str_usage .db " Usage: CPUSPD [Half|Full|Double]",0 stksav .dw 0 ; stack pointer saved at start .fill stksiz,0 ; stack stack .equ $ ; stack top +; +; +tmpstr .fill 9,0 ; temp string (8 chars, 0 term) +ws_mem .db $FF ; memory wait states +ws_io .db $FF ; I/O wait states + + ; ;======================================================================= ; diff --git a/Source/Doc/Applications.md b/Source/Doc/Applications.md index 4a2d6a2e..c4680d04 100644 --- a/Source/Doc/Applications.md +++ b/Source/Doc/Applications.md @@ -47,7 +47,8 @@ found: | TALK | Yes | Yes | Yes | | RTC | Yes | Yes | Yes | | TIMER | Yes | Yes | Yes | -| INTTEST | Yes | Yes | Yes | +| CPUSPD | Yes | Yes | Yes | +| INTTEST | No | Yes | Yes | | FAT | No | Yes | Yes | | TUNE | No | Yes | Yes | @@ -955,3 +956,70 @@ player code is from MYMPLAY 0.4 by Lieves!Tuore and the PT player code is (c)2004-2007 S.V.Bulba . The source code is provided in the RomWBW distribution. + +# CPUSPD + +The `CPUSPD` application is used to change the running speed and wait +states of a RomWBW system. + + The functionality is highly dependent on +the capabilities of your system. + +At present, all Z180 systems can change their CPU speed and their +wait states. SBC and MBC systems may be able to change their CPU +speed if the hardware supports it and it is enabled in the HBIOS +configuration. + +## Syntax + +| `CPUSPD [`*``*`[,[`*``*`][,[`*``*`]]]` + +*``* is one of HALF, FULL, or DOUBLE. +*``* is a number specifying the desired memory wait states. +*``* is a number specifying the desired I/O wait states. + +## Usage + +Entering `CPUSPD` with no parameters will display the current CPU speed +and wait state information of the running system. Wait state +information is not available for all systems. + +To modify the running speed of a system, you can specify the +`*``*` parameter. To modify either or both of the wait +states, you can enter the desired number. Either or both of the wait +state parameters may be omitted and the current wait state settings +will remain in effect. + +## Notes + +The ability to modify the running speed and wait states of a system +varies widely depending on the hardware capabilities and the HBIOS +configuration settings. + +Note that it is frequently impossible to tell if a system is capable +of dynamic speed changes. This function makes the changes blindly. +If an attempt is made to change the speed of a system +that is definitely incapable of doing so, then an error result is +returned. + +The `CPUSPD` command makes no attempt to ensure that the new CPU +speed will actually work on the current hardware. Setting a CPU +speed that exceeds the capabilities of the system will result in +unstable operation or a system stall. + +Some peripherals are dependant on the CPU speed. For example, the Z180 +ASCI baud rate and system timer are derived from the CPU speed. The +CPUSPD applicastion will attempt to adjust these peripherals for +correct operation after modifying the CPU speed. However, in some +cases this may not be possible. The baud rate of ASCI ports have a +limited set of divisors. If there is no satisfactory divisor to +retain the existing baud rate under the new CPU speed, then the baud +rate of the ASCI port(s) will be affected. + +## Etymology + +The `CPUSPD` application was custom written for RomWBW. All of the +hardware interface code is specific to RomWBW and the application will +not operate correctly on non-RomWBW systems. + +The source code is provided in the RomWBW distribution. diff --git a/Source/Doc/Architecture.md b/Source/Doc/Architecture.md index a761c02d..6d542843 100644 --- a/Source/Doc/Architecture.md +++ b/Source/Doc/Architecture.md @@ -2034,10 +2034,18 @@ This function will modify the running CPU speed attributes of a system. Note that it is frequently impossible to tell if a system is capable of dynamic speed changes. This function makes the changes blindly. You can specify 0xFF for either of the wait state settings to have them -left alone. - -In the case of the Z180, the SIO port buad rate is derived from the CPU -speed. So, when the speed is changed the baud rate will change. +left alone. If an attempt is made to change the speed of a system +that is definitely incapable of doing so, then an error result is +returned. + +Some peripherals are dependant on the CPU speed. For example, the Z180 +ASCI baud rate and system timer are derived from the CPU speed. The +Set CPU Speed function will attempt to adjust these peripherals for +correct operation after modifying the CPU speed. However, in some +cases this may not be possible. The baud rate of ASCI ports have a +limited set of divisors. If there is no satisfactory divisor to +retain the existing baud rate under the new CPU speed, then the baud +rate of the ASCI port(s) will be affected. ### Function 0xFA -- System Peek (SYSPEEK) diff --git a/Source/Doc/GettingStarted.md b/Source/Doc/GettingStarted.md index 1c31f15b..899b8c34 100644 --- a/Source/Doc/GettingStarted.md +++ b/Source/Doc/GettingStarted.md @@ -424,7 +424,7 @@ therefore, globally available. | TALK | Direct console I/O to a specified character device. | | RTC | Manage and test the Real Time Clock hardware. | | TIMER | Display value of running periodic system timer. | -| INTTEST | Test interrupt vector hooking. | +| CPUSPD | Change the running CPU speed and wait states of the system. | Some custom applications do not fit on the ROM disk. They are found on the disk image files or the individual files can be found in the Binary\\Apps @@ -434,6 +434,7 @@ directory of the distribution. | ----------- | -------------------------------------------------------------- | | TUNE | Play .PT2, .PT3, .MYM audio files. | | FAT | Access MS-DOS FAT filesystems from RomWBW (based on FatFs). | +| INTTEST | Test interrupt vector hooking. | Additional documentation on all of these applications can be found in "RomWBW Applications.pdf" in the Doc directory of the distribution. diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index 18f9a886..5e6cfe42 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -70,8 +70,6 @@ ; #DEFINE HBIOS ; -;;;#DEFINE TESTING -; ; MAKE SURE EXACTLY ONE OF ROMBOOT, APPBOOT, IMGBOOT IS DEFINED. ; MODCNT .EQU 0 @@ -188,19 +186,11 @@ RTCDEF .SET RTCDEF | %00000001 ; SC128 I2C SCL BIT #ENDIF ; #IF ((CPUSPDCAP==SPD_HILO) & (PLATFORM==PLT_MBC)) - #IF (CPUSPDDEF==SPD_HIGH) -RTCDEF .SET RTCDEF | %00001000 ; DEFAULT SPEED HIGH - #ELSE -RTCDEF .SET RTCDEF & ~%00001000 ; DEFAULT SPEED LOW - #ENDIF +RTCDEF .SET RTCDEF & ~%00001000 ; INITIAL SPEED LOW #ENDIF ; #IF ((CPUSPDCAP==SPD_HILO) & (PLATFORM==PLT_SBC)) - #IF (CPUSPDDEF==SPD_HIGH) -RTCDEF .SET RTCDEF & ~%00001000 ; DEFAULT SPEED HIGH - #ELSE -RTCDEF .SET RTCDEF | %00001000 ; DEFAULT SPEED LOW - #ENDIF +RTCDEF .SET RTCDEF | %00001000 ; INITIAL SPEED LOW #ENDIF ; ; @@ -1775,56 +1765,119 @@ HB_CPU1: OUT ($6D),A ; IMPLEMENT IT ; #ENDIF +; + DIAG(%00011111) +; +; INIT OSCILLATOR SPEED FROM CONFIG +; + LD HL,CPUOSC / 1000 + LD (HB_CPUOSC),HL +; +; ATTEMPT DYNAMIC CPU SPEED DERIVATION +; NOTE THAT FOR PLATFORMS WITH SOFTWARE SELECTABLE CPU SPEED, +; THIS IS BEING DONE WITH THE CPU SPEED SET TO THE LOWEST +; POSSIBLE SETTING. THE FINAL CPU SPEED WILL BE ADJUSTED +; LATER. +; + CALL HB_CPUSPD ; CPU SPEED DETECTION + JR NZ,HB_CPUSPD2 ; SKIP IF FAILED +; +; RECORD THE UPDATED CPU OSCILLATOR SPEED +; +#IF ((CPUFAM == CPU_Z180) | (CPUSPDCAP == SPD_HILO)) + ; SPEED MEASURED WILL BE HALF OSCILLATOR SPEED + ; SO RECORD DOUBLE THE MEASURED VALUE + SLA L + RL H + LD (HB_CPUOSC),HL +#ENDIF +; +HB_CPUSPD2: +; +; INIT CPUKHZ BASED ON OSCILLATOR SPEED +; + LD HL,(HB_CPUOSC) +; +; TRANSITION TO FINAL DESIRED CPU SPEED FOR THOSE PLATFORMS +; THAT SUPPORT SOFTWARE SELECTABLE CPU SPEED. UPDATE CB_CPUKHZ +; IN HCB AS WE DO THIS. +; +#IF ((CPUSPDCAP==SPD_HILO) & (PLATFORM==PLT_MBC) & (CPUSPDDEF==SPD_HIGH)) + ; SET HIGH SPEED VIA RTC LATCH + LD A,(HB_RTCVAL) + OR %00001000 ; SET HI SPEED BIT + LD (HB_RTCVAL),A ; SAVE SHADOW + OUT (RTCIO),A ; IMPLEMENT + ; HL IS ALREADY CORRECT FOR FULL SPEED OPERATION +#ELSE + ; ADJUST HL TO REFLECT HALF SPEED OPERATION + SRL H ; ADJUST HL ASSUMING + RR L ; HALF SPEED OPERATION +#ENDIF +; +#IF ((CPUSPDCAP==SPD_HILO) & (PLATFORM==PLT_SBC) & (CPUSPDDEF==SPD_HIGH)) + ; SET HIGH SPEED VIA RTC LATCH + LD A,(HB_RTCVAL) + AND ~%00001000 ; CLEAR HI SPEED BIT + LD (HB_RTCVAL),A ; SAVE SHADOW + OUT (RTCIO),A ; IMPLEMENT + ; HL IS ALREADY CORRECT FOR FULL SPEED OPERATION +#ELSE + ; ADJUST HL TO REFLECT HALF SPEED OPERATION + SRL H ; ADJUST HL ASSUMING + RR L ; HALF SPEED OPERATION +#ENDIF ; #IF (CPUFAM == CPU_Z180) ; - ; AT BOOT, Z180 PHI IS OSC / 2 - LD C,(CPUOSC / 2) / 1000000 - LD DE,(CPUOSC / 2) / 1000 + LD HL,(HB_CPUOSC) ; INIT HL TO CPU OSC FREQ (KHZ) ; - #IF (Z180_CLKDIV >= 1) + #IF (Z180_CLKDIV == 0) + ; ADJUST HL TO REFLECT HALF SPEED OPERATION + SRL H ; ADJUST HL ASSUMING + RR L ; HALF SPEED OPERATION + #ENDIF +; + #IF (Z180_CLKDIV == 1) LD A,(HB_CPUTYPE) ; GET CPU TYPE CP 2 ; Z8S180 REV K OR BETTER? - JR C,HB_CPU2 ; IF NOT, NOT POSSIBLE! + JR C,HB_CPU3 ; IF NOT, NOT POSSIBLE! ; SET CLOCK DIVIDE TO 1 RESULTING IN FULL XTAL SPEED LD A,$80 OUT0 (Z180_CCR),A - ; REFLECT SPEED CHANGE - LD C,CPUOSC / 1000000 - LD DE,CPUOSC / 1000 + ; HL ALREADY REFLECTS FULL SPEED OPERATION #ENDIF - +; #IF (Z180_CLKDIV >= 2) LD A,(HB_CPUTYPE) ; GET CPU TYPE CP 3 ; Z8S180 REV N OR BETTER? - JR C,HB_CPU2 ; IF NOT, NOT POSSIBLE! + JR C,HB_CPU3 ; IF NOT, NOT POSSIBLE! ; SET CPU MULTIPLIER TO 1 RESULTING IN XTAL * 2 SPEED ; ALSO SET CCR AGAIN BECAUSE OF REPORTS THAT CCR ; *MUST* BE SET AFTER CMR. LD A,$80 OUT0 (Z180_CMR),A ; CPU MULTIPLIER OUT0 (Z180_CCR),A ; CLOCK DIVIDE - ; REFLECT SPEED CHANGE - LD C,(CPUOSC * 2) / 1000000 - LD DE,(CPUOSC * 2) / 1000 + ; ADJUST HL TO REFLECT DOUBLE SPEED OPERATION + SLA L + RL H #ENDIF ; -HB_CPU2: - ; SAVE CPU SPEED IN CONFIG BLOCK - LD A,C - LD (CB_CPUMHZ),A - LD (CB_CPUKHZ),DE -; +HB_CPU3: #ENDIF ; - DIAG(%00011111) -; -; PERFORM DYNAMIC CPU SPEED DERIVATION +; HL SHOULD NOW HAVE FINAL CPU RUNNING SPEED IN KHZ. +; UPDATE CB_CPUMHZ/CB_CPUKHZ WITH THIS VALUE. ; - CALL HB_CPUSPD ; CPU SPEED DETECTION -; - LD A,(CB_CPUMHZ) ; CPU SPEED TO ACCUM AND INIT - CALL DELAY_INIT ; .. SPEED COMPENSATED DELAY + LD (CB_CPUKHZ),HL ; UPDATE CPUKHZ + LD DE,1000 ; SET UP TO DIV BY 1000 FOR MHZ + CALL DIV16 ; BC=CPU MHZ, HL=REMAINDER + LD DE,500 ; SET UP TO ROUND UP + XOR A ; IF WITHIN 500 KHZ + SBC HL,DE ; REMAINDER - 500 + CCF ; COMPLEMENT CF + ADC A,C ; C -> A; ADD CF FOR ROUNDING + LD (CB_CPUMHZ),A ; SAVE IT ; #IF (CPUFAM == CPU_Z180) ; @@ -1855,6 +1908,9 @@ HB_CPU2: LDCTL (C),HL ; #ENDIF +; + LD A,(CB_CPUMHZ) ; CPU SPEED TO ACCUM AND INIT + CALL DELAY_INIT ; .. SPEED COMPENSATED DELAY ; #IF (INTMODE == 2) ; SETUP Z80 IVT AND INT MODE 2 @@ -1931,6 +1987,8 @@ HB_CPU2: ; NOW IF DIVIDE BOTH SIDES BY 1000, WE CAN USE ; CPUKHZ VALUE AND SIMPLIFY TO ; RLDR = CPUKHZ + XOR A ; ALL BITS ZERO + OUT0 (Z180_TCR),A ; ... INHIBITS TIMER OPERATION LD HL,(CB_CPUKHZ) ; 50HZ = 18432000 / 20 / 50 / X, SO X = CPU KHZ OUT0 (Z180_TMDR0L),L ; INITIALIZE TIMER 0 DATA REGISTER OUT0 (Z180_TMDR0H),H @@ -1997,6 +2055,7 @@ Z280_TC .EQU CPUOSC / 4 / 50 / 2 ; TIME CONSTANT CALL FILL ; DO IT ; DIAG(%00111111) +; #IF FALSE ; ; TEST DEBUG *************************************************************************************** @@ -2025,8 +2084,6 @@ NOT_REC_M0: CALL CALLLIST ; PROCESS THE PRE-INIT CALL TABLE ; #IF (DSKYENABLE) - ;CALL DSKY_PREINIT - LD HL,MSG_HBVER + 5 LD A,(DSKY_HEXMAP + RMJ) OR $80 @@ -3812,14 +3869,18 @@ SYS_GETBNKINFO: ; SYS_GETCPUSPD: ; -#IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_MBC)) +#IF (((PLATFORM == PLT_SBC) | (PLATFORM == PLT_MBC)) & (CPUSPDCAP==SPD_HILO)) LD A,(HB_RTCVAL) BIT 3,A +#IF (PLATFORM == PLT_SBC) + XOR %00001000 ; SBC SPEED BIT IS INVERTED +#ENDIF LD L,0 ; ASSUME HALF SPEED JR Z,SYS_GETCPUSPD1 LD L,1 SYS_GETCPUSPD1: LD DE,$FFFF ; UNKNOWN WAIT STATES +; XOR A RET #ENDIF @@ -4040,9 +4101,9 @@ SYS_SETSECS: ; SYS_SETCPUSPD: ; -#IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_MBC)) +#IF (((PLATFORM == PLT_SBC) | (PLATFORM == PLT_MBC)) & (CPUSPDCAP==SPD_HILO)) ; -; WAIT STATE SETTINGS ARE IGNORED FOR Z80 +; NOTE: WAIT STATE SETTINGS ARE IGNORED FOR Z80 ; LD A,L ; CLK SPD TO ACCUM LD C,%00000000 ; HALF SPEED @@ -4056,24 +4117,69 @@ SYS_SETCPUSPD1: LD A,(HB_RTCVAL) AND ~%00001000 ; CLEAR SPEED BIT OR C ; IMPLEMENT NEW SPEED BIT +#IF (PLATFORM == PLT_SBC) + ; SBC SPEED BIT IS INVERTED, ADJUST IT + LD A,C + XOR %00001000 + LD C,A +#ENDIF LD (HB_RTCVAL),A ; SAVE IN SHADOW REGISTER OUT (RTCIO),A ; UPDATE HARDWARE REGISTER +; + ; UPDATE THE CURRENT CPU SPEED IN HCB! + LD A,L + LD HL,(HB_CPUOSC) ; ASSUME FULL SPEED + CP 1 ; CHECK FOR 1 (FULL SPEED) + JR Z,SYS_SETCPUSPD2 ; IF SO, ALL DONE + ; ADJUST HL TO REFLECT HALF SPEED OPERATION + SRL H ; ADJUST HL ASSUMING + RR L ; HALF SPEED OPERATION +; +SYS_SETCPUSPD2: +; +; HL SHOULD NOW HAVE FINAL CPU RUNNING SPEED IN KHZ. +; UPDATE CB_CPUMHZ/CB_CPUKHZ WITH THIS VALUE. +; + LD (CB_CPUKHZ),HL ; UPDATE CPUKHZ + LD DE,1000 ; SET UP TO DIV BY 1000 FOR MHZ + CALL DIV16 ; BC=CPU MHZ, HL=REMAINDER + LD DE,500 ; SET UP TO ROUND UP + XOR A ; IF WITHIN 500 KHZ + SBC HL,DE ; REMAINDER - 500 + CCF ; COMPLEMENT CF + ADC A,C ; C -> A; ADD CF FOR ROUNDING + LD (CB_CPUMHZ),A ; SAVE IT +; + ; REINIT DELAY ROUTINE + LD A,(CB_CPUMHZ) ; CPU SPEED TO ACCUM AND INIT + CALL DELAY_INIT ; .. SPEED COMPENSATED DELAY +; XOR A RET #ENDIF ; #IF (CPUFAM == CPU_Z180) + PUSH DE ; SAVE WAIT STATES FOR NOW LD A,L ; CLK SPD TO ACCUM LD B,0 ; B HAS BIT FOR CMR LD C,0 ; C HAS BIT FOR CCR CP 2 ; DOUBLE SPEED? - JR C,SYS_SETCPUSPD1 - LD B,%10000000 + JR C,SYS_SETCPUSPD1 ; <2?, SKIP AHEAD + LD B,%10000000 ; SET CMR BIT SYS_SETCPUSPD1: - CP 1 - JR C,SYS_SETCPUSPD2 - LD C,%10000000 + CP 1 ; FULL SPEED? + JR C,SYS_SETCPUSPD2 ; <1?, SKIP AHEAD + LD C,%10000000 ; SET CCR BIT SYS_SETCPUSPD2: + ; BEFORE IMPLEMENTING THE NEW CPU SPEED, WE SWITCH THE + ; WAIT STATES TO MAXIMUM BECAUSE WE MAY BE IMPLEMENTING + ; SLOWER WAIT STATES REQUIRED BY THE NEW SPEED. WE SAVE + ; THE ORIGINAL WAIT STATES REGISTER VALUE ON STACK + IN0 A,(Z180_DCNTL) ; GET CURRENT REGISTER VALUE + LD E,A ; PUT IN L + PUSH DE ; SAVE FOR LATER + OR %11110000 ; MAX WAIT STATES + OUT0 (Z180_DCNTL),A ; DO IT ; IN0 A,(Z180_CMR) AND ~%10000000 @@ -4084,6 +4190,105 @@ SYS_SETCPUSPD2: AND ~%10000000 OR C OUT0 (Z180_CCR),A +; + ; UPDATE THE CURRENT CPU SPEED IN HCB! + LD A,L ; SETTING TO A + LD HL,(HB_CPUOSC) ; START WITH CPU OSC VALUE + ; ADJUST HL TO REFLECT HALF SPEED OPERATION + SRL H ; ADJUST HL ASSUMING + RR L ; HALF SPEED OPERATION + OR A ; CHECK FOR HALF SPEED + JR Z,SETCPUSPD2A ; IF SO, DONE + ; ADJUST HL TO REFLECT FULL SPEED OPERATION + SLA L + RL H + CP 1 ; CHECK FOR FULL SPEED + JR Z,SETCPUSPD2A ; IF SO DONE + ; ADJUST HL TO REFLECT DOUBLE SPEED OPERATION + SLA L + RL H +; +SETCPUSPD2A: +; +; HL SHOULD NOW HAVE FINAL CPU RUNNING SPEED IN KHZ. +; UPDATE CB_CPUMHZ/CB_CPUKHZ WITH THIS VALUE. +; + LD (CB_CPUKHZ),HL ; UPDATE CPUKHZ + LD DE,1000 ; SET UP TO DIV BY 1000 FOR MHZ + CALL DIV16 ; BC=CPU MHZ, HL=REMAINDER + LD DE,500 ; SET UP TO ROUND UP + XOR A ; IF WITHIN 500 KHZ + SBC HL,DE ; REMAINDER - 500 + CCF ; COMPLEMENT CF + ADC A,C ; C -> A; ADD CF FOR ROUNDING + LD (CB_CPUMHZ),A ; SAVE IT +; + ; NOW IMPLEMENT ANY WAIT STATE CHANGES. + POP HL ; INIT L WITH ORIG VALUE + POP DE ; RECOVER WAIT STATES + LD A,D ; GET MEM WS + CP $FF ; SKIP? + JR Z,SYS_SETCPUSPD3 ; IF SO, GO AHEAD + AND %00000011 ; JUST TWO BITS + RRCA ; MEM WS IS TOP TWO BITS + RRCA + LD H,A ; MOVE WS BITS TO H + LD A,L ; CUR VALUE TO A + AND %00111111 ; MASK OFF MEM WS BITS + OR H ; SET NEW MEM WS BITS + LD L,A ; BACK TO L +; +SYS_SETCPUSPD3: +; + LD A,E ; GET I/O WS + CP $FF ; SKIP? + JR Z,SYS_SETCPUSPD4 ; IF SO, GO AHEAD + DEC A ; ADJUST FOR BUILT-IN I/O WS + AND %00000011 ; JUST TWO BITS + RRCA ; I/O WS IS BITS 5-4 + RRCA + RRCA + RRCA + LD H,A ; MOVE WS BITS TO H + LD A,L ; CUR VALUE TO A + AND %11001111 ; MASK OFF I/O WS BITS + OR H ; SET NEW I/O WS BITS + LD L,A ; BACK TO L +; +SYS_SETCPUSPD4: + LD A,L ; WORKING VALUE TO A + OUT0 (Z180_DCNTL),A ; IMPLEMENT NEW VALUE +; + ; REINIT DELAY ROUTINE + LD A,(CB_CPUMHZ) ; CPU SPEED TO ACCUM AND INIT + CALL DELAY_INIT ; .. SPEED COMPENSATED DELAY +; + #IF ((INTMODE == 2) & (Z180_TIMER)) + ; THE Z180 TIMER IS BASED ON CPU SPEED. SO HERE + ; WE RECOMPUTE THE TIMER CONSTANTS BASED ON THE NEW SPEED. + XOR A ; ALL BITS ZERO + OUT0 (Z180_TCR),A ; ... INHIBITS TIMER OPERATION + LD HL,(CB_CPUKHZ) ; 50HZ = 18432000 / 20 / 50 / X, SO X = CPU KHZ + OUT0 (Z180_TMDR0L),L ; INITIALIZE TIMER 0 DATA REGISTER + OUT0 (Z180_TMDR0H),H + DEC HL ; RELOAD OCCURS *AFTER* ZERO + OUT0 (Z180_RLDR0L),L ; INITIALIZE TIMER 0 RELOAD REGISTER + OUT0 (Z180_RLDR0H),H + LD A,%00010001 ; ENABLE TIMER0 INT AND DOWN COUNTING + OUT0 (Z180_TCR),A + #ENDIF +; + #IF (ASCIENABLE) + ; RESET THE ASCI PORTS IN CASE SPEED CHANGED! + ; N.B., THIS WILL FAIL IF THE CURRENT BAUD RATE + ; IS IMPOSSIBLE TO IMPLEMENT AT THE NEW CPU SPEED!!! + LD DE,-1 + LD IY,ASCI0_CFG + CALL ASCI_INITDEV + LD DE,-1 + LD IY,ASCI1_CFG + CALL ASCI_INITDEV + #ENDIF ; XOR A RET @@ -5595,16 +5800,8 @@ HB_CPUSPD1: SLA L RL H ; - LD (CB_CPUKHZ),HL ; HL=CPU SPEED IN KHZ - LD DE,1000 ; SET UP TO DIV BY 1000 FOR MHZ - CALL DIV16 ; BC=CPU MHZ, HL=REMAINDER - LD DE,500 ; SET UP TO ROUND UP - XOR A ; IF WITHIN 500 KHZ - SBC HL,DE ; REMAINDER - 500 - CCF ; COMPLEMENT CF - ADC A,C ; C -> A; ADD CF FOR ROUNDING - LD (CB_CPUMHZ),A ; SAVE IT -; + ; RETURN CURRENT CPU SPD (KHZ) IN HL + XOR A ; SIGNAL SUCCESS RET ; HB_WAITSEC: @@ -5657,6 +5854,7 @@ HB_RDSEC: ; #ELSE ; + OR $FF ; SIGNAL ERROR RET ; NO RTC, ABORT ; #ENDIF @@ -6536,6 +6734,7 @@ HB_SECTCK .DB TICKFREQ ; TICK COUNTER FOR FRACTIONAL SECONDS HB_SECS .FILL 4,0 ; 32 BIT SECONDS COUNTER ; HB_CPUTYPE .DB 0 ; 0=Z80, 1=80180, 2=SL1960, 3=ASCI BRG +HB_CPUOSC .DW CPUOSC ; ACTUAL CPU HARDWARE OSC FREQ IN KHZ ; IOPRVAL .DW 0 ; TEMP STORAGE FOR IOPR ; diff --git a/Source/Images/fd_bp.txt b/Source/Images/fd_bp.txt index fa97b717..6b251b2a 100644 --- a/Source/Images/fd_bp.txt +++ b/Source/Images/fd_bp.txt @@ -11,6 +11,7 @@ # #../../Binary/Apps/*.com 15: ../../Binary/Apps/assign.com 15: +../../Binary/Apps/cpuspd.com 15: ../../Binary/Apps/fat.com 15: ../../Binary/Apps/fdu.com 15: ../../Binary/Apps/fdu.doc 15: diff --git a/Source/Images/fd_cpm22.txt b/Source/Images/fd_cpm22.txt index 525717c8..859b7e30 100644 --- a/Source/Images/fd_cpm22.txt +++ b/Source/Images/fd_cpm22.txt @@ -7,6 +7,7 @@ d_cpm22/ReadMe.txt 0: # #../../Binary/Apps/*.com 0: ../../Binary/Apps/assign.com 0: +../../Binary/Apps/cpuspd.com 0: ../../Binary/Apps/fat.com 0: ../../Binary/Apps/fdu.com 0: ../../Binary/Apps/fdu.doc 0: diff --git a/Source/Images/fd_cpm3.txt b/Source/Images/fd_cpm3.txt index 92eb3860..43c3e8ba 100644 --- a/Source/Images/fd_cpm3.txt +++ b/Source/Images/fd_cpm3.txt @@ -23,6 +23,7 @@ # #../../Binary/Apps/*.com 0: ../../Binary/Apps/assign.com 0: +../../Binary/Apps/cpuspd.com 0: ../../Binary/Apps/fat.com 0: ../../Binary/Apps/fdu.com 0: ../../Binary/Apps/fdu.doc 0: diff --git a/Source/Images/fd_nzcom.txt b/Source/Images/fd_nzcom.txt index 5a4dfb46..a569b365 100644 --- a/Source/Images/fd_nzcom.txt +++ b/Source/Images/fd_nzcom.txt @@ -7,6 +7,7 @@ d_nzcom/ReadMe.txt 0: # #../../Binary/Apps/*.com 0: ../../Binary/Apps/assign.com 0: +../../Binary/Apps/cpuspd.com 0: ../../Binary/Apps/fat.com 0: ../../Binary/Apps/fdu.com 0: ../../Binary/Apps/rtc.com 0: diff --git a/Source/Images/fd_zpm3.txt b/Source/Images/fd_zpm3.txt index dcec6bfa..a7077906 100644 --- a/Source/Images/fd_zpm3.txt +++ b/Source/Images/fd_zpm3.txt @@ -22,6 +22,7 @@ # #../../Binary/Apps/*.com 15: ../../Binary/Apps/assign.com 15: +../../Binary/Apps/cpuspd.com 15: ../../Binary/Apps/fat.com 15: ../../Binary/Apps/fdu.com 15: ../../Binary/Apps/fdu.doc 15: diff --git a/Source/Images/fd_zsdos.txt b/Source/Images/fd_zsdos.txt index 333d6526..1b7acc71 100644 --- a/Source/Images/fd_zsdos.txt +++ b/Source/Images/fd_zsdos.txt @@ -20,6 +20,7 @@ d_cpm22/u0/XSUB.COM 0: # #../../Binary/Apps/*.com 0: ../../Binary/Apps/assign.com 0: +../../Binary/Apps/cpuspd.com 0: ../../Binary/Apps/fat.com 0: ../../Binary/Apps/fdu.com 0: ../../Binary/Apps/fdu.doc 0: diff --git a/Source/Images/hd_bp.txt b/Source/Images/hd_bp.txt index 7449e46d..340f07d3 100644 --- a/Source/Images/hd_bp.txt +++ b/Source/Images/hd_bp.txt @@ -11,6 +11,7 @@ # #../../Binary/Apps/*.com 15: ../../Binary/Apps/assign.com 15: +../../Binary/Apps/cpuspd.com 15: ../../Binary/Apps/fat.com 15: ../../Binary/Apps/fdu.com 15: ../../Binary/Apps/fdu.doc 15: diff --git a/Source/Images/hd_cpm22.txt b/Source/Images/hd_cpm22.txt index e98400cc..a57d2283 100644 --- a/Source/Images/hd_cpm22.txt +++ b/Source/Images/hd_cpm22.txt @@ -7,6 +7,7 @@ d_cpm22/ReadMe.txt 0: # #../../Binary/Apps/*.com 0: ../../Binary/Apps/assign.com 0: +../../Binary/Apps/cpuspd.com 0: ../../Binary/Apps/fat.com 0: ../../Binary/Apps/fdu.com 0: ../../Binary/Apps/fdu.doc 0: diff --git a/Source/Images/hd_cpm3.txt b/Source/Images/hd_cpm3.txt index 40feb417..2cc80492 100644 --- a/Source/Images/hd_cpm3.txt +++ b/Source/Images/hd_cpm3.txt @@ -23,6 +23,7 @@ # #../../Binary/Apps/*.com 0: ../../Binary/Apps/assign.com 0: +../../Binary/Apps/cpuspd.com 0: ../../Binary/Apps/fat.com 0: ../../Binary/Apps/fdu.com 0: ../../Binary/Apps/fdu.doc 0: diff --git a/Source/Images/hd_nzcom.txt b/Source/Images/hd_nzcom.txt index 2f561e07..95968469 100644 --- a/Source/Images/hd_nzcom.txt +++ b/Source/Images/hd_nzcom.txt @@ -24,6 +24,7 @@ d_zsdos/u0/*.* 0: # #../../Binary/Apps/*.com 0: ../../Binary/Apps/assign.com 0: +../../Binary/Apps/cpuspd.com 0: ../../Binary/Apps/fat.com 0: ../../Binary/Apps/fdu.com 0: ../../Binary/Apps/fdu.doc 0: diff --git a/Source/Images/hd_zpm3.txt b/Source/Images/hd_zpm3.txt index 3d52e4b7..55853d5b 100644 --- a/Source/Images/hd_zpm3.txt +++ b/Source/Images/hd_zpm3.txt @@ -22,6 +22,7 @@ # #../../Binary/Apps/*.com 15: ../../Binary/Apps/assign.com 15: +../../Binary/Apps/cpuspd.com 15: ../../Binary/Apps/fat.com 15: ../../Binary/Apps/fdu.com 15: ../../Binary/Apps/fdu.doc 15: diff --git a/Source/Images/hd_zsdos.txt b/Source/Images/hd_zsdos.txt index 4d8c8e06..e23d5c4a 100644 --- a/Source/Images/hd_zsdos.txt +++ b/Source/Images/hd_zsdos.txt @@ -20,6 +20,7 @@ d_cpm22/u0/XSUB.COM 0: # #../../Binary/Apps/*.com 0: ../../Binary/Apps/assign.com 0: +../../Binary/Apps/cpuspd.com 0: ../../Binary/Apps/fat.com 0: ../../Binary/Apps/fdu.com 0: ../../Binary/Apps/fdu.doc 0: diff --git a/Source/RomDsk/Build.cmd b/Source/RomDsk/Build.cmd index 1a5295b9..8c6faf12 100644 --- a/Source/RomDsk/Build.cmd +++ b/Source/RomDsk/Build.cmd @@ -12,7 +12,7 @@ set ZXLIBDIR=%TOOLS%/cpm/lib/ set ZXINCDIR=%TOOLS%/cpm/include/ set RomApps1=assign mode rtc syscopy xm -set RomApps2=fdu format survey sysgen talk timer +set RomApps2=fdu format survey sysgen talk timer cpuspd :: :: Make all variants of the ROM Disk contents image. Three sizes are diff --git a/Source/RomDsk/Makefile b/Source/RomDsk/Makefile index 4f899321..c94e9ab7 100644 --- a/Source/RomDsk/Makefile +++ b/Source/RomDsk/Makefile @@ -7,7 +7,7 @@ include $(TOOLS)/Makefile.inc .SHELLFLAGS = -ce ROMAPPS1 := assign mode rtc syscopy xm -ROMAPPS2 := fdu format survey sysgen talk timer +ROMAPPS2 := fdu format survey sysgen talk timer cpuspd rom256_%.dat: ROMSIZ=256 rom512_%.dat: ROMSIZ=512 diff --git a/Source/ver.inc b/Source/ver.inc index 0f82f97b..c670d283 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,4 +2,4 @@ #DEFINE RMN 1 #DEFINE RUP 1 #DEFINE RTP 0 -#DEFINE BIOSVER "3.1.1-pre.151" +#DEFINE BIOSVER "3.1.1-pre.152" diff --git a/Source/ver.lib b/Source/ver.lib index 61894d78..4c6b0ca3 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 1 rup equ 1 rtp equ 0 biosver macro - db "3.1.1-pre.151" + db "3.1.1-pre.152" endm From 92399fe537cd8f7cd77f380108296a84a18ee85d Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Wed, 2 Feb 2022 17:08:55 -0800 Subject: [PATCH 08/34] More CPUSPD Tweaks I know I said I was done, but I found a few more things I decided to tweak. Functionality is unchanged. --- Doc/ROM Applications.pdf | Bin 193897 -> 193897 bytes Doc/RomWBW Applications.pdf | Bin 241325 -> 241324 bytes Doc/RomWBW Architecture.pdf | Bin 451481 -> 451608 bytes Doc/RomWBW Disk Catalog.pdf | Bin 134793 -> 134794 bytes Doc/RomWBW Getting Started.pdf | Bin 272620 -> 272671 bytes ReadMe.md | 7 +- ReadMe.txt | 7 +- Source/Apps/cpuspd/cpuspd.asm | 214 +++++++++++++++++++++++++++------ Source/Doc/Architecture.md | 1 + Source/HBIOS/API.txt | 1 + Source/HBIOS/hbios.asm | 31 +++-- Source/ver.inc | 2 +- Source/ver.lib | 2 +- 13 files changed, 206 insertions(+), 59 deletions(-) diff --git a/Doc/ROM Applications.pdf b/Doc/ROM Applications.pdf index 5d7c2dacdf8c3183bad07b8a7c328372f3460a03..26d4f1a67644222392be853f11ccd23f757325e4 100644 GIT binary patch delta 258 zcmaF)iu>g&?hW;f^)Gey<@O}ReRi9CO|_mo=VHWqeN~UIDNCMja}~nT0_Z7yZO@orpqM%MqQX~ zuCZI{_!iwGfBGG-Bn4L`GZ{_4XY=RQ+wZ$IcUM^P9+s(<-FilT_bYuX=9!DuH#0J| zGcqx5XJlepa+KZ3(9Foh&|tD3yEu=LkpU1w1h$_)&Sa(QZ0TreX<*`P=;UfYHDO+V5eY1NXc}cuS~K4HGgI7 delta 258 zcmaF)iu>g&?hW;f^`akhlUY8`GM}|Y?`L#E_pz#4O~+O0%C_5eCq|9#(^M=xheJbUqaMe4sBq4kWG%o7)_Yi49> zXJlgB&d9{HE%-x(F&CQHVEnOX*9PJcr2q~HF^OZ>!0BrqeZvX%Q diff --git a/Doc/RomWBW Applications.pdf b/Doc/RomWBW Applications.pdf index bb6a0000440b7909589057f3abefcf8149169fd5..9810891d98d568daf230a332ad2c37fe88eb20f6 100644 GIT binary patch delta 16512 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 ACIA2c delta 16606 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 R17?;G1SKDzl9n>%{|7OQmc#%6 delta 19761 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 F{{Y2sD&6 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 @@ -455,7 +455,7 @@ therefore, globally available. | TALK | Direct console I/O to a specified character device. | | RTC | Manage and test the Real Time Clock hardware. | | TIMER | Display value of running periodic system timer. | -| INTTEST | Test interrupt vector hooking. | +| CPUSPD | Change the running CPU speed and wait states of the system. | Some custom applications do not fit on the ROM disk. They are found on the disk image files or the individual files can be found in the @@ -465,6 +465,7 @@ Binary\\Apps directory of the distribution. |-------------|-------------------------------------------------------------| | TUNE | Play .PT2, .PT3, .MYM audio files. | | FAT | Access MS-DOS FAT filesystems from RomWBW (based on FatFs). | +| INTTEST | Test interrupt vector hooking. | Additional documentation on all of these applications can be found in “RomWBW Applications.pdf†in the Doc directory of the distribution. diff --git a/ReadMe.txt b/ReadMe.txt index b94fb4d5..92cfdabb 100644 --- a/ReadMe.txt +++ b/ReadMe.txt @@ -1,6 +1,6 @@ RomWBW Getting Started Wayne Warthen (mailto:wwarthen@gmail.com) -01 Feb 2022 +02 Feb 2022 @@ -17,7 +17,7 @@ RomWBW Z80/Z180 System Software Version 3.1 Pre-release -01 Feb 2022 +02 Feb 2022 Wayne Warthen wwarthen@gmail.com @@ -460,7 +460,7 @@ therefore, globally available. TIMER Display value of running periodic system timer. - INTTEST Test interrupt vector hooking. + CPUSPD Change the running CPU speed and wait states of the system. ----------------------------------------------------------------------------- Some custom applications do not fit on the ROM disk. They are found on @@ -471,6 +471,7 @@ Binary\Apps directory of the distribution. ------------- ------------------------------------------------------------- TUNE Play .PT2, .PT3, .MYM audio files. FAT Access MS-DOS FAT filesystems from RomWBW (based on FatFs). + INTTEST Test interrupt vector hooking. Additional documentation on all of these applications can be found in “RomWBW Applications.pdf†in the Doc directory of the distribution. diff --git a/Source/Apps/cpuspd/cpuspd.asm b/Source/Apps/cpuspd/cpuspd.asm index 0aecb7f8..363c4e75 100644 --- a/Source/Apps/cpuspd/cpuspd.asm +++ b/Source/Apps/cpuspd/cpuspd.asm @@ -21,6 +21,11 @@ rtc_port .equ $70 ; RTC latch port adr restart .equ $0000 ; CP/M restart vector bdos .equ $0005 ; BDOS invocation vector ; +ident .equ $FFFE ; loc of RomWBW HBIOS ident ptr +; +rmj .equ 3 ; intended CBIOS version - major +rmn .equ 1 ; intended CBIOS version - minor +; ;======================================================================= ; .org $100 ; standard CP/M executable @@ -33,6 +38,10 @@ bdos .equ $0005 ; BDOS invocation vector call crlf ld de,str_banner ; banner call prtstr +; + ; initialization + call init ; initialize + jr nz,exit ; abort if init fails ; call main ; do the real work ; @@ -47,6 +56,46 @@ exit: ; Main Program ;======================================================================= ; +; +; Initialization +; +init: + ; check for UNA (UBIOS) + ld a,($FFFD) ; fixed location of UNA API vector + cp $C3 ; jp instruction? + jr nz,initwbw ; if not, not UNA + ld hl,($FFFE) ; get jp address + ld a,(hl) ; get byte at target address + cp $FD ; first byte of UNA push ix instruction + jr nz,initwbw ; if not, not UNA + inc hl ; point to next byte + ld a,(hl) ; get next byte + cp $E5 ; second byte of UNA push ix instruction + jr nz,initwbw ; if not, not UNA + jp err_una ; UNA not supported +; +initwbw: + ; get location of config data and verify integrity + ld hl,(ident) ; HL := adr or RomWBW HBIOS ident + ld a,(hl) ; get first byte of RomWBW marker + cp 'W' ; match? + jp nz,err_inv ; abort with invalid config block + inc hl ; next byte (marker byte 2) + ld a,(hl) ; load it + cp ~'W' ; match? + jp nz,err_inv ; abort with invalid config block + inc hl ; next byte (major/minor version) + ld a,(hl) ; load it + cp rmj << 4 | rmn ; match? + jp nz,err_ver ; abort with invalid os version +; +initz: + ; initialization complete + xor a ; signal success + ret ; return +; +; +; main: ; skip to start of first parm ld ix,$81 ; point to start of parm area (past len byte) @@ -64,13 +113,19 @@ main1: jr main1 ; continue option checking ; main2: + ret z ; if end, nothing to do + cp ',' ; no new speed? + jr z,main2a ; go to wait states ; parse speed string (half, full, double) call getalpha ; extract speed ("HALF", "FULL", "DOUBLE") -; + call parse_spd ; parse to numeric + jp c,err_parm ; if invalid, abort + ld (new_cpu_spd),a ; save it call nonblank ; skip whitespace jp z,set_spd ; if nothing else, set new speed cp ',' ; parm separator jp nz,err_parm ; invalid format, show usage and abort +main2a: inc ix ; pass separator call nonblank ; skip whitespace jp z,set_spd ; if nothing else, set new speed @@ -78,7 +133,7 @@ main2: jr c,main3 ; nope, try skipping this parm call getnum ; get memory wait states jp c,err_parm ; if overflow, show usage and abort - ld (ws_mem),a ; save memory wait states + ld (new_ws_mem),a ; save memory wait states ; main3: call nonblank ; skip whitespace @@ -90,42 +145,40 @@ main3: jp z,set_spd ; if nothing else, set new speed call getnum ; get I/O wait states jp c,err_parm ; if overflow, show usage and abort - ld (ws_io),a ; save memory wait states + ld (new_ws_io),a ; save memory wait states ; call nonblank ; skip whitespace jp nz,err_parm ; invalid format, show usage and abort - ; -; -set_spd: - ld a,(tmpstr) - cp 'H' - jr z,set_half - cp 'F' - jr z,set_full - cp 'D' - jr z,set_dbl - jp err_parm + jp set_spd ; set new speed and return +; +parse_spd: + ld a,(tmpstr) ; first byte of string + ld c,0 ; assume half speed + cp 'H' ; check it + jr z,parse_spd1 ; if equal, done + ld c,1 ; assume full speed + cp 'F' ; check it + jr z,parse_spd1 ; if equal, done + ld c,2 ; assume double speed + cp 'D' ; check it + jr z,parse_spd1 ; if equal, done + or a ; clear CF + ccf ; set CF to indicate error + ret +parse_spd1: + ld a,c ; result to a + or a ; clear CF ret ; -set_half: - ld l,0 - jr new_spd -; -set_full: - ld l,1 - jr new_spd -; -set_dbl: - ld l,2 - jr new_spd -; -new_spd: +set_spd: call delay ld b,BF_SYSSET ld c,BF_SYSSET_CPUSPD - ld a,(ws_mem) + ld a,(new_cpu_spd) + ld l,a + ld a,(new_ws_mem) ld d,a - ld a,(ws_io) + ld a,(new_ws_io) ld e,a rst 08 jp nz,err_not_sup @@ -134,6 +187,19 @@ new_spd: ret ; show_spd: + ld b,BF_SYSGET + ld c,BF_SYSGET_CPUINFO + rst 08 + jp nz,err_not_sup + call crlf2 + push de ; save CPU speed for now + push bc ; Oscillator speed to HL + pop hl + ld de,str_spacer + call prtstr + call prtd3m ; print it + ld de,str_oscspd + call prtstr ld b,BF_SYSGET ld c,BF_SYSGET_CPUSPD rst 08 @@ -151,10 +217,15 @@ show_spd: jr z,show_spd1 jp err_invalid show_spd1: - call crlf2 + call crlf + call prtstr + pop bc ; recover wait states + pop hl ; recover CPU speed + push bc ; resave wait states + call prtd3m + ld de,str_cpuspd call prtstr pop hl -; ld a,h ; memory wait states cp $FF jr z,show_spd2 @@ -198,6 +269,15 @@ usage: ; ; Error Handlers ; +err_una: + ld de,str_err_una + jr err_ret +err_inv: + ld de,str_err_inv + jr err_ret +err_ver: + ld de,str_err_ver + jr err_ret err_parm: ld de,str_err_parm jr err_ret @@ -235,8 +315,9 @@ prtchr: pop af ret ; -prtdot: +; Print a dot character without destroying any registers ; +prtdot: ; shortcut to print a dot preserving all regs push af ; save af ld a,'.' ; load dot char @@ -389,6 +470,46 @@ prtdec2: ld e,0 call prtchr ret +; +; Print value of HL as thousandths, ie. 0.000 +; +prtd3m: + push bc + push de + push hl + ld e,'0' + ld bc,-10000 + call prtd3m1 + ld e,0 + ld bc,-1000 + call prtd3m1 + call prtdot + ld bc,-100 + call prtd3m1 + ld c,-10 + call prtd3m1 + ld c,-1 + call prtd3m1 + pop hl + pop de + pop bc + ret +prtd3m1: + ld a,'0' - 1 +prtd3m2: + inc a + add hl,bc + jr c,prtd3m2 + sbc hl,bc + cp e + jr z,prtd3m3 + ld e,0 + call prtchr +prtd3m3: + ret + + + ; ; Get the next non-blank character from (HL). ; @@ -541,17 +662,29 @@ delay1: ; Constants ;======================================================================= ; -str_banner .db "RomWBW CPU Speed Selector v0.4, 31-Jan-2022",0 +str_banner .db "RomWBW CPU Speed Selector v0.5, 2-Feb-2022",0 str_spacer .db " ",0 -str_slow .db " CPU speed is HALF",0 -str_full .db " CPU speed is FULL",0 -str_dbl .db " CPU speed is DOUBLE",0 +str_oscspd .db " MHz Oscillator",0 +str_slow .db " CPU speed is HALF (",0 +str_full .db " CPU speed is FULL (",0 +str_dbl .db " CPU speed is DOUBLE (",0 +str_cpuspd .db " MHz)",0 str_memws .db " Memory Wait State(s)",0 str_iows .db " I/O Wait State(s)",0 -str_err_parm .db " Parameter error (CPUSPD /? for usage)",0 +str_err_una .db " ERROR: UNA not supported by application",0 +str_err_inv .db " ERROR: Invalid BIOS (signature missing)",0 +str_err_ver .db " ERROR: Unexpected HBIOS version",0 +str_err_parm .db " ERROR: Parameter error (CPUSPD /? for usage)",0 str_err_not_sup .db " ERROR: Platform or configuration not supported!",0 str_err_invalid .db " ERROR: Invalid configuration!",0 -str_usage .db " Usage: CPUSPD [(Half|Full|Double)[,[,]]]",0 +str_usage .db " Usage: CPUSPD ,,\r\n" + .db "\r\n" + .db " : \"Half\", \"Full\", or \"Double\"\r\n" + .db " : Memory wait states\r\n" + .db " : I/O wait states\r\n" + .db "\r\n" + .db " Any parameter may be omitted\r\n" + .db " Ability to set values varies by system\r\n",0 ; ;======================================================================= ; Working data @@ -563,8 +696,9 @@ stack .equ $ ; stack top ; ; tmpstr .fill 9,0 ; temp string (8 chars, 0 term) -ws_mem .db $FF ; memory wait states -ws_io .db $FF ; I/O wait states +new_cpu_spd .db $FF ; new CPU speed +new_ws_mem .db $FF ; new memory wait states +new_ws_io .db $FF ; new I/O wait states ; diff --git a/Source/Doc/Architecture.md b/Source/Doc/Architecture.md index 6d542843..cff5522d 100644 --- a/Source/Doc/Architecture.md +++ b/Source/Doc/Architecture.md @@ -1938,6 +1938,7 @@ lookup. | H: Z80 CPU Variant | L: CPU Speed in MHz | DE: CPU Speed in KHz +| BC: Oscillator Speed in KHz #### SYSGET Subfunction 0xF1 -- Get Memory Information (MEMINFO) diff --git a/Source/HBIOS/API.txt b/Source/HBIOS/API.txt index aeae56e9..af68ecfe 100644 --- a/Source/HBIOS/API.txt +++ b/Source/HBIOS/API.txt @@ -100,6 +100,7 @@ GET ($F8): H=Z80 CPU Variant L=CPU Speed in MHz DE=CPU Speed in KHz + BC=Oscillator Freq in KHz MEMINFO ($F1): BC=FuSnction/Subfunction A=Result diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index 5e6cfe42..f8146f48 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -3832,6 +3832,7 @@ SYS_GETCPUINFO: LD A,(CB_CPUMHZ) LD L,A LD DE,(CB_CPUKHZ) + LD BC,(HB_CPUOSC) XOR A RET ; @@ -4106,6 +4107,8 @@ SYS_SETCPUSPD: ; NOTE: WAIT STATE SETTINGS ARE IGNORED FOR Z80 ; LD A,L ; CLK SPD TO ACCUM + CP $FF ; NO CHANGE? + JR Z,SYS_SETCPUSPD3 ; DONE IF SO LD C,%00000000 ; HALF SPEED CP 0 JR Z,SYS_SETCPUSPD1 @@ -4154,13 +4157,27 @@ SYS_SETCPUSPD2: LD A,(CB_CPUMHZ) ; CPU SPEED TO ACCUM AND INIT CALL DELAY_INIT ; .. SPEED COMPENSATED DELAY ; +SYS_SETCPUSPD3: XOR A RET #ENDIF ; #IF (CPUFAM == CPU_Z180) PUSH DE ; SAVE WAIT STATES FOR NOW - LD A,L ; CLK SPD TO ACCUM + ; BEFORE IMPLEMENTING THE NEW CPU SPEED, WE SWITCH THE + ; WAIT STATES TO MAXIMUM BECAUSE WE MAY BE IMPLEMENTING + ; SLOWER WAIT STATES REQUIRED BY THE NEW SPEED. WE SAVE + ; THE ORIGINAL WAIT STATES REGISTER VALUE ON STACK + IN0 A,(Z180_DCNTL) ; GET CURRENT REGISTER VALUE + LD E,A ; PUT IN E + PUSH DE ; SAVE FOR LATER + OR %11110000 ; MAX WAIT STATES + OUT0 (Z180_DCNTL),A ; DO IT +; + LD A,L ; NEW CLK SPD TO ACCUM + CP $FF ; NO CHANGE? + JR Z,SYS_SETCPUSPD2B ; IF SO, SKIP TO WAIT STATES +; LD B,0 ; B HAS BIT FOR CMR LD C,0 ; C HAS BIT FOR CCR CP 2 ; DOUBLE SPEED? @@ -4171,15 +4188,6 @@ SYS_SETCPUSPD1: JR C,SYS_SETCPUSPD2 ; <1?, SKIP AHEAD LD C,%10000000 ; SET CCR BIT SYS_SETCPUSPD2: - ; BEFORE IMPLEMENTING THE NEW CPU SPEED, WE SWITCH THE - ; WAIT STATES TO MAXIMUM BECAUSE WE MAY BE IMPLEMENTING - ; SLOWER WAIT STATES REQUIRED BY THE NEW SPEED. WE SAVE - ; THE ORIGINAL WAIT STATES REGISTER VALUE ON STACK - IN0 A,(Z180_DCNTL) ; GET CURRENT REGISTER VALUE - LD E,A ; PUT IN L - PUSH DE ; SAVE FOR LATER - OR %11110000 ; MAX WAIT STATES - OUT0 (Z180_DCNTL),A ; DO IT ; IN0 A,(Z180_CMR) AND ~%10000000 @@ -4223,8 +4231,9 @@ SETCPUSPD2A: ADC A,C ; C -> A; ADD CF FOR ROUNDING LD (CB_CPUMHZ),A ; SAVE IT ; +SYS_SETCPUSPD2B: ; NOW IMPLEMENT ANY WAIT STATE CHANGES. - POP HL ; INIT L WITH ORIG VALUE + POP HL ; INIT L WITH ORIG DCNTL VALUE POP DE ; RECOVER WAIT STATES LD A,D ; GET MEM WS CP $FF ; SKIP? diff --git a/Source/ver.inc b/Source/ver.inc index c670d283..0ed9e30c 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,4 +2,4 @@ #DEFINE RMN 1 #DEFINE RUP 1 #DEFINE RTP 0 -#DEFINE BIOSVER "3.1.1-pre.152" +#DEFINE BIOSVER "3.1.1-pre.153" diff --git a/Source/ver.lib b/Source/ver.lib index 4c6b0ca3..06000c8a 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 1 rup equ 1 rtp equ 0 biosver macro - db "3.1.1-pre.152" + db "3.1.1-pre.153" endm From 97aa0aae9f52a0964923e3be1b304835ac8963c4 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Wed, 2 Feb 2022 17:39:36 -0800 Subject: [PATCH 09/34] Bug Fix Fixed a small issue in the boot management of the CPU speed for MBC and SBC platforms. --- Source/HBIOS/hbios.asm | 12 ++++++++---- Source/ver.inc | 2 +- Source/ver.lib | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index f8146f48..0e4b9e30 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -1802,30 +1802,34 @@ HB_CPUSPD2: ; THAT SUPPORT SOFTWARE SELECTABLE CPU SPEED. UPDATE CB_CPUKHZ ; IN HCB AS WE DO THIS. ; -#IF ((CPUSPDCAP==SPD_HILO) & (PLATFORM==PLT_MBC) & (CPUSPDDEF==SPD_HIGH)) +#IF ((CPUSPDCAP==SPD_HILO) & (PLATFORM==PLT_MBC)) + #IF (CPUSPDDEF==SPD_HIGH) ; SET HIGH SPEED VIA RTC LATCH LD A,(HB_RTCVAL) OR %00001000 ; SET HI SPEED BIT LD (HB_RTCVAL),A ; SAVE SHADOW OUT (RTCIO),A ; IMPLEMENT ; HL IS ALREADY CORRECT FOR FULL SPEED OPERATION -#ELSE + #ELSE ; ADJUST HL TO REFLECT HALF SPEED OPERATION SRL H ; ADJUST HL ASSUMING RR L ; HALF SPEED OPERATION + #ENDIF #ENDIF ; -#IF ((CPUSPDCAP==SPD_HILO) & (PLATFORM==PLT_SBC) & (CPUSPDDEF==SPD_HIGH)) +#IF ((CPUSPDCAP==SPD_HILO) & (PLATFORM==PLT_SBC)) + #IF (CPUSPDDEF==SPD_HIGH) ; SET HIGH SPEED VIA RTC LATCH LD A,(HB_RTCVAL) AND ~%00001000 ; CLEAR HI SPEED BIT LD (HB_RTCVAL),A ; SAVE SHADOW OUT (RTCIO),A ; IMPLEMENT ; HL IS ALREADY CORRECT FOR FULL SPEED OPERATION -#ELSE + #ELSE ; ADJUST HL TO REFLECT HALF SPEED OPERATION SRL H ; ADJUST HL ASSUMING RR L ; HALF SPEED OPERATION + #ENDIF #ENDIF ; #IF (CPUFAM == CPU_Z180) diff --git a/Source/ver.inc b/Source/ver.inc index 0ed9e30c..6c0cd517 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,4 +2,4 @@ #DEFINE RMN 1 #DEFINE RUP 1 #DEFINE RTP 0 -#DEFINE BIOSVER "3.1.1-pre.153" +#DEFINE BIOSVER "3.1.1-pre.154" diff --git a/Source/ver.lib b/Source/ver.lib index 06000c8a..661456a8 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 1 rup equ 1 rtp equ 0 biosver macro - db "3.1.1-pre.153" + db "3.1.1-pre.154" endm From 214ed545843b964cda4945f5919aa95ac5b3b06a Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Sat, 5 Feb 2022 11:54:46 -0800 Subject: [PATCH 10/34] Miscellaneous - Fix build under Windows (credit to Dean Netherton for finding this). - Fix ReadMe.md file format to remove superfluous junk at top. - Improve RAM size detection (work in progress, not part of normal build). --- Doc/ROM Applications.pdf | Bin 193897 -> 193897 bytes Doc/RomWBW Applications.pdf | Bin 241324 -> 241324 bytes Doc/RomWBW Architecture.pdf | Bin 451608 -> 451608 bytes Doc/RomWBW Disk Catalog.pdf | Bin 134794 -> 134794 bytes Doc/RomWBW Getting Started.pdf | Bin 272671 -> 272671 bytes ReadMe.md | 41 --------------------------------- Source/Apps/cpuspd/Build.cmd | 2 +- Source/Doc/Build.cmd | 2 +- Source/HBIOS/hbios.asm | 35 ++++++++++++++++++---------- Source/ver.inc | 2 +- Source/ver.lib | 2 +- 11 files changed, 27 insertions(+), 57 deletions(-) diff --git a/Doc/ROM Applications.pdf b/Doc/ROM Applications.pdf index 26d4f1a67644222392be853f11ccd23f757325e4..6f67aa2cc7a53ee8dddd1520722ee5bbee0f3916 100644 GIT binary patch delta 115 zcmaF)iu>g&?uHh|ElkUgvsxIKo0?7bV;AQ!GBN-{L$JX1^T(O2be)ZyoDH0eolH$k loz0wGEL@!oT-=Nt&CN~B+#HQv-AwEhYzQft?(>yN768>@AKw4~ delta 115 zcmaF)iu>g&?uHh|ElkUgvzi&17#d9WV;AQ!GBN-{L$JX1^T(O2be%07EiDa9oDH2^ l%?vCo%#9qKEzAv^jm?}*Tun`lObqN4YzQft?(>yN767t19{m6S diff --git a/Doc/RomWBW Applications.pdf b/Doc/RomWBW Applications.pdf index 9810891d98d568daf230a332ad2c37fe88eb20f6..a64d5d210b2446a2f12b98c5b684b7627ee0c97a 100644 GIT binary patch delta 111 zcmZ2;mv7BozJ?aY7N#xCYPqZy2Ij`*)3tM%_T}T^&t5m4PR8bLb_zCxluZBqm`xS{lMFMN diff --git a/Doc/RomWBW Disk Catalog.pdf b/Doc/RomWBW Disk Catalog.pdf index 2ae54ac0efd175f42e69263f769dec81937d15bd..7a3c3a43de979ac5e4927731b4bdd8f9158948aa 100644 GIT binary patch delta 107 zcmeC0%h5HLqhSlFi?QVrb#)Y-Z_f;b>xN dVP@=R;b`dULyOfFy-=P@!e0765sz;@Bk%&SZj932ge&77Rw zTrEt^OpFXHEL{zpja|*%T;0r#9gR%P>=bMWDv4FFv*Ri*Nh~U DESIRED 32K PAGE - AND %11111000 OUT0 (Z180_BBR),A ; WRITE TO BANK BASE RET ; DONE #ENDIF @@ -1077,13 +1076,18 @@ Z280_BOOTERR .TEXT "\r\n\r\n*** Application mode boot not supported under Z280 n DI ; NO INTERRUPTS IM 1 ; INTERRUPT MODE 1 -;#IF ((PLATFORM=PLT_MBC) | (PLATFORM=PLT_SBC)) +;#IF ((PLATFORM == PLT_MBC) | (PLATFORM == PLT_SBC)) ; INITIALIZE RTC LATCH BYTE ; FOR SOME PLATFORMS THIS CONTROLS HI/LO SPEED CIRCUIT LD A,(RTCDEFVAL) ; GET DEFAULT VALUE OUT (RTCIO),A ; SET IT ;#ENDIF ; +#IF (PLATFORM == PLT_N8) + LD A,N8_DEFACR ; ENSURE N8 ACR + OUT0 (N8_ACR),A ; ... REGISTER IS INITIALIZED +#ENDIF +; #IF (DIAGENABLE) LD A,%00000001 OUT (DIAGPORT),A @@ -1375,31 +1379,34 @@ RS_START: PUSH AF ; SAVE IT LD C,0 ; RUNNING BANK COUNT + LD HL,$7FFF ; BYTE TEST ADDRESS LD IX,RS_ARY ; ORIG BYTE STORAGE ARRAY PTR RS_LOOP1: LD A,C ADD A,$80 ; OFFSET BY START OF RAM BANKS CALL HBX_BNKSEL ; SELECT THE BANK - LD A,($7FFF) ; GET ORIGINAL VALUE + LD A,(HL) ; GET ORIGINAL VALUE LD (IX),A ; SAVE IT TO RESTORE LATER INC IX ; BUMP IX LD A,$AA ; TEST LOC WITH $AA - LD ($7FFF),A - LD A,($7FFF) + LD (HL),A ; AVOID PROBLEMS WITH + LD (HL),A ; ... DS1210 + LD (HL),A + LD A,(HL) CP $AA JR NZ,RS_DONE LD A,$55 ; TEST LOC WITH $55 - LD ($7FFF),A - LD A,($7FFF) + LD (HL),A + LD A,(HL) CP $55 JR NZ,RS_DONE ; STORE A UNIQUE VALUE LD A,C - LD ($7FFF),A + LD (HL),A OR A ; ZERO? JR Z,RS_NEXT ; SKIP STORED VALUE CHECK @@ -1410,7 +1417,7 @@ RS_LOOP3: LD A,E ADD A,$80 CALL HBX_BNKSEL - LD A,($7FFF) + LD A,(HL) CP E ; VERIFY JR NZ,RS_DONE ; ABORT IF MISCOMPARE INC E ; NEXT BANK @@ -1422,6 +1429,9 @@ RS_NEXT: ; RS_DONE: LD E,C ; FINAL BANK COUNT TO E + LD A,C + OR A + JR Z,RS_LOOPZ ; RESTORE SAVED VALUES LD IX,RS_ARY LD B,C ; LOOP COUNT @@ -1431,9 +1441,10 @@ RS_LOOP2: CALL HBX_BNKSEL INC C LD A,(IX) ; GET VALUE - LD ($7FFF),A ; RESTORE IT + LD (HL),A ; RESTORE IT INC IX DJNZ RS_LOOP2 ; ALL BANKS +RS_LOOPZ: ; ; MBC RUNTIME MEMORY SIZE ADJUSTMENT ; diff --git a/Source/ver.inc b/Source/ver.inc index 6c0cd517..fd73e28a 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,4 +2,4 @@ #DEFINE RMN 1 #DEFINE RUP 1 #DEFINE RTP 0 -#DEFINE BIOSVER "3.1.1-pre.154" +#DEFINE BIOSVER "3.1.1-pre.155" diff --git a/Source/ver.lib b/Source/ver.lib index 661456a8..c16db76f 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 1 rup equ 1 rtp equ 0 biosver macro - db "3.1.1-pre.154" + db "3.1.1-pre.155" endm From e5b1d5afc8da46cb27a250d1ff58f25bbd937ded Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Tue, 8 Feb 2022 10:07:01 -0800 Subject: [PATCH 11/34] Update Readme.unix --- Readme.unix | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Readme.unix b/Readme.unix index 62d6aca2..dbcf93b7 100644 --- a/Readme.unix +++ b/Readme.unix @@ -43,13 +43,18 @@ the "SCZ180" platform: Please be aware that the make-based build does have a couple of deficiencies. -First, there are some build failures that will not stop the make -process. Some of this is because real CP/M 2.2 tools are used in +First and most important, the Makefiles do not handle reruns very well. +To ensure a full buld, use "make clobber" from the top level directory +before running the actual build. For those used to using "make clean", +you can do that but it is not as thorough as "make clobber". + +Second, there are some build failures that will not stop the make +process. Most of this is because real CP/M 2.2 tools are used in places and CP/M 2.2 does not allow programs to return a result code. -Second, not all dependencies are properly handled. So, changes to some +Third, not all dependencies are properly handled. So, changes to some files will not cause things to rebuild as appropriate. In general, I -recommend doing a "make clean" before running "make" to ensure that +recommend doing a "make clobber" before running "make" to ensure that everything is fully rebuilt. For macOS users, you may encounter a failure reading or writing files. From 8c9ce2184e77ad961fe2b164a541748e20de7141 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Thu, 10 Feb 2022 16:51:33 -0800 Subject: [PATCH 12/34] ZXCC Sync - Attempting to sync ZXCC with latest source in repository by Tony Nicholson. Generally a failure, but it is closer. --- Source/Apps/Build.cmd | 12 +- Source/Apps/Test/Build.cmd | 6 +- Source/Apps/XM/Build.cmd | 20 +- Source/Apps/XM/Makefile | 6 +- Source/Apps/ZMD/Build.cmd | 38 +- Source/Apps/ZMD/Makefile | 4 +- Source/Apps/ZMP/Build.cmd | 10 +- Source/Apps/ZMP/Makefile | 2 +- Source/BPBIOS/Build.cmd | 14 +- Source/BPBIOS/Makefile | 2 +- Source/BPBIOS/ZCPR33/Build.cmd | 8 +- Source/BPBIOS/ZCPR33/Makefile | 4 +- Source/CBIOS/Build.cmd | 6 +- Source/CPM22/Build.cmd | 30 +- Source/CPM3/Build.cmd | 80 +- Source/CPM3/Makefile | 16 +- Source/Forth/Build.cmd | 10 +- Source/HBIOS/Build.cmd | 6 +- Source/HDIAG/Build.cmd | 4 - Source/RomDsk/Build.cmd | 6 +- Source/ZCPR-DJ/Build.cmd | 10 +- Source/ZCPR-DJ/Makefile | 2 +- Source/ZCPR/Build.cmd | 14 +- Source/ZCPR/Makefile | 4 +- Source/ZPM3/Build.cmd | 22 +- Source/ZPM3/Makefile | 4 +- Source/ZSDOS/Build.cmd | 10 +- Source/ZSDOS/Clock/Build.cmd | 8 +- Source/ZSDOS/Makefile | 4 +- Tools/Makefile.inc | 5 +- Tools/cpm/{bin => bin80}/ARCV.COM | Bin Tools/cpm/{bin => bin80}/AS.COM | Bin Tools/cpm/{bin => bin80}/BASCOM.COM | Bin Tools/cpm/{bin => bin80}/CC.COM | Bin Tools/cpm/{bin => bin80}/CNM.COM | Bin Tools/cpm/{bin => bin80}/CRC.COM | Bin Tools/cpm/{bin => bin80}/CREF80.COM | Bin Tools/cpm/{bin => bin80}/CZ.COM | Bin Tools/cpm/{bin => bin80}/DIRX.COM | Bin Tools/cpm/{bin => bin80}/DISKINFO.COM | Bin Tools/cpm/{bin => bin80}/GENCPM.COM | Bin Tools/cpm/{bin => bin80}/HEX80.COM | Bin Tools/cpm/{bin => bin80}/HEXCOM.COM | Bin Tools/cpm/{bin => bin80}/L80.COM | Bin Tools/cpm/{bin => bin80}/LBREXT.COM | Bin Tools/cpm/{bin => bin80}/LIB.COM | Bin Tools/cpm/{bin => bin80}/LIB80.COM | Bin Tools/cpm/{bin => bin80}/LIBUTIL.COM | Bin Tools/cpm/{bin => bin80}/LINK.COM | Bin Tools/cpm/{bin => bin80}/LN.COM | Bin Tools/cpm/{bin => bin80}/M80.COM | Bin Tools/cpm/{bin => bin80}/MAC.COM | Bin Tools/cpm/{bin => bin80}/MLOAD25.COM | Bin Tools/cpm/{bin => bin80}/NULU.COM | Bin Tools/cpm/{bin => bin80}/RMAC.COM | Bin Tools/cpm/{bin => bin80}/SIDSYM.COM | Bin Tools/cpm/{bin => bin80}/SLR180.COM | Bin Tools/cpm/{bin => bin80}/SLRMAC.COM | Bin Tools/cpm/{bin => bin80}/SLRNK.COM | Bin Tools/cpm/{bin => bin80}/SQZ.COM | Bin Tools/cpm/{bin => bin80}/TEX21.COM | Bin Tools/cpm/{bin => bin80}/TEX21A.COM | Bin Tools/cpm/{bin => bin80}/TEX21B.COM | Bin Tools/cpm/{bin => bin80}/UCRLZH.COM | Bin Tools/cpm/{bin => bin80}/UNARC.COM | Bin Tools/cpm/{bin => bin80}/UNCR.COM | Bin Tools/cpm/{bin => bin80}/UNZIP.COM | Bin Tools/cpm/{bin => bin80}/UNZIP154.COM | Bin Tools/cpm/{bin => bin80}/UNZIP186.COM | Bin Tools/cpm/{bin => bin80}/USQ.COM | Bin Tools/cpm/{bin => bin80}/Z80ASM.COM | Bin Tools/cpm/{bin => bin80}/ZMAC.COM | Bin Tools/cpm/{bin => bin80}/ZML.COM | Bin Tools/cpm/{bin => bin80}/ZMLIB.COM | Bin Tools/cpm/{bin => bin80}/ZSM.COM | Bin Tools/cpm/{include => include80}/CTYPE.H | 0 Tools/cpm/{include => include80}/ERRNO.H | 0 Tools/cpm/{include => include80}/FCNTL.H | 0 Tools/cpm/{include => include80}/IO.H | 0 Tools/cpm/{include => include80}/LIBC.H | 0 Tools/cpm/{include => include80}/MATH.H | 0 Tools/cpm/{include => include80}/SETJMP.H | 0 Tools/cpm/{include => include80}/SGTTY.H | 0 Tools/cpm/{include => include80}/STDIO.H | 0 Tools/cpm/{lib => lib80}/C.LIB | Bin Tools/cpm/{lib => lib80}/M.LIB | Bin Tools/cpm/{lib => lib80}/ROM.LIB | Bin Tools/cpm/{lib => lib80}/T.LIB | Bin Tools/unix/Makefile | 2 +- Tools/unix/zx/Makefile | 37 - Tools/unix/zx/config.h.darwin | 16 - Tools/unix/zx/config.h.linux | 17 - Tools/unix/zx/config.h.windows | 9 - Tools/unix/zx/cpmparse.c | 126 - Tools/unix/zx/readme.txt | 72 - Tools/unix/zx/xlt.c | 191 -- Tools/unix/zx/zx.html | 132 - Tools/unix/zxcc/Build-OW.cmd | 21 + Tools/unix/zxcc/Build-VC.cmd | 25 + Tools/unix/{zx => zxcc}/COPYING | 0 Tools/unix/zxcc/Clean.cmd | 11 + Tools/unix/zxcc/Makefile | 40 + Tools/unix/{zx => zxcc}/cbops.h | 344 +-- Tools/unix/zxcc/config.h.darwin | 6 + Tools/unix/zxcc/config.h.linux | 9 + Tools/unix/zxcc/config.h.windows | 5 + Tools/unix/{zx => zxcc/cpm}/bios.bin | Bin Tools/unix/{zx => zxcc}/cpm/bios.com | Bin Tools/unix/{zx => zxcc}/cpm/bios.lst | 0 Tools/unix/{zx => zxcc}/cpm/bios.z80 | 0 Tools/unix/{zx => zxcc}/cpmdrv.c | 14 +- Tools/unix/{zx => zxcc}/cpmglob.c | 37 +- Tools/unix/{zx => zxcc}/cpmint.h | 99 +- Tools/unix/zxcc/cpmparse.c | 126 + Tools/unix/{zx => zxcc}/cpmredir.c | 154 +- Tools/unix/{zx => zxcc}/cpmredir.h | 0 Tools/unix/{zx => zxcc}/dirent.c | 0 Tools/unix/{zx => zxcc}/dirent.h | 0 Tools/unix/{zx => zxcc}/drdos.c | 472 ++-- Tools/unix/{zx => zxcc}/edops.h | 0 Tools/unix/zxcc/readme.txt | 86 + Tools/unix/zxcc/track.c | 150 ++ Tools/unix/{zx => zxcc}/util.c | 99 +- Tools/unix/zxcc/xlt.c | 241 ++ Tools/unix/{zx => zxcc}/z80.c | 542 ++--- Tools/unix/{zx => zxcc}/z80.h | 172 +- Tools/unix/{zx => zxcc}/z80ops.h | 2664 ++++++++++----------- Tools/unix/{zx => zxcc}/zxbdos.c | 30 +- Tools/unix/{zx => zxcc}/zxbdos.h | 0 Tools/unix/{zx => zxcc}/zxcbdos.c | 32 +- Tools/unix/{zx => zxcc}/zxcbdos.h | 0 Tools/unix/{zx/zx.c => zxcc/zxcc.c} | 261 +- Tools/unix/zxcc/zxcc.doc | 207 ++ Tools/unix/{zx/zx.h => zxcc/zxcc.h} | 89 +- Tools/unix/zxcc/zxcc.html | 200 ++ Tools/unix/{zx => zxcc}/zxdbdos.c | 185 +- Tools/unix/{zx => zxcc}/zxdbdos.h | 0 Tools/zx/ReadMe.txt | 12 - Tools/zx/bios.bin | Bin 384 -> 0 bytes Tools/zx/zx-src.zip | Bin 58984 -> 0 bytes Tools/zx/zx.exe | Bin 94720 -> 0 bytes Tools/zx/zx.html | 132 - Tools/zx/zxdbg.exe | Bin 102400 -> 0 bytes Tools/{zx => zxcc}/COPYING | 0 Tools/zxcc/ReadMe.txt | 86 + Tools/{unix/zx/cpm => zxcc}/bios.bin | Bin Tools/zxcc/zxcc-src.zip | Bin 0 -> 69549 bytes Tools/zxcc/zxcc.exe | Bin 0 -> 95744 bytes Tools/zxcc/zxcc.html | 200 ++ Tools/zxcc/zxccdbg.exe | Bin 0 -> 104448 bytes 150 files changed, 4289 insertions(+), 3431 deletions(-) rename Tools/cpm/{bin => bin80}/ARCV.COM (100%) rename Tools/cpm/{bin => bin80}/AS.COM (100%) rename Tools/cpm/{bin => bin80}/BASCOM.COM (100%) rename Tools/cpm/{bin => bin80}/CC.COM (100%) rename Tools/cpm/{bin => bin80}/CNM.COM (100%) rename Tools/cpm/{bin => bin80}/CRC.COM (100%) rename Tools/cpm/{bin => bin80}/CREF80.COM (100%) rename Tools/cpm/{bin => bin80}/CZ.COM (100%) rename Tools/cpm/{bin => bin80}/DIRX.COM (100%) rename Tools/cpm/{bin => bin80}/DISKINFO.COM (100%) rename Tools/cpm/{bin => bin80}/GENCPM.COM (100%) rename Tools/cpm/{bin => bin80}/HEX80.COM (100%) rename Tools/cpm/{bin => bin80}/HEXCOM.COM (100%) rename Tools/cpm/{bin => bin80}/L80.COM (100%) rename Tools/cpm/{bin => bin80}/LBREXT.COM (100%) rename Tools/cpm/{bin => bin80}/LIB.COM (100%) rename Tools/cpm/{bin => bin80}/LIB80.COM (100%) rename Tools/cpm/{bin => bin80}/LIBUTIL.COM (100%) rename Tools/cpm/{bin => bin80}/LINK.COM (100%) rename Tools/cpm/{bin => bin80}/LN.COM (100%) rename Tools/cpm/{bin => bin80}/M80.COM (100%) rename Tools/cpm/{bin => bin80}/MAC.COM (100%) rename Tools/cpm/{bin => bin80}/MLOAD25.COM (100%) rename Tools/cpm/{bin => bin80}/NULU.COM (100%) rename Tools/cpm/{bin => bin80}/RMAC.COM (100%) rename Tools/cpm/{bin => bin80}/SIDSYM.COM (100%) rename Tools/cpm/{bin => bin80}/SLR180.COM (100%) rename Tools/cpm/{bin => bin80}/SLRMAC.COM (100%) rename Tools/cpm/{bin => bin80}/SLRNK.COM (100%) rename Tools/cpm/{bin => bin80}/SQZ.COM (100%) rename Tools/cpm/{bin => bin80}/TEX21.COM (100%) rename Tools/cpm/{bin => bin80}/TEX21A.COM (100%) rename Tools/cpm/{bin => bin80}/TEX21B.COM (100%) rename Tools/cpm/{bin => bin80}/UCRLZH.COM (100%) rename Tools/cpm/{bin => bin80}/UNARC.COM (100%) rename Tools/cpm/{bin => bin80}/UNCR.COM (100%) rename Tools/cpm/{bin => bin80}/UNZIP.COM (100%) rename Tools/cpm/{bin => bin80}/UNZIP154.COM (100%) rename Tools/cpm/{bin => bin80}/UNZIP186.COM (100%) rename Tools/cpm/{bin => bin80}/USQ.COM (100%) rename Tools/cpm/{bin => bin80}/Z80ASM.COM (100%) rename Tools/cpm/{bin => bin80}/ZMAC.COM (100%) rename Tools/cpm/{bin => bin80}/ZML.COM (100%) rename Tools/cpm/{bin => bin80}/ZMLIB.COM (100%) rename Tools/cpm/{bin => bin80}/ZSM.COM (100%) rename Tools/cpm/{include => include80}/CTYPE.H (100%) rename Tools/cpm/{include => include80}/ERRNO.H (100%) rename Tools/cpm/{include => include80}/FCNTL.H (100%) rename Tools/cpm/{include => include80}/IO.H (100%) rename Tools/cpm/{include => include80}/LIBC.H (100%) rename Tools/cpm/{include => include80}/MATH.H (100%) rename Tools/cpm/{include => include80}/SETJMP.H (100%) rename Tools/cpm/{include => include80}/SGTTY.H (100%) rename Tools/cpm/{include => include80}/STDIO.H (100%) rename Tools/cpm/{lib => lib80}/C.LIB (100%) rename Tools/cpm/{lib => lib80}/M.LIB (100%) rename Tools/cpm/{lib => lib80}/ROM.LIB (100%) rename Tools/cpm/{lib => lib80}/T.LIB (100%) delete mode 100644 Tools/unix/zx/Makefile delete mode 100644 Tools/unix/zx/config.h.darwin delete mode 100644 Tools/unix/zx/config.h.linux delete mode 100644 Tools/unix/zx/config.h.windows delete mode 100644 Tools/unix/zx/cpmparse.c delete mode 100644 Tools/unix/zx/readme.txt delete mode 100644 Tools/unix/zx/xlt.c delete mode 100644 Tools/unix/zx/zx.html create mode 100644 Tools/unix/zxcc/Build-OW.cmd create mode 100644 Tools/unix/zxcc/Build-VC.cmd rename Tools/unix/{zx => zxcc}/COPYING (100%) create mode 100644 Tools/unix/zxcc/Clean.cmd create mode 100644 Tools/unix/zxcc/Makefile rename Tools/unix/{zx => zxcc}/cbops.h (96%) create mode 100644 Tools/unix/zxcc/config.h.darwin create mode 100644 Tools/unix/zxcc/config.h.linux create mode 100644 Tools/unix/zxcc/config.h.windows rename Tools/unix/{zx => zxcc/cpm}/bios.bin (100%) rename Tools/unix/{zx => zxcc}/cpm/bios.com (100%) rename Tools/unix/{zx => zxcc}/cpm/bios.lst (100%) rename Tools/unix/{zx => zxcc}/cpm/bios.z80 (100%) rename Tools/unix/{zx => zxcc}/cpmdrv.c (96%) rename Tools/unix/{zx => zxcc}/cpmglob.c (94%) rename Tools/unix/{zx => zxcc}/cpmint.h (76%) create mode 100644 Tools/unix/zxcc/cpmparse.c rename Tools/unix/{zx => zxcc}/cpmredir.c (87%) rename Tools/unix/{zx => zxcc}/cpmredir.h (100%) rename Tools/unix/{zx => zxcc}/dirent.c (100%) rename Tools/unix/{zx => zxcc}/dirent.h (100%) rename Tools/unix/{zx => zxcc}/drdos.c (95%) rename Tools/unix/{zx => zxcc}/edops.h (100%) create mode 100644 Tools/unix/zxcc/readme.txt create mode 100644 Tools/unix/zxcc/track.c rename Tools/unix/{zx => zxcc}/util.c (83%) create mode 100644 Tools/unix/zxcc/xlt.c rename Tools/unix/{zx => zxcc}/z80.c (93%) rename Tools/unix/{zx => zxcc}/z80.h (96%) rename Tools/unix/{zx => zxcc}/z80ops.h (93%) rename Tools/unix/{zx => zxcc}/zxbdos.c (95%) rename Tools/unix/{zx => zxcc}/zxbdos.h (100%) rename Tools/unix/{zx => zxcc}/zxcbdos.c (77%) rename Tools/unix/{zx => zxcc}/zxcbdos.h (100%) rename Tools/unix/{zx/zx.c => zxcc/zxcc.c} (61%) create mode 100644 Tools/unix/zxcc/zxcc.doc rename Tools/unix/{zx/zx.h => zxcc/zxcc.h} (51%) create mode 100644 Tools/unix/zxcc/zxcc.html rename Tools/unix/{zx => zxcc}/zxdbdos.c (64%) rename Tools/unix/{zx => zxcc}/zxdbdos.h (100%) delete mode 100644 Tools/zx/ReadMe.txt delete mode 100644 Tools/zx/bios.bin delete mode 100644 Tools/zx/zx-src.zip delete mode 100644 Tools/zx/zx.exe delete mode 100644 Tools/zx/zx.html delete mode 100644 Tools/zx/zxdbg.exe rename Tools/{zx => zxcc}/COPYING (100%) create mode 100644 Tools/zxcc/ReadMe.txt rename Tools/{unix/zx/cpm => zxcc}/bios.bin (100%) create mode 100644 Tools/zxcc/zxcc-src.zip create mode 100644 Tools/zxcc/zxcc.exe create mode 100644 Tools/zxcc/zxcc.html create mode 100644 Tools/zxcc/zxccdbg.exe diff --git a/Source/Apps/Build.cmd b/Source/Apps/Build.cmd index cbcf8a01..675d1f44 100644 --- a/Source/Apps/Build.cmd +++ b/Source/Apps/Build.cmd @@ -4,13 +4,11 @@ setlocal set TOOLS=../../Tools set APPBIN=..\..\Binary\Apps -set PATH=%TOOLS%\tasm32;%TOOLS%\zx;%PATH% +set PATH=%TOOLS%\tasm32;%TOOLS%\zxcc;%PATH% set TASMTABS=%TOOLS%\tasm32 -set ZXBINDIR=%TOOLS%/cpm/bin/ -set ZXLIBDIR=%TOOLS%/cpm/lib/ -set ZXINCDIR=%TOOLS%/cpm/include/ +set CPMDIR80=%TOOLS%/cpm/ call :asm syscopy || exit /b call :asm assign || exit /b @@ -21,10 +19,10 @@ call :asm rtc || exit /b call :asm timer || exit /b call :asm rtchb || exit /b -zx Z80ASM -SYSGEN/F || exit /b +zxcc Z80ASM -SYSGEN/F || exit /b -zx MAC SURVEY.ASM -$PO || exit /b -zx MLOAD25 -SURVEY.COM=SURVEY.HEX || exit /b +zxcc MAC SURVEY.ASM -$PO || exit /b +zxcc MLOAD25 -SURVEY.COM=SURVEY.HEX || exit /b pushd XM && call Build || exit /b & popd pushd FDU && call Build || exit /b & popd diff --git a/Source/Apps/Test/Build.cmd b/Source/Apps/Test/Build.cmd index fb322d6b..ac6e0c2b 100644 --- a/Source/Apps/Test/Build.cmd +++ b/Source/Apps/Test/Build.cmd @@ -4,13 +4,11 @@ setlocal set TOOLS=../../../Tools set APPBIN=..\..\Binary\Apps -set PATH=%TOOLS%\tasm32;%TOOLS%\zx;%PATH% +set PATH=%TOOLS%\tasm32;%TOOLS%\zxcc;%PATH% set TASMTABS=%TOOLS%\tasm32 -set ZXBINDIR=%TOOLS%/cpm/bin/ -set ZXLIBDIR=%TOOLS%/cpm/lib/ -set ZXINCDIR=%TOOLS%/cpm/include/ +set CPMDIR80=%TOOLS%/cpm/ pushd DMAmon && call Build || exit /b & popd pushd tstdskng && call Build || exit /b & popd diff --git a/Source/Apps/XM/Build.cmd b/Source/Apps/XM/Build.cmd index fef70f92..cf07e3cd 100644 --- a/Source/Apps/XM/Build.cmd +++ b/Source/Apps/XM/Build.cmd @@ -3,22 +3,20 @@ setlocal set TOOLS=..\..\..\Tools -set PATH=%TOOLS%\zx;%PATH% +set PATH=%TOOLS%\zxcc;%PATH% -set ZXBINDIR=%TOOLS%\cpm\bin\ -set ZXLIBDIR=%TOOLS%\cpm\lib\ -set ZXINCDIR=%TOOLS%\cpm\include\ +set CPMDIR80=%TOOLS%/cpm/ -zx mac xmdm125.asm $PO || exit /b +zxcc mac xmdm125.asm $PO || exit /b -zx slr180 -xmhb/HF || exit /b -zx mload25 XM=xmdm125,xmhb || exit /b +zxcc slr180 -xmhb/HF || exit /b +zxcc mload25 XM=xmdm125,xmhb || exit /b -rem zx slr180 -xmuf/HF || exit /b -rem zx mload25 XMUF=xmdm125,xmuf || exit /b +rem zxcc slr180 -xmuf/HF || exit /b +rem zxcc mload25 XMUF=xmdm125,xmuf || exit /b -zx slr180 -xmhb_old/HF || exit /b -zx mload25 XMOLD=xmdm125,xmhb_old || exit /b +zxcc slr180 -xmhb_old/HF || exit /b +zxcc mload25 XMOLD=xmdm125,xmhb_old || exit /b rem set PROMPT=[Build] %PROMPT% rem %comspec% diff --git a/Source/Apps/XM/Makefile b/Source/Apps/XM/Makefile index 62c4f1e8..fc9a62e6 100644 --- a/Source/Apps/XM/Makefile +++ b/Source/Apps/XM/Makefile @@ -7,10 +7,10 @@ OTHERS = *.hex include $(TOOLS)/Makefile.inc xm.com: xmdm125.hex xmhb.hex - $(ZXCC) $(CPM)/MLOAD25 XM=xmdm125,xmhb + $(ZXCC) MLOAD25 XM=xmdm125,xmhb xmuf.com: xmdm125.hex xmuf.hex - $(ZXCC) $(CPM)/MLOAD25 XMUF=xmdm125,xmuf + $(ZXCC) MLOAD25 XMUF=xmdm125,xmuf xmold.com: xmdm125.hex xmhb_old.hex - $(ZXCC) $(CPM)/MLOAD25 XMOLD=xmdm125,xmhb_old + $(ZXCC) MLOAD25 XMOLD=xmdm125,xmhb_old diff --git a/Source/Apps/ZMD/Build.cmd b/Source/Apps/ZMD/Build.cmd index cc8d63d5..5d8d700d 100644 --- a/Source/Apps/ZMD/Build.cmd +++ b/Source/Apps/ZMD/Build.cmd @@ -3,35 +3,33 @@ setlocal set TOOLS=..\..\..\Tools -set PATH=%TOOLS%\zx;%PATH% +set PATH=%TOOLS%\zxcc;%PATH% -set ZXBINDIR=%TOOLS%\cpm\bin\ -set ZXLIBDIR=%TOOLS%\cpm\lib\ -set ZXINCDIR=%TOOLS%\cpm\include\ +set CPMDIR80=%TOOLS%/cpm/ -zx z80asm -zmd/fm -zx l80 -zmd,zmd/n/e +zxcc z80asm -zmd/fm +zxcc l80 -zmd,zmd/n/e -zx z80asm -zmap/fm -zx l80 -zmap,zmap/n/e +zxcc z80asm -zmap/fm +zxcc l80 -zmap,zmap/n/e -zx z80asm -znews/fm -zx l80 -znews,znews/n/e +zxcc z80asm -znews/fm +zxcc l80 -znews,znews/n/e -zx z80asm -znewp/fm -zx l80 -znewp,znewp/n/e +zxcc z80asm -znewp/fm +zxcc l80 -znewp,znewp/n/e -zx z80asm -zfors/fm -zx l80 -zfors,zfors/n/e +zxcc z80asm -zfors/fm +zxcc l80 -zfors,zfors/n/e -zx z80asm -zforp/fm -zx l80 -zforp,zforp/n/e +zxcc z80asm -zforp/fm +zxcc l80 -zforp,zforp/n/e -zx z80asm -zmdel/fm -zx l80 -zmdel,zmdel/n/e +zxcc z80asm -zmdel/fm +zxcc l80 -zmdel,zmdel/n/e -zx z80asm -zmdhb/fh -zx mload25 -zmd=zmd.com,zmdhb +zxcc z80asm -zmdhb/fh +zxcc mload25 -zmd=zmd.com,zmdhb copy /Y zmd.com ..\..\..\Binary\Apps\ || exit /b diff --git a/Source/Apps/ZMD/Makefile b/Source/Apps/ZMD/Makefile index 997b4997..70350198 100644 --- a/Source/Apps/ZMD/Makefile +++ b/Source/Apps/ZMD/Makefile @@ -6,5 +6,5 @@ OTHERS = *.hex zmd.rel include $(TOOLS)/Makefile.inc zmd.com: zmd.rel zmdhb.hex - $(ZXCC) $(CPM)/L80 -zmd,zmd/n/e - $(ZXCC) $(CPM)/MLOAD25 -zmd=zmd.com,zmdhb + $(ZXCC) L80 -zmd,zmd/n/e + $(ZXCC) MLOAD25 -zmd=zmd.com,zmdhb diff --git a/Source/Apps/ZMP/Build.cmd b/Source/Apps/ZMP/Build.cmd index 71f79633..8df63e1a 100644 --- a/Source/Apps/ZMP/Build.cmd +++ b/Source/Apps/ZMP/Build.cmd @@ -3,14 +3,12 @@ setlocal set TOOLS=..\..\..\Tools -set PATH=%TOOLS%\zx;%PATH% +set PATH=%TOOLS%\zxcc;%PATH% -set ZXBINDIR=%TOOLS%\cpm\bin\ -set ZXLIBDIR=%TOOLS%\cpm\lib\ -set ZXINCDIR=%TOOLS%\cpm\include\ +set CPMDIR80=%TOOLS%/cpm/ -zx Z80ASM -ZMO-RW01/H || exit /b -zx MLOAD25 -ZMP.COM=ZMPX.COM,ZMO-RW01 || exit /b +zxcc Z80ASM -ZMO-RW01/H || exit /b +zxcc MLOAD25 -ZMP.COM=ZMPX.COM,ZMO-RW01 || exit /b copy /Y zmp.com ..\..\..\Binary\Apps\ || exit /b copy /Y *.ovr ..\..\..\Binary\Apps\ || exit /b diff --git a/Source/Apps/ZMP/Makefile b/Source/Apps/ZMP/Makefile index 09abd053..11574dd6 100644 --- a/Source/Apps/ZMP/Makefile +++ b/Source/Apps/ZMP/Makefile @@ -7,4 +7,4 @@ NODELETE = *.ovr zmp.doc *.hlp include $(TOOLS)/Makefile.inc zmp.com: zmo-rw01.hex - $(ZXCC) $(CPM)/MLOAD25 -ZMP.COM=ZMPX.COM,ZMO-RW01 + $(ZXCC) MLOAD25 -ZMP.COM=ZMPX.COM,ZMO-RW01 diff --git a/Source/BPBIOS/Build.cmd b/Source/BPBIOS/Build.cmd index 90aa684f..184aafec 100644 --- a/Source/BPBIOS/Build.cmd +++ b/Source/BPBIOS/Build.cmd @@ -3,11 +3,9 @@ setlocal pushd ZCPR33 && call Build || exit /b & popd -set PATH=%PATH%;..\..\Tools\zx;..\..\Tools\cpmtools; +set PATH=%PATH%;..\..\Tools\zxcc;..\..\Tools\cpmtools; -set ZXBINDIR=../../tools/cpm/bin/ -set ZXLIBDIR=../../tools/cpm/lib/ -set ZXINCDIR=../../tools/cpm/include/ +set CPMDIR80=%TOOLS%/cpm/ call :makebp 33 call :makebp 33bnk @@ -45,7 +43,7 @@ echo. copy def-ww-z%VER%.lib def-ww.lib || exit /b rem if exist bpbio-ww.rel del bpbio-ww.rel || exit /b -zx ZMAC -BPBIO-WW -/P || exit /b +zxcc ZMAC -BPBIO-WW -/P || exit /b if exist bp%VER%.prn del bp%VER%.prn || exit /b ren bpbio-ww.prn bp%VER%.prn || exit /b if exist bp%VER%.err del bp%VER%.err || exit /b @@ -56,18 +54,18 @@ rem pause rem BPBUILD attempts to rename bpsys.img -> bpsys.bak rem while is is still open. Real CP/M does not care, -rem but zx fails due to host OS. Below, a temp file +rem but zxcc fails due to host OS. Below, a temp file rem is used to avoid the problematic rename. if exist bpsys.img del bpsys.img || exit /b if exist bpsys.tmp del bpsys.tmp || exit /b copy bp%VER%.dat bpsys.tmp || exit /b rem bpsys.tmp -> bpsys.img -zx bpbuild -bpsys.tmp bpsys.img -zx bpbuild -bpsys.tmp $@ diff --git a/Tools/Makefile.inc b/Tools/Makefile.inc index 70820679..59b7e6d5 100644 --- a/Tools/Makefile.inc +++ b/Tools/Makefile.inc @@ -37,7 +37,8 @@ CASEFN = $(TOOLS)/unix/casefn.sh # # compiler/assembler locations and flags # -ZXCC=$(BINDIR)/zx +ZXCC=$(BINDIR)/zxcc +export CPMDIR80=$(TOOLS)/cpm/ TASM=$(BINDIR)/uz80as -t z80 TASMFLAGS= OPENSPIN=$(BINDIR)/openspin @@ -48,7 +49,7 @@ CPMCHATTR=$(BINDIR)/cpmchattr # # directory containing cpm binaries # -CPM=$(TOOLS)/cpm/bin +CPM=$(TOOLS)/cpm/bin80/ # # .ONESHELL uses a single shell instance for all shell scripts. diff --git a/Tools/cpm/bin/ARCV.COM b/Tools/cpm/bin80/ARCV.COM similarity index 100% rename from Tools/cpm/bin/ARCV.COM rename to Tools/cpm/bin80/ARCV.COM diff --git a/Tools/cpm/bin/AS.COM b/Tools/cpm/bin80/AS.COM similarity index 100% rename from Tools/cpm/bin/AS.COM rename to Tools/cpm/bin80/AS.COM diff --git a/Tools/cpm/bin/BASCOM.COM b/Tools/cpm/bin80/BASCOM.COM similarity index 100% rename from Tools/cpm/bin/BASCOM.COM rename to Tools/cpm/bin80/BASCOM.COM diff --git a/Tools/cpm/bin/CC.COM b/Tools/cpm/bin80/CC.COM similarity index 100% rename from Tools/cpm/bin/CC.COM rename to Tools/cpm/bin80/CC.COM diff --git a/Tools/cpm/bin/CNM.COM b/Tools/cpm/bin80/CNM.COM similarity index 100% rename from Tools/cpm/bin/CNM.COM rename to Tools/cpm/bin80/CNM.COM diff --git a/Tools/cpm/bin/CRC.COM b/Tools/cpm/bin80/CRC.COM similarity index 100% rename from Tools/cpm/bin/CRC.COM rename to Tools/cpm/bin80/CRC.COM diff --git a/Tools/cpm/bin/CREF80.COM b/Tools/cpm/bin80/CREF80.COM similarity index 100% rename from Tools/cpm/bin/CREF80.COM rename to Tools/cpm/bin80/CREF80.COM diff --git a/Tools/cpm/bin/CZ.COM b/Tools/cpm/bin80/CZ.COM similarity index 100% rename from Tools/cpm/bin/CZ.COM rename to Tools/cpm/bin80/CZ.COM diff --git a/Tools/cpm/bin/DIRX.COM b/Tools/cpm/bin80/DIRX.COM similarity index 100% rename from Tools/cpm/bin/DIRX.COM rename to Tools/cpm/bin80/DIRX.COM diff --git a/Tools/cpm/bin/DISKINFO.COM b/Tools/cpm/bin80/DISKINFO.COM similarity index 100% rename from Tools/cpm/bin/DISKINFO.COM rename to Tools/cpm/bin80/DISKINFO.COM diff --git a/Tools/cpm/bin/GENCPM.COM b/Tools/cpm/bin80/GENCPM.COM similarity index 100% rename from Tools/cpm/bin/GENCPM.COM rename to Tools/cpm/bin80/GENCPM.COM diff --git a/Tools/cpm/bin/HEX80.COM b/Tools/cpm/bin80/HEX80.COM similarity index 100% rename from Tools/cpm/bin/HEX80.COM rename to Tools/cpm/bin80/HEX80.COM diff --git a/Tools/cpm/bin/HEXCOM.COM b/Tools/cpm/bin80/HEXCOM.COM similarity index 100% rename from Tools/cpm/bin/HEXCOM.COM rename to Tools/cpm/bin80/HEXCOM.COM diff --git a/Tools/cpm/bin/L80.COM b/Tools/cpm/bin80/L80.COM similarity index 100% rename from Tools/cpm/bin/L80.COM rename to Tools/cpm/bin80/L80.COM diff --git a/Tools/cpm/bin/LBREXT.COM b/Tools/cpm/bin80/LBREXT.COM similarity index 100% rename from Tools/cpm/bin/LBREXT.COM rename to Tools/cpm/bin80/LBREXT.COM diff --git a/Tools/cpm/bin/LIB.COM b/Tools/cpm/bin80/LIB.COM similarity index 100% rename from Tools/cpm/bin/LIB.COM rename to Tools/cpm/bin80/LIB.COM diff --git a/Tools/cpm/bin/LIB80.COM b/Tools/cpm/bin80/LIB80.COM similarity index 100% rename from Tools/cpm/bin/LIB80.COM rename to Tools/cpm/bin80/LIB80.COM diff --git a/Tools/cpm/bin/LIBUTIL.COM b/Tools/cpm/bin80/LIBUTIL.COM similarity index 100% rename from Tools/cpm/bin/LIBUTIL.COM rename to Tools/cpm/bin80/LIBUTIL.COM diff --git a/Tools/cpm/bin/LINK.COM b/Tools/cpm/bin80/LINK.COM similarity index 100% rename from Tools/cpm/bin/LINK.COM rename to Tools/cpm/bin80/LINK.COM diff --git a/Tools/cpm/bin/LN.COM b/Tools/cpm/bin80/LN.COM similarity index 100% rename from Tools/cpm/bin/LN.COM rename to Tools/cpm/bin80/LN.COM diff --git a/Tools/cpm/bin/M80.COM b/Tools/cpm/bin80/M80.COM similarity index 100% rename from Tools/cpm/bin/M80.COM rename to Tools/cpm/bin80/M80.COM diff --git a/Tools/cpm/bin/MAC.COM b/Tools/cpm/bin80/MAC.COM similarity index 100% rename from Tools/cpm/bin/MAC.COM rename to Tools/cpm/bin80/MAC.COM diff --git a/Tools/cpm/bin/MLOAD25.COM b/Tools/cpm/bin80/MLOAD25.COM similarity index 100% rename from Tools/cpm/bin/MLOAD25.COM rename to Tools/cpm/bin80/MLOAD25.COM diff --git a/Tools/cpm/bin/NULU.COM b/Tools/cpm/bin80/NULU.COM similarity index 100% rename from Tools/cpm/bin/NULU.COM rename to Tools/cpm/bin80/NULU.COM diff --git a/Tools/cpm/bin/RMAC.COM b/Tools/cpm/bin80/RMAC.COM similarity index 100% rename from Tools/cpm/bin/RMAC.COM rename to Tools/cpm/bin80/RMAC.COM diff --git a/Tools/cpm/bin/SIDSYM.COM b/Tools/cpm/bin80/SIDSYM.COM similarity index 100% rename from Tools/cpm/bin/SIDSYM.COM rename to Tools/cpm/bin80/SIDSYM.COM diff --git a/Tools/cpm/bin/SLR180.COM b/Tools/cpm/bin80/SLR180.COM similarity index 100% rename from Tools/cpm/bin/SLR180.COM rename to Tools/cpm/bin80/SLR180.COM diff --git a/Tools/cpm/bin/SLRMAC.COM b/Tools/cpm/bin80/SLRMAC.COM similarity index 100% rename from Tools/cpm/bin/SLRMAC.COM rename to Tools/cpm/bin80/SLRMAC.COM diff --git a/Tools/cpm/bin/SLRNK.COM b/Tools/cpm/bin80/SLRNK.COM similarity index 100% rename from Tools/cpm/bin/SLRNK.COM rename to Tools/cpm/bin80/SLRNK.COM diff --git a/Tools/cpm/bin/SQZ.COM b/Tools/cpm/bin80/SQZ.COM similarity index 100% rename from Tools/cpm/bin/SQZ.COM rename to Tools/cpm/bin80/SQZ.COM diff --git a/Tools/cpm/bin/TEX21.COM b/Tools/cpm/bin80/TEX21.COM similarity index 100% rename from Tools/cpm/bin/TEX21.COM rename to Tools/cpm/bin80/TEX21.COM diff --git a/Tools/cpm/bin/TEX21A.COM b/Tools/cpm/bin80/TEX21A.COM similarity index 100% rename from Tools/cpm/bin/TEX21A.COM rename to Tools/cpm/bin80/TEX21A.COM diff --git a/Tools/cpm/bin/TEX21B.COM b/Tools/cpm/bin80/TEX21B.COM similarity index 100% rename from Tools/cpm/bin/TEX21B.COM rename to Tools/cpm/bin80/TEX21B.COM diff --git a/Tools/cpm/bin/UCRLZH.COM b/Tools/cpm/bin80/UCRLZH.COM similarity index 100% rename from Tools/cpm/bin/UCRLZH.COM rename to Tools/cpm/bin80/UCRLZH.COM diff --git a/Tools/cpm/bin/UNARC.COM b/Tools/cpm/bin80/UNARC.COM similarity index 100% rename from Tools/cpm/bin/UNARC.COM rename to Tools/cpm/bin80/UNARC.COM diff --git a/Tools/cpm/bin/UNCR.COM b/Tools/cpm/bin80/UNCR.COM similarity index 100% rename from Tools/cpm/bin/UNCR.COM rename to Tools/cpm/bin80/UNCR.COM diff --git a/Tools/cpm/bin/UNZIP.COM b/Tools/cpm/bin80/UNZIP.COM similarity index 100% rename from Tools/cpm/bin/UNZIP.COM rename to Tools/cpm/bin80/UNZIP.COM diff --git a/Tools/cpm/bin/UNZIP154.COM b/Tools/cpm/bin80/UNZIP154.COM similarity index 100% rename from Tools/cpm/bin/UNZIP154.COM rename to Tools/cpm/bin80/UNZIP154.COM diff --git a/Tools/cpm/bin/UNZIP186.COM b/Tools/cpm/bin80/UNZIP186.COM similarity index 100% rename from Tools/cpm/bin/UNZIP186.COM rename to Tools/cpm/bin80/UNZIP186.COM diff --git a/Tools/cpm/bin/USQ.COM b/Tools/cpm/bin80/USQ.COM similarity index 100% rename from Tools/cpm/bin/USQ.COM rename to Tools/cpm/bin80/USQ.COM diff --git a/Tools/cpm/bin/Z80ASM.COM b/Tools/cpm/bin80/Z80ASM.COM similarity index 100% rename from Tools/cpm/bin/Z80ASM.COM rename to Tools/cpm/bin80/Z80ASM.COM diff --git a/Tools/cpm/bin/ZMAC.COM b/Tools/cpm/bin80/ZMAC.COM similarity index 100% rename from Tools/cpm/bin/ZMAC.COM rename to Tools/cpm/bin80/ZMAC.COM diff --git a/Tools/cpm/bin/ZML.COM b/Tools/cpm/bin80/ZML.COM similarity index 100% rename from Tools/cpm/bin/ZML.COM rename to Tools/cpm/bin80/ZML.COM diff --git a/Tools/cpm/bin/ZMLIB.COM b/Tools/cpm/bin80/ZMLIB.COM similarity index 100% rename from Tools/cpm/bin/ZMLIB.COM rename to Tools/cpm/bin80/ZMLIB.COM diff --git a/Tools/cpm/bin/ZSM.COM b/Tools/cpm/bin80/ZSM.COM similarity index 100% rename from Tools/cpm/bin/ZSM.COM rename to Tools/cpm/bin80/ZSM.COM diff --git a/Tools/cpm/include/CTYPE.H b/Tools/cpm/include80/CTYPE.H similarity index 100% rename from Tools/cpm/include/CTYPE.H rename to Tools/cpm/include80/CTYPE.H diff --git a/Tools/cpm/include/ERRNO.H b/Tools/cpm/include80/ERRNO.H similarity index 100% rename from Tools/cpm/include/ERRNO.H rename to Tools/cpm/include80/ERRNO.H diff --git a/Tools/cpm/include/FCNTL.H b/Tools/cpm/include80/FCNTL.H similarity index 100% rename from Tools/cpm/include/FCNTL.H rename to Tools/cpm/include80/FCNTL.H diff --git a/Tools/cpm/include/IO.H b/Tools/cpm/include80/IO.H similarity index 100% rename from Tools/cpm/include/IO.H rename to Tools/cpm/include80/IO.H diff --git a/Tools/cpm/include/LIBC.H b/Tools/cpm/include80/LIBC.H similarity index 100% rename from Tools/cpm/include/LIBC.H rename to Tools/cpm/include80/LIBC.H diff --git a/Tools/cpm/include/MATH.H b/Tools/cpm/include80/MATH.H similarity index 100% rename from Tools/cpm/include/MATH.H rename to Tools/cpm/include80/MATH.H diff --git a/Tools/cpm/include/SETJMP.H b/Tools/cpm/include80/SETJMP.H similarity index 100% rename from Tools/cpm/include/SETJMP.H rename to Tools/cpm/include80/SETJMP.H diff --git a/Tools/cpm/include/SGTTY.H b/Tools/cpm/include80/SGTTY.H similarity index 100% rename from Tools/cpm/include/SGTTY.H rename to Tools/cpm/include80/SGTTY.H diff --git a/Tools/cpm/include/STDIO.H b/Tools/cpm/include80/STDIO.H similarity index 100% rename from Tools/cpm/include/STDIO.H rename to Tools/cpm/include80/STDIO.H diff --git a/Tools/cpm/lib/C.LIB b/Tools/cpm/lib80/C.LIB similarity index 100% rename from Tools/cpm/lib/C.LIB rename to Tools/cpm/lib80/C.LIB diff --git a/Tools/cpm/lib/M.LIB b/Tools/cpm/lib80/M.LIB similarity index 100% rename from Tools/cpm/lib/M.LIB rename to Tools/cpm/lib80/M.LIB diff --git a/Tools/cpm/lib/ROM.LIB b/Tools/cpm/lib80/ROM.LIB similarity index 100% rename from Tools/cpm/lib/ROM.LIB rename to Tools/cpm/lib80/ROM.LIB diff --git a/Tools/cpm/lib/T.LIB b/Tools/cpm/lib80/T.LIB similarity index 100% rename from Tools/cpm/lib/T.LIB rename to Tools/cpm/lib80/T.LIB diff --git a/Tools/unix/Makefile b/Tools/unix/Makefile index cba1782e..571e876d 100644 --- a/Tools/unix/Makefile +++ b/Tools/unix/Makefile @@ -9,7 +9,7 @@ ifeq ($(UNAME), Darwin) SUFFIX=osx endif -SUBDIRS = bst uz80as zx cpmtools bin2asm lzsa +SUBDIRS = bst uz80as zxcc cpmtools bin2asm lzsa all: @chmod +x casefn.sh diff --git a/Tools/unix/zx/Makefile b/Tools/unix/zx/Makefile deleted file mode 100644 index 862ec7a3..00000000 --- a/Tools/unix/zx/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -# -# hacked up brute force makefile for linux and osx -# -UNAME := $(shell uname) -ifeq ($(UNAME), Linux) - SUFFIX=linux -endif -ifeq ($(UNAME), Darwin) - SUFFIX=darwin -endif - -DEST = ../../$(UNAME) -CFLAGS = -g # -DDEBUG - -OBJECTS = zx.o cpmdrv.o cpmglob.o cpmparse.o cpmredir.o \ - drdos.o util.o xlt.o zxbdos.o zxcbdos.o zxdbdos.o z80.o -UNUSED = dirent.o - -all: zx $(DEST) - cp -p bios.bin zx $(DEST) - -$(DEST): - mkdir -p $(DEST) - -clean: - -rm -f $(OBJECTS) config.h zx - -clobber: clean - -rm -f $(DEST)/zx $(DEST)/bios.bin zx - -$(OBJECTS): config.h - -zx: $(OBJECTS) - $(CC) -o zx $(OBJECTS) - -config.h: config.h.$(SUFFIX) - cp config.h.$(SUFFIX) config.h diff --git a/Tools/unix/zx/config.h.darwin b/Tools/unix/zx/config.h.darwin deleted file mode 100644 index cc4b425c..00000000 --- a/Tools/unix/zx/config.h.darwin +++ /dev/null @@ -1,16 +0,0 @@ -//#define HAVE_WINDOWS_H -#define HAVE_DIRENT_H -#define HAVE_UTIME_H -#define HAVE_FCNTL_H -#define HAVE_UNISTD_H -#define BINDIR80 getenv("ZXBINDIR") -#define LIBDIR80 getenv("ZXLIBDIR") -#define INCDIR80 getenv("ZXINCDIR") -#define DARWIN -#include -#include -#define _S_IFDIR S_IFDIR -#define strcmpi(a,b) strcasecmp(a,b) -//#define WIN32 -//#define WINVER 0x0501 // target Windows XP -//#define _WIN32_WINNNT 0x0501 // target Windows XP diff --git a/Tools/unix/zx/config.h.linux b/Tools/unix/zx/config.h.linux deleted file mode 100644 index a015591c..00000000 --- a/Tools/unix/zx/config.h.linux +++ /dev/null @@ -1,17 +0,0 @@ -//#define HAVE_WINDOWS_H -#define HAVE_DIRENT_H -#define HAVE_UTIME_H -#define HAVE_FCNTL_H -#define HAVE_SYS_VFS_H -#define HAVE_UNISTD_H -#define BINDIR80 getenv("ZXBINDIR") -#define LIBDIR80 getenv("ZXLIBDIR") -#define INCDIR80 getenv("ZXINCDIR") -#define LINUX -#include -#include -#define _S_IFDIR S_IFDIR -#define strcmpi(a,b) strcasecmp(a,b) -//#define WIN32 -//#define WINVER 0x0501 // target Windows XP -//#define _WIN32_WINNNT 0x0501 // target Windows XP diff --git a/Tools/unix/zx/config.h.windows b/Tools/unix/zx/config.h.windows deleted file mode 100644 index 8186c485..00000000 --- a/Tools/unix/zx/config.h.windows +++ /dev/null @@ -1,9 +0,0 @@ -#define HAVE_WINDOWS_H -//#define HAVE_DIRENT_H -#define HAVE_FCNTL_H -#define BINDIR80 getenv("ZXBINDIR") -#define LIBDIR80 getenv("ZXLIBDIR") -#define INCDIR80 getenv("ZXINCDIR") -#define WIN32 -#define WINVER 0x0501 // target Windows XP -#define _WIN32_WINNNT 0x0501 // target Windows XP diff --git a/Tools/unix/zx/cpmparse.c b/Tools/unix/zx/cpmparse.c deleted file mode 100644 index 4c709ec1..00000000 --- a/Tools/unix/zx/cpmparse.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - - CPMREDIR: CP/M filesystem redirector - Copyright (C) 1998, John Elliott - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - This file parses filenames to FCBs. -*/ - -#include "cpmint.h" - -#define is_num(c) ((c >= '0') && (c <= '9')) - -static int parse_drive_user(char *txt, cpm_byte *fcb) -{ - char uid[4], drvid[4]; - int up, dp; - - for (up = dp = 0; *txt != ':'; ++txt) - { - if (is_num (*txt)) uid [up++] = *txt; - if (isalpha(*txt)) drvid[dp++] = *txt; - if (!is_num(*txt) && !isalpha(*txt)) return -1; - } - uid[up] = 0; drvid[dp] = 0; - - if (dp > 1) return -1; /* Invalid driveletter */ - if (up > 2) return -1; /* Invalid uid */ - - fcb[0x0d] = atoi(uid) + 1; if (fcb[0x0d] > 16) return -1; - - if (islower(drvid[0])) drvid[0] = toupper(drvid[0]); - - if (drvid[0] < 'A' || drvid[0] > 'P') return -1; - - fcb[0] = drvid[0] - '@'; - return 0; -} - - - -cpm_word fcb_parse(char *txt, cpm_byte *fcb) -{ - int nl = 0, tl = 0, pl = 0, phase = 0; - char *ntxt, ch; - - memset(fcb, 0, 0x24); - - if (txt[1] == ':' || txt[2] == ':' || txt[3] == ':') - { - if (parse_drive_user(txt, fcb)) return 0xFFFF; - /* Move past the colon */ - ntxt = strchr(txt, ':') + 1; - } - else ntxt = txt; - while (phase < 3) - { - ch = *ntxt; - if (islower(ch)) ch = toupper(ch); - - switch(ch) - { - case 0: - case '\r': /* EOL */ - phase = 4; - break; - - case '.': /* file.typ */ - if (!phase) ++phase; - else phase = 3; - break; - - case ';': /* Password */ - if (phase < 2) phase = 2; - else phase = 3; - break; - - case '[': case ']': case '=': case 9: case ' ': - case '>': case '<': case ':': case ',': case '/': - case '|': /* Terminator */ - phase = 3; - - default: - switch(phase) - { - case 0: - if (nl >= 8) return 0xFFFF; - fcb[++nl] = ch; - break; - - case 1: - if (tl >= 3) return 0xFFFF; - fcb[tl + 9] = ch; - ++tl; - break; - - case 2: - if (pl >= 8) return 0xFFFF; - fcb[pl + 0x10] = ch; - ++pl; - break; - } - break; - } - } - if (!nl) return 0xFFFF; - - fcb[0x1A] = pl; - - if (phase == 4) return 0; - - return ntxt - txt; -} diff --git a/Tools/unix/zx/readme.txt b/Tools/unix/zx/readme.txt deleted file mode 100644 index 15feb3e8..00000000 --- a/Tools/unix/zx/readme.txt +++ /dev/null @@ -1,72 +0,0 @@ -ZX Command - -An adaptation of zxcc-0.5.6 by Wayne Warthen - -This directory contains the source files used to build the "zx" tool. This tool -is essentially just John Elliott's zxcc package version zxcc-0.5.6 modified to -build for Windows and simplified down to just a single command (zx) -which is essentially just the zxcc command. - -Please see http://www.seasip.info/Unix/Zxcc/ for more information on zxcc. - -Note that this is a Win32 build. The code has not been updated to build as a 64-bit -binary. However, Win32 binaries run very nicely under 64 bit Windows. - -To build under Open Watcom or Microsoft Visual C++, use the following command: - - cl /Fe"zx.exe" zx.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c dirent.c - -To build a debug version, use the following command: - - cl /DDEBUG /Fe"zxdbg.exe" zx.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c dirent.c - -WARNING: There seems to be a rare scenario that breaks zx under the Open Watcom build. -CP/M allows a file to be accessed under multiple FCB's without an error. Open Watcom -will see this as an error. At present, the only tool I know of that does this is M80. - -December 5, 2014 - -After struggling to get the entire zxcc package to build nicely using autoconf, -I finally gave up and took a much more direct approach. I have extracted just -the source files needed and created a simple batch file to build the tool. I -realize this could be done much better, but I cheated in the interest of time. - -The one "real" change I made in the source code was that I modified the tool -to look for bios.bin in the same directory as the executable is in. This -just makes it much easier to set up (for me, anyway). - -The GPL status of everything remains in place and carries forward. - -Wayne Warthen -wwarthen@gmail.com - -March 15, 2017 - -- Updated to compile under Open Watcom. -- Implemented BDOS console status function. -- Set stdin and stdout to binary mode at startup. - -August 21, 2021 - -- Incorporated filename case insensitivity changes from Curt Mayer -- Incorporated fixes from Tony Nicholson at https://github.com/agn453/ZXCC - - Emulation of CP/M BDOS function 60 (call resident system extension) - should be disabled and return 0xFF in both the A and L registers. - - Change cpm_bdos_10() to return an unsigned result to avoid buffer - size being interpreted as negative. - - Fix the emulation of Z80 opcodes for IN (HL),(C) and - OUT (C),(HL) - opcodes 0xED,0x70 and 0xED,0x71 respectively. - This is noted in Fred Weigel's AM9511 arithmetic processing unit - emulation from https://github.com/ratboy666/am9511 in the howto.txt - description. NB: I have not included Fred's am9511 support at this - time into ZXCC. -- Fixed parse_to_fcb function in zx.c to handle parsing second automatic - FCB from command line -- I have not been able to reproduce the multiple FCBs referring to a - single file issue with Watcom documented above. Perhaps I fixed it - and don't remember or I found a bug-fixed version of M80. Not sure. - -Wayne Warthen -wwarthen@gmail.com - ---WBW 4:09 PM 8/21/2021 \ No newline at end of file diff --git a/Tools/unix/zx/xlt.c b/Tools/unix/zx/xlt.c deleted file mode 100644 index f0ba1da5..00000000 --- a/Tools/unix/zx/xlt.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - - CPMREDIR: CP/M filesystem redirector - Copyright (C) 1998, John Elliott - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - This file holds functions dealing with name translation; also the - initialisation code. -*/ - -#include "cpmint.h" - -/* Detect DRDOS */ - -#ifdef __MSDOS__ -static void drdos_init(void) -{ - -/* The DJGPP DOS extender won't detect DRDOS using intdos(), so we have - to use __dpmi_int() instead. */ - -#ifdef __GO32__ - __dpmi_regs ir; - - ir.x.ax = 0x4452; /* "DR" */ - - __dpmi_int(0x21, &ir); - if (ir.x.flags & 1) return; /* Not DRDOS */ - - redir_Msg("DRDOS detected.\r\n"); - - redir_drdos = 1; - -#else /* __GO32__ */ - - union REGS ir, or; - - ir.w.ax = 0x4452; /* "DR" */ - - intdos(&ir, &or); - if (or.w.cflag) return; /* Not DRDOS */ - - redir_Msg("DRDOS detected.\r\n"); - - redir_drdos = 1; -#endif /* __GO32__ */ -} -#endif /* __MSDOS__ */ - - - -int fcb_init(void) -{ - int n; - - /* A: to O: free */ - for (n = 0; n < 15; n++) redir_drive_prefix[n][0] = 0; - - strcpy(redir_drive_prefix[15], "./"); /* P: is current directory */ - - /* Log on to P:. It is the only drive at this point which we - * know works. */ - redir_cpmdrive = 15; -#ifdef __MSDOS__ - drdos_init(); -#endif - - return 1; -} - -/* Deinitialise the library. */ - -void fcb_deinit(void) -{ - /* Nothing */ -} - -/* Translate a name from the host FS to a CP/M name. This will (if necessary) - * create a mapping between a CP/M drive and a host directory path. - * - * CP/M drives A: to O: can be mapped in this way. P: is always the current - * drive. - * - */ - -void xlt_name(char *localname, char *cpmname) -{ - char ibuf[CPM_MAXPATH + 1]; - char nbuf[CPM_MAXPATH + 1]; - char *pname; - int n; - - sprintf(ibuf, "%-.*s", CPM_MAXPATH, localname); - pname = strrchr(ibuf, '/'); -#ifdef __MSDOS__ - if (!pname) pname = strrchr(ibuf,'\\'); - if (!pname) pname = strrchr(ibuf,':'); -#endif - if (!pname) /* No path separators in the name. It is therefore a - local filename, so map it to drive P: */ - { - strcpy(cpmname, "p:"); - strcat(cpmname, ibuf); - return; - } - ++pname; - strcpy(nbuf, pname); /* nbuf holds filename component */ - *pname = 0; /* ibuf holds path component */ - - /* See if the path is one of those already mapped to drives */ - - for (n = 0; n < 15; n++) - { - if (redir_drive_prefix[n][0] && !strcmp(ibuf, redir_drive_prefix[n])) - { - sprintf(cpmname,"%c:%s", n + 'a', nbuf); - return; - } - } - - /* It is not, see if another drive can be allocated */ - - for (n = 0; n < 15; n++) if (!redir_drive_prefix[n][0]) - { - strcpy(redir_drive_prefix[n], ibuf); - sprintf(cpmname,"%c:%s", n + 'a', nbuf); - return; - } - - /* No other drive can be allocated */ - - strcpy(cpmname,"p:"); - strcat(cpmname, nbuf); -} - -/* It is sometimes convenient to set some fixed mappings. This will create - * a mapping for a given directory. - * Pass drive = -1 for "first available", or 0-15 for A: to P: - */ - -int xlt_map(int drive, char *localdir) -{ - int n; - - if (drive == -1) - { - for (n = 0; n < 15; n++) if (!redir_drive_prefix[n][0]) - { - drive = n; - break; - } - if (drive == -1) return 0; /* No space for mappings */ - } - if (redir_drive_prefix[drive][0]) return 0; /* Drive taken */ - - sprintf(redir_drive_prefix[drive], "%-.*s", CPM_MAXPATH, localdir); - return 1; -} - - -/* Unmap a drive - */ - -int xlt_umap(int drive) -{ - if (!redir_drive_prefix[drive][0]) return 0; /* Drive not taken */ - redir_drive_prefix[drive][0] = 0; - return 1; -} - - -char *xlt_getcwd(int drive) -{ - if (drive < 0 || drive > 16) return ""; - - return redir_drive_prefix[drive]; -} - diff --git a/Tools/unix/zx/zx.html b/Tools/unix/zx/zx.html deleted file mode 100644 index ff2da790..00000000 --- a/Tools/unix/zx/zx.html +++ /dev/null @@ -1,132 +0,0 @@ -zx CP/M Command Line Emulator - -

zx CP/M Command Line Emulator

- -

zx allows execution of CP/M 2.2 and 3.X application from a -Windows command line. It is compatible with Windows XP and greater (both -32 and 64 bit).

- -

zx is basically a port of a subset of the zxcc program by John Elliott. -The GPLv2 licensing carries forward. Please refer to the - -zxcc web page for more information.

- -

While the original zxcc package was generally intended to allow -execution of the Hi-Tech C CP/M compiler under Unix, zx is slightly -more general and intended to allow running most CP/M tools. Specific -changes were incorporated to improve interactice console operation of -CP/M applications. Additionally, Curt Mayer added case insensitivity -for filenames under Unix variants.

- -

Setup

- -

The zx application (zx.exe) may be copied to any directory for execution. -The bios.bin file must be copied to the same directory. For ease of use, -you will probably want the directory to part of your PATH environment -variable so that you can run the tool from any location.

- -

You will also need the CP/M applications that you want to run. -zx will load files fromthe current directory or one of the following -directories based on file type. Any of the following environment -variables may be defined to determine where zx searches for the -respective file types:

- -
    -
  • ZXBINDIR may contain a single path which will -be searched for executable files (usually *.com)
  • -
  • ZXLIBDIR may contain a single path which will -be search for library files (usually *.lib)
  • -
  • ZXINCDIR may contain a single path which will -be searched for include files (usually *.inc)
  • -
- -

Usage

- -

In general CP/M applications are executed by prefixing the CP/M command -line with "zx". So for example, you could assemble a test.asm using -rmac with a command line like:

- -
zx rmac hello
- -

In this case, rmac.com would need to be in the directory specified by -environment variable ZXBINDIR or in the current directory. Also, -hello.asm would need to be in the current directory.

- -

Filenames

- -

Where you would normally enter a CP/M filename you instead enter -a Windows filename. Note that you will need to use a forward slash -instead of the traditional backslash as a directory separator. The -filename itself (as opposed to any directories in -its path) must obey CP/M 8.3 naming conventions.

- -

Where the documentation requires a CP/M drive letter/user number -you should enter a path complete with trailing slash, for example:

-
-I/usr/src/linux-80/include/
- -

Technical

- -

zx emulates a subset of CP/M 3; hopefully enough to run the -most CP/M tools. It can be used as a limited general-purpose CP/M 3 -emulator provided the emulated program only uses a common subset of -system calls.

- -

Syntax for zx is:

- -
-zx comfile.com arg1 arg2 ... -
- -

The comfile is the program to run; zx searches the current -directory and ZXBINDIR for it.

- -

The arguments are parsed in this way:

- -
    -
  • Any argument starting with a - sign is passed to the CP/M program as-is, -minus the leading - sign. -
  • Any argument starting with a + sign is parsed as a filename (see below) -and then concatenated to the previous argument. -
  • Any argument starting "+-" is concatenated without being parsed. -
  • All other arguments are parsed as filenames. The path is -converted to a CP/M driveletter. -
- -

For example: -

-zx foo.com --Q -A /src/main --I +/src/sub +-, +/foo/bar -
- -

would pass these arguments to foo.com:

- -
--Q A d:main -Id:sub,e:bar -
- -

The other programs are merely wrappers that convert their command lines -into the form required by zx.

- -

Errors

- -

Any errors raised by the zx runtime system will be prefixed -with zx:. Some errors you may encounter are:

- -
-
Unsupported BDOS call
-
Part of CP/M 3 that the program uses has not been emulated. Add the -required functionality to zxbdos.c and recompile.
-
Z80 encountered invalid trap
-
The CP/M program being run attempted to call the zx runtime -system with an unknown call number.
-
- -

Acknowledgements

- -
    -
  • zxcc was written by John Elliott
  • -
  • Hi-Tech C was written by Hi-Tech Software.
  • -
  • The Z80 emulation engine was written by Ian Collier.
  • -
  • Thanks to Jacob Nevins, Andy Parkins and others for bug fix suggestions.
  • -
- - diff --git a/Tools/unix/zxcc/Build-OW.cmd b/Tools/unix/zxcc/Build-OW.cmd new file mode 100644 index 00000000..3be3cdaa --- /dev/null +++ b/Tools/unix/zxcc/Build-OW.cmd @@ -0,0 +1,21 @@ +@echo off +setlocal + +:: +:: Edit WATCOM variable below as needed for your environment +:: +set WATCOM=..\..\Tools\WATCOM2 + +set PATH=%WATCOM%\BINNT;%WATCOM%\BINW;%PATH% +set EDPATH=%WATCOM%\EDDAT +set INCLUDE=%WATCOM%\H;%WATCOM%\H\NT + +copy config.h.windows config.h + +cl /Fe"zxcc.exe" zxcc.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c track.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c +if errorlevel 1 exit /b 255 + +cl /Fe"zxccdbg.exe" /DDEBUG zxcc.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c track.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c +if errorlevel 1 exit /b 255 + +copy cpm\bios.bin . \ No newline at end of file diff --git a/Tools/unix/zxcc/Build-VC.cmd b/Tools/unix/zxcc/Build-VC.cmd new file mode 100644 index 00000000..2d199c6d --- /dev/null +++ b/Tools/unix/zxcc/Build-VC.cmd @@ -0,0 +1,25 @@ +@echo off +setlocal + +:: +:: Visual Studio x86 Native Tools Command Prompt is assumed +:: + +:: Below configures VS2012 to target Windows XP and beyond +:: Not sure if it will work in later versions of VS, but seems +:: to do no harm. +set INCLUDE=%ProgramFiles(x86)%\Microsoft SDKs\Windows\7.1A\Include;%INCLUDE% +set PATH=%ProgramFiles(x86)%\Microsoft SDKs\Windows\7.1A\Bin;%PATH% +set LIB=%ProgramFiles(x86)%\Microsoft SDKs\Windows\7.1A\Lib;%LIB% +set CL=/D_USING_V110_SDK71_;%CL% +set LINK=/SUBSYSTEM:CONSOLE,5.01 %LINK% + +copy config.h.windows config.h + +cl zxcc.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c dirent.c track.c +if errorlevel 1 exit /b 255 + +cl /DDEBUG /Fe"zxccdbg.exe" zxcc.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c dirent.c track.c +if errorlevel 1 exit /b 255 + +copy cpm\bios.bin . \ No newline at end of file diff --git a/Tools/unix/zx/COPYING b/Tools/unix/zxcc/COPYING similarity index 100% rename from Tools/unix/zx/COPYING rename to Tools/unix/zxcc/COPYING diff --git a/Tools/unix/zxcc/Clean.cmd b/Tools/unix/zxcc/Clean.cmd new file mode 100644 index 00000000..eb7fc764 --- /dev/null +++ b/Tools/unix/zxcc/Clean.cmd @@ -0,0 +1,11 @@ +@echo off +setlocal + +if exist *.exe del *.exe +if exist *.obj del *.obj +if exist *.err del *.err +if exist *.o del *.o +if exist *.bin del *.bin +if exist zxcc del zxcc +if exist zxccdbg del zxccdbg +if exist config.h del config.h diff --git a/Tools/unix/zxcc/Makefile b/Tools/unix/zxcc/Makefile new file mode 100644 index 00000000..70420378 --- /dev/null +++ b/Tools/unix/zxcc/Makefile @@ -0,0 +1,40 @@ +# +# hacked up brute force makefile for linux and osx +# +UNAME := $(shell uname) +ifeq ($(UNAME), Linux) + SUFFIX=linux +endif +ifeq ($(UNAME), Darwin) + SUFFIX=darwin +endif + +DEST = ../../$(UNAME) +CFLAGS = -g # -DDEBUG + +OBJECTS = zxcc.o cpmdrv.o cpmglob.o cpmparse.o cpmredir.o \ + drdos.o util.o xlt.o zxbdos.o zxcbdos.o zxdbdos.o z80.o track.o +UNUSED = dirent.o + +all: zxcc $(DEST) + cp -p bios.bin zxcc $(DEST) + +$(DEST): + mkdir -p $(DEST) + +clean: + -rm -f $(OBJECTS) config.h zxcc bios.bin + +clobber: clean + -rm -f $(DEST)/zxcc $(DEST)/bios.bin zxcc + +$(OBJECTS): config.h bios.bin + +zxcc: $(OBJECTS) + $(CC) -o zxcc $(OBJECTS) + +config.h: config.h.$(SUFFIX) + cp config.h.$(SUFFIX) config.h + +bios.bin: cpm/bios.bin + cp cpm/bios.bin . diff --git a/Tools/unix/zx/cbops.h b/Tools/unix/zxcc/cbops.h similarity index 96% rename from Tools/unix/zx/cbops.h rename to Tools/unix/zxcc/cbops.h index 47b69da0..f583e3a8 100644 --- a/Tools/unix/zx/cbops.h +++ b/Tools/unix/zxcc/cbops.h @@ -1,172 +1,172 @@ -/* Emulations of the CB operations of the Z80 instruction set. - * Copyright (C) 1994 Ian Collier. - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#define var_t unsigned char t -#define rlc(x) (x=(x<<1)|(x>>7),rflags(x,x&1)) -#define rrc(x) do{var_t=x&1;x=(x>>1)|(t<<7);rflags(x,t);}while(0) -#define rl(x) do{var_t=x>>7;x=(x<<1)|(f&1);rflags(x,t);}while(0) -#define rr(x) do{var_t=x&1;x=(x>>1)|(f<<7);rflags(x,t);}while(0) -#define sla(x) do{var_t=x>>7;x<<=1;rflags(x,t);}while(0) -#define sra(x) do{var_t=x&1;x=((signed char)x)>>1;rflags(x,t);}while(0) -#define sll(x) do{var_t=x>>7;x=(x<<1)|1;rflags(x,t);}while(0) -#define srl(x) do{var_t=x&1;x>>=1;rflags(x,t);}while(0) - -#define rflags(x,c) (f=(c)|(x&0xa8)|((!x)<<6)|parity(x)) - -#define bit(n,x) (f=(f&1)|((x&(1<>3)&7; - switch(op&0xc7){ - case 0x40: bit(n,b); break; - case 0x41: bit(n,c); break; - case 0x42: bit(n,d); break; - case 0x43: bit(n,e); break; - case 0x44: bit(n,h); break; - case 0x45: bit(n,l); break; - case 0x46: tstates+=4;val=fetch(addr);bit(n,val);store(addr,val);break; - case 0x47: bit(n,a); break; - case 0x80: res(n,b); break; - case 0x81: res(n,c); break; - case 0x82: res(n,d); break; - case 0x83: res(n,e); break; - case 0x84: res(n,h); break; - case 0x85: res(n,l); break; - case 0x86: tstates+=4;val=fetch(addr);res(n,val);store(addr,val);break; - case 0x87: res(n,a); break; - case 0xc0: set(n,b); break; - case 0xc1: set(n,c); break; - case 0xc2: set(n,d); break; - case 0xc3: set(n,e); break; - case 0xc4: set(n,h); break; - case 0xc5: set(n,l); break; - case 0xc6: tstates+=4;val=fetch(addr);set(n,val);store(addr,val);break; - case 0xc7: set(n,a); break; - } - } - if(ixoriy)switch(reg){ - case 0:b=val; break; - case 1:c=val; break; - case 2:d=val; break; - case 3:e=val; break; - case 4:h=val; break; - case 5:l=val; break; - case 7:a=val; break; - } -} - -#undef var_t -#undef rlc -#undef rrc -#undef rl -#undef rr -#undef sla -#undef sra -#undef sll -#undef srl -#undef rflags -#undef bit -#undef set -#undef res +/* Emulations of the CB operations of the Z80 instruction set. + * Copyright (C) 1994 Ian Collier. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define var_t unsigned char t +#define rlc(x) (x=(x<<1)|(x>>7),rflags(x,x&1)) +#define rrc(x) do{var_t=x&1;x=(x>>1)|(t<<7);rflags(x,t);}while(0) +#define rl(x) do{var_t=x>>7;x=(x<<1)|(f&1);rflags(x,t);}while(0) +#define rr(x) do{var_t=x&1;x=(x>>1)|(f<<7);rflags(x,t);}while(0) +#define sla(x) do{var_t=x>>7;x<<=1;rflags(x,t);}while(0) +#define sra(x) do{var_t=x&1;x=((signed char)x)>>1;rflags(x,t);}while(0) +#define sll(x) do{var_t=x>>7;x=(x<<1)|1;rflags(x,t);}while(0) +#define srl(x) do{var_t=x&1;x>>=1;rflags(x,t);}while(0) + +#define rflags(x,c) (f=(c)|(x&0xa8)|((!x)<<6)|parity(x)) + +#define bit(n,x) (f=(f&1)|((x&(1<>3)&7; + switch(op&0xc7){ + case 0x40: bit(n,b); break; + case 0x41: bit(n,c); break; + case 0x42: bit(n,d); break; + case 0x43: bit(n,e); break; + case 0x44: bit(n,h); break; + case 0x45: bit(n,l); break; + case 0x46: tstates+=4;val=fetch(addr);bit(n,val);store(addr,val);break; + case 0x47: bit(n,a); break; + case 0x80: res(n,b); break; + case 0x81: res(n,c); break; + case 0x82: res(n,d); break; + case 0x83: res(n,e); break; + case 0x84: res(n,h); break; + case 0x85: res(n,l); break; + case 0x86: tstates+=4;val=fetch(addr);res(n,val);store(addr,val);break; + case 0x87: res(n,a); break; + case 0xc0: set(n,b); break; + case 0xc1: set(n,c); break; + case 0xc2: set(n,d); break; + case 0xc3: set(n,e); break; + case 0xc4: set(n,h); break; + case 0xc5: set(n,l); break; + case 0xc6: tstates+=4;val=fetch(addr);set(n,val);store(addr,val);break; + case 0xc7: set(n,a); break; + } + } + if(ixoriy)switch(reg){ + case 0:b=val; break; + case 1:c=val; break; + case 2:d=val; break; + case 3:e=val; break; + case 4:h=val; break; + case 5:l=val; break; + case 7:a=val; break; + } +} + +#undef var_t +#undef rlc +#undef rrc +#undef rl +#undef rr +#undef sla +#undef sra +#undef sll +#undef srl +#undef rflags +#undef bit +#undef set +#undef res diff --git a/Tools/unix/zxcc/config.h.darwin b/Tools/unix/zxcc/config.h.darwin new file mode 100644 index 00000000..b3df1720 --- /dev/null +++ b/Tools/unix/zxcc/config.h.darwin @@ -0,0 +1,6 @@ +#define HAVE_DIRENT_H +#define HAVE_UTIME_H +#define HAVE_FCNTL_H +#define HAVE_UNISTD_H +#define DARWIN +//#define FILETRACKER 1 diff --git a/Tools/unix/zxcc/config.h.linux b/Tools/unix/zxcc/config.h.linux new file mode 100644 index 00000000..86925d43 --- /dev/null +++ b/Tools/unix/zxcc/config.h.linux @@ -0,0 +1,9 @@ +#define HAVE_DIRENT_H +#define HAVE_UTIME_H +#define HAVE_FCNTL_H +#define HAVE_SYS_VFS_H +#define HAVE_UNISTD_H +#define HAVE_STRING_H +#define HAVE_STDLIB_H +#define LINUX +//#define FILETRACKER 1 diff --git a/Tools/unix/zxcc/config.h.windows b/Tools/unix/zxcc/config.h.windows new file mode 100644 index 00000000..1b838310 --- /dev/null +++ b/Tools/unix/zxcc/config.h.windows @@ -0,0 +1,5 @@ +#define HAVE_WINDOWS_H +#define HAVE_FCNTL_H +#define WINVER _WIN32_WINNT_WINXP // target Windows XP +#define _WIN32_WINNT _WIN32_WINNT_WINXP // target Windows XP +//#define FILETRACKER 1 diff --git a/Tools/unix/zx/bios.bin b/Tools/unix/zxcc/cpm/bios.bin similarity index 100% rename from Tools/unix/zx/bios.bin rename to Tools/unix/zxcc/cpm/bios.bin diff --git a/Tools/unix/zx/cpm/bios.com b/Tools/unix/zxcc/cpm/bios.com similarity index 100% rename from Tools/unix/zx/cpm/bios.com rename to Tools/unix/zxcc/cpm/bios.com diff --git a/Tools/unix/zx/cpm/bios.lst b/Tools/unix/zxcc/cpm/bios.lst similarity index 100% rename from Tools/unix/zx/cpm/bios.lst rename to Tools/unix/zxcc/cpm/bios.lst diff --git a/Tools/unix/zx/cpm/bios.z80 b/Tools/unix/zxcc/cpm/bios.z80 similarity index 100% rename from Tools/unix/zx/cpm/bios.z80 rename to Tools/unix/zxcc/cpm/bios.z80 diff --git a/Tools/unix/zx/cpmdrv.c b/Tools/unix/zxcc/cpmdrv.c similarity index 96% rename from Tools/unix/zx/cpmdrv.c rename to Tools/unix/zxcc/cpmdrv.c index 24042e5b..8dcd8889 100644 --- a/Tools/unix/zx/cpmdrv.c +++ b/Tools/unix/zxcc/cpmdrv.c @@ -22,13 +22,12 @@ #include "cpmint.h" -#ifdef WIN32 - +#ifdef _WIN32 static char *drive_to_hostdrive(int cpm_drive) { static char prefix[CPM_MAXPATH]; char *lpfp; - DWORD dw; + dword dw; if (!redir_drive_prefix[cpm_drive]) return NULL; dw = GetFullPathName(redir_drive_prefix[cpm_drive], sizeof(prefix), @@ -37,7 +36,7 @@ static char *drive_to_hostdrive(int cpm_drive) if (!dw) return NULL; if (prefix[1] == ':') /* If path starts with a drive, limit it */ { /* to just that drive */ - prefix[2] = '/'; + prefix[2] = '\\'; /* GetDiskFreeSpace should have trailing backslash */ prefix[3] = 0; } return prefix; @@ -122,7 +121,7 @@ cpm_word fcb_resro(cpm_word bitmap) cpm_word fcb_sync(cpm_byte flag) { -#ifdef WIN32 +#ifdef _WIN32 return 0; #else sync(); return 0; /* Apparently some sync()s are void not int */ @@ -132,7 +131,7 @@ cpm_word fcb_sync(cpm_byte flag) cpm_word fcb_purge() { -#ifdef WIN32 +#ifdef _WIN32 return 0; #else sync(); return 0; /* Apparently some sync()s are void not int */ @@ -182,3 +181,6 @@ cpm_word fcb_dfree (cpm_byte drive, cpm_byte *dma) redir_wr24(dma, 0x8000L); /* 8MB / 128 / 2 */ return 0; } + + + diff --git a/Tools/unix/zx/cpmglob.c b/Tools/unix/zxcc/cpmglob.c similarity index 94% rename from Tools/unix/zx/cpmglob.c rename to Tools/unix/zxcc/cpmglob.c index 5566d8a4..dadae255 100644 --- a/Tools/unix/zx/cpmglob.c +++ b/Tools/unix/zxcc/cpmglob.c @@ -21,6 +21,10 @@ */ #include "cpmint.h" +#ifdef _MSC_VER +#define S_ISDIR(mode) (((mode) & _S_IFDIR) != 0) +#endif + static cpm_byte *find_fcb; static int find_n; @@ -50,7 +54,8 @@ static char upper(char c) static int cpm_match(char *s, cpm_byte *fcb, cpm_byte *pattern) { - int n, m; + int n; + size_t m; char *dotpos; m = strlen(s); @@ -98,10 +103,11 @@ static int cpm_match(char *s, cpm_byte *fcb, cpm_byte *pattern) if (((fcb[0] & 0x7F) == '?') || (fcb[0] & 0x80)) { return 1; } - - for (n = 0; n < 11; n++) { + for (n = 0; n < 11; n++) + { if (fcb[n+1] == '?') continue; - if ((pattern[n] & 0x7F) != (fcb[n+1] & 0x7F)) { + if ((pattern[n] & 0x7F) != (fcb[n+1] & 0x7F)) + { return 0; } } @@ -147,8 +153,7 @@ static struct dirent * next_entry(DIR *dir, cpm_byte *fcb, cpm_byte *pattern, redir_Msg("Can't stat %s so omitting it.\n", target_name); continue; /* Can't stat */ } - //if (S_ISDIR(st->st_mode)) - if ((st->st_mode) & _S_IFDIR) + if (S_ISDIR(st->st_mode)) { /* Searching for files only */ if (fcb[0] != '?' && fcb[0] < 0x80) @@ -291,17 +296,17 @@ cpm_word redir_find(int n, cpm_byte *fcb, cpm_byte *dma) dma[0x0d] = st.st_size & 0x7F; /* Last record byte count */ dma[0x0e] = 0; /* Extent counter, high */ -#ifdef __MSDOS__ - _dos_getfileattr(target_name, (unsigned int *)&attrib); +#ifdef _WIN32 + attrib = GetFileAttributesA(target_name); rights = redir_drdos_get_rights(target_name); if (rights && ((fcb[0] & 0x7F) == '?')) find_xfcb = 1; #else attrib = 0; rights = 0; #endif - if (attrib & 1) dma[9] |= 0x80; - if (attrib & 4) dma[10] |= 0x80; - if (!(attrib & 0x20)) dma[11] |= 0x80; + if (attrib & 1) dma[9] |= 0x80; /* read only */ + if (attrib & 4) dma[10] |= 0x80; /* system */ + if (!(attrib & 0x20)) dma[11] |= 0x80; /* archive */ @@ -310,14 +315,13 @@ cpm_word redir_find(int n, cpm_byte *fcb, cpm_byte *dma) recs = (st.st_size + 127) / 128; dma[0x0f] = (recs > 127) ? 0x80 : (recs & 0x7F); dma[0x10] = 0x80; - //if (S_ISDIR(st.st_mode)) dma[0x10] |= 0x40; - if ((st.st_mode) & _S_IFDIR) {dma[0x10] |= 0x40;} + if (S_ISDIR(st.st_mode)) dma[0x10] |= 0x40; if (attrib & 2) dma[0x10] |= 0x20; dma[0x10] |= ((entryno & 0x1FFF) >> 8); dma[0x11] = dma[0x10]; dma[0x12] = entryno & 0xFF; - redir_wr32(dma + 0x16, st.st_mtime); /* Modification time. */ + redir_wr32(dma + 0x16, (dword)st.st_mtime); /* Modification time. */ /* TODO: It should be in DOS */ /* format */ /* TODO: At 0x1A, 1st cluster */ @@ -483,10 +487,12 @@ cpm_word fcb_unlink(cpm_byte *fcb, cpm_byte *dma) } else { + releaseFile(target_name); handle = unlink(target_name); if (handle && redir_password_error()) { redir_password_append(target_name, dma); + releaseFile(target_name); handle = unlink(target_name); } } @@ -559,7 +565,8 @@ cpm_word redir_get_label(cpm_byte drv, char *pattern) cpm_word redir_get_label(cpm_byte drv, char *pattern) { char *dname; - int l, n; + size_t l; + int n; memset(pattern, ' ', 11); diff --git a/Tools/unix/zx/cpmint.h b/Tools/unix/zxcc/cpmint.h similarity index 76% rename from Tools/unix/zx/cpmint.h rename to Tools/unix/zxcc/cpmint.h index e6878174..65879654 100644 --- a/Tools/unix/zx/cpmint.h +++ b/Tools/unix/zxcc/cpmint.h @@ -20,82 +20,100 @@ This file holds internal declarations for the library. */ -#include "config.h" +#ifndef _WIN32 + #include "config.h" + #define DIRSEP "/" +#else + #include "config.h" + #define DIRSEP "/\\:" +#endif #include -#include +#ifdef HAVE_STDLIB_H + #include +#endif #include -#include +#ifdef HAVE_STRING_H + #include +#endif #include #include -#include +#ifdef _WIN32 + #include +#endif +#ifdef HAVE_SYS_TYPES_H + #include +#endif #include #include #ifdef HAVE_DIRENT_H -# include -#else -#ifdef __WATCOMC__ -# include -# include + #include + #ifdef HAVE_DIRECT_H + #include + #endif #else -# include "dirent.h" -#endif + #ifdef __WATCOMC__ + #include + #include + #else + #include "dirent.h" + #endif #endif #ifdef HAVE_NDIR_H -# include + #include #endif #ifdef HAVE_SYS_DIR_H -# include + #include #endif #ifdef HAVE_SYS_NDIR_H -# include + #include #endif #ifdef HAVE_WINDOWS_H -# include + #include #endif #ifdef HAVE_WINNT_H -# include + #include #endif #ifdef HAVE_SYS_VFS_H -# include + #include #endif #ifdef HAVE_UTIME_H -# include + #include #endif #ifdef HAVE_FCNTL_H -# include + #include #endif #ifdef HAVE_UNISTD_H -# include + #include #endif -#ifdef WIN32 -# define strcasecmp _stricmp +#ifndef _WIN32 + #include + #include + #define _S_IFDIR S_IFDIR #endif +/* MSDOS includes removed */ -#ifdef __MSDOS__ - #include - #include - #include - #ifdef __GO32__ - #include - #include - #include - #endif +#ifdef _WIN32 + #define mkdir(dir, mode) _mkdir(dir) + #define strcasecmp _stricmp + int truncate(const char* path, off_t length); /* see util.c */ + #define ftruncate _chsize + /* note Windows build assumes Windows is configured as a non case sensitive filesystem */ +#else + #define CASE_SENSITIVE_FILESYSTEM 1 #endif -#define CASE_SENSITIVE_FILESYSTEM 0 - - #include "cpmredir.h" typedef unsigned long dword; /* Must be at least 32 bits, and >= sizeof(int) */ + #ifdef CPMDEF - #define EXT - #define INIT(x) =x + #define EXT + #define INIT(x) =x #else - #define EXT extern - #define INIT(x) + #define EXT extern + #define INIT(x) #endif /* The 16 directories to which the 16 CP/M drives are mapped */ @@ -149,9 +167,11 @@ int redir_verify_fcb(cpm_byte *fcb); long zxlseek(int fd, long offset, int wh); #ifdef DEBUG + // long zxlseek(int fd, long offset, int wh); void redir_Msg(char *s, ...); void redir_showfcb(cpm_byte *fcb); #else + // #define zxlseek lseek /* Warning: This is a GCC extension */ #define redir_Msg(x, ...) #define redir_showfcb(x) @@ -224,3 +244,6 @@ cpm_word redir_password_error(void); /* Append password to filename (FILE.TYP -> FILE.TYP;PASSWORD) */ void redir_password_append(char *s, cpm_byte *dma); +void releaseFile(char *fname); +int trackFile(char *fname, void *fcb, int fd); +#define releaseFCB(fcb) trackFile(NULL, fcb, -1) diff --git a/Tools/unix/zxcc/cpmparse.c b/Tools/unix/zxcc/cpmparse.c new file mode 100644 index 00000000..ea0949ed --- /dev/null +++ b/Tools/unix/zxcc/cpmparse.c @@ -0,0 +1,126 @@ +/* + + CPMREDIR: CP/M filesystem redirector + Copyright (C) 1998, John Elliott + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + This file parses filenames to FCBs. +*/ + +#include "cpmint.h" + +#define is_num(c) ((c >= '0') && (c <= '9')) + +static int parse_drive_user(char *txt, cpm_byte *fcb) +{ + char uid[4], drvid[4]; + int up, dp; + + for (up = dp = 0; *txt != ':'; ++txt) + { + if (is_num (*txt)) uid [up++] = *txt; + if (isalpha(*txt)) drvid[dp++] = *txt; + if (!is_num(*txt) && !isalpha(*txt)) return -1; + } + uid[up] = 0; drvid[dp] = 0; + + if (dp > 1) return -1; /* Invalid driveletter */ + if (up > 2) return -1; /* Invalid uid */ + + fcb[0x0d] = atoi(uid) + 1; if (fcb[0x0d] > 16) return -1; + + if (islower(drvid[0])) drvid[0] = toupper(drvid[0]); + + if (drvid[0] < 'A' || drvid[0] > 'P') return -1; + + fcb[0] = drvid[0] - '@'; + return 0; +} + + + +cpm_word fcb_parse(char *txt, cpm_byte *fcb) +{ + int nl = 0, tl = 0, pl = 0, phase = 0; + char *ntxt, ch; + + memset(fcb, 0, 0x24); + + if (txt[1] == ':' || txt[2] == ':' || txt[3] == ':') + { + if (parse_drive_user(txt, fcb)) return 0xFFFF; + /* Move past the colon */ + ntxt = strchr(txt, ':') + 1; + } + else ntxt = txt; + while (phase < 3) + { + ch = *ntxt; + if (islower(ch)) ch = toupper(ch); + + switch(ch) + { + case 0: + case '\r': /* EOL */ + phase = 4; + break; + + case '.': /* file.typ */ + if (!phase) ++phase; + else phase = 3; + break; + + case ';': /* Password */ + if (phase < 2) phase = 2; + else phase = 3; + break; + + case '[': case ']': case '=': case 9: case ' ': + case '>': case '<': case ':': case ',': case '/': + case '|': /* Terminator */ + phase = 3; + + default: + switch(phase) + { + case 0: + if (nl >= 8) return 0xFFFF; + fcb[++nl] = ch; + break; + + case 1: + if (tl >= 3) return 0xFFFF; + fcb[tl + 9] = ch; + ++tl; + break; + + case 2: + if (pl >= 8) return 0xFFFF; + fcb[pl + 0x10] = ch; + ++pl; + break; + } + break; + } + } + if (!nl) return 0xFFFF; + + fcb[0x1A] = pl; + + if (phase == 4) return 0; + + return (cpm_word)(ntxt - txt); +} diff --git a/Tools/unix/zx/cpmredir.c b/Tools/unix/zxcc/cpmredir.c similarity index 87% rename from Tools/unix/zx/cpmredir.c rename to Tools/unix/zxcc/cpmredir.c index d8a5e337..6484608e 100644 --- a/Tools/unix/zx/cpmredir.c +++ b/Tools/unix/zxcc/cpmredir.c @@ -71,7 +71,8 @@ cpm_word fcb_open(cpm_byte *fcb, cpm_byte *dma) { char fname[CPM_MAXPATH]; int handle; - int drv, l; + int drv; + size_t l; char *s; DIR *dir; @@ -95,23 +96,13 @@ cpm_word fcb_open(cpm_byte *fcb, cpm_byte *dma) { l = strlen(redir_drive_prefix[drv]) - 1; s = redir_drive_prefix[drv]; + while (--l > 0 && !strchr(DIRSEP, s[l])) --l; - while (l > 0) - { - if (s[l] == '/') break; -#ifdef __MSDOS__ - if (s[l] == '\\') break; - if (s[l] == ':') break; -#endif - --l; - } -#ifdef __MSDOS__ - if (l < 2) return 0; /* "C:" */ -#else - if (l <= 0) return 0; /* "/" */ + if (l == 0) return 0; /* "/" or "\" */ +#ifdef _WIN32 + if (s[l] == ':' && l < 2) return 0; /* "C:" */ #endif - ++l; - s[l] = 0; + s[l + 1] = 0; return 0; } /* Opening some other directory */ @@ -160,11 +151,11 @@ cpm_word fcb_open(cpm_byte *fcb, cpm_byte *dma) */ /* Get the file length */ - redir_wr32(fcb + 0x1C, zxlseek(handle, 0, SEEK_END)); + redir_wr32(fcb + LENGTH_OFFSET, zxlseek(handle, 0, SEEK_CUR)); zxlseek(handle, 0, SEEK_SET); /* Set the last record byte count */ - if (fcb[0x20] == 0xFF) fcb[0x20] = fcb[0x1C] & 0x7F; + if (fcb[0x20] == 0xFF) fcb[0x20] = fcb[LENGTH_OFFSET] & 0x7F; redir_Msg("Ret: 0\n"); @@ -179,7 +170,7 @@ cpm_word fcb_close(cpm_byte *fcb) SHOWNAME("fcb_close") if ((handle = redir_verify_fcb(fcb)) < 0) return -1; - redir_Msg(" (at %lx)\n", zxlseek(handle, 0, SEEK_CUR)); + redir_Msg(" (at %lx)\n", zxlseek(handle, 0, SEEK_END)); if (fcb[0] & 0x80) /* Close directory */ { @@ -195,13 +186,13 @@ cpm_word fcb_close(cpm_byte *fcb) if (fcb[5] & 0x80) /* CP/M 3: Flush rather than close */ { -#ifndef WIN32 +#ifndef _WIN32 sync(); #endif return 0; } -#ifdef WIN32 +#ifdef _WIN32 { BOOL b; redir_Msg(">CloseHandle() Handle=%lu\n", handle); @@ -290,7 +281,7 @@ cpm_word fcb_read(cpm_byte *fcb, cpm_byte *dma) memset(dma, 0x00, redir_rec_len); -#ifdef WIN32 +#ifdef _WIN32 { BOOL b; redir_Msg(">ReadFile() Handle=%lu, DMA=%lu, Len=%lu\n", handle, dma, redir_rec_len); @@ -324,6 +315,9 @@ cpm_word fcb_read(cpm_byte *fcb, cpm_byte *dma) return redir_xlt_err(); /* unwritten extent */ } + /* if not multiple of 128 bytes, pad sector with 0x1A */ + for (n = rv; n < rd_len; n++) dma[n] = 0x1A; + /* Less was read in than asked for. Report the number of 128-byte * records that _were_ read in. */ @@ -332,16 +326,11 @@ cpm_word fcb_read(cpm_byte *fcb, cpm_byte *dma) { /* Pack from the size actually read up to the size we claim * to have read */ - for (n = rv; n < rd_len; n++) dma[n] = 0x1A; - rd_len = ((rv + 127) / 128) << 8; /* High byte */ + rd_len = rd_len * 2; /* rd_len already sector * 128, so * 2 to move to High byte */ redir_Msg("Ret: 0x%x\n", rd_len | 1); return rd_len | 1; /* eof */ } - /* We have reported that all records were read in. But the last - * record might be less than 128 bytes, so pack it with 0x1A bytes */ - - for (n = rv; n < rd_len; n++) dma[n] = 0x1A; redir_Msg("Ret: 0 (bytes read=%d)\n", rv); return 0; } @@ -366,7 +355,7 @@ cpm_word fcb_write(cpm_byte *fcb, cpm_byte *dma) redir_Msg(" (to %lx)\n", zxlseek(handle, 0, SEEK_CUR)); -#ifdef WIN32 +#ifdef _WIN32 { BOOL b; redir_Msg(">WriteFile() Handle=%lu, DMA=%lu, Len=%lu\n", handle, dma, redir_rec_len); @@ -382,8 +371,8 @@ cpm_word fcb_write(cpm_byte *fcb, cpm_byte *dma) redir_put_fcb_pos(fcb, npos); /* Update the file length */ - len = redir_rd32(fcb + 0x1C); - if (len < npos) redir_wr32(fcb + 0x1C, npos); + len = redir_rd32(fcb + LENGTH_OFFSET); + if (len < npos) redir_wr32(fcb + LENGTH_OFFSET, npos); if (rv < 0) return redir_xlt_err(); /* error */ if (rv < redir_rec_len) return 1; /* disk full */ @@ -397,6 +386,8 @@ cpm_word fcb_creat(cpm_byte *fcb, cpm_byte *dma) char fname[CPM_MAXPATH]; int handle; + releaseFCB(fcb); /* release existing fcb usage */ + /* Don't support ambiguous filenames */ if (redir_fcb2unix(fcb, fname)) return 0x09FF; redir_Msg("fcb_creat(\"%s\")\n", fname); @@ -408,16 +399,13 @@ cpm_word fcb_creat(cpm_byte *fcb, cpm_byte *dma) if (fcb[0] & 0x80) { -#ifdef WIN32 - handle = mkdir(fname); -#else handle = mkdir(fname, 0x777); -#endif if (handle) return redir_xlt_err(); return 0; } + releaseFile(fname); /* purge any open handles for this file */ -#ifdef WIN32 +#ifdef _WIN32 redir_Msg(">CreateFile([CREATE_ALWAYS]) Name='%s'\n", fname); handle = (int)CreateFile(fname, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); redir_Msg("ReadFile() Handle=%lu, DMA=%lu, Len=%lu\n", handle, dma, redir_rec_len); @@ -526,16 +519,20 @@ cpm_word fcb_randrd(cpm_byte *fcb, cpm_byte *dma) redir_put_fcb_pos(fcb, offs); + if (rv < 0) return redir_xlt_err(); /* Error */ + rd_len = ((rv + 127) / 128) * 128; - if (rv < 0) return redir_xlt_err(); /* Error */ + /* PMO: pad partial sector to 128 bytes, even if EOF reached in multi sector read */ + for (n = rv; n < rd_len; n++) dma[n] = 0x1A; /* pad last read to 128 boundary with 0x1A*/ + if (rd_len < redir_rec_len) /* eof */ { - rd_len = ((rv + 127) / 128) << 8; /* High byte */ + rd_len = rd_len * 2; /* rd_len already sector * 128, so * 2 to move to High byte */ redir_Msg("Ret: 0x%x\n", rd_len | 1); return rd_len | 1; /* eof */ } - for (n = rv; n < rd_len; n++) dma[n] = 0x1A; + return 0; } @@ -546,7 +543,7 @@ cpm_word fcb_randwr(cpm_byte *fcb, cpm_byte *dma) int handle; int rv; dword offs = redir_rd24(fcb + 0x21) * 128; - long len; + dword len; SHOWNAME("fcb_randwr") @@ -555,7 +552,8 @@ cpm_word fcb_randwr(cpm_byte *fcb, cpm_byte *dma) if (redir_ro_fcb(fcb)) return 0x02FF; if (zxlseek(handle, offs, SEEK_SET) < 0) return 6; /* bad record no. */ -#ifdef WIN32 + +#ifdef _WIN32 { BOOL b; redir_Msg(">WriteFile() Handle=%lu, DMA=%lu, Len=%lu\n", handle, dma, redir_rec_len); @@ -569,15 +567,38 @@ cpm_word fcb_randwr(cpm_byte *fcb, cpm_byte *dma) zxlseek(handle, offs, SEEK_SET); redir_put_fcb_pos(fcb, offs); + if (rv < 0) return redir_xlt_err(); /* Error */ /* Update the file length */ - len = redir_rd32(fcb + 0x1C); - if (len < offs) redir_wr32(fcb + LENGTH_OFFSET, offs); + len = redir_rd32(fcb + LENGTH_OFFSET); + /* PMO: Bug fix, account for the data just written */ + if (len < offs + rv) { + redir_wr32(fcb + LENGTH_OFFSET, offs + rv); + // fcb[0x20] = (offs + rv) % 256; + } - if (rv < 0) return redir_xlt_err(); /* Error */ if (rv < redir_rec_len) return 1; /* disk full */ return 0; } +#ifndef OLD_RANDWZ +/* PMO: + * Under CP/M for random write with zero fill, the zero fill is only done for a newly allocated + * block and not fill from previous end of file + * to implement this fully would require tracking sparse files and filling to block + * boundaries. + * As the default for POSIX/Windows lseek is to effectively zero fill and for modern hard disks + * the additional space used is small compared to capacity, fcb_randwz is the same as fcb_randwr + * Note zero padding to the end of the block will be done automatically as required when data is + * written to later offsets + */ +/* Write random with 0 fill */ +cpm_word fcb_randwz(cpm_byte* fcb, cpm_byte* dma) +{ + SHOWNAME("fcb_randwz"); + return fcb_randwr(fcb, dma); +} + +#else /* Write random with 0 fill */ cpm_word fcb_randwz(cpm_byte *fcb, cpm_byte *dma) { @@ -588,8 +609,11 @@ cpm_word fcb_randwz(cpm_byte *fcb, cpm_byte *dma) SHOWNAME("fcb_randwz") if ((handle = redir_verify_fcb(fcb)) < 0) return 9; /* Invalid FCB */ + /* Software write-protection */ + if (redir_ro_fcb(fcb)) return 0x02FF; + offs = redir_rd24(fcb + 0x21) * 128; - len = redir_rd32(fcb + 0x1C); + len = redir_rd32(fcb + LENGTH_OFFSET); redir_wr32(fcb + LENGTH_OFFSET, offs); @@ -601,7 +625,7 @@ cpm_word fcb_randwz(cpm_byte *fcb, cpm_byte *dma) rl = sizeof(zerorec); if ((offs - len) < sizeof(zerorec)) rl = offs - len; -#ifdef WIN32 +#ifdef _WIN32 { BOOL b; redir_Msg(">WriteFile() Handle=%lu, DMA=%lu, Len=%lu\n", handle, zerorec, rl); @@ -623,6 +647,8 @@ cpm_word fcb_randwz(cpm_byte *fcb, cpm_byte *dma) return fcb_randwr(fcb, dma); } +#endif + cpm_word fcb_tell(cpm_byte *fcb) { @@ -656,7 +682,7 @@ cpm_word fcb_stat(cpm_byte *fcb) rv = stat(fname, &st); - redir_Msg("fcb_stat(\"%s\") fcb=%x\n", fname, (int)fcb); + redir_Msg("fcb_stat(\"%s\") fcb=%p\n", fname, fcb); if (rv < 0) { redir_Msg("ret: -1\n"); @@ -687,6 +713,10 @@ cpm_word fcb_date(cpm_byte *fcb) struct stat st; int rv; + /* as this function will overwrite the fcb info used by ZXCC + * release any file associated with it + */ + releaseFCB(fcb); /* Don't support ambiguous filenames */ if (redir_fcb2unix(fcb, fname)) return 0x09FF; @@ -703,23 +733,20 @@ cpm_word fcb_date(cpm_byte *fcb) } - cpm_word fcb_trunc(cpm_byte *fcb, cpm_byte *dma) { char fname[CPM_MAXPATH]; dword offs = redir_rd24(fcb + 0x21) * 128; + releaseFCB(fcb); /* CP/M requires truncated files be closed */ /* Don't support ambiguous filenames */ if (redir_fcb2unix(fcb, fname)) return 0x09FF; /* Software write-protection */ if (redir_ro_fcb(fcb)) return 0x02FF; + releaseFile(fname); /* after truncate open files are invalid */ redir_log_fcb(fcb); -#ifdef WIN32 - (void)offs; - return 0x06FF; /* Simply not implemented */ -#else if (truncate(fname, offs)) { if (redir_password_error()) @@ -730,24 +757,13 @@ cpm_word fcb_trunc(cpm_byte *fcb, cpm_byte *dma) return redir_xlt_err(); } return 0; -#endif } cpm_word fcb_sdate(cpm_byte *fcb, cpm_byte *dma) { char fname[CPM_MAXPATH]; -#ifdef WIN32 - /* TODO: Use SetFileTime() here */ - - /* Don't support ambiguous filenames */ - if (redir_fcb2unix(fcb, fname)) return 0x09FF; - - /* Software write-protection */ - if (redir_ro_fcb(fcb)) return 0x02FF; - redir_log_fcb(fcb); -#else struct utimbuf buf; buf.actime = redir_unixtime(dma); @@ -770,7 +786,6 @@ cpm_word fcb_sdate(cpm_byte *fcb, cpm_byte *dma) } return redir_xlt_err(); } -#endif return 0; } @@ -809,7 +824,7 @@ cpm_word fcb_chmod(cpm_byte *fcb, cpm_byte *dma) } return redir_xlt_err(); } -#elif defined (WIN32) +#elif defined (_WIN32) omode = 0; if (fcb[9] & 0x80) omode |= FILE_ATTRIBUTE_READONLY; @@ -838,13 +853,16 @@ cpm_word fcb_chmod(cpm_byte *fcb, cpm_byte *dma) { if (stat(fname, &st)) return redir_xlt_err(); + releaseFCB(fcb); /* cpm required file to be closed so release FCB */ + releaseFile(fname); /* also make sure no other handles open to file */ handle = open(fname, O_RDWR | O_BINARY); if (handle < 0) return redir_xlt_err(); newoffs = offs = ((st.st_size + 127) / 128) * 128; if (fcb[0x20] & 0x7F) { - newoffs -= (0x80 - (fcb[0x20] & 0x7F)); + newoffs -= fcb[0x20] & 0x7f; + //newoffs -= (0x80 - (fcb[0x20] & 0x7F)); } if (newoffs == st.st_size) { @@ -852,13 +870,11 @@ cpm_word fcb_chmod(cpm_byte *fcb, cpm_byte *dma) } else if (newoffs < st.st_size) { -#ifndef WIN32 /* XXX Do this somehow in Win32 */ if (ftruncate(handle, newoffs)) { close(handle); return redir_xlt_err(); } -#endif } else while (newoffs > st.st_size) { diff --git a/Tools/unix/zx/cpmredir.h b/Tools/unix/zxcc/cpmredir.h similarity index 100% rename from Tools/unix/zx/cpmredir.h rename to Tools/unix/zxcc/cpmredir.h diff --git a/Tools/unix/zx/dirent.c b/Tools/unix/zxcc/dirent.c similarity index 100% rename from Tools/unix/zx/dirent.c rename to Tools/unix/zxcc/dirent.c diff --git a/Tools/unix/zx/dirent.h b/Tools/unix/zxcc/dirent.h similarity index 100% rename from Tools/unix/zx/dirent.h rename to Tools/unix/zxcc/dirent.h diff --git a/Tools/unix/zx/drdos.c b/Tools/unix/zxcc/drdos.c similarity index 95% rename from Tools/unix/zx/drdos.c rename to Tools/unix/zxcc/drdos.c index 97bd583c..baf7a00b 100644 --- a/Tools/unix/zx/drdos.c +++ b/Tools/unix/zxcc/drdos.c @@ -1,236 +1,236 @@ -/* - - CPMREDIR: CP/M filesystem redirector - Copyright (C) 1998, John Elliott - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - This file holds DRDOS-specific password code. -*/ - -#include "cpmint.h" - -cpm_word redir_drdos_pwmode(cpm_byte b) -{ - cpm_word mode = 0; - - if (b & 0x80) mode |= 0xddd; - if (b & 0x40) mode |= 0x555; - if (b & 0x20) mode |= 0x111; - - return mode; -} - -cpm_byte redir_cpm_pwmode(cpm_word w) -{ - cpm_byte mode = 0; - - if (w & 0x8) mode |= 0x80; - if (w & 0x4) mode |= 0x40; - if (w & 0x1) mode |= 0x20; - - return mode; -} - -#ifdef __MSDOS__ -#ifdef __GO32__ /* The GO32 extender doesn't understand DRDOS password - * functions, so these are done with __dpmi_int() rather - * than intdos() */ - -cpm_word redir_drdos_get_rights(char *path) -{ - __dpmi_regs r; - - if (!redir_drdos) return 0; - - redir_Msg("Rights for file %s: \n\r", path); - - dosmemput(path, strlen(path) + 1, __tb); - r.x.ax = 0x4302; - r.x.dx = __tb & 0x0F; - r.x.ds = (__tb) >> 4; - - __dpmi_int(0x21, &r); - - redir_Msg(" %04x \n\r", r.x.cx); - - if (r.x.flags & 1) return 0; - return r.x.cx; -} - - -cpm_word redir_drdos_put_rights(char *path, cpm_byte *dma, cpm_word rights) -{ - __dpmi_regs r; - - if (!redir_drdos) return 0; - - redir_Msg("Put rights for file %s: %04x %-8.8s %-8.8s\n\r", path, rights, dma, dma + 8); - - dosmemput(dma+8, 8, __tb); /* Point DTA at password */ - r.x.ax = 0x1A00; - r.x.dx = (__tb & 0x0F); - r.x.ds = (__tb) >> 4; - __dpmi_int(0x21, &r); - - dosmemput(path, strlen(path) + 1, __tb + 0x10); - r.x.ax = 0x4303; /* Set rights */ - r.x.cx = rights; - r.x.dx = (__tb & 0x0F) + 0x10; - r.x.ds = (__tb) >> 4; - - __dpmi_int(0x21, &r); - - if (r.x.flags & 1) - { - redir_Msg(" Try 1 failed. Error %04x\n\r", r.x.ax); - if (redir_password_error()) - { - redir_password_append(path, dma); - - dosmemput(path, strlen(path) + 1, __tb + 0x10); - r.x.ax = 0x4303; /* Set rights */ - r.x.cx = rights; - r.x.dx = (__tb & 0x0F) + 0x10; - r.x.ds = (__tb) >> 4; - - __dpmi_int(0x21, &r); - if (!r.x.flags & 1) return 0; - if (redir_password_error()) return 0x7FF; - } - return 0xFF; - } - return 0; -} - -#else /* __GO32__ */ - -cpm_word redir_drdos_get_rights(char *path) -{ - union REGS r; - struct SREGS s; - - if (!redir_drdos) return 0; - - redir_Msg("Rights for file %s: \n\r", path); - - dosmemput(path, strlen(path) + 1, __tb); - r.w.ax = 0x4302; - r.w.dx = __tb & 0x0F; - s.ds = (__tb) >> 4; - - intdosx(&r, &r, &s); - - redir_Msg(" %04x \n\r", r.w.cx); - - if (r.w.cflag) return 0; - return r.w.cx; -} - - -cpm_word redir_drdos_put_rights(char *path, cpm_byte *dma, cpm_word rights) -{ - union REGS r; - struct SREGS s; - - if (!redir_drdos) return 0; - - redir_Msg("Put rights for file %s: %04x\n\r", path, rights); - - dosmemput(dma, 8, __tb); /* Point DTA at password */ - r.w.ax = 0x1A00; - r.w.dx = (__tb & 0x0F); - s.ds = (__tb) >> 4; - intdosx(&r, &r, &s); - - dosmemput(path, strlen(path) + 1, __tb + 0x10); - r.w.ax = 0x4303; /* Set rights */ - r.w.cx = rights; - r.w.dx = (__tb & 0x0F) + 0x10; - s.ds = (__tb) >> 4; - - intdosx(&r, &r, &s); - - if (r.w.cflag) - { - redir_Msg(" Try 1 failed. Error %04x \n\r", r.w.ax); - if (redir_password_error()) - { - redir_password_append(path, dma); - - dosmemput(path, strlen(path) + 1, __tb + 0x10); - r.w.ax = 0x4303; /* Set rights */ - r.w.cx = rights; - r.w.dx = (__tb & 0x0F) + 0x10; - s.ds = (__tb) >> 4; - - intdosx(&r, &r, &s); - if (!r.w.cflag) return 0; - } - return 0xFF; - } - return 0; -} - -#endif /* __GO32__ */ - - -cpm_word redir_password_error(void) -{ - union REGS r; - - if (!redir_drdos) return 0; - - r.w.ax = 0x5900; - r.w.bx = 0x0000; - - intdos(&r, &r); - - redir_Msg("Last error was: %04x\r\n", r.w.ax); - - if (r.w.ax == 0x56) return 1; /* Bad password */ - return 0; -} - - -void redir_password_append(char *s, cpm_byte *dma) -{ - int n, m; - - if (!redir_drdos) return; - - if (dma[0] == 0 || dma[0] == 0x20) return; - - strcat(s, ";"); - m = strlen(s); - - for (n = 0; n < 8; n++) - { - if (dma[n] == ' ') s[m] = 0; - else s[m] = dma[n]; - ++m; - } - s[m] = 0; - -} -#else /* __MSDOS__ */ -void redir_password_append(char *s, cpm_byte *dma) {} -cpm_word redir_password_error(void) { return 0; } -cpm_word redir_drdos_put_rights(char *path, cpm_byte *dma, cpm_word rights) -{ return 0; } -cpm_word redir_drdos_get_rights(char *path) { return 0; } -#endif /* __MSDOS__ */ - - +/* + + CPMREDIR: CP/M filesystem redirector + Copyright (C) 1998, John Elliott + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + This file holds DRDOS-specific password code. +*/ + +#include "cpmint.h" + +cpm_word redir_drdos_pwmode(cpm_byte b) +{ + cpm_word mode = 0; + + if (b & 0x80) mode |= 0xddd; + if (b & 0x40) mode |= 0x555; + if (b & 0x20) mode |= 0x111; + + return mode; +} + +cpm_byte redir_cpm_pwmode(cpm_word w) +{ + cpm_byte mode = 0; + + if (w & 0x8) mode |= 0x80; + if (w & 0x4) mode |= 0x40; + if (w & 0x1) mode |= 0x20; + + return mode; +} + +#ifdef __MSDOS__ +#ifdef __GO32__ /* The GO32 extender doesn't understand DRDOS password + * functions, so these are done with __dpmi_int() rather + * than intdos() */ + +cpm_word redir_drdos_get_rights(char *path) +{ + __dpmi_regs r; + + if (!redir_drdos) return 0; + + redir_Msg("Rights for file %s: \n\r", path); + + dosmemput(path, strlen(path) + 1, __tb); + r.x.ax = 0x4302; + r.x.dx = __tb & 0x0F; + r.x.ds = (__tb) >> 4; + + __dpmi_int(0x21, &r); + + redir_Msg(" %04x \n\r", r.x.cx); + + if (r.x.flags & 1) return 0; + return r.x.cx; +} + + +cpm_word redir_drdos_put_rights(char *path, cpm_byte *dma, cpm_word rights) +{ + __dpmi_regs r; + + if (!redir_drdos) return 0; + + redir_Msg("Put rights for file %s: %04x %-8.8s %-8.8s\n\r", path, rights, dma, dma + 8); + + dosmemput(dma+8, 8, __tb); /* Point DTA at password */ + r.x.ax = 0x1A00; + r.x.dx = (__tb & 0x0F); + r.x.ds = (__tb) >> 4; + __dpmi_int(0x21, &r); + + dosmemput(path, strlen(path) + 1, __tb + 0x10); + r.x.ax = 0x4303; /* Set rights */ + r.x.cx = rights; + r.x.dx = (__tb & 0x0F) + 0x10; + r.x.ds = (__tb) >> 4; + + __dpmi_int(0x21, &r); + + if (r.x.flags & 1) + { + redir_Msg(" Try 1 failed. Error %04x\n\r", r.x.ax); + if (redir_password_error()) + { + redir_password_append(path, dma); + + dosmemput(path, strlen(path) + 1, __tb + 0x10); + r.x.ax = 0x4303; /* Set rights */ + r.x.cx = rights; + r.x.dx = (__tb & 0x0F) + 0x10; + r.x.ds = (__tb) >> 4; + + __dpmi_int(0x21, &r); + if (!r.x.flags & 1) return 0; + if (redir_password_error()) return 0x7FF; + } + return 0xFF; + } + return 0; +} + +#else /* __GO32__ */ + +cpm_word redir_drdos_get_rights(char *path) +{ + union REGS r; + struct SREGS s; + + if (!redir_drdos) return 0; + + redir_Msg("Rights for file %s: \n\r", path); + + dosmemput(path, strlen(path) + 1, __tb); + r.w.ax = 0x4302; + r.w.dx = __tb & 0x0F; + s.ds = (__tb) >> 4; + + intdosx(&r, &r, &s); + + redir_Msg(" %04x \n\r", r.w.cx); + + if (r.w.cflag) return 0; + return r.w.cx; +} + + +cpm_word redir_drdos_put_rights(char *path, cpm_byte *dma, cpm_word rights) +{ + union REGS r; + struct SREGS s; + + if (!redir_drdos) return 0; + + redir_Msg("Put rights for file %s: %04x\n\r", path, rights); + + dosmemput(dma, 8, __tb); /* Point DTA at password */ + r.w.ax = 0x1A00; + r.w.dx = (__tb & 0x0F); + s.ds = (__tb) >> 4; + intdosx(&r, &r, &s); + + dosmemput(path, strlen(path) + 1, __tb + 0x10); + r.w.ax = 0x4303; /* Set rights */ + r.w.cx = rights; + r.w.dx = (__tb & 0x0F) + 0x10; + s.ds = (__tb) >> 4; + + intdosx(&r, &r, &s); + + if (r.w.cflag) + { + redir_Msg(" Try 1 failed. Error %04x \n\r", r.w.ax); + if (redir_password_error()) + { + redir_password_append(path, dma); + + dosmemput(path, strlen(path) + 1, __tb + 0x10); + r.w.ax = 0x4303; /* Set rights */ + r.w.cx = rights; + r.w.dx = (__tb & 0x0F) + 0x10; + s.ds = (__tb) >> 4; + + intdosx(&r, &r, &s); + if (!r.w.cflag) return 0; + } + return 0xFF; + } + return 0; +} + +#endif /* __GO32__ */ + + +cpm_word redir_password_error(void) +{ + union REGS r; + + if (!redir_drdos) return 0; + + r.w.ax = 0x5900; + r.w.bx = 0x0000; + + intdos(&r, &r); + + redir_Msg("Last error was: %04x\r\n", r.w.ax); + + if (r.w.ax == 0x56) return 1; /* Bad password */ + return 0; +} + + +void redir_password_append(char *s, cpm_byte *dma) +{ + int n, m; + + if (!redir_drdos) return; + + if (dma[0] == 0 || dma[0] == 0x20) return; + + strcat(s, ";"); + m = strlen(s); + + for (n = 0; n < 8; n++) + { + if (dma[n] == ' ') s[m] = 0; + else s[m] = dma[n]; + ++m; + } + s[m] = 0; + +} +#else /* __MSDOS__ */ +void redir_password_append(char *s, cpm_byte *dma) {} +cpm_word redir_password_error(void) { return 0; } +cpm_word redir_drdos_put_rights(char *path, cpm_byte *dma, cpm_word rights) +{ return 0; } +cpm_word redir_drdos_get_rights(char *path) { return 0; } +#endif /* __MSDOS__ */ + + diff --git a/Tools/unix/zx/edops.h b/Tools/unix/zxcc/edops.h similarity index 100% rename from Tools/unix/zx/edops.h rename to Tools/unix/zxcc/edops.h diff --git a/Tools/unix/zxcc/readme.txt b/Tools/unix/zxcc/readme.txt new file mode 100644 index 00000000..ba94bf5d --- /dev/null +++ b/Tools/unix/zxcc/readme.txt @@ -0,0 +1,86 @@ +This is an adaptation of zxcc-0.5.7 for RomWBW by Wayne Warthen. + +In general, this is a stripped down variant of John Elliott's zxcc package that +runs under a Windows command line (32 or 64 bit Windows), Linux, or MacOS. +This adaptation implements only the main "zxcc" command. The other programs +(zxc, zxas, zxlink, and zslibr) are not inluded here because they are fairly +specific to Hi-Tech C. + +Please see http://www.seasip.info/Unix/Zxcc/ for more information on the original +version of zxcc. Also, refer to https://github.com/agn453/ZXCC which has an +updated version of the code. + +The included zxcc.html documentation is from the original version, so it does not +reflect the changes made here. + +To build under Open Watcom, use Build-OW.cmd. To build under Microsoft Visual C, +use Build-VC.cmd. To build under Linux or MacOS, use the Makefile. + +The GPL status of everything remains in place and carries forward. + +December 5, 2014 + +After struggling to get the entire zxcc package to build nicely using autoconf, +I finally gave up and took a much more direct approach. I have extracted just +the source files needed and created a simple batch file to build the tool. I +realize this could be done much better, but I cheated in the interest of time. + +The one "real" change I made in the source code was that I modified the tool +to look for bios.bin in the same directory as the executable is in. This +just makes it much easier to set up (for me, anyway). + +Wayne Warthen +wwarthen@gmail.com + +March 15, 2017 + +- Updated to compile under Open Watcom. +- Implemented BDOS console status function. +- Set stdin and stdout to binary mode at startup. + +August 21, 2021 + +- Incorporated filename case insensitivity changes from Curt Mayer +- Incorporated fixes from Tony Nicholson at https://github.com/agn453/ZXCC + - Emulation of CP/M BDOS function 60 (call resident system extension) + should be disabled and return 0xFF in both the A and L registers. + - Change cpm_bdos_10() to return an unsigned result to avoid buffer + size being interpreted as negative. + - Fix the emulation of Z80 opcodes for IN (HL),(C) and + OUT (C),(HL) - opcodes 0xED,0x70 and 0xED,0x71 respectively. + This is noted in Fred Weigel's AM9511 arithmetic processing unit + emulation from https://github.com/ratboy666/am9511 in the howto.txt + description. NB: I have not included Fred's am9511 support at this + time into ZXCC. +- Fixed parse_to_fcb function in zxcc.c to handle parsing second automatic + FCB from command line + +Wayne Warthen +wwarthen@gmail.com + +--WBW 4:09 PM 8/21/2021 + +January 9, 2022 + +- Running zxcc under WSL (Windows Subsystem for Linux) was gererating output + that was correct but did not match standard Windows or Linux runs. This + turned out to be an assumption in a few places in the code that reading + into a buffer would not modify the area of the buffer that was beyond + the space required by the data being read. Under WSL, this "slack" space + was mangled. I made changes in these locations to clean up the slack + space after such reads. This fixed WSL runs to produce binary identical + output. Although only required by WSL, the changes cause no problems for + other environments and are actually correct per POSIX. + +--WBW 11:56 AM 1/9/2022 + +- I have attempted to sync my code up with the latest code found in Tony + Nicholson's GitHub repo at https://github.com/agn453/ZXCC. The most + significant difference in my code is that I am using the WIN32 API + for all disk I/O. Although the file tracking code is retained, I have + found this mechanism to fail insome scenarios. By using the WIN32 API + I can achieve the same file sharing attributes as Unix which makes the + file tracking mechanism optional. + +--WBW 9:34 AM 2/10/2022 + diff --git a/Tools/unix/zxcc/track.c b/Tools/unix/zxcc/track.c new file mode 100644 index 00000000..20770a8a --- /dev/null +++ b/Tools/unix/zxcc/track.c @@ -0,0 +1,150 @@ +/* + + CPMREDIR: CP/M filesystem redirector + Optional Open file tracker + Copyright (C) 2021, Mark Ogden + + This is an addition to the CPMREDIR + Copyright (C) 1998, John Elliott + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +//#include "cpmint.h" +#include "zxcc.h" + +/* CP/M does not require that files opened for reading need to be closed, + * this has two impacts + * 1) a lot of file handles can remain opened even when the file is no + * longer used. For modern OS builds this isn't a major problem as + * the system limits are quite high. It is however wasteful + * 2) for windows it can lead to issues when trying to delete / rename a file + * as normally windows will not allow files to be deleted/renamed if the + * file is currently open. Unix variants don't have this restriction. + * + * As an example the build of cgen.com using my decompiled sources + * the linq phase without tracking left 42 open files + * with tracking this was reduced to 2 + * + * This code keeps track of files that are opened until they are explicitly + * closed or the FCB used to open the file is reused, or the file needs to be + * renamed or deleted. + * To do this it keeps track of the expanded filename, fcb location and allocated + * file handle + * + * Two public functions are used to manage the file list, and are called from + * within the bdos emulation + * + * trackFile(char *fname, void *fcb, int fd) + * removes existing tracking with matchin fcb or fd and + * if (fname != NULL) - add the info to the head of the open files list + * it returns fd + * + * the function is called in the following circumstances + * 1) before closing a file (fname is NULL) + * 2) just after the file has been opened/created. + * 3) to remove association with a given fcb trackFile(NULL, fcb, -1) + * + * note a helper macro releaseFCB(fcb) can be used for (3) above + * + * releaseFile(char *fname) + * this scans through the list of open files and for each open file + * with a matching fname, the file is closed + * + * the function is called before deleting a file or renaming a file + * + * + * there is a helper function that removes the info from the list + * + * Notes: + * For most applications the tracker could in principle automatically + * close existing open files at the start of a new executable invocation. + * Unfortunately this does not support the case where there is a scripting + * engine intercepting the warm reboots, as it may need to keep the script + * source file open. + * + * Note in theory it would be possible for a CP/M program to open a file + * with a given fcb, move the fcb internally and then open another file + * with the original fcb. If this happens the FCB tracking could cause + * a problem. I am not aware of any real programs that do this. + * Please let me know if the situation arises. +*/ +/* windows needs to use file tracking, for unix/linux it is optional */ +#ifdef FILETRACKER +typedef struct _track { + struct _track* next; + int handle; + void* fcb; + char* fname; +} track_t; + +track_t* openFiles; + +static track_t* rmHandle(track_t* s) { + track_t* next = s->next; + free(s->fname); + free(s); + return next; +} + +void releaseFile(char* fname) { + track_t* s = (track_t*)&openFiles; + while (s->next) + if (strcmp(s->next->fname, fname) == 0) { + close(s->next->handle); + Msg("releaseFile closed file \"%s\"\n", s->next->fname); + s->next = rmHandle(s->next); + } + else + s = s->next; +} + + +int trackFile(char* fname, void* fcb, int fd) { + track_t* s = (track_t*)&openFiles; + Msg("trackFile: \"%s\", FCB=0x%X, Handle=%i\n", fname, (byte *)fcb - RAM, fd); + while (s->next) { /* find any existing fcb or fd */ + if (s->next->fcb == fcb || s->next->handle == fd) { + if (s->next->handle != fd) { + close(s->next->handle); + Msg(" closed file \"%s\", Handle=%i\n", s->next->fname, s->next->handle); + } + Msg(" released file \"%s\", Handle=%i\n", s->next->fname, s->next->handle); + s->next = rmHandle(s->next); /* release the tracker */ + } + else + s = s->next; + } + if (fname && fd >= 0) { + if ((s = malloc(sizeof(track_t))) == NULL) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + s->next = openFiles; + s->fname = strdup(fname); + s->fcb = fcb; + s->handle = fd; + openFiles = s; + } + return fd; +} + +#else + +void releaseFile(char* fname) {} +int trackFile(char* fname, void* fcb, int fd) { return fd; } + +#endif + diff --git a/Tools/unix/zx/util.c b/Tools/unix/zxcc/util.c similarity index 83% rename from Tools/unix/zx/util.c rename to Tools/unix/zxcc/util.c index cb22e18b..bc3dbb6e 100644 --- a/Tools/unix/zx/util.c +++ b/Tools/unix/zxcc/util.c @@ -22,13 +22,18 @@ #include "cpmint.h" + + + + + /* In debug mode, lseek()s can be traced. */ #ifdef DEBUG long zxlseek(int fd, long offset, int wh) { -#ifdef WIN32 +#ifdef _WIN32 long v; redir_Msg(">SetFilePointer() Handle=%lu, Offset=%lu, Method=%lu\n", fd, offset, wh); v = SetFilePointer((HANDLE)fd, offset, NULL, wh); @@ -49,6 +54,22 @@ long zxlseek(int fd, long offset, int wh) #endif } +#else + +long zxlseek(int fd, long offset, int wh) +{ + #ifdef _WIN32 + return SetFilePointer((HANDLE)fd, offset, NULL, wh); + #else + return lseek(fd, offset, wh); + #endif +} + + +#endif + +#ifdef DEBUG + void redir_showfcb(cpm_byte *fd) { int n; @@ -61,18 +82,6 @@ void redir_showfcb(cpm_byte *fd) printf("\r\n"); } -#else - -long zxlseek(int fd, long offset, int wh) -{ -#ifdef WIN32 - return SetFilePointer((HANDLE)fd, offset, NULL, wh); -#else - return lseek(fd, offset, wh); -#endif -} - - #endif /* Get the "sequential access" file pointer out of an FCB */ @@ -90,9 +99,9 @@ long redir_get_fcb_pos(cpm_byte *fcb) void redir_put_fcb_pos(cpm_byte *fcb, long npos) { - fcb[0x20] = (npos / 128) % 128; - fcb[0x0C] = (npos / 16384) % 32; - fcb[0x0E] = (npos / 524288L) % 64; + fcb[0x20] = (npos / 128) % 128; /* Record */ + fcb[0x0C] = (npos / 16384) % 32; /* Extent */ + fcb[0x0E] = (npos / 524288L) % 64; /* S2 */ } @@ -132,10 +141,8 @@ swizzle(char *fullpath) closedir(dirp); } -/* - * Passed a CP/M FCB, convert it to a unix filename. Turn its drive back into - * a path. - */ +/* Passed a CP/M FCB, convert it to a unix filename. Turn its drive back into + * a path. */ int redir_fcb2unix(cpm_byte *fcb, char *fname) { @@ -178,10 +185,10 @@ int redir_fcb2unix(cpm_byte *fcb, char *fname) int redir_ofile(cpm_byte *fcb, char *s) { - int h, rv; + int h; /* Software write-protection */ -#ifdef WIN32 +#ifdef _WIN32 redir_Msg(">CreateFile([OPEN_EXISTING]) Name='%s'\n", s); h = (int)CreateFile(s, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); redir_Msg("= 0 || (errno != EACCES && errno != EROFS)) return h; + if (h >= 0 || (errno != EACCES && errno != EROFS)) + return trackFile(s, fcb, h); } - redir_Msg("**2**"); h = open(s, O_RDONLY | O_BINARY); if (h < 0) return -1; fcb[9] |= 0x80; #endif #endif - - return h; + return trackFile(s, fcb, h); } @@ -250,10 +257,10 @@ void redir_Msg(char *s, ...) va_list ap; va_start(ap, s); - printf("cpmredir trace: "); - vprintf(s, ap); + fprintf(stderr, "cpmredir trace: "); + vfprintf(stderr, s, ap); va_end(ap); - fflush(stdout); + fflush(stderr); } #endif @@ -263,9 +270,16 @@ void redir_Msg(char *s, ...) /* Convert time_t to CP/M day count/hours/minutes */ dword redir_cpmtime(time_t t) { - long d = (t / 86400) - 2921; /* CP/M day 0 is unix day 2921 */ - long h = (t % 86400) / 3600; /* Hour, 0-23 */ - long m = (t % 3600) / 60; /* Minute, 0-59 */ +/* Microsoft compiler warned around the conversion from time_t to long + * as to support dates beyond 2038 time_t is set as a long long + * and for the Microsoft compiler sizeof(long) == 4 and sizeof(long long) == 8 + * for other compilers both have size 8 + * As the result is a dword (unsigned long), the code below is modified to reflect this + */ + + dword d = (dword)((t / 86400) - 2921); /* CP/M day 0 is unix day 2921 */ + dword h = (t % 86400) / 3600; /* Hour, 0-23 */ + dword m = (t % 3600) / 60; /* Minute, 0-59 */ return (d | (BCD(h) << 16) | (BCD(m) << 24)); } @@ -375,3 +389,20 @@ cpm_word redir_xlt_err(void) } } + +#ifdef _WIN32 +/* minimal implementation of truncate */ +int truncate(const char* path, off_t length) +{ + int result; + int fd = open(path, O_BINARY | O_RDWR); + + if (fd < 0) + return -1; + result = ftruncate(fd, length); + return close(fd) == 0 && result == 0 ? 0 : -1; + +} + + +#endif diff --git a/Tools/unix/zxcc/xlt.c b/Tools/unix/zxcc/xlt.c new file mode 100644 index 00000000..84b76952 --- /dev/null +++ b/Tools/unix/zxcc/xlt.c @@ -0,0 +1,241 @@ +/* + + CPMREDIR: CP/M filesystem redirector + Copyright (C) 1998, John Elliott + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + This file holds functions dealing with name translation; also the + initialisation code. +*/ + +#include "cpmint.h" +static char* skipUser(char* localname); +/* Detect DRDOS */ + +#ifdef __MSDOS__ +static void drdos_init(void) +{ + +/* The DJGPP DOS extender won't detect DRDOS using intdos(), so we have + to use __dpmi_int() instead. */ + +#ifdef __GO32__ + __dpmi_regs ir; + + ir.x.ax = 0x4452; /* "DR" */ + + __dpmi_int(0x21, &ir); + if (ir.x.flags & 1) return; /* Not DRDOS */ + + redir_Msg("DRDOS detected.\r\n"); + + redir_drdos = 1; + +#else /* __GO32__ */ + + union REGS ir, or; + + ir.w.ax = 0x4452; /* "DR" */ + + intdos(&ir, &or); + if (or.w.cflag) return; /* Not DRDOS */ + + redir_Msg("DRDOS detected.\r\n"); + + redir_drdos = 1; +#endif /* __GO32__ */ +} +#endif /* __MSDOS__ */ + + + +int fcb_init(void) +{ + int n; + + /* A: to O: free */ + for (n = 0; n < 15; n++) redir_drive_prefix[n][0] = 0; + + strcpy(redir_drive_prefix[15], "./"); /* P: is current directory */ + + /* Log on to P:. It is the only drive at this point which we + * know works. */ + redir_cpmdrive = 15; +#ifdef __MSDOS__ + drdos_init(); +#endif + + return 1; +} + +/* Deinitialise the library. */ + +void fcb_deinit(void) +{ + /* Nothing */ +} + +/* Translate a name from the host FS to a CP/M name. This will (if necessary) + * create a mapping between a CP/M drive and a host directory path. + * + * CP/M drives A: to O: can be mapped in this way. P: is always the current + * drive. + * + */ + +void xlt_name(char *localname, char *cpmname) +{ + char ibuf[CPM_MAXPATH + 1]; + char nbuf[CPM_MAXPATH + 1]; + char *pname = ibuf; + char *s; + int n; + + sprintf(ibuf, "%-.*s", CPM_MAXPATH, skipUser(localname)); + + while ((s = strpbrk(pname, DIRSEP))) { /* find the last directory separator allows mixed \ and / in windows */ +#ifdef _WIN32 + if (*s == '\\') /* convert separators to common format so directory tracking works more efficiently */ + *s = '/'; +#endif + pname = s + 1; + } + + if (pname == ibuf) { /* No path separators in the name. It is therefore a + local filename, so map it to drive P: */ + strcpy(cpmname, "p:"); + strcat(cpmname, ibuf); + return; + } + + /* catch user specified current drive a,b,c,p or A,B,C,P only, which map to predefined directories */ + if (pname == ibuf + 2 && ibuf[1] == ':' && (s = strchr("aAbBcCpP", ibuf[0]))) { + cpmname[0] = tolower(*s); /* make sure it's lower case */ + strcpy(cpmname + 1, ibuf + 1); + return; + } + + strcpy(nbuf, pname); /* nbuf holds filename component */ + *pname = 0; /* ibuf holds path component */ + + /* See if the path is one of those already mapped to drives */ + + for (n = 0; n < 15; n++) + { + if (redir_drive_prefix[n][0] && !strcmp(ibuf, redir_drive_prefix[n])) + { + sprintf(cpmname,"%c:%s", n + 'a', nbuf); + return; + } + } + + /* It is not, see if another drive can be allocated */ + + for (n = 0; n < 15; n++) if (!redir_drive_prefix[n][0]) + { + strcpy(redir_drive_prefix[n], ibuf); + sprintf(cpmname,"%c:%s", n + 'a', nbuf); + return; + } + + /* No other drive can be allocated */ + + strcpy(cpmname,"p:"); + strcat(cpmname, nbuf); +} + +/* It is sometimes convenient to set some fixed mappings. This will create + * a mapping for a given directory. + * Pass drive = -1 for "first available", or 0-15 for A: to P: + */ + +int xlt_map(int drive, char *localdir) +{ + int n; + + if (drive == -1) + { + for (n = 0; n < 15; n++) if (!redir_drive_prefix[n][0]) + { + drive = n; + break; + } + if (drive == -1) return 0; /* No space for mappings */ + } + if (redir_drive_prefix[drive][0]) return 0; /* Drive taken */ + + sprintf(redir_drive_prefix[drive], "%-.*s", CPM_MAXPATH, localdir); + return 1; +} + + +/* Unmap a drive + */ + +int xlt_umap(int drive) +{ + if (!redir_drive_prefix[drive][0]) return 0; /* Drive not taken */ + redir_drive_prefix[drive][0] = 0; + return 1; +} + + +char *xlt_getcwd(int drive) +{ + if (drive < 0 || drive > 16) return ""; + + return redir_drive_prefix[drive]; +} + +/* as zxcc doesn't really support user spaces, remove any user specification + *hitech c supports + * [[0-9]+[:]][[a-pA-P]:]name[.ext] | [[a-pA-p][[0-9]+]:]name[.ext] + * this function also checks that user is no more than 2 digits and user # <= 31 + * the hitech fcb checks for : as char 2, 3, or 4 which aligns to this + */ +static char* skipUser(char* localname) { + char* s; + int user; + int drive; + + if (!localname || !(s = strchr(localname, ':')) || s > localname + 3) + return localname; + s = localname; + if (isdigit(*s)) { + user = *s++ - '0'; + if (isdigit(*s)) { + user = user * 10 + *s++ - '0'; + if (user > 31) /* check sensible user id */ + return localname; + } + if (*s == ':') /* just strip the user id assume rest is a filename */ + return s + 1; + if ('a' <= (drive = tolower(*s)) && drive <= 'p' && s[1] == ':') + return s; /* was form [0-9]+[a-pA-P] so strip user id */ + else + return localname; /* not vaild so don't change */ + } + if ((drive = tolower(*s++)) < 'a' || 'p' < drive || !isdigit(*s)) + return localname; /* not a valid drive prefix or simple drive spec */ + + user = *s++ - '0'; + if (isdigit(*s)) + user = user * 10 + *s++ - '0'; + if (*s != ':' || user > 31) + return localname; + *--s = drive; /* reinsert the drive just before the : */ + return s; +} diff --git a/Tools/unix/zx/z80.c b/Tools/unix/zxcc/z80.c similarity index 93% rename from Tools/unix/zx/z80.c rename to Tools/unix/zxcc/z80.c index d1d99cd5..1b62994c 100644 --- a/Tools/unix/zx/z80.c +++ b/Tools/unix/zxcc/z80.c @@ -1,270 +1,272 @@ -/* Emulation of the Z80 CPU with hooks into the other parts of xz80. - * Copyright (C) 1994 Ian Collier. - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include "zx.h" - -#define parity(a) (partable[a]) - -unsigned char partable[256]={ - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4 - }; - -#ifdef DEBUG -static unsigned short breakpoint=0; -static unsigned int breaks=0; - -//static void inline log(fp,name,val) -static void log(fp,name,val) -FILE *fp; -char *name; -unsigned short val; -{ - int i; - fprintf(fp,"%s=%04X ",name,val); - for(i=0;i<8;i++,val++)fprintf(fp," %02X",fetch(val)); - putc('\n',fp); -} -#endif - -void mainloop(word spc, word ssp){ - register unsigned char a, f, b, c, d, e, h, l; - unsigned char r, a1, f1, b1, c1, d1, e1, h1, l1, i, iff1, iff2, im; - register unsigned short pc; - unsigned short ix, iy, sp; - register unsigned long tstates; - register unsigned int radjust; - register unsigned char ixoriy, new_ixoriy; - unsigned char intsample; - register unsigned char op; -#ifdef DEBUG - char flags[9]; - int bit; - FILE *fp=0; - register unsigned short af2=0,bc2=0,de2=0,hl2=0,ix2=0,iy2=0,sp2=0; - register unsigned char i2=0; - //unsigned char *memory=memptr[0]; - struct _next {unsigned char bytes[8];} *next; - unsigned short BC, DE, HL, AF; - - fputs("Press F11 to log\n",stderr); -#endif - a=f=b=c=d=e=h=l=a1=f1=b1=c1=d1=e1=h1=l1=i=r=iff1=iff2=im=0; - ixoriy=new_ixoriy=0; - ix=iy=0; - pc=spc; - sp=ssp; - tstates=radjust=0; - while(1){ - ixoriy=new_ixoriy; - new_ixoriy=0; -#ifdef DEBUG - next=(struct _next *)&fetch(pc); - BC=bc;DE=de;HL=hl;AF=(a<<8)|f; - if(fp && !ixoriy){ - log(fp,"pc",pc); - if(sp!=sp2)log(fp,"sp",sp2=sp); - if(iy!=iy2)log(fp,"iy",iy2=iy); - if(ix!=ix2)log(fp,"ix",ix2=ix); - if(hl!=hl2)log(fp,"hl",hl2=hl); - if(de!=de2)log(fp,"de",de2=de); - if(bc!=bc2)log(fp,"bc",bc2=bc); - if(((a<<8)|f)!=af2){ - af2=(a<<8)|f; - strcpy(flags,"SZ H VNC"); - for(bit=0;bit<8;bit++)if(!(f&(1<<(7-bit))))flags[bit]=' '; - fprintf(fp,"af=%04X %s\n",af2,flags); - } - if(i!=i2)fprintf(fp,"ir=%02X%02X\n",i2=i,r); - putc('\n',fp); - } - if(pc==breakpoint && pc) - breaks++; /* some code at which to set a breakpoint */ - a=AF>>8; f=AF; h=HL>>8; l=HL; d=DE>>8; e=DE; b=BC>>8; c=BC; -#endif -/* -{ - static int tr = 0; - static int id = 0; -// static byte b = 0; -// - if (pc == 0x1177) tr = 1; - if (pc == 0x1185) tr = 0; - if (tr >= 1) ++id; - if (tr >= 1) printf("%d: PC=%04x %02x AF=%02x:%02x BC=%04x DE=%04x HL=%04x IX=%04x IY=%04x\r\n", - id, pc, fetch(pc), a,f, bc, de, hl, ix, iy); -} -*/ - intsample=1; - op=fetch(pc); - pc++; - radjust++; - switch(op){ -#include "z80ops.h" - } -/*** - * ZXCC doesn't do interrupts at all, so all this is commented out - if(tstates>=int_cycles && intsample){ - tstates-=int_cycles; - frames++; - // Carry out X-related tasks (including waiting for timer - // signal if necessary) - switch(interrupt()){ - case Z80_quit: -#ifdef DEBUG - if(fp)fclose(fp); -#endif - return; - case Z80_NMI: - if(fetch(pc)==0x76)pc++; - iff2=iff1; - iff1=0; - // The Z80 performs a machine fetch cycle for 5 Tstates - // but ignores the result. It takes a further 10 Tstates - // to jump to the NMI routine at 0x66. - tstates+=15; - push2(pc); - pc=0x66; - break; - case Z80_reset: - a=f=b=c=d=e=h=l=a1=f1=b1=c1=d1=e1= - h1=l1=i=r=iff1=iff2=im=0; - ix=iy=sp=pc=0; - radjust=0; - break; -#ifdef DEBUG - case Z80_log: - if(fp){ - fclose(fp); - fp=0; - fputs("Logging turned off\n",stderr); - } else { - fp=fopen(config.log,"a"); - if(fp)fprintf(stderr,"Logging to file %s\n",config.log); - else perror(config.log); - } - break; -#endif - - case Z80_load: - stopwatch(); - if(snapload()){ - a=snapa; - f=snapf; - b=snapb; - c=snapc; - d=snapd; - e=snape; - h=snaph; - l=snapl; - a1=snapa1; - f1=snapf1; - b1=snapb1; - c1=snapc1; - d1=snapd1; - e1=snape1; - h1=snaph1; - l1=snapl1; - iff1=snapiff1; - iff2=snapiff2; - i=snapi; - r=snapr; - radjust=r; - im=snapim; - ix=snapix; - iy=snapiy; - sp=snapsp; - pc=snappc; - } - startwatch(1); - break; - case Z80_save: - r=(r&0x80)|(radjust&0x7f); - snapa=a; - snapf=f; - snapb=b; - snapc=c; - snapd=d; - snape=e; - snaph=h; - snapl=l; - snapa1=a1; - snapf1=f1; - snapb1=b1; - snapc1=c1; - snapd1=d1; - snape1=e1; - snaph1=h1; - snapl1=l1; - snapiff1=iff1; - snapiff2=iff2; - snapi=i; - snapr=r; - snapim=im; - snapix=ix; - snapiy=iy; - snapsp=sp; - snappc=pc; - snapsave(); - startwatch(1); - break; - - } - if(iff1){ -#ifdef DEBUG - if(fp)fprintf(fp,"Interrupt (im=%d)\n\n",im); -#endif - if(fetch(pc)==0x76)pc++; - iff1=iff2=0; - tstates+=5; // accompanied by an input from the data bus // - switch(im){ - case 0: // IM 0 // - case 1: // undocumented // - case 2: // IM 1 // - // there is little to distinguish between these cases // - tstates+=8; - push2(pc); - pc=0x38; - break; - case 3: // IM 2 // - tstates+=14; - { - int addr=fetch2((i<<8)|0xff); - push2(pc); - pc=addr; - } - } - } - }*/ - } -} +/* Emulation of the Z80 CPU with hooks into the other parts of xz80. + * Copyright (C) 1994 Ian Collier. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include "zxcc.h" + +#define parity(a) (partable[a]) + +unsigned char partable[256]={ + 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, + 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, + 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, + 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, + 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, + 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, + 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, + 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, + 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, + 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, + 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, + 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, + 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, + 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, + 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, + 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4 + }; + +#ifdef DEBUG +// Avoid name conflict with built-in log math function +#define log z80_log + +static unsigned short breakpoint=0; +static unsigned int breaks=0; + +static void inline log(fp,name,val) +FILE *fp; +char *name; +unsigned short val; +{ + int i; + fprintf(fp,"%s=%04X ",name,val); + for(i=0;i<8;i++,val++)fprintf(fp," %02X",fetch(val)); + putc('\n',fp); +} +#endif + +void mainloop(word spc, word ssp){ + register unsigned char a, f, b, c, d, e, h, l; + unsigned char r, a1, f1, b1, c1, d1, e1, h1, l1, i, iff1, iff2, im; + register unsigned short pc; + unsigned short ix, iy, sp; + register unsigned long tstates; + register unsigned int radjust; + register unsigned char ixoriy, new_ixoriy; + unsigned char intsample; + register unsigned char op; +#ifdef DEBUG + char flags[9]; + int bit; + FILE *fp=0; + register unsigned short af2=0,bc2=0,de2=0,hl2=0,ix2=0,iy2=0,sp2=0; + register unsigned char i2=0; + /*unsigned char *memory=memptr[0];*/ + struct _next {unsigned char bytes[8];} *next; + unsigned short BC, DE, HL, AF; + + fputs("Press F11 to log\n",stderr); +#endif + a=f=b=c=d=e=h=l=a1=f1=b1=c1=d1=e1=h1=l1=i=r=iff1=iff2=im=0; + ixoriy=new_ixoriy=0; + ix=iy=0; + pc=spc; + sp=ssp; + tstates=radjust=0; + while(1){ + ixoriy=new_ixoriy; + new_ixoriy=0; +#ifdef DEBUG + next=(struct _next *)&fetch(pc); + BC=bc;DE=de;HL=hl;AF=(a<<8)|f; + if(fp && !ixoriy){ + log(fp,"pc",pc); + if(sp!=sp2)log(fp,"sp",sp2=sp); + if(iy!=iy2)log(fp,"iy",iy2=iy); + if(ix!=ix2)log(fp,"ix",ix2=ix); + if(hl!=hl2)log(fp,"hl",hl2=hl); + if(de!=de2)log(fp,"de",de2=de); + if(bc!=bc2)log(fp,"bc",bc2=bc); + if(((a<<8)|f)!=af2){ + af2=(a<<8)|f; + strcpy(flags,"SZ H VNC"); + for(bit=0;bit<8;bit++)if(!(f&(1<<(7-bit))))flags[bit]=' '; + fprintf(fp,"af=%04X %s\n",af2,flags); + } + if(i!=i2)fprintf(fp,"ir=%02X%02X\n",i2=i,r); + putc('\n',fp); + } + if(pc==breakpoint && pc) + breaks++; /* some code at which to set a breakpoint */ + a=AF>>8; f=AF; h=HL>>8; l=HL; d=DE>>8; e=DE; b=BC>>8; c=BC; +#endif +/* +{ + static int tr = 1; + static int id = 0; +// static byte b = 0; +// +// if (pc == 0x1177) tr = 1; + // if (pc == 0x1185) tr = 0; + if (tr >= 1) ++id; + if (tr >= 1) printf("%d: PC=%04x %02x AF=%02x:%02x BC=%04x DE=%04x HL=%04x IX=%04x IY=%04x\r\n", + id, pc, fetch(pc), a,f, bc, de, hl, ix, iy); +} +*/ + intsample=1; + op=fetch(pc); + pc++; + radjust++; + switch(op){ +#include "z80ops.h" + } +/*** + * ZXCC doesn't do interrupts at all, so all this is commented out + if(tstates>=int_cycles && intsample){ + tstates-=int_cycles; + frames++; + // Carry out X-related tasks (including waiting for timer + // signal if necessary) + switch(interrupt()){ + case Z80_quit: +#ifdef DEBUG + if(fp)fclose(fp); +#endif + return; + case Z80_NMI: + if(fetch(pc)==0x76)pc++; + iff2=iff1; + iff1=0; + // The Z80 performs a machine fetch cycle for 5 Tstates + // but ignores the result. It takes a further 10 Tstates + // to jump to the NMI routine at 0x66. + tstates+=15; + push2(pc); + pc=0x66; + break; + case Z80_reset: + a=f=b=c=d=e=h=l=a1=f1=b1=c1=d1=e1= + h1=l1=i=r=iff1=iff2=im=0; + ix=iy=sp=pc=0; + radjust=0; + break; +#ifdef DEBUG + case Z80_log: + if(fp){ + fclose(fp); + fp=0; + fputs("Logging turned off\n",stderr); + } else { + fp=fopen(config.log,"a"); + if(fp)fprintf(stderr,"Logging to file %s\n",config.log); + else perror(config.log); + } + break; +#endif + + case Z80_load: + stopwatch(); + if(snapload()){ + a=snapa; + f=snapf; + b=snapb; + c=snapc; + d=snapd; + e=snape; + h=snaph; + l=snapl; + a1=snapa1; + f1=snapf1; + b1=snapb1; + c1=snapc1; + d1=snapd1; + e1=snape1; + h1=snaph1; + l1=snapl1; + iff1=snapiff1; + iff2=snapiff2; + i=snapi; + r=snapr; + radjust=r; + im=snapim; + ix=snapix; + iy=snapiy; + sp=snapsp; + pc=snappc; + } + startwatch(1); + break; + case Z80_save: + r=(r&0x80)|(radjust&0x7f); + snapa=a; + snapf=f; + snapb=b; + snapc=c; + snapd=d; + snape=e; + snaph=h; + snapl=l; + snapa1=a1; + snapf1=f1; + snapb1=b1; + snapc1=c1; + snapd1=d1; + snape1=e1; + snaph1=h1; + snapl1=l1; + snapiff1=iff1; + snapiff2=iff2; + snapi=i; + snapr=r; + snapim=im; + snapix=ix; + snapiy=iy; + snapsp=sp; + snappc=pc; + snapsave(); + startwatch(1); + break; + + } + if(iff1){ +#ifdef DEBUG + if(fp)fprintf(fp,"Interrupt (im=%d)\n\n",im); +#endif + if(fetch(pc)==0x76)pc++; + iff1=iff2=0; + tstates+=5; // accompanied by an input from the data bus // + switch(im){ + case 0: // IM 0 // + case 1: // undocumented // + case 2: // IM 1 // + // there is little to distinguish between these cases // + tstates+=8; + push2(pc); + pc=0x38; + break; + case 3: // IM 2 // + tstates+=14; + { + int addr=fetch2((i<<8)|0xff); + push2(pc); + pc=addr; + } + } + } + }*/ + } +} diff --git a/Tools/unix/zx/z80.h b/Tools/unix/zxcc/z80.h similarity index 96% rename from Tools/unix/zx/z80.h rename to Tools/unix/zxcc/z80.h index 89e12a84..d9e3a547 100644 --- a/Tools/unix/zx/z80.h +++ b/Tools/unix/zxcc/z80.h @@ -1,86 +1,86 @@ -/* Miscellaneous definitions for xz80, copyright (C) 1994 Ian Collier. - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* [John Elliott, 15 July 2001] - * Copied this file into ZXCC, a CP/M emulator. - * Since ZXCC's memory is a flat 64k space and will never be bank-switched, - * the bank-switching code is removed. - * Since ZXCC has no memory-mapped screen, all the screen management code - * goes as well. - * Since ZXCC doesn't need its speed regulated, all the speed regulation - * code goes as well. - * Since ZXCC doesn't save or load snapshots... OK, you get the idea. - */ - -#ifdef HAVE_SYS_PARAM_H -#include -#endif - -#define Z80_quit 1 -#define Z80_NMI 2 -#define Z80_reset 3 -#define Z80_load 4 -#define Z80_save 5 -#define Z80_log 6 - -unsigned int in(); -unsigned int out(); -//int interrupt(); -int snapload(); -void snapsave(); -void mainloop(word xpc, word xsp); -void eachframe(); -void itimeron(); -void itimeroff(); -void startwatch(); -unsigned long stopwatch(); -void requester(); -int loader(); -int saver(); -void multiloader(); -void usage(); -void version(); -void drawborder(); - -#define fetch(x) (RAM[x]) -#define fetch2(x) ((fetch((x)+1)<<8)|fetch(x)) - -#define store(x,y) do { RAM[(x)] = (y); } while(0) - -#define store2b(x,hi,lo) do {\ - RAM[(x)]=(lo); \ - RAM[((x+1) & 0xFFFF)]=(hi); } while(0) - -#define store2(x,y) store2b(x,(y)>>8,y) - -#ifdef __GNUC__ -static void inline storefunc(unsigned short ad,unsigned char b){ - store(ad,b); -} -#undef store -#define store(x,y) storefunc(x,y) - -static void inline store2func(unsigned short ad,unsigned char b1,unsigned char b2){ - store2b(ad,b1,b2); -} -#undef store2b -#define store2b(x,hi,lo) store2func(x,hi,lo) -#endif - -#define bc ((b<<8)|c) -#define de ((d<<8)|e) -#define hl ((h<<8)|l) +/* Miscellaneous definitions for xz80, copyright (C) 1994 Ian Collier. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* [John Elliott, 15 July 2001] + * Copied this file into ZXCC, a CP/M emulator. + * Since ZXCC's memory is a flat 64k space and will never be bank-switched, + * the bank-switching code is removed. + * Since ZXCC has no memory-mapped screen, all the screen management code + * goes as well. + * Since ZXCC doesn't need its speed regulated, all the speed regulation + * code goes as well. + * Since ZXCC doesn't save or load snapshots... OK, you get the idea. + */ + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#define Z80_quit 1 +#define Z80_NMI 2 +#define Z80_reset 3 +#define Z80_load 4 +#define Z80_save 5 +#define Z80_log 6 + +unsigned int in(); +unsigned int out(); +//int interrupt(); +int snapload(); +void snapsave(); +void mainloop(word xpc, word xsp); +void eachframe(); +void itimeron(); +void itimeroff(); +void startwatch(); +unsigned long stopwatch(); +void requester(); +int loader(); +int saver(); +void multiloader(); +void usage(); +void version(); +void drawborder(); + +#define fetch(x) (RAM[x]) +#define fetch2(x) ((fetch((x)+1)<<8)|fetch(x)) + +#define store(x,y) do { RAM[(x)] = (y); } while(0) + +#define store2b(x,hi,lo) do {\ + RAM[(x)]=(lo); \ + RAM[((x+1) & 0xFFFF)]=(hi); } while(0) + +#define store2(x,y) store2b(x,(y)>>8,y) + +#ifdef __GNUC__ +static void inline storefunc(unsigned short ad,unsigned char b){ + store(ad,b); +} +#undef store +#define store(x,y) storefunc(x,y) + +static void inline store2func(unsigned short ad,unsigned char b1,unsigned char b2){ + store2b(ad,b1,b2); +} +#undef store2b +#define store2b(x,hi,lo) store2func(x,hi,lo) +#endif + +#define bc ((b<<8)|c) +#define de ((d<<8)|e) +#define hl ((h<<8)|l) diff --git a/Tools/unix/zx/z80ops.h b/Tools/unix/zxcc/z80ops.h similarity index 93% rename from Tools/unix/zx/z80ops.h rename to Tools/unix/zxcc/z80ops.h index aac5d548..a07cfe5e 100644 --- a/Tools/unix/zx/z80ops.h +++ b/Tools/unix/zxcc/z80ops.h @@ -1,1332 +1,1332 @@ -/* Emulations of the Z80 CPU instruction set - part of xz80. - * Copyright (C) 1994 Ian Collier. - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#define instr(opcode,cycles) case opcode: {tstates+=cycles -#define HLinstr(opcode,cycles,morecycles) \ - case opcode: {unsigned short addr; \ - tstates+=cycles; \ - if(ixoriy==0)addr=hl; \ - else tstates+=morecycles, \ - addr=(ixoriy==1?ix:iy)+ \ - (signed char)fetch(pc),\ - pc++ -#define endinstr }; break - -#define cy (f&1) - -#define xh (ixoriy==0?h:ixoriy==1?(ix>>8):(iy>>8)) -#define xl (ixoriy==0?l:ixoriy==1?(ix&0xff):(iy&0xff)) - -#define setxh(x) (ixoriy==0?(h=(x)):ixoriy==1?(ix=(ix&0xff)|((x)<<8)):\ - (iy=(iy&0xff)|((x)<<8))) -#define setxl(x) (ixoriy==0?(l=(x)):ixoriy==1?(ix=(ix&0xff00)|(x)):\ - (iy=(iy&0xff00)|(x))) - -#define inc(var) /* 8-bit increment */ ( var++,\ - f=(f&1)|(var&0xa8)|\ - ((!(var&15))<<4)|((!var)<<6)|\ - ((var==128)<<2)\ - ) -#define dec(var) /* 8-bit decrement */ ( f=(f&1)|((!(var&15))<<4)|2,\ - --var,\ - f|=(var&0xa8)|((var==127)<<2)|\ - ((!var)<<6)\ - ) -#define swap(x,y) {unsigned char t=x; x=y; y=t;} -#define addhl(hi,lo) /* 16-bit add */ if(!ixoriy){\ - unsigned short t;\ - l=t=l+(lo);\ - f=(f&0xc4)|(((t>>=8)+(h&0x0f)+((hi)&0x0f)>15)<<4);\ - h=t+=h+(hi);\ - f|=(h&0x28)|(t>>8);\ - }\ - else do{unsigned long t=(ixoriy==1?ix:iy);\ - f=(f&0xc4)|(((t&0xfff)+((hi<<8)|lo)>0xfff)<<4);\ - t+=(hi<<8)|lo;\ - if(ixoriy==1)ix=t; else iy=t;\ - f|=((t>>8)&0x28)|(t>>16);\ - } while(0) -#define adda(x,c) /* 8-bit add */ do{unsigned short y;\ - unsigned char z=(x);\ - y=a+z+(c);\ - f=(y&0xa8)|(y>>8)|(((a&0x0f)+(z&0x0f)+(c)>15)<<4)|\ - (((~a^z)&0x80&(y^a))>>5);\ - f|=(!(a=y))<<6;\ - } while(0) -#define suba(x,c) /* 8-bit subtract */ do{unsigned short y;\ - unsigned char z=(x);\ - y=(a-z-(c))&0x1ff;\ - f=(y&0xa8)|(y>>8)|(((a&0x0f)<(z&0x0f)+(c))<<4)|\ - (((a^z)&0x80&(y^a))>>5)|2;\ - f|=(!(a=y))<<6;\ - } while(0) -#define cpa(x) /* 8-bit compare */ do{unsigned short y;\ - unsigned char z=(x);\ - y=(a-z)&0x1ff;\ - f=(y&0xa8)|(y>>8)|(((a&0x0f)<(z&0x0f))<<4)|\ - (((a^z)&0x80&(y^a))>>5)|2|((!y)<<6);\ - } while(0) -#define anda(x) /* logical and */ do{\ - a&=(x);\ - f=(a&0xa8)|((!a)<<6)|0x10|parity(a);\ - } while(0) -#define xora(x) /* logical xor */ do{\ - a^=(x);\ - f=(a&0xa8)|((!a)<<6)|parity(a);\ - } while(0) -#define ora(x) /* logical or */ do{\ - a|=(x);\ - f=(a&0xa8)|((!a)<<6)|parity(a);\ - } while(0) - -#define jr /* execute relative jump */ do{int j=(signed char)fetch(pc);\ - pc+=j+1;\ - tstates+=5;\ - } while(0) -#define jp /* execute jump */ (pc=fetch2(pc)) -#define call /* execute call */ do{\ - tstates+=7;\ - push2(pc+2);\ - jp;\ - } while(0) -#define ret /* execute return */ do{\ - tstates+=6;\ - pop2(pc);\ - } while(0) -#define pop2(var) /* pop 16-bit register */ (var=fetch2(sp),sp+=2) -#define pop1(v1,v2) /* pop register pair */ (v2=fetch(sp),\ - v1=fetch(sp+1),sp+=2) -#define push2(val) /* push 16-bit register */ do{sp-=2;store2(sp,(val));}\ - while(0) -#define push1(v1,v2) /* push register pair */ do{sp-=2;\ - store2b(sp,v1,v2);\ - }while(0) - -instr(0,4); - /* nop */ -endinstr; - -instr(1,10); - c=fetch(pc),pc++; - b=fetch(pc),pc++; -endinstr; - -instr(2,7); - store(bc,a); -endinstr; - -instr(3,6); - if(!++c)b++; -endinstr; - -instr(4,4); - inc(b); -endinstr; - -instr(5,4); - dec(b); -endinstr; - -instr(6,7); - b=fetch(pc),pc++; -endinstr; - -instr(7,4); - a=(a<<1)|(a>>7); - f=(f&0xc4)|(a&0x29); -endinstr; - -instr(8,4); - swap(a,a1); - swap(f,f1); -endinstr; - -instr(9,11); - addhl(b,c); -endinstr; - -instr(10,7); - a=fetch(bc); -endinstr; - -instr(11,6); - if(!c--)b--; -endinstr; - -instr(12,4); - inc(c); -endinstr; - -instr(13,4); - dec(c); -endinstr; - -instr(14,7); - c=fetch(pc),pc++; -endinstr; - -instr(15,4); - f=(f&0xc4)|(a&1); - a=(a>>1)|(a<<7); - f|=a&0x28; -endinstr; - -instr(16,8); - if(!--b)pc++; - else jr; -endinstr; - -instr(17,10); - e=fetch(pc),pc++; - d=fetch(pc),pc++; -endinstr; - -instr(18,7); - store(de,a); -endinstr; - -instr(19,6); - if(!++e)d++; -endinstr; - -instr(20,4); - inc(d); -endinstr; - -instr(21,4); - dec(d); -endinstr; - -instr(22,7); - d=fetch(pc),pc++; -endinstr; - -instr(23,4); - {int t=a>>7; - a=(a<<1)|(f&1); - f=(f&0xc4)|(a&0x28)|t; - } -endinstr; - -instr(24,7); - jr; -endinstr; - -instr(25,11); - addhl(d,e); -endinstr; - -instr(26,7); - a=fetch(de); -endinstr; - -instr(27,6); - if(!e--)d--; -endinstr; - -instr(28,4); - inc(e); -endinstr; - -instr(29,4); - dec(e); -endinstr; - -instr(30,7); - e=fetch(pc),pc++; -endinstr; - -instr(31,4); - {int t=a&1; - a=(a>>1)|(f<<7); - f=(f&0xc4)|(a&0x28)|t; - } -endinstr; - -instr(32,7); - if(f&0x40)pc++; - else jr; -endinstr; - -instr(33,10); - if(!ixoriy){ - l=fetch(pc),pc++; - h=fetch(pc),pc++; - } - else { - if(ixoriy==1)ix=fetch2(pc); - else iy=fetch2(pc); - pc+=2; - } -endinstr; - -instr(34,16); - {unsigned short addr=fetch2(pc); - pc+=2; - if(!ixoriy)store2b(addr,h,l); - else if(ixoriy==1)store2(addr,ix); - else store2(addr,iy); - } -endinstr; - -instr(35,6); - if(!ixoriy){if(!++l)h++;} - else if(ixoriy==1)ix++; - else iy++; -endinstr; - -instr(36,4); - if(ixoriy==0)inc(h); - else{unsigned char t; - t=(ixoriy==1?ix:iy)>>8; - inc(t); - if(ixoriy==1)ix=(ix&0xff)|(t<<8); - else iy=(iy&0xff)|(t<<8); - } -endinstr; - -instr(37,4); - if(ixoriy==0)dec(h); - else{unsigned char t; - t=(ixoriy==1?ix:iy)>>8; - dec(t); - if(ixoriy==1)ix=(ix&0xff)|(t<<8); - else iy=(iy&0xff)|(t<<8); - } -endinstr; - -instr(38,7); - setxh(fetch(pc)); - pc++; -endinstr; - -instr(39,4); - { - /* Frank D. Cringle's DAA implementation, converted from yaze 1.10 */ - unsigned int acu,temp,cbits; - - acu=a; - temp=(acu&15); - cbits=(f&1); - if(f&2) /* if N */ - { - /* last operation was a subtract */ - int hd=(cbits || (acu>0x99)); - if((f&16) || (temp>9)) - { /* adjust low digit */ - if(temp>5) f&=~16; - acu-=6; - acu&=0xff; - } - /* adjust high digit */ - if(hd) - acu-=0x160; - } - else - { - /* last operation was an add */ - if((f&16) || (temp>9)) - { - /* adjust low digit */ - if(temp>9) f|=16; else f&=~16; - acu+=6; - } - /* adjust high digit */ - if(cbits || ((acu&0x1f0)>0x90)) - acu+=0x60; - } - cbits|=((acu>>8)&1); - acu&=0xff; - a=acu; - f=((acu&0xa8)|((acu==0)<<6)|(f&0x12)|parity(a)|cbits); - } -endinstr; - -instr(40,7); - if(f&0x40)jr; - else pc++; -endinstr; - -instr(41,11); - if(!ixoriy)addhl(h,l); - else if(ixoriy==1)addhl((ix>>8),(ix&0xff)); - else addhl((iy>>8),(iy&0xff)); -endinstr; - -instr(42,16); - {unsigned short addr=fetch2(pc); - pc+=2; - if(!ixoriy){ - l=fetch(addr); - h=fetch(addr+1); - } - else if(ixoriy==1)ix=fetch2(addr); - else iy=fetch2(addr); - } -endinstr; - -instr(43,6); - if(!ixoriy){if(!l--)h--;} - else if(ixoriy==1)ix--; - else iy--; -endinstr; - -instr(44,4); - if(!ixoriy)inc(l); - else {unsigned char t; - t=(ixoriy==1?ix:iy); - inc(t); - if(ixoriy==1)ix=(ix&0xff00)|t; - else iy=(iy&0xff00)|t; - } -endinstr; - -instr(45,4); - if(!ixoriy)dec(l); - else {unsigned char t; - t=(ixoriy==1?ix:iy); - dec(t); - if(ixoriy==1)ix=(ix&0xff00)|t; - else iy=(iy&0xff00)|t; - } -endinstr; - -instr(46,7); - setxl(fetch(pc)); - pc++; -endinstr; - -instr(47,4); - a=~a; - f=(f&0xc5)|(a&0x28)|0x12; -endinstr; - -instr(48,7); - if(f&1)pc++; - else jr; -endinstr; - -instr(49,10); - sp=fetch2(pc); - pc+=2; -endinstr; - -instr(50,13); - {unsigned short addr=fetch2(pc); - pc+=2; - store(addr,a); - } -endinstr; - -instr(51,6); - sp++; -endinstr; - -HLinstr(52,11,8); - {unsigned char t=fetch(addr); - inc(t); - store(addr,t); - } -endinstr; - -HLinstr(53,11,8); - {unsigned char t=fetch(addr); - dec(t); - store(addr,t); - } -endinstr; - -HLinstr(54,10,5); - store(addr,fetch(pc)); - pc++; -endinstr; - -instr(55,4); - f=(f&0xc4)|1|(a&0x28); -endinstr; - -instr(56,7); - if(f&1)jr; - else pc++; -endinstr; - -instr(57,11); - addhl((sp>>8),(sp&0xff)); -endinstr; - -instr(58,13); - {unsigned short addr=fetch2(pc); - pc+=2; - a=fetch(addr); - } -endinstr; - -instr(59,6); - sp--; -endinstr; - -instr(60,4); - inc(a); -endinstr; - -instr(61,4); - dec(a); -endinstr; - -instr(62,7); - a=fetch(pc),pc++; -endinstr; - -instr(63,4); - f=(f&0xc4)|(cy^1)|(cy<<4)|(a&0x28); -endinstr; - -instr(0x40,4); - /* ld b,b */ -endinstr; - -instr(0x41,4); - b=c; -endinstr; - -instr(0x42,4); - b=d; -endinstr; - -instr(0x43,4); - b=e; -endinstr; - -instr(0x44,4); - b=xh; -endinstr; - -instr(0x45,4); - b=xl; -endinstr; - -HLinstr(0x46,7,8); - b=fetch(addr); -endinstr; - -instr(0x47,4); - b=a; -endinstr; - -instr(0x48,4); - c=b; -endinstr; - -instr(0x49,4); - /* ld c,c */ -endinstr; - -instr(0x4a,4); - c=d; -endinstr; - -instr(0x4b,4); - c=e; -endinstr; - -instr(0x4c,4); - c=xh; -endinstr; - -instr(0x4d,4); - c=xl; -endinstr; - -HLinstr(0x4e,7,8); - c=fetch(addr); -endinstr; - -instr(0x4f,4); - c=a; -endinstr; - -instr(0x50,4); - d=b; -endinstr; - -instr(0x51,4); - d=c; -endinstr; - -instr(0x52,4); - /* ld d,d */ -endinstr; - -instr(0x53,4); - d=e; -endinstr; - -instr(0x54,4); - d=xh; -endinstr; - -instr(0x55,4); - d=xl; -endinstr; - -HLinstr(0x56,7,8); - d=fetch(addr); -endinstr; - -instr(0x57,4); - d=a; -endinstr; - -instr(0x58,4); - e=b; -endinstr; - -instr(0x59,4); - e=c; -endinstr; - -instr(0x5a,4); - e=d; -endinstr; - -instr(0x5b,4); - /* ld e,e */ -endinstr; - -instr(0x5c,4); - e=xh; -endinstr; - -instr(0x5d,4); - e=xl; -endinstr; - -HLinstr(0x5e,7,8); - e=fetch(addr); -endinstr; - -instr(0x5f,4); - e=a; -endinstr; - -instr(0x60,4); - setxh(b); -endinstr; - -instr(0x61,4); - setxh(c); -endinstr; - -instr(0x62,4); - setxh(d); -endinstr; - -instr(0x63,4); - setxh(e); -endinstr; - -instr(0x64,4); - /* ld h,h */ -endinstr; - -instr(0x65,4); - setxh(xl); -endinstr; - -HLinstr(0x66,7,8); - h=fetch(addr); -endinstr; - -instr(0x67,4); - setxh(a); -endinstr; - -instr(0x68,4); - setxl(b); -endinstr; - -instr(0x69,4); - setxl(c); -endinstr; - -instr(0x6a,4); - setxl(d); -endinstr; - -instr(0x6b,4); - setxl(e); -endinstr; - -instr(0x6c,4); - setxl(xh); -endinstr; - -instr(0x6d,4); - /* ld l,l */ -endinstr; - -HLinstr(0x6e,7,8); - l=fetch(addr); -endinstr; - -instr(0x6f,4); - setxl(a); -endinstr; - -HLinstr(0x70,7,8); - store(addr,b); -endinstr; - -HLinstr(0x71,7,8); - store(addr,c); -endinstr; - -HLinstr(0x72,7,8); - store(addr,d); -endinstr; - -HLinstr(0x73,7,8); - store(addr,e); -endinstr; - -HLinstr(0x74,7,8); - store(addr,h); -endinstr; - -HLinstr(0x75,7,8); - store(addr,l); -endinstr; - -instr(0x76,4); - /* Was HALT - ZXCC ignores HALT */ -endinstr; - -HLinstr(0x77,7,8); - store(addr,a); -endinstr; - -instr(0x78,4); - a=b; -endinstr; - -instr(0x79,4); - a=c; -endinstr; - -instr(0x7a,4); - a=d; -endinstr; - -instr(0x7b,4); - a=e; -endinstr; - -instr(0x7c,4); - a=xh; -endinstr; - -instr(0x7d,4); - a=xl; -endinstr; - -HLinstr(0x7e,7,8); - a=fetch(addr); -endinstr; - -instr(0x7f,4); - /* ld a,a */ -endinstr; - -instr(0x80,4); - adda(b,0); -endinstr; - -instr(0x81,4); - adda(c,0); -endinstr; - -instr(0x82,4); - adda(d,0); -endinstr; - -instr(0x83,4); - adda(e,0); -endinstr; - -instr(0x84,4); - adda(xh,0); -endinstr; - -instr(0x85,4); - adda(xl,0); -endinstr; - -HLinstr(0x86,7,8); - adda(fetch(addr),0); -endinstr; - -instr(0x87,4); - adda(a,0); -endinstr; - -instr(0x88,4); - adda(b,cy); -endinstr; - -instr(0x89,4); - adda(c,cy); -endinstr; - -instr(0x8a,4); - adda(d,cy); -endinstr; - -instr(0x8b,4); - adda(e,cy); -endinstr; - -instr(0x8c,4); - adda(xh,cy); -endinstr; - -instr(0x8d,4); - adda(xl,cy); -endinstr; - -HLinstr(0x8e,7,8); - adda(fetch(addr),cy); -endinstr; - -instr(0x8f,4); - adda(a,cy); -endinstr; - -instr(0x90,4); - suba(b,0); -endinstr; - -instr(0x91,4); - suba(c,0); -endinstr; - -instr(0x92,4); - suba(d,0); -endinstr; - -instr(0x93,4); - suba(e,0); -endinstr; - -instr(0x94,4); - suba(xh,0); -endinstr; - -instr(0x95,4); - suba(xl,0); -endinstr; - -HLinstr(0x96,7,8); - suba(fetch(addr),0); -endinstr; - -instr(0x97,4); - suba(a,0); -endinstr; - -instr(0x98,4); - suba(b,cy); -endinstr; - -instr(0x99,4); - suba(c,cy); -endinstr; - -instr(0x9a,4); - suba(d,cy); -endinstr; - -instr(0x9b,4); - suba(e,cy); -endinstr; - -instr(0x9c,4); - suba(xh,cy); -endinstr; - -instr(0x9d,4); - suba(xl,cy); -endinstr; - -HLinstr(0x9e,7,8); - suba(fetch(addr),cy); -endinstr; - -instr(0x9f,4); - suba(a,cy); -endinstr; - -instr(0xa0,4); - anda(b); -endinstr; - -instr(0xa1,4); - anda(c); -endinstr; - -instr(0xa2,4); - anda(d); -endinstr; - -instr(0xa3,4); - anda(e); -endinstr; - -instr(0xa4,4); - anda(xh); -endinstr; - -instr(0xa5,4); - anda(xl); -endinstr; - -HLinstr(0xa6,7,8); - anda(fetch(addr)); -endinstr; - -instr(0xa7,4); - anda(a); -endinstr; - -instr(0xa8,4); - xora(b); -endinstr; - -instr(0xa9,4); - xora(c); -endinstr; - -instr(0xaa,4); - xora(d); -endinstr; - -instr(0xab,4); - xora(e); -endinstr; - -instr(0xac,4); - xora(xh); -endinstr; - -instr(0xad,4); - xora(xl); -endinstr; - -HLinstr(0xae,7,8); - xora(fetch(addr)); -endinstr; - -instr(0xaf,4); - xora(a); -endinstr; - -instr(0xb0,4); - ora(b); -endinstr; - -instr(0xb1,4); - ora(c); -endinstr; - -instr(0xb2,4); - ora(d); -endinstr; - -instr(0xb3,4); - ora(e); -endinstr; - -instr(0xb4,4); - ora(xh); -endinstr; - -instr(0xb5,4); - ora(xl); -endinstr; - -HLinstr(0xb6,7,8); - ora(fetch(addr)); -endinstr; - -instr(0xb7,4); - ora(a); -endinstr; - -instr(0xb8,4); - cpa(b); -endinstr; - -instr(0xb9,4); - cpa(c); -endinstr; - -instr(0xba,4); - cpa(d); -endinstr; - -instr(0xbb,4); - cpa(e); -endinstr; - -instr(0xbc,4); - cpa(xh); -endinstr; - -instr(0xbd,4); - cpa(xl); -endinstr; - -HLinstr(0xbe,7,8); - cpa(fetch(addr)); -endinstr; - -instr(0xbf,4); - cpa(a); -endinstr; - -instr(0xc0,5); - if(!(f&0x40))ret; -endinstr; - -instr(0xc1,10); - pop1(b,c); -endinstr; - -instr(0xc2,10); - if(!(f&0x40))jp; - else pc+=2; -endinstr; - -instr(0xc3,10); - jp; -endinstr; - -instr(0xc4,10); - if(!(f&0x40))call; - else pc+=2; -endinstr; - -instr(0xc5,11); - push1(b,c); -endinstr; - -instr(0xc6,7); - adda(fetch(pc),0); - pc++; -endinstr; - -instr(0xc7,11); - push2(pc); - pc=0; -endinstr; - -instr(0xc8,5); - if(f&0x40)ret; -endinstr; - -instr(0xc9,4); - ret; -endinstr; - -instr(0xca,10); - if(f&0x40)jp; - else pc+=2; -endinstr; - -instr(0xcb,4); -#include "cbops.h" -endinstr; - -instr(0xcc,10); - if(f&0x40)call; - else pc+=2; -endinstr; - -instr(0xcd,10); - call; -endinstr; - -instr(0xce,7); - adda(fetch(pc),cy); - pc++; -endinstr; - -instr(0xcf,11); - push2(pc); - pc=8; -endinstr; - -instr(0xd0,5); - if(!cy)ret; -endinstr; - -instr(0xd1,10); - pop1(d,e); -endinstr; - -instr(0xd2,10); - if(!cy)jp; - else pc+=2; -endinstr; - -instr(0xd3,11); - tstates+=out(tstates,a,fetch(pc),a); - pc++; -endinstr; - -instr(0xd4,10); - if(!cy)call; - else pc+=2; -endinstr; - -instr(0xd5,11); - push1(d,e); -endinstr; - -instr(0xd6,7); - suba(fetch(pc),0); - pc++; -endinstr; - -instr(0xd7,11); - push2(pc); - pc=16; -endinstr; - -instr(0xd8,5); - if(cy)ret; -endinstr; - -instr(0xd9,4); - swap(b,b1); - swap(c,c1); - swap(d,d1); - swap(e,e1); - swap(h,h1); - swap(l,l1); -endinstr; - -instr(0xda,10); - if(cy)jp; - else pc+=2; -endinstr; - -instr(0xdb,11); - {unsigned short t; - a=t=in(tstates,a,fetch(pc)); - tstates+=t>>8; - pc++; - } -endinstr; - -instr(0xdc,10); - if(cy)call; - else pc+=2; -endinstr; - -instr(0xdd,4); - new_ixoriy=1; - intsample=0; -endinstr; - -instr(0xde,7); - suba(fetch(pc),cy); - pc++; -endinstr; - -instr(0xdf,11); - push2(pc); - pc=24; -endinstr; - -instr(0xe0,5); - if(!(f&4))ret; -endinstr; - -instr(0xe1,10); - if(!ixoriy)pop1(h,l); - else if(ixoriy==1)pop2(ix); - else pop2(iy); -endinstr; - -instr(0xe2,10); - if(!(f&4))jp; - else pc+=2; -endinstr; - -instr(0xe3,19); - if(!ixoriy){ - unsigned short t=fetch2(sp); - store2b(sp,h,l); - l=t; - h=t>>8; - } - else if(ixoriy==1){ - unsigned short t=fetch2(sp); - store2(sp,ix); - ix=t; - } - else{ - unsigned short t=fetch2(sp); - store2(sp,iy); - iy=t; - } -endinstr; - -instr(0xe4,10); - if(!(f&4))call; - else pc+=2; -endinstr; - -instr(0xe5,11); - if(!ixoriy)push1(h,l); - else if(ixoriy==1)push2(ix); - else push2(iy); -endinstr; - -instr(0xe6,7); - anda(fetch(pc)); - pc++; -endinstr; - -instr(0xe7,11); - push2(pc); - pc=32; -endinstr; - -instr(0xe8,5); - if(f&4)ret; -endinstr; - -instr(0xe9,4); - pc=!ixoriy?hl:ixoriy==1?ix:iy; -endinstr; - -instr(0xea,10); - if(f&4)jp; - else pc+=2; -endinstr; - -instr(0xeb,4); - swap(h,d); - swap(e,l); -endinstr; - -instr(0xec,10); - if(f&4)call; - else pc+=2; -endinstr; - -instr(0xed,4); -#include"edops.h" -endinstr; - -instr(0xee,7); - xora(fetch(pc)); - pc++; -endinstr; - -instr(0xef,11); - push2(pc); - pc=40; -endinstr; - -instr(0xf0,5); - if(!(f&0x80))ret; -endinstr; - -instr(0xf1,10); - pop1(a,f); -endinstr; - -instr(0xf2,10); - if(!(f&0x80))jp; - else pc+=2; -endinstr; - -instr(0xf3,4); - iff1=iff2=0; - intsample=0; -endinstr; - -instr(0xf4,10); - if(!(f&0x80))call; - else pc+=2; -endinstr; - -instr(0xf5,11); - push1(a,f); -endinstr; - -instr(0xf6,7); - ora(fetch(pc)); - pc++; -endinstr; - -instr(0xf7,11); - push2(pc); - pc=48; -endinstr; - -instr(0xf8,5); - if(f&0x80)ret; -endinstr; - -instr(0xf9,6); - sp=!ixoriy?hl:ixoriy==1?ix:iy; -endinstr; - -instr(0xfa,10); - if(f&0x80)jp; - else pc+=2; -endinstr; - -instr(0xfb,4); - iff1=iff2=1; - intsample=0; -endinstr; - -instr(0xfc,10); - if(f&0x80)call; - else pc+=2; -endinstr; - -instr(0xfd,4); - new_ixoriy=2; - intsample=0; -endinstr; - -instr(0xfe,7); - cpa(fetch(pc)); - pc++; -endinstr; - -instr(0xff,11); - push2(pc); - pc=56; -endinstr; - +/* Emulations of the Z80 CPU instruction set - part of xz80. + * Copyright (C) 1994 Ian Collier. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define instr(opcode,cycles) case opcode: {tstates+=cycles +#define HLinstr(opcode,cycles,morecycles) \ + case opcode: {unsigned short addr; \ + tstates+=cycles; \ + if(ixoriy==0)addr=hl; \ + else tstates+=morecycles, \ + addr=(ixoriy==1?ix:iy)+ \ + (signed char)fetch(pc),\ + pc++ +#define endinstr }; break + +#define cy (f&1) + +#define xh (ixoriy==0?h:ixoriy==1?(ix>>8):(iy>>8)) +#define xl (ixoriy==0?l:ixoriy==1?(ix&0xff):(iy&0xff)) + +#define setxh(x) (ixoriy==0?(h=(x)):ixoriy==1?(ix=(ix&0xff)|((x)<<8)):\ + (iy=(iy&0xff)|((x)<<8))) +#define setxl(x) (ixoriy==0?(l=(x)):ixoriy==1?(ix=(ix&0xff00)|(x)):\ + (iy=(iy&0xff00)|(x))) + +#define inc(var) /* 8-bit increment */ ( var++,\ + f=(f&1)|(var&0xa8)|\ + ((!(var&15))<<4)|((!var)<<6)|\ + ((var==128)<<2)\ + ) +#define dec(var) /* 8-bit decrement */ ( f=(f&1)|((!(var&15))<<4)|2,\ + --var,\ + f|=(var&0xa8)|((var==127)<<2)|\ + ((!var)<<6)\ + ) +#define swap(x,y) {unsigned char t=x; x=y; y=t;} +#define addhl(hi,lo) /* 16-bit add */ if(!ixoriy){\ + unsigned short t;\ + l=t=l+(lo);\ + f=(f&0xc4)|(((t>>=8)+(h&0x0f)+((hi)&0x0f)>15)<<4);\ + h=t+=h+(hi);\ + f|=(h&0x28)|(t>>8);\ + }\ + else do{unsigned long t=(ixoriy==1?ix:iy);\ + f=(f&0xc4)|(((t&0xfff)+((hi<<8)|lo)>0xfff)<<4);\ + t+=(hi<<8)|lo;\ + if(ixoriy==1)ix=t; else iy=t;\ + f|=((t>>8)&0x28)|(t>>16);\ + } while(0) +#define adda(x,c) /* 8-bit add */ do{unsigned short y;\ + unsigned char z=(x);\ + y=a+z+(c);\ + f=(y&0xa8)|(y>>8)|(((a&0x0f)+(z&0x0f)+(c)>15)<<4)|\ + (((~a^z)&0x80&(y^a))>>5);\ + f|=(!(a=y))<<6;\ + } while(0) +#define suba(x,c) /* 8-bit subtract */ do{unsigned short y;\ + unsigned char z=(x);\ + y=(a-z-(c))&0x1ff;\ + f=(y&0xa8)|(y>>8)|(((a&0x0f)<(z&0x0f)+(c))<<4)|\ + (((a^z)&0x80&(y^a))>>5)|2;\ + f|=(!(a=y))<<6;\ + } while(0) +#define cpa(x) /* 8-bit compare */ do{unsigned short y;\ + unsigned char z=(x);\ + y=(a-z)&0x1ff;\ + f=(y&0xa8)|(y>>8)|(((a&0x0f)<(z&0x0f))<<4)|\ + (((a^z)&0x80&(y^a))>>5)|2|((!y)<<6);\ + } while(0) +#define anda(x) /* logical and */ do{\ + a&=(x);\ + f=(a&0xa8)|((!a)<<6)|0x10|parity(a);\ + } while(0) +#define xora(x) /* logical xor */ do{\ + a^=(x);\ + f=(a&0xa8)|((!a)<<6)|parity(a);\ + } while(0) +#define ora(x) /* logical or */ do{\ + a|=(x);\ + f=(a&0xa8)|((!a)<<6)|parity(a);\ + } while(0) + +#define jr /* execute relative jump */ do{int j=(signed char)fetch(pc);\ + pc+=j+1;\ + tstates+=5;\ + } while(0) +#define jp /* execute jump */ (pc=fetch2(pc)) +#define call /* execute call */ do{\ + tstates+=7;\ + push2(pc+2);\ + jp;\ + } while(0) +#define ret /* execute return */ do{\ + tstates+=6;\ + pop2(pc);\ + } while(0) +#define pop2(var) /* pop 16-bit register */ (var=fetch2(sp),sp+=2) +#define pop1(v1,v2) /* pop register pair */ (v2=fetch(sp),\ + v1=fetch(sp+1),sp+=2) +#define push2(val) /* push 16-bit register */ do{sp-=2;store2(sp,(val));}\ + while(0) +#define push1(v1,v2) /* push register pair */ do{sp-=2;\ + store2b(sp,v1,v2);\ + }while(0) + +instr(0,4); + /* nop */ +endinstr; + +instr(1,10); + c=fetch(pc),pc++; + b=fetch(pc),pc++; +endinstr; + +instr(2,7); + store(bc,a); +endinstr; + +instr(3,6); + if(!++c)b++; +endinstr; + +instr(4,4); + inc(b); +endinstr; + +instr(5,4); + dec(b); +endinstr; + +instr(6,7); + b=fetch(pc),pc++; +endinstr; + +instr(7,4); + a=(a<<1)|(a>>7); + f=(f&0xc4)|(a&0x29); +endinstr; + +instr(8,4); + swap(a,a1); + swap(f,f1); +endinstr; + +instr(9,11); + addhl(b,c); +endinstr; + +instr(10,7); + a=fetch(bc); +endinstr; + +instr(11,6); + if(!c--)b--; +endinstr; + +instr(12,4); + inc(c); +endinstr; + +instr(13,4); + dec(c); +endinstr; + +instr(14,7); + c=fetch(pc),pc++; +endinstr; + +instr(15,4); + f=(f&0xc4)|(a&1); + a=(a>>1)|(a<<7); + f|=a&0x28; +endinstr; + +instr(16,8); + if(!--b)pc++; + else jr; +endinstr; + +instr(17,10); + e=fetch(pc),pc++; + d=fetch(pc),pc++; +endinstr; + +instr(18,7); + store(de,a); +endinstr; + +instr(19,6); + if(!++e)d++; +endinstr; + +instr(20,4); + inc(d); +endinstr; + +instr(21,4); + dec(d); +endinstr; + +instr(22,7); + d=fetch(pc),pc++; +endinstr; + +instr(23,4); + {int t=a>>7; + a=(a<<1)|(f&1); + f=(f&0xc4)|(a&0x28)|t; + } +endinstr; + +instr(24,7); + jr; +endinstr; + +instr(25,11); + addhl(d,e); +endinstr; + +instr(26,7); + a=fetch(de); +endinstr; + +instr(27,6); + if(!e--)d--; +endinstr; + +instr(28,4); + inc(e); +endinstr; + +instr(29,4); + dec(e); +endinstr; + +instr(30,7); + e=fetch(pc),pc++; +endinstr; + +instr(31,4); + {int t=a&1; + a=(a>>1)|(f<<7); + f=(f&0xc4)|(a&0x28)|t; + } +endinstr; + +instr(32,7); + if(f&0x40)pc++; + else jr; +endinstr; + +instr(33,10); + if(!ixoriy){ + l=fetch(pc),pc++; + h=fetch(pc),pc++; + } + else { + if(ixoriy==1)ix=fetch2(pc); + else iy=fetch2(pc); + pc+=2; + } +endinstr; + +instr(34,16); + {unsigned short addr=fetch2(pc); + pc+=2; + if(!ixoriy)store2b(addr,h,l); + else if(ixoriy==1)store2(addr,ix); + else store2(addr,iy); + } +endinstr; + +instr(35,6); + if(!ixoriy){if(!++l)h++;} + else if(ixoriy==1)ix++; + else iy++; +endinstr; + +instr(36,4); + if(ixoriy==0)inc(h); + else{unsigned char t; + t=(ixoriy==1?ix:iy)>>8; + inc(t); + if(ixoriy==1)ix=(ix&0xff)|(t<<8); + else iy=(iy&0xff)|(t<<8); + } +endinstr; + +instr(37,4); + if(ixoriy==0)dec(h); + else{unsigned char t; + t=(ixoriy==1?ix:iy)>>8; + dec(t); + if(ixoriy==1)ix=(ix&0xff)|(t<<8); + else iy=(iy&0xff)|(t<<8); + } +endinstr; + +instr(38,7); + setxh(fetch(pc)); + pc++; +endinstr; + +instr(39,4); + { + /* Frank D. Cringle's DAA implementation, converted from yaze 1.10 */ + unsigned int acu,temp,cbits; + + acu=a; + temp=(acu&15); + cbits=(f&1); + if(f&2) /* if N */ + { + /* last operation was a subtract */ + int hd=(cbits || (acu>0x99)); + if((f&16) || (temp>9)) + { /* adjust low digit */ + if(temp>5) f&=~16; + acu-=6; + acu&=0xff; + } + /* adjust high digit */ + if(hd) + acu-=0x160; + } + else + { + /* last operation was an add */ + if((f&16) || (temp>9)) + { + /* adjust low digit */ + if(temp>9) f|=16; else f&=~16; + acu+=6; + } + /* adjust high digit */ + if(cbits || ((acu&0x1f0)>0x90)) + acu+=0x60; + } + cbits|=((acu>>8)&1); + acu&=0xff; + a=acu; + f=((acu&0xa8)|((acu==0)<<6)|(f&0x12)|parity(a)|cbits); + } +endinstr; + +instr(40,7); + if(f&0x40)jr; + else pc++; +endinstr; + +instr(41,11); + if(!ixoriy)addhl(h,l); + else if(ixoriy==1)addhl((ix>>8),(ix&0xff)); + else addhl((iy>>8),(iy&0xff)); +endinstr; + +instr(42,16); + {unsigned short addr=fetch2(pc); + pc+=2; + if(!ixoriy){ + l=fetch(addr); + h=fetch(addr+1); + } + else if(ixoriy==1)ix=fetch2(addr); + else iy=fetch2(addr); + } +endinstr; + +instr(43,6); + if(!ixoriy){if(!l--)h--;} + else if(ixoriy==1)ix--; + else iy--; +endinstr; + +instr(44,4); + if(!ixoriy)inc(l); + else {unsigned char t; + t=(ixoriy==1?ix:iy); + inc(t); + if(ixoriy==1)ix=(ix&0xff00)|t; + else iy=(iy&0xff00)|t; + } +endinstr; + +instr(45,4); + if(!ixoriy)dec(l); + else {unsigned char t; + t=(ixoriy==1?ix:iy); + dec(t); + if(ixoriy==1)ix=(ix&0xff00)|t; + else iy=(iy&0xff00)|t; + } +endinstr; + +instr(46,7); + setxl(fetch(pc)); + pc++; +endinstr; + +instr(47,4); + a=~a; + f=(f&0xc5)|(a&0x28)|0x12; +endinstr; + +instr(48,7); + if(f&1)pc++; + else jr; +endinstr; + +instr(49,10); + sp=fetch2(pc); + pc+=2; +endinstr; + +instr(50,13); + {unsigned short addr=fetch2(pc); + pc+=2; + store(addr,a); + } +endinstr; + +instr(51,6); + sp++; +endinstr; + +HLinstr(52,11,8); + {unsigned char t=fetch(addr); + inc(t); + store(addr,t); + } +endinstr; + +HLinstr(53,11,8); + {unsigned char t=fetch(addr); + dec(t); + store(addr,t); + } +endinstr; + +HLinstr(54,10,5); + store(addr,fetch(pc)); + pc++; +endinstr; + +instr(55,4); + f=(f&0xc4)|1|(a&0x28); +endinstr; + +instr(56,7); + if(f&1)jr; + else pc++; +endinstr; + +instr(57,11); + addhl((sp>>8),(sp&0xff)); +endinstr; + +instr(58,13); + {unsigned short addr=fetch2(pc); + pc+=2; + a=fetch(addr); + } +endinstr; + +instr(59,6); + sp--; +endinstr; + +instr(60,4); + inc(a); +endinstr; + +instr(61,4); + dec(a); +endinstr; + +instr(62,7); + a=fetch(pc),pc++; +endinstr; + +instr(63,4); + f=(f&0xc4)|(cy^1)|(cy<<4)|(a&0x28); +endinstr; + +instr(0x40,4); + /* ld b,b */ +endinstr; + +instr(0x41,4); + b=c; +endinstr; + +instr(0x42,4); + b=d; +endinstr; + +instr(0x43,4); + b=e; +endinstr; + +instr(0x44,4); + b=xh; +endinstr; + +instr(0x45,4); + b=xl; +endinstr; + +HLinstr(0x46,7,8); + b=fetch(addr); +endinstr; + +instr(0x47,4); + b=a; +endinstr; + +instr(0x48,4); + c=b; +endinstr; + +instr(0x49,4); + /* ld c,c */ +endinstr; + +instr(0x4a,4); + c=d; +endinstr; + +instr(0x4b,4); + c=e; +endinstr; + +instr(0x4c,4); + c=xh; +endinstr; + +instr(0x4d,4); + c=xl; +endinstr; + +HLinstr(0x4e,7,8); + c=fetch(addr); +endinstr; + +instr(0x4f,4); + c=a; +endinstr; + +instr(0x50,4); + d=b; +endinstr; + +instr(0x51,4); + d=c; +endinstr; + +instr(0x52,4); + /* ld d,d */ +endinstr; + +instr(0x53,4); + d=e; +endinstr; + +instr(0x54,4); + d=xh; +endinstr; + +instr(0x55,4); + d=xl; +endinstr; + +HLinstr(0x56,7,8); + d=fetch(addr); +endinstr; + +instr(0x57,4); + d=a; +endinstr; + +instr(0x58,4); + e=b; +endinstr; + +instr(0x59,4); + e=c; +endinstr; + +instr(0x5a,4); + e=d; +endinstr; + +instr(0x5b,4); + /* ld e,e */ +endinstr; + +instr(0x5c,4); + e=xh; +endinstr; + +instr(0x5d,4); + e=xl; +endinstr; + +HLinstr(0x5e,7,8); + e=fetch(addr); +endinstr; + +instr(0x5f,4); + e=a; +endinstr; + +instr(0x60,4); + setxh(b); +endinstr; + +instr(0x61,4); + setxh(c); +endinstr; + +instr(0x62,4); + setxh(d); +endinstr; + +instr(0x63,4); + setxh(e); +endinstr; + +instr(0x64,4); + /* ld h,h */ +endinstr; + +instr(0x65,4); + setxh(xl); +endinstr; + +HLinstr(0x66,7,8); + h=fetch(addr); +endinstr; + +instr(0x67,4); + setxh(a); +endinstr; + +instr(0x68,4); + setxl(b); +endinstr; + +instr(0x69,4); + setxl(c); +endinstr; + +instr(0x6a,4); + setxl(d); +endinstr; + +instr(0x6b,4); + setxl(e); +endinstr; + +instr(0x6c,4); + setxl(xh); +endinstr; + +instr(0x6d,4); + /* ld l,l */ +endinstr; + +HLinstr(0x6e,7,8); + l=fetch(addr); +endinstr; + +instr(0x6f,4); + setxl(a); +endinstr; + +HLinstr(0x70,7,8); + store(addr,b); +endinstr; + +HLinstr(0x71,7,8); + store(addr,c); +endinstr; + +HLinstr(0x72,7,8); + store(addr,d); +endinstr; + +HLinstr(0x73,7,8); + store(addr,e); +endinstr; + +HLinstr(0x74,7,8); + store(addr,h); +endinstr; + +HLinstr(0x75,7,8); + store(addr,l); +endinstr; + +instr(0x76,4); + /* Was HALT - ZXCC ignores HALT */ +endinstr; + +HLinstr(0x77,7,8); + store(addr,a); +endinstr; + +instr(0x78,4); + a=b; +endinstr; + +instr(0x79,4); + a=c; +endinstr; + +instr(0x7a,4); + a=d; +endinstr; + +instr(0x7b,4); + a=e; +endinstr; + +instr(0x7c,4); + a=xh; +endinstr; + +instr(0x7d,4); + a=xl; +endinstr; + +HLinstr(0x7e,7,8); + a=fetch(addr); +endinstr; + +instr(0x7f,4); + /* ld a,a */ +endinstr; + +instr(0x80,4); + adda(b,0); +endinstr; + +instr(0x81,4); + adda(c,0); +endinstr; + +instr(0x82,4); + adda(d,0); +endinstr; + +instr(0x83,4); + adda(e,0); +endinstr; + +instr(0x84,4); + adda(xh,0); +endinstr; + +instr(0x85,4); + adda(xl,0); +endinstr; + +HLinstr(0x86,7,8); + adda(fetch(addr),0); +endinstr; + +instr(0x87,4); + adda(a,0); +endinstr; + +instr(0x88,4); + adda(b,cy); +endinstr; + +instr(0x89,4); + adda(c,cy); +endinstr; + +instr(0x8a,4); + adda(d,cy); +endinstr; + +instr(0x8b,4); + adda(e,cy); +endinstr; + +instr(0x8c,4); + adda(xh,cy); +endinstr; + +instr(0x8d,4); + adda(xl,cy); +endinstr; + +HLinstr(0x8e,7,8); + adda(fetch(addr),cy); +endinstr; + +instr(0x8f,4); + adda(a,cy); +endinstr; + +instr(0x90,4); + suba(b,0); +endinstr; + +instr(0x91,4); + suba(c,0); +endinstr; + +instr(0x92,4); + suba(d,0); +endinstr; + +instr(0x93,4); + suba(e,0); +endinstr; + +instr(0x94,4); + suba(xh,0); +endinstr; + +instr(0x95,4); + suba(xl,0); +endinstr; + +HLinstr(0x96,7,8); + suba(fetch(addr),0); +endinstr; + +instr(0x97,4); + suba(a,0); +endinstr; + +instr(0x98,4); + suba(b,cy); +endinstr; + +instr(0x99,4); + suba(c,cy); +endinstr; + +instr(0x9a,4); + suba(d,cy); +endinstr; + +instr(0x9b,4); + suba(e,cy); +endinstr; + +instr(0x9c,4); + suba(xh,cy); +endinstr; + +instr(0x9d,4); + suba(xl,cy); +endinstr; + +HLinstr(0x9e,7,8); + suba(fetch(addr),cy); +endinstr; + +instr(0x9f,4); + suba(a,cy); +endinstr; + +instr(0xa0,4); + anda(b); +endinstr; + +instr(0xa1,4); + anda(c); +endinstr; + +instr(0xa2,4); + anda(d); +endinstr; + +instr(0xa3,4); + anda(e); +endinstr; + +instr(0xa4,4); + anda(xh); +endinstr; + +instr(0xa5,4); + anda(xl); +endinstr; + +HLinstr(0xa6,7,8); + anda(fetch(addr)); +endinstr; + +instr(0xa7,4); + anda(a); +endinstr; + +instr(0xa8,4); + xora(b); +endinstr; + +instr(0xa9,4); + xora(c); +endinstr; + +instr(0xaa,4); + xora(d); +endinstr; + +instr(0xab,4); + xora(e); +endinstr; + +instr(0xac,4); + xora(xh); +endinstr; + +instr(0xad,4); + xora(xl); +endinstr; + +HLinstr(0xae,7,8); + xora(fetch(addr)); +endinstr; + +instr(0xaf,4); + xora(a); +endinstr; + +instr(0xb0,4); + ora(b); +endinstr; + +instr(0xb1,4); + ora(c); +endinstr; + +instr(0xb2,4); + ora(d); +endinstr; + +instr(0xb3,4); + ora(e); +endinstr; + +instr(0xb4,4); + ora(xh); +endinstr; + +instr(0xb5,4); + ora(xl); +endinstr; + +HLinstr(0xb6,7,8); + ora(fetch(addr)); +endinstr; + +instr(0xb7,4); + ora(a); +endinstr; + +instr(0xb8,4); + cpa(b); +endinstr; + +instr(0xb9,4); + cpa(c); +endinstr; + +instr(0xba,4); + cpa(d); +endinstr; + +instr(0xbb,4); + cpa(e); +endinstr; + +instr(0xbc,4); + cpa(xh); +endinstr; + +instr(0xbd,4); + cpa(xl); +endinstr; + +HLinstr(0xbe,7,8); + cpa(fetch(addr)); +endinstr; + +instr(0xbf,4); + cpa(a); +endinstr; + +instr(0xc0,5); + if(!(f&0x40))ret; +endinstr; + +instr(0xc1,10); + pop1(b,c); +endinstr; + +instr(0xc2,10); + if(!(f&0x40))jp; + else pc+=2; +endinstr; + +instr(0xc3,10); + jp; +endinstr; + +instr(0xc4,10); + if(!(f&0x40))call; + else pc+=2; +endinstr; + +instr(0xc5,11); + push1(b,c); +endinstr; + +instr(0xc6,7); + adda(fetch(pc),0); + pc++; +endinstr; + +instr(0xc7,11); + push2(pc); + pc=0; +endinstr; + +instr(0xc8,5); + if(f&0x40)ret; +endinstr; + +instr(0xc9,4); + ret; +endinstr; + +instr(0xca,10); + if(f&0x40)jp; + else pc+=2; +endinstr; + +instr(0xcb,4); +#include "cbops.h" +endinstr; + +instr(0xcc,10); + if(f&0x40)call; + else pc+=2; +endinstr; + +instr(0xcd,10); + call; +endinstr; + +instr(0xce,7); + adda(fetch(pc),cy); + pc++; +endinstr; + +instr(0xcf,11); + push2(pc); + pc=8; +endinstr; + +instr(0xd0,5); + if(!cy)ret; +endinstr; + +instr(0xd1,10); + pop1(d,e); +endinstr; + +instr(0xd2,10); + if(!cy)jp; + else pc+=2; +endinstr; + +instr(0xd3,11); + tstates+=out(tstates,a,fetch(pc),a); + pc++; +endinstr; + +instr(0xd4,10); + if(!cy)call; + else pc+=2; +endinstr; + +instr(0xd5,11); + push1(d,e); +endinstr; + +instr(0xd6,7); + suba(fetch(pc),0); + pc++; +endinstr; + +instr(0xd7,11); + push2(pc); + pc=16; +endinstr; + +instr(0xd8,5); + if(cy)ret; +endinstr; + +instr(0xd9,4); + swap(b,b1); + swap(c,c1); + swap(d,d1); + swap(e,e1); + swap(h,h1); + swap(l,l1); +endinstr; + +instr(0xda,10); + if(cy)jp; + else pc+=2; +endinstr; + +instr(0xdb,11); + {unsigned short t; + a=t=in(tstates,a,fetch(pc)); + tstates+=t>>8; + pc++; + } +endinstr; + +instr(0xdc,10); + if(cy)call; + else pc+=2; +endinstr; + +instr(0xdd,4); + new_ixoriy=1; + intsample=0; +endinstr; + +instr(0xde,7); + suba(fetch(pc),cy); + pc++; +endinstr; + +instr(0xdf,11); + push2(pc); + pc=24; +endinstr; + +instr(0xe0,5); + if(!(f&4))ret; +endinstr; + +instr(0xe1,10); + if(!ixoriy)pop1(h,l); + else if(ixoriy==1)pop2(ix); + else pop2(iy); +endinstr; + +instr(0xe2,10); + if(!(f&4))jp; + else pc+=2; +endinstr; + +instr(0xe3,19); + if(!ixoriy){ + unsigned short t=fetch2(sp); + store2b(sp,h,l); + l=t; + h=t>>8; + } + else if(ixoriy==1){ + unsigned short t=fetch2(sp); + store2(sp,ix); + ix=t; + } + else{ + unsigned short t=fetch2(sp); + store2(sp,iy); + iy=t; + } +endinstr; + +instr(0xe4,10); + if(!(f&4))call; + else pc+=2; +endinstr; + +instr(0xe5,11); + if(!ixoriy)push1(h,l); + else if(ixoriy==1)push2(ix); + else push2(iy); +endinstr; + +instr(0xe6,7); + anda(fetch(pc)); + pc++; +endinstr; + +instr(0xe7,11); + push2(pc); + pc=32; +endinstr; + +instr(0xe8,5); + if(f&4)ret; +endinstr; + +instr(0xe9,4); + pc=!ixoriy?hl:ixoriy==1?ix:iy; +endinstr; + +instr(0xea,10); + if(f&4)jp; + else pc+=2; +endinstr; + +instr(0xeb,4); + swap(h,d); + swap(e,l); +endinstr; + +instr(0xec,10); + if(f&4)call; + else pc+=2; +endinstr; + +instr(0xed,4); +#include"edops.h" +endinstr; + +instr(0xee,7); + xora(fetch(pc)); + pc++; +endinstr; + +instr(0xef,11); + push2(pc); + pc=40; +endinstr; + +instr(0xf0,5); + if(!(f&0x80))ret; +endinstr; + +instr(0xf1,10); + pop1(a,f); +endinstr; + +instr(0xf2,10); + if(!(f&0x80))jp; + else pc+=2; +endinstr; + +instr(0xf3,4); + iff1=iff2=0; + intsample=0; +endinstr; + +instr(0xf4,10); + if(!(f&0x80))call; + else pc+=2; +endinstr; + +instr(0xf5,11); + push1(a,f); +endinstr; + +instr(0xf6,7); + ora(fetch(pc)); + pc++; +endinstr; + +instr(0xf7,11); + push2(pc); + pc=48; +endinstr; + +instr(0xf8,5); + if(f&0x80)ret; +endinstr; + +instr(0xf9,6); + sp=!ixoriy?hl:ixoriy==1?ix:iy; +endinstr; + +instr(0xfa,10); + if(f&0x80)jp; + else pc+=2; +endinstr; + +instr(0xfb,4); + iff1=iff2=1; + intsample=0; +endinstr; + +instr(0xfc,10); + if(f&0x80)call; + else pc+=2; +endinstr; + +instr(0xfd,4); + new_ixoriy=2; + intsample=0; +endinstr; + +instr(0xfe,7); + cpa(fetch(pc)); + pc++; +endinstr; + +instr(0xff,11); + push2(pc); + pc=56; +endinstr; + diff --git a/Tools/unix/zx/zxbdos.c b/Tools/unix/zxcc/zxbdos.c similarity index 95% rename from Tools/unix/zx/zxbdos.c rename to Tools/unix/zxcc/zxbdos.c index 3c4dd931..811dcd6d 100644 --- a/Tools/unix/zx/zxbdos.c +++ b/Tools/unix/zxcc/zxbdos.c @@ -1,4 +1,4 @@ -#include "zx.h" +#include "zxcc.h" #define BDOS_DEF #include "zxbdos.h" @@ -12,11 +12,14 @@ #define BCD(x) (((x % 10)+16*(x/10)) & 0xFF) /* Convert time_t to CP/M day count/hours/minutes */ +/* there is a duplicate of this code in util.c. +* same modification applied here +*/ dword cpmtime(time_t t) { - long d = (t / 86400) - 2921; /* CP/M day 0 is unix day 2921 */ - long h = (t % 86400) / 3600; /* Hour, 0-23 */ - long m = (t % 3600) / 60; /* Minute, 0-59 */ + dword d = (dword)((t / 86400) - 2921); /* CP/M day 0 is unix day 2921 */ + dword h = (t % 86400) / 3600; /* Hour, 0-23 */ + dword m = (t % 3600) / 60; /* Minute, 0-59 */ return (d | (BCD(h) << 16) | (BCD(m) << 24)); } @@ -203,7 +206,7 @@ void cpmbdos(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, /* For GENCOM's benefit, claim to be v3.1 */ *l = 0x31; /* v3.1 */ - //*l = 0x22; /* v2.2 */ + /* *l = 0x22; * v2.2 */ *h = 0; /* CP/M, no network */ break; @@ -237,9 +240,6 @@ void cpmbdos(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, case 0x14: /* Sequential read using FCB */ setw(l, h, fcb_read(pde, pdma)); - - //Msg("fcb_read L=%02x H=%02x\n", *l, *h); - break; case 0x15: /* Sequential write using FCB */ @@ -470,14 +470,12 @@ void cpmbdos(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, fprintf(stderr,"%s: Unsupported BDOS call %d\n", progname, (int)(*c)); dump_regs(stderr,*a,*b,*c,*d,*e,*f,*h,*l,*pc,*ix,*iy); - zx_exit(1); + zxcc_exit(1); break; } *a = *l; *b = *h; - - Msg("BDOS service completion.\n"); } @@ -492,7 +490,7 @@ void cpmbios(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, switch(func) /* BIOS function */ { case 1: - zx_exit(zx_term()); /* Program termination */ + zxcc_exit(zxcc_term()); /* Program termination */ break; case 2: /* CONST */ @@ -540,8 +538,8 @@ void cpmbios(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, printf("This program has attempted to call USERF, which " "is not implemented.\n"); #endif - zx_term(); - zx_exit(1); + zxcc_term(); + zxcc_exit(1); break; default: @@ -554,8 +552,6 @@ void cpmbios(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, fprintf(stderr,"%s: Unsupported BIOS call %d\n", progname, func); dump_regs(stderr,*a,*b,*c,*d,*e,*f,*h,*l,*pc,*ix,*iy); - zx_exit(1); + zxcc_exit(1); } - - Msg("BIOS service completion.\n"); } diff --git a/Tools/unix/zx/zxbdos.h b/Tools/unix/zxcc/zxbdos.h similarity index 100% rename from Tools/unix/zx/zxbdos.h rename to Tools/unix/zxcc/zxbdos.h diff --git a/Tools/unix/zx/zxcbdos.c b/Tools/unix/zxcc/zxcbdos.c similarity index 77% rename from Tools/unix/zx/zxcbdos.c rename to Tools/unix/zxcc/zxcbdos.c index 355dd687..e3eb1f2f 100644 --- a/Tools/unix/zx/zxcbdos.c +++ b/Tools/unix/zxcc/zxcbdos.c @@ -1,10 +1,8 @@ -#include "zx.h" +#include "zxcc.h" #include "zxbdos.h" #include "zxcbdos.h" -#if !(defined(__MINGW32__) || defined(_MSC_BUILD) || defined(__WATCOMC__)) -#include -#endif -#ifdef WIN32 + +#ifdef _WIN32 #include #endif @@ -76,7 +74,6 @@ void bdos_rdline(word line, word *PC) #ifndef USE_CPMIO - int cpm_bdos_6(byte e) { int c; @@ -100,11 +97,10 @@ int cpm_bdos_6(byte e) } #endif -#if defined(__MINGW32__) || defined(_MSC_BUILD) || defined(__WATCOMC__) - +#ifdef _WIN32 byte cin() { - if (_isatty(_fileno(stdin))) + if (_isatty(STDIN_FILENO)) return getch(); else return getchar(); @@ -112,7 +108,7 @@ byte cin() void cout(byte c) { - if (_isatty(_fileno(stdout))) + if (_isatty(STDOUT_FILENO)) putch(c); else putchar(c); @@ -120,30 +116,34 @@ void cout(byte c) int cstat() { - if (_isatty(_fileno(stdin))) + if (_isatty(STDIN_FILENO)) return _kbhit() ? 0xFF : 0; else return 0xFF; } -#else /* defined(__MINGW32__) || defined(_MSC_BUILD) || defined(__WATCOMC__) */ +#else /* def _WIN32 */ byte cin() { - return getchar(); + char c = 0; + + read(STDIN_FILENO, &c, 1); + return c; } void cout(byte c) { - putchar(c); + write(STDOUT_FILENO, &c, 1); + return; } int cstat() { int i; - ioctl(_fileno(stdin), FIONREAD, &i); - if (i > 0) return 0xff; + ioctl(STDIN_FILENO, FIONREAD, &i); + if (i > 0) return 0xFF; return 0; } diff --git a/Tools/unix/zx/zxcbdos.h b/Tools/unix/zxcc/zxcbdos.h similarity index 100% rename from Tools/unix/zx/zxcbdos.h rename to Tools/unix/zxcc/zxcbdos.h diff --git a/Tools/unix/zx/zx.c b/Tools/unix/zxcc/zxcc.c similarity index 61% rename from Tools/unix/zx/zx.c rename to Tools/unix/zxcc/zxcc.c index 88b20cb3..9668243b 100644 --- a/Tools/unix/zx/zx.c +++ b/Tools/unix/zxcc/zxcc.c @@ -1,8 +1,4 @@ -#include "zx.h" - -#ifdef WIN32 -#include "windows.h" -#endif +#include "zxcc.h" /* Global variables */ @@ -11,16 +7,26 @@ char **argv; int argc; byte cpm_drive; -char *mypath; - byte cpm_user; extern byte cpm_error; +char bindir80[CPM_MAXPATH] = ""; +char libdir80[CPM_MAXPATH] = ""; +char incdir80[CPM_MAXPATH] = ""; + byte RAM[65536]; /* The Z80's address space */ void load_comfile(void); /* Forward declaration */ static int deinit_term, deinit_gsx; +static void mkpath(char* fullpath, char* path, char* subdir); + +#ifndef _WIN32 +struct termios tc_orig; + +void raw_init(void); +void deinit_raw(void); +#endif void dump_regs(FILE *fp, byte a, byte b, byte c, byte d, byte e, byte f, byte h, byte l, word pc, word ix, word iy) @@ -39,8 +45,10 @@ char *parse_to_fcb(char *s, int afcb) RAM[afcb] = 0; memset(fcb, ' ', 11); - while (*s == ' ') ++s; - + while (s[0]==' ') /* skip leading spaces */ + { + s++; + } while (1) { if (s[0] == 0) break; @@ -73,10 +81,9 @@ void Msg(char *s, ...) va_list ap; va_start(ap, s); - printf("%s trace: ", progname); - vprintf(s, ap); - fflush(stdout); - if (s[strlen(s) - 1] == '\n') putchar('\r'); + fprintf(stderr, "%s trace: ", progname); + vfprintf(stderr, s, ap); + fflush(stderr); va_end(ap); #endif } @@ -97,8 +104,8 @@ void ed_fe(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, case 0xC2: fprintf(stderr,"%s: Incompatible BIOS.BIN\n", progname); - zx_term(); - zx_exit(1); + zxcc_term(); + zxcc_exit(1); case 0xC3: cpmbios(a,b,c,d,e,f,h,l,pc,ix,iy); @@ -107,8 +114,8 @@ void ed_fe(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, default: fprintf(stderr, "%s: Z80 encountered invalid trap\n", progname); dump_regs(stderr,*a,*b,*c,*d,*e,*f,*h,*l,*pc,*ix,*iy); - zx_term(); - zx_exit(1); + zxcc_term(); + zxcc_exit(1); } } @@ -121,54 +128,52 @@ void ed_fe(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, void load_bios(void) { - int bios_len; - - FILE * fp = NULL; - char biospath[CPM_MAXPATH + 1] = ""; + char dir[CPM_MAXPATH + 1], fname[CPM_MAXPATH + 1]; + char* q; + size_t bios_len; -#ifdef WIN32 + FILE* fp = fopen("bios.bin", "rb"); if (!fp) { - GetModuleFileName(NULL, biospath, sizeof(biospath)); - strcpy(strrchr(biospath, '\\'), "\\bios.bin"); - fp = fopen(biospath, "rb"); + strcpy(fname, bindir80); + strcat(fname, "bios.bin"); + fp = fopen(fname, "rb"); } + if (!fp) + { +#ifdef _WIN32 + dir[0] = 0; /* use strncat in case the path is very long */ + strncat(dir, _pgmptr, CPM_MAXPATH - 8); /* copy the executable path */ +#elif defined(__APPLE__) + uint32_t size = CPM_MAXPATH - 8; + _NSGetExecutablePath(dir, &size); #else - if (!fp) { - strcpy(biospath, mypath); - strcpy(strrchr(biospath, '/'), "/bios.bin"); - fp = fopen(biospath, "rb"); - } + readlink("/proc/self/exe", dir, CPM_MAXPATH - 8); /* allow room for bios.bin */ #endif - - if (!fp && BINDIR80) - { - strcpy(biospath, BINDIR80); - strcat(biospath, "bios.bin"); - fp = fopen(biospath, "rb"); + q = strrchr(dir, DIRSEPCH); + *++q = 0; + strcpy(fname, dir); + strcat(fname, "bios.bin"); + fp = fopen(fname, "rb"); } - - if (!fp) fp = fopen("bios.bin", "rb"); - if (!fp) { fprintf(stderr,"%s: Cannot locate bios.bin\n", progname); - zx_term(); - zx_exit(1); + zxcc_term(); + zxcc_exit(1); } bios_len = fread(RAM + 0xFE00, 1, 512, fp); if (bios_len < 1 || ferror(fp)) { fclose(fp); fprintf(stderr,"%s: Cannot load bios.bin\n", progname); - zx_term(); - zx_exit(1); + zxcc_term(); + zxcc_exit(1); } fclose(fp); Msg("Loaded %d bytes of BIOS\n", bios_len); } - /* * try_com() attempts to open file, file.com, file.COM, file.cpm and file.CPM * @@ -198,32 +203,33 @@ FILE *try_com(char *s) void load_comfile(void) { - int com_len; - char fname[CPM_MAXPATH + 1] = ""; + size_t com_len; + char fname[CPM_MAXPATH + 1]; FILE *fp; - if (BINDIR80) strcpy(fname, BINDIR80); - strcat(fname, argv[1]); + /* Look in current directory first */ + strcpy(fname, argv[1]); fp = try_com(fname); if (!fp) { - strcpy(fname, argv[1]); + strcpy(fname, bindir80); + strcat(fname, argv[1]); fp = try_com(fname); } if (!fp) { fprintf(stderr,"%s: Cannot locate %s, %s.com, %s.COM, %s.cpm _or_ %s.CPM\r\n", progname, argv[1], argv[1], argv[1], argv[1], argv[1]); - zx_term(); - zx_exit(1); + zxcc_term(); + zxcc_exit(1); } com_len = fread(RAM + 0x0100, 1, 0xFD00, fp); if (com_len < 1 || ferror(fp)) { fclose(fp); fprintf(stderr,"%s: Cannot load %s\n", progname, fname); - zx_term(); - zx_exit(1); + zxcc_term(); + zxcc_exit(1); } fclose(fp); @@ -245,7 +251,7 @@ unsigned int out() { return 0; } * the result to the command line. */ -void zx_xltname(char *name, char *pcmd) +void zxcc_xltname(char *name, char *pcmd) { char nbuf[CPM_MAXPATH + 1]; @@ -265,23 +271,31 @@ int main(int ac, char **av) { int n; char *pCmd, *str; + char* tmpenv; + argc = ac; argv = av; #ifdef __PACIFIC__ /* Pacific C doesn't support argv[0] */ - progname="ZX"; + progname="ZXCC"; #endif progname = argv[0]; - mypath = strdup(argv[0]); /* DJGPP includes the whole path in the program name, which looks * untidy... */ - str = strrchr(progname, '/'); - if (!str) str = strrchr(progname, '\\'); - if (str) progname = str + 1; + while ((str = strpbrk(progname, DIRSEP))) + progname = str + 1; + +#ifdef DEBUG + fprintf(stderr, "\n\n"); + Msg("Start of execution: "); + for (n = 0; n < argc; n++) + fprintf(stderr, " %s", argv[n]); + fprintf(stderr, "\n"); +#endif - if (_isatty(_fileno(stdin))) + if (_isatty(STDIN_FILENO)) Msg("Using interactive console mode\n"); else Msg("Using standard input/ouput mode\n"); @@ -290,18 +304,22 @@ int main(int ac, char **av) { fprintf(stderr,"%s: type lengths incorrect; edit typedefs " "and recompile.\n", progname); - zx_exit(1); + zxcc_exit(1); } if (argc < 2) { fprintf(stderr,"%s: No CP/M program name provided.\n",progname); - zx_exit(1); + zxcc_exit(1); } - - setmode(_fileno(stdin), O_BINARY ); - setmode(_fileno(stdout), O_BINARY ); +#ifdef _WIN32 + setmode(STDIN_FILENO, O_BINARY ); + setmode(STDOUT_FILENO, O_BINARY ); +#else + if (_isatty(STDIN_FILENO)) + raw_init(); +#endif /* Parse arguments. An argument can be either: @@ -319,12 +337,37 @@ int main(int ac, char **av) if (!fcb_init()) { fprintf(stderr, "Could not initialise CPMREDIR library\n"); - zx_exit(1); + zxcc_exit(1); } - xlt_map(0, BINDIR80); /* Establish the 3 fixed mappings */ - xlt_map(1, LIBDIR80); - xlt_map(2, INCDIR80); + /* allow environment variables to override default locations */ + /* two options are supported, explicit overrides for each directory + * (BINDIR80, LIBDIR80, INCDIR80) + * or a common directory prefix override (CPMDIR80) + * the explict override takes precedence + */ + if ((tmpenv = getenv("CPMDIR80"))) { + mkpath(bindir80, tmpenv, BIN80); /* use CPMDIR80 & std subdirs */ + mkpath(libdir80, tmpenv, LIB80); + mkpath(incdir80, tmpenv, INC80); + } + if ((tmpenv = getenv("BINDIR80"))) + mkpath(bindir80, tmpenv, ""); + + if ((tmpenv = getenv("LIBDIR80"))) + mkpath(libdir80, tmpenv, ""); + + if ((tmpenv = getenv("INCDIR80"))) + mkpath(incdir80, tmpenv, ""); + + Msg("BINDIR80=\"%s\"\n", bindir80); + Msg("LIBDIR80=\"%s\"\n", libdir80); + Msg("INCDIR80=\"%s\"\n", incdir80); + + xlt_map(0, bindir80); /* Establish the 3 fixed mappings */ + xlt_map(1, libdir80); + xlt_map(2, incdir80); + pCmd = (char *)RAM + 0x81; for (n = 2; n < argc; n++) @@ -342,17 +385,17 @@ int main(int ac, char **av) } else if (argv[n][0] == '+') { - zx_xltname(pCmd, argv[n]+1); + zxcc_xltname(pCmd, argv[n]+1); } else /* Translate a filename */ { strcat(pCmd, " "); - zx_xltname(pCmd, argv[n]); + zxcc_xltname(pCmd, argv[n]); } } pCmd[0x7F] = 0; /* Truncate to fit the buffer */ - RAM[0x80] = strlen(pCmd); + RAM[0x80] = (byte)strlen(pCmd); str = parse_to_fcb(pCmd, 0x5C); parse_to_fcb(str, 0x6C); @@ -401,10 +444,10 @@ int main(int ac, char **av) /* Start the Z80 at 0xFF00, with stack at 0xFE00 */ mainloop(0xFF00, 0xFE00); - return zx_term(); + return zxcc_term(); } -void zx_exit(int code) +void zxcc_exit(int code) { #ifdef USE_CPMIO if (deinit_term) cpm_scr_unit(); @@ -415,10 +458,13 @@ void zx_exit(int code) exit(code); } -int zx_term(void) +int zxcc_term(void) { word n; +#ifndef _WIN32 + deinit_raw(); +#endif //n = RAM[0x81]; /* Get the return code. This is Hi-Tech C */ //n = (n << 8) | RAM[0x80]; /* specific and fails with other COM files */ @@ -438,4 +484,69 @@ int zx_term(void) else return 0; } +/* helper function to build full path */ +/* make sure that a / or \ is present at the end of path + * before appending the subdir + */ +static void mkpath(char* fullpath, char* path, char* subdir) { + char* s; + strcpy(fullpath, path); + s = strchr(fullpath, '\0'); + if (*fullpath && !ISDIRSEP(s[-1])) /* make sure we have dir sep */ + *s++ = '/'; + strcpy(s, subdir); +} + +#ifndef _WIN32 +void raw_init(void) +{ + struct termios tc_raw; + + Msg("Enabling RAW Terminal IO\n"); + + if (tcgetattr(STDIN_FILENO, &tc_orig) == -1) + { + Msg("Failed to enable RAW Terminal IO - tcgetattr() failed\n"); + zxcc_exit(1);; + } + + //tc_raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + //tc_raw.c_oflag &= ~(OPOST); + //tc_raw.c_cflag |= (CS8); + //tc_raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + //tc_raw.c_cc[VMIN] = 1; + //tc_raw.c_cc[VTIME] = 0; + + tc_raw.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON); + tc_raw.c_oflag &= ~(OPOST); + tc_raw.c_cflag |= (CS8); + tc_raw.c_lflag &= ~(ECHO | ICANON | IEXTEN); + tc_raw.c_cc[VMIN] = 1; + tc_raw.c_cc[VTIME] = 0; + + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tc_raw) == -1) + { + Msg("Failed to enable RAW Terminal IO - tcsetattr() failed\n"); + zxcc_exit(1); + } + + Msg("Enabled RAW Terminal IO\n"); + + return; +} + +void deinit_raw(void) +{ + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tc_orig) == -1) + { + Msg("Failed to disable RAW Terminal IO - tcsetattr() failed\n"); + return; + } + + Msg("Disabled RAW Terminal IO\n"); + + return; +} + +#endif diff --git a/Tools/unix/zxcc/zxcc.doc b/Tools/unix/zxcc/zxcc.doc new file mode 100644 index 00000000..2f30a1ac --- /dev/null +++ b/Tools/unix/zxcc/zxcc.doc @@ -0,0 +1,207 @@ + zxcc v0.5.7 + + zxcc is a wrapper for the Hi-Tech C CP/M compiler, allowing it to be + used as a cross-compiler under UNIX. Version 0.5.0 also works with the + build tools necessary to assemble CP/M 3 (MAC, RMAC, LINK, GENCOM). + + New in this version: + * Compiles on boxes where sync() does not return int (reported by + multiple users). + * BDOS function 10 takes a pointer to unsigned char, thus allowing + input buffers longer than 128 bytes (Andy Parkins) + +Setting up + + Firstly, build the compiler. It should not be necessary to rebuild + bios.bin; but if you have to, it assembles using the z80asm assembler + (part of the z80pack emulation package which can be found on the Walnut + Creek CP/M CDROM) or the [1]ZMAC assembler (downloadable from + ). + + Previous versions of ZXCC could be compiled under DOS using DJGPP; this + may still be possible, but has not been tested since the build system + was changed to use the GNU autotools. + + This version of zxcc contains copies of the CPMIO and CPMREDIR + libraries, so you won't need to obtain them separately. + + You will need the tools you want to use; either the Hi-Tech C compiler + for CP/M <[2]http://www.hitech.com.au> or Digital Research's tools at + <[3]http://www.cpm.z80.de> Once you have obtained the tools, + documentation and possibly the library source, you need to decide where + to put the files. zxcc uses three directories: + * BINDIR80 (by default, /usr/local/lib/cpm/bin80) holds the compiler + itself. You should copy the compiler .com files (or MAC, RMAC etc.) + and bios.bin to this directory. + * LIBDIR80 (by default, /usr/local/lib/cpm/lib80) holds the C + libraries libc.lib, libf.lib, crtcpm.obj and rrtcpm.obj. + * INCDIR80 (by default, /usr/local/lib/cpm/include80) holds the + compiler .h files. + + The locations of these directories are normally set by the configure + script; you can override them by editing zxcc.h and uncommenting the + lines that redefine them. + + Once you have installed zxcc and the build tools, try building Hello + World: + + #include + void main() + { + printf("Hello World\n"); + } + + or for RMAC: + + CSEG + LXI D,HELLO + MVI C,9 + CALL 5 + RST 0 + HELLO: DB 'Hello World',13,10,'$' + + To compile the first example, type + + zxc hello.c + + ; if all goes well, you should end up with a file called hello.com. You + can test the resulting file by typing + + zxcc hello.com + + . + + To assemble the second example, type + + zxcc rmac.com hello + zxcc link.com hello + + and run it as above. NOTE: RMAC requires that lines be terminated with + CR/LF. You may need to put a unix2dos command in your makefile before + you invoke RMAC. + +Using zxcc + + For detailed instructions, see the documentation for Hi-Tech C or the + CP/M tools. zxcc behaves in the same way, but note the following + points: + + Program names + + The names of the programs have been changed between CP/M and UNIX; for + example, you would type + + zxc hello.c + + instead of + + c hello.c + + . The programs to use are: + + zxc + The equivalent of C.COM. + + zxas + The equivalent of ZAS.COM. + + zxlink + The equivalent of LINK.COM. + + zxlibr + The equivalent of LIBR.COM. + + All these programs work by converting their arguments to a form + suitable for zxcc, and then invoking zxcc. + + There are no front-end programs for the CP/M build tools; you will have + to enter arguments to these in the zxcc format given below. + + Filenames + + Where the documentation allows you to enter a CP/M filename, you should + instead enter a UNIX one. The filename itself (as opposed to any + directories in its path) must obey CP/M 8.3 naming conventions and be + all lowercase. + + Where the documentation requires a CP/M driveletter / user number + + -I2:C: + + you should enter a path complete with trailing slash: + + -I/usr/src/linux-80/include/ + +Technical + + zxcc emulates a subset of CP/M 3; hopefully enough to run the Hi-Tech C + compiler. It can be used as a limited general-purpose CP/M 3 emulator + provided the emulated program only uses a restricted subset of system + calls. + + zxcc behaves like the emulator com, allowing CP/M programs to be used + transparently from a UNIX prompt. However com: + * Emulates all of CP/M 2, rather than a subset of CP/M 3; + * Is designed for general use, not tailored to Hi-Tech C; + * Is written partly in assembly language and will only run on + 68000-based computers; + * Cannot map UNIX directories to CP/M drives; + * Contains some bugs connected with command parsing and file I/O. + + Syntax for zxcc is: + + zxcc comfile.com arg1 arg2 ... + + The comfile is the program to run; zxcc searches the current directory + and BINDIR80 for it. + + The arguments are parsed in this way: + * Any argument starting with a - sign is passed to the CP/M program + as-is, minus the leading - sign. + * Any argument starting with a + sign is parsed as a filename (see + below) and then concatenated to the previous argument. + * Any argument starting "+-" is concatenated without being parsed. + * All other arguments are parsed as filenames. The UNIX pathname is + converted to a CP/M driveletter. + + For example: + + zxcc foo.com --Q -A /dev/null --I +/dev/zero +-, +/foo/bar + + would pass these arguments to foo.com: + + -Q A d:null -Id:zero,e:bar + + The other programs are merely wrappers that convert their command lines + into the form required by zxcc. + +Errors + + Any errors raised by the zxcc runtime system will be prefixed with + zxcc:. Some errors you may encounter are: + + Unsupported BDOS call + Part of CP/M 3 that the program uses has not been emulated. Add + the required functionality to zxbdos.c and recompile. + + Z80 encountered invalid trap + The CP/M program being run attempted to call the zxcc runtime + system with an unknown call number. This will happen if the + program was written for my emulator "Joyce". + +Acknowledgements + + * Hi-Tech C was written by Hi-Tech Software. + * The Z80 emulation engine was written by Ian Collier. + * Thanks to Jacob Nevins, Andy Parkins and others for bug fix + suggestions. + __________________________________________________________________ + + + John Elliott, 28 March 2003 + +References + + 1. http://www.nenie.org/cpcip/index.html#zmac + 2. http://www.hitech.com.au/ + 3. http://www.cpm.z80.de/ diff --git a/Tools/unix/zx/zx.h b/Tools/unix/zxcc/zxcc.h similarity index 51% rename from Tools/unix/zx/zx.h rename to Tools/unix/zxcc/zxcc.h index dac69ce0..4d08949a 100644 --- a/Tools/unix/zx/zx.h +++ b/Tools/unix/zxcc/zxcc.h @@ -1,23 +1,44 @@ /* * Change the directories in these #defines if necessary. Note trailing slash. */ +#ifndef _WIN32 + #include "config.h" + #define ISDIRSEP(c) ((c) == '/') + #define DIRSEPCH '/' + #define DIRSEP "/" +#else + #include "config.h" + #define ISDIRSEP(c) ((c) == '/' || (c) == '\\') + #define DIRSEPCH '\\' + #define DIRSEP "/\\:" +#endif + +#ifndef CPMDIR80 + #ifdef _WIN32 + #define CPMDIR80 "d:/local/lib/cpm/" + #else + #define CPMDIR80 "/usr/local/lib/cpm/" + #endif +#endif -#include "config.h" +/* the default sub directories trailing / is required */ +#define BIN80 "bin80/" +#define LIB80 "lib80/" +#define INC80 "include80/" -#ifdef __MSDOS__ - #define BINDIR80 "d:/tools/cpm/bin80/" - #define LIBDIR80 "d:/tools/cpm/lib80/" - #define INCDIR80 "d:/tools/cpm/include/" -#else -/* Unless overridden, these are defined by autoconf. Note trailing slash. - #undef BINDIR80 - #undef LIBDIR80 - #undef INCDIR80 - #define BINDIR80 "/usr/local/lib/cpm/bin80/" - #define LIBDIR80 "/usr/local/lib/cpm/lib80/" - #define INCDIR80 "/usr/local/lib/cpm/include80/" -*/ +#ifndef BINDIR80 + #define BINDIR80 CPMDIR80 BIN80 +#endif +#ifndef LIBDIR80 + #define LIBDIR80 CPMDIR80 LIB80 #endif +#ifndef INCDIR80 + #define INCDIR80 CPMDIR80 INC80 +#endif + +extern char bindir80[]; +extern char libdir80[]; +extern char incdir80[]; #define SERIAL "ZXCC05" @@ -31,30 +52,42 @@ #include #include #include -#if defined(LINUX) || defined(DARWIN) -#include -#define _isatty(a) isatty(a) -#define _fileno(a) fileno(a) -#define setmode(a,b) -#define O_BINARY 0 +#ifdef HAVE_UNISTD_H + #include #endif -#ifdef WIN32 -#include +#ifdef _WIN32 + #include + #include + #define strcasecmp _stricmp + #ifndef STDIN_FILENO + #define STDIN_FILENO _fileno(stdin) + #define STDOUT_FILENO _fileno(stdout) + #define STDERR_FILENO _fileno(stderr) + #endif +#else + #include + #define _isatty(a) isatty(a) + #define _fileno(a) fileno(a) #endif #include #include #ifdef __MSDOS -#include + #include +#endif +#ifndef _WIN32 + #include + #include + #define _S_IFDIR S_IFDIR #endif /* Library includes */ #ifdef USE_CPMIO -#include "cpmio.h" + #include "cpmio.h" #endif #ifdef USE_CPMGSX -#include "cpmgsx.h" + #include "cpmgsx.h" #endif #include "cpmredir.h" /* BDOS disc simulation */ @@ -73,8 +106,8 @@ void cpmbios(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, void dump_regs(FILE *fp, byte a, byte b, byte c, byte d, byte e, byte f, byte h, byte l, word pc, word ix, word iy); void Msg(char *s, ...); -int zx_term(void); -void zx_exit(int code); +int zxcc_term(void); +void zxcc_exit(int code); byte cin(void); void cout(byte); @@ -87,8 +120,6 @@ extern char **argv; extern int argc; extern byte RAM[65536]; /* The Z80's address space */ -extern int usestdio; - /* Z80 CPU emulation */ #include "z80.h" diff --git a/Tools/unix/zxcc/zxcc.html b/Tools/unix/zxcc/zxcc.html new file mode 100644 index 00000000..502d8777 --- /dev/null +++ b/Tools/unix/zxcc/zxcc.html @@ -0,0 +1,200 @@ +zxcc v0.5.7 + +

zxcc v0.5.7

+ +

zxcc is a wrapper for the Hi-Tech C CP/M compiler, allowing it to +be used as a cross-compiler under UNIX. Version 0.5.0 also works with the build +tools necessary to assemble CP/M 3 (MAC, RMAC, LINK, GENCOM). + +

New in this version: +

    +
  • Compiles on boxes where sync() does not return int (reported by multiple +users). +
  • BDOS function 10 takes a pointer to unsigned char, thus allowing input +buffers longer than 128 bytes (Andy Parkins) +
+ +

Setting up

+ +

Firstly, build the compiler. It should not be necessary to rebuild bios.bin; +but if you have to, it assembles using the z80asm assembler (part of +the z80pack emulation package which can be found on the Walnut Creek +CP/M CDROM) or the +ZMAC assembler +(downloadable from <http://www.nenie.org/cpcip/index.html#zmac>). +

Previous versions of ZXCC could be compiled under DOS using +DJGPP; this may still be possible, but has not been tested since the build +system was changed to use the GNU autotools. + +

This version of zxcc contains copies of the CPMIO and CPMREDIR libraries, +so you won't need to obtain them separately. + +

You will need the tools you want to use; either the Hi-Tech C compiler for +CP/M <http://www.hitech.com.au> + +or Digital Research's tools at + +<http://www.cpm.z80.de> + +Once you have obtained the tools, documentation and possibly the library +source, you need to decide where to put the files. zxcc uses +three directories: + +

    +
  • BINDIR80 (by default, /usr/local/lib/cpm/bin80) + holds the compiler itself. You should copy the compiler .com files + (or MAC, RMAC etc.) and bios.bin to this directory. +
  • LIBDIR80 (by default, /usr/local/lib/cpm/lib80) + holds the C libraries libc.lib, libf.lib, crtcpm.obj and rrtcpm.obj. +
  • INCDIR80 (by default, /usr/local/lib/cpm/include80) + holds the compiler .h files. +
+ +

The locations of these directories are normally set by the configure +script; you can override them by editing zxcc.h and uncommenting the lines +that redefine them. + +

Once you have installed zxcc and the build tools, try +building Hello World: + +

+#include <stdio.h>
+void main()
+{
+ printf("Hello World\n");
+}
+
+ +or for RMAC: + +
+ CSEG
+
+ LXI D,HELLO
+ MVI C,9
+ CALL 5
+ RST 0
+
+HELLO: DB 'Hello World',13,10,'$' + +
+ +

To compile the first example, type

zxc hello.c
; if +all goes well, you should end up with a file called hello.com. You can +test the resulting file by typing
zxcc hello.com
. + +

To assemble the second example, type +

+ zxcc rmac.com hello
+ zxcc link.com hello +
+and run it as above. NOTE: RMAC requires that lines be terminated with CR/LF. +You may need to put a unix2dos command in your makefile before you invoke RMAC. + +

Using zxcc

+ +

For detailed instructions, see the documentation for Hi-Tech C or +the CP/M tools. zxcc behaves in the same way, but note the +following points: + +

Program names

+ +

The names of the programs have been changed between CP/M and UNIX; for +example, you would type

zxc hello.c
instead of +
c hello.c
. The programs to use are: + +
+
zxc
The equivalent of C.COM. +
zxas
The equivalent of ZAS.COM. +
zxlink
The equivalent of LINK.COM. +
zxlibr
The equivalent of LIBR.COM. +
+ +

All these programs work by converting their arguments to a form suitable +for zxcc, and then invoking zxcc. + +

There are no front-end programs for the CP/M build tools; you will have to +enter arguments to these in the zxcc format given below. + +

Filenames

+ +

Where the documentation allows you to enter a CP/M filename, you should +instead enter a UNIX one. The filename itself (as opposed to any directories in +its path) must obey CP/M 8.3 naming conventions and be all lowercase. +

Where the documentation requires a CP/M driveletter / user number +

-I2:C:
you should enter a path complete with + trailing slash:
-I/usr/src/linux-80/include/
+ +

Technical

+ +

zxcc emulates a subset of CP/M 3; hopefully enough to run the +Hi-Tech C compiler. It can be used as a limited general-purpose CP/M 3 +emulator provided the emulated program only uses a restricted subset of +system calls. +

zxcc behaves like the emulator com, allowing CP/M +programs to be used transparently from a UNIX prompt. However com: +

    +
  • Emulates all of CP/M 2, rather than a subset of CP/M 3; +
  • Is designed for general use, not tailored to Hi-Tech C; +
  • Is written partly in assembly language and will only run on 68000-based +computers; +
  • Cannot map UNIX directories to CP/M drives; +
  • Contains some bugs connected with command parsing and file I/O. +
+ +

Syntax for zxcc is: + +

+ zxcc comfile.com arg1 arg2 ... +
+ +

The comfile is the program to run; zxcc searches the current +directory and BINDIR80 for it. +

The arguments are parsed in this way: + +

    +
  • Any argument starting with a - sign is passed to the CP/M program as-is, + minus the leading - sign. +
  • Any argument starting with a + sign is parsed as a filename (see below) + and then concatenated to the previous argument. +
  • Any argument starting "+-" is concatenated without being parsed. +
  • All other arguments are parsed as filenames. The UNIX pathname is + converted to a CP/M driveletter. +
+

For example: +

+ zxcc foo.com --Q -A /dev/null --I +/dev/zero +-, +/foo/bar +
+would pass these arguments to foo.com: +
+ -Q A d:null -Id:zero,e:bar +
+ +

The other programs are merely wrappers that convert their command lines +into the form required by zxcc. + +

Errors

+ +

Any errors raised by the zxcc runtime system will be prefixed +with zxcc:. Some errors you may encounter are: + +

+
Unsupported BDOS call +
Part of CP/M 3 that the program uses has not been emulated. Add the +required functionality to zxbdos.c and recompile. +
Z80 encountered invalid trap +
The CP/M program being run attempted to call the zxcc runtime +system with an unknown call number. This will happen if the program was +written for my emulator "Joyce". +
+

Acknowledgements

+ +
    +
  • Hi-Tech C was written by Hi-Tech Software. +
  • The Z80 emulation engine was written by Ian Collier. +
  • Thanks to Jacob Nevins, Andy Parkins and others for bug fix suggestions. +
+
+
John Elliott, 28 March 2003
+ + diff --git a/Tools/unix/zx/zxdbdos.c b/Tools/unix/zxcc/zxdbdos.c similarity index 64% rename from Tools/unix/zx/zxdbdos.c rename to Tools/unix/zxcc/zxdbdos.c index f5f21f3b..36cbe532 100644 --- a/Tools/unix/zx/zxdbdos.c +++ b/Tools/unix/zxcc/zxdbdos.c @@ -1,88 +1,97 @@ -#include "zx.h" -#include "zxbdos.h" -#include "zxdbdos.h" - -/* This file used to deal with all disc-based BDOS calls. - Now the calls have been moved into libcpmredir, it's a bit empty round - here. - - ZXCC does a few odd things when searching, to make Hi-Tech C behave - properly. -*/ - - -/* If a file could not be found on the default drive, try again on a "search" - drive (A: for .COM files, B: for .LIB and .OBJ files) */ - -int fcbforce(byte *fcb, byte *odrv) -{ - byte drive; - char typ[4]; - int n; - - for (n = 0; n < 3; n++) typ[n] = fcb[n+9] & 0x7F; - typ[3] = 0; - - Msg("fcbforce: typ=%s, fcb=%hhx\r\n", typ, *fcb); - - drive = 0; - if (*fcb) return 0; /* not using default drive */ - //if ((*fcb) != 16) return 0; /* not using default drive */ - if (!strcmpi(typ, "COM")) drive = 1; - if (!strcmpi(typ, "LIB")) drive = 2; - if (!strcmpi(typ, "OBJ")) drive = 2; - if (!strcmpi(typ, "H ")) drive = 3; - - Msg("fcbforce: drive=%i\r\n", drive); - - if (!drive) return 0; - - *odrv = *fcb; - *fcb = drive; - return 1; -} - -/* zxcc has a trick with some filenames: If it can't find them where they - should be, and a drive wasn't specified, it searches BINDIR80, - LIBDIR80 or INCDIR80 (depending on the type of the file). - */ - -word x_fcb_open(byte *fcb, byte *dma) -{ - word rv = fcb_open(fcb, dma); - byte odrv; - - Msg("x_fcb_open: rv=%X\r\n", rv); - - if (rv == 0xFF) - { - if (fcbforce(fcb, &odrv)) - { - rv = fcb_open(fcb, dma); - Msg("x_fcb_open: rv=%X\r\n", rv); - *fcb = odrv; - } - } - return rv; -} - - - -word x_fcb_stat(byte *fcb) -{ - word rv = fcb_stat(fcb); - byte odrv; - - if (rv == 0xFF) - { - if (fcbforce(fcb, &odrv)) - { - rv = fcb_stat(fcb); - *fcb = odrv; - } - } - return rv; -} - - - +#include "zxcc.h" +#include "zxbdos.h" +#include "zxdbdos.h" + +/* This file used to deal with all disc-based BDOS calls. + Now the calls have been moved into libcpmredir, it's a bit empty round + here. + + ZXCC does a few odd things when searching, to make Hi-Tech C behave + properly. +*/ + + +/* If a file could not be found on the default drive, try again on a "search" + drive (A: for .COM files, B: for .LIB and .OBJ files) */ + +int fcbforce(byte *fcb, byte *odrv) +{ + byte drive; + char nam[9]; + char typ[4]; + int n; + + for (n = 0; n < 8; n++) nam[n] = fcb[n+1] & 0x7F; + nam[8] = 0; + for (n = 0; n < 3; n++) typ[n] = fcb[n+9] & 0x7F; + typ[3] = 0; + + drive = 0; + if (*fcb) return 0; /* not using default drive */ + + /* Microsoft BASIC compiler run-time */ + if (!strcmp(nam,"BCLOAD ") && !strcmp(typ, " ")) drive = 2; + + /* HI-TECH C options help file */ + if (!strcmp(nam,"OPTIONS ") && !strcmp(typ, " ")) drive = 1; + + /* binaries, libraries and object files */ + if (!strcmp(typ, "COM")) drive = 1; + if (!strcmp(typ, "LIB")) drive = 2; + if (!strcmp(typ, "OBJ")) drive = 2; + + /* some extras for messages, overlays, includes */ + if (!strcmp(typ, "HLP")) drive = 1; + if (!strcmp(typ, "MSG")) drive = 1; + if (!strcmp(typ, "OVR")) drive = 1; + if (!strcmp(typ, "REL")) drive = 2; + if (!strcmp(typ, "H ")) drive = 3; + + if (!drive) return 0; + + *odrv = *fcb; + *fcb = drive; + return 1; +} + +/* zxcc has a trick with some filenames: If it can't find them where they + should be, and a drive wasn't specified, it searches BINDIR80, + LIBDIR80 or INCDIR80 (depending on the type of the file). + */ + +word x_fcb_open(byte *fcb, byte *dma) +{ + word rv = fcb_open(fcb, dma); + byte odrv; + + if (rv == 0xFF) + { + if (fcbforce(fcb, &odrv)) + { + rv = fcb_open(fcb, dma); + *fcb = odrv; + } + } + return rv; +} + + + +word x_fcb_stat(byte *fcb) +{ + word rv = fcb_stat(fcb); + byte odrv; + + if (rv == 0xFF) + { + if (fcbforce(fcb, &odrv)) + { + rv = fcb_stat(fcb); + *fcb = odrv; + } + } + return rv; +} + + + diff --git a/Tools/unix/zx/zxdbdos.h b/Tools/unix/zxcc/zxdbdos.h similarity index 100% rename from Tools/unix/zx/zxdbdos.h rename to Tools/unix/zxcc/zxdbdos.h diff --git a/Tools/zx/ReadMe.txt b/Tools/zx/ReadMe.txt deleted file mode 100644 index 90a7b1c3..00000000 --- a/Tools/zx/ReadMe.txt +++ /dev/null @@ -1,12 +0,0 @@ -ZX Command - -An adaptation of zxcc-0.5.6 by Wayne Warthen - -This is simply a stripped down variant of John Elliott's zxcc package that -runs under a Windows command line (32 or 64 bit Windows). It contains -only one command, "zx", which is generally equivalent to the original -zxcc command. - -Please see http://www.seasip.info/Unix/Zxcc/ for more information on zxcc. - -Refer to the zx.html document for usage information. diff --git a/Tools/zx/bios.bin b/Tools/zx/bios.bin deleted file mode 100644 index b20e62d901a87453f143ee811a912600c740df47..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 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 z 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%0D~18g z>kz{I#dl|!{a^B9>aS#tahzqYxC47b@TR&R)@#yadSu|Tdw~=}knsN?6Wl<%($VeT z#86N@E-%h3fS`k&$_FXm+I2Ln|N9ZWF4h8D8s9 zgEq$r$SJCw`w5_VP6e=0qC0YbC6kMo+%C29Y>6N|6crYRxkCjQ5(4cf5JbrE6Y}#W z<3s-3*8m|aog%88M5NHxVs%1sf1OFRa%AsYLUr!I@TAyvO*TcVGjS>8wlsZEsx9Vd zSpOOMX1L`~I}IG^grKDL^kZ!|WD=MfO~#+Akw=lux_8xlspbI;X_{vo%e%Gw7Hclj zel>YPEeU8K-;s}hI4JB*h6v7_Lhvdq{Jo|f_zYr9Pj4Ng8=JTqVGdzEUTznlNfy(X z)R_g^21)(am*TaqMPbww6^-VPEG{&5MwBl0A-ZRYLxz(#`_hr1aFCu;$^QD5p=9j^)FJb^hq`jy%@k#)sop()h|q@s*z ziHGUk8=bT(r4b=yO1iZ~e6So2R>U7D zt(s!LksAlulnNmv+dm_v)cJ`3Y-r!O9g~ygocc38*ZVR;0f8i(O2g{r8f3iz=Yn^EDP^X*`}A=K>2r-{(#YJnyA_}Lto3!oHH9I3KB>{B3<`HvFGif-!`tb5zoJkt}q^s!iWbB-$l z7+G-NQ)=A@x^%C@SEl4Fsq)7`Cv@aB+3Xw}`>7ok24>Vh)Y!Pi=T6@2VvOqpOk><< zyk6Ts%f!dy(ti=i>hrpUIq(nmoyo5V%m4-uM54e#;$1nuTGA{S8I1)eSC3Pw5CD+T zVkjYz1Xxg-D23rcHc!!}G8xM_Io01Yt|V5HQ*`e$32tJqO`8HmA4!b(p;M&>!rRz} zJoSYfdrK%L^%-Jajp_Sl90Czv32;TMJG@ygJe>d1wWxpiHEMR7OoU7_@&(`mz_VPY z|AYtYt|UWy2G}M$JdoDD|0>s?oEjK!dl&lVbJ9Vc@$2ukYrDvA`pyM5KO&e9iHL0Z zq(^mtgNwK~Z_!>-TknSx<22?oGj7lbiIOv_gW|%z7PDNIFTL*6 zu%p`_TF}lFN&UKd$@Hp^2&|de;$2UJ(>EUwOH>VP|Cko*ow73ddEh9zEk;_1iFK*8 zKbaVDPEx~1iO6hwKMppH-$HxStlYGw+11KSX37G=Dg$KC2dd@?w@aRlpR~D2&NM3s zVKmOaQBK$V)7}?Xa*d`Z&~{Zwr44Y|xzWzqd?B(A9*~U?my-78$Pbw1@Mf_MS!@D) z;c4VGa{F^V3J!%njW2$a#EU{|<_J?W;QU_uCr>?*lRq^IH9M91v&i@HGAfYt{FOG^ zYz*(_dt`qA9{*|iO0L(D>)=2*SYVvIZgdIml}ovfpDl)&>K&nYLG$ZY>p32s!^DP9 zbDYL@iNYhe{im0eLeezVmVdkh7xb3q#()2ZLE`SJ|6h!VB6Sa&U)kf&#y5&)J4^hvO)?Zf4z;Wf;?k!I-n z^1iNal3rZ3=CI84m@*|TrNMez)bI{#V0wI{p9kbrw)jZr|S@LJ7%{knZkON{|wUkVcRmx`s}r5u^kp zB_sqT1?dh!N(BjN0g(nNY0&?}aJ|2oi|;!u7Q?JrpR;Grckgq~^PIDfJ}QWFCnP^& zz*P>DXp-t(Y>3}uH+M_Qs)+|)6*ur_L#{UBnPN5C@zJ!4OR#)E7n=P{zm;NH;h!q6 zpT4@jXZK}&*||&Ety0zPEa$jNza)l+;nNRqLGW>ak-YRB=%50VPQRSCpB)c#t0uuMt5*_%h+nf*$n6)(uRz!`-_npME_2 zfKUB&yo(KAL;&ryj$@avL)MTb!oW|K1nSdewy!i(KF)5PVJ+=3RGqC|H=xA#bh2+v zvLIROCz+3hQXY?mGAUVXaMv4>-cSrZ5HTHlTwkAxG;H|^5`39)M)@(JE8ANnP)e%AMYA}@K;8YT7r`| zpPt_>8PZ&}xIW}ein1knHJ`NJ5*^hK3O*DtV=~ChYCl!fJ*0p-%!&kk#(6A59#PQS zHm8P%7Z%LteRknwQ0S*P5re`yr@h}9%{!hIK?h7aD ze5P3@<{#kYXXpa^p@-)yN!@1;j%rQiEs->VeT@Zbxyp&6gly;CqAiGB?lEhp=sJCb zYLEJ~!AUa$#rFZayo~d5{cD9Nh#a`TjckRQx7#fq^LTCAWcbACY-oCOALimZjdwy6?S-mtMYnv@RZtbn^fC6-{ouS~p&Z))jq1`G( z$NV*iN^D7;JF{fId!0B(+snmxTb(DC0|LYn?OhH&I^|mldaOB?%5IeY_qW5S{I?FF z8dlm#-WuKsA&|0(sfdD!7AUFT&`~L1lf#8_1uVb0)X8sY`qc{&(7{bfw zi}7?K-tVE#0e3+01LrpwsLLVdb~Zw#uW&e?q<7OYL^1I@RyZhCZ^jL9eu=?w^mdMR z-+ikv^^B9c7UWE^EQs-K2Yg%l>oe@gO9YBmT*Vp!My!;%XgjH*g=3bj zTpH*)G)ArV-%)rR&d*)(J&K4oMOX7Y#a4f}_=`g^rgM|G2Dnupg{~~AW?W3s#17awF!%f9% z^Y9=tS>520Buaa#8b%}Wv_$?dvbaFB`&ck^1Vo@(5(9=Z&ApMubpg6#Qm`)}x`S_&3HbBm7U`qO5^UmS<4 z33B@lsW+Yvw!g#kW@YFR&P-`j)UEE!`PDRQ^qm%p9-jfN32kXhClJ<)lwfJM!D;i0 zBm8OQQvkvy$6USw{t?G`_e^ZGlRj&j;|#I^=}+It zxq+EA&Dak<2+4?%s+Z;64VI1vwZ7JoUop^_s9R%;3XcPeCOCfrx@3=E|5@Ae(D1?193S_HtaWt0Wd~m8VRo$%M6V_)#XUG?_F5OW2TY-h zP-%b1w#0Ik!m(#FWy_ib{7YgA1#i{EWOE6>cdSNZ|3!DhLyq6tWi-FF!Zys0nDG`Q zK9L%M71=7h>9?v>cM=x;(wSg9iXDarY#Oho>1T+qHdlu-?33(}uIPSC`=I!+LD5E~ zBYk{oK>*Kt9rt?BD>!-47xT+sJyMu$Sl(V4RjVIxl7u)B{ zlJX7T-5z#pY!sf5N9o)8Jeh9B6gjlstBF5kwh^Z1I;sN`w{HF>*Zp{Xyi$8tOW1H^y?aqh$oL7fA+bm; zJOA2zy>`u7p3D06v#>mE^ zARg_Tk%L=GcsDbWvQAA2r$}MtBGCzQBQb8dG{K>FrLpkuuODHWS*dNLGp3CQbv2Gr zWv|3cPgknu8LL`H()EYOU~BW3HB;%WUF6Q{S?-XllQU}m z@G}0pXPPFvul`1b64iqxm-($m8Dfw|A*-hJ^J99kocX6UDbe%R(Jn89{1cuxQcM{c z{?f3@086{bkax*bBxuzudn*@&TUWiAq;ae`W;?a}Q`$kNgSP3b;HRpc0{pi` z^Vhi38b0BC7V-+R9b(0QlaZan9&={r_|CEM#JX_#8C@vJHzqj|;#~faw4UkI?qmzS zh)+yGQxk>El+;cm?N(Ot49+?YfHUqpXw=$FH^u`Hqt%jV{EMOE-z|3`~m%W zl#0V!vDoCSG8B1hf8)@v*(V;3d=Kv(?bZqbYpW1L8z*pKR&bR6ewU^+o(+lU-tQ@-lZK zx#7a`$Z<-mfD>NkaNFyv%B;Cr)gg>TdyK;|PHeJ!^o2wtT99oEiEnn8qaTiRAQ^@9 zM{$W+6DiI4o$i!r>z0x6Bjt9|T2YzGePaE64k~X;PxyFqJj#6atWj@+Cx>e|*2Kwx)(~T`B z_YEv#i)0@w{$hYYbUDc&MQjQ5l6tge5#u8#5-B2Ixh>CFQZg6?8jh;$Z6o4d+w18W zu~FcNx5-Wi{={f`^zfiBAEutT*N$zd^ljRY!{{z^z3wPlJLI0|I{`}PK?8ZW45EAi z2Riu{B%(xA#I9M8~WYVjtwUj6&jjlx9e^n zr2CeZ^S@>+OO|b0&WccG7Ljk`@Je{SK4vCOP8%S1CwTqS)j+D96b|Q(*9SC4wpy@K zNgm-A7|gL0_FI;htgVJL#CUfF0~c!vyXxvAg&XbGgM%@lvt^&hThj*VqPphksx~4M zpxB;$T@H-~CBd^=tUu1aV}Tw9*$BOmmx$MMB#91i*htUPa5i%KNjkcQ>C>DQ+v#0* zGYDHZZf&(p0y4U1EBxlOATcEEmPJE7hC9~8iei?U))tA*j}C>{=cyWs-xDyWBvphR zCvN``(qP;WpT?lQ+S>BCX zP^{Dw#rm?E>bH)V(K4TF=G5^$+kIyfSOeGNOsp=`;e{ni!`fe{9 zgLd)+Hzj+<<2vp9vSOe160zS*>9>{M7fDFh09RNF$fk`m*VisJYJ*i5; zNAM`7#f%)i+?5VX;gLc>#MRgIgi>l9XjvncqiOfiVU?s{{hdv!$%b(yEp~S5oG}4c z%f%0!4NNZuA`S6IjQgf-62EUkNAdgkS+4tRh1O49k8c=$EB`K%#`DBCsdIJ%_sh=b zkFCdkV&amfYOxPIyCgA^b5SNLI9u-=l2?ar%2rIT5RQKvB+iTo;jN`GTHjnyrZUEs zw3452zjb$s_PcmY)>qZQnwzh_%-RYzGKMrBwqKEJ!=54|9}14H_NJ^ct$ao1cZ{c^ zi6gKRCLFey#j)GU=VQZKlhsY^%DU<(gz0{oW*_gh^TpF(%<{YpvLVV-1U3hE`Y>Be zLq9UIb=)nDRSta)U4Kip$TUR4nQ!(!(1Xl`kUa)sq)@0V$U{Uay+QYyk4Wo1O3e#M zp|griv~oM4+Xt$QBWKyFJCdFluG3n5I(?LjJ*ILW?z!Kj`9_^y;F`q% zd7@h_L7YIILGna-Iex~%xE@bN0PkCd2n$RvA`JdCN>^R9q-<5+RC<)f5f(_s5g+8k zSd0~6q4MM{NClfgoO@POOFs6C?PG8bd(Ja;xzABtgcIsNAzb%nO%8|G$)I{au9srJ zkGFcmSc8_Q$J8I6Z*JB|3Mx?!@h&zHD}Zr*R;{wnqp*dX#D$c++SZ~)ZC?2*jW4?J zy((vG&<_&m%&R2yORD_qtI|?wmDpeANn({VQEbI@w$YRJ7U;`LkxJ4`>&!W67`yy&OkxgD`04Jf33}(qJ6|E$nkS-C)Py zr>YZ4u`j*??i^Gw@3?+izp^J~9v={wF3pU-sCL}eE-3HFQHQniH4CEoi*?R`%BYX` zF}39@`fyA0w{e0!jXkSei<9ejyO$?%DxB%1tnju8)Ujf1Y|$y69^P`Mje4%2Y_ix& zQ#-iaH4DjX2s)((jl5yG0m~Y1sNWi{MwxE^*)(${=EKLLA2n0D!9Ley$W~F+Z^>%0 z7QL%`rq*SLwgYAU@bbN1ML?-{rtr1)6bh%^&l@Lq#7t1smxZAyd4;yit?Cql4+Ej6 zVz*vvUEupNpeO{j@(}-L1nw7bsVK^3Mo5#5nf-2T9c2!@r!CAaPz_Wgk z*7aSoUT$%7VbC2pwLLuE!RTmt=s=;bdlyMpWht8?L8U&Cmh6Vx>_*sc%=`hWHRY5T zt&wEyJ9`{e`hj=q_jQQy%!&6(aUYo8Ds>;z85U_}U-gPisH>3f==+)giT6+t- zHyifU?IjNRGCpj9qC0!|YlZ*7y$arryj(eF`Ov3F?K@;LVTtBjYOu@nl=ZD zuQcrv7id&` zl+6U4l~? z9rOhOZYA7IvR}Q5xliPq@*~`*xU}imvJR6XIGy~ANdt&gNUEbtN%!MDj+)pz!F5s7 zzs~aNlV_gurhT&7->GDqpg|5Gi+Zj?6(C3*{teWN00M62DPafj;-C*aQjN=txVgof z=b+(a%D{J6*F;E)J^hjQDM~;cc~W|W^&+?7`&(XA+tJeX2iIHaAYNCEgNh9vC@8rd zK-1(-#&(^7!4(RsB!~!T0~4MesIryBV8DL?zz_=)1gyP>KWP8?Yi0u+L~Lf`hz+`U z1qE~i1olj#Z(STg361nyjY}CtIj+Q5um@Jk{g-UcoG9N0R1KjaK0mP%k(>z7p=R)H z`-tH1-UK-K>m)xM+@_9s39Ro^piF7K z#$5v%!u*YO$@KFEUQ4@CZ2%2y0uA6HH6Ra+Y5r{hNW$)3h#x@3RtnCa>AB$hgkHPE zKTpDlt|36;8v{A{Up`>HIn2`)u?0%Ci*NN$3jzYTms;S902V7OhK|AjH}m8DS1+_c zp96Fh<}M!GP(*TvJ^}f;PppL=t(@z{;PquPZ2+;R$I^YNd_oY2PUyS?LDWkXPy-ks zTiL_RkkL3?`Bt+48vjNy9Q|4_So0NT=ocZt!J2^XkwqRv4@U!?9I|3)U4zQU z0J1R^3tTZpc6gWEaqjS?{;h@Yz!Ini;KO4h89mJoCp($CxLP1vjbE4w*E##IQn=Np zvwvrE8NJPMBL#s%bpOj<;eoSVEP$ivk=e6`&*AJ1!f7}gtb_koyVu{8*+>E&!6*4I zJM=CB8!3vK>C)irEXj-b6z%&v8!@HeAo*nd9-Phd|4S=m28A2vGD%yd{Hx{vZ+fU2 z0v!r-KolWH=7qfDW?sPqRNR^Ruk^>t(obKWmpTH2K*+XJt0U0uUEL7rXC27&@dKK_ z(%oY#Yteu)60l3-KlF7S1UgXD1d)EchD`VJqx&me*Q8~;AJC#Ku!{;=8GWR@7As16e;m;7q>DguK<;8}GRL6!3DzNkrQ4C2^dRKY@bMq34;CWft zn(UIfmscntg5%$vgD)n7h-B=#SF20sqp(RfxOxqzFO$z@hI|DOksLMfFB!=hG%2}o zNmTXoz{$ZJE^cRX3)grgg~5YfOW0C=1mjXdo} zM1L6h9~#N(9|14nR(FJQ!O=6s6ql?%M;G_+P4oI@!3;ZQ>#x&|XElxE=QIO0(25de}GrR%Tw|b=Oh@eOCZBf{Vs# zz#VHi8>2nwy?tUbK`MROy&Mhmx z?`L-zl`%Hn_nkw^%}8qg|K0vyjDZc2LzVdVfAI+a-_ZUw3>0dgmpV{YpZ`}$y581Z z5^(2;OSZU7x?X@ zzHHY#<>#hL+$X9nXFJqoRNS7maHLwVM6%Uq=+P50M>Z;b=eje4k6QCYi;-Get=gg< z+pXLYc1VgVL%;8JNm4U{vofzpqe^+x)|EZ2HQsjXyqoJwNgeC=y(UTZgo|8yx)o2? z-w-Iz*1~?t9x9U;UTm*--DR(HO=XKwz+UTqHsXH@Zj!84?XX6f?PC`o)(b70v zvvAGC)lz^~$Jx-xc; zy8AWmj5qE#z!_m*t^10ar|5n0o08rL@@CgScBO!IrMU2;o6JIz!U-=udJWJUymG>D{w3 zvt8$bP$#}6Nr6#B@Y$v7;w`F1i`T_lycBmR{x!U@Ii))Ypq~NVo(4;>c=v6$-Zby# zBF>UI=ucn&XV7Pkz%fJ#!|noF^?G2R4@hg&uK<(#YGvQc9JTbiptKLI&elIc58#ei z!4r*w#7m-`f>P51RPgnI1^)?=1or2}3R!reCk7U35rr;{6_RKV6>i89^pi(+Nw(7zZ-Ct!erN!|ds zo`!6F38Y*INGa~tN{8Z1vLug~WB~^-!6X-h>b+nb(O*H}1mcysrL*G=-@+Tt($9!D zEaMKf>Jzo*loq4BZa+XQlgS#vIzpGN{3D^(P;9>v4dKg*ji*|xB+`Kopep1!qx4aXB$8J83=QbsJ{nM}XFBy~EH!etdVh*Ga_N7?<{v(u)q`<7b~&@KnOM+myR08fSi}JhoaFaN59q>&RZ<$nLxvH z3SdTw;vT%akHEbdce6`xq)~R`7Wi0uH}Y+*`iY=H&C}3uZ^*g?RF$kttHx7$e>iOw zuC{R6YFtd=v^R0NHk?+2%dxL1DAtO*Xihk7Gp{2;9|-pz$w6t;pn6lo6Ijz|xO! z?NCNhy{ss&5KW_Z{_)#gc@k)onj2L&l`J_Rnaa{jJO`rgiMG}fZR?!U{~{Fr^&5^t zt>vbh>ut68BcyRG0D?V!z6EXAYM<}=C840clqPt3_wS(jZLMmZ))Hz@H?=5s->XYz zNRn%e)}oE4qWU!uL9|w16NR60lhNk8sJD_{8}0mw+ObDnFxCeShA!~N?n-t7EPalPp$E(v+6eXtRcTe3v2aoAa6kH+P+}w55d4!(|xjo7eG^5 z%Nj{Rv(t|kF!7O=;RUBb_fp|4TI6?Y^-Dpuo4EDmDli{~0EcI{1-7?vxBfQiiFLNt zVCpe5!cw-UZ{(u=YtAK58g+$~eOPmLK?k1UiCW|*ZiDW&wNC4kga3^p!PGJGyHfDN zWAsNLr8$ddsOgcN!G}$vevj@zeKO;xqt>(!Wbb5Lr+nb)M?(|H2=wSbLhqiQ6#21K z-f+O#HKlP{UHSM#%ah|Rci^o92pPd4p4M0X17yhW&NQ3!gHRP}2t!bI0EjCsksSf& zZoibX*nXMoeB5?Riu+7kYb1RJ##f$=98-(`N|Vxind>Xm@=K_fvv_Kw>ofKU)F0;$ z_8{)a*yLcO`UJQlgte>!ZL?OSYajZ}Ig3x_By;Zf^jzjj1&&6nB9_ve`y=VWE2CQe z{&mhSV!X%*PkEOldtJB>I6L(oa@L%?VJ}JpMSAec6ScisV>E3w1V*2Wq2R>_fx`WU zD6Jtu3bmU}bu}-L=J+ir$nUgf{ZG(n;=WJc`8RGGs=BYRI$W9l)0Bgkxzdz_O4(A3 z7w!qXUCsstG@e;65kGo%+Y7XfYl(@)+@(?9ju-G|W}E!Z8ht-FG*DQ>0SV`2-eGD9 z=Zzv*f`xCV5m@0oS<&Z9vqA$u(!KLNHGP zKHy5!z;M`_)?(5j`Dfh|o;7O3nlo{)&dLnV%2GyW=@}RluTjHm>uZ(0OYtDx z7wXAaat`H54&v&?k7m>;XeyH8XhB@Q9XZ! z!CejP#JSm><%_yU61(U&FiNE5TCI`vE&iA}LDq3Dg3LtqGB`g%b~9?C1jmcM=%SN@ z`L6~FcSCZ5x0>`5;As)x;!!^a!W!9pZDcFguQWt8-R}&CXN`s&Dc6it)LEkf&akI; zaeTD4Cfl|_;|v4g7;CrlEr%;rxhBie9WwKq?7%4EZ(A)UXeSXmvqHTVYoj_VOPw`l zCB0H-jSUoj5S%qZuN+To7Y@#vr2BAN;@jprkrZW{wpYIZYL%l#opleVroIMlT6os& zlLOA?;5B#X{{y4SS?wxn#rc8$2{MA$6!W}`d0v-(8gR3uJWPa=A6J1%U|4xL^D^1@ z2!99*?C*V^NXENamqzSC(#%LiOS$5Qw+JcHLi%j9tBrbv4^Z3m{L`rQJeAj)pC<;> zvw&!tq4QeJ&rz*aR5~zbj;jndU?#^yU8bSf< zoSg&?wCJXBKxjr>AL)>qp3B@BTpLA9S87fjlV+!`p9(0UTSnAG%^1dL)D9HthL(vj zkbWtNg|nU5g0l_Vg-(L`F9cVtX3>nGq+<0W#$9r;EPo4CI&R^=3Z zwo&D{c$Ev|Rn8H`y4@DvHraO(8PYkBY zFr2y*uBuueOr0=8of!EdoPMsYmIrc(0l2YVxspRb#(J}@6)}y8%7IHZOX<&B z^s3Tdu=o#Z*Vzu+HZ@&qgYM$^i<`~Qo)swc>`pD1vz9C=>>q6SLJZ8-Z3FIgTa)I7 z?3pfcWhxJwFL9+S52sw>J}XeziI@5w@EouSR*ZsNzE5mi_UuT9-Rc_et##+T1xqL~H~#pVD6SWL3l57E`6=*LzW*(V zlN9mb-gT*`*W^0U*ChK&foXDef_cPag`KlZdsQ==L%C5vdzQ#G^_f0YXIR-KlwZCZ z#m9;lDTTYE&fV&aEOrtyeBH9Qm&C8I(@(j_dwNsdskYikn$~ufQ;#z)A$}r|q?bIy z5x-=2DxM&!n?$%mFCP_C0alF1OD`MsUu6Mvrkus{n_WIgO5h@LVus)$EF^VTSsETH-{IAo*=E{wfdQz2etlc!dvb&-YYdMoC}gnX^;b5Lyt zw1L*_(apZvM@I%T&C0a%Tq##Z_MoZ989EKavy<3oxC@F1(JDAQ3ANOS7y7N3KgRa6;tx?ip!{dt5t{#DZx5GdERqTRk|d4~QX&=tA- z(oxh{`I%bJw8nC4a9p}0Y(74+Z%9j_9Tug@q%}sy3@VwV(c|OG$HavuVx&{UGy%Ga z=tTp}-~)_ofX}r}ND2HVNOoima?S>T81Fhh+>AlPh25Eh5l_04qc%3;l<5S%)}{4% z!jtslPzUXtfZnF{lv}kvJgf$818&{dT|Pp84PCN)AnMYKsG1zS4EJIp@zj$Iv5Ii!B8T`0E2m1dOd&P z{sLv}s36J^d7kx~R>K_J;rURKUxcLonJ^w&;paJLDRLGsa` z{_Y>CCE0sDP^?=a;Uw#Ch?ii?-RT4wA<8KKxKaKzD!&D9sl1Qt1~$$h(^Q~M-&GxB zvrI6}W>4*8eGfz?)Sf{y)1!A{G#I>7Pe@h)00Jl3w&^dUVV;kx#HJ#jgsXE{;p#-M zR1H#rnhQ_^59r``bm#0GEOVWZIo~$$+YAtieR2@|CZtT(LNPgFVPtD<(;DUA8r;PM z?`z^gJ~(UA;2=W~?8*8u7#&9175XAW&oBmu8E#B%JV;G;=}S=x7&CbCR?6(t8Ugt0 zSU^Y&*@+j)Lxz7jP{72ffyqA9eHe8~o=D7Iqx&xXO^|Y0&x1nD^1w-fqE0^Ss{sJp zg+TMACyJrsq(8b&bgb?5)K1bDplSV4lJ?``AVJaK&0M?*EWe$&f&;2M!MYogREU*w>n@|H`JTQ-{Y3~28I)cz+bCfa)&Iez58sr(By)J`Ctgoemk zF4$>X}yT&OUi~mmj2)>^3@su8I z9m-Ez=bE#q;L`HuN3Yg;&&qFJ(o2OfkE070-!+K7qPq)83%u|v+%BhEZ9NpwsjooL z8_P3s`wN&@HUck9`OT46k#P@Y+>RK#;N!JV;_*@_dGYuP9&7GE!v>o_P0vvv+<30Q zGliic=90b`4|7y3^K{n{8b5&%@2+#W(nb}6ExYToaW@8pL$sV1FQDRDT`r1ST;^Am z?z&W9+|gZU!X-NvQ$G`>jLuFnI-}W-J~sIw&3KqdZ+dyry_881Zv$ zE2L=;P=qpTP-fsV_$2DRp;Cwzrp7QAo5IeoB)?=s6rE#+0yt({E!v7X_$k4Hs1a~T z1X<8!0KM?#jYxW)r#G|w+FPAizg*z{zNpDtMls689D7#JxmU zs&che0kQ=jv^{}2&%;@V+?d>tkz5l?pFv+@;n|MXY9Ji6W>@d29V;rlj0!QvN%3E4 z4s}?p&9)|75Vp5&#GES&-ip>@Z6xmD_;jHP-@Q?&h1M#wO)zBN>8Wq}wfD3(Ttc6xn!Xg8A=HtjHCjKW zcl$uH#;3kH5ZaX*Og-P=<%!mwBEH$7zLZNv$KwV>S}3>MUtr4Z^qa8MQcI)AOEG;6 zPOl3cILWqk%2rz7!bRHz-c2RmO})2vgsF`;d~ch5$+~;suK9m#7Q0&zD*S+?B0MGR z*(K8jz{D#yjxgRpvt-z-C5^EZ*=b38&omFi= zz6k7ey4gzLOnFuMJ;psWSb%Lj7f-5s}vZu%D8tLgtbx-7u7uG{bxz|J?sP!BL zxCaXw7+-<5p+ODFpAk+K>#CkUc~N9d4aBHscO@2ud?3uaG@A1u^eGmwV(R>6w7|Wf zTo^|^A5S!Y%)*1Vsi2hNL#1ocPSB^r1{LU!z)kWrWN{TJ@^lLthbB69O-QJSiFgh! zr{W9>Qwm;bG6E^h`XS&f4B2bq+DI;+nOL7tcw|CyeZke2sm^G8E%*Q28$}ZZp3oh$ zOB>M7TzwCm4?q&RGTz#$Lt1lxApjAv*Tv{P@@5Ro2k>MBb=q_T$CIifh<8(cSfQXzoNQdwUZC=DT@cI9!b(yzP;wI~40MkrcCp$6 z5_8@6Fv|XK(S77Qa-eo<0w^+Ybrf1214?6VV{6i9LGzTr%+reC0&oyl!St&2n>|>M zBn^yNAr!S17P>o0&%zps4P^qY<>&>fiwh>yl3Gc-A_wa*)r3s7(u}_`P39!%v`wK1 zR1m~%$xf0vwVDcQn~YW>T&wXnhBBJ0`>D!PZdD+!~({7iSp30v-fg5WtEt?@P z+XMLQ_m!O@FS`?S2Ya>b_0ZKNd*{=2f$Y5jS2mN1-79-fr_A}X_ZZ4NK&{+e_5*p@ zU+M0rvbT+{C9<~xSN3OmxJ&l>=z6E@eGu0`KEY{0(=IKHr|obIgIlk0{fO>3tjgVG9q~1Pa^zAcx$>PUIi9+Cbq%Dyv^hEV~ns>BpfLH9eex4cd4Nr`sa?^f_BWjrZ_K{UJ7XE1pYW z&KnB5H1@ZQDxP62}%HQ)rQbn!QjD z1^SsAi2%DXH7I$W)Ch|pT(`ynoYpABfC@3-f76hEKn;$hJ3brl+Jd_?lX^Y#Yh>)> zXytf$90hVanKh}1<4Y82L6I1wnGt0C9T~vTSfc0_asT>m zWvaZC7vddW`4yha@a#7~x0!~LjiK0@0?zIJ5o8C^#t8)ewTUV|YLmDK2M7AyCxN0S z|7^2bNxK=vLyB6t0uSsXP?lq^OQ|6X7IlvuP@4Uf7eIZ5Dy!-ItwMFx4EAfh#1Vj! z02KFrQu2;_Yf}P6lS(xFZTIJyR9xHqd1kumn7XJb{=8JErJ|4gd1>^Jj;$hj8BmS0 zQEjf8LEHXu>L5Q8&uv&=pA#ShqU)0&vVp=$0q6b_&CE_jzu?|*dXyc5Tm88iAs+l$izCSIK;=cjZri_#vGN@-E)*d3)+GFPCxew#O!Vf z8F4GZGX5n*4j4X~fMCYz_i%ThaY-Fr`3VjX{{42ebv@c5--%|U`pb$i#F?09eyrtp z1@f~5g>pN&-T>EObJ=dFXG~SgcOx_~r*sBJp!dAbXVRX&)UwkS7JB+7l#O3_i>L2I z+4~5}disuc-O1oA;%=O4CPOc{OL3j*=`*`zYy@yWpf83^X4~+hhLouO6iB9~vkxib z5dK8I!l+X8rKEw^;CU^1PdGS&&1g>n$Lu94xF1#ZegBL`pX(v^M1(>ry^FxRW(B$Q zsrvEggnP&l*Bs-(!fL$dA%Q?)wtkutx3I8&!ouQ4SXkWfV<2X-r=~z58Ch6VWb;!X zBk8V-^0xWS{*ww4M?ki&j~UkhjA&^XJ+fCoV-eT5U@`ftv_%usICxlr>7;VVSL%`9 zd^JI@CTx4w|BfN4_4ZNNMPPBC=4*QNs~QWkbUHXvla0F{>x3VxYh+}c-iKP4j~>f+8S^$ofLy;DFX9oz>8LzMY&iep zW4uC!-u5(w3_a8LyYmq69J8tmR|>g!z8vN08}(3D4Q1#jKSRb$ZMmr)ySSsHsIWFZ zR+O@ZgTB2S9jJAy_$KzNL>D9JRFl364ct_Jxb4kZREBSH)~n%`-c-+bH>+7{i+u#5 zRq?&gk@jIWI>+X|x1n<}xRzynaI*dgdIefWib=NkOLCV3tmx;VJa~YnEZFpenEg1D ze~#6G2(fzI8DC?k>Y}g0&V5|_76hGL1*Q8zlH6_jl4c@GrZP=(W!P#N&1u$*0r#Mc zK9+arHviSMX1tLVT|qD)%e>||BWrge>jWcfODrpexTc_VGV=9fc~2JaHrH?bCN-T4 zk$PP6#+z&!NXeq4fo#${KY*3iFwbQRTO&f*nDy$10+q5smQ1LtWoMyI=y!@uu(l9QEokPm$b{M6*weW=Erk z&HN=AK?}5Bh%bq(ZE#2rUh9y4hx8uOr$`eD9MUyN#Yh39zaTv{+adiL=`Tp1Bb_kE zAzgx0iu7xw^+@eV2a!&k>yYk5T8#7uqz0rHuX9LmBW**H3mwuNqD-Z2GTo7A0SbgO}Mrpr4&1)vymP{dID($(sM{u=J&Y%1F0WrUWr4x1L;+y zPmoUksVH+3u9>9{>8D7)McRPWgLKY44(S#oYA0hpaE$azB!-lCuS0qoX+P2x_lYvk z;`$9z+5(3(0%c@G23S@Db7_nnP+vTHtp`I?}TNl&t_?Azg>`IMVA#rw1`6 zq_K|!cBFl)K|@^ML3(Tj@QpO}8HZ$j)*&rLdK~HRNZXLoR$|OZS0nus>7rHO6{I?( z50K2yIiy>Weu{L`^A2e~(n6#kynud@?t0N7xslF%32-9SAT=NzLXuy0NarKXMEW`e zyw#yDl8W>eQVY^{qzmgoFQnfhZ9?isx}X6vhjcU2-;nB&X1@p8KjDy;A-#=cs&q&{ zL@Gl171BSEe(+0&^dqD@kb+3BB5gwIMw;>@^aPR%>9Mf1L@~TzeH+6+JV%IH0CLXG#!cb=#3_*?LRN%Y8&gVIe0A5 zeC^PjCED`sxa4ljZL)Q%EAGRbB^O>;i5Ao;JF59;)}pSsA1~Au+5B$~|2v8QJ%j!h zeWVsWtro3Ri(1qb6M0UhT2!GHDe8(v{L!lxscKQRT2!SL?Jm()&|z2h>9yo5z$NkX zK$hzCYCR4EF60L|fS&LO@wz0+pV`7=sFvTU(g`$*f;qj`7Jp%tC!E2Sp+$eW*Aq_f zU#FIPvEv#U{Z5rVNH3h#IVOLx+TWlSt4il;f1zq=@Pt#l>twmAwzfUh(%^07cj=Y} zrBA^v`}j80bE{M;j8YA?ovFMTb)TiZe|@HzhUKhQ4lL&H%xYWCYP7PA(cuO@G(aW5 zzd{8V^J&DbfWENG@2m>-WteKMEvmE1UtFzpHsnm<@UYwOAz-WgFLG2CSE)X_LBIau z7C@pFSF6qzw(=UdyWx>ooG8rg#>}d)5}2?x;qXaeh3c$SI^>d&Zc%AHt4J-;>XeK`ceS#s!Lk_}cHPxjM=DZL*|e2?Jp!Jd3Cn}ai3=j>f#pOn z_`&(AwjQxVgz56V2wO%a$+|_`gaD_E?}}_$(o0wQHx2%xYG6v)*>IQ-8g> z9TWv}EDdUrx4S+;(QR>x9#Gg6i~?W~IYR@;`98?`KFGPiOXNHhBd5;E`4u}gg`m`W z!K;8O&tOO`ND{>UHU@xj0)l8cCQAdh2^Uw#iQJK~v4;~m=M41AI?O0d9A)YMKy|Bb zi+130_RJ*)yU6eIp=*5(Q=KQA#&%CLUO)`AUeRx!>Qn&Chb3Ag#FRj|A_mYq9H1Tm zgc(Y!-$%mdFH{gnWo?)O`ke}iMlBkUeYgJvc;qEmA#MqkTv!KTljpJD6XO0z%@OY2 zGtkRNZL+ijan5R0?{8FjduoFn2!uqLK@&@Z@($ILSUa>1;65ObczF!w6&&W79A+R8 zUVnqsz=aI7EQXv^=V06284wmryM_3lMduBRtxWdr)R;*8A}$ijup$9@Fm3cNC%_;m zA^?8`x!_3PqG4*mj)*3u;|vlk)medtpoRLNg{rO1?0+s8R&I#@MHBf7MBr!y$JS)o z=?@ZoT!3hLU!<_VAEa1}ple+HDXbaUc-_CAq@+ku4nRznTm|y-2G~N}5_$6#&^DxQ zh)YVo!o|SQeNAym=~Y-1VG1HOIE81Y3R;7iASultc%ed)(ifAI7A`3<_1SK5RDfeI@DG$iq$G+nAU_F<<6G;PL?8rdlD9VD*XS?zGiT5q1g@a*|m z+cAMT;4sybz+Cr3Vu2CRiWd(sEtSKV7J~zYT>&jwK3av^JJYC1;T6P0047+LEDe{< z+)is9v=>*5r}0-%oRw5|*m9&eOFZ0knc40uF?Jk=?ejm$8}HUO@kdgqPtyF{6VB3l zbGz}m4(nE9tQg8c5;VMJZjX~H5zvt)a1%P8fPSH0iz;Q`IjGPNJe?|f%!Em%=Gk~W0nu846o%%h zr-kk#QLo1d6Kwj=nEsR`NeeUhhRq1#{1Cn@H_l307mo4trY%fWimSi&=;=J_gVS@D zoO3%Ad*p)ddZW}>Dw?k3S7${;+1hk8o27-8?C3(tCB2o@eu}5|c5Dk~7S9fov4jcv zha08ts@;_iZV8j-A8SEafqWsQ9bpAa7t?MfN^*rDdn1VKaugX_z+qZPIv^Dz<(`r3 z`wO~?`$uZaAm_-|Bt~DNg7{^d1rX!1B zc*qOX^-(MNeE7+5k+_DhWS?}Cc*s5zdH`449V5HnS()2?cvA)~Vz5V_1^a!5F=ddG zcp(k83nwH=dGrH8!;PdQz$XA=6xxT{`cTx8`!!s@FDxY*Ts~{>;hjFRT}FKjZAfKn zuc?`a*ozphp-8bULZ{6^p7t}W!YZ)m&n5)Gjsd{j?f_RV@Nu!CGn|Xd?KvMG7l0!o zf!4*ioPbu)IJ8|5ek>Vw*Z^2|!4o_aij&<75giUg0j@MLPU=zM2{^^7HE6$+d&cXv zjo7wy7|+;15>;lK@rT=i!7^XFIgH>vrR3Os(_ z1k~+^Y9Ea&Fa@)~d587qky+sQVS90(WEKi5$t)ni%gsVzC3^^M55+Q{pHR7vl#Zje z1)~gG(7|4_#O*)_qca`?f{P%be2S2m&V2?O@FBdK@=CG+(U@1$!@Zg)I~A)BL!nbY zIdZ_#N3aPj&S7h` z7@kR$*y*D6q?sYZp71D^e;)S}s5$Tv`}8tHPrHx7{MA{J+pX0@#KCmdO_7T*L*gjs zE(WHcTmz7lkUu731BTi+wHUDh!QgEIjs2KqSF7Yn&@7~5HLO0-+tLB8LU-ww4m-RE z+?g#M(CyUpR+WEpjm?ZhHYT?dO5a&QaJ5^kb&(5>9xeka6L%mDIfcdLkSIG%1k842 zgBg>>{zjTH5h(a(+s@UNopBhqTZ+jvfnyWPWetd`5wZTS;*fwYlOx zlJVuLn@U0-;>@m55o1X_>ki`s)MeFE=Jp)k;5@iTkko ziS--2-Ry2qjzbLvAV5Mqs)}v38=(u6vL7Gi0JSY*>dm8J&>}f!uu|&ONih?OV4X=d z_$)v26~YM-U8qznOo1aKpMVLm{s!?RqY|<5TW*niERouzqLq=?hVpA}C)XU2-w2)f zeTyEmL)~Ib%*L+>!C*vQcH^c0Cr6Ylw=MsQGBLC(XRF~xBqBN<1e8Fu|I;-3kBrEv zu-6d=qv3QJtoNVgy8j%Fgaja1q_PTZ8iEL%m~imb+-`1S44;_&9nq}Vlnyl#Z@JI7 zipRQWo=p*OHeEC~D$$%b^5;ZtZ%q0|3JkJQqWomi&?KuO7M9yd_M`437ix zSH=E`m_q`8RV)SM5miQl4dCdr7cb_H_Gp82;HIlk#+cL;s;mtyh#F}mH5<^wXn`ny zp_e_4x3RKb_Da00#SpF)C_ct$S`d9V)etiqSkO#{H32ac*H(L7d@wq*`$e*S&Z z&xm6INULHO;E^Lu$RBcia0z0Bsba_ADGtf^rINrLcV0+dx53=sTf1I1;y=+YkI=I} zBdq@YgRHO{;_Z$b=;pVuXRu-OyLd3t$FH3KpFlwsyAJI_t3X?jKll^= zlw@bg#oH-ViQ(e49YG8uYmjnnlixczg+ug1s12I0VI338rc>#O2aFKe zQ?cGd831ueoDVy!>%=LI++Crac)uDm4eZkT(3n9)E!I9nV3u!y%wk=wunHBHe}so` zHfby9ioo9rYWxE6)VyS;f;sQxt)afOk-QfB(P-|%@tZ_tp<-eYr}!&_4X;V+;(Vwe{JyEa~9bY))YF zH&{Z(S`>iTMePGfO$5@O;X%^S4}~y;oNk=V>q7@D+6oR3r{73^4=h^` zh-{Fzs7m|n$S|z}OiBD-5&6LpLt-XQo&hRsc;hj}LxARrCE*aH@uO6*N6Pkkb8dpgg2-yse-r&B5rG1uk12`y_2Qzu*exKi~>O;xiDHk z6Vk_VHoOe7sQ`}DzL(U#vpu)dgxDB%`*77t%k`xF3)=@E3K>|}F$pabTQH$>gSoq) z(mGb-*bS$?_OUp745bC4S`S#U0fzJx*Ae(01J@%-cA%(zFn6+ zFM&NA4>wq<&bAHc1Hys65FK119b*0GQie2E&e>#hdQflyPu+GT3vY8Mt(-J)(HL(9)#nm|>~ zt4AZnM}_L)j0KyU1V3<5$!)~&J`xxa)=h08=!?D|=)Z%Qu>~B`?^}@yHJaN=7CT0i zHgGu+1+F{8M5_5BUa*CpvcLeWs;!HK;kAS~H>!wcs7 z1giW+Z`;;`u*p*eY6LiBcXMJY-v_z`hl%+NIl6|=y@L47u&o9$w+`^MhY)i!p(~7i z1nktD0si5)c)IWqe*&fkE(ao&CS>&D+mU)Wqe9rSVg@FrWpER)t#$=9X~ULOvK+SN zq$$`y-o#+o<6Hb(=j+1_q44!@hksZNki-7q(QbEg$5zW2WSw=_*MaB;hcB+EslsGh^+?CP?JM=hPaEJ1v6;4z1(k`(uOr^axG!QHXDc`KMm## zfbN1D41|&QhN&oNjeYEFv=H}AeYc<|5(C}_S24>eD_P56D>$@F%rS-9sY>XaX6T%w z3Rb|?f-#|{QQ!7)!hVpN-UJ=3tjFecVLVt0RtE>DzqWxO7UH7Heli9rc`!C|oIaxy$%AW^uj*9}D?Ws%#?f!qYwo*>4`zlroV z5hS+DciQkM#8AkeFd{tIWT27e9?9o#*y7GTKE98A1@#0$9U`S1&T8&8(ej89E;~{T zV2FP@1+EZM%mWg972_s#A4%Pj>^9<6@PUlYM+bzSKeC2rFAjwFNE%Re!W|{00Otsz zSv{o<2-fN$2Q9WHayB}-vq31|BN&7B)D7ZY@#5R&3!Hh&ain1Y=f*uB>sI1lSjl|8 zm@-VT^g0HX>N@J8qg?H+6HPGOt_O2&G6juU7~O5Mpn;VVHG+oJ51v4 zuJU$cV~V;L`(+@;mJX#ki+zc03^dm+uF9tKGuWgb+up=?+VBmVRBq2{C?|ZX{Hkp1 z4M|n=tGw7|-k>(e+QaG7#z-r|%upxU*ukBOBSK!B*=SI=CKYLm{28x~c14E+Fu6qy zgH6ag#)*R3jr*UOU{I`Z@@)=az+{zd=qJ#f7Mn_FpDcQ(SURqAfB#o0ilsJB)6eF^90D(R1abAeXmYYPjT9B=s$i^<75~EnIK{2(1XjY4t z3Vo7-Zw#7T%yNx!i zsbOy|n*j}*RQo8XBuPm$3En5RN) zV5*wZ0&S?R!(EO{8~MpAnA$EsS&P+&9xP7as~S0oP~n?2A+1GdacuQPWWm~K#o`6{ zF`t^TVaqz7MzlU-?H8M4Ot z-L{2UIik|&=$Y)h0Edp*N#ptEXJbn%A2Bu%@;#2UrIVjjrd`oE?nTdLwth3u6;0fW zCTP${+B!{}yZLd*`msk*7#&7Fz#nSgJx^?T#i!$#+0Prn`A`M>PWeX*dB>hwGo1vZ zeZN|xaS|-?7N^dzH#B~bjc=f3G=by?4~$a>>`VYAw&0?tFU_DKK&H_mxEJqAU`X_U z$urL4u-*K8Cq_SjS1#ndLMJ+)9Vi||82}?bTZ^sBB+VPR?i{j6Gce9(tkCeH>oE_e zX202FI}neyZ3-Po6U$5FbQtqsm}+&qr6INhddpcDDn|oHDsU$78XqPO1;){dF*7D4o~hD{P`7zZG@)t^dVEG!}jqKpe$IBQ(t*SCJao$`*-63KgSk z#pqh`7b~J7WWdF!OzL_Z=-o+8KyGl{KFBja z^!46xD?9J z=0J|s>}N(1oXnsjrh|Y2?pKR1Hku<6huK>TXvqgE0q7AS@G;8>(Ov@Ez|;{p7# z2@t*>#)K_5I;QaCpjJ1k&1e*pTt>f05aV)nGwt)|sFPZ8)Z`;DJ;!HjpCk4{^c@u zD|SH8xQIs$SP1_ySa1(m;JdMt;VN+46Hg#e#W@w6KS-^zB64}V^bLEfl z64xmZ08S`>el=%(44%}@I8rwo{43~6uyP^6StZh1oP0uTScL&o)j*i4;xKVqZAB23 zSx^+Dv9(I@?NxOi(-Fb^oRRNv@+iSUSEPBfks7Sfp<38^E$`OAi_FLN7jg z5`V?D#8%eHUvZuj1};`0!G_F?v7$Nx2ukd&!F4QKyu#t-iufzRW$aS%suHIr{+Q&AAnz7P|0o~-JhVXx|3M(ic)A{W>*?Tv?3CrG#_|1Fx{5Eb_0e`9&pOI!}{90XxPp!3na;9{u`aMw6&6j>3~pJH{!4*d06CJRkNQC*Mj#*EqEhu5AKpH!6Ve+Tov&Ru9mMH zp-!>FX2TE+sZ(*JIu-1M;p$W#sZJ$hO)}qi_l2-={Fpx|8--($po@x89Yp zR-krm47E*!+8usg%etPh3!e@KE#Gj4#T%7RZ`e1W$B;2q9SOcF_G7^Jx~a93xJqSj zpoQ3zm%W^L5~}Lg$WXUaQH6gkS1@BG|B$zE&c#H_kh2ZKsG|H1?NecL*^l;M}l(Gp6uTTzUxb9L8rMc!Rhf-aavnj;*hs>^1ltU)hF)(4iW2uUd z+G1PZgB}pKtHSZy(sl9M^BUu~ftvX38TfXtQElOe@sNq@T5*^cv+qbeq|tWxkVe~( zkOmwZ#4Ttt&K|>=GI50cDcqHK{z$oI1bRiNM9jYr+jeq5BWe2Y36EjtqB$O2Ne*l{ zYlq)eSy&5@62T3uj}F~}IwaI_CR|pn2LL{W@qB+a|@neS(C^0erZjM!fcM)9VUp>RgVj|qoP+KZEPlUp7G<`X0 zd)6U1B_c2j!J2@R;`+c=eifon&=$>p{xK!`cKt)(jov&{n5}ptsg*}z!dN5zB)G-s zo-AuDaF)y(h6T>VvNVsF@X)eYNPAfrdHq zj=UJH?`*>vjDMBZSrU^uEhx4HtkXk0ww3rk1Umufpc6U8EAib$)wzMo&c!~ z7GRr+13+>RoKqVz5-0Z|tf7GUIon==2wsd$rXm;;XQ2#yVm~SP_b)|Mx%v@tR11!U zf$>f3x|3;!iD=r8Z3f?EUs1;4H-ijj8BzoT0^XEyxaA2%QPZrwN)zA2nJ;z+QB-sT z`y2xZyhE}Ft?)HOt7ni_2ypq22Sj@knnB~$N`!)#D6t)w^NE0HDtk`nG{agAexE)j zT?#ky{DU?z1u!72KKnI(a*{sqmi*rMRGY|33Z>#>S+Rips=8rWG~UqgwKUWcjFHNo z<-i{UfbWXeit{>sUq^ILp&J?!@^2-?_c;R ze;RKy-VFuthZ$u&*MFpMz$Nz^J88ZfT_tMAzU-11&4AAUB?^i!tR)m7KTmB$#0PdG zzW1tQ)@R^R_CAYX2wR08_kfrJn`a+pQK52>qGhQ9Etd^d$~@?uRGf~m$M`WB9Ckb4 z7|hEAds5xxq2SAb!o&$iW|L7JNPq<3AROma+AEV`?3Jm*#te18m;*M`cjmk3yPY(( z&$D2yM0_%IddA^aQMjp$1Cm%_NFD$%W=K=E#D3L7C?pk}${xlv3@Q=moIqPDDq=qj z;jFZVSm;ljp9UQ^AnOuhFXCN{GQJx=2W8$tvt02miYZ>YA>~|L$+fP+%0fw%TF^CX zMNM0+F!aC=$_@N7DSjPk=?$0-$;*x(i4*LL0NPr&Y3d9Of1Fm9lp!KIz2*l=(o}wSXRr9QK9O^h1>Qb85P6H0~ae5viiS>EU77 z`vk6RE|qyuUYd?t^0Mtz*DZV9=!l(5JcOI(94!>7&cx5-N@P#4fqyLSM5T-hb`aAVnIc^Umaxcw%1 z>BqRr%R1=k7TJ3muIxo{zP(UhdK?}WF16nvd+B$J*mN{!|8dzYd091P6ZUJUl_`{0 zATOOr@vvn!;*mMB_bFW21N3mUywroj@-hk$*z;u^E&va{NDniqKK*d1eHOYxw!CZ` z+*tERDiH{~@EklKO_`w2l7gVkS zpibbjoA7BuTC>VQFj%$J#lO)5%&EGNb+!Y9rIxVOpL|XP^SoM@+RQ!xc=U}*!~qcD zb9%|*`2{&sV|sI`9cxeUKx~pO=2kIx3ffkvz(Lj3yXD~(7i-b`Z{?f5f|E!&LUQWFz7+J z>LwtC*q{RFMM>*Mtvyr@OHQ9K_>WkeCIVD0XlubWAiDTuJyY;{ zFwxEPL3AHkvVnBxSqAC-Z_s<%_8KF<+Qm*gm`r^hXNfC_HTOW!!Ym8@@vlyc7`#&< znu7EoF(xn|F+LwBgnLQ|yZ^xn^pmfUzbPS-@*~MNQFDNN$Az2T3>0pfA`TU9%1st- zK9T$u;pQz3;R`SYSi{;3&Y&&W?U-~OC12pz01{5F*5`oqb1E1bz?eKApcSF=s_xH7 z_{DBl&KeYN25a;TV2$Vi)`+rxs?22`6Fjl<2x-Qa*EA82=M-)5`|bmU@r_@$ANFuC zk9_)5QVhyK2656B08$Kox5CGqqzV+a2S^x>^n+Y5@MuvrBmyeh#PvG;g;vLJhkZyN zjfL*`jARr#9bbBYq+{Zb8m13Xfz&t7LWV~gAFLao&<{`ZxHcb5aBclJn+%N}vTaQ$ z11iV<2WT8fRH4F1pKY!l`5!jF4HW@=koN!_@4*HHxTXLGM?I~n;?ohd4G@M97TwYi z>O&Ny%2sP_2E(cNlu6w3K>3b_2@!G!UCFTr#S5n;_PYouthTXPSR5Kmfq&psHbi|8 z1!%vD5QIwhF`sW(Vopva(~%*JA%2Vkt8UPFut8)I|Nk?EJRowErjW|AE=~bhwxs=8 z!+J9Y?+XkK;(eIRf>r;9CY!(~nWR9Hs3|yr*4P>lMCKnerS(UwZ*-|UxGlktyIUKf z`veEU+!$VEBRNCdN`oEPULGkM=;nTLC*nk8`(cu>9aC*EZ6@cVb2aFVrRv(mIwQEx zSgPh4roe%Z`+2C{1;(uH#Q1Y4e@EFnA&Q-9w47bXyad7B^?u3 zPWe-?Rdk@y#Od6G`=osgE;UKeprW|-L+s!cIyB}Ki;>aybf$ewhv-7s7(Kvu68;nn z+s;%NHta+l%rlrO2Z9{Pjkda&#w5pS(*VcGFpyi>))*hf12>1&3p@lHw~hiK6uO`g z%m76JE;Gy}`{7Ek7ryh`MuB`f)j>2O1IG;|-Xts~IL2c9q7AGbZs94nvW-|p8Z7fW z@O70~Y&0?1G4#fQDmL2iq>X7!73;?8@c^QUz=|*reJtaj^!jLIiGNPG8)|~<8^I$O zZEhz5`H0|&P(H@aS94xK+-QiB6aijjb8jxrc#0KTFq0Oyx%YvONf%bSQ}8neSR}^} z6XYxIbn!DN*m!_1_ZNGWgHgQC$L<8Q#V2Xj7GJIWY%Qr>NJI$!=^6O2Km8mDdk_QU zXE{~ph9M9oFA4cdVFAUlN>GL%dXaLlQ6D?@v6b66op6*}xv45hd{hS%DC+2}=0D*e z#=XGX|2}@{Mmco2abgdmnFiH2!nuJx!Pz8pz?^u^t-$|a`4Hbuj++a2r77Hx_Q_bG{oXAT!`gRq98TvFpgF&J@`k4wbM*6ZY zZC31mU)eC0KCVk&)>Y$E^#=Ns@2$L>!8+FPQHOF7SO_5XHw!)j7b$%lft-;rHidr- z{Y~gr<9Ap7fLp;EzOzBEBeRDi#va9(xMtERj(=&7KQ(g{j6v>ZdwTzR9NFRAfuD>a zp0B{}wxi|^J}7oS|0eW6_W18x$d-ulCfT4wSQ8&Lsf2pz|G-2HqV&h`_-#CLVJiCv zkop~X;{_zJxWrMR6pf7Co-cvj_{Gw>-1gZrEc z|B!TQ$`OU&R{T;^li-K+&Mb2bivFxlQYb>k4w@Y?LC&H?4?@LUpy zfF|=pXoC;ofz3#jeF#;?87?vUqh>c}qp^5AkiR~!eiqh|V1)%~z?+$1Q@a~PX zF#!&e@kQ$Z2NS+B8}ky$F&tC+=8A}E;LvTx@CVcd`Lte33x0dAnmzO@Ac8xh&;$d{ zKz+B>yE7#AkL~1x)9Rff`#!(}`xJYj0GOBq2*}73#B#7oXM|E?YuYn0-x6zgitPPw z{D`vFi{J}ueG)qkc%VySpTTy-iuk&>0(!CMqm?#R@pXIr^hK&!IB*;*GlEx|jk#d2 zMI07MIv*C>RF#L`hOEOnDBw^TU7RNgPrk5<9Y8sO?8F&fLN?C3f5}}kXkjDN9$P@U zf)-1~_MI%+dLRHEuoDb{7-JbUS2Cos)q$NA!UOHIum`p!kn5#~I2L0wd**MZBJ`6s z_yrcyw+VM86ghV2_iOobsd2!Ioygm#Q(3_Le6+;J7;pQO#ux=mk=tYF_tNQ9WAV8a z8!2Mw?@L0z*h=wjB;dO$*t^(Uhm9q$O{wg0P&NhvXK9KQIBSw79U1=OntyG^kzaEZ zUL`*d9ot(pPalRk#HJBYZa9J&)SN1@cehX&LaKjkW=^V(6+%w#$tF}`8jWzA~p?JP~Q@?#Oe%F33>SeAy2qmLUnzSS$ zVFC9X`m?y}<{POw9TbJo;7E2^=*AbZm|4ohmGxBfb z|E?V7pD0kx|Ea_LqxVn)|EvCadhS?c@$~#+af(OJ2A1Z|rf=U|GSQ7==31RYxkPgB z)f(r;@jSc0KSH%Ay^>6;^pgK76V?#aD@{1qicEJ$GOB5yb7x@Ih@FX}ou@|^v@+$)i1k5t>wa{t<6&yn1Z zuS?A#x+zU55%1sWj{O2m%kR)B!|HVO9bRCxiT^~9csQ+}&BdFbf(labN%|Y8z5WI* ztbG{x|5$q)_^67je|+y|H!NYpE|_4XK~`Lq7{J7rN=Q;SfrNJq3GX6`LJEk0$-RIU z@rF$_vzN8B+FxxS+lpvQTU&kl;uC^mULXnh7ElqP3JB_~7i%yYLO}NSJu`Rn0&Raj z|Ia^s*gJP#&di)SbLPyMGv`k8!!AW%>^@)J+JC;Amy&HonWrj*JehU$89-+Z`a~bq zR#m8qG7l7k`n| z0AFSZz(RoF>gvFqR0Gbv4)C92HnA4|43NTF?poB~vf(C$8R}?MJU^=wO3h&1Ra7R) z?WHCSLX&EB^fKgfZop^5EhN7={7c?3ccYpjB| zCJY?L4f;0zJ~gDFs!qMED6?TMYYPnm!d$!#d>dY&XoM+aIAAmOmSi5`+fnBojk2DS znZ>L=nw$!v+S>V(d>a5K)t*Pdumj%Y>`4walQo#9jUq?Ze(lPRe0QAc7KDkm+#YAM zMU#Cf%UTwIf(#T_>&qKwsf)Gq$e zUyxL@am%Eq&{^!3Rw5dzvdSfR8Uw5Ls*6~co@G_ZymRu7OWo+S{KGwdlv=+Ml~CZI<7y%4hq(hwmLtW^_8cx zAI1Cxn3I3R|FM$1A6)OoxRoI?v!f%B==D@lxO=#bnGP^~kGN2B<}jl96X-ZNasq{$ z5$@jvl5nZXpaBdBPXY}J&L;U;UZP8Nv6g7E?WdUPL_`9IZDJwVg(gLr40Dr+x5=!M z>|)DIR?p{Aas!Zk)Q7ZIa26eHvxSRo#*s_di8_FIND{FI?HkD~Y6$*<`Hk`|#!Q}- zkp!vN-@lV*uI(kyL>|K%{vxl*XRqS4p3=DqX87hO5ufdx2d>}=(z?iBLUv*{p2`RD zx*hYP63<#9Q+6=x9rbQWvYx7Si1xoG-!!{BAUfZ09kKy~#F{MDsa^{<8GOiXQx|7X z@oEc0`ELJf)%k9#Bu=RGHv-l7xT%=LH?6ypx_=GJK!F&FsfOK<~KIVF*%QgKbSib<84#F7tAd}vu)~C zwIsCGK)wVcrzq3Y6T@Fb7o*8k5QKt6))ILI){MolF76%M8u=|^?2gdenf;M`mEnZ{{ zXd?`}J|)rHWJ@&i9Z`FLl%?uy+*W*P%lt@XE*kJuvtW!KE>?=Pod^hCTQ4ND32}T1SaCV0o(0smag*6U98@_ z`hMT|8^))n-*ls|SX(uE*7Ez8`pO?HSC`&D##gkuOkKWuRk?5c>NO9RE&t&%)i-i{ zny=)+dlr{39p#(6>fSNF%&f6vN8gx{apM??x7aUD{}059a1r~p_|Lw3qdTKNN*hq*L6 z*ShmU3zYoor$q_?RQ(R6AWB>oys%Im7`$+U+CQ(U(w&aH3&XGYsr)YQfq;#jP~HY` zYTw*{yYPoAMFIY-Xq-AK_=;$~OF$Gn#PuZ7@w?F?}#csj` ziT91z56Z4`@>D^M9EyQ4KMZzWuf7oMyiNTbYs$;7IO_lq&*mgb`&msIUievJbbGLB z4vay#{3?vhkYPMFm>e@7Z>i`WXvX%ze%<(PQ9L+kXR8j z+So+sZ`wqSjYEW!Zv}mTOn!+6rcYxHn3;{|0QiDNu8D{2KdVRf{=ph5Z_^w!2L;a9 z>xNEooWAIe9)8+XA#g((uD{JzFt5ON@9I_bfB7mu36itfCq-Z#bn~hrH~yhK?7+(V z)%XC_bk+p$s46(`sa%6V?S=OO=sLd=qXx*%9rl9(+Y0&@Cw^_1trKXrHq&gq7Fd2# z;MT77+iCLwUP7=lPIK-g#l+lb@>nFA-|MM#Kx{0Wln41c3eJORl~$a1*;88a`s9Fl zb4RmJyP>1mt6l$>G5XtjD1Kan+OH6j?l#!Sf^E0Hw7K{741x zP73npkvUw&Y46a*YXnx*4A09VrbA!c6tLB)KK<1QGK|wM*I)e{frZ*Y{Z$hI8xRN} zHr9#4uVX3H$BxtD!gK8*d(J}Dk#mCo~#8J-3+8*8dfgE^w>#EFI=@9 zw1n;DGI2k%S-b+lHdfHd3ch9q=UG9U>6h7xfOg`iBs?eZYa#GOQUL>Si5+7fG~Q~5 z)AMpavmd%bI&VI@Kh{>hn8h3MtZ=YV)q)zsKYJIytZ)cBXNWraOXyVi&d%`cuS;2> zD_r#o()m3jz!?5#cBkim3ce2Cd7j&eEfiiEp54X@uMJndKzV+EJVrrVX?DTa_N(^_ft`BXlZjHa8ha%dJ#%cY)`R5 zH!F0=mNyrQ<+Qo*Mxf1x4By9;EF6pauFtF^a_L?tDV_di76WC+#89YCTICw~2WSkQ zz0xQ3NvBP0cRKhNtO~pxn}|m2YFxl;O}0KowCwhj80Ov;?h!pSE1={qRD6Qt-2WVQl+A zPP5W5vQR7H)!V;wr;hgUHHgbR0A&wpPXN$?HPc7ttwIG7q8hNx>S*wJDpNq429#b7 zrWk?qh)&v?0S47f)5dnD^(sWrf~%-*Jd$*<4N5`yDu<`?B?N2f9d)F#))lrA(to;( zux<6tM5BB~vn_VjKwTJ3&G4zikPn+VKM*D}F7*3KdNRT;y^^+F;DVE=_ielaHz_g? z5bLhB`7lkQc2CtN>S zR3e}bZl2&zwIi2cLc&Wd#X!Kd)x_Z^k^$^@Gz8SsHBNfH3a^0l7#1d8?4vD?7z}9c zV7aUaPny9fK7~%kz&MqQz}zv~qtf$K(Y0aGmTP*qrO)~W%y|u45s(5z7Xd*@#X?<; zt@eUOqYm^e705nz9DDavWJqB`iJZjiz!soR>7~6OeI@iMkhqf2Oa3L;&&nVGmdOT}UaK%bxZVl-bBiTn^)|nJRn$VR4mo}EjtEaw2#X?u#+AO=Z-ik)bV3iNH+OpbkVXEo{2V~yN& z2SKP5We`W%v>WkGn8Z5))<%#7)C)c66D6n1t_fYMXe=SS2#I3Q&|DfJnn%5{{kKc8 zEvX9Im80w}hJmr zrm+-bf~Qhxxtra|?)(~S1{oI9wF&9Eto)JK52!tCzFG z0I7fa2>%7@rg{`i2gq)FwG`6v-W{HP(zx?$V|FK{eFCHj^hTnWsYT#AQJbw|A4U6@b8=G1KFi!r-c0na6NSnlKvFa_I116}bj&%mSH zxl2b%xG>ItKK&RrH=nVBQ^+5D_-otRTa1FvxB{+^P0-dD1*e)E{SxsAAV*e{wkSOP z6m*zf)bLT%aG07B0c04nPr-9; zA{gv)t9ua33QnRG1*c@yfEBV;JH}D9QA$M3*ijU4$O@iKccQeprB^$iBjn0Lp(Af>1N;;L8xjoKP^&$ct4G0j;mTWOn zjD+mhwFl1ZuV{>3xNza>4=PUR_|p~`^Bl$$2hwI=lJ)~*p39ixLR!`(X(OOqF{ZeY zHY`}@4K{c$&Y^C;V}5#Fsm3X=4$YVN7z2o8r($A<{o?g;Tp4k>3+JL)3MmLER`{utkM6}H!O^>IU7)Zs_OaYSIgLHWR1urNXdWA<36d&FY;!X$D2>BZ7j zldv|=#?^kbnqGPUD%P*ysTAXuq@O|)nwx@O*0|L{leW{Y-V^Lp)Lby~q#`VAkY~A6eEks;!GA7pn|(o?=_b z^wc=&JBLh=7W3TK*ueO5=|{^p=6j*Lx|z*)@SjqXgus_#Jm9G6*f_<=lWm4(`V&lO z^I1cw_TsQlAv}NFk(cODuM%>lF^II}Gm(eoIb`9)SYcy+l6h2fffAl|UPuQI zu_z0R#h_Q#z^?;du}5_Yf&g6_3DGHzJeCm3!=*h`jwo5cH~?{JHa`6w@XE!>fP!?A zJ9t)62Vfyt)T10#v?YQy?EvT~uK@LuZW3D4fHpFCHc?B4o^v{BIltI&r(wrlBQz<> z?7_1`wf>?Aa(lb=n5^Ya3}$2ZyJ)A3Ds#+WWx(DBcMlZvDX1;3M!l@w3?rB#gU`|^ z3i;554~9G=d!Rs3Q751w-2yz_lfVts&4;^OknZvY7u78TD~@pUx01~g`g8CE=2bBMJ? zE50s;c%71%&?gTFKOVxi9Dx!XV6b;KALi|-7qcr4&18o`F+p@vY!7=+5CfD1x@~m! z7)`FD>C^D61N)$Q?p;P?TDpzYHkoxhNl+`@N-xr+X`4&L0+R)BCbfs2QdlD{TE6ws{f3l9TWoO@0p5)n+`A5Ae;-H_#Bu$WwuaX6GTiQc^T| zJ#z6|A%)=bO3F4rvgqeVsKa`8vUU}o-g-8?Be3BOj7w1mkme;mppPA)eM7+`0rODh z0rlO0xqDj+phuH805XYdi_voaeN@XDN{y6lK2%W}L>gT1-;%dIe$F#n04((Dw~ zQyK*L{`3|^Wv9jKe#-HN2sTmhZ#6}q1#H{iMa9@;^sgZfK)Yyxu%}Au?L#^Y1UBD6kVt@2%7)2Sk z&`^WvC(|^8hW-HmDJ3RTNwZ~6<`>cAl{EgNDWA*(=s2Gz0s{5(c4)g-0BtW&E(m8h z=6?n zy3RTX((vuCnQR!*E6#yXWvvGQh>?p!p^y2=>#+xyah!xyY`Brv+)LA`)fmJbp8{&0 zH^%6s`38C<80+sgP&wr2SROp7#LruG%+*U zvD={zu0F0G@2Y-Ne^U{*B-N`Dcj%u72nXMwdC<&8)ud2iqQ9#e2W^h((nO@B1MMA! zZXb5_Xkiq3qyDSh*80>cL~%sP_slx+jyCoD4cM!W8tdI2r}nS*2I}{@CTs08aV*ZU zzqZW}9*PwXdm+I&QL>#=NY^F_{&) zSdm*z8C&FIMTkj4ObRPX4F`PMhv7h5IN%i-Wj?%#s*)u%HPL!H#nTczttQV{t@@U( zTCM$XneYCk_pdH{(5J5UEnc~D^}UPLrM}YTD{)MvmTC8@TG`Ta*w=ucKa&Xo$=@k( zwxbQ!Xw}zHOfdI6!Zvk+&>-`63_kc}K7=D-(=pY-;@Esw^LSGK(~{j3NTNrueyC+m z!-i4D;Dc_P_6oL9iDXqmb3ww}26*By>ZMwmoi*N50UKY`g>ArZtgeU$$!GV~4c$fU zQkq27nS0TW5fG*W4p9`x;{h!mzb^GMz7WRldF&8`gpXK@n0nZ(f0_FObg2AeSTKEL zO@$c07HSyt7glUBNS-s0Nn{oYXZUM&lD!qRuu&X)(rSPaTmWSQ1)Bp7Oa@!e+rU0= zpgn6}(W|g)L9Zd3nVs)=1VX&anCwbV$ZC1GpWrt08})nKUn=&re4)g%nuqyYY!tcl zyWL+J#jsLx06eT~7Q_}IxqrrtJlH+qU<44aE`{vl)dDz&)#B10aA1@mTUk;KQ`lFK zh9Gd6{E?f*QtqiD-!9!&0b)fb?uk|ML#LpEH-O)xRRlI&@E>{)Vsm zp2Uvb{j?L+pXqPgs~<|d#6S}C7qgG5C2|&KQR&#PWqqJJa5DO3=nl93dR+Bh_Co8E&xG;DlQGa9cTU>(_2a-RGr~TK68suX7V?n*_Tjz**q1KaF8C%T?P@zrl!#{ANuM2c)^`rDb=V+`g+Bt z4XmLVh+{LFdkb*HEoY55&aMmDV-T)}mx1~a6A+Fo(zmKQFjQ;-BM%m>5Pbnd{t5MF z#)0Zteg*&S>|=gCXbBseXmSRvw8!`_(Q52ltU|@HihTd7sRO8~I6$wnFK7&i2F}E0 z3Oa@~sbeU=3IZyuu4a}L^8;XbsO2B11*Dvc{Ss=KZ&`mla}EcosF-Rd!w6uDuAY(@o|3{QxloSqP1_Q1h_idU9cq8129RoQM}Ut0 z%->*}L0~V=j7-+wOdw;pg^bHfR@jR9KCnpO!O}9Sm&H)@ee3uAbZw@)-#(i(}>TBKawy8wxQSZuJ}jPz<*3?qWykO@z0 zhl(9~<`>&xe@3XF^&Pf4>S!z%Ut&@5X;))M400aC8g>%lNL#diV8FB`jAwh~rn%30 zQ}uE`E*TT1=vM*YN>)$ zu=239y^KXinzgc4Vz7;{_`KM@M<&cH=D!Cs#RRcV++)XSF@7YcK^eq?1&yp>>kA;Q z`j72~100CsB;OTkDV8FYc@Pf|2T% zIWSvW(q6AWX0JbCS76TqU&`Q&Y&11!8$rIfK5H$F$#1d`qNBOgcCDW*(8%eV8e6GV z%}xSFiM;??Yw{M-2W+K!vg*r6W{bX*e;*&1J7I@?<*mTM>lrqi0I$ClU`cVpwjWAC zcrcRQ7nDN*{yUO?8id|Oq>KEq%!KuxKWtt#r7`O5slRwmbc6C5#y)w3|%)#obyMlG`xs<8wQ!KxDTKp=UXXn4ipfo9V^EDcO>>sP~Nw{4@ z9tJ?l2!MzC0$kS(kTMZKda6m|9#G1i1gM#y5(6<$Uvgp&{s1!*sA$Bx%yW@z>%xa1 z(A44BA@e}`F&rBXqX?kxnK!LORzb=QoPF%$|F{8~n1W881lLnMiWjKoX?clZ2=JG= zut(nEpk4GZQXLq{q^;Px<`*Ea(a5)L9tL$QrEl}nkBWq?RA!r-e%9l)N9Yp7?iJ_V zE|{ZXEoP7+u~!cQl9A+3`zjEgqJaK_4Gw7a^^eaht>{Z;)Q`gseu0*e1{_zrGwUFi zU4he32eU)l>SJR`=PK=!aV>|ve=&_C*%i(i%8rNcaKOA@$!u_AwnK&chO4GDoQ0qsg=I0&rlry&*u}a<3OWEp)WjV6w4bL&byL718Qrk zxQf;_ng^o1)bAY(;>t~G>6s?GO&it`XIE27Af#KCXeVgr(j2FwnE4OnabU7`#5pty zdqvo*wTkIO8Ih~^AE+!f)P>$F2dnQ);q#Cr zgs9k_kn-bFUzD|4>jSVu!X^JJBC)2-wBC_ztIXE7Nm3r5^`aTe{G4FtyX$6#mkkJh z(i!~LTkd=nQXp6~2~AB7KV+}$(L(Z>*e$`_06}B24)N7fsUt6TfNT`)z&w=Aih!Vh+_#^#b#VNr~n{gU@tVpOdqsf&RQ(;IrIslF54Oxx2 z%W;VR01FchoR%gR@T@QCx@E;~Di7kjqmiG&&cQsDb!ctB8d6=D|6rfyUChc@XRi`g zJ7N#AK^`DLOK{ug23hB2oJu#58jd-GQummNem z=a#@E@hNl?7)i`Jw5~t#7Ezw3p$me72pXCD)2=`r3AuMTcpjEf*FudW-W)amALs zo^i7NTz|MD_YV)AcqDk-6KpJ+3>&K?@OH1b;VTysa*tGxZ}Z}I^0C|WkB1``(i~!y zy85#Nn8Pn7aPT-Kq~L!l{`+9jLRY#z#EuMSpBOo-1(=_#KHHg!6?a|#t@I$;g@G7m zBz7CgKEz;k0~_)43`j)SOC8a!l|4-Vg6KYgoZSUMQbdz;Fptc4MQm0}c`|E&h^ZV7 zG}~#WV5Q7zDfTXd=XN&ybUc=Hx^h^8Rs#>wIp9p(qcE50`0 z-6`5B60G$K44Tj;?Q-cvARwl?(4BtINFD_Q<}>kN@5rvPLqr2c@<>YB>c=mJk8ipL z3x$Z=Mp4YYC7iEpqddJ!%`6tuFem$q6&>;%O_)48X@}G~!z`k1)lf@_-Co1# z9wVpEDZ~!wM4==UQa$_(fMKnnmxJa9d?e*PA>+jQB2WS_lY+U_G@F{0c?2gE6x=v0 zvqN;j$cdkeD|q9jwQ=?^O5N~@NaDA)5eE?6lIkmHx~@hX6Xb9Hz85`iBT|elr=(A1 z4c6@GCnrH8|2<6;#1g@+b@F{+!z`JKSsA+LJ_WWbT1qo%s_Nv559LdoKES@+pk;Ds5z1g9lw^@RAfd>jFmmq=LhkQinsaOoK286-WQkAb|C4wWj*%Nmlk-aK@-;LxSraxT9HW1QJSfy|%LcrMZJ` z>(D2ut&EYEybni*XkjgcGV@?pP7HA!a9msj+fB_r9T9y-gT{8T<%-Ce(AlMN_D8d#Y>jp{IR@O0|0GZ*>Y7~N^mbt_AOqu zB;nr0t5)HB6LS&m(Uv0PckL67M9c19ywbON&C)VJ`cHite^H;xmM&gGP3n!UF$q+$ zb-;S>YHj5bA2sZrrM~ajqE$X^)sm%UK<&DV+5$B7;P<e90RFia&E0VATkOpSxYQv=r@I zbuXG|jexD7a9W=x6ik@h=RFTiS_!HI1^ln6vS9qYKClWV^nOpU73BBr{(o+K_cXf* z`Tt>(73BA>&}SPhi!Q~4uodL>O`FhXY$P?VDO>%+vc>nqETCs>yNRsV45WGaoym9k zs-^1}->dr8E?%j@uHfIZh~Dg>prr4xln4S`qTRp7H?pK;TtP`u+IOAOL}RFX`4Ty$ zi68x^RseLbK?L6Z1)h3SMxWW!x|?pRrBsum#C@o{levv55-~L7`2!wC- zSo8qx>U!s~1YXM?;HbP8N7h+3tt-5ye`siRO63vFkA*pvb;4?92v+KkJ(EK}orJ}) zo;#{%DyaB#+EDA~GE`?_Am7{v4dHt28+MvrUX95YCF1r6=@X0>{3-O9ZZqz8=(&rb z*R!dfn6?3H*B#K4HaRI?;mKI%QNwY*61PK1NO+$#L57kG?PZ-ONN2yfVG&G-LlD;o zpduWMVC}U7(CuReoWPL10FGBH;gSN&Y#4qkdM>`tgmmDBJ)mU>xKkfUD5Z-DwSNTq z*fFY(AEo`ucY`1cQ>ilrFx*R?Kr0Q$aEJSTQe9%xa1$ zvtqVW%$*eTC%5R*ub!cpsT4EB%JVeEWFZEXDzef|RuXB3`IVIUI?*BHSGy_3O)>?ozJAprm{-y%# znLTuN=c#%gDYfmQr%>?Qk+K8lZZ`H6Ypd@Xe&#I1*MYUa7Y#@H$Jplm?;9klQu`MM z_c($VCT*+~BBNA~StRax^aE6y`vgd~e0VO-sX)1ZMNCJ*Rj`jS5UTwt+8DVN?ejdk zjq-j=nJTG2x&KE5U!)*Vi=s4!wNC((k$4nXJ1_Ugh}Q0?Ednwk?dU@;&fJiX&|dqV z#5g9011Yu3LU%W7qZq%)vlL3F&{Gup z2zeuqQ|KoYs-(~Xs`w!ay&*;%kRG77$Enmk6dFgZokyYJl5Vcx8tSh-NI3$CXS{YR zQoe5poASs^&}@vKfc?q2YP*MIW-Sie2Al-Y8$w3ixXbcvFW~=Q@&7ISuf_kT@P9Y{ z3;s#x2e`PFWT^hsj`5CoZG{o%ERRNS3wFkP9=i)967^TL4MxdLz*v*>Zo!X!HWGBw z%6|1=;S{ilpiP|7NHrJA62EJTeiHC4GQ(HwLQb!wwBTEfeZ3W&-E6#q zQ`&5#QN(FPJWdf4tcXrTfFNvr%n}CUmfrhyOaEa6W`X!TF(bcO=&=pgBXPii5*Ni%TK6CH zf5B5eQUR_=#Tw+Go2q^guov`#<3{K}9HmAg8Ft6b^5aJQS=`Yd;M3})$wR7N z)i0E56R4hms9=e0Q0zw`}k)vuzyH7uYgf2)|IG9z-G_ z{NoY`h+l~o^o?I>Qp?s{(y}!s7ajLhrqj%#UV9$*A$W1mPs%w$=a~oD;imDUef(~W zu4T`wkG)!Mc`}r|VtQJi!MEYS(1VtFKqSuO;Z~?Kex$O(d>bO)&R`*VxyQCE+qp)glyN zZK%R41llgOJW20bsrknhL6s*GbV^t|Pw#pN-wf|sr~N&E+yR+;h4#BZX~k5B4$p7M z)UJ2URsDL`3=Phg^r=oe#Zt)OqY!Kd5ESr4vN)m=kR-lKW|lVRgAzh1xc#rX^>bHi ziTV_W5-`8O!)2b)&!uaFLMt5ln~rKzKk;q#0!P5yub=a2mxUg3bTm7(cdNzcZl@rA z2c&Z?zIwsvfca-|4Cv$N{0ojSV66Z%@qKwT-<^T1Hmx0Pv+P6YF!vx%$&P?!YuA+q zam5DI&yJNEgW!di|MD8S27anEnjh0u9S1R^QbQ>P_fE}fe*~Fv%Fd2a=KHP8$B_9S zS?wF&rVH?*fb1^prKGjddo0y2K61~#^7-V@g6Nb< z)$^6CueA1X(nuKp^_$dW&zNF<6F17=R6r^^vOW?g`owNw&jQnqBS*tgB#s& zWYApb2A*v@Vg3lkDBDN+XFH#Uy4mY=ttdVZzgibE!=9~4!N+{_C`?nh6qDb6Uy?ro zK;g!~t~X=^st4s|7rHlmj3Y%%Fhy7A!UFi}$$HipO_>}T1k%=~HYpiqgtay)qt6`5 zV-A0$46`9TRcVUL)Uz;9s4+wB3Mn~bv?S!E4^HJpd!>{%D;d-|bglXzK17iz!`5mh zOrA=LI|2@ucCEgCbcW`GF}N`=CA}yq?QnWgYI>0`y~v+lG_vZzMyK))o0oE_zn$24 zki*3fgAb+JHr^`7{_WF>x9;$tPLtR#h%B!x;w zv2XRRd$h99A_x3tdMdx6e7Mny3lzqJPGT{sehi8$G-ni+GY5^S-nGONd=@NA?<(>H z_hE0ScNKVoBQfZD*LY9mT~2VbLKoE-DjZb}dJv|qIK?HO7mQ2WokqQDwaWA^O|8_s z)_W>RU9NY{gX=vJSRya+hBjj6p;`Y;%}NP2x>yRXgWu7sVVMUy3LVJt7Ufvzhl%0_ z@I+7L8}vRWDGYP)IXc-R*C9;)nU48SN7RXA9RG4;G~ zSZLrwaqfJz`;p4aw9ZlwkgyfFxPcI}N^i)Yo|NG2X^GCY;Zc#9UM zV6^v%4M)#tmrvEZN(fm=>k^3^iO3?uP@&#cUcON8S_8)+*sKLNl3P2_Af@Z2jiXgZXC zzPcX(9v}?%%yKwIrf&pN8$naH$SO3(^C&q?(Yq#kD(@G8LQf^RG>hyOjUf!a0kgCS z-EbE5R6dW8MD1TGfp#yLA1CmDj~NG+GGkE^&1>Zx-!vS9zH!t%F|0!urf7*qO|m2uHNh zLZZeE|Dv8!W9E6wBEFN~A*)d@le1-7@BA1tpq@timfq167yFa)3zq!Rmc9Qqy#G5u z@_~)s?K-YyzoCO{T6n>`=q?;>^QU1jjO9`q`7hXKS-&C10$5VKlc)p+0cFT}$@L!V zyg8R{%^8wO_WO0KpyE%+tc99s)pe4lZVg%7+_-tE(klqBxxwv zA5koB6R0!A9bYzV3E)aVLtwnX=A6$Dr39)MM4^49YqHws&7`5imku28ad^uF@MJufn(mvx4eM@Ft6j^|iN!*ZB-@ z);sHR+3nu6!_kQ;!7guEe%PJDZg;am;B)gFxbF{9hs|_h84{koJ&)0Sf3spIexv47&_kIoN3q=H z5!wiOlN=GU+<*{6J?SO~nm=?%v0BDn1=u#JOF&0wLy(*f`Yf}>hPGC@D+Bl zl#;W)=a$iQXnIkiXzpxq=Oie3q>mzPa_p)V-Hmj0dkt^pPlCZfxg@q3vdP~<^;<*z zFh8>jHFoDeWWJT1k^k5FbMztt=AD zWN*)DDu+Bal5h)-b+dD6l|gTsQz}K`XPmvy(#1=Q(k_UrYJsQ5oAwHSU`mj zAcMS=Cqau}z!&xq0v4RZ1>AyNesT(BlB?;+D)>)iw73m?3F9`wRt|#^Y@Ge)jbsYq z62UR0b=xTf`AV=mBbjXax00PdAOGcrC{O<#8i0EPpd73hP0*YP6VF64DpaowOa=2a zzX^mA@~bCBr)nofbUzvW5pIR`reBzW^lClekwG6_n-aH-9a#b0S$;%xuygbq)K7SMBQo7W+;0zX z|5im;-F7%FORPGwv46Oh>I^T7?x1JdQ2^*Xb6VLWpKSk5??Ch(_m|JKBdQSopRhLW z-|;d@8z`28-_v3tywL#R4V=h|NglFT#rh=*RgQ4bV;! zb8z9jg=pa%CSlUt`YvzQ{tZfi6?#3dIVPsnXCBB47bt9odj~phLk(?gP721pG5iFf z0z|zKAf42RsY?A6)OyOS?ybJTeY56#AIjPwtKbxqHPjH&g}*qU2mY(O&nv=3*ah%6 zXp;0|ShE&T;s0O$#C+UZ2YX5V8v1R+`A%bTC|ShpQ$$MjLH*Oyh_AkdViz>heK~w) zSRb2FcDX(_Yu(`c4kW<$kW1MY2!5V{=<*1=3>~rh4F5<%0hEL>$MvO!elJ|(stedZ zL$hs_2ef6(Olz+=r=vR?ojd7a6HzsKAz!QRc|W zT05OKK1pHPkIpx|aM5A>7|y zy*p2T!;_&N& z9WEXY80M1SG%pDb-3Z%7SQS`PPD`{!R5S?C$+%Y^H%3c`y*LbV$({i0vtHEe)_*WY z8_Yf?PtC_EK}M%Ej~6>V@x7anpdJ0w_Ubmbi?I1Dbq!xq;V+63z^bQ;L{^De`n({k z7m@ig64)hs0#+{+QN5=V`7fahCjx;4nlmltsrowt&|Ba%V6=4G z`I;c1{ox15GZn->evK^DBtJd3> z38EkUsUJmxJ5C}z`@znpgK)Fz)n$aFd(khOdM8pQ1^9EMacQ6}@%SBnss=9XFXjUx zA*=$>(TkI|k{vkYmTBoY#KZY6mM>8=(Yb7b4xl#UfLOmEVi>oOp*Y;bQbCqngWuZi zIBb=yu$@mpdqNqkxe_j%s&7dn=%PfBE*;TICTe6SMiZiIDV<>+b~ZZ+5)Co81A??q zXJ^yF{BR`9gmpUgJ+by~R2JahQnwo=XgzzBR#IDu`0#k;HG<1OA{e4x6t~P+qOXZ{ z@2fQDW@MG7EkGR&Vl*wen&M(P(~=3AVC2DLZd`#w+k%}gPmtUW<9kG&O1jxZhZm#N z;lvc<^32n8NY@$46|2B!?bV%bmzb~r0?OwY%$=gWd5Y){JI>$0M8YU~sz@^2L7kA( z-?)Vk4JMF&vtKSI)$Or%p51Y2kIu>-o$cGBv-;}}*^TO9)Iiz6i$BvK&)uQm1>Bxc*SK>0atY$z%@B3t~<-T8X_US zD3--5vQQjU-=#*S|2YCrG$UW1rPn3hug}oyvhLSk)9cFa*I(jw(zZ3-?_|ZbP3?Yt znqJpiuQ)j0Mnfv^XUy0}^d!U6wh_I_@RV&^y2FK&;Cb>%@yc>H;7JE<6IiZ};I^l% z_-Cy6Ni6p{ihmkEHRz+QVmFP=T{NTQ)cck!2D{^$bb+SGyP&2fUEm{PBHZkxAt)*& z2Tg=@BD9O)$^Ax68@LsBK1u9Fe6Iq#2Yfq8!{ru;YhPf3_1S~S^~8@`HtT&h^$MfN z7wiJ}-;G8Zfz&kc6~Exj;Y~uyzaO?RAS~fYyoRJmIH**PD2I#`&ue4r&w10%v7?zs zuvmy~Fdbr%1<^wB;Vwp!0ez$K7$SV!j_tHDGbJ4kw}TD+c9MV@6Zju+2QN6aAA}b{ zhf;qmE?lOh9a7q|IyYVi_n1L$2jfds;IaW}X{`!ao@`?c3A_<<5W)_bN5X|s6Mmsm zW2thQVEJVGsju+g_z-^G#u~5jkT>hXBPkn(v%{Re8i3WFJR}}RFso@}k2gK(qpA0F z6aK`+l94JgxFOL9_=3Aru?o--XLba0X=d0o4_o7-^&yrb_?|H@sfK8r(}i-NCy7w| z1P~#(%xjbc=PFLZys_NN+dLBaI&ui)hi8q(&c*OTZpXeTtpTS-w7g@(`Xe7$QXB}* zDDh^!xA6`k?FgqjLqy*SAUUD3C+k>K#ivoggICt7A(S8YPQ)(h0%ZLMdUa(dwdOUN zDv@Pqt;F?@5Yo0Ac`3oVe(B>=#Ktj&Mv}Pm20z@MxS_DexQi_D|0c_%v{s|Ujco2< zms7h2)5#U&{jyQa6Q)x=(RjSNJ>lE%8o3!i;e1*HK8{OkfRrY({&-lQtUpeoto`w0 zl%xV5iZ(okOa42|9_)h>x6S~;KuXDK*r?>gooZ@UgXhQOdrQ>lsoalXqzOOxK-*nD z;1+vqPgOnoXH4{F?b(=#@x@`B4LkBK5Dck8;20Lhcu>p4vqNcZprpQ7)ZPZkgWS{S zru3os`R=rLL`pnTUhSC+-x|x^nH|%iIZk^o*y+TFp(Jv$8XrjzjT8oTS$jN>KSbSK zg`Y`1c*$yf*vdr)b;z}O7Ud$G8go-gW#{Y0$rFhJCj)!o1Xo~VNJ&PK%nqQZaxg)N z$B&!`;2*QeV{@4+b8lArh9vEB^6k9Bk!5ahX#)&sY#z2g76PBFm=Vy22)C7vK)~!s z!{ygL+{k7-@^K@u*z-sC$%CE!;B%_e0q^Q9hWpLkm{2Tfk9g3RN6C9hoU~Chrp3*Z zAvP;+p15J&d%A){qW*4h{SC)^1SRI&&X~|TukUSFqweDTEq(JZyf{CaEBp^+HK@Xq z9ms&0yDwqX1mun1IdqUm|bhQ}icBUr-PT*JwNs6OoKH6nw@Dod89|X#a7qe2Q-!i!sCrOcJ!W$al!nQ6e+?DfKZU>2!rIGr&2W z0&ge_v8TdL?xq80ZenqvO*)nV;lstB2LQ(l;m3M%bzu}PXTB!Y#YmxQks}6oS;2D& zkf`c5^yj}J0%)1vc;--(eRMwGV!fi;?myCR!L_g*R->L#i*v463vV~49eLGu^9)^F zY%H{H5{(v@4SnU>nl<>Ep156y6kM9=<81=?uBEwN(;5KD`hI(nFozT&j7)=oHHp0` zI;^6@N73O4Y^8s~O?$I1^K9ymd`64WK;8cdFmM@`tO8( z5&ZqX$Aenq&y%gGo=?i}WB+DA0yq!;-;T%ly9y^yE4XX&jKbS(y~4Q`nrZ(eQ0T1* zoyEev|eV6szt0_D`{4 zBnuICEb~B<<7OLw7`Xq-xUi<+jO+AwfRK0zglvLvJwYH{#&?0S_mhiTaRwZ~AeCP| ztZ>HdLKoqw6d?IWe?|CoghZ#BY1ID@krP@HOPobdfFJAV9S&uvXAQzb=#8*~e<~kx zt`l}v<|+10`Y?F{PqFpq?0U`>FwEo|U&L01*fhMNTP4&40gvB{B*0K6Dd(?V0Q#FjL3^e%mr6ZX+g9L)rM* z3QQa1m|5I{(;H#_r@@2z8mw)s(Y!O*iNm63@=JI%zYKPMiz8h$EgJbNwWIUAmcyUH zYwd6FT2p}^{vf@cr`KcjO8bvyC)G(awb@A(KZhkFQifM-mgT3O!Ud=3^8u<@P_+cH z?CqtVaZ&>64}XOPxCaU@v~5WH3dU7=Y(9*DOEjo78`KIfinq}5A(@%MqvVBk%Z+&2 z6~atljyvleEgqNn@o}{5>9+C(BqoEx9pq5D6#+6kFyQ;h1=|B-wk>Oa`D)gh)}p*F zzcJP6^#qH7cky9ZAs_D$!UVRKMEi}#T9+_x3z<(s1f2~f2s}}g{SuwHNY705GKjZFW6`b!Hs~}cMH-p+eMqC zC#-E$++Zyrx1FS6raL%1T=iCQ0c;;x72h@0>dssLKzof%4_qeGcoBZlq zZ~HMdUdWx6R}6t5%rDQ&85ooHP(s@4>;vuU7=)prUkfk3Clt@i?dW0xt}VePEni84 zGpz100)AONK1*};&Lx0HCxU2PqC6hO`5#`SeuCz>#H^^c`$w*~w7GUb21@ml@rqhX znt-(nOM?$X&YvMJTDVF<*8Fieyp&EXGU)7k9F)&4Xarzzez5{NEy*9;W5EMAzUm!()>1}`1QZ)E%g-ROl)9I*17~S8bO}1pizYQ zO+Tlun~NW4FzJ@HjW7HNRm0(l>d4}nNAML{2Tiy%4#L1`T{8p(VWI^y7xf6VlWz9U zOFiCVX1K%UN)t{kaRwHQ!z2Ml* zTIz>Ta_%(nQ;^L-yddpepe8&|F&uu+i;essw!y*$OQz?=geW3-ngQcTvFhX;lo9$ej; z2xF|QGaJ5<9&Ml-n5Y2zKz?36Z6B)0J_C)5(3}yHZ(19yV`LWeI7W|xV}llQaJZx< z(qS&$Y(j^$ObT5C=L9yWZ#^$_0fZP7Ro$BPpYf+42 z^>Lv=N+%No*c@}-)afMOBqc@p&>ez6QOU`jnRL0?B{&WZ6dpC>T* z!}8jI)wz|IK&l76;g*tC{#M?O_dGPam1oHm06+?@r;wI$nJAO8=T?2O_C~s0HF78M z4*Grr{{Xen8s}v#)AQVcN@Fnfs+MEmh$VHmsf{m3vc-~Ov6)|(|7~#~ zNRV{J34Np68N{BhrLk|}e~F;E;7I5@v83_TwkGsE!}B7Jo%V728DL&;q&6N;RS1rB z-G5zDndC?VFHOK$-VdEsPh-XW?B++rAPvEfG>i{BTN(sI`W_t^+WCis1aKr=Bjo!L zE{*Y|w@QPU!{29Z=}sz-sgEh^HwLmc2%?D);|+Ws=RA4MraQDVKm##G5-`u;0v%RS zy1}SDMGUTDE5Yc+Kzh!jAhH1$0ikR6go{uJTq9moexnFqQyP58PAtR_oZj!X_w$3Nci?Tp*^ zM@rkDAGEh{Vrlzx{m#=DS?4!mqjeOi^x>lR=jro9NRlZ%lMf*=|KSfDTV|{tgK^Mv zIdRu3fC^_RDJ!sZJ|!l%MBP_0asLWhsruYDP~}(B-v^8NZ99B(DB5$y@8KS#REYYo^xPyH4%;@7jA;oqNyOhacI)AG?4a zW3M?zV{YAhPdDWw;YxDkbbFxkS;GHIr@5DqnrfehPfa^df4t;2aic>V&2k+-h!emM z;s^S1N^BuBSj6I>mL3}jasEJQNioc1U@!pQEz99sT8KMsOUXj;5(HeOWTlsk zE=5h8>(b(4U`z(My-Pw(@1hJwabZeHd1;X^v$Vj6P&0>85dcSp!P-1@*P>?^a^I5a z1ql6yQ&YiprZ0PZ8T9a5p8iKeM9q1Q!wo2iS~#hSqN1$aU}4|fVyKE*a#}`ic`z*y zD1|NRUMJ0&=qvzg#nUjziXvyJs%ypnk~$cn*0-r)xq$ZDa9Y2#OwK0{zvhdX6!zzd zPy(k63>H+25lZA~-tn-~5+CO$xZ&i^`VhL0=L~`+aZ+tj2K>F3;m-@?Ib^_{d% z4vn`2{wUzO7}~A9R-Ms6kb-bCDZxNdcuoP-r4~KB+Fd!N)_M)f4fu2OxK?!gm7Kxg z@(1cT(+Gk9=7DEa5J4o?P_wwRRUfRM#3{8nD)V$sNui^s1-G0ELQA~3f_^m%sc4Wt z5Uj{8O5)#xL`bVibA>>-Ce^>f7Z{I_j%pa1U3!bl$UuX^ORKM%D@lli(_tn$7WO~r zU&#TN%Y~wodN8jbRdVnor`*0yO}l;FE92I6OmzAXNGO$_^r7K6i&s)AW01F;c+$a7 zXmJ^6DG0D9IlbS&uF2_r!&$?0;SM*VH9k0lf!wkfG(68=THZC!UxEU8XxI>_m6|>P z-6Ha~Q^Fp6LHzjVNNcjfjo-@41<#n(EyXxy!B^n%a&MWSBA(LG&X{rS!{m zQf1*(7Ej&XmAAaJCtSmcp-MPiR_qyB8W_p*QnE5*e>oCw`7g&XI#5~+HDXXsIrod~ zC@MHZ1@rC651R{5G3)|0`QSCQq#!rIJtBiG>Q-6-xViuzXb>#9r^r|GV6dvJN{)l8d0J{fyD8H;2JPG>)uo^I{in5@mM@llU zhPrk`-Y#7`m7_9(y!pfn8#78y?KjX z;@`Cm%j~crDJg>LFeIm>`hgLU7^gMZLW-P`-qAMaA{$8k8FmTr1jaG%5TNnU2AOCWszkp->(PGn18U+DTzy^qb+$H$ zqWjT!v=F_E4xr1ZsY`VAbCtLRQIZu^!@7~1mk)yaV4;7^Lq)|UrDbE`SXMFa;mYw7 zc*|2z-Fr~zo=^n*GBE|AI`A9NtpI5_ecldJP{;+~{Dc8NYt%*X>L-Vq>u~B$dhNXb zu6#|on)dEa{~EofTuuCI_`Fz3wh_?bSaXaw*sF2GY z8C5SjF|N8exEXM_f>t2Zi+A1Eut8l;akq0vyQ1Cg+BIq7Zqo)1P2mvdL~*VNUOW;Y zF~a2zMe+)6Xt18wX*4ku5futWM@QThLJ`ps(QbFh9fFKo-Sdn1xcGSf$T4*7;2H$Y z)-d>gIUaVS`#S-Y-Jh!0cbp z{-uPp)c@lFz&C*4DPH~x6Mt=q^NPQ;#A6P8O*oJ5j=_t-7EULwa18vtBhBeG_3w^( zz2~aSFMt@52qh&sz{~QUdCZ?Ifqp0FK!DhmA*@=ps#DwaXZT|mZCdRZ+iKCGMJ&Ne$#_@@)Aj`7`-|d_+AIo^lkbs{iJ?bk1`q>_ZgazVe~hOjY{JMW1X?t*l!#+B1tQv zk`&U13?M_vC^Ciw$ape^%p~*4@5mCejI1MnAe+fYX;49c(b!9n}%tdBh6{% z9CMYq-rR5AG$W{+wxf*pp@V2Kt)lJNi`Ey`57rGU%8s+=*gx7J1|CNT;47-Jf-PhT z_Y1|slR}m7zVL~#U$|FH5c9?N#Dik2R4N6f3DOd2xwJ}JCw(IAm5xcB<>7Lbyh?sY z-YcJ%f0QE>kJ3q5qO?#k@U5NZ!%yPncoX*MaYmxi+30Rm87qzR#?#~lvYLED#+w}} zrZ;FkHjrIl*I94tj0Iy75aRD7Bnq8`8{#tgvJ$CMb(s2+`my>)^(2nh+v`*xr_a*s z7_mlEBi_g{CK>M=+l-S&3~5f1;dvi`KbO5d#S)xXhy*3&>24j6}xW5x+s z%`+e?7mX{%RpW-?B9SDT#F8e&O{vcNe<}E2$D;D z#7~OJSW*G{Gl@(kGstW*7qn;r$i`C8qvd2JSp(X%o@@kt+Df*QU1Sg0M-Gs~9tQG2Lbh(76QDYj!ldn4+nI?lCjTOf%EXOtZh4V-7V( zn7O9U^qa-zShK<$Z%#6&nlsGV=3H~WxxidxE;W~#%gvSM8gm_J>qc|4xz*fm?lSk7 z`^*F8Ve^=I!aQl7G0&S9%`4_r^M>i7ku;jd(k7tQEoeMVpkCUMcA+9wsR3G^MAK+G z&7}Ql4joEI&|K=He$e}|w1SSOlju~C{MmFaolh6gMRX}$Mwio-bPZ_2db*Krrd#QD zx{L0i`{)6Bm>vV|I7!b?1ixYzfC>x|=7^o78Pdzrds3tzBb}B$2K&4aEb|!kQI%?0T5tUUJq_0PGt%CiY#uRH znAI`5l5OTs;g#`C4$fFoywn#LV6NS0N?3(2i4CMYWxUc@Yp*?lU&ifBYIdb5w2)4K zF}_X@(#y0i=x!nFV3mW0oU%fe#~yB@c?hLKn~Q}ngmYkxlI5B5LixIqq)pZ+j@6qR zub3foHvN+R4MwqpMOy7a1KZe{c9H!k=+B$>1shd`dDul5Bs35+#jnH;QV%I0sq!p& zvAhXv=LNZ*VkmtTpE60QQr=ZQQ=-&(Ra2i=x2rBq(S~Vrv>bd>Z)Wr$N#;P1tagmB zo?u-pdw`wCdAK&*N1W&t6|twtx#yFrq$5(ClAs7m3hZykl}>7*I#esxrf4H^F`fw4 zc?&*{v-R%AIO7eY9_c{JNv^rr++nt)3f)3?g0<;kRl%C2@;&kAWSbbCdP`!jjy(h^4y_^Pizlyv=PLX>- zXX=8i{X`?#53D;_tmmy4thLq$mS{g_&$Ku4{`MloA9jp@eLxTlAw$R){K9x)vancC z#G&Ft;xuWsv{A03HdI?^82061TA?;WdrDgf`?4GRVCT7xn}SX88MBR7j2{g**#x_R z1U;{#-_Q%R5qlM^{y^&i>pAP3)!Oc6_XK{vY=32=;~-0LZqUSl_?UQ~+*{6)2g~qv z1~@l7EiaJYlsCwG7`^Vc}lr5QJJSKRNhk)G*Np~yR7}JHOFmm9v+Jq z;urBs{3c$H-@_l`z4#bDjW6LFI8u+*o9eCgwt6SMn~rr;@1ghBvp~v=^$Gf`U>UdS z`}8kC&f*OP_RlmU6HW}njZv^-Q;cVgMaEj=J!30a%Zo6-IIx7tq%X+^>oz1XJYtyvZ+G6c}?T~g% z`$nsSqi{pq47lgT9dTEz;56J1kH*jA9e6iBhcDyidc4l`G<~|hKwqZs*AMGo!O7|@ zoUN|vH}wdkzH>I%3YPpV`Hh)qK50gQOsCSv=`(aO{Tyu4H(=i`!;apPbz;3)eUQJ8 ztn>W*fn4ZYz)?aYp}F7@l7*ha2w|e|m@rG2E4(JWDZC?W5e^IA3TK7OLTj;`sEVf8 zODqtli?4~R#ka+i;t!%rsxLK`T1knLAgNM!(D;GUC~18TYPG3kTr5~iL5|SIr zZD3DLgFW?rxlk^a2P(x1Qk$r+sjJoX>K5SCarLBnQ?08-YfZFvng;yJ1b#iIeWHD< zMdLUu!4CT@oU=CI{p<*6(>2x)?Cd)0qLpB`2TLp2`SuulqWzRzWxr)_vk%%AZ3G@P zX2BdI1h>#0bc?TNr7%ZWB77zs1WVUM6va{EgW`JeJJ|gjfkl;I4!xyp=>e$_Y}Z6- zj`W=LBIw@+>2v9@bV|A)U51nOb(m3IxxTE)N%BybPbKKfbIK}ZpK?g~Qfa4}aH1Zi zj#F2_{_&Lx1AxPM5TXwSTN)r8m3qqA@*?p@_md+~2Vr_%nZ2;_TMRu7z&YocZ2_)jEecb+z^QOBCaql9{ zgnNY?(CgviS#gXsMxG8k)hcc`X2o| zG#SNrMo&^eFN@9{)R8$v(WpO_z?aRSdfol=i7we0gJo> zP6JE8uFS)8@O1nrj5Giv9*sxgVK^K2#l1k{DAurmJK?stHExcZf@P|Q5xxc%{(J4T z_O*6YJE-jiecYyfplyJaT&=yPRl&N#;L2S52!#&Pqx2fR4m1CnBGy=MrZb>*~{WRPWt=1c|=Azx CP/M Command Line Emulator - -

zx CP/M Command Line Emulator

- -

zx allows execution of CP/M 2.2 and 3.X application from a -Windows command line. It is compatible with Windows XP and greater (both -32 and 64 bit).

- -

zx is basically a port of a subset of the zxcc program by John Elliott. -The GPLv2 licensing carries forward. Please refer to the - -zxcc web page for more information.

- -

While the original zxcc package was generally intended to allow -execution of the Hi-Tech C CP/M compiler under Unix, zx is slightly -more general and intended to allow running most CP/M tools. Specific -changes were incorporated to improve interactice console operation of -CP/M applications. Additionally, Curt Mayer added case insensitivity -for filenames under Unix variants.

- -

Setup

- -

The zx application (zx.exe) may be copied to any directory for execution. -The bios.bin file must be copied to the same directory. For ease of use, -you will probably want the directory to part of your PATH environment -variable so that you can run the tool from any location.

- -

You will also need the CP/M applications that you want to run. -zx will load files fromthe current directory or one of the following -directories based on file type. Any of the following environment -variables may be defined to determine where zx searches for the -respective file types:

- -
    -
  • ZXBINDIR may contain a single path which will -be searched for executable files (usually *.com)
  • -
  • ZXLIBDIR may contain a single path which will -be search for library files (usually *.lib)
  • -
  • ZXINCDIR may contain a single path which will -be searched for include files (usually *.inc)
  • -
- -

Usage

- -

In general CP/M applications are executed by prefixing the CP/M command -line with "zx". So for example, you could assemble a test.asm using -rmac with a command line like:

- -
zx rmac hello
- -

In this case, rmac.com would need to be in the directory specified by -environment variable ZXBINDIR or in the current directory. Also, -hello.asm would need to be in the current directory.

- -

Filenames

- -

Where you would normally enter a CP/M filename you instead enter -a Windows filename. Note that you will need to use a forward slash -instead of the traditional backslash as a directory separator. The -filename itself (as opposed to any directories in -its path) must obey CP/M 8.3 naming conventions.

- -

Where the documentation requires a CP/M drive letter/user number -you should enter a path complete with trailing slash, for example:

-
-I/usr/src/linux-80/include/
- -

Technical

- -

zx emulates a subset of CP/M 3; hopefully enough to run the -most CP/M tools. It can be used as a limited general-purpose CP/M 3 -emulator provided the emulated program only uses a common subset of -system calls.

- -

Syntax for zx is:

- -
-zx comfile.com arg1 arg2 ... -
- -

The comfile is the program to run; zx searches the current -directory and ZXBINDIR for it.

- -

The arguments are parsed in this way:

- -
    -
  • Any argument starting with a - sign is passed to the CP/M program as-is, -minus the leading - sign. -
  • Any argument starting with a + sign is parsed as a filename (see below) -and then concatenated to the previous argument. -
  • Any argument starting "+-" is concatenated without being parsed. -
  • All other arguments are parsed as filenames. The path is -converted to a CP/M driveletter. -
- -

For example: -

-zx foo.com --Q -A /src/main --I +/src/sub +-, +/foo/bar -
- -

would pass these arguments to foo.com:

- -
--Q A d:main -Id:sub,e:bar -
- -

The other programs are merely wrappers that convert their command lines -into the form required by zx.

- -

Errors

- -

Any errors raised by the zx runtime system will be prefixed -with zx:. Some errors you may encounter are:

- -
-
Unsupported BDOS call
-
Part of CP/M 3 that the program uses has not been emulated. Add the -required functionality to zxbdos.c and recompile.
-
Z80 encountered invalid trap
-
The CP/M program being run attempted to call the zx runtime -system with an unknown call number.
-
- -

Acknowledgements

- -
    -
  • zxcc was written by John Elliott
  • -
  • Hi-Tech C was written by Hi-Tech Software.
  • -
  • The Z80 emulation engine was written by Ian Collier.
  • -
  • Thanks to Jacob Nevins, Andy Parkins and others for bug fix suggestions.
  • -
- - diff --git a/Tools/zx/zxdbg.exe b/Tools/zx/zxdbg.exe deleted file mode 100644 index 598ace60d8893647757c8ceddc154c1dad81467f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102400 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 diff --git a/Tools/zx/COPYING b/Tools/zxcc/COPYING similarity index 100% rename from Tools/zx/COPYING rename to Tools/zxcc/COPYING diff --git a/Tools/zxcc/ReadMe.txt b/Tools/zxcc/ReadMe.txt new file mode 100644 index 00000000..ba94bf5d --- /dev/null +++ b/Tools/zxcc/ReadMe.txt @@ -0,0 +1,86 @@ +This is an adaptation of zxcc-0.5.7 for RomWBW by Wayne Warthen. + +In general, this is a stripped down variant of John Elliott's zxcc package that +runs under a Windows command line (32 or 64 bit Windows), Linux, or MacOS. +This adaptation implements only the main "zxcc" command. The other programs +(zxc, zxas, zxlink, and zslibr) are not inluded here because they are fairly +specific to Hi-Tech C. + +Please see http://www.seasip.info/Unix/Zxcc/ for more information on the original +version of zxcc. Also, refer to https://github.com/agn453/ZXCC which has an +updated version of the code. + +The included zxcc.html documentation is from the original version, so it does not +reflect the changes made here. + +To build under Open Watcom, use Build-OW.cmd. To build under Microsoft Visual C, +use Build-VC.cmd. To build under Linux or MacOS, use the Makefile. + +The GPL status of everything remains in place and carries forward. + +December 5, 2014 + +After struggling to get the entire zxcc package to build nicely using autoconf, +I finally gave up and took a much more direct approach. I have extracted just +the source files needed and created a simple batch file to build the tool. I +realize this could be done much better, but I cheated in the interest of time. + +The one "real" change I made in the source code was that I modified the tool +to look for bios.bin in the same directory as the executable is in. This +just makes it much easier to set up (for me, anyway). + +Wayne Warthen +wwarthen@gmail.com + +March 15, 2017 + +- Updated to compile under Open Watcom. +- Implemented BDOS console status function. +- Set stdin and stdout to binary mode at startup. + +August 21, 2021 + +- Incorporated filename case insensitivity changes from Curt Mayer +- Incorporated fixes from Tony Nicholson at https://github.com/agn453/ZXCC + - Emulation of CP/M BDOS function 60 (call resident system extension) + should be disabled and return 0xFF in both the A and L registers. + - Change cpm_bdos_10() to return an unsigned result to avoid buffer + size being interpreted as negative. + - Fix the emulation of Z80 opcodes for IN (HL),(C) and + OUT (C),(HL) - opcodes 0xED,0x70 and 0xED,0x71 respectively. + This is noted in Fred Weigel's AM9511 arithmetic processing unit + emulation from https://github.com/ratboy666/am9511 in the howto.txt + description. NB: I have not included Fred's am9511 support at this + time into ZXCC. +- Fixed parse_to_fcb function in zxcc.c to handle parsing second automatic + FCB from command line + +Wayne Warthen +wwarthen@gmail.com + +--WBW 4:09 PM 8/21/2021 + +January 9, 2022 + +- Running zxcc under WSL (Windows Subsystem for Linux) was gererating output + that was correct but did not match standard Windows or Linux runs. This + turned out to be an assumption in a few places in the code that reading + into a buffer would not modify the area of the buffer that was beyond + the space required by the data being read. Under WSL, this "slack" space + was mangled. I made changes in these locations to clean up the slack + space after such reads. This fixed WSL runs to produce binary identical + output. Although only required by WSL, the changes cause no problems for + other environments and are actually correct per POSIX. + +--WBW 11:56 AM 1/9/2022 + +- I have attempted to sync my code up with the latest code found in Tony + Nicholson's GitHub repo at https://github.com/agn453/ZXCC. The most + significant difference in my code is that I am using the WIN32 API + for all disk I/O. Although the file tracking code is retained, I have + found this mechanism to fail insome scenarios. By using the WIN32 API + I can achieve the same file sharing attributes as Unix which makes the + file tracking mechanism optional. + +--WBW 9:34 AM 2/10/2022 + diff --git a/Tools/unix/zx/cpm/bios.bin b/Tools/zxcc/bios.bin similarity index 100% rename from Tools/unix/zx/cpm/bios.bin rename to Tools/zxcc/bios.bin diff --git a/Tools/zxcc/zxcc-src.zip b/Tools/zxcc/zxcc-src.zip new file mode 100644 index 0000000000000000000000000000000000000000..16bedad54b5b901c188b9e649c5088963527bb78 GIT binary patch literal 69549 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 literal 0 HcmV?d00001 diff --git a/Tools/zxcc/zxcc.exe b/Tools/zxcc/zxcc.exe new file mode 100644 index 0000000000000000000000000000000000000000..54681729808f2e75d650385f6acb9dca08afb9fd GIT binary patch literal 95744 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%0A7bG8>c3;xuqRSWOSHxPTzp;o52O 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%0D#er1=?3rVj@RO#UArw}7| z2&+%KYD` z+daR=3$JRufDTck3QI6lw!#I$1Q+HsYYw%JHgRr@Ibd_BPwTDP#cN7yFnut*iRnp9 zPh#iO58EFjGLhp#jeP7Lf>6cFAddPaPsTf867K|99!G*u1bWaXN>0(c=7()I$Qw(@ zE<_?9G&Gk+h-P0Tw*UThZ0l4BasLAxunB56-wXkwXd$sz>MthWkc=sE9Etrttp|s| z@O+inicV2%o5+*EuNSb7Jm->F-W9f>m)(02tLUyb3AM&nzX@S&0nWu?Vn9-}SN#PM zd$E~&1y42aimq>MM##|2H7U}aJ$E@C z46m;PG`f|KYN>dXM;%a*;LW$VuB4nyYha(SymQFzdGw;N?k*q8)!G4D0Q%SCQ%@4BK9{hQCI@*I`_bX#Y%}b`f>^A3;0Syt4+@!H(|%>3Mpy z$)>XuHk}6NVE(0#fu}(hye7y3Ef}gxpT`a1zM5HbFTH5#2#a4Be6=~^TOB)Aeg*wZIv@xCrho{MLZ4PPI zJxfv=eAAE1Nsx28r~gxquL??m#()E--Vhs&*!QRZ^ZEvx>7FINTC2PEww&p2$QxtZ zq|&_>`EzP~RW7jeq-vcWD=$R+yy@#r^4!?Zq&xyK%PeOjGJX1bi#!dHscL~ZeU>Os zK%{H>`Y8EkMBc!2M$6YB(ms8Cj6BTKVD&UvV?UGkPJswT)rTagBG@Bc7{im=N-%`1 zi!BSL9r;(PRJYz0l)e$q;HJp_Dlzss=5Q)vIT8E)*o7{1~el^ ze$tP5&LygMIDP`XYF0e{GT-jM(8-}Gl6uCPQEeO1X{yvQU zf(<@Kc6`)qf4Ran%)2=Vd1AOp8k^QI0EE(QX~8{Il=X6(9O`@@_QeZ&CK92LunZ#^ zDGXqTN%{sX@VhgyNknB1SOXI%3|w(NfzA`PpAznU>?CzxLH8k11ryHEQrxNSqp97j zLg!$_LH};3H$zZ#T+?5w4~)*ub!gIp+U&T!PHEWQXeqXiL@jL&DuUKqSz+r(CT3Ez zZMO)}#bnVRIYV9IsP2-dvL&KcMor>kUZVQ2SlzQ@7L@F|ZlhI`u~Gz{RZTSx*aWHf zfzv(NaiVk+mnPNWq;o%oW5X<4)C=MZMYX6LQF;Nj1KnSM4`;g_I%1(rR10jL%O+_k7KRlA z%0^sy5N7WrI&u3H>H46Ebj#yCm*eCFs1E0n;_$PIdsVX=j#~vmX7*ejEe{Fhc7*kU zto2^t#ut9)P1U2y#Cfa?2&}LTKneUDiV7#X1#PYu!2~_{ERCP%oE6`Bo#Ddv2h&Td zy@?oPP#(c;!#8ulo`Y7B3Lzd~4^WJm!)>;~1SeMZz`Jl}(bLf{e;0~J{0Mk6dlzKb z=vLAN$&wTJ3SdxMVe!KC7l9KHogpI_@mQK6(-yA3SlWW^NL=ioJfQmj9D)T-p*mpU z01+SAbwYawwPM7gq2%fes8AhC$V9*0b(n)bJxqULFR5u)hx1|7-hvbu%yxuE(>s5h zu54)@7|;CBc-pJm?A4WkV2r7{(Wd5Gl~UVVo{v%u1@d|A4OClO8kZLAIVegaYECJq z`fA=#-Y{`Pdd5Lb(;Ry((vTX5yYaAfrrccwGop4Q(w2BmS)}1L zj+v6JX0vIg6pi$n&1T<|{D+bc>>Uf6l*8*5XUZ3;m^6K+l*}BgP@KsMt*p={B~B}J zvO>hfBPNj*CVAaX`F*eZyw~mE8TEX4d(* zMf??{8C)->jf6V^*W|gmF^A0-p|f3LZOO$RoU^26cRX<>PvdCArGSkgv$*FGn;`!K zVqYAY)`{xtO(;;e`BS&R9WAN&z>oOfq6ZsBze){B>oT?Q+S1y-()NYPoSegz z9s}@;)k3RszwHaP7@ifxsNg3M-a+c~1NOIL;Rym0XEbb*$OnGxklnDg$d;6cMcwFW za9U!t&iRv3aF`>Nmuw=Zx8ei0^yDCE$=4YEPzm#tZo zw{gq5vP~NwTC-6qfhlX_1LfJmU2CMTM}Ko{wlF)dcwXL|DU&D7m@@~}7_)=xPxShu zKBs6m^!bC7D~KU|V+;FW4_P`{0xdq8AKpu84SUF78%#JzGFH>Gb0Ly7YL3!9q|Apv zxSO83%j%vY9tG#@XDF9$9^bQoN7l60B+Nr-&l3FEO>t@h1?gCR`<{CdQnIL!X!raA zEv)PO+$|KQb*zp0!j0C8-k&W33lwEl(i&RtsRecuNU@{Vj!5X7kTO@ zJe7kMwnQZ&52b2t&>go#x$sI!!Gvwdr9C|igWpt}xF-o&l>TwjcOuoelOtayK&M;x zIa=mlfm!07o+u3^-F~!NnKn-Tih@Vnfj8lzbJ!iI-xJRpU4c4iufGbt(vFiJyQx%7 z+~Y)Lr5@CF6A9I3?PH{%OLypRo%-9I@G1&?<}EarW{j5XrJm`6Gz3uyjFT_$*LKSB z8V??#;9u)UaD+KgHGYt0mmZ&7;r$p^H&^xw7jmIk` zg^PneuwE=$u$z#C**IQ}qaI)-uw&wMX>S4RYz#$tvS>&IIpN;>Xr^FN{f*KRs9>ON zZ3D2!2lea2IYi|}7X>@gK4TLJiVi|2V%Q@=pb*Hkr_!LCGsuDV{a8rc*lyRSqJ&Q5 zTIy6(d0yK$1(b9XA^t}(L=^&Z)Dd^ncH*6DosAiS^#SfE*JD&ervC33rhXZpax7wF zXg&lJ<`Y?AZiB3Jvwz^UR)tE8IBgrR<_hu#+9E^+6oCAO%?)&t$+|YE{3ghZaGokE zDc1f9V+I7tlblkdvDm+0xAIMj79*OBgpl=bh{aOS_mCV-;;z(Yh`T7rtE2HkrtkKl zOWWfGd01^u++MR(+>#UjI5Ma?@!IbI0P8D*myh8|FspWZobpL;&1EojrAV6$OL}UdO)Qy+Fi&CqUqEo zAqk> zLejf-0v0F6vt-1z!je!vV)yHKs73MV?d8!dfnH!@0w6*gYgK2G<;?~-R&}`PaQe}* zI<>$Wj^d!po>w_6#Afo0dhCzjZpTYI5NXp}ft#R67??#621VaT(QyY+J5sKTERaVj zGf_bH4>W9`|D@5x4jF4RxfWrEoc7sX_>+|*2g#rCJ&`6tH2MMplvBPLJ5q44!JcK; zL8_oFSu{JOZ(2D)=+3dsRQ;Kp2tYk<2i#mp_UQx$DZ7~+3JWRR%aIUP<5SLjQL`it z%eYy3Nqxks-e-je;qS3+W*X`u<@8DDUz_(8!u3mQ!WN}j zjD~|n0 zH<8-3hal@>)Ifa(H|GOnh>w&vi`p*7=(&B`IJg4urY5ySQ7R=yKr`ebtT#XtRg&IV zK0bqYr2M=1n)VqpyeIC2=-q{Nh~rUt)6L>7+}9RLy72WSrcSr^ThM=?i7P>PI?o@< z92!~uSxoXniYMy|=BXehliX4JlQn21E_u*JDJfprW&$VYe&|bmb;OUC!i!`nAAe%^ zI7?#=LAV*$l{MBf4&jtZznEJZR$FWU@9QrM=l^?FBTb*<=p9O7xBS zR)f#E9jGUOlo0?=3{|zINRg!E9+sR?A0_5V&>(!>>!WZq=c!6f0*jk7R z_~av%6QqK)AY3$@GE`2NGKWZ)ahXKb-;po1L76@d_8jz(+VfbrU&qKZzo&SDoNu6Fjx%y9mk#MCCM_us+w0Q?5AWTfvatt{qo( zR(eypvP^aW;Ar@SjFY2trmwsz{Q{fP)SSRm%9SC~JArp=SDKV72 z{dd3v9_|IO#F1k;wyuyZ&(O{^-j)2N8_XEYz|$nc%AuUTVrmEO(}FJ8b+iu%%}ucB z+tM1Kn7Kf=BGUO5 zA@Fy-o#2maMF_F`1pHCQkaVvm(AHx2+W!Q1BYM~~AJcU=rSGxQpAAUZO=b4j=+9=n z(unKuc2j0D*F6P-02P4W93`9MYD~7U+fo^vnu3@{IEQ0F$rg)(7U@KTUM3l!xW6>s z(f5HEumhbpL$6iYM~am#a3a7%{mCn6bz@&*C|Ts9V^~+hxu@Dd(jz6nAw^$5upuYO zQ`>_`@PH!Y9oc@YXB)Kq(R?I-^kd%b@vPUoWR&)r1rwks5sGeTH9nXGbz`*a&YJ9m z{T6CezSFyK0?Qul&Aw5)>2@rrl{X<;7t-oP140K<1kGmJAgi)?{^}6lC!~CdO(}hQgZsGR>6zsT6#7TLiDtD5Iqe+ z?cYdFq+hNz)sDkmoY9#}x0*$#awWUWs$5yR)uJ49PCF@E!6n4(oWOAsU}{csMRYRG z0U5(i>m>}Vt=g2!Tww(tDiA8(SK%E~vr`+bcRq@*gh;5T1l+!-ne-Azc?k>v{}KIE zp5yGZ1#nLm@-1vIp$h#W-&!fvjUDdfbRW*1bZQ@92MBM926^frfrK0f2n65jY4rJ% zz`69!E%tCGZ2pD7arSZc*Ra?dQIZ-&zKxL_3(doV36;r_`uhdW_3JSon?LL;avE!eu*zKwfxBk`lXPKnT)5FB%&`kF{ZeM&!3ehU?p#$qAN37pTt10enu z_#ZTX>cvpW!0U*-v7VZ(L)BYqG^(BRG#w_K)~8kmP7ID4MIpf zfW8akXUv`$eFpfn7l;ucmI!W3l=dm^Q)LNM%*dcmeB9%D4h%1PW_m&vAth48 zk1sdm2|+BKeE`98DZX5h-YUgb9;9f}qH@1Db`nV5(HIQwqv-TEA2qWJaL<1YQcdr1 zDj~m_{HA<*pp-rcw4UMoH8(0lg4wkfb?d0Mdwz+q_IqHTI|UH$JD=8}YhA#2JI-Mo zAVv>Jg^vByIm)EHM2UxJjx2)AYr~wm0>UMNTdvw%SVzv|6;xapE?qu9qrxRVDl+`# zV)A+Pbt8fCg$}uT`h!q|L-HY+opaS|HD!S_p}g9eudqP8o&Lp+y{w;o%FZVTv==cQ z0{? z>;lI~OIjDI)@CMSSY|-K3xit1;vJBEe+$L3sSoIkPD!{Q5kPU}W&5or;Zaw0M}@WW zvW>!t2;+nm(5Fwz%1qaXt8f9rIh_{|Bn-5M%NLtu$whJoou7EJ)HBT_kMe92aoVg@ zb;p)wIfSwyrCB3{t>}}!`wvZLn%{6gZ_r7`lcizK!b0!KI>!UIhx}l`cGe4P6;#U) zRhZTyq^xbV5+@|5@I6#8&>ES?OnKaE8wTE*pGm|5<@uBaNP|E{u+O(PMSIuu6RLm zLf^3+R16lAa80K7kSWj{!T`@6@|%LIRhY<>tn=tQZbHCd>GrYW!q)@Qix$qDk#~0; zF)h%?K=aVPQm$67O;q|PN;akcW;sroC7RrU&+xDYE-C#f^6=XAqVk4V6Hw0lvu3I2 z4jfVXo$|=q?P5=hD8F69zZWwL@%xniR5`k4=|p$nPdfg~ul4}Em zpfYWeJd0ik$pk1x2lQP6l=k3kTO=S`;52(znJro`eaL=b4eXDEY6H}X?plYpz@+r8 zEl*MU=GZ-t5YWDvvIDB5@5-^tHuF?`@Bxv;iH#Nn4tqD7w~}6Lt-X3V(r{>Jw&w@UDFFOk$8ea30oE`ecSO7wZ5(LOK#+L>$%sZ&K4CD&(y8-Es|VH z-#qzAd{ljQl$l~FBswVs%>#lQ9#7`dIfoRQ4J0> z74096L2B=U=fC`&QV+b0pdDr>OV#1HM@U-_&O>DVvB?MA!Bt5lUR=-uUsXaaKWf+m5Jab84WwS)2q4w$TEiug~PYhc17> z;=v2;yLMnSJUeVSw$YMrBXiMyn47>j*kR7dwIt%JuaRd}bTk4rbtRMIEOrkSadw&)SkGw!&O?EIMrL@JAirxW# zP$}a2%rrf$qteSYBqhZ?ZqX{=s%)E>Dm&qPqApHMDU44(ky4nHQs_)6bfpxIukP3p zWje|hC&E1&DPZD-~S0DT9JS}EzBPj^E+&DTTJ89?5?Bm(AD95o@ z`+-sU!FPf)lLDW49!U~*9!AsnAhcw|L72FT{%YvcVA5ypExAx|K*>@vo|U**iIbHi zv64hq5?@;~f&EkITPc^-E*Ei^2tL$C`QX6|Zz^?ZFU|QR7Y4yvyKn-W+C&;drEj&} z^DH=+(pPBr9JWv(&+ZwIL00;5@f8&89$WIQRAX)agc^)LHyuKfX$41Rny!n(1l=St zrB9Zslsn{kai5{PoCBmKko`{B}b@b$m$nhrS zSmuIBr~*vNUiCV?FO2stHL>OK&EoWldbU4NH2Q;+R`fT?M3$(| zzM^}C!^uiy=)0)SywcO;l!ii&4g<3Pb9AJq$ziYh2mxKU?mvN`(zniDMYkIGU#A=` z1X70q0Q~wH!Yve{>Z~h(N+7NFSKIt|QUeIyBn0dS+WfcTS>5JO!{gF%|4snon1E|u zWS>&_=hS;z%=W5f$P$_4^v^$eR?A0VpVj07A zAJs2X5DF}N^=}Yr&f^odN!@|7bxG;H_FYjJY!t_ZA@rqO6cS_Y-kT8wM~YP*6;kb0 z33vkwizRfuOfbErM2OWzC4N|&NDqc3m6}G|LEBh%@ z`wU=}9TN(nNbA)apmEUa)3h19K2qR~9#r4b<`_{?U&|erS0ieWQeNVV6IS4UL zU1-y;LZzjn4HqTtGNDaC-w!Vn#2wU^1L$D{ZnnuY`S_Zoshr$N_sNIEu7}3IVLsy;*F1?8D=I_knYnz0?5advR4g3z`qsMaf<9m{Yu{h_Ubj%fNrcAy?Mce zwGd#@lqr!-u|M9xK`bsGru3EAt73p#|LrJcfBYVf=2h~)aR&z+6bBw{2S32`{QJ*R{HP---mc0-(K}O;{6ACV+e!q_2QL0 zx_LcS&m*Lx)<+4?;1%eq^)hr-A#=0p3@gn^-5MJvo4YKO>Lg-mtEM@hiW^t^GnC@7du)VS*# z>M2!=uIREQh&V&9MjENlmSvIoF=RkJjdosSbmWqR^`i0|aSQf7dy~y@6{I!byuX47 zp%kxku#dtJ&TFM}po<~NL7ut3HpY9mDf1TTM*D$wbhUuJ6+EVVUywh+{%mpOL4t;* z$%hSAftp7y*xOKe8E#{aeWzXAU@C(m#dLdck7mB%U-F4-w3VpbLkJBHUg z2`IW8JQkeeDhz1s3{sW}JFcTh`+V4~esn0qvpM+H0Y7k8fQj3x9is0=RJhg(J0=c>wKkwBS4*U0I)L}C z1%T)c!Vbrv=nVmC*5aGQWiSUNPdD~ zBiD5C0HJfu&{N6{pAMzEWcTb<{LxU^nJpD zlDuNWk#qjqHO_S#b#HQ9Wa3;QIa9Z#8b9Z%6>|BS)y@^p)$6vbE2s38k2trlDcj^M z-LPqe1TRwO=1uE1O0jFUty;60ZbF$9E993rvm#&!+0M;nD86CM0{|6S*VYx~PTb|N zN|vY&$+=?nYWTC4M>GJ?wwA4vq%{Qh>&ea)8&}7!TCs5>{NKa6|7Ms`2QRGF8%co3|-8IkX?LSD|`?*IG7ho{*!$p1H!EH5XrLZ>iMFS-U3LdeS=oHk?7 z*yz-_xopz|Wh)-SF_VF@4HH?!45WGat;u)Y#x>hktdg8tR&0=QPUT;-h)DL3S2B25 zN;mHUnu|_!DXRnghZCSHu-Nx0MwhE{-G_i54XU&GyAYX9U0rbQ|5O9)yacz4dX;NFU zf~0jpz#IlI9OFbKsRh^0ypf+6tD_Z$EK4VY9b}b^%wtGo#(9+w^~+<(!5j(_@8%)3 zqiYhYx?~sZ9Z9$pGANCL=JT|DX6;Xu92mPav8Kp`ia#Z#3^agJRK7b0E(zOB+vKm< z1$uc!uL1T+F7T0YT>XP9ksfme^&wHox))-oAlXBvb1azmz;C8GisDWD{2gjIr6qj| z(E!@1cgep&HDx^sOOV||zG+!r9*o6aF$-4DZ&rr;4ifPt6 z`QO~4la3fvYSJs6Y!oL?F6~Cj{H{^_AjQ}yW{Od~j$-<-E2)3kh-si0jbhBB^-BLi zF~=z8W+P84#T-NoDix{Hg8EmDN`FpCFHq)Bj7p!T82V6q{iN%4fEYnRtEQL}Misj# zrW`T|+pB&G5cLo7IuFpU5tfxd^8O|P?4?7bO|e%$kCgg7ys5B7nUS&&&Y}Y3 z#Pf}PV=rBXIbc}*5+Sx!X_SqlbLwWy6nX0HiSwG`J(phBzwJ1tsSf7ib z@kgV;mc>~=LbQBOy#QqRyU~ZND4vhdUSF*bAtr~2l=|!S0a%i#ebtX?_6QvKXVs73 zk!f9ix?H>d5`p;xh5n53^OF-teHZwT|K}9?A@cfvNTF;BRZ-|MDzTkH6@0`2>0x^N z9+h87p-(CAVhX*b)6MmojQZ;zryOp?Gp)V|P`<0u@zs<5BG7DzpMd@8bJe<%WNLmv z7%X}81~ZJ>@afIj!ZKI3unPZo;QxC3FTj5Z|2h98cMxpC<5kI()RQYl%j;E3RCzG? zeNS(+{fYZPB0*R6Gk{Y67%r_b@@HMp8T84QcQgIbQ(sLX+GeWx<4aX*eI?#YD=#1KlVj^^D2-gnDdGYmen=5?>oi65A_4>< z_@@{VUxgyZA)*!+3wO!OYhe#Lm8x8J$WirRszQ%|cF#ee)@^d7W~SP!zmFGno>Ny# zs`)NBRNq2#s)D;S-^YqvOBYa`Sew@)gU@tpNEr~4IqNm z42MrbI(4#t!tza-Rrh=lU)aHGK6(KsX%)_ZC=uFh8nKiX{&9aKC%Le!Pr@3+ufw9t z3ll*vYCK&=FP5rtblS}VJ3EFDH`$Gf5>nxOfQ!4B1#VSN&p{`dXv!SMVYc#^D8UJD z+xL+Vk7I0{|u_k07us*eamPzI%6K?U5HzwgYy#cQf|#y?$}~s%N-fZhlIVtJZ$6AYB0gLA1bOptCup=LP#=Vj zI-4*@_$v_o$w-Cefp-ASCi#$r!iw>Rdc>*KpTKtzf(aYA4nmIAe(^ROKv2rK`!htW zqKML5GZMBf6TAU;l6P?Y1r8-U5gBqQDMwga3i!~ufNR+?~`m1;~MzT!G7)Oqu>L&qsTWXa{^~W z;+#0rMjlM$`iB1az4EFxM#x;3SEBGxSJj zQ9nOck_tB*vUYVI@pqR#KeDa+Ic?fuq-i?sW0Ba0tbq&KIK<-aO%38jr}k5VWn`gh z!$0yD=(RkW03D%z2)iek&<}&mF`1k+P^1i^ zQA52ekYSLo3$Mgrb=;WfbrXHSqcn>S+hX;iL$K-?Is^%?#i;!+-Uc?MP=aui>^w5|?R*1|UyOTD6(sKx|+A;r=`=OTWNmu20L3Rour8U?R1w(v?$ zZKAtoX%O2AI>IV{+CriizFQ*#KX()$H#QqX(i(Db=lD$dvi5h}=4ALo_iFF9!lCWi za7<*E&>w9tkh`1T_l(Vu8b?(_=RTIu1HIlaP?#l9ayW@2mY*nnloH2K34`hf>Bk{Y zq&4_wV0RJzk^6Cb&!Hf$7(R@v_!~d9*5H1On%IyF2-?H-fxHS_4XEFytVKc39!#jA zEt%(Y01MAC@>kkD6$1cMzw3&cKtUYxIB9C%GYvs)7b;g1$ftid`T1)<_g@YAUwfVw zU;Z=PTiI!H>R$%cW2w%jJw~z|*35iLomoqv9 zeQPsT9`52BM^2^Ejqcesg~7mA?%LR#nu6eL`7Do)(W5`WsmBm5sDY$ojQo-IayK0k zz#LYDW1mhc(URk!hd0OBl9Nawmg8bM<5>=_ZE4BDkb`=( z2`mQ&WAg;!XWpC%SgYwMp%s(%`M~d30#y|Fb0ob`{i@ZQJ=E0;58Lm++pi%Lfg9Dh zlRIz-tF;_X#;&WZF)C>1Ct=Q>N1X0f%*^0_;f=N-6u|%3y_U|Rst$M}2NN7v$0H>M zI_|{af0W~1y0zhj!5vFK@X#7g(fG}wIC>%3zUKLvg zl(~ed)re6qf5^0`M^>_+HJGR|8 zv~63oR)7k9myTcR@*KyZJiJ^waj6qlaG&uU+V)6%D47P+2>UePJ@gVPGPF$|JzE-; zn{i_65VcipO6j=N{o_mB>IwBoN}Dg^a9NT(BBOKbuoR!#nbMZh!BOTzsOzaG4*M1? zT$IwIUR6K0bd78)8<~gvUu_jLI=6h$JF;hFaPGEoM~)xqO7UHP_^YzdEj-3{#DApA z;v0FS{EGm8s-5a#wOM`lzUBA&;PNiVfWcTUo$(bGUpl3>F1~ce!v7rch5TP|gq&eL zcd({?v;^_}CD|t3vmxg#k7q|J`*-i?zgPj2EAk-48p;Meg~?alRx!M~>(P;XLG~E_ zFP=u*?7&A}5BVx;-J|)~SPAG-0QHtwSUakLEAkCZjlJe|M<0T0ZE9liE^o;ys$ezR z!LwXK6_7QPo5(l8`&0_@?SB$~^u&Iw$W~L6R~!POTPGE zL#8Df5{5lXDKZHaj+}|~3|xq!$E?6dm3<$q!rHPcn+P!one{q+PR9c4SLLVVp17`q z^5IaG(J3@4^2gUF<~u-*_0~Lyp3?EmOFitZ#xKkVsFlerdd#{m-of69uTwvbi(sCF zx(Q~LciEejeGPkY-(MVji-vgXsZQ_O;68dLe+U4*moAtN=}(-VbqquAaW%)KZbaqd zzO_r;h|NSB24cY&E_LstI+?~sA@2o9@qTSKx|xg<4;9N^rLl!9rVkLCm!#c&Js+c} zS80Iuk0o%2Su4>(Ke$l*qQ*W)`jHBgo8>#~uZnjiH>P!Dd-F_?Yxkk!0%|zV7A8Wl z@OhsiRDexf0V|B6M$9%f&O)u{0yUBB4f38r_>x%KE8nXnmZ_V zsgKUX;w#+BwA6}G%Cz*I!yoK`cb`?i!x*uTe#%CoA4ZpT{U!X(;xXnpuDHzQz-7?V zQucZ60->ryUdsZ>-Ie_cdb1;HKRwh;7dw9KAskabklt(oy67V1#ruI>2!6GBLS|}( zn3=v~E*akANxt*d@}4MXyKC@WQEOfe?@ZuFO5X(ODHN7|NVhD*-6-|Z=sf>c;1+&j z_8-!IAn*l}$NH0!>0_`X>YzsJ4Fe4bYe>`tr>!U4f<5eX-E0EyXL&jO4xjsy5`L`Y5ac7Mqt%m zy$Bg~%>IId;gLCdB(O{RNY=<5p(3Xf-KRwdus8wDCCEjDZB@+6q(vp()!6HRKRQ(nwqKH@*KR}M--ZfDp|F%r zKAYscie)>9HmBIDOMnRf9Q;9f6sI8-X;}0@weg`y4EzbN__D?U;+Dk3u415#C}Nd* zRFnQFAxc1I{jHUa3{@G4UT_HRKUfHN(K)U;`-T7t`{clx$=O2p^ZX53d)I-ODfA9B zG-?llFw+|$j-nq!h{y^#cPt=0yTH!o>ggX5l1`#;f^-5Y1#ay*C>U82?L2b#xu}|t z*%#OH0iJ-1$X)EiYm;`9Uq0^Jo|8iUCnoZ`=QU$~!9kpS^z}6)#NPF_<8X3R>Z4c_ zLM)$<(Vv_!f#O0rlM}|{mG%RiU()&q2@Ur!Q;jTP8UEJKK@OdVc56e?k=j(&T-75F ztGVM1q3SA_};* zH*_>jpCHF$Hr7+qw0%5I8v*j*Jlk{9=IOPT*N|_Hhdf~?NMniP;iE(s$R)eCHjA_P zPr7S*ZB{-RBg)x5L}&X6GNvf6mYveR!u-JC*sE_xqCTN{cQC6{L|09>@|w7Z+FCP) zKx>a0O^ zC^st{DgKWUZi%9CD9oq3qlg%Y(65D8Tz3-OL;LEdG~G3F_QP&Qgv5>;A|O8fH<~a= zN22q07xsbMoNzT$3!R=maN~n$pXyFZ#yod%PU(G&OWluRcS6d^A0xevq&i&CYU(m| zs)_bjr#1FFlKa_*X=D8Xrf6u!dI=aS_7H^pe%Et5Qy*s{x>tQ{b8H^~&gs-9?Ex8?vN285( zB!Ke!@o~v#mp4Bcz&(UXp;UdIU^!z)sIR!cbUXgq)XffcyCePT&cuqb?1Xj>c*g2W zXL(N{nBKf&;C3(l;=ixWH_pP7bPQJ5)y+;?Uy{I=X?)XqJXth11li68r*P(?E{?Aw zD%VzH-UC7Lgj|@$1kNB{r6e^wK8kR!u5)Nt<8<^Z$idO?oj(zK3Dp5f8atI_TulND zTfz7|KX8JZSTG7|i6i};9rtkggWq8_iuW!TvJ5JFx`8!UejEfm+)G?Nit^)R4&S$2 zWe*SP%6@9it29~sYtdRA+dn`^-m7LOdKzLz%gNx+9m9vi}?_7ZlR*xASJ&H>3lZb)z1VamaU!b#~(_8%R?!1EgI zRYwr?H{%aJd3c`_xW%sDUfqcPsdqWj5A8_9_`*F~fR3OKB=b2Ea5XZ_YfuzLv(Du6 zpryfB#PyR!MDQt#5(m-z5?k_7o)V3eR|aOoKh<@%w4S*zP9(qM>5amt#&qPQ`*z0i zMsgEb`XT!dw^MiNn|}oZcuDs?YUCml8FKBKPq_%E>Y^l43_HU(**%owWLN}Fa3VW| zlmrw>>j8SIXd(2|jhMPW#=-@3V|kf1tu4K~B3{0Z?lxa9rUxpl@=#UCFh6R19tRf^ zV?Gp-`UOWe%W?>;aWQDx%)lha>0ZosFIMc)6fCvSFY*$h4B!WJ|t%Y zT<&JVAL+Wzg*gxc{RbQ%DexSeL!#nB_5ppn4l4rs`y=Y_`Q=baHCu3m2imDze!h_6j2{2*_@)-Pvh^0! zETQG*cE$|ZTr)@_e$4-XasU8h4m(PQcU3{P(i9XA){1Xx~eZ)^s+vG_y$ zL0@vE+ovpsnRAY1u^wXcEsOb$8j=T4MG$z!43zH2F`?SgdDz3Po|1geClFnN=uZ6ZoD`H3%c<= z<5sN}#kH4E7y3C?moGX2J#2Rzf?D{k&4|?E2+x$fKM#98{BQV{|MlMS`!GN;rKrn(0f47JOin_pw#`h<3=W!K2(i3d9hld1%q&c&OWj z7HU4c2R_%TV73a>hjH*EtZDVuFm_cOrziISZ-sfW_pdY;aK!ET=RJLE<&RsU$irbX zhP@?~-Z=p_v)L+$9JkfP3eJn{8jRs*dKRmJ3qosk*q*;8A7u-RnQ&wK5Qfnc;Kwjk+N&O>o;C3+t0#N1$OejQ=WuQ>aE={K8KYY)DYmiStYlt~ zgT30DzsD|!NETleFiJ?V9G>2s0U+=W)d?7_Fm5rQ_5^Xz{-BIc7iPybcAeEaWs4SeD0 z|EImGn%doeMgAUFoa1H}Dglhxz$$Sk@5aRUw0+y9&eXrfEx^iQgJ^Ul!+ zJ0#9=#jhl0A2J~pfP-^=#lrBdsR{I<4wvWC3F^bv3i!~ABKY>L~O<_5D0O93H!^bxRtECHa7V+c3gIaAly*)8B^sM+D}Qb z@GHZivm8@0Zr>u=mje*S3K_yuVVm$D!b`&2Lbov7lxmu1B9q2gAyc?VctrTQ@UrlZ za8VdxN;BPU+GvVoahwqGsh*qnuLd}>*kErTr<<=}pTUd1U!{T7NnNis^jDYXXsabc zhE8&kvy4PxZy-RJw}KyFU_W!N1ceBQee zLURrox!dg?nn`@ZdyB59vC65d>8@SwFDm0fvVNGBU zS{WS8?iJM-lbPF?IUGKBLqL-osZbj8DX*E>Xm65PX*2QGv!VR%U~2jpqv;7jccM2} z)E@s0E$$%*p*9=~oD_;-^RZ>7@3ivoho&y|>0d(m^l2i5%oVT)t=r+qT#skj4r^vP z@@_ZsF2Y@@w*Y^GS9HD@#si`3otil=2k3JoH1%|YYUnUl46fE<=77H$L?>jzfbc&6 zLN6xpE_-z+-jwO^!F(A3I0h;G+w9f55#~!0rBr>S7qF3O2A344wKaZXwjVHS^hq+- zoZe~Q)rA}xNR%z8oSS182smlz5TxPoFhm7qL*x;Nz*Wmb@xXEIs?QJ|meHVS)AQS_ z_USf@nj$KWv1Ax$eYbimKCKR$Lz@{g+|J;{5&*wROL4`_-7*la#+Pk zPrqyDFgPRP7$B9LfZOE0mSi0!9AdvARVscxefHfO@ zH|>9Z&2#~dd$=i-zB9*TbNrtoxQ~E`!O`2!@Eh;G{v9{i&_X>b!cB40P%^aPDB4FW zpLPq6LJ0hb4{;(pgwKEyx2(^?A7}vS)B*f=K0t-IgG>_BHQCN*A+B#R5z^ZCAh*2Yzw;kY=YuLoC8o60ZKe; zu|O4bEvss_kdDi-h~PoZaFJGEG9y~GO}KOu63tpXK&YuWQ(ip_IHH*nYBKf%Gm(5v zN2pTx+i2QEvoSq>3*4pMBa>SjqUQ#i{l`laBOL ztrBIy3+3-a2>s|;lnLGWOw@Nxh2gZQucx8-%LFRiW@HKfiWX!DK^}T9e2vC%2cwr*iHJ8|2i9Ny zd3Nn7uo#R3uA#&_53Egraw8jq+^#*Mrv!KkU(X;x@>LxgGg`N_MLdUm0X?~bATO1x z$2kCC8-kwREPUdmJ%DRBwDEcp!F~flEfIe}2y_niUQi?&>!da2Ieba|I+c6EA$86# z;BCfb!WrhEAr+zrv_3*-cZ9v4M$ONv{%p%+x;eIxOkhA@zYaL$RMyy)gHO`F{^Xb57A+|7g*9%Hd#BAEJ)L#ryU7t!CKJv4v={ zLqB)Xz^+q2LEJgZi~$YUT6D1_)|)N(3#&QMLRru+A6A<9`?uXi1&iedUF0{^ZgyCr zr?W7@k%%>(CY-_HX?B(-H4Ufh9VS2hE?z@;@jz_1{iO1h`*zMd`5M@n40x;N6uvuH zG9H^wVZfYrlT?mxxEYnAsbLAA);AV8sGWZb_HIIsUM=@(9CC*d%G1~tnoy408n7J% zhAu;zY8-3^*Ge@F&eszViP%B+=>Zg@b;BMya7AA_Qp(0o8mF=)l>xdjo_;YO3epZD z|MXL>#EdJ*i~i&LHpaFykkTD5O)Gm+xlll#=Aek~D+%`eyVkjMPdY)kVk@dYc!>H( z7@RCRDSZc<0gk{X?Z?hBjbR?_LyUy=NvJ`rNDew{9RC(<-v~!93Si^3)wFByeHWeK z)qJ!_q^z;18>RL8(HczSa7avnX_88VuI*@GN=@USwzL?=9fUYxQHPrEuuro+mZ^){ z)TB1!w3tfTec^E+=bJF>=RN&LI>&v3zBp`y{op3XuAl~Uan#trAmXNz)d6o-9)uc) zMWoY)r3Z6gvHvTJyYMyueb%(y*uK5uYr^!$6Q<&!(8o>*glO|VhPi+@@rUIN6$5bI#_kz? zL-sBy4=kA(SbX%C@TI$lk7(ICKJ>=#H$*hkGt9=nx%gVGX#cDc*p4jpHwH{6fdicYML|a~yxJb^Kh%Z+849$Iojf$;3%L0a2^nyA40AH351rPwqfE++E;BLTDz-GYffO^1ZfNuaX1tFwAKmiN|i~$q_<^rhu z|Jv`%Y-?O`Vp<4EE6gh&T?ShdDcGw;(u#c*-b|RCDE8w0Um6Tb_`T^x<=&}&ocD+l zp)F|{GjL)X;$bcEp)jP8LfVpaZ?V_!4aUMry00P~7336^cyoL-k%mYFJ})owd&+%N zVOE1glGcnI-(}@V)Me?}IAXH6wHQ86ABykPotBbzPIzb$UN{9GN@ARp;og}o3GKwCbnwwf#0CNoZQm6x=pS-7eup*$LG*4D(fe$<9Y1mg%g6?O-Xg~_-bXCe&(m9w? zTH!194)f)E3F+dbRF=ccga2|&b-gS-r;u9a$im-5aWpj@hDW?Pv&!&hh$ zroiS%1+dz^HPyjakBc$fLV7x}%Hm>Ap1*K-UI{88*U+@=yb6CtdAYBgkZYYdMVeCq ziKlTix3bt7nwGnI{W^6lA=h0>4blPX?@iN2WDKJibI~vzyp*6_6hf}2DWm-PEo4Lb z&^UeY1YfC_Vix91sL=yL`qG>+7y>7jK(g@~HoIs_d7eXCZp1Ge=gTOj9~lO-A;AH@ zfefoG_7|nj0$usW7Ug>>0h9j3lUH7pH-&NqLvwyL z#%ybK_gCf>r_i%n z36Wdl^Z-Vpw8n0!^p?+pd1um!)EwVMOcRZag~c0h3ua*9JQxpl-I1)nd;e+-goK2U zsFb0mo8e|saHXbQ3a4jW3TI|t3`a+0jYCA3>B<@(yn5(O!pvymuFzaru)9)H25tr6 zx>B=7j7mz)8XnA=pfFdMWofl(;xErDizek$$dn>qMbea_Qm3M{p!p-v8$BDiH7i)t z#k@S26=}IC+K~mYGvcPEMj!=Uz5=HK^p+$vieA!240B>-!I+1}G}p!IoJYAU5?#SN zoGWe##>+}vxB1F%qj_nbVeNn25_iR~+fY#ME5RMnWXME~jIN-Dr5s*`H5o{7*VLe# zaFsw2M7QL_>`G~VUO6=>1tB!VR|&tR0Bx)vBHUH%Exp}eSb-u_eb5_I{kqGWU*vZ( zv5%sH8jx}!9YX;@1%poX&fz{+nrFx`Sgi`0$SH;Br;!;Dfz;?z+C|e&MWsdlBG{X$ z@ZyePBVk}@q^me6Wl_vC3~`0QaFr^|5P}SPK~st=^Sv~P5f7Fi*;%Qnz{-Zj#T6QWCjJ(yc^!!S^i>!Kq`mm&_* zhk&V)$kehDSa~Wc$6y0tm1Ta{(6m%)n3W_AA@0FR11p@uWg5v#nUXp+t;|E*Q#Cg< zeQNrMQLYMa`HZ5e)S}o7-yPn3)Z*}i%i$49`jD)y^kFIVJnJAYOc68=yU6M6~e4o9&Cn{lu^54c#=~OotF(wblq84 zG_{aoh??dqDk&@W(i3r=aiwE_MH}c-FSfx^b(-r|cm5=od+p4egU909E@F=etF)1Rlc=cYkgP8e=EJU zT%3Ym)b@{9FuZ~|`ew1S-ZA6QWzw0j{38Bkzc0~r=Y5E(vG>5|P?%x{&qdvs{ z^MF=Y-_Q~UQP6)inX}2{e+sR2{?o6^zH=H$zk;W<+e(X67W{8%k{-cIqC!I2g@?6m z+qO+;c!#zL;gKQNUE4V>E;KG7E+#H6E<8LgfPEJ9^>T|t;zdVGTynHPL?9%tZA5rf zANs~K=;GqyQ43snuaLem?ZWUPGcK-QTvSL@T)%#uI>q(wjYUMzb#X3TLPBZrwtzmN zA#s7W^oBT87>@tS;rawZVIVsyD)cHB2#pGjii-=x1&|SZc8lMuORrvZ%PJn-k`lb2 zTHx`&aaAsHD ze&IyFYNEKJ-!##yCk1H$8m41Gaeeg_d*F7`bPa#w(kt+MMVzL$-hcI#mS53Q9>()_ zBI-Pg`m`){c;39xaJbq$+?Fj{1}0=JPe8nP{5#X*SFc{()Biz6cNB^1qCeMVc|um_ zPH@QYNZr!EDjg=L&1%1I-@cfbH<_4M8rHQ-%)h=J>WN-oW=7XMek5vg>YON48C7@e zKxB1wb>xEB)JWVPF}HD7#Qpc*9}!XMiNK>Gh%57*WI|lEU&D{iZKmO!Fjqrdjf1FP zJCyo$r)hc}&Fvc71i$w(n%lcB4E{gI#o`!!Bj_ zvxnHDEXPgbeB35q%C(>!@ zJE>U;k=x6ib;@)CKu{DizgeolT(enjd0hEeIitLyzNNmW9#T7NiP~swp>|mN z3^+*8Io;A1>KpYJ^zC@Yw|ZxzuQA=Y&uBE-n!~NBR*|*XT48Oqp11Z}hk%zzyMuk5 zE!n1>W#<4p`|VHcFYF&_JCX^>1+#jPKF*$K=i2#pp|^$E`=s3ftT)={>?XU}u4Ohc z&oEK!)9eMViH{Pl1xxJ6D(6Gw?t#8Pp#^qRC+`cOI{eJ!1p4A9Ug@(=RQGEv4V zHOflmQROG4liFQfpe|M)SD#Z~QctVjt3Rm`S{Gn>uqJ4lwp%-(eWm@VMeDtEMo-hn z=tcTm{Xsq3@EAG9IAfxbYvdb+MzK+5_>GyyT%*cZU{o86jb+9PW0kSSs5Lein~kkT zow3c>ZtO628hebr#y+FoIA|Qf2p%_18V$x7VECNTWHcMZ3^OCm7&F%FYW6VWO_!Nq z_BRtv#uQA&G|Xf(-OMzzO^=yljx#5kxn{muXcn7grr(@t&NZvd1!lFm*j#3=Fjtvt z%vy7Ux!K%m)|uPP?dA@1r@6=6Ywk1a&4cC<^O$+uJZUzVXUs2{`_Z4(b6O&~MEgfWp!3=_+AWqL62 zjEhNN`ZI~J{w^>IY(OS6>EO<6#>3=*Lnku1Og>Y{6f8sd~ zW!>&Cu||XSA6C3Q$hN`VcYtq5E+G@q?Xyfc>t+kt z+3ch2R`zw)#Yx=+8)&ZrTr7-*)pgfTol10+^eoqS#UL}B1Ayi4MMW8QrapdgL}5C`_)^` z>1Mt)%UX+({j>F{6=M&yHTzC`Ev;u6-kstynR%LdmFdNb>=<@AyNheXcj2!U#)@mi zXT`R%4*51%{XzX!n_+%vj<=q%-n3>w8hi*2$IZ2b6ywqX616Xz%I2^>b^-e~8_Esf zKIg9IpXJZ%hYGp>mVVL^-8^7KdTEyZ*#o45Za^BoMqi(ziQK2 ziXZh8W&-2GGmf*}xLdfFpiRStTcAaE2nU7Fg>dnDF;%=%+$@Gkij*VW25sq<3*^~y zs(K%!(;W;4$* zZP*A_Wi#06>=MY!aol9?c5XIT#VzDEaa+0fxO~2XU(CP3|13NvhD&cr-R1T2F38K1 z@^^AarH9f-$yI8VKPlfUnQAq(r&p`dHfld;gY=v9W%^_K^Lo1R2gtT+vzyh&nr^KJ zO}uaAL)xPq$Fa8smoCh8;6Oh(?0x2Q=0~(?Bs-10n_bDa;nxfA3H8E9;Ehl*O6(}c ziAka&4iiU;cZo~Hb>d#}pm;+3UTg-}^pJFU66OWlsjGUbzChotCmI#TN@JrDFou{9n~y;jz6|O=010>kvM<7FZ*_yL z8v%)yYn4NWt+W1Q^?{rjZcl*bx*b|;rad2;f0ez?ehOOZd1$EJ_WQv1G5dsl%06$C zM(_>hSA=QLbY`wWZwD}g8Ju zH?hyK&#~JvYuL|z%Z6|fTwgAW8;Q}%2WLOPZNZ%E0QWWM=3V|U-^@n~f^eJQ6{>}$ z!b)MCuvs`NxWp8360pTcmC{Sld!cfy+*eMLhs$H-TzQtfP<~imBR?zemru)$@_D(l z(p`yH5|kl|sHlpiq${J9+mso~Cd{l3Dbdi5x2hFt6{v5AdQ3g3Mr!S$8AZ*n-KRaI z0PUJMsgL!EsW>8h!!`xbK16K!W zdXPKHo#Z<3y?Hl3h*$U=-p@bGui@A8hxotp-||g75n_bSf=h4r9;;yB>$Md^U_CAho?@Rli0mi_W3$j)5QTDTgc#;Go6 zR+*trR`b;&%q|zI535f>0vu4!sROlitw^iTmTTxxEcT+{!ts9+b_w|>oo7F3e_(%Pe+oJxt`JH_;FW8j!7NbD6mZN!=1JxS<}KzU<`nZY z(+%211Le$P7qV;EUF;WZEZ3d$0xwT z{3CoVzk%P(Z{_RwZTxorE8r%VLFpOg zW#xbpp$=AUb(}iI={22Czot&q=40J}TCK0g%<*;okbXipjnSAL-C@iy z=71`;7>A7$Muz!E^Qh^v?zbMY&{1rw+lxywvyzF2{(75Zd6`e+Z|28il@SZ6a8%&L z8^x7aPpp*kF&0g7oWg)gM=8^kGNlqT+6Te^o0S)o-B<~HtbC&clzu9w%4(+SQ47>N z)H&)s>NfSynCl)>&#N7@9$G)l>$0>-T8TDSTckazZP8xV_M#8Rp>vzG2)(0zjow?o z0drwlAE_7U<@()vwZ2Y|K`#XJW^)uYXQ{aebEOcg9p*77ZIT>^0!jqu|wZoD1tG4?m6<1VhNenrS?E)-T*8JP4kB0{of)x+@fmv2OB&$bQD2WWQz`*`L{t+-_*e7x*vu48bQnAS{Cf z`dNqMi9;CDK}Hqx3#zA^CE(yhZ*+Zl^S$MaR^`YCTpVd(_v} z?dtRDR&|qFi*?!xbt$yWz3N)s2L%9g6jwhLunf`qxK|SG%dPYP1@r zUQn8p@35-*N;$3^RSqieLwfC2b|^1mzOzNypsZC^Da)0`%0dPGD#KnhTxMehvew=T zeX$TLj~&`RtsXRRL^}pLIEfYE8Ld$}2YP7Mh#scr={xi-Sgq9AFWSp(I`^e>-c=M& I|0eD~0V9dMbpQYW literal 0 HcmV?d00001 diff --git a/Tools/zxcc/zxcc.html b/Tools/zxcc/zxcc.html new file mode 100644 index 00000000..502d8777 --- /dev/null +++ b/Tools/zxcc/zxcc.html @@ -0,0 +1,200 @@ +zxcc v0.5.7 + +

zxcc v0.5.7

+ +

zxcc is a wrapper for the Hi-Tech C CP/M compiler, allowing it to +be used as a cross-compiler under UNIX. Version 0.5.0 also works with the build +tools necessary to assemble CP/M 3 (MAC, RMAC, LINK, GENCOM). + +

New in this version: +

    +
  • Compiles on boxes where sync() does not return int (reported by multiple +users). +
  • BDOS function 10 takes a pointer to unsigned char, thus allowing input +buffers longer than 128 bytes (Andy Parkins) +
+ +

Setting up

+ +

Previous versions of ZXCC could be compiled under DOS using +DJGPP; this may still be possible, but has not been tested since the build +system was changed to use the GNU autotools. + +

This version of zxcc contains copies of the CPMIO and CPMREDIR libraries, +so you won't need to obtain them separately. + +

You will need the tools you want to use; either the Hi-Tech C compiler for +CP/M <http://www.hitech.com.au> + +or Digital Research's tools at + +<http://www.cpm.z80.de> + +Once you have obtained the tools, documentation and possibly the library +source, you need to decide where to put the files. zxcc uses +three directories: + +

    +
  • BINDIR80 (by default, /usr/local/lib/cpm/bin80) + holds the compiler itself. You should copy the compiler .com files + (or MAC, RMAC etc.) and bios.bin to this directory. +
  • LIBDIR80 (by default, /usr/local/lib/cpm/lib80) + holds the C libraries libc.lib, libf.lib, crtcpm.obj and rrtcpm.obj. +
  • INCDIR80 (by default, /usr/local/lib/cpm/include80) + holds the compiler .h files. +
+ +

The locations of these directories are normally set by the configure +script; you can override them by editing zxcc.h and uncommenting the lines +that redefine them. + +

Once you have installed zxcc and the build tools, try +building Hello World: + +

+#include <stdio.h>
+void main()
+{
+ printf("Hello World\n");
+}
+
+ +or for RMAC: + +
+ CSEG
+
+ LXI D,HELLO
+ MVI C,9
+ CALL 5
+ RST 0
+
+HELLO: DB 'Hello World',13,10,'$' + +
+ +

To compile the first example, type

zxc hello.c
; if +all goes well, you should end up with a file called hello.com. You can +test the resulting file by typing
zxcc hello.com
. + +

To assemble the second example, type +

+ zxcc rmac.com hello
+ zxcc link.com hello +
+and run it as above. NOTE: RMAC requires that lines be terminated with CR/LF. +You may need to put a unix2dos command in your makefile before you invoke RMAC. + +

Using zxcc

+ +

For detailed instructions, see the documentation for Hi-Tech C or +the CP/M tools. zxcc behaves in the same way, but note the +following points: + +

Program names

+ +

The names of the programs have been changed between CP/M and UNIX; for +example, you would type

zxc hello.c
instead of +
c hello.c
. The programs to use are: + +
+
zxc
The equivalent of C.COM. +
zxas
The equivalent of ZAS.COM. +
zxlink
The equivalent of LINK.COM. +
zxlibr
The equivalent of LIBR.COM. +
+ +

All these programs work by converting their arguments to a form suitable +for zxcc, and then invoking zxcc. + +

There are no front-end programs for the CP/M build tools; you will have to +enter arguments to these in the zxcc format given below. + +

Filenames

+ +

Where the documentation allows you to enter a CP/M filename, you should +instead enter a UNIX one. The filename itself (as opposed to any directories in +its path) must obey CP/M 8.3 naming conventions and be all lowercase. +

Where the documentation requires a CP/M driveletter / user number +

-I2:C:
you should enter a path complete with + trailing slash:
-I/usr/src/linux-80/include/
+ +

Technical

+ +

zxcc emulates a subset of CP/M 3; hopefully enough to run the +Hi-Tech C compiler. It can be used as a limited general-purpose CP/M 3 +emulator provided the emulated program only uses a restricted subset of +system calls. +

zxcc behaves like the emulator com, allowing CP/M +programs to be used transparently from a UNIX prompt. However com: +

    +
  • Emulates all of CP/M 2, rather than a subset of CP/M 3; +
  • Is designed for general use, not tailored to Hi-Tech C; +
  • Is written partly in assembly language and will only run on 68000-based +computers; +
  • Cannot map UNIX directories to CP/M drives; +
  • Contains some bugs connected with command parsing and file I/O. +
+ +

Syntax for zxcc is: + +

+ zxcc comfile.com arg1 arg2 ... +
+ +

The comfile is the program to run; zxcc searches the current +directory and BINDIR80 for it. +

The arguments are parsed in this way: + +

    +
  • Any argument starting with a - sign is passed to the CP/M program as-is, + minus the leading - sign. +
  • Any argument starting with a + sign is parsed as a filename (see below) + and then concatenated to the previous argument. +
  • Any argument starting "+-" is concatenated without being parsed. +
  • All other arguments are parsed as filenames. The UNIX pathname is + converted to a CP/M driveletter. +
+

For example: +

+ zxcc foo.com --Q -A /dev/null --I +/dev/zero +-, +/foo/bar +
+would pass these arguments to foo.com: +
+ -Q A d:null -Id:zero,e:bar +
+ +

The other programs are merely wrappers that convert their command lines +into the form required by zxcc. + +

Errors

+ +

Any errors raised by the zxcc runtime system will be prefixed +with zxcc:. Some errors you may encounter are: + +

+
Unsupported BDOS call +
Part of CP/M 3 that the program uses has not been emulated. Add the +required functionality to zxbdos.c and recompile. +
Z80 encountered invalid trap +
The CP/M program being run attempted to call the zxcc runtime +system with an unknown call number. This will happen if the program was +written for my emulator "Joyce". +
+

Acknowledgements

+ +
    +
  • Hi-Tech C was written by Hi-Tech Software. +
  • The Z80 emulation engine was written by Ian Collier. +
  • Thanks to Jacob Nevins, Andy Parkins and others for bug fix suggestions. +
+
+
John Elliott, 28 March 2003
+ + diff --git a/Tools/zxcc/zxccdbg.exe b/Tools/zxcc/zxccdbg.exe new file mode 100644 index 0000000000000000000000000000000000000000..543aac00e58689b1c57506603e428e465ae1524e GIT binary patch literal 104448 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%0AN*q4Ll&#@ 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 Date: Thu, 10 Feb 2022 17:23:24 -0800 Subject: [PATCH 13/34] Update config.h.darwin --- Tools/unix/zxcc/config.h.darwin | 1 + 1 file changed, 1 insertion(+) diff --git a/Tools/unix/zxcc/config.h.darwin b/Tools/unix/zxcc/config.h.darwin index b3df1720..6ed6f3d1 100644 --- a/Tools/unix/zxcc/config.h.darwin +++ b/Tools/unix/zxcc/config.h.darwin @@ -2,5 +2,6 @@ #define HAVE_UTIME_H #define HAVE_FCNTL_H #define HAVE_UNISTD_H +#define HAVE_STRING_H #define DARWIN //#define FILETRACKER 1 From d599a3d57b332f1c93ac6f76b2bedb5718713adf Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Thu, 10 Feb 2022 17:33:02 -0800 Subject: [PATCH 14/34] Update config.h.darwin --- Tools/unix/zxcc/config.h.darwin | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tools/unix/zxcc/config.h.darwin b/Tools/unix/zxcc/config.h.darwin index 6ed6f3d1..3a1ec05c 100644 --- a/Tools/unix/zxcc/config.h.darwin +++ b/Tools/unix/zxcc/config.h.darwin @@ -1,7 +1,8 @@ +#define HAVE_STDLIB_H +#define HAVE_STRING_H #define HAVE_DIRENT_H #define HAVE_UTIME_H #define HAVE_FCNTL_H #define HAVE_UNISTD_H -#define HAVE_STRING_H #define DARWIN //#define FILETRACKER 1 From 1b8e88e1a20ca869e9233cddddb99a864304f707 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Thu, 10 Feb 2022 17:41:44 -0800 Subject: [PATCH 15/34] Update zxcbdos.c --- Tools/unix/zxcc/zxcbdos.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Tools/unix/zxcc/zxcbdos.c b/Tools/unix/zxcc/zxcbdos.c index e3eb1f2f..46cc8d0b 100644 --- a/Tools/unix/zxcc/zxcbdos.c +++ b/Tools/unix/zxcc/zxcbdos.c @@ -2,6 +2,10 @@ #include "zxbdos.h" #include "zxcbdos.h" +#ifndef _WIN32 +#include +#endif + #ifdef _WIN32 #include #endif From c5043d66f92f7f5a5b9785292a6fea61c68a302e Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Thu, 10 Feb 2022 18:21:57 -0800 Subject: [PATCH 16/34] Final ZXCC Cleanup Honestly, ZXCC still deserves a lot of refactoring, but this will need to do for now. --- Readme.unix | 9 ++++++--- Tools/unix/zxcc/{readme.txt => ReadMe.txt} | 0 Tools/zxcc/zxcc-src.zip | Bin 69549 -> 69571 bytes Tools/zxcc/zxcc.exe | Bin 95744 -> 95744 bytes Tools/zxcc/zxccdbg.exe | Bin 104448 -> 104448 bytes 5 files changed, 6 insertions(+), 3 deletions(-) rename Tools/unix/zxcc/{readme.txt => ReadMe.txt} (100%) diff --git a/Readme.unix b/Readme.unix index dbcf93b7..8814e28c 100644 --- a/Readme.unix +++ b/Readme.unix @@ -19,10 +19,14 @@ with respect to the .DS directive. it's usually a bad idea to mix It assumes that you have some standard system tools and libraries installed, specifically: gcc, gnu make, libncurses, and srecord. Typically, something like this will take care of adding all -required packages: +required packages in Linux: sudo apt install build-essential libncurses-dev srecord +For MacOS, you will need: + + brew install srecord + To build: cd to the top directory and type "make". @@ -40,8 +44,7 @@ the "SCZ180" platform: make ROM_PLATFORM=SCZ180 ROM_CONFIG=126 -Please be aware that the make-based build does have a couple of -deficiencies. +Please be aware that the make-based build does have a few deficiencies. First and most important, the Makefiles do not handle reruns very well. To ensure a full buld, use "make clobber" from the top level directory diff --git a/Tools/unix/zxcc/readme.txt b/Tools/unix/zxcc/ReadMe.txt similarity index 100% rename from Tools/unix/zxcc/readme.txt rename to Tools/unix/zxcc/ReadMe.txt diff --git a/Tools/zxcc/zxcc-src.zip b/Tools/zxcc/zxcc-src.zip index 16bedad54b5b901c188b9e649c5088963527bb78..1ae919e4f1fcd045b48e6ffa8caeda9192de8000 100644 GIT binary patch delta 1798 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 FzX2mg)};Ud diff --git a/Tools/zxcc/zxcc.exe b/Tools/zxcc/zxcc.exe index 54681729808f2e75d650385f6acb9dca08afb9fd..c51614dac121daab13358f7d735a921b4ffbd607 100644 GIT binary patch delta 18 ZcmZp8!`kqMbwUTzouiFiTe}#`N&!|M2-E-o delta 18 ZcmZp8!`kqMbwUS|OnhV4)-J}fQUFXZ2d)4B diff --git a/Tools/zxcc/zxccdbg.exe b/Tools/zxcc/zxccdbg.exe index 543aac00e58689b1c57506603e428e465ae1524e..f5f2adfb8acfd1e9e4fbee36af8e407e5bc4b3ce 100644 GIT binary patch delta 18 acmZqJz}B#VZ9)gry`zm?Te}#`rUL*^EC_-C delta 18 ZcmZqJz}B#VZ9)f=e0*cq)-J}f=>SDV2VDRF From 2c0b818abad30349774e935fd3c43b63018b6d9a Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Mon, 14 Feb 2022 13:36:06 -0800 Subject: [PATCH 17/34] ZXCC Cleanup - I know I said I was done, but I found some more stuff to clean up. I think I am really done now. --- Binary/Apps/Makefile | 2 +- Tools/unix/zxcc/Build-VC.cmd | 6 +- Tools/unix/zxcc/COPYING | 678 +++++----- Tools/unix/zxcc/cbops.h | 242 ++-- Tools/unix/zxcc/config.h.windows | 5 + Tools/unix/zxcc/cpmdrv.c | 368 +++--- Tools/unix/zxcc/cpmglob.c | 1188 +++++++++--------- Tools/unix/zxcc/cpmint.h | 523 ++++---- Tools/unix/zxcc/cpmparse.c | 206 ++-- Tools/unix/zxcc/cpmredir.c | 1971 +++++++++++++++--------------- Tools/unix/zxcc/cpmredir.h | 301 +++-- Tools/unix/zxcc/dirent.c | 221 ++-- Tools/unix/zxcc/dirent.h | 48 +- Tools/unix/zxcc/drdos.c | 96 +- Tools/unix/zxcc/track.c | 48 +- Tools/unix/zxcc/util.c | 892 +++++++------- Tools/unix/zxcc/xlt.c | 312 +++-- Tools/unix/zxcc/z80.c | 2 +- Tools/unix/zxcc/z80.h | 34 +- Tools/unix/zxcc/zxbdos.c | 1112 +++++++++-------- Tools/unix/zxcc/zxbdos.h | 99 +- Tools/unix/zxcc/zxcbdos.c | 299 +++-- Tools/unix/zxcc/zxcbdos.h | 10 +- Tools/unix/zxcc/zxcc.c | 1096 +++++++++-------- Tools/unix/zxcc/zxcc.h | 267 ++-- Tools/unix/zxcc/zxdbdos.c | 62 +- Tools/unix/zxcc/zxdbdos.h | 12 +- Tools/zxcc/COPYING | 678 +++++----- Tools/zxcc/zxcc-src.zip | Bin 69571 -> 70311 bytes Tools/zxcc/zxcc.exe | Bin 95744 -> 96256 bytes Tools/zxcc/zxccdbg.exe | Bin 104448 -> 120320 bytes 31 files changed, 5449 insertions(+), 5329 deletions(-) diff --git a/Binary/Apps/Makefile b/Binary/Apps/Makefile index 20ebfc63..0b913750 100644 --- a/Binary/Apps/Makefile +++ b/Binary/Apps/Makefile @@ -8,4 +8,4 @@ all:: mkdir -p Tunes clobber:: - @rm -f *.bin *.com *.img *.rom *.pdf *.log *.eeprom *.ovr *.hlp *.doc *.COM *.BIN Tunes/*.mym Tunes/*.pt? + @rm -f *.bin *.com *.img *.rom *.pdf *.log *.eeprom *.ovr *.hlp *.doc *.COM *.BIN Tunes/*.mym Tunes/*.pt? Tunes/*.vgm diff --git a/Tools/unix/zxcc/Build-VC.cmd b/Tools/unix/zxcc/Build-VC.cmd index 2d199c6d..b9383633 100644 --- a/Tools/unix/zxcc/Build-VC.cmd +++ b/Tools/unix/zxcc/Build-VC.cmd @@ -5,7 +5,7 @@ setlocal :: Visual Studio x86 Native Tools Command Prompt is assumed :: -:: Below configures VS2012 to target Windows XP and beyond +:: Below configures VS2012 to target Windows XP. :: Not sure if it will work in later versions of VS, but seems :: to do no harm. set INCLUDE=%ProgramFiles(x86)%\Microsoft SDKs\Windows\7.1A\Include;%INCLUDE% @@ -16,10 +16,10 @@ set LINK=/SUBSYSTEM:CONSOLE,5.01 %LINK% copy config.h.windows config.h -cl zxcc.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c dirent.c track.c +cl -I. zxcc.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c dirent.c track.c if errorlevel 1 exit /b 255 -cl /DDEBUG /Fe"zxccdbg.exe" zxcc.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c dirent.c track.c +cl -I. /DDEBUG /Fe"zxccdbg.exe" zxcc.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c dirent.c track.c if errorlevel 1 exit /b 255 copy cpm\bios.bin . \ No newline at end of file diff --git a/Tools/unix/zxcc/COPYING b/Tools/unix/zxcc/COPYING index a43ea212..92851102 100644 --- a/Tools/unix/zxcc/COPYING +++ b/Tools/unix/zxcc/COPYING @@ -1,339 +1,339 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - Appendix: How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Tools/unix/zxcc/cbops.h b/Tools/unix/zxcc/cbops.h index f583e3a8..6772b004 100644 --- a/Tools/unix/zxcc/cbops.h +++ b/Tools/unix/zxcc/cbops.h @@ -33,128 +33,128 @@ #define res(n,x) (x&=~(1<>3)&7; - switch(op&0xc7){ - case 0x40: bit(n,b); break; - case 0x41: bit(n,c); break; - case 0x42: bit(n,d); break; - case 0x43: bit(n,e); break; - case 0x44: bit(n,h); break; - case 0x45: bit(n,l); break; - case 0x46: tstates+=4;val=fetch(addr);bit(n,val);store(addr,val);break; - case 0x47: bit(n,a); break; - case 0x80: res(n,b); break; - case 0x81: res(n,c); break; - case 0x82: res(n,d); break; - case 0x83: res(n,e); break; - case 0x84: res(n,h); break; - case 0x85: res(n,l); break; - case 0x86: tstates+=4;val=fetch(addr);res(n,val);store(addr,val);break; - case 0x87: res(n,a); break; - case 0xc0: set(n,b); break; - case 0xc1: set(n,c); break; - case 0xc2: set(n,d); break; - case 0xc3: set(n,e); break; - case 0xc4: set(n,h); break; - case 0xc5: set(n,l); break; - case 0xc6: tstates+=4;val=fetch(addr);set(n,val);store(addr,val);break; - case 0xc7: set(n,a); break; - } - } - if(ixoriy)switch(reg){ - case 0:b=val; break; - case 1:c=val; break; - case 2:d=val; break; - case 3:e=val; break; - case 4:h=val; break; - case 5:l=val; break; - case 7:a=val; break; - } +if (op < 64)switch (op) { +case 0: rlc(b); break; +case 1: rlc(c); break; +case 2: rlc(d); break; +case 3: rlc(e); break; +case 4: rlc(h); break; +case 5: rlc(l); break; +case 6: tstates += 7; val = fetch(addr); rlc(val); store(addr, val); break; +case 7: rlc(a); break; +case 8: rrc(b); break; +case 9: rrc(c); break; +case 10: rrc(d); break; +case 11: rrc(e); break; +case 12: rrc(h); break; +case 13: rrc(l); break; +case 14: tstates += 7; val = fetch(addr); rrc(val); store(addr, val); break; +case 15: rrc(a); break; +case 0x10: rl(b); break; +case 0x11: rl(c); break; +case 0x12: rl(d); break; +case 0x13: rl(e); break; +case 0x14: rl(h); break; +case 0x15: rl(l); break; +case 0x16: tstates += 7; val = fetch(addr); rl(val); store(addr, val); break; +case 0x17: rl(a); break; +case 0x18: rr(b); break; +case 0x19: rr(c); break; +case 0x1a: rr(d); break; +case 0x1b: rr(e); break; +case 0x1c: rr(h); break; +case 0x1d: rr(l); break; +case 0x1e: tstates += 7; val = fetch(addr); rr(val); store(addr, val); break; +case 0x1f: rr(a); break; +case 0x20: sla(b); break; +case 0x21: sla(c); break; +case 0x22: sla(d); break; +case 0x23: sla(e); break; +case 0x24: sla(h); break; +case 0x25: sla(l); break; +case 0x26: tstates += 7; val = fetch(addr); sla(val); store(addr, val); break; +case 0x27: sla(a); break; +case 0x28: sra(b); break; +case 0x29: sra(c); break; +case 0x2a: sra(d); break; +case 0x2b: sra(e); break; +case 0x2c: sra(h); break; +case 0x2d: sra(l); break; +case 0x2e: tstates += 7; val = fetch(addr); sra(val); store(addr, val); break; +case 0x2f: sra(a); break; +case 0x30: sll(b); break; +case 0x31: sll(c); break; +case 0x32: sll(d); break; +case 0x33: sll(e); break; +case 0x34: sll(h); break; +case 0x35: sll(l); break; +case 0x36: tstates += 7; val = fetch(addr); sll(val); store(addr, val); break; +case 0x37: sll(a); break; +case 0x38: srl(b); break; +case 0x39: srl(c); break; +case 0x3a: srl(d); break; +case 0x3b: srl(e); break; +case 0x3c: srl(h); break; +case 0x3d: srl(l); break; +case 0x3e: tstates += 7; val = fetch(addr); srl(val); store(addr, val); break; +case 0x3f: srl(a); break; +} +else { + unsigned char n = (op >> 3) & 7; + switch (op & 0xc7) { + case 0x40: bit(n, b); break; + case 0x41: bit(n, c); break; + case 0x42: bit(n, d); break; + case 0x43: bit(n, e); break; + case 0x44: bit(n, h); break; + case 0x45: bit(n, l); break; + case 0x46: tstates += 4; val = fetch(addr); bit(n, val); store(addr, val); break; + case 0x47: bit(n, a); break; + case 0x80: res(n, b); break; + case 0x81: res(n, c); break; + case 0x82: res(n, d); break; + case 0x83: res(n, e); break; + case 0x84: res(n, h); break; + case 0x85: res(n, l); break; + case 0x86: tstates += 4; val = fetch(addr); res(n, val); store(addr, val); break; + case 0x87: res(n, a); break; + case 0xc0: set(n, b); break; + case 0xc1: set(n, c); break; + case 0xc2: set(n, d); break; + case 0xc3: set(n, e); break; + case 0xc4: set(n, h); break; + case 0xc5: set(n, l); break; + case 0xc6: tstates += 4; val = fetch(addr); set(n, val); store(addr, val); break; + case 0xc7: set(n, a); break; + } +} +if (ixoriy)switch (reg) { +case 0:b = val; break; +case 1:c = val; break; +case 2:d = val; break; +case 3:e = val; break; +case 4:h = val; break; +case 5:l = val; break; +case 7:a = val; break; +} } #undef var_t diff --git a/Tools/unix/zxcc/config.h.windows b/Tools/unix/zxcc/config.h.windows index 1b838310..0f256eac 100644 --- a/Tools/unix/zxcc/config.h.windows +++ b/Tools/unix/zxcc/config.h.windows @@ -1,5 +1,10 @@ #define HAVE_WINDOWS_H #define HAVE_FCNTL_H +#ifdef _MSC_VER + #define HAVE_DIRENT_H +#endif +#define HAVE_DIRECT_H +#define HAVE_IO_H #define WINVER _WIN32_WINNT_WINXP // target Windows XP #define _WIN32_WINNT _WIN32_WINNT_WINXP // target Windows XP //#define FILETRACKER 1 diff --git a/Tools/unix/zxcc/cpmdrv.c b/Tools/unix/zxcc/cpmdrv.c index 8dcd8889..691e774f 100644 --- a/Tools/unix/zxcc/cpmdrv.c +++ b/Tools/unix/zxcc/cpmdrv.c @@ -1,186 +1,182 @@ -/* - - CPMREDIR: CP/M filesystem redirector - Copyright (C) 1998,2003 John Elliott - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - This file deals with drive-based functions. -*/ - -#include "cpmint.h" - -#ifdef _WIN32 -static char *drive_to_hostdrive(int cpm_drive) -{ - static char prefix[CPM_MAXPATH]; - char *lpfp; - dword dw; - - if (!redir_drive_prefix[cpm_drive]) return NULL; - dw = GetFullPathName(redir_drive_prefix[cpm_drive], sizeof(prefix), - prefix, &lpfp); - - if (!dw) return NULL; - if (prefix[1] == ':') /* If path starts with a drive, limit it */ - { /* to just that drive */ - prefix[2] = '\\'; /* GetDiskFreeSpace should have trailing backslash */ - prefix[3] = 0; - } - return prefix; -} -#endif - - -cpm_byte fcb_reset(void) -{ -#ifdef __MSDOS__ - bdos(0x0D, 0, 0); -#endif - - redir_l_drives = 0; - redir_cpmdrive = 0; /* A reset forces current drive to A: */ -/* redir_ro_drives = 0; Software write protect not revoked by func 0Dh. - * - * This does not follow true CP/M, but does match many 3rd-party replacements. - */ - return 0; -} - - -cpm_word fcb_drive (cpm_byte drv) -{ - if (redir_drive_prefix[drv][0]) - { - redir_cpmdrive = drv; - redir_log_drv(drv); - return 0; - } - else return 0x04FF; /* Drive doesn't exist */ -} - -cpm_byte fcb_getdrv(void) -{ - return redir_cpmdrive; -} - - -cpm_byte fcb_user (cpm_byte usr) -{ - if (usr != 0xFF) redir_cpmuser = usr % 16; - - redir_Msg("User: parameter %d returns %d\r\n", usr, redir_cpmuser); - - return redir_cpmuser; -} - - - -cpm_word fcb_logvec(void) -{ - return redir_l_drives; -} - - -cpm_word fcb_rovec(void) -{ - return redir_ro_drives; -} - - -cpm_word fcb_rodisk(void) -{ - cpm_word mask = 1; - - if (redir_cpmdrive) mask = mask << redir_cpmdrive; - - redir_ro_drives |= mask; - return 0; -} - - -cpm_word fcb_resro(cpm_word bitmap) -{ - redir_ro_drives &= ~bitmap; - - return 0; -} - - -cpm_word fcb_sync(cpm_byte flag) -{ -#ifdef _WIN32 - return 0; -#else - sync(); return 0; /* Apparently some sync()s are void not int */ -#endif -} - - -cpm_word fcb_purge() -{ -#ifdef _WIN32 - return 0; -#else - sync(); return 0; /* Apparently some sync()s are void not int */ -#endif -} - -/* Generic 8MB disk definition */ - -static cpm_byte exdpb[0x11] = { - 0x80, 0, /* 128 records/track */ - 0x04, 0x0F, /* 2k blocks */ - 0x00, /* 16k / extent */ - 0xFF, 0x0F, /* 4095 blocks */ - 0xFF, 0x03, /* 1024 dir entries */ - 0xFF, 0xFF, /* 16 directory blocks */ - 0x00, 0x80, /* Non-removable media */ - 0x00, 0x00, /* No system tracks */ - 0x02, 0x03 /* 512-byte sectors */ -}; - -cpm_word fcb_getdpb(cpm_byte *dpb) -{ - /* Return the example dpb */ - memcpy(dpb, &exdpb, 0x11); - return 0x11; -} - - -/* Create an entirely bogus ALV - * TODO: Make it a bit better */ - -cpm_word fcb_getalv(cpm_byte *alv, cpm_word max) -{ - if (max > 1024) max = 1024; - - memset(alv, 0xFF, max / 2); - memset(alv + (max / 2), 0, max / 2); - - return max; -} - -/* Get disk free space */ - -cpm_word fcb_dfree (cpm_byte drive, cpm_byte *dma) -{ - /* Return half of disk capacity */ - redir_wr24(dma, 0x8000L); /* 8MB / 128 / 2 */ - return 0; -} - - - +/* + + CPMREDIR: CP/M filesystem redirector + Copyright (C) 1998,2003 John Elliott + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + This file deals with drive-based functions. +*/ + +#include "cpmint.h" + +#ifdef _WIN32 +static char* drive_to_hostdrive(int cpm_drive) +{ + static char prefix[CPM_MAXPATH]; + char* lpfp; + dword dw; + + if (!redir_drive_prefix[cpm_drive]) return NULL; + dw = GetFullPathName(redir_drive_prefix[cpm_drive], sizeof(prefix), + prefix, &lpfp); + + if (!dw) return NULL; + if (prefix[1] == ':') /* If path starts with a drive, limit it */ + { /* to just that drive */ + prefix[2] = '\\'; /* GetDiskFreeSpace should have trailing backslash */ + prefix[3] = 0; + } + return prefix; +} +#endif + + +cpm_byte fcb_reset(void) +{ +#ifdef __MSDOS__ + bdos(0x0D, 0, 0); +#endif + + redir_l_drives = 0; + redir_cpmdrive = 0; /* A reset forces current drive to A: */ +/* redir_ro_drives = 0; Software write protect not revoked by func 0Dh. + * + * This does not follow true CP/M, but does match many 3rd-party replacements. + */ + return 0; +} + + +cpm_word fcb_drive(cpm_byte drv) +{ + if (redir_drive_prefix[drv][0]) + { + redir_cpmdrive = drv; + redir_log_drv(drv); + return 0; + } + else return 0x04FF; /* Drive doesn't exist */ +} + +cpm_byte fcb_getdrv(void) +{ + return redir_cpmdrive; +} + + +cpm_byte fcb_user(cpm_byte usr) +{ + if (usr != 0xFF) redir_cpmuser = usr % 16; + + DBGMSGV("User: parameter %d returns %d\n", usr, redir_cpmuser); + + return redir_cpmuser; +} + + + +cpm_word fcb_logvec(void) +{ + return redir_l_drives; +} + + +cpm_word fcb_rovec(void) +{ + return redir_ro_drives; +} + + +cpm_word fcb_rodisk(void) +{ + cpm_word mask = 1; + + if (redir_cpmdrive) mask = mask << redir_cpmdrive; + + redir_ro_drives |= mask; + return 0; +} + + +cpm_word fcb_resro(cpm_word bitmap) +{ + redir_ro_drives &= ~bitmap; + + return 0; +} + + +cpm_word fcb_sync(cpm_byte flag) +{ +#ifdef _WIN32 + return 0; +#else + sync(); return 0; /* Apparently some sync()s are void not int */ +#endif +} + + +cpm_word fcb_purge() +{ +#ifdef _WIN32 + return 0; +#else + sync(); return 0; /* Apparently some sync()s are void not int */ +#endif +} + +/* Generic 8MB disk definition */ + +static cpm_byte exdpb[0x11] = { + 0x80, 0, /* 128 records/track */ + 0x04, 0x0F, /* 2k blocks */ + 0x00, /* 16k / extent */ + 0xFF, 0x0F, /* 4095 blocks */ + 0xFF, 0x03, /* 1024 dir entries */ + 0xFF, 0xFF, /* 16 directory blocks */ + 0x00, 0x80, /* Non-removable media */ + 0x00, 0x00, /* No system tracks */ + 0x02, 0x03 /* 512-byte sectors */ +}; + +cpm_word fcb_getdpb(cpm_byte* dpb) +{ + /* Return the example dpb */ + memcpy(dpb, &exdpb, 0x11); + return 0x11; +} + +/* Create an entirely bogus ALV + * TODO: Make it a bit better */ + +cpm_word fcb_getalv(cpm_byte* alv, cpm_word max) +{ + if (max > 1024) max = 1024; + + memset(alv, 0xFF, max / 2); + memset(alv + (max / 2), 0, max / 2); + + return max; +} + +/* Get disk free space */ + +cpm_word fcb_dfree(cpm_byte drive, cpm_byte* dma) +{ + /* Return half of disk capacity */ + redir_wr24(dma, 0x8000L); /* 8MB / 128 / 2 */ + return 0; +} diff --git a/Tools/unix/zxcc/cpmglob.c b/Tools/unix/zxcc/cpmglob.c index dadae255..3705b05e 100644 --- a/Tools/unix/zxcc/cpmglob.c +++ b/Tools/unix/zxcc/cpmglob.c @@ -1,590 +1,598 @@ -/* - - CPMREDIR: CP/M filesystem redirector - Copyright (C) 1998, John Elliott - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - This file implements those BDOS functions that use wildcard expansion. -*/ - -#include "cpmint.h" -#ifdef _MSC_VER -#define S_ISDIR(mode) (((mode) & _S_IFDIR) != 0) -#endif - - -static cpm_byte *find_fcb; -static int find_n; -static int find_ext = 0; -static int find_xfcb = 0; -static int entryno; -static cpm_byte lastdma[0x80]; -static long lastsize; -static char target_name[CPM_MAXPATH]; - -static char upper(char c) -{ - if (islower(c)) return toupper(c); - return c; -} - -/* - * we need to handle case sensitive filesystems correctly. - * underlying files need to just work, irrespective if the files - * in the native filesystem are mixed, upper or lower. - * the naive code in the distributed zx will not work everywhere. - */ - -/* Does the string "s" match the CP/M FCB? */ -/* pattern[0-10] will become a CP/M name parsed from "s" if it matches. */ -/* If 1st byte of FCB is '?' then anything matches. */ - -static int cpm_match(char *s, cpm_byte *fcb, cpm_byte *pattern) -{ - int n; - size_t m; - char *dotpos; - - m = strlen(s); - - /* - * let's cook the filename into something that we can match against - * the fcb. we reject any that can't be valid cp/m filenames, - * normalizing case as we go. all this goes into 'pattern' - */ - for (n = 0; n < 11; n++) pattern[n] = ' '; - - /* The name must have 1 or 0 dots */ - dotpos = strchr(s, '.'); - if (!dotpos) { /* No dot. The name must be at most 8 characters */ - if (m > 8) return 0; - for (n = 0; n < m; n++) { - pattern[n] = upper(s[n]) & 0x7F; - } - } else { /* at least one dot */ - if (strchr(dotpos + 1, '.')) { /* More than 1 dot */ - return 0; - } - if (dotpos == s) { /* Dot right at the beginning */ - return 0; - } - if ((dotpos - s) > 8) { /* "name" > 8 characters */ - return 0; - } - if (strlen(dotpos + 1) > 3) { /* "type" > 3 characters */ - return 0; - } - for (n = 0; n < (dotpos - s); n++) { /* copy filename portion */ - pattern[n] = upper(s[n]) & 0x7F; - } - m = strlen(dotpos + 1); - for (n = 0; n < m; n++) { /* copy extention portion */ - pattern[n + 8] = upper(dotpos[n + 1]) & 0x7F; - } - } - - /* - * handle special case where fcb[0] == '?' or fcb[0] & 0x80 - * this is used to return a full directory list on bdos's - */ - if (((fcb[0] & 0x7F) == '?') || (fcb[0] & 0x80)) { - return 1; - } - for (n = 0; n < 11; n++) - { - if (fcb[n+1] == '?') continue; - if ((pattern[n] & 0x7F) != (fcb[n+1] & 0x7F)) - { - return 0; - } - } - return 1; /* Success! */ -} - - -/* Get the next entry from the host's directory matching "fcb" */ - -static struct dirent * next_entry(DIR *dir, cpm_byte *fcb, cpm_byte *pattern, - struct stat *st) -{ - struct dirent *en; - int unsatisfied; - int drv = fcb[0] & 0x7F; - - if (drv == '?') drv = 0; - if (!drv) drv = redir_cpmdrive; - else drv--; - - for (unsatisfied = 1; unsatisfied; ) - { - /* 1. Get the next entry */ - - en = readdir(dir); - if (!en) return NULL; /* No next entry */ - ++entryno; /* 0 for 1st, 1 for 2nd, etc. */ - - /* 2. See if it matches. We do this first (in preference to - seeing if it's a subdirectory first) because it doesn't - require disc access */ - if (!cpm_match(en->d_name, fcb, pattern)) - { - continue; - } - /* 3. Stat it, & reject it if it's a directory */ - - strcpy(target_name, redir_drive_prefix[drv]); - strcat(target_name, en->d_name); - - if (stat(target_name, st)) - { - redir_Msg("Can't stat %s so omitting it.\n", target_name); - continue; /* Can't stat */ - } - if (S_ISDIR(st->st_mode)) - { - /* Searching for files only */ - if (fcb[0] != '?' && fcb[0] < 0x80) - { - continue; - } - } - unsatisfied = 0; - } - return en; -} - - - -void volume_label(int drv, cpm_byte *dma) -{ - struct stat st; - - memset(dma, 0x20, 12); /* Volume label */ - - /* Get label name */ - redir_get_label(drv, (char *)(dma + 1)); - /* [0x0c] = label byte - * [0x0d] = password byte (=0) - * [0x10-0x17] = password - * [0x18] = label create date - * [0x1c] = label update date - */ -#ifdef __MSDOS__ - dma[0x0c] = 0x21; /* Under DOS, only "update" */ - if (redir_drdos) dma[0x0c] |= 0x80; /* Under DRDOS, passwords allowed */ -#else - dma[0x0c] = 0x61; /* Label exists and time stamps allowed */ -#endif /* (update & access) */ - dma[0x0d] = 0; /* Label not passworded */ - dma[0x0f] = 0x80; /* Non-CP/M media */ - - if (stat(redir_drive_prefix[drv], &st)) - { - redir_Msg("stat() fails on '%s'\n", redir_drive_prefix[drv]); - return; - } - - redir_wr32(dma + 0x18, redir_cpmtime(st.st_atime)); - redir_wr32(dma + 0x1C, redir_cpmtime(st.st_mtime)); -} - - - -cpm_word redir_find(int n, cpm_byte *fcb, cpm_byte *dma) -{ - DIR *hostdir; - int drv, attrib; - long recs; - struct stat st; - struct dirent *de; - cpm_word rights; - - drv = (fcb[0] & 0x7F); - if (!drv || drv == '?') drv = redir_cpmdrive; - else drv--; - - if (find_xfcb) /* Return another extent */ - { - memcpy(dma, lastdma, 0x80); - dma[0] |= 0x10; /* XFCB */ - dma[0x0c] = dma[0x69]; /* Password mode */ - dma[0x0d] = 0x0A; /* Password decode byte */ - memset(dma + 0x10, '*', 7); - dma[0x17] = ' '; /* Encoded password */ - memcpy(lastdma, dma, 0x80); - - find_xfcb = 0; - return 0; - } - - if (find_ext) /* Return another extent */ - { - memcpy(dma, lastdma, 0x80); - dma[0x0c]++; - if (dma[0x0c] == 0x20) - { - dma[0x0c] = 0; - dma[0x0e]++; - } - lastsize -= 0x4000; - recs = (lastsize + 127) / 128; - dma[0x0f] = (recs > 127) ? 0x80 : (recs & 0x7F); - - if (lastsize <= 0x4000) find_ext = 0; - memcpy(lastdma, dma, 0x80); - - return 0; - } - - - memset(dma, 0, 128); /* Zap the buffer */ - - /* - If returning all entries, return a volume label. - */ - if ((fcb[0] & 0x7F) == '?') - { - if (!n) - { - volume_label(drv, dma); - return 0; - } - else --n; - } - - /* Note: This implies that opendir() works on a filename with a - trailing slash. It does under Linux, but that's the only assurance - I can give. - */ - - entryno = -1; - hostdir = opendir(redir_drive_prefix[drv]); - - if (!hostdir) - { - redir_Msg("opendir() fails on '%s'\n", redir_drive_prefix[drv]); - return 0xFF; - } - /* We have a handle to the directory. */ - while (n >= 0) - { - de = next_entry(hostdir, fcb, dma + 1, &st); - if (!de) - { - closedir(hostdir); - return 0xFF; - } - --n; - } - /* Valid entry found & statted. dma+1 holds filename. */ - - dma[0] = redir_cpmuser; /* Uid always matches */ - dma[0x0c] = 0; /* Extent counter, low */ - dma[0x0d] = st.st_size & 0x7F; /* Last record byte count */ - dma[0x0e] = 0; /* Extent counter, high */ - -#ifdef _WIN32 - attrib = GetFileAttributesA(target_name); - rights = redir_drdos_get_rights(target_name); - if (rights && ((fcb[0] & 0x7F) == '?')) find_xfcb = 1; -#else - attrib = 0; - rights = 0; -#endif - if (attrib & 1) dma[9] |= 0x80; /* read only */ - if (attrib & 4) dma[10] |= 0x80; /* system */ - if (!(attrib & 0x20)) dma[11] |= 0x80; /* archive */ - - - -/* TODO: Under Unix, work out correct RO setting */ - - recs = (st.st_size + 127) / 128; - dma[0x0f] = (recs > 127) ? 0x80 : (recs & 0x7F); - dma[0x10] = 0x80; - if (S_ISDIR(st.st_mode)) dma[0x10] |= 0x40; - if (attrib & 2) dma[0x10] |= 0x20; - dma[0x10] |= ((entryno & 0x1FFF) >> 8); - dma[0x11] = dma[0x10]; - dma[0x12] = entryno & 0xFF; - - redir_wr32(dma + 0x16, (dword)st.st_mtime); /* Modification time. */ - /* TODO: It should be in DOS */ - /* format */ - /* TODO: At 0x1A, 1st cluster */ - redir_wr32(dma + 0x1C, st.st_size); /* True size */ - - if (rights) /* Store password mode. Don't return an XFCB. */ - { - dma[0x69] = redir_cpm_pwmode(rights); - memcpy(lastdma, dma, 0x80); - } - - dma[0x60] = 0x21; /* XFCB */ - redir_wr32(dma + 0x61, redir_cpmtime(st.st_atime)); - redir_wr32(dma + 0x65, redir_cpmtime(st.st_mtime)); - - closedir(hostdir); - - if (st.st_size > 0x4000 && (fcb[0x0C] == '?')) /* All extents? */ - { - lastsize = st.st_size; - find_ext = 1; - memcpy(lastdma, dma, 0x80); - } - return 0; -} - - -#ifdef DEBUG -#define SHOWNAME(func) \ - { \ - char fname[CPM_MAXPATH]; \ - redir_fcb2unix(fcb, fname); \ - redir_Msg(func "(\"%s\")\n", fname); \ - } - -#else - #define SHOWNAME(func) -#endif - -cpm_word fcb_find1 (cpm_byte *fcb, cpm_byte *dma) /* 0x11 */ -{ -#ifdef DEBUG - int rv; -#endif - SHOWNAME("fcb_find1") - - redir_log_fcb(fcb); - - find_n = 0; - find_fcb = fcb; - find_ext = 0; - find_xfcb = 0; -#ifdef DEBUG - rv = redir_find(find_n, fcb, dma); - - if (rv < 4) - { - redir_Msg("Ret: %-11.11s\n", dma + 1); - } - else redir_Msg("Ret: Fail\n"); - return rv; -#else - return redir_find(find_n, find_fcb, dma); -#endif -} - -/* We don't bother with the FCB parameter - it's undocmented, and - * programs that do know about it will just pass in the same parameter - * that they did to function 0x11 */ - -cpm_word fcb_find2 (cpm_byte *fcb, cpm_byte *dma) /* 0x12 */ -{ -#ifdef DEBUG - int rv; - - char fname[CPM_MAXPATH]; - redir_fcb2unix(find_fcb, fname); - redir_Msg("fcb_find2(\"%s\") no. %d\n", fname, find_n); -#endif - ++find_n; -#ifdef DEBUG - rv = redir_find(find_n, find_fcb, dma); - - if (rv < 4) - { - redir_Msg("Ret: %-11.11s\n", dma + 1); - } - else redir_Msg("Ret: Fail\n"); - return rv; -#else - return redir_find(find_n, find_fcb, dma); -#endif -} - -/* Under CP/M, unlinking works with wildcards */ - -cpm_word fcb_unlink(cpm_byte *fcb, cpm_byte *dma) -{ - DIR *hostdir; - int drv; - struct dirent *de; - struct stat st; - int handle = 0; - int unpasswd = 0; - char fname[CPM_MAXPATH]; - - SHOWNAME("fcb_unlink") - - if (fcb[5] & 0x80) unpasswd = 1; /* Remove password rather than file */ - - redir_log_fcb(fcb); - - drv = (fcb[0] & 0x7F); - if (!drv || drv == '?') drv = redir_cpmdrive; - else drv--; - - if (redir_ro_drv(drv)) return 0x02FF; /* Error: R/O drive */ - -#ifdef DEBUG - redir_fcb2unix(fcb, fname); - redir_Msg("fcb_unlink(\"%s\")\n", fname); -#endif - - /* Note: This implies that opendir() works on a filename with a - trailing slash. It does under Linux, but that's the only assurance - I can give. - */ - - hostdir = opendir(redir_drive_prefix[drv]); - - if (!hostdir) - { - redir_Msg("opendir() fails on '%s'\n", redir_drive_prefix[drv]); - return 0xFF; - } - /* We have a handle to the directory. */ - do - { - de = next_entry(hostdir, fcb, (cpm_byte *)fname, &st); - if (de) - { - strcpy(target_name, redir_drive_prefix[drv]); - strcat(target_name, de->d_name); - redir_Msg("Deleting %s\n", de->d_name); - if (unpasswd) - { -#ifdef __MSDOS__ - if (redir_drdos) - { - handle = redir_drdos_put_rights (target_name, dma, 0); - } - else handle = 0; -#endif - } - else if (fcb[0] & 0x80) - { - handle = rmdir(target_name); - if (handle && redir_password_error()) - { - redir_password_append(target_name, dma); - handle = rmdir(target_name); - } - } - else - { - releaseFile(target_name); - handle = unlink(target_name); - if (handle && redir_password_error()) - { - redir_password_append(target_name, dma); - releaseFile(target_name); - handle = unlink(target_name); - } - } - - if (handle) de = NULL; /* Delete failed */ - } - } - while (de != NULL); - if (handle) - { - redir_Msg("Ret: -1\n"); - closedir(hostdir); - return 0xFF; - } - redir_Msg("Ret: 0\n"); - closedir(hostdir); - return 0; -} - - - - - -#ifdef __MSDOS__ -cpm_word redir_get_label(cpm_byte drv, char *pattern) -{ - char strs[10]; - struct ffblk fblk; - int done; - char *s; - int n; - - /* We need the drive prefix to be of the form "C:\etc..." */ - - memset(pattern, ' ', 11); - if (!redir_drive_prefix[drv][0] || redir_drive_prefix[drv][1] != ':') - return 0; - - sprintf(strs,"%c:/*.*", redir_drive_prefix[drv][0]); - - done = findfirst(strs, &fblk, FA_LABEL); - while (!done) - { - if ((fblk.ff_attrib & FA_LABEL) && - !(fblk.ff_attrib & (FA_SYSTEM | FA_HIDDEN))) - { - s = strchr(fblk.ff_name, '/'); - if (!s) s = strchr(fblk.ff_name, '\\'); - if (!s) s = strchr(fblk.ff_name, ':'); - if (!s) s = fblk.ff_name; - for (n = 0; n < 11; n++) - { - if (!(*s)) break; - if (*s == '.') - { - n = 7; - ++s; - continue; - } - pattern[n] = upper(*s); - ++s; - } - return 1; - } - done = findnext(&fblk); - } - return 0; -} -#else -cpm_word redir_get_label(cpm_byte drv, char *pattern) -{ - char *dname; - size_t l; - int n; - - memset(pattern, ' ', 11); - - dname = strrchr(redir_drive_prefix[drv], '/'); - if (dname) - { - ++dname; - l = strlen(dname); - if (l > 11) l = 11; - for (n = 0; n < l; n++) pattern[n] = upper(dname[l]); - } - else - { - pattern[0] = '.'; - } - return 0; -} - - - -#endif +/* + + CPMREDIR: CP/M filesystem redirector + Copyright (C) 1998, John Elliott + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + This file implements those BDOS functions that use wildcard expansion. +*/ + +#include "cpmint.h" +#ifdef _MSC_VER + #define S_ISDIR(mode) (((mode) & _S_IFDIR) != 0) +#endif + +static cpm_byte* find_fcb; +static int find_n; +static int find_ext = 0; +static int find_xfcb = 0; +static int entryno; +static cpm_byte lastdma[0x80]; +static long lastsize; +static char target_name[CPM_MAXPATH]; + +static char upper(char c) +{ + if (islower(c)) return toupper(c); + return c; +} + +/* + * we need to handle case sensitive filesystems correctly. + * underlying files need to just work, irrespective if the files + * in the native filesystem are mixed, upper or lower. + * the naive code in the distributed zx will not work everywhere. + */ + + /* + * Does the string "s" match the CP/M FCB? + * pattern[0-10] will become a CP/M name parsed from "s" if it matches. + * If 1st byte of FCB is '?' then anything matches. + */ + +static int cpm_match(char* s, cpm_byte* fcb, cpm_byte* pattern) +{ + int n; + size_t m; + char* dotpos; + + m = strlen(s); + + /* + * let's cook the filename into something that we can match against + * the fcb. we reject any that can't be valid cp/m filenames, + * normalizing case as we go. all this goes into 'pattern' + */ + + for (n = 0; n < 11; n++) pattern[n] = ' '; + + /* The name must have 1 or 0 dots */ + dotpos = strchr(s, '.'); + if (!dotpos) { /* No dot. The name must be at most 8 characters */ + if (m > 8) return 0; + for (n = 0; n < m; n++) { + pattern[n] = upper(s[n]) & 0x7F; + } + } + else { /* at least one dot */ + if (strchr(dotpos + 1, '.')) { /* More than 1 dot */ + return 0; + } + if (dotpos == s) { /* Dot right at the beginning */ + return 0; + } + if ((dotpos - s) > 8) { /* "name" > 8 characters */ + return 0; + } + if (strlen(dotpos + 1) > 3) { /* "type" > 3 characters */ + return 0; + } + for (n = 0; n < (dotpos - s); n++) { /* copy filename portion */ + pattern[n] = upper(s[n]) & 0x7F; + } + m = strlen(dotpos + 1); + for (n = 0; n < m; n++) { /* copy extention portion */ + pattern[n + 8] = upper(dotpos[n + 1]) & 0x7F; + } + } + + /* + * handle special case where fcb[0] == '?' or fcb[0] & 0x80 + * this is used to return a full directory list on bdos's + */ + + if (((fcb[0] & 0x7F) == '?') || (fcb[0] & 0x80)) { + return 1; + } + for (n = 0; n < 11; n++) + { + if (fcb[n + 1] == '?') continue; + if ((pattern[n] & 0x7F) != (fcb[n + 1] & 0x7F)) + { + return 0; + } + } + return 1; /* Success! */ +} + +/* Get the next entry from the host's directory matching "fcb" */ + +static struct dirent* next_entry(DIR* dir, cpm_byte* fcb, cpm_byte* pattern, + struct stat* st) +{ + struct dirent* en; + int unsatisfied; + int drv = fcb[0] & 0x7F; + + if (drv == '?') drv = 0; + if (!drv) drv = redir_cpmdrive; + else drv--; + + for (unsatisfied = 1; unsatisfied; ) + { + /* 1. Get the next entry */ + en = readdir(dir); + if (!en) return NULL; /* No next entry */ + ++entryno; /* 0 for 1st, 1 for 2nd, etc. */ + + /* 2. See if it matches. We do this first (in preference to + * seeing if it's a subdirectory first) because it doesn't + * require disc access */ + if (!cpm_match(en->d_name, fcb, pattern)) + { + continue; + } + + /* 3. Stat it, & reject it if it's a directory */ + strcpy(target_name, redir_drive_prefix[drv]); + strcat(target_name, en->d_name); + + if (stat(target_name, st)) + { + DBGMSGV("Can't stat %s so omitting it.\n", target_name); + continue; /* Can't stat */ + } + if (S_ISDIR(st->st_mode)) + { + /* Searching for files only */ + if (fcb[0] != '?' && fcb[0] < 0x80) + { + continue; + } + } + unsatisfied = 0; + } + return en; +} + +void volume_label(int drv, cpm_byte* dma) +{ + struct stat st; + + memset(dma, 0x20, 12); /* Volume label */ + + /* Get label name */ + redir_get_label(drv, (char*)(dma + 1)); + + /* [0x0c] = label byte + * [0x0d] = password byte (=0) + * [0x10-0x17] = password + * [0x18] = label create date + * [0x1c] = label update date + */ +#ifdef __MSDOS__ + dma[0x0c] = 0x21; /* Under DOS, only "update" */ + if (redir_drdos) dma[0x0c] |= 0x80; /* Under DRDOS, passwords allowed */ +#else + dma[0x0c] = 0x61; /* Label exists and time stamps allowed */ +#endif /* (update & access) */ + dma[0x0d] = 0; /* Label not passworded */ + dma[0x0f] = 0x80; /* Non-CP/M media */ + + if (stat(redir_drive_prefix[drv], &st)) + { + DBGMSGV("stat() fails on '%s'\n", redir_drive_prefix[drv]); + return; + } + + redir_wr32(dma + 0x18, redir_cpmtime(st.st_atime)); + redir_wr32(dma + 0x1C, redir_cpmtime(st.st_mtime)); +} + +cpm_word redir_find(int n, cpm_byte* fcb, cpm_byte* dma) +{ + DIR* hostdir; + int drv, attrib; + long recs; + struct stat st; + struct dirent* de; + cpm_word rights; + + drv = (fcb[0] & 0x7F); + if (!drv || drv == '?') drv = redir_cpmdrive; + else drv--; + + if (find_xfcb) /* Return another extent */ + { + memcpy(dma, lastdma, 0x80); + dma[0] |= 0x10; /* XFCB */ + dma[0x0c] = dma[0x69]; /* Password mode */ + dma[0x0d] = 0x0A; /* Password decode byte */ + memset(dma + 0x10, '*', 7); + dma[0x17] = ' '; /* Encoded password */ + memcpy(lastdma, dma, 0x80); + + find_xfcb = 0; + return 0; + } + + if (find_ext) /* Return another extent */ + { + memcpy(dma, lastdma, 0x80); + dma[0x0c]++; + if (dma[0x0c] == 0x20) + { + dma[0x0c] = 0; + dma[0x0e]++; + } + lastsize -= 0x4000; + recs = (lastsize + 127) / 128; + dma[0x0f] = (recs > 127) ? 0x80 : (recs & 0x7F); + + if (lastsize <= 0x4000) find_ext = 0; + memcpy(lastdma, dma, 0x80); + + return 0; + } + + memset(dma, 0, 128); /* Zap the buffer */ + + /* If returning all entries, return a volume label. */ + + if ((fcb[0] & 0x7F) == '?') + { + if (!n) + { + volume_label(drv, dma); + return 0; + } + else --n; + } + + /* Note: This implies that opendir() works on a filename with a + * trailing slash. It does under Linux, but that's the only assurance + * I can give. */ + + entryno = -1; + hostdir = opendir(redir_drive_prefix[drv]); + + if (!hostdir) + { + DBGMSGV("opendir() fails on '%s'\n", redir_drive_prefix[drv]); + return 0xFF; + } + + /* We have a handle to the directory. */ + while (n >= 0) + { + de = next_entry(hostdir, fcb, dma + 1, &st); + if (!de) + { + closedir(hostdir); + return 0xFF; + } + --n; + } + /* Valid entry found & statted. dma+1 holds filename. */ + + dma[0] = redir_cpmuser; /* Uid always matches */ + dma[0x0c] = 0; /* Extent counter, low */ + dma[0x0d] = st.st_size & 0x7F; /* Last record byte count */ + dma[0x0e] = 0; /* Extent counter, high */ + +#ifdef _WIN32 + attrib = GetFileAttributesA(target_name); + rights = redir_drdos_get_rights(target_name); + if (rights && ((fcb[0] & 0x7F) == '?')) find_xfcb = 1; +#else + attrib = 0; + rights = 0; +#endif + if (attrib & 1) dma[9] |= 0x80; /* read only */ + if (attrib & 4) dma[10] |= 0x80; /* system */ + if (!(attrib & 0x20)) dma[11] |= 0x80; /* archive */ + +/* TODO: Under Unix, work out correct RO setting */ + + recs = (st.st_size + 127) / 128; + dma[0x0f] = (recs > 127) ? 0x80 : (recs & 0x7F); + dma[0x10] = 0x80; + if (S_ISDIR(st.st_mode)) dma[0x10] |= 0x40; + if (attrib & 2) dma[0x10] |= 0x20; + dma[0x10] |= ((entryno & 0x1FFF) >> 8); + dma[0x11] = dma[0x10]; + dma[0x12] = entryno & 0xFF; + + redir_wr32(dma + 0x16, (dword)st.st_mtime); /* Modification time. */ + /* TODO: It should be in DOS format */ + /* TODO: At 0x1A, 1st cluster */ + redir_wr32(dma + 0x1C, st.st_size); /* True size */ + + if (rights) /* Store password mode. Don't return an XFCB. */ + { + dma[0x69] = redir_cpm_pwmode(rights); + memcpy(lastdma, dma, 0x80); + } + + dma[0x60] = 0x21; /* XFCB */ + redir_wr32(dma + 0x61, redir_cpmtime(st.st_atime)); + redir_wr32(dma + 0x65, redir_cpmtime(st.st_mtime)); + + closedir(hostdir); + + if (st.st_size > 0x4000 && (fcb[0x0C] == '?')) /* All extents? */ + { + lastsize = st.st_size; + find_ext = 1; + memcpy(lastdma, dma, 0x80); + } + return 0; +} + +cpm_word fcb_find1(cpm_byte* fcb, cpm_byte* dma) /* 0x11 */ +{ +#ifdef DEBUG + int rv; +#endif + + FCBENT(fcb); + + redir_log_fcb(fcb); + + find_n = 0; + find_fcb = fcb; + find_ext = 0; + find_xfcb = 0; + +#ifdef DEBUG + rv = redir_find(find_n, fcb, dma); + + if (rv < 4) + { + DBGMSGV("Ret: %-11.11s\n", dma + 1); + } + else DBGMSG("Ret: Fail\n"); + FCBRET(rv); +#else + FCBRET(redir_find(find_n, find_fcb, dma)); +#endif +} + +/* We don't bother with the FCB parameter - it's undocmented, and + * programs that do know about it will just pass in the same parameter + * that they did to function 0x11 */ + +cpm_word fcb_find2(cpm_byte* fcb, cpm_byte* dma) /* 0x12 */ +{ +#ifdef DEBUG + int rv; + char fname[CPM_MAXPATH]; +#endif + + FCBENT(find_fcb); + +#ifdef DEBUG + redir_fcb2unix(find_fcb, fname); + DBGMSGV("file number %d, '%s'\n", find_n, fname); +#endif + + ++find_n; + +#ifdef DEBUG + rv = redir_find(find_n, find_fcb, dma); + + if (rv < 4) + { + DBGMSGV("Ret: %-11.11s\n", dma + 1); + } + else DBGMSG("Ret: Fail\n"); + FCBRET(rv); +#else + FCBRET(redir_find(find_n, find_fcb, dma)); +#endif +} + +/* Under CP/M, unlinking works with wildcards */ + +cpm_word fcb_unlink(cpm_byte* fcb, cpm_byte* dma) +{ + DIR* hostdir; + int drv; + struct dirent* de; + struct stat st; + int handle = 0; + int unpasswd = 0; + char fname[CPM_MAXPATH]; + int del_cnt = 0; + + FCBENT(fcb); + + if (fcb[5] & 0x80) unpasswd = 1; /* Remove password rather than file */ + + redir_log_fcb(fcb); + + drv = (fcb[0] & 0x7F); + if (!drv || drv == '?') drv = redir_cpmdrive; + else drv--; + + if (redir_ro_drv(drv)) + { + /* Error: R/O drive */ + DBGMSG("delete failed - R/O drive\n"); + FCBRET(0x02FF); + } + +#ifdef DEBUG + redir_fcb2unix(fcb, fname); + DBGMSGV("fcb_unlink('%s')\n", fname); +#endif + + /* Note: This implies that opendir() works on a filename with a + * trailing slash. It does under Linux, but that's the only assurance + * I can give.*/ + + hostdir = opendir(redir_drive_prefix[drv]); + + if (!hostdir) + { + DBGMSGV("opendir failed on '%s'\n", redir_drive_prefix[drv]); + FCBRET(0xFF); + } + + /* We have a handle to the directory. */ + do + { + de = next_entry(hostdir, fcb, (cpm_byte*)fname, &st); + if (de) + { + strcpy(target_name, redir_drive_prefix[drv]); + strcat(target_name, de->d_name); + DBGMSGV("deleting '%s'\n", de->d_name); + if (unpasswd) + { +#ifdef __MSDOS__ + if (redir_drdos) + { + handle = redir_drdos_put_rights(target_name, dma, 0); + } + else handle = 0; +#endif + } + else if (fcb[0] & 0x80) + { + DBGMSGV("rmdir '%s'\n", target_name); + handle = rmdir(target_name); + if (handle && redir_password_error()) + { + DBGMSGV("rmdir failed (errno=%lu): %s\n", errno, strerror(errno)); + redir_password_append(target_name, dma); + DBGMSGV("rmdir '%s'\n", target_name); + handle = rmdir(target_name); + } + if (handle) + DBGMSGV("rmdir failed (errno=%lu): %s\n", errno, strerror(errno)); + } + else + { + releaseFile(target_name); + DBGMSGV("unlink '%s'\n", target_name); + handle = unlink(target_name); + if (handle && redir_password_error()) + { + DBGMSGV("unlink failed (errno=%lu): %s\n", errno, strerror(errno)); + redir_password_append(target_name, dma); + releaseFile(target_name); + DBGMSGV("unlink '%s'\n", target_name); + handle = unlink(target_name); + } + if (handle) + DBGMSGV("unlink failed (errno=%lu): %s\n", errno, strerror(errno)); + } + + if (handle) + de = NULL; /* Delete failed */ + else + del_cnt++; + } + } while (de != NULL); + + if (!handle && !del_cnt) + DBGMSG("no matching directory entries\n"); + else + DBGMSGV("deleted %i file(s)\n", del_cnt); + + if (handle || !del_cnt) + { + DBGMSG("delete processing failed\n"); + closedir(hostdir); + FCBRET(0xFF); + } + + DBGMSG("delete processing succeeded\n"); + closedir(hostdir); + FCBRET(0); +} + +#ifdef __MSDOS__ +cpm_word redir_get_label(cpm_byte drv, char* pattern) +{ + char strs[10]; + struct ffblk fblk; + int done; + char* s; + int n; + + /* We need the drive prefix to be of the form "C:\etc..." */ + + memset(pattern, ' ', 11); + if (!redir_drive_prefix[drv][0] || redir_drive_prefix[drv][1] != ':') + return 0; + + sprintf(strs, "%c:/*.*", redir_drive_prefix[drv][0]); + + done = findfirst(strs, &fblk, FA_LABEL); + while (!done) + { + if ((fblk.ff_attrib & FA_LABEL) && + !(fblk.ff_attrib & (FA_SYSTEM | FA_HIDDEN))) + { + s = strchr(fblk.ff_name, '/'); + if (!s) s = strchr(fblk.ff_name, '\\'); + if (!s) s = strchr(fblk.ff_name, ':'); + if (!s) s = fblk.ff_name; + for (n = 0; n < 11; n++) + { + if (!(*s)) break; + if (*s == '.') + { + n = 7; + ++s; + continue; + } + pattern[n] = upper(*s); + ++s; + } + return 1; + } + done = findnext(&fblk); + } + return 0; +} +#else +cpm_word redir_get_label(cpm_byte drv, char* pattern) +{ + char* dname; + size_t l; + int n; + + memset(pattern, ' ', 11); + + dname = strrchr(redir_drive_prefix[drv], '/'); + if (dname) + { + ++dname; + l = strlen(dname); + if (l > 11) l = 11; + for (n = 0; n < l; n++) pattern[n] = upper(dname[l]); + } + else + { + pattern[0] = '.'; + } + return 0; +} + +#endif diff --git a/Tools/unix/zxcc/cpmint.h b/Tools/unix/zxcc/cpmint.h index 65879654..9520e05e 100644 --- a/Tools/unix/zxcc/cpmint.h +++ b/Tools/unix/zxcc/cpmint.h @@ -1,249 +1,274 @@ -/* - - CPMREDIR: CP/M filesystem redirector - Copyright (C) 1998, John Elliott - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - This file holds internal declarations for the library. -*/ - -#ifndef _WIN32 - #include "config.h" - #define DIRSEP "/" -#else - #include "config.h" - #define DIRSEP "/\\:" -#endif -#include -#ifdef HAVE_STDLIB_H - #include -#endif -#include -#ifdef HAVE_STRING_H - #include -#endif -#include -#include -#ifdef _WIN32 - #include -#endif -#ifdef HAVE_SYS_TYPES_H - #include -#endif -#include -#include -#ifdef HAVE_DIRENT_H - #include - #ifdef HAVE_DIRECT_H - #include - #endif -#else - #ifdef __WATCOMC__ - #include - #include - #else - #include "dirent.h" - #endif -#endif -#ifdef HAVE_NDIR_H - #include -#endif -#ifdef HAVE_SYS_DIR_H - #include -#endif -#ifdef HAVE_SYS_NDIR_H - #include -#endif -#ifdef HAVE_WINDOWS_H - #include -#endif -#ifdef HAVE_WINNT_H - #include -#endif -#ifdef HAVE_SYS_VFS_H - #include -#endif -#ifdef HAVE_UTIME_H - #include -#endif -#ifdef HAVE_FCNTL_H - #include -#endif -#ifdef HAVE_UNISTD_H - #include -#endif -#ifndef _WIN32 - #include - #include - #define _S_IFDIR S_IFDIR -#endif - -/* MSDOS includes removed */ - -#ifdef _WIN32 - #define mkdir(dir, mode) _mkdir(dir) - #define strcasecmp _stricmp - int truncate(const char* path, off_t length); /* see util.c */ - #define ftruncate _chsize - /* note Windows build assumes Windows is configured as a non case sensitive filesystem */ -#else - #define CASE_SENSITIVE_FILESYSTEM 1 -#endif - -#include "cpmredir.h" - -typedef unsigned long dword; /* Must be at least 32 bits, and - >= sizeof(int) */ - -#ifdef CPMDEF - #define EXT - #define INIT(x) =x -#else - #define EXT extern - #define INIT(x) -#endif - -/* The 16 directories to which the 16 CP/M drives are mapped */ - -EXT char redir_drive_prefix[16][CPM_MAXPATH]; - -/* Current drive and user */ - -EXT int redir_cpmdrive; -EXT int redir_cpmuser; - -/* Length of 1 read/write operation, bytes */ - -EXT int redir_rec_len INIT(128); - -/* Same, but in 128-byte records */ -EXT int redir_rec_multi INIT(1); - -/* Using a DRDOS system? */ -EXT int redir_drdos INIT(0); - -/* Default password */ -#ifdef __MSDOS__ -EXT char redir_passwd[8] INIT(""); -#endif - -EXT cpm_word redir_l_drives INIT(0); -EXT cpm_word redir_ro_drives INIT(0); - -#undef EXT -#undef INIT - - - -/* Convert FCB to a Unix filename, returning 1 if it's ambiguous */ -int redir_fcb2unix(cpm_byte *fcb, char *fname); - -/* Open FCB, set file attributes */ -int redir_ofile(cpm_byte * fcb, char *s); - -/* Check that the FCB we have is valid */ -int redir_verify_fcb(cpm_byte *fcb); - -#ifndef O_BINARY /* Necessary in DOS, not present in Linux */ -#define O_BINARY 0 -#endif - -/* Facilities for debug tracing */ - - -long zxlseek(int fd, long offset, int wh); - -#ifdef DEBUG - // long zxlseek(int fd, long offset, int wh); - void redir_Msg(char *s, ...); - void redir_showfcb(cpm_byte *fcb); -#else - // #define zxlseek lseek - /* Warning: This is a GCC extension */ - #define redir_Msg(x, ...) - #define redir_showfcb(x) -#endif - - - -/* Get the "sequential access" file pointer out of an FCB */ - -long redir_get_fcb_pos(cpm_byte *fcb); - -/* Write "sequential access" pointer to FCB */ - -void redir_put_fcb_pos(cpm_byte *fcb, long npos); - -/* Convert time_t to CP/M day count/hours/minutes */ -dword redir_cpmtime(time_t t); -/* And back */ -time_t redir_unixtime(cpm_byte *c); - - -/* Functions to access 24-bit & 32-bit words in memory. These are always - little-endian. */ - -void redir_wr24(cpm_byte *addr, dword v); -void redir_wr32(cpm_byte *addr, dword v); -dword redir_rd24(cpm_byte *addr); -dword redir_rd32(cpm_byte *addr); - -/* If you have 64-bit file handles, you'll need to write separate wrhandle() - and rdhandle() routines */ -#define redir_wrhandle redir_wr32 -#define redir_rdhandle redir_rd32 - -/* Mark a drive as logged in */ - -void redir_log_drv(cpm_byte drv); -void redir_log_fcb(cpm_byte *fcb); - -/* Check if a drive is software read-only */ - -int redir_ro_drv(cpm_byte drv); -int redir_ro_fcb(cpm_byte *fcb); - -/* Translate errno to a CP/M error */ - -cpm_word redir_xlt_err(void); - -/* Get disc label */ -cpm_word redir_get_label(cpm_byte drv, char *pattern); - - -/* DRDOS set/get access rights - no-ops under MSDOS and Unix: - * - * CP/M password mode -> DRDOS password mode */ -cpm_word redir_drdos_pwmode(cpm_byte b); - -/* DRDOS password mode to CP/M password mode */ -cpm_byte redir_cpm_pwmode(cpm_word w); - -/* Get DRDOS access rights for a file */ -cpm_word redir_drdos_get_rights(char *path); - -/* Set DRDOS access rights and/or password */ -cpm_word redir_drdos_put_rights(char *path, cpm_byte *dma, cpm_word rights); - -/* Was the last error caused by invalid password? */ -cpm_word redir_password_error(void); - -/* Append password to filename (FILE.TYP -> FILE.TYP;PASSWORD) */ -void redir_password_append(char *s, cpm_byte *dma); - -void releaseFile(char *fname); -int trackFile(char *fname, void *fcb, int fd); -#define releaseFCB(fcb) trackFile(NULL, fcb, -1) +/* + + CPMREDIR: CP/M filesystem redirector + Copyright (C) 1998, John Elliott + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + This file holds internal declarations for the library. +*/ + +#include "config.h" +#include +#ifdef HAVE_STDLIB_H + #include +#endif +#include +#ifdef HAVE_STRING_H + #include +#endif +#include +#include +#ifdef _WIN32 + #include +#endif +#ifdef HAVE_SYS_TYPES_H + #include +#endif +#include +#include +#ifdef HAVE_DIRENT_H + #include +#endif +#ifdef HAVE_DIRECT_H + #include +#endif +#ifdef HAVE_IO_H + #include +#endif +#ifdef HAVE_NDIR_H + #include +#endif +#ifdef HAVE_SYS_DIR_H + #include +#endif +#ifdef HAVE_SYS_NDIR_H + #include +#endif +#ifdef HAVE_WINDOWS_H + #include +#endif +#ifdef HAVE_WINNT_H + #include +#endif +#ifdef HAVE_SYS_VFS_H + #include +#endif +#ifdef HAVE_UTIME_H + #include +#endif +#ifdef HAVE_FCNTL_H + #include +#endif +#ifdef HAVE_UNISTD_H + #include +#endif +#ifndef _WIN32 + #include + #include + #define _S_IFDIR S_IFDIR +#endif + +/* MSDOS includes removed */ + +#ifdef _WIN32 + #define DIRSEP "/" + #define mkdir(dir, mode) _mkdir(dir) + #define strcasecmp _stricmp + #define ftruncate _chsize +/* note Windows build assumes Windows is configured as a non case sensitive filesystem */ + #ifndef STDIN_FILENO + #define STDIN_FILENO _fileno(stdin) + #define STDOUT_FILENO _fileno(stdout) + #define STDERR_FILENO _fileno(stderr) + #endif +#else + #define DIRSEP "/\\:" + #define CASE_SENSITIVE_FILESYSTEM 1 +#endif + +#ifdef _WIN32 +int truncate(const char* path, off_t length); /* see util.c */ +#endif + +typedef unsigned char byte; /* Must be exactly 8 bits */ +typedef unsigned short word; /* Must be exactly 16 bits */ +typedef unsigned long dword; /* Must be at least 32 bits, and + >= sizeof(int) */ + +#include "cpmredir.h" + +#ifdef CPMDEF + #define EXT + #define INIT(x) =x +#else + #define EXT extern + #define INIT(x) +#endif + +/* The 16 directories to which the 16 CP/M drives are mapped */ + +EXT char redir_drive_prefix[16][CPM_MAXPATH]; + +/* Current drive and user */ + +EXT int redir_cpmdrive; +EXT int redir_cpmuser; + +/* Length of 1 read/write operation, bytes */ + +EXT int redir_rec_len INIT(128); + +/* Same, but in 128-byte records */ +EXT int redir_rec_multi INIT(1); + +/* Using a DRDOS system? */ +EXT int redir_drdos INIT(0); + +/* Default password */ +#ifdef __MSDOS__ +EXT char redir_passwd[8] INIT(""); +#endif + +EXT cpm_word redir_l_drives INIT(0); +EXT cpm_word redir_ro_drives INIT(0); + +#undef EXT +#undef INIT + +/* Convert FCB to a Unix filename, returning 1 if it's ambiguous */ +int redir_fcb2unix(cpm_byte* fcb, char* fname); + +/* Open FCB, set file attributes */ +int redir_ofile(cpm_byte* fcb, char* s); + +/* Check that the FCB we have is valid */ +int redir_verify_fcb(cpm_byte* fcb); + +#ifndef O_BINARY /* Necessary in DOS, not present in Linux */ +#define O_BINARY 0 +#endif + +/* Facilities for debug tracing */ + +long zxlseek(int fd, long offset, int wh); + +#ifdef _WIN32 +char* GetErrorStr(DWORD); +#endif + +#ifdef DEBUG +// long zxlseek(int fd, long offset, int wh); +// void redir_Msg(char *s, ...); +void DbgMsg(const char* file, int line, const char* func, char* s, ...); +void redir_showfcb(cpm_byte* fcb); +#else +// #define zxlseek lseek +/* Warning: This is a GCC extension */ +// #define redir_Msg(x, ...) +#define redir_showfcb(x) +#endif + +#ifdef DEBUG +#define FCBENT(fcb) \ + { \ + char fname[CPM_MAXPATH] = ""; \ + redir_fcb2unix(fcb, fname); \ + DBGMSGV("entry w/ FCB @ 0x%04X, filename:'%s'\n", fcb-RAM, fname); \ + } + +#define FCBRET(rc) \ + { \ + DBGMSGV("returning 0x%04X\n", rc); \ + return rc; \ + } + +#define DBGMSGV(s, ...) DbgMsg(__FILE__, __LINE__, __func__, s, __VA_ARGS__) +#define DBGMSG(s) DbgMsg(__FILE__, __LINE__, __func__, s) +#else +#define FCBENT(fcb) +#define FCBRET(rc) return rc; +#define DBGMSGV(s, ...) +#define DBGMSG(s) +#endif + +/* Get the "sequential access" file pointer out of an FCB */ + +long redir_get_fcb_pos(cpm_byte* fcb); + +/* Write "sequential access" pointer to FCB */ + +void redir_put_fcb_pos(cpm_byte* fcb, long npos); + +/* Convert time_t to CP/M day count/hours/minutes */ +dword redir_cpmtime(time_t t); +/* And back */ +time_t redir_unixtime(cpm_byte* c); + +/* Functions to access 24-bit & 32-bit words in memory. These are always + little-endian. */ + +void redir_wr24(cpm_byte* addr, dword v); +void redir_wr32(cpm_byte* addr, dword v); +dword redir_rd24(cpm_byte* addr); +dword redir_rd32(cpm_byte* addr); + +/* If you have 64-bit file handles, you'll need to write separate wrhandle() + and rdhandle() routines */ +#define redir_wrhandle redir_wr32 +#define redir_rdhandle redir_rd32 + +/* Mark a drive as logged in */ + +void redir_log_drv(cpm_byte drv); +void redir_log_fcb(cpm_byte* fcb); + +/* Check if a drive is software read-only */ + +int redir_ro_drv(cpm_byte drv); +int redir_ro_fcb(cpm_byte* fcb); + +/* Translate errno to a CP/M error */ + +cpm_word redir_xlt_err(void); + +/* Get disc label */ +cpm_word redir_get_label(cpm_byte drv, char* pattern); + +/* DRDOS set/get access rights - no-ops under MSDOS and Unix: + * + * CP/M password mode -> DRDOS password mode */ +cpm_word redir_drdos_pwmode(cpm_byte b); + +/* DRDOS password mode to CP/M password mode */ +cpm_byte redir_cpm_pwmode(cpm_word w); + +/* Get DRDOS access rights for a file */ +cpm_word redir_drdos_get_rights(char* path); + +/* Set DRDOS access rights and/or password */ +cpm_word redir_drdos_put_rights(char* path, cpm_byte* dma, cpm_word rights); + +/* Was the last error caused by invalid password? */ +cpm_word redir_password_error(void); + +/* Append password to filename (FILE.TYP -> FILE.TYP;PASSWORD) */ +void redir_password_append(char* s, cpm_byte* dma); + +void releaseFile(char* fname); +int trackFile(char* fname, void* fcb, int fd); +#define releaseFCB(fcb) trackFile(NULL, fcb, -1) + +extern byte RAM[65536]; /* The Z80's address space */ diff --git a/Tools/unix/zxcc/cpmparse.c b/Tools/unix/zxcc/cpmparse.c index ea0949ed..73919c68 100644 --- a/Tools/unix/zxcc/cpmparse.c +++ b/Tools/unix/zxcc/cpmparse.c @@ -1,126 +1,124 @@ /* - CPMREDIR: CP/M filesystem redirector - Copyright (C) 1998, John Elliott + CPMREDIR: CP/M filesystem redirector + Copyright (C) 1998, John Elliott - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. - This library 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 - Library General Public License for more details. + This library 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 + Library General Public License for more details. - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - This file parses filenames to FCBs. + This file parses filenames to FCBs. */ #include "cpmint.h" #define is_num(c) ((c >= '0') && (c <= '9')) -static int parse_drive_user(char *txt, cpm_byte *fcb) +static int parse_drive_user(char* txt, cpm_byte* fcb) { - char uid[4], drvid[4]; - int up, dp; + char uid[4], drvid[4]; + int up, dp; - for (up = dp = 0; *txt != ':'; ++txt) - { - if (is_num (*txt)) uid [up++] = *txt; - if (isalpha(*txt)) drvid[dp++] = *txt; - if (!is_num(*txt) && !isalpha(*txt)) return -1; - } - uid[up] = 0; drvid[dp] = 0; + for (up = dp = 0; *txt != ':'; ++txt) + { + if (is_num(*txt)) uid[up++] = *txt; + if (isalpha(*txt)) drvid[dp++] = *txt; + if (!is_num(*txt) && !isalpha(*txt)) return -1; + } + uid[up] = 0; drvid[dp] = 0; - if (dp > 1) return -1; /* Invalid driveletter */ - if (up > 2) return -1; /* Invalid uid */ - - fcb[0x0d] = atoi(uid) + 1; if (fcb[0x0d] > 16) return -1; + if (dp > 1) return -1; /* Invalid driveletter */ + if (up > 2) return -1; /* Invalid uid */ - if (islower(drvid[0])) drvid[0] = toupper(drvid[0]); + fcb[0x0d] = atoi(uid) + 1; if (fcb[0x0d] > 16) return -1; - if (drvid[0] < 'A' || drvid[0] > 'P') return -1; - - fcb[0] = drvid[0] - '@'; - return 0; -} + if (islower(drvid[0])) drvid[0] = toupper(drvid[0]); + if (drvid[0] < 'A' || drvid[0] > 'P') return -1; + fcb[0] = drvid[0] - '@'; + return 0; +} -cpm_word fcb_parse(char *txt, cpm_byte *fcb) +cpm_word fcb_parse(char* txt, cpm_byte* fcb) { - int nl = 0, tl = 0, pl = 0, phase = 0; - char *ntxt, ch; - - memset(fcb, 0, 0x24); - - if (txt[1] == ':' || txt[2] == ':' || txt[3] == ':') - { - if (parse_drive_user(txt, fcb)) return 0xFFFF; - /* Move past the colon */ - ntxt = strchr(txt, ':') + 1; - } - else ntxt = txt; - while (phase < 3) - { - ch = *ntxt; - if (islower(ch)) ch = toupper(ch); - - switch(ch) - { - case 0: - case '\r': /* EOL */ - phase = 4; - break; - - case '.': /* file.typ */ - if (!phase) ++phase; - else phase = 3; - break; - - case ';': /* Password */ - if (phase < 2) phase = 2; - else phase = 3; - break; - - case '[': case ']': case '=': case 9: case ' ': - case '>': case '<': case ':': case ',': case '/': - case '|': /* Terminator */ - phase = 3; - - default: - switch(phase) - { - case 0: - if (nl >= 8) return 0xFFFF; - fcb[++nl] = ch; - break; - - case 1: - if (tl >= 3) return 0xFFFF; - fcb[tl + 9] = ch; - ++tl; - break; - - case 2: - if (pl >= 8) return 0xFFFF; - fcb[pl + 0x10] = ch; - ++pl; - break; - } - break; - } - } - if (!nl) return 0xFFFF; - - fcb[0x1A] = pl; - - if (phase == 4) return 0; - - return (cpm_word)(ntxt - txt); + int nl = 0, tl = 0, pl = 0, phase = 0; + char* ntxt, ch; + + memset(fcb, 0, 0x24); + + if (txt[1] == ':' || txt[2] == ':' || txt[3] == ':') + { + if (parse_drive_user(txt, fcb)) return 0xFFFF; + /* Move past the colon */ + ntxt = strchr(txt, ':') + 1; + } + else ntxt = txt; + while (phase < 3) + { + ch = *ntxt; + if (islower(ch)) ch = toupper(ch); + + switch (ch) + { + case 0: + case '\r': /* EOL */ + phase = 4; + break; + + case '.': /* file.typ */ + if (!phase) ++phase; + else phase = 3; + break; + + case ';': /* Password */ + if (phase < 2) phase = 2; + else phase = 3; + break; + + case '[': case ']': case '=': case 9: case ' ': + case '>': case '<': case ':': case ',': case '/': + case '|': /* Terminator */ + phase = 3; + + default: + switch (phase) + { + case 0: + if (nl >= 8) return 0xFFFF; + fcb[++nl] = ch; + break; + + case 1: + if (tl >= 3) return 0xFFFF; + fcb[tl + 9] = ch; + ++tl; + break; + + case 2: + if (pl >= 8) return 0xFFFF; + fcb[pl + 0x10] = ch; + ++pl; + break; + } + break; + } + } + if (!nl) return 0xFFFF; + + fcb[0x1A] = pl; + + if (phase == 4) return 0; + + return (cpm_word)(ntxt - txt); } diff --git a/Tools/unix/zxcc/cpmredir.c b/Tools/unix/zxcc/cpmredir.c index 6484608e..cb47cc1c 100644 --- a/Tools/unix/zxcc/cpmredir.c +++ b/Tools/unix/zxcc/cpmredir.c @@ -1,967 +1,1004 @@ -/* - - CPMREDIR: CP/M filesystem redirector - Copyright (C) 1998, John Elliott - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* This file handles actual reading and writing */ - -#define CPMDEF -#include "cpmint.h" - -#ifdef DEBUG -#define SHOWNAME(func) \ - { \ - char fname[CPM_MAXPATH]; \ - redir_fcb2unix(fcb, fname); \ - redir_Msg(func "(\"%s\")\n", fname); \ - } - -#else - #define SHOWNAME(func) -#endif - - -/* DISK BDOS FUNCTIONS */ - -/* General treatment: - * - * We use the "disk block number" fields in the FCB to store our file handle; - * this is a similar trick to that used by DOSPLUS, which stores its cluster - * number in there. It works if: - * - * a) sizeof(int) <= 8 bytes (64 bits). If it's more, this needs rewriting - * to use a hash table; - * b) the program never touches these bytes. Practically no CP/M program does. - * - * We store a "magic number" (0x00FD) in the first two bytes of this field, and - * if the number has been changed then we abort. - * - * nb: Since I wrote ZXCC, I have found that DOSPLUS uses 0x8080 as a magic - * number [well, actually this is an oversimplification, but a hypothetical - * program written against DOSPLUS would work with 0x8080]. Perhaps 0x8080 - * should be used instead. - * - * Format of the field: - * - * [--2 bytes--] magic number - * [--8 bytes--] file handle. 8 bytes reserved but only 4 currently used. - * [--2 bytes--] reserved. - * [--4 bytes--] file length. - */ -#define MAGIC_OFFSET 0x10 -#define HANDLE_OFFSET 0x12 -#define LENGTH_OFFSET 0x1C - -cpm_word fcb_open(cpm_byte *fcb, cpm_byte *dma) -{ - char fname[CPM_MAXPATH]; - int handle; - int drv; - size_t l; - char *s; - DIR *dir; - - /* Don't support ambiguous filenames */ - if (redir_fcb2unix(fcb, fname)) return 0x09FF; - - redir_log_fcb(fcb); - - drv = fcb[0] & 0x7F; - if (!drv) drv = redir_cpmdrive; else --drv; - - if (fcb[0] & 0x80) /* Open directory */ - { - if (fcb[0x0C]) return 0x0BFF; /* Can't assign "floating" dir */ - - if (!memcmp(fcb + 1, ". ", 11)) - { - return 0; /* Opening "." */ - } - if (!memcmp(fcb + 1, ".. ", 11)) - { - l = strlen(redir_drive_prefix[drv]) - 1; - s = redir_drive_prefix[drv]; - while (--l > 0 && !strchr(DIRSEP, s[l])) - --l; - if (l == 0) return 0; /* "/" or "\" */ -#ifdef _WIN32 - if (s[l] == ':' && l < 2) return 0; /* "C:" */ -#endif - s[l + 1] = 0; - return 0; - } -/* Opening some other directory */ - - dir = opendir(fname); - if (!dir) return 0xFF; /* Not a directory */ - closedir(dir); - strcpy(redir_drive_prefix[drv], fname); - strcat(redir_drive_prefix[drv], "/"); - return 0; - } - - /* Note: Some programs (MAC is an example) don't close a file - * if they opened it just to do reading. MAC then reopens the - * file (which rewinds it); this causes FCB leaks under some - * DOS-based emulators */ - - handle = redir_ofile(fcb, fname); - redir_Msg("fcb_open(\"%s\")\r\n", fname); - if (handle < 0 && redir_password_error()) - { - redir_Msg("1st chance open failed on %s\r\n", fname); - redir_password_append(fname, dma); - redir_Msg("Trying with %s\r\n", fname); - handle = redir_ofile(fcb, fname); - } - - - if (handle == -1) - { - redir_Msg("Ret: -1\n"); - if (redir_password_error()) return 0x7FF; - return 0xFF; - } - fcb[MAGIC_OFFSET ] = 0xFD; /* "Magic number" */ - fcb[MAGIC_OFFSET + 1] = 0x00; - -/* TODO: Should the magic number perhaps be 0x8080, as in DOSPLUS? */ - - redir_wrhandle(fcb + HANDLE_OFFSET, handle); - - redir_put_fcb_pos(fcb, fcb[0x0C] * 16384); - /* (v1.01) "seek" to beginning of extent, not file. - * This is necessary for the awful I/O code - * in LINK-80 to work - */ - - /* Get the file length */ - redir_wr32(fcb + LENGTH_OFFSET, zxlseek(handle, 0, SEEK_CUR)); - zxlseek(handle, 0, SEEK_SET); - - /* Set the last record byte count */ - if (fcb[0x20] == 0xFF) fcb[0x20] = fcb[LENGTH_OFFSET] & 0x7F; - - redir_Msg("Ret: 0\n"); - - return 0; -} - - -cpm_word fcb_close(cpm_byte *fcb) -{ - int handle, drv; - - SHOWNAME("fcb_close") - - if ((handle = redir_verify_fcb(fcb)) < 0) return -1; - redir_Msg(" (at %lx)\n", zxlseek(handle, 0, SEEK_END)); - - if (fcb[0] & 0x80) /* Close directory */ - { - drv = fcb[0] & 0x7F; - if (!drv) drv = redir_cpmdrive; else drv--; -#ifdef __MSDOS__ - strcpy(redir_drive_prefix[drv] + 1, ":/"); -#else - strcpy(redir_drive_prefix[drv], "/"); -#endif - return 0; - } - - if (fcb[5] & 0x80) /* CP/M 3: Flush rather than close */ - { -#ifndef _WIN32 - sync(); -#endif - return 0; - } - -#ifdef _WIN32 - { - BOOL b; - redir_Msg(">CloseHandle() Handle=%lu\n", handle); - b = CloseHandle((HANDLE)handle); - redir_Msg("80h, let it be 80h - -*/ - - -cpm_word fcb_read(cpm_byte *fcb, cpm_byte *dma) -{ - int handle; - int rv, n, rd_len; - long npos; - - SHOWNAME("fcb_read") - - if ((handle = redir_verify_fcb(fcb)) < 0) return 9; /* Invalid FCB */ - - /* The program may have mucked about with the counters, so - * do an lseek() to where it should be. */ - - npos = redir_get_fcb_pos(fcb); - zxlseek(handle, npos, SEEK_SET); - redir_Msg(" (from %lx)\n", zxlseek(handle, 0, SEEK_CUR)); - - /* Read in the required amount */ - - memset(dma, 0x00, redir_rec_len); - -#ifdef _WIN32 - { - BOOL b; - redir_Msg(">ReadFile() Handle=%lu, DMA=%lu, Len=%lu\n", handle, dma, redir_rec_len); - b = ReadFile((HANDLE)handle, dma, redir_rec_len, (unsigned long *)(&rv), NULL); - redir_Msg("= 0) && (rv < redir_rec_len)) - memset(dma + rv, 0x00, redir_rec_len - rv); - - /* rd_len = length supposedly read, bytes. Round to nearest 128 bytes. - */ - rd_len = ((rv + 127) / 128) * 128; - - npos += rd_len; - - /* Write new file pointer into FCB */ - - redir_put_fcb_pos(fcb, npos); - - if (rv < 0) - { - redir_Msg("Ret: -1\n"); - return redir_xlt_err(); /* unwritten extent */ - } - - /* if not multiple of 128 bytes, pad sector with 0x1A */ - for (n = rv; n < rd_len; n++) dma[n] = 0x1A; - - /* Less was read in than asked for. Report the number of 128-byte - * records that _were_ read in. - */ - - if (rd_len < redir_rec_len) /* eof */ - { - /* Pack from the size actually read up to the size we claim - * to have read */ - rd_len = rd_len * 2; /* rd_len already sector * 128, so * 2 to move to High byte */ - redir_Msg("Ret: 0x%x\n", rd_len | 1); - return rd_len | 1; /* eof */ - } - - redir_Msg("Ret: 0 (bytes read=%d)\n", rv); - return 0; -} - - -cpm_word fcb_write(cpm_byte *fcb, cpm_byte *dma) -{ - int handle; - int rv; - long npos, len; - - SHOWNAME("fcb_write") - - if ((handle = redir_verify_fcb(fcb)) < 0) return 9; /* Invalid FCB */ - - /* Software write-protection */ - if (redir_ro_fcb(fcb)) return 0x02FF; - - /* Check for a seek */ - npos = redir_get_fcb_pos(fcb); - zxlseek(handle, npos, SEEK_SET); - - redir_Msg(" (to %lx)\n", zxlseek(handle, 0, SEEK_CUR)); - -#ifdef _WIN32 - { - BOOL b; - redir_Msg(">WriteFile() Handle=%lu, DMA=%lu, Len=%lu\n", handle, dma, redir_rec_len); - b = WriteFile((HANDLE)handle, dma, redir_rec_len, (unsigned long *)(&rv), NULL); - redir_Msg("CreateFile([CREATE_ALWAYS]) Name='%s'\n", fname); - handle = (int)CreateFile(fname, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - redir_Msg("ReadFile() Handle=%lu, DMA=%lu, Len=%lu\n", handle, dma, redir_rec_len); - b = ReadFile((HANDLE)handle, dma, redir_rec_len, (unsigned long *)(&rv), NULL); - redir_Msg("= 0) && (rv < redir_rec_len)) - memset(dma + rv, 0x00, redir_rec_len - rv); - - zxlseek(handle, offs, SEEK_SET); - - redir_put_fcb_pos(fcb, offs); - - if (rv < 0) return redir_xlt_err(); /* Error */ - - rd_len = ((rv + 127) / 128) * 128; - - /* PMO: pad partial sector to 128 bytes, even if EOF reached in multi sector read */ - for (n = rv; n < rd_len; n++) dma[n] = 0x1A; /* pad last read to 128 boundary with 0x1A*/ - - if (rd_len < redir_rec_len) /* eof */ - { - rd_len = rd_len * 2; /* rd_len already sector * 128, so * 2 to move to High byte */ - redir_Msg("Ret: 0x%x\n", rd_len | 1); - return rd_len | 1; /* eof */ - } - - return 0; -} - - - -cpm_word fcb_randwr(cpm_byte *fcb, cpm_byte *dma) -{ - int handle; - int rv; - dword offs = redir_rd24(fcb + 0x21) * 128; - dword len; - - SHOWNAME("fcb_randwr") - - if ((handle = redir_verify_fcb(fcb)) < 0) return 9; /* Invalid FCB */ - /* Software write-protection */ - if (redir_ro_fcb(fcb)) return 0x02FF; - - if (zxlseek(handle, offs, SEEK_SET) < 0) return 6; /* bad record no. */ - -#ifdef _WIN32 - { - BOOL b; - redir_Msg(">WriteFile() Handle=%lu, DMA=%lu, Len=%lu\n", handle, dma, redir_rec_len); - b = WriteFile((HANDLE)handle, dma, redir_rec_len, (unsigned long *)(&rv), NULL); - redir_Msg("WriteFile() Handle=%lu, DMA=%lu, Len=%lu\n", handle, zerorec, rl); - b = WriteFile((HANDLE)handle, zerorec, rl, (unsigned long *)(&rv), NULL); - redir_Msg("= 0) len += rv; - - if (rv < rl) - { - redir_wr32(fcb + LENGTH_OFFSET, len); - return redir_xlt_err(); - } - } - redir_wr32(fcb + LENGTH_OFFSET, offs); - - return fcb_randwr(fcb, dma); -} -#endif - - -cpm_word fcb_tell(cpm_byte *fcb) -{ - int handle; - off_t rv; - - SHOWNAME("fcb_tell") - - if ((handle = redir_verify_fcb(fcb)) < 0) return 9; /* Invalid FCB */ - - rv = zxlseek(handle, 0, SEEK_CUR); - - if (rv < 0) return 0xFF; - - rv = rv >> 7; - fcb[0x21] = rv & 0xFF; - fcb[0x22] = (rv >> 8) & 0xFF; - fcb[0x23] = (rv >> 16) & 0xFF; - return 0; -} - - -cpm_word fcb_stat(cpm_byte *fcb) -{ - char fname[CPM_MAXPATH]; - struct stat st; - int rv; - - /* Don't support ambiguous filenames */ - if (redir_fcb2unix(fcb, fname)) return 0x09FF; - - rv = stat(fname, &st); - - redir_Msg("fcb_stat(\"%s\") fcb=%p\n", fname, fcb); - if (rv < 0) - { - redir_Msg("ret: -1\n"); - return 0xFF; - } - - redir_wr24(fcb + 0x21, (st.st_size + 127) / 128); - - redir_Msg("ret: 0"); - return 0; -} - - -cpm_word fcb_multirec(cpm_byte rc) -{ - if (rc < 1 || rc > 128) return 0xFF; - - redir_rec_multi = rc; - redir_rec_len = 128 * rc; - redir_Msg("Set read/write to %d bytes\n", redir_rec_len); - return 0; -} - - -cpm_word fcb_date(cpm_byte *fcb) -{ - char fname[CPM_MAXPATH]; - struct stat st; - int rv; - - /* as this function will overwrite the fcb info used by ZXCC - * release any file associated with it - */ - releaseFCB(fcb); - /* Don't support ambiguous filenames */ - if (redir_fcb2unix(fcb, fname)) return 0x09FF; - - rv = stat(fname, &st); - - redir_Msg("fcb_stat(\"%s\")\n", fname); - if (rv < 0) return 0xFF; - - redir_wr32(fcb + 0x18, redir_cpmtime(st.st_atime)); - redir_wr32(fcb + 0x1C, redir_cpmtime(st.st_ctime)); - - fcb[0x0C] = redir_cpm_pwmode(redir_drdos_get_rights(fname)); - return 0; -} - - -cpm_word fcb_trunc(cpm_byte *fcb, cpm_byte *dma) -{ - char fname[CPM_MAXPATH]; - dword offs = redir_rd24(fcb + 0x21) * 128; - - releaseFCB(fcb); /* CP/M requires truncated files be closed */ - /* Don't support ambiguous filenames */ - if (redir_fcb2unix(fcb, fname)) return 0x09FF; - - /* Software write-protection */ - if (redir_ro_fcb(fcb)) return 0x02FF; - - releaseFile(fname); /* after truncate open files are invalid */ - redir_log_fcb(fcb); - if (truncate(fname, offs)) - { - if (redir_password_error()) - { - redir_password_append(fname, dma); - if (!truncate(fname, offs)) return 0; - } - return redir_xlt_err(); - } - return 0; -} - - -cpm_word fcb_sdate(cpm_byte *fcb, cpm_byte *dma) -{ - char fname[CPM_MAXPATH]; - - struct utimbuf buf; - - buf.actime = redir_unixtime(dma); - buf.modtime = redir_unixtime(dma + 4); - - /* Don't support ambiguous filenames */ - if (redir_fcb2unix(fcb, fname)) return 0x09FF; - - /* Software write-protection */ - if (redir_ro_fcb(fcb)) return 0x02FF; - - redir_log_fcb(fcb); - - if (utime(fname, &buf)) - { - if (redir_password_error()) - { - redir_password_append(fname, dma); - if (!utime(fname, &buf)) return 0; - } - return redir_xlt_err(); - } - return 0; -} - - - -cpm_word fcb_chmod(cpm_byte *fcb, cpm_byte *dma) -{ - char fname[CPM_MAXPATH]; - struct stat st; - int handle, wlen, omode; - long offs, newoffs; - cpm_byte zero[128]; - - /* Don't support ambiguous filenames */ - if (redir_fcb2unix(fcb, fname)) return 0x09FF; - - /* Software write-protection */ - if (redir_ro_fcb(fcb)) return 0x02FF; - - redir_log_fcb(fcb); - - if (stat(fname, &st)) return redir_xlt_err(); - -#ifdef __MSDOS__ - omode = 0; - if (fcb[9] & 0x80) omode |= 1; - if (fcb[10] & 0x80) omode |= 4; - if (!(fcb[11] & 0x80)) omode |= 0x20; - - if (_chmod(fname, 1, omode) < 0) - { - if (redir_password_error()) - { - redir_password_append(fname, dma); - if (_chmod(fname, 1, omode) >= 0) return 0; - } - return redir_xlt_err(); - } -#elif defined (_WIN32) - omode = 0; - - if (fcb[9] & 0x80) omode |= FILE_ATTRIBUTE_READONLY; - if (fcb[10] & 0x80) omode |= FILE_ATTRIBUTE_SYSTEM; - if (!(fcb[11] & 0x80)) omode |= FILE_ATTRIBUTE_ARCHIVE; - - if (!omode) omode = FILE_ATTRIBUTE_NORMAL; - - SetFileAttributes(fname, omode); -#else - omode = st.st_mode; - if (fcb[9] & 0x80) /* Read-only */ - { - st.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); - } - else st.st_mode |= S_IWUSR; - - if (omode != st.st_mode) - { - if (chmod(fname, st.st_mode)) return redir_xlt_err(); - } - -#endif - - if (fcb[6] & 0x80) /* Set exact size */ - { - if (stat(fname, &st)) return redir_xlt_err(); - - releaseFCB(fcb); /* cpm required file to be closed so release FCB */ - releaseFile(fname); /* also make sure no other handles open to file */ - handle = open(fname, O_RDWR | O_BINARY); - if (handle < 0) return redir_xlt_err(); - - newoffs = offs = ((st.st_size + 127) / 128) * 128; - if (fcb[0x20] & 0x7F) - { - newoffs -= fcb[0x20] & 0x7f; - //newoffs -= (0x80 - (fcb[0x20] & 0x7F)); - } - if (newoffs == st.st_size) - { - ; /* Nothing to do! */ - } - else if (newoffs < st.st_size) - { - if (ftruncate(handle, newoffs)) - { - close(handle); - return redir_xlt_err(); - } - } - else while (newoffs > st.st_size) - { - wlen = newoffs - st.st_size; - if (wlen > 0x80) wlen = 0x80; - memset(zero, 0x1A, sizeof(zero)); - if (write(handle, zero, wlen) < wlen) - { - close(handle); - return redir_xlt_err(); - } - st.st_size += wlen; - } - close(handle); - } - return 0; -} - - - - -cpm_word fcb_setpwd(cpm_byte *fcb, cpm_byte *dma) -{ -#ifdef __MSDOS__ - char fname[CPM_MAXPATH]; - cpm_word rv; - - /* Don't support ambiguous filenames */ - if (redir_fcb2unix(fcb, fname)) return 0x09FF; - - /* Software write-protection */ - if (redir_ro_fcb(fcb)) return 0x02FF; - - redir_log_fcb(fcb); - - rv = redir_drdos_put_rights(fname, dma, redir_drdos_pwmode(fcb[0x0c])); - if (rv || !(fcb[0x0c] & 1)) return rv; - return redir_drdos_put_rights(fname, dma, redir_drdos_pwmode(fcb[0x0c]) | 0x8000); -#else - return 0xFF; /* Unix doesn't do this */ -#endif -} - - -cpm_word fcb_getlbl(cpm_byte drv) -{ - redir_Msg("fcb_getlbl()\r\n"); -#ifdef __MSDOS__ - if (redir_drdos) return 0xA1; /* Supports passwords & Update stamps */ - return 0x21; /* Update stamps only */ -#else - return 0x61; /* Update & Access stamps */ -#endif -} - -cpm_word fcb_setlbl(cpm_byte *fcb, cpm_byte *dma) -{ -/* I am not letting CP/M fiddle with the host's FS settings - even if they - * could be altered, which they mostly can't. */ - - return 0x03FF; -} - - - -cpm_word fcb_defpwd(cpm_byte *pwd) -{ -#ifdef __MSDOS__ - union REGS r; - struct SREGS s; - - if (pwd[0] == 0 || pwd[0] == ' ') - { - redir_passwd[0] = 0; - } - else memcpy(redir_passwd, pwd, 8); - if (redir_drdos) - { - dosmemput(pwd, 8, __tb); - r.w.ax = 0x4454; - r.w.dx = __tb & 0x0F; - s.ds = __tb >> 4; - intdosx(&r, &r, &s); - } - -#endif - return 0; -} - - +/* + + CPMREDIR: CP/M filesystem redirector + Copyright (C) 1998, John Elliott + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This file handles actual reading and writing */ + +#define CPMDEF +#include "cpmint.h" + +/* DISK BDOS FUNCTIONS */ + +/* General treatment: + * + * We use the "disk block number" fields in the FCB to store our file handle; + * this is a similar trick to that used by DOSPLUS, which stores its cluster + * number in there. It works if: + * + * a) sizeof(int) <= 8 bytes (64 bits). If it's more, this needs rewriting + * to use a hash table; + * b) the program never touches these bytes. Practically no CP/M program does. + * + * We store a "magic number" (0x00FD) in the first two bytes of this field, and + * if the number has been changed then we abort. + * + * nb: Since I wrote ZXCC, I have found that DOSPLUS uses 0x8080 as a magic + * number [well, actually this is an oversimplification, but a hypothetical + * program written against DOSPLUS would work with 0x8080]. Perhaps 0x8080 + * should be used instead. + * + * Format of the field: + * + * [--2 bytes--] magic number + * [--8 bytes--] file handle. 8 bytes reserved but only 4 currently used. + * [--2 bytes--] reserved. + * [--4 bytes--] file length. + */ + +#define MAGIC_OFFSET 0x10 +#define HANDLE_OFFSET 0x12 +#define LENGTH_OFFSET 0x1C + +cpm_word fcb_open(cpm_byte* fcb, cpm_byte* dma) +{ + char fname[CPM_MAXPATH]; + int handle; + int drv; + size_t l; + char* s; + DIR* dir; + + FCBENT(fcb); + + /* Don't support ambiguous filenames */ + if (redir_fcb2unix(fcb, fname)) FCBRET(0x09FF); + + redir_log_fcb(fcb); + + drv = fcb[0] & 0x7F; + if (!drv) drv = redir_cpmdrive; else --drv; + + if (fcb[0] & 0x80) /* Open directory */ + { + if (fcb[0x0C]) FCBRET(0x0BFF); /* Can't assign "floating" dir */ + + if (!memcmp(fcb + 1, ". ", 11)) + { + FCBRET(0); /* Opening "." */ + } + if (!memcmp(fcb + 1, ".. ", 11)) + { + l = strlen(redir_drive_prefix[drv]) - 1; + s = redir_drive_prefix[drv]; + while (--l > 0 && !strchr(DIRSEP, s[l])) + --l; + if (l == 0) FCBRET(0); /* "/" or "\" */ +#ifdef _WIN32 + if (s[l] == ':' && l < 2) FCBRET(0); /* "C:" */ +#endif + s[l + 1] = 0; + FCBRET(0); + } + /* Opening some other directory */ + + dir = opendir(fname); + if (!dir) FCBRET(0xFF); /* Not a directory */ + closedir(dir); + strcpy(redir_drive_prefix[drv], fname); + strcat(redir_drive_prefix[drv], "/"); + FCBRET(0); + } + + /* Note: Some programs (MAC is an example) don't close a file + * if they opened it just to do reading. MAC then reopens the + * file (which rewinds it); this causes FCB leaks under some + * DOS-based emulators */ + + handle = redir_ofile(fcb, fname); + //DBGMSGV("fcb_open('%s')\n", fname); + if (handle < 0 && redir_password_error()) + { + DBGMSGV("1st chance open failed on %s\n", fname); + redir_password_append(fname, dma); + DBGMSGV("Trying with %s\n", fname); + handle = redir_ofile(fcb, fname); + } + + if (handle == -1) + { + if (redir_password_error()) FCBRET(0x7FF); + FCBRET(0xFF); + } + fcb[MAGIC_OFFSET] = 0xFD; /* "Magic number" */ + fcb[MAGIC_OFFSET + 1] = 0x00; + + /* TODO: Should the magic number perhaps be 0x8080, as in DOSPLUS? */ + + redir_wrhandle(fcb + HANDLE_OFFSET, handle); + + redir_put_fcb_pos(fcb, fcb[0x0C] * 16384); + /* (v1.01) "seek" to beginning of extent, not file. + * This is necessary for the awful I/O code + * in LINK-80 to work + */ + + /* Get the file length */ + redir_wr32(fcb + LENGTH_OFFSET, zxlseek(handle, 0, SEEK_END)); + zxlseek(handle, 0, SEEK_SET); + + /* Set the last record byte count */ + if (fcb[0x20] == 0xFF) fcb[0x20] = fcb[LENGTH_OFFSET] & 0x7F; + + FCBRET(0); +} + +cpm_word fcb_close(cpm_byte* fcb) +{ + int handle, drv; + + FCBENT(fcb); + + if ((handle = redir_verify_fcb(fcb)) < 0) FCBRET(-1); + DBGMSGV(" (at 0x%lX)\n", zxlseek(handle, 0, SEEK_CUR)); + + if (fcb[0] & 0x80) /* Close directory */ + { + drv = fcb[0] & 0x7F; + if (!drv) drv = redir_cpmdrive; else drv--; +#ifdef __MSDOS__ + strcpy(redir_drive_prefix[drv] + 1, ":/"); +#else + strcpy(redir_drive_prefix[drv], "/"); +#endif + FCBRET(0); + } + + if (fcb[5] & 0x80) /* CP/M 3: Flush rather than close */ + { +#ifdef _WIN32 + BOOL b; + DBGMSGV("flush file #%i\n", handle); + b = FlushFileBuffers((HANDLE)handle); + if (!b) + DBGMSGV("failed to flush file #%i (Error=%lu): %s\n", handle, GetLastError(), GetErrorStr(GetLastError())); +#else + DBGMSGV("flush file #%i\n", handle); + sync(); +#endif + FCBRET(0); + } + +#ifdef _WIN32 + { + BOOL b; + DBGMSGV("close file #%i\n", handle); + b = CloseHandle((HANDLE)handle); + if (!b) + { + DBGMSGV("failed to close file #%i (Error=%lu): %s\n", handle, GetLastError(), GetErrorStr(GetLastError())); + FCBRET(0xFF); + } + } +#else + DBGMSGV("close file #%i\n", handle); + if (close(handle)) + { + DBGMSGV("failed to close file #%i (Error=%lu): %s\n", handle, errno, strerror(errno)); + FCBRET(0xFF); + } +#endif + + FCBRET(0); +} + +/* In theory, fcb_read() is supposed to be sequential access - the program + just reads one record after another and lets the OS worry about file + pointers. + + In practice, it isn't so easy. For example, DR's LINK-80 does seeks when + the file size gets above 8k, and SAVE rewinds the file by setting the + counter fields to 0. + + Seeking is done by relying on the following fields: + + ex (FCB+12) = (position / 16k) % 32 + s2 (FCB+14) = position / 512k + cr (FCB+32) = (position % 16k) / 128 + + TODO: Set rc to number of 80h-byte records in last extent: ie: + + length of file - (file ptr - (file ptr % 16384)) / 128 + + if >80h, let it be 80h + +*/ + +cpm_word fcb_read(cpm_byte* fcb, cpm_byte* dma) +{ + int handle; + int rv, n, rd_len; + long npos; + + FCBENT(fcb); + + if ((handle = redir_verify_fcb(fcb)) < 0) FCBRET(9); /* Invalid FCB */ + + /* The program may have mucked about with the counters, so + * do an lseek() to where it should be. */ + + npos = redir_get_fcb_pos(fcb); + zxlseek(handle, npos, SEEK_SET); + DBGMSGV(" (from 0x%lX)\n", zxlseek(handle, 0, SEEK_CUR)); + + /* Read in the required amount */ + +#ifdef _WIN32 + { + BOOL b; + DBGMSGV("read file #%i @ 0x%X, %i bytes\n", handle, dma - RAM, redir_rec_len); + b = ReadFile((HANDLE)handle, dma, redir_rec_len, (unsigned long*)(&rv), NULL); + if (!b) + { + DBGMSGV("failed to read file #%i (Error=%lu): %s\n", handle, GetLastError(), GetErrorStr(GetLastError())); + rv = -1; + } + } +#else + DBGMSGV("read file #%i @ 0x%X, %i bytes\n", handle, dma - RAM, redir_rec_len); + rv = read(handle, dma, redir_rec_len); + if (rv == -1) + DBGMSGV("failed to read file #%i (errno=%lu): %s\n", handle, errno, strerror(errno)); +#endif + + /* read() can corrupt buffer area following data read if length + * of data read is less than buffer. Clean it up. */ + if (rv == -1) + memset(dma, 0x00, redir_rec_len); + else + memset(dma + rv, 0x00, redir_rec_len - rv); + + /* rd_len = length supposedly read, bytes. Round to nearest 128 + * bytes. */ + rd_len = ((rv + 127) / 128) * 128; + + npos += rd_len; + + /* Write new file pointer into FCB */ + + redir_put_fcb_pos(fcb, npos); + + if (rv < 0) + { + DBGMSG("Ret: -1\n"); + FCBRET(redir_xlt_err()); /* unwritten extent */ + } + + /* if not multiple of 128 bytes, pad sector with 0x1A */ + for (n = rv; n < rd_len; n++) dma[n] = 0x1A; + + /* Less was read in than asked for. Report the number of 128-byte + * records that _were_ read in. + */ + + if (rd_len < redir_rec_len) /* eof */ + { + /* Pack from the size actually read up to the size we claim + * to have read */ + rd_len = rd_len * 2; /* rd_len already sector * 128, so * 2 to move to High byte */ + FCBRET(rd_len | 1); /* eof */ + } + + DBGMSGV("Ret: 0 (bytes read=%d)\n", rv); + FCBRET(0); +} + +cpm_word fcb_write(cpm_byte* fcb, cpm_byte* dma) +{ + int handle; + int rv; + long npos, len; + + FCBENT(fcb); + + if ((handle = redir_verify_fcb(fcb)) < 0) FCBRET(9); /* Invalid FCB */ + + /* Software write-protection */ + if (redir_ro_fcb(fcb)) FCBRET(0x02FF); + + /* Check for a seek */ + npos = redir_get_fcb_pos(fcb); + zxlseek(handle, npos, SEEK_SET); + + DBGMSGV(" (to %lX)\n", zxlseek(handle, 0, SEEK_CUR)); + +#ifdef _WIN32 + { + BOOL b; + DBGMSGV("write file #%i @ 0x%X, %i bytes\n", handle, dma - RAM, redir_rec_len); + b = WriteFile((HANDLE)handle, dma, redir_rec_len, (unsigned long*)(&rv), NULL); + if (!b) + { + DBGMSGV("failed to write file #%i (Error=%lu): %s\n", handle, GetLastError(), GetErrorStr(GetLastError())); + rv = -1; + } + } +#else + DBGMSGV("write file #%i @ 0x%X, %i bytes\n", handle, dma - RAM, redir_rec_len); + rv = write(handle, dma, redir_rec_len); + if (rv == -1) + DBGMSGV("failed to write file #%i (errno=%lu): %s\n", handle, errno, strerror(errno)); +#endif + npos += redir_rec_len; + + redir_put_fcb_pos(fcb, npos); + + /* Update the file length */ + len = redir_rd32(fcb + LENGTH_OFFSET); + if (len < npos) redir_wr32(fcb + LENGTH_OFFSET, npos); + + if (rv < 0) FCBRET(redir_xlt_err()); /* error */ + if (rv < redir_rec_len) FCBRET(1); /* disk full */ + FCBRET(0); +} + +cpm_word fcb_creat(cpm_byte* fcb, cpm_byte* dma) +{ + char fname[CPM_MAXPATH]; + int handle; + + FCBENT(fcb); + + releaseFCB(fcb); /* release existing fcb usage */ + + /* Don't support ambiguous filenames */ + if (redir_fcb2unix(fcb, fname)) FCBRET(0x09FF); + DBGMSGV("fcb_creat('%s')\n", fname); + + /* Software write-protection */ + if (redir_ro_fcb(fcb)) FCBRET(0x02FF); + + redir_log_fcb(fcb); + + if (fcb[0] & 0x80) + { + handle = mkdir(fname, 0x777); + if (handle) FCBRET(redir_xlt_err()); + FCBRET(0); + } + releaseFile(fname); /* purge any open handles for this file */ + +#ifdef _WIN32 + DBGMSGV("create file '%s'\n", fname); + handle = (int)CreateFile(fname, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (handle == HFILE_ERROR) + { + DBGMSGV("failed to create file '%s' (Error=%lu): %s\n", fname, GetLastError(), GetErrorStr(GetLastError())); + FCBRET(0xFF); + } +#else + DBGMSGV("create file '%s'\n", fname); + handle = open(fname, O_RDWR | O_CREAT | O_EXCL | O_BINARY, + S_IREAD | S_IWRITE); + if (handle < 0) + { + DBGMSGV("failed to create file '%s' (Error=%lu): %s\n", fname, errno, strerror(errno)); + FCBRET(0xFF); + } +#endif + + trackFile(fname, fcb, handle); /* track new file */ + + fcb[MAGIC_OFFSET] = 0xFD; /* "Magic number" */ + fcb[MAGIC_OFFSET + 1] = 0; + redir_wrhandle(fcb + HANDLE_OFFSET, handle); + redir_wr32(fcb + LENGTH_OFFSET, 0); + redir_put_fcb_pos(fcb, 0); /* Seek to 0 */ + +#ifdef __MSDOS__ + if (redir_drdos && (fcb[6] & 0x80)) + { + cpm_word rights = redir_drdos_pwmode(dma[9]); + redir_drdos_put_rights(fname, dma, rights | 0x8000); + } +#endif + + FCBRET(0); +} + +cpm_word fcb_rename(cpm_byte* fcb, cpm_byte* dma) +{ + char ofname[CPM_MAXPATH], nfname[CPM_MAXPATH]; + cpm_byte sdrv, ddrv; + + FCBENT(fcb); + + releaseFCB(fcb); /* release any file associated with the fcb */ + redir_log_fcb(fcb); + + /* Don't support ambiguous filenames */ + if (redir_fcb2unix(fcb, ofname)) FCBRET(0x09FF); + if (redir_fcb2unix(fcb + 0x10, nfname)) FCBRET(0x09FF); + + /* Software write-protection */ + if (redir_ro_fcb(fcb)) FCBRET(0x02FF); + + if (fcb[0] & 0x80) FCBRET(0xFF); /* Can't rename directories */ + + /* Check we're not trying to rename across drives. Otherwise, it + * might let you do it if the two "drives" are on the same disk. */ + + sdrv = fcb[0] & 0x7F; if (!sdrv) sdrv = redir_cpmdrive + 1; + ddrv = fcb[0x10] & 0x7F; if (!ddrv) ddrv = redir_cpmdrive + 1; + + if (sdrv != ddrv) FCBRET(0xFF); + + DBGMSGV("rename '%s' to '%s'\n", ofname, nfname); + + releaseFile(ofname); /* need ofname and nfname to be closed */ + releaseFile(nfname); + if (rename(ofname, nfname)) + { + if (redir_password_error()) + { + redir_password_append(ofname, dma); + if (!rename(ofname, nfname)) FCBRET(0); + if (redir_password_error()) FCBRET(0x7FF); + } + FCBRET(0xFF); + } + + FCBRET(0); +} + +cpm_word fcb_randrd(cpm_byte* fcb, cpm_byte* dma) +{ + int handle; + int rv, n, rd_len; + dword offs = redir_rd24(fcb + 0x21) * 128; + + FCBENT(fcb); + + if ((handle = redir_verify_fcb(fcb)) < 0) FCBRET(9); /* Invalid FCB */ + + if (zxlseek(handle, offs, SEEK_SET) < 0) FCBRET(6); /* bad record no. */ + +#ifdef _WIN32 + { + BOOL b; + DBGMSGV("read file #%i @ 0x%X, %i bytes\n", handle, dma - RAM, redir_rec_len); + b = ReadFile((HANDLE)handle, dma, redir_rec_len, (unsigned long*)(&rv), NULL); + if (!b) + { + DBGMSGV("failed to read file #%i (Error=%lu): %s\n", handle, GetLastError(), GetErrorStr(GetLastError())); + rv = -1; + } + } +#else + DBGMSGV("read file #%i @ 0x%X, %i bytes\n", handle, dma - RAM, redir_rec_len); + rv = read(handle, dma, redir_rec_len); + if (rv == -1) + DBGMSGV("failed to read file #%i (errno=%lu): %s\n", handle, errno, strerror(errno)); +#endif + + // read() can corrupt buffer area following data read if length + // of data read is less than buffer. Clean it up. + if (rv == -1) + memset(dma, 0x00, redir_rec_len); + else + memset(dma + rv, 0x00, redir_rec_len - rv); + + zxlseek(handle, offs, SEEK_SET); + + redir_put_fcb_pos(fcb, offs); + + if (rv < 0) FCBRET(redir_xlt_err()); /* Error */ + + rd_len = ((rv + 127) / 128) * 128; + + /* PMO: pad partial sector to 128 bytes, even if EOF reached in multi sector read */ + for (n = rv; n < rd_len; n++) dma[n] = 0x1A; /* pad last read to 128 boundary with 0x1A*/ + + if (rd_len < redir_rec_len) /* eof */ + { + rd_len = rd_len * 2; /* rd_len already sector * 128, so * 2 to move to High byte */ + DBGMSGV("Ret: 0x%x\n", rd_len | 1); + FCBRET(rd_len | 1); /* eof */ + } + + FCBRET(0); +} + +cpm_word fcb_randwr(cpm_byte* fcb, cpm_byte* dma) +{ + int handle; + int rv; + dword offs = redir_rd24(fcb + 0x21) * 128; + dword len; + + FCBENT(fcb); + + if ((handle = redir_verify_fcb(fcb)) < 0) FCBRET(9); /* Invalid FCB */ + /* Software write-protection */ + if (redir_ro_fcb(fcb)) FCBRET(0x02FF); + + if (zxlseek(handle, offs, SEEK_SET) < 0) FCBRET(6); /* bad record no. */ + +#ifdef _WIN32 + { + BOOL b; + DBGMSGV("write file #%i @ 0x%X, %i bytes\n", handle, dma - RAM, redir_rec_len); + b = WriteFile((HANDLE)handle, dma, redir_rec_len, (unsigned long*)(&rv), NULL); + if (!b) + { + DBGMSGV("failed to write file #%i (Error=%lu): %s\n", handle, GetLastError(), GetErrorStr(GetLastError())); + rv = -1; + } + } +#else + DBGMSGV("write file #%i @ 0x%X, %i bytes\n", handle, dma - RAM, redir_rec_len); + rv = write(handle, dma, redir_rec_len); + if (rv == -1) + DBGMSGV("failed to write file #%i (errno=%lu): %s\n", handle, errno, strerror(errno)); +#endif + zxlseek(handle, offs, SEEK_SET); + redir_put_fcb_pos(fcb, offs); + + if (rv < 0) FCBRET(redir_xlt_err()); /* Error */ + /* Update the file length */ + len = redir_rd32(fcb + LENGTH_OFFSET); + /* PMO: Bug fix, account for the data just written */ + if (len < offs + rv) { + redir_wr32(fcb + LENGTH_OFFSET, offs + rv); + /* WBW: Not actually a bug. Causes problems w/ GENCPM */ + // fcb[0x20] = (offs + rv) % 256; + } + + if (rv < redir_rec_len) FCBRET(1); /* disk full */ + FCBRET(0); +} + +#ifndef OLD_RANDWZ +/* PMO: + * Under CP/M for random write with zero fill, the zero fill is only done for a newly allocated + * block and not fill from previous end of file + * to implement this fully would require tracking sparse files and filling to block + * boundaries. + * As the default for POSIX/Windows lseek is to effectively zero fill and for modern hard disks + * the additional space used is small compared to capacity, fcb_randwz is the same as fcb_randwr + * Note zero padding to the end of the block will be done automatically as required when data is + * written to later offsets + */ + /* Write random with 0 fill */ +cpm_word fcb_randwz(cpm_byte* fcb, cpm_byte* dma) +{ + FCBENT(fcb); + FCBRET(fcb_randwr(fcb, dma)); +} +#else +/* Write random with 0 fill */ +cpm_word fcb_randwz(cpm_byte* fcb, cpm_byte* dma) +{ + dword offs, len; + int handle, rl, rv; + cpm_byte zerorec[128]; + + FCBENT(fcb); + + if ((handle = redir_verify_fcb(fcb)) < 0) FCBRET(9); /* Invalid FCB */ + /* Software write-protection */ + if (redir_ro_fcb(fcb)) FCBRET(0x02FF); + + offs = redir_rd24(fcb + 0x21) * 128; + len = redir_rd32(fcb + LENGTH_OFFSET); + + redir_wr32(fcb + LENGTH_OFFSET, offs); + + memset(zerorec, 0, sizeof(zerorec)); + + while (len < offs) + { + memset(zerorec, 0, sizeof(zerorec)); + + rl = sizeof(zerorec); + if ((offs - len) < sizeof(zerorec)) rl = offs - len; +#ifdef _WIN32 + { + BOOL b; + DBGMSGV("write file #%i (zeroes), %i bytes\n", handle, redir_rec_len); + b = WriteFile((HANDLE)handle, zerorec, rl, (unsigned long*)(&rv), NULL); + if (!b) + { + DBGMSGV("failed to write file #%i (Error=%lu): %s\n", handle, GetLastError(), GetErrorStr(GetLastError())); + rv = -1; + } + } +#else + DBGMSGV("write file #%i (zeroes), %i bytes\n", handle, redir_rec_len); + rv = write(handle, zerorec, rl); + if (rv == -1) + DBGMSGV("failed to write file #%i (errno=%lu): %s\n", handle, errno, strerror(errno)); +#endif + if (rv >= 0) len += rv; + + if (rv < rl) + { + redir_wr32(fcb + LENGTH_OFFSET, len); + FCBRET(redir_xlt_err()); + } + } + redir_wr32(fcb + LENGTH_OFFSET, offs); + + FCBRET(fcb_randwr(fcb, dma)); +} +#endif + +cpm_word fcb_tell(cpm_byte* fcb) +{ + int handle; + off_t rv; + + FCBENT(fcb); + + if ((handle = redir_verify_fcb(fcb)) < 0) FCBRET(9); /* Invalid FCB */ + + rv = zxlseek(handle, 0, SEEK_CUR); + + if (rv < 0) FCBRET(0xFF); + + rv = rv >> 7; + fcb[0x21] = rv & 0xFF; + fcb[0x22] = (rv >> 8) & 0xFF; + fcb[0x23] = (rv >> 16) & 0xFF; + FCBRET(0); +} + +cpm_word fcb_stat(cpm_byte* fcb) +{ + char fname[CPM_MAXPATH]; + struct stat st; + int rv; + + FCBENT(fcb); + + /* Don't support ambiguous filenames */ + if (redir_fcb2unix(fcb, fname)) FCBRET(0x09FF); + + DBGMSGV("stat '%s', FCB=%0.4X\n", fname, fcb - RAM); + rv = stat(fname, &st); + if (rv < 0) + { + DBGMSGV("failed to stat file '%s' (errno=%lu): %s\n", fname, errno, strerror(errno)); + FCBRET(0xFF); + } + + redir_wr24(fcb + 0x21, (st.st_size + 127) / 128); + + FCBRET(0); +} + +cpm_word fcb_multirec(cpm_byte rc) +{ + if (rc < 1 || rc > 128) return 0xFF; + + redir_rec_multi = rc; + redir_rec_len = 128 * rc; + DBGMSGV("Set read/write to %d bytes\n", redir_rec_len); + return 0; +} + +cpm_word fcb_date(cpm_byte* fcb) +{ + char fname[CPM_MAXPATH]; + struct stat st; + int rv; + + FCBENT(fcb); + + /* as this function will overwrite the fcb info used by ZXCC + * release any file associated with it + */ + releaseFCB(fcb); + /* Don't support ambiguous filenames */ + if (redir_fcb2unix(fcb, fname)) FCBRET(0x09FF); + + DBGMSGV("stat '%s', FCB=%0.4X\n", fname, fcb - RAM); + rv = stat(fname, &st); + if (rv < 0) + { + DBGMSGV("failed to stat file '%s' (errno=%lu): %s\n", fname, errno, strerror(errno)); + FCBRET(0xFF); + } + + redir_wr32(fcb + 0x18, redir_cpmtime(st.st_atime)); + redir_wr32(fcb + 0x1C, redir_cpmtime(st.st_ctime)); + + fcb[0x0C] = redir_cpm_pwmode(redir_drdos_get_rights(fname)); + FCBRET(0); +} + +cpm_word fcb_trunc(cpm_byte* fcb, cpm_byte* dma) +{ + char fname[CPM_MAXPATH]; + dword offs = redir_rd24(fcb + 0x21) * 128; + + FCBENT(fcb); + + releaseFCB(fcb); /* CP/M requires truncated files be closed */ + /* Don't support ambiguous filenames */ + if (redir_fcb2unix(fcb, fname)) FCBRET(0x09FF); + + /* Software write-protection */ + if (redir_ro_fcb(fcb)) FCBRET(0x02FF); + + releaseFile(fname); /* after truncate open files are invalid */ + redir_log_fcb(fcb); + + DBGMSGV("truncate file '%s' at %lu\n", fname, offs); + if (truncate(fname, offs)) + { + DBGMSGV("failed to truncate file '%s' (errno=%lu): %s\n", fname, errno, strerror(errno)); + if (redir_password_error()) + { + redir_password_append(fname, dma); + DBGMSGV("truncate file '%s' w/ password at %lu\n", fname, offs); + if (!truncate(fname, offs)) FCBRET(0); + DBGMSGV("failed to truncate file '%s' (errno=%lu): %s\n", fname, errno, strerror(errno)); + } + FCBRET(redir_xlt_err()); + } + FCBRET(0); +} + +cpm_word fcb_sdate(cpm_byte* fcb, cpm_byte* dma) +{ + char fname[CPM_MAXPATH]; + struct utimbuf buf; + + FCBENT(fcb); + + buf.actime = redir_unixtime(dma); + buf.modtime = redir_unixtime(dma + 4); + + /* Don't support ambiguous filenames */ + if (redir_fcb2unix(fcb, fname)) FCBRET(0x09FF); + + /* Software write-protection */ + if (redir_ro_fcb(fcb)) FCBRET(0x02FF); + + redir_log_fcb(fcb); + + DBGMSGV("utime file '%s'\n", fname); + if (utime(fname, &buf)) + { + DBGMSGV("failed to utime file '%s' (Error=%lu): %s\n", fname, errno, strerror(errno)); + if (redir_password_error()) + { + redir_password_append(fname, dma); + DBGMSGV("utime file '%s' w/ password\n", fname); + if (!utime(fname, &buf)) FCBRET(0); + DBGMSGV("failed to utime file '%s' (Error=%lu): %s\n", fname, errno, strerror(errno)); + } + FCBRET(redir_xlt_err()); + } + FCBRET(0); +} + +cpm_word fcb_chmod(cpm_byte* fcb, cpm_byte* dma) +{ + char fname[CPM_MAXPATH]; + struct stat st; + int handle, wlen, omode; + long offs, newoffs; + cpm_byte zero[128]; + + FCBENT(fcb); + + /* Don't support ambiguous filenames */ + if (redir_fcb2unix(fcb, fname)) FCBRET(0x09FF); + + /* Software write-protection */ + if (redir_ro_fcb(fcb)) FCBRET(0x02FF); + + redir_log_fcb(fcb); + + DBGMSGV("stat '%s', FCB=%0.4X\n", fname, fcb - RAM); + if (stat(fname, &st)) + { + DBGMSGV("failed to stat file '%s' (errno=%lu): %s\n", fname, errno, strerror(errno)); + FCBRET(redir_xlt_err()); + } + +#ifdef __MSDOS__ + omode = 0; + if (fcb[9] & 0x80) omode |= 1; + if (fcb[10] & 0x80) omode |= 4; + if (!(fcb[11] & 0x80)) omode |= 0x20; + + if (_chmod(fname, 1, omode) < 0) + { + if (redir_password_error()) + { + redir_password_append(fname, dma); + if (_chmod(fname, 1, omode) >= 0) FCBRET(0); + } + FCBRET(redir_xlt_err()); + } +#elif defined (_WIN32) + omode = 0; + + if (fcb[9] & 0x80) omode |= FILE_ATTRIBUTE_READONLY; + if (fcb[10] & 0x80) omode |= FILE_ATTRIBUTE_SYSTEM; + if (!(fcb[11] & 0x80)) omode |= FILE_ATTRIBUTE_ARCHIVE; + + if (!omode) omode = FILE_ATTRIBUTE_NORMAL; + + { + BOOL b; + DBGMSGV("set attributes file '%s', FCB=%0.4X\n", fname, fcb - RAM); + b = SetFileAttributes(fname, omode); + if (!b) + { + DBGMSGV("failed to set attributes file '%s' (Error=%lu): %s\n", fname, GetLastError(), GetErrorStr(GetLastError())); + FCBRET(redir_xlt_err()); + } + } +#else + omode = st.st_mode; + if (fcb[9] & 0x80) /* Read-only */ + { + st.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); + } + else st.st_mode |= S_IWUSR; + + if (omode != st.st_mode) + { + DBGMSGV("chmod '%s', FCB=%0.4X\n", fname, fcb - RAM); + if (chmod(fname, st.st_mode)) + { + DBGMSGV("failed to chmod file '%s' (errno=%lu): %s\n", fname, errno, strerror(errno)); + FCBRET(redir_xlt_err()); + } + } +#endif + + if (fcb[6] & 0x80) /* Set exact size */ + { + DBGMSGV("stat '%s', FCB=%0.4X\n", fname, fcb - RAM); + if (stat(fname, &st)) + { + DBGMSGV("failed to stat file '%s' (errno=%lu): %s\n", fname, errno, strerror(errno)); + FCBRET(redir_xlt_err()); + } + + releaseFCB(fcb); /* cpm required file to be closed so release FCB */ + releaseFile(fname); /* also make sure no other handles open to file */ + DBGMSGV("open '%s', FCB=%0.4X\n", fname, fcb - RAM); + handle = open(fname, O_RDWR | O_BINARY); + if (handle < 0) + { + DBGMSGV("failed to open file '%s' (errno=%lu): %s\n", fname, errno, strerror(errno)); + FCBRET(redir_xlt_err()); + } + DBGMSGV("file '%s' opened at #%i\n", fname, handle); + + newoffs = offs = ((st.st_size + 127) / 128) * 128; + if (fcb[0x20] & 0x7F) + { + newoffs -= fcb[0x20] & 0x7f; + //newoffs -= (0x80 - (fcb[0x20] & 0x7F)); + } + if (newoffs == st.st_size) + { + ; /* Nothing to do! */ + } + else if (newoffs < st.st_size) + { + DBGMSGV("ftruncate file #%i at %lu\n", handle, newoffs); + if (ftruncate(handle, newoffs)) + { + DBGMSGV("failed to ftruncate file #%i (errno=%lu): %s\n", handle, errno, strerror(errno)); + close(handle); + FCBRET(redir_xlt_err()); + } + } + else while (newoffs > st.st_size) + { + wlen = newoffs - st.st_size; + if (wlen > 0x80) wlen = 0x80; + memset(zero, 0x1A, sizeof(zero)); + DBGMSGV("write file #%i (zeroes), %lu bytes\n", handle, wlen); + if (write(handle, zero, wlen) < wlen) + { + DBGMSGV("failed to write file #%i (errno=%lu): %s\n", handle, errno, strerror(errno)); + close(handle); + FCBRET(redir_xlt_err()); + } + st.st_size += wlen; + } + close(handle); + } + FCBRET(0); +} + +cpm_word fcb_setpwd(cpm_byte* fcb, cpm_byte* dma) +{ +#ifdef __MSDOS__ + char fname[CPM_MAXPATH]; + cpm_word rv; + + FCBENT(fcb); + + /* Don't support ambiguous filenames */ + if (redir_fcb2unix(fcb, fname)) FCBRET(0x09FF); + + /* Software write-protection */ + if (redir_ro_fcb(fcb)) FCBRET(0x02FF); + + redir_log_fcb(fcb); + + rv = redir_drdos_put_rights(fname, dma, redir_drdos_pwmode(fcb[0x0c])); + if (rv || !(fcb[0x0c] & 1)) FCBRET(rv); + FCBRET(redir_drdos_put_rights(fname, dma, redir_drdos_pwmode(fcb[0x0c]) | 0x8000)); +#else + FCBRET(0xFF); /* Unix doesn't do this */ +#endif +} + +cpm_word fcb_getlbl(cpm_byte drv) +{ + DBGMSG("fcb_getlbl()\n"); +#ifdef __MSDOS__ + if (redir_drdos) return 0xA1; /* Supports passwords & Update stamps */ + return 0x21; /* Update stamps only */ +#else + return 0x61; /* Update & Access stamps */ +#endif +} + +cpm_word fcb_setlbl(cpm_byte* fcb, cpm_byte* dma) +{ + /* I am not letting CP/M fiddle with the host's FS settings - even if they + * could be altered, which they mostly can't. */ + + return 0x03FF; +} + +cpm_word fcb_defpwd(cpm_byte* pwd) +{ +#ifdef __MSDOS__ + union REGS r; + struct SREGS s; + + if (pwd[0] == 0 || pwd[0] == ' ') + { + redir_passwd[0] = 0; + } + else memcpy(redir_passwd, pwd, 8); + if (redir_drdos) + { + dosmemput(pwd, 8, __tb); + r.w.ax = 0x4454; + r.w.dx = __tb & 0x0F; + s.ds = __tb >> 4; + intdosx(&r, &r, &s); + } + +#endif + return 0; +} diff --git a/Tools/unix/zxcc/cpmredir.h b/Tools/unix/zxcc/cpmredir.h index 2584e239..40810159 100644 --- a/Tools/unix/zxcc/cpmredir.h +++ b/Tools/unix/zxcc/cpmredir.h @@ -1,151 +1,150 @@ -/* - CPMREDIR: CP/M filesystem redirector - Copyright (C) 1998, John Elliott - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - This file holds the public interface to CPMREDIR. -*/ - -#ifndef CPMREDIR_H_INCLUDED - -#define CPMREDIR_H_INCLUDED 16-11-1998 - -/* The "cpm_byte" must be exactly 8 bits. - The "cpm_word" must be exactly 16 bits. */ - -typedef unsigned char cpm_byte; -typedef unsigned short cpm_word; - -/* Maximum length of a directory path */ -#ifdef _POSIX_PATH_MAX - #define CPM_MAXPATH _POSIX_PATH_MAX -#else - #ifdef _MAX_PATH - #define CPM_MAXPATH _MAX_PATH - #else - #define CPM_MAXPATH 260 - #endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Initialise this library. Call this function first. - * - * Returns 0 if failed to initialise. - */ -int fcb_init(void); - -/* Deinitialise the library. */ - -void fcb_deinit(void); - -/* Translate a name from the host FS to a CP/M name. This will (if necessary) - * create a mapping between a CP/M drive and a host directory path. - * - * CP/M drives A: to O: can be mapped in this way. P: is always the current - * drive. - * - */ - -void xlt_name(char *localname, char *cpmname); - -/* It is sometimes convenient to set some fixed mappings. This will create - * a mapping for a given directory. - * Pass drive = -1 for "first available", or 0-15 for A: to P: - * Returns 1 if OK, 0 if requested drive not available. - * - * NB: It is important that the localname should have a trailing - * directory separator! - */ - -int xlt_map(int drive, char *localdir); - -/* - * This revokes a mapping. No check is made whether CP/M has files open - * on the drive or not. - */ - -int xlt_umap(int drive); - -/* Find out if a drive is mapped, and if so to what directory */ - -char *xlt_getcwd(int drive); - - -/* BDOS functions. Eventually this should handle all disc-related BDOS - * functions. - * - * I am assuming that your emulator has the CP/M RAM in its normal address - * space, accessible as a range 0-64k. If this is not the case - * (eg: you are emulating banked memory, or using a segmented architecture) - * you will have to use "copy in and copy out" techniques. The "fcb" area - * must be 36 bytes long; the "dma" area should be 128 * the value set - * in fcb_multirec() [default is 1, so 128 bytes]. - * - */ - -cpm_byte fcb_reset (void); /* 0x0D */ -cpm_word fcb_drive (cpm_byte drv); /* 0x0E */ -cpm_word fcb_open (cpm_byte *fcb, cpm_byte *dma); /* 0x0F */ -cpm_word fcb_close (cpm_byte *fcb); /* 0x10 */ -cpm_word fcb_find1 (cpm_byte *fcb, cpm_byte *dma); /* 0x11 */ -cpm_word fcb_find2 (cpm_byte *fcb, cpm_byte *dma); /* 0x12 */ -cpm_word fcb_unlink(cpm_byte *fcb, cpm_byte *dma); /* 0x13 */ -cpm_word fcb_read (cpm_byte *fcb, cpm_byte *dma); /* 0x14 */ -cpm_word fcb_write (cpm_byte *fcb, cpm_byte *dma); /* 0x15 */ -cpm_word fcb_creat (cpm_byte *fcb, cpm_byte *dma); /* 0x16 */ -cpm_word fcb_rename(cpm_byte *fcb, cpm_byte *dma); /* 0x17 */ -cpm_word fcb_logvec(void); /* 0x18 */ -cpm_byte fcb_getdrv(void); /* 0x19 */ -/* DMA is a parameter to routines, not a separate call */ -cpm_word fcb_getalv(cpm_byte *alv, cpm_word max); /* 0x1B */ -/* Get alloc vector: caller must provide space and say how big it is. */ -cpm_word fcb_rodisk(void); /* 0x1C */ -cpm_word fcb_rovec (void); /* 0x1D */ -cpm_word fcb_chmod (cpm_byte *fcb, cpm_byte *dma); /* 0x1E */ -cpm_word fcb_getdpb(cpm_byte *dpb); /* 0x1F */ -cpm_byte fcb_user (cpm_byte usr); /* 0x20 */ -cpm_word fcb_randrd(cpm_byte *fcb, cpm_byte *dma); /* 0x21 */ -cpm_word fcb_randwr(cpm_byte *fcb, cpm_byte *dma); /* 0x22 */ -cpm_word fcb_stat (cpm_byte *fcb); /* 0x23 */ -cpm_word fcb_tell (cpm_byte *fcb); /* 0x24 */ -cpm_word fcb_resro (cpm_word bitmap); /* 0x25 */ -/* Access Drives and Free Drives are not supported. */ -cpm_word fcb_randwz(cpm_byte *fcb, cpm_byte *dma); /* 0x28 */ -/* Record locking calls not supported (though they could be) */ -cpm_word fcb_multirec(cpm_byte rc); /* 0x2C */ -/* Set hardware error action must be done by caller */ -cpm_word fcb_dfree (cpm_byte drive, cpm_byte *dma);/* 0x2E */ -cpm_word fcb_sync (cpm_byte flag); /* 0x30 */ -cpm_word fcb_purge (void); /* 0x62 */ -cpm_word fcb_trunc (cpm_byte *fcb, cpm_byte *dma); /* 0x63 */ -cpm_word fcb_setlbl(cpm_byte *fcb, cpm_byte *dma); /* 0x64 */ -cpm_word fcb_getlbl(cpm_byte drive); /* 0x65 */ -cpm_word fcb_date (cpm_byte *fcb); /* 0x66 */ -cpm_word fcb_setpwd(cpm_byte *fcb, cpm_byte *dma); /* 0x67 */ -cpm_word fcb_defpwd(cpm_byte *pwd); /* 0x6A */ -cpm_word fcb_sdate (cpm_byte *fcb, cpm_byte *dma); /* 0x74 */ -cpm_word fcb_parse (char *txt, cpm_byte *fcb); /* 0x98 */ - -/* fcb_parse returns length of filename parsed, 0 if EOL, 0xFFFF if error */ -#ifdef __cplusplus -} -#endif - - -#endif /* def CPMREDIR_H_INCLUDED */ +/* + CPMREDIR: CP/M filesystem redirector + Copyright (C) 1998, John Elliott + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + This file holds the public interface to CPMREDIR. +*/ + +#ifndef CPMREDIR_H_INCLUDED + +#define CPMREDIR_H_INCLUDED 16-11-1998 + +/* The "cpm_byte" must be exactly 8 bits. + The "cpm_word" must be exactly 16 bits. */ + +typedef unsigned char cpm_byte; +typedef unsigned short cpm_word; + +/* Maximum length of a directory path */ +#ifdef _POSIX_PATH_MAX + #define CPM_MAXPATH _POSIX_PATH_MAX +#else + #ifdef _MAX_PATH + #define CPM_MAXPATH _MAX_PATH + #else + #define CPM_MAXPATH 260 + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + /* Initialise this library. Call this function first. + * + * Returns 0 if failed to initialise. + */ + int fcb_init(void); + + /* Deinitialise the library. */ + + void fcb_deinit(void); + + /* Translate a name from the host FS to a CP/M name. This will (if necessary) + * create a mapping between a CP/M drive and a host directory path. + * + * CP/M drives A: to O: can be mapped in this way. P: is always the current + * drive. + * + */ + + void xlt_name(char* localname, char* cpmname); + + /* It is sometimes convenient to set some fixed mappings. This will create + * a mapping for a given directory. + * Pass drive = -1 for "first available", or 0-15 for A: to P: + * Returns 1 if OK, 0 if requested drive not available. + * + * NB: It is important that the localname should have a trailing + * directory separator! + */ + + int xlt_map(int drive, char* localdir); + + /* + * This revokes a mapping. No check is made whether CP/M has files open + * on the drive or not. + */ + + int xlt_umap(int drive); + + /* Find out if a drive is mapped, and if so to what directory */ + + char* xlt_getcwd(int drive); + + /* BDOS functions. Eventually this should handle all disc-related BDOS + * functions. + * + * I am assuming that your emulator has the CP/M RAM in its normal address + * space, accessible as a range 0-64k. If this is not the case + * (eg: you are emulating banked memory, or using a segmented architecture) + * you will have to use "copy in and copy out" techniques. The "fcb" area + * must be 36 bytes long; the "dma" area should be 128 * the value set + * in fcb_multirec() [default is 1, so 128 bytes]. + * + */ + + cpm_byte fcb_reset(void); /* 0x0D */ + cpm_word fcb_drive(cpm_byte drv); /* 0x0E */ + cpm_word fcb_open(cpm_byte* fcb, cpm_byte* dma); /* 0x0F */ + cpm_word fcb_close(cpm_byte* fcb); /* 0x10 */ + cpm_word fcb_find1(cpm_byte* fcb, cpm_byte* dma); /* 0x11 */ + cpm_word fcb_find2(cpm_byte* fcb, cpm_byte* dma); /* 0x12 */ + cpm_word fcb_unlink(cpm_byte* fcb, cpm_byte* dma); /* 0x13 */ + cpm_word fcb_read(cpm_byte* fcb, cpm_byte* dma); /* 0x14 */ + cpm_word fcb_write(cpm_byte* fcb, cpm_byte* dma); /* 0x15 */ + cpm_word fcb_creat(cpm_byte* fcb, cpm_byte* dma); /* 0x16 */ + cpm_word fcb_rename(cpm_byte* fcb, cpm_byte* dma); /* 0x17 */ + cpm_word fcb_logvec(void); /* 0x18 */ + cpm_byte fcb_getdrv(void); /* 0x19 */ + /* DMA is a parameter to routines, not a separate call */ + cpm_word fcb_getalv(cpm_byte* alv, cpm_word max); /* 0x1B */ + /* Get alloc vector: caller must provide space and say how big it is. */ + cpm_word fcb_rodisk(void); /* 0x1C */ + cpm_word fcb_rovec(void); /* 0x1D */ + cpm_word fcb_chmod(cpm_byte* fcb, cpm_byte* dma); /* 0x1E */ + cpm_word fcb_getdpb(cpm_byte* dpb); /* 0x1F */ + cpm_byte fcb_user(cpm_byte usr); /* 0x20 */ + cpm_word fcb_randrd(cpm_byte* fcb, cpm_byte* dma); /* 0x21 */ + cpm_word fcb_randwr(cpm_byte* fcb, cpm_byte* dma); /* 0x22 */ + cpm_word fcb_stat(cpm_byte* fcb); /* 0x23 */ + cpm_word fcb_tell(cpm_byte* fcb); /* 0x24 */ + cpm_word fcb_resro(cpm_word bitmap); /* 0x25 */ + /* Access Drives and Free Drives are not supported. */ + cpm_word fcb_randwz(cpm_byte* fcb, cpm_byte* dma); /* 0x28 */ + /* Record locking calls not supported (though they could be) */ + cpm_word fcb_multirec(cpm_byte rc); /* 0x2C */ + /* Set hardware error action must be done by caller */ + cpm_word fcb_dfree(cpm_byte drive, cpm_byte* dma); /* 0x2E */ + cpm_word fcb_sync(cpm_byte flag); /* 0x30 */ + cpm_word fcb_purge(void); /* 0x62 */ + cpm_word fcb_trunc(cpm_byte* fcb, cpm_byte* dma); /* 0x63 */ + cpm_word fcb_setlbl(cpm_byte* fcb, cpm_byte* dma); /* 0x64 */ + cpm_word fcb_getlbl(cpm_byte drive); /* 0x65 */ + cpm_word fcb_date(cpm_byte* fcb); /* 0x66 */ + cpm_word fcb_setpwd(cpm_byte* fcb, cpm_byte* dma); /* 0x67 */ + cpm_word fcb_defpwd(cpm_byte* pwd); /* 0x6A */ + cpm_word fcb_sdate(cpm_byte* fcb, cpm_byte* dma); /* 0x74 */ + cpm_word fcb_parse(char* txt, cpm_byte* fcb); /* 0x98 */ + + /* fcb_parse returns length of filename parsed, 0 if EOL, 0xFFFF if error */ + +#ifdef __cplusplus +} +#endif + +#endif /* def CPMREDIR_H_INCLUDED */ diff --git a/Tools/unix/zxcc/dirent.c b/Tools/unix/zxcc/dirent.c index 87cf85a9..1cdce1cb 100644 --- a/Tools/unix/zxcc/dirent.c +++ b/Tools/unix/zxcc/dirent.c @@ -1,16 +1,15 @@ /* - Implementation of POSIX directory browsing functions and types for Win32. + Implementation of POSIX directory browsing functions and types for Win32. - Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com) - History: Created March 1997. Updated June 2003 and July 2012. - Rights: See end of file. + Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com) + History: Created March 1997. Updated June 2003 and July 2012. + Rights: See end of file. */ - +#pragma warning(disable : 4996) #include "dirent.h" #include -#include /* _findfirst and _findnext set errno iff they return -1 */ #include #include @@ -19,115 +18,89 @@ extern "C" { #endif -//typedef ptrdiff_t handle_type; /* C99's intptr_t not sufficiently portable */ -typedef long handle_type; /* C99's intptr_t not sufficiently portable */ - -struct DIR -{ - handle_type handle; /* -1 for failed rewind */ - struct _finddata_t info; - struct dirent result; /* d_name null iff first time */ - char *name; /* null-terminated char string */ -}; - -DIR *opendir(const char *name) -{ - DIR *dir = 0; - - if(name && name[0]) - { - size_t base_length = strlen(name); - const char *all = /* search pattern must end with suitable wildcard */ - strchr("/\\", name[base_length - 1]) ? "*" : "/*"; - - if((dir = (DIR *) malloc(sizeof *dir)) != 0 && - (dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0) - { - strcat(strcpy(dir->name, name), all); - - if((dir->handle = - (handle_type) _findfirst(dir->name, &dir->info)) != -1) - { - dir->result.d_name = 0; - } - else /* rollback */ - { - free(dir->name); - free(dir); - dir = 0; - } - } - else /* rollback */ - { - free(dir); - dir = 0; - errno = ENOMEM; - } - } - else - { - errno = EINVAL; - } - - return dir; -} - -int closedir(DIR *dir) -{ - int result = -1; - - if(dir) - { - if(dir->handle != -1) - { - result = _findclose(dir->handle); - } - - free(dir->name); - free(dir); - } - - if(result == -1) /* map all errors to EBADF */ - { - errno = EBADF; - } - - return result; -} - -struct dirent *readdir(DIR *dir) -{ - struct dirent *result = 0; - - if(dir && dir->handle != -1) - { - if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) - { - result = &dir->result; - result->d_name = dir->info.name; - } - } - else - { - errno = EBADF; - } - - return result; -} - -void rewinddir(DIR *dir) -{ - if(dir && dir->handle != -1) - { - _findclose(dir->handle); - dir->handle = (handle_type) _findfirst(dir->name, &dir->info); - dir->result.d_name = 0; - } - else - { - errno = EBADF; - } -} + DIR* opendir(const char* name) { + DIR* dir = 0; + + if (name && name[0]) { + size_t base_length = strlen(name); + const char* all = /* search pattern must end with suitable wildcard */ + strchr("/\\", name[base_length - 1]) ? "*" : "/*"; + + if ((dir = (DIR*)malloc(sizeof * dir)) != 0 && + (dir->name = (char*)malloc(base_length + strlen(all) + 1)) != 0) { + strcat(strcpy(dir->name, name), all); + + if ((dir->handle = + (handle_type)_findfirst(dir->name, &dir->info)) != -1) { + dir->result.d_name = 0; + } + else /* rollback */ + { + free(dir->name); + free(dir); + dir = 0; + } + } + else /* rollback */ + { + free(dir); + dir = 0; + errno = ENOMEM; + } + } + else { + errno = EINVAL; + } + + return dir; + } + + int closedir(DIR* dir) { + int result = -1; + + if (dir) { + if (dir->handle != -1) { + result = _findclose(dir->handle); + } + + free(dir->name); + free(dir); + } + + if (result == -1) /* map all errors to EBADF */ + { + errno = EBADF; + } + + return result; + } + + struct dirent* readdir(DIR* dir) { + struct dirent* result = 0; + + if (dir && dir->handle != -1) { + if (!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) { + result = &dir->result; + result->d_name = dir->info.name; + } + } + else { + errno = EBADF; + } + + return result; + } + + void rewinddir(DIR* dir) { + if (dir && dir->handle != -1) { + _findclose(dir->handle); + dir->handle = (handle_type)_findfirst(dir->name, &dir->info); + dir->result.d_name = 0; + } + else { + errno = EBADF; + } + } #ifdef __cplusplus } @@ -135,15 +108,15 @@ void rewinddir(DIR *dir) /* - Copyright Kevlin Henney, 1997, 2003, 2012. All rights reserved. + Copyright Kevlin Henney, 1997, 2003, 2012. All rights reserved. - Permission to use, copy, modify, and distribute this software and its - documentation for any purpose is hereby granted without fee, provided - that this copyright and permissions notice appear in all copies and - derivatives. - - This software is supplied "as is" without express or implied warranty. + Permission to use, copy, modify, and distribute this software and its + documentation for any purpose is hereby granted without fee, provided + that this copyright and permissions notice appear in all copies and + derivatives. - But that said, if there are any problems please get in touch. + This software is supplied "as is" without express or implied warranty. -*/ + But that said, if there are any problems please get in touch. + +*/ \ No newline at end of file diff --git a/Tools/unix/zxcc/dirent.h b/Tools/unix/zxcc/dirent.h index bbbfce52..7db1a3ee 100644 --- a/Tools/unix/zxcc/dirent.h +++ b/Tools/unix/zxcc/dirent.h @@ -8,40 +8,48 @@ Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com) History: Created March 1997. Updated June 2003. Rights: See end of file. - + */ +#include /* _findfirst and _findnext set errno iff they return -1 */ + #ifdef __cplusplus extern "C" { #endif -typedef struct DIR DIR; + struct dirent { + char *d_name; + }; -struct dirent -{ - char *d_name; -}; + typedef ptrdiff_t handle_type; /* C99's intptr_t not sufficiently portable */ -DIR *opendir(const char *); -int closedir(DIR *); -struct dirent *readdir(DIR *); -void rewinddir(DIR *); + typedef struct { + handle_type handle; /* -1 for failed rewind */ + struct _finddata_t info; + struct dirent result; /* d_name null iff first time */ + char *name; /* null-terminated char string */ + } DIR; -/* + DIR *opendir(const char *); + int closedir(DIR *); + struct dirent *readdir(DIR *); + void rewinddir(DIR *); - Copyright Kevlin Henney, 1997, 2003. All rights reserved. + /* - Permission to use, copy, modify, and distribute this software and its - documentation for any purpose is hereby granted without fee, provided - that this copyright and permissions notice appear in all copies and - derivatives. - - This software is supplied "as is" without express or implied warranty. + Copyright Kevlin Henney, 1997, 2003. All rights reserved. - But that said, if there are any problems please get in touch. + Permission to use, copy, modify, and distribute this software and its + documentation for any purpose is hereby granted without fee, provided + that this copyright and permissions notice appear in all copies and + derivatives. -*/ + This software is supplied "as is" without express or implied warranty. + + But that said, if there are any problems please get in touch. + + */ #ifdef __cplusplus } diff --git a/Tools/unix/zxcc/drdos.c b/Tools/unix/zxcc/drdos.c index baf7a00b..f62a3a5c 100644 --- a/Tools/unix/zxcc/drdos.c +++ b/Tools/unix/zxcc/drdos.c @@ -1,23 +1,23 @@ /* - CPMREDIR: CP/M filesystem redirector - Copyright (C) 1998, John Elliott + CPMREDIR: CP/M filesystem redirector + Copyright (C) 1998, John Elliott - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. - This library 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 - Library General Public License for more details. + This library 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 + Library General Public License for more details. - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - This file holds DRDOS-specific password code. + This file holds DRDOS-specific password code. */ #include "cpmint.h" @@ -46,24 +46,24 @@ cpm_byte redir_cpm_pwmode(cpm_word w) #ifdef __MSDOS__ #ifdef __GO32__ /* The GO32 extender doesn't understand DRDOS password - * functions, so these are done with __dpmi_int() rather - * than intdos() */ + * functions, so these are done with __dpmi_int() rather + * than intdos() */ -cpm_word redir_drdos_get_rights(char *path) +cpm_word redir_drdos_get_rights(char* path) { __dpmi_regs r; - if (!redir_drdos) return 0; + if (!redir_drdos) return 0; redir_Msg("Rights for file %s: \n\r", path); dosmemput(path, strlen(path) + 1, __tb); r.x.ax = 0x4302; r.x.dx = __tb & 0x0F; - r.x.ds = (__tb) >> 4; + r.x.ds = (__tb) >> 4; __dpmi_int(0x21, &r); - + redir_Msg(" %04x \n\r", r.x.cx); if (r.x.flags & 1) return 0; @@ -71,15 +71,15 @@ cpm_word redir_drdos_get_rights(char *path) } -cpm_word redir_drdos_put_rights(char *path, cpm_byte *dma, cpm_word rights) +cpm_word redir_drdos_put_rights(char* path, cpm_byte* dma, cpm_word rights) { __dpmi_regs r; - if (!redir_drdos) return 0; + if (!redir_drdos) return 0; redir_Msg("Put rights for file %s: %04x %-8.8s %-8.8s\n\r", path, rights, dma, dma + 8); - dosmemput(dma+8, 8, __tb); /* Point DTA at password */ + dosmemput(dma + 8, 8, __tb); /* Point DTA at password */ r.x.ax = 0x1A00; r.x.dx = (__tb & 0x0F); r.x.ds = (__tb) >> 4; @@ -89,11 +89,11 @@ cpm_word redir_drdos_put_rights(char *path, cpm_byte *dma, cpm_word rights) r.x.ax = 0x4303; /* Set rights */ r.x.cx = rights; r.x.dx = (__tb & 0x0F) + 0x10; - r.x.ds = (__tb) >> 4; + r.x.ds = (__tb) >> 4; __dpmi_int(0x21, &r); - - if (r.x.flags & 1) + + if (r.x.flags & 1) { redir_Msg(" Try 1 failed. Error %04x\n\r", r.x.ax); if (redir_password_error()) @@ -104,7 +104,7 @@ cpm_word redir_drdos_put_rights(char *path, cpm_byte *dma, cpm_word rights) r.x.ax = 0x4303; /* Set rights */ r.x.cx = rights; r.x.dx = (__tb & 0x0F) + 0x10; - r.x.ds = (__tb) >> 4; + r.x.ds = (__tb) >> 4; __dpmi_int(0x21, &r); if (!r.x.flags & 1) return 0; @@ -117,22 +117,22 @@ cpm_word redir_drdos_put_rights(char *path, cpm_byte *dma, cpm_word rights) #else /* __GO32__ */ -cpm_word redir_drdos_get_rights(char *path) +cpm_word redir_drdos_get_rights(char* path) { union REGS r; struct SREGS s; - if (!redir_drdos) return 0; + if (!redir_drdos) return 0; redir_Msg("Rights for file %s: \n\r", path); dosmemput(path, strlen(path) + 1, __tb); r.w.ax = 0x4302; r.w.dx = __tb & 0x0F; - s.ds = (__tb) >> 4; + s.ds = (__tb) >> 4; intdosx(&r, &r, &s); - + redir_Msg(" %04x \n\r", r.w.cx); if (r.w.cflag) return 0; @@ -140,30 +140,30 @@ cpm_word redir_drdos_get_rights(char *path) } -cpm_word redir_drdos_put_rights(char *path, cpm_byte *dma, cpm_word rights) +cpm_word redir_drdos_put_rights(char* path, cpm_byte* dma, cpm_word rights) { union REGS r; struct SREGS s; - if (!redir_drdos) return 0; + if (!redir_drdos) return 0; redir_Msg("Put rights for file %s: %04x\n\r", path, rights); - dosmemput(dma, 8, __tb); /* Point DTA at password */ + dosmemput(dma, 8, __tb); /* Point DTA at password */ r.w.ax = 0x1A00; r.w.dx = (__tb & 0x0F); - s.ds = (__tb) >> 4; + s.ds = (__tb) >> 4; intdosx(&r, &r, &s); dosmemput(path, strlen(path) + 1, __tb + 0x10); r.w.ax = 0x4303; /* Set rights */ r.w.cx = rights; r.w.dx = (__tb & 0x0F) + 0x10; - s.ds = (__tb) >> 4; + s.ds = (__tb) >> 4; intdosx(&r, &r, &s); - - if (r.w.cflag) + + if (r.w.cflag) { redir_Msg(" Try 1 failed. Error %04x \n\r", r.w.ax); if (redir_password_error()) @@ -174,7 +174,7 @@ cpm_word redir_drdos_put_rights(char *path, cpm_byte *dma, cpm_word rights) r.w.ax = 0x4303; /* Set rights */ r.w.cx = rights; r.w.dx = (__tb & 0x0F) + 0x10; - s.ds = (__tb) >> 4; + s.ds = (__tb) >> 4; intdosx(&r, &r, &s); if (!r.w.cflag) return 0; @@ -198,14 +198,14 @@ cpm_word redir_password_error(void) intdos(&r, &r); - redir_Msg("Last error was: %04x\r\n", r.w.ax); + redir_Msg("Last error was: %04x\n", r.w.ax); if (r.w.ax == 0x56) return 1; /* Bad password */ return 0; } -void redir_password_append(char *s, cpm_byte *dma) +void redir_password_append(char* s, cpm_byte* dma) { int n, m; @@ -223,14 +223,14 @@ void redir_password_append(char *s, cpm_byte *dma) ++m; } s[m] = 0; - + } #else /* __MSDOS__ */ -void redir_password_append(char *s, cpm_byte *dma) {} +void redir_password_append(char* s, cpm_byte* dma) {} cpm_word redir_password_error(void) { return 0; } -cpm_word redir_drdos_put_rights(char *path, cpm_byte *dma, cpm_word rights) -{ return 0; } -cpm_word redir_drdos_get_rights(char *path) { return 0; } +cpm_word redir_drdos_put_rights(char* path, cpm_byte* dma, cpm_word rights) +{ + return 0; +} +cpm_word redir_drdos_get_rights(char* path) { return 0; } #endif /* __MSDOS__ */ - - diff --git a/Tools/unix/zxcc/track.c b/Tools/unix/zxcc/track.c index 20770a8a..7c944b79 100644 --- a/Tools/unix/zxcc/track.c +++ b/Tools/unix/zxcc/track.c @@ -1,7 +1,7 @@ /* CPMREDIR: CP/M filesystem redirector - Optional Open file tracker + Optional Open file tracker Copyright (C) 2021, Mark Ogden This is an addition to the CPMREDIR @@ -22,8 +22,8 @@ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -//#include "cpmint.h" -#include "zxcc.h" + +#include "cpmint.h" /* CP/M does not require that files opened for reading need to be closed, * this has two impacts @@ -37,52 +37,66 @@ * As an example the build of cgen.com using my decompiled sources * the linq phase without tracking left 42 open files * with tracking this was reduced to 2 - * + * * This code keeps track of files that are opened until they are explicitly * closed or the FCB used to open the file is reused, or the file needs to be * renamed or deleted. * To do this it keeps track of the expanded filename, fcb location and allocated * file handle - * + * * Two public functions are used to manage the file list, and are called from * within the bdos emulation - * + * * trackFile(char *fname, void *fcb, int fd) * removes existing tracking with matchin fcb or fd and * if (fname != NULL) - add the info to the head of the open files list * it returns fd - * + * * the function is called in the following circumstances * 1) before closing a file (fname is NULL) - * 2) just after the file has been opened/created. + * 2) just after the file has been opened/created. * 3) to remove association with a given fcb trackFile(NULL, fcb, -1) * * note a helper macro releaseFCB(fcb) can be used for (3) above - * + * * releaseFile(char *fname) * this scans through the list of open files and for each open file * with a matching fname, the file is closed - * + * * the function is called before deleting a file or renaming a file - * - * + * + * * there is a helper function that removes the info from the list - * + * * Notes: * For most applications the tracker could in principle automatically * close existing open files at the start of a new executable invocation. * Unfortunately this does not support the case where there is a scripting * engine intercepting the warm reboots, as it may need to keep the script * source file open. - * + * * Note in theory it would be possible for a CP/M program to open a file * with a given fcb, move the fcb internally and then open another file * with the original fcb. If this happens the FCB tracking could cause * a problem. I am not aware of any real programs that do this. * Please let me know if the situation arises. */ -/* windows needs to use file tracking, for unix/linux it is optional */ + +/* + * The FILETRACKER functionality was implemented primarily because + * MSDOS file interface does not allow opening files in shared mode. + * This port of zxcc deprecates MSDOS and uses WIN32 API calls to handle + * all file I/O. So, this means that FILETRACKER is now optional for + * for Windows as well as Unix. I have found some edge cases where + * FILETRACKER caused a CP/M program to misbehave. Specifically, ZSM4 + * reuses FCBs if files are included and does it such a way that the + * FILETRACKER is unable to solve the problem. For maximum + * compatibility, FILETRACKER may now be left off with the implication + * that a lot of file handles will be left open. + */ + #ifdef FILETRACKER + typedef struct _track { struct _track* next; int handle; @@ -111,10 +125,9 @@ void releaseFile(char* fname) { s = s->next; } - int trackFile(char* fname, void* fcb, int fd) { track_t* s = (track_t*)&openFiles; - Msg("trackFile: \"%s\", FCB=0x%X, Handle=%i\n", fname, (byte *)fcb - RAM, fd); + Msg("trackFile: \"%s\", FCB=0x%X, Handle=%i\n", fname, (byte*)fcb - RAM, fd); while (s->next) { /* find any existing fcb or fd */ if (s->next->fcb == fcb || s->next->handle == fd) { if (s->next->handle != fd) { @@ -147,4 +160,3 @@ void releaseFile(char* fname) {} int trackFile(char* fname, void* fcb, int fd) { return fd; } #endif - diff --git a/Tools/unix/zxcc/util.c b/Tools/unix/zxcc/util.c index bc3dbb6e..e26fa0db 100644 --- a/Tools/unix/zxcc/util.c +++ b/Tools/unix/zxcc/util.c @@ -1,408 +1,484 @@ -/* - - CPMREDIR: CP/M filesystem redirector - Copyright (C) 1998, John Elliott - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - This file holds miscellaneous utility functions. -*/ - -#include "cpmint.h" - - - - - - -/* In debug mode, lseek()s can be traced. */ - -#ifdef DEBUG - -long zxlseek(int fd, long offset, int wh) -{ -#ifdef _WIN32 - long v; - redir_Msg(">SetFilePointer() Handle=%lu, Offset=%lu, Method=%lu\n", fd, offset, wh); - v = SetFilePointer((HANDLE)fd, offset, NULL, wh); - redir_Msg("= 0) return v; - - redir_Msg("lseek fails with errno = %d\n", errno); - if (errno == EBADF) redir_Msg(" (bad file descriptor %d)\n", fd); - if (errno == ESPIPE) redir_Msg(" (file %d is a pipe)\n", fd); - if (errno == EINVAL) redir_Msg(" (bad parameter %d)\n", wh); - - return -1; -#endif -} - -#else - -long zxlseek(int fd, long offset, int wh) -{ - #ifdef _WIN32 - return SetFilePointer((HANDLE)fd, offset, NULL, wh); - #else - return lseek(fd, offset, wh); - #endif -} - - -#endif - -#ifdef DEBUG - -void redir_showfcb(cpm_byte *fd) -{ - int n; - - for (n = 0; n < 32; n++) - { - if (!n || n>= 12) printf("%02x ", fd[n]); - else printf("%c", fd[n] & 0x7F); - } - printf("\r\n"); -} - -#endif - -/* Get the "sequential access" file pointer out of an FCB */ - -long redir_get_fcb_pos(cpm_byte *fcb) -{ - long npos; - - npos = 524288L * fcb[0x0E]; /* S2 */ - npos += 16384L * fcb[0x0C]; /* Extent */ - npos += 128L * fcb[0x20]; /* Record */ - - return npos; -} - -void redir_put_fcb_pos(cpm_byte *fcb, long npos) -{ - fcb[0x20] = (npos / 128) % 128; /* Record */ - fcb[0x0C] = (npos / 16384) % 32; /* Extent */ - fcb[0x0E] = (npos / 524288L) % 64; /* S2 */ -} - - -/* - * find a filename that works. - * note that this is where we handle the case sensitivity/non-case sensitivity - * horror. - * the name that is passed in should be in lower case. - * we'll modify it to the first one that matches - */ -void -swizzle(char *fullpath) -{ - struct stat ss; - char *slash; - DIR *dirp; - struct dirent *dentry; - - /* short circuit if ok */ - if (stat(fullpath, &ss) == 0) { - return; - } - - slash = strrchr(fullpath, '/'); - if (!slash) { - return; - } - *slash = '\0'; - dirp = opendir(fullpath); - *slash = '/'; - while ((dentry = readdir(dirp)) != NULL) { - if (strcasecmp(dentry->d_name, slash + 1) == 0) { - strcpy(slash + 1, dentry->d_name); - break; - } - } - closedir(dirp); -} - -/* Passed a CP/M FCB, convert it to a unix filename. Turn its drive back into - * a path. */ - -int redir_fcb2unix(cpm_byte *fcb, char *fname) -{ - int n, q, drv, ddrv; - char s[2]; - - s[1] = 0; - q = 0; - drv = fcb[0] & 0x7F; - if (drv == '?') drv = 0; - - ddrv = fcb[0] & 0x7F; - if (ddrv < 0x1F) ddrv += '@'; - - redir_Msg("%c:%-8.8s.%-3.3s\n", - ddrv, - fcb + 1, - fcb + 9); - - if (!drv) strcpy(fname, redir_drive_prefix[redir_cpmdrive]); - else strcpy(fname, redir_drive_prefix[drv - 1]); - - for (n = 1; n < 12; n++) - { - s[0] = (fcb[n] & 0x7F); - if (s[0] == '?') q = 1; - if (isupper(s[0])) s[0] = tolower(s[0]); - if (s[0] != ' ') - { - if (n == 9) strcat(fname, "."); - strcat(fname, s); - } - } - return q; -} - -#ifndef EROFS /* Open fails because of read-only FS */ -#define EROFS EACCES -#endif - -int redir_ofile(cpm_byte *fcb, char *s) -{ - int h; - - /* Software write-protection */ -#ifdef _WIN32 - redir_Msg(">CreateFile([OPEN_EXISTING]) Name='%s'\n", s); - h = (int)CreateFile(s, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - redir_Msg("= 0 || (errno != EACCES && errno != EROFS)) - return trackFile(s, fcb, h); - } - h = open(s, O_RDONLY | O_BINARY); - if (h < 0) return -1; - fcb[9] |= 0x80; - #endif -#endif - return trackFile(s, fcb, h); -} - - -/* Extract a file handle from where it was stored in an FCB by fcb_open() - or fcb_creat(). Aborts if the FCB has been tampered with. - - Note: Some programs (like GENCOM) close FCBs they never opened. This causes - the Corrupt FCB message, but no harm seems to ensue. */ - -int redir_verify_fcb(cpm_byte *fcb) -{ - if (fcb[16] != 0xFD || fcb[17] != 0x00) - { - fprintf(stderr,"cpmredir: Corrupt FCB\n"); - return -1; - } - return (int)(redir_rd32(fcb + 18)); - -} - -/* Print a trace message */ - -#ifdef DEBUG - -void redir_Msg(char *s, ...) -{ - va_list ap; - - va_start(ap, s); - fprintf(stderr, "cpmredir trace: "); - vfprintf(stderr, s, ap); - va_end(ap); - fflush(stderr); -} - -#endif - -#define BCD(x) (((x % 10)+16*(x/10)) & 0xFF) - -/* Convert time_t to CP/M day count/hours/minutes */ -dword redir_cpmtime(time_t t) -{ -/* Microsoft compiler warned around the conversion from time_t to long - * as to support dates beyond 2038 time_t is set as a long long - * and for the Microsoft compiler sizeof(long) == 4 and sizeof(long long) == 8 - * for other compilers both have size 8 - * As the result is a dword (unsigned long), the code below is modified to reflect this - */ - - dword d = (dword)((t / 86400) - 2921); /* CP/M day 0 is unix day 2921 */ - dword h = (t % 86400) / 3600; /* Hour, 0-23 */ - dword m = (t % 3600) / 60; /* Minute, 0-59 */ - - return (d | (BCD(h) << 16) | (BCD(m) << 24)); -} - -#undef BCD - -#define UNBCD(x) (((x % 16) + 10 * (x / 16)) & 0xFF) - -time_t redir_unixtime(cpm_byte *c) -{ - time_t t; - cpm_word days; - - days = (c[0] + 256 * c[1]) + 2921; - - t = 60L * UNBCD(c[3]); - t += 3600L * UNBCD(c[2]); - t += 86400L * days; - - return t; -} - -#undef UNBCD - - -/* Functions to access 24-bit & 32-bit words in memory. These are always - little-endian. */ - -void redir_wr24(cpm_byte *addr, dword v) -{ - addr[0] = v & 0xFF; - addr[1] = (v >> 8) & 0xFF; - addr[2] = (v >> 16) & 0xFF; -} - -void redir_wr32(cpm_byte *addr, dword v) -{ - addr[0] = v & 0xFF; - addr[1] = (v >> 8) & 0xFF; - addr[2] = (v >> 16) & 0xFF; - addr[3] = (v >> 24) & 0xFF; -} - -dword redir_rd24(cpm_byte *addr) -{ - register dword rv = addr[2]; - - rv = (rv << 8) | addr[1]; - rv = (rv << 8) | addr[0]; - return rv; -} - - -dword redir_rd32(cpm_byte *addr) -{ - register dword rv = addr[3]; - - rv = (rv << 8) | addr[2]; - rv = (rv << 8) | addr[1]; - rv = (rv << 8) | addr[0]; - return rv; -} - - -void redir_log_drv(cpm_byte drv) -{ - if (!drv) redir_l_drives |= 1; - else redir_l_drives |= (1L << drv); -} - -void redir_log_fcb(cpm_byte *fcb) -{ - int drv = fcb[0] & 0x7F; - - if (drv && drv != '?') redir_log_drv(drv - 1); - else redir_log_drv(redir_cpmdrive); -} - - -int redir_ro_drv(cpm_byte drv) -{ - if (!drv) return redir_ro_drives & 1; - else return redir_ro_drives & (1L << drv); -} - -int redir_ro_fcb(cpm_byte *fcb) -{ - int drv = fcb[0] & 0x7F; - - if (drv && drv != '?') return redir_ro_drv(drv - 1); - else return redir_ro_drv(redir_cpmdrive); -} - - - -cpm_word redir_xlt_err(void) -{ - if (redir_password_error()) return 0x7FF; /* DRDOS pwd error */ - switch(errno) - { - case EISDIR: - case EBADF: return 9; /* Bad FCB */ - case EINVAL: return 0x03FF; /* Readonly file */ - case EPIPE: return 0x01FF; /* Broken pipe */ - case ENOSPC: return 1; /* No space */ - default: return 0xFF; /* Software error */ - } -} - - -#ifdef _WIN32 -/* minimal implementation of truncate */ -int truncate(const char* path, off_t length) -{ - int result; - int fd = open(path, O_BINARY | O_RDWR); - - if (fd < 0) - return -1; - result = ftruncate(fd, length); - return close(fd) == 0 && result == 0 ? 0 : -1; - -} - - -#endif +/* + + CPMREDIR: CP/M filesystem redirector + Copyright (C) 1998, John Elliott + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + This file holds miscellaneous utility functions. +*/ + +#include "cpmint.h" + +#ifdef _WIN32 + +char* GetErrorStr(dword dwErr) +{ + LPVOID lpMsgBuf; + static char ErrStr[256] = ""; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_MAX_WIDTH_MASK, + NULL, + dwErr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpMsgBuf, + sizeof(ErrStr), NULL); + + strncpy(ErrStr, lpMsgBuf, sizeof(ErrStr)); + + LocalFree(lpMsgBuf); + + return ErrStr; +} + +#endif + +char* whence(int wh) +{ + switch (wh) + { + case SEEK_SET: return("SEEK_SET"); + case SEEK_CUR: return("SEEK_CUR"); + case SEEK_END: return("SEEK_END"); + default: return("SEEK_???"); + } +} + +/* In debug mode, lseek()s can be traced. */ + +long zxlseek(int fd, long offset, int wh) +{ +#ifdef _WIN32 + + long v; + DBGMSGV("seek on file #%i to 0x%lX using %s\n", fd, offset, whence(wh)); + v = SetFilePointer((HANDLE)fd, offset, NULL, wh); + if (v != INVALID_SET_FILE_POINTER) return v; + DBGMSGV("seek failed (Error=%lu): %s\n", GetLastError(), GetErrorStr(GetLastError())); + return -1; + +#else + + DBGMSGV("seek on #%i to 0x%lX using %s\n", fd, offset, whence(wh)); + long v = lseek(fd, offset, wh); + if (v >= 0) return v; + DBGMSGV("seek failed (errno=%lu): %s\n", errno, strerror(errno)); + return -1; + +#endif +} + +#ifdef DEBUG + +void redir_showfcb(cpm_byte* fd) +{ + int n; + + for (n = 0; n < 32; n++) + { + if (!n || n >= 12) printf("%02x ", fd[n]); + else printf("%c", fd[n] & 0x7F); + } + printf("\n"); +} + +#endif + +/* Get the "sequential access" file pointer out of an FCB */ + +long redir_get_fcb_pos(cpm_byte* fcb) +{ + long npos; + + npos = 524288L * fcb[0x0E]; /* S2 */ + npos += 16384L * fcb[0x0C]; /* Extent */ + npos += 128L * fcb[0x20]; /* Record */ + + return npos; +} + +void redir_put_fcb_pos(cpm_byte* fcb, long npos) +{ + fcb[0x20] = (npos / 128) % 128; /* Record */ + fcb[0x0C] = (npos / 16384) % 32; /* Extent */ + fcb[0x0E] = (npos / 524288L) % 64; /* S2 */ +} + +/* + * find a filename that works. + * note that this is where we handle the case sensitivity/non-case sensitivity + * horror. + * the name that is passed in should be in lower case. + * we'll modify it to the first one that matches + */ +void swizzle(char* fullpath) +{ + struct stat ss; + char* slash; + DIR* dirp; + struct dirent* dentry; + + /* short circuit if ok */ + if (stat(fullpath, &ss) == 0) { + return; + } + + slash = strrchr(fullpath, '/'); + if (!slash) { + return; + } + *slash = '\0'; + dirp = opendir(fullpath); + *slash = '/'; + while ((dentry = readdir(dirp)) != NULL) { + if (strcasecmp(dentry->d_name, slash + 1) == 0) { + strcpy(slash + 1, dentry->d_name); + break; + } + } + closedir(dirp); +} + +/* Passed a CP/M FCB, convert it to a unix filename. Turn its drive back into + * a path. */ + +int redir_fcb2unix(cpm_byte* fcb, char* fname) +{ + int n, q, drv, ddrv; + char s[2]; + char buf[256]; + + s[1] = 0; + q = 0; + drv = fcb[0] & 0x7F; + if (drv == '?') drv = 0; + + ddrv = fcb[0] & 0x7F; + if (ddrv < 0x1F) ddrv += '@'; + + if (!drv) strcpy(fname, redir_drive_prefix[redir_cpmdrive]); + else strcpy(fname, redir_drive_prefix[drv - 1]); + + for (n = 1; n < 12; n++) + { + s[0] = (fcb[n] & 0x7F); + if (s[0] == '?') q = 1; + if (isupper(s[0])) s[0] = tolower(s[0]); + if (s[0] != ' ') + { + if (n == 9) strcat(fname, "."); + strcat(fname, s); + } + } + + sprintf(buf, "'%c:%-8.8s.%-3.3s' --> '%s'", ddrv, fcb + 1, fcb + 9, fname); + for (n = 0; buf[n] != '\0'; n++) + { + buf[n] &= 0x7F; + if (buf[n] < ' ') buf[n] = 'x'; + } + + DBGMSGV("%s\n", buf); + + return q; +} + +#ifndef EROFS /* Open fails because of read-only FS */ +#define EROFS EACCES +#endif + +int redir_ofile(cpm_byte* fcb, char* s) +{ + int h; + + /* Software write-protection */ + +#ifdef _WIN32 + + releaseFCB(fcb); + + if (!redir_ro_fcb(fcb)) + { + // Attempt to open existing file with read/write access + DBGMSGV("open existing file '%s' with read/write access\n", s); + h = (int)CreateFile(s, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (h != HFILE_ERROR) + { + DBGMSGV("file '%s' opened R/W as #%i\n", s, h); + return trackFile(s, fcb, h); + } + DBGMSGV("open R/W failed (errno=%lu): %s\n", GetLastError(), GetErrorStr(GetLastError())); + } + + // Attempt to open existing file with read-only access + DBGMSGV("open existing file '%s' with read-only access\n", s); + h = (int)CreateFile(s, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (h == HFILE_ERROR) + { + DBGMSGV("open R/O failed (errno=%lu): %s\n", GetLastError(), GetErrorStr(GetLastError())); + return -1; + } + DBGMSGV("file '%s' opened R/O as #%i\n", s, h); + fcb[9] |= 0x80; + +#elif defined(__MSDOS__) + + int rv; + if (!redir_ro_fcb(fcb)) + { + rv = _dos_open(s, O_RDWR, &h); + if (!rv) return h; + DBGMSGV("Open of %s fails: error %x\n", s, rv); + } + rv = _dos_open(s, O_RDONLY, &h); + if (rv) return -1; + fcb[9] |= 0x80; + +#else + + releaseFCB(fcb); + + swizzle(s); + + if (!redir_ro_fcb(fcb)) + { + // Attempt to open existing file with read/write access + DBGMSGV("open existing file '%s' with read/write access\n", s); + h = open(s, O_RDWR | O_BINARY); + if (h >= 0 || (errno != EACCES && errno != EROFS)) + { + DBGMSGV("file '%s' opened R/W as #%i\n", s, h); + return trackFile(s, fcb, h); + } + DBGMSGV("failed to open R/W (errno=%lu): %s\n", errno, strerror(errno)); + } + + // Attempt to open existing file with read-only access + DBGMSGV("open existing file '%s' with read-only access\n", s); + h = open(s, O_RDONLY | O_BINARY); + if (h < 0) + { + DBGMSGV("failed to open R/O (errno=%lu): %s\n", errno, strerror(errno)); + return -1; + } + DBGMSGV("file '%s' opened R/O as #%i\n", s, h); + fcb[9] |= 0x80; + +#endif + + return trackFile(s, fcb, h); +} + +/* Extract a file handle from where it was stored in an FCB by fcb_open() + or fcb_creat(). Aborts if the FCB has been tampered with. + + Note: Some programs (like GENCOM) close FCBs they never opened. This causes + the Corrupt FCB message, but no harm seems to ensue. */ + +int redir_verify_fcb(cpm_byte* fcb) +{ + if (fcb[16] != 0xFD || fcb[17] != 0x00) + { + fprintf(stderr, "cpmredir: Corrupt FCB\n"); + return -1; + } + return (int)(redir_rd32(fcb + 18)); +} + +/* Print a trace message */ + +#ifdef DEBUG + +void DbgMsg(const char* file, int line, const char* func, char* s, ...) +{ + va_list ap; + + va_start(ap, s); + fprintf(stderr, "%s(%s@%i): ", func, file, line); + vfprintf(stderr, s, ap); + va_end(ap); + fflush(stderr); +} + +#endif + +#define BCD(x) (((x % 10)+16*(x/10)) & 0xFF) + +/* Convert time_t to CP/M day count/hours/minutes */ +dword redir_cpmtime(time_t t) +{ + /* Microsoft compiler warned around the conversion from time_t to long + * as to support dates beyond 2038 time_t is set as a long long + * and for the Microsoft compiler sizeof(long) == 4 and sizeof(long long) == 8 + * for other compilers both have size 8 + * As the result is a dword (unsigned long), the code below is modified to reflect this + */ + + dword d = (dword)((t / 86400) - 2921); /* CP/M day 0 is unix day 2921 */ + dword h = (t % 86400) / 3600; /* Hour, 0-23 */ + dword m = (t % 3600) / 60; /* Minute, 0-59 */ + + return (d | (BCD(h) << 16) | (BCD(m) << 24)); +} + +#undef BCD + +#define UNBCD(x) (((x % 16) + 10 * (x / 16)) & 0xFF) + +time_t redir_unixtime(cpm_byte* c) +{ + time_t t; + cpm_word days; + + days = (c[0] + 256 * c[1]) + 2921; + + t = 60L * UNBCD(c[3]); + t += 3600L * UNBCD(c[2]); + t += 86400L * days; + + return t; +} + +#undef UNBCD + +/* Functions to access 24-bit & 32-bit words in memory. These are always + little-endian. */ + +void redir_wr24(cpm_byte* addr, dword v) +{ + addr[0] = v & 0xFF; + addr[1] = (v >> 8) & 0xFF; + addr[2] = (v >> 16) & 0xFF; +} + +void redir_wr32(cpm_byte* addr, dword v) +{ + addr[0] = v & 0xFF; + addr[1] = (v >> 8) & 0xFF; + addr[2] = (v >> 16) & 0xFF; + addr[3] = (v >> 24) & 0xFF; +} + +dword redir_rd24(cpm_byte* addr) +{ + register dword rv = addr[2]; + + rv = (rv << 8) | addr[1]; + rv = (rv << 8) | addr[0]; + return rv; +} + +dword redir_rd32(cpm_byte* addr) +{ + register dword rv = addr[3]; + + rv = (rv << 8) | addr[2]; + rv = (rv << 8) | addr[1]; + rv = (rv << 8) | addr[0]; + return rv; +} + +void redir_log_drv(cpm_byte drv) +{ + if (!drv) redir_l_drives |= 1; + else redir_l_drives |= (1L << drv); +} + +void redir_log_fcb(cpm_byte* fcb) +{ + int drv = fcb[0] & 0x7F; + + if (drv && drv != '?') redir_log_drv(drv - 1); + else redir_log_drv(redir_cpmdrive); +} + +int redir_ro_drv(cpm_byte drv) +{ + if (!drv) return redir_ro_drives & 1; + else return redir_ro_drives & (1L << drv); +} + +int redir_ro_fcb(cpm_byte* fcb) +{ + int drv = fcb[0] & 0x7F; + + if (drv && drv != '?') return redir_ro_drv(drv - 1); + else return redir_ro_drv(redir_cpmdrive); +} + +cpm_word redir_xlt_err(void) +{ + if (redir_password_error()) return 0x7FF; /* DRDOS pwd error */ + + switch (errno) + { + case EISDIR: + case EBADF: return 9; /* Bad FCB */ + case EINVAL: return 0x03FF; /* Readonly file */ + case EPIPE: return 0x01FF; /* Broken pipe */ + case ENOSPC: return 1; /* No space */ + default: return 0xFF; /* Software error */ + } +} + +#ifdef _WIN32 + +int truncate(const char* path, off_t length) +{ + BOOL bResult; + HANDLE hFile; + DWORD dwOffset; + + DBGMSGV("truncate file %s to %lu\n", path, length); + + hFile = CreateFile(path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + DBGMSGV("truncate failed to open file (Error=%lu): %s\n", GetLastError(), GetErrorStr(GetLastError())); + return -1; + } + + dwOffset = SetFilePointer(hFile, length, NULL, FILE_BEGIN); + if (dwOffset == INVALID_SET_FILE_POINTER) + { + DBGMSGV("truncate failed to open file (Error=%lu): %s\n", GetLastError(), GetErrorStr(GetLastError())); + CloseHandle(hFile); + return -1; + } + + bResult = SetEndOfFile(hFile); + if (!bResult) + { + DBGMSGV("truncate failed to set end of file (Error=%lu): %s\n", GetLastError(), GetErrorStr(GetLastError())); + CloseHandle(hFile); + return -1; + } + + bResult = CloseHandle(hFile); + if (!bResult) + { + DBGMSGV("truncate failed to close file (Error=%lu): %s\n", GetLastError(), GetErrorStr(GetLastError())); + return -1; + } + + DBGMSGV("truncate set file length to %lu\n", dwOffset); + return 0; +} + +#endif diff --git a/Tools/unix/zxcc/xlt.c b/Tools/unix/zxcc/xlt.c index 84b76952..a36f7f50 100644 --- a/Tools/unix/zxcc/xlt.c +++ b/Tools/unix/zxcc/xlt.c @@ -1,24 +1,24 @@ /* - CPMREDIR: CP/M filesystem redirector - Copyright (C) 1998, John Elliott + CPMREDIR: CP/M filesystem redirector + Copyright (C) 1998, John Elliott - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. - This library 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 - Library General Public License for more details. + This library 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 + Library General Public License for more details. - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - This file holds functions dealing with name translation; also the - initialisation code. + This file holds functions dealing with name translation; also the + initialisation code. */ #include "cpmint.h" @@ -29,213 +29,209 @@ static char* skipUser(char* localname); static void drdos_init(void) { -/* The DJGPP DOS extender won't detect DRDOS using intdos(), so we have - to use __dpmi_int() instead. */ + /* The DJGPP DOS extender won't detect DRDOS using intdos(), so we have + to use __dpmi_int() instead. */ -#ifdef __GO32__ - __dpmi_regs ir; + #ifdef __GO32__ + __dpmi_regs ir; - ir.x.ax = 0x4452; /* "DR" */ + ir.x.ax = 0x4452; /* "DR" */ - __dpmi_int(0x21, &ir); - if (ir.x.flags & 1) return; /* Not DRDOS */ + __dpmi_int(0x21, &ir); + if (ir.x.flags & 1) return; /* Not DRDOS */ - redir_Msg("DRDOS detected.\r\n"); + redir_Msg("DRDOS detected.\n"); - redir_drdos = 1; + redir_drdos = 1; -#else /* __GO32__ */ + #else /* __GO32__ */ - union REGS ir, or; + union REGS ir, or ; - ir.w.ax = 0x4452; /* "DR" */ + ir.w.ax = 0x4452; /* "DR" */ - intdos(&ir, &or); - if (or.w.cflag) return; /* Not DRDOS */ + intdos(&ir, &or ); + if (or .w.cflag) return; /* Not DRDOS */ - redir_Msg("DRDOS detected.\r\n"); + redir_Msg("DRDOS detected.\n"); - redir_drdos = 1; -#endif /* __GO32__ */ + redir_drdos = 1; + #endif /* __GO32__ */ } -#endif /* __MSDOS__ */ - - +#endif /* __MSDOS__ */ int fcb_init(void) { - int n; + int n; - /* A: to O: free */ - for (n = 0; n < 15; n++) redir_drive_prefix[n][0] = 0; + /* A: to O: free */ + for (n = 0; n < 15; n++) redir_drive_prefix[n][0] = 0; - strcpy(redir_drive_prefix[15], "./"); /* P: is current directory */ + strcpy(redir_drive_prefix[15], "./"); /* P: is current directory */ - /* Log on to P:. It is the only drive at this point which we - * know works. */ - redir_cpmdrive = 15; + /* Log on to P:. It is the only drive at this point which we + * know works. */ + redir_cpmdrive = 15; #ifdef __MSDOS__ - drdos_init(); + drdos_init(); #endif - return 1; + return 1; } /* Deinitialise the library. */ void fcb_deinit(void) { - /* Nothing */ + /* Nothing */ } /* Translate a name from the host FS to a CP/M name. This will (if necessary) - * create a mapping between a CP/M drive and a host directory path. + * create a mapping between a CP/M drive and a host directory path. * * CP/M drives A: to O: can be mapped in this way. P: is always the current - * drive. + * drive. * */ -void xlt_name(char *localname, char *cpmname) +void xlt_name(char* localname, char* cpmname) { - char ibuf[CPM_MAXPATH + 1]; - char nbuf[CPM_MAXPATH + 1]; - char *pname = ibuf; - char *s; - int n; + char ibuf[CPM_MAXPATH + 1]; + char nbuf[CPM_MAXPATH + 1]; + char* pname = ibuf; + char* s; + int n; - sprintf(ibuf, "%-.*s", CPM_MAXPATH, skipUser(localname)); + sprintf(ibuf, "%-.*s", CPM_MAXPATH, skipUser(localname)); - while ((s = strpbrk(pname, DIRSEP))) { /* find the last directory separator allows mixed \ and / in windows */ + while ((s = strpbrk(pname, DIRSEP))) { /* find the last directory separator allows mixed \ and / in windows */ #ifdef _WIN32 - if (*s == '\\') /* convert separators to common format so directory tracking works more efficiently */ - *s = '/'; + if (*s == '\\') /* convert separators to common format so directory tracking works more efficiently */ + *s = '/'; #endif - pname = s + 1; - } - - if (pname == ibuf) { /* No path separators in the name. It is therefore a - local filename, so map it to drive P: */ - strcpy(cpmname, "p:"); - strcat(cpmname, ibuf); - return; - } - - /* catch user specified current drive a,b,c,p or A,B,C,P only, which map to predefined directories */ - if (pname == ibuf + 2 && ibuf[1] == ':' && (s = strchr("aAbBcCpP", ibuf[0]))) { - cpmname[0] = tolower(*s); /* make sure it's lower case */ - strcpy(cpmname + 1, ibuf + 1); - return; - } - - strcpy(nbuf, pname); /* nbuf holds filename component */ - *pname = 0; /* ibuf holds path component */ - - /* See if the path is one of those already mapped to drives */ - - for (n = 0; n < 15; n++) - { - if (redir_drive_prefix[n][0] && !strcmp(ibuf, redir_drive_prefix[n])) - { - sprintf(cpmname,"%c:%s", n + 'a', nbuf); - return; - } - } - - /* It is not, see if another drive can be allocated */ - - for (n = 0; n < 15; n++) if (!redir_drive_prefix[n][0]) - { - strcpy(redir_drive_prefix[n], ibuf); - sprintf(cpmname,"%c:%s", n + 'a', nbuf); - return; - } - - /* No other drive can be allocated */ - - strcpy(cpmname,"p:"); - strcat(cpmname, nbuf); + pname = s + 1; + } + + if (pname == ibuf) { /* No path separators in the name. It is therefore a + local filename, so map it to drive P: */ + strcpy(cpmname, "p:"); + strcat(cpmname, ibuf); + return; + } + + /* catch user specified current drive a,b,c,p or A,B,C,P only, which map to predefined directories */ + if (pname == ibuf + 2 && ibuf[1] == ':' && (s = strchr("aAbBcCpP", ibuf[0]))) { + cpmname[0] = tolower(*s); /* make sure it's lower case */ + strcpy(cpmname + 1, ibuf + 1); + return; + } + + strcpy(nbuf, pname); /* nbuf holds filename component */ + *pname = 0; /* ibuf holds path component */ + + /* See if the path is one of those already mapped to drives */ + + for (n = 0; n < 15; n++) + { + if (redir_drive_prefix[n][0] && !strcmp(ibuf, redir_drive_prefix[n])) + { + sprintf(cpmname, "%c:%s", n + 'a', nbuf); + return; + } + } + + /* It is not, see if another drive can be allocated */ + + for (n = 0; n < 15; n++) if (!redir_drive_prefix[n][0]) + { + strcpy(redir_drive_prefix[n], ibuf); + sprintf(cpmname, "%c:%s", n + 'a', nbuf); + return; + } + + /* No other drive can be allocated */ + + strcpy(cpmname, "p:"); + strcat(cpmname, nbuf); } /* It is sometimes convenient to set some fixed mappings. This will create - * a mapping for a given directory. + * a mapping for a given directory. * Pass drive = -1 for "first available", or 0-15 for A: to P: */ -int xlt_map(int drive, char *localdir) +int xlt_map(int drive, char* localdir) { - int n; - - if (drive == -1) - { - for (n = 0; n < 15; n++) if (!redir_drive_prefix[n][0]) - { - drive = n; - break; - } - if (drive == -1) return 0; /* No space for mappings */ - } - if (redir_drive_prefix[drive][0]) return 0; /* Drive taken */ - - sprintf(redir_drive_prefix[drive], "%-.*s", CPM_MAXPATH, localdir); - return 1; + int n; + + if (drive == -1) + { + for (n = 0; n < 15; n++) if (!redir_drive_prefix[n][0]) + { + drive = n; + break; + } + if (drive == -1) return 0; /* No space for mappings */ + } + if (redir_drive_prefix[drive][0]) return 0; /* Drive taken */ + + sprintf(redir_drive_prefix[drive], "%-.*s", CPM_MAXPATH, localdir); + return 1; } - /* Unmap a drive */ int xlt_umap(int drive) { - if (!redir_drive_prefix[drive][0]) return 0; /* Drive not taken */ - redir_drive_prefix[drive][0] = 0; - return 1; + if (!redir_drive_prefix[drive][0]) return 0; /* Drive not taken */ + redir_drive_prefix[drive][0] = 0; + return 1; } - -char *xlt_getcwd(int drive) +char* xlt_getcwd(int drive) { - if (drive < 0 || drive > 16) return ""; + if (drive < 0 || drive > 16) return ""; - return redir_drive_prefix[drive]; + return redir_drive_prefix[drive]; } /* as zxcc doesn't really support user spaces, remove any user specification - *hitech c supports + * hitech c supports * [[0-9]+[:]][[a-pA-P]:]name[.ext] | [[a-pA-p][[0-9]+]:]name[.ext] * this function also checks that user is no more than 2 digits and user # <= 31 * the hitech fcb checks for : as char 2, 3, or 4 which aligns to this */ static char* skipUser(char* localname) { - char* s; - int user; - int drive; - - if (!localname || !(s = strchr(localname, ':')) || s > localname + 3) - return localname; - s = localname; - if (isdigit(*s)) { - user = *s++ - '0'; - if (isdigit(*s)) { - user = user * 10 + *s++ - '0'; - if (user > 31) /* check sensible user id */ - return localname; - } - if (*s == ':') /* just strip the user id assume rest is a filename */ - return s + 1; - if ('a' <= (drive = tolower(*s)) && drive <= 'p' && s[1] == ':') - return s; /* was form [0-9]+[a-pA-P] so strip user id */ - else - return localname; /* not vaild so don't change */ - } - if ((drive = tolower(*s++)) < 'a' || 'p' < drive || !isdigit(*s)) - return localname; /* not a valid drive prefix or simple drive spec */ - - user = *s++ - '0'; - if (isdigit(*s)) - user = user * 10 + *s++ - '0'; - if (*s != ':' || user > 31) - return localname; - *--s = drive; /* reinsert the drive just before the : */ - return s; + char* s; + int user; + int drive; + + if (!localname || !(s = strchr(localname, ':')) || s > localname + 3) + return localname; + s = localname; + if (isdigit(*s)) { + user = *s++ - '0'; + if (isdigit(*s)) { + user = user * 10 + *s++ - '0'; + if (user > 31) /* check sensible user id */ + return localname; + } + if (*s == ':') /* just strip the user id assume rest is a filename */ + return s + 1; + if ('a' <= (drive = tolower(*s)) && drive <= 'p' && s[1] == ':') + return s; /* was form [0-9]+[a-pA-P] so strip user id */ + else + return localname; /* not vaild so don't change */ + } + if ((drive = tolower(*s++)) < 'a' || 'p' < drive || !isdigit(*s)) + return localname; /* not a valid drive prefix or simple drive spec */ + + user = *s++ - '0'; + if (isdigit(*s)) + user = user * 10 + *s++ - '0'; + if (*s != ':' || user > 31) + return localname; + *--s = drive; /* reinsert the drive just before the : */ + return s; } diff --git a/Tools/unix/zxcc/z80.c b/Tools/unix/zxcc/z80.c index 1b62994c..59af1ed3 100644 --- a/Tools/unix/zxcc/z80.c +++ b/Tools/unix/zxcc/z80.c @@ -123,7 +123,7 @@ void mainloop(word spc, word ssp){ // if (pc == 0x1177) tr = 1; // if (pc == 0x1185) tr = 0; if (tr >= 1) ++id; - if (tr >= 1) printf("%d: PC=%04x %02x AF=%02x:%02x BC=%04x DE=%04x HL=%04x IX=%04x IY=%04x\r\n", + if (tr >= 1) printf("%d: PC=%04x %02x AF=%02x:%02x BC=%04x DE=%04x HL=%04x IX=%04x IY=%04x\n", id, pc, fetch(pc), a,f, bc, de, hl, ix, iy); } */ diff --git a/Tools/unix/zxcc/z80.h b/Tools/unix/zxcc/z80.h index d9e3a547..7634389f 100644 --- a/Tools/unix/zxcc/z80.h +++ b/Tools/unix/zxcc/z80.h @@ -15,16 +15,16 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* [John Elliott, 15 July 2001] - * Copied this file into ZXCC, a CP/M emulator. - * Since ZXCC's memory is a flat 64k space and will never be bank-switched, - * the bank-switching code is removed. - * Since ZXCC has no memory-mapped screen, all the screen management code - * goes as well. - * Since ZXCC doesn't need its speed regulated, all the speed regulation - * code goes as well. - * Since ZXCC doesn't save or load snapshots... OK, you get the idea. - */ + /* [John Elliott, 15 July 2001] + * Copied this file into ZXCC, a CP/M emulator. + * Since ZXCC's memory is a flat 64k space and will never be bank-switched, + * the bank-switching code is removed. + * Since ZXCC has no memory-mapped screen, all the screen management code + * goes as well. + * Since ZXCC doesn't need its speed regulated, all the speed regulation + * code goes as well. + * Since ZXCC doesn't save or load snapshots... OK, you get the idea. + */ #ifdef HAVE_SYS_PARAM_H #include @@ -61,21 +61,21 @@ void drawborder(); #define store(x,y) do { RAM[(x)] = (y); } while(0) -#define store2b(x,hi,lo) do {\ - RAM[(x)]=(lo); \ - RAM[((x+1) & 0xFFFF)]=(hi); } while(0) +#define store2b(x,hi,lo) do { \ + RAM[(x)]=(lo); \ + RAM[((x+1) & 0xFFFF)]=(hi); } while(0) #define store2(x,y) store2b(x,(y)>>8,y) #ifdef __GNUC__ -static void inline storefunc(unsigned short ad,unsigned char b){ - store(ad,b); +static void inline storefunc(unsigned short ad, unsigned char b) { + store(ad, b); } #undef store #define store(x,y) storefunc(x,y) -static void inline store2func(unsigned short ad,unsigned char b1,unsigned char b2){ - store2b(ad,b1,b2); +static void inline store2func(unsigned short ad, unsigned char b1, unsigned char b2) { + store2b(ad, b1, b2); } #undef store2b #define store2b(x,hi,lo) store2func(x,hi,lo) diff --git a/Tools/unix/zxcc/zxbdos.c b/Tools/unix/zxcc/zxbdos.c index 811dcd6d..dab19e58 100644 --- a/Tools/unix/zxcc/zxbdos.c +++ b/Tools/unix/zxcc/zxbdos.c @@ -1,557 +1,555 @@ -#include "zxcc.h" - -#define BDOS_DEF -#include "zxbdos.h" -#include "zxcbdos.h" -#include "zxdbdos.h" - -#ifdef __MSDOS__ -#include -#endif - -#define BCD(x) (((x % 10)+16*(x/10)) & 0xFF) - -/* Convert time_t to CP/M day count/hours/minutes */ -/* there is a duplicate of this code in util.c. -* same modification applied here -*/ -dword cpmtime(time_t t) -{ - dword d = (dword)((t / 86400) - 2921); /* CP/M day 0 is unix day 2921 */ - dword h = (t % 86400) / 3600; /* Hour, 0-23 */ - dword m = (t % 3600) / 60; /* Minute, 0-59 */ - - return (d | (BCD(h) << 16) | (BCD(m) << 24)); -} - - -byte get_time(cpm_word b) -{ - time_t t; - - time(&t); - wr32(b, cpmtime(t)); - - return (BCD(t % 60)); -} - - -/* Functions to access 24-bit & 32-bit words in memory. These are always - little-endian. */ - -void wr24(word addr, dword v) -{ - RAM[addr ] = v & 0xFF; - RAM[addr + 1] = (v >> 8) & 0xFF; - RAM[addr + 2] = (v >> 16) & 0xFF; -} - -void wr32(word addr, dword v) -{ - RAM[addr ] = v & 0xFF; - RAM[addr + 1] = (v >> 8) & 0xFF; - RAM[addr + 2] = (v >> 16) & 0xFF; - RAM[addr + 3] = (v >> 24) & 0xFF; -} - -dword rd24(word addr) -{ - register dword rv = RAM[addr + 2]; - - rv = (rv << 8) | RAM[addr + 1]; - rv = (rv << 8) | RAM[addr]; - return rv; -} - - -dword rd32(word addr) -{ - register dword rv = RAM[addr + 3]; - - rv = (rv << 8) | RAM[addr + 2]; - rv = (rv << 8) | RAM[addr + 1]; - rv = (rv << 8) | RAM[addr]; - return rv; -} - -#define peekw(addr) ( (((word)(RAM[addr + 1])) << 8) | RAM[addr]) - - -/* Get / set the program return code. We store this in 'C' form: 0 for - success, 1-255 for failure. Translate to/from the CP/M form of: - - 0x0000-0xFEFF for success - 0xFF00-0xFFFE for failure - - We also store the actual value so it can be returned - - */ - -word cpm_errcde(word DE) -{ - static word real_err = 0; - - if (DE == 0xFFFF) return real_err; - real_err = DE; - - if (DE == 0xFF00) cpm_error = 1; - else if (DE > 0xFF00) cpm_error = (DE & 0xFF); - else cpm_error = 0; - return 0; -} - - -#ifdef USE_CPMGSX -gsx_byte gsxrd(gsx_word addr) -{ - return RdZ80(addr); -} - -void gsxwr(gsx_word addr, gsx_byte value) -{ - WrZ80(addr, value); -} - -#endif - -#undef bc -#undef de -#undef hl - -void setw(byte *l, byte *h, word w) -{ - *l = (w & 0xFF); - *h = (w >> 8) & 0xFF; -} - -void cpmbdos(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, - byte *h, byte *l, word *pc, word *ix, word *iy) -{ - word de = ((*d) << 8) | *e; - word hl = ((*h) << 8) | *l; - byte *pde = &RAM[de]; - byte *pdma = &RAM[cpm_dma]; - word temp; - int retv; - - Msg("BDOS service invoked: C=%02x DE=%04x\n", *c, de); - - switch(*c) - { - case 0: - *pc = 0; - break; - - case 1: /* Get a character */ -#ifdef USE_CPMIO - retv = cpm_bdos_1(); -#else - retv = cin(); -#endif - if (retv < 0) *pc = 0; - setw(l, h, retv); - break; - - case 2: /* Print a character */ -#ifdef USE_CPMIO - if (cpm_bdos_2(*e)) *pc = 0; -#else - cout(*e); -#endif - break; - - case 3: /* No auxin */ - setw(l, h, 0x1A); - break; - - case 4: /* No auxout */ - break; - - case 5: /* No printer */ - break; - - case 6: /* Direct console I/O */ - retv = cpm_bdos_6(*e); - if (retv < 0) *pc = 0; - setw(l, h, retv); - break; - - case 7: /* No auxist */ - case 8: /* No auxost */ - break; - - case 9: /* Print a $-terminated string */ -#ifdef USE_CPMIO - if (cpm_bdos_9((char *)pde)) *pc = 0; -# else - for (temp = 0; RAM[de + temp] != '$'; ++temp) - { - cout(RAM[de + temp]); - } -#endif - break; - - case 0x0A: - bdos_rdline(de, &(*pc)); - break; - - case 0x0B: /* Console status */ - //*l = *h = 0; /* No keys pressed */ - *l = cstat(); - *h = 0; - break; - - case 0x0C: /* Get CP/M version */ - -/* For GENCOM's benefit, claim to be v3.1 */ - - *l = 0x31; /* v3.1 */ - /* *l = 0x22; * v2.2 */ - *h = 0; /* CP/M, no network */ - break; - - case 0x0D: /* Re-log discs */ - fcb_reset(); - break; - - case 0x0E: /* Set default drive */ - setw(l, h, fcb_drive(*e)); - break; - - case 0x0F: /* Open using FCB */ - setw(l, h, x_fcb_open(pde, pdma)); - break; - - case 0x10: /* Close using FCB */ - setw(l, h, fcb_close(pde)); - break; - - case 0x11: /* Find first */ - setw(l, h, fcb_find1(pde, pdma)); - break; - - case 0x12: - setw(l, h, fcb_find2(pde, pdma)); - break; - - case 0x13: /* Delete using FCB */ - setw(l, h, fcb_unlink(pde, pdma)); - break; - - case 0x14: /* Sequential read using FCB */ - setw(l, h, fcb_read(pde, pdma)); - break; - - case 0x15: /* Sequential write using FCB */ - setw(l, h, fcb_write(pde, pdma)); - break; - - case 0x16: /* Create using FCB */ - setw(l, h, fcb_creat(pde, pdma)); - break; - - case 0x17: /* Rename using FCB */ - setw(l, h, fcb_rename(pde, pdma)); - break; - - case 0x18: /* Get login vector */ - setw(l, h, fcb_logvec()); - break; - - case 0x19: /* Get default drive */ - setw(l, h, cpm_drive); - break; - - case 0x1A: /* Set DMA */ - Msg("Set DMA to %04x\n", de); - cpm_dma = de; - break; - - case 0x1B: /* Get alloc vector */ - fcb_getalv(RAM + 0xFF80, 0x40); - setw(l, h, 0xFF80); - break; - - case 0x1C: /* Make disc R/O */ - setw(l, h, fcb_rodisk()); - break; - - case 0x1D: /* Get R/O vector */ - setw(l, h, fcb_rovec()); - break; - - case 0x1E: /* Set attributes */ - setw(l, h, fcb_chmod(pde, pdma)); - break; - - case 0x1F: /* Get DPB */ - fcb_getdpb(RAM + 0xFFC0); - setw(l, h, 0xFFC0); - break; /* Whoops. Missed that 'break'. */ - - case 0x20: /* Get/set uid */ - setw(l, h, fcb_user(*e)); - break; - - case 0x21: /* Read a record */ - setw(l, h, fcb_randrd(pde, pdma)); - break; - - case 0x22: /* Write a record */ - setw(l, h, fcb_randwr(pde, pdma)); - break; - - case 0x23: /* Get file size */ - setw(l, h, x_fcb_stat(pde)); - break; - - case 0x24: /* Get file pointer */ - setw(l, h, fcb_tell(pde)); - break; - - case 0x25: - setw(l, h, fcb_resro(de)); - break; - - /* MP/M drive access functions, not implemented */ - - case 0x28: /* Write with 0 fill */ - setw(l, h, fcb_randwz(pde, pdma)); - break; - - /* MP/M record locking functions, not implemented */ - - case 0x2C: /* Set no. of records to read/write */ - setw(l, h, fcb_multirec(*e)); - break; - - case 0x2D: /* Set error mode */ - err_mode = *e; - break; - - case 0x2E: - setw(l, h, fcb_dfree(*e, pdma)); - break; /* Whoops. Missed that 'break'. */ - - /* 0x2F: Chain */ - - case 0x30: - setw(l, h, fcb_sync(*e)); - break; - - case 0x31: - if (pde[1] == 0xFE) - { - RAM[0xFE9C + *pde] = pde[2]; - RAM[0xFE9D + *pde] = pde[3]; - } - else if (RAM[hl + 1] == 0xFF) - { - RAM[0xFE9C + *pde] = pde[2]; - } - else - { - *l = RAM[0xFE9C + *pde]; - *h = RAM[0xFE9D + *pde]; - } - break; - - case 0x32: - temp = *ix; - *ix = 3 * (pde[0] + 1); - *a = pde[1]; - *c = pde[2]; - *b = pde[3]; - *e = pde[4]; - *d = pde[5]; - *l = pde[6]; - *h = pde[7]; - cpmbios(a,b,c,d,e,f,h,l,pc,ix,iy); - *ix = temp; - break; - - case 0x3C: /* Communicate with RSX */ - *h = 0; *l = 0xFF; /* return error */ - break; - - case 0x62: /* Purge */ - setw(l, h, fcb_purge()); - break; - - case 0x63: /* Truncate file */ - setw(l, h, fcb_trunc(pde, pdma)); - break; - - case 0x64: /* Set label */ - setw(l, h, fcb_setlbl(pde, pdma)); - break; - - case 0x65: /* Get label byte */ - setw(l, h, fcb_getlbl(*e)); - break; - - case 0x66: /* Get file date */ - setw(l, h, fcb_date(pde)); - break; - - case 0x67: /* Set password */ - setw(l, h, fcb_setpwd(pde, pdma)); - break; - - case 0x68: /* Set time of day */ - /* Not advisable to let an emulator play with the clock */ - break; - - case 0x69: /* Get time of day */ - setw(l, h, get_time(de)); - break; - - case 0x6A: /* Set default password */ - setw(l, h, fcb_defpwd(pde)); - break; - - case 0x6B: /* Get serial number */ - memcpy(pde, SERIAL, 6); - break; - - case 0x6C: /* 0.03 set error code */ - setw(l, h, cpm_errcde(de)); - break; - -#ifdef USE_CPMIO - case 0x6D: /* Set/get console mode */ - setw(l, h, cpm_bdos_109(de)); - break; - - case 0x6E: /* Set/get string delimiter */ - setw(l, h, cpm_bdos_110(*e)); - break; - - case 0x6F: /* Send fixed length string to screen */ - if (cpm_bdos_111((char *)RAM + peekw(de), - peekw(de + 2))) - *pc = 0; - break; - - case 0x70: /* Send fixed length string to printer */ - break; - - /* 0x71: Strange PCP/M function */ -#else - case 0x6D: /* Set/get console mode */ - setw(l, h, 0); - break; - -#endif - -#ifdef USE_CPMGSX - case 0x73: /* GSX */ - setw(l, h, gsx80(gsxrd, gsxwr, de)); - break; -#endif - - case 0x74: /* Set date stamp */ - setw(l, h, fcb_sdate(pde, pdma)); - break; - - case 0x98: /* Parse filename */ - setw(l, h, fcb_parse((char *)RAM + peekw(de), - (byte *)RAM + peekw(de + 2))); - break; - - default: -#ifdef USE_CPMIO - cpm_scr_unit(); -#endif -#ifdef USE_CPMGSX - gsx_deinit(); -#endif - - fprintf(stderr,"%s: Unsupported BDOS call %d\n", progname, - (int)(*c)); - dump_regs(stderr,*a,*b,*c,*d,*e,*f,*h,*l,*pc,*ix,*iy); - zxcc_exit(1); - break; - } - - *a = *l; - *b = *h; -} - - - -void cpmbios(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, - byte *h, byte *l, word *pc, word *ix, word *iy) -{ - int func = (((*ix) & 0xFF) / 3) - 1; - - Msg("BIOS service invoked: func=%02x\n", func); - - switch(func) /* BIOS function */ - { - case 1: - zxcc_exit(zxcc_term()); /* Program termination */ - break; - - case 2: /* CONST */ -#ifdef USE_CPMIO - *a = cpm_const(); -#else - *a = cpm_bdos_6(0xFE); -#endif - break; - - case 3: /* CONIN */ -#ifdef USE_CPMIO - *a = cpm_conin(); -#else - *a = cpm_bdos_6(0xFD); -#endif - break; - - case 4: /* CONOUT */ -#ifdef USE_CPMIO - cpm_conout(*c); -#else - cpm_bdos_6(*c); -#endif - break; - - case 20: /* DEVTBL */ - setw(l, h, 0xFFFF); - break; - - case 22: /* DRVTBL */ - setw(l, h, 0xFFFF); - break; - - case 26: /* TIME */ - RAM[0xFEF8] = get_time(0xFEF4); - break; - - case 30: /* USERF!!! */ -#ifdef USE_CPMIO - cpm_bdos_110('$'); - cpm_bdos_9("This program has attempted to call USERF, " - "which is not implemented\r\n$"); -#else - printf("This program has attempted to call USERF, which " - "is not implemented.\n"); -#endif - zxcc_term(); - zxcc_exit(1); - break; - - default: -#ifdef USE_CPMIO - cpm_scr_unit(); -#endif -#ifdef USE_CPMGSX - gsx_deinit(); -#endif - - fprintf(stderr,"%s: Unsupported BIOS call %d\n", progname, func); - dump_regs(stderr,*a,*b,*c,*d,*e,*f,*h,*l,*pc,*ix,*iy); - zxcc_exit(1); - } -} +#include "zxcc.h" + +#define BDOS_DEF +#include "zxbdos.h" +#include "zxcbdos.h" +#include "zxdbdos.h" + +#ifdef __MSDOS__ +#include +#endif + +#define BCD(x) (((x % 10)+16*(x/10)) & 0xFF) + +/* Convert time_t to CP/M day count/hours/minutes */ +/* there is a duplicate of this code in util.c. +* same modification applied here +*/ +dword cpmtime(time_t t) +{ + dword d = (dword)((t / 86400) - 2921); /* CP/M day 0 is unix day 2921 */ + dword h = (t % 86400) / 3600; /* Hour, 0-23 */ + dword m = (t % 3600) / 60; /* Minute, 0-59 */ + + return (d | (BCD(h) << 16) | (BCD(m) << 24)); +} + + +byte get_time(cpm_word b) +{ + time_t t; + + time(&t); + wr32(b, cpmtime(t)); + + return (BCD(t % 60)); +} + + +/* Functions to access 24-bit & 32-bit words in memory. These are always + little-endian. */ + +void wr24(word addr, dword v) +{ + RAM[addr] = v & 0xFF; + RAM[addr + 1] = (v >> 8) & 0xFF; + RAM[addr + 2] = (v >> 16) & 0xFF; +} + +void wr32(word addr, dword v) +{ + RAM[addr] = v & 0xFF; + RAM[addr + 1] = (v >> 8) & 0xFF; + RAM[addr + 2] = (v >> 16) & 0xFF; + RAM[addr + 3] = (v >> 24) & 0xFF; +} + +dword rd24(word addr) +{ + register dword rv = RAM[addr + 2]; + + rv = (rv << 8) | RAM[addr + 1]; + rv = (rv << 8) | RAM[addr]; + return rv; +} + + +dword rd32(word addr) +{ + register dword rv = RAM[addr + 3]; + + rv = (rv << 8) | RAM[addr + 2]; + rv = (rv << 8) | RAM[addr + 1]; + rv = (rv << 8) | RAM[addr]; + return rv; +} + +#define peekw(addr) ( (((word)(RAM[addr + 1])) << 8) | RAM[addr]) + + +/* Get / set the program return code. We store this in 'C' form: 0 for + success, 1-255 for failure. Translate to/from the CP/M form of: + + 0x0000-0xFEFF for success + 0xFF00-0xFFFE for failure + + We also store the actual value so it can be returned + + */ + +word cpm_errcde(word DE) +{ + static word real_err = 0; + + if (DE == 0xFFFF) return real_err; + real_err = DE; + + if (DE == 0xFF00) cpm_error = 1; + else if (DE > 0xFF00) cpm_error = (DE & 0xFF); + else cpm_error = 0; + return 0; +} + + +#ifdef USE_CPMGSX +gsx_byte gsxrd(gsx_word addr) +{ + return RdZ80(addr); +} + +void gsxwr(gsx_word addr, gsx_byte value) +{ + WrZ80(addr, value); +} + +#endif + +#undef bc +#undef de +#undef hl + +void setw(byte* l, byte* h, word w) +{ + *l = (w & 0xFF); + *h = (w >> 8) & 0xFF; +} + +void cpmbdos(byte* a, byte* b, byte* c, byte* d, byte* e, byte* f, + byte* h, byte* l, word* pc, word* ix, word* iy) +{ + word de = ((*d) << 8) | *e; + word hl = ((*h) << 8) | *l; + byte* pde = &RAM[de]; + byte* pdma = &RAM[cpm_dma]; + word temp; + int retv; + + DBGMSGV("BDOS service invoked: C=0x%02X DE=0x%04X\n", *c, de); + + switch (*c) + { + case 0: + *pc = 0; + break; + + case 1: /* Get a character */ +#ifdef USE_CPMIO + retv = cpm_bdos_1(); +#else + retv = cin(); +#endif + if (retv < 0) *pc = 0; + setw(l, h, retv); + break; + + case 2: /* Print a character */ +#ifdef USE_CPMIO + if (cpm_bdos_2(*e)) *pc = 0; +#else + cout(*e); +#endif + break; + + case 3: /* No auxin */ + setw(l, h, 0x1A); + break; + + case 4: /* No auxout */ + break; + + case 5: /* No printer */ + break; + + case 6: /* Direct console I/O */ + retv = cpm_bdos_6(*e); + if (retv < 0) *pc = 0; + setw(l, h, retv); + break; + + case 7: /* No auxist */ + case 8: /* No auxost */ + break; + + case 9: /* Print a $-terminated string */ +#ifdef USE_CPMIO + if (cpm_bdos_9((char*)pde)) *pc = 0; +# else + for (temp = 0; RAM[de + temp] != '$'; ++temp) + { + cout(RAM[de + temp]); + } +#endif + break; + + case 0x0A: + bdos_rdline(de, &(*pc)); + break; + + case 0x0B: /* Console status */ + // *l = *h = 0; /* No keys pressed */ + *l = cstat(); + *h = 0; + break; + + case 0x0C: /* Get CP/M version */ + + /* For GENCOM's benefit, claim to be v3.1 */ + + *l = 0x31; /* v3.1 */ + /* *l = 0x22; * v2.2 */ + *h = 0; /* CP/M, no network */ + break; + + case 0x0D: /* Re-log discs */ + fcb_reset(); + break; + + case 0x0E: /* Set default drive */ + setw(l, h, fcb_drive(*e)); + break; + + case 0x0F: /* Open using FCB */ + setw(l, h, x_fcb_open(pde, pdma)); + break; + + case 0x10: /* Close using FCB */ + setw(l, h, fcb_close(pde)); + break; + + case 0x11: /* Find first */ + setw(l, h, fcb_find1(pde, pdma)); + break; + + case 0x12: + setw(l, h, fcb_find2(pde, pdma)); + break; + + case 0x13: /* Delete using FCB */ + setw(l, h, fcb_unlink(pde, pdma)); + break; + + case 0x14: /* Sequential read using FCB */ + setw(l, h, fcb_read(pde, pdma)); + break; + + case 0x15: /* Sequential write using FCB */ + setw(l, h, fcb_write(pde, pdma)); + break; + + case 0x16: /* Create using FCB */ + setw(l, h, fcb_creat(pde, pdma)); + break; + + case 0x17: /* Rename using FCB */ + setw(l, h, fcb_rename(pde, pdma)); + break; + + case 0x18: /* Get login vector */ + setw(l, h, fcb_logvec()); + break; + + case 0x19: /* Get default drive */ + setw(l, h, cpm_drive); + break; + + case 0x1A: /* Set DMA */ + DBGMSGV("Set DMA to 0x%04X\n", de); + cpm_dma = de; + break; + + case 0x1B: /* Get alloc vector */ + fcb_getalv(RAM + 0xFF80, 0x40); + setw(l, h, 0xFF80); + break; + + case 0x1C: /* Make disc R/O */ + setw(l, h, fcb_rodisk()); + break; + + case 0x1D: /* Get R/O vector */ + setw(l, h, fcb_rovec()); + break; + + case 0x1E: /* Set attributes */ + setw(l, h, fcb_chmod(pde, pdma)); + break; + + case 0x1F: /* Get DPB */ + fcb_getdpb(RAM + 0xFFC0); + setw(l, h, 0xFFC0); + break; + + case 0x20: /* Get/set uid */ + setw(l, h, fcb_user(*e)); + break; + + case 0x21: /* Read a record */ + setw(l, h, fcb_randrd(pde, pdma)); + break; + + case 0x22: /* Write a record */ + setw(l, h, fcb_randwr(pde, pdma)); + break; + + case 0x23: /* Get file size */ + setw(l, h, x_fcb_stat(pde)); + break; + + case 0x24: /* Get file pointer */ + setw(l, h, fcb_tell(pde)); + break; + + case 0x25: + setw(l, h, fcb_resro(de)); + break; + + /* MP/M drive access functions, not implemented */ + + case 0x28: /* Write with 0 fill */ + setw(l, h, fcb_randwz(pde, pdma)); + break; + + /* MP/M record locking functions, not implemented */ + + case 0x2C: /* Set no. of records to read/write */ + setw(l, h, fcb_multirec(*e)); + break; + + case 0x2D: /* Set error mode */ + err_mode = *e; + break; + + case 0x2E: + setw(l, h, fcb_dfree(*e, pdma)); + break; + + /* 0x2F: Chain */ + + case 0x30: + setw(l, h, fcb_sync(*e)); + break; + + case 0x31: + if (pde[1] == 0xFE) + { + RAM[0xFE9C + *pde] = pde[2]; + RAM[0xFE9D + *pde] = pde[3]; + } + else if (RAM[hl + 1] == 0xFF) + { + RAM[0xFE9C + *pde] = pde[2]; + } + else + { + *l = RAM[0xFE9C + *pde]; + *h = RAM[0xFE9D + *pde]; + } + break; + + case 0x32: + temp = *ix; + *ix = 3 * (pde[0] + 1); + *a = pde[1]; + *c = pde[2]; + *b = pde[3]; + *e = pde[4]; + *d = pde[5]; + *l = pde[6]; + *h = pde[7]; + cpmbios(a, b, c, d, e, f, h, l, pc, ix, iy); + *ix = temp; + break; + + case 0x3C: /* Communicate with RSX */ + *h = 0; *l = 0xFF; /* return error */ + break; + + case 0x62: /* Purge */ + setw(l, h, fcb_purge()); + break; + + case 0x63: /* Truncate file */ + setw(l, h, fcb_trunc(pde, pdma)); + break; + + case 0x64: /* Set label */ + setw(l, h, fcb_setlbl(pde, pdma)); + break; + + case 0x65: /* Get label byte */ + setw(l, h, fcb_getlbl(*e)); + break; + + case 0x66: /* Get file date */ + setw(l, h, fcb_date(pde)); + break; + + case 0x67: /* Set password */ + setw(l, h, fcb_setpwd(pde, pdma)); + break; + + case 0x68: /* Set time of day */ + /* Not advisable to let an emulator play with the clock */ + break; + + case 0x69: /* Get time of day */ + setw(l, h, get_time(de)); + break; + + case 0x6A: /* Set default password */ + setw(l, h, fcb_defpwd(pde)); + break; + + case 0x6B: /* Get serial number */ + memcpy(pde, SERIAL, 6); + break; + + case 0x6C: /* 0.03 set error code */ + setw(l, h, cpm_errcde(de)); + break; + +#ifdef USE_CPMIO + case 0x6D: /* Set/get console mode */ + setw(l, h, cpm_bdos_109(de)); + break; + + case 0x6E: /* Set/get string delimiter */ + setw(l, h, cpm_bdos_110(*e)); + break; + + case 0x6F: /* Send fixed length string to screen */ + if (cpm_bdos_111((char*)RAM + peekw(de), + peekw(de + 2))) + *pc = 0; + break; + + case 0x70: /* Send fixed length string to printer */ + break; + + /* 0x71: Strange PCP/M function */ +#else + case 0x6D: /* Set/get console mode */ + setw(l, h, 0); + break; + +#endif + +#ifdef USE_CPMGSX + case 0x73: /* GSX */ + setw(l, h, gsx80(gsxrd, gsxwr, de)); + break; +#endif + + case 0x74: /* Set date stamp */ + setw(l, h, fcb_sdate(pde, pdma)); + break; + + case 0x98: /* Parse filename */ + setw(l, h, fcb_parse((char*)RAM + peekw(de), + (byte*)RAM + peekw(de + 2))); + break; + + default: +#ifdef USE_CPMIO + cpm_scr_unit(); +#endif +#ifdef USE_CPMGSX + gsx_deinit(); +#endif + + fprintf(stderr, "%s: Unsupported BDOS call %d\n", progname, + (int)(*c)); + dump_regs(stderr, *a, *b, *c, *d, *e, *f, *h, *l, *pc, *ix, *iy); + zxcc_exit(1); + break; + } + + *a = *l; + *b = *h; +} + +void cpmbios(byte* a, byte* b, byte* c, byte* d, byte* e, byte* f, + byte* h, byte* l, word* pc, word* ix, word* iy) +{ + int func = (((*ix) & 0xFF) / 3) - 1; + + DBGMSGV("BIOS service invoked: func=0x%02X\n", func); + + switch (func) /* BIOS function */ + { + case 1: + zxcc_exit(zxcc_term()); /* Program termination */ + break; + + case 2: /* CONST */ +#ifdef USE_CPMIO + * a = cpm_const(); +#else + * a = cpm_bdos_6(0xFE); +#endif + break; + + case 3: /* CONIN */ +#ifdef USE_CPMIO + * a = cpm_conin(); +#else + * a = cpm_bdos_6(0xFD); +#endif + break; + + case 4: /* CONOUT */ +#ifdef USE_CPMIO + cpm_conout(*c); +#else + cpm_bdos_6(*c); +#endif + break; + + case 20: /* DEVTBL */ + setw(l, h, 0xFFFF); + break; + + case 22: /* DRVTBL */ + setw(l, h, 0xFFFF); + break; + + case 26: /* TIME */ + RAM[0xFEF8] = get_time(0xFEF4); + break; + + case 30: /* USERF!!! */ +#ifdef USE_CPMIO + cpm_bdos_110('$'); + cpm_bdos_9("This program has attempted to call USERF, " + "which is not implemented\n$"); +#else + printf("This program has attempted to call USERF, which " + "is not implemented.\n"); +#endif + zxcc_term(); + zxcc_exit(1); + break; + + default: +#ifdef USE_CPMIO + cpm_scr_unit(); +#endif +#ifdef USE_CPMGSX + gsx_deinit(); +#endif + + fprintf(stderr, "%s: Unsupported BIOS call %d\n", progname, func); + dump_regs(stderr, *a, *b, *c, *d, *e, *f, *h, *l, *pc, *ix, *iy); + zxcc_exit(1); + } +} diff --git a/Tools/unix/zxcc/zxbdos.h b/Tools/unix/zxcc/zxbdos.h index 4111c78e..fd7bebc2 100644 --- a/Tools/unix/zxcc/zxbdos.h +++ b/Tools/unix/zxcc/zxbdos.h @@ -1,50 +1,49 @@ -extern char *progname; -extern char **argv; -extern int argc; - -extern byte cpm_drive; -extern byte cpm_user; - -extern byte RAM[65536]; /* The Z80's address space */ - -extern void Msg(char *s, ...); - -#ifdef BDOS_DEF - -word cpm_dma = 0x80; /* DMA address */ -byte err_mode = 0xFF; -byte rec_multi = 1; -word rec_len = 128; -word ffirst_fcb = 0xFFFF; -byte cpm_error = 0; /* Error code returned by CP/M */ - -#else /* BDOS_DEF */ - -extern word cpm_dma, rec_len, ffirst_fcb; -extern byte err_mode, rec_multi, cpm_error; - -#endif /* BDOS_DEF */ - -#ifndef O_BINARY /* Necessary in DOS, not present in Linux */ -#define O_BINARY 0 -#endif - -typedef unsigned long dword; - -/* Functions in zxbdos.c */ - -void wr24(word addr, dword v); -void wr32(word addr, dword v); -dword rd24(word addr); -dword rd32(word addr); -dword cpmtime(time_t t); -word cpm_errcde(word DE); - -#ifdef USE_CPMGSX -gsx_byte gsxrd(gsx_word addr); -void gsxwr(gsx_word addr, gsx_byte value); -#endif - -void cpmbdos(); -void cpmbios(); - +extern char* progname; +extern char** argv; +extern int argc; + +extern byte cpm_drive; +extern byte cpm_user; + +extern byte RAM[65536]; /* The Z80's address space */ + +extern void Msg(char* s, ...); + +#ifdef BDOS_DEF + +word cpm_dma = 0x80; /* DMA address */ +byte err_mode = 0xFF; +byte rec_multi = 1; +word rec_len = 128; +word ffirst_fcb = 0xFFFF; +byte cpm_error = 0; /* Error code returned by CP/M */ + +#else /* BDOS_DEF */ + +extern word cpm_dma, rec_len, ffirst_fcb; +extern byte err_mode, rec_multi, cpm_error; + +#endif /* BDOS_DEF */ + +#ifndef O_BINARY /* Necessary in DOS, not present in Linux */ + #define O_BINARY 0 +#endif + +typedef unsigned long dword; + +/* Functions in zxbdos.c */ + +void wr24(word addr, dword v); +void wr32(word addr, dword v); +dword rd24(word addr); +dword rd32(word addr); +dword cpmtime(time_t t); +word cpm_errcde(word DE); + +#ifdef USE_CPMGSX +gsx_byte gsxrd(gsx_word addr); +void gsxwr(gsx_word addr, gsx_byte value); +#endif + +void cpmbdos(); +void cpmbios(); diff --git a/Tools/unix/zxcc/zxcbdos.c b/Tools/unix/zxcc/zxcbdos.c index 46cc8d0b..17466e47 100644 --- a/Tools/unix/zxcc/zxcbdos.c +++ b/Tools/unix/zxcc/zxcbdos.c @@ -1,154 +1,145 @@ -#include "zxcc.h" -#include "zxbdos.h" -#include "zxcbdos.h" - -#ifndef _WIN32 -#include -#endif - -#ifdef _WIN32 -#include -#endif - -/* Line input */ -#ifdef USE_CPMIO - - -void bdos_rdline(word line, word *PC) -{ - unsigned char *buf; - - if (!line) line = cpm_dma; - else RAM[line + 1] = 0; - - buf = (unsigned char *)&RAM[line]; - - if (cpm_bdos_10(buf)) *PC = 0; -} - -#else /* def USE_CPMIO */ - -void bdos_rdline(word line, word *PC) -{ - unsigned char c; - unsigned char *p; - int n; - int maxlen; - - if (!line) line = cpm_dma; - maxlen = RAM[line]; - - // fgets causes extra linefeeds, so we invent our own - //fgets((char *)(RAM + line + 2), maxlen, stdin); - - p = (RAM + line + 2); - n = 0; - - while (1) { - c = cin(); - if (c == '\r') - break; - if (c == '\b') { - if (n > 0) { - cout('\b'); - cout(' '); - cout('\b'); - n--; - p--; - } - } - else { - if (n < maxlen) { - cout(c); - *p++ = c; - n++; - } - } - } - - cout('\r'); - *p = '\0'; - - //RAM[line + 1] = strlen((char *)(RAM + line + 2)) - 1; - RAM[line + 1] = (unsigned char)n; - - Msg("Input: [%d] %-*.*s\n", RAM[line + 1], RAM[line + 1], RAM[line +1], (char *)(RAM+line+2)); -} -#endif /* ndef USE_CPMIO */ - -#ifndef USE_CPMIO - -int cpm_bdos_6(byte e) -{ - int c; - - switch(e) { - case 0xFF: - if (cstat()) return cin(); - return 0; - - case 0xFE: - return cstat(); - - case 0xFD: - return cin(); - - default: - cout(e); - break; - } - return 0; -} -#endif - -#ifdef _WIN32 -byte cin() -{ - if (_isatty(STDIN_FILENO)) - return getch(); - else - return getchar(); -} - -void cout(byte c) -{ - if (_isatty(STDOUT_FILENO)) - putch(c); - else - putchar(c); -} - -int cstat() -{ - if (_isatty(STDIN_FILENO)) - return _kbhit() ? 0xFF : 0; - else - return 0xFF; -} - -#else /* def _WIN32 */ - -byte cin() -{ - char c = 0; - - read(STDIN_FILENO, &c, 1); - return c; -} - -void cout(byte c) -{ - write(STDOUT_FILENO, &c, 1); - return; -} - -int cstat() -{ - int i; - - ioctl(STDIN_FILENO, FIONREAD, &i); - if (i > 0) return 0xFF; - return 0; -} - -#endif +#include "zxcc.h" +#include "zxbdos.h" +#include "zxcbdos.h" + +/* Line input */ +#ifdef USE_CPMIO + +void bdos_rdline(word line, word* PC) +{ + unsigned char* buf; + + if (!line) line = cpm_dma; + else RAM[line + 1] = 0; + + buf = (unsigned char*)&RAM[line]; + + if (cpm_bdos_10(buf)) *PC = 0; +} + +#else /* def USE_CPMIO */ + +void bdos_rdline(word line, word* PC) +{ + unsigned char c; + unsigned char* p; + int n; + int maxlen; + + if (!line) line = cpm_dma; + maxlen = RAM[line]; + + // fgets causes extra linefeeds, so we invent our own + // fgets((char *)(RAM + line + 2), maxlen, stdin); + + p = (RAM + line + 2); + n = 0; + + while (1) { + c = cin(); + if (c == '\r') + break; + if (c == '\b') { + if (n > 0) { + cout('\b'); + cout(' '); + cout('\b'); + n--; + p--; + } + } + else { + if (n < maxlen) { + cout(c); + *p++ = c; + n++; + } + } + } + + cout('\r'); + *p = '\0'; + + //RAM[line + 1] = strlen((char *)(RAM + line + 2)) - 1; + RAM[line + 1] = (unsigned char)n; + + DBGMSGV("Input: [%d] %-*.*s\n", RAM[line + 1], RAM[line + 1], RAM[line + 1], (char*)(RAM + line + 2)); +} +#endif /* ndef USE_CPMIO */ + +#ifndef USE_CPMIO + +int cpm_bdos_6(byte e) +{ + int c; + + switch (e) { + case 0xFF: + if (cstat()) return cin(); + return 0; + + case 0xFE: + return cstat(); + + case 0xFD: + return cin(); + + default: + cout(e); + break; + } + return 0; +} +#endif + +#ifdef _WIN32 +byte cin() +{ + if (_isatty(STDIN_FILENO)) + return getch(); + else + return getchar(); +} + +void cout(byte c) +{ + if (_isatty(STDOUT_FILENO)) + putch(c); + else + putchar(c); +} + +int cstat() +{ + if (_isatty(STDIN_FILENO)) + return _kbhit() ? 0xFF : 0; + else + return 0xFF; +} + +#else /* def _WIN32 */ + +byte cin() +{ + char c = 0; + + read(STDIN_FILENO, &c, 1); + return c; +} + +void cout(byte c) +{ + write(STDOUT_FILENO, &c, 1); + return; +} + +int cstat() +{ + int i; + + ioctl(STDIN_FILENO, FIONREAD, &i); + if (i > 0) return 0xFF; + return 0; +} + +#endif diff --git a/Tools/unix/zxcc/zxcbdos.h b/Tools/unix/zxcc/zxcbdos.h index 7f724441..dde4c08d 100644 --- a/Tools/unix/zxcc/zxcbdos.h +++ b/Tools/unix/zxcc/zxcbdos.h @@ -1,4 +1,6 @@ -void bdos_rdline(word line, word *PC); -int cpm_bdos_6(byte e); - - +void bdos_rdline(word line, word* PC); +int cpm_bdos_6(byte e); + +byte cin(void); +void cout(byte); +int cstat(void); diff --git a/Tools/unix/zxcc/zxcc.c b/Tools/unix/zxcc/zxcc.c index 9668243b..1dacc9bd 100644 --- a/Tools/unix/zxcc/zxcc.c +++ b/Tools/unix/zxcc/zxcc.c @@ -1,552 +1,544 @@ -#include "zxcc.h" - -/* Global variables */ - -char *progname; -char **argv; -int argc; - -byte cpm_drive; -byte cpm_user; -extern byte cpm_error; - -char bindir80[CPM_MAXPATH] = ""; -char libdir80[CPM_MAXPATH] = ""; -char incdir80[CPM_MAXPATH] = ""; - -byte RAM[65536]; /* The Z80's address space */ - -void load_comfile(void); /* Forward declaration */ - -static int deinit_term, deinit_gsx; -static void mkpath(char* fullpath, char* path, char* subdir); - -#ifndef _WIN32 -struct termios tc_orig; - -void raw_init(void); -void deinit_raw(void); -#endif - -void dump_regs(FILE *fp, byte a, byte b, byte c, byte d, byte e, byte f, - byte h, byte l, word pc, word ix, word iy) -{ - fprintf(fp, "\tAF=%02x%02x BC=%02x%02x DE=%02x%02x HL=%02x%02x\n" - "\tIX=%04x IY=%04x PC=%04x\n", - a,f,b,c,d,e,h,l,pc,ix,iy); -} - - - -char *parse_to_fcb(char *s, int afcb) -{ - byte *fcb = &RAM[afcb+1]; - - RAM[afcb] = 0; - memset(fcb, ' ', 11); - - while (s[0]==' ') /* skip leading spaces */ - { - s++; - } - while (1) - { - if (s[0] == 0) break; - if (s[0] == ' ') break; - if (s[1] == ':') - { - RAM[afcb] = s[0] - '@'; - if (RAM[afcb] > 16) RAM[afcb] -= 0x20; - s+=2; - continue; - } - if (s[0] == '.') - { - ++s; - fcb = &RAM[afcb+9]; - continue; - } - *fcb = *s; if (islower(*fcb)) *fcb = toupper(*fcb); - ++s; - ++fcb; - if (fcb >= &RAM[afcb+12]) break; - } - return s; -} - - -void Msg(char *s, ...) -{ -#ifdef DEBUG - va_list ap; - - va_start(ap, s); - fprintf(stderr, "%s trace: ", progname); - vfprintf(stderr, s, ap); - fflush(stderr); - va_end(ap); -#endif -} - - -void ed_fe(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, - byte *h, byte *l, word *pc, word *ix, word *iy) -{ - switch(*a) - { - case 0xC0: - cpmbdos(a,b,c,d,e,f,h,l,pc,ix,iy); - break; - - case 0xC1: - load_comfile(); - break; - - case 0xC2: - fprintf(stderr,"%s: Incompatible BIOS.BIN\n", progname); - zxcc_term(); - zxcc_exit(1); - - case 0xC3: - cpmbios(a,b,c,d,e,f,h,l,pc,ix,iy); - break; - - default: - fprintf(stderr, "%s: Z80 encountered invalid trap\n", progname); - dump_regs(stderr,*a,*b,*c,*d,*e,*f,*h,*l,*pc,*ix,*iy); - zxcc_term(); - zxcc_exit(1); - - } -} - - -/* - * load_bios() loads the minimal CP/M BIOS and BDOS. - * - */ - -void load_bios(void) -{ - char dir[CPM_MAXPATH + 1], fname[CPM_MAXPATH + 1]; - char* q; - size_t bios_len; - - FILE* fp = fopen("bios.bin", "rb"); - if (!fp) - { - strcpy(fname, bindir80); - strcat(fname, "bios.bin"); - fp = fopen(fname, "rb"); - } - if (!fp) - { -#ifdef _WIN32 - dir[0] = 0; /* use strncat in case the path is very long */ - strncat(dir, _pgmptr, CPM_MAXPATH - 8); /* copy the executable path */ -#elif defined(__APPLE__) - uint32_t size = CPM_MAXPATH - 8; - _NSGetExecutablePath(dir, &size); -#else - readlink("/proc/self/exe", dir, CPM_MAXPATH - 8); /* allow room for bios.bin */ -#endif - q = strrchr(dir, DIRSEPCH); - *++q = 0; - strcpy(fname, dir); - strcat(fname, "bios.bin"); - fp = fopen(fname, "rb"); - } - if (!fp) - { - fprintf(stderr,"%s: Cannot locate bios.bin\n", progname); - zxcc_term(); - zxcc_exit(1); - } - bios_len = fread(RAM + 0xFE00, 1, 512, fp); - if (bios_len < 1 || ferror(fp)) - { - fclose(fp); - fprintf(stderr,"%s: Cannot load bios.bin\n", progname); - zxcc_term(); - zxcc_exit(1); - } - fclose(fp); - - Msg("Loaded %d bytes of BIOS\n", bios_len); -} -/* - * try_com() attempts to open file, file.com, file.COM, file.cpm and file.CPM - * - */ - -FILE *try_com(char *s) -{ - char fname[CPM_MAXPATH + 1]; - FILE *fp; - - strcpy(fname, s); - fp = fopen(s, "rb"); if (fp) return fp; - sprintf(s,"%s.com", fname); fp = fopen(s, "rb"); if (fp) return fp; - sprintf(s,"%s.COM", fname); fp = fopen(s, "rb"); if (fp) return fp; - sprintf(s,"%s.cpm", fname); fp = fopen(s, "rb"); if (fp) return fp; - sprintf(s,"%s.CPM", fname); fp = fopen(s, "rb"); if (fp) return fp; - - strcpy(s, fname); - return NULL; -} - -/* - * load_comfile() loads the COM file whose name was passed as a parameter. - * - */ - - -void load_comfile(void) -{ - size_t com_len; - char fname[CPM_MAXPATH + 1]; - FILE *fp; - - /* Look in current directory first */ - strcpy(fname, argv[1]); - fp = try_com(fname); - if (!fp) - { - strcpy(fname, bindir80); - strcat(fname, argv[1]); - fp = try_com(fname); - } - if (!fp) - { - fprintf(stderr,"%s: Cannot locate %s, %s.com, %s.COM, %s.cpm _or_ %s.CPM\r\n", - progname, argv[1], argv[1], argv[1], argv[1], argv[1]); - zxcc_term(); - zxcc_exit(1); - } - com_len = fread(RAM + 0x0100, 1, 0xFD00, fp); - if (com_len < 1 || ferror(fp)) - { - fclose(fp); - fprintf(stderr,"%s: Cannot load %s\n", progname, fname); - zxcc_term(); - zxcc_exit(1); - } - fclose(fp); - - memset(RAM + 0x0100 + com_len, 0, 0xFD00 - com_len); - - Msg("Loaded %d bytes from %s\n", com_len, fname); -} - -unsigned int in() { return 0; } -unsigned int out() { return 0; } - - - -/* - * xltname: Convert a unix filepath into a CP/M compatible drive:name form. - * The unix filename must be 8.3 or the CP/M code will reject it. - * - * This uses the library xlt_name to do the work, and then just strcat()s - * the result to the command line. - */ - -void zxcc_xltname(char *name, char *pcmd) -{ - char nbuf[CPM_MAXPATH + 1]; - - xlt_name(pcmd, nbuf); - - strcat(name, nbuf); -} - -/* main() parses the arguments to CP/M form. argv[1] is the name of the CP/M - program to load; the remaining arguments are arguments for the CP/M program. - - main() also loads the vestigial CP/M BIOS and does some sanity checks - on the endianness of the host CPU and the sizes of data types. - */ - -int main(int ac, char **av) -{ - int n; - char *pCmd, *str; - char* tmpenv; - - - argc = ac; - argv = av; -#ifdef __PACIFIC__ /* Pacific C doesn't support argv[0] */ - progname="ZXCC"; -#endif - progname = argv[0]; - - /* DJGPP includes the whole path in the program name, which looks - * untidy... - */ - while ((str = strpbrk(progname, DIRSEP))) - progname = str + 1; - -#ifdef DEBUG - fprintf(stderr, "\n\n"); - Msg("Start of execution: "); - for (n = 0; n < argc; n++) - fprintf(stderr, " %s", argv[n]); - fprintf(stderr, "\n"); -#endif - - if (_isatty(STDIN_FILENO)) - Msg("Using interactive console mode\n"); - else - Msg("Using standard input/ouput mode\n"); - - if (sizeof(int) > 8 || sizeof(byte) != 1 || sizeof(word) != 2) - { - fprintf(stderr,"%s: type lengths incorrect; edit typedefs " - "and recompile.\n", progname); - zxcc_exit(1); - } - - if (argc < 2) - { - fprintf(stderr,"%s: No CP/M program name provided.\n",progname); - zxcc_exit(1); - } - -#ifdef _WIN32 - setmode(STDIN_FILENO, O_BINARY ); - setmode(STDOUT_FILENO, O_BINARY ); -#else - if (_isatty(STDIN_FILENO)) - raw_init(); -#endif - - /* Parse arguments. An argument can be either: - - * preceded by a '-', in which case it is copied in as-is, less the - dash; - * preceded by a '+', in which case it is parsed as a filename and - then concatenated to the previous argument; - * preceded by a '+-', in which case it is concatenated without - parsing; - * not preceded by either, in which case it is parsed as a filename. - - So, the argument string "--a -b c +-=q --x +/dev/null" would be rendered - into CP/M form as "-a b p:c=q -xd:null" */ - - if (!fcb_init()) - { - fprintf(stderr, "Could not initialise CPMREDIR library\n"); - zxcc_exit(1); - } - - /* allow environment variables to override default locations */ - /* two options are supported, explicit overrides for each directory - * (BINDIR80, LIBDIR80, INCDIR80) - * or a common directory prefix override (CPMDIR80) - * the explict override takes precedence - */ - if ((tmpenv = getenv("CPMDIR80"))) { - mkpath(bindir80, tmpenv, BIN80); /* use CPMDIR80 & std subdirs */ - mkpath(libdir80, tmpenv, LIB80); - mkpath(incdir80, tmpenv, INC80); - } - if ((tmpenv = getenv("BINDIR80"))) - mkpath(bindir80, tmpenv, ""); - - if ((tmpenv = getenv("LIBDIR80"))) - mkpath(libdir80, tmpenv, ""); - - if ((tmpenv = getenv("INCDIR80"))) - mkpath(incdir80, tmpenv, ""); - - Msg("BINDIR80=\"%s\"\n", bindir80); - Msg("LIBDIR80=\"%s\"\n", libdir80); - Msg("INCDIR80=\"%s\"\n", incdir80); - - xlt_map(0, bindir80); /* Establish the 3 fixed mappings */ - xlt_map(1, libdir80); - xlt_map(2, incdir80); - - pCmd = (char *)RAM + 0x81; - - for (n = 2; n < argc; n++) - { - if (argv[n][0] == '+' && argv[n][1] == '-') - { - /* Append, no parsing */ - strcat(pCmd, argv[n] + 2); - } - else if (!argv[n][0] || argv[n][0] == '-') - { - /* Append with space; no parsing. */ - strcat(pCmd, " "); - strcat(pCmd, argv[n] + 1); - } - else if (argv[n][0] == '+') - { - zxcc_xltname(pCmd, argv[n]+1); - } - else /* Translate a filename */ - { - strcat(pCmd, " "); - zxcc_xltname(pCmd, argv[n]); - } - - } - pCmd[0x7F] = 0; /* Truncate to fit the buffer */ - RAM[0x80] = (byte)strlen(pCmd); - - str = parse_to_fcb(pCmd, 0x5C); - parse_to_fcb(str, 0x6C); - - // This statement is very useful when creating a client like zxc or zxas - Msg("Command tail is \"%s\"\n", pCmd); - - load_bios(); - - memset(RAM + 0xFE9C, 0, 0x64); /* Zap the SCB */ - RAM[0xFE98] = 0x06; - RAM[0xFE99] = 0xFE; /* FE06, BDOS entry */ - RAM[0xFEA1] = 0x31; /* BDOS 3.1 */ - RAM[0xFEA8] = 0x01; /* UK date format */ - RAM[0xFEAF] = 0x0F; /* CCP drive */ - -#ifdef USE_CPMIO - RAM[0xFEB6] = cpm_term_direct(CPM_TERM_WIDTH, -1); - RAM[0xFEB8] = cpm_term_direct(CPM_TERM_HEIGHT, -1); -#else - RAM[0xFEB6] = 79; - RAM[0xFEB8] = 23; -#endif - RAM[0xFED1] = 0x80; /* Buffer area */ - RAM[0xFED2] = 0xFF; - RAM[0xFED3] = '$'; - RAM[0xFED6] = 0x9C; - RAM[0xFED7] = 0xFE; /* SCB address */ - RAM[0xFED8] = 0x80; /* DMA address */ - RAM[0xFED9] = 0x00; - RAM[0xFEDA] = 0x0F; /* P: */ - RAM[0xFEE6] = 0x01; /* Multi sector count */ - RAM[0xFEFE] = 0x06; - RAM[0xFEFF] = 0xFE; /* BDOS */ - - cpm_drive = 0x0F; /* Start logged into P: */ - cpm_user = 0; /* and user 0 */ - -#ifdef USE_CPMIO - cpm_scr_init(); deinit_term = 1; -#endif -#ifdef USE_CPMGSX - gsx_init(); deinit_gsx = 1; -#endif - - /* Start the Z80 at 0xFF00, with stack at 0xFE00 */ - mainloop(0xFF00, 0xFE00); - - return zxcc_term(); -} - -void zxcc_exit(int code) -{ -#ifdef USE_CPMIO - if (deinit_term) cpm_scr_unit(); -#endif -#ifdef USE_CPMGSX - if (deinit_gsx) gsx_deinit(); -#endif - exit(code); -} - -int zxcc_term(void) -{ - word n; - -#ifndef _WIN32 - deinit_raw(); -#endif - - //n = RAM[0x81]; /* Get the return code. This is Hi-Tech C */ - //n = (n << 8) | RAM[0x80]; /* specific and fails with other COM files */ - n = 0; - - putchar('\n'); - - if (cpm_error != 0) /* The CP/M "set return code" call was used */ - { /* (my modified Hi-Tech C library uses this */ - n = cpm_error; /* call) */ - } - if (n < 256 || n == 0xFFFF) - { - Msg("Return code %d\n", n); - return n; - } - else return 0; -} - -/* helper function to build full path */ -/* make sure that a / or \ is present at the end of path - * before appending the subdir - */ -static void mkpath(char* fullpath, char* path, char* subdir) { - char* s; - strcpy(fullpath, path); - s = strchr(fullpath, '\0'); - if (*fullpath && !ISDIRSEP(s[-1])) /* make sure we have dir sep */ - *s++ = '/'; - strcpy(s, subdir); -} - -#ifndef _WIN32 - -void raw_init(void) -{ - struct termios tc_raw; - - Msg("Enabling RAW Terminal IO\n"); - - if (tcgetattr(STDIN_FILENO, &tc_orig) == -1) - { - Msg("Failed to enable RAW Terminal IO - tcgetattr() failed\n"); - zxcc_exit(1);; - } - - //tc_raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); - //tc_raw.c_oflag &= ~(OPOST); - //tc_raw.c_cflag |= (CS8); - //tc_raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); - //tc_raw.c_cc[VMIN] = 1; - //tc_raw.c_cc[VTIME] = 0; - - tc_raw.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON); - tc_raw.c_oflag &= ~(OPOST); - tc_raw.c_cflag |= (CS8); - tc_raw.c_lflag &= ~(ECHO | ICANON | IEXTEN); - tc_raw.c_cc[VMIN] = 1; - tc_raw.c_cc[VTIME] = 0; - - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tc_raw) == -1) - { - Msg("Failed to enable RAW Terminal IO - tcsetattr() failed\n"); - zxcc_exit(1); - } - - Msg("Enabled RAW Terminal IO\n"); - - return; -} - -void deinit_raw(void) -{ - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tc_orig) == -1) - { - Msg("Failed to disable RAW Terminal IO - tcsetattr() failed\n"); - return; - } - - Msg("Disabled RAW Terminal IO\n"); - - return; -} - -#endif +#include "zxcc.h" + +/* Global variables */ + +char* progname; +char** argv; +int argc; + +byte cpm_drive; +byte cpm_user; +extern byte cpm_error; + +char bindir80[CPM_MAXPATH] = ""; +char libdir80[CPM_MAXPATH] = ""; +char incdir80[CPM_MAXPATH] = ""; + +#ifndef _WIN32 +struct termios tc_orig; +#endif + +byte RAM[65536]; /* The Z80's address space */ + +void load_comfile(void); /* Forward declaration */ + +static int deinit_term, deinit_gsx; +static void mkpath(char* fullpath, char* path, char* subdir); + +void dump_regs(FILE* fp, byte a, byte b, byte c, byte d, byte e, byte f, + byte h, byte l, word pc, word ix, word iy) +{ + fprintf(fp, "\tAF=%02x%02x BC=%02x%02x DE=%02x%02x HL=%02x%02x\n" + "\tIX=%04x IY=%04x PC=%04x\n", + a, f, b, c, d, e, h, l, pc, ix, iy); +} + +char* parse_to_fcb(char* s, int afcb) +{ + byte* fcb = &RAM[afcb + 1]; + + RAM[afcb] = 0; + memset(fcb, ' ', 11); + + while (s[0] == ' ') /* skip leading spaces */ + { + s++; + } + while (1) + { + if (s[0] == 0) break; + if (s[0] == ' ') break; + if (s[1] == ':') + { + RAM[afcb] = s[0] - '@'; + if (RAM[afcb] > 16) RAM[afcb] -= 0x20; + s += 2; + continue; + } + if (s[0] == '.') + { + ++s; + fcb = &RAM[afcb + 9]; + continue; + } + *fcb = *s; if (islower(*fcb)) *fcb = toupper(*fcb); + ++s; + ++fcb; + if (fcb >= &RAM[afcb + 12]) break; + } + return s; +} + +void ed_fe(byte* a, byte* b, byte* c, byte* d, byte* e, byte* f, + byte* h, byte* l, word* pc, word* ix, word* iy) +{ + switch (*a) + { + case 0xC0: + cpmbdos(a, b, c, d, e, f, h, l, pc, ix, iy); + break; + + case 0xC1: + load_comfile(); + break; + + case 0xC2: + fprintf(stderr, "%s: Incompatible BIOS.BIN\n", progname); + zxcc_term(); + zxcc_exit(1); + + case 0xC3: + cpmbios(a, b, c, d, e, f, h, l, pc, ix, iy); + break; + + default: + fprintf(stderr, "%s: Z80 encountered invalid trap\n", progname); + dump_regs(stderr, *a, *b, *c, *d, *e, *f, *h, *l, *pc, *ix, *iy); + zxcc_term(); + zxcc_exit(1); + + } +} + +/* + * load_bios() loads the minimal CP/M BIOS and BDOS. + * + */ + +void load_bios(void) +{ + char dir[CPM_MAXPATH + 1], fname[CPM_MAXPATH + 1]; + char* q; + size_t bios_len; + + FILE* fp = fopen("bios.bin", "rb"); + if (!fp) + { + strcpy(fname, bindir80); + strcat(fname, "bios.bin"); + fp = fopen(fname, "rb"); + } + if (!fp) + { +#ifdef _WIN32 + dir[0] = 0; /* use strncat in case the path is very long */ + strncat(dir, _pgmptr, CPM_MAXPATH - 8); /* copy the executable path */ +#elif defined(__APPLE__) + uint32_t size = CPM_MAXPATH - 8; + _NSGetExecutablePath(dir, &size); +#else + readlink("/proc/self/exe", dir, CPM_MAXPATH - 8); /* allow room for bios.bin */ +#endif + q = strrchr(dir, DIRSEPCH); + *++q = 0; + strcpy(fname, dir); + strcat(fname, "bios.bin"); + fp = fopen(fname, "rb"); + } + if (!fp) + { + fprintf(stderr, "%s: Cannot locate bios.bin\n", progname); + zxcc_term(); + zxcc_exit(1); + } + bios_len = fread(RAM + 0xFE00, 1, 512, fp); + if (bios_len < 1 || ferror(fp)) + { + fclose(fp); + fprintf(stderr, "%s: Cannot load bios.bin\n", progname); + zxcc_term(); + zxcc_exit(1); + } + fclose(fp); + + DBGMSGV("Loaded %d bytes of BIOS\n", bios_len); +} +/* + * try_com() attempts to open file, file.com, file.COM, file.cpm and file.CPM + * + */ + +FILE* try_com(char* s) +{ + char fname[CPM_MAXPATH + 1]; + FILE* fp; + + strcpy(fname, s); + fp = fopen(s, "rb"); if (fp) return fp; + sprintf(s, "%s.com", fname); fp = fopen(s, "rb"); if (fp) return fp; + sprintf(s, "%s.COM", fname); fp = fopen(s, "rb"); if (fp) return fp; + sprintf(s, "%s.cpm", fname); fp = fopen(s, "rb"); if (fp) return fp; + sprintf(s, "%s.CPM", fname); fp = fopen(s, "rb"); if (fp) return fp; + + strcpy(s, fname); + return NULL; +} + +/* + * load_comfile() loads the COM file whose name was passed as a parameter. + * + */ + + +void load_comfile(void) +{ + size_t com_len; + char fname[CPM_MAXPATH + 1]; + FILE* fp; + + /* Look in current directory first */ + strcpy(fname, argv[1]); + fp = try_com(fname); + if (!fp) + { + strcpy(fname, bindir80); + strcat(fname, argv[1]); + fp = try_com(fname); + } + if (!fp) + { + fprintf(stderr, "%s: Cannot locate %s, %s.com, %s.COM, %s.cpm _or_ %s.CPM\n", + progname, argv[1], argv[1], argv[1], argv[1], argv[1]); + zxcc_term(); + zxcc_exit(1); + } + com_len = fread(RAM + 0x0100, 1, 0xFD00, fp); + if (com_len < 1 || ferror(fp)) + { + fclose(fp); + fprintf(stderr, "%s: Cannot load %s\n", progname, fname); + zxcc_term(); + zxcc_exit(1); + } + fclose(fp); + + /* read() can corrupt buffer area following data read if length + * of data read is less than buffer. Clean it up. */ + memset(RAM + 0x0100 + com_len, 0, 0xFD00 - com_len); + + DBGMSGV("Loaded %d bytes from %s\n", com_len, fname); +} + +unsigned int in() { return 0; } +unsigned int out() { return 0; } + +/* + * xltname: Convert a unix filepath into a CP/M compatible drive:name form. + * The unix filename must be 8.3 or the CP/M code will reject it. + * + * This uses the library xlt_name to do the work, and then just strcat()s + * the result to the command line. + */ + +void zxcc_xltname(char* name, char* pcmd) +{ + char nbuf[CPM_MAXPATH + 1]; + + xlt_name(pcmd, nbuf); + + strcat(name, nbuf); +} + +/* main() parses the arguments to CP/M form. argv[1] is the name of the CP/M + program to load; the remaining arguments are arguments for the CP/M program. + + main() also loads the vestigial CP/M BIOS and does some sanity checks + on the endianness of the host CPU and the sizes of data types. + */ + +int main(int ac, char** av) +{ + int n; + char* pCmd, * str; + char* tmpenv; + + argc = ac; + argv = av; +#ifdef __PACIFIC__ /* Pacific C doesn't support argv[0] */ + progname = "ZXCC"; +#endif + progname = argv[0]; + + /* DJGPP includes the whole path in the program name, which looks + * untidy... + */ + while ((str = strpbrk(progname, DIRSEP))) + progname = str + 1; + +#ifdef DEBUG + fprintf(stderr, "\n\n"); + DBGMSG("Start of execution: "); + for (n = 0; n < argc; n++) + fprintf(stderr, " %s", argv[n]); + fprintf(stderr, "\n"); +#endif + + term_init(); + + if (sizeof(int) > 8 || sizeof(byte) != 1 || sizeof(word) != 2) + { + fprintf(stderr, "%s: type lengths incorrect; edit typedefs " + "and recompile.\n", progname); + zxcc_exit(1); + } + + if (argc < 2) + { + fprintf(stderr, "%s: No CP/M program name provided.\n", progname); + zxcc_exit(1); + } + + /* Parse arguments. An argument can be either: + + * preceded by a '-', in which case it is copied in as-is, less the + dash; + * preceded by a '+', in which case it is parsed as a filename and + then concatenated to the previous argument; + * preceded by a '+-', in which case it is concatenated without + parsing; + * not preceded by either, in which case it is parsed as a filename. + + So, the argument string "--a -b c +-=q --x +/dev/null" would be rendered + into CP/M form as "-a b p:c=q -xd:null" */ + + if (!fcb_init()) + { + fprintf(stderr, "Could not initialise CPMREDIR library\n"); + zxcc_exit(1); + } + + /* allow environment variables to override default locations */ + /* two options are supported, explicit overrides for each directory + * (BINDIR80, LIBDIR80, INCDIR80) + * or a common directory prefix override (CPMDIR80) + * the explict override takes precedence + */ + if ((tmpenv = getenv("CPMDIR80"))) { + mkpath(bindir80, tmpenv, BIN80); /* use CPMDIR80 & std subdirs */ + mkpath(libdir80, tmpenv, LIB80); + mkpath(incdir80, tmpenv, INC80); + } + if ((tmpenv = getenv("BINDIR80"))) + mkpath(bindir80, tmpenv, ""); + + if ((tmpenv = getenv("LIBDIR80"))) + mkpath(libdir80, tmpenv, ""); + + if ((tmpenv = getenv("INCDIR80"))) + mkpath(incdir80, tmpenv, ""); + + DBGMSGV("BINDIR80=\"%s\"\n", bindir80); + DBGMSGV("LIBDIR80=\"%s\"\n", libdir80); + DBGMSGV("INCDIR80=\"%s\"\n", incdir80); + + xlt_map(0, bindir80); /* Establish the 3 fixed mappings */ + xlt_map(1, libdir80); + xlt_map(2, incdir80); + + pCmd = (char*)RAM + 0x81; + + for (n = 2; n < argc; n++) + { + if (argv[n][0] == '+' && argv[n][1] == '-') + { + /* Append, no parsing */ + strcat(pCmd, argv[n] + 2); + } + else if (!argv[n][0] || argv[n][0] == '-') + { + /* Append with space; no parsing. */ + strcat(pCmd, " "); + strcat(pCmd, argv[n] + 1); + } + else if (argv[n][0] == '+') + { + zxcc_xltname(pCmd, argv[n] + 1); + } + else /* Translate a filename */ + { + strcat(pCmd, " "); + zxcc_xltname(pCmd, argv[n]); + } + + } + pCmd[0x7F] = 0; /* Truncate to fit the buffer */ + RAM[0x80] = (byte)strlen(pCmd); + + str = parse_to_fcb(pCmd, 0x5C); + parse_to_fcb(str, 0x6C); + + // This statement is very useful when creating a client like zxc or zxas + DBGMSGV("Command tail is \"%s\"\n", pCmd); + + load_bios(); + + memset(RAM + 0xFE9C, 0, 0x64); /* Zap the SCB */ + RAM[0xFE98] = 0x06; + RAM[0xFE99] = 0xFE; /* FE06, BDOS entry */ + RAM[0xFEA1] = 0x31; /* BDOS 3.1 */ + RAM[0xFEA8] = 0x01; /* UK date format */ + RAM[0xFEAF] = 0x0F; /* CCP drive */ + +#ifdef USE_CPMIO + RAM[0xFEB6] = cpm_term_direct(CPM_TERM_WIDTH, -1); + RAM[0xFEB8] = cpm_term_direct(CPM_TERM_HEIGHT, -1); +#else + RAM[0xFEB6] = 79; + RAM[0xFEB8] = 23; +#endif + RAM[0xFED1] = 0x80; /* Buffer area */ + RAM[0xFED2] = 0xFF; + RAM[0xFED3] = '$'; + RAM[0xFED6] = 0x9C; + RAM[0xFED7] = 0xFE; /* SCB address */ + RAM[0xFED8] = 0x80; /* DMA address */ + RAM[0xFED9] = 0x00; + RAM[0xFEDA] = 0x0F; /* P: */ + RAM[0xFEE6] = 0x01; /* Multi sector count */ + RAM[0xFEFE] = 0x06; + RAM[0xFEFF] = 0xFE; /* BDOS */ + + cpm_drive = 0x0F; /* Start logged into P: */ + cpm_user = 0; /* and user 0 */ + +#ifdef USE_CPMIO + cpm_scr_init(); deinit_term = 1; +#endif +#ifdef USE_CPMGSX + gsx_init(); deinit_gsx = 1; +#endif + + /* Start the Z80 at 0xFF00, with stack at 0xFE00 */ + mainloop(0xFF00, 0xFE00); + + return zxcc_term(); +} + +void zxcc_exit(int code) +{ +#ifdef USE_CPMIO + if (deinit_term) cpm_scr_unit(); +#endif +#ifdef USE_CPMGSX + if (deinit_gsx) gsx_deinit(); +#endif + exit(code); +} + +int zxcc_term(void) +{ + word n; + + //n = RAM[0x81]; /* Get the return code. This is Hi-Tech C */ + //n = (n << 8) | RAM[0x80]; /* specific and fails with other COM files */ + n = 0; + + putchar('\n'); + + if (cpm_error != 0) /* The CP/M "set return code" call was used */ + { /* (my modified Hi-Tech C library uses this */ + n = cpm_error; /* call) */ + } + + if (n < 256 || n == 0xFFFF) + DBGMSGV("Return code %d\n", n); + else + n = 0; + + term_reset(); + + return n; +} + +/* helper function to build full path */ +/* make sure that a / or \ is present at the end of path + * before appending the subdir + */ +static void mkpath(char* fullpath, char* path, char* subdir) { + char* s; + strcpy(fullpath, path); + s = strchr(fullpath, '\0'); + if (*fullpath && !ISDIRSEP(s[-1])) /* make sure we have dir sep */ + *s++ = '/'; + strcpy(s, subdir); +} + +#ifndef _WIN32 + +void raw_init(void) +{ + struct termios tc_raw; + + DBGMSG("Enabling RAW Terminal IO\n"); + + if (tcgetattr(STDIN_FILENO, &tc_orig) == -1) + { + DBGMSG("Failed to enable RAW Terminal IO - tcgetattr() failed\n"); + zxcc_exit(1);; + } + + //tc_raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + //tc_raw.c_oflag &= ~(OPOST); + //tc_raw.c_cflag |= (CS8); + //tc_raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + //tc_raw.c_cc[VMIN] = 1; + //tc_raw.c_cc[VTIME] = 0; + + tc_raw.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON); + tc_raw.c_oflag &= ~(OPOST); + tc_raw.c_cflag |= (CS8); + tc_raw.c_lflag &= ~(ECHO | ICANON | IEXTEN); + tc_raw.c_cc[VMIN] = 1; + tc_raw.c_cc[VTIME] = 0; + + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tc_raw) == -1) + { + DBGMSG("Failed to enable RAW Terminal IO - tcsetattr() failed\n"); + zxcc_exit(1); + } + + DBGMSG("Enabled RAW Terminal IO\n"); + + return; +} + +void deinit_raw(void) +{ + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tc_orig) == -1) + { + DBGMSG("Failed to disable RAW Terminal IO - tcsetattr() failed\n"); + return; + } + + DBGMSG("Disabled RAW Terminal IO\n"); + + return; +} + +#endif + +void term_init(void) +{ +#ifdef _WIN32 + setmode(STDIN_FILENO, O_BINARY); + setmode(STDOUT_FILENO, O_BINARY); +#else + if (_isatty(STDIN_FILENO)) + raw_init(); +#endif + + if (_isatty(STDIN_FILENO)) + DBGMSG("Using interactive console mode\n"); + else + DBGMSG("Using standard input/output mode\n"); + + return; +} + +void term_reset(void) +{ +#ifndef _WIN32 + if (_isatty(STDIN_FILENO)) + deinit_raw(); +#endif +} diff --git a/Tools/unix/zxcc/zxcc.h b/Tools/unix/zxcc/zxcc.h index 4d08949a..d60cd1ba 100644 --- a/Tools/unix/zxcc/zxcc.h +++ b/Tools/unix/zxcc/zxcc.h @@ -1,126 +1,141 @@ -/* - * Change the directories in these #defines if necessary. Note trailing slash. - */ -#ifndef _WIN32 - #include "config.h" - #define ISDIRSEP(c) ((c) == '/') - #define DIRSEPCH '/' - #define DIRSEP "/" -#else - #include "config.h" - #define ISDIRSEP(c) ((c) == '/' || (c) == '\\') - #define DIRSEPCH '\\' - #define DIRSEP "/\\:" -#endif - -#ifndef CPMDIR80 - #ifdef _WIN32 - #define CPMDIR80 "d:/local/lib/cpm/" - #else - #define CPMDIR80 "/usr/local/lib/cpm/" - #endif -#endif - -/* the default sub directories trailing / is required */ -#define BIN80 "bin80/" -#define LIB80 "lib80/" -#define INC80 "include80/" - -#ifndef BINDIR80 - #define BINDIR80 CPMDIR80 BIN80 -#endif -#ifndef LIBDIR80 - #define LIBDIR80 CPMDIR80 LIB80 -#endif -#ifndef INCDIR80 - #define INCDIR80 CPMDIR80 INC80 -#endif - -extern char bindir80[]; -extern char libdir80[]; -extern char incdir80[]; - -#define SERIAL "ZXCC05" - -/* System include files */ - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_UNISTD_H - #include -#endif -#ifdef _WIN32 - #include - #include - #define strcasecmp _stricmp - #ifndef STDIN_FILENO - #define STDIN_FILENO _fileno(stdin) - #define STDOUT_FILENO _fileno(stdout) - #define STDERR_FILENO _fileno(stderr) - #endif -#else - #include - #define _isatty(a) isatty(a) - #define _fileno(a) fileno(a) -#endif -#include -#include -#ifdef __MSDOS - #include -#endif -#ifndef _WIN32 - #include - #include - #define _S_IFDIR S_IFDIR -#endif - -/* Library includes */ - -#ifdef USE_CPMIO - #include "cpmio.h" -#endif - -#ifdef USE_CPMGSX - #include "cpmgsx.h" -#endif - -#include "cpmredir.h" /* BDOS disc simulation */ - -typedef unsigned char byte; /* Must be exactly 8 bits */ -typedef unsigned short word; /* Must be exactly 16 bits */ - -/* Prototypes */ - -void ed_fe (byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, - byte *h, byte *l, word *pc, word *ix, word *iy); -void cpmbdos(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, - byte *h, byte *l, word *pc, word *ix, word *iy); -void cpmbios(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, - byte *h, byte *l, word *pc, word *ix, word *iy); -void dump_regs(FILE *fp, byte a, byte b, byte c, byte d, byte e, byte f, - byte h, byte l, word pc, word ix, word iy); -void Msg(char *s, ...); -int zxcc_term(void); -void zxcc_exit(int code); - -byte cin(void); -void cout(byte); -int cstat(void); - -/* Global variables */ - -extern char *progname; -extern char **argv; -extern int argc; -extern byte RAM[65536]; /* The Z80's address space */ - -/* Z80 CPU emulation */ - -#include "z80.h" - +/* + * Change the directories in these #defines if necessary. Note trailing slash. + */ +#ifndef _WIN32 + #include "config.h" + #define ISDIRSEP(c) ((c) == '/') + #define DIRSEPCH '/' + #define DIRSEP "/" +#else + #include "config.h" + #define ISDIRSEP(c) ((c) == '/' || (c) == '\\') + #define DIRSEPCH '\\' + #define DIRSEP "/\\:" +#endif + +#ifndef CPMDIR80 + #ifdef _WIN32 + #define CPMDIR80 "d:/local/lib/cpm/" + #else + #define CPMDIR80 "/usr/local/lib/cpm/" + #endif +#endif + +/* the default sub directories trailing / is required */ +#ifdef _WIN32 + #define BIN80 "bin80\\" + #define LIB80 "lib80\\" + #define INC80 "include80\\" +#else + #define BIN80 "bin80/" + #define LIB80 "lib80/" + #define INC80 "include80/" +#endif + +#ifndef BINDIR80 + #define BINDIR80 CPMDIR80 BIN80 +#endif +#ifndef LIBDIR80 + #define LIBDIR80 CPMDIR80 LIB80 +#endif +#ifndef INCDIR80 + #define INCDIR80 CPMDIR80 INC80 +#endif + +extern char bindir80[]; +extern char libdir80[]; +extern char incdir80[]; + +#define SERIAL "ZXCC05" + +/* System include files */ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H + #include +#endif +#ifdef _WIN32 + #include + #include + #include + #define strcasecmp _stricmp + #ifndef STDIN_FILENO + #define STDIN_FILENO _fileno(stdin) + #define STDOUT_FILENO _fileno(stdout) + #define STDERR_FILENO _fileno(stderr) + #endif +#else + #include + #define _isatty(a) isatty(a) + #define _fileno(a) fileno(a) +#endif +#include +#include +#ifdef __MSDOS + #include +#endif +#ifndef _WIN32 + #include + #include + #define _S_IFDIR S_IFDIR +#endif + +/* Library includes */ + +#ifdef USE_CPMIO + #include "cpmio.h" +#endif + +#ifdef USE_CPMGSX + #include "cpmgsx.h" +#endif + +typedef unsigned char byte; /* Must be exactly 8 bits */ +typedef unsigned short word; /* Must be exactly 16 bits */ + +#include "cpmredir.h" /* BDOS disc simulation */ + +/* Prototypes */ + +void ed_fe (byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, + byte *h, byte *l, word *pc, word *ix, word *iy); +void cpmbdos(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, + byte *h, byte *l, word *pc, word *ix, word *iy); +void cpmbios(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f, + byte *h, byte *l, word *pc, word *ix, word *iy); +void dump_regs(FILE *fp, byte a, byte b, byte c, byte d, byte e, byte f, + byte h, byte l, word pc, word ix, word iy); +void Msg(char *s, ...); +void DbgMsg(const char *file, int line, const char *func, char *s, ...); +int zxcc_term(void); +void zxcc_exit(int code); + +void term_init(void); +void term_reset(void); + +#ifdef DEBUG + #define DBGMSGV(s, ...) DbgMsg(__FILE__, __LINE__, __func__, s, __VA_ARGS__) + #define DBGMSG(s) DbgMsg(__FILE__, __LINE__, __func__, s) + +#else + #define DBGMSGV(s, ...) + #define DBGMSG(s) +#endif + +/* Global variables */ + +extern char *progname; +extern char **argv; +extern int argc; +extern byte RAM[65536]; /* The Z80's address space */ + +/* Z80 CPU emulation */ + +#include "z80.h" diff --git a/Tools/unix/zxcc/zxdbdos.c b/Tools/unix/zxcc/zxdbdos.c index 36cbe532..9a839e5e 100644 --- a/Tools/unix/zxcc/zxdbdos.c +++ b/Tools/unix/zxcc/zxdbdos.c @@ -2,43 +2,42 @@ #include "zxbdos.h" #include "zxdbdos.h" -/* This file used to deal with all disc-based BDOS calls. +/* This file used to deal with all disc-based BDOS calls. Now the calls have been moved into libcpmredir, it's a bit empty round - here. + here. ZXCC does a few odd things when searching, to make Hi-Tech C behave properly. */ - /* If a file could not be found on the default drive, try again on a "search" drive (A: for .COM files, B: for .LIB and .OBJ files) */ - -int fcbforce(byte *fcb, byte *odrv) + +int fcbforce(byte* fcb, byte* odrv) { byte drive; char nam[9]; - char typ[4]; + char typ[4]; int n; - for (n = 0; n < 8; n++) nam[n] = fcb[n+1] & 0x7F; + for (n = 0; n < 8; n++) nam[n] = fcb[n + 1] & 0x7F; nam[8] = 0; - for (n = 0; n < 3; n++) typ[n] = fcb[n+9] & 0x7F; + for (n = 0; n < 3; n++) typ[n] = fcb[n + 9] & 0x7F; typ[3] = 0; drive = 0; if (*fcb) return 0; /* not using default drive */ /* Microsoft BASIC compiler run-time */ - if (!strcmp(nam,"BCLOAD ") && !strcmp(typ, " ")) drive = 2; + if (!strcmp(nam, "BCLOAD ") && !strcmp(typ, " ")) drive = 2; /* HI-TECH C options help file */ - if (!strcmp(nam,"OPTIONS ") && !strcmp(typ, " ")) drive = 1; + if (!strcmp(nam, "OPTIONS ") && !strcmp(typ, " ")) drive = 1; /* binaries, libraries and object files */ if (!strcmp(typ, "COM")) drive = 1; - if (!strcmp(typ, "LIB")) drive = 2; - if (!strcmp(typ, "OBJ")) drive = 2; + if (!strcmp(typ, "LIB")) drive = 2; + if (!strcmp(typ, "OBJ")) drive = 2; /* some extras for messages, overlays, includes */ if (!strcmp(typ, "HLP")) drive = 1; @@ -48,18 +47,18 @@ int fcbforce(byte *fcb, byte *odrv) if (!strcmp(typ, "H ")) drive = 3; if (!drive) return 0; - + *odrv = *fcb; *fcb = drive; return 1; } /* zxcc has a trick with some filenames: If it can't find them where they - should be, and a drive wasn't specified, it searches BINDIR80, - LIBDIR80 or INCDIR80 (depending on the type of the file). + should be, and a drive wasn't specified, it searches BINDIR80, + LIBDIR80 or INCDIR80 (depending on the type of the file). */ -word x_fcb_open(byte *fcb, byte *dma) +word x_fcb_open(byte* fcb, byte* dma) { word rv = fcb_open(fcb, dma); byte odrv; @@ -75,23 +74,18 @@ word x_fcb_open(byte *fcb, byte *dma) return rv; } - - -word x_fcb_stat(byte *fcb) +word x_fcb_stat(byte* fcb) { - word rv = fcb_stat(fcb); - byte odrv; - - if (rv == 0xFF) - { - if (fcbforce(fcb, &odrv)) - { - rv = fcb_stat(fcb); - *fcb = odrv; - } - } - return rv; -} - - + word rv = fcb_stat(fcb); + byte odrv; + if (rv == 0xFF) + { + if (fcbforce(fcb, &odrv)) + { + rv = fcb_stat(fcb); + *fcb = odrv; + } + } + return rv; +} diff --git a/Tools/unix/zxcc/zxdbdos.h b/Tools/unix/zxcc/zxdbdos.h index 7a47b801..16bcde18 100644 --- a/Tools/unix/zxcc/zxdbdos.h +++ b/Tools/unix/zxcc/zxdbdos.h @@ -1,8 +1,4 @@ - - - -int fcbforce(byte *fcb, byte *odrv); - -word x_fcb_open(byte *fcb, byte *dma); -word x_fcb_stat(byte *fcb); - +int fcbforce(byte* fcb, byte* odrv); + +word x_fcb_open(byte* fcb, byte* dma); +word x_fcb_stat(byte* fcb); diff --git a/Tools/zxcc/COPYING b/Tools/zxcc/COPYING index a43ea212..92851102 100644 --- a/Tools/zxcc/COPYING +++ b/Tools/zxcc/COPYING @@ -1,339 +1,339 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - Appendix: How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Tools/zxcc/zxcc-src.zip b/Tools/zxcc/zxcc-src.zip index 1ae919e4f1fcd045b48e6ffa8caeda9192de8000..25238d8af7609c967953ff343d0d209deb1f4a31 100644 GIT binary patch delta 50899 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 H1?>L-^;%Xp delta 50154 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 BubBV< diff --git a/Tools/zxcc/zxcc.exe b/Tools/zxcc/zxcc.exe index c51614dac121daab13358f7d735a921b4ffbd607..a66b00537cad6bb7802f4422c18217a63ba23e26 100644 GIT binary patch delta 28288 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 delta 39429 zcma&P3tW`N_dov3vRnlhl@(M_Q1E_Xy`(1OfGS`8dA;U&X3m^BbLPyM zGiNT(VtqZ>x;JQ({jRS+2)tMF{WVA%SR1BkFD+t{)KvvO=D|A>!3vmURO1>+Vp1EV zB}prucruvTRM2Tn! z-XSQsX&cy*khw?pz<5rWW#47%J@b_ULBo+us-^Ykn|) z<5Nkp2Rk#v?+m0uX(MY_Y?JHe&zp63b*}uqi7MeAd<nEI$i3-OmTAhSG|4$P z+_d1uG)bO&**W(zAEp;A2zTU$lo6QU2f89=ILRMCT+Y4hysu^U-E#%mWFq^}$F81% zcMN}Im?XJR6CgGKvEzvO>Y0stL?wJZIItZJ=W&pF83~q zJ(#a4sxS{OuiuJx7xC+$HRA-3DBqX9pVCywm%dXi<$5_N(z0Vmnp9KN02U;^i16ls zVW$A_XOMPop}ZO+^B4XP3g1lJOX-`4e?#)DDQY(N@(HRG6{~`}_@OE&8`M-4)M5*w zhb3wh39d|fGhLE@ub~MC!U(>wVvwVG=i0b&a$0duDom0>lf)sSQ%30Jz@@wmFl3d5z zqd7$tx}x1eER>yP`VCaG`E#fN-7eY=L^pJd5UImeI$5SG0`Z|+5i10ud6q!3fSmL+ zk(+QU)(a}uP(P_)fs}MB(kc~6=iEY!fr(sjYp5Vyo~7zC`c2~3j``Jx8d?$#89K7G zLK!Sx-W_Fpit#;BA$3Z=S)CXVZYcx_-6-?6TBg}N%#V{pfBvp&3%=Ff{|Q{!j>dBt z=1uMW*{F+ozXm^$)j+9`kX?!c?rv>Fmp4>_~ z8Zo&^kmjW*YB*UYfq0(}Ssix)+ea$fWSI*pJp516kZ||c&=eC{U;a@Y39?#E98nWA z9HU5{Zy}xCsx|e_Eteq!KB*t*iYPkbKd=eT`>vrEOtD07EsDTmmWF_JSuc7(Q;K$2 zr1DkZKnxYW2AmdEm)GcYsDM4P6jy4}v1DW(6S0f9pf7F~^#Qx0d(Ril(SYt5CGeG7p*jH1Oq0G=0e7 z`;nHb%E+4WW?&p%20+>A=K(#=zbAm10B2qhfYU_7N+h0Eo7C>Gd=r6pDZ7}mSNtuT z2=Zq&(7!SlNE9pIU?+F;Q95YXmvtgAlf0(N`ai~P_IkZy8j$O1(kv4H66SEH6|4gz{SV|VC5}fRmTmfw8hr{; zXz1ZZfMZ6@yyEqiZG$C$SH}m`NK#&H;B!a?U9Sl&!P`(1xCbv*6L{cF=>L?Oz%nGG z-?0MkBx2sgn!wNT-c}R%gNk<@uORz?xA01?c>B6te*!VP{tTWwzobVL6t-Ntj?R|6 z@E9V#p!@-6=^5b_aXm2j#?j!r1DGTSLLJ%`&rwX$5on?6*_=mmYL4MtbKq1=&RTP1 z$!xs)1x~;d7U_|8<(Y_;g^>itpp++}ga9>CSh186mVdz-LFFR7qJTG$@{0A5+tVcU zk2cwBKb2STr-W%O&-SO++^OKZ5tw&j%Px=@H#Q3~%4cTZU2Ukq!xT={OaM#S(=k1L z%{Rbw$#oF%EA_5d+a_41BRy}HuPH&mGgRc2YEhe^qO`G+q*ZMSAsRnbV>UFLv{%XX zl?_3x-kMVM`rGMn1l!5=vYt?Rb0QU=U0vqYO44i}&39042W3~AVu;R8q_cBUy!o9C z$Ly7^cXb^s$aLtN@XSd zjTKueRV(G|#Kmk@v=YA=esCI<+0r zYovJF)i!G{yB0)+bXbZhUapZdnqW$M+q@yVC$_rQL=EWQUrhbFqI&`)Y2+um!n^VA z^NHwZHc2?w)368x76ms#JF zRl2t6W0Rf-#F254U#59DgTtvQEGE$0M(4P$@^5mTH*n9}uCMgb7N}5VgN9X=?V{ne z^8?6{VzAT)TH{yw4%N0sn<&o|<$}mNb`ukU`%##hJjb0O$raX%O?j!3(cHE;C}nhh zNQzarVGc4K864gW++iWQnZ#?$5t>SEjVW3E_;XdZS~P9Hw#-In^|TxLAYr80?m(w<4CkdRjRmSq& z00UOXg8>68eg|@a1XgAqarKGr(G{xcVdHJ7m!VBke$HVl^2%dK5Ka8{k6eqRyIHn^ zX#p=2@ZV}OqvN?2JtRj^Dfid&-<7*5Kf zzMHw?D?fA@VxlZxy-)3LDwYy0DWlDiMP73o>USOoKgUx)MXnNgc&TB=m_?<<%nxjGMSg#HHe zVYPvmx4C+BT13ifs3^GL?M9-Eth^EuT4&FUv}d;4L9E*|+dFbUab|YpkHwMV)HpL^ z`9p~26`jlP3cD(wk$>a$(Y}tcXFec$lAneNuE|`G;K(@coO};I-NmOaLy1bpC%hT} z=j8k3Dhti80@%p2AfkeGHPlPGr{W=0@M~QiK3Z4QK_qHKr^vsRQg?}ZY6D3(#K84n zk`}99r1+5cXfR-5s6~pF0b1Ke96Lp>MVLduEY2Y11E+GIbs_s zD1D9|M8A}D(Qu4EiXO>>3w}kru3hGI(@N^Z*VWRV2-5~iZWl?dT<5&+GNw~?e8v+? zC5MS6A4extkGN#pUJES5tLUK;sx8Y|L_Twt$w{_mqBeH{N;|h~Lx;&t7XBub$5}+FEK!{!w}H<>b-p>d+&`SE zP`_NyEpWEgaTJrIj-&oS_KzcXPoh0(mvcK2#L$6u4uaza9jGRYjl$64h8wgY{~Na2 zR@s#skK8cV(-6-#9i+~vgIK_TZQVslS7ZT|<{)eS5Z?%+p&+< z%mzTz*a4tU8f*d`h$Hn}lwf z4P~3V_YJ_D?;6m(i+JDFy=TI`Fx_OgBT^zCIYCO&>jL$1x;2WTn}x+=SO z)J!aMec3%-bEeuA*Q0a9P40u{kZWuYkEM0ok2`SdxIg6^_fz5Cs`?iS{ZpVLFgtyq zc*QKyqC3!peVGu)FjZ?OH#4iQ@C&rY`e?XBI*XRM7ov>V(@QHqLt~gUPXprh_I-vZ{(z7o9YZ$1GY_0Sz7J9ba^8RkTx!)<%{!QTIqyM9&;B z-gB|&n67XRDYCYWb;RxFP}>!aZo^#w)Qs)KBzGERse3YO&;do33NyF_!*1xS#AD!O zsO?5=YsxX{UM9ZI@QsMO1F5ioVn8Kzk*YqA^ii7MCFu6xbBO~VPnCJ?mz3!SJySC|4lF7slO z&u=-MY3*y$BL9+qt4V8zy$C&NS8;YYX4!As9!4W1z6G_)O@@;eeh5^Yvtosp@*Rc@ zpy%M7?gZHSXgo$raawGm#hw;#GE(KiYUPFskBd~NH>mM;`$=_ZGf|y0oLd^n9LB)| zb{0`I%QTM4eu$QkC930dMVpE$)>$BZh~EvPs;*m6b#GLiWtv4Lo(EnrLzz9+{NzLn zEfI>2LEnV)4i8EGr1C-#`?X9c$_0(+Eo{gfErYpupgAqjYF;?qw2UZasdZ2H>QiWf zuaT?0`W*#WjAj)z=LeTfL;aq>vP`_POfnUS7X`wL&Y7cBvFiZv*-EWPr%K~bG!a`T z!XDh%3QQrPTz^N5C(IL(NXoS|kv5Q6LPUpCG|RNtLRB3QR6<}B#vw-A7VE;wFxn(H zX)?h7Zi^l~2h%P5#xSHrFN%fRwFqLl0(2m{r79&yTnnaMOfqr%Fg;Q{YkIcnG}Sdh zU_>sKoEaCh9C{07=1kA_>KjNb)$q=RT%;_=q>I^bRQ@KK>qH}1rD0pgC37fdG^n4~ z69oJ2HS7FUgP9UY091;Ot?j5nM}E03yw8WUBr)(p%FMWEu~k@FJx#gNk=s~#A($PP zTWAT>jHWr}UMxDd&esJSAv%bg&w&zpGUPKO>(+%jqk@bzn$Dg}qavs+>$obC}R_vQ29UPL`a4f_^3)vkUE&6{?;8DmmwPeizx(cGA~9JdVO!TIncDRy+ITUefAwG`GI_8!nWb@&~Dy=bmnMaWJ6aNnpx1_1m7fU892HaxJ zVrg-J39$+vnpZ!L21cz#dfPYZ8*~+`70vNd=Y3r0Q-jEzJ*g)%wSPrdolk??vnr{TFk*>U*>v6 z@ja2&ixwFEB%0N)A05$P{=zpyp@pbD%QT6E5Q57m-ABw%gwjE)EXeyBf`X`NU&3#9{{xR7 zwg{W!dr-N6WAQJ!zaY5JxS|7(q550RYcpv1MrZ@f>wj6-i~bQhsXdn-TPlAH<_nPeTL(OhN>Fe}#LbF3hk#cx>z(6KXwr>t8G{VJv264k%VnYtVJy)V z|7|QqS6DDLLLmRkTJ}?Eh^~OO6kP$C%2&a{W@v=4jdQ>YdPjn3tVfI82cV&_qhS9K z+70UL>d5+)!ANgG&pI+1Mg@{yxIYHh7LsHvS<7!;B}w{SC>idzI0N#KTPLD9CYeOH z6*Nh7XEClJ9QMi;ki4PDILa^~mJtf*T0>$C(`Wtq`LO+V`b#B=Y_94|_P>&m?`2zJ+Zke-) za`_ajCa9(RufzUjnSLQwKOij=G3y@xU{!TP{=#OdND%z<;h-WPmuoOP?}zv>&7dR}3_k?( z2ZbWgYylki*Emx^^L8M9V@f#&pgQ~UB`A#zq2G9d;7hCox&TIV@(!T!kzft>Usre< zdqNhqlzf%P0PIWr#yx_%u5dXDxZeO?Ya8C*tqzlLp;YoIY-_B9FtDBNOxJP~$wg&7 z<1)D1hm(gJo$v(+0r&&D)XzHR-zouh<~H$%k>P8_C@3RvhHxk5VVbSF`FK0amjeQ9 zA7XnIF^qqO!tPa|WvFmJM%CAerUdl1wVlS>=q@KO|Mh@96BJ{**KR zCiW!viq;Hg?tWfR?JE)lBC*DS6pMbsICN~GlFjL%*8D)>i1`6w)_hI4)}Lx)HEY7- zu}}^ao4D9AOSYg~mRH{bA4jde*%)Ni75;gd)OEkFs+SL{RasG$&=!>--zelIxOo&& zlZGTCxXa?(u#HG&s-~!7?OoW)ym_3e#WB!|XJ^FAwawL*{BZkO>$liWxZ0;ht_AwY z+WbZ9x(f698YrOya$!IBAj%(s4BT_U;HY)S*N>L3^qX|t_3-qrmccKh_ANs(S;`** z_Y`(pM%Jy}%O)N7yodBuly$d3G4-(Jo|lmP1(Tn8oRx#5={k+WzUY{;d(cuWG<=6W z!;o3#g?{?dNl4R45Za6_10-_nRR&k(j9wb|F4s>p5-rucT5-z|Z9O%5?dHUbz67?G z;2k27Emuy>$udPM;9?Mc7}i-pTrShAn0 z$@p0+#yS`K5mg4S?doW=1{)jxO;lS;w{-!w3Zrv!Xtr}Q%g!>brv@&=sDmi6g%sit z2a_H);l?JWZx0iE?Z!A22Zf%XG~1Q%byJ+$wyxy6aVGVRQ8MO>y|pm#ZqI16u4|0X zud`hVHHVjPLLDgm2ueHQW1Zm-BIbEbZlNtgb%!vS+H$ExZ3^1)MUH7RaaIL5#)yCI z5zxB!$nmW@#2y8?C{s=4RA93xKz)u)i6(+r1w<>K5m(r7q|#!Y9BSnkpd13C_UUTW zZCxGtmpRC~x}B6CW4eyA>K&STWMKer1caeOgya4!yxX}uA55M77!fQ-xP1-UXL=@t?8_0{_;M|ZfA^PUP( zPk{&SaP6PBM^pGO*Sz_?G$u5Jg#R zx__oxhS5OftKq|u*@t@ob5qUZ%3Wm(j20|uaJsu4w1lzC;ehP7dqdh~ydqt) z@Yf*5+CW;DVM(Xn0r8)#Pa@JZPbO=?cd9GsbPDG% z2$mBgq}+fUFy9MFxeASsu#T8x4ycg^IVUjB1(b26E({47Mp$QfSJ$M4eTI%ef_HmG zjPN+@Tsyb?N^{sMOiuOy=NQIMK{MPSh$=ajjyNc)biKMTZV+~MrTibo2?g`tlA9u? zH1i1+HOp3cPqrxy6-?zxuI7c^j8w+_qqEyg9pF#`_YY$p*#e&&B?}d{%d0l#M4hKSAdLtM412nRmdo`@ZgjZpQ{b z7O}RLd)D4*Ygukd$I(E5dNL57Kg@6rWs7mxPDO20wB^3rG*`A_5GoxOY*iVc`m3Bc z0NH%NbvAEmhpW#))8!Llpj5g;?3<*$F5~@Cboc3a zF4Zv1)vH2wQWP;2c4PkjNI|Qp4PMEWXX>bb4QcANM8~>FhdByob~p@lJ#C7yG!_RZ zdn+44io1rMfp3b_UPngbA>v-f31Fq6;xNVYN~l_a%soSWhTU=+RSz7) zHcbFlKPg>x8{T3#*nRvCEfy{*x(zWRRUe3yX+^s3@n0eBl%*?r=pN4vLhL!6rEnER z@^yuC>HVOta01@$v4pooSJ;_=i*+ zUEyka->WOk!`m^57-g*&Cm#pDVmfh5isyekD@m?*9~fi7)&my5#W6tD-~yhwCq1#& zw^hjdo}ew3hTuPdBS@7}t?%oNJiQ*Ht^&aDAFQCFy={2p*|k#>Jiz<6C@ zIo@RzZ>39zE1-G&m6NW0i~F>_k8)#mg;NQ2nCqv-JM~&vH%CTHUM(c)UWWu0%12x! zOA;+DB+H3_9PUhc>+zt5^9;brntIUbm<% z{%VhU0JtP1D!U_8fnGZ8v7=?0I4Pd?3=bD;l6XQL#xx^f(oPGfj;+TwEL#yT=C=gAs( zKU54It_kwG;}PXKpPuTwe>X>`&-61ipgP1sh-l?Z@K zXAk2pDe1Yr+Wi}3j{@5%I~duAG0voN3$zZI$mpEj~XX z4Z@&uPX{sb+)}^}ALQz|d`S2%ngSB5gkSDjw0xB1ljA@66sQlBiqOdn81VXu(~sO1l! z65;-M@^gG2TZC;Dwmle4$&KebT}cm5p6vU~qw<>Ojn*-bO-j{X#O!=Kj!~-RX!YT2>|0|@hCi=x8PYuZp8%tGoGFgNB+95 z7N+q`8vhDud*^gdSs6BlCH@H>H5%N}g+OWG;e)3ZTZJYI$aPs+S*G6L-M*2!fsd~s zQAVkYBFrNa4+WFBciJ}Px~@>;TDT(F@{yCA@CrT%(>mPWV1CEzbj8w^n*3s#B&}~( z(jRXuI3sO8McA%JJQ7((0B(PSEWEvbb~Ua-dm{*0*85QjtolgHh`PN>h?jqaNfK4G zq3@G;@S9Xk^RoYOLpYL<#4Ta|K0KJ&)#8G%J-Awz!#~^=_OA|peUj!Q zo~zcY;}_p>Syy&pM_t=iPPU{#PB;(d%l8mh<__f<0?@?gs{qYDP5F2q&cwgtjPm2K z@*H2W-ZwzgeIUIbq$!{618MxAnVRx>KG=VD3l22(m)3*1_3S>PO5LGWgQ`; zkKysIeda_>muFpHn!8x8er1#n+-;N^5yIyfrGW_35dMWwg>Vr;JJ%@vg%Cf_D2+u} zkMKUiIfORzjZ!+oN`xm6b|Acma2cW90;4n%Aq%1NJ)n&+0bxDD0fbZc7%h_aUZd0> z;Zuaw3ysoYg#1NDDe^v}WI@QtGfGPktPdEa?u(6*3E?+{RZCC?;Rl51rABEg!X|`& zA*4QNl+GheS!R^(M|cdu{E$(47oig2cZ5O9jnc&B7NbNGSd7Ga1RH`K;UL0Agv^JH z(qsg}xfk#I5tbsnfKZ3fcZE?Jj4%d)aPGo83&Dc$Izro(MyVr0FN8q|gfkTHg$SDv zezOn|VM4x9+Kf<#KuFi{t}z>>-m8q#9E2ATP9R)I82E^aa~|(IRvV>d2qzJSK5CR) z2$vBiKc?dB#ap)qU5C&cVF1ElgnJO4LJB4Q3!n~GD?>a&OC0EUVZ}lVmHF-7^QNAnZ>BkVU$iIJo}_k+U7J$w>@Q) zS`gmcXq0AcGD;nuHcCwh^_$WEU%QNw^BGi%(0~xI#VGYeScz}|!SJk6nvSpx!G&-L z;Y);`3UmO$gAnTX_!MDe2{e2s7(jUJeJCHj5$=D-C_Rc$k5IbLDE)$P6`|jLqck32 zIl_5_$af(*1pNV{lz<>3>_9k$@IAsW7Cd$zgd!kZN7!9vl=dM6l|y3@dK@-Nc?fSK z{2Spf1l@aREkY^6nsY|!RfOLW*m?9VLK?yZgaZf{5ZZi&k$_-EID~Kx;Q~T4f<^PS zQF;ksXsJDnyAe5n(w(9m01A z(rZR34xt~yXoNWkk0Q7b-bC;q=wCNVLlCkN)*+N5w0i@Ji!cS@afIy%`w={EL_s`n zLTm`+^z34ojPG?_f2@;c!Hcd=YsN*`U^L}_KLg{-gI;zmTk}ltK0s#h|d=G1_VZ^H`BU{%ADKvY;iOP^qNZ;UfZ2M@iR7>&qzjXu)WZI#f_Vq(<3h4JIP2 z3S``=Gck|Ugcbg59{M*jMfrkJKcyO5&kiUCB!{Tkw>jeS+B*FsykBAWXy7Mbr2992 zE3>Gu2NRLz1ay1Ra@6V>Z~cpzal(ssiDta{cz2+lc>J60QE=-* zn%wU`Kx_v$XEYjhg@@tM3tZj%X!E|4PYev84WqwTi|(-r)-}l&Z8edh^=Nc2aVfia zGx>A&E!1MM6I5&^7fxlyJ!}~EvcXSxA1-AjH>3SNR4R)lUSb$}g06TMZ)STV|BkY6 zqhl#a|JswC@r-tM#q&0&5zj}QUH_+`UUw$_&phs2sYlIuUeP8-Quaw}`BS4n_w}cy zP+3;*!;rD<3?D+sv;D@$fw6UC97KO`V+tE6n(*H}MGXtB7wz=RPLxl08f|p#f4ULR zlFc3PT=z^T*C(4vN&V^0u6?d|Z%TjakMFx@OM>Q~S>LB9?0;mr-q^Yh6#6~C5YLUz z--G9`&(Fg%>ji@Be_=YFZMG5o!EImRDfrkofBPXViNP->wK2)f)Qo+DcHS5C51HO# z>>uuXZO`t&f5=ozKJaFbpqrae->OIZO7@@7#Qax{#Sd~(W%0p1?0@G@I5hkJBlo@X zhXVc=N3Qhuf26$D@zw%U;vb{NBi+@(rP>~hM#>dN34&U4BoWUYM`CX&Pu9g>{?w6S zgmEs~6<-mCSig!9-B6bpU_{BNj)W~sF@9_{ZN#qahKffuTeiCXs_3qHZmTPyGEwuw zR@a?)y|~r&VC5`L$yQfgWx8h9R#$jcnr8P_*OaQPF0aDU^6Tkj(%fAS`9`(cS+4S` zuTiz(GrjB0>Sc(<9gW6w*wIWp*B?YWIA)4At~-F?-^`w_x_KD@2{tq69k^<2Y0ssNFekBo#f@{?hI z$FYNg^^;Jlsrb|9G(hTc@-ymYJIMdme6rYlKK^t0YrFZp9g9&{MWon+ktE1nK)f?}O*lpC7~1 z@L31fvM&y{0h!`lj*Ypy=ev^6+<}~j&eXN$cXZwJWlvF+-`=aWkp*;Z|1y3OivN>N z3CmCgqd@(yalebzf2%sE*7KiAxx&s4PF5+BHBzfW|Dp#-ohrWz@xemR7H=nOY<~{o zT6#7f%s9{X8u9m{C_tl1Fmr=ovAFiE9s-D38eGONqg?^#VtjS0Gtx~XL~TtgN5$Le zCX}fAu5%<&^SQow?l_l#XVtk0ct)JZwB@?}{BS&1oF9zmOXs_j@*O)*sD{s?Tp?e5 zjF_*B+KUGI=0R#PvLe3j289{$^{4EXk#`ect_}^OHN$7@o7T{kX`-jQ@-K`)9sAzA z5XXAokcC{2=?Ib#QVczdW?&-NPGem(;lZCeyCS|@p$VI|ui(1^Hd-zCU$e51!3{e` z^C6M=oAC$RY2UBXoXmC|`hJpTQ?@JQhogP|4;1HKv_Fro{QZaRnm?xOd*;U;?558A z#|DUg^*J;3H)bD5>_2?^|9|sawdcW~(!uoJpJ>Q6{WL;z&%}LwJ%d=!{{z!-3tX1Q z7!-W2k!<9@8}HUUJi*oZ=l;~w<9?n9*p{E0`u`tDZKqxpB6$0kb(*`!?MwboG#iS7 zLg{WYwymm2leus;E~+zky-(R)Ynt+@DNRrwSLClxK_LJ7l`*Y*tk>(B@^iG-j$g5H z9rzbvvxgNbnmg?%Y zR6Grz^>;1$tD9;$8(W97f1=y^R~C?d`m0MUbyzd}M;eCYwTs^I&vpsdd&a(%re14< z<#f}Ys5++1Vh(pLybfL3lFGWc-oH*J`{H$K$pkN1WSjSp$m_wRE%RBo__6qH8b{O2 zQ9<)o1@U$g4$Nnk#bWVLjx`8=l_z1#i|n>74J=yoS;CepthZ)K_k%qci(~O_M?5fY z{L#&;5k0VQS(!-FW3^(`u3Ikughf);CKBe^ZAa=;&>ofIDL$cXgnXQDVZyvHVn z{4q4qb~JMC{CT*cauZQUTBLP+c)Sm@!gCG)H6fqzd;%_C0Zn&X*sIxH$IdN*XVmG zvqD+Crb91fO(^T8S*}yIg|gV5?jF5}A=)R$^{G=(s3)I6a#Uaw7}446i1YYf%JnuZ zMK`!N>5ErSjfP?<dg#M}3XwJs#x2X=5#`CmNHsEkq*QmL`c#{7YlYuQ z8FcgI4vJKI_5oH699v7O`5nZ2^;Yf-V+PAmFlb9ntb$XS-`|$H2}vnGvfK-P$|CW= z_tyY<^@QiukHAx|b8k$*DNQR1H=+v9dAaHqta|qYz-s-Qnw^WUiPE8cBr`{Ph+`(M zO)=$be}SsKBNnye({%?LI@lb@tqjbI5w7U1SyjV%%8MI(O;d;c_er$N<@ z_v%B2qu{6!dDMx>4#2eHl2})Xf)@%HeLQcBESs3YusrQ^2xVgn2{Kf07&B!4o_QX4LbMUoAU(5~E*kK#;9D2W}QSNCWcMY)E6lC$FQNAaRtiu7#0`x zj7n)XzT549OZ)kWkzA*I62k^3N*hQ4%+WsC@@?J0{?T}02B&&{5@02<6WgR&x>GsO z3A8~ourme}-UB;h*8H)va%X3DhbB5!d7?9WxZOlj2MumoSz#OS`9l{avAb7fX6 zTN5U}f~yhmuVdLu5k#t$kg_QbLP*@8)Wor_G%^1W$9hJnwzdjVdN%7REF=2g&I}za~NQ_)0Mgx z73ns-`u)L#Zfp?C5|=QYV-us~?;O(-BV}!38Jz<1XD}*pjEi5Lfx1PsD zF-6>VG)C=|J~im9wot7gc~}bCA-8zGs12kTI!^N7V{zS<3iVqH0+z&7DcT;aPcJ`4 z9-NDCgSRw>DrgbE8wG-2;S=3oiHtI>2TRO3ijo+?k@R~b6i17F8bN)>i!jzOM>S+k z_3EwQezAl|BO)+h^rfO)L)O#>GgJsme!K@8&Vm(9BFoU+*H#&y2xsm@gz{h_TTlMb z&xx48p)-o@d<*}aZ&d~S3B*rq7^mtF!C9*Y1a&)`Hl;1(N*HLV2 z(qD-YeB9_#I+e87JK721^3iT(bT1Z5yv*&z25aKlC{Ood@#7gtHSy2-fukx2HmW!? zBJryIsP!YQJud<|qtH#__Ynij$&qnnMusj6_widVbQd5Yv8%n<)xi%!=@MH+`9pNz zZBHVIEp-H*QvO&m3-E;)KPCpPys3!VfkaL-DSTWQS2Ju$qk##{4*b0IKx5d-y{Wc zY1tQjJ~x-SbCD$S^!4~0$e%oHrCTP88Soi2%h4W}%zscFLDdU)8dYDyb4V~okJ>=2 z5~BJt6Lrq|zHCV5pM3>Cx}qnM-Rd!m0Y}yXQ?wg*RUmO^C9u9~%-(Z7WC9 ze(uL&MxuX8sgq<#lNK0Ie5Vx^OOBJcs7|OQl#QtaCR-p>J0fL$OQmv0f7Ypwkkc@M z(QKX}^rYYl`FAT9!BGz|PgT|A&9;iQKZ|;B5AK}FkA};WwW90ghePCHVg(cA7p!V( z96^rBTEUm&(QwZZTV-dJ>WXb;w}UsH)m98U{Bp_>$%sjMT)gM`R=EWNgUBgt0DG85 zcK!gCWFe!Yr(wn2&{_QA*~B{h0+IeG*^a86pCO}?N9L81zkwBK3B7TX6^?1?mjZ-O z<8~01dcC#uD*?ps&+0!%tn>mNB?NQmDT>RXq4lNTBW6vdLRy{0_B_}sTO9%`U^r=d z32#|{0$E=DUez*`2~MC1!QPXll%w8X?hVElONZ%`VXuAc7t zoZ7(Gk)$lIel@W8GZAD5iepM+fnxo$NB4Xjz!XQSzcQxDAAED7ztPiF_Ed;cK9KcF z*(R7;3mTXO3m1~O51|6ND$fy98V_RlF}m*g3AE(b@EYWRtPR|YBxQ*!G&D3Yyf7GN;yTF&^m$UhaoPMt=FoCq5#JS+4@NnGGAbf#CnV9nWEx(M>?nMF8zk!~;ngqQpNn=ui3AP}Vc3sV%y9h4SH0mZ+Ijulzccb)((^a8sdxk)iSbjW$#gf-<7w? zAA%RGM2BM{b70&-D$2MKY@mTC$x#7vU2Fdk6ZDs39Uax3ywGfpwSCH@@2{e^a+pny|w-jgfpXs4{gCUi75xKk6;JcQdp8h z5+05?GSLn_+5ZyLF?2W4FP#SYmr#Cb2tAe}qeM%waC$69k~CfI&=NwXMUD#N`% zr)Z_Q2;vcoZY5z98=FAtCTE2dT$RAss=#u3IW}jYV=Ax4kTxohk75JclWF0l-~sZ? zhSz|#Tg@mof<2{pN3mG#iGdhe-BQ@7u{6+Yw23eUqf%+auA1f$qZwl~1!10JR+KCN zBQLG!fN|f%v-&_HVy9#&I(}5#w4KU}DXimkG58~Be0vU%pLtXIWf@q2AGf9?O8HSB zau*oDScs#l-7CN+U{4GZunT}O_dLLa^$1I4^FmFnLU=fpnT8I*MOu``>Kx)je=S5B z1M>_&u96KD8j6f^%D|5sa&|?DxP$f66c#AA-=Qup=G=ir1LRe32b+*AbrKz44zChs z@($ad+Law!$2Ke_CIl!a&4KR|s@VVO67KmN8a!hv_EEMKDBVZ1{HZrt1Nm3ayQnz| z?eKhn=6NoGmpV|O@gkh&!`5e?lN=%VC2!20$N0YnNYVi5>Bs}Z{AK4XCZlF7P~4-L zf&HL#F|z)anGoY6p(XSpEU$ho=|i1EzW@*z5je!XI9)==L~zdBr?m;Hd9spv`pe>5 zZW7rLxC@>W0y?s8r5>M6eXC(-jkOx;09%!IWZjD2lH_`| z3>r1^?8+o6nBPswNMjua554S1_Iw0VUB%i-C8RRvHXJ{6zI8uUUU~74d zx_LJ$j&j$2FS7WICOX#D#M#Hy>K1}9vwJhJnTSp4nhciQM_A=5xuKs1TTZimBOFYLVQy=T6#FAy{jLJ#p-i@7 zu!EfUUqx-T_-IR;$gf}vl3%7NvB{xtD24H!0dJOF1+PK<^t@E*a3^zFra`#2)a8&W z_7ZHV`64n%-BS_k#G5~DW+qf`HJK7f>1dy~lnQ$4ZpP6Nj?uK>1`g4@iJ*UUb6VFX zln@141vrlJB>4cTH2NQkcy?Z<_-HYF*!dra2h)og_PHCn!XE*`mmL5WTj8oiO=YQ?QT+~1oyyi}hQY=e&cVU%?Q^i> zdEZ9ydk#y{LX5>Q9)^#Z4ns2dkpR^`V}eP#pAEj9#)Zzd63yht@i`1kFLYSw+Fjpx zz4&pcZlrD0!QwZuq#U9Aq`%73_p@jVZMLF@bagWnzohynGvjyA{Ch=Q`#rf&LP3Qa z-+GE7_BA}d-$B9&=7*zF67%u9yS|xp#tQ-4H={KDvSZGyG%lTBvxn$azRMCT2alL}k=A6mcITUz+n7~KCIIa2RkkSN>X)pg^ z`x&e%uy@vA8a#EVj{4o)7QbTZ+fSw5H60r+HW14SlxuU?R89SCC3`L#-y4n`e)gQs zeaL$RXLna=rJBIGfHO{CNP^S_p5j)j=CVQI(}$rk4USpiJi)7sp2re9&^(ZJc<%_R zoBF-{+;C;+JeYiup~A><`Xd9Tlu7wZ%Lm;iXl$o_Ywp5?QQpA^*+q~7f^1gn+5S2~ z=vUv$clscE2r`!-U-?SyAjn+=$@JlnQC`AF0)$$bTI)N$y#0jTm9S?(AZW|>qXY>j z$iAT}q>La}G0~OZ<||b}5c+t$e8UhG=RJaaPLR@}%B1YNex9S8S19LxUk%R? zL?OtV=p(9g6G4gyGJB}<;(TW4_TSsC zu|a@~FX77XMx))&5v(oM`_wfHqLq|gNI(r0d5mJ$gmggaVM@JE#qOopVk$P1VpCKZ zcj9I+P##1yjDX9$`~-4t!^eu)+;?ZAGyRi6c8*C^&X5hlCJTocDq;7s{<-mpmv4YHY69noK~aRW6Ku>s)lKZo;)f7Y2`*ua76V9b zP{)pxCC`D)%umF&XE>_De{;|kS%H9S4cNIk=(v}KvKZ^mG!!iS0Q`zy7lCu!0siPt z<@JTEXIrWbE*NmA3Z-Eo%ghmz_qb{JQuyQ|w3gww(9^U=u((LppgA`=LhvUD*6RO&*BJ5?95!C2zCn0J+OQjdRi%efOSr?e@Ik>n|un;|MjymFK8xJc9oC1$grkGgwKK)LiEPhZElxI7&PA#xl9oG}I2C!_gi7Tfr zs8gOdvHm^Bff&}2p@xcdd%AbL`3m3Ph1@@41+#Q7d;rOJc2OElEM~zTG`xgrCsPZz zT@*EUBUJcyKjE84Sx?!mS=cS0^&bZ3$CMdIB?ttbX!cH*=toD8fJ)*@?O0{e18ktO zVlmT)41=y?Yp_7sxR`aE@g5o}_5mDviefLIfz_8*Aj+SFW;*n=R4<|BJ9nM9?sboP ziFTpIU-oqR4-lWr-_lxr4h;9y={P71L1HFmg~d2%&LSXSTEIR+9J8xf11gi_S-N6e z!t|PnJCzwr*!}dbSc0oTrd>+o5;j&7xj`Ac6gFmHtzuouqQjT&5>sItTk3N=l+vYa z)bN2YIM_V-12V0_JtHVge@GPaixGDXbdV@Ir48Um0mns=uMiDAeo+4)8^tu67AiT* zFmb)Q@Zj!ctVjR`E{Es#>Oy7Qa`u!4-piTgxZBVOkJOq(&n8;~tIjFb3&?R+LT~%$ z)*pTa+&-+aR9W&cd%2y+y?Dv~t@U_Fh8@UC_Z6(HJ%JN1*^j1KKMFB4+d)uiT*0PC z`_SLVSe8T?_Nyo~YbBc~3R!=+WN!)&al${}i9!cgvR^b$E>w2svya;kxhqY&^b-B_ zpX6MdnE3vTyOhVxY=fquR0&(fx>z_WJsgQOJa#YY$gcl+I0d-!@jiiNume6A*1eR~ zN57w7e#}1ly-1Qu38$CVxcGL_aPly@=(7GIp5>>3p~~hGZv(X|PL^v5o6T+Q!*Y>r zd(d}US|W;kH-I=PryQ}csSP9=)NWo6&(jenuzu|qn+UHej##&j=x>fFe-f1#`NtqH zS6OfGZ;rxxvYdG1hXjnbhd!e-ly;A>q`5+#KVGu8goi*}ScB2S)(~!M3DMam0`o8x zb*3>vSH8f1hZJR!gfdp$snOR0cVtpegO8I_>j_?m2d~G}EOsypj*=rM zPFGaz`->dTR#=TyNXz{x=D`|k?rkI&_YX+a22xjKWzqo;bt&oN-wEcFC1X(W`?e^D z9%T#38gzY(rLe)u-H)*xvKnta#9gygXiRvK@`Z+(ZLKXr*IjR2hk$FM>W{ zr4vQxRxa=>6z|BBI~D61)`bXfU&9`1N2o_ggyLU@l%aySwX9mRdEvot*Ru8u5v6$@ zTOYaz_77Gxc7w8RJr0oJZy#LG_69AVg_2pygBCW5V6R%3mEQfW>|l=;FeyiUAYQa> zO?%q`zG-}7z)Ue)2NkfsVT3VTUAEj_zfV!ppHYIcMu57`owR$l# zHQY@;I)_z5C1^R-GFQ3H zhGTXZ-?=u{Wni0mY0?;k$p2GNUbf*}x@@j;%m%|v?uv7*W~TEUYM-qt$9^21Os{Cc_5%=r4fi2v%Q{noNM zqTXPIJ^Zw*ijlGa6VxtBXPls`(RW zBK;;^m{-3Xs)yf`nPvO)I^71?U!WMCU|lUJ%@3`E=-|Eh{xN3;c`q*kMs=tRsI2S? zK=aatk4IeL=cwqiPQK7-{Mt6bj)@sC<2N2FYG!8aAM6K0DK*6d+f8png+K$kWQ5B_ z@0DoF6%Y zo~@<*d+9_%{P|CfVvBKs9T2gHbJ@<4+fbXO{4T{W-dA^Ukj!SV?qaCr#kr^0d-UGAk;QfTd^h>rP<658fGf|o)ghAkb5DcvRxy}f z|BQ01m`xQI0=qfb4h@EJrGu@a_sA!4Uuo$s<$))eqIvRbMdO6K{>2+gFDDxu<$|RB zrg9y)G4iM1P#$!$VV29($yJykLimwgQ1TZ1zZU4+Npo@$=Ee!=6XGYvXMo|@Z$-A) z_qho=HZjukDlT*nKs9vC)PcG(H4B=8)lwTIkaq#qVqXMXK)Sc8`FF1ah@FwH`9pPY z(aP&5UVy^1H9Z=`e;6te=5zE@*jq>I?tY4OS#p3dT6rO<`v0S~lCMFjx(G`Y4OxTe|9n-Ovpz7()cNpUE-FqQA8d3fj9#|6M zYXeFx#iLIRekKeOwSA!V>_-y3SJEkJ^$oZ*akTQ?b^Q?H}o=hDQ7mb zuF;>95|TVVrbwmx3fu}jSe{{ngtGywb-F+~_zc$V=){I+Fe~F7yah9C;fqS&Ex37(^r|hadm@b_ z=*Df3bg-d9tkc!I;|`%u`5j7u`Q8>bs^|CkB{mvY^sfx?Cr}-FD({?sjUQZt+z8;t zJyL*JVewE;#iiA=ILiR`X7iR`{Ni5w4aQmn|W5b;P6r)8!$i58yTq?zJLD^qWh zT|8-D!ka`pDBdL6vhgO-2B$aaw0P16tT$I2h|`V#Jlo1;plNr?#W3?n(KH|Rad>@RgGs+)m+btA{4i!C0A8d{gf0} zaaCQ^PnF-AiInz!e)seH{Qmg;=JQ!=X4cH?z4qE`eb<`DNkaB&wastX+k&XfpeaCefl7fs1UdwC7U(We z_+$sy6sQA`0+a}p3X}yD1eyl49B3=h0ie@Bmx1m8MNDyUkw7s(U4aHnafG;7Rd&aoA z=D+U2C0q-8ufXd~%?ys}ojC>?;UXEqAmCwX?(n+<|FXU(zQPC_u?tsX%DzTS8&ub$U9OOoWv>62UCT9=aD?>Jg?=Pj`% z`OW;H8fmKE;|scBMuZxPJt3mC_k_Wul2)aTR$-Vci7Iup7{C#3fF}?v$n?g0z5Z;D zqc!`<0k@lzYxepUxC7(hgFddtFzNnZt;H!^M!*wvKN=i-AF<=TQb&KsysnP8g)1F> z>pFvh%xt&fEa|<{vAE>!N=LfmnUa)MjxHrLRym%p?R4dH5hazY9Z_xi=X-o3o%um< zhRi^Y(_`7Yi@yN4a}4-=$@{Au3mSFdyq+wX@4|U}+1`R2H*A*lU+oB#v|8hE(q|&L zgiK$@pw&tcns(;0F}Q>$W>`(e-jYr{B_~t9`A5nhALbayFq`R+gIHjj0EKeo!KQ{y$dgMVJ|%}&Kkt4 zp5Q1L7zqBQ2TP-DuRq^iqtLItMT0S%PM3FVrwGnSuuiFVKrlr0hVJqfL~z<~52d;D zAtrQJc5KM`DCn!tvpNbu5d6NM=-hyROieddlvob?n?7QliM`^jMq-^QZr`I`pE&bz zmrg4b^PSc)-4$tHP>nm)7ukd7$GXOrgs*qB3;kXbXLQj2c*M4Y{?BxI^3;D(#yS|R zRvYwxLY@7$tKZf?FCe9fBZ zUhd#1Kg_!AlK*m*HIJ$O{OVJGI|(jc80+L**&Ouf%2r&RqRYdH?O4)B~R^2>7fZ?Tkv^-UOK`J8w+Do#P4AU?7+w zt_$bt92b*s2YsHxWyWW9%TCBkwH1aO*DbM6KWDx>Q0U2a0|XZOUvcLs&IH{aTVfKd zrLhqftXq-f1TU`^3?7(}z+=vpuQ>br@(c3v{DGjmq-B}oh1%AY5heZ09662b6s9$Web~>It#v6ppe-G=qvvi%J%@SiY*(lT zZiIm@5nL1C&ISn<@0w`w8}P`Hb8_JpPqmIVE^7e1%{l9wHmR-Rq34PcM+G=&9FmZR z($G+J6rDg{qe#IixP(6m+k|rAuy9(qBGePRiD}{}(I@7Mi^X!WLOdvbFSe5mDMcD7 z6-cwBCDLD{z0!TjiFurkv+yW92G7I0@IHJ9-@tW90eOu~BGbt%@-|sXJ|KI^A@VnJ zl3XHJL!=gspv`F%?MP$kNb04N={&lGuBPkhHd;;((G&C=dXfH<-lO4iL%D_APL7tb ztjOKv6nT*Bmi_WLdA7Vn-YtJ2pOb%*Yq4l%vVkm@`B(ufW|P^QYyn%wRS^^ywY|1MYind1uNhN~KO0Mp_lz>5z4?;4&D>)iF@G^(qMRIe4OaE}7W@l*PkuOG z#LwX8@+bN4`2XZp)CUbjFQZ~~9^FS`NLU~&5lX?(w}pGcLm^y@6g!E-#F1i942e_4 zKa1{WhNV%47NAT?7hRHv$cR@bUK)X)*Nfi_SZr3JNOZH~5BTdnQY zsclNiLHg$j_t>eU?t7Z-Qg4r)ly)d6>LQ9>U6$4eBoS zbM=h6Nc&2=pxxGL>y34%9&7lGB4dg%-&kg>Fs>Vu%{R?=&G*gCmcmfO-+-qk*Xd1q z2VD9=h=$2^$bl@~%3ESFcxYvm2{CV8{GT`rgR$ou6(@?rU?d|W;$pO(+c zRq`eIihNzZDc_Or$)N{w7^}k~Sbf%zHD!^kHEYW{uoxD{1V)&`4AzY$v!1LsOJf7r zU^bj(L1>MJ;0mxpR>W4Yt8A81uGCT+sPCwo)e5l3TCK5h#E65a7;HYxt9*Apg@2F# znE#X~$N>M(MjrGwT7%w0J45Io{L6%I(Is>Z1%;`?B4NGok#J0?0;j1fwuCGdFE)}o zNfLPfBx#y7Q<^Q!l@>xIESFYFYo!g+CTX*@T`HIMNc*Kj(qZYSbX+5g;{VkQjN!4bGVZit)WNZcB?#T{@c2FGCm6RcnZcf-lJC+>~Y@Blm*4+kX6 z#iOwg2XG-Sf-swer{S4+HlB+Y;w5-FUWwP@4R{mYjJM-*ya(?GygQ7K;^X)vK8?@f zDtrlF!PoIkd;^8_lk_HOWB?fq z&X`4V$!Ovu0a8ec$anzJX=EmuP3Dq?WC>XgV7iuUAe+c$vK<_D57`gEdYBv~#{pbV zle44>AodC%!cB6A+#?T27_9?nTc0+hO=%=;P218?2O2};s6Yu-s6o5YWZIMVrfGBl z9ZZMQESgJ4Qy&e`LRv(}(@At1ok?fYxpX0b^m4kAuB993Cc2q!2e95l_XA)brbp>< zdXk=|XK59^M6Xb81jpro^E>!>{$tci(1hMXfiPWIA#4djY+e%@h??jTTf;OA!U~N1 zb+(l4WQW;BcAGt=G*hO4Ywb}Vs;xCi8?5C)u-(-peTu$Bk1|Z7*qm#wH@Q5Hv)+qn zd?%!%XM`x>N1--E`S;=RSX_xea)B=BpH<6!61#KX^02zkL#Sr-iA+m4D zO_X9R)o}g zT9g*hW<%;(uT^SSwHI`+eq8^9aS#mK+Jek;@I5lD!cY=mdxkhv%oE=NW!HkbyTzXX z#cxUb@K^XMzKg#j0=V!(x|EiIGb-{Q0sa0e|EFA=A=Zm|SaYSd(os<$-6t!#idUJb zgxag3nxcl(UD^=+kUrJ;%E&e+ns1q_0k4mlr_3soyTNhuK>;T}g7@=V_`0YEstq;L zi-H@fq^m-Nm?{nt17f(;Pb!vrK)GRkP)H&q z^=Dg@s*qBoP0*%8+TEhuJ{G)uuD(j&s8?97XFOx3n>prL zunRn0bXY}(hu_D4!e8XC@lj|9Dnpkc@xnLoVjZ!b*k0@fs(HlM#kt}Mv6VDmx*;{g zt#ATB+h@2D!6cMK-XX^bp(@PyAei%fIu@dQ7JZk#4>A1_{ej-493&?vB%(f``(;QS z_hgPe#Tu~YtR3sjWXKTRSqkKbp^zJVkQIvAB=$O6$V%D!Y%@6H9`-5w99;4|y8&)l zS3wF@dMocL?<)sFN~Q9p@*j}#uPHZ_I*>%#shw0)O;%q5pB<>?sDAY=b%pw_`my@G zdQ*L%hHKAhFa8sBYr0h-Iup zR_O~Bu^(^4NAL+8P8tJbZwIhGMy`?Y5a4lRz~Z)aApMZ;r86LRACp^xzb3Ohs8Fd= zqAXX|DP_thV5ieyqi5A7YD)-2q8e(VnyPx#pjxC(Q8%f3)r0C0^^|%`ZLASZ(-O1- zZL;>3wn!`0Hfo!-3h=H0jz+0O9WH zzvu(Zd>h$51k+tMA6TL2glF!sYRo6|V|Wfdht{HvXd8U57Ytu}ZEcLG+mpky1y`$KkVyn^4(9|nW}gRh4e)NiYx z(NB;mghOT24yvJ${Hc6ij$(bGq8$cKHjgb~8^NtASrxm*>L^i)s3a*Fibr`(SqRoD zS3Xl7f;T;{#zVC`M=en=s!g>{nxXa5vLJsH0TRvzyR6hg8?|!n02G;LAna=CPwUN~ zf@`lw>#;fyC8wVE|5EYjEMJM{y`X~SXGHS3!L%va3G<{Wb^AjBnWR9zib{^6eG zHws?}%^>hP10swCkosQyr&w32FS#T^dQ(~>l>v+&l8#9KfRdyG7D9Ld6b3N>7GII` zWR84M_A1kqrs_m>x;jr?s;*c2Y9q8rJqBvu68)lnTfb;*H4m6vs>5<*t_SbtCqS}U z#h3FH{6YQ*|1BWFUA`7-h}xh|cDYrECP78K2$iDkXcs{9-(Z?r0)WK|$wFwjFiI#C zW(teJlXnZB3E#jS-#y`Ju{n%^hqT-SisqN0X!eV*ij&0Y;!1J5xL-Ufo)T}0LtzwC z@KU@A?}X~-8=OM=k|D%NC3!1U$hYNp*=06bX{W}h3b<;XI#w-J*QryqSpfF$0Nj6| z9SCWkYu{=YwI8%RJ*Y3$Kh!@0q&omu_nBS^F?|Z$@tl4^f653L#l|dSj@Oj3w!{#xm9p;@)LSa z5CkfOOd(sy6J`l(g*(E1Axx|*wiN|2M;s#_l8#B=N(}#mml2chpns=r*`L^M_BCs) zJg>A@;uOhFB`+y2!~J4wwU&k;z3$acYv;6^+Dnke7U*mAuk{=HGXP72;jW;}*bVms zw~f|j65KtVGVhsOC=XtFf!4kFA-oJ4#X|5ng-D^XP+zDkgbDZIFZJ9&SKx-~EK~%? z(Ps#L0t7c%ThS)84y{DX&_Xl^%|uhsco<&*c~LGJfd<29dqbM)2DkPE@hAqhN3BtF z@QHe;4&u-~{uY0ozsy(hX=mWRlq-ezXrM$Gt_vlx#LIkr9E%hAbbcT|6tZ3pKZ^JA rd3=x`%NK*YO@W}D#edHyA^|rBj57f7PKjs48{#d|iQzTicE^7K3O*wf From 33afeac10d789e2814e51ecd870e03d2bc361ff8 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Mon, 14 Feb 2022 13:59:41 -0800 Subject: [PATCH 18/34] Fix ZXCC Build Under MacOS - Adding missing include directive. --- Tools/unix/zxcc/zxcbdos.c | 4 ++++ Tools/zxcc/zxcc-src.zip | Bin 70311 -> 70328 bytes Tools/zxcc/zxcc.exe | Bin 96256 -> 96256 bytes Tools/zxcc/zxccdbg.exe | Bin 120320 -> 120320 bytes 4 files changed, 4 insertions(+) diff --git a/Tools/unix/zxcc/zxcbdos.c b/Tools/unix/zxcc/zxcbdos.c index 17466e47..2777f85e 100644 --- a/Tools/unix/zxcc/zxcbdos.c +++ b/Tools/unix/zxcc/zxcbdos.c @@ -2,6 +2,10 @@ #include "zxbdos.h" #include "zxcbdos.h" +#ifndef _WIN32 +#include +#endif + /* Line input */ #ifdef USE_CPMIO diff --git a/Tools/zxcc/zxcc-src.zip b/Tools/zxcc/zxcc-src.zip index 25238d8af7609c967953ff343d0d209deb1f4a31..99e39026acc8b0aeffe5e783a3e63a9a270ce07e 100644 GIT binary patch delta 1405 zcmY+EX;4#F9L3)ayex#UX+btw6=ew$jezHARC|tS!|4}M zARwQktTaxjqpfpW(9zY{bcck*3DL-(rR2FT*|*pOuC)x>7YaW1xTro&28y-#q` z%`>J7loE%7iuxAwFA_$siw3Y6$!j4H_Sjl+dWJkMOC>9?wE6;WjpaW5Wn?Zmx{15& zLaw4^y07;XZCm6skm{!vZz}O@Y;nD?gIQ``D5qGsw2!wB4Hm~d^%ihcs4~UT+Pr)X zlSqFLK1mtwgM{;^YvgyQ`V6I+6O!NG4o?tzoM)4j4P%xc02N`j*| z$K|iHdeJ}BwahMdpz?q*M`ks-d2f~dCHtsyiJkx2*q8ohQSIK##~wTnNfr?w$)3`B z{KbA zqH~-HS-J&(0!ZJm_1X`+l&%mwX>#!`no5r%kVfJ*O3rlcxqZ`H*4en96mHDE7AO^6 z3CoL5wf?rFp4<4fbHIa_6!ME^>o#fPALSLeNLpykko?_txv!8Z$X{J$d}rN<_1en8 z^|^1#(-c)~JHdNtcU`atGmYLhTlNtrtCc7FwDt4GKf1*zi8$wIr{b0F6B!0d{lLv` zWlrm!@4Q?)(^#3*Lv&UwFg4xez9v41v!6C%GseHCx*PA+W^TEo2wN!Wv7yx8K*X`VWq(a_C{w z)Y9BsnP}Bd-9{_#-=(TZ+^-Ox<0A37)vX;;{;x@MS<}-;%B8L7gMnE;yL)WM7`9J+ zbkFEUw&Fm^p`*gR0k8a*dUUEi`j;EzKK_nb#12G*Ge%vh_4k*A;}SAkge9_rk40Uh z$tjGi3lWdRW-Na1$LvDGh}A41!VJ~Z#~e(+qT9`XW_Y1q&wf#BvE3+$M)?NEZ}wx= zD2PC>HZh@Ujt7yb)tjj&TI>iO?3g#S;z8^@(g&dXOyKp2AlB>V977oqQec@I@Oa5BdRnF1TA(^ht8DB-oG&o8E!#WUV#w|Lx|lr z;V>fG5T^MmC*eZFI(2tqEi{Bsz&6xkL;*3M0$8Zi&$_;oI#dPd#+XJBzm$|4!H6#^ zFow8RJp;Y55M3iz(AB!?%5I5>Y1;{yp#bNLEQF5`5&8eqguO5Z%PIGsD|ny%4ghAD zm;gFZV?ids9#xcELM2hB1YtK!fGxTt4uvr_I%O9&X#(u#@4?m-(48{=`TWjtsqqGg zJ&Z#TfGk2jnfV+Ehjn;)Yv5t2(1=6Fuv?~Z_ME-$2AZJ+7GrobnD{W*2AbT=pi+eG dfy&bVwuzq2o8Jb->yBOuzjO+M*rEXb{R;u~VzmGO delta 1428 zcmY+EdpJ~i7{||iq=ZhxJ)zKPD(60k|FmkYKCGWTPn4u zH06HlB4Kuw)Q(c*lF22>8cZ0H(h_So_BZK|?K%H^&i8r0@B4kvd7ig2A6uA@EzNHc zFTTj;CcSh!@(u$*y*LOWKoAsr!2id9{gF)ne6F|0(oK3IN#b1CaW8>^PN}O=)^9g4 zlJDdPf{fZu{Sj4gW&zHyODPzU-TVeI-#2;rzB55ILkQh zse%#%y~L=M*Ux&hq!IG?RGzs!)I!{Ft6?zgu-*CPnVBc(k4NfNO!FJXZ%t~V3utq5J6+H=n+6Z6hLoc={6|<2KyR+Z~TyT4xnWXPd z3vT}^jwn$r3`wO~b=Wc{6WWs_oUp?Yeiy=4Hq!PNKV9e=*g?7*;ApR3lykPIUydjQ z876L&?3h>2ELT`G9U5FOetE7uBi!a&SednqpratIP|&L@p#Hg>guSfXXAF_wP;T0Y zh~Dum`5=pSLO#l?F0rlcoQ$P-QF+qD8|jW_o)ulP%HY3mQu5M_m7@}bt)6gGXM|f` zi(k~lnR`_Ke4yTgv#gjrR?}1xhpS@8DJh}OveSQFnG!{FZirt7= z!Z&WCUp^Y@W?&b%YNqR}gw)9`astW;Vh3N~n6_U1CKJmh9_<+)m(DId;b6ple7xi# z>lf>E3#y?-X8nMeC;s{}#ij7*_=7Uet?qS}NzI!*gg&b2ol|Aie0$f0!;@C&udZ&B z@`^AmAy|{vmd!J|(am~e_s(Q)Y}7a0-CH$g6qUW(G>4azE7fzSa&N{CcG0JBU-k>u z2K})-#L>m8llA@*=lWqLpPOgn)nl2W`&L~L$7M!7*LF!?G+x_Vl$LDRw~cViE_~Qc zPm8gn_+EK!Yrz_%!ES4W8Vy5WJ`$7CxqS$2Mqn<2cmFqBjhbn}-y=iE3KG=l5iNKZ z(k<9i*M_RJVDC@pgoAe@b2HtcYBV1Q^N^7SS(qA~!vR}%+AzSKc%b5YPJ(6?cz6dg zSThP#9Rk3RBpOhK8qD+m2Vflm=98M<rt=Itivb6!OyRTWOKpRZ6DbE87VaPyT z%!mT2HyPfJTxtCQU^yA)APj68Kq3X;yvf`LMgBHd*ur*wP?$Cj0$XI(V zP!0jb#JcU{rSfO`6CoOC1wk;h7(V zKUw$w-#Vjf7w!eDH8d5NApwP$i3zk?RQU{9G>%!J97qBom pnE@Y9=4TCk9V`btK|@*T{QCUatWWDBTAI9c@FbBTNE?B{+ken`Zb|?E diff --git a/Tools/zxcc/zxcc.exe b/Tools/zxcc/zxcc.exe index a66b00537cad6bb7802f4422c18217a63ba23e26..cdd06094d52e5bbf48a5f5ef939250643cf86e5e 100644 GIT binary patch delta 18 ZcmZqpz}oPEbwUSI@wvvXtzC>|| Date: Tue, 15 Feb 2022 15:20:33 -0800 Subject: [PATCH 19/34] Improve Z280 DMA Memory Copy The Z280 interbank memory copy uses DMA and did not properly handle scenarios where the source or destination memory range crossed over the banked/common memory boundary. It added a bunch of code, but it is fixed now. This seems to be required by CP/M 3. --- Source/HBIOS/hbios.asm | 175 ++++++++++++++++++++++++++++++++++++++++- Source/ver.inc | 2 +- Source/ver.lib | 2 +- 3 files changed, 176 insertions(+), 3 deletions(-) diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index 30c8349c..9336f63c 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -561,7 +561,7 @@ HBX_MMA .DB 0 ; TEMPORARY STORAGE FOR REG A HBX_BNKCPY: #IF (MEMMGR == MM_Z280) .DB $ED,$71 ; SC - .DW Z280_BNKCPY ; SC PARAMETER + .DW Z280_BNKCPYX ; SC PARAMETER RET #ELSE #IF (CPUFAM == CPU_Z280) @@ -2600,6 +2600,71 @@ HB_WDZ: INITSYS3: CALL PRTSUM ; PRINT UNIT/DEVICE SUMMARY TABLE ; +#IF 0 + CALL NEWLINE + CALL NEWLINE + CALL NEWLINE + + ; SRC & DEST BELOW BND + CALL NEWLINE + LD HL,$4000 + LD DE,$5000 + LD BC,$3000 + CALL NEWLINE + CALL REGDMP + CALL Z280_BNKCPYX + + ; SRC & DEST ABOVE BND + CALL NEWLINE + LD HL,$8000 + LD DE,$9000 + LD BC,$1000 + CALL NEWLINE + CALL REGDMP + CALL Z280_BNKCPYX + + ; SRC CROSSOVER + CALL NEWLINE + LD HL,$7000 + LD DE,$9000 + LD BC,$2000 + CALL NEWLINE + CALL REGDMP + CALL Z280_BNKCPYX + + ; DEST CROSSOVER + CALL NEWLINE + LD HL,$9000 + LD DE,$7000 + LD BC,$2000 + CALL NEWLINE + CALL REGDMP + CALL Z280_BNKCPYX + + ; DOUBLE CROSSOVER + CALL NEWLINE + LD HL,$7800 + LD DE,$7000 + LD BC,$2000 + CALL NEWLINE + CALL REGDMP + CALL Z280_BNKCPYX + + ; DOUBLE CROSSOVER SINGLE BYTES + CALL NEWLINE + LD HL,$7FFE + LD DE,$7FFF + LD BC,$0500 + CALL NEWLINE + CALL REGDMP + CALL Z280_BNKCPYX + + CALL NEWLINE + CALL NEWLINE + CALL NEWLINE +; +#ENDIF +; INITSYS4: ; #IF (MEMMGR == MM_Z280) @@ -5209,8 +5274,115 @@ Z280_BNKSEL_LEN .EQU $ - Z280_BNKSEL ; ; Z280 BANK COPY (CALLED FROM PROXY) ; +; USE Z280 PHYSICAL MEMORY DMA COPY TO PERFORM AN INTERBANK COPY. +; COPY FROM (HB_SRCBNK):(HL) TO (HB_DSTBNK):(DE) FOR BC BYTES. BOTH +; HB_SRCBNK AND HB_DSTBNK MUST BE INITIALIZED PRIOR TO CALLING THIS +; ROUTINE. +; +; ADDRESSES ARE TRANSLATED FROM LOGICAL (Z80) TO PHYSICAL (Z280) TO +; SETUP THE DMA COPY PARAMETERS. IF THE SOURCE OR DESTINATION RANGE +; CROSSES OVER THE BANKED/COMMON BOUNDARY AT $8000, THEN SPECIAL STEPS +; MUST BE TAKEN BECAUSE THE BANKED AND COMMON AEAS ARE PROBABLY NOT +; SEQUENTIALLY LOCATED IN PHYSICAL MEMORY. TWO ENTRY POINTS ARE +; PROVIDED. Z280_BNKCPY IS MUCH FASTER, BUT DOES NOT ACCOUNT FOR THE +; COPY RANGES CROSSING OVER THE BANKED/COMMON BOUNDARY (WORKS GREAT +; FOR ANY COPY KNOWN TO STAY WITHIN IT'S OWN AREA). Z280_BNKCPYX +; WILL HANDLE COPIES WHERE THE SOURCE AND/OR DESTINATION RANGES +; CROSS OVER THE BANKED/COMMON MEMORY BOUNDARY. IT DOES THIS BY +; BREAKING UP THE COPY REQUESTS INTO MULTIPLE REQUESTS THAT ALL FIT +; WITHIN A SINGLE BANKED/COMMON MEMORY SEGMENT AND CALLING Z280_BNKCPY +; ITERATIVELY UNTIL THE COPY IS COMPLETE. +; +; THERE IS ESSENTIALLY NO PROTECTION FOR CALLING THESE ROUTINES WITH +; INVALID PARAMETERS. FOR EXAMPLE, A REQUEST TO COPY $2000 BYTES +; STARTING AT $F000 EXCEEDS THE SIZE OF THE Z80 MEMORY SPACES AND +; RESULTS IN UNDEFINED BEHAVIOR. +; +; THE COPY IS ALWAYS DONE FROM START TO END. IF THE SOURCE AND +; DESTINATION RANGES OVERLAP, THEN YOU MUST TAKE THIS INTO ACCOUNT. +; +; THE ROUTINE FUNCTIONS LOGICALLY LIKE THE Z80 LDIR INSTRUCTION. ON +; RETURN THE SOURCE (HL) AND DESTINATION (DE) REGISTERS WILL BE LEFT +; POINTING TO THE NEXT BYTE THAT WOULD BE COPIED IF THE COPY ROUTINE +; CONTINUED. BC WILL BE 0. AF IS UNDEFINED. +; #IF (MEMMGR == MM_Z280) ; +; ADJUST THE LENGTH OF THE COPY SUCH THAT BOTH THE SOURCE AND +; DESTINATION RANGES DO NOT CROSS OVER THE BANKED/COMMON MEMORY +; BOUNDARY. CALL Z280_BNKCPY TO DO AS MANY ITERATIONS AS NEEDED TO +; COMPLETE THE COPY. +; +; +Z280_BNKCPYX: + LD (Z280_BNKCPY_LEN),BC ; SAVE LENGTH +; + CALL Z280_BNKCPY_XOVER ; ADJUST FOR XOVER AS NEEDED + EX DE,HL ; SWAP SOURCE/DEST + CALL Z280_BNKCPY_XOVER ; ADJUST FOR XOVER AS NEEDED + EX DE,HL ; SWAP BACK +; + ; DO THE WORK, SAVE THE LEN OF THIS ITERATION + PUSH BC ; SAVE ITER LENGTH + CALL Z280_BNKCPY ; DO THE WORK +; + ;;; *DEBUG* SIMULATE CALL TO Z280_BNKCPY + ;;CALL NEWLINE + ;;CALL REGDMP ; *DEBUG* + ;;ADD HL,BC ; INCREMENT SRC ADR BY COUNT + ;;EX DE,HL ; SWAP + ;;ADD HL,BC ; INCREMENT DST ADR BY COUNT + ;;EX DE,HL ; SWAP BACK + ;;LD BC,0 ; COUNT IS NOW ZERO + ;;; END *DEBUG* +; + POP BC ; RECOVER ITER LENGTH +; + ; ACCUNT FOR WORK ACTUALLY PERFORMED + PUSH HL ; SAVE SOURCE ADR + LD HL,(Z280_BNKCPY_LEN) ; GET PENDING LENGTH + OR A ; CLEAR CARRY + SBC HL,BC ; SUBTRACT WHAT WE DID + PUSH HL ; MOVE NEW PENDING LEN + POP BC ; TO BC + POP HL ; RECOVER SOURCE ADR +; + ; SEE IF WE NEED TO ITERATE + LD A,B ; IS LENGTH + OR C ; ... NOW ZERO? + RET Z ; IF SO, ALL DONE + JR Z280_BNKCPYX ; ELSE ITERATE UNTIL DONE +; +Z280_BNKCPY_LEN .DW 0 ; TEMP STORAGE FOR BC +; +Z280_BNKCPY_XOVER: + ; DETECT XOVER IN RANGE AND ADJUST COPY LEN IF SO + ; HL=START, BC=LEN + ; BC IS REDUCED AS NEEDED TO AVOID XOVER + BIT 7,H ; START ABOVE 32K? + RET NZ ; YES, NO XOVER + PUSH HL ; SAVE START ADR + ADD HL,BC ; ADD COPY LEN + DEC HL ; CONVERT TO "LAST" BYTE OF RANGE + BIT 7,H ; ABOVE 32K? + POP HL ; RESTORE HL + RET Z ; IF NOT, NO XOVER +; + ; START IS BELOW 32K, END IS OVER 32K, XOVER IN SOURCE! + ; REDUCE LENGTH TO AVOID IT + ; COMPUTE (32K - START) FOR NEW LEN + PUSH DE ; SAVE DEST (DE) + PUSH HL ; SAVE START (HL) + LD DE,$8000 + EX DE,HL ; DE=START, HL=32K + OR A ; CLEAR CARRY + SBC HL,DE ; HL = NEW LEN + PUSH HL ; MOVE NEW LEN + POP BC ; ... TO BC + POP HL ; RECOVER START + POP DE ; RECOVER DEST + RET ; RETURN +; Z280_BNKCPY: ; Z280 MEMORY TO MEMORY DMA ; USE FLOW THROUGH MODE @@ -5324,6 +5496,7 @@ Z2DMAADR2: INC C ; BUMP TO NEXT REG ; RET +; #ENDIF ; ; Z280 SYSCALL VECTOR ENTRY POINT. TAKES STACK PARAMETER AS A BRANCH diff --git a/Source/ver.inc b/Source/ver.inc index fd73e28a..d6117e2a 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,4 +2,4 @@ #DEFINE RMN 1 #DEFINE RUP 1 #DEFINE RTP 0 -#DEFINE BIOSVER "3.1.1-pre.155" +#DEFINE BIOSVER "3.1.1-pre.156" diff --git a/Source/ver.lib b/Source/ver.lib index c16db76f..e13f6c1b 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 1 rup equ 1 rtp equ 0 biosver macro - db "3.1.1-pre.155" + db "3.1.1-pre.156" endm From bf965c2604d06f00d77a7658be541bf2a705d558 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Thu, 17 Feb 2022 11:34:31 -0800 Subject: [PATCH 20/34] Minor Z280 Fixes - Fixed the ROM VERIFY functionality on Z280. It was indicating errors incorrectly. - Revised the way that ZZRCC is built to remove a bunch of complexity that was causing issues. An implication of this is that ZZRCC now treats the data loaded from the CF Card as a ROM disk instead of a RAM disk. - Updated the assemblers to handle some more Z280 instructions used in HBIOS. - When building ZZRCC, checks have been added to ensure the ROM image is exactly 256K. The build defaults to 512K and that causes the ZZRCC disk image to be corrupted. This will stop the build if the user fails to specify a 256K ROM size. --- Source/HBIOS/Config/RCZ280_nat_zzr.asm | 11 ++-- Source/HBIOS/cfg_dyno.asm | 3 +- Source/HBIOS/cfg_ezz80.asm | 3 +- Source/HBIOS/cfg_master.asm | 3 +- Source/HBIOS/cfg_mbc.asm | 3 +- Source/HBIOS/cfg_mk4.asm | 3 +- Source/HBIOS/cfg_n8.asm | 3 +- Source/HBIOS/cfg_rcz180.asm | 3 +- Source/HBIOS/cfg_rcz280.asm | 3 +- Source/HBIOS/cfg_rcz80.asm | 3 +- Source/HBIOS/cfg_sbc.asm | 3 +- Source/HBIOS/cfg_scz180.asm | 3 +- Source/HBIOS/cfg_una.asm | 2 - Source/HBIOS/cfg_zeta.asm | 3 +- Source/HBIOS/cfg_zeta2.asm | 3 +- Source/HBIOS/hbios.asm | 73 +++++++++++++++++--------- Source/HBIOS/std.asm | 34 +++++++++--- Source/ver.inc | 2 +- Source/ver.lib | 2 +- Tools/tasm32/TASM280.TAB | 10 +++- Tools/unix/uz80as/z80.c | 7 +++ 21 files changed, 111 insertions(+), 69 deletions(-) diff --git a/Source/HBIOS/Config/RCZ280_nat_zzr.asm b/Source/HBIOS/Config/RCZ280_nat_zzr.asm index 71b08a4b..4fc7db32 100644 --- a/Source/HBIOS/Config/RCZ280_nat_zzr.asm +++ b/Source/HBIOS/Config/RCZ280_nat_zzr.asm @@ -30,14 +30,13 @@ ; CPUOSC .SET 29491200 ; CPU OSC FREQ IN MHZ ; -RAMSIZE .SET 384 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) -PLT_RAM_R .SET 128 ; RESERVE FIRST N KB OF RAM (USUALLY 0) -PLT_ROM_R .SET 0 ; RESERVE FIRST N KB OR ROM (USUALLY 0) +RAMSIZE .SET 256 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMSIZE_CHK .SET 256 ; ROMSIZE VALUE VEREIFICATION (0=DISABLED) ; -RAMLOC .SET 23 ; START OF RAM AS POWER OF 2 (2^N) IN PHYSICAL ADDRESS SPACE +RAMLOC .SET 18 ; START OF RAM AS POWER OF 2 (2^N) IN PHYSICAL ADDRESS SPACE RAMBIAS .SET (1 << (RAMLOC - 10)) ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE ; -MDROM .SET FALSE ; MD: ENABLE ROM DISK -MDRAM .SET TRUE ; MD: ENABLE RAM DISK +MDROM .SET TRUE ; MD: ENABLE ROM DISK +MDRAM .SET FALSE ; MD: ENABLE RAM DISK ; Z2U0HFC .SET TRUE ; Z2U 0: ENABLE HARDWARE FLOW CONTROL diff --git a/Source/HBIOS/cfg_dyno.asm b/Source/HBIOS/cfg_dyno.asm index be14562c..c0b466ee 100644 --- a/Source/HBIOS/cfg_dyno.asm +++ b/Source/HBIOS/cfg_dyno.asm @@ -32,8 +32,7 @@ INTMODE .EQU 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) DEFSERCFG .EQU SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG (SEE STD.ASM) ; RAMSIZE .EQU 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) -PLT_RAM_R .EQU 0 ; RESERVE FIRST N KB OF RAM (USUALLY 0) -PLT_ROM_R .EQU 0 ; RESERVE FIRST N KB OR ROM (USUALLY 0) +ROMSIZE_CHK .EQU 0 ; ROMSIZE VALUE VEREIFICATION (0=DISABLED) MEMMGR .EQU MM_Z180 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC] RAMLOC .EQU 19 ; START OF RAM AS POWER OF 2 (2^N) IN PHYSICAL ADDRESS SPACE RAMBIAS .EQU (1 << (RAMLOC - 10)) ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE diff --git a/Source/HBIOS/cfg_ezz80.asm b/Source/HBIOS/cfg_ezz80.asm index d18bfb42..1ac317dc 100644 --- a/Source/HBIOS/cfg_ezz80.asm +++ b/Source/HBIOS/cfg_ezz80.asm @@ -32,8 +32,7 @@ INTMODE .EQU 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) DEFSERCFG .EQU SER_115200_8N1 ; DEFAULT SERIAL LINE CONFIG (SEE STD.ASM) ; RAMSIZE .EQU 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) -PLT_RAM_R .EQU 0 ; RESERVE FIRST N KB OF RAM (USUALLY 0) -PLT_ROM_R .EQU 0 ; RESERVE FIRST N KB OR ROM (USUALLY 0) +ROMSIZE_CHK .EQU 0 ; ROMSIZE VALUE VEREIFICATION (0=DISABLED) MEMMGR .EQU MM_Z2 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC] MPGSEL_0 .EQU $78 ; Z2 MEM MGR BANK 0 PAGE SELECT REG (WRITE ONLY) MPGSEL_1 .EQU $79 ; Z2 MEM MGR BANK 1 PAGE SELECT REG (WRITE ONLY) diff --git a/Source/HBIOS/cfg_master.asm b/Source/HBIOS/cfg_master.asm index b666088c..a507dee1 100644 --- a/Source/HBIOS/cfg_master.asm +++ b/Source/HBIOS/cfg_master.asm @@ -29,8 +29,7 @@ INTMODE .EQU 0 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) DEFSERCFG .EQU SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG (SEE STD.ASM) ; RAMSIZE .EQU 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) -PLT_RAM_R .EQU 0 ; RESERVE FIRST N KB OF RAM (USUALLY 0) -PLT_ROM_R .EQU 0 ; RESERVE FIRST N KB OR ROM (USUALLY 0) +ROMSIZE_CHK .EQU 0 ; ROMSIZE VALUE VEREIFICATION (0=DISABLED) MEMMGR .EQU MM_NONE ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC] RAMLOC .EQU 19 ; START OF RAM AS POWER OF 2 (2^N) IN PHYSICAL ADDRESS SPACE RAMBIAS .EQU (1 << (RAMLOC - 10)) ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE diff --git a/Source/HBIOS/cfg_mbc.asm b/Source/HBIOS/cfg_mbc.asm index 74b64d92..2824bd83 100644 --- a/Source/HBIOS/cfg_mbc.asm +++ b/Source/HBIOS/cfg_mbc.asm @@ -32,8 +32,7 @@ INTMODE .EQU 0 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) DEFSERCFG .EQU SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG (SEE STD.ASM) ; RAMSIZE .EQU 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) -PLT_RAM_R .EQU 0 ; RESERVE FIRST N KB OF RAM (USUALLY 0) -PLT_ROM_R .EQU 0 ; RESERVE FIRST N KB OR ROM (USUALLY 0) +ROMSIZE_CHK .EQU 0 ; ROMSIZE VALUE VEREIFICATION (0=DISABLED) MEMMGR .EQU MM_MBC ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC] MPCL_RAM .EQU $78 ; SBC MEM MGR RAM PAGE SELECT REG (WRITE ONLY) MPCL_ROM .EQU $7C ; SBC MEM MGR ROM PAGE SELECT REG (WRITE ONLY) diff --git a/Source/HBIOS/cfg_mk4.asm b/Source/HBIOS/cfg_mk4.asm index 01aa44fb..1a4910bd 100644 --- a/Source/HBIOS/cfg_mk4.asm +++ b/Source/HBIOS/cfg_mk4.asm @@ -32,8 +32,7 @@ INTMODE .EQU 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) DEFSERCFG .EQU SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG (SEE STD.ASM) ; RAMSIZE .EQU 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) -PLT_RAM_R .EQU 0 ; RESERVE FIRST N KB OF RAM (USUALLY 0) -PLT_ROM_R .EQU 0 ; RESERVE FIRST N KB OR ROM (USUALLY 0) +ROMSIZE_CHK .EQU 0 ; ROMSIZE VALUE VEREIFICATION (0=DISABLED) MEMMGR .EQU MM_Z180 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC] RAMLOC .EQU 19 ; START OF RAM AS POWER OF 2 (2^N) IN PHYSICAL ADDRESS SPACE RAMBIAS .EQU (1 << (RAMLOC - 10)) ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE diff --git a/Source/HBIOS/cfg_n8.asm b/Source/HBIOS/cfg_n8.asm index f4bcf1b2..a867f64b 100644 --- a/Source/HBIOS/cfg_n8.asm +++ b/Source/HBIOS/cfg_n8.asm @@ -32,8 +32,7 @@ INTMODE .EQU 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) DEFSERCFG .EQU SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG (SEE STD.ASM) ; RAMSIZE .EQU 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) -PLT_RAM_R .EQU 0 ; RESERVE FIRST N KB OF RAM (USUALLY 0) -PLT_ROM_R .EQU 0 ; RESERVE FIRST N KB OR ROM (USUALLY 0) +ROMSIZE_CHK .EQU 0 ; ROMSIZE VALUE VEREIFICATION (0=DISABLED) MEMMGR .EQU MM_N8 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC] RAMBIAS .EQU 0 ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE RAMLOC .EQU 0 ; START OF RAM AS POWER OF 2 (2^N) IN PHYSICAL ADDRESS SPACE diff --git a/Source/HBIOS/cfg_rcz180.asm b/Source/HBIOS/cfg_rcz180.asm index 2a5a8f25..d01e14e6 100644 --- a/Source/HBIOS/cfg_rcz180.asm +++ b/Source/HBIOS/cfg_rcz180.asm @@ -32,8 +32,7 @@ INTMODE .EQU 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) DEFSERCFG .EQU SER_115200_8N1 ; DEFAULT SERIAL LINE CONFIG (SEE STD.ASM) ; RAMSIZE .EQU 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) -PLT_RAM_R .EQU 0 ; RESERVE FIRST N KB OF RAM (USUALLY 0) -PLT_ROM_R .EQU 0 ; RESERVE FIRST N KB OR ROM (USUALLY 0) +ROMSIZE_CHK .EQU 0 ; ROMSIZE VALUE VEREIFICATION (0=DISABLED) MEMMGR .EQU MM_Z180 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC] RAMLOC .EQU 19 ; START OF RAM AS POWER OF 2 (2^N) IN PHYSICAL ADDRESS SPACE RAMBIAS .EQU (1 << (RAMLOC - 10)) ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE diff --git a/Source/HBIOS/cfg_rcz280.asm b/Source/HBIOS/cfg_rcz280.asm index a13b1308..5430ca21 100644 --- a/Source/HBIOS/cfg_rcz280.asm +++ b/Source/HBIOS/cfg_rcz280.asm @@ -32,8 +32,7 @@ INTMODE .EQU 0 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) DEFSERCFG .EQU SER_115200_8N1 ; DEFAULT SERIAL LINE CONFIG (SEE STD.ASM) ; RAMSIZE .EQU 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) -PLT_RAM_R .EQU 0 ; RESERVE FIRST N KB OF RAM (USUALLY 0) -PLT_ROM_R .EQU 0 ; RESERVE FIRST N KB OR ROM (USUALLY 0) +ROMSIZE_CHK .EQU 0 ; ROMSIZE VALUE VEREIFICATION (0=DISABLED) MEMMGR .EQU MM_Z2 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC] RAMLOC .EQU 19 ; START OF RAM AS POWER OF 2 (2^N) IN PHYSICAL ADDRESS SPACE RAMBIAS .EQU (1 << (RAMLOC - 10)) ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE diff --git a/Source/HBIOS/cfg_rcz80.asm b/Source/HBIOS/cfg_rcz80.asm index a6d411a2..19fbb10c 100644 --- a/Source/HBIOS/cfg_rcz80.asm +++ b/Source/HBIOS/cfg_rcz80.asm @@ -32,8 +32,7 @@ INTMODE .EQU 1 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) DEFSERCFG .EQU SER_115200_8N1 ; DEFAULT SERIAL LINE CONFIG (SEE STD.ASM) ; RAMSIZE .EQU 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) -PLT_RAM_R .EQU 0 ; RESERVE FIRST N KB OF RAM (USUALLY 0) -PLT_ROM_R .EQU 0 ; RESERVE FIRST N KB OR ROM (USUALLY 0) +ROMSIZE_CHK .EQU 0 ; ROMSIZE VALUE VEREIFICATION (0=DISABLED) MEMMGR .EQU MM_Z2 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC] MPGSEL_0 .EQU $78 ; Z2 MEM MGR BANK 0 PAGE SELECT REG (WRITE ONLY) MPGSEL_1 .EQU $79 ; Z2 MEM MGR BANK 1 PAGE SELECT REG (WRITE ONLY) diff --git a/Source/HBIOS/cfg_sbc.asm b/Source/HBIOS/cfg_sbc.asm index f71d5203..95ee53ad 100644 --- a/Source/HBIOS/cfg_sbc.asm +++ b/Source/HBIOS/cfg_sbc.asm @@ -32,8 +32,7 @@ INTMODE .EQU 0 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) DEFSERCFG .EQU SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG (SEE STD.ASM) ; RAMSIZE .EQU 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) -PLT_RAM_R .EQU 0 ; RESERVE FIRST N KB OF RAM (USUALLY 0) -PLT_ROM_R .EQU 0 ; RESERVE FIRST N KB OR ROM (USUALLY 0) +ROMSIZE_CHK .EQU 0 ; ROMSIZE VALUE VEREIFICATION (0=DISABLED) MEMMGR .EQU MM_SBC ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC] MPCL_RAM .EQU $78 ; SBC MEM MGR RAM PAGE SELECT REG (WRITE ONLY) MPCL_ROM .EQU $7C ; SBC MEM MGR ROM PAGE SELECT REG (WRITE ONLY) diff --git a/Source/HBIOS/cfg_scz180.asm b/Source/HBIOS/cfg_scz180.asm index 1698252b..6505fad7 100644 --- a/Source/HBIOS/cfg_scz180.asm +++ b/Source/HBIOS/cfg_scz180.asm @@ -32,8 +32,7 @@ INTMODE .EQU 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) DEFSERCFG .EQU SER_115200_8N1 ; DEFAULT SERIAL LINE CONFIG (SEE STD.ASM) ; RAMSIZE .EQU 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) -PLT_RAM_R .EQU 0 ; RESERVE FIRST N KB OF RAM (USUALLY 0) -PLT_ROM_R .EQU 0 ; RESERVE FIRST N KB OR ROM (USUALLY 0) +ROMSIZE_CHK .EQU 0 ; ROMSIZE VALUE VEREIFICATION (0=DISABLED) MEMMGR .EQU MM_Z180 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC] RAMLOC .EQU 19 ; START OF RAM AS POWER OF 2 (2^N) IN PHYSICAL ADDRESS SPACE RAMBIAS .EQU (1 << (RAMLOC - 10)) ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE diff --git a/Source/HBIOS/cfg_una.asm b/Source/HBIOS/cfg_una.asm index 408e0fb6..9d0e2af5 100644 --- a/Source/HBIOS/cfg_una.asm +++ b/Source/HBIOS/cfg_una.asm @@ -26,8 +26,6 @@ CPUOSC .EQU 18432000 ; CPU OSC FREQ IN MHZ INTMODE .EQU 0 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .EQU 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) -PLT_RAM_R .EQU 0 ; RESERVE FIRST N KB OF RAM (USUALLY 0) -PLT_ROM_R .EQU 0 ; RESERVE FIRST N KB OR ROM (USUALLY 0) ; RTCIO .EQU $70 ; RTC LATCH REGISTER ADR ; diff --git a/Source/HBIOS/cfg_zeta.asm b/Source/HBIOS/cfg_zeta.asm index bcd7c7f4..6deb725a 100644 --- a/Source/HBIOS/cfg_zeta.asm +++ b/Source/HBIOS/cfg_zeta.asm @@ -32,8 +32,7 @@ INTMODE .EQU 0 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) DEFSERCFG .EQU SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG (SEE STD.ASM) ; RAMSIZE .EQU 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) -PLT_RAM_R .EQU 0 ; RESERVE FIRST N KB OF RAM (USUALLY 0) -PLT_ROM_R .EQU 0 ; RESERVE FIRST N KB OR ROM (USUALLY 0) +ROMSIZE_CHK .EQU 0 ; ROMSIZE VALUE VEREIFICATION (0=DISABLED) MEMMGR .EQU MM_SBC ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC] MPCL_RAM .EQU $78 ; SBC MEM MGR RAM PAGE SELECT REG (WRITE ONLY) MPCL_ROM .EQU $7C ; SBC MEM MGR ROM PAGE SELECT REG (WRITE ONLY) diff --git a/Source/HBIOS/cfg_zeta2.asm b/Source/HBIOS/cfg_zeta2.asm index acff03b4..9778f105 100644 --- a/Source/HBIOS/cfg_zeta2.asm +++ b/Source/HBIOS/cfg_zeta2.asm @@ -32,8 +32,7 @@ INTMODE .EQU 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) DEFSERCFG .EQU SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG (SEE STD.ASM) ; RAMSIZE .EQU 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) -PLT_RAM_R .EQU 0 ; RESERVE FIRST N KB OF RAM (USUALLY 0) -PLT_ROM_R .EQU 0 ; RESERVE FIRST N KB OR ROM (USUALLY 0) +ROMSIZE_CHK .EQU 0 ; ROMSIZE VALUE VEREIFICATION (0=DISABLED) MEMMGR .EQU MM_Z2 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC] MPGSEL_0 .EQU $78 ; Z2 MEM MGR BANK 0 PAGE SELECT REG (WRITE ONLY) MPGSEL_1 .EQU $79 ; Z2 MEM MGR BANK 1 PAGE SELECT REG (WRITE ONLY) diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index 9336f63c..bd4e40a2 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -87,6 +87,20 @@ MODCNT .SET MODCNT + 1 !!! ; FORCE AN ASSEMBLY ERROR #ENDIF ; +; SOME HARDWARE REQUIRES A SPECIFIC ROMSIZE (NOTABLY ZZRCC) OR THE +; RESULTING BUILD IMAGES WILL BE CORRUPT. ROMSIZE_CHK IS SPECIFIED +; IN THE CONFIG FILE AND IS VERIFIED AGAINST THE ROMSIZE BEING USED +; BY THE BUILD. A ROMSIZE_CHK VALUE OF 0 INDICATES THE VERFICATION +; IS DISABLED (WHICH IT USUALLY IS). +; +#IF (ROMSIZE_CHK != 0) & (ROMSIZE != ROMSIZE_CHK) + .ECHO "*** ERROR: ROMSIZE VALUE VERIFICATION FAILURE.\n" + .ECHO "THIS CONFIGURATION REQUIRES A ROMSIZE OF " \ .ECHO ROMSIZE_CHK \ .ECHO ".\n" + .ECHO "BUILD IS USING A ROMSIZE OF " \ .ECHO ROMSIZE \ .ECHO ".\n" + .ECHO "SEE COMMENTS IN HBIOS.ASM.\n" + !!! ; FORCE AN ASSEMBLY ERROR +#ENDIF +; ; ; #IF (DIAGENABLE) @@ -129,7 +143,7 @@ MODCNT .SET MODCNT + 1 #IF (INTMODE == 3) ; Z280 MODE 3 INTERRUPT HANDLING (INTA, C/T 0, & UART RCVR ENABLED) #DEFINE HB_DI DI -#DEFINE HB_EI .DB $ED,$7F,$0B +#DEFINE HB_EI EI $0B #ELSE ; Z280 MODE 1/2 INTERRUPT HANDLING #DEFINE HB_DI DI @@ -352,8 +366,7 @@ HBX_INVOKE: LD A,BID_BIOS ; HBIOS BANK LD (HB_CURBNK),A ; SET AS CURRENT BANK ; - .DB $ED,$71 ; SC - .DW HB_DISPATCH ; SC PARAMETER + SC HB_DISPATCH ; PUSH AF LD A,(HB_INVBNK) @@ -490,8 +503,7 @@ HBX_BNKSEL1: PUSH BC ; SAVE BC PUSH HL ; SAVE HL LD B,$00 ; FIRST USER PDR - .DB $ED,$71 ; SC - .DW Z280_BNKSEL ; SC PARAMETER + SC Z280_BNKSEL ; SYSCALL POP HL ; RESTORE HL POP BC ; RESTORE BC RET ; DONE @@ -560,9 +572,11 @@ HBX_MMA .DB 0 ; TEMPORARY STORAGE FOR REG A ; HBX_BNKCPY: #IF (MEMMGR == MM_Z280) - .DB $ED,$71 ; SC - .DW Z280_BNKCPYX ; SC PARAMETER + SC Z280_BNKCPYX ; SYSCALL TO BNKCPYX RET +; +IOPRVAL .DW 0 ; TEMP STORAGE FOR IOPR +; #ELSE #IF (CPUFAM == CPU_Z280) PUSH HL @@ -651,8 +665,7 @@ HBX_BNKCALL: #IF (MEMMGR == MM_Z280) CP BID_BIOS ; CALLING HBIOS? JR NZ,HBX_BNKCALL3 ; NOPE, DO NORMAL PROCESSING - .DB $ED,$71 ; SC - .DW HBX_BNKCALL2 ; CALL HERE IN SYSTEM MODE + SC HBX_BNKCALL2 ; SYSCALL TO BNKCALL2 RET ; THEN RETURN ; HBX_BNKCALL2: @@ -1127,7 +1140,7 @@ Z280_BOOTERR .TEXT "\r\n\r\n*** Application mode boot not supported under Z280 n LD HL,Z280_BOOTPDRTBL ; START OF PDR VALUES TABLE LD C,Z280_MMUBLKMOV ; PDR BLOCK MOVE PORT LD B,16 ; PROGRAM 16 PDRS - .DB $ED,$93 ; OTIRW + OTIRW ; OTIRW ; ; INITIALIZE ALL OF THE USER PAGE DESCRIPTORS WITH BLOCK MOVE LD A,$10 ; FIRST SYSTEM PDR @@ -1135,7 +1148,7 @@ Z280_BOOTERR .TEXT "\r\n\r\n*** Application mode boot not supported under Z280 n LD HL,Z280_BOOTPDRTBL ; START OF PDR VALUES TABLE LD C,Z280_MMUBLKMOV ; PDR BLOCK MOVE PORT LD B,16 ; PROGRAM 16 PDRS - .DB $ED,$93 ; OTIRW + OTIRW ; OTIRW ; ; ENABLE MMU (SYSTEM AND USER TRANSLATION) LD C,Z280_MMUMCR ; MMU MASTER CONTROL REGISTER @@ -1532,7 +1545,11 @@ MBC_SINGLE: LD HL,0 LD DE,0 LD BC,$8000 +#IF (MEMMGR == MM_Z280) + CALL Z280_BNKCPY +#ELSE CALL HBX_BNKCPY +#ENDIF ; ; TRANSITION TO HBIOS IN RAM BANK ; @@ -1621,9 +1638,9 @@ HB_START1: ; BNKCALL ARRIVES HERE, BUT NOW RUNNING IN RAM BANK ; ASSUME THAT CB_RAMBANKS IS THE NUMBER OF 32K RAM BANKS THAT HAS BEEN SET EITHER ; AT ASSEMBLY TIME OR BY PROBING THE ACTUAL AVAILABLE MEMORY (NOT IMPLEMENTED YET). ; - LD A,(CB_RAMBANKS) ; CALCULATE START - DEC A ; RAMBANK AFTER - ADD A,($80 + (PLT_RAM_R / 32)) ; RESERVED BANKS + LD A,(CB_RAMBANKS) ; CALCULATE TOP RAMBANK + ADD A,BID_RAM0 ; AS FIRST RAMBANK + + DEC A ; #RAMBANKS - 1 ; LD HL,CB_BIDCOM LD B,4 @@ -1631,12 +1648,12 @@ CB_IDS: LD (HL),A ; POPULATE CB_BIDCOM INC HL ; POPULATE CB_BIDUSR DEC A ; POPULATE CB_BIDBIOS DJNZ CB_IDS ; POPULATE CB_BIDAUX - +; LD A,(CB_BIDUSR) LD (HB_SRCBNK),A ; POPULATE HB_SRCBNK LD (HB_DSTBNK),A ; POPULATE HB_DSTBNK ; - LD A,+($80 + (PLT_RAM_R / 32)) ; POPULATE CB_BIDRAMD0 ; START RAMBANK + LD A,BID_RAM0 ; POPULATE CB_BIDRAMD0 ; START RAMBANK LD (HL),A INC HL ; @@ -2471,7 +2488,13 @@ HB_CKBNK: LD BC,1 ; DECREMENT VALUE XOR A ; ZERO ACCUM HB_CKBNK1: +#IF (MEMMGR == MM_Z280) + LD D,A ; WORKING VALUE TO D + LDUD A,(HL) ; GRAB NEXT BYTE FROM USER SPACE + ADD A,D ; ADD NEXT BYTE +#ELSE ADD A,(HL) ; ADD NEXT BYTE +#ENDIF OR A ; CLEAR CARRY SBC HL,BC ; DECREMENT JR NC,HB_CKBNK1 ; LOOP TILL DONE @@ -4782,7 +4805,7 @@ Z280_BADINT: CALL PRTHEXWORDHL ; DUMP MSR EX (SP),HL ; MSR TO STK, RECOVER HL ; - .DB $ED,$55 ; RETIL + RETIL ; RETURN FROM INT ; Z280_SSTEP: ; SAVE HL AND MSR FOR POSSIBLE RETURN VIA RETIL @@ -4876,7 +4899,7 @@ Z280_PRIVINST: PUSH BC PUSH DE ; - .DB $ED,$96 ; LDUP A,(HL) + LDUP A,(HL) ; BYTE FROM USER SPACE ; ; HANDLE DI CP $F3 ; DI? @@ -4904,7 +4927,7 @@ Z280_PRIVINST3: CALL PC_LBKT LD B,$10 Z280_PRIVINST4: - .DB $ED,$96 ; LDUP A,(HL) + LDUP A,(HL) ; BYTE FROM USER SPACE CALL PRTHEXBYTE INC HL DJNZ Z280_PRIVINST4 @@ -4925,7 +4948,7 @@ Z280_PRIVINSTX: PUSH HL ; SAVE HL LD HL,(HB_MSRSAV) ; GET SAVED MSR EX (SP),HL ; MSR TO STK, RECOVER HL - .DB $ED,$55 ; RETIL + RETIL ; RETURN FROM INT ; HB_MSRSAV .DW 0 ; SAVED MSR HB_RCSAV .DW 0 ; SAVED REASON CODE @@ -5230,7 +5253,7 @@ Z280_BNKSEL2: ; ; SET LOW NIBBLE LD A,$0A ; VALUE FOR LOW NIBBLE - .DB $ED,$6D ; ADD HL,A ; HL=0000 RBBB B000 1010 + ADD HL,A ; ADD HL,A ; HL=0000 RBBB B000 1010 ; ; POINT TO FIRST PDR TO PROGRAM LD A,B ; INITIAL PDR TO PROG @@ -5427,7 +5450,7 @@ Z280_BNKCPY: ; ; WAIT FOR XFER TO COMPLETE Z2DMALOOP: - .DB $ED,$B7 ; INW HL,(C) + INW HL,(C) ; WORD INPUT BIT 7,H ; CHECK EN BIT OF TDR JR NZ,Z2DMALOOP ; LOOP WHILE ACTIVE ; @@ -5510,7 +5533,7 @@ Z280_SYSCALL: POP HL Z280_SYSCALL_GO: CALL $FFFF ; PARM SET ABOVE - .DB $ED,$55 ; RETIL + RETIL ; RETURN FROM INT #ENDIF ; ;================================================================================================== @@ -6288,7 +6311,7 @@ PS_PRTDC: RET ; DONE ; PS_PRTDC1: - ; PRINT ROM/ROM DISK CAPACITY IN KB + ; PRINT ROM/RAM DISK CAPACITY IN KB LD B,BF_DIOCAP ; HBIOS FUNC: GET CAPACTIY RST 08 ; DE:HL := BLOCKS JP NZ,PS_PRTNUL ; MEDIA PROBLEM @@ -6933,8 +6956,6 @@ HB_SECS .FILL 4,0 ; 32 BIT SECONDS COUNTER HB_CPUTYPE .DB 0 ; 0=Z80, 1=80180, 2=SL1960, 3=ASCI BRG HB_CPUOSC .DW CPUOSC ; ACTUAL CPU HARDWARE OSC FREQ IN KHZ ; -IOPRVAL .DW 0 ; TEMP STORAGE FOR IOPR -; HB_BATCOND .DB 0 ; BATTERY CONDITION (0=LOW, 1=OK) ; RTCDEFVAL .DB RTCDEF ; STORAGE FOR RTC DEFAULT VALUE diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index 080677e3..4a9fa080 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -495,17 +495,17 @@ SYSTIM .SET TM_Z280 ; WBW_ROM_R .EQU 128 ; 128K ; RESERVED ROM REQUIRED FOR ROMWBW WBW_RAM_R .EQU 256 ; 256K ; RESERVED RAM REQUIRED FOR ROMWBW -TOT_ROM_RB .EQU (PLT_ROM_R + WBW_ROM_R)/32 ; TOTAL ROM BANKS RESERVED -TOT_RAM_RB .EQU (PLT_RAM_R + WBW_RAM_R)/32 ; TOTAL RAM BANKS RESERVED +TOT_ROM_RB .EQU (WBW_ROM_R / 32) ; TOTAL ROM BANKS RESERVED +TOT_RAM_RB .EQU (WBW_RAM_R / 32) ; TOTAL RAM BANKS RESERVED ; #IF (BIOS == BIOS_UNA) -BID_ROM0 .EQU $0000 + (PLT_ROM_R / 32) -BID_RAM0 .EQU $8000 + (PLT_RAM_R / 32) +BID_ROM0 .EQU $0000 +BID_RAM0 .EQU $8000 #ENDIF ; #IF (BIOS == BIOS_WBW) -BID_ROM0 .EQU $00 + (PLT_ROM_R / 32) -BID_RAM0 .EQU $80 + (PLT_RAM_R / 32) +BID_ROM0 .EQU $00 +BID_RAM0 .EQU $80 #ENDIF BID_ROMN .EQU (BID_ROM0 + ((ROMSIZE / 32) - 1)) @@ -528,6 +528,28 @@ BID_IMG2 .EQU BID_ROM0 + 3 ; NETWORK BOOT -+ ROM BANKS BID_ROMD0 .EQU BID_ROM0 + 4 ; FIRST ROM DRIVE BANK | ROM BID_ROMDN .EQU BID_ROMN ; LAST ROM DRIVE BANK V DRIVE ; +#IF FALSE + .ECHO "BID_AUX: " \ .ECHO BID_AUX \ .ECHO "\n" + .ECHO "BID_BIOS: " \ .ECHO BID_BIOS \ .ECHO "\n" + .ECHO "BID_USR: " \ .ECHO BID_USR \ .ECHO "\n" + .ECHO "BID_COM: " \ .ECHO BID_COM \ .ECHO "\n" + + .ECHO "BID_BOOT: " \ .ECHO BID_BOOT \ .ECHO "\n" + .ECHO "BID_IMG0: " \ .ECHO BID_IMG0 \ .ECHO "\n" + .ECHO "BID_IMG1: " \ .ECHO BID_IMG1 \ .ECHO "\n" + .ECHO "BID_IMG2: " \ .ECHO BID_IMG2 \ .ECHO "\n" + + .ECHO "BID_ROMD0: " \ .ECHO BID_ROMD0 \ .ECHO "\n" + .ECHO "BID_ROMDN: " \ .ECHO BID_ROMDN \ .ECHO "\n" + .ECHO "BID_RAMD0: " \ .ECHO BID_RAMD0 \ .ECHO "\n" + .ECHO "BID_RAMDN: " \ .ECHO BID_RAMDN \ .ECHO "\n" + + .ECHO "BID_ROM0: " \ .ECHO BID_ROM0 \ .ECHO "\n" + .ECHO "BID_ROMN: " \ .ECHO BID_ROMN \ .ECHO "\n" + .ECHO "BID_RAM0: " \ .ECHO BID_RAM0 \ .ECHO "\n" + .ECHO "BID_RAMN: " \ .ECHO BID_RAMN \ .ECHO "\n" +#ENDIF +; ; MEMORY LAYOUT ; SYS_SIZ .EQU $3000 ; COMBINED SIZE OF SYSTEM AREA (OS + HBIOS PROXY) diff --git a/Source/ver.inc b/Source/ver.inc index d6117e2a..4ee49ba3 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,4 +2,4 @@ #DEFINE RMN 1 #DEFINE RUP 1 #DEFINE RTP 0 -#DEFINE BIOSVER "3.1.1-pre.156" +#DEFINE BIOSVER "3.1.1-pre.157" diff --git a/Source/ver.lib b/Source/ver.lib index e13f6c1b..e588be99 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 1 rup equ 1 rtp equ 0 biosver macro - db "3.1.1-pre.156" + db "3.1.1-pre.157" endm diff --git a/Tools/tasm32/TASM280.TAB b/Tools/tasm32/TASM280.TAB index f8644eec..b57fad84 100644 --- a/Tools/tasm32/TASM280.TAB +++ b/Tools/tasm32/TASM280.TAB @@ -127,8 +127,8 @@ DEC L 2D 1 NOP 1 DEC SP 3B 1 NOP 1 DI "" F3 1 NOP 1 DJNZ * 10 2 R1 1 - EI "" FB 1 NOP 1 +EI * 7FED 3 NOP 1 /* Z280 */ EX (SP),HL E3 1 NOP 1 EX (SP),IX E3DD 2 NOP 1 EX (SP),IY E3FD 2 NOP 1 @@ -158,6 +158,8 @@ IN L,(C) 68ED 2 NOP 1 IN A,(*) DB 2 NOP 1 +INW HL,(C) B7ED 2 NOP 1 /* Z280 */ + IN0 A,(*) 38ED 3 NOP 2 IN0 B,(*) 00ED 3 NOP 2 IN0 C,(*) 08ED 3 NOP 2 @@ -342,6 +344,8 @@ LD SP,HL F9 1 NOP 1 LD SP,IX F9DD 2 NOP 1 LD SP,IY F9FD 2 NOP 1 LD SP,* 31 3 NOP 1 +LDUD A,(HL) 86ED 2 NOP 1 /* Z280 */ +LDUP A,(HL) 96ED 2 NOP 1 /* Z280 */ LDCTL (C),HL 6EED 2 NOP 1 /* Z280 */ LDCTL HL,(C) 66ED 2 NOP 1 /* Z280 */ LDCTL USP,HL 8FED 2 NOP 1 /* Z280 */ @@ -378,6 +382,7 @@ OTDR "" BBED 2 NOP 1 OTIM "" 83ED 2 NOP 2 OTIMR "" 93ED 2 NOP 2 OTIR "" B3ED 2 NOP 1 +OTIRW "" 93ED 2 NOP 1 /* Z280 */ OUT (C),A 79ED 2 NOP 1 OUT (C),B 41ED 2 NOP 1 @@ -524,6 +529,9 @@ SBC HL,DE 52ED 2 NOP 1 SBC HL,HL 62ED 2 NOP 1 SBC HL,SP 72ED 2 NOP 1 SBC A,* DE 2 NOP 1 + +SC * 71ED 4 NOP 1 /* Z280 */ + SCF "" 37 1 NOP 1 SET *,(HL) C6CB 2 ZBIT 1 diff --git a/Tools/unix/uz80as/z80.c b/Tools/unix/uz80as/z80.c index 60df3c08..214f6964 100644 --- a/Tools/unix/uz80as/z80.c +++ b/Tools/unix/uz80as/z80.c @@ -210,6 +210,13 @@ static const struct matchtab s_matchtab_z80[] = { { "MULTU A,a", "FD.ED.F9.d0.", 4, 0 }, { "OUTW (C),HL", "ED.BF.", 4, 0 }, { "RETIL", "ED.55.", 4, 0 }, + { "EI a", "ED.7F.d0.", 4, 0 }, + { "SC a", "ED.71.e0", 4, 0 }, + { "OTIRW", "ED.93.", 4, 0 }, + { "LDUD A,(HL)", "ED.86.", 4, 0 }, + { "LDUP A,(HL)", "ED.96.", 4, 0 }, + { "ADD HL,A", "ED.6D.", 4, 0 }, + { "INW HL,(C)", "ED.B7.", 4, 0 }, { NULL, NULL }, }; From 36b160f934a79da5ca64d506809a173e5d9f0838 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Fri, 18 Feb 2022 16:36:14 -0800 Subject: [PATCH 21/34] Minor Cosmetic Cleanup Primarily fixed the Z280 config files to display the correct CPU speed in boot messages. --- Source/CBIOS/cbios.asm | 7 ++++ Source/CPM3/diskio.z80 | 7 ++++ Source/HBIOS/Config/RCZ280_nat.asm | 2 +- Source/HBIOS/Config/RCZ280_nat_zzr.asm | 6 ++-- Source/HBIOS/cfg_rcz280.asm | 2 +- Source/HBIOS/std.asm | 13 +++++++- Source/ZZR/Bank Layout.txt | 45 +++++++++++++++++--------- Source/ZZR/Build.cmd | 30 +++++++++++++++-- Source/ZZR/Makefile | 22 ++++++------- Source/ver.inc | 2 +- Source/ver.lib | 2 +- 11 files changed, 100 insertions(+), 38 deletions(-) diff --git a/Source/CBIOS/cbios.asm b/Source/CBIOS/cbios.asm index 0c8c14d8..197cee9c 100644 --- a/Source/CBIOS/cbios.asm +++ b/Source/CBIOS/cbios.asm @@ -2412,6 +2412,13 @@ MD_INIT: ; UDPATE THE RAM/ROM DPB STRUCTURES BASED ON HARDWARE ; #IFDEF PLTWBW + ; TODO: HANDLE DISABLED RAM/ROM DISK BETTER. + ; IF RAM OR ROM DISK ARE DISABLED, BELOW WILL STILL + ; TRY TO ADJUST THE DPB BASED ON RAM BANK CALCULATIONS. + ; IT SHOULD NOT MATTER BECAUSE THE DPB SHOULD NEVER BE + ; USED. IT WOULD BE BETTER TO GET RAMD0/ROMD0 AND + ; RAMDN/ROMDN FROM THE HCB AND USE THOSE TO CALC THE + ; DPB ADJUSTMENT. IF DN-D0=0, BYPASS ADJUSTMENT. LD A,(HCB + HCB_ROMBANKS) ; ROM BANK COUNT SUB 4 ; REDUCE BANK COUNT BY RESERVED PAGES LD IX,DPB_ROM ; ADDRESS OF DPB diff --git a/Source/CPM3/diskio.z80 b/Source/CPM3/diskio.z80 index 0cba818b..2d87a132 100644 --- a/Source/CPM3/diskio.z80 +++ b/Source/CPM3/diskio.z80 @@ -355,6 +355,13 @@ dpb$hdnew: ; 8MB Hard Disk Drive (new format) ; called for first time initialization. dsk$init: + ; TODO: Handle disabled RAM/ROM disk better. + ; If RAM or ROM disk are disabled, below will still + ; try to adjust the DPB based on RAM bank calculations. + ; It should not matter because the DPB should never be + ; used. It would be better to get RAMD0/ROMD0 and + ; RAMDN/ROMDN from the HCB and use those to calc the + ; DPB adjustment. If DN-D0=0, bypass adjustment. ld b,0FAh ; HBIOS Peek Function ld a,(@hbbio) ; HBIOS bank id ld d,a ; ... goes in D diff --git a/Source/HBIOS/Config/RCZ280_nat.asm b/Source/HBIOS/Config/RCZ280_nat.asm index 8fe12ab4..2f0797cf 100644 --- a/Source/HBIOS/Config/RCZ280_nat.asm +++ b/Source/HBIOS/Config/RCZ280_nat.asm @@ -28,7 +28,7 @@ ; CRTACT .SET FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP ; -CPUOSC .SET 24000000 ; CPU OSC FREQ IN MHZ +CPUOSC .SET 12000000 ; CPU OSC FREQ IN MHZ ; MEMMGR .SET MM_Z280 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280] ; diff --git a/Source/HBIOS/Config/RCZ280_nat_zzr.asm b/Source/HBIOS/Config/RCZ280_nat_zzr.asm index 4fc7db32..4439f45d 100644 --- a/Source/HBIOS/Config/RCZ280_nat_zzr.asm +++ b/Source/HBIOS/Config/RCZ280_nat_zzr.asm @@ -28,7 +28,7 @@ ; #include "Config/RCZ280_nat.asm" ; -CPUOSC .SET 29491200 ; CPU OSC FREQ IN MHZ +CPUOSC .SET 14745600 ; CPU OSC FREQ IN MHZ ; RAMSIZE .SET 256 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE_CHK .SET 256 ; ROMSIZE VALUE VEREIFICATION (0=DISABLED) @@ -39,4 +39,6 @@ RAMBIAS .SET (1 << (RAMLOC - 10)) ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS MDROM .SET TRUE ; MD: ENABLE ROM DISK MDRAM .SET FALSE ; MD: ENABLE RAM DISK ; -Z2U0HFC .SET TRUE ; Z2U 0: ENABLE HARDWARE FLOW CONTROL +; +Z2UOSC .SET (CPUOSC / 8) ; Z2U: OSC FREQUENCY IN MHZ +Z2U0HFC .SET TRUE ; Z2U0: ENABLE HARDWARE FLOW CONTROL diff --git a/Source/HBIOS/cfg_rcz280.asm b/Source/HBIOS/cfg_rcz280.asm index 5430ca21..480f6724 100644 --- a/Source/HBIOS/cfg_rcz280.asm +++ b/Source/HBIOS/cfg_rcz280.asm @@ -27,7 +27,7 @@ BOOT_TIMEOUT .EQU -1 ; AUTO BOOT TIMEOUT IN SECONDS, -1 TO DISABLE, 0 FOR IMMED ; CPUSPDCAP .EQU SPD_FIXED ; CPU SPEED CHANGE CAPABILITY SPD_FIXED|SPD_HILO CPUSPDDEF .EQU SPD_HIGH ; CPU SPEED DEFAULT SPD_UNSUP|SPD_HIGH|SPD_LOW -CPUOSC .EQU 24000000 ; CPU OSC FREQ IN MHZ +CPUOSC .EQU 12000000 ; CPU OSC FREQ IN MHZ INTMODE .EQU 0 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) DEFSERCFG .EQU SER_115200_8N1 ; DEFAULT SERIAL LINE CONFIG (SEE STD.ASM) ; diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index 4a9fa080..9abd000d 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -528,7 +528,18 @@ BID_IMG2 .EQU BID_ROM0 + 3 ; NETWORK BOOT -+ ROM BANKS BID_ROMD0 .EQU BID_ROM0 + 4 ; FIRST ROM DRIVE BANK | ROM BID_ROMDN .EQU BID_ROMN ; LAST ROM DRIVE BANK V DRIVE ; -#IF FALSE +#IF (!MDRAM) +BID_RAMD0 .SET $FF ; RAM DRIVE DISABLED +BID_RAMDN .SET $FF ; RAM DRIVE DISABLED +#ENDIF +; +#IF (!MDROM) +BID_ROMD0 .SET $FF ; ROM DRIVE DISABLED +BID_ROMDN .SET $FF ; ROM DRIVE DISABLED +#ENDIF +; +; +#IF TRUE .ECHO "BID_AUX: " \ .ECHO BID_AUX \ .ECHO "\n" .ECHO "BID_BIOS: " \ .ECHO BID_BIOS \ .ECHO "\n" .ECHO "BID_USR: " \ .ECHO BID_USR \ .ECHO "\n" diff --git a/Source/ZZR/Bank Layout.txt b/Source/ZZR/Bank Layout.txt index d7b4bc64..9e2d951e 100644 --- a/Source/ZZR/Bank Layout.txt +++ b/Source/ZZR/Bank Layout.txt @@ -1,19 +1,32 @@ +ZZRCC has no real ROM. It has a single 512K RAM chip. The first +256K of the RAM chip is loaded from the CF card. This 256K is +treated like ROM by RomWBW. The remainder of the RAM (256K) is +treated like RAM by RomWBW. + +Because of the memory constraints, notice that there is no RAM Disk, +only a ROM disk. If you perform a ROM boot to an OS, the A: drive +will be the ROM disk and will not be writable. Booting a ROM OS +on this system is not typical since the system has a CF card by +definition. + Bank ROM RAM RAM ---- --- --- --- -0 HBIOS (IMG) RAMDISK RAMDISK -1 ROMLDR+MON+CP/M2+ZSYS RAMDISK RAMDISK -2 FTH+BAS+TBAS+PLAY+USR RAMDISK RAMDISK -3 RESERVED RAMDISK RAMDISK -4 ROMDISK RAMDISK RAMDISK -5 ROMDISK RAMDISK RAMDISK -6 ROMDISK RAMDISK RAMDISK -7 ROMDISK RAMDISK RAMDISK +0 HBIOS (IMG) +1 ROMLDR+MON+CP/M2+ZSYS +2 FTH+BAS+TBAS+PLAY+USR +3 RESERVED +4 ROMDISK +5 ROMDISK +6 ROMDISK +7 ROMDISK -8 ROMDISK BUF (CPM3) BUF (CPM3) -9 ROMDISK BUF (CPM3) BUF (CPM3) -A ROMDISK BUF (CPM3) BUF (CPM3) -B ROMDISK BUF (CPM3) BUF (CPM3) -C ROMDISK AUX (CPM3) TPA (CPM3) -D ROMDISK HBIOS (EXEC) HBIOS (EXEC) -E ROMDISK TPA-LO OS (CPM3) -F ROMDISK COMMON (TPA-HI) COMMON (TPA-HI) \ No newline at end of file +8 BUF (CPM3) BUF (CPM3) +9 BUF (CPM3) BUF (CPM3) +A BUF (CPM3) BUF (CPM3) +B BUF (CPM3) BUF (CPM3) +C AUX (CPM3) TPA (CPM3) +D HBIOS (EXEC) HBIOS (EXEC) +E TPA-LO OS (CPM3) +F COMMON (TPA-HI) COMMON (TPA-HI) + +--WBW 6:40 PM 2/16/2022 \ No newline at end of file diff --git a/Source/ZZR/Build.cmd b/Source/ZZR/Build.cmd index 3d6b0872..4dea5d8e 100644 --- a/Source/ZZR/Build.cmd +++ b/Source/ZZR/Build.cmd @@ -1,7 +1,27 @@ @echo off setlocal -if not exist ..\..\Binary\RCZ280_nat_zzr.rom goto :eof +set ROMFILE=..\..\Binary\RCZ280_nat_zzr.rom +set ROMSIZE=262144 + +if not exist %ROMFILE% goto :eof + +:: +:: The ROM image *must* be exactly 256K or the resulting disk +:: image produced below will be invalid. Check for the proper size. +:: + +call :filesize %ROMFILE% + +if "%FILESIZE%" neq "%ROMSIZE%" ( + echo. + echo. + echo ERROR: "%ROMFILE%" is not exactly %ROMSIZE% bytes as required!!! + echo You must specify a ROMSIZE of "256" when building the ZZRCC ROM image. + echo. + echo. + exit /b 1 +) rem ..\..\Tools\srecord\srec_cat.exe ..\..\Binary\RCZ280_nat_zzr.rom -Binary -Exclude 0x5000 0x7000 zzr_romldr.hex -Intel -Output ..\..\Binary\RCZ280_nat_zzr.hex -Intel || exit /b @@ -13,4 +33,10 @@ rem copy /b zzr_cfldr.bin + zzr_ptbl.bin + zzr_fill_1.bin + zzr_mon.bin + zzr_fi copy /b zzr_cfldr.bin + zzr_ptbl.bin + zzr_fill_1.bin + zzr_mon.bin + zzr_fill_2.bin + ..\..\Binary\RCZ280_nat_zzr.rom + zzr_fill_3.bin ..\..\Binary\hd1024_zzr_prefix.dat || exit /b -copy /b ..\..\Binary\hd1024_zzr_prefix.dat + ..\..\Binary\hd1024_cpm22.img + ..\..\Binary\hd1024_zsdos.img + ..\..\Binary\hd1024_nzcom.img + ..\..\Binary\hd1024_cpm3.img + ..\..\Binary\hd1024_zpm3.img + ..\..\Binary\hd1024_ws4.img ..\..\Binary\hd1024_zzr_combo.img || exit /b \ No newline at end of file +copy /b ..\..\Binary\hd1024_zzr_prefix.dat + ..\..\Binary\hd1024_cpm22.img + ..\..\Binary\hd1024_zsdos.img + ..\..\Binary\hd1024_nzcom.img + ..\..\Binary\hd1024_cpm3.img + ..\..\Binary\hd1024_zpm3.img + ..\..\Binary\hd1024_ws4.img ..\..\Binary\hd1024_zzr_combo.img || exit /b + +goto :eof + +:filesize +set FILESIZE=%~z1 +goto :eof \ No newline at end of file diff --git a/Source/ZZR/Makefile b/Source/ZZR/Makefile index 36b67930..2e1b2b30 100644 --- a/Source/ZZR/Makefile +++ b/Source/ZZR/Makefile @@ -1,17 +1,15 @@ HD1024ZZRPREFIX = hd1024_zzr_prefix.dat HD1024ZZZROMBOIMG = hd1024_zzr_combo.img ZZRROM = ../../Binary/RCZ280_nat_zzr.rom -ZZRLDRROM = RCZ280_nat_zzr_ldr.rom ZZRROMHEX = RCZ280_nat_zzr.hex HD1024IMGS = ../../Binary/hd1024_cpm22.img ../../Binary/hd1024_zsdos.img ../../Binary/hd1024_nzcom.img \ ../../Binary/hd1024_cpm3.img ../../Binary/hd1024_zpm3.img ../../Binary/hd1024_ws4.img - +ZZRROMSIZE = 262144 OBJECTS := ifneq ($(wildcard $(ZZRROM)),) -# OBJECTS += $(ZZRROMHEX) $(ZZRLDRROM) $(HD1024ZZRPREFIX) $(HD1024ZZZROMBOIMG) - OBJECTS += $(ZZRROMHEX) $(HD1024ZZRPREFIX) $(HD1024ZZZROMBOIMG) + OBJECTS += $(ZZRROMHEX) $(HD1024ZZRPREFIX) $(HD1024ZZZROMBOIMG) endif DEST=../../Binary @@ -22,16 +20,14 @@ include $(TOOLS)/Makefile.inc DIFFPATH = $(DIFFTO)/Binary -$(HD1024ZZRPREFIX): -# cat zzr_cfldr.bin zzr_ptbl.bin zzr_fill_1.bin zzr_mon.bin zzr_fill_2.bin $(ZZRLDRROM) zzr_fill_3.bin >$@ +zzrromchk: + [ `stat -c%s $(ZZRROM)` = $(ZZRROMSIZE) ] + +$(HD1024ZZRPREFIX): zzrromchk cat zzr_cfldr.bin zzr_ptbl.bin zzr_fill_1.bin zzr_mon.bin zzr_fill_2.bin $(ZZRROM) zzr_fill_3.bin >$@ -$(HD1024ZZZROMBOIMG): $(HD1024ZZRPREFIX) $(HD1024IMGS) - cat $^ > $@ +$(HD1024ZZZROMBOIMG): zzrromchk $(HD1024ZZRPREFIX) $(HD1024IMGS) + cat $(HD1024ZZRPREFIX) $(HD1024IMGS) > $@ -$(ZZRROMHEX): $(ZZRROM) -# srec_cat $(ZZRROM) -Binary -Exclude 0x5000 0x7000 zzr_romldr.hex -Intel -Output $(ZZRROMHEX) -Intel +$(ZZRROMHEX): zzrromchk $(ZZRROM) srec_cat $(ZZRROM) -Binary -Output $(ZZRROMHEX) -Intel -CRLF - -$(ZZRLDRROM): $(ZZRROMHEX) - srec_cat $(ZZRROMHEX) -Intel -Output $(ZZRLDRROM) -Binary diff --git a/Source/ver.inc b/Source/ver.inc index 4ee49ba3..afcf6d1e 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,4 +2,4 @@ #DEFINE RMN 1 #DEFINE RUP 1 #DEFINE RTP 0 -#DEFINE BIOSVER "3.1.1-pre.157" +#DEFINE BIOSVER "3.1.1-pre.158" diff --git a/Source/ver.lib b/Source/ver.lib index e588be99..64bd8a1c 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 1 rup equ 1 rtp equ 0 biosver macro - db "3.1.1-pre.157" + db "3.1.1-pre.158" endm From 689f8a228066eec638084879117130b80b699952 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Fri, 18 Feb 2022 17:08:13 -0800 Subject: [PATCH 22/34] Update Makefile Try to fix MacOS build. --- Source/ZZR/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/ZZR/Makefile b/Source/ZZR/Makefile index 2e1b2b30..03d78ad3 100644 --- a/Source/ZZR/Makefile +++ b/Source/ZZR/Makefile @@ -21,8 +21,8 @@ include $(TOOLS)/Makefile.inc DIFFPATH = $(DIFFTO)/Binary zzrromchk: - [ `stat -c%s $(ZZRROM)` = $(ZZRROMSIZE) ] - + [ `wc -c $(ZZRROM) | awk '{print $$1}'` = $(ZZRROMSIZE) ] + $(HD1024ZZRPREFIX): zzrromchk cat zzr_cfldr.bin zzr_ptbl.bin zzr_fill_1.bin zzr_mon.bin zzr_fill_2.bin $(ZZRROM) zzr_fill_3.bin >$@ From 25374946e042e74255d725b1e133c3c159164d63 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Fri, 18 Feb 2022 17:54:12 -0800 Subject: [PATCH 23/34] Update std.asm Fix UNA build. --- Source/HBIOS/std.asm | 51 +++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index 9abd000d..dcc452eb 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -528,37 +528,40 @@ BID_IMG2 .EQU BID_ROM0 + 3 ; NETWORK BOOT -+ ROM BANKS BID_ROMD0 .EQU BID_ROM0 + 4 ; FIRST ROM DRIVE BANK | ROM BID_ROMDN .EQU BID_ROMN ; LAST ROM DRIVE BANK V DRIVE ; -#IF (!MDRAM) +#IF (BIOS == BIOS_WBW) +; + #IF (!MDRAM) BID_RAMD0 .SET $FF ; RAM DRIVE DISABLED BID_RAMDN .SET $FF ; RAM DRIVE DISABLED -#ENDIF + #ENDIF ; -#IF (!MDROM) + #IF (!MDROM) BID_ROMD0 .SET $FF ; ROM DRIVE DISABLED BID_ROMDN .SET $FF ; ROM DRIVE DISABLED -#ENDIF + #ENDIF ; +#ENDIF ; -#IF TRUE - .ECHO "BID_AUX: " \ .ECHO BID_AUX \ .ECHO "\n" - .ECHO "BID_BIOS: " \ .ECHO BID_BIOS \ .ECHO "\n" - .ECHO "BID_USR: " \ .ECHO BID_USR \ .ECHO "\n" - .ECHO "BID_COM: " \ .ECHO BID_COM \ .ECHO "\n" - - .ECHO "BID_BOOT: " \ .ECHO BID_BOOT \ .ECHO "\n" - .ECHO "BID_IMG0: " \ .ECHO BID_IMG0 \ .ECHO "\n" - .ECHO "BID_IMG1: " \ .ECHO BID_IMG1 \ .ECHO "\n" - .ECHO "BID_IMG2: " \ .ECHO BID_IMG2 \ .ECHO "\n" - - .ECHO "BID_ROMD0: " \ .ECHO BID_ROMD0 \ .ECHO "\n" - .ECHO "BID_ROMDN: " \ .ECHO BID_ROMDN \ .ECHO "\n" - .ECHO "BID_RAMD0: " \ .ECHO BID_RAMD0 \ .ECHO "\n" - .ECHO "BID_RAMDN: " \ .ECHO BID_RAMDN \ .ECHO "\n" - - .ECHO "BID_ROM0: " \ .ECHO BID_ROM0 \ .ECHO "\n" - .ECHO "BID_ROMN: " \ .ECHO BID_ROMN \ .ECHO "\n" - .ECHO "BID_RAM0: " \ .ECHO BID_RAM0 \ .ECHO "\n" - .ECHO "BID_RAMN: " \ .ECHO BID_RAMN \ .ECHO "\n" +#IF FALSE + .ECHO "BID_AUX: " \ .ECHO BID_AUX \ .ECHO "\n" + .ECHO "BID_BIOS: " \ .ECHO BID_BIOS \ .ECHO "\n" + .ECHO "BID_USR: " \ .ECHO BID_USR \ .ECHO "\n" + .ECHO "BID_COM: " \ .ECHO BID_COM \ .ECHO "\n" + + .ECHO "BID_BOOT: " \ .ECHO BID_BOOT \ .ECHO "\n" + .ECHO "BID_IMG0: " \ .ECHO BID_IMG0 \ .ECHO "\n" + .ECHO "BID_IMG1: " \ .ECHO BID_IMG1 \ .ECHO "\n" + .ECHO "BID_IMG2: " \ .ECHO BID_IMG2 \ .ECHO "\n" + + .ECHO "BID_ROMD0: " \ .ECHO BID_ROMD0 \ .ECHO "\n" + .ECHO "BID_ROMDN: " \ .ECHO BID_ROMDN \ .ECHO "\n" + .ECHO "BID_RAMD0: " \ .ECHO BID_RAMD0 \ .ECHO "\n" + .ECHO "BID_RAMDN: " \ .ECHO BID_RAMDN \ .ECHO "\n" + + .ECHO "BID_ROM0: " \ .ECHO BID_ROM0 \ .ECHO "\n" + .ECHO "BID_ROMN: " \ .ECHO BID_ROMN \ .ECHO "\n" + .ECHO "BID_RAM0: " \ .ECHO BID_RAM0 \ .ECHO "\n" + .ECHO "BID_RAMN: " \ .ECHO BID_RAMN \ .ECHO "\n" #ENDIF ; ; MEMORY LAYOUT From 51d9bdb6559c09705213c81e2785a21abc9f945b Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Mon, 28 Feb 2022 10:54:59 -0800 Subject: [PATCH 24/34] Minor ASSIGN Fixes, Add 2PIOTST - Improved ASSIGN operation under CP/M 3 to better handle BIOS function invocations - Added 2PIOTST for testing the DUALPIO MBC board - Increased default RAM drive size for ZRC --- Doc/ROM Applications.pdf | Bin 193897 -> 193897 bytes Doc/RomWBW Applications.pdf | Bin 241324 -> 241636 bytes Doc/RomWBW Architecture.pdf | Bin 451608 -> 451609 bytes Doc/RomWBW Disk Catalog.pdf | Bin 134794 -> 134794 bytes Doc/RomWBW Getting Started.pdf | Bin 272671 -> 272671 bytes ReadMe.md | 2 +- ReadMe.txt | 4 +- Source/Apps/Test/2piotst/2piotst.mac | 567 +++++++++++++++++++++++++++ Source/Apps/Test/2piotst/Build.cmd | 13 + Source/Apps/Test/2piotst/Clean.cmd | 8 + Source/Apps/Test/2piotst/Makefile | 8 + Source/Apps/Test/Build.cmd | 1 + Source/Apps/Test/Clean.cmd | 1 + Source/Apps/Test/Makefile | 2 +- Source/Apps/assign.asm | 101 +++-- Source/Doc/Applications.md | 5 + Source/HBIOS/Config/RCZ80_zrc.asm | 1 + Source/HBIOS/hbios.asm | 17 +- Source/HBIOS/std.asm | 12 +- Source/ver.inc | 2 +- Source/ver.lib | 2 +- Tools/Makefile.inc | 3 + 22 files changed, 701 insertions(+), 48 deletions(-) create mode 100644 Source/Apps/Test/2piotst/2piotst.mac create mode 100644 Source/Apps/Test/2piotst/Build.cmd create mode 100644 Source/Apps/Test/2piotst/Clean.cmd create mode 100644 Source/Apps/Test/2piotst/Makefile diff --git a/Doc/ROM Applications.pdf b/Doc/ROM Applications.pdf index 6f67aa2cc7a53ee8dddd1520722ee5bbee0f3916..0eea282c3040e6edae6c86cf3d01ca084f3a3c49 100644 GIT binary patch delta 260 zcmaF)iu>g&?hSQ}_51rGYi>&%-1DqgZLRk|u^Wpv#>IP0cy-d_d~UbOwIbHPhP|t= zoNt{|{O5P!3_o|nsoP(h%v&}y{HeD0?V|Gj*IXhCl?{(FMkgD6s}ouV)9ppun;Dtf z8JQTjGcqwPKFVQaVQ64rVPrhnk6oO{$jHD5Cb0edaV9HWXA@&XM{_q*BO@~>BVz*t gBQsYgM>kg!Q#U6=Hx~mpM>_=@LQ1Cld}Wda0FyOlP5=M^ delta 260 zcmaF)iu>g&?hSQ}_4Y4y_T}~@#C>*~d`-2UJLh7=dVN)ouPIBOZ*vvO-r4kT#<9>> z&z;U${`+g;vwZQ4Q@2Z{{4bwb{b}mb+?~6Rm$G(Um^kB6!&*bhO1t^e{-(<$|3+Py zZLYCf>i8DjBY*lGuOtOmB{LaKzi0F3*4yv9HFsB7@gA0`mEC$qe)lVV7OR||TKrh hV&Up!;NoWFXl`y|=H_VZ>Ski6U_(gBbf2$GvH<(mXFUJ_ diff --git a/Doc/RomWBW Applications.pdf b/Doc/RomWBW Applications.pdf index a64d5d210b2446a2f12b98c5b684b7627ee0c97a..7b8f44ed78bb1b43424891e840edadf9f0a4a74d 100644 GIT binary patch delta 16584 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 A9RL6T delta 16271 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 diff --git a/Doc/RomWBW Disk Catalog.pdf b/Doc/RomWBW Disk Catalog.pdf index 7a3c3a43de979ac5e4927731b4bdd8f9158948aa..e204ef9866104b46baf21121a2eaec13bba19b5f 100644 GIT binary patch delta 255 zcmeC0%h5HLV?!xpeZ+AcyX>9>xz8?>uc=Yec|C$c;MQMo;!KldzVXH?x@pw zu{>U5w^aKUjUzSN8#EV9{~V;IP^@|G>G#`4={vm6FaCOA(|iBjuh_r8W}5eZx}hd-4d-pY@QpD_+{x9&)xgcr%+1u$+0w<#&DqGr c#L>~*)X~7u)WXcf(ZEi@hJcdkIebiV0D{?R$^ZZW delta 255 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 diff --git a/ReadMe.txt b/ReadMe.txt index 92cfdabb..5f17c6dc 100644 --- a/ReadMe.txt +++ b/ReadMe.txt @@ -1,6 +1,6 @@ RomWBW Getting Started Wayne Warthen (mailto:wwarthen@gmail.com) -02 Feb 2022 +28 Feb 2022 @@ -17,7 +17,7 @@ RomWBW Z80/Z180 System Software Version 3.1 Pre-release -02 Feb 2022 +28 Feb 2022 Wayne Warthen wwarthen@gmail.com diff --git a/Source/Apps/Test/2piotst/2piotst.mac b/Source/Apps/Test/2piotst/2piotst.mac new file mode 100644 index 00000000..027dcddf --- /dev/null +++ b/Source/Apps/Test/2piotst/2piotst.mac @@ -0,0 +1,567 @@ +; 24.9.2018 PMS (b1ackmai1er) +; Modified version for ECB-ZILOG PERIPHERALS BOARD - TEST 2 PIO's +; 01.11.2011 WKA +; Assembler M80 +; ECB-4PIO +; Testprogramm fr die I/O-Karte ECB-4PIO in Z80-Mnemonics + + PAGE 72 + .Z80 + ASEG + ORG 100H +; +;CP/M-ADDRESSES +;* * * * * * * +; +BOOT EQU 0 ;WARMBOOT CP/M +BDOS EQU 5 ;ENTRY BDOS +NMI EQU 66H ;Error-ROUTINE +; +;CONSOLE-CODES +;* * * * * * * +; +EOT EQU 4 ;END OF TEXT +BS EQU 8 ;BACKSPACE +TAB EQU 9 ;TABULATOR +LF EQU 0AH ;LINE-FEED +CR EQU 0DH ;CARRIAGE-RETURN +FF EQU 0CH ;FORM-FEED +ESC EQU 1BH ;ESCAPE +CTRLC EQU 'C'-40H ;CONTROL-C +CTRLW EQU 'W'-40H ;CONTROL-W +CTRLX EQU 'X'-40H ;CONTROL-X +CTRLY EQU 'Y'-40H ;CONTROL-Y +CTRLZ EQU 'Z'-40H ;CONTROL-Z +; +BASE EQU 0B8H ; 4 DIL-SCHALTER +; +PIO0AD EQU BASE+0 ; PIO 0 A DATEN +PIO0AC EQU BASE+2 ; PIO 0 A CONTROL +PIO0BD EQU BASE+1 ; PIO 0 B DATEN +PIO0BC EQU BASE+3 ; PIO 0 B CONTROL +; +PIO1AD EQU BASE+4 ; PIO 1 A DATEN +PIO1AC EQU BASE+6 ; PIO 1 A CONTROL +PIO1BD EQU BASE+5 ; PIO 1 B DATEN +PIO1BC EQU BASE+7 ; PIO 1 B CONTROL +; +MAIN: LD DE,PIO_SRTMSG + CALL PSTRIN +; + LD DE,INI_MSG + CALL PSTRIN + CALL INIT +; + LD DE,PIO0ADW ;PIO0 A + CALL PSTRIN + LD A,55H + PUSH AF + CALL OUTB + LD DE,LINE_E + CALL PSTRIN + POP AF + OUT (PIO0AD),A + IN A,(PIO0AD) + PUSH AF +; + LD DE,PIO0ADR + CALL PSTRIN + POP AF + CALL OUTB + LD DE,LINE_E + CALL PSTRIN +; + LD DE,PIO0ADW + CALL PSTRIN + LD A,0AAH + PUSH AF + CALL OUTB + LD DE,LINE_E + CALL PSTRIN + POP AF + OUT (PIO0AD),A + IN A,(PIO0AD) + PUSH AF +; + LD DE,PIO0ADR + CALL PSTRIN + POP AF + CALL OUTB + LD DE,LINE_E + CALL PSTRIN +; + LD DE,PIO0BDW ;PIO0 B + CALL PSTRIN + LD A,55H + PUSH AF + CALL OUTB + LD DE,LINE_E + CALL PSTRIN + POP AF + OUT (PIO0BD),A + IN A,(PIO0BD) + PUSH AF +; + LD DE,PIO0BDR + CALL PSTRIN + POP AF + CALL OUTB + LD DE,LINE_E + CALL PSTRIN +; + LD DE,PIO0BDW + CALL PSTRIN + LD A,0AAH + PUSH AF + CALL OUTB + LD DE,LINE_E + CALL PSTRIN + POP AF + OUT (PIO0BD),A + IN A,(PIO0BD) + PUSH AF +; + LD DE,PIO0BDR + CALL PSTRIN + POP AF + CALL OUTB + LD DE,LINE_E + CALL PSTRIN +; + LD DE,PIO1ADW ;PIO1 A + CALL PSTRIN + LD A,55H + PUSH AF + CALL OUTB + LD DE,LINE_E + CALL PSTRIN + POP AF + OUT (PIO1AD),A + IN A,(PIO1AD) + PUSH AF +; + LD DE,PIO1ADR + CALL PSTRIN + POP AF + CALL OUTB + LD DE,LINE_E + CALL PSTRIN +; + LD DE,PIO1ADW + CALL PSTRIN + LD A,0AAH + PUSH AF + CALL OUTB + LD DE,LINE_E + CALL PSTRIN + POP AF + OUT (PIO1AD),A + IN A,(PIO1AD) + PUSH AF +; + LD DE,PIO1ADR + CALL PSTRIN + POP AF + CALL OUTB + LD DE,LINE_E + CALL PSTRIN +; + LD DE,PIO1BDW ;PIO1 B + CALL PSTRIN + LD A,55H + PUSH AF + CALL OUTB + LD DE,LINE_E + CALL PSTRIN + POP AF + OUT (PIO1BD),A + IN A,(PIO1BD) + PUSH AF +; + LD DE,PIO1BDR + CALL PSTRIN + POP AF + CALL OUTB + LD DE,LINE_E + CALL PSTRIN +; + LD DE,PIO1BDW + CALL PSTRIN + LD A,0AAH + PUSH AF + CALL OUTB + LD DE,LINE_E + CALL PSTRIN + POP AF + OUT (PIO1BD),A + IN A,(PIO1BD) + PUSH AF +; + LD DE,PIO1BDR + CALL PSTRIN + POP AF + CALL OUTB + LD DE,LINE_E + CALL PSTRIN +; + LD DE,PIO_ENDMSG + CALL PSTRIN + JP BOOT +; +;========================================================================== +INIT: LD HL,PIO0T ; PIO0 INITITALISIEREN + CALL INITX + LD HL,PIO1T ; PIO1 INITITALISIEREN + CALL INITX + RET +; +INITX: LD A,(HL) ; BYTE-ANZAHL + OR A + RET Z + LD B,A ; Port-Adresse nach C + INC HL + LD C,(HL) + INC HL + OTIR + JR INITX +; +PIO0T: DEFB 05 ; 5 BYTE ZUM PIO 0 A CONTROL + DEFB PIO0AC + DEFB 00000011B ; DIS-INT + DEFB 01001111B ; BETR.ART BYTE EINGABE + DEFB 01001111B ; BETR.ART BYTE EINGABE + DEFB 11001111B ; BETR.ART BIT EIN/AUSG. + DEFB 00000000B ; ALLES AUSG. + DEFB 01 ; 1 BYTE ZUM PIO 0 A DATEN + DEFB PIO0AD + DEFB 00000000B ; DATEN "LOW" +; + DEFB 05 ; 5 BYTE ZUM PIO 0 B CONTROL + DEFB PIO0BC + DEFB 00000011B ; DIS-INT + DEFB 01001111B ; BETR.ART BYTE EINGABE + DEFB 01001111B ; BETR.ART BYTE EINGABE + DEFB 11001111B ; BETR.ART BIT EIN/AUSG. + DEFB 00000000B ; ALLES AUSG. + DEFB 01 ; 1 BYTE ZUM PIO 0 B DATEN + DEFB PIO0BD + DEFB 00000000B ; DATEN "LOW" + DEFB 0 ; ENDE PIO 0 B -TABELLE +; +PIO1T: DEFB 05 ; 5 BYTE ZUM PIO 1 A CONTROL + DEFB PIO1AC + DEFB 00000011B ; DIS-INT + DEFB 01001111B ; BETR.ART BYTE EINGABE + DEFB 01001111B ; BETR.ART BYTE EINGABE + DEFB 11001111B ; BETR.ART BIT EIN/AUSG. + DEFB 00000000B ; ALLES AUSG. + DEFB 01 ; 1 BYTE ZUM PIO 1 A DATEN + DEFB PIO1AD + DEFB 00000000B ; DATEN "LOW" +; + DEFB 05 ; 5 BYTE ZUM PIO 1 B CONTROL + DEFB PIO1BC + DEFB 00000011B ; DIS-INT + DEFB 01001111B ; BETR.ART BYTE EINGABE + DEFB 01001111B ; BETR.ART BYTE EINGABE + DEFB 11001111B ; BETR.ART BIT EIN/AUSG. + DEFB 00000000B ; ALLES AUSG. + DEFB 01 ; 1 BYTE ZUM PIO 1 B DATEN + DEFB PIO1BD + DEFB 00000000B ; DATEN "LOW" + DEFB 0 ; ENDE PIO 1 B -TABELLE +; +;========================================================================== +; +;Output on Screen +;**************** +; +PRBS: LD E,BS + CALL PCHAR + RET +; +;Output CR+LF on Screen +;********************** +; +CRLF: LD E,CR + CALL PCHAR + LD E,LF + CALL PCHAR + RET +; +;Output ASCII-Character +;********************** +; +PRINP: PUSH AF + LD E,A + CALL PCHAR + POP AF + RET; +; +;CALL BDOS with Register Save +;**************************** +; +INCHA: LD C,1 ;INPUT CHARACTER TO A + JR BDO +PCHAR: LD C,2 ;PRINT CHARACTER IN E + JR BDO +PSTRIN: LD C,9 ;PRINT STRING + JR BDO +INBUFF: LD C,10 ;READ CONSOLE-BUFFER + JR BDO +CSTS: LD C,11 ;CONSOLE-STATUS + JR BDO +OPEN: LD C,15 ;OPEN FILE + JR BDO +CLOSE: LD C,16 ;CLOSE FILE + JR BDO +DELETE: LD C,19 ;DELETE FILE + JR BDO +READS: LD C,20 ;READ SEEK + JR BDO +WRITES: LD C,21 ;WRITE SEEK + JR BDO +MAKE: LD C,22 ;MAKE FILE + JR BDO +SETDMA: LD C,26 ;SET DMA-ADDRESS +BDO: PUSH HL + PUSH DE + PUSH BC + PUSH IX + PUSH IY + CALL BDOS + POP IY + POP IX + POP BC + POP DE + POP HL + RET +; +;DIRECT CONSOLE INPUT +;******************** +; +INDCON: CALL INDCOX + CP 0 + JR Z,INDCON + RET +; +INDCOX: LD C,6 ;Code for Direct Console Input + LD E,0FFH ;Code for Input + PUSH HL + PUSH DE + PUSH BC + PUSH IX + PUSH IY + CALL BDOS + POP IY + POP IX + POP BC + POP DE + POP HL + RET +; +; +;Output WORD +;*********** +; +;PARAMETER: Entry WORD IN HL +;********* +; +OUTW: LD A,H + CALL OUTB + LD A,L + CALL OUTB + RET +; +;Output BYTE +;*********** +; +;PARAMETER: Entry BYTE IN A +;********* +; +OUTB: PUSH AF + RRCA + RRCA + RRCA + RRCA + AND 0FH + CALL HBTHE ;Change Half-BYTE + POP AF + AND 0FH + CALL HBTHE + RET +; +;Output HALF-BYTE +;**************** +; +;PARAMETER: Entry Half-BYTE IN A (BIT 0 - 3) +;********* +; +HBTHE: CP 0AH + JR C,HBTHE1 + ADD A,7 ;Character to Letter +HBTHE1: ADD A,30H + LD E,A + CALL PCHAR + RET +; +;Input ADDRESS +;************* +; +;PARAMETER: Exit with ADDRESS IN HL +;********* +; +INADR: LD HL,0 +INADR1: CALL INCHAR ;Input TETRADE + LD D,A + CALL INBYT1 ;IN HEXA + RET C ;END OF Input + ADD HL,HL + ADD HL,HL + ADD HL,HL + ADD HL,HL + OR L + LD L,A + JR INADR1 ;New Key +; +; +;Input BYTE +;********** +; +;PARAMTER: Exit with BYTE IN A +;******** +; +INBYT: CALL INADR + LD A,L + RET +; +;Input of one TETRADE to A (BIT 0-3) +;************************************ +; +INBYT1: SUB '0' + RET C + CP 'G'-30H + JR NC,INBYT3 ;Error + CP ':'-30H + JR C,INBYT2 + CP 'A'-30H + JR C,INBYT3 ;Error + SUB 7 +INBYT2: OR A + RET +; +INBYT3: SCF + RET +; +;Input ASCII-Character to A +;************************** +; +INCON: CALL INDCON ;Input ASCII-Character to A + CP CTRLC ;TEST CONTROL-C + JP Z,QUIT + CP CTRLX ;TEST CONTROL-X + JR Z,INCHA1 + CP CTRLW ;TEST CONTROL-W + JR Z,INCHA3 + CP CTRLY ;TEST CONTROL-Y + JR Z,INCHA2 + CP BS + RET Z + CP CR + RET Z + CP ' ' + JR C,INCON + JR INCH1 +; +INCHAR: CALL INCHA ;Input ASCII-Character to A + CP CTRLC ;TEST CONTROL-C + JR Z,QUIT + CP CTRLX ;TEST CONTROL-X + JR Z,INCHA1 + CP CTRLW ;TEST CONTROL-W + JR Z,INCHA3 + CP CTRLY ;TEST CONTROL-Y + JR Z,INCHA2 + CP BS + RET Z + CP CR + RET Z + CP ' ' + JR C,INCHAR ;Input invalied +; +INCH1: CP 'A' + RET C ;Character ok +; + RES 5,A ;lower case -> upper case + RET +INCHA1: POP HL + LD E,FF + CALL PCHAR ;Clear screen + JP GOON +INCHA2: POP HL + LD E,FF + CALL PCHAR ;Clear screen + JP GOON +INCHA3: LD E,FF + CALL PCHAR + RET +; +;ABBRUCH DER BEARBEITUNG +;*********************** +; +COMPLT: LD DE,TCOMP + CALL PSTRIN + JP GOON +QUIT: CALL CRLF + LD DE,TQUIT + JR FINIS +INTTIM: POP DE ;STACK OK +; CALL DESAK + LD DE,TNMIAB + CALL PSTRIN + LD DE,MAIN ;NEW ADDRESS + PUSH DE + RETN +FINIS: CALL PSTRIN ;AT BDOS-ERROR +GOON: + JP BOOT +; +; +;TEXT-Messages +;************* +; +TCOMP: DEFB ESC,21,0,14H,ESC,23,0 + DEFM 'Function complete !!$' +TQUIT: DEFB ESC,23,0,14H,7 + DEFM 'End Run RAMFTEST$' +TNMIAB: DEFB ESC,23,0,14H + DEFM 'Time Out !!$' +; +; +INI_MSG:DEFM 'ECB-4PIO Init all PIO Bit-Mode ',CR,LF,'$' +PIO0ADW:DEFM 'ECB-4PIO Write to PIO0AD ','$' +PIO0ADR:DEFM 'ECB-4PIO Read from PIO0AD ','$' +PIO0BDW:DEFM 'ECB-4PIO Write to PIO0BD ','$' +PIO0BDR:DEFM 'ECB-4PIO Read from PIO0BD ','$' +PIO1ADW:DEFM 'ECB-4PIO Write to PIO1AD ','$' +PIO1ADR:DEFM 'ECB-4PIO Read from PIO1AD ','$' +PIO1BDW:DEFM 'ECB-4PIO Write to PIO1BD ','$' +PIO1BDR:DEFM 'ECB-4PIO Read from PIO1BD ','$' + +PIO_SRTMSG: + DEFM 'ECB-ZILOG PERIPHERALS start test 1.0',CR,LF,'$' +PIO_ENDMSG: + DEFM 'ECB-ZILOG PERIPHERALS end test 1.0',CR,LF,'$' +LINE_E: DEFM 'H',CR,LF,'$' +; + IF1 + .PRINTX 'Pass 1 complete' + ENDIF +; + IF2 + .PRINTX 'Pass 2 complete' + .PRINTX 'Assembly complete' + ENDIF +; + END + diff --git a/Source/Apps/Test/2piotst/Build.cmd b/Source/Apps/Test/2piotst/Build.cmd new file mode 100644 index 00000000..8d719eab --- /dev/null +++ b/Source/Apps/Test/2piotst/Build.cmd @@ -0,0 +1,13 @@ +@echo off +setlocal + +set TOOLS=..\..\..\..\Tools + +set PATH=%TOOLS%\zxcc;%PATH% + +set CPMDIR80=%TOOLS%/cpm/ + +zxcc M80 -=2piotst/l || exit /b +zxcc L80 -2piotst,2piotst.com/n/e || exit /b + +copy /Y 2piotst.com ..\..\..\..\Binary\Apps\Test\ || exit /b diff --git a/Source/Apps/Test/2piotst/Clean.cmd b/Source/Apps/Test/2piotst/Clean.cmd new file mode 100644 index 00000000..a9c92a7d --- /dev/null +++ b/Source/Apps/Test/2piotst/Clean.cmd @@ -0,0 +1,8 @@ +@echo off +setlocal + +if exist *.com del *.com +if exist *.lst del *.lst +if exist *.bin del *.bin +if exist *.rel del *.rel +if exist *.prn del *.prn diff --git a/Source/Apps/Test/2piotst/Makefile b/Source/Apps/Test/2piotst/Makefile new file mode 100644 index 00000000..6dde1f3a --- /dev/null +++ b/Source/Apps/Test/2piotst/Makefile @@ -0,0 +1,8 @@ +OBJECTS = 2piotst.com +DEST = ../../../../Binary/Apps/Test +TOOLS =../../../../Tools +OTHERS = *.rel + +include $(TOOLS)/Makefile.inc + +2piotst.com : 2piotst.rel \ No newline at end of file diff --git a/Source/Apps/Test/Build.cmd b/Source/Apps/Test/Build.cmd index ac6e0c2b..e0fca5e1 100644 --- a/Source/Apps/Test/Build.cmd +++ b/Source/Apps/Test/Build.cmd @@ -20,6 +20,7 @@ pushd rzsz && call Build || exit /b & popd pushd vdctest && call Build || exit /b & popd pushd kbdtest && call Build || exit /b & popd pushd ps2info && call Build || exit /b & popd +pushd 2piotst && call Build || exit /b & popd goto :eof diff --git a/Source/Apps/Test/Clean.cmd b/Source/Apps/Test/Clean.cmd index 9e1f36d9..ee9e01eb 100644 --- a/Source/Apps/Test/Clean.cmd +++ b/Source/Apps/Test/Clean.cmd @@ -17,3 +17,4 @@ pushd rzsz && call Clean || exit /b 1 & popd pushd vdctest && call Clean || exit /b 1 & popd pushd kbdtest && call Clean || exit /b 1 & popd pushd ps2info && call Clean || exit /b 1 & popd +pushd 2piotst && call Clean || exit /b 1 & popd diff --git a/Source/Apps/Test/Makefile b/Source/Apps/Test/Makefile index aed32df2..56f2b77a 100644 --- a/Source/Apps/Test/Makefile +++ b/Source/Apps/Test/Makefile @@ -1,5 +1,5 @@ OBJECTS = -SUBDIRS = DMAmon I2C inttest ppidetst ramtest tstdskng rzsz vdctest kbdtest ps2info +SUBDIRS = DMAmon I2C inttest ppidetst ramtest tstdskng rzsz vdctest kbdtest ps2info 2piotst DEST = ../../../Binary/Apps/Test TOOLS =../../../Tools diff --git a/Source/Apps/assign.asm b/Source/Apps/assign.asm index a3ed2981..258573e8 100644 --- a/Source/Apps/assign.asm +++ b/Source/Apps/assign.asm @@ -22,12 +22,14 @@ ; 2016-04-08 [WBW] Determine key memory addresses dynamically ; 2019-08-07 [WBW] Fixed DPB selection error ; 2019-11-17 [WBW] Added preliminary CP/M 3 support -; 2019-12-24 [WBW] Fixed location of BIOS save area\ +; 2019-12-24 [WBW] Fixed location of BIOS save area ; 2020-04-29 [WBW] Updated for larger DPH (16 -> 20 bytes) ; 2020-05-06 [WBW] Add patch level to version compare ; 2020-05-10 [WBW] Set media change flag in XDPH for CP/M 3 ; 2020-05-12 [WBW] Back out media change flag ; 2021-12-06 [WBW] Fix inverted ROM/RAM DPB mapping in buffer alloc +; 2022-02-28 [WBW] Use HBIOS to swap banks under CP/M 3 +; Use CPM3 BDOS direct BIOS call to get DRVTBL adr ;_______________________________________________________________________________ ; ; ToDo: @@ -43,6 +45,7 @@ stksiz .equ $40 ; Working stack size ; restart .equ $0000 ; CP/M restart vector bdos .equ $0005 ; BDOS invocation vector +bnksel .equ $FFF3 ; HBIOS bank select vector ; stamp .equ $40 ; loc of RomWBW CBIOS zero page stamp ; @@ -108,8 +111,11 @@ init: ld c,$0C ; function number call bdos ; do it, HL := version ld (cpmver),hl ; save it - ld a,l ; low byte - cp $30 ; CP/M 3.0? + ;push hl ; *debug* + ;pop bc ; *debug* + ;call prthexword ; *debug* + ;ld a,l ; low byte + ;cp $30 ; CP/M 3.0? ; ; get location of config data and verify integrity ld hl,stamp ; HL := adr or RomWBW zero page stamp @@ -231,18 +237,24 @@ initx: ; CP/M 3 initialization ; initcpm3: - ld hl,(bioloc) - ld de,22*3 ; offset of DRVTBL func - add hl,de ; HL := DRVTBL func - call jphl ; do it, HL := DRVTBL adr - ld (drvtbl),hl ; save it + ld a,22 ; XBIOS DRVTBL function + call xbios ; Invoke XBIOS + ld (drvtbl),hl ; save DRVTBL address +; +; The CP/M 3 drvtbl is in common memory, but the XDPHs are not. +; So, here we temporarily swap the bank to the CP/M 3 system +; bank. We cannot use the CP/M Direct BIOS call because it +; explicitly blocks use of SELMEM, so we are foreced to use +; HBIOS call. The CP/M 3 system bank is always the HBIOS +; user bank. ; ; switch to sysbnk - ld hl,(bioloc) - ld de,27*3 ; offset of SELMEM func - add hl,de ; HL := SELMEM func - ld a,0 ; bank 0 is system bank - call jphl + ld a,($FFE0) ; get current bank + push af ; save it + ld bc,$F8F2 ; HBIOS Get Bank Info + rst 08 ; call HBIOS, E=User Bank + ld a,e ; HBIOS User Bank + call bnksel ; HBIOS BNKSEL ; ; copy CP/M 3 drvtbl to drvmap working copy ld hl,(drvtbl) ; get drive table in HL @@ -278,11 +290,8 @@ initc4: djnz initc2 ; ; switch back to tpabnk - ld hl,(bioloc) - ld de,27*3 ; offset of SELMEM func - add hl,de ; HL := SELMEM func - ld a,1 ; bank 1 is tpa bank - call jphl + pop af ; recover prev bank + call bnksel ; HBIOS BNKSEL ; ; return success xor a ; signal success @@ -397,6 +406,15 @@ usage: call crlf ; formatting ld de,msgban1 ; point to version message part 1 call prtstr ; print it + ld de,msg22 ; assume CP/M 2.2 + ld a,(cpmver) ; low byte of ver + cp $30 ; CP/M 3.0? + jp c,usage1 ; if not, jump ahead + ld de,msg3 ; CP/M 3 +usage1: + call prtstr + ld de,msbban2 ; next portion of banner + call prtstr ld a,(unamod) ; get UNA flag or a ; set flags ld de,msghb ; point to HBIOS mode message @@ -404,7 +422,7 @@ usage: ld de,msgub ; point to UBIOS mode message call nz,prtstr ; if UNA, say so call crlf ; formatting - ld de,msgban2 ; point to version message part 2 + ld de,msgban3 ; point to version message part 2 call prtstr ; print it call crlf2 ; blank line ld de,msguse ; point to usage message @@ -728,13 +746,13 @@ makdph3: ; ; instcpm3: -; - ; switch to sysbnk - ld hl,(bioloc) - ld de,27*3 ; offset of SELMEM func - add hl,de ; HL := SELMEM func - ld a,0 ; bank 0 is system bank - call jphl + ; swicth to sysbnk + ld a,($FFE0) ; get current bank + push af ; save it + ld bc,$F8F2 ; HBIOS Get Bank Info + rst 08 ; call HBIOS, E=User Bank + ld a,e ; HBIOS User Bank + call $FFF3 ; HBIOS BNKSEL ; ; copy drvmap working copy to CP/M 3 drvtbl ld hl,(drvtbl) ; get drvtbl address @@ -802,11 +820,8 @@ instc3: djnz instc1 ; ; switch back to tpabnk - ld hl,(bioloc) - ld de,27*3 ; offset of SELMEM func - add hl,de ; HL := SELMEM func - ld a,1 ; bank 1 is tpa bank - call jphl + pop af ; recover prev bank + call $FFF3 ; HBIOS BNKSEL ; ; set SCB drive door open flag ld a,$54 ; SCB drive door opened flag @@ -1733,6 +1748,23 @@ cbios: call addhl ; determine specific function address jp (hl) ; invoke CBIOS ; +; Routine to call CPM3 BIOS routines via BDOS +; function 50. +; +xbios: + ld (biofnc),a ; set BIOS function + ld c,50 ; direct BIOS call function + ld (dereg),de ; set DE parm + ld de,biospb ; BIOS parameter block + jp bdos ; invoke BDOS +; +biospb: +biofnc .db 0 ; BIOS function +areg .db 0 ; A register +bcreg .dw 0 ; BC register +dereg .dw 0 ; DE register +hlreg .dw 0 ; HL register +; ; Add the value in A to HL (HL := HL + A) ; addhl: @@ -1911,10 +1943,13 @@ stack .equ $ ; stack top ; Messages ; indent .db " ",0 -msgban1 .db "ASSIGN v1.4a for RomWBW CP/M, 6-Dec-2021",0 +msgban1 .db "ASSIGN v1.5 for RomWBW CP/M ",0 +msg22 .db "2.2",0 +msg3 .db "3",0 +msbban2 .db ", 28-Feb-2022",0 msghb .db " (HBIOS Mode)",0 msgub .db " (UBIOS Mode)",0 -msgban2 .db "Copyright 2021, Wayne Warthen, GNU GPL v3",0 +msgban3 .db "Copyright 2021, Wayne Warthen, GNU GPL v3",0 msguse .db "Usage: ASSIGN D:[=[{D:|[]:[]}]][,...]",13,10 .db " ex. ASSIGN (display all active assignments)",13,10 .db " ASSIGN /? (display version and usage)",13,10 diff --git a/Source/Doc/Applications.md b/Source/Doc/Applications.md index c4680d04..eae4dd92 100644 --- a/Source/Doc/Applications.md +++ b/Source/Doc/Applications.md @@ -168,6 +168,11 @@ This command is particularly sensitive to being matched to the appropriate version of the RomWBW ROM you are using. Be very careful to keep all copies of `ASSIGN.COM` up to date with your ROM. +Additionally, the `ASSIGN` command must be able to adjust to CP/M 2.2 +vs. CP/M 3. If you utilize an RSX that modifies the BDOS version +returned, you are likely to have serious problems. In this case, be +sure to use `ASSIGN` prior to loading the RSX or after it is unloaded. + ## Etymology The `ASSIGN` command is an original product and the source code is diff --git a/Source/HBIOS/Config/RCZ80_zrc.asm b/Source/HBIOS/Config/RCZ80_zrc.asm index e03cebba..44997489 100644 --- a/Source/HBIOS/Config/RCZ80_zrc.asm +++ b/Source/HBIOS/Config/RCZ80_zrc.asm @@ -30,6 +30,7 @@ CRTACT .SET FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP ; CPUOSC .SET 7372800 ; CPU OSC FREQ IN MHZ ; +RAMSIZE .SET 1536 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) MEMMGR .SET MM_ZRC ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180] ; UARTENABLE .SET TRUE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM) diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index bd4e40a2..f6579df9 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -575,7 +575,7 @@ HBX_BNKCPY: SC Z280_BNKCPYX ; SYSCALL TO BNKCPYX RET ; -IOPRVAL .DW 0 ; TEMP STORAGE FOR IOPR +IOPRSAV .DW 0 ; TEMP STORAGE FOR IOPR ; #ELSE #IF (CPUFAM == CPU_Z280) @@ -1529,6 +1529,17 @@ MBC_SINGLE: #ENDIF ; #ENDIF +; +; IF THIS IS NOT A ROMBOOT, THEN WE NEED TO COPY THE "APP" BANK TO +; TPA. IT IS DONE PRIOR TO COPYING HBIOS TO IT'S FINAL BANK BECAUSE +; THE SOURCE OF THE APP BANK CODE MAY BE THE BANK THAT HBIOS WANTS TO +; USE AS IT'S FINAL LOCATION (PRIMARILY IN CASE OF RAMBOOT WHERE THE +; SYSTEM HAS THE MINIMUM 128KB OF RAM). +; + + + + ; ; IF ALREADY EXECUTING IN RAM, BYPASS RAM BANK INSTALLATION ; @@ -5428,7 +5439,7 @@ Z280_BNKCPY: ; SELECT I/O PAGE $FF LD C,Z280_IOPR ; I/O PAGE REGISTER LDCTL HL,(C) ; GET CURRENT I/O PAGE - LD (IOPRVAL),HL ; SAVE IT + LD (IOPRSAV),HL ; SAVE IT LD L,$FF ; I/O PAGE $FF LDCTL (C),HL ; @@ -5456,7 +5467,7 @@ Z2DMALOOP: ; ; RESTORE I/O PAGE LD C,Z280_IOPR ; I/O PAGE REGISTER - LD HL,(IOPRVAL) ; RESTORE I/O PAGE + LD HL,(IOPRSAV) ; RESTORE I/O PAGE LDCTL (C),HL ; ; SETUP RETURN VALUES diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index dcc452eb..51669aad 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -513,13 +513,13 @@ BID_RAMN .EQU (BID_RAM0 + ((RAMSIZE / 32) - 1)) ; BID_RAMD0 .EQU BID_RAM0 ; FIRST RAM DRIVE BANK ^ RAM BID_RAMDN .EQU BID_RAMN - TOT_RAM_RB ; LAST RAM DRIVE BANK | DRIVE -; ; OS BUFFERS CP/M3? -+ THESE -; ; OS BUFFERS CP/M3? | MAKE -; ; OS BUFFERS CP/M3? | UP -; ; OS BUFFERS CP/M3? | THE -BID_AUX .EQU BID_RAMN - 3 ; AUX BANK (BPBIOS, ETC.) | 256KB +; ; OS BUFFERS CP/M3? -+ THESE CPM3 BNK 5 (BUF) +; ; OS BUFFERS CP/M3? | MAKE CPM3 BNK 4 (BUF) +; ; OS BUFFERS CP/M3? | UP CPM3 BNK 3 (BUF) +; ; OS BUFFERS CP/M3? | THE CPM3 BNK 2 (BUF) +BID_AUX .EQU BID_RAMN - 3 ; AUX BANK (BPBIOS, ETC.) | 256KB CPM3 BNK 1 (TPA) BID_BIOS .EQU BID_RAMN - 2 ; BIOS BANK | RESERVED -BID_USR .EQU BID_RAMN - 1 ; USER BANK (CP/M TPA, ETC.) | RAM +BID_USR .EQU BID_RAMN - 1 ; USER BANK (CP/M TPA, ETC.) | RAM CPM3 BNK 0 (OS) BID_COM .EQU BID_RAMN - 0 ; COMMON BANK, UPPER 32K -+ BANKS BID_BOOT .EQU BID_ROM0 + 0 ; BOOT BANK -+ THESE MAKE BID_IMG0 .EQU BID_ROM0 + 1 ; ROM LOADER AND FIRST IMAGES BANK | UP THE 128KB diff --git a/Source/ver.inc b/Source/ver.inc index afcf6d1e..ea9cd84d 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,4 +2,4 @@ #DEFINE RMN 1 #DEFINE RUP 1 #DEFINE RTP 0 -#DEFINE BIOSVER "3.1.1-pre.158" +#DEFINE BIOSVER "3.1.1-pre.159" diff --git a/Source/ver.lib b/Source/ver.lib index 64bd8a1c..42a77a7b 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 1 rup equ 1 rtp equ 0 biosver macro - db "3.1.1-pre.158" + db "3.1.1-pre.159" endm diff --git a/Tools/Makefile.inc b/Tools/Makefile.inc index 59b7e6d5..da16e091 100644 --- a/Tools/Makefile.inc +++ b/Tools/Makefile.inc @@ -112,6 +112,9 @@ CPM=$(TOOLS)/cpm/bin80/ %.rel: %.mac $(ZXCC) $(CPM)/M80 -=$(basename $<) +%.com: %.rel + $(ZXCC) $(CPM)/L80 -$(basename $<),$(basename $<).com/n/e + ifeq ($(UNAME), Linux) %.eeprom: %.spin $(BSTC) -e -l $< From 4e153a2bc12782ae61515082072d83f7871d969a Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Mon, 28 Feb 2022 14:25:28 -0800 Subject: [PATCH 25/34] Add DOS/65 Boot Disk Image --- Source/Images/Build.cmd | 1 + Source/Images/Makefile | 4 +- Source/Images/d_dos65/u0/alloc.co6 | Bin 0 -> 444 bytes Source/Images/d_dos65/u0/asm.co6 | Bin 0 -> 9839 bytes Source/Images/d_dos65/u0/assign.co6 | Bin 0 -> 5688 bytes Source/Images/d_dos65/u0/bcompile.co6 | Bin 0 -> 10686 bytes Source/Images/d_dos65/u0/compare.co6 | Bin 0 -> 2893 bytes Source/Images/d_dos65/u0/copy.co6 | Bin 0 -> 541 bytes Source/Images/d_dos65/u0/cpm.co6 | Bin 0 -> 6184 bytes Source/Images/d_dos65/u0/dbasic.co6 | Bin 0 -> 10921 bytes Source/Images/d_dos65/u0/debug.co6 | Bin 0 -> 3329 bytes Source/Images/d_dos65/u0/dos65.com | Bin 0 -> 11561 bytes Source/Images/d_dos65/u0/dos65.hex | 321 +++++++++++++++++++++++ Source/Images/d_dos65/u0/dos65.s19 | 361 ++++++++++++++++++++++++++ Source/Images/d_dos65/u0/edit.co6 | Bin 0 -> 6830 bytes Source/Images/d_dos65/u0/run.co6 | Bin 0 -> 10896 bytes Source/Images/d_dos65/u0/sedit.co6 | Bin 0 -> 3841 bytes Source/Images/hd_dos65.txt | 3 + 18 files changed, 688 insertions(+), 2 deletions(-) create mode 100644 Source/Images/d_dos65/u0/alloc.co6 create mode 100644 Source/Images/d_dos65/u0/asm.co6 create mode 100644 Source/Images/d_dos65/u0/assign.co6 create mode 100644 Source/Images/d_dos65/u0/bcompile.co6 create mode 100644 Source/Images/d_dos65/u0/compare.co6 create mode 100644 Source/Images/d_dos65/u0/copy.co6 create mode 100644 Source/Images/d_dos65/u0/cpm.co6 create mode 100644 Source/Images/d_dos65/u0/dbasic.co6 create mode 100644 Source/Images/d_dos65/u0/debug.co6 create mode 100644 Source/Images/d_dos65/u0/dos65.com create mode 100644 Source/Images/d_dos65/u0/dos65.hex create mode 100644 Source/Images/d_dos65/u0/dos65.s19 create mode 100644 Source/Images/d_dos65/u0/edit.co6 create mode 100644 Source/Images/d_dos65/u0/run.co6 create mode 100644 Source/Images/d_dos65/u0/sedit.co6 create mode 100644 Source/Images/hd_dos65.txt diff --git a/Source/Images/Build.cmd b/Source/Images/Build.cmd index 63c6572d..b9b264e3 100644 --- a/Source/Images/Build.cmd +++ b/Source/Images/Build.cmd @@ -23,6 +23,7 @@ call BuildDisk.cmd nzcom hd wbw_hd512 ..\zsdos\zsys_wbw.sys || exit /b call BuildDisk.cmd cpm3 hd wbw_hd512 ..\cpm3\cpmldr.sys || exit /b call BuildDisk.cmd zpm3 hd wbw_hd512 ..\zpm3\zpmldr.sys || exit /b call BuildDisk.cmd ws4 hd wbw_hd512 || exit /b +call BuildDisk.cmd dos65 hd wbw_hd512 ..\zsdos\zsys_wbw.sys || exit /b if exist ..\BPBIOS\bpbio-ww.rel call BuildDisk.cmd bp hd wbw_hd512 || exit /b diff --git a/Source/Images/Makefile b/Source/Images/Makefile index bda9e88b..4a6a5f50 100644 --- a/Source/Images/Makefile +++ b/Source/Images/Makefile @@ -16,7 +16,7 @@ HD512PREFIX = HD1024PREFIX = hd1024_prefix.dat OBJECTS = $(FDIMGS) -OBJECTS += $(HD512IMGS) hd512_combo.img $(HD512PREFIX) +OBJECTS += $(HD512IMGS) hd512_dos65.img hd512_combo.img $(HD512PREFIX) OBJECTS += $(HD1024IMGS) hd1024_combo.img $(HD1024PREFIX) OTHERS = blank144 blankhd512 blankhd1024 @@ -71,7 +71,7 @@ blankhd1024: @sys= ; \ case $@ in \ (*cpm22*) sys=../CPM22/cpm_wbw.sys;; \ - (*zsdos* | *nzcom*) sys=../ZSDOS/zsys_wbw.sys;; \ + (*zsdos* | *nzcom* | *dos65*) sys=../ZSDOS/zsys_wbw.sys;; \ (*cpm3*) sys=../CPM3/cpmldr.sys;; \ (*zpm3*) sys=../ZPM3/zpmldr.sys;; \ esac ; \ diff --git a/Source/Images/d_dos65/u0/alloc.co6 b/Source/Images/d_dos65/u0/alloc.co6 new file mode 100644 index 0000000000000000000000000000000000000000..bf0fda846bcaa7c4c94e0c845a3f26f9dd69885f GIT binary patch literal 444 zcmX|-J4*vW5XbNK9@*V{}5)nxw_#kO=5YT)85eu(RWu=g@un-XuvuuUFXq`&CPR?=us)5 zf+nbM^=VXQXGG{y7=2ynhA~|p*}@*+JfOmwtb#S}eG3|9GL&*SH814M zEi%K#8K(VVnGB_5$8+E)1LOr}b)@|NqT}9ANV9;TL5mEh`nfCb>dF?RBo{b{9BCuU zksRxEi+NZ_YS~}&*ZqoL-taHU6}cui$H2fa=_l!UBo<0X zNhnApF_fNCLj{`}FPj6doYGs|KvF`nydi_L7~omRzi*1y zJjj!R^btXsEp`)0AO%7CxG+p@S7zl$sBoo6{#41f?^E|YvclfG^a!8q*8;W83%u)- z0+|*xvy>OS)HZWWwiQejVd)X}3(VCc+vbFv|8oNy{g1oN(x|Xtzc|b47aSM+nKeeb z?bAiWDSO4vOch6NnA)-2qttOFAb%Rmefpk9`Erl)<#KjvpLg)(p1NTr;KIg~p^ zEp9XUoiKlR;lb&?wXrjH@WzKrPupv=K{6`nl2JivM62RJ8%n4;prV(?A218@etO4@ zL6*F9|BOlA50FxBe*K)8dSw&yoz^U>k+tNgnVFVMOJ-_f0yS&DQjOZbDOEW}>*Y9Y zknd28a!@hI{bbb+JH}t#&xGYy%mRB`Yb`WCYZjKDkH?Q8zQ&@_7?86%DJEP3)DmQ9(XxGxLzY zaO6pu)N231XTMmRuTc$X4t1MW$7Qd0bL6A-1$U0Og$h>nt^%|g)~f@k!V7q{Smmr~ zjvs9=yUD@&GK3iL<-@_%az!C{mwy44d*oj5y;J!^PnX=4AIaZFCY=RiuDDh0XSTBd zgv#74`4M#8A%CdWsNTjbl^v{3y`2e_57qkQN67v41#8hEeXjwLXDzy=#RhdR3IZ>H z(V__j4t$K*oWoa)|7aF4H#u5QoUVddT533ACXcx2R@Ozgunn}Ab9?Q1FjL+z=!nI%AN8MG#KQP9XGW0 z*2-NABe_+!zBU+|fGub}0G#9jCyI23R>y~H4fI2rKnH7+>Ckr5UhknHxtI1F8kBn! z!YtbW8`e&4d=}9X6-#M9n$4P zbWoQM>b_32MudbNpxBUx6LQOm*!%#(&r&k7 z&hrA^X4ZP%jkkq4&pX)9VA@eSB=0Sm>xOy<3w5;1F34Rg?AK`QuG`x?dQC)!yodJ6 zz;kF+zTS_va94m3(60-ppIKenu9>BWox?d~I2SUU`&x$k4ic5O;9%R3s@5a7_>tX? zKksr|1GC#+?t1-jkToB7{|dtAUGm^E9z#crIbV8K;^CnE*vZ2|>b~GC2y8QTU1%(K^A%n^96aSZ?tT|#I(W)Ohn7#dj?`7wBX#n` z0UG<{qw-^9vwPv_nT{X=%c5>%LX18ZugZ^2`yU%{An(+vca=?nKU?TKgEWL~xpGt? zC|3Fw`YzsCUVkEBV{d8SQ`eKV@YuFSTM5v_k*7rBAYd!We86 zAWc6mRIJdWF2^@@**b^9Cb>!JlGl|CMH4iCwTU^8yWctYERl!LT_Wlr z*u4EUWG|~?I62#|G^1A?K`)mF9Y4_Unz>-lty%uJ{&^QE+u;RxlAqXN`2WQTN^pXk5`go%{@EVkpgMSgBCU407HpOx=d`sD|xDEsI>xr0VxaEKP*qa7sVp*}oNnP$!y z-NwRX(u1!=);*(I3PQ;|e8nui*Q6L?D+69AbbqaP#Rr>oRPJY2Di5&B80T2%8>r)B z|7#r}RJKiPEzc;&dODfqg!H2(?}=-S1GSq*vz{Qa9gnjHz)Q;a0boMD zmx>qe1KG+tX=)waci~?4cG0jf{^D%^lc~ymSoq%M)%^It{#$Lulhp&5AwzA`sVeuCjQOL|6HV{ZHaKn@ZH42uzD9oR zC?mY!D^hShPoMQj+4;>ljl5CN&{+5--zoQKKO>hNWxHZ7nism!bD^7ygV>VBTCfwD zrLQ#4Z-V0%?3zun7tQE0w;fx2*`hc=*e2D?1oDKtV3yu&r2+QsN??H?N26I_uPz=5 zs)YHFx73j4RwuOvbxIS|46;uOVbv`C-jny24Cf99W2^s;;CP2_iY;u!iHPH~aUdhw z7(Yxj(ZLHHtd0&{@M&&<*wMm|2ngpP@`P)l`;s5=yW)`+J(VpLlJ|4n%~E$;Z3e5- ziiIj$xc&q{yW4oXwP=t$ZR9KUbmu?=z|>2}+LT5-=oaLrEqpW6)-7}^Eky%jtz^ji z@*UDG>(^qB_8^XWWgjHd@}{qug_Y?uhl4Bb_c+=XpzYDo_G-<@aHa)6Xv2^}4B?0Y zbfJ4yc}MmropQ5cmN}#Pc}Q29u(x3*8%8>%pL$BpT9)&$7G${-aHiKfWzV_SF_L!P z?=eshPj()7X!DBuCj%|@D+FkCC=E=g= zqJj2)dA9$e37C79QKDS|I}G`b-BbYT$5ZmOMaW-+IT{y(Pzt=%- zX4`pZehSw~`y)a40f3X1@(%w2fG*`$j*Mt7J{Y}&>nnQ{le`NW7Y_2K0NYU6UD-`< zRV7Wj20-UQYi5mlfq8f<(5?gQ8@o(0Yh|~z-;2PuDh)i&Fca(1dw0>@pu;q`OS0BFrM>HdW@1nbTF5j&-7Tk&p$auXGb$8i$_V|l0cXp(ivy||7`y(;W7e9z+pu3GcwYRz|d<3@yJ1?>g$w}O9mz|C(xa)LI` z-w;2|uO&Vr(8sNxLmSFyJI>!|JEpuXcPfXALH(p!UobAuH7r_;&svScZ{q0MST-J? za}LwSD<+gpOU_dDDdpALIb`R0WmH!f=4_SQWS`t2x62#k@soYsCj;FlZ|m0QuF94g zJbsY*xn22XZS=1J!%i^AL;4)FoxEhH8}L9M=+J?EU%%lA%xZ$tj%{1|QakQNxJr{X zRoe9{nYDJL!*8_X%7&{oDc}MrlMSV_B)N~ILYWM?rP1Mkzhnm_Vj_CI#}0oqnc2Q` zh@iVT9+t#(qvL>>&cu@mvLkrQE&U-3h)a?<7LrIb9X}wFsF;b5B|_O``h7EDtxPhV zjVH!PW@1c$_cy+me6RYh`Z_yCI#L}EcAV;X zp@Vh&uA{3n+&SG@=%k%5bxtIr;=Xu7jIN>cOQEnRkyKhd5Km5Iq$%j7w_n#bnI_}$ zOol6zOhuAW(I1LN(;{e1B(vl|NQy`Op-5z6d_v-6ka2X;n?jP5JP4TklIer|4lyn6 z6VqZMB9eH51jAFXPnrY|g1>Yq0V=>n%_0);t>KC$#o9VyaSWpl#glf1*!^=5GrEP|+H!v9B>ulo~;#?xXX3(vVeAej=Od6a-4 z`01EPJ}jn_I)5M7B^1sir3t{|4Exg}=;nSH#vG9tNlxhgj>;HTSo73tD`clqqP|Qv z7SBMBOg23MEI_(8ESv=741u>pNgXIzvoh@N4{e*=HnlCYjc~Ln5=x6OW=2dOfE(%l zlkun0$+2{397InfU=NZ&r0DQ)hm5XSl1-9<>uO!M8`uPGoENy)hz^l6o=Hxm;V0Y? zFmTPL(fENlTq`_P;|cC?1LN10^X6qMP zpJ@7O%XeG8)dClU_i^SE(PS!%S0Xuvi4w`o{y3id5qXKED8)00q!fxqpnWJKg(H!0 zBoh|z49BzK@pw2PhEq~Fy+3>)5nEBY@$N%!nfA`HFR`Id$hyJmkXt3Z9 z->RXxxmtBstIc@eb?xJZ;Q#Y67|8#zyZeS!s#SrH0t)`9RvQ`&2B86e_*SbvU$yGR z3k`UA@n8FJfzfDnI-NHBH{*+sv97KGPyCxL#(KfpY~)g_6*9a{b_cIEH-D_Vu29ze z1I%qm9r3<4`JI2bcz$W+c&M_vERnC4iu>L$#)Rp<-h1}u{$=>xPk%l?_srSvo_OlC z;o2vZ8NXKi;5VG+gBz|%Q|ZLD;?4I>25vHNlYyHI++^S;12-AC$-qqpZZdF_fjy&O_u-w literal 0 HcmV?d00001 diff --git a/Source/Images/d_dos65/u0/assign.co6 b/Source/Images/d_dos65/u0/assign.co6 new file mode 100644 index 0000000000000000000000000000000000000000..b84a4efc63a214136b6aba1f90b769a9ad55677d GIT binary patch literal 5688 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 literal 0 HcmV?d00001 diff --git a/Source/Images/d_dos65/u0/bcompile.co6 b/Source/Images/d_dos65/u0/bcompile.co6 new file mode 100644 index 0000000000000000000000000000000000000000..bed7b51c818e001a1e18ad5e9560fb36a3f32246 GIT binary patch literal 10686 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 literal 0 HcmV?d00001 diff --git a/Source/Images/d_dos65/u0/copy.co6 b/Source/Images/d_dos65/u0/copy.co6 new file mode 100644 index 0000000000000000000000000000000000000000..4bcaaab293f4d6a63b996243aa27194fd24992e8 GIT binary patch literal 541 zcmcJK%}T>S6ooUHBr~@~EdC{kg%OG%B6Qh>Ac`VFu~2=0Y`gRgx@cSog}y+bgw7(1 zzCfYNbWsS*q6@JU1fdW`C@vHwh%;^R4V=X{%suzqd#2PiP?F!Td$en!B;!Ge(?s(q zhlG0Ia9Yc&M@=f>agd!5ByhP16MJzF#aqZ?iUf^wi^`oIJ4le2A)ycSAloO%??FK? z;=YaiG59GA#Y@*l%`r4n=n~ZI!F|9Ml58D5WyO1d!-D@TJHOc;urHcZOW7_kJm(tx z6_#44d4wGSyM+SDeW=c#rRhMKWR4X4S2^%gX*RgQY8j&-r?9TDp|Gj2rC=*;ON8S# zxM5ErRp4z1VUv-4`TQe}tiw(}`>Fr{$QTv! literal 0 HcmV?d00001 diff --git a/Source/Images/d_dos65/u0/dbasic.co6 b/Source/Images/d_dos65/u0/dbasic.co6 new file mode 100644 index 0000000000000000000000000000000000000000..b5c19c7360cd7a39e81fbac76c66e714db5387eb GIT binary patch literal 10921 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 literal 0 HcmV?d00001 diff --git a/Source/Images/d_dos65/u0/dos65.hex b/Source/Images/d_dos65/u0/dos65.hex new file mode 100644 index 00000000..393d60db --- /dev/null +++ b/Source/Images/d_dos65/u0/dos65.hex @@ -0,0 +1,321 @@ +:203800004C21CED84820FCBB682000BCAD92CC4A4A4A4A8DF6BFAD43BFD03CA2FF9AD8A946 +:203820001120F0BB2069BCA93E20F0BBAD8BBEAC8CBE20F4BBA000AE43BFF0DFB944BFC956 +:20384000619009C97BB005295F9944BFC8CAD0EC8A9944BF8DE7BF20A4BD202BBC8DE8BFEE +:2038600020A5BCD064ADE9BFF004A915D02EA900AA8DECBFA001BD1DBFF01AD9C3BFD00490 +:20388000E8C8D0F2E8BD1DBFD0FAE8EEECBFADECBFC907D0DFADECBF0A6DECBFAAE8BD96B4 +:2038A000BEBC97BE8DEABF8CEBBFAD8FBE48AD8EBE486CEABF2034BC20A5BCADC4BF38E953 +:2038C000200DE9BFD0034C1BB820E1BBACEDBFB944BFF00AC920F0062072BCC8D0F1A93FB9 +:2038E00020F0BB4C1BB820A5BC20ABBDA920CDC4BFD00FCDCCBFD00AA93FA00B99C3BF8875 +:20390000D0FA205FBC3058ADF6BF8DF5BF20E1BB206CBCA93A20F0BBADEEBF0A0A0A0A0A39 +:203920002960A8C8A201B92801297F2072BCC8E8E00CF00CE009D0EEA92E2072BC4C26B984 +:2039400020F8BBD0192097BC2010BC8DEEBF300ECEF5BFF0B220EEBB20EEBB4C10B960A009 +:20396000344CC0BD20A5BCD057209EBC20ABBD205FBC304F20E0BDACE7BFB944BFC920D062 +:203980003C20A5BCD037ADE9BFF012CDF2BFF00D38E901CDE8BFD025ADF2BFD020ADF2BF5A +:2039A0008DE9BFA9008DD3BF20ABBD205FBC100920E0BD2097BC4C27BCA03ED0082034BC09 +:2039C0004CC9B8A0344CC0BDA900A0088DFCBF8CFDBF2005BED07A8DF1BF0DF1BFF07220F3 +:2039E000A5BCD06D20E0BD209EBC2005BEAEC4BFE020F00A8DFCBF8CFDBFC002905320F39C +:203A0000BD20ABBD2014BC2097BC2023BC3045204ABC304418ADFDBF6DF1BF8DF1BFADFC6C +:203A2000BFACFDBF8DF3BF8CF4BF20CACA2097BC201FBCD02718ADF3BFACF4BF6980900376 +:203A4000C8F005CCF1BFD0DC2097BC2008BC3010604CC9B8A001D00AA055D006A062D002A3 +:203A6000A00A4CC0BD20A5BCC90BD013A01820C0BD20EABB4820E1BB68295FC959D0D120AA +:203A8000ABBD4C14BC20A5BCD0302047BC303220E1BB2059BCF00410203022A200BD2801AD +:203AA000C91AF0152072BC20F8BBD008AEEFBFE810EB30DEA206200301604CC9B8A029D046 +:203AC00002A0344CC0BD20D5BD20A5BCD0EC20E0BD209EBC2005BEAEC4BFE020F00320D921 +:203AE000BD20F3BD2047BC30D8ADF3BFACF4BF202FBC2059BCD00620B7CA4CEFBA30BE4C6A +:203B0000A4BD2005BEAEC4BFE020F0034C76BB4C72BBADC4BFC920D011ADE9BFF00938E9DE +:203B2000018DE8BF2000BC4CB8B8ADCCBFC920F0034CD9BBA202BDE4BF9DCCBFCA10F720A7 +:203B400047BC10034CD6BB20D5BD202FBC2059BCD01E20B7CACD91BE9007CC92BE90EBB0F7 +:203B600007CC92BE90E4F0E220A4BD2059BCF06C306AA900A0088DCBBB8CCCBB2034BC2089 +:203B8000A5BCADE9BF8DC3BFA21020A7BCADE9BF8DD3BFA0008CE3BFA220BDC3BF9D070143 +:203BA000CA10F7E8B944BFF007C920F003C8D0F4A9008D2801B944BF9D2901F007E8C8EEBA +:203BC0002801D0F120E1BB20A4BD200008ADE8BF2000BC4C1BB82034BC4CC9B8A04A4CC074 +:203BE000BDA90D20F0BBA90AD006A201D043A920A202D03DA20AD039A20BD035A20DD031B7 +:203C0000A20ED02DA20FD029A210D025A211D021A212D01D2097BCA213D016A214D012A219 +:203C200015D00EA216D00AA217D006A219D002A21A4C0301ADE9BFF01F38E901CDE8BFF0ED +:203C400017ADE8BF4C00BC20ABBDA9008DE3BF2097BC2004BC8DEEBF602097BC4C1BBC20EE +:203C600097BC200CBC8DEEBF6020E1BB202BBC1869418EEFBF8CF0BF20C1C8B01048AD9085 +:203C8000CC20F0BB68094020F0BBAD8FCC20F0BBACF0BFAEEFBF60AD94BEAC95BE60ADE933 +:203CA000BF8DF2BF60A2008A48A9008DE9BFACE7BF2072BD8CEDBFF00D290F48C8B944BF7B +:203CC000C93AF00A6888ADE8BF9DC3BF1008688DE9BF9DC3BFC8A9088DECBF207FBDF01D96 +:203CE000E8C92AD007A93F9DC3BFD0049DC3BFC8CEECBFD0E6207FBDF011C8D0F8E8A92083 +:203D00009DC3BFCEECBFD0F5B944BF48A9038DECBF68C92ED023C8207FBDF01DE8C92AD030 +:203D200007A93F9DC3BFD0049DC3BFC8CEECBFD0E6207FBDF00EC8D0F8E8A9209DC3BFCE03 +:203D4000ECBFD0F5A9038DECBFE8A9009DC3BFCEECBFD0F58CE7BFA9008DECBF68A8A20B51 +:203D6000C8B9C3BFC93FD003EEECBFCAD0F2ADECBF60B944BFF007C920D003C8D0F460B974 +:203D800044BFF01CC9209019F016C93DF012C92EF00EC93AF00AC93BF006C93CF002C93E8A +:203DA000604CC9B8A928A0014C2FBCA9008DC3BFADE9BFF01F38E901CDE8BFF0174C00BC6C +:203DC0008CF0BF20E1BBACF0BFB9AFBEF0062072BCC8D0F560A900A0088DF3BF8CF4BF600B +:203DE000A20FBDC3BFBCD3BF9DD3BF989DC3BFCA10F060A20FBDD3BF9DC3BFCA10F7ADF2E6 +:203E0000BF8DE9BF60A9098DF7BF20A5BCADE9BFD0678DF8BF8DF9BFA8B9C4BFC924D0061C +:203E2000A90F8DF7BFC8C8B9C3BFC920F04E20A1CA900E20ABCAB041E906A20FECF7BFD0D4 +:203E400038290F48ADF8BF8DFABFADF9BF8DFBBFAEF7BF18ADF8BF6DFABF8DF8BFADF9BFA5 +:203E60006DFBBF8DF9BFB011CAD0E9686DF8BF8DF8BF90B2EEF9BFD0AD4CC9B8ADCCBFC98F +:203E800020D0F6ADF8BFACF9BF604C42BF4CB4B84C03B84CC3BF4CE6B84CC8B94C65BA4CCC +:203EA00085BA4C64B94C02BB4CC6BA4C12BBFF004E4F2053504143450043414E204E4F5461 +:203EC00020434C4F534500414C4C2046494C45532028592F4E293F00524541442045525235 +:203EE0004F52004E4F5420464F554E440046494C4520455849535453004C4F41442045529D +:203F0000524F520043414E204E4F54204F50454E005752495445204552524F520044495265 +:203F20002000534156452000455241200054595045200052454E2000474F20004C4F4144DD +:203F400020007F0000000000000000000000000000000000000000000000000000000000C2 +:203F6000000000000000000000000000000000000000000000000000000000000000000041 +:203F8000000000000000000000000000000000000000000000000000000000000000000021 +:203FA000000000000000000000000000000000000000000000000000000000000000000001 +:203FC0000000000000000000000000000000000000000000000000000000000000000000E1 +:203FE00000000000434F360000000000000000000000000008000009000000000008D88D7B +:2040000098CB8DDCCB8C99CB8CDDCB8E9ACBE024B050BD54CBF008A9FF8D97CB20E9C2A90F +:20402000008D9FCBAD9ACB0A6D9ACBAAE8BD76C0BC77C08DA0CB8CA1CBADE4CA48ADE3CA36 +:2040400048AD98CBAC99CB6CA0CB8D9BCB8C9CCBAD9FCBF00DA0009102ADA9CB8D98CB20C3 +:2040600004C32C97CB100820E9C2A9008D97CBAC9CCBAD9BCB604CEAC04CDBC24C19C94C91 +:204080006BCC4C68CC4C65CC4C8BC84C1FC14C2AC14CD0C84C85C94C9BC84C83CC4C32C3E1 +:2040A0004C04C34CAFC54CEAC54C0EC64C3AC14CA2C14C42C14CC7C14CB7C64C80C14C3225 +:2040C000C14C2EC14CF9C24C23C14C6DC54C36C14CE2C04CE6C04CFAC04C0EC14C18C14C7A +:2040E00089CC8D95CB60AD95CB602C97CB100820E9C2A9008D97CB4C59CC2086CC8DC5CBA8 +:204100008CC6CB8EC7CB8A2980A8ADC5CB60ADC7CB297FA8ADC6CB60AD6CC3AC6DC360ADF8 +:20412000060160ADD4CBACD5CB608D060160ADAACB60ADABCB60ADACCB602012C3A90D4CAC +:204140001BC62012C3208FC5ADB5CBCDB6CB9013C980F003A90160A20120F3C6C900D0F4A8 +:204160008DB5CB2084C7ADB0CB0DB1CBD003A902602066C620ACC4203DC8209EC5A90060AB +:204180002012C3201AC8A90C2013C63014A900A0109102A90CA2102086C6A90C201BC610B1 +:2041A000EC602012C3201AC8A90C2013C63017A20020EAC7ACAFCBAD53CB91042043C8A9FA +:2041C0000C201BC610E9602012C3201AC8208FC5ADB5CBC9809003A901602084C7A9008D5A +:2041E000D9CBADB0CB0DB1CBF0034CAAC2A9028DD9CBAD91CB48C910F01AA8882CC0CB10B8 +:204200000188B1028DB0CBC8A9002CC0CB1002B1028DB1CBADB0CB8DA5CB8DA7CBADB1CB17 +:204220008DA6CB8DA8CBADA7CBCDCBCBD008ACA8CBCCCCCBF012EEA7CBD003EEA8CBADA5BC +:20424000CB0DA6CBF018D00BADA5CB0DA6CBD003A8F030ADA5CBD003CEA6CBCEA5CBADA53D +:20426000CBACA6CB2051C5D009ADA5CBACA6CB4C83C2ADA7CBACA8CB2051C5D0A9ADA7CB70 +:20428000ACA8CB8DB0CB8CB1CB0DB1CBD00468A90260ADB0CB2065C568A8ADB0CB9102AD35 +:2042A000B1CBC82CC0CB100291022066C620ACC42049C8AEB5CBECB6CB9005E88EB6CBCA60 +:2042C000E07FD011209EC5A20020F3C6C900D00AA9FF8DB5CB209EC5A90060208BC820C168 +:2042E000C89005482019C96860A207B502BCDCCB9DDCCB9402CA10F360A502A4038504842A +:20430000054C7ACCAD98CBCDAACBF0EC8DAACB4C45C3A000B102F01938E90129078D98CBE4 +:20432000ADAACB8DA9CBB1028D9FCB9891022004C360A9028DAACB8DABCBA928A001850295 +:20434000840320F9C2ADAACBC908900F206CC8ADE6CAACE7CA20D0C84CEAC02071CC8D6C57 +:20436000C38C6DC30D6DC3F0E3A00DB9FFFF99CBCB8810F7ADD1CBA81869038DC4CBB98BB7 +:20438000CB8DC3CBADD2CB8DC1CBADD3CB4A6EC1CB4A6EC1CB8DC2CBA9008DC0CBADCCCBE2 +:2043A000F00588386EC0CBB988CB8DDACB38A91FF988CB8DDBCBAEAACBBD80CB2DABCBD0F4 +:2043C0000CBD80CB0DABCB8DABCB4CCEC360202EC8ADCBCB8DC8CBADCCCBA2034A6EC8CB59 +:2043E000CAD0F98DC9CBEEC8CBD003EEC9CBADD4CBACD5CB85068407A000A9009106E606B9 +:20440000D002E607ADC8CBD003CEC9CBCEC8CBADC8CB0DC9CBD0E3ADC1CB8DC8CBADC2CBE0 +:20442000AEC4CB4A6EC8CBCAD0F98DC9CBEEC8CBD003EEC9CB8EB0CB8EB1CBADB0CBACB1D2 +:20444000CB2065C5EEB0CBD003EEB1CBADC8CBD003CEC9CBCEC8CBADC8CB0DC9CBD0DC201E +:204460007EC420DEC7A2012026C73011ACAFCBB104C9E5F0F0A20120EAC74C65C460206E04 +:20448000CCADCFCBACD0CB4C74CCADAECB8DB1CBADADCB4EB1CB6A4EB1CB6A8DB7CB8DB02E +:2044A000CBADB1CB8DB8CBA9008DB2CBA2008ECACB8EA2CB8EA3CB8EA4CBADB0CBCDA2CB2A +:2044C000ADB1CBEDA3CBADB2CBEDA4CB902118ADA2CB6DCDCB8DA2CBADA3CB6DCECB8DA39F +:2044E000CB9003EEA4CBE8D0D1EECACB4CBAC4CAE0FFD003CECACB8A186DCFCBAAADCACBB7 +:204500006DD0CBA88A2074CC38ADA2CBEDCDCB8DA2CBADA3CBEDCECB8DA3CB38ADB0CBED47 +:20452000A2CBAAADB1CBEDA3CBA88A2089CC4C77CC488407A00346076A88D0FA186DD4CB07 +:204540008506A5076DD5CB8507682907AABD78CB602031C5310660E001F00A2031C549FF03 +:2045600031069106602031C51106910660AEAACBBD80CB0DACCB8DACCB60A900A07F187185 +:20458000048810FA60AEAACBBD80CB2DACCB60A020B1028DB5CBA00FB1028DB6CB60AEB543 +:2045A000CBE88AA0209102ADB6CBA00F9102602012C32011C63032A90C0DAFCBA8B104AA0A +:2045C00098291FA88A9102980DAFCBA8C898291FD0EBA00CAD92CBD102F00B9102A980903C +:2045E000010AA00F9102ADB9CB602012C32011C6301B2085C5D013A00CB10248980DAFCB93 +:20460000A868D1046E90CB2082C6ADB9CB602012C3A90D4820DEC7207EC4688DB3CBA200C4 +:204620008EB4CB2026C7303DAEB3CBACB4CBEEB4CBB102C00CD0138D92CB48980DAFCBA8D4 +:204640006851042DDBCBF017D0D4C93FF01148980DAFCBA868851CB104297FC51CD0BFCA67 +:20466000D0C9ADB9CB60AEC4CB0EB0CB2EB1CB2EB2CBCAD0F4ADC3CB2DB5CB0DB0CB8DB0BA +:20468000CB60A920A2008DB3CBCEB3CB188A6DB3CBA8C00CF004C00FD0052C90CB100DB13F +:2046A0000248ADB3CB0DAFCBA8689104CEB3CB10DB208AC44C43C82012C3201AC8A5024877 +:2046C000A50348ADE9CAACEACA85028403A9012013C6688503688502ADB9CB3015A00DA9CE +:2046E000009102C8C021D0F9386E90CB2082C6ADB9CB608E9ECB20EDC5302AA00CB1021821 +:204700006901291FF01791022011C6100BAD9ECBD01320BAC64C1BC720B2C51003A90160C0 +:20472000208FC5A900608A48EEADCBD003EEAECBADD2CBCDADCBADD3CBEDAECBB00568AA83 +:204740004CDEC7ADADCB29038DB9CB0A0A0A0A0A8DAFCBF00568AA4C62C7208AC4203DC8BE +:2047600068AAADB9CB602CD6CB30FACAD009207AC520C8C7910860207AC520C8C7D108F01E +:20478000E44C6DC5AEC4CBADB5CB4ACAD0FC8DB0CB38A908EDC4CBAAA00CB1022DDACB4ADB +:2047A0002ACAD0FC186DB0CB2CC0CB10010A1869108D91CBA8B1028DB0CBC8A9002CC0CB62 +:2047C0001002B1028DB1CB604818ADB7CB6DD7CB8508ADB8CB6DD8CB8509A0006860A9FFA2 +:2047E0008DADCB8DAECB8DB9CB6018ADAFCB6910A88CBECB8A48B1048DBFCBC8207EC80DEF +:20480000BFCBF00A207EC8A8ADBFCB2057C568AAACBECBC898290FD0D8602085C5F01D2015 +:204820006CC8ADECCAACEDCA20D0C84CEAC0AEAACBBD80CB49FF2DACCB8DACCB60207DCCEC +:204840004C4FC8A201A901D003ADD9CB2080CCC900F0E9206CC8ADEFCAACF0CA20D0C8207E +:204860008BC8C90DF0034CEAC04C67CAADF2CAACF3CA20D0C8ADAACB1869414C19C9A90064 +:204880002CC0CB1005B1048CBECB60AD94CB48A9008D94CB68D003205FCC60AD94CBD02057 +:2048A000205CCCC900F019205FCCC913D00D205FCCC903D0034CEAC0A900608D94CBA9FF5D +:2048C00060C90DF00AC90AF006C909F002C920608DD9C88CDAC8A000B9FFFFC924F00CC86E +:2048E0008CBACB2019C9ACBACBD0ED602C95CB100A2CBCCB3005482065CC686020C1C8B00F +:204900001848AD90CC2032C9A95E20ECC8680940202AC9AD8FCC4C32C9C909D00DA920208D +:204920002AC9AD96CB2907D0F46048209BC86820ECC8482CBCCB30032062CC68EE96CBC91F +:2049400020B026CD8ECCF021CE96CBCD8CCCD006CE96CB300F60C90DF00ACD93CCF005CD73 +:2049600094CCD005A9008D96CB60A90D202AC9A90A20ECC8AD93CBCD96CBF0EDAD8ECC207E +:2049800032C94C74C9A900A00191028C9DCBAD96CB8D93CB208BC8AC9DCBC90DD0034C64E9 +:2049A000CAC908D05EC001F0EBB10248A00138B102E901910268CE9DCBC920B040C909D075 +:2049C00030386EBCCBAD96CB8DBDCB206AC92071CAAD96CB4838ADBDCBED96CB8DBDCB0E75 +:2049E000BCCB2091CACEBDCBD0F8688D96CB4C94C9AD8FCC208DCAAD90CC208DCA2091CA1E +:204A00004C94C9C910D00BAD95CB49FF8D95CB4C94C9C918D00C206AC9AD8DCC2032C94CD1 +:204A200085C9C912D009206AC92071CA4C94C9C89102488C9DCBA0019818710291026820A7 +:204A4000FCC8AC9DCBB102C903D00BA001B102C901D0034CEAC0A001B10288D102B0034C8F +:204A600094C9A90D4C2AC9A90D202AC9A90A4C2AC9AD9DCB8DBBCBA9014868CEBBCBD00182 +:204A800060A8C89848B10220FCC84C7ACAC9209019AD8CCC482032C9A9202032C9684C327B +:204AA000C9C9309004C93A9001386020A1CA90FAC94190F5C94760ADF3BFACF4BF186980A1 +:204AC0008DF3BF9004C88CF4BF60ADF3BFACF4BF8DD9CA8CDACAA200BDFFFF9D2801E81063 +:204AE000F7604C49C04C42CB4C53CB4CF8CA4CFFCA4C32CB4CCBCBFF202D20522F4F242079 +:204B00002D2042414420534543544F520D0A3C5245543E20544F2049474E4F5245202D2DF4 +:204B2000203C4F544845523E20544F2041424F5254240D0A50454D204552524F52204F4E7A +:204B40002024202D20494E56414C494420445249564524E5000000000000000000000100F9 +:204B600000010101010101010101010100000100000000000000000080402010080402012A +:204B80000102040810204080000103070F1F3F7F000000000000000000000000000000001F +:204BA0000000000000000000000000000000000000000000000000000000000000000000F5 +:204BC0000000000000000000000000000000000000000000000000000000000000000000D5 +:204BE0000000000048DA5AAA4A4A4A4A1820F8CB8A20F8CB7AFA6860290F0930C93A30031C +:204C00001869074CB5CE48DA5AA90D20B5CEA90A20B5CE7AFA68605ADA48A000A2FF38E8F9 +:204C2000E964B0FB69642040CCA2FF38E8E90AB0FB690A2040CCAAA0012040CC68FA7A60D2 +:204C400048C000D0098AA8C000D0034C54CC8A093020B5CE68604CAECD4C21CE4CAFCE4CFD +:204C6000B2CE4CB5CE4CB8CE4CB9CE4CBACE4C5ACE4C29CE4C5ECE4C66CE4CAACE4C6DCE72 +:204C80004C8BCEA901604CBBCE4CBCCE08010C005E18500C1E020D0A6438383838622E20A8 +:204CA000202E643838622E20202E64383838382E20202020644420202020206F6F6F6F6F6F +:204CC0000D0A38382020603844202E3850202059382E2038382020205950202020643820A7 +:204CE0002020202038507E7E7E7E0D0A3838202020383820383820202020383820603862C3 +:204D00006F2E202020206438202020202064500D0A383820202038382038382020202038E7 +:204D200038202020605938622E206438383838622E205638383838622E0D0A0038382020B9 +:204D40002E384420603862202064382720646220202038442038382020603844202020209E +:204D6000206038440D0A593838383844202020605938385020202060383838385920206031 +:204D80003838383850202038386F6F62590D0A11444F532F3635204F4E20544845204E487E +:204DA000594F44594E4520332E30300D0A0078A2FF9AD8A996A0CC20BDCEA93CA0CD20BD13 +:204DC000CE2006CC2075D820AFD0201ED5207DD7546E5C5E6E54794020B9D7A9448530A98E +:204DE000BF8531A94A852EA9CE852F2037CF20B9D8A2008E88DA8E89DABD1BCE9D0001E8E7 +:204E0000E006D0F5A928A00120AACEAD82DAA9022029CE205ACEA9024C03B84C59CC4CFE5D +:204E2000BF78A2FF9AD84CEECD29078D82DAAD82DA0AAABD3ACEBC3BCE6012DA20DA2EDA73 +:204E40003CDA4ADA58DA66DA74DA00000100300030013002300330043006A900A000188D39 +:204E60008ADA8C8BDA608D8CDA8C8DDA60201BCF29F0C900D004202CD960C920D003A9FF8E +:204E800060C930D0034C70D2A9FF60201BCF29F0C900D0042060D960C920D003A9FF60C94A +:204EA00030D00420C4D260A9FF6085F484F5604C9DD04C8ED04C6FD0606060606085F084B7 +:204EC000F1A000B1F0C900F00720B5CEC84CC3CE6048AD8CDA2903182AAABDF2CE85EEE8ED +:204EE000BDF2CE85EFA5F485ECA5F585ED2028CF686009E389E309E489E448AD8CDA290393 +:204F0000182AAABDF2CE85ECE8BDF2CE85EDA5F485EEA5F585EF2028CF6860DAAD82DA29DB +:204F2000070AAABD4ACEFA605AA000B1EE91ECC898C980D0F67A602006CC48DA5AA200BD5B +:204F400053CFE8C924F00620B5CE4C3FCF7AFA684C67CF4469736B20436F6E666967757221 +:204F60006174696F6E3A242006CCA20048DA5AA200BD85CFE8C924F00620B5CE4C71CF7A81 +:204F8000FA684C8ACF20202020248A4A18694120B5CEA93A20B5CEA93D20B5CE20B4CFA9D2 +:204FA0003A20B5CEE8BD4ACE2017CCE82006CCE010D0B960BD4ACE4829F0C900D01F48DA91 +:204FC0005AA200BDD7CFE8C924F00620B5CE4CC3CF7AFA684CDACF4D44244C67D0C910D074 +:204FE0002048DA5AA200BDFACFE8C924F00620B5CE4CE6CF7AFA684CFECF554E4B244C67C4 +:20500000D0C920D01F48DA5AA200BD1ED0E8C924F00620B5CE4C0AD07AFA684C21D04644E8 +:20502000244C67D0C930D02248DA5AA200BD41D0E8C924F00620B5CE4C2DD07AFA684C47CC +:20504000D05050494445244C67D048DA5AA200BD63D0E8C924F00620B5CE4C4FD07AFA68A4 +:205060004C67D0554E4B2468290F2017CC606048AD6D032920C900F0F7688D680360AD6D00 +:20508000032901C900F004AD680360A90060AD6D032901C900F0F7AD6803297F60AD6D0371 +:2050A0002901C900F003A9FF60A9006000000048DA5AA200BDC8D0E8C924F00620B5CE4CCC +:2050C000B4D07AFA684CD0D05050494445203A242006CC2062D2D03548DA5AA200BDF1D0AD +:2050E000E8C924F00620B5CE4CDDD07AFA684CF8D020494F3D307824A90320E4CBA96020F4 +:20510000E4CB20F7D2209BD1B0034C36D148DA5AA200BD26D1E8C924F00620B5CE4C12D1F6 +:205120007AFA684C33D1204E4F542050524553454E54244C97D12006CC48DA5AA200BD52FA +:20514000D1E8C924F00620B5CE4C3ED17AFA684C63D1205050494445303A20426C6F636B52 +:20516000733D24A90020DBD148DA5AA200BD81D1E8C924F00620B5CE4C6DD17AFA684C9207 +:20518000D1205050494445313A20426C6F636B733D24A90120DBD12006CC60A9008D600301 +:2051A0002022D3B034A90F20D4D48A2940C900F028A90A20D4D4E001D01FA90B20D4D4E0FB +:2051C00001D016A90C20D4D4E000D00DA90D20D4D4E000D004184CDAD1386029010A0A0A8D +:2051E0000A09E0AAA000A90E20F2D42022D3B048A90FA2EC20F2D4204AD3B03C207AD348BE +:20520000DA5AA200BD18D2E8C924F00620B5CE4C04D27AFA684C1BD2307824AD84E320E488 +:20522000CBAD83E320E4CBAD82E320E4CBAD81E320E4CB2006CC186048DA5AA200BD51D298 +:20524000E8C924F00620B5CE4C3DD27AFA684C5DD24E4F542050524553454E54242006CCE6 +:2052600038602016D5A9008D6003AD6003C900602077D220D1CE602019D4AD90DACD95DAD1 +:20528000D013AD8FDACD94DAD00BAD8EDACD93DAD003A900602022D3B02720E6D3A90FA2B5 +:2052A0002020F2D4204AD3B018207AD3AD90DA8D95DAAD8EDA8D93DAAD8FDA8D94DAA9009A +:2052C00060A9FF602077D220FACE2022D3B02520E6D3A90FA23020F2D4204AD3B01620AF10 +:2052E000D32022D3B00EA9FF8D95DA8D93DA8D94DAA90060A9FF60A9008D90DA8D8EDA8D3C +:205300008FDAA9FF8D95DA8D93DA8D94DAA9808D6203A200CAE000D0FBA9008D6203200A94 +:20532000D660DA5A48A9008DADD08DAED0A90F20D4D48A2980F00EEEADD0D0F1EEAED0D0E4 +:20534000EC384C46D318687AFA60DA5A48A9008DADD08DAED0A90F20D4D48A2988C908F0BA +:20536000142901C901F00AEEADD0D0E9EEAED0D0E4384C76D318687AFA60A2008EACD0A971 +:205380000820D4D48AAEACD09D09E3E8989D09E3E8E000D0E78EACD0A90820D4D48AAEAC11 +:2053A000D09D09E4E8989D09E4E8E000D0E760A2008EACD0BD0AE3A8BD09E3AAA90820F296 +:2053C000D4AEACD0E8E8E000D0E7A2008EACD0BD0AE4A8BD09E4AAA90820F2D4AEACD0E86C +:2053E000E8E000D0E760201BCF29010A0A0A0A09E0AAA000A90E20F2D4AE8FDAA90D20F2C3 +:20540000D4AE8EDAA90C20F2D4AE90DAA90B20F2D4A201A90A20F2D460AD8ADA290F0A0A5C +:205420000A0AAAAD8CDA4A4A290F8D90DA8A0D90DA8D90DAAD8ADA8D8EDAAD8BDA8D8FDAD2 +:20544000AD8FDA4A8D8FDAAD8EDA6A8D8EDAAD8FDA4A8D8FDAAD8EDA6A8D8EDAAD8FDA4A58 +:205460008D8FDAAD8EDA6A8D8EDAAD8FDA4A8D8FDAAD8EDA6A8D8EDAAD82DA29070AAAE823 +:20548000BD4ACE8D98DAA9008D97DA186E98DA6E97DA6E98DA6E97DABD4ACE186D97DA8DA3 +:2054A00097DA18AD97DA6D8EDA8D8EDAAD98DA6D8FDA8D8FDAAD82DA8D71D8AD8FDA8D729C +:2054C000D8AD8EDA8D73D8AD90DA8D74D82090D620C5D660200ED58D620309408D620348FE +:2054E000AE6003AC61036849408D6203A9008D6203602016D58E60038C61038D62030920A6 +:205500008D620349208D6203A9008D62036048A9928D6303686048A9808D6303686020DADF +:20552000D548DA5AA200BD3AD5E8C924F00620B5CE4C26D57AFA684C40D544534B593A2421 +:205540002006CC48DA5AA200BD5CD5E8C924F00620B5CE4C48D57AFA684C63D520494F3D21 +:20556000307824A90320E4CBA96020E4CB48DA5AA200BD86D5E8C924F00620B5CE4C72D5D5 +:205580007AFA684C8DD5204D4F44453D2448DA5AA200BDA6D5E8C924F00620B5CE4C92D564 +:2055A0007AFA684CA9D54E4724AD68D8C9FFF02648DA5AA200BDC9D5E8C924F00620B5CEDA +:2055C0004CB5D57AFA684CD6D5204E4F542050524553454E54242006CC60201FD6D02A202B +:2055E00041D8A9068D620309808D6203297F8D6203200AD6A9A5A000205BD7A000206FD796 +:20560000C9A5D005A9FF8D68D8602053D8A92120DBD6A9DF20DBD6A200DAFACAD0FB6020A8 +:205620002AD8A9008D6003AD6003C90060AD68D8C9FFD0052014D7290F60AD68D8C9FFD0E4 +:2056400024202DD6F0F4A94020DBD62019D749C048293F8D66D8A200BD74D6CD66D8F00924 +:20566000E8E01CD0F368A9FF606825C08D66D88A0D66D8600D040C14030B13020A1201094C +:205680001100081005151D1C1B1A191823222120A200BD71D84A4A4A4ADAAABD56D8FADA8F +:2056A000488A0AAA689D69D8FABD71D8290FDAAABD56D8FADA488A0AAAE8689D69D8FAE80D +:2056C000E004D0CE6048DA5AA200BD69D8DA7A205BD7E8E008D0F37AFA686048A9014CE435 +:2056E000D648A900202AD809068D620309188D62038D66D8688D6003AD66D829FD8D620387 +:20570000EA09028D620329E78D620329E68D62032053D860A9014C1BD7A9002041D809061B +:205720008D620309188D6203297B8D62038D66D8AD600348AD66D809048D620329E78D62C2 +:205740000329E68D62032053D86860A99020DBD6A210A9FF20E1D6CAD0F8605A484818986B +:205760006990A820DBD66849FF20E1D6687A6018986970A820DBD62019D749FF608E66D868 +:20578000BA6885146885159AAE66D8DA5A4818E6149002E615A000B114205BD7C8C008D094 +:2057A000F6687AFA8D66D81868690885149003681A48A51448AD66D8605ADA48A00F206F5F +:2057C000D70920A920A00F205BD7A28FA0FF88D0FDCAD0FAA00F206FD729DFA9DFA00F20D2 +:2057E0005BD768FA7A605A48A00D206FD70920A00D205BD7687A605A48A00E206FD709203D +:20580000A00E205BD7687A605A48A00D206FD729DFA00D205BD7687A605A48A00E206FD792 +:2058200029DFA00E205BD7687A6048AD67D8C982F00DA9828D63038D67D8A9068D620368AF +:205840006048AD67D8C992F008A9928D63038D67D868604C41D83F065B4F666D7D077F670E +:20586000777C395E797100000000000000000000000000000048DA5AA200BD8ED8E8C9249E +:20588000F00620B5CE4C7AD87AFA684CB6D84D443A20554E4954533D322052414D4449534E +:2058A0004B3D3235364B4220524F4D4449534B3D3338344B42242006CCA200BDC7D89D00E3 +:2058C00002E8E000D0F560488415A00084148A2980C900D0388A2940C900D00DA9808D7CF1 +:2058E000036809808D7803D00BA9008D780368297F8D7C03A200DA7AB1149D0004E8E000E0 +:20590000D0F4A9808D7C03A98E8D7803606809808D7803A200DA7ABD00049114E8E000D002 +:20592000F4A9808D7C03A98E8D7803602035D920C6D9A90060201BCF29010A0A0A0A0A0A39 +:20594000297FAA2083D9E000F00CEE8EDAEE8EDAEE8EDAEE8EDAAD8EDAAC90DA2000026098 +:20596000201BCF2901C900F003A9FF602035D92083D920ECD9AD8EDAAC90DAA28020000231 +:20598000A90060DAAD8CDA4A291F8D90DAAD8ADA29030A0A0A0A0A09800D90DA8D90DAAD75 +:2059A0008ADA4A4A8D8EDAAD82DA8D71D8A9008D72D8AD8EDA8D73D8AD90DA8D74D820900E +:2059C000D620C5D6FA6048AD8CDA2901C900D007A90085EE4CDBD9A98085EEA90485EFA539 +:2059E000F485ECA5F585ED2028CF686048AD8CDA2901C900D007A90085EC4C01DAA9808543 +:205A0000ECA90485EDA5F485EEA5F585EF2028CF68607F004000000001FF0099DA0089E2E5 +:205A2000BF0040000000019B0097DB0089E2FF074000100002FF0195DC0089E2FF07400074 +:205A4000100002FF0193DD0089E2FF074000100002FF0191DE0089E2FF074000100002FFD0 +:205A6000018FDF0089E2FF074000100002FF018DE00089E2FF074000100002FF018BE10058 +:205A800089E202000000000000000000000000000000000000000000000000000000000099 +:205AA0000000000000000000000000000000000000000000000000000000000000000000E6 +:205AC0000000000000000000000000000000000000000000000000000000000000000000C6 +:205AE0000000000000000000000000000000000000000000000000000000000000000000A6 +:205B0000000000000000000000000000000000000000000000000000000000000000000085 +:205B2000000000000000000000000000000000000000000000000000000000000000000065 +:205B4000000000000000000000000000000000000000000000000000000000000000000045 +:205B6000000000000000000000000000000000000000000000000000000000000000000025 +:205B8000000000000000000000000000000000000000000000000000000000000000000005 +:205BA0000000000000000000000000000000000000000000000000000000000000000000E5 +:205BC0000000000000000000000000000000000000000000000000000000000000000000C5 +:205BE0000000000000000000000000000000000000000000000000000000000000000000A5 +:205C0000000000000000000000000000000000000000000000000000000000000000000084 +:205C2000000000000000000000000000000000000000000000000000000000000000000064 +:205C4000000000000000000000000000000000000000000000000000000000000000000044 +:205C6000000000000000000000000000000000000000000000000000000000000000000024 +:205C8000000000000000000000000000000000000000000000000000000000000000000004 +:205CA0000000000000000000000000000000000000000000000000000000000000000000E4 +:205CC0000000000000000000000000000000000000000000000000000000000000000000C4 +:205CE0000000000000000000000000000000000000000000000000000000000000000000A4 +:205D0000000000000000000000000000000000000000000000000000000000000000000083 +:205D2000000000000000000000000000000000000000000000000000000000000000000063 +:205D4000000000000000000000000000000000000000000000000000000000000000000043 +:205D6000000000000000000000000000000000000000000000000000000000000000000023 +:205D8000000000000000000000000000000000000000000000000000000000000000000003 +:205DA0000000000000000000000000000000000000000000000000000000000000000000E3 +:205DC0000000000000000000000000000000000000000000000000000000000000000000C3 +:205DE0000000000000000000000000000000000000000000000000000000000000000000A3 +:205E0000000000000000000000000000000000000000000000000000000000000000000082 +:205E2000000000000000000000000000000000000000000000000000000000000000000062 +:205E4000000000000000000000000000000000000000000000000000000000000000000042 +:205E6000000000000000000000000000000000000000000000000000000000000000000022 +:205E8000000000000000000000000000000000000000000000000000000000000000000002 +:205EA0000000000000000000000000000000000000000000000000000000000000000000E2 +:205EC0000000000000000000000000000000000000000000000000000000000000000000C2 +:205EE0000000000000000000000000000000000000000000000000000000000000000000A2 +:205F0000000000000000000000000000000000000000000000000000000000000000000081 +:205F2000000000000000000000000000000000000000000000000000000000000000000061 +:205F4000000000000000000000000000000000000000000000000000000000000000000041 +:205F6000000000000000000000000000000000000000000000000000000000000000000021 +:205F8000000000000000000000000000000000000000000000000000000000000000000001 +:205FA0000000000000000000000000000000000000000000000000000000000000000000E1 +:205FC0000000000000000000000000000000000000000000000000000000000000000000C1 +:205FE0000000000000000000000000000000000000000000000000000000000000000000A1 +:00000001FF diff --git a/Source/Images/d_dos65/u0/dos65.s19 b/Source/Images/d_dos65/u0/dos65.s19 new file mode 100644 index 00000000..8a5da23f --- /dev/null +++ b/Source/Images/d_dos65/u0/dos65.s19 @@ -0,0 +1,361 @@ +S123B7F3FD7F3ECD77DBFF0000000000004C21CED84820FCBB682000BCAD92CC4A4A4A4AB1 +S123B8138DF6BFAD43BFD03CA2FF9AD8A91120F0BB2069BCA93E20F0BBAD8BBEAC8CBE2079 +S123B833F4BBA000AE43BFF0DFB944BFC9619009C97BB005295F9944BFC8CAD0EC8A9944D2 +S123B853BF8DE7BF20A4BD202BBC8DE8BF20A5BCD064ADE9BFF004A915D02EA900AA8DEC9D +S123B873BFA001BD1DBFF01AD9C3BFD004E8C8D0F2E8BD1DBFD0FAE8EEECBFADECBFC90719 +S123B893D0DFADECBF0A6DECBFAAE8BD96BEBC97BE8DEABF8CEBBFAD8FBE48AD8EBE486C59 +S123B8B3EABF2034BC20A5BCADC4BF38E9200DE9BFD0034C1BB820E1BBACEDBFB944BFF05F +S123B8D30AC920F0062072BCC8D0F1A93F20F0BB4C1BB820A5BC20ABBDA920CDC4BFD00FBE +S123B8F3CDCCBFD00AA93FA00B99C3BF88D0FA205FBC3058ADF6BF8DF5BF20E1BB206CBC95 +S123B913A93A20F0BBADEEBF0A0A0A0A0A2960A8C8A201B92801297F2072BCC8E8E00CF0D6 +S123B9330CE009D0EEA92E2072BC4C26B920F8BBD0192097BC2010BC8DEEBF300ECEF5BFD8 +S123B953F0B220EEBB20EEBB4C10B960A0344CC0BD20A5BCD057209EBC20ABBD205FBC3075 +S123B9734F20E0BDACE7BFB944BFC920D03C20A5BCD037ADE9BFF012CDF2BFF00D38E90125 +S123B993CDE8BFD025ADF2BFD020ADF2BF8DE9BFA9008DD3BF20ABBD205FBC100920E0BDE5 +S123B9B32097BC4C27BCA03ED0082034BC4CC9B8A0344CC0BDA900A0088DFCBF8CFDBF209D +S123B9D305BED07A8DF1BF0DF1BFF07220A5BCD06D20E0BD209EBC2005BEAEC4BFE020F0EE +S123B9F30A8DFCBF8CFDBFC002905320F3BD20ABBD2014BC2097BC2023BC3045204ABC306C +S123BA134418ADFDBF6DF1BF8DF1BFADFCBFACFDBF8DF3BF8CF4BF20CACA2097BC201FBC80 +S123BA33D02718ADF3BFACF4BF69809003C8F005CCF1BFD0DC2097BC2008BC3010604CC9B5 +S123BA53B8A001D00AA055D006A062D002A00A4CC0BD20A5BCC90BD013A01820C0BD20EAF3 +S123BA73BB4820E1BB68295FC959D0D120ABBD4C14BC20A5BCD0302047BC303220E1BB20B7 +S123BA9359BCF00410203022A200BD2801C91AF0152072BC20F8BBD008AEEFBFE810EB302C +S123BAB3DEA206200301604CC9B8A029D002A0344CC0BD20D5BD20A5BCD0EC20E0BD209EF6 +S123BAD3BC2005BEAEC4BFE020F00320D9BD20F3BD2047BC30D8ADF3BFACF4BF202FBC20F2 +S123BAF359BCD00620B7CA4CEFBA30BE4CA4BD2005BEAEC4BFE020F0034C76BB4C72BBAD69 +S123BB13C4BFC920D011ADE9BFF00938E9018DE8BF2000BC4CB8B8ADCCBFC920F0034CD94C +S123BB33BBA202BDE4BF9DCCBFCA10F72047BC10034CD6BB20D5BD202FBC2059BCD01E2023 +S123BB53B7CACD91BE9007CC92BE90EBB007CC92BE90E4F0E220A4BD2059BCF06C306AA995 +S123BB7300A0088DCBBB8CCCBB2034BC20A5BCADE9BF8DC3BFA21020A7BCADE9BF8DD3BF42 +S123BB93A0008CE3BFA220BDC3BF9D0701CA10F7E8B944BFF007C920F003C8D0F4A9008D10 +S123BBB32801B944BF9D2901F007E8C8EE2801D0F120E1BB20A4BD200008ADE8BF2000BCAE +S123BBD34C1BB82034BC4CC9B8A04A4CC0BDA90D20F0BBA90AD006A201D043A920A202D0A2 +S123BBF33DA20AD039A20BD035A20DD031A20ED02DA20FD029A210D025A211D021A212D0B4 +S123BC131D2097BCA213D016A214D012A215D00EA216D00AA217D006A219D002A21A4C03FC +S123BC3301ADE9BFF01F38E901CDE8BFF017ADE8BF4C00BC20ABBDA9008DE3BF2097BC209C +S123BC5304BC8DEEBF602097BC4C1BBC2097BC200CBC8DEEBF6020E1BB202BBC1869418ED5 +S123BC73EFBF8CF0BF20C1C8B01048AD90CC20F0BB68094020F0BBAD8FCC20F0BBACF0BF95 +S123BC93AEEFBF60AD94BEAC95BE60ADE9BF8DF2BF60A2008A48A9008DE9BFACE7BF20724A +S123BCB3BD8CEDBFF00D290F48C8B944BFC93AF00A6888ADE8BF9DC3BF1008688DE9BF9DC5 +S123BCD3C3BFC8A9088DECBF207FBDF01DE8C92AD007A93F9DC3BFD0049DC3BFC8CEECBFC4 +S110BCF3D0E6207FBDF011C8D0F8E8A920EC +S123BD009DC3BFCEECBFD0F5B944BF48A9038DECBF68C92ED023C8207FBDF01DE8C92AD0AC +S123BD2007A93F9DC3BFD0049DC3BFC8CEECBFD0E6207FBDF00EC8D0F8E8A9209DC3BFCE7F +S123BD40ECBFD0F5A9038DECBFE8A9009DC3BFCEECBFD0F58CE7BFA9008DECBF68A8A20BCD +S123BD60C8B9C3BFC93FD003EEECBFCAD0F2ADECBF60B944BFF007C920D003C8D0F460B9F0 +S123BD8044BFF01CC9209019F016C93DF012C92EF00EC93AF00AC93BF006C93CF002C93E06 +S123BDA0604CC9B8A928A0014C2FBCA9008DC3BFADE9BFF01F38E901CDE8BFF0174C00BCE8 +S123BDC08CF0BF20E1BBACF0BFB9AFBEF0062072BCC8D0F560A900A0088DF3BF8CF4BF6087 +S123BDE0A20FBDC3BFBCD3BF9DD3BF989DC3BFCA10F060A20FBDD3BF9DC3BFCA10F7ADF262 +S123BE00BF8DE9BF60A9098DF7BF20A5BCADE9BFD0678DF8BF8DF9BFA8B9C4BFC924D00698 +S123BE20A90F8DF7BFC8C8B9C3BFC920F04E20A1CA900E20ABCAB041E906A20FECF7BFD050 +S123BE4038290F48ADF8BF8DFABFADF9BF8DFBBFAEF7BF18ADF8BF6DFABF8DF8BFADF9BF21 +S123BE606DFBBF8DF9BFB011CAD0E9686DF8BF8DF8BF90B2EEF9BFD0AD4CC9B8ADCCBFC90B +S123BE8020D0F6ADF8BFACF9BF604C42BF4CB4B84C03B84CC3BF4CE6B84CC8B94C65BA4C48 +S123BEA085BA4C64B94C02BB4CC6BA4C12BBFF004E4F2053504143450043414E204E4F54DD +S123BEC020434C4F534500414C4C2046494C45532028592F4E293F005245414420455252B1 +S123BEE04F52004E4F5420464F554E440046494C4520455849535453004C4F414420455219 +S123BF00524F520043414E204E4F54204F50454E005752495445204552524F5200444952E1 +S123BF202000534156452000455241200054595045200052454E2000474F20004C4F414459 +S123BF4020007F00000000000000000000000000000000000000000000000000000000003E +S123BF600000000000000000000000000000000000000000000000000000000000000000BD +S123BF8000000000000000000000000000000000000000000000000000000000000000009D +S123BFA000000000000000000000000000000000000000000000000000000000000000007D +S123BFC000000000000000000000000000000000000000000000000000000000000000005D +S123BFE000000000434F360000000000000000000000000008000009000000000008D88DF7 +S123C00098CB8DDCCB8C99CB8CDDCB8E9ACBE024B050BD54CBF008A9FF8D97CB20E9C2A98B +S123C020008D9FCBAD9ACB0A6D9ACBAAE8BD76C0BC77C08DA0CB8CA1CBADE4CA48ADE3CAB2 +S123C04048AD98CBAC99CB6CA0CB8D9BCB8C9CCBAD9FCBF00DA0009102ADA9CB8D98CB203F +S123C06004C32C97CB100820E9C2A9008D97CBAC9CCBAD9BCB604CEAC04CDBC24C19C94C0D +S123C0806BCC4C68CC4C65CC4C8BC84C1FC14C2AC14CD0C84C85C94C9BC84C83CC4C32C35D +S123C0A04C04C34CAFC54CEAC54C0EC64C3AC14CA2C14C42C14CC7C14CB7C64C80C14C32A1 +S123C0C0C14C2EC14CF9C24C23C14C6DC54C36C14CE2C04CE6C04CFAC04C0EC14C18C14CF6 +S123C0E089CC8D95CB60AD95CB602C97CB100820E9C2A9008D97CB4C59CC2086CC8DC5CB24 +S123C1008CC6CB8EC7CB8A2980A8ADC5CB60ADC7CB297FA8ADC6CB60AD6CC3AC6DC360AD74 +S123C120060160ADD4CBACD5CB608D060160ADAACB60ADABCB60ADACCB602012C3A90D4C28 +S123C1401BC62012C3208FC5ADB5CBCDB6CB9013C980F003A90160A20120F3C6C900D0F424 +S123C1608DB5CB2084C7ADB0CB0DB1CBD003A902602066C620ACC4203DC8209EC5A9006027 +S123C1802012C3201AC8A90C2013C63014A900A0109102A90CA2102086C6A90C201BC6102D +S123C1A0EC602012C3201AC8A90C2013C63017A20020EAC7ACAFCBAD53CB91042043C8A976 +S123C1C00C201BC610E9602012C3201AC8208FC5ADB5CBC9809003A901602084C7A9008DD6 +S123C1E0D9CBADB0CB0DB1CBF0034CAAC2A9028DD9CBAD91CB48C910F01AA8882CC0CB1034 +S123C2000188B1028DB0CBC8A9002CC0CB1002B1028DB1CBADB0CB8DA5CB8DA7CBADB1CB93 +S123C2208DA6CB8DA8CBADA7CBCDCBCBD008ACA8CBCCCCCBF012EEA7CBD003EEA8CBADA538 +S123C240CB0DA6CBF018D00BADA5CB0DA6CBD003A8F030ADA5CBD003CEA6CBCEA5CBADA5B9 +S123C260CBACA6CB2051C5D009ADA5CBACA6CB4C83C2ADA7CBACA8CB2051C5D0A9ADA7CBEC +S123C280ACA8CB8DB0CB8CB1CB0DB1CBD00468A90260ADB0CB2065C568A8ADB0CB9102ADB1 +S123C2A0B1CBC82CC0CB100291022066C620ACC42049C8AEB5CBECB6CB9005E88EB6CBCADC +S123C2C0E07FD011209EC5A20020F3C6C900D00AA9FF8DB5CB209EC5A90060208BC820C1E4 +S123C2E0C89005482019C96860A207B502BCDCCB9DDCCB9402CA10F360A502A403850484A6 +S123C300054C7ACCAD98CBCDAACBF0EC8DAACB4C45C3A000B102F01938E90129078D98CB60 +S123C320ADAACB8DA9CBB1028D9FCB9891022004C360A9028DAACB8DABCBA928A001850211 +S123C340840320F9C2ADAACBC908900F206CC8ADE6CAACE7CA20D0C84CEAC02071CC8D6CD3 +S123C360C38C6DC30D6DC3F0E3A00DB9FFFF99CBCB8810F7ADD1CBA81869038DC4CBB98B33 +S123C380CB8DC3CBADD2CB8DC1CBADD3CB4A6EC1CB4A6EC1CB8DC2CBA9008DC0CBADCCCB5E +S123C3A0F00588386EC0CBB988CB8DDACB38A91FF988CB8DDBCBAEAACBBD80CB2DABCBD070 +S123C3C00CBD80CB0DABCB8DABCB4CCEC360202EC8ADCBCB8DC8CBADCCCBA2034A6EC8CBD5 +S123C3E0CAD0F98DC9CBEEC8CBD003EEC9CBADD4CBACD5CB85068407A000A9009106E60635 +S123C400D002E607ADC8CBD003CEC9CBCEC8CBADC8CB0DC9CBD0E3ADC1CB8DC8CBADC2CB5C +S123C420AEC4CB4A6EC8CBCAD0F98DC9CBEEC8CBD003EEC9CB8EB0CB8EB1CBADB0CBACB14E +S123C440CB2065C5EEB0CBD003EEB1CBADC8CBD003CEC9CBCEC8CBADC8CB0DC9CBD0DC209A +S123C4607EC420DEC7A2012026C73011ACAFCBB104C9E5F0F0A20120EAC74C65C460206E80 +S123C480CCADCFCBACD0CB4C74CCADAECB8DB1CBADADCB4EB1CB6A4EB1CB6A8DB7CB8DB0AA +S123C4A0CBADB1CB8DB8CBA9008DB2CBA2008ECACB8EA2CB8EA3CB8EA4CBADB0CBCDA2CBA6 +S123C4C0ADB1CBEDA3CBADB2CBEDA4CB902118ADA2CB6DCDCB8DA2CBADA3CB6DCECB8DA31B +S123C4E0CB9003EEA4CBE8D0D1EECACB4CBAC4CAE0FFD003CECACB8A186DCFCBAAADCACB33 +S123C5006DD0CBA88A2074CC38ADA2CBEDCDCB8DA2CBADA3CBEDCECB8DA3CB38ADB0CBEDC3 +S123C520A2CBAAADB1CBEDA3CBA88A2089CC4C77CC488407A00346076A88D0FA186DD4CB83 +S123C5408506A5076DD5CB8507682907AABD78CB602031C5310660E001F00A2031C549FF7F +S123C56031069106602031C51106910660AEAACBBD80CB0DACCB8DACCB60A900A07F187101 +S123C580048810FA60AEAACBBD80CB2DACCB60A020B1028DB5CBA00FB1028DB6CB60AEB5BF +S123C5A0CBE88AA0209102ADB6CBA00F9102602012C32011C63032A90C0DAFCBA8B104AA86 +S123C5C098291FA88A9102980DAFCBA8C898291FD0EBA00CAD92CBD102F00B9102A98090B8 +S123C5E0010AA00F9102ADB9CB602012C32011C6301B2085C5D013A00CB10248980DAFCB0F +S123C600A868D1046E90CB2082C6ADB9CB602012C3A90D4820DEC7207EC4688DB3CBA20040 +S123C6208EB4CB2026C7303DAEB3CBACB4CBEEB4CBB102C00CD0138D92CB48980DAFCBA850 +S123C6406851042DDBCBF017D0D4C93FF01148980DAFCBA868851CB104297FC51CD0BFCAE3 +S123C660D0C9ADB9CB60AEC4CB0EB0CB2EB1CB2EB2CBCAD0F4ADC3CB2DB5CB0DB0CB8DB036 +S123C680CB60A920A2008DB3CBCEB3CB188A6DB3CBA8C00CF004C00FD0052C90CB100DB1BB +S123C6A00248ADB3CB0DAFCBA8689104CEB3CB10DB208AC44C43C82012C3201AC8A50248F3 +S123C6C0A50348ADE9CAACEACA85028403A9012013C6688503688502ADB9CB3015A00DA94A +S123C6E0009102C8C021D0F9386E90CB2082C6ADB9CB608E9ECB20EDC5302AA00CB102189D +S123C7006901291FF01791022011C6100BAD9ECBD01320BAC64C1BC720B2C51003A901603C +S123C720208FC5A900608A48EEADCBD003EEAECBADD2CBCDADCBADD3CBEDAECBB00568AAFF +S123C7404CDEC7ADADCB29038DB9CB0A0A0A0A0A8DAFCBF00568AA4C62C7208AC4203DC83A +S123C76068AAADB9CB602CD6CB30FACAD009207AC520C8C7910860207AC520C8C7D108F09A +S123C780E44C6DC5AEC4CBADB5CB4ACAD0FC8DB0CB38A908EDC4CBAAA00CB1022DDACB4A57 +S123C7A02ACAD0FC186DB0CB2CC0CB10010A1869108D91CBA8B1028DB0CBC8A9002CC0CBDE +S123C7C01002B1028DB1CB604818ADB7CB6DD7CB8508ADB8CB6DD8CB8509A0006860A9FF1E +S123C7E08DADCB8DAECB8DB9CB6018ADAFCB6910A88CBECB8A48B1048DBFCBC8207EC80D6B +S123C800BFCBF00A207EC8A8ADBFCB2057C568AAACBECBC898290FD0D8602085C5F01D2091 +S123C8206CC8ADECCAACEDCA20D0C84CEAC0AEAACBBD80CB49FF2DACCB8DACCB60207DCC68 +S123C8404C4FC8A201A901D003ADD9CB2080CCC900F0E9206CC8ADEFCAACF0CA20D0C820FA +S123C8608BC8C90DF0034CEAC04C67CAADF2CAACF3CA20D0C8ADAACB1869414C19C9A900E0 +S123C8802CC0CB1005B1048CBECB60AD94CB48A9008D94CB68D003205FCC60AD94CBD020D3 +S123C8A0205CCCC900F019205FCCC913D00D205FCCC903D0034CEAC0A900608D94CBA9FFD9 +S123C8C060C90DF00AC90AF006C909F002C920608DD9C88CDAC8A000B9FFFFC924F00CC8EA +S123C8E08CBACB2019C9ACBACBD0ED602C95CB100A2CBCCB3005482065CC686020C1C8B08B +S123C9001848AD90CC2032C9A95E20ECC8680940202AC9AD8FCC4C32C9C909D00DA9202009 +S123C9202AC9AD96CB2907D0F46048209BC86820ECC8482CBCCB30032062CC68EE96CBC99B +S123C94020B026CD8ECCF021CE96CBCD8CCCD006CE96CB300F60C90DF00ACD93CCF005CDEF +S123C96094CCD005A9008D96CB60A90D202AC9A90A20ECC8AD93CBCD96CBF0EDAD8ECC20FA +S123C98032C94C74C9A900A00191028C9DCBAD96CB8D93CB208BC8AC9DCBC90DD0034C6465 +S123C9A0CAC908D05EC001F0EBB10248A00138B102E901910268CE9DCBC920B040C909D0F1 +S123C9C030386EBCCBAD96CB8DBDCB206AC92071CAAD96CB4838ADBDCBED96CB8DBDCB0EF1 +S123C9E0BCCB2091CACEBDCBD0F8688D96CB4C94C9AD8FCC208DCAAD90CC208DCA2091CA9A +S123CA004C94C9C910D00BAD95CB49FF8D95CB4C94C9C918D00C206AC9AD8DCC2032C94C4D +S123CA2085C9C912D009206AC92071CA4C94C9C89102488C9DCBA001981871029102682023 +S123CA40FCC8AC9DCBB102C903D00BA001B102C901D0034CEAC0A001B10288D102B0034C0B +S123CA6094C9A90D4C2AC9A90D202AC9A90A4C2AC9AD9DCB8DBBCBA9014868CEBBCBD001FE +S123CA8060A8C89848B10220FCC84C7ACAC9209019AD8CCC482032C9A9202032C9684C32F7 +S123CAA0C9C9309004C93A9001386020A1CA90FAC94190F5C94760ADF3BFACF4BF1869801D +S123CAC08DF3BF9004C88CF4BF60ADF3BFACF4BF8DD9CA8CDACAA200BDFFFF9D2801E810DF +S123CAE0F7604C49C04C42CB4C53CB4CF8CA4CFFCA4C32CB4CCBCBFF202D20522F4F2420F5 +S123CB002D2042414420534543544F520D0A3C5245543E20544F2049474E4F5245202D2D70 +S123CB20203C4F544845523E20544F2041424F5254240D0A50454D204552524F52204F4EF6 +S123CB402024202D20494E56414C494420445249564524E500000000000000000000010075 +S123CB600001010101010101010101010000010000000000000000008040201008040201A6 +S123CB800102040810204080000103070F1F3F7F000000000000000000000000000000009B +S123CBA0000000000000000000000000000000000000000000000000000000000000000071 +S123CBC0000000000000000000000000000000000000000000000000000000000000000051 +S123CBE00000000048DA5AAA4A4A4A4A1820F8CB8A20F8CB7AFA6860290F0930C93A300398 +S123CC001869074CB5CE48DA5AA90D20B5CEA90A20B5CE7AFA68605ADA48A000A2FF38E875 +S123CC20E964B0FB69642040CCA2FF38E8E90AB0FB690A2040CCAAA0012040CC68FA7A604E +S123CC4048C000D0098AA8C000D0034C54CC8A093020B5CE68604CAECD4C21CE4CAFCE4C79 +S123CC60B2CE4CB5CE4CB8CE4CB9CE4CBACE4C5ACE4C29CE4C5ECE4C66CE4CAACE4C6DCEEE +S123CC804C8BCEA901604CBBCE4CBCCE08010C005E18500C1E020D0A6438383838622E2024 +S123CCA0202E643838622E20202E64383838382E20202020644420202020206F6F6F6F6FEB +S123CCC00D0A38382020603844202E3850202059382E203838202020595020202064382023 +S123CCE02020202038507E7E7E7E0D0A38382020203838203838202020203838206038623F +S123CD006F2E202020206438202020202064500D0A38382020203838203838202020203863 +S123CD2038202020605938622E206438383838622E205638383838622E0D0A003838202035 +S123CD402E384420603862202064382720646220202038442038382020603844202020201A +S123CD60206038440D0A5938383838442020206059383850202020603838383859202060AD +S123CD803838383850202038386F6F62590D0A11444F532F3635204F4E20544845204E48FA +S123CDA0594F44594E4520332E30300D0A0078A2FF9AD8A996A0CC20BDCEA93CA0CD20BD8F +S123CDC0CE2006CC2075D820AFD0201ED5207DD7546E5C5E6E54794020B9D7A9448530A90A +S123CDE0BF8531A94A852EA9CE852F2037CF20B9D8A2008E88DA8E89DABD1BCE9D0001E863 +S123CE00E006D0F5A928A00120AACEAD82DAA9022029CE205ACEA9024C03B84C59CC4CFED9 +S123CE20BF78A2FF9AD84CEECD29078D82DAAD82DA0AAABD3ACEBC3BCE6012DA20DA2EDAEF +S123CE403CDA4ADA58DA66DA74DA00000100300030013002300330043006A900A000188DB5 +S123CE608ADA8C8BDA608D8CDA8C8DDA60201BCF29F0C900D004202CD960C920D003A9FF0A +S123CE8060C930D0034C70D2A9FF60201BCF29F0C900D0042060D960C920D003A9FF60C9C6 +S123CEA030D00420C4D260A9FF6085F484F5604C9DD04C8ED04C6FD0606060606085F08433 +S123CEC0F1A000B1F0C900F00720B5CEC84CC3CE6048AD8CDA2903182AAABDF2CE85EEE869 +S123CEE0BDF2CE85EFA5F485ECA5F585ED2028CF686009E389E309E489E448AD8CDA29030F +S123CF00182AAABDF2CE85ECE8BDF2CE85EDA5F485EEA5F585EF2028CF6860DAAD82DA2957 +S123CF20070AAABD4ACEFA605AA000B1EE91ECC898C980D0F67A602006CC48DA5AA200BDD7 +S123CF4053CFE8C924F00620B5CE4C3FCF7AFA684C67CF4469736B20436F6E66696775729D +S123CF606174696F6E3A242006CCA20048DA5AA200BD85CFE8C924F00620B5CE4C71CF7AFD +S123CF80FA684C8ACF20202020248A4A18694120B5CEA93A20B5CEA93D20B5CE20B4CFA94E +S123CFA03A20B5CEE8BD4ACE2017CCE82006CCE010D0B960BD4ACE4829F0C900D01F48DA0D +S123CFC05AA200BDD7CFE8C924F00620B5CE4CC3CF7AFA684CDACF4D44244C67D0C910D0F0 +S123CFE02048DA5AA200BDFACFE8C924F00620B5CE4CE6CF7AFA684CFECF554E4B244C6740 +S123D000D0C920D01F48DA5AA200BD1ED0E8C924F00620B5CE4C0AD07AFA684C21D0464464 +S123D020244C67D0C930D02248DA5AA200BD41D0E8C924F00620B5CE4C2DD07AFA684C4748 +S123D040D05050494445244C67D048DA5AA200BD63D0E8C924F00620B5CE4C4FD07AFA6820 +S123D0604C67D0554E4B2468290F2017CC606048AD6D032920C900F0F7688D680360AD6D7C +S123D080032901C900F004AD680360A90060AD6D032901C900F0F7AD6803297F60AD6D03ED +S123D0A02901C900F003A9FF60A9006000000048DA5AA200BDC8D0E8C924F00620B5CE4C48 +S123D0C0B4D07AFA684CD0D05050494445203A242006CC2062D2D03548DA5AA200BDF1D029 +S123D0E0E8C924F00620B5CE4CDDD07AFA684CF8D020494F3D307824A90320E4CBA9602070 +S123D100E4CB20F7D2209BD1B0034C36D148DA5AA200BD26D1E8C924F00620B5CE4C12D172 +S123D1207AFA684C33D1204E4F542050524553454E54244C97D12006CC48DA5AA200BD5276 +S123D140D1E8C924F00620B5CE4C3ED17AFA684C63D1205050494445303A20426C6F636BCE +S123D160733D24A90020DBD148DA5AA200BD81D1E8C924F00620B5CE4C6DD17AFA684C9283 +S123D180D1205050494445313A20426C6F636B733D24A90120DBD12006CC60A9008D60037D +S123D1A02022D3B034A90F20D4D48A2940C900F028A90A20D4D4E001D01FA90B20D4D4E077 +S123D1C001D016A90C20D4D4E000D00DA90D20D4D4E000D004184CDAD1386029010A0A0A09 +S123D1E00A09E0AAA000A90E20F2D42022D3B048A90FA2EC20F2D4204AD3B03C207AD3483A +S123D200DA5AA200BD18D2E8C924F00620B5CE4C04D27AFA684C1BD2307824AD84E320E404 +S123D220CBAD83E320E4CBAD82E320E4CBAD81E320E4CB2006CC186048DA5AA200BD51D214 +S123D240E8C924F00620B5CE4C3DD27AFA684C5DD24E4F542050524553454E54242006CC62 +S123D26038602016D5A9008D6003AD6003C900602077D220D1CE602019D4AD90DACD95DA4D +S123D280D013AD8FDACD94DAD00BAD8EDACD93DAD003A900602022D3B02720E6D3A90FA231 +S123D2A02020F2D4204AD3B018207AD3AD90DA8D95DAAD8EDA8D93DAAD8FDA8D94DAA90016 +S123D2C060A9FF602077D220FACE2022D3B02520E6D3A90FA23020F2D4204AD3B01620AF8C +S123D2E0D32022D3B00EA9FF8D95DA8D93DA8D94DAA90060A9FF60A9008D90DA8D8EDA8DB8 +S123D3008FDAA9FF8D95DA8D93DA8D94DAA9808D6203A200CAE000D0FBA9008D6203200A10 +S123D320D660DA5A48A9008DADD08DAED0A90F20D4D48A2980F00EEEADD0D0F1EEAED0D060 +S123D340EC384C46D318687AFA60DA5A48A9008DADD08DAED0A90F20D4D48A2988C908F036 +S123D360142901C901F00AEEADD0D0E9EEAED0D0E4384C76D318687AFA60A2008EACD0A9ED +S123D3800820D4D48AAEACD09D09E3E8989D09E3E8E000D0E78EACD0A90820D4D48AAEAC8D +S123D3A0D09D09E4E8989D09E4E8E000D0E760A2008EACD0BD0AE3A8BD09E3AAA90820F212 +S123D3C0D4AEACD0E8E8E000D0E7A2008EACD0BD0AE4A8BD09E4AAA90820F2D4AEACD0E8E8 +S123D3E0E8E000D0E760201BCF29010A0A0A0A09E0AAA000A90E20F2D4AE8FDAA90D20F23F +S123D400D4AE8EDAA90C20F2D4AE90DAA90B20F2D4A201A90A20F2D460AD8ADA290F0A0AD8 +S123D4200A0AAAAD8CDA4A4A290F8D90DA8A0D90DA8D90DAAD8ADA8D8EDAAD8BDA8D8FDA4E +S123D440AD8FDA4A8D8FDAAD8EDA6A8D8EDAAD8FDA4A8D8FDAAD8EDA6A8D8EDAAD8FDA4AD4 +S123D4608D8FDAAD8EDA6A8D8EDAAD8FDA4A8D8FDAAD8EDA6A8D8EDAAD82DA29070AAAE89F +S123D480BD4ACE8D98DAA9008D97DA186E98DA6E97DA6E98DA6E97DABD4ACE186D97DA8D1F +S123D4A097DA18AD97DA6D8EDA8D8EDAAD98DA6D8FDA8D8FDAAD82DA8D71D8AD8FDA8D7218 +S123D4C0D8AD8EDA8D73D8AD90DA8D74D82090D620C5D660200ED58D620309408D6203487A +S123D4E0AE6003AC61036849408D6203A9008D6203602016D58E60038C61038D6203092022 +S123D5008D620349208D6203A9008D62036048A9928D6303686048A9808D6303686020DA5B +S123D520D548DA5AA200BD3AD5E8C924F00620B5CE4C26D57AFA684C40D544534B593A249D +S123D5402006CC48DA5AA200BD5CD5E8C924F00620B5CE4C48D57AFA684C63D520494F3D9D +S123D560307824A90320E4CBA96020E4CB48DA5AA200BD86D5E8C924F00620B5CE4C72D551 +S123D5807AFA684C8DD5204D4F44453D2448DA5AA200BDA6D5E8C924F00620B5CE4C92D5E0 +S123D5A07AFA684CA9D54E4724AD68D8C9FFF02648DA5AA200BDC9D5E8C924F00620B5CE56 +S123D5C04CB5D57AFA684CD6D5204E4F542050524553454E54242006CC60201FD6D02A20A7 +S123D5E041D8A9068D620309808D6203297F8D6203200AD6A9A5A000205BD7A000206FD712 +S123D600C9A5D005A9FF8D68D8602053D8A92120DBD6A9DF20DBD6A200DAFACAD0FB602024 +S123D6202AD8A9008D6003AD6003C90060AD68D8C9FFD0052014D7290F60AD68D8C9FFD060 +S123D64024202DD6F0F4A94020DBD62019D749C048293F8D66D8A200BD74D6CD66D8F009A0 +S123D660E8E01CD0F368A9FF606825C08D66D88A0D66D8600D040C14030B13020A120109C8 +S123D6801100081005151D1C1B1A191823222120A200BD71D84A4A4A4ADAAABD56D8FADA0B +S123D6A0488A0AAA689D69D8FABD71D8290FDAAABD56D8FADA488A0AAAE8689D69D8FAE889 +S123D6C0E004D0CE6048DA5AA200BD69D8DA7A205BD7E8E008D0F37AFA686048A9014CE4B1 +S123D6E0D648A900202AD809068D620309188D62038D66D8688D6003AD66D829FD8D620303 +S123D700EA09028D620329E78D620329E68D62032053D860A9014C1BD7A9002041D8090697 +S123D7208D620309188D6203297B8D62038D66D8AD600348AD66D809048D620329E78D623E +S123D7400329E68D62032053D86860A99020DBD6A210A9FF20E1D6CAD0F8605A48481898E7 +S123D7606990A820DBD66849FF20E1D6687A6018986970A820DBD62019D749FF608E66D8E4 +S123D780BA6885146885159AAE66D8DA5A4818E6149002E615A000B114205BD7C8C008D010 +S123D7A0F6687AFA8D66D81868690885149003681A48A51448AD66D8605ADA48A00F206FDB +S123D7C0D70920A920A00F205BD7A28FA0FF88D0FDCAD0FAA00F206FD729DFA9DFA00F204E +S123D7E05BD768FA7A605A48A00D206FD70920A00D205BD7687A605A48A00E206FD70920B9 +S123D800A00E205BD7687A605A48A00D206FD729DFA00D205BD7687A605A48A00E206FD70E +S123D82029DFA00E205BD7687A6048AD67D8C982F00DA9828D63038D67D8A9068D6203682B +S123D8406048AD67D8C992F008A9928D63038D67D868604C41D83F065B4F666D7D077F678A +S123D860777C395E797100000000000000000000000000000048DA5AA200BD8ED8E8C9241A +S123D880F00620B5CE4C7AD87AFA684CB6D84D443A20554E4954533D322052414D444953CA +S123D8A04B3D3235364B4220524F4D4449534B3D3338344B42242006CCA200BDC7D89D005F +S123D8C002E8E000D0F560488415A00084148A2980C900D0388A2940C900D00DA9808D7C6D +S123D8E0036809808D7803D00BA9008D780368297F8D7C03A200DA7AB1149D0004E8E0005C +S123D900D0F4A9808D7C03A98E8D7803606809808D7803A200DA7ABD00049114E8E000D07E +S123D920F4A9808D7C03A98E8D7803602035D920C6D9A90060201BCF29010A0A0A0A0A0AB5 +S123D940297FAA2083D9E000F00CEE8EDAEE8EDAEE8EDAEE8EDAAD8EDAAC90DA2000026014 +S123D960201BCF2901C900F003A9FF602035D92083D920ECD9AD8EDAAC90DAA280200002AD +S123D980A90060DAAD8CDA4A291F8D90DAAD8ADA29030A0A0A0A0A09800D90DA8D90DAADF1 +S123D9A08ADA4A4A8D8EDAAD82DA8D71D8A9008D72D8AD8EDA8D73D8AD90DA8D74D820908A +S123D9C0D620C5D6FA6048AD8CDA2901C900D007A90085EE4CDBD9A98085EEA90485EFA5B5 +S123D9E0F485ECA5F585ED2028CF686048AD8CDA2901C900D007A90085EC4C01DAA98085BF +S123DA00ECA90485EDA5F485EEA5F585EF2028CF68607F004000000001FF0099DA0089E261 +S123DA20BF0040000000019B0097DB0089E2FF074000100002FF0195DC0089E2FF074000F0 +S123DA40100002FF0193DD0089E2FF074000100002FF0191DE0089E2FF074000100002FF4C +S123DA60018FDF0089E2FF074000100002FF018DE00089E2FF074000100002FF018BE100D4 +S123DA8089E202000000000000000000000000000000000000000000000000000000000015 +S123DAA0000000000000000000000000000000000000000000000000000000000000000062 +S123DAC0000000000000000000000000000000000000000000000000000000000000000042 +S123DAE0000000000000000000000000000000000000000000000000000000000000000022 +S123DB00000000000000000000000000000000000000000000000000000000000000000001 +S123DB200000000000000000000000000000000000000000000000000000000000000000E1 +S123DB400000000000000000000000000000000000000000000000000000000000000000C1 +S123DB600000000000000000000000000000000000000000000000000000000000000000A1 +S123DB80000000000000000000000000000000000000000000000000000000000000000081 +S123DBA0000000000000000000000000000000000000000000000000000000000000000061 +S123DBC0000000000000000000000000000000000000000000000000000000000000000041 +S123DBE0000000000000000000000000000000000000000000000000000000000000000021 +S123DC00000000000000000000000000000000000000000000000000000000000000000000 +S123DC200000000000000000000000000000000000000000000000000000000000000000E0 +S123DC400000000000000000000000000000000000000000000000000000000000000000C0 +S123DC600000000000000000000000000000000000000000000000000000000000000000A0 +S123DC80000000000000000000000000000000000000000000000000000000000000000080 +S123DCA0000000000000000000000000000000000000000000000000000000000000000060 +S123DCC0000000000000000000000000000000000000000000000000000000000000000040 +S123DCE0000000000000000000000000000000000000000000000000000000000000000020 +S123DD000000000000000000000000000000000000000000000000000000000000000000FF +S123DD200000000000000000000000000000000000000000000000000000000000000000DF +S123DD400000000000000000000000000000000000000000000000000000000000000000BF +S123DD6000000000000000000000000000000000000000000000000000000000000000009F +S123DD8000000000000000000000000000000000000000000000000000000000000000007F +S123DDA000000000000000000000000000000000000000000000000000000000000000005F +S123DDC000000000000000000000000000000000000000000000000000000000000000003F +S123DDE000000000000000000000000000000000000000000000000000000000000000001F +S123DE000000000000000000000000000000000000000000000000000000000000000000FE +S123DE200000000000000000000000000000000000000000000000000000000000000000DE +S123DE400000000000000000000000000000000000000000000000000000000000000000BE +S123DE6000000000000000000000000000000000000000000000000000000000000000009E +S123DE8000000000000000000000000000000000000000000000000000000000000000007E +S123DEA000000000000000000000000000000000000000000000000000000000000000005E +S123DEC000000000000000000000000000000000000000000000000000000000000000003E +S123DEE000000000000000000000000000000000000000000000000000000000000000001E +S123DF000000000000000000000000000000000000000000000000000000000000000000FD +S123DF200000000000000000000000000000000000000000000000000000000000000000DD +S123DF400000000000000000000000000000000000000000000000000000000000000000BD +S123DF6000000000000000000000000000000000000000000000000000000000000000009D +S123DF8000000000000000000000000000000000000000000000000000000000000000007D +S123DFA000000000000000000000000000000000000000000000000000000000000000005D +S123DFC000000000000000000000000000000000000000000000000000000000000000003D +S123DFE000000000000000000000000000000000000000000000000000000000000000001D +S123E0000000000000000000000000000000000000000000000000000000000000000000FC +S123E0200000000000000000000000000000000000000000000000000000000000000000DC +S123E0400000000000000000000000000000000000000000000000000000000000000000BC +S123E06000000000000000000000000000000000000000000000000000000000000000009C +S123E08000000000000000000000000000000000000000000000000000000000000000007C +S123E0A000000000000000000000000000000000000000000000000000000000000000005C +S123E0C000000000000000000000000000000000000000000000000000000000000000003C +S123E0E000000000000000000000000000000000000000000000000000000000000000001C +S123E1000000000000000000000000000000000000000000000000000000000000000000FB +S123E1200000000000000000000000000000000000000000000000000000000000000000DB +S123E1400000000000000000000000000000000000000000000000000000000000000000BB +S123E16000000000000000000000000000000000000000000000000000000000000000009B +S123E18000000000000000000000000000000000000000000000000000000000000000007B +S123E1A000000000000000000000000000000000000000000000000000000000000000005B +S123E1C000000000000000000000000000000000000000000000000000000000000000003B +S123E1E000000000000000000000000000000000000000000000000000000000000000001B +S123E2000000000000000000000000000000000000000000000000000000000000000000FA +S123E2200000000000000000000000000000000000000000000000000000000000000000DA +S123E2400000000000000000000000000000000000000000000000000000000000000000BA +S123E26000000000000000000000000000000000000000000000000000000000000000009A +S123E28000000000000000000000000000000000000000000000000000000000000000007A +S123E2A000000000000000000000000000000000000000000000000000000000000000005A +S123E2C000000000000000000000000000000000000000000000000000000000000000003A +S123E2E000000000000000000000000000000000000000000000000000000000000000001A +S123E3000000000000000000000000000000000000000000000000000000000000000000F9 +S123E3200000000000000000000000000000000000000000000000000000000000000000D9 +S123E3400000000000000000000000000000000000000000000000000000000000000000B9 +S123E360000000000000000000000000000000000000000000000000000000000000000099 +S123E380000000000000000000000000000000000000000000000000000000000000000079 +S123E3A0000000000000000000000000000000000000000000000000000000000000000059 +S123E3C0000000000000000000000000000000000000000000000000000000000000000039 +S123E3E0000000000000000000000000000000000000000000000000000000000000000019 +S123E4000000000000000000000000000000000000000000000000000000000000000000F8 +S123E4200000000000000000000000000000000000000000000000000000000000000000D8 +S123E4400000000000000000000000000000000000000000000000000000000000000000B8 +S123E460000000000000000000000000000000000000000000000000000000000000000098 +S123E480000000000000000000000000000000000000000000000000000000000000000078 +S123E4A0000000000000000000000000000000000000000000000000000000000000000058 +S123E4C0000000000000000000000000000000000000000000000000000000000000000038 +S123E4E0000000000000000000000000000000000000000000000000000000000000000018 diff --git a/Source/Images/d_dos65/u0/edit.co6 b/Source/Images/d_dos65/u0/edit.co6 new file mode 100644 index 0000000000000000000000000000000000000000..e685410cbb323216529b76c124062483e089a7f2 GIT binary patch literal 6830 zcmeHKTWlN073K2%&@LaMr6u(mOSCQ7mMy;;#YO8-)XHSMA{~;7?HF$MBXX4Vr}+!= z69eH2P644biZp2u0R*8TvPPsxMT4S6RiHscga!(1Q3FMdG;s=>vDzkO+Z3tM0_vF| zCEGyKzXJUbKXzyC+_`h^xsO?@gYHD;^to*6WHL_%6GP)v&x`xpVVt=3V2hQkZz9MXNCPida5QzAx$r%3o)%gXM?WYot8NUWdvLvDaZT zCF#dT7wy7Z4q;u;iQc;`TrTV^^pz~HT_LpBv{w77y^C(4MogRfytF7|)ZinRkTfiF zE@4J@nofF5ch;R%=VGUzyG%#Ld1uyDb&>B$#!{(Q4;OaucSoTUTiS)WurRkrD3eu} zFh3Nz7Wjg?)|?HQJRupbl28s3n=s-vJ}Gq)zob4TQDMi=@gYBG#(Q=3g8cJu$>7-d9YkJqt#(O*_#$ss)+g2=fu-9{ZxB8C9P?(mJyeh&~BgrNbCe&4N&boA``ktG*YbkJE z_m(Y-7v(jN>7ZUyxHj8H{ulraH@wu{_`D{Y?c`;Vd?W#Zm8^%z5B%y*Z!Kg7?i2r| zoylG_PmmWxwwd3@cMJ$kuB6a9Th{s>Dtb}Ub#s@XA@k>ZY>5y_?1YIIOlHgv$Uy*KlVCs^GT=1(FpFvu2{jSHj1gpQ0bau9r;mG;e@sF|Ny{$w+2uQyl@P2s&0!16S7$7$!)6P_|K4x}PYidKc@g+Yck%PAUaq%g-J71n5f`%no&~AV}wv)B$^#y&R^MkQ-JDp2kl5zKw9fI@~H%m{~b_MZQQ9QstGelUJqjpA?u_RVjOhVpov@K($YuUR0~m)P)*Z2< z0YNKURhv*2*u#TI^0g%T%*>lJs#hxe(IaacS~<{qw==CUd+cD3j+VHSO?;RD0&z$N zc0`y+Vvi^u&EDFioE}5RR4oE)r|6l|9Zb_mzHY2Wd31xZ)$69(}O#qhFgky zHFkM4tTP%*6PCa~<97_=4p({Z)Xu^0+Q_n?)s8RQhy0_Otf9Km(;!Mxn^*6r_PzQ* z+2*wEwqG;v%G5U9uiL17dO)|!Gt)NR2EcaK3ZDtE>j#$FOrIg5tltf=KF_I5kWZHf^!e`W7vRnzNRzI2xcCzT8a0IQ=_MjdwH`MD# zV2?)z_sxeIbs=3xX~+5!Pn;9@^u-|B}cA_Zv2LMMv=`wD2a0GW1x_6~T_ zS?xDJRHZ{Ft9~>@|s$)_uUUb&ZFIzePH-bg$(32YVHV%@LtWRC?RD8F* z#V#6i>}mvQ49UK$8e=n@dC60@%=+rS)uo6QYYW&^hZGY7Jt!v8*o!u0Oqb-c7Zq=? z%NJsYj+?CF`SV5DjZc{kT^z)HD9%4E*FCFGBmCs>`Jjn>|#UF-eJ?#(+8A#C19GL?}x zsLg4+-m~mQ(2Gn{xA0+*a!lTkAbq1qU+|H_>=6Ut>n=Xef1i$pVy1<__9b>xbc1lc`6s z)`hMCn!Bpel_-+yx0{RRuVA;#qG^8)oG8%DCS51jQ7!qWyae4M)7g*~bm=64;2bT{zrsqTio-7w{% zj)o0&zO~%Fwi~SOSr*XDR(2;5`*<31E*>h0IkyMW4QYX_Gr`b3?H94ka$@%=b z)A$r76PYZTjGw(AdI`y;Nj^g+Gmk6y)5HD+ozHz^-vt5|e#IQdM9Ie_h{bX?uS_83!nYzmpe)-zLi z5?4Vbb9@tiHXWbj)MS}oYHBRYvSxENoon)N=zJot4nJ|BIXleE=BCDS`BZ)i#BWMj zCbjgN4uTP&WNG$a96ZC6&SX=JZ*9NIsLjw>bsxmC4g&Y-(ac$s*a)${7wd zHavLlV0!38?6fk;1w_ea0cLPwN>xt`#Yj9)Vq@^|6lx$g4$eSRp4AO=lx0OOpNmZ@ zlNtElv`*O8*!_GoZN?JuG)ZUjEF@dCc3MfKCQ=HLkp(935Z%sv0ZXf z-slX;mn{D`KX~`$Sk9usu-{iIeEGI*={5t~3~V#7&A>JT+YD?ou+6~#l7asKr%+q5 literal 0 HcmV?d00001 diff --git a/Source/Images/d_dos65/u0/run.co6 b/Source/Images/d_dos65/u0/run.co6 new file mode 100644 index 0000000000000000000000000000000000000000..cd6edb2433b31a2326666827fb4e5199c16f5299 GIT binary patch literal 10896 zcmdUVdsI|cx@SEA4+RCqON#dvv3LknY1GgfqdW>JIaEObCTfXCBLtFYjM2O_0h2mN z2$frPqiO6}nN^Eh$IIbbxm3E--R9o(?exS9l{=b~Os{)acY1oIGfG1`GL>|99-WzH ze%~oj(|4_2YyKRT?z8u|zy0lRf3Lmww~PO&jX%oqk8%7{9Pj5e_-k~v?{+(Ov~;l= z=5{o;)VrHleJ$hd_3qsOt+(0g2<`vjFIw+Uite4(Rqhw$MPDW-IPpK6&RsNduV!#e zul1#KV$RE>-^Yp7`a<`!ALdGjLcQWK@1sFYT{uBIpAa}U6He65 zYXZk)O;Cr{Pm`3dgPO>(mYK-0$^JO%IN#Prls5nLm8Y$K zy{v&41?J8R*K-#eIFg6Fg1u|z?_N85MA6MYEFHOgPKN(-gm0_YTjbR_g}91zC1(ikUK`_>uw z^9H#TUl56L3wBP?FElUF2HKT%hL|a8jHNCtPYC?*It*9RmKdmxB}9$N=lrvIY`wu8 zZsLNP0WE7?DVn?)<^ipuogt-%?cBv?sNGwmVnEkHjbsXVW~7XON7k^!5Li=6rIyNM zE$>L7)}Q0wopEsG*YReuZs|J||5jC@KUgLu1y0OJD?mtkJn;!7QBH&wE<7H3Vs2Q# zQoIMko4AX2a-zq(FI>l6{0>J(E+t(aRFb3>mxp2;&78m-DN>T6duPQvN$iCb7zKMg z2g-Xig*}&o?{`z!<`nj5N{~fPKt#l~GbOf>m`#Xf5j2)qHxD>Lz5y{dloLyo^<*a= zq7h4C4}xqe$Vh{sAu-9jLYT#bvn#;LlhTUoPfahGXm~Sc+ybS>4Yq|Wt6E?C9K5>G&G$><DxfzsOs1%c^Si$~tPEa$pjf8mQZ(O8z->d9Fu`PpJVz$HV|)7=3g7DjBbssiSCcBiq^)8qMKuR(Jir@=v}dl z=-n}6bTF12t%@Z^x5c!AT!=vwS7pw3);OV=o5Q+_7Oct_FaE7jz7W)qWuNdq_Uhjn zU%6o&e`Ue??KKh0DKZP37*W27ctkA5BPP#8xael3awNjBUJjA?dr`;q%a!RPffEs~ zZeHhm$!M0i0iDSCb+gHQUK-@a0T_PC7&Su1si@C#&~7q9_c`OjIpf81#yG9oSlWMk z$vB-n!+MN?6TB@AoeO8FpTH&+>Ec;qytgflIgMm8CoViT7c7IJkHW;oYWKA@2lg+z5~(zES3E(6~X5&&bO5VFL!f5)xf5p?@Y*zmE|dk z>=))(qRgr4uZwtK#vaf{wDz!*DKJ}D7Yy&>7EWC6y@RFYvzPNL2hF`OW0=B}x}(6H z;WkW2m+q(>tlq|%5-Yc%<@=X3l)==*J_VHO z{OY?o8$u;}FqMy_WAS$*z(J`7(rn5|#Na!Z9)2lZNxFJ2o&O+RE(IbROP962v+3b; z=~vFC`$@nQF%xAo2}$i=IGfJ@k_I9St3$44f>nr@_`A6zaub0arrgAxTM1Rc`=+%cB9Lfo2O&lmmF=@DA++4cN`x|a zN6UB+Di^II{U~dtm7!dU`h-jU6!+uSc5B9^zQ9VdIzlE^v1jnda%F8$U7ne6D+fDt=Pk5z zd_zW<=PtIzW4V*N=u%@j(E<&FuY+46@DI7>!yO!mVsSooda>ABLU@7V@tHvJw^%4K zOU3ZyVt6v4cml<+lR)v(l$SHuv#lTmR9WR;$$6` z8Sdg}m20X0&l%JsuAf1%AzsYA0y+;YDGEm%vQTp#eCTD>SlxL9IGM-t z^63C11a%RNi)O;=umh*%!*YG|nPZ=18b8SdB)qsNRBB@>LH(uKf`Dhl^p!A)iNI1e zSQ03BaO@5uuTu%@^VzR5p$gv)jxA<_9-6)u&U|DKGM$nd1mNAw)dj2@wMP#!^&^&G#1YA7oLFm``&R&?-{M2Su|tkH0}(J))Ty zqflV>{V;3n^{ns@v#z|J<*y*f`}xyJER-c{1*{%loiJ+#yLq$uC<_)|&*Hz#BDkI+ z6Jk?M_Jrm|TQ*LFC9EM25f@=MH7}MZ=TLz8c|P&tvt`qo&}V`_L3USc*?tu*eR-`o zL(Pz?f1V%5sJmgy_N~hfYToxu=Z0&Deu_D~E*nP_5C3X5Y5@K$^C}gRUW#y7Bz?$6I+?$^Hog zx+s!Pq%T)Y%a!cqO3rd+<#Htpg!t!k=zKMi58y;H3ST!jwu_UFh8_`1y{oYs?B;xX zIH@#ob?o6_LZnpL1JRcvpq5V7jb1OE8o$08mH9-3P2WCltOwSM5xe1}duU*|n=|g> zVr$H(T-?PCBtl5Oz1*0G3-9Bu?B&8e+zk)sPn1eStA%CC!=>VC{%1K$V-w|Ea_HUM z#XX!5XAdOF-MTq;F^AX;Cdk@A>FslvdrL*jc<*YloQMW2;5T5QDt3m_$$s;I4vdHu z-b(m`B~Tiun32lq14^2J#VlD6;w*mMEQU)oTv{El#Frp$^4@8dN(U0fQuMD5t)9@( z4UYJ)n@<#(?;Z}a@U9xWms5!`wjtLnG0k*bl5syJR1@X%8gAQ~vum55bXi+3$JWr3<0X;q*~2M z&|yRoFvg5z%iCeg{PrAjZG(9%#SFtrHBVUU!Upra37~L_dA{72VxF760noq_Xn;U0 zXeO+=B`p0dtR>I@ftIiiEn#VHVG(Gl*MREW^dAT43y^Fx8qDBIX4R=?Tk=P?SQ5^B zspe6z3*LklrZLMq)b;eU4|D0E?lY&&|575&?y@&_mn6*HrTa zdej;MS8RC*qULRN&rHU*x@IzN^gfm1W1z4r%Bsq^4ihOLa^o;qv% zn1gXWFxj5TezIQ=s-AdNKvh5$=Q>#<9v9dn1?>B)!tYt5Oi7tooO@HTzVe<``4T6@ zH?LZiKfQR>DzjIvVk?xdB3{Z?$XP=q#RS@!5)%_*YsLiH9}=zz`To3%LVhFxp>+1R z{M_Z^(|Q~s7leHN(R@L)dDmge4dTY2Nm{?tk1NWCUYoc<+St2J+}O9VZ$sZ5ed|Y* z|0%5x-9dcGuLcWPYB77FfcXm8LOv;#&RldV7y%ok6#nykS~a^?$ks7X?+{%Rnlj#` zeRsH3+8(OMH9x48_&`G(n-wf!!+N%h{KPo0c*kN@d?Y(nOk?=B3fZwj9@9QjKy$Et zMZ^QP!zAn-*fQxtqE-<^0MMyw;I9=DZ46fVLW|gYtFUaF$t>q1lY>*rRQ!}OexcE5bwhc(riLCXjXhg8wSC3$ zv$fkFuXP=LYD9PBR8?^HnW?GvLCjBdXugEu;(veR%z4Y9Gpje;J1p({2owF1dt%GK z?>y-}qB~`M>(5VrZ{6{y_iXh(6BwL%hX1E)gHuxv(a4}iZ1eIH{<`5-2+~PP;7=Dz zF2|ziBJqm6)P}N6a-wuf9Vk0yI~2pLQ%Ra_gTwHG)EY~cTvhVov<_z$vBBHOeqS8a zOU^*Uh}1@fD|v7Y^f)551{%B_g1FsV4};h)I!92nQQ=A+5_zh$-rnC$kS;2A*`2SQianBF*-i{yW&gy@lJ*x|~pVbahf>)OhpUD_P&IqhS* z$MpRV%qX9l)kVT>8gNC`^WQIwG}v7xJ^!P^YpqH_q#=3eGOuLKL>ex)DXBB^;N^}; z!*wV21IgvrITra#g)Q>`K#K9L!hVq~cw$5qep_7puw?4x;XPot6%$kxUFaCLPq-!b zBwBx0Tz9=Sw$`8JZ4K@6LQw-yqSrpr$~Pe7csrtBo08abMSNE=7O+dp4i}Z}HSxjL zkK8d`&|T+P?6r#>m-L!H>P6=zo#u}^vF(yp^GB`7!{dhwkxVmR;FY^Cv<>qYoWpIH z+Ue~W;1FZxAjDSDB@hA0*-O%I>m~W~z0d&v^Wp(*QisK9X|wRAKY+>U_rRQ1Z1tzk z!bJM`zP3JRUk7rf;x;mxq_{4qnwr$%=h$SSqG$hBEJ*Gc?jo(z2_}aJ)rsOGfw6n3o(TUb2WAL^Mlai})sF_dXMII&rfYcft zpUy?-^>#=u*wIjxJTA7vZ@$ByDi*}e-YrW;s(y}^ut}!c<DLe!wEKvcg=1_ zAlM>p4sBsaap&EPH2-EC;HaHiECchMyOis~Y}19NH$B$qX1`X5+Wb1RP$x*u27|e` z*hMSRCF7z;sqi*$$I#wuN<;^jD^{*&=>3W%;V3cBM8xpeB}tK?#bn&p`u{ z*#BbugR9CMrZm!BGe5ejZ%5gV_SdB5y6Y`sb1Vz_!wV&|&C1t&Xcfr5gPOF{WVp?K zgIbwE>^iyT{8g*y@;1%LwhQF9@0ZG&kA`Bp>16p07|PKS`A=et{6kbP6vcF=O!>9t zY8p{)Q5I;b7UfsVyXQJKp_N+911oIFQ6yyt7N=w#QiNjjaLXtNWQCgK+8Inbio=+V zD&D4`W@5-JIiLKhfV}g`FAHF_{F7f4i2NM<={o%BH>3Up_@!aMIx{ol-5P3|nW`Mb zSj?XkC+BSnZ5?$iRt`=5G*fvk)O6{pbtGzweFaHsXXLdPnqxI4t`3IUJcTtYR@r|3 zJ?kh=fphbQ>2C%$pZ~x*dj5T@tU3SRtpX^c@}5ZFE}M$bPn_I zCKtkVhYVL|r;7=fw({>6#=32tQb(dQu}#U6_{u>%Wwb_5D=XA6z~czlIzQAxqvT(z z1m$<}`B91dGko?H$y~6IjWGGD+Sd<*kUs!rXo7ry*}ne`y+=zxcf_9pMQ&DUy9D+C zGfUqYI325OQOUuSF__dy!5asQxnem7^h0!b+1t;OO5!0!en*{+!Vb0>`PXRSh=UkW zUj&kb%Y-8NV}SQzJ8CgyEU8;^*^(v1XR(ebQ-5l4ze!JxO~FEbgb^||rPh|{Y5xk9 zDJ->BU1PrrqN(>4VH7`CEWkMh(`rgGX(IwoT@j&j8?N{x5y1dDpQzcIlX*N}hMURX zl=*yRZ~Du8FP5>fGURap<`);;YkJo_vF3#}lWTsn=JPe*tVysKEh{Z07Mo><<&(S~ z%Yen5_mHI_@0jIj%ZrxpT7nkY@|xwJEbmxWWX)NO<%JoB%%bv&@^$5#%Nxrb<=y2E zmOom4vV5rgWusUgDvy-ES>CaxV@+B9O!-eTKQ0evzMQ#`|4q5EBB!FLqPC*H!dv01 zIA1YQ@p{Eu6;~>LQSnVheq~?fvC3yEU#R?UWvKGUmA|UgS8-M5s-mjWs*b7$s!mnC zo&QGFr&ap31#8!=rPHW-62yKwT!1qlo{pA5(BWT#5a(`!)Fes*j(^MeKf0|Gsjmz= zS61R|__G4KYJ6oYV%I6%ol1F^!2)Jnt)5sx@}bqYsJ0YDwLsGFpHepI(@X|{F7^lI z237R2-znGBit=&nL#k+%U&KC8aTFyMT{=oT7NJJvOTLiK*6g?H@p@ekm{7i?72Xcc zxE+k#uiF&QsP*F>@oXOd6|R>Ai>L2?l=T<90TAa6l{jxyQF$X=l{dm6-em19LU{i> ziS(8v;NBq}P;CwgL{Y%5Z~#k34h@;YXYDu$5BO2V?Ryf&!(Y5`t^KSzWSm(d%R9MKA-0QT=|m#qfyeZaAY}DaS-c2p#>my+{lqYeD&N| z1AYLIj6^Ru1ZV0Oi^hZ93Oo+uS@>)Ig%qS60jQ{pzo5+PeAN}W$&S@jgzw_6R9A$z zayM!!ra5qc=L&lTQVS2J$_8rSJq6D!yu#bnD>=4TR@%S_!iA@DkaB^z zU_QW>*7nO%k|r)wzc9C84UR?jX=Xomxk$N+_wMQ?JdF7-x77>Fmf(=-S7!El1%%Ju zsvr@=g%ahJrWZoWj(R@^R%eEJ-}BCJ9N(1vDX;giprlKAR_NCXpTE8ww8@T|B!9RNTt70bGY?0y;?#50P}s=}Zm3J{uDtOM7dqtOF3niJt0wbNH%t zK-&^0rRKWH&2YWPMrWmL0_H;^JD#jo2~C0CQjST#iu?t7M4}g~c)V)ti7Nc2gVu#e z*{a}Rd|f@;K|=DpT2leo!(iu-8ulXsV>_fvJ~X6?5tooi54<(dR5hI_ zn@HU8XGJi8K3JUj@TDp;ubZ)}gMyT4Id&m5&>J#d5@3?!uu0mEU^Ni&L*B#jnz{FZ zmhs*PgHS)cEm2N{-Jd+M_&tVwtJ!3CyIpSlIHv5LdbiWz+(A|5a5CQEw6ij2H_x-q zE;n_w*LQZ>@q?O9)ZF!L_Aa}db-B=PWX;{q#x94;Sr(^uPm6=Mvqs+4N#p8SGn!>h zj?Px*w%0eY zvpsgVtIY0dX3bzDbgr(5X z2Hw@!N_FDV;oMcvJDR{sdv_OWc7vBjm$TD#Th|hy|G;dVXLY?!*6nn)+nvi)za(t<1nsVObYg+bY2N`7yX?%_-PW+A z1J>@k$L=n}${kKHPLgPLbwd{5v&jLTyIk(wWw#R}ML?rn%nmGwQB^@bxcin4X&JZa z(BW*d-%B*1gU+scum;wd3$g-*2AZ(*uTHWgJksFpV()g|-elcmX7@O{TK>Ww>fP@8 z-K?{_p|jELfK0wU?~;}BcIOU^jO)0Qt>3t@tP{G&B5zqOm~A61cixoc?OfYo1Kn5~ z>#BF|P}kSY+8xZbi)4L|t88i7HhbG&$TV)M^{k`YMWbD+S;nncl`d4wH^p`Af(0~n zt8PUuQAWg@dDlH8+j>}h3*5`m$RK_*Yy=%{{onHI#+TX8DsIINp!N->#mm&aSzmW_Qi;n(>-{t@*shR9jW+ ztbMZfOzmXtmD+_`y%p)MzxvnyS9||I=#(8klU8>6GPH7+FHoiw^ly*-0COhLRs&7cEq(P$QPb=e?tlB<{f#T0$AK z#r_dr?3mAEPYgWIUt5P}_y8B(6ibcXiJV3cen(fVRI>AgG>ilB@Z>1AyeVvX@fUbH zE)U~vewaj7Uu)Y~Q(yLf0Z%U@6`t|N-kF`5o!2^XV~{S1jd6+6^`?zYLnN=go9vpgce8d9B3J4FP1#fm zq9L@v4;+U~C=sq=UTq3UqgAG4tQIBw0V74SDtWaNDR6&QssvV{i_=%8ty;O2+U49k z`*2%$xx#xW6-0z$_$W+k}RCGM*GFHqIED?PmgDAP1tSEX~Sz_^{OEv#} zi?f-<{oFE#J1Z3s=0-R=jBnPOW<`}4AUZ7g0_^z{ z`8BqSP$i&aJQ-bQt1JNgn%@C-j5Cs(vxEgwBKRZY6M;*8aSz7A>-z|4uglQvXZCkdJ>j2|WdjdqFn>Ym=QE0H)xhJj2sWa?Ot`$WUzy0+owhh7sFuJ|0; zOG=2iro6s`Khi+TBBZ40A(0?1Qp5#G1029WGg1a3ZRWxc)iYTZA%is>hSL>|3&a?l zepLdNMa{AV2_j`4g$l(ywG=YmlOWp+pd@)UUY1Ia*rb_~GsGc7iaxajt%%@Xt!Hco z+8yb5g!WX!U|15Qs2_-&(h} z7-rA)$(1DzI`j4lh%j;M;Qq~yQd+ouwp`+k5DRq>-xZJ3sz~J~@7wtRnj9^p(-SD2 z%1-49=)Zh=Zmak3U4Cc{16qXk?AX0;e|8Fl`*)A$QfUwdcTXk{5Md|~l9M10Bz8{~ z_D_s%Z{f?0x8y(yn!!8GlqAM_GS6ntWX_9=FLd_HT}R?`X$8c`;0az+%6VaNp}v+; zKy0n;RooFu}IoMfX%)$M}{KG{aIGG^#3T40+6xqlL!t zfeZ!~z{23sFH@B8Dc~}8t<(X!-i+Vxp^KZmZhrt8f7s)E)%dG|4yZQk#!WIZ^p|zH z`Zz@;DWy*#DAExSuk#TNemJ+ zV3yS2Yf)8CR$A7R?6H=}jwD@Q2kXExdPNWv-8P!!}!z zNwhV*1$24%?us}(+~E;RcO{h2O!tu88FYCD(7+x`Ybd&K4ci+}DW%O|ftrdDQ_#&k z)*m)XYKfs&qPN)}gcNEXIve(8E{4GD(g|EOuBae6nwR%Qmzm|O8XDG&Hey~g)>P`A zT2;Vm1C&Yh$R50b=v8^lRU=LW?gQvnNOMoN(2_d;jjaVG`C3D8Y@N=OBp1!SuG7Zp zz7CTS@PhslgNx%8^s#Onk2aV^_;J^(_b%7&!>!`Ix&Ho#_d67C_w>NPt^v{*{^J9x zwBsQ(kv@p_WQ{bMNRFo;L_PAYds`IL34xk~+(=kd!x4A9ewcN#*7cBgBq*^Io#WeDN*adl1OHrHPn4_zCc z3$swm=p0-dOFUkKqGK+PC@eTy%$a7 zP^yrHEz&)_NH&63Th177TVC>5$1SB)$~~B#!X%KpwDgD+SB{_ zzAyC02NFB(e_-d}(3ggjBcrMGp1qlDeqUj7YX5p o{JT#)`MvL-m_7NUQ`YGpKlPKd^FRCfFMj!}XP!OB{2xC52F=W&X#fBK literal 0 HcmV?d00001 diff --git a/Source/Images/hd_dos65.txt b/Source/Images/hd_dos65.txt new file mode 100644 index 00000000..7d6b7d12 --- /dev/null +++ b/Source/Images/hd_dos65.txt @@ -0,0 +1,3 @@ +# +# Nothing to add for now +# From dd22c54f32ff8f41a4792cb5ac6d439ae2b222f4 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Wed, 2 Mar 2022 16:02:37 -0800 Subject: [PATCH 26/34] Minor ZXCC Updates - Added a missing call to trackFile. - Corrected close functions in track.c to properly handle WIN32 variant. --- Tools/unix/zxcc/Build-OW.cmd | 21 --------------------- Tools/unix/zxcc/Build-VC.cmd | 25 ------------------------- Tools/unix/zxcc/Clean.cmd | 11 ----------- Tools/unix/zxcc/ReadMe.txt | 7 +++++++ Tools/unix/zxcc/cpmredir.c | 2 ++ Tools/unix/zxcc/track.c | 35 +++++++++++++++++++++++++++++------ Tools/unix/zxcc/zxcc.c | 6 ++++++ Tools/zxcc/zxcc-src.zip | Bin 70328 -> 70604 bytes Tools/zxcc/zxcc.exe | Bin 96256 -> 96256 bytes Tools/zxcc/zxcc_ft.exe | Bin 0 -> 96256 bytes Tools/zxcc/zxccdbg.exe | Bin 120320 -> 120320 bytes Tools/zxcc/zxccdbg_ft.exe | Bin 0 -> 120832 bytes 12 files changed, 44 insertions(+), 63 deletions(-) delete mode 100644 Tools/unix/zxcc/Build-OW.cmd delete mode 100644 Tools/unix/zxcc/Build-VC.cmd delete mode 100644 Tools/unix/zxcc/Clean.cmd create mode 100644 Tools/zxcc/zxcc_ft.exe create mode 100644 Tools/zxcc/zxccdbg_ft.exe diff --git a/Tools/unix/zxcc/Build-OW.cmd b/Tools/unix/zxcc/Build-OW.cmd deleted file mode 100644 index 3be3cdaa..00000000 --- a/Tools/unix/zxcc/Build-OW.cmd +++ /dev/null @@ -1,21 +0,0 @@ -@echo off -setlocal - -:: -:: Edit WATCOM variable below as needed for your environment -:: -set WATCOM=..\..\Tools\WATCOM2 - -set PATH=%WATCOM%\BINNT;%WATCOM%\BINW;%PATH% -set EDPATH=%WATCOM%\EDDAT -set INCLUDE=%WATCOM%\H;%WATCOM%\H\NT - -copy config.h.windows config.h - -cl /Fe"zxcc.exe" zxcc.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c track.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c -if errorlevel 1 exit /b 255 - -cl /Fe"zxccdbg.exe" /DDEBUG zxcc.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c track.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c -if errorlevel 1 exit /b 255 - -copy cpm\bios.bin . \ No newline at end of file diff --git a/Tools/unix/zxcc/Build-VC.cmd b/Tools/unix/zxcc/Build-VC.cmd deleted file mode 100644 index b9383633..00000000 --- a/Tools/unix/zxcc/Build-VC.cmd +++ /dev/null @@ -1,25 +0,0 @@ -@echo off -setlocal - -:: -:: Visual Studio x86 Native Tools Command Prompt is assumed -:: - -:: Below configures VS2012 to target Windows XP. -:: Not sure if it will work in later versions of VS, but seems -:: to do no harm. -set INCLUDE=%ProgramFiles(x86)%\Microsoft SDKs\Windows\7.1A\Include;%INCLUDE% -set PATH=%ProgramFiles(x86)%\Microsoft SDKs\Windows\7.1A\Bin;%PATH% -set LIB=%ProgramFiles(x86)%\Microsoft SDKs\Windows\7.1A\Lib;%LIB% -set CL=/D_USING_V110_SDK71_;%CL% -set LINK=/SUBSYSTEM:CONSOLE,5.01 %LINK% - -copy config.h.windows config.h - -cl -I. zxcc.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c dirent.c track.c -if errorlevel 1 exit /b 255 - -cl -I. /DDEBUG /Fe"zxccdbg.exe" zxcc.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c dirent.c track.c -if errorlevel 1 exit /b 255 - -copy cpm\bios.bin . \ No newline at end of file diff --git a/Tools/unix/zxcc/Clean.cmd b/Tools/unix/zxcc/Clean.cmd deleted file mode 100644 index eb7fc764..00000000 --- a/Tools/unix/zxcc/Clean.cmd +++ /dev/null @@ -1,11 +0,0 @@ -@echo off -setlocal - -if exist *.exe del *.exe -if exist *.obj del *.obj -if exist *.err del *.err -if exist *.o del *.o -if exist *.bin del *.bin -if exist zxcc del zxcc -if exist zxccdbg del zxccdbg -if exist config.h del config.h diff --git a/Tools/unix/zxcc/ReadMe.txt b/Tools/unix/zxcc/ReadMe.txt index ba94bf5d..a0b0a63e 100644 --- a/Tools/unix/zxcc/ReadMe.txt +++ b/Tools/unix/zxcc/ReadMe.txt @@ -84,3 +84,10 @@ January 9, 2022 --WBW 9:34 AM 2/10/2022 +- Added a call to trackFile in fcb_close. I think it was always + supposed to be there. Was not causing any real problems other + than superfluous attempts by releaseFile to close files that + were already closed. + +--WBW 3:58 PM 3/2/2022 + diff --git a/Tools/unix/zxcc/cpmredir.c b/Tools/unix/zxcc/cpmredir.c index cb47cc1c..ff32a3c0 100644 --- a/Tools/unix/zxcc/cpmredir.c +++ b/Tools/unix/zxcc/cpmredir.c @@ -204,6 +204,8 @@ cpm_word fcb_close(cpm_byte* fcb) } #endif + trackFile(NULL, fcb, handle); + FCBRET(0); } diff --git a/Tools/unix/zxcc/track.c b/Tools/unix/zxcc/track.c index 7c944b79..6b961e31 100644 --- a/Tools/unix/zxcc/track.c +++ b/Tools/unix/zxcc/track.c @@ -97,6 +97,8 @@ #ifdef FILETRACKER +#include "cpmint.h" + typedef struct _track { struct _track* next; int handle; @@ -115,10 +117,21 @@ static track_t* rmHandle(track_t* s) { void releaseFile(char* fname) { track_t* s = (track_t*)&openFiles; + DBGMSGV("releaseFile: \"%s\"\n", fname); while (s->next) if (strcmp(s->next->fname, fname) == 0) { - close(s->next->handle); - Msg("releaseFile closed file \"%s\"\n", s->next->fname); + DBGMSGV(" closing file #%i: \"%s\"\n", s->next->handle, s->next->fname); +#ifdef _WIN32 + { + BOOL b; + b = CloseHandle((HANDLE)s->next->handle); + if (!b) + DBGMSGV(" failed to close file #%i (Error=%lu): %s\n", s->next->handle, GetLastError(), GetErrorStr(GetLastError())); + } +#else + if (close(s->next->handle)) + DBGMSGV(" failed to close file #%i (errno=%lu): %s\n", s->next->handle, errno, strerror(errno)); +#endif s->next = rmHandle(s->next); } else @@ -127,14 +140,24 @@ void releaseFile(char* fname) { int trackFile(char* fname, void* fcb, int fd) { track_t* s = (track_t*)&openFiles; - Msg("trackFile: \"%s\", FCB=0x%X, Handle=%i\n", fname, (byte*)fcb - RAM, fd); + DBGMSGV("trackFile: \"%s\", FCB=0x%X, Handle=%i\n", fname, (byte*)fcb - RAM, fd); while (s->next) { /* find any existing fcb or fd */ if (s->next->fcb == fcb || s->next->handle == fd) { if (s->next->handle != fd) { - close(s->next->handle); - Msg(" closed file \"%s\", Handle=%i\n", s->next->fname, s->next->handle); + DBGMSGV(" closing file #%i: \"%s\"\n", s->next->handle, s->next->fname); +#ifdef _WIN32 + { + BOOL b; + b = CloseHandle((HANDLE)s->next->handle); + if (!b) + DBGMSGV(" failed to close file #%i (Error=%lu): %s\n", s->next->handle, GetLastError(), GetErrorStr(GetLastError())); + } +#else + if (close(s->next->handle)) + DBGMSGV(" failed to close file #%i (errno=%lu): %s\n", s->next->handle, errno, strerror(errno)); +#endif } - Msg(" released file \"%s\", Handle=%i\n", s->next->fname, s->next->handle); + DBGMSGV(" released file \"%s\", Handle=%i\n", s->next->fname, s->next->handle); s->next = rmHandle(s->next); /* release the tracker */ } else diff --git a/Tools/unix/zxcc/zxcc.c b/Tools/unix/zxcc/zxcc.c index 1dacc9bd..21929704 100644 --- a/Tools/unix/zxcc/zxcc.c +++ b/Tools/unix/zxcc/zxcc.c @@ -306,6 +306,12 @@ int main(int ac, char** av) fprintf(stderr, "Could not initialise CPMREDIR library\n"); zxcc_exit(1); } + +#ifdef FILETRACKER + DBGMSG("File tracking is ENABLED\n"); +#else + DBGMSG("File tracking is DISABLED\n"); +#endif /* allow environment variables to override default locations */ /* two options are supported, explicit overrides for each directory diff --git a/Tools/zxcc/zxcc-src.zip b/Tools/zxcc/zxcc-src.zip index 99e39026acc8b0aeffe5e783a3e63a9a270ce07e..9f6a04cf4a561ec1624308602ebca5f532a2b4f8 100644 GIT binary patch delta 16111 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 PLlHqhSfM_@r$GK6>)9m8 delta 15763 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

pj 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 WtuppD^finzOfal9;{V}k%KrfncBSqB delta 27342 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[e z@Qc74;@BL1Y)axuyt4(q;zHxs{fNq+Hn!K$oi$oIKl3Be;Z&ALcIxUNP+ttBs(?*r zmAwpd$otcejPmeZ-x@oo`}Uh7ofTfBb)Gc<^Xe6S8B<7G&^SMWw(`oi;Fgi_GGOIg zJQQpXqdf`Rd$5Gj>)=jji{_*ciFS@|4pDyN%xO-{fjJ-&8Z(lV5IUlo=A<`~<|$f` zIRrM5+mgr|by|xNF7eI}>VW;9!!tvGgo?A$(24kBc)0x-ZTg}WtZBQ`6arfabuJ1a zIYjDg6H3~GpDL7W#Ujl6xi#3sBQsVg}mbt4X=3@&IjBO~#XeO@-py z-u2FQ9Z4?`5AH~!a9hxkbZQ%l8NdhwaRd@fpRs|W2Y(paPUpUkL`in%RdysD2qxm! zi9}*{Jv)&;&6yFDjR$G5%Th8rkzF9_)tQWem9Obc^2kPKTo<;gmUJQ5pF7WWA!@N@ zIh($t53{k>UCE2qt+5@8s?97(JMDRp?sGCbQ4EaS8Pko7BZba2-AH?K+4)5`GJte; z{?&~bvHa!T$xL+mNq3mVZs+apB(k|nqSOps>#$Wc8I9Vx(U|;hXLdB14j0k52kG8{ zE;h_SGz7=_LC8fy;PhN-`^f%t=pA1%U=`=aFcdy) z$fi`{rwzGMhRiI_4DODnTqQ0!6z2%0k3|(ezU8@EJf#_FBhP^JkI;F3S1oq<((~5g zxZ8s}p{6eQFiymsBYKiR(#biaC+QeS|2#lfxD(-I7kpIc#W_FfNjkTt=QbWGGP)@h ze;VkK(!)|!lW%hV(vx)csJY~9)QhC}Oktc~UUJ%ck)DCIV5N8hR-eICPk4DckMtr2 z^z*zI3G)sFsdczBOhQ8a=uk%1otOS$kLl#JNQktf9~&H%oFGxa&TE8&a?BtS(-6La zByp7Q+$bSEwanqA21u_a*~2%2ye@bgW>gRWLTMo!9#B;`g_UUR!U>yM^UKZ`5~wKN z*;Y!rLLKo^ato!dGSUvEzB1AYr8i|njnWPo=}z*UoFu>*ye}sa;f3g*E*%Vq{$pR947V3KEU@yO&NFhd5aySl zAY;)@jsku)+j&<(V&UDpDv1QPJz9yPA|1UypjC^UTWJ-2rd1y}OI0MM2X#yHJ?W2K?ZODpm+lz8GJKL*C`O`SX6xBsB?D{@b82LpTU5UKUoF`?LEeK7-m1 zA&}aS!;_Rb{NtTl)o>N@&O$Y5Yoi=3n2>FD`U;Gs1gCJJ%b@Jxpe? z366ZTGuuQ4O7;w3Qz$@Ii%i0l{=#!XD|dWp1`$gOA$l5hj#5$u-i4mZjPPWVeKepULLc0CS6fU67O=|y%{o3JCS45n1IlG-j7SgW8e(y7<*}5Fy-zDrzPq6jH?TqIsErKBV$Qu7)1%~=;

)rV8PzTL@Q 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 diff --git a/Tools/zxcc/zxccdbg_ft.exe b/Tools/zxcc/zxccdbg_ft.exe new file mode 100644 index 0000000000000000000000000000000000000000..aa6a6c0f532a06197232475c76e61add2ddf2fc8 GIT binary patch literal 120832 zcmeEv3w%_?75CjdHxSr>poj=Tqk_+@PaaV>ND!^)CKymOR;$DnwOZW87m>wH^xj=o zDV2(?SnyHt(blTi7!>m|gn*g{Vt7 z-kE#m%$ak}oH_Hjb7#!)D>g+@;t;yK6{Q$g`g8H`k$?PnJa|mWVCBuE55^YTuJ~Z= z)t=k#NyYz7sk3kUSEt_WxoQ4QH+$#KKjY53Zkd}p_rAF|`@A>(;*Pn4 z2BazOEJeA(7N-<`JLVT=X-&$*wt=>op~?zScCt*p=s4V`;QlqD)+O&_6wp490f>J7 zOO2J4K?HaBqfE$?YTWi*aECwOdn-ZS_Wv8JG!F0o$$yiYnS1qBl;87Pqh3^3s}d4( zs-oO@=54p!diYA#hVnh@Y{)GWta zz7g~@jDC{o$3AQEF4ztwd+~0%I5*A=&Pd5#+)R-iPh4rH;ua0S7pOe`g z{l9i(Dt>RG2!lp7F+45#(s;_0IdQ}Mr?u*z-*D}96~u~kB6Rh4V8!fEL8?|2R5Hru zI~JUuQQ^Hgque_|Uj%@RQs0BKLs_HTp@I>(4#PDC*JNDnv$Zxcf3BkFTL{x>XmENB z?pCKXO;OyQt4cE!&w-CK74as@2vjDEyU@OisX2;SxI>|%fN2CU4Z}4B*JNDnZeU$| z2XH;qgKM6J%L81_QeevuB?5ulS;{vf%$s4j3F1kLaZNU^cD@Fa+=eur8-oL#JAxyf z^~FSE@M!Vrcir7$bD~M&8@T&9BsxkVUS+@>3*Wy;s5!G1x27OkvIImGKaL;q8yI1& zs;Ja=cF8TZnM$}wbOG0$Hk(pH&y9Ei#VL~!&y%^@eYdOwVx%^Kg3xf$n5k6py&@i< zEZ18P#mk6?mlIr-3wN@d_&((f?^Dh{p$4F?-FJ#1nH8WxN@gSqCdqt^UP4Od9o(%` zsCp!*V&&5*indSW0HszQ=&;RCXrGpx>OBiG`YP6@ga(nUvpsKG7^}aP7y}l@dAI}k zdjQYzd`N(M>F0Mq@7aetF?kkc85W+~cEg-&ughcIOhf4+9=Nh|7Ps0FK|?AJ7qt;z zhl6j-N3B{Mi@Ft+I*MLo9?@gBrvpf{#UD@}s%8SVp`8&RDV4(+$ zj8KamM!c;+Jlj&B+VJuNV2C*NI+Vh<5XxRuF+BHQkccOZ@GV6aSnlWSsE9V4r4jQS z)v81VDcpj@J*aU}sW;XY`P{RF2xK$&0dfW^?ViUe<$3xU3>sL+ojXMCOlHL7;|Xy= zD$7IL9y)jFEYC|Oic5sXIFcicoH<51tgg_J#};6zh|x&?Nn%qpe#PqJ74 zyq0v{H_9`p+@x{5#3g}h0pvNCo-wr-nAD1wa+ucQEAdQhRnYd!P~CIZ%|=`+FD4r& zE`zyWcLNfNJ#|Q}5fdn3E+yPi&k3g>q4;hjuzduAA?xmsLSU!I571+;!tAsj6GEYb zxZ(gk&h7J<(2E+Poe1$P0gSAG+p2)brV0%65GK#>Er4tbV1ofbxI8ag067-GA0+@c zHD{@qI|mJcurcS}Ufcu{vMG%a6oVFJ9sP(4ktRj#2rouLh&4!S48=X{pKzLQsQ*6O z8R)d#G0?m_VcsIwYM-(ylc6(kYQDf9Gkw z#IW0@RY#67fldIBQB-wk*xBOSe|2|XqTkcq-Oas+R$Z032yPD=@3Vf84z#)7;2C;Z zMf?nR*`9S45AL^k@GN|8aBGhu7gw z9o~rFXSdPMFlu!QtZ10pifnG42oX21 z0zbzBKH~5Ur+ZE~4hgb%UU?pqfWg@*=l;&LLx zS+ACBwPj5SwpxEi(W|?rD2jK8R;vvsQ1LXh%UL?7qPQD&%|t&G`Bu?m!y3mRo}H7? z?H%ddsFrCpWu0T3b>r&-yBu`U2DJe+G@O2OPD1VAc21x=%*M~Wt35a3B6iLIN`gSY zF$ZiyX^MFHYv}K4qTEP$iW7dv30wme3E6K$a#|vmH)O63AH7P zA82oeP(c%N{`B_~2Y%uJI3VrTvabxg)&8&?McWdp_&%G=-yyC+ej2wdLavD)ItuT{b^M2cF1zFL zU*Z;xe(N_dQ5~_4N3UnZp{%y?)f3ALhWB6|YhiB2Qx}ZGv&f@unAmyGaY%5ipBiHm z|AJ?%mZ1v%T_9q*J+dp5)f!aN7G+%QJsY>}ir;stvp$kA1@$XPMT)I9INjzyc(M0O z3dW=@VymrX9SC$> z?2QAD2COFYiiAi)czU-s)z1uFckcr`U`E0dk(~ zAt=us)SZOrhot5CE%hkDOSu=<=Yg;Jp-b)QrT&(-{0kMAZ*VXH?6PP09S_gI!%&vM zXb-aptUI>=fpE5xK@YTMxV5@<)C-iP;s=WI9v)zDm~9JY6^ku!MMAm7O!+#Z+g4kZ znS2wdugV;x*eb%g?`VxxnGU}gEvX$d)3b_*e2aeG2S!P0(=?_uGA@+0Rh$X3!`F_` z%HcDFrV|^t2g*i?V~~urYH=^pK(09izXMpr!x2N(r=kbSZPPvt#yB^oEmF&hHhSX& z2QT*7L);%mY?lQtRMCei-kf!Qnii?k9E&eB zpDnUG>oqPenkcat#n90G0A|nfD)DDpJo55Ai}x2xe8KEvlL}7=t9#U!69nd-&6T z#TcMWHiNUkBdsDI8b7?JDg!pe6Z5IzwU^nvasDfl{Ox6NbTa@qsXp8c^oO#l0;P*A z2KQlW732%nhO&x#+6S_wxZ2BN2vJIEXb?43XDO!S#*h?K$`0C-s?}*J>a-!N=#e^Y zXejr?@U)}F4)7wBTNR!*O4Q;uzi5YdG&|4Q*W!eW44qJ?-Ns5J8vdy$Rnu-98_KE) zUwM-_Z>pi;%Lz-?hawFL;Vb8|)-UF?R&f=?vACd$^uzJk5C{<5@ZXnwv7;!CBUMu9 zUq45h!o_TeC#@tN={qqU!PA6@i7SQl*%r6PA?nU~I};$`cUysG{n+DOn0lbw{V#~~ zQC7H!BJL2+pPWI{v~JH{(t|;j`1v^yurh>Jwg60|TteC~LPEoiUjX8rrBYv?TLHr4 z6Kyz2@42Uupq0bpKLe`btk1^`UT0jv$)O^`<#KzDp(41PJI!*$pV34}-$r>(ww~T) zJzdIAQ*t~`>*3wj!+T^_trjzRG|4QjUPcU9GI_7b5<8;3IC9cxm$Lr_$&=MYu^0o5 zG}yuk(OkKN%3W*~sc?}a!pj8&Aan16Hed<~arbKCh}$!R@^Ho?Gb7ju0D-v^OkpzL zhEvg*;H_4zaf;~Z?87wVFqy{K9yhUx`++BlY5erp*3;|wsmU~cxC{^VDoBBpW(jfV z*gYnPu13^Snx|1{cscz#OV^JdSr6EL)7?I#Gh#qglAg zr;x27SBQAzKBQ-d5VTscg@!&fQ#w7z^Ls0Ig_&E_K*0d%=|-_plvP>)F9E=`y!x47 zX?Vu-;gw9^a^f&d|H+s&f%jKI4#-s0A(Sf)p@t1?plr0bSqDC{zHl|}#eKHt4U4Rg ztWwXBWCaRZ6i3lsBui$%@p2S?N~E$wQf}qkY2`c!okxYFL9fEp473DtxnE3}NVc-n zdzYw1YDf_W(NVZX1x4)Ho)0ZtO%|>{F|HAzQG$BB<*@3*SF1d}UBGGN(~>{q_QrltNJT`j6lQe|P%Acz^fAhlWKx^(C$&mo75P68zL(=sM|&(D|? zIgl}E{@?|}GS2jl%sAb9d`4=dIU~tCyb!MM+i}RO`|wk=kru(jZ^z<3ax3^&aNupI zkrD~u-a9#P(B>Uow9!%I0jFvF8_vWHYBSCDwHl-6P--`*Jx!+CI&B}RQnmQ##AA^LVc1Phs>UVNmf|NQka4^mn=PZrHYmKMT=*{qCK*vviKXKqE z4*bM{pE&Rn2Y%wfPaOD(13z)#Cl36?fuA_=69<0cz!5mW3nLiGi}OB`lNQ*JiKts^ zh+Y}_S-PudWn|PTG^cH>jL=lQF{fQfvrsSNXWk{AH*gW%<9P;8E&yO*1EAuwlX;@( zBu{q|X0+B@S*FP>n~|lM9_cq?*2Bp2)oJE!5X+Tvfir4tQ$q1f>@CQIbs@zI{Fr!( z!he;-e+T2oBc0ZU zk(YsK`MLt@phXM7Z!F_({{(!R-hElo#s$ZOhYc(i$mm!qwEhUPiGS=wUS6jG-8uD`Zz5uGpO5=qCEli!;3cfcg)nLNX~8^k z`w4P__eM#A+w%nwNNw=RQuje^XbE7uLFAdpVFKH$OyGMZaHRz9r8;|0;#tLm-M%dG zud%W?$T_i>oC{?BLgX)|NBRixtS=uP()ZJ}5^H3jbZC{U>pQKc%GIri6zGRcch(2p z$z{!hjjf|6qHNmocP^-w3sixMQM_9JcW@JrcHrSL^pLUo?@R5*h6C5A&~j3H=$e2EE0V%1-aVG{oX9KHf@pPtv0;qU=N)~yGSCoE48+=Jqfm| zVqSvZ6T>=ZYZLXbL?*8o^Gm?Yv!J{v_RCqGiB_SnS%oe`MNrtR?%`f6prd`IcMpFR zccNnq=#=;FS)R+RtZ!IZXLHt3y~-@6GFRbemggQT%X%wInpN6VS=u#5X~ABl1+1*) zR#qJo!hy#RIaFj7{c)}QyhsWFwb z=(>%TWk=Lny<{z#d3KZ*T>^<7R*U{bRl!y(Lu*gu0!=OYD>V`=*9!x zhOAbYm2QYJLhCo(z7$DD=y<}8jabKod{_jgGGvnW_4xg^Hs{yESBcU9_A4Bs5f>@740aP;TgWcto;dA`7go9&`TSOp@JvT0)f$6F_UOjPuBWj1{)^k z08C%~Eh!R_qcu*fE=a73iy7&P{B!akBDdfS+eWQA*%poGY!i=vqfJ~OQEAoswS=dj zb+%`;Mc8>Jq)3rqriL;-=i{k947te9n2Lz_pz842IQyI^ZCndJ99A38r}8hhie5gJ zcw%bfiHP;qMh4Hc!1DoMX=4$#5*XUp4AElU1)WL^*vS1R=On@_k3ApIk};6O^` z0`rAhX(bhLLCn4s;(l|++`BLi-h6|P{E7N)N8}!egQMr%Ly3+ zj8Ku&qWo9J<2CV!B&rCxuw?4Sfojvqd6~*%V4nrN6G{#^$bg*VUyMCO{}}#03;tEW zOZ{7I}s%%wi7^>)qD@WwewS-y#d&^|E|%F2M8$v2DUI0u1H{m_8ec z2GXIBxLKKXR%MDTWDbc8vhyqGsbc0S^I|=?D>X884|l`Z(!y}J?*>C#=ZxslRulIJ z7H-YL{RZrE?_QHh3|auo03dtKLbAH-c4-v`<>}4eiW)EE;EooOxBQvK|Zp``*0-jgGMb8Xi(o; z))A@-Jc!1>g%aP`FLiP{BI1tsES*Hu(n&Jxfzq+i9^8nZLsn%?iR*91Hb>sCM!o?C z60T#2B?QvTvGVZP{#fGZ-+@$0FBR01in5y{{tP9;Uiu9@lrWq?&hVL);U568y4}H` zIh5Oqcdd3|-wAS^FfTzW3Fq2n<$9ZPB|r?3YSZJ}3HoFMGCV%cvd7Bu2(rLfkjE!_ zJU+_RkH^<|RF4IkF2%|kd5i06QvOK=PdbGIQR;>e7 zZAV$SH&`Z6@lc+Cr{@%JKr^H5G?Sp9F-cy(2{Va)LM#E8-mnikcuCLRUabsz30mMr z_UGRH4DMZxzs8p1Nh1L=<^dLFGQhx`6UF<1=0kG+Cdub;{;o%{X1~lxXd{t+0aB@7 zX5DLh=X>bhZm^Sd@74=?>s}?;aai3ui%1_~5+5xG6QY%mv7KvSyMT!s zCL93MXZ-`bTT8rylc==;pJ;()i_H}iYwt;fkN5#) z?LcL!6$4!iAie1;sa6xv3dK_;rdrWk_;{Nxx7Bd@co2L01Q!`%;DH5u2-T929BupJ zFKE+tjx=ABNQK-M1vh~LQX$B+QA|Qt7|j8O&9-3AW7uI5b}(S|s|@-wh`xhw6Mg;9 z)7&*Ninv{n0Jz17rKSeHl`3? zD57n1FV;zD*-~g%5>sBZhPfE<=P{wbuE9WJ8G zZqIB&&Cst}&{r7vb6=BCJb8l7=|*un=Hjq#HTOfbJu!wNDLE#lJ1tDFS(suNQ}i?s z7xh;QU>6isI;_7y&(imGjS8?E^_vahn2m$;zlHp|9o3L;6fgQ4cK6xl$7T2zBrviH z7Rhr%U&WYrP4NryCboT+DPq#P#v_eY=QcNCauOGNnw(#p#(#B0$Q)$iwdu*Vj4F> zdEMeS6d5to#NI>Ww-)vVjD3{265NUIFrgc z6fcAuE+SdtO(mj~p@&(}$1}OZ!nrLHN+dvSNC^_zEx;@lROtjv`MO0bMM#w-wi_&L z$5_}tLaQNF8iNratI|?ZB~nw$Bff)6X=c}~?8jNzmvZ(fV(y22M2$z8_E7-W1D^xk zb&|S5sJL5PNfA3#v@dnXTj-qzbxGh!v=TAeF&5YWNrh;JsPyqD$WS5%8%w3fBaxKo zU(gz{{xwsHDiJlioODv4z(u4$bPF5xqMa&Fkx+OX$)i`7^G9OG=@t!-z>q?V!plzw zWT=SXMLrPpQ5ep3mX*tmT$aMz)ner&o$OE^RXMfSXjl;b?G{ z^Q|nqp}$08?wb-yd|k?=+$Ji@S!-I~C%L>ukqNU+Ozdbdrim7&rx?>H@hcP=Ef)rx zWP#0RuwmkIfa$;9ZPw0N-|kBCd*k^aDM@_0Yk=Py>#vD3qXYduL{p3EeeorJQpvSc z$HiZfn>NcN?KKhsmpR)ivkPVqm4wnWBf5v%5}f8Xe&v^l0`h&o3VD3l4vVbs~E@ob2gK5D{uxk2c{JPgBI6JCo(dljh*{A6L-giJsw&Md+Gf;9(jNN@h|&&@FI#-jkGqHB-=@nt`YFL& z7x;fJJazHX91k8S{&i_x`WHTV_x&Om&bWy zl3nfPHe6E8Q;3!T$|!8HQ5eh!4l0X|+$tl~&74aQXCscG4c^ECr)X(7oZFV;p~HII zNa)5`Z5^d{55Es96nKrl_-Ps=*=r!CtTvdaok-?1yzIs2Aj)HV6rc@s#CV6}pepYG z^tD5aQ^B%|;_>`@HvdkhUwM9A?MqM{yqVf4-hn2$bFw{C@zCSJ&%9}#yKxaUpb65S zIZw&S?jD{DgGtLJPQzl-3sk1X^xSLZy-enP40*9v13rJ{2%LKaw^$K*RAi1;hDB)y zP6tUXxS$B9m<2kM7mmasBtfVapxmA(sO)Q?tS~H*Pxy)Pim}`CJ3NatdsY(2c?=Rq zXEnhXE23)+q3751+=GMDv18__vR&Btl4`4A%rFPGS_`@s&@;2)D%NSW*3kqS4uBZr zEFWJUXkJ7Yty-O#il>9=WQf60PZ@}wCgbT*^z^8xrx#ORb>?8>0M%=Vx*NGXOw8a+ z4=e`dz9vGLs)3o$=64q%hkyPFO}>n#t-Tkb9U4Dz=Y>UZ@l1XtL7I?-^LEz!USbQRo0gZ_OM|;5Hp8f z+>XKPhDTdgQp**A&M^fE;mcjx3>=_>-7eO|SHLO)!e7vu>a7kOO!6g{`~lJhJ|FOf zc}nbd+(llQ8J?Epo;C~9)H6M+0b-03og2jtSWDZGZ8QEs!^Slcjo-+D@f1^mX{RBi}Dnje9c0kGFZ=e06s=R5s&hhlQ4wFM$^A+mEz)vDR|rY-1s^0xipXihH&vnKE+j z&#c^2IQIw~8PcIcu?tKbj=p z`9@h6MVEEIh3*Rr-7}1Cgx1I}(4r#0vw)~1<}S|QxYq#dpp!zxF)-o`FB|ZMFVL3B zl<$0a1$Btx9pU*K;ovhfpTZ-9rn$o zlwMo@z_GExhNAY6o^QHmj^NDlqIU$_X?D-Idh4V&md0JjuIIm5d2>jqtD0dhi z{wreNrwtZ-4+s&5sJ;MuHso-^a^Y`*zsf4KNbthnKHMdp^( zR;SxkcMJ@@odh^s0s>6J;Hk`(Quf7&-q~VQcdXezeEMvUw!}a|SX+V$E?mPT>KoKD zUI}Pu%1?@?Q~!_`jaw1VBCmDQg*S~(p&HXw&G{rviwQYiR9^2NMEPvjqME!+9Qll) zcu=F3IZGRw^H09dW)9JY$bD z7Rh}o?uOy0U`F5`1XRd|vl6&*$RIRkYmVEqof_wU`Y8ptG@mQr2Eq_W+qoDrDz2GP zcFuR6VN`VNU$8uge_7~wjhr2j%OpCjkxuM{%~WOqocs{2iae1F1JCOI@ocupvPnE3 zg0@I%ZG;XHMGgTkHqgw8Msw;1X6U#z7)YO!EL=)O2~6-LcXkskfe9+483xE#+u6N6_l3X(|f=JH2{Vg=N=TZ`4_ z;}SYfza1B8yexNl9BP9@^xWDf+NWCWEIDCEp0MZm4^g#C=;v`0v8>%t1N%{Q5*XI& zU|T0YVD~0Xo*(BZg6&Y4vWZ*0`Jw5_**UU~jEH)0N#TdsCMK&1E*w(LvtZLr&5f=m zBYDa~q5%mUXg~l7vD7oeqIs1Cbu&Ya05e9wdjT^pA)Yko8Mx44cHS$C+8174jQK(g zV@gpQ943Rqntw^CxN}^H&KJHiH&{J(4bA~3A#1VVl2`?iYL_Hy58AbR;8a2qNs#=@_{2(CoK6F9L`5Y@_Ixd!^Kt6M zk0FDY1f~G%@pOdZasm)z--X*58@|LQzFLi59OaTfiP;7my|WW3Rp`DqvLov#m} ze#s3eJ@S@WQ8!|8XAf$9GezXdd(!0?_%v9}2AS;PDaNsjj)J2MVVcM3`gE;<&K!=1 zExE2jYos?t@MBiTCua2sh^cUkN8!z|MnOEtBUR=1zvp2wAJrR`9S32|si^X^+Hf9o z7=1gz7nLr=xlk!MN^d1tGKc&P6p!$#wP%~bX0jI8pQT&e$uyqbVh=JF2-Fd%ET}E} z)^5~#B-`YxNodVa$}?5d@WqpmZZ9uriQ?Y0MFk}5E=N$(Dh z2__((1o!f7s%bv@5;}`DOW5GUuH&TDPZM2$Z=xZ2D6f&4f!nhRjoed1KN?E*)Z3XN5kfsUssRVYrqwrKpoaZP!ni9JR%PsSdb3F1E-QDUa+(FlTN8tus_17tK zv!hU@>n|LI3vdn1AhK=l)$(IB|0KGpQw_~X6=`4^eM2TCKV%Edkl&EOjr@j;jXo5U zz+a0A&ET)ca7s)lcMB!PxIzt0lT8gJT3X5^o&q3SE zI0KcV#M2#xchhy8qmY(B^rPwFSYiyV+-9UX3RCIviH<_rEUdRvVydHX6RyRjpG{HL zl|qrkL(gG%(bJ$Z!!iGE$0Mug?&$fGfQ0Tw5<1%Fm2o^+N!L-1!dr0Fr%~isN8!H+ zY=oomOI&rDS;-hmc?#)nxTElobRC9$t@OBnB10U7*HVODa>z)al2(zJ2U0FUcY_^; zU349UWfffYW{L~|2k4sQDD>m1{~7&zM$G(S3$DzFcNDIoSe&D91+J0HGi-F6l%psf zF?>@fpSlpe01@m@(xF0Xc~N})!5DD@22}bL$gplCWqrs@ zzYCekbBUmN;8bGgMvQVpGuqH@4%o_qf29WF?*iZH#87;HsjWNffY^#Wk&m6Fq1+MF zzJ!OAv<*Ipn21u;gsMbE--T#Zf-|yT{ACrSQI9Cmft`Qr5YNY0j9!Ll$4Ehc3(rEi zP4ohwSYQY0T` z3z@NlAEM9)pjl?Z-E~N~4GH2s&=yhCq4}%m(+m1SBoag5wioX}6LS}nfpB|hhN_q> zgj?icBN3isRFeN385Vsn25luS@VD4c8tEsEbfB^51E_>W#Elc_?iRW`7I!8Yr!^y? znfc6&+Wv>`?(`PD11ToRoCbir7nSh-$4DT>0n7X(;%a&Sd?V7|!9AqfN%Vua7f^w; z6UoH(*(XT&6$5dBt=kd53Graev(HdfMxiRsjiIcj-~j3yf#cVNyD#nh{H`-b*{*8jo)$nU4jY63s?Q(iSu zUxtVHN>_de4$J{E`>xwdV?%kP@-bS-+ZoKXskk-Exz z1T`U)mm17WoT(=A_r7L~!0;@Tmpn6+wKFthOAhkGkcp8HZ76pX^gmyV(MO_OsB=|9 zx9-5LIGXBvOO(RCy8{VlL?w*FHVJ)HkGi*hj(9TSkkH55aDQ?X@H6!AAK-EbN7m(F z_JdSjt6;@h#>YIXAOugrLj`|3l)cN$Y z2TYbd?C1!O=y7oG{F4{t20D+PKYYRUfzHv6Lh@__og=-!(8=WubPn@Q)%|=I>pdyZ z8RK=}07Bod#KGTzwjFp-OeR*)`?YFMieGU@Wk*|Rdye)#1Tm(Xe#xwMB;t3SO{a(bIV|2Lzst9+vxvAo>7|I)6 zF1kb6<>E$mxwzraw#85fYYXL4uZu1g$^6x}fpphKX*+^3!7=WhPqv-5)a-5Jsgl2k ztmRb6rpL&arO#$yx(wb|=t43*;JVh~ct0SjGii-!~PHe|dRSdpZ1MOIh ztxWhnXGfrvYNl4Z-EPnG#Fb+FU@@)|7xi&cEpY+1r{Visa?+e#KRc>`@16|K=yDXs zp!kgMyaOY{=(uwl@gBn;yx|#0xgAs7ga_8D=%z3Y{Y%B!=-&XHDE7ThYoLJ(E8zku z4-HveiYrZ{2fi2-=p1x!N--sf$(T>n%GKIA75KhT_aFk+hMS<2EPePp3AXz6oTPT?TFQI!RAz~rZ4HJDQa!T04xt#-{6Tf_4C0Ub55dd z3Dr|vBa3y2Cs8DoFDEqRFSWunl12r9p$GWp02bi3VoW*A7R<4^uok9XJ#KfP!@ls# zs;pMv;|EE`gMZ+23iM#VlD>n!ypxF2OaBRUCAAP(7#|+cO8n`38nEhnw=m-OsxD+SCLWDmclp*Xw*dBH%-yw{B%%xn1@Oy+}1c5N- zahKvoxCNmA;VFbVgs%{eUg}cLK==k>;ICcEDG1jg{08AQgk1rxyDsR#r!4%agfu1C-iA_)5t;+{i!2m~_(R~N#a2p>@z!YR+Yl)DgK zKp>cHxIXuSONsxZOPPppAHtszb|4IVQNp~9>v3yb%Fht~f-vMImvT2k9l~iZOPDaO ztq9*C#J}QF1|T>PE<(5+fy(*-*9Tv9DQSOlDW4%M`?E{A=`SevHJ5VLUmX3+M5OSu=} zU4(rI$9)KRgjW%cu7hqPoKugyUqSEaiZHd=rOZP36M}!YOWB0*34*=FrJRf~1L19i zFA-k++@*Yt(1nn{2W0f*;`xggposZgnZQBCJ5zh_Dagm`?zQ za2LY!2;~T0A&hKvDVHPMiSQJ{Mg-?JmvS3I7@-W|O9cCNv`d5;2rnR%BK#ep6T!a2 zrHn$Dh%gJ`ZiEm*HNw{jDLY-tnFw_PglYtV;P@0a2X_2< z8+wDAinuqx@iBKJieYPARnd*;L6j15{qnVym9XUbT9`&@P7H9I?HZr!q!n#OidMwq zF@7;XD|(YtO8IvUe)Bbc39R@Sm~HLdCy*lEeiglcdwNTHy*js6&23C?PcKz{Thy%A z)VXWa+&5LT6Pq==^B)g*!N1Qnv1skc2yOQ^Mis^>|83M8+dg2A$dfV=TZimUJ74Tmc5+BhjCa^ zZ4mpIsuJ~oO~HKsyObKJO6c04@~xvNg5)mFqGO^$!S19qTacyRRVk(KZ&?#uPW7=@ z2CCxpB@ldYEyWRQuW~q^C@pP@3(jrzx7gJE_NJ~)$ua6mRvYYU`gRdNk5P95jlB|n z6M-k#o9tPw`duiHD=KRuxu(^+KyJRqY|^h_5G)dehXE8AM@vp*_f&9%T05!(7W*<2lXW?8q+@ zcIQSpC!VjB+3IA)@kFNCYOpBi_(Qq6wRBHhFt^p;TxtIr2ifPg0`W@L7v_|0yPi2f zQT*T8uxX56wTL8yis+lVkPky(CR|&-gcCw5=_)DW>Gq@stsLb!FeKWJ;W@63Cwmu( z0x>7QL!t_O^!qU3fh)DUQe?-ebimq`)ujItS5zXH*M!Cc z&Nim4k&Ml2(qAB@xU&iI_V@d+4h;-!6J6D?LK$FMWob)H8d{gXph?kxkHRonM}`7i z>tiHN1=q}G1pN)p75-+M(qi9&2$~P{+21nGzC}+PY*gE1iLE?Pm8>5-$81YCqeE#4 zE~j1tHTxb7DYxm6R#e&?7sQtr_Eg%pq7C_a+E8wjUV>Wm(|pY3s2#!FreIzRtta)@ zSfVfkFWOvgQ&fWs=C}q{n$couHuQg^VcshJ2ciEl#I3k?NIcp|qIg)z8VC^`ElgymAwe9=Mi#PO z--anUNU(pszXIkCZNC&&9rPGl9-INoNAa{u5^2jg|1KL$EZTIOKIdAZBC$QI)#bHo z4VUQcN&Uz+Ucc}ff*Sxkc`n=J9))M?NNJ|dbI;hL_WD&In1ppYXM`zS%F}?oSh8gK0Y(#}Uz}l39`sWIm?1

syEkosRaFl2nWOU|Rq_ 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

9UgN5ItMWeBmX9UUaP_ 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 Tv@Z#>E~23t<49WiN5B6Dc3l{- literal 0 HcmV?d00001 From 0b0b3611bb46424c356dd616abe657ea704a1594 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Wed, 2 Mar 2022 18:49:47 -0800 Subject: [PATCH 27/34] Housekeeping - Minor updates to a few redistributed CP/M binary files. --- Source/RomDsk/ROM_1024KB/UNZIP.COM | Bin 3328 -> 8704 bytes Source/RomDsk/ROM_1024KB/UNZIP154.COM | Bin 5248 -> 0 bytes Source/RomDsk/ROM_1024KB/UNZIP186.COM | Bin 8576 -> 0 bytes Tools/cpm/bin80/SLR180.COM | Bin 25216 -> 25344 bytes Tools/cpm/bin80/TEX21B.COM | Bin 10624 -> 10624 bytes Tools/cpm/bin80/UNZIP.COM | Bin 3456 -> 8704 bytes Tools/cpm/bin80/UNZIP154.COM | Bin 5248 -> 0 bytes Tools/cpm/bin80/UNZIP186.COM | Bin 8576 -> 0 bytes 8 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Source/RomDsk/ROM_1024KB/UNZIP154.COM delete mode 100644 Source/RomDsk/ROM_1024KB/UNZIP186.COM delete mode 100644 Tools/cpm/bin80/UNZIP154.COM delete mode 100644 Tools/cpm/bin80/UNZIP186.COM diff --git a/Source/RomDsk/ROM_1024KB/UNZIP.COM b/Source/RomDsk/ROM_1024KB/UNZIP.COM index afde72047347290bcc1fcee1b9977a3c2572b545..9da369ff7dda1919d27c90d74e498740a763e066 100644 GIT binary patch literal 8704 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 E3&_*^!vFvP literal 3328 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 diff --git a/Source/RomDsk/ROM_1024KB/UNZIP154.COM b/Source/RomDsk/ROM_1024KB/UNZIP154.COM deleted file mode 100644 index f0572630f7ed298de0b9d21d22ece18683407269..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5248 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 Q*c-y^O?P-HF%QOn0LHJoq5uE@ diff --git a/Source/RomDsk/ROM_1024KB/UNZIP186.COM b/Source/RomDsk/ROM_1024KB/UNZIP186.COM deleted file mode 100644 index c750ff5224cc2547a4f1a4fa6ad37bd41c09fc2a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8576 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 diff --git a/Tools/cpm/bin80/SLR180.COM b/Tools/cpm/bin80/SLR180.COM index 0360a7d53a3bab2196dd1082cdebc36f12d456b7..91255eed88757e8559eb059d8a953229f31d0205 100644 GIT binary patch delta 20763 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 delta 20603 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 diff --git a/Tools/cpm/bin80/TEX21B.COM b/Tools/cpm/bin80/TEX21B.COM index aa72b28780fff1af4e5b14938b6060371b880982..68326c1f4596eb6a37b62b427e75799926d26331 100644 GIT binary patch literal 10624 zcmeHNd2k%nneUb~l19f^qg$h6=FO$<*FFbZ;6?|wWn+V-u_Zee*u)mLV#Fa?wu5aj z4hh5w%Lc;b5MX1nIchh{9ggx=MZw)b(n^}ZRH1;jCg(OP^{UXiSvuvVV7|cVJ)Wn!bHt5!yO9u)BZY>wS83UEki27}vKg zy1c6^*`{#_P3)z~D-uf*-9(%{%lS@x${ z@~iO|8}j8R;&z>fXeHyxEd7o+o`S;k`}xXX%FMF& zl$bAN*-EYXY}V)3vp?}2+K?TM@wa(U&(e$Hvf=>Y{|A0^wIN_>1^Zs z*_Qkwb-I`wJoZ91|1*zE^39UB6KsK7X#70e*G5xxZLci+xJV
nU7d|hw%Bn#?F3M8Qbx64wQdej?W7U{UmQr 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 C7rMv* literal 10624 zcmeHNYj9k}mA+Sxk!B=~G?Mjx%ECPgR_B(y= zSl+7C{>fHtZSA_`>F(2~PoF;L^m+7*xgbmF7};}h-_Xum4k+sOxU%T-rOis`(9WR) z+iq3*2lo$d+qeA|WqsEsCDF7f(wtbh=(2@N7p)q)bx;`|IiTD;a@+8Z$Th<|25%l3 z9^9eeU&qMq-P-`%II?eta$sacxpicCXJpOr?b~i0+M)Dq+qZ4^;DNz?k)jnhjqJmw z*DmadE6XEA%KWC~yiIRy-*Wxt)k6oAZNmqZPY)gh31$1p@PVP>+XnT>`oTLCv2Jij zq^rNbw_jHx9lbr^Z@nJr83E_}2Dcv=*>_MG*t2c>V5Dls(&a4$fBu^;JW|L;G(5`3`r}iySVRj>=Mgz$4kINQw<>_OBxWDQ({u z@yqtBkYDgHrYb?6iP&rS+XkIKg(h>jV+S=iiMFHH#v=+ZDzBG*cYSvig++t zkS#w=1Nm9v(v~EPy~X$HYca*M`CGi(Zige6}(49yk9eXv@YQvw4sPO@+$J)uV}NPAHQf<*;eKgjK065-(S~?eFLK zF9$6?4OOAvOgt1ZC0DR(u@Cuv4JXomc@m$m=^yg8#D{z~J-#uQUx0c);3s{f=!HWU zI0oU+2i$DVwb&%C$y<3|-?09}Cpqiiei2H90dsta?4sfk;w}&;k0QO@- z)vt!0p7YpEp5Ww@9tUPV=Mn0A&O@3?3*`a@%4HsHFHAj=r|KRpA#DDa9@bhG%2&;g zJah?U<1G)n=Mq4UG3{YF9tVRJ&O^syc@STo)(v;Uit?s-zIw)D6;6lyU>9G_#nCP1 zB{>HQC7!QUPc@Xo|7^-dKRne?;8)OR1zL+_`}1_4ihEL%Ppx8X%>&5n7tjcx_VWDT z6N1GjAoHW_~qq=|^2{)fEw0zrN166(o3^OiilKnqU(iJ-EV&IF|^Moqr_9z2f&=$!m=5(d>kGWX;&NeX@3Xt5$F$z7rs zX`|?e0S|oGh}AC`X1={E-(r4kuf>XC6~)?YuJJ}b`Ynq2Za$4Y#=By?fCkEBu9p{U z-E1~r+-}wxUu+)o(v;WO>t!W4lU{#7&zN8HTC5BU%P?C;vvD6B)-Rn|zmNUO>9JURvEB>f zvX95&F)76=B>TZgyJWu((aAmvit{x4#%M4Za|iNWZnW%$_0L{wgne+}2%F|VW6N@E zS&l8sY0GUsy;@CFXnF-86$H7~2NpN@92T$eAtiXpYc}~TR*7|$8n`*C%^YU&__33# zPfQ;2IX=VU7h(|WOw8K@fj{CbXBT3NEgn`e@s#S-FT{>b$j4{&kjld9vEvI*uKs2) z87^=TA}SP8CDiqASd9pyS820d#u=a98c(#vS!=vSGV2Nm+H0hJdV4&vJkHwZp#4U1 z0c)EZ$BeoHwj5*Zw%B~aXWxTERO1j7O)3l7J-$$l24>(aR~4`)Xw)uY!B}#Afxnlc z5~I1t3jl2cbXS4D%Yn8fFq0ntQUS=}RAb}!7qI&arg)8Z#@v-bf4sooPv}dr+qVn+ z-RQf7o_7dk7QbA;PPvPp&n%v#lPnPgT%O*cvn=tGVZh4d9j<>tF!Pw>8Y(ysG0O+1`C;jP#SJQ-c;vGX=|as4Sbuo7Xn3} zjvedO>$Hbn3Q`#EwGVswbgbKMEU;KTuJ`#mbeh3dkX70xq9y$Y6=9+zbVw~wP13(P_I)HkYyfhwSlEq|OrschM-dMrFudd?l}|1#5^2I=ueq#9T-IepLMvDV zZxM#K2n)x^;7bz`O{`~E#`TCcW(*Y}UK}noZ!6*vxSiXI-0M+f*%LW>EDq#eKkkGc zjYCGU_=)6?irgVC%&|mNb7JW8MLY_QxX=8N(*tjDT3zMmJf4!TiQAqcy&p>cs7N0W z4b~G?kmzlfPY^t+y%g-lsr+fMq;~_W$nP&?KEK0MmET=LIM7NsG(S$_Ndw#>iIXq! z`!|toQoLU7x7T{~9`t(s@+ZP?{3h$-v5ZIkdJUzcLw=-Ri5gXJBz7P5Gc}Ixv9>Mp zB=JmJVn|zx9UgUduvjC7UAxcEHF8}%rrG}#3B@!$rnUCkH~E6epZEbJC7G7rK3HUt zrJW~Bt5zRMsM=we6JyBwF2opzQR^yc=H6noiMXamz;{P6OkoNDT#KXpTx?6X-BCir zbFrhNE|^;F=qOV)LHrc1!4y9q>uyNf&lH2UxvQ9r7JI4MF^pkVZM~;}OP{dN-Ubu3i!@OiGmaF?H&9?T?=3dZ_;FF0I+pxyG5iKQ8#~&2st3EIzzg7@A;?DJ3lovJ z#hPHKlveK5PVRk;H6zZk`I-)*Df^po^)Na@93QjBL6f`i&6E3uKPE#VpkLEN{)iDu0-iuDDW#V*V6^cqWO`Xcc1 znG!T@iABOK16#igqswSCB`&LP)a)s-5X?elDs-%OK^tEwVHPEW5Jv~R=1V2w@_oOA zSK{KrWmJp%i@7D{=78f?#>O`X1lBJ~+$)OU*&@3u+GUmip$!4o>y0a78Tr4w0QsBq zvBbHUqY3>};6M??lJx<$6jpC40ejp}x`wB6+fGK2F!tg zelA8Pu{n@&F|dsDF7!!m1a; zr6Shco%~qcTNPe?a zRQi^Au$1*cD%jDf-R;s$LO9iM1VzoJT;zb1L5@1*{A4MW^B9Q7hu@dV#aWrMzAaM^ zxy2k`s!>X+Ybo@q-IR1$8E?gTC@;02h~kPgm7(8KW0_0KE=f_d%PdsbVVoqzkd4aG z$(zbhcu(;U8#}uLc;$GnlycbFMqs5dQQdy`cTi8v))+_1?4eS2q|7NfP>+X0IckbY z`FKv5{B{}2^r^rNl8muKB1Z*I3g9^sFPAZ^EL5nn0<~om9t@R_qG%j_*%CPjgG{mY;TK?6(eHPOGz==59X=Lv)H_OQ@juf6jd^Y zHc$7fvp%#u4_EJF55Nh(ic$d3@veDnC9qL6nTdI9i3p+t4uBAp?nKV@r@$TqI{4sw6ji4)FuMbFszb zAFm|;XrXRr>!B-h86BD<{%=*%lfWaD_J@^t9jT;w*?g^%CN<-f7-tcN16p9bCP3Nr z1VAe;RI(1u{)Y(gCz`iZNYxs73UF6XmV@(mKb7AK#r zqM(tZLSWFB{a{rv`O_+Let5Pj3-1l@u|#q9MitrW;T*OM%e9sYi}fM%LuEn$iCv8k z3@-g+y+FVp1VeHy8vlHa-ixYXSB>6-^vIa1Ch&lVM{_ZY{jk#9SqnxBF88&6f+Kdf?b z))_ynX6xoy=rDea@!W2aafcPfZRa~}qDM1#inFXYKB%VH`o|jcCIRR(s%nU%P08XK z3ZIxLCqSY^buqe(c7buN(OkpU(q7A)730fl%(EFfn~W_2dY!SMhOLB%%^PYc0*j4+ z#(E%Mb5!6&jL{krdD;=hXKTnHebqwN<6kDCPPy~78deA8>U~hf2^aQ5tRx;zfFfEd zKGtE{t`VxYYwVY+L``$L1~tv;8d1}TsrPF{z9ouXOWx%?jSi62ley&>N-c4-Vp6GX z??a3lLkEC~D|o*)n!$JMBe70)JN+`nyfjQnUnftjfV;Vdt&?4Mb3-l6+5AjMOp!-e z7xH><3~xxC(fj4uPUD_hm?`@d9p-ZxR7~_5$7_-M;bOGM@s5CSbH0`q^cio~+KWps zu@Lv#yj%;IhAPcGEsoG@pq&qQe3~Yxd~+%E8}HMW7`cprYQo5`^KZ2`L=soU%{_Ir zQHN1m=Wim=nhdDRSX76V4qF`==vrfW9lqXim-QLz>g?OAdhIl z-)gn9wMs+<`L8{RqrN%Ka zx8h2pqn<3JX}qnT(ipwo$$J{>O?>mTN08_-w$y_`9#p$|EfPmC6vQ*8nA>FRuDAa# zjM1gM%+X(C{FK&$w5Wg|ulEP={RYBVVmeAEmc+MR&(_noT~F2P)6qmCE-+8l!`BfH zABla|8gB|7YSr$B&k+Z;cn=pd1I7pSsH3~dwzN2abDOU;)CSflUJ4*dRKQq==ZJW` z4Z_9n-dvLG#s-qpdSiWq`#1qnIk;Hb2wc_0h3Gam%u!!q>~0{v!PX`7T|uPFxVs@^ zEe>Rr@fCrDqslJQCgYt3eH~JV6Af}*mh%Ok^CUU`Vgs^gq^_Ad;gtrbo-lviK-XCs zf4xBz4j5CKO_?c(&au>I{JDYk6I2S$L01@SgJ9IL^9xb&GGp+det`-A9%L7yOW1T2 zU&LLAq8*!D6Xel&H@*mc%#ZP6V`0#&Q=B`rCFqZm310~-5}>ulu^@y5$sL`cRiuUK zXz#fb$p?dcI!aFoka9F`J{)x7p0ljScs6*+ohP2tF2!EMB5rvd@^TQXQ(btUQJ?_s zGBvwI@Ee$FHnHBqlRt~Xzyd9WjFwIM@cz^GQ>NI~zSY$jHUw5(sA7|5hzS1bM) z{1X}BN5@!2;c3!5)g4%Ysqz|t}(u+P$51Yy|j=W z8-GGUmWW48YyoSZjsg85JMf>=3N$?-i{i0BosdNFNNJv8H%D-d{Ml4$Zs9F=i8_aE zf%zg&W zW(&vrnLh|1sgcSDJgTP6=fn=Z#y*B)i(F-d5mz#}awq$YFVUnhHv|Y+kvlP9e3g-3 zl-==q;~7SW0-@hz0XE0&3gbOSCh3OKGsI9U*%jgqzNF~E5x^C4PYgy)gPF}C$38!1 zm-jP!;0`A@&1jY_Sc_D=i%xkG}Ze>rwD*z*m~|MV$R`2pABMi}l6J0aueAz_6248C(Y>QWp4zR*+( zr>UmL=#9voNp%9CZ`4pvMHgH8O5C>R!Xih`HeL?v1<2jd3W^r}l40`qVYUJms6S0V zp?E7yKcRR!M!DFDTzxZUx&ir zdZb;~yKlIY_ePM|SSU_D^X-v4pW114cB6!7FPVv_9*w6ScxdFV$99$_zZ>z^o@+B6 ziCC0F#i!!&limzwJQYtRe;V<&8UN}`-}O>(=b_+8k@0Fo(0yd&&L?+TLtA^ot7;w^ zDXV#Gr-e6=nn%zDoOV98<<9WeH>RwBL@#f-kpE@~VKZu%ls}8c__;w@6hHXDZ$H?L zn7UC+c9!f7RI~V^%U7&fckQ;Jy$A34!b6Xz{|ci2 zJxdk$UtfREUnZDAShGp_uMzNDr@xHw|4>L^SaZZMD^xz4&XICF(k81+k)-4Kl7v5L zm9#3~lSOE#U;l6aORtnX*|{>(DoIMGv(o9b1i9t9LP?W=qBk^c&5Zx&uaV2i|Ayv2 E0CP9EMgRZ+ diff --git a/Tools/cpm/bin80/UNZIP.COM b/Tools/cpm/bin80/UNZIP.COM index b231bf47bc6c61f342ad584d028285f2f994b9cc..9da369ff7dda1919d27c90d74e498740a763e066 100644 GIT binary patch literal 8704 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 E3&_*^!vFvP literal 3456 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 Q*c-y^O?P-HF%QOn0LHJoq5uE@ diff --git a/Tools/cpm/bin80/UNZIP186.COM b/Tools/cpm/bin80/UNZIP186.COM deleted file mode 100644 index c750ff5224cc2547a4f1a4fa6ad37bd41c09fc2a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8576 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 From a0d437357ee45369937b211b1a97548eb7ad83d4 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Wed, 2 Mar 2022 19:23:05 -0800 Subject: [PATCH 28/34] Fix Build I had updated SLR180. The newer version switched the default file extension it looks for from .180 to .z80. Changed filenames and build/make files to adjust to this. --- Source/Apps/XM/{xmhb.180 => xmhb.z80} | 0 Source/Apps/XM/{xmhb_old.180 => xmhb_old.z80} | 0 Source/Apps/XM/{xmuf.180 => xmuf.z80} | 0 Tools/Makefile.inc | 6 +++--- 4 files changed, 3 insertions(+), 3 deletions(-) rename Source/Apps/XM/{xmhb.180 => xmhb.z80} (100%) rename Source/Apps/XM/{xmhb_old.180 => xmhb_old.z80} (100%) rename Source/Apps/XM/{xmuf.180 => xmuf.z80} (100%) diff --git a/Source/Apps/XM/xmhb.180 b/Source/Apps/XM/xmhb.z80 similarity index 100% rename from Source/Apps/XM/xmhb.180 rename to Source/Apps/XM/xmhb.z80 diff --git a/Source/Apps/XM/xmhb_old.180 b/Source/Apps/XM/xmhb_old.z80 similarity index 100% rename from Source/Apps/XM/xmhb_old.180 rename to Source/Apps/XM/xmhb_old.z80 diff --git a/Source/Apps/XM/xmuf.180 b/Source/Apps/XM/xmuf.z80 similarity index 100% rename from Source/Apps/XM/xmuf.180 rename to Source/Apps/XM/xmuf.z80 diff --git a/Tools/Makefile.inc b/Tools/Makefile.inc index da16e091..1a579e50 100644 --- a/Tools/Makefile.inc +++ b/Tools/Makefile.inc @@ -97,10 +97,10 @@ CPM=$(TOOLS)/cpm/bin80/ %.rel: %.z80 $(ZXCC) $(CPM)/Z80ASM -$(basename $<)/MF -%.hex: %.z80 - $(ZXCC) $(CPM)/Z80ASM -$(basename $<)/HF +#%.hex: %.z80 +# $(ZXCC) $(CPM)/Z80ASM -$(basename $<)/HF -%.hex: %.180 +%.hex: %.z80 $(ZXCC) $(CPM)/SLR180 -$(basename $<)/HF %.rel: %.azm From 8e414a3efc33d1f1180d2612b873ad3a499e16f3 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Mon, 14 Mar 2022 10:46:11 -0700 Subject: [PATCH 29/34] DMAMON Enhancements - Added interrupt testing to DMAMON - Updated FIND to latest --- Source/Apps/Test/DMAmon/Readme.txt | 7 + Source/Apps/Test/DMAmon/dmamon.asm | 351 ++++++++++++++++++++++++----- Source/Apps/Test/DMAmon/dmamon.sh | 3 - Source/Images/Common/All/FIND.COM | Bin 10662 -> 10280 bytes desktop.ini | 4 + 5 files changed, 311 insertions(+), 54 deletions(-) delete mode 100644 Source/Apps/Test/DMAmon/dmamon.sh create mode 100644 desktop.ini diff --git a/Source/Apps/Test/DMAmon/Readme.txt b/Source/Apps/Test/DMAmon/Readme.txt index 1d6ab543..24ca0401 100644 --- a/Source/Apps/Test/DMAmon/Readme.txt +++ b/Source/Apps/Test/DMAmon/Readme.txt @@ -1 +1,8 @@ DMAmon is a program to verify operation of the Z80 MBC DMA board + +Version 2 has been hacked to include testing for interrupts. This +requires running the application under RomWBW using IM2. There +is an equate in the source file to disable interrupt testing +if needed. + +--WBW 10:36 AM 3/14/2022 \ No newline at end of file diff --git a/Source/Apps/Test/DMAmon/dmamon.asm b/Source/Apps/Test/DMAmon/dmamon.asm index 5baa6be3..9cfc0441 100644 --- a/Source/Apps/Test/DMAmon/dmamon.asm +++ b/Source/Apps/Test/DMAmon/dmamon.asm @@ -16,6 +16,14 @@ TRUE .EQU ~FALSE SPD_FIXED .EQU 0 ; PLATFORM SPEED FIXED AND CANNOT CHANGE SPEEDS SPD_HILO .EQU 1 ; PLATFORM CAN CHANGE BETWEEN TWO SPEEDS ; +; INTERRUPT TESTING CONFIGURATION +; N.B., INTERRUPT TESTING REQUIRES ROMWBW!!! +; ASSUMES SYSTEM IS ALREADY CONFIGURED FOR IM2 OPERATION +; INTIDX MUST BE SET TO AN UNUSED INTERRUPT SLOT +; +INTENABLE .EQU TRUE ; ENABLE INT TESTING +INTIDX .EQU 1 ; INT VECTOR INDEX +; ; SYSTEM SPEED CHARACTERISTICS ; SPD_UNSUP .EQU 0 ; PLATFORM CAN CHANGE SPEEDS BUT IS UNSUPPORTED @@ -56,14 +64,20 @@ DMA_RESET .equ $c3 ;DMA_RESET_PORT_B_TIMING .equ $cb ;DMA_CONTINUE .equ $d3 ;DMA_DISABLE_INTERUPTS .equ $af -;DMA_ENABLE_INTERUPTS .equ $ab +DMA_ENABLE_INTERUPTS .equ $ab ;DMA_RESET_DISABLE_INTERUPTS .equ $a3 ;DMA_ENABLE_AFTER_RETI .equ $b7 -;DMA_REINIT_STATUS_BYTE .equ $8b +DMA_REINIT_STATUS_BYTE .equ $8b ; DMA_RDY .EQU %00001000 DMA_FORCE .EQU 0 - +; +bf_sysint .equ $FC ; INT function +; +bf_sysintinfo .equ $00 ; INT INFO subfunction +bf_sysintget .equ $10 ; INT GET subfunction +bf_sysintset .equ $20 ; INT SET subfunction +; #IF (DMA_USEHS & (DMAMODE=DMAMODE_MBC)) #IF (CPUSPDDEF=SPD_HIGH) #DEFINE DMAIOSLO LD A,(HB_RTCVAL) \ AND %11110111 \ OUT (RTCIO),A @@ -100,66 +114,128 @@ MAIN: LD SP,STACK ; STACK ; call PRTSTRD ; WELCOME - .db "DMA MONITOR\n\r$" + .db "\n\rDMA Monitor V2\n\r$" +; +#IF (INTENABLE) +; + ; Install interrupt handler in upper mem + ld hl,reladr + ld de,$A000 + ld bc,hsiz + ldir +; + ; Install interrupt vector (RomWBW specific!!!) + ld hl,int ; pointer to my interrupt handler + ld b,bf_sysint + ld c,bf_sysintset ; set new vector + ld e,INTIDX ; vector idx + di + rst 08 ; do it + ld (orgvec),hl ; save the original vector + ei ; interrupts back on +; +#ENDIF ; MENULP: CALL DISPM ; DISPLAY MENU CALL CIN ; GET SELECTION -; + ; Force upper case + CP 'a' ; < 'a' + JR C,MENULP1 ; IF SO, JUST CONTINUE + CP 'z'+1 ; > 'z' + JR NC,MENULP1 ; IS SO, JUST CONTINUE + SUB 'a'-'A' ; CONVERT TO UPPER +; +MENULP1: + CALL NEWLINE CP 'D' JP Z,DMATST_D ; DUMP REGISTERS CP 'I' JP Z,DMATST_I ; INITIALIZE +#IF (INTENABLE) + CP 'T' + JP Z,DMATST_T ; TOGGLE INT USAGE +#ENDIF CP 'M' - JP Z,DMATST_M ; MEMORY MOVE + JP Z,DMATST_M ; MEMORY COPY + CP 'N' + JP Z,DMATST_N ; MEMORY COPY ITER CP '0' JP Z,DMATST_01 CP '1' - JR Z,DMATST_01 + JP Z,DMATST_01 CP 'R' JP Z,DMATST_R ; TOGGLE RESET CP 'Y' JP Z,DMATST_Y ; TOGGLE READY CP 'X' - JR Z,DMABYE ; EXIT + JP Z,DMABYE ; EXIT ; JR MENULP ; -DMABYE: LD SP,(SAVSTK) ; RESTORE CP/M STACK +DMABYE: +#IF (INTENABLE) + ; Deinstall interrupt vector + ld hl,(orgvec) ; original vector + ld b,bf_sysint + ld c,bf_sysintset ; set new vector + ld e,INTIDX ; vector idx + di + rst 08 ; do it + ei ; interrupts back on +#ENDIF +; + LD SP,(SAVSTK) ; RESTORE CP/M STACK RET ; DMATST_I: call PRTSTRD - .db "\n\rSTART DMA_INIT\n\r$" + .db "\n\rStart Initialization\n\r$" CALL DMA_INIT JP MENULP ; +#IF (INTENABLE) +; +DMATST_T: + LD A,(USEINT) + XOR $FF + LD (USEINT),A + JP MENULP +; +#ENDIF +; DMATST_M: call PRTSTRD - .db "\n\rSTART DMAMemMove\n\r$" - CALL DMAMemMove + .db "\n\rPerforming Memory-Memory Copy Test\n\r$" + CALL DMAMemTest + JP MENULP +; +DMATST_N: + call PRTSTRD + .db "\n\rPerforming Iterative Memory-Memory Copy Test\n\r$" + CALL DMAMemTestIter JP MENULP ; DMATST_01: call PRTSTRD - .db "\n\rTOGGLE PORT\n\r$" + .db "\n\rPerforming Port Selection Test\n\r$" CALL DMA_Port01 JP MENULP ; DMATST_D: call PRTSTRD - .db "\n\rSTART DMARegDump\n\r$" + .db "\n\rDump Registers\n\r$" CALL DMARegDump JP MENULP ; DMATST_Y: call PRTSTRD - .db "\n\rTEST READY\n\r$" + .db "\n\rPerforming Ready Bit Test\n\r$" CALL DMA_ReadyT JP MENULP ; DMATST_R: call PRTSTRD - .db "\n\rRESET\n\r$" + .db "\n\rPerforming Reset\n\r$" ; CALL JP MENULP ;================================================================================================== @@ -167,19 +243,39 @@ DMATST_R: ;================================================================================================== ; DISPM: call PRTSTRD - .db "\n\rDMA DEVICE: $" + .db "\n\rDMA Device: $" LD C,DMAMODE ; DISPLAY LD A,00000111B ; TARGET LD DE,DMA_DEV_STR ; DEVICE CALL PRTIDXMSK - CALL NEWLINE ; call PRTSTRD - .db "DMA PORT: $" + .db ", Port=0x$" LD A,DMABASE ; DISPLAY CALL PRTHEXBYTE ; DMA PORT - CALL NEWLINE ; +#IF (INTENABLE) +; + call PRTSTRD + .db "\n\rInterrupts=$" + LD A,(USEINT) + OR A + LD A,'Y' + JR NZ,DISPM_INT + LD A,'N' + JR DISPM_INT +; +DISPM_INT: + CALL COUT +; + call PRTSTRD + .db ", Interrupt Count=$" + ld hl,(counter) + call PRTDEC +; +#ENDIF +; + call NEWLINE LD HL,MENU_OPT ; DISPLAY CALL PRTSTR ; MENU OPTIONS ; @@ -206,7 +302,7 @@ DMA_INIT: jr nz,DMA_NOTFOUND ; call PRTSTRD - .db " DMA FOUND\n\r$" + .db " DMA Found\n\r$" ; ld hl,DMACode ; program the ld b,DMACode_Len ; dma command @@ -224,7 +320,7 @@ DMA_EXIT: DMA_NOTFOUND: push af call PRTSTRD - .db " NOT PRESENT$" + .db " NOT Present$" pop af jr DMA_EXIT ; @@ -242,38 +338,41 @@ DMA_DEV_STR: MENU_OPT: .TEXT "\n\r" .TEXT "I) Initialize DMA\n\r" - .TEXT "M) Memory to Memory test\n\r" - .TEXT "0) DMA Port select test\n\r" - .TEXT "1) DMA Latch Port select test\n\r" - .TEXT "Y) Ready bit test\n\r" + .TEXT "T) Toggle Interrupt Usage\n\r" + .TEXT "M) Test Memory-Memory Copy\n\r" + .TEXT "N) Test Memory-Memory Copy Iteratively\n\r" + .TEXT "0) Test DMA Port Selection\n\r" + .TEXT "1) Test DMA Latch Port Selection\n\r" + .TEXT "Y) Test Ready Bit\n\r" .TEXT "X) Exit\n\r" .TEXT ">$" ; ;================================================================================================== -; TOGGLE A PORT ON AND OFF +; PULSE PORT ;================================================================================================== ; DMA_Port01: + call PRTSTRD + .db "\r\nPulsing port 0x$" sub '0' ; Calculate add a,DMABASE ; Port to + call PRTHEXBYTE + call NEWLINE ld c,a ; toggle - ld b,0 + ld b,$20 ; loop counter portlp: push bc - call PRTSTRD - .db "\n\rON ...$" - call PRTHEXWORD + call PC_PERIOD push bc ld b,0 ld a,0 portlp1:out (c),a djnz portlp1 pop bc - call PRTSTRD - .db " OFF$" call delay pop bc djnz portlp + call NEWLINE JP MENULP ; delay: push bc @@ -290,18 +389,23 @@ dlylp: dec bc ;================================================================================================== ; DMA_ReadyT: + call NEWLINE ld c,DMABASE+1 ; toggle - ld b,0 + ld b,$20 ; loop counter portlp2:push bc + ld a,b + call PRTDECB call PRTSTRD - .db "\n\rON ...$" - call PRTHEXWORD + .db ": ON$" + call delay ld a,$FF ld c,DMABASE+1 out (c),a call PRTSTRD - .db " OFF$" + .db " -> OFF$" call delay + call PRTSTRD + .db "\r \r$" ld c,DMABASE+1 ld a,0 out (c),a @@ -332,8 +436,16 @@ DMAMemMove: LD HL,PROEND ; DMA COPY LD DE,$8000 LD BC,4096-1 - CALL DMALDIR - + LD A,(USEINT) ; USE INTS? + OR A ; TEST VALUE + JR NZ,DMAMemMove1 ; IF SO, DO SO + CALL DMALDIR ; ELSE NORMAL DMA + JR DMAMemMove2 +; +DMAMemMove1: + CALL DMALDIRINT ; DMA W/ INTERRUPTS +; +DMAMemMove2: ; ; LD HL,$8400 ; PLANT ; LD A,$00 ; BAD @@ -345,15 +457,57 @@ DMAMemMove: NXTCMP: CPI JP PO,CMPOK JR Z,NXTCMP - - call PRTHEXWORD + RET ; RET W/ ZF CLEAR +; +CMPOK: + RET ; RET W/ ZF SET +; +;================================================================================================== +; DMA MEMORY TEST +;================================================================================================== +; +DMAMemTest: + call DMAMemMove ; do a single memory copy + jr z,DMAMemTestOK + jr DMAMemTestFail +; +DMAMemTestOK: call PRTSTRD - .db " TEST MEMORY MOVE FAILED\n\r$" - RET - -CMPOK: call PRTSTRD - .db "TEST MEMORY MOVE SUCCEEDED\n\r$" - RET + .db "\n\rMemory-Memory Test Passed\n\r$" + ret +; +DMAMemTestFail: + call PRTSTRD + .db "\n\rMemory-Memory Test Failed\n\r$" + ret +; +;================================================================================================== +; DMA MEMORY MOVE ITERATIVE +;================================================================================================== +; +DMAMemTestIter: + ld b,$20 ; loop counter + call PRTSTRD + .db "\n\rPerforming $" + ld a,b + call PRTDECB + call PRTSTRD + .db " iterations, '.'=OK, '*'=Fail\n\r$" +DMAMemTestIterLoop: + push bc ; save loop control + call DMAMemMove ; do an iteration + jr z,DMAMemTestIterOK + call PC_ASTERISK ; signal failure + jr DMAMemTestIterCont ; continue +; +DMAMemTestIterOK: + call PC_PERIOD ; signal pass +; +DMAMemTestIterCont: + pop bc + djnz DMAMemTestIterLoop + call NEWLINE + ret ; ;================================================================================================== ; DMA PROBE - WRITE TO ADDRESS REGISTER AND READ BACK @@ -455,6 +609,62 @@ DMADest .dw 0 ; R4-Port B, Destination address DMACopy_Len .equ $-DMACopy ; ;================================================================================================== +; DMA COPY BLOCK CODE - ASSUMES DMA PREINITIALIZED +; INTERRUPT VERSION! +;================================================================================================== +; +DMALDIRINT: +; +#IF (INTENABLE) +; + ld (DMASourceInt),hl ; populate the dma + ld (DMADestInt),de ; register template + ld (DMALengthInt),bc +; + ld hl,DMACopyInt ; program the + ld b,DMACopyInt_Len ; dma command + ld c,DMABASE ; block +; + DMAIOSLO + di + otir ; load and execute dma + ei +; + ld a,DMA_READ_STATUS_BYTE ; check status + out (DMABASE),a ; of transfer + in a,(DMABASE) ; set non-zero + and %00111011 ; if failed + sub %00011011 + DMAIONOR +; +#ENDIF +; + ret +; +#IF (INTENABLE) +; +DMACopyInt ;.db DMA_DISABLE ; R6-Command Disable DMA + .db %01111101 ; R0-Transfer mode, A -> B, start address, block length follow +DMASourceInt .dw 0 ; R0-Port A, Start address +DMALengthInt .dw 0 ; R0-Block length + .db %00010100 ; R1-No timing bytes follow, address increments, is memory + .db %00010000 ; R2-No timing bytes follow, address increments, is memory + .db %10100000 ; R3-DMA, interrupt, stop on match disabled + .db DMA_CONTINUOUS ; R4-Continuous mode, destination address, interrupt and control byte follow +DMADestInt .dw 0 ; R4-Port B, Destination address + .db %00011110 ; R4-Interrupt control byte: Pulse byte follows, Pulse generated + .db 0 ; R4-Pulse control byte + .db INTIDX*2 ; R4-Interrupt vector +; .db %10010010+DMA_RDY;R5-Stop on end of block, ce/wait multiplexed, READY active config + .db %10011010 + .db DMA_LOAD ; R6-Command Load + .db DMA_FORCE_READY ; R6-Command Force ready + .db DMA_ENABLE ; R6-Command Enable DMA +DMACopyInt_Len .equ $-DMACopyInt +; +#ENDIF +; +;================================================================================================== ; DMA I/O OUT BLOCK CODE - ADDRESS TO I/O PORT ;================================================================================================== ; @@ -552,8 +762,6 @@ DMAIn_Len .equ $-DMAInCode ; DEBUG - READ START, DESTINATION AND COUNT REGISTERS ;================================================================================================== ; -;#IF (0) -; DMARegDump: ld a,DMA_READ_MASK_FOLLOWS out (DMABASE),a @@ -586,7 +794,6 @@ DMARegDump: ; call NEWLINE ret -;#ENDIF ; CIO_CONSOLE .EQU $80 ; CONSOLE UNIT TO C BF_CIOOUT .EQU $01 ; HBIOS FUNC: OUTPUT CHAR @@ -662,10 +869,52 @@ CST: POP DE POP BC RET - +; +USEINT .DB FALSE ; USE INTERRUPTS FLAG +; SAVSTK: .DW 2 .FILL 64 STACK: .EQU $ +; +orgvec .dw 0 ; saved interrupt vector +; +;=============================================================================== +; Interrupt Handler +;=============================================================================== +; +reladr .equ $ ; relocation start adr +; + .org $A000 ; code will run here +; +int: + ; According to the DMA doc, you must issue + ; a DMA_DISABLE command prior to a + ; DMA_REINIT_STATUS_BYTE command to avoid a + ; potential race condition. + ld a,DMA_DISABLE + out (DMABASE),a +; + ; The doc confuses me, but apparently it is + ; necessary to reinitialize the status byte + ; when an end-of-block interrupt occurs. Otherwise, + ; the end-of-block condition remains set and + ; causes the interrupt to fire continuously. + ld a,DMA_REINIT_STATUS_BYTE + out (DMABASE),a +; + ld hl,(counter) + inc hl + ld (counter),hl +; + or $ff ; signal int handled + ret +; +counter .dw 0 +; +hsiz .equ $ - $A000 ; size of handler to relocate +; + .org reladr + hsiz +; PROEND: .EQU $ ; .END diff --git a/Source/Apps/Test/DMAmon/dmamon.sh b/Source/Apps/Test/DMAmon/dmamon.sh deleted file mode 100644 index 2d738d47..00000000 --- a/Source/Apps/Test/DMAmon/dmamon.sh +++ /dev/null @@ -1,3 +0,0 @@ -~/RomWBW-dev/Tools/unix/uz80as/uz80as -t z80 dmamon.asm dmamon.bin -#srec_cat dmamon.bin -binary -offset 0x0100 --address-length=2 -o dmamon.hex -Intel -cat dmamon.bin > dmamon.com \ No newline at end of file diff --git a/Source/Images/Common/All/FIND.COM b/Source/Images/Common/All/FIND.COM index 2ed5c52be9bf878283c8502d04525f4cc37f6356..163dcc9123bc09bb9e4752edf90697ecf96d88dd 100644 GIT binary patch literal 10280 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 z Date: Thu, 17 Mar 2022 20:16:29 -0700 Subject: [PATCH 30/34] Add PIOMON --- Source/Apps/Test/Build.cmd | 1 + Source/Apps/Test/Clean.cmd | 1 + Source/Apps/Test/Makefile | 2 +- Source/Apps/Test/piomon/Build.cmd | 10 + Source/Apps/Test/piomon/Clean.cmd | 6 + Source/Apps/Test/piomon/Makefile | 7 + Source/Apps/Test/piomon/Readme.txt | 36 + Source/Apps/Test/piomon/piomon.asm | 1361 ++++++++++++++++++++++++++++ desktop.ini | 4 - 9 files changed, 1423 insertions(+), 5 deletions(-) create mode 100644 Source/Apps/Test/piomon/Build.cmd create mode 100644 Source/Apps/Test/piomon/Clean.cmd create mode 100644 Source/Apps/Test/piomon/Makefile create mode 100644 Source/Apps/Test/piomon/Readme.txt create mode 100644 Source/Apps/Test/piomon/piomon.asm delete mode 100644 desktop.ini diff --git a/Source/Apps/Test/Build.cmd b/Source/Apps/Test/Build.cmd index e0fca5e1..e68dee33 100644 --- a/Source/Apps/Test/Build.cmd +++ b/Source/Apps/Test/Build.cmd @@ -21,6 +21,7 @@ pushd vdctest && call Build || exit /b & popd pushd kbdtest && call Build || exit /b & popd pushd ps2info && call Build || exit /b & popd pushd 2piotst && call Build || exit /b & popd +pushd piomon && call Build || exit /b & popd goto :eof diff --git a/Source/Apps/Test/Clean.cmd b/Source/Apps/Test/Clean.cmd index ee9e01eb..243c2a5c 100644 --- a/Source/Apps/Test/Clean.cmd +++ b/Source/Apps/Test/Clean.cmd @@ -18,3 +18,4 @@ pushd vdctest && call Clean || exit /b 1 & popd pushd kbdtest && call Clean || exit /b 1 & popd pushd ps2info && call Clean || exit /b 1 & popd pushd 2piotst && call Clean || exit /b 1 & popd +pushd piomon && call Clean || exit /b 1 & popd diff --git a/Source/Apps/Test/Makefile b/Source/Apps/Test/Makefile index 56f2b77a..8f14cfa7 100644 --- a/Source/Apps/Test/Makefile +++ b/Source/Apps/Test/Makefile @@ -1,5 +1,5 @@ OBJECTS = -SUBDIRS = DMAmon I2C inttest ppidetst ramtest tstdskng rzsz vdctest kbdtest ps2info 2piotst +SUBDIRS = DMAmon I2C inttest ppidetst ramtest tstdskng rzsz vdctest kbdtest ps2info 2piotst piomon DEST = ../../../Binary/Apps/Test TOOLS =../../../Tools diff --git a/Source/Apps/Test/piomon/Build.cmd b/Source/Apps/Test/piomon/Build.cmd new file mode 100644 index 00000000..f0e405e1 --- /dev/null +++ b/Source/Apps/Test/piomon/Build.cmd @@ -0,0 +1,10 @@ +@echo off +setlocal + +set TOOLS=../../../../Tools +set PATH=%TOOLS%\tasm32;%PATH% +set TASMTABS=%TOOLS%\tasm32 + +tasm -t180 -g3 -fFF piomon.asm piomon.com piomon.lst || exit /b + +copy /Y piomon.com ..\..\..\..\Binary\Apps\Test\ || exit /b diff --git a/Source/Apps/Test/piomon/Clean.cmd b/Source/Apps/Test/piomon/Clean.cmd new file mode 100644 index 00000000..9ecb428f --- /dev/null +++ b/Source/Apps/Test/piomon/Clean.cmd @@ -0,0 +1,6 @@ +@echo off +setlocal + +if exist *.com del *.com +if exist *.lst del *.lst +if exist *.bin del *.bin diff --git a/Source/Apps/Test/piomon/Makefile b/Source/Apps/Test/piomon/Makefile new file mode 100644 index 00000000..d3054352 --- /dev/null +++ b/Source/Apps/Test/piomon/Makefile @@ -0,0 +1,7 @@ +OBJECTS = piomon.com +DEST = ../../../../Binary/Apps/Test +TOOLS =../../../../Tools + +USETASM=1 + +include $(TOOLS)/Makefile.inc \ No newline at end of file diff --git a/Source/Apps/Test/piomon/Readme.txt b/Source/Apps/Test/piomon/Readme.txt new file mode 100644 index 00000000..ddf13f7a --- /dev/null +++ b/Source/Apps/Test/piomon/Readme.txt @@ -0,0 +1,36 @@ +PIOMON is a program to verify operation of the Z80 MBC DUALPIO board + +Most testing requires the use of loopback hardware constructed as: + +Channel A RDY STB D0 D1 D2 D3 D4 D5 D6 D7 + \ / | | | | | | | | + \ / | | | | | | | | + X | | | | | | | | + / \ | | | | | | | | + / \ | | | | | | | | +Channel B RDY STB D0 D1 D2 D3 D4 D5 D6 D7 + +The DUALPIO has, well, 2 PIO chips. Only one chip +is tested at a time. At startup, PIOMON will ask +you for the port of the chip to test. It defaults +to the standard port number for the primary PIO chip +on an MBC DUALPIO board. + +The port number specified is the base I/O port. Each +chip has two channels which are addressed in the +menu by specifying A or B. + +MBC DUALPIO Primary PIO = 0xB8 +MBC DUALPIO Secondary PIO = 0xBC + +If you try to use PIOMON without the RDY and STB +cross connected, you may have interrupt issues +because STB will be floating. + +N.B., V1 and V2 of the DUALPIO lack a hardware reset. The +PIO chips will reset at power-on, but they do not reset +when the reset button is pushed. + +Happy St. Patrick's Day!!! + +--WBW 7:42 PM 3/17/2022 \ No newline at end of file diff --git a/Source/Apps/Test/piomon/piomon.asm b/Source/Apps/Test/piomon/piomon.asm new file mode 100644 index 00000000..d7cdb71f --- /dev/null +++ b/Source/Apps/Test/piomon/piomon.asm @@ -0,0 +1,1361 @@ +; +;======================================================================= +; Zilog PIO Monitor & Hardware Testing Application +;======================================================================= +; +iodef .equ $B8 ; Default base I/O port address +; +; +; +; Port address offsets from base address +iodata .equ 0 ; Channel A Data +iodatb .equ 1 ; Channel B Data +ioctla .equ 2 ; Channel A Control +ioctlb .equ 3 ; Channel B Control +; +intveca .equ 0 ; Channel A interrupt vector +intvecb .equ 1 ; Channel B interrupt vector +; +iocmd .equ $E3 ; PS/2 controller command port address +iodat .equ $E2 ; PS/2 controller data port address +; +cpumhz .equ 8 ; for time delay calculations (not critical) +; +; General operational equates (should not requre adjustment) +; +stksiz .equ $40 ; Working stack size +buflen .equ $80 ; Command buffer length +; +ltimout .equ 0 ; 256*10ms = 2.56s +stimout .equ 10 ; 10*10ms = 100ms +; +restart .equ $0000 ; CP/M restart vector +bdos .equ $0005 ; BDOS invocation vector +; +bf_sysint .equ $FC ; INT function +; +bf_sysintinfo .equ $00 ; INT INFO subfunction +bf_sysintget .equ $10 ; INT GET subfunction +bf_sysintset .equ $20 ; INT SET subfunction +; +bel .equ 7 ; ASCII bell +bs .equ 8 ; ASCII backspace +lf .equ 10 ; ASCII linefeed +cr .equ 13 ; ASCII carriage return +; +;======================================================================= +; + .org $100 ; standard CP/M executable +; +; + ; setup stack (save old value) + ld (stksav),sp ; save stack + ld sp,stack ; set new stack +; + call nl + ld hl,str_banner ; banner + call pstr +; +getport1: + ld hl,str_port1 + call pstr + ld a,(iobase) + call prthexbyte + ld hl,str_port2 + call pstr + call rdln + ld ix,cmdbuf + call skipws + or a + jr z,getport2 + call ishex + jr nz,getport1 + call gethex ; get port value + jp c,getport1 ; handle overflow + ld (iobase),a ; save value +; +getport2: + call init +; + call main ; do the real work +; +exit: + call deinit +; + call nl2 + ld hl,str_exit + call pstr +; + ; clean up and return to command processor + call nl ; formatting + ld sp,(stksav) ; restore stack + jp restart ; return to CP/M via restart +; +;======================================================================= +; Initialize +;======================================================================= +; +init: + ; Install interrupt handler in upper mem + ld hl,reladr + ld de,$A000 + ld bc,hsiz + ldir +; + ; Install interrupt vectors (RomWBW specific!!!) + ld hl,inta ; pointer to my interrupt handler + ld b,bf_sysint + ld c,bf_sysintset ; set new vector + ld e,intveca ; vector idx + di + rst 08 ; do it + ld (orgveca),hl ; save the original vector + ei ; interrupts back on + ld hl,intb ; pointer to my interrupt handler + ld b,bf_sysint + ld c,bf_sysintset ; set new vector + ld e,intvecb ; vector idx + di + rst 08 ; do it + ld (orgvecb),hl ; save the original vector + ei ; interrupts back on +; + ; Load the interrupt vectors + ld a,(iobase) + add a,ioctla + ld c,a + ld a,intveca * 2 + out (c),a + ld a,(iobase) + add a,ioctlb + ld c,a + ld a,intvecb * 2 + out (c),a +; + ; Set the interrupt control words + ld a,(iobase) + add a,ioctla + ld c,a + ld a,%10000111 + out (c),a ; int enab, no mask follows + ;ld a,%11111111 + ;out (ioctla),a ; no ints in control mode + ld a,(iobase) + add a,ioctlb + ld c,a + ld a,%10000111 + out (c),a ; int enab, no mask follows + ;ld a,%11111111 + ;out (ioctlb),a ; no ints in control mode +; + ret +; +deinit: + call reset +; + ld a,(iobase) + add a,ioctla + ld c,a + ld a,%00010111 ; clear interrupt ctl word + out (c),a + ld a,%11111111 ; clear mask + out (c),a + ld a,%00000000 ; clear interrupt vector + out (c),a +; + ld a,(iobase) + add a,ioctlb + ld c,a + ld a,%00010111 ; clear interrupt ctl word + out (c),a + ld a,%11111111 ; clear mask + out (c),a + ld a,%00000000 ; clear interrupt vector + out (c),a +; + ; Deinstall interrupt vectors + ld hl,(orgveca) ; original vector + ld b,bf_sysint + ld c,bf_sysintset ; set new vector + ld e,intveca ; vector idx + di + rst 08 ; do it + ei ; interrupts back on + ld hl,(orgvecb) ; original vector + ld b,bf_sysint + ld c,bf_sysintset ; set new vector + ld e,intvecb ; vector idx + di + rst 08 ; do it + ei ; interrupts back on + ret +; +;======================================================================= +; Main Program +;======================================================================= +; +main: + ; Prompt + call nl2 + ld hl,str_pre + call pstr + ld a,(iobase) + call prthexbyte +; + ld hl,str_int1 + call pstr + ld hl,(intcnta) + call prtdec + ld hl,str_int2 + call pstr + ld hl,(intcntb) + call prtdec +; + ld hl,str_pre2 + call pstr +; + ; Read command line + call rdln + ld ix,cmdbuf +; +main1: + ;;;; Upper case the entire command line + ;;;ld a,(ix) + ;;;or a + ;;;jr z,main2 + ;;;call upcase + ;;;ld (ix),a + ;;;inc ix + ;;;jr main1 +; +main2: + ld ix,cmdbuf + call skipws + or a ; check for eol + call nz,runcmd ; run command if not eol + jr main ; loop +; +; Run the command line pointed to by IX +; +runcmd: + ld ix,cmdbuf ; point to cmd line + call skipws + or a ; check for eol + ret z ; return if nothing there +; + ld a,(ix) ; get character +; + ; Dispatch + cp '?' ; Help + jp z,help + cp 'H' ; Help + jp z,help + cp 'X' ; Exit + jp z,exit + cp 'P' ; PIO Base Port + jp z,setport + cp 'Z' ; Reset Chip + jp z,reschip + cp 'W' ; Watch pins + jp z,watch + cp 'I' ; Input pins on channel + jp z,input + cp 'O' ; Output pins on channel + jp z,output + cp 'S' ; Send strobed byte to channel + jp z,send + cp 'R' ; Read strobed byte from channel + jp z,receive + cp 'T' ; Test + jp z,test + jp err_invcmd ; Invalid command +; +help: + ld hl,str_usage + call pstr + ret +; +setport: + call findws ; skip command + call skipws ; skip white space + call ishex ; do we have a number + jp nz,err_invcmd ; handle invalid command + call gethex + jp c,err_invcmd ; handle overflow error + push af + call deinit + pop af + ld (iobase),a ; set new port value + call init + ret ; and done +; +reschip: + ld hl,str_reschip1 + call pstr + call reset + ld hl,str_reschip2 + call pstr + ret +; +watch: + inc ix ; skip command byte + call getchan ; get channel + jp nz,err_invcmd ; handle invalid channel +; + ld hl,str_watch1 + call pstr + ld a,(channel) + add a,'A' + call cout + ld hl,str_watch2 + call pstr + call nl2 ; formatting + call ctlport ; set c to ctl port of channel + ld a,%11001111 ; bit control mode + out (c),a ; do it + ld a,%11111111 ; set all pins to input + out (c),a ; do it + call dataport ; set c to data port + ld a,0 + ld b,0 + jr watch2 +watch1: + call keychk ; key pressed? + ret nz ; return if so + in a,(c) ; read data port + cp b ; same as before + jr z,watch1 ; loop +watch2: + ld b,a ; save in B + ld hl,str_watchtag + call pstr + ld a,b ; restore value read + call prthexbyte ; print new value + jr watch1 +; +input: + inc ix ; skip command byte + call getchan ; get channel + jp nz,err_invcmd ; handle invalid channel +; + ld hl,str_input1 + call pstr + ld a,(channel) + add a,'A' + call cout + ld hl,str_input2 + call pstr + call ctlport ; set c to ctl port of channel + ld a,%11001111 ; bit control mode + out (c),a ; do it + ld a,%11111111 ; set all pins to input + out (c),a ; do it + call dataport ; set c to data port + in a,(c) + call prthexbyte + ret +; +output: + inc ix ; skip command byte + call getchan ; get channel + jp nz,err_invcmd ; handle invalid channel +; + call findws ; skip command + call skipws ; skip white space + call ishex ; do we have a number + jp nz,err_invcmd ; handle invalid command + call gethex + jp c,err_invcmd ; handle overflow error + push af +; + ld hl,str_output1 + call pstr + ld a,(channel) + add a,'A' + call cout + ld hl,str_output2 + call pstr + call ctlport ; set c to ctl port of channel + ld a,%11001111 ; bit control mode + out (c),a ; do it + ld a,%00000000 ; set all pins to output + out (c),a ; do it + call dataport ; set c to data port + pop af + out (c),a + call prthexbyte + ret +; +send: + inc ix ; skip command byte + call getchan ; get channel + jp nz,err_invcmd ; handle invalid channel +; + call findws ; skip command + call skipws ; skip white space + call ishex ; do we have a number + jp nz,err_invcmd ; handle invalid command + call gethex + jp c,err_invcmd ; handle overflow error + push af +; + ld hl,str_send1 + call pstr + ld a,(channel) + add a,'A' + call cout + ld hl,str_send2 + call pstr + call ctlport ; set c to ctl port of channel + ld a,%00001111 ; strobed output mode + out (c),a ; do it + call dataport ; set c to data port + pop af + out (c),a + call prthexbyte + ret +; +receive: + inc ix ; skip command byte + call getchan ; get channel + jp nz,err_invcmd ; handle invalid channel +; + ld hl,str_receive1 + call pstr + ld a,(channel) + add a,'A' + call cout + ld hl,str_receive2 + call pstr + call ctlport ; set c to ctl port of channel + ld a,%01001111 ; strobed input mode + out (c),a ; do it + call dataport ; set c to data port + in a,(c) + call prthexbyte + ret +; +test: + inc ix ; skip command byte + ld a,(ix) ; get character +; + ; Dispatch + cp 'R' + jp z,test_rdbk ; Readback Test + cp 'L' + jp z,test_lpbk ; Loopback Test + cp 'S' + jp z,test_stlp ; Strobed Loopback Test + jp err_invcmd + ret +; +test_rdbk: + inc ix ; skip command byte + call getchan ; get channel + jp nz,err_invcmd ; handle invalid channel +; + ld hl,str_rdbk + call pstr + ld a,(channel) + add a,'A' + call cout + call nl ; formatting + call ctlport ; set c to ctl port of channel + ld a,%00001111 ; mode 0 (output mode) + out (c),a ; do it + call dataport ; set c to data port +; + ld hl,vallist + ld b,vallen +test_rdbk0: + push hl + push bc + ld a,(hl) + call test_rdbk1 + pop bc + pop hl + jp nz,err_fail + inc hl + djnz test_rdbk0 + ret +; +test_rdbk1: + ld b,a + call nl + ld a,b + call prthexbyte + out (c),a + ld hl,str_arrow + call pstr + in a,(c) + call prthexbyte + cp b + ret +; +test_lpbk: + ld hl,str_lpbkAB + call pstr + ld a,(iobase) ; Test from A + add a,ioctla + ld d,a + ld a,(iobase) ; ... to B + add a,ioctlb + ld e,a + push de + call reset + call test_lpbk1 ; avoid output on both channels + pop de + jp nz,err_fail + ld hl,str_lpbkBA + call pstr + ld a,d ; switch direction + ld d,e + ld e,a + call reset ; avoid output on both channels + call test_lpbk1 + jp nz,err_fail + ret +; +test_lpbk1: + ; Setup output channel + ld c,d + ld a,%11001111 ; bit control mode + out (c),a ; do it + ld a,%00000000 ; set all pins to output + out (c),a ; do it +; + ; Setup input channel + ld c,e + ld a,%11001111 ; bit control mode + out (c),a ; do it + ld a,%11111111 ; set all pins to input + out (c),a ; do it +; + ; Loop through test values + dec d ; point to data port (output) + dec d + dec e ; point to data port (input) + dec e + ld hl,vallist + ld b,vallen +; +test_lpbk2: + call test_lpbk3 + ret nz + inc hl + djnz test_lpbk2 + ret +; +test_lpbk3: + call nl + ld c,d + ld a,(hl) + call prthexbyte + out (c),a + push hl + ld hl,str_arrow + call pstr + pop hl + ld c,e + in a,(c) + call prthexbyte + cp (hl) + ret +; +test_stlp: + ld hl,str_stlpAB + call pstr + ld a,(iobase) ; Test from A + add a,ioctla + ld d,a + ld a,(iobase) ; ... to B + add a,ioctlb + ld e,a + push de + call reset + call test_stlp1 ; avoid output on both channels + pop de + jp nz,err_fail + ld hl,str_stlpBA + call pstr + ld a,d ; switch direction + ld d,e + ld e,a + call reset ; avoid output on both channels + call test_stlp1 + jp nz,err_fail + ret +; +test_stlp1: + ; Setup output channel + ld c,d + ld a,%00001111 ; strobed output mode + out (c),a ; do it +; + ; Setup input channel + ld c,e + ld a,%01001111 ; strobed input mode + out (c),a ; do it +; + ; Loop through test values + dec d ; point to data port (output) + dec d + dec e ; point to data port (input) + dec e + ld hl,vallist + ld b,vallen +; +test_stlp2: + call test_stlp3 + ret nz + inc hl + djnz test_stlp2 + ret +; +test_stlp3: + call nl + ld c,d + ld a,(hl) + call prthexbyte + out (c),a + push hl + ld hl,str_arrow + call pstr + pop hl + ld c,e + in a,(c) + call prthexbyte + cp (hl) + ret +; +; +; +getchan: + ld a,(ix) ; get byte + sub 'A' ; convert to binary + cp 2 ; check for max value + ret nc ; return with NZ if too high + ld (channel),a ; save new value + cp a ; set ZF + ret ; done +; +; +; +reset: + ld a,(iobase) + add a,ioctla + ld c,a + call reset1 + ld a,(iobase) + add a,ioctlb + ld c,a + jr reset1 +; +reset1: + ld a,%01001111 ; set mode 1 (input) + out (c),a + ;ld a,%00010111 ; clear interrupt ctl word + ;out (c),a + ;ld a,%11111111 ; clear mask + ;out (c),a + ;ld a,%00000000 ; clear interrupt vector + ;out (c),a + ret +; +; +; +ctlport: + ld a,(iobase) ; base port + add a,ioctla ; offset to control ports + ld c,a ; put in c + ld a,(channel) ; get channel + add a,c ; combine + ld c,a + ret +; +; +; +dataport: + ld a,(iobase) ; base port + add a,iodata ; offset to data ports + ld c,a ; put in c + ld a,(channel) ; get channel + add a,c ; combine + ld c,a + ret +; +; Error Handlers +; +err_abort: + ld hl,str_err_abort + jr err_ret +err_invcmd: + ld hl,str_err_invcmd + jr err_ret +err_fail: + ld hl,str_err_fail + jr err_ret +; +err_ret: + push hl + ld hl,str_err_prefix + call pstr + pop hl + jp pstr +; +str_err_prefix .db bel,"\r\n\r\n*** ",0 +str_err_abort .db "User Aborted",0 +str_err_invcmd .db "Invalid command, press '?' for help",0 +str_err_fail .db "Test failed!",0 +; +;======================================================================= +; Utility functions +;======================================================================= +; +; Print string at HL on console, null terminated +; +pstr: + push af + push hl +pstr1: + ld a,(hl) ; get next character + or a ; set flags + inc hl ; bump pointer regardless + jr z,pstr2 ; done if null + call cout ; display character + jr pstr1 ; loop till done +pstr2: + pop hl + pop af + ret +; +; Print volume label string at HL, '$' terminated, 16 chars max +; +pvol: + ld b,16 ; init max char downcounter +pvol1: + ld a,(hl) ; get next character + cp '$' ; set flags + inc hl ; bump pointer regardless + ret z ; done if null + call cout ; display character + djnz pvol1 ; loop till done + ret ; hit max of 16 chars +; +; Start a newline on console (cr/lf) +; +nl2: + call nl ; double newline +nl: + ld a,cr ; cr + call cout ; send it + ld a,lf ; lf + jp cout ; send it and return +; +; Print a dot on console +; +pdot: + push af + ld a,'.' + call cout + pop af + ret +; +; +; +keychk: + call cst + or a + ret z + call cin + or $FF + ret +; +; Read a string on the console to cmdbuf +; +; Input is zero terminated +; +rdln: + ld de,cmdbuf ; init buffer address ptr +rdln_nxt: + call cin ; get a character + cp bs ; backspace? + jr z,rdln_bs ; handle it if so + cp cr ; return? + jr z,rdln_cr ; handle it if so +; + ; check for non-printing characters + cp ' ' ; first printable is space char + jr c,rdln_bel ; too low, beep and loop + cp '~'+1 ; last printable char + jr nc,rdln_bel ; too high, beep and loop +; + ; need to check for buffer overflow here!!! + ld hl,cmdbuf+buflen ; max cmd length + or a ; clear carry + sbc hl,de ; test for max + jr z,rdln_bel ; at max, beep and loop +; + ; good to go, echo and store character + call upcase + call cout ; echo character input + ld (de),a ; save in buffer + inc de ; inc buffer ptr + jr rdln_nxt ; loop till done +; +rdln_bs: + ld hl,cmdbuf ; start of buffer + or a ; clear carry + sbc hl,de ; subtract from cur buf ptr + jr z,rdln_bel ; at buf start, just beep + ld hl,str_bs ; backspace sequence + call pstr ; send it + dec de ; backup buffer pointer + jr rdln_nxt ; and loop +; +rdln_bel: + ld a,bel ; Bell characters + call cout ; send it + jr rdln_nxt ; and loop +; +rdln_cr: + xor a ; null to A + ld (de),a ; store terminator + ret ; and return +; +; Find next whitespace character at buffer adr in DE, returns with first +; whitespace character in A. +; +findws: + ld a,(ix) ; get next char + or a ; check for eol + ret z ; done if so + cp ' ' ; blank? + ret z ; nope, done + inc ix ; bump buffer pointer + jr findws ; and loop +; +; Skip whitespace at buffer adr in DE, returns with first +; non-whitespace character in A. +; +skipws: + ld a,(ix) ; get next char + or a ; check for eol + ret z ; done if so + cp ' ' ; blank? + ret nz ; nope, done + inc ix ; bump buffer pointer + jr skipws ; and loop +; +; Uppercase character in A +; +upcase: + cp 'a' ; below 'a'? + ret c ; if so, nothing to do + cp 'z'+1 ; above 'z'? + ret nc ; if so, nothing to do + and ~$20 ; convert character to lower + ret ; done +; +; Get numeric chars at IX and convert to number returned in A +; Carry flag set on overflow +; +getnum: + ld c,0 ; C is working register +getnum1: + ld a,(ix) ; get the active char + cp '0' ; compare to ascii '0' + jr c,getnum2 ; abort if below + cp '9' + 1 ; compare to ascii '9' + jr nc,getnum2 ; abort if above +; + ; valid digit, add new digit to C + ld a,c ; get working value to A + rlca ; multiply by 10 + ret c ; overflow, return with carry set + rlca ; ... + ret c ; overflow, return with carry set + add a,c ; ... + ret c ; overflow, return with carry set + rlca ; ... + ret c ; overflow, return with carry set + ld c,a ; back to C + ld a,(ix) ; get new digit + sub '0' ; make binary + add a,c ; add in working value + ret c ; overflow, return with carry set + ld c,a ; back to C +; + inc ix ; bump to next char + jr getnum1 ; loop +; +getnum2: ; return result + ld a,c ; return result in A + or a ; with flags set, CF is cleared + ret +; +; Get hex chars at IX and convert to binary number returned in A +; Carry flag set on overflow +; +gethex: + ld c,0 ; C is working register +gethex1: + ld a,(ix) ; get the active char + call ishex ; is it a hex char? + jr nz,gethex9 ; abort if not +; + ; valid digit, add new digit to C + ld a,c ; get working value to A + rlca ; multiply by 16 + ret c ; overflow, return with carry set + rlca ; ... + ret c ; overflow, return with carry set + rlca ; ... + ret c ; overflow, return with carry set + rlca ; ... + ret c ; overflow, return with carry set + ld c,a ; back to C + ld a,(ix) ; get new hex digit + call isnum ; regular number? + jr z,gethex2 ; if so, handle it, else hex char + sub 'A'-10 ; convert to binary + jr gethex3 ; and continue +gethex2: + sub '0' ; convert to binary +gethex3: + add a,c ; add in working value + ret c ; overflow, return with carry set + ld c,a ; back to C +; + inc ix ; bump to next char + jr gethex1 ; loop +; +gethex9: ; return result + ld a,c ; return result in A + or a ; with flags set, CF is cleared + ret +; +; Is character in A numberic? NZ if not +; +isnum: + cp '0' ; compare to ascii '0' + jr c,isnum1 ; abort if below + cp '9' + 1 ; compare to ascii '9' + jr nc,isnum1 ; abort if above + cp a ; set Z + ret +isnum1: + cp '0' ; set NZ w/o changing value + ret ; and done +; +; Is character in A hex? NZ if not +; +ishex: + call isnum ; is it a numeric? + ret z ; if so, all done + cp 'A' ; first hex char + jr c,ishex1 ; abort if below + cp 'F' + 1 ; last hex char + jr nc,ishex1 ; abort if above + cp a ; set Z + ret ; done +ishex1: + cp '0' ; set NZ w/o changing value + ret ; done +; +; Delay 16us (cpu speed compensated) incuding call/ret invocation +; Register A and flags destroyed +; No compensation for z180 memory wait states +; There is an overhead of 3ts per invocation +; Impact of overhead diminishes as cpu speed increases +; +; cpu scaler (cpuscl) = (cpuhmz - 2) for 16us + 3ts delay +; note: cpuscl must be >= 1! +; +; example: 8mhz cpu (delay goal is 16us) +; loop = ((6 * 16) - 5) = 91ts +; total cost = (91 + 40) = 131ts +; actual delay = (131 / 8) = 16.375us +; + ; --- total cost = (loop cost + 40) ts -----------------+ +delay: ; 17ts (from invoking call) | + ld a,(cpuscl) ; 13ts | +; | +delay1: ; | + ; --- loop = ((cpuscl * 16) - 5) ts ------------+ | + dec a ; 4ts | | + jr nz,delay1 ; 12ts (nz) / 7ts (z) | | + ; ----------------------------------------------+ | +; | + ret ; 10ts (return) | + ;-------------------------------------------------------+ +; +; Delay 16us * DE (cpu speed compensated) +; Register DE, A, and flags destroyed +; No compensation for z180 memory wait states +; There is a 27ts overhead for call/ret per invocation +; Impact of overhead diminishes as DE and/or cpu speed increases +; +; cpu scaler (cpuscl) = (cpuhmz - 2) for 16us outer loop cost +; note: cpuscl must be > 0! +; +; Example: 8MHz cpu, DE=6250 (delay goal is .1 sec or 100,000us) +; inner loop = ((16 * 6) - 5) = 91ts +; outer loop = ((91 + 37) * 6250) = 800,000ts +; actual delay = ((800,000 + 27) / 8) = 100,003us +; + ; --- total cost = (outer loop + 27) ts ------------------------+ +vdelay: ; 17ts (from invoking call) | +; | + ; --- outer loop = ((inner loop + 37) * de) ts ---------+ | + ld a,(cpuscl) ; 13ts | | +; | | +vdelay1: ; | | + ; --- inner loop = ((cpuscl * 16) - 5) ts ------+ | | + dec a ; 4ts | | | + jr nz,vdelay1 ; 12ts (nz) / 7ts (z) | | | + ; ----------------------------------------------+ | | +; | | + dec de ; 6ts | | + ld a,d ; 4ts | | + or e ; 4ts | | + jp nz,vdelay ; 10ts | | + ;-------------------------------------------------------+ | +; | + ret ; 10ts (final return) | + ;---------------------------------------------------------------+ +; +; Delay about 0.5 seconds +; 500000us / 16us = 31250 +; +ldelay: + push af + push de + ld de,31250 + call vdelay + pop de + pop af + ret +; +#if (cpumhz < 3) +cpuscl .db 1 ; cpu scaler must be > 0 +#else +cpuscl .db cpumhz - 2 ; otherwise 2 less than phi mhz +#endif +; +; Print value of a in decimal with leading zero suppression +; +prtdecb: + push hl + push af + ld l,a + ld h,0 + call prtdec + pop af + pop hl + ret +; +; Print value of HL in decimal with leading zero suppression +; +prtdec: + push bc + push de + push hl + ld e,'0' + ld bc,-10000 + call prtdec1 + ld bc,-1000 + call prtdec1 + ld bc,-100 + call prtdec1 + ld c,-10 + call prtdec1 + ld e,0 + ld c,-1 + call prtdec1 + pop hl + pop de + pop bc + ret +prtdec1: + ld a,'0' - 1 +prtdec2: + inc a + add hl,bc + jr c,prtdec2 + sbc hl,bc + cp e + jr z,prtdec3 + ld e,0 + call cout +prtdec3: + ret +; +; Short delay functions. No clock speed compensation, so they +; will run longer on slower systems. The number indicates the +; number of call/ret invocations. A single call/ret is +; 27 t-states on a z80, 25 t-states on a z180. +; +; ; z80 z180 +; ; ---- ---- +dly64: call dly32 ; 1728 1600 +dly32: call dly16 ; 864 800 +dly16: call dly8 ; 432 400 +dly8: call dly4 ; 216 200 +dly4: call dly2 ; 108 100 +dly2: call dly1 ; 54 50 +dly1: ret ; 27 25 +; +; Add hl,a +; +; A register is destroyed! +; +addhla: + add a,l + ld l,a + ret nc + inc h + ret +; +; +; +prtdot: + push af + ld a,'.' + call cout + pop af + ret +; +; Print the hex byte value in A +; +prthexbyte: + push af + push de + call hexascii + ld a,d + call cout + ld a,e + call cout + pop de + pop af + ret +; +; Print the hex word value in BC +; +prthexword: + push af + ld a,b + call prthexbyte + ld a,c + call prthexbyte + pop af + ret +; +; Print the hex dword value in DE:HL +; +prthex32: + push bc + push de + pop bc + call prthexword + push hl + pop bc + call prthexword + pop bc + ret +; +; Convert binary value in A to ASCII hex characters in DE +; +hexascii: + ld d,a + call hexconv + ld e,a + ld a,d + rlca + rlca + rlca + rlca + call hexconv + ld d,a + ret +; +; Convert low nibble of A to ASCII hex +; +hexconv: + and 0Fh ; low nibble only + add a,90h + daa + adc a,40h + daa + ret +; +; Output character from A +; +cout: + ; Save all incoming registers + push af + push bc + push de + push hl +; + ; Output character to console via BDOS + ld e,a ; output char to E + ld c,6 ; BDOS direct console I/O + call bdos ; output character +; + ; Restore all registers + pop hl + pop de + pop bc + pop af + ret +; +; Input character to A +; +cin: + ; Save incoming registers (AF is output) + push bc + push de + push hl +; + ; Input character from console via BDOS +cin1: + ld e,$FF ; input request + ld c,6 ; BDOS direct console I/O + call bdos ; input character to A + or a ; test for zero (no input) + jr z,cin1 ; loop till we have a char +; + ; Restore registers (AF is output) + pop hl + pop de + pop bc + ret +; +; Return input status in A (0 = no char, != 0 char waiting) +; +cst: + ; Save incoming registers (AF is output) + push bc + push de + push hl +; + ; Get console input status via BDOS + ld e,$FE ; status + ld c,6 ; BDOS direct console I/O + call bdos ; input status to A +; + ; Restore registers (AF is output) + pop hl + pop de + pop bc + ret +; +; +; +;======================================================================= +; Constants +;======================================================================= +; +str_banner .db "Zilog PIO Monitor v0.1, 14-Mar-2022\r\n" + .db "Press ? for help$" +str_bs .db bs,' ',bs,0 +str_port1 .db "\r\n\r\nEnter PIO port in hex [",0 +str_port2 .db "]:",0 +str_pre .db "Zilog PIO @ Port 0x",0 +str_pre2 .db "\r\n\r\n>",0 +str_exit .db "Done, Thank you for using Zilog PIO Monitor!",0 +str_reschip1 .db "\r\n\r\nFull Reset of PIO Chip... ",0 +str_reschip2 .db "Done",0 +str_int1 .db "\r\nChannel A Interrupts=",0 +str_int2 .db ", Channel B Interrupts=",0 +str_watch1 .db "\r\n\r\nWatching Channel ",0 +str_watch2 .db ", press any to end...",0 +str_watchtag .db "\rPort Value=0x",0 +str_input1 .db "\r\n\r\nValue of Pins on Channel ",0 +str_input2 .db " = 0x",0 +str_output1 .db "\r\n\r\nSetting Value of Pins on Channel ",0 +str_output2 .db " = 0x",0 +str_receive1 .db "\r\n\r\nReceived from Channel ",0 +str_receive2 .db " = 0x",0 +str_send1 .db "\r\n\r\nSent to Channel ",0 +str_send2 .db " = 0x",0 +str_rdbk .db "\r\n\r\nReadback Test on Channel ",0 +str_arrow .db " --> ",0 +str_lpbkAB .db "\r\n\r\nLoopback Test in Bit Control Mode A->B...\r\n",0 +str_lpbkBA .db "\r\n\r\nLoopback Test in Bit Control Mode B->A...\r\n",0 +str_stlpAB .db "\r\n\r\nLoopback Test in Strobed Mode A->B...\r\n",0 +str_stlpBA .db "\r\n\r\nLoopback Test in Strobed Mode B->A...\r\n",0 +str_usage .db "\r\n" + .db "\r\n P n - Set Current PIO Base Port" + .db "\r\n Z - Reset PIO (both channels)" + .db "\r\n Wc - Watch Channel c Pin Values (bit control)" + .db "\r\n Oc n - Output Channel c Pin Values (bit control)" + .db "\r\n Ic - Input Channel c Pin Values (bit control)" + .db "\r\n Sc n - Send Value to Channel c (strobed)" + .db "\r\n Rc - Receive Value from Channel c (strobed)" + .db "\r\n TRc - Test Readback on Channel c (bit control)" + .db "\r\n TL - Test Loopback (bit control)" + .db "\r\n TS - Test Loopback (strobed)" + .db "\r\n H,? - Help" + .db "\r\n X - Exit" + .db "\r\n " + .db "\r\n Loopback tests require hardware loopback (see readme.txt)" + .db 0 +; +;======================================================================= +; Working data +;======================================================================= +; +stksav .dw 0 ; stack pointer saved at start + .fill stksiz,0 ; stack +stack .equ $ ; stack top +; +iobase .db iodef ; current I/O base address +channel .db 0 ; current channel +wrkval .db 0 +; +cmdbuf .fill buflen+1,0 +; +vallist: + .db $00,$FF,$AA,$55,$A5,$5A,$FF,$00 +vallen .equ $ - vallist +; +orgveca .dw 0 ; saved int vector, channel A +orgvecb .dw 0 ; saved int vector, channel B +; +;=============================================================================== +; Interrupt Handler +;=============================================================================== +; +reladr .equ $ ; relocation start adr +; + .org $A000 ; code will run here +; +inta: +; + ld hl,(intcnta) + inc hl + ld (intcnta),hl +; + or $ff ; signal int handled + ret +; +intb: +; + ld hl,(intcntb) + inc hl + ld (intcntb),hl +; + or $ff ; signal int handled + ret +; +intcnta .dw 0 +intcntb .dw 0 +; +hsiz .equ $ - $A000 ; size of handler to relocate +; + .org reladr + hsiz +; + .end + \ No newline at end of file diff --git a/desktop.ini b/desktop.ini deleted file mode 100644 index bb9f3d69..00000000 --- a/desktop.ini +++ /dev/null @@ -1,4 +0,0 @@ -[ViewState] -Mode= -Vid= -FolderType=Generic From 9f3c9e180da81440b3e769d88daaba4750509a1e Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Fri, 18 Mar 2022 16:22:08 -0700 Subject: [PATCH 31/34] Add PIO Driver - Just a stub that detects and initializes the hardware. --- Source/HBIOS/cfg_dyno.asm | 2 + Source/HBIOS/cfg_ezz80.asm | 2 + Source/HBIOS/cfg_master.asm | 5 + Source/HBIOS/cfg_mbc.asm | 5 + Source/HBIOS/cfg_mk4.asm | 5 + Source/HBIOS/cfg_n8.asm | 5 + Source/HBIOS/cfg_rcz180.asm | 5 + Source/HBIOS/cfg_rcz280.asm | 5 + Source/HBIOS/cfg_rcz80.asm | 5 + Source/HBIOS/cfg_sbc.asm | 5 + Source/HBIOS/cfg_scz180.asm | 5 + Source/HBIOS/cfg_zeta.asm | 5 + Source/HBIOS/cfg_zeta2.asm | 2 + Source/HBIOS/hbios.asm | 17 +- Source/HBIOS/pio.asm | 1166 ++++++++--------------------------- Source/HBIOS/pio_ps.asm | 999 ++++++++++++++++++++++++++++++ Source/ver.inc | 2 +- Source/ver.lib | 2 +- 18 files changed, 1330 insertions(+), 912 deletions(-) create mode 100644 Source/HBIOS/pio_ps.asm diff --git a/Source/HBIOS/cfg_dyno.asm b/Source/HBIOS/cfg_dyno.asm index c0b466ee..71983d85 100644 --- a/Source/HBIOS/cfg_dyno.asm +++ b/Source/HBIOS/cfg_dyno.asm @@ -179,6 +179,8 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) PIO_SBC .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR 8255 CHIP diff --git a/Source/HBIOS/cfg_ezz80.asm b/Source/HBIOS/cfg_ezz80.asm index 1ac317dc..022236ca 100644 --- a/Source/HBIOS/cfg_ezz80.asm +++ b/Source/HBIOS/cfg_ezz80.asm @@ -221,6 +221,8 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) PIO_SBC .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR 8255 CHIP diff --git a/Source/HBIOS/cfg_master.asm b/Source/HBIOS/cfg_master.asm index a507dee1..8e17d028 100644 --- a/Source/HBIOS/cfg_master.asm +++ b/Source/HBIOS/cfg_master.asm @@ -286,6 +286,11 @@ PPPCONENABLE .EQU TRUE ; PPP: ENABLE PPP DRIVER VIDEO/KBD SUPPORT HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) HDSKTRACE .EQU 1 ; HDSK: TRACE LEVEL (0=NO,1=ERRORS,2=ALL) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO4BASE .EQU $90 ; PIO: PIO REGISTERS BASE ADR FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) diff --git a/Source/HBIOS/cfg_mbc.asm b/Source/HBIOS/cfg_mbc.asm index 2824bd83..e17de8c3 100644 --- a/Source/HBIOS/cfg_mbc.asm +++ b/Source/HBIOS/cfg_mbc.asm @@ -218,6 +218,11 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) HDSKTRACE .EQU 1 ; HDSK: TRACE LEVEL (0=NO,1=ERRORS,2=ALL) ; +PIOENABLE .EQU TRUE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO4BASE .EQU $90 ; PIO: PIO REGISTERS BASE ADR FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) diff --git a/Source/HBIOS/cfg_mk4.asm b/Source/HBIOS/cfg_mk4.asm index 1a4910bd..14f9a8f2 100644 --- a/Source/HBIOS/cfg_mk4.asm +++ b/Source/HBIOS/cfg_mk4.asm @@ -219,6 +219,11 @@ PPPCONENABLE .EQU TRUE ; PPP: ENABLE PPP DRIVER VIDEO/KBD SUPPORT ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO4BASE .EQU $90 ; PIO: PIO REGISTERS BASE ADR FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) diff --git a/Source/HBIOS/cfg_n8.asm b/Source/HBIOS/cfg_n8.asm index a867f64b..070298a6 100644 --- a/Source/HBIOS/cfg_n8.asm +++ b/Source/HBIOS/cfg_n8.asm @@ -217,6 +217,11 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO4BASE .EQU $90 ; PIO: PIO REGISTERS BASE ADR FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) diff --git a/Source/HBIOS/cfg_rcz180.asm b/Source/HBIOS/cfg_rcz180.asm index d01e14e6..d9306673 100644 --- a/Source/HBIOS/cfg_rcz180.asm +++ b/Source/HBIOS/cfg_rcz180.asm @@ -233,6 +233,11 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) PIO_SBC .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR 8255 CHIP diff --git a/Source/HBIOS/cfg_rcz280.asm b/Source/HBIOS/cfg_rcz280.asm index 480f6724..65214adc 100644 --- a/Source/HBIOS/cfg_rcz280.asm +++ b/Source/HBIOS/cfg_rcz280.asm @@ -249,6 +249,11 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) PIO_SBC .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR 8255 CHIP diff --git a/Source/HBIOS/cfg_rcz80.asm b/Source/HBIOS/cfg_rcz80.asm index 19fbb10c..00e56501 100644 --- a/Source/HBIOS/cfg_rcz80.asm +++ b/Source/HBIOS/cfg_rcz80.asm @@ -238,6 +238,11 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) PIO_SBC .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR 8255 CHIP diff --git a/Source/HBIOS/cfg_sbc.asm b/Source/HBIOS/cfg_sbc.asm index 95ee53ad..f55d0b5d 100644 --- a/Source/HBIOS/cfg_sbc.asm +++ b/Source/HBIOS/cfg_sbc.asm @@ -218,6 +218,11 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) HDSKTRACE .EQU 1 ; HDSK: TRACE LEVEL (0=NO,1=ERRORS,2=ALL) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO4BASE .EQU $90 ; PIO: PIO REGISTERS BASE ADR FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) diff --git a/Source/HBIOS/cfg_scz180.asm b/Source/HBIOS/cfg_scz180.asm index 6505fad7..3e4bdd4e 100644 --- a/Source/HBIOS/cfg_scz180.asm +++ b/Source/HBIOS/cfg_scz180.asm @@ -228,6 +228,11 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) PIO_SBC .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR 8255 CHIP diff --git a/Source/HBIOS/cfg_zeta.asm b/Source/HBIOS/cfg_zeta.asm index 6deb725a..198a5985 100644 --- a/Source/HBIOS/cfg_zeta.asm +++ b/Source/HBIOS/cfg_zeta.asm @@ -162,6 +162,11 @@ PPPCONENABLE .EQU TRUE ; PPP: ENABLE PPP DRIVER VIDEO/KBD SUPPORT ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) PIO_SBC .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR 8255 CHIP diff --git a/Source/HBIOS/cfg_zeta2.asm b/Source/HBIOS/cfg_zeta2.asm index 9778f105..42970e1b 100644 --- a/Source/HBIOS/cfg_zeta2.asm +++ b/Source/HBIOS/cfg_zeta2.asm @@ -173,6 +173,8 @@ PPPCONENABLE .EQU TRUE ; PPP: ENABLE PPP DRIVER VIDEO/KBD SUPPORT ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) PIO_SBC .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR 8255 CHIP diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index f6579df9..abb3ae04 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -2825,6 +2825,9 @@ HB_PCINITTBL: #IF (ACIAENABLE) .DW ACIA_PREINIT #ENDIF +#IF (PIOENABLE) + .DW PIO_PREINIT +#ENDIF #IF (PIO_4P | PIO_ZP) .DW PIO_PREINIT #ENDIF @@ -2944,6 +2947,9 @@ HB_INITTBL: #IF (PPPENABLE) .DW PPP_INIT #ENDIF +#IF (PIOENABLE) + .DW PIO_INIT +#ENDIF #IF (PIO_4P | PIO_ZP) .DW PIO_INIT #ENDIF @@ -5897,6 +5903,15 @@ SIZ_SPK .EQU $ - ORG_SPK .ECHO " bytes.\n" #ENDIF ; +#IF (PIOENABLE) +ORG_PIO .EQU $ + #INCLUDE "pio.asm" +SIZ_PIO .EQU $ - ORG_PIO + .ECHO "PIO occupies " + .ECHO SIZ_PIO + .ECHO " bytes.\n" +#ENDIF +; #IF (PIO_4P | PIO_ZP | PIO_SBC) ORG_PIO .EQU $ #INCLUDE "pio.asm" @@ -6747,7 +6762,7 @@ PS_SDPRPCON .TEXT "PRPCON$" PS_SDPPPCON .TEXT "PPPCON$" PS_SDSIO .TEXT "SIO$" PS_SDACIA .TEXT "ACIA$" -PS_SDPIO .TEXT "PORT$" +PS_SDPIO .TEXT "PIO$" PS_SDUF .TEXT "UF$" PS_SDDUART .TEXT "DUART$" PS_SDZ2U .TEXT "Z2U$" diff --git a/Source/HBIOS/pio.asm b/Source/HBIOS/pio.asm index f198f25a..90a27864 100644 --- a/Source/HBIOS/pio.asm +++ b/Source/HBIOS/pio.asm @@ -1,776 +1,254 @@ -; PIO driver sets up the parallel port as a subtype of Serial/Char device. ; +;================================================================================================== +; PIO DRIVER (SERIAL PORT) +;================================================================================================== ; -; HBIOS initializes driver by: +; SETUP PARAMETER WORD: +; +-------+---+-------------------+ +---+---+-----------+---+-------+ +; | |RTS| ENCODED BAUD RATE | |DTR|XON| PARITY |STP| 8/7/6 | +; +-------+---+---+---------------+ ----+---+-----------+---+-------+ +; F E D C B A 9 8 7 6 5 4 3 2 1 0 +; -- MSB (D REGISTER) -- -- LSB (E REGISTER) -- ; -; 1) Calling Pre-initialization +; THIS DRIVER IS JUST A STUB TO DETECT AND INITIALIZE PIO HARDWARE +; IF IT EXISTS. FOR NOW, IT DOES NOT REGISTER ANY OF THE PIO CHANNELS +; AS CHARCTER DEVICE UNITS. ; -; This involves setting up all the data structures describing the devices. -; If possible, do a hardware test to verify it is available for adding to available devices. -; -; 2) Calling device initialization. -; -; Hardware initialization. -; Configure to initial state or to a new state. -; -; Implementation limitations: -; -; The fully functionality of the Z80 PIO can only be realized by using Z80 interrupt mode 2. -; Registers cannot be interrogated for interrupts status and the originating interrupt -; device cannot be determine. -; -; Full implementation of IM2 functionality for an ECB-ZP and ECB-4P board would require the -; allocation of an interrupt handler for each chip channel. Thus, 12 interrupt handlers -; would be required to support this configuration. As the HBIOS only has an allocation of -; 16, a full implmentation is impractical. -; -; The compromise solution is to allow 4 interrupts for the PIO driver. All remaining PIO's -; are limited to Bit mode or blind read and write to the input/output ports. -; -; Zilog PIO reset state: -; -; Both port mask registers are reset to inhibit All port data bits. -; Port data bus lines are set to a high-impedance state and the Ready "handshake" -; Mode 1 (output) is automatically selected. -; The vector address registers are not reset. -; Both port interrupt enable flip-flops are reset. -; Both port output registers are reset. -; -; Register addressing example for ECB-ZP and ECB-4P assuming base address 90h and 88h respectively. +PIO_NONE .EQU 0 +PIO_PIO .EQU 1 ; -; PIO ----ZP---- ----4P---- -; 0 DATA 0 90h DATA 0 B8h -; 0 DATA 1 91h DATA 1 B9h -; 0 CMD 0 92h CMD 0 BAh -; 0 CMD 1 93h CMD 1 BBh -; 1 DATA 0 94h DATA 0 BCh -; 1 DATA 1 95h DATA 1 BDh -; 1 CMD 0 96h CMD 0 BEh -; 1 CMD 1 97h CMD 1 BFh -; 2 DATA 0 C0h -; 2 DATA 1 C1h -; 2 CMD 0 C2h -; 2 CMD 1 C3h -; 3 DATA 0 C4h -; 3 DATA 1 C5h -; 3 CMD 0 C6h -; 3 CMD 1 C7h +PIO0A_CTL .EQU PIO0BASE + $02 +PIO0A_DAT .EQU PIO0BASE + $00 +PIO0B_CTL .EQU PIO0BASE + $03 +PIO0B_DAT .EQU PIO0BASE + $01 ; -PIODEBUG .EQU 1 +#IF (PIOCNT >= 2) ; -M_Output .EQU $00 << 6 -M_Input .EQU $01 << 6 -M_Bidir .EQU $02 << 6 -M_BitCtrl .EQU $03 << 6 -M_BitAllIn .EQU $FF -M_BitAllOut .EQU $00 +PIO1A_CTL .EQU PIO1BASE + $02 +PIO1A_DAT .EQU PIO1BASE + $00 +PIO1B_CTL .EQU PIO1BASE + $03 +PIO1B_DAT .EQU PIO1BASE + $01 ; -PIO_NONE .EQU 0 -PIO_ZPIO .EQU 1 -PIO_8255 .EQU 2 -PIO_PORT .EQU 3 - -; SET MAXIMUM NUMBER OF INTERRUPTS AVAILABLE FOR ALL -; ENSURE INTERRUPTS ARE NOT TURNED ON IF IM2 IS NOT SET. - -INT_ALLOC .DB 0 -INT_N .EQU 00000000B -#IF (INTMODE == 2) -INT_Y .EQU 00000100B -INT_ALLOW .EQU 4 -#ELSE -INT_Y .EQU INT_N -INT_ALLOW .EQU 0 #ENDIF ; -INT0 .EQU 00000000B -INT1 .EQU 00000001B -INT2 .EQU 00000010B -INT3 .EQU 00000011B - +PIO_PREINIT: ; ; SETUP THE DISPATCH TABLE ENTRIES +; NOTE: INTS WILL BE DISABLED WHEN PREINIT IS CALLED AND THEY MUST REMIAIN +; DISABLED. ; -; PIO_CNT HOLDS THE NUMBER OF DEVICED CALCULATED FROM THE NUMBER OF DEFPIO MACROS -; PIO_CNT SHOULD INCREASE BY 2 FOR EVERY PIO CHIP ADDED. + CALL PIO_PROBE ; PROBE FOR CHIPS ; -; PIO_PREINIT WILL READ THROUGH ALL PIOCFG TABLES AND CONFIGURE EACH TABLE. -; IT WITH THEN CALL PIO_INITUNIT TO INITIALIZE EACH DEVICE TO ITS DEFAULT STATE -; -; EXPECTS NOTHING ON ENTRY -; -PIO_PREINIT: - CALL NEWLINE ;D - LD B,PIO_CNT ; LOOP CONTROL - LD C,0 ; PHYSICAL UNIT INDEX + LD B,PIO_CFGCNT ; LOOP CONTROL XOR A ; ZERO TO ACCUM -; LD (PIO_DEV),A ; CURRENT DEVICE NUMBER - LD (INT_ALLOC),A ; START WITH NO INTERRUPTS ALLOCATED + LD (PIO_DEV),A ; CURRENT DEVICE NUMBER + LD IY,PIO_CFG ; POINT TO START OF CFG TABLE PIO_PREINIT0: PUSH BC ; SAVE LOOP CONTROL -; LD A,C ; INITIALIZE THE UNIT - -; PUSH AF ;D -; LD A,'u' ;D -; CALL COUT ;D -; POP AF ;D -; CALL PRTHEXBYTE ;D UNIT -; CALL PC_SPACE ;D - -; RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (32 BYTES) -; RLCA ; ... -; RLCA ; ... TO GET OFFSET INTO CFG TABLE -; RLCA -;; RLCA -; LD HL,PIO_CFG ; POINT TO START OF CFG TABLE -; PUSH AF -; CALL ADDHLA ; HL := ENTRY ADDRESS -; POP AF -; CALL ADDHLA ; HL := ENTRY ADDRESS -; PUSH HL ; SAVE IT -; POP IY ; ... TO IY - - CALL IDXCFG - - LD (HL),C - - PUSH AF ;D - LD A,'c' ;D - CALL COUT ;D - POP AF ;D - PUSH BC ;D - PUSH HL ;D - POP BC ;D - CALL PRTHEXWORD ;D CONFIG TABLE - CALL PC_SPACE ;D - POP BC ;D - + CALL PIO_INITUNIT ; HAND OFF TO GENERIC INIT CODE + POP BC ; RESTORE LOOP CONTROL +; LD A,(IY+1) ; GET THE PIO TYPE DETECTED - CP PIO_PORT ; SET FLAGS - - PUSH AF ;D - LD A,'t' ;D - CALL COUT ;D - POP AF ;D - CALL PRTHEXBYTE ;D TYPE - CALL PC_SPACE ;D - -; JR Z,BADINIT - -; PUSH BC ; SAVE LOOP CONTROL -; LD BC,PIO_FNTBL ; BC := FUNCTION TABLE ADDRESS -; DEC A -; JR Z,TYPFND ; SKIP IT IF NOTHING FOUND -; LD BC,PPI_FNTBL ; BC := FUNCTION TABLE ADDRESS -; DEC A -; JR Z,TYPFND ; ADD ENTRY IF PIO FOUND, BC:DE -; LD BC,PRT_FNTBL -; DEC A -; JR Z,TYPFND -; POP BC -; JR BADINIT - - PUSH HL - LD DE,-1 ; INITIALIZE THIS DEVICE WITH - CALL PIO_INITDEV ; DEFAULT VALUES - POP HL - -; JR NZ,SKPINIT - - ; AT THIS POINT WE KNOW WE - ; HAVE A VALID DEVICE SO ADD IT - - LD A,8 ; CALCULATE THE FUNCTION TABLE - CALL ADDHLA ; POSITION WHICH FOLLOWS THE - PUSH HL ; CONFIGURATION TABLE OF EACH - POP BC ; DEVICE - -TYPFND: PUSH AF ;D - LD A,'f' ;D - CALL COUT ;D - POP AF ;D - PUSH BC ;D - CALL PRTHEXWORD ;D FUNCTION TABLE - POP BC ;D - CALL NEWLINE ;D - - PUSH IY ; ADD ENTRY IF PIO FOUND, BC:DE - POP DE ; BC: DRIVER FUNCTION TABLE - CALL CIO_ADDENT ; DE: ADDRESS OF UNIT INSTANCE DATA - -BADINIT:POP BC ; RESTORE LOOP CONTROL - - INC C ; NEXT PHYSICAL UNIT -SKPINIT:DJNZ PIO_PREINIT0 ; LOOP UNTIL DONE - - PUSH AF ;D - PRTS("INTS=$") ;D - LD A,(INT_ALLOC) ;D - CALL PRTHEXBYTE ;D - POP AF ;D - PUSH DE ;D - LD DE,CIO_TBL-3 ;D - CALL DUMP_BUFFER ;D - POP DE ;D + OR A ; SET FLAGS + JR Z,PIO_PREINIT2 ; SKIP IT IF NOTHING FOUND +; + PUSH BC ; SAVE LOOP CONTROL + PUSH IY ; CFG ENTRY ADDRESS + POP DE ; ... TO DE + LD BC,PIO_FNTBL ; BC := FUNCTION TABLE ADDRESS + ; REGISTRATION OF CHARACTER UNIT IN HBIOS IS BYPASSED + ; FOR NOW. NOT SURE WHAT TO DO WITH THIS HARDWARE YET. + ;CALL NZ,CIO_ADDENT ; ADD ENTRY IF PIO FOUND, BC:DE + POP BC ; RESTORE LOOP CONTROL +; +PIO_PREINIT2: + LD DE,PIO_CFGSIZ ; SIZE OF CFG ENTRY + ADD IY,DE ; BUMP IY TO NEXT ENTRY + DJNZ PIO_PREINIT0 ; LOOP UNTIL DONE +; XOR A ; SIGNAL SUCCESS RET ; AND RETURN ; -; INDEX INTO THE CONFIG TABLE -; ON ENTRY C = UNIT NUMBER -; ON EXIT IY = CONFIG DATA POINTER -; ON EXIT DE = CONFIG TABLE START -; -; EACH CONFIG TABLE IS 24 BYTES LONG -; -CFG_SIZ .EQU 24 -; -IDXCFG: LD A,C - RLCA ; X 2 - RLCA ; X 4 - RLCA ; X 8 - LD H,0 - LD L,A ; HL = X 8 - PUSH HL - ADD HL,HL ; HL = X 16 - POP DE - ADD HL,DE ; HL = X 24 - LD DE,PIO_CFG - ADD HL,DE - PUSH HL ; COPY CFG DATA PTR - POP IY ; ... TO IY - RET - -; PIO_INITDEV - INITIALIZE DEVICE +; PIO INITIALIZATION ROUTINE ; -; IF DE = FFFF THEN THE SETUP PARAMETER WORD WILL BE READ FROM THE DEVICE CONFIGURATION -; TABLE POINTED TO BY IY AND THE PIO PORT WILL BE PROGRAMMED BASED ON THAT CONFIGURATION. +PIO_INITUNIT: + CALL PIO_DETECT ; DETERMINE PIO TYPE + LD (IY+1),A ; SAVE IN CONFIG TABLE + OR A ; SET FLAGS + RET Z ; ABORT IF NOTHING THERE ; -; OTHERWISE THE PIO PORT WILL BE PROGRAMMED BY THE SETUP PARAMETER WORD IN DE AND THIS -; WILL BE SAVED IN THE DEVICE CONFIGURATION TABLE POINTED TO BY IY. + ; UPDATE WORKING PIO DEVICE NUM + LD HL,PIO_DEV ; POINT TO CURRENT UART DEVICE NUM + LD A,(HL) ; PUT IN ACCUM + INC (HL) ; INCREMENT IT (FOR NEXT LOOP) + LD (IY),A ; UPDATE UNIT NUM +; + ; SET DEFAULT CONFIG + LD DE,-1 ; LEAVE CONFIG ALONE + ; CALL INITDEVX TO IMPLEMENT CONFIG, BUT NOTE THAT WE CALL + ; THE INITDEVX ENTRY POINT THAT DOES NOT ENABLE/DISABLE INTS! + JP PIO_INITDEVX ; IMPLEMENT IT AND RETURN ; -; ALL OTHER CONFIGURATION OF THE DEVICE CONFIGURATION TABLE IS DONE UPSTEAM BY PIO_PREINIT - -PIO_INITDEV: - ; TEST FOR -1 (FFFF) WHICH MEANS USE CURRENT CONFIG (JUST REINIT) - LD A,D ; TEST DE FOR - AND E ; ... VALUE OF -1 - INC A ; ... SO Z SET IF -1 - JR NZ,PIO_INITDEV1 ; IF DE == -1, REINIT CURRENT CONFIG -PIO_INITDEV0: - ; LOAD EXISTING CONFIG (DCW) TO REINIT - LD E,(IY+4) ; LOW BYTE - LD D,(IY+5) ; HIGH BYTE -; -PIO_INITDEV1: ; WHICH DEVICE TYPE? - LD A,(IY+1) - CP PIO_ZPIO - JR Z,SETPIO0 - CP PIO_8255 - JP Z,SET_8255 - CP PIO_PORT - JP Z,SET_PORT -BAD_SET:OR $FF ; UNKNOWN DEVICE - RET - -SETPIO0:LD A,E ; GET MODE - AND 11000000B ; BITS (B7B6) - CP 10000000B ; IS IT BIDIR? - JR NZ,SETPIO1 - LD A,(IY+2) ; GET CHANNEL - OR A - JR NZ,BAD_SET ; CAN'T DO ON CH1 - - ; VALIDATE INTERRUPT REQUEST - ; GRANT INTERRUPT IF THERE IS A FREE INTERRUPT - ; GRANT INTERRUPT IF AN INTERRUPT IS ALREADY ALLOCATED TO THIS UNIT - -SETPIO1:PUSH AF ;D - LD A,'[' ;D - CALL COUT ;D - LD A,(IY) ;D - CALL PRTHEXBYTE ;D - LD A,']' ;D - CALL COUT ;D - POP AF ;D - - BIT 2,E ; SKIP IF WE ARE NOT REQUESTING - JP Z,SETPIO2 ; AN INTERRUPT - - PRTS("[INTREQ]$") ;D - -; LD A,(IY+4) ; GET CURRENT INTERRUPT SETTING -; BIT 2,A ; SKIP IF IT IS ALREADY -; JP NZ,SETPIO2 ; ALLOCATED TO THIS UNIT - - LD A,(INT_ALLOC) ; WE NEED TO ALLOCATE AN - CP INT_ALLOW ; INTERRUPT. DO WE HAVE - JR NC,BAD_SET ; ONE FREE? - - PRTS("[ALLOCINT]$") ;D - - ; WHICH INTERRUPT IS FREE ? - ; SCAN THROUGH THE CFG TABLES - ; AND FIND A FREE ONE - - PUSH AF ; NESTED LOOP - LD DE,CFG_SIZ ; OUTSIDE LOOP IS INTERRUPT - LD B,INT_ALLOW ; INSIDE LOOP IS DEVICE -SETPIOP: LD C,B - DEC C - PUSH BC - LD B,PIO_CNT - LD HL,PIO_CFG+4 -SETPIOX: LD A,(HL) - BIT 2,A ; JUMP TO NEXT DEVICE - JR Z,SETPIOY ; IF NO INTERRUPT ON - AND 00000011B ; THIS DEVICE - - CP C ; IF WE MATCH AN INTERRUPT HERE THEN IT IS NOT FREE. - JR NZ,SETPIOY ; SO EXIT INSIDE LOOP AND TRY NEXT INTERRUPT - - XOR A ; WE MATCH INT 0 - IF WE ARE CHECKING FOR IT THEN - OR C ; WE REGARD IS AS FREE. - JR NZ,SETPIOZ - -SETPIOY: ADD HL,DE - DJNZ SETPIOX - - JR SETPIOQ ; WE GET HERE IF THE CURRENT INTERRUPT - ; WAS NOT MATCHED SO IT IS FREE -SETPIOZ: POP BC - DJNZ SETPIOP - POP AF - - PRTS("[NONEFREE]$") - RET - -SETPIOQ:PUSH AF ; AVAILABLE INTERRUPT IS IN C - PRTS("[FREE]=$") - LD A,C - CALL PRTHEXBYTE - POP AF - - POP AF - POP AF - -SETPIOR:LD HL,INT_ALLOC ; INCREASE THE COUNT - INC (HL) ; OF USED INTERRUPTS - LD A,(HL) - -; LD A,(IY) ; IS THIS UNIT -; INC A ; UNITIALIZED? -; JR Z,SETPIO6 - - LD A,(IY+4) ; IT IS UNITIALIZED SO - OR C ; SAVE THE ALLOCATES - LD (IY+4),A ; INTERRUPT -; -; FOR THIS DEVICE AND INTERRUPT, UPDATE THE CONFIG TABLE FOR THIS DEVICE. -; PIO_IN, PIO_OUT, PIO_IST, PIO_OST ENTRIES NEED TO BE REDIRECTED. -; INTERRUPT VECTOR NEEDS TO BE UPDATED -; - LD A,(IY+0) - LD HL,0 - ; SETUP PIO INTERRUPT VECTOR IN IVT - LD HL,HBX_IV09+1 - -; CALL SPK_BEEP ; -SETPIO6:RET - - ; EXIT WITH FREE INTERRUPT IN C - - LD A,C - LD (INT_ALLOC),A - - LD A,E - AND 11000000B - OR 00000100B - OR C - LD E,A - LD (IY+5),A ; - ; TODO: DEALLOCATE AN INTERRUPT +PIO_INIT: + LD B,PIO_CFGCNT ; COUNT OF POSSIBLE PIO UNITS + LD IY,PIO_CFG ; POINT TO START OF CFG TABLE +PIO_INIT1: + PUSH BC ; SAVE LOOP CONTROL + LD A,(IY+1) ; GET PIO TYPE + OR A ; SET FLAGS + CALL NZ,PIO_PRTCFG ; PRINT IF NOT ZERO + POP BC ; RESTORE LOOP CONTROL + LD DE,PIO_CFGSIZ ; SIZE OF CFG ENTRY + ADD IY,DE ; BUMP IY TO NEXT ENTRY + DJNZ PIO_INIT1 ; LOOP TILL DONE ; -; LD A,(INT_ALLOC) -; DEC A -; LD (INT_ALLOC),A + XOR A ; SIGNAL SUCCESS + RET ; DONE ; -SETPIO2: - -; DE CONTAINS THE MODE IF INTERRUPT ROUTINE SKIPPED - - PRTS("[NOINTREQ]$") ;D - -; LD A,(IY+4) - LD A,E ; GET MODE AND CREATE COMMAND - AND 11000000B ; $B0 - OR 00001111B ; $0F - - LD C,(IY+3) ; GET DATA PORT - INC C ; POINT TO CMD - INC C ; PORT - OUT (C),A ; SET MODE - CP (M_BitCtrl | $0F) ; IF MODE 3 - JR NZ,SETPIO3 - LD A,(IY+5) ; SET I/O DIRECTION - OUT (C),A ; FOR MODE 3 - -SETPIO3:; INTERUPT HANDLING - - JP SETPIO4 - - ; SETUP THE INTERRUPT VECTOR - - LD A,E - AND 00000011B -; DEC A ; INDEX INTO THE - ADD A,A ; THE VECTOR TABLE - ADD A,A ; - LD C,A - LD B,0 - LD HL,HBX_IV09+1 - ADD HL,BC ; GET THE ADDRESS OF - PUSH DE - LD D,(HL) ; THAT INTERRUPT - INC HL ; HANDLER - LD E,(HL) - LD HL,0 ;HBX_IVT+IVT_PIO0 ; POPULATE THE - LD A,L ; GET LOW BYTE OF IVT ADDRESS - ADD HL,BC ; INTERRUPT TABLE - LD (HL),D ; WITH THE INTERRUPT - INC HL ; HANDLER ADDRESS FOR - LD (HL),E ; THIS UNIT - POP DE - LD HL,INT_ALLOC - LD C,(HL) - LD B,0 - LD HL,PRTTAB-1 ; SAVE THE DATA - ADD HL,BC ; PORT FOR EACH INTERRUPT - LD C,(IY+3) - LD (HL),C - - INC C ; POINT TO CMD PORT - INC C - DI ; SET THE VECTOR ADDRESS - OUT (C),A - -; LD A,10000011B ; ENABLE INTERRUPTS ON - OUT (C),A ; THIS UNIT - EI -; JR GUD_SET +; DRIVER FUNCTION TABLE +; +PIO_FNTBL: + .DW PIO_IN + .DW PIO_OUT + .DW PIO_IST + .DW PIO_OST + .DW PIO_INITDEV + .DW PIO_QUERY + .DW PIO_DEVICE +#IF (($ - PIO_FNTBL) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" +#ENDIF ; -SETPIO4:LD A,00000111B ; $07 - OUT (C),A ; NO INTERRUPTS ; -; SUCCESSFULL SO SAVE DEVICE CONFIGURATION WORD (DCW) ; -GUD_SET:LD (IY+4),E ; LOW BYTE - LD (IY+5),D ; HIGH BYTE +PIO_IN: + LD E,0 ; DUMMY VALUE + XOR A ; SIGNAL SUCCESS + RET ; -; UPDATE THE DEVICE TABLE WITH THE ADDRESSES FOR THE CORRECT ROUTINE. ; - LD A,E - AND 00000111B - LD HL,INTMATRIX ; POINT TO EITHER THE INTERRUPT - JR NZ, USEIM - LD HL,POLMATRIX ; MATRIX OR THE POLLED MATRIX -USEIM: PUSH HL - - PUSH IY ; CALCULATE THE DESTINATION - POP HL ; ADDRESS IN THE PIO_CFG TABLE - LD BC,8 ; FOR THE FOUR ADDESSES TO BE - ADD HL,BC ; COPIED TO - -; LD B,0 ; 00000000 CALCULATE THE SOURCE ADDRESS - LD C,E ; XX?????? FROM THE MATRIX. EACH ENTRY - SRL C ; 0XX????? IN THE MATRIX IS 8 BYTES SO - SRL C ; 00XX???? SOURCE = MATRIX BASE + (8 * MODE) - SRL C ; 000XX??? - POP DE ; LOAD THE MATRIX BASE -; LD DE,POLMATRIX - EX DE,HL - ADD HL,BC ; HL = SOURCE - - LD C,8 ; COPY 8 BYTES - LDIR - -; PUSH IY -; POP DE -; CALL DUMP_BUFFER - - XOR A - RET - -PRTTAB: .DB 0 - .DB 0 - .DB 0 - .DB 0 -; -;----------------------------------------------------------------------------- -; -; INPUT INTERRUPT VECTOR MACRO AND DEFINITION FOR FOUR PORTS -; -#DEFINE PIOMIVT(PIOIN,PIOIST,PIOPRT) \ -#DEFCONT ;\ -#DEFCONT ; RETURN WITH ERROR IF THERE IS \ -#DEFCONT ; ALREADY A CHARACTER IN BUFFER \ -#DEFCONT ;\ -#DEFCONT ; OTHERWISE CHANGE THE STATUS TO \ -#DEFCONT ; SHOW THERE IS ONE CHARACTER IN \ -#DEFCONT ; THE BUFFER AND READ IT IN AND \ -#DEFCONT ; AND STORE IT.RETURN GOOD STATUS.\ -#DEFCONT ;\ -#DEFCONT \ LD A,(_CIST) -#DEFCONT \ OR A -#DEFCONT \ JR NZ,_OVFL -#DEFCONT \ LD A,(PIOPRT) -#DEFCONT \ LD C,A -#DEFCONT \ LD A,1 -#DEFCONT \ LD (_CIST),A -#DEFCONT \ IN A,(C) -#DEFCONT \ LD (_CICH),A -#DEFCONT \ OR $FF -#DEFCONT \ RET -#DEFCONT \_OVFL:XOR A -#DEFCONT \ RET -#DEFCONT ;\ -#DEFCONT ;\ -#DEFCONT ;\ -#DEFCONT ;\ -#DEFCONT ;\ -#DEFCONT ;\ -#DEFCONT \PIOIN:CALL PIOIST -#DEFCONT \ JR Z,PIOIN -#DEFCONT \ LD A,(_CICH) -#DEFCONT \ LD E,A -#DEFCONT \ XOR A -#DEFCONT \ LD (_CIST),A -#DEFCONT \ RET -#DEFCONT ;\ -#DEFCONT ; If THERE A CHARACTER \ -#DEFCONT ; AVAILABLE? RETURN NUMBER \ -#DEFCONT ; IN A - 0 OR 1 \ -#DEFCONT ;\ -#DEFCONT \PIOIST:LD A,(_CIST) -#DEFCONT \ AND 00000001B -#DEFCONT \ RET -#DEFCONT ;\ -#DEFCONT ; CIST : 01 = CHARACTER READY ELSE NOT READY \ -#DEFCONT ; CISH : CHARACTER STORED BY INTERRUPT \ -#DEFCONT ;\ -#DEFCONT \_CIST .DB 00 -#DEFCONT \_CICH .DB 00 -; -PIOIVT0:.MODULE PIOIVT0 -PIOMIVT(PIO0IN,PI0_IST,PRTTAB+0) -PIOIVT1:.MODULE PIOIVT1 -PIOMIVT(PIO1IN,PI1_IST,PRTTAB+1) -PIOIVT2:.MODULE PIOIVT2 -PIOMIVT(PIO2IN,PI2_IST,PRTTAB+2) -PIOIVT3:.MODULE PIOIVT3 -PIOMIVT(PIO3IN,PI3_IST,PRTTAB+3) -; -;----------------------------------------------------------------------------- -; -; OUTPUT INTERRUPT VECTOR MACRO AND DEFINITION FOR FOUR PORTS -; -; AN INTERRUPT IS GENERATED WHEN THE RECEIVING DEVICE CAN ACCEPT A CHARACTER -; -#DEFINE PIOMOVT(PIOOUT,PIOOST,PIOPRT) \ -#DEFCONT ;\ -#DEFCONT ; RETURN IF WE ARE WAITING FOR A \ -#DEFCONT ; CHARACTER (COST = 00) \ -#DEFCONT ;\ -#DEFCONT ; IF ZERO CHARACTERS READY -#DEFCONT ; (COST = 01) CHANGE STATUS TO \ -#DEFCONT ; WAITING FOR CHARACTER (COST 00) \ -#DEFCONT ;\ -#DEFCONT ; IF A CHARACTER IS READY THEN \ -#DEFCONT ; OUTPUT AND CHANGE STATUS TO \ -#DEFCONT ; ZERO CHARACTERS READY \ -#DEFCONT ;\ -#DEFCONT \ LD A,(_COST) -#DEFCONT \ DEC A -#DEFCONT \ RET M -#DEFCONT \ JR Z,_WFC -#DEFCONT \ LD A,(_COCH) -#DEFCONT \ LD E,A -#DEFCONT \_ONOW:LD A,(PIOPRT) -#DEFCONT \ LD C,A -#DEFCONT \ OUT (C),E -#DEFCONT \ LD A,1 -#DEFCONT \_WFC: LD (_COST),A -#DEFCONT \ RET -#DEFCONT ;\ -#DEFCONT ; WAIT FOR SPACE FOR THE CHARACTER\ -#DEFCONT ; IF WE ARE WAITING FOR A \ -#DEFCONT ; CHARACTRE THEN OUTPUT IT NOW \ -#DEFCONT ; OTHERWISE STORE IT UNTIL THE \ -#DEFCONT ; INTERRUPT CALLS FOR IT \ -#DEFCONT ;\ -#DEFCONT \PIOOUT:LD A,(_COST) -#DEFCONT \ CP 2 -#DEFCONT \ JR C,_ONOW -#DEFCONT \ LD A,E -#DEFCONT \ LD (_COCH),A -#DEFCONT \ LD A,2 -#DEFCONT \ LD (_COST),A -#DEFCONT \ JR PIOOUT -#DEFCONT ;\ -#DEFCONT ; RETURN WITH NUMBER OF \ -#DEFCONT ; CHARACTERS AVAILABLE 0 or 1 \ -#DEFCONT ;\ -#DEFCONT \PIOOST:LD A,(_COST) -#DEFCONT \ DEC A -#DEFCONT \ DEC A -#DEFCONT \ RET Z -#DEFCONT \ LD A,1 -#DEFCONT \ RET -#DEFCONT ;\ -#DEFCONT ; COST : 00 WAITING FOR CHARACTER\ -#DEFCONT ; 01 ZERO CHARACTERS READY\ -#DEFCONT ; 02 ONE CHARACTER READY \ -#DEFCONT ; COCH : CHARACTER TO OUTPUT \ -#DEFCONT ;\ -#DEFCONT \_COST .DB 01 -#DEFCONT \_COCH .DB 00 -; -PIOOVT0:.MODULE PIOOVT0 -PIOMOVT(PIO0OUT,PI0_OST,PRTTAB+0) -PIOOVT1:.MODULE PIOOVT1 -PIOMOVT(PIO1OUT,PI1_OST,PRTTAB+1) -PIOOVT2:.MODULE PIOOVT2 -PIOMOVT(PIO2OUT,PI2_OST,PRTTAB+2) -PIOOVT3:.MODULE PIOOVT3 -PIOMOVT(PIO3OUT,PI3_OST,PRTTAB+3) -; -;----------------------------------------------------------------------------- -; -; NON INTERRUPT OUTPUT ROUTINE - SHARED -; -; INPUT WILL ALWAYS RETURN ERROR, CHARACTER RETURNED IS UNDEFINED. -; OUTPUT WILL ALWAYS RETURN SUCCESS -; INPUT-STATUS WILL ALWAYS RETURN 0 CHARACTERS IN BUFFER. -; OUTPUT-STATUS WILL ALWAYS RETURN 1 CHARACTER SPACE IN BUFFER. - -PIOSHO_IN: - LD A,1 - RET ; -PIOSHO_OUT: - LD C,(IY+3) - OUT (C),E - XOR A +PIO_OUT: + XOR A ; SIGNAL SUCCESS RET ; -PIOSHO_IST: XOR A - RET ; -PIOSH_OST: - LD A,1 - RET ; -;----------------------------------------------------------------------------- +PIO_IST: + XOR A ; NO CHARS WAITING + RET ; -; NON INTERRUPT INPUT ROUTINE - SHARED ; -; INPUT WILL ALWAYS A CHARACTER AND SUCCESS. -; OUTPUT WILL ALWAYS RETURN FAILURE -; INPUT STATUS WILL ALWAYS RETURN 1 CHARACTER IN BUFFER. -;OUTPUT-STATUS WILL ALWAYS RETURN 0 CHARACTER SPACE IN BUFFER. ; -PIOSHI_IN: - LD C,(IY+3) - IN A,(C) - LD E,A - XOR A +PIO_OST: + XOR A ; NO BUFFER SPACE AVAIL RET ; -PIOSHI_OUT: - LD A,1 - RET +; NOTE THAT THERE ARE TWO ENTRY POINTS. INITDEV WILL DISABLE/ENABLE INTS +; AND INITDEVX WILL NOT. THIS IS DONE SO THAT THE PREINIT ROUTINE ABOVE +; CAN AVOID ENABLING/DISABLING INTS. ; -PIOSH_IST: - LD A,1 - RET +PIO_INITDEV: + HB_DI ; DISABLE INTS + CALL PIO_INITDEVX ; DO THE WORK + HB_EI ; INTS BACK ON + RET ; DONE ; -PIOSHI_OST: - XOR A +PIO_INITDEVX: +; +; THIS ENTRY POINT BYPASSES DISABLING/ENABLING INTS WHICH IS REQUIRED BY +; PREINIT ABOVE. PREINIT IS NOT ALLOWED TO ENABLE INTS! +; + LD C,(IY+3) ; CONTROL PORT + LD A,%00010111 ; CLEAR INTERRUPT CTL WORD + OUT (C),A + LD A,%11111111 ; CLEAR MASK + OUT (C),A + LD A,%00000000 ; CLEAR INTERRUPT VECTOR + OUT (C),A + LD A,%01001111 ; SET MODE 1 (INPUT) + OUT (C),A RET ; -;----------------------------------------------------------------------------- ; -; ON ENTRY IY POINTS TO THE DEVICE RECORD. GET AND RETURN THE CONFIGURATION WORD IN DE ; PIO_QUERY: -PPI_QUERY: - LD E,(IY+4) ; FIRST CONFIG BYTE TO E - LD D,(IY+5) ; SECOND CONFIG BYTE TO D + LD E,(IY+5) ; FIRST CONFIG BYTE TO E + LD D,(IY+6) ; SECOND CONFIG BYTE TO D XOR A ; SIGNAL SUCCESS - RET + RET ; DONE ; -;----------------------------------------------------------------------------- ; -; ON ENTRY IY POINTS TO THE DEVICE RECORD. FOR CHARACTER DEVICES BIT 6 OF ATTRIBUTE -; INDICATES PARALLEL PORT IF 1 SO WE SET IT. COMMON TO ALL PORTS ; PIO_DEVICE: -PPI_DEVICE: LD D,CIODEV_PIO ; D := DEVICE TYPE LD E,(IY) ; E := PHYSICAL UNIT - LD C,$40 ; C := ATTRIBUTE - LD H,0 ; H := 0, DRIVER HAS NO MODES + LD C,$40 ; C := DEVICE TYPE, 0x40 IS PIO + LD H,(IY+1) ; H := MODE LD L,(IY+3) ; L := BASE I/O ADDRESS XOR A ; SIGNAL SUCCESS RET ; -INTMATRIX: - .DW PIO0IN, PIO0OUT, PI0_IST, PI0_OST - .DW PIO1IN, PIO1OUT, PI1_IST, PI1_OST - .DW PIO2IN, PIO2OUT, PI2_IST, PI2_OST - .DW PIO3IN, PIO3OUT, PI3_IST, PI3_OST -POLMATRIX: - .DW PIOSHO_IN, PIOSHO_OUT, PIOSHO_IST, PIOSH_OST ; OUTPUT - .DW PIOSHI_IN, PIOSHI_OUT, PIOSH_IST, PIOSHI_OST ; INPUT - .DW 0,0,0,0 ; BIDIR - .DW 0,0,0,0 ; BIT MODE - -SET_8255: - RET +; PIO CHIP PROBE +; CHECK FOR PRESENCE OF PIO CHIPS AND POPULATE THE +; PIO_MAP BITMAP (ONE BIT PER CHIP). THIS DETECTS +; CHIPS, NOT CHANNELS. EACH CHIP HAS 2 CHANNELS. +; MAX OF TWO CHIPS CURRENTLY. INT VEC VALUE IS TRASHED! +; +PIO_PROBE: + ; CLEAR THE PRESENCE BITMAP + LD HL,PIO_MAP ; HL POINTS TO BITMAP + XOR A ; ZERO + LD (PIO_MAP),A ; CLEAR CHIP PRESENT BITMAP +; + ; FIRST POSSIBLE CHIP + LD C,PIO0A_CTL ; FIRST CHIP CMD/STAT PORT + CALL PIO_PROBECHIP ; PROBE IT + JR NZ,PIO_PROBE1 ; IF NOT ZERO, NOT FOUND + SET 0,(HL) ; SET BIT FOR FIRST CARD +PIO_PROBE1: +; +#IF (PIOCNT >= 2) + LD C,PIO1A_CTL ; SECOND CHIP CMD/STAT PORT + CALL PIO_PROBECHIP ; PROBE IT + JR NZ,PIO_PROBE2 ; IF NOT ZERO, NOT FOUND + SET 1,(HL) ; SET BIT FOR SECOND CARD +PIO_PROBE2: +#ENDIF ; -SET_BYE: - XOR A ; SIGNAL SUCCESS RET ; -; ------------------------------------ -; i8255 FUNCTION TABLE ROUTINES -;------------------------------------- - -PPI_IN: - XOR A ; SIGNAL SUCCESS - RET -; -PPI_OUT: - XOR A ; SIGNAL SUCCESS - RET -; -PPI_IST: - RET -; -PPI_OST: +PIO_PROBECHIP: + ; PIO IS HRD TO DETECT DEFINITIVELY. BEST I CAN THINK + ; OF IS TO CHECK THE VALUE READ FROM THE CONTROL PORT. + ; IT APPEARS TO BE ZERO CONSISTENTLY IF CHIP EXISTS. + IN A,(C) ; GET VALUE + OR A ; COMPARE TO ZERO RET ; -; PIO_INITDEV - Configure device. -; If DE = FFFF then extract the configuration information from the table of devices and program the device using those settings. -; Otherwise use the configuration information in DE to program those settings and save them in the device table - -PPI_INITDEV: - XOR A ; SIGNAL SUCCESS - RET -PPI_INT:OR $FF ; NZ SET TO INDICATE INT HANDLED - RET -; +; PIO DETECTION ROUTINE +; THERE IS ONLY ONE VARIATION OF PIO CHIP, SO HERE WE JUST CHECK THE +; CHIP PRESENCE BITMAP TO SET THE CHIP TYPE OF EITHER NONE OR PIO. +; +PIO_DETECT: + LD B,(IY+2) ; GET CHIP/CHANNEL + SRL B ; SHIFT AWAY THE CHANNEL BIT + INC B ; NUMBER OF TIMES TO ROTATE BITS + LD A,(PIO_MAP) ; BIT MAP IN A +PIO_DETECT1: + ; ROTATE DESIRED CHIP BIT INTO CF + RRA ; ROTATE NEXT BIT INTO CF + DJNZ PIO_DETECT1 ; DO THIS UNTIL WE HAVE DESIRED BIT + ; RETURN CHIP TYPE + LD A,PIO_NONE ; ASSUME NOTHING HERE + RET NC ; IF CF NOT SET, RETURN + LD A,PIO_PIO ; CHIP TYPE IS PIO + RET ; DONE +; +; +; PIO_PRTCFG: ; ANNOUNCE PORT CALL NEWLINE ; FORMATTING @@ -780,220 +258,90 @@ PIO_PRTCFG: PRTS(": IO=0x$") ; FORMATTING LD A,(IY+3) ; GET BASE PORT CALL PRTHEXBYTE ; PRINT BASE PORT -; + ; PRINT THE PIO TYPE CALL PC_SPACE ; FORMATTING LD A,(IY+1) ; GET PIO TYPE BYTE - LD DE,PIO_TYPE_STR ; POINT HL TO TYPE MAP TABLE - CALL PRTIDXDEA - - ; ALL DONE IF NO PIO WAS DETECTED - LD A,(IY+1) ; GET PIO TYPE BYTE - OR A ; SET FLAGS - RET Z ; IF ZERO, NOT PRESENT -; - PRTS(" MODE=$") ; FORMATTING - LD E,(IY+4) ; LOAD CONFIG - LD D,(IY+5) ; ... WORD TO DE - CALL PS_PRTPC0 ; PRINT CONFIG -; - LD A,(IY+4) ; PRINT - BIT 2,A ; ALLOCATED - JR Z,NOINT ; INTERRUPT - PRTS("/i$") - LD A,(IY+4) - AND 00000011B - CALL PRTDECB -NOINT: XOR A + RLCA ; MAKE IT A WORD OFFSET + LD HL,PIO_TYPE_MAP ; POINT HL TO TYPE MAP TABLE + CALL ADDHLA ; HL := ENTRY + LD E,(HL) ; DEREFERENCE + INC HL ; ... + LD D,(HL) ; ... TO GET STRING POINTER + CALL WRITESTR ; PRINT IT +; + XOR A RET ; -; WORKING VARIABLES ; -PIO_DEV .DB 0 ; DEVICE NUM USED DURING INIT -; -; DESCRIPTION OF DIFFERENT PORT TYPES -; -PIO_TYPE_STR: - .TEXT "$" ; IDX 0 - .TEXT "Zilog PIO$" ; IDX 1 - .TEXT "i8255 PPI$" ; IDX 2 - .TEXT "IO Port$" ; IDX 3 -; -; Z80 PIO PORT TABLE - EACH ENTRY IS FOR 1 CHIP I.E. TWO PORTS -; -; 32 BYTE DATA STRUCTURE FOR EACH PORT -; -; .DB 0 ; IY+0 CIO DEVICE NUMBER (SET DURING PRE-INIT, THEN FIXED) -; .DB 0 ; IY+1 PIO TYPE (SET AT ASSEMBLY, FIXED) -; .DB 0 ; IY+2 PIO CHANNEL (SET AT ASSEMBLY, FIXED) -; .DB PIOBASE+2 ; IY+3 BASE DATA PORT (SET AT ASSEMBLY, FIXED) -; .DB 0 ; IY+4 SPW - MODE 3 I/O DIRECTION BYTE (SET AT ASSEMBLE, SET WITH INIT) -; .DB 0 ; IY+5 SPW - MODE, INTERRUPT (SET AT ASSEMBLY, SET WITH INIT) -; .DW 0 ; IY+6/7 FUNCTION TABLE (SET AT ASSEMBLY, SET DURING PRE-INIT AND AT INIT) -; .DW PIO_IN ; IY+8 ADDR FOR DEVICE INPUT (SET WITH INIT) -; .DW PIO_OUT ; IY+10 ADDR FOR DEVICE OUTPUT (SET WITH INIT) -; .DW PIO_IST ; IY+12 ADDR FOR DEVICE INPUT STATUS (SET WITH INIT) -; .DW PIO_OST ; IY+14 ADDR FOR DEVICE OUTPUT STATUS (SET WITH INIT) -; .DW PIO_INITDEV ; IY+16 ADDR FOR INITIALIZE DEVICE ROUTINE (SET AT ASSEMBLY, FIXED) -; .DW PIO_QUERY ; IY+18 ADDR FOR QUERY DEVICE RECORD ROUTINE (SET AT ASSEMBLY, FIXED) -; .DW PIO_DEVICE ; IY+20 ADDR FOR DEVICE TYPE ROUTINE (SET AT ASSEMBLY, FIXED) -; .FILL 10 -; -; SETUP PARAMETER WORD: -; -; +-------------------------------+ +-------+-----------+---+-------+ -; | BIT CONTROL | | MODE | | A | INT | -; +-------------------------------+ --------------------+-----------+ -; F E D C B A 9 8 7 6 5 4 3 2 1 0 -; -- MSB (D REGISTER) -- -- LSB (E REGISTER) -- -; -; -; MSB = BIT CONTROL MAP USE IN MODE 3 -; -; MODE B7 B6 = 00 Mode 0 Output -; 01 Mode 1 Input -; 10 Mode 2 Bidir -; 11 Mode 3 Bit Mode -; -; INTERRUPT ALLOCATED B2 = 0 NOT ALLOCATED -; = 1 IS ALLOCATED -; -; WHICH IVT IS ALLOCATES B1 B0 00 IVT_PIO0 -; 01 IVT_PIO1 -; 10 IVT_PIO2 -; 11 IVT_PIO3 -; -#DEFINE DEFPIO(MPIOBASE,MPIOCH0,MPIOCH1,MPIOCH0X,MPIOCH1X,MPIOIN0,MPIOIN1) \ -#DEFCONT \ .DB 0 -#DEFCONT \ .DB PIO_ZPIO -#DEFCONT \ .DB 0 -#DEFCONT \ .DB MPIOBASE -#DEFCONT \ .DB (MPIOCH0|MPIOIN0) -#DEFCONT \ .DB MPIOCH0X -#DEFCONT \ .DW 0 -#DEFCONT \ .DW 0,0,0,0, PIO_INITDEV,PIO_QUERY,PIO_DEVICE -#DEFCONT \ .FILL 2 -#DEFCONT \ .DB 0 -#DEFCONT \ .DB PIO_ZPIO -#DEFCONT \ .DB 1 -#DEFCONT \ .DB MPIOBASE+1 -#DEFCONT \ .DB (MPIOCH1|MPIOIN1) -#DEFCONT \ .DB MPIOCH1X -#DEFCONT \ .DW 0 -#DEFCONT \ .DW 0,0,0,0, PIO_INITDEV,PIO_QUERY,PIO_DEVICE -#DEFCONT \ .FILL 2 -; -; i8255 PORT TABLE - EACH ENTRY IS FOR 1 CHIP I.E. THREE PORTS -; -#DEFINE DEFPPI(MPPIBASE,MPPICH1,MPPICH2,MPPICH3,MPPICH1X,MPPICH2X,MPPICH3X) \ -#DEFCONT \ .DB 0 -#DEFCONT \ .DB PIO_8255 -#DEFCONT \ .DB 0 -#DEFCONT \ .DB MPPIBASE -#DEFCONT \ .DB (MPPICH1|00001000B) -#DEFCONT \ .DB MPPICH1X -#DEFCONT \ .DW 0 -#DEFCONT \ .DW PPI_IN,PPI_OUT,PPI_IST,PPI_OST,PPI_INITDEV,PPI_QUERY,PPI_DEVICE -#DEFCONT \ .FILL 2 -#DEFCONT \ .DB 0 -#DEFCONT \ .DB PIO_8255 -#DEFCONT \ .DB 1 -#DEFCONT \ .DB MPPIBASE+2 -#DEFCONT \ .DB (MPPICH2|00010000B) -#DEFCONT \ .DB MPPICH2X -#DEFCONT \ .DW 0 -#DEFCONT \ .DW PPI_IN,PPI_OUT,PPI_IST,PPI_OST,PPI_INITDEV,PPI_QUERY,PPI_DEVICE -#DEFCONT \ .FILL 2 -#DEFCONT \ .DB 0 -#DEFCONT \ .DB PIO_8255 -#DEFCONT \ .DB 2 -#DEFCONT \ .DB MPPIBASE+4 -#DEFCONT \ .DB (MPPICH3|00100000B) -#DEFCONT \ .DB MPPICH3X -#DEFCONT \ .DW 0 -#DEFCONT \ .DW PPI_IN,PPI_OUT,PPI_IST,PPI_OST,PPI_INITDEV,PPI_QUERY,PPI_DEVICE -#DEFCONT \ .FILL 2 -; -; HERE WE ACTUALLY DEFINE THE HARDWARE THAT THE HBIOS CAN ACCESS -; THE INIT ROUTINES READ AND SET THE INITIAL MODES FROM THIS INFO ; -PIO_CFG: -; -#IF PIO_4P -DEFPIO(PIO4BASE+0,M_Output,M_Input,M_BitAllOut,M_BitAllOut,INT_N,INT_N) -DEFPIO(PIO4BASE+4,M_Input,M_Input,M_BitAllOut,M_BitAllOut,INT_N,INT_N) -DEFPIO(PIO4BASE+8,M_Output,M_Output,M_BitAllOut,M_BitAllOut,INT_N,INT_N) -DEFPIO(PIO4BASE+12,M_Output,M_Output,M_BitAllOut,M_Output,INT_N,INT_N) -#ENDIF -#IF PIO_ZP -DEFPIO(PIOZBASE+0,M_Input,M_Input,M_BitAllOut,M_BitAllOut,INT_N,INT_N) -DEFPIO(PIOZBASE+4,M_Output,M_Output,M_BitAllOut,M_BitAllOut,INT_N,INT_N) -#ENDIF -; PIO_SBC & (PLATFORM == PLT_SBC) & (PPIDEMODE != PPIDEMODE_SBC)) +PIO_TYPE_MAP: + .DW PIO_STR_NONE + .DW PIO_STR_PIO -#IF PIO_SBC -DEFPPI(PIOSBASE,M_Output,M_Output,M_Output,M_BitAllOut,M_BitAllOut,M_BitAllOut) -#ENDIF +PIO_STR_NONE .DB "$" +PIO_STR_PIO .DB "PIO$" ; -PIO_CNT .EQU ($ - PIO_CFG) / CFG_SIZ +; WORKING VARIABLES ; -;------------------------------------------------------------------- -; WHEN WE GET HERE IY POINTS TO THE PIO_CFG TABLE WE ARE WORKING ON. -; C IS THE UNIT NUMBER -;------------------------------------------------------------------- +PIO_DEV .DB 0 ; DEVICE NUM USED DURING INIT +PIO_MAP .DB 0 ; CHIP PRESENCE BITMAP ; -;PIO_INITUNIT: -; LD A,C ; SET THE UNIT NUMBER -; LD (IY),A +PIO0A_RCVBUF .EQU 0 +PIO0B_RCVBUF .EQU 0 ; -; LD DE,-1 ; LEAVE CONFIG ALONE -; CALL PIO_INITDEV ; IMPLEMENT IT AND RETURN -; XOR A ; SIGNAL SUCCESS -; RET ; AND RETURN +#IF (PIOCNT >= 2) +PIO1A_RCVBUF .EQU 0 +PIO1B_RCVBUF .EQU 0 +#ENDIF ; -PIO_INIT: -; CALL SPK_BEEP - LD B,PIO_CNT ; COUNT OF POSSIBLE PIO UNITS - LD C,0 ; INDEX INTO PIO CONFIG TABLE -PIO_INIT1: - PUSH BC ; SAVE LOOP CONTROL - -; LD A,C ; PHYSICAL UNIT TO A -; RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (32 BYTES) -; RLCA ; ... -; RLCA ; ... TO GET OFFSET INTO CFG TABLE -; RLCA -;; RLCA -; LD HL,PIO_CFG ; POINT TO START OF CFG TABLE -; PUSH AF -; CALL ADDHLA ; HL := ENTRY ADDRESS -; POP AF -; CALL ADDHLA ; HL := ENTRY ADDRESS -; PUSH HL ; COPY CFG DATA PTR -; POP IY ; ... TO IY -; POP IY ; ... TO IY - - CALL IDXCFG - - LD A,(IY+1) ; GET PIO TYPE - OR A ; SET FLAGS - CALL NZ,PIO_PRTCFG ; PRINT IF NOT ZERO - -; PUSH DE -; LD DE,$FFFF ; INITIALIZE DEVICE/CHANNEL -; CALL PIO_INITDEV ; BASED ON DPW -; POP DE - - POP BC ; RESTORE LOOP CONTROL - INC C ; NEXT UNIT - DJNZ PIO_INIT1 ; LOOP TILL DONE +; PIO PORT TABLE ; - XOR A ; SIGNAL SUCCESS - RET ; DONE +PIO_CFG: + ; PIO0 CHANNEL A +PIO0A_CFG: + .DB 0 ; DEVICE NUMBER (SET DURING INIT) + .DB 0 ; PIO TYPE (SET DURING INIT) + .DB $00 ; CHIP 0 / CHANNEL A (LOW BIT IS CHANNEL) + .DB PIO0A_CTL ; CMD/STATUS PORT + .DB PIO0A_DAT ; DATA PORT + .DW DEFSERCFG ; LINE CONFIGURATION + .DW PIO0A_RCVBUF ; POINTER TO RCV BUFFER STRUCT +; +PIO_CFGSIZ .EQU $ - PIO_CFG ; SIZE OF ONE CFG TABLE ENTRY +; + ; PIO0 CHANNEL B +PIO0B_CFG: + .DB 0 ; DEVICE NUMBER (SET DURING INIT) + .DB 0 ; PIO TYPE (SET DURING INIT) + .DB $01 ; CHIP 0 / CHANNEL B (LOW BIT IS CHANNEL) + .DB PIO0B_CTL ; CMD/STATUS PORT + .DB PIO0B_DAT ; DATA PORT + .DW DEFSERCFG ; LINE CONFIGURATION + .DW PIO0B_RCVBUF ; POINTER TO RCV BUFFER STRUCT +; +#IF (PIOCNT >= 2) +; + ; PIO1 CHANNEL A +PIO1A_CFG: + .DB 0 ; DEVICE NUMBER (SET DURING INIT) + .DB 0 ; PIO TYPE (SET DURING INIT) + .DB $02 ; CHIP 1 / CHANNEL A (LOW BIT IS CHANNEL) + .DB PIO1A_CTL ; CMD/STATUS PORT + .DB PIO1A_DAT ; DATA PORT + .DW DEFSERCFG ; LINE CONFIGURATION + .DW PIO1A_RCVBUF ; POINTER TO RCV BUFFER STRUCT +; + ; PIO1 CHANNEL B +PIO1B_CFG: + .DB 0 ; DEVICE NUMBER (SET DURING INIT) + .DB 0 ; PIO TYPE (SET DURING INIT) + .DB $03 ; CHIP 1 / CHANNEL B (LOW BIT IS CHANNEL) + .DB PIO1B_CTL ; CMD/STATUS PORT + .DB PIO1B_DAT ; DATA PORT + .DW DEFSERCFG ; LINE CONFIGURATION + .DW PIO1B_RCVBUF ; POINTER TO RCV BUFFER STRUCT ; -SET_PORT: - ; DEVICE TYPE IS I/O PORT SO JUST WRITE $00 TO IT - LD C,(IY+3) - OUT (C),A - XOR A - RET +#ENDIF +; +PIO_CFGCNT .EQU ($ - PIO_CFG) / PIO_CFGSIZ diff --git a/Source/HBIOS/pio_ps.asm b/Source/HBIOS/pio_ps.asm new file mode 100644 index 00000000..f198f25a --- /dev/null +++ b/Source/HBIOS/pio_ps.asm @@ -0,0 +1,999 @@ +; PIO driver sets up the parallel port as a subtype of Serial/Char device. +; +; +; HBIOS initializes driver by: +; +; 1) Calling Pre-initialization +; +; This involves setting up all the data structures describing the devices. +; If possible, do a hardware test to verify it is available for adding to available devices. +; +; 2) Calling device initialization. +; +; Hardware initialization. +; Configure to initial state or to a new state. +; +; Implementation limitations: +; +; The fully functionality of the Z80 PIO can only be realized by using Z80 interrupt mode 2. +; Registers cannot be interrogated for interrupts status and the originating interrupt +; device cannot be determine. +; +; Full implementation of IM2 functionality for an ECB-ZP and ECB-4P board would require the +; allocation of an interrupt handler for each chip channel. Thus, 12 interrupt handlers +; would be required to support this configuration. As the HBIOS only has an allocation of +; 16, a full implmentation is impractical. +; +; The compromise solution is to allow 4 interrupts for the PIO driver. All remaining PIO's +; are limited to Bit mode or blind read and write to the input/output ports. +; +; Zilog PIO reset state: +; +; Both port mask registers are reset to inhibit All port data bits. +; Port data bus lines are set to a high-impedance state and the Ready "handshake" +; Mode 1 (output) is automatically selected. +; The vector address registers are not reset. +; Both port interrupt enable flip-flops are reset. +; Both port output registers are reset. +; +; Register addressing example for ECB-ZP and ECB-4P assuming base address 90h and 88h respectively. +; +; PIO ----ZP---- ----4P---- +; 0 DATA 0 90h DATA 0 B8h +; 0 DATA 1 91h DATA 1 B9h +; 0 CMD 0 92h CMD 0 BAh +; 0 CMD 1 93h CMD 1 BBh +; 1 DATA 0 94h DATA 0 BCh +; 1 DATA 1 95h DATA 1 BDh +; 1 CMD 0 96h CMD 0 BEh +; 1 CMD 1 97h CMD 1 BFh +; 2 DATA 0 C0h +; 2 DATA 1 C1h +; 2 CMD 0 C2h +; 2 CMD 1 C3h +; 3 DATA 0 C4h +; 3 DATA 1 C5h +; 3 CMD 0 C6h +; 3 CMD 1 C7h +; +PIODEBUG .EQU 1 +; +M_Output .EQU $00 << 6 +M_Input .EQU $01 << 6 +M_Bidir .EQU $02 << 6 +M_BitCtrl .EQU $03 << 6 +M_BitAllIn .EQU $FF +M_BitAllOut .EQU $00 +; +PIO_NONE .EQU 0 +PIO_ZPIO .EQU 1 +PIO_8255 .EQU 2 +PIO_PORT .EQU 3 + +; SET MAXIMUM NUMBER OF INTERRUPTS AVAILABLE FOR ALL +; ENSURE INTERRUPTS ARE NOT TURNED ON IF IM2 IS NOT SET. + +INT_ALLOC .DB 0 +INT_N .EQU 00000000B +#IF (INTMODE == 2) +INT_Y .EQU 00000100B +INT_ALLOW .EQU 4 +#ELSE +INT_Y .EQU INT_N +INT_ALLOW .EQU 0 +#ENDIF +; +INT0 .EQU 00000000B +INT1 .EQU 00000001B +INT2 .EQU 00000010B +INT3 .EQU 00000011B + +; +; SETUP THE DISPATCH TABLE ENTRIES +; +; PIO_CNT HOLDS THE NUMBER OF DEVICED CALCULATED FROM THE NUMBER OF DEFPIO MACROS +; PIO_CNT SHOULD INCREASE BY 2 FOR EVERY PIO CHIP ADDED. +; +; PIO_PREINIT WILL READ THROUGH ALL PIOCFG TABLES AND CONFIGURE EACH TABLE. +; IT WITH THEN CALL PIO_INITUNIT TO INITIALIZE EACH DEVICE TO ITS DEFAULT STATE +; +; EXPECTS NOTHING ON ENTRY +; +PIO_PREINIT: + CALL NEWLINE ;D + LD B,PIO_CNT ; LOOP CONTROL + LD C,0 ; PHYSICAL UNIT INDEX + XOR A ; ZERO TO ACCUM +; LD (PIO_DEV),A ; CURRENT DEVICE NUMBER + LD (INT_ALLOC),A ; START WITH NO INTERRUPTS ALLOCATED +PIO_PREINIT0: + PUSH BC ; SAVE LOOP CONTROL +; LD A,C ; INITIALIZE THE UNIT + +; PUSH AF ;D +; LD A,'u' ;D +; CALL COUT ;D +; POP AF ;D +; CALL PRTHEXBYTE ;D UNIT +; CALL PC_SPACE ;D + +; RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (32 BYTES) +; RLCA ; ... +; RLCA ; ... TO GET OFFSET INTO CFG TABLE +; RLCA +;; RLCA +; LD HL,PIO_CFG ; POINT TO START OF CFG TABLE +; PUSH AF +; CALL ADDHLA ; HL := ENTRY ADDRESS +; POP AF +; CALL ADDHLA ; HL := ENTRY ADDRESS +; PUSH HL ; SAVE IT +; POP IY ; ... TO IY + + CALL IDXCFG + + LD (HL),C + + PUSH AF ;D + LD A,'c' ;D + CALL COUT ;D + POP AF ;D + PUSH BC ;D + PUSH HL ;D + POP BC ;D + CALL PRTHEXWORD ;D CONFIG TABLE + CALL PC_SPACE ;D + POP BC ;D + + LD A,(IY+1) ; GET THE PIO TYPE DETECTED + CP PIO_PORT ; SET FLAGS + + PUSH AF ;D + LD A,'t' ;D + CALL COUT ;D + POP AF ;D + CALL PRTHEXBYTE ;D TYPE + CALL PC_SPACE ;D + +; JR Z,BADINIT + +; PUSH BC ; SAVE LOOP CONTROL +; LD BC,PIO_FNTBL ; BC := FUNCTION TABLE ADDRESS +; DEC A +; JR Z,TYPFND ; SKIP IT IF NOTHING FOUND +; LD BC,PPI_FNTBL ; BC := FUNCTION TABLE ADDRESS +; DEC A +; JR Z,TYPFND ; ADD ENTRY IF PIO FOUND, BC:DE +; LD BC,PRT_FNTBL +; DEC A +; JR Z,TYPFND +; POP BC +; JR BADINIT + + PUSH HL + LD DE,-1 ; INITIALIZE THIS DEVICE WITH + CALL PIO_INITDEV ; DEFAULT VALUES + POP HL + +; JR NZ,SKPINIT + + ; AT THIS POINT WE KNOW WE + ; HAVE A VALID DEVICE SO ADD IT + + LD A,8 ; CALCULATE THE FUNCTION TABLE + CALL ADDHLA ; POSITION WHICH FOLLOWS THE + PUSH HL ; CONFIGURATION TABLE OF EACH + POP BC ; DEVICE + +TYPFND: PUSH AF ;D + LD A,'f' ;D + CALL COUT ;D + POP AF ;D + PUSH BC ;D + CALL PRTHEXWORD ;D FUNCTION TABLE + POP BC ;D + CALL NEWLINE ;D + + PUSH IY ; ADD ENTRY IF PIO FOUND, BC:DE + POP DE ; BC: DRIVER FUNCTION TABLE + CALL CIO_ADDENT ; DE: ADDRESS OF UNIT INSTANCE DATA + +BADINIT:POP BC ; RESTORE LOOP CONTROL + + INC C ; NEXT PHYSICAL UNIT +SKPINIT:DJNZ PIO_PREINIT0 ; LOOP UNTIL DONE + + PUSH AF ;D + PRTS("INTS=$") ;D + LD A,(INT_ALLOC) ;D + CALL PRTHEXBYTE ;D + POP AF ;D + PUSH DE ;D + LD DE,CIO_TBL-3 ;D + CALL DUMP_BUFFER ;D + POP DE ;D + XOR A ; SIGNAL SUCCESS + RET ; AND RETURN +; +; INDEX INTO THE CONFIG TABLE +; ON ENTRY C = UNIT NUMBER +; ON EXIT IY = CONFIG DATA POINTER +; ON EXIT DE = CONFIG TABLE START +; +; EACH CONFIG TABLE IS 24 BYTES LONG +; +CFG_SIZ .EQU 24 +; +IDXCFG: LD A,C + RLCA ; X 2 + RLCA ; X 4 + RLCA ; X 8 + LD H,0 + LD L,A ; HL = X 8 + PUSH HL + ADD HL,HL ; HL = X 16 + POP DE + ADD HL,DE ; HL = X 24 + LD DE,PIO_CFG + ADD HL,DE + PUSH HL ; COPY CFG DATA PTR + POP IY ; ... TO IY + RET + +; PIO_INITDEV - INITIALIZE DEVICE +; +; IF DE = FFFF THEN THE SETUP PARAMETER WORD WILL BE READ FROM THE DEVICE CONFIGURATION +; TABLE POINTED TO BY IY AND THE PIO PORT WILL BE PROGRAMMED BASED ON THAT CONFIGURATION. +; +; OTHERWISE THE PIO PORT WILL BE PROGRAMMED BY THE SETUP PARAMETER WORD IN DE AND THIS +; WILL BE SAVED IN THE DEVICE CONFIGURATION TABLE POINTED TO BY IY. +; +; ALL OTHER CONFIGURATION OF THE DEVICE CONFIGURATION TABLE IS DONE UPSTEAM BY PIO_PREINIT + +PIO_INITDEV: + ; TEST FOR -1 (FFFF) WHICH MEANS USE CURRENT CONFIG (JUST REINIT) + LD A,D ; TEST DE FOR + AND E ; ... VALUE OF -1 + INC A ; ... SO Z SET IF -1 + JR NZ,PIO_INITDEV1 ; IF DE == -1, REINIT CURRENT CONFIG +PIO_INITDEV0: + ; LOAD EXISTING CONFIG (DCW) TO REINIT + LD E,(IY+4) ; LOW BYTE + LD D,(IY+5) ; HIGH BYTE +; +PIO_INITDEV1: ; WHICH DEVICE TYPE? + LD A,(IY+1) + CP PIO_ZPIO + JR Z,SETPIO0 + CP PIO_8255 + JP Z,SET_8255 + CP PIO_PORT + JP Z,SET_PORT +BAD_SET:OR $FF ; UNKNOWN DEVICE + RET + +SETPIO0:LD A,E ; GET MODE + AND 11000000B ; BITS (B7B6) + CP 10000000B ; IS IT BIDIR? + JR NZ,SETPIO1 + LD A,(IY+2) ; GET CHANNEL + OR A + JR NZ,BAD_SET ; CAN'T DO ON CH1 + + ; VALIDATE INTERRUPT REQUEST + ; GRANT INTERRUPT IF THERE IS A FREE INTERRUPT + ; GRANT INTERRUPT IF AN INTERRUPT IS ALREADY ALLOCATED TO THIS UNIT + +SETPIO1:PUSH AF ;D + LD A,'[' ;D + CALL COUT ;D + LD A,(IY) ;D + CALL PRTHEXBYTE ;D + LD A,']' ;D + CALL COUT ;D + POP AF ;D + + BIT 2,E ; SKIP IF WE ARE NOT REQUESTING + JP Z,SETPIO2 ; AN INTERRUPT + + PRTS("[INTREQ]$") ;D + +; LD A,(IY+4) ; GET CURRENT INTERRUPT SETTING +; BIT 2,A ; SKIP IF IT IS ALREADY +; JP NZ,SETPIO2 ; ALLOCATED TO THIS UNIT + + LD A,(INT_ALLOC) ; WE NEED TO ALLOCATE AN + CP INT_ALLOW ; INTERRUPT. DO WE HAVE + JR NC,BAD_SET ; ONE FREE? + + PRTS("[ALLOCINT]$") ;D + + ; WHICH INTERRUPT IS FREE ? + ; SCAN THROUGH THE CFG TABLES + ; AND FIND A FREE ONE + + PUSH AF ; NESTED LOOP + LD DE,CFG_SIZ ; OUTSIDE LOOP IS INTERRUPT + LD B,INT_ALLOW ; INSIDE LOOP IS DEVICE +SETPIOP: LD C,B + DEC C + PUSH BC + LD B,PIO_CNT + LD HL,PIO_CFG+4 +SETPIOX: LD A,(HL) + BIT 2,A ; JUMP TO NEXT DEVICE + JR Z,SETPIOY ; IF NO INTERRUPT ON + AND 00000011B ; THIS DEVICE + + CP C ; IF WE MATCH AN INTERRUPT HERE THEN IT IS NOT FREE. + JR NZ,SETPIOY ; SO EXIT INSIDE LOOP AND TRY NEXT INTERRUPT + + XOR A ; WE MATCH INT 0 - IF WE ARE CHECKING FOR IT THEN + OR C ; WE REGARD IS AS FREE. + JR NZ,SETPIOZ + +SETPIOY: ADD HL,DE + DJNZ SETPIOX + + JR SETPIOQ ; WE GET HERE IF THE CURRENT INTERRUPT + ; WAS NOT MATCHED SO IT IS FREE +SETPIOZ: POP BC + DJNZ SETPIOP + POP AF + + PRTS("[NONEFREE]$") + RET + +SETPIOQ:PUSH AF ; AVAILABLE INTERRUPT IS IN C + PRTS("[FREE]=$") + LD A,C + CALL PRTHEXBYTE + POP AF + + POP AF + POP AF + +SETPIOR:LD HL,INT_ALLOC ; INCREASE THE COUNT + INC (HL) ; OF USED INTERRUPTS + LD A,(HL) + +; LD A,(IY) ; IS THIS UNIT +; INC A ; UNITIALIZED? +; JR Z,SETPIO6 + + LD A,(IY+4) ; IT IS UNITIALIZED SO + OR C ; SAVE THE ALLOCATES + LD (IY+4),A ; INTERRUPT +; +; FOR THIS DEVICE AND INTERRUPT, UPDATE THE CONFIG TABLE FOR THIS DEVICE. +; PIO_IN, PIO_OUT, PIO_IST, PIO_OST ENTRIES NEED TO BE REDIRECTED. +; INTERRUPT VECTOR NEEDS TO BE UPDATED +; + LD A,(IY+0) + LD HL,0 + ; SETUP PIO INTERRUPT VECTOR IN IVT + LD HL,HBX_IV09+1 + +; CALL SPK_BEEP +; +SETPIO6:RET + + ; EXIT WITH FREE INTERRUPT IN C + + LD A,C + LD (INT_ALLOC),A + + LD A,E + AND 11000000B + OR 00000100B + OR C + LD E,A + LD (IY+5),A +; + ; TODO: DEALLOCATE AN INTERRUPT +; +; LD A,(INT_ALLOC) +; DEC A +; LD (INT_ALLOC),A +; +SETPIO2: + +; DE CONTAINS THE MODE IF INTERRUPT ROUTINE SKIPPED + + PRTS("[NOINTREQ]$") ;D + +; LD A,(IY+4) + LD A,E ; GET MODE AND CREATE COMMAND + AND 11000000B ; $B0 + OR 00001111B ; $0F + + LD C,(IY+3) ; GET DATA PORT + INC C ; POINT TO CMD + INC C ; PORT + OUT (C),A ; SET MODE + CP (M_BitCtrl | $0F) ; IF MODE 3 + JR NZ,SETPIO3 + LD A,(IY+5) ; SET I/O DIRECTION + OUT (C),A ; FOR MODE 3 + +SETPIO3:; INTERUPT HANDLING + + JP SETPIO4 + + ; SETUP THE INTERRUPT VECTOR + + LD A,E + AND 00000011B +; DEC A ; INDEX INTO THE + ADD A,A ; THE VECTOR TABLE + ADD A,A ; + LD C,A + LD B,0 + LD HL,HBX_IV09+1 + ADD HL,BC ; GET THE ADDRESS OF + PUSH DE + LD D,(HL) ; THAT INTERRUPT + INC HL ; HANDLER + LD E,(HL) + LD HL,0 ;HBX_IVT+IVT_PIO0 ; POPULATE THE + LD A,L ; GET LOW BYTE OF IVT ADDRESS + ADD HL,BC ; INTERRUPT TABLE + LD (HL),D ; WITH THE INTERRUPT + INC HL ; HANDLER ADDRESS FOR + LD (HL),E ; THIS UNIT + POP DE + LD HL,INT_ALLOC + LD C,(HL) + LD B,0 + LD HL,PRTTAB-1 ; SAVE THE DATA + ADD HL,BC ; PORT FOR EACH INTERRUPT + LD C,(IY+3) + LD (HL),C + + INC C ; POINT TO CMD PORT + INC C + DI ; SET THE VECTOR ADDRESS + OUT (C),A + +; LD A,10000011B ; ENABLE INTERRUPTS ON + OUT (C),A ; THIS UNIT + EI +; JR GUD_SET +; +SETPIO4:LD A,00000111B ; $07 + OUT (C),A ; NO INTERRUPTS +; +; SUCCESSFULL SO SAVE DEVICE CONFIGURATION WORD (DCW) +; +GUD_SET:LD (IY+4),E ; LOW BYTE + LD (IY+5),D ; HIGH BYTE +; +; UPDATE THE DEVICE TABLE WITH THE ADDRESSES FOR THE CORRECT ROUTINE. +; + LD A,E + AND 00000111B + LD HL,INTMATRIX ; POINT TO EITHER THE INTERRUPT + JR NZ, USEIM + LD HL,POLMATRIX ; MATRIX OR THE POLLED MATRIX +USEIM: PUSH HL + + PUSH IY ; CALCULATE THE DESTINATION + POP HL ; ADDRESS IN THE PIO_CFG TABLE + LD BC,8 ; FOR THE FOUR ADDESSES TO BE + ADD HL,BC ; COPIED TO + +; LD B,0 ; 00000000 CALCULATE THE SOURCE ADDRESS + LD C,E ; XX?????? FROM THE MATRIX. EACH ENTRY + SRL C ; 0XX????? IN THE MATRIX IS 8 BYTES SO + SRL C ; 00XX???? SOURCE = MATRIX BASE + (8 * MODE) + SRL C ; 000XX??? + POP DE ; LOAD THE MATRIX BASE +; LD DE,POLMATRIX + EX DE,HL + ADD HL,BC ; HL = SOURCE + + LD C,8 ; COPY 8 BYTES + LDIR + +; PUSH IY +; POP DE +; CALL DUMP_BUFFER + + XOR A + RET + +PRTTAB: .DB 0 + .DB 0 + .DB 0 + .DB 0 +; +;----------------------------------------------------------------------------- +; +; INPUT INTERRUPT VECTOR MACRO AND DEFINITION FOR FOUR PORTS +; +#DEFINE PIOMIVT(PIOIN,PIOIST,PIOPRT) \ +#DEFCONT ;\ +#DEFCONT ; RETURN WITH ERROR IF THERE IS \ +#DEFCONT ; ALREADY A CHARACTER IN BUFFER \ +#DEFCONT ;\ +#DEFCONT ; OTHERWISE CHANGE THE STATUS TO \ +#DEFCONT ; SHOW THERE IS ONE CHARACTER IN \ +#DEFCONT ; THE BUFFER AND READ IT IN AND \ +#DEFCONT ; AND STORE IT.RETURN GOOD STATUS.\ +#DEFCONT ;\ +#DEFCONT \ LD A,(_CIST) +#DEFCONT \ OR A +#DEFCONT \ JR NZ,_OVFL +#DEFCONT \ LD A,(PIOPRT) +#DEFCONT \ LD C,A +#DEFCONT \ LD A,1 +#DEFCONT \ LD (_CIST),A +#DEFCONT \ IN A,(C) +#DEFCONT \ LD (_CICH),A +#DEFCONT \ OR $FF +#DEFCONT \ RET +#DEFCONT \_OVFL:XOR A +#DEFCONT \ RET +#DEFCONT ;\ +#DEFCONT ;\ +#DEFCONT ;\ +#DEFCONT ;\ +#DEFCONT ;\ +#DEFCONT ;\ +#DEFCONT \PIOIN:CALL PIOIST +#DEFCONT \ JR Z,PIOIN +#DEFCONT \ LD A,(_CICH) +#DEFCONT \ LD E,A +#DEFCONT \ XOR A +#DEFCONT \ LD (_CIST),A +#DEFCONT \ RET +#DEFCONT ;\ +#DEFCONT ; If THERE A CHARACTER \ +#DEFCONT ; AVAILABLE? RETURN NUMBER \ +#DEFCONT ; IN A - 0 OR 1 \ +#DEFCONT ;\ +#DEFCONT \PIOIST:LD A,(_CIST) +#DEFCONT \ AND 00000001B +#DEFCONT \ RET +#DEFCONT ;\ +#DEFCONT ; CIST : 01 = CHARACTER READY ELSE NOT READY \ +#DEFCONT ; CISH : CHARACTER STORED BY INTERRUPT \ +#DEFCONT ;\ +#DEFCONT \_CIST .DB 00 +#DEFCONT \_CICH .DB 00 +; +PIOIVT0:.MODULE PIOIVT0 +PIOMIVT(PIO0IN,PI0_IST,PRTTAB+0) +PIOIVT1:.MODULE PIOIVT1 +PIOMIVT(PIO1IN,PI1_IST,PRTTAB+1) +PIOIVT2:.MODULE PIOIVT2 +PIOMIVT(PIO2IN,PI2_IST,PRTTAB+2) +PIOIVT3:.MODULE PIOIVT3 +PIOMIVT(PIO3IN,PI3_IST,PRTTAB+3) +; +;----------------------------------------------------------------------------- +; +; OUTPUT INTERRUPT VECTOR MACRO AND DEFINITION FOR FOUR PORTS +; +; AN INTERRUPT IS GENERATED WHEN THE RECEIVING DEVICE CAN ACCEPT A CHARACTER +; +#DEFINE PIOMOVT(PIOOUT,PIOOST,PIOPRT) \ +#DEFCONT ;\ +#DEFCONT ; RETURN IF WE ARE WAITING FOR A \ +#DEFCONT ; CHARACTER (COST = 00) \ +#DEFCONT ;\ +#DEFCONT ; IF ZERO CHARACTERS READY +#DEFCONT ; (COST = 01) CHANGE STATUS TO \ +#DEFCONT ; WAITING FOR CHARACTER (COST 00) \ +#DEFCONT ;\ +#DEFCONT ; IF A CHARACTER IS READY THEN \ +#DEFCONT ; OUTPUT AND CHANGE STATUS TO \ +#DEFCONT ; ZERO CHARACTERS READY \ +#DEFCONT ;\ +#DEFCONT \ LD A,(_COST) +#DEFCONT \ DEC A +#DEFCONT \ RET M +#DEFCONT \ JR Z,_WFC +#DEFCONT \ LD A,(_COCH) +#DEFCONT \ LD E,A +#DEFCONT \_ONOW:LD A,(PIOPRT) +#DEFCONT \ LD C,A +#DEFCONT \ OUT (C),E +#DEFCONT \ LD A,1 +#DEFCONT \_WFC: LD (_COST),A +#DEFCONT \ RET +#DEFCONT ;\ +#DEFCONT ; WAIT FOR SPACE FOR THE CHARACTER\ +#DEFCONT ; IF WE ARE WAITING FOR A \ +#DEFCONT ; CHARACTRE THEN OUTPUT IT NOW \ +#DEFCONT ; OTHERWISE STORE IT UNTIL THE \ +#DEFCONT ; INTERRUPT CALLS FOR IT \ +#DEFCONT ;\ +#DEFCONT \PIOOUT:LD A,(_COST) +#DEFCONT \ CP 2 +#DEFCONT \ JR C,_ONOW +#DEFCONT \ LD A,E +#DEFCONT \ LD (_COCH),A +#DEFCONT \ LD A,2 +#DEFCONT \ LD (_COST),A +#DEFCONT \ JR PIOOUT +#DEFCONT ;\ +#DEFCONT ; RETURN WITH NUMBER OF \ +#DEFCONT ; CHARACTERS AVAILABLE 0 or 1 \ +#DEFCONT ;\ +#DEFCONT \PIOOST:LD A,(_COST) +#DEFCONT \ DEC A +#DEFCONT \ DEC A +#DEFCONT \ RET Z +#DEFCONT \ LD A,1 +#DEFCONT \ RET +#DEFCONT ;\ +#DEFCONT ; COST : 00 WAITING FOR CHARACTER\ +#DEFCONT ; 01 ZERO CHARACTERS READY\ +#DEFCONT ; 02 ONE CHARACTER READY \ +#DEFCONT ; COCH : CHARACTER TO OUTPUT \ +#DEFCONT ;\ +#DEFCONT \_COST .DB 01 +#DEFCONT \_COCH .DB 00 +; +PIOOVT0:.MODULE PIOOVT0 +PIOMOVT(PIO0OUT,PI0_OST,PRTTAB+0) +PIOOVT1:.MODULE PIOOVT1 +PIOMOVT(PIO1OUT,PI1_OST,PRTTAB+1) +PIOOVT2:.MODULE PIOOVT2 +PIOMOVT(PIO2OUT,PI2_OST,PRTTAB+2) +PIOOVT3:.MODULE PIOOVT3 +PIOMOVT(PIO3OUT,PI3_OST,PRTTAB+3) +; +;----------------------------------------------------------------------------- +; +; NON INTERRUPT OUTPUT ROUTINE - SHARED +; +; INPUT WILL ALWAYS RETURN ERROR, CHARACTER RETURNED IS UNDEFINED. +; OUTPUT WILL ALWAYS RETURN SUCCESS +; INPUT-STATUS WILL ALWAYS RETURN 0 CHARACTERS IN BUFFER. +; OUTPUT-STATUS WILL ALWAYS RETURN 1 CHARACTER SPACE IN BUFFER. + +PIOSHO_IN: + LD A,1 + RET +; +PIOSHO_OUT: + LD C,(IY+3) + OUT (C),E + XOR A + RET +; +PIOSHO_IST: XOR A + RET +; +PIOSH_OST: + LD A,1 + RET +; +;----------------------------------------------------------------------------- +; +; NON INTERRUPT INPUT ROUTINE - SHARED +; +; INPUT WILL ALWAYS A CHARACTER AND SUCCESS. +; OUTPUT WILL ALWAYS RETURN FAILURE +; INPUT STATUS WILL ALWAYS RETURN 1 CHARACTER IN BUFFER. +;OUTPUT-STATUS WILL ALWAYS RETURN 0 CHARACTER SPACE IN BUFFER. +; +PIOSHI_IN: + LD C,(IY+3) + IN A,(C) + LD E,A + XOR A + RET +; +PIOSHI_OUT: + LD A,1 + RET +; +PIOSH_IST: + LD A,1 + RET +; +PIOSHI_OST: + XOR A + RET +; +;----------------------------------------------------------------------------- +; +; ON ENTRY IY POINTS TO THE DEVICE RECORD. GET AND RETURN THE CONFIGURATION WORD IN DE +; +PIO_QUERY: +PPI_QUERY: + LD E,(IY+4) ; FIRST CONFIG BYTE TO E + LD D,(IY+5) ; SECOND CONFIG BYTE TO D + XOR A ; SIGNAL SUCCESS + RET +; +;----------------------------------------------------------------------------- +; +; ON ENTRY IY POINTS TO THE DEVICE RECORD. FOR CHARACTER DEVICES BIT 6 OF ATTRIBUTE +; INDICATES PARALLEL PORT IF 1 SO WE SET IT. COMMON TO ALL PORTS +; +PIO_DEVICE: +PPI_DEVICE: + LD D,CIODEV_PIO ; D := DEVICE TYPE + LD E,(IY) ; E := PHYSICAL UNIT + LD C,$40 ; C := ATTRIBUTE + LD H,0 ; H := 0, DRIVER HAS NO MODES + LD L,(IY+3) ; L := BASE I/O ADDRESS + XOR A ; SIGNAL SUCCESS + RET +; +INTMATRIX: + .DW PIO0IN, PIO0OUT, PI0_IST, PI0_OST + .DW PIO1IN, PIO1OUT, PI1_IST, PI1_OST + .DW PIO2IN, PIO2OUT, PI2_IST, PI2_OST + .DW PIO3IN, PIO3OUT, PI3_IST, PI3_OST +POLMATRIX: + .DW PIOSHO_IN, PIOSHO_OUT, PIOSHO_IST, PIOSH_OST ; OUTPUT + .DW PIOSHI_IN, PIOSHI_OUT, PIOSH_IST, PIOSHI_OST ; INPUT + .DW 0,0,0,0 ; BIDIR + .DW 0,0,0,0 ; BIT MODE + +SET_8255: + RET +; +SET_BYE: + XOR A ; SIGNAL SUCCESS + RET +; +; ------------------------------------ +; i8255 FUNCTION TABLE ROUTINES +;------------------------------------- + +PPI_IN: + XOR A ; SIGNAL SUCCESS + RET +; +PPI_OUT: + XOR A ; SIGNAL SUCCESS + RET +; +PPI_IST: + RET +; +PPI_OST: + RET +; +; PIO_INITDEV - Configure device. +; If DE = FFFF then extract the configuration information from the table of devices and program the device using those settings. +; Otherwise use the configuration information in DE to program those settings and save them in the device table + +PPI_INITDEV: + XOR A ; SIGNAL SUCCESS + RET +PPI_INT:OR $FF ; NZ SET TO INDICATE INT HANDLED + RET +; +PIO_PRTCFG: + ; ANNOUNCE PORT + CALL NEWLINE ; FORMATTING + PRTS("PIO$") ; FORMATTING + LD A,(IY) ; DEVICE NUM + CALL PRTDECB ; PRINT DEVICE NUM + PRTS(": IO=0x$") ; FORMATTING + LD A,(IY+3) ; GET BASE PORT + CALL PRTHEXBYTE ; PRINT BASE PORT +; + ; PRINT THE PIO TYPE + CALL PC_SPACE ; FORMATTING + LD A,(IY+1) ; GET PIO TYPE BYTE + LD DE,PIO_TYPE_STR ; POINT HL TO TYPE MAP TABLE + CALL PRTIDXDEA + + ; ALL DONE IF NO PIO WAS DETECTED + LD A,(IY+1) ; GET PIO TYPE BYTE + OR A ; SET FLAGS + RET Z ; IF ZERO, NOT PRESENT +; + PRTS(" MODE=$") ; FORMATTING + LD E,(IY+4) ; LOAD CONFIG + LD D,(IY+5) ; ... WORD TO DE + CALL PS_PRTPC0 ; PRINT CONFIG +; + LD A,(IY+4) ; PRINT + BIT 2,A ; ALLOCATED + JR Z,NOINT ; INTERRUPT + PRTS("/i$") + LD A,(IY+4) + AND 00000011B + CALL PRTDECB +NOINT: XOR A + RET +; +; WORKING VARIABLES +; +PIO_DEV .DB 0 ; DEVICE NUM USED DURING INIT +; +; DESCRIPTION OF DIFFERENT PORT TYPES +; +PIO_TYPE_STR: + .TEXT "$" ; IDX 0 + .TEXT "Zilog PIO$" ; IDX 1 + .TEXT "i8255 PPI$" ; IDX 2 + .TEXT "IO Port$" ; IDX 3 +; +; Z80 PIO PORT TABLE - EACH ENTRY IS FOR 1 CHIP I.E. TWO PORTS +; +; 32 BYTE DATA STRUCTURE FOR EACH PORT +; +; .DB 0 ; IY+0 CIO DEVICE NUMBER (SET DURING PRE-INIT, THEN FIXED) +; .DB 0 ; IY+1 PIO TYPE (SET AT ASSEMBLY, FIXED) +; .DB 0 ; IY+2 PIO CHANNEL (SET AT ASSEMBLY, FIXED) +; .DB PIOBASE+2 ; IY+3 BASE DATA PORT (SET AT ASSEMBLY, FIXED) +; .DB 0 ; IY+4 SPW - MODE 3 I/O DIRECTION BYTE (SET AT ASSEMBLE, SET WITH INIT) +; .DB 0 ; IY+5 SPW - MODE, INTERRUPT (SET AT ASSEMBLY, SET WITH INIT) +; .DW 0 ; IY+6/7 FUNCTION TABLE (SET AT ASSEMBLY, SET DURING PRE-INIT AND AT INIT) +; .DW PIO_IN ; IY+8 ADDR FOR DEVICE INPUT (SET WITH INIT) +; .DW PIO_OUT ; IY+10 ADDR FOR DEVICE OUTPUT (SET WITH INIT) +; .DW PIO_IST ; IY+12 ADDR FOR DEVICE INPUT STATUS (SET WITH INIT) +; .DW PIO_OST ; IY+14 ADDR FOR DEVICE OUTPUT STATUS (SET WITH INIT) +; .DW PIO_INITDEV ; IY+16 ADDR FOR INITIALIZE DEVICE ROUTINE (SET AT ASSEMBLY, FIXED) +; .DW PIO_QUERY ; IY+18 ADDR FOR QUERY DEVICE RECORD ROUTINE (SET AT ASSEMBLY, FIXED) +; .DW PIO_DEVICE ; IY+20 ADDR FOR DEVICE TYPE ROUTINE (SET AT ASSEMBLY, FIXED) +; .FILL 10 +; +; SETUP PARAMETER WORD: +; +; +-------------------------------+ +-------+-----------+---+-------+ +; | BIT CONTROL | | MODE | | A | INT | +; +-------------------------------+ --------------------+-----------+ +; F E D C B A 9 8 7 6 5 4 3 2 1 0 +; -- MSB (D REGISTER) -- -- LSB (E REGISTER) -- +; +; +; MSB = BIT CONTROL MAP USE IN MODE 3 +; +; MODE B7 B6 = 00 Mode 0 Output +; 01 Mode 1 Input +; 10 Mode 2 Bidir +; 11 Mode 3 Bit Mode +; +; INTERRUPT ALLOCATED B2 = 0 NOT ALLOCATED +; = 1 IS ALLOCATED +; +; WHICH IVT IS ALLOCATES B1 B0 00 IVT_PIO0 +; 01 IVT_PIO1 +; 10 IVT_PIO2 +; 11 IVT_PIO3 +; +#DEFINE DEFPIO(MPIOBASE,MPIOCH0,MPIOCH1,MPIOCH0X,MPIOCH1X,MPIOIN0,MPIOIN1) \ +#DEFCONT \ .DB 0 +#DEFCONT \ .DB PIO_ZPIO +#DEFCONT \ .DB 0 +#DEFCONT \ .DB MPIOBASE +#DEFCONT \ .DB (MPIOCH0|MPIOIN0) +#DEFCONT \ .DB MPIOCH0X +#DEFCONT \ .DW 0 +#DEFCONT \ .DW 0,0,0,0, PIO_INITDEV,PIO_QUERY,PIO_DEVICE +#DEFCONT \ .FILL 2 +#DEFCONT \ .DB 0 +#DEFCONT \ .DB PIO_ZPIO +#DEFCONT \ .DB 1 +#DEFCONT \ .DB MPIOBASE+1 +#DEFCONT \ .DB (MPIOCH1|MPIOIN1) +#DEFCONT \ .DB MPIOCH1X +#DEFCONT \ .DW 0 +#DEFCONT \ .DW 0,0,0,0, PIO_INITDEV,PIO_QUERY,PIO_DEVICE +#DEFCONT \ .FILL 2 +; +; i8255 PORT TABLE - EACH ENTRY IS FOR 1 CHIP I.E. THREE PORTS +; +#DEFINE DEFPPI(MPPIBASE,MPPICH1,MPPICH2,MPPICH3,MPPICH1X,MPPICH2X,MPPICH3X) \ +#DEFCONT \ .DB 0 +#DEFCONT \ .DB PIO_8255 +#DEFCONT \ .DB 0 +#DEFCONT \ .DB MPPIBASE +#DEFCONT \ .DB (MPPICH1|00001000B) +#DEFCONT \ .DB MPPICH1X +#DEFCONT \ .DW 0 +#DEFCONT \ .DW PPI_IN,PPI_OUT,PPI_IST,PPI_OST,PPI_INITDEV,PPI_QUERY,PPI_DEVICE +#DEFCONT \ .FILL 2 +#DEFCONT \ .DB 0 +#DEFCONT \ .DB PIO_8255 +#DEFCONT \ .DB 1 +#DEFCONT \ .DB MPPIBASE+2 +#DEFCONT \ .DB (MPPICH2|00010000B) +#DEFCONT \ .DB MPPICH2X +#DEFCONT \ .DW 0 +#DEFCONT \ .DW PPI_IN,PPI_OUT,PPI_IST,PPI_OST,PPI_INITDEV,PPI_QUERY,PPI_DEVICE +#DEFCONT \ .FILL 2 +#DEFCONT \ .DB 0 +#DEFCONT \ .DB PIO_8255 +#DEFCONT \ .DB 2 +#DEFCONT \ .DB MPPIBASE+4 +#DEFCONT \ .DB (MPPICH3|00100000B) +#DEFCONT \ .DB MPPICH3X +#DEFCONT \ .DW 0 +#DEFCONT \ .DW PPI_IN,PPI_OUT,PPI_IST,PPI_OST,PPI_INITDEV,PPI_QUERY,PPI_DEVICE +#DEFCONT \ .FILL 2 +; +; HERE WE ACTUALLY DEFINE THE HARDWARE THAT THE HBIOS CAN ACCESS +; THE INIT ROUTINES READ AND SET THE INITIAL MODES FROM THIS INFO +; +PIO_CFG: +; +#IF PIO_4P +DEFPIO(PIO4BASE+0,M_Output,M_Input,M_BitAllOut,M_BitAllOut,INT_N,INT_N) +DEFPIO(PIO4BASE+4,M_Input,M_Input,M_BitAllOut,M_BitAllOut,INT_N,INT_N) +DEFPIO(PIO4BASE+8,M_Output,M_Output,M_BitAllOut,M_BitAllOut,INT_N,INT_N) +DEFPIO(PIO4BASE+12,M_Output,M_Output,M_BitAllOut,M_Output,INT_N,INT_N) +#ENDIF +#IF PIO_ZP +DEFPIO(PIOZBASE+0,M_Input,M_Input,M_BitAllOut,M_BitAllOut,INT_N,INT_N) +DEFPIO(PIOZBASE+4,M_Output,M_Output,M_BitAllOut,M_BitAllOut,INT_N,INT_N) +#ENDIF +; PIO_SBC & (PLATFORM == PLT_SBC) & (PPIDEMODE != PPIDEMODE_SBC)) + +#IF PIO_SBC +DEFPPI(PIOSBASE,M_Output,M_Output,M_Output,M_BitAllOut,M_BitAllOut,M_BitAllOut) +#ENDIF +; +PIO_CNT .EQU ($ - PIO_CFG) / CFG_SIZ +; +;------------------------------------------------------------------- +; WHEN WE GET HERE IY POINTS TO THE PIO_CFG TABLE WE ARE WORKING ON. +; C IS THE UNIT NUMBER +;------------------------------------------------------------------- +; +;PIO_INITUNIT: +; LD A,C ; SET THE UNIT NUMBER +; LD (IY),A +; +; LD DE,-1 ; LEAVE CONFIG ALONE +; CALL PIO_INITDEV ; IMPLEMENT IT AND RETURN +; XOR A ; SIGNAL SUCCESS +; RET ; AND RETURN +; +PIO_INIT: +; CALL SPK_BEEP + LD B,PIO_CNT ; COUNT OF POSSIBLE PIO UNITS + LD C,0 ; INDEX INTO PIO CONFIG TABLE +PIO_INIT1: + PUSH BC ; SAVE LOOP CONTROL + +; LD A,C ; PHYSICAL UNIT TO A +; RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (32 BYTES) +; RLCA ; ... +; RLCA ; ... TO GET OFFSET INTO CFG TABLE +; RLCA +;; RLCA +; LD HL,PIO_CFG ; POINT TO START OF CFG TABLE +; PUSH AF +; CALL ADDHLA ; HL := ENTRY ADDRESS +; POP AF +; CALL ADDHLA ; HL := ENTRY ADDRESS +; PUSH HL ; COPY CFG DATA PTR +; POP IY ; ... TO IY +; POP IY ; ... TO IY + + CALL IDXCFG + + LD A,(IY+1) ; GET PIO TYPE + OR A ; SET FLAGS + CALL NZ,PIO_PRTCFG ; PRINT IF NOT ZERO + +; PUSH DE +; LD DE,$FFFF ; INITIALIZE DEVICE/CHANNEL +; CALL PIO_INITDEV ; BASED ON DPW +; POP DE + + POP BC ; RESTORE LOOP CONTROL + INC C ; NEXT UNIT + DJNZ PIO_INIT1 ; LOOP TILL DONE +; + XOR A ; SIGNAL SUCCESS + RET ; DONE +; +SET_PORT: + ; DEVICE TYPE IS I/O PORT SO JUST WRITE $00 TO IT + LD C,(IY+3) + OUT (C),A + XOR A + RET diff --git a/Source/ver.inc b/Source/ver.inc index ea9cd84d..3b25aa3f 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,4 +2,4 @@ #DEFINE RMN 1 #DEFINE RUP 1 #DEFINE RTP 0 -#DEFINE BIOSVER "3.1.1-pre.159" +#DEFINE BIOSVER "3.1.1-pre.160" diff --git a/Source/ver.lib b/Source/ver.lib index 42a77a7b..364713e9 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 1 rup equ 1 rtp equ 0 biosver macro - db "3.1.1-pre.159" + db "3.1.1-pre.160" endm From f6285a8e6ab7613693f70281424e64130c63fcef Mon Sep 17 00:00:00 2001 From: Dan Werner Date: Sun, 20 Mar 2022 11:12:12 -0500 Subject: [PATCH 32/34] Nhyodyne Sound Support --- Source/Apps/Tune/tune.asm | 5 ++++- Source/HBIOS/ay38910.asm | 14 +++++++++++++- Source/HBIOS/cfg_dyno.asm | 4 ++-- Source/HBIOS/cfg_ezz80.asm | 4 ++-- Source/HBIOS/cfg_master.asm | 2 +- Source/HBIOS/cfg_mbc.asm | 4 ++-- Source/HBIOS/cfg_mk4.asm | 4 ++-- Source/HBIOS/cfg_n8.asm | 4 ++-- Source/HBIOS/cfg_rcz180.asm | 4 ++-- Source/HBIOS/cfg_rcz280.asm | 4 ++-- Source/HBIOS/cfg_rcz80.asm | 4 ++-- Source/HBIOS/cfg_sbc.asm | 4 ++-- Source/HBIOS/cfg_scz180.asm | 4 ++-- Source/HBIOS/cfg_zeta2.asm | 2 +- Source/HBIOS/std.asm | 1 + 15 files changed, 40 insertions(+), 24 deletions(-) diff --git a/Source/Apps/Tune/tune.asm b/Source/Apps/Tune/tune.asm index 513c21d4..4659f556 100644 --- a/Source/Apps/Tune/tune.asm +++ b/Source/Apps/Tune/tune.asm @@ -622,6 +622,9 @@ CFGTBL: ; PLT RSEL RDAT RIN Z180 ACR ; .DB $0B, $33, $32, $32, $FF, $FF ; RCZ280 W/ LINC SOUND MODULE .DW HWSTR_LINC +; + .DB 13, $A0, $A1, $A0, $FF, $A2 ; MBC + .DW HWSTR_MBC ; .DB $FF ; END OF TABLE MARKER ; @@ -674,6 +677,7 @@ HWSTR_RCEB .DB "RC2014 Sound Module (EB)",0 HWSTR_RCEB6 .DB "RC2014 Sound Module (EBv6)",0 HWSTR_RCMF .DB "RC2014 Sound Module (MF)",0 HWSTR_LINC .DB "Z50 LiNC Sound Module",0 +HWSTR_MBC .DB "NHYODYNE Sound Module",0 MSGUNSUP .db "MYM files not supported with HBIOS yet!\r\n", 0 @@ -2649,4 +2653,3 @@ data: ; ;=============================================================================== .END - diff --git a/Source/HBIOS/ay38910.asm b/Source/HBIOS/ay38910.asm index 3a196605..2dde8d29 100644 --- a/Source/HBIOS/ay38910.asm +++ b/Source/HBIOS/ay38910.asm @@ -48,6 +48,14 @@ AY_RDAT .EQU $32 AY_RIN .EQU $32 #ENDIF ; +#IF (AYMODE == AYMODE_MBC) +AY_RSEL .EQU $A0 +AY_RDAT .EQU $A1 +AY_RIN .EQU AY_RSEL +AY_ACR .EQU $A2 +AY_CLK .SET 3579545 ; MSX NTSC COLOUR BURST FREQ = 315/88 +#ENDIF +; ;====================================================================== ; ; REGISTERS @@ -128,6 +136,10 @@ AY38910_INIT: PRTS(" MODE=MSX$") #ENDIF ; +#IF (AYMODE == AYMODE_MBC) + PRTS(" MODE=MBC$") +#ENDIF +; #IF (AYMODE == AYMODE_LINC) PRTS(" MODE=LINC$") #ENDIF @@ -136,7 +148,7 @@ AY38910_INIT: LD A,AY_RSEL CALL PRTHEXBYTE ; -#IF ((AYMODE == AYMODE_SCG) | (AYMODE == AYMODE_N8)) +#IF ((AYMODE == AYMODE_SCG) | (AYMODE == AYMODE_N8) | (AYMODE == AYMODE_MBC)) LD A,$FF ; ACTIVATE DEVICE BIT 4 IS AY RESET CONTROL, BIT 3 IS ACTIVE LED OUT (AY_ACR),A ; SET INIT AUX CONTROL REG #ENDIF diff --git a/Source/HBIOS/cfg_dyno.asm b/Source/HBIOS/cfg_dyno.asm index 71983d85..7be37bcb 100644 --- a/Source/HBIOS/cfg_dyno.asm +++ b/Source/HBIOS/cfg_dyno.asm @@ -125,7 +125,7 @@ MDENABLE .EQU TRUE ; MD: ENABLE MEMORY (ROM/RAM) DISK DRIVER (MD.ASM) MDROM .EQU TRUE ; MD: ENABLE ROM DISK MDRAM .EQU TRUE ; MD: ENABLE RAM DISK MDTRACE .EQU 1 ; MD: TRACE LEVEL (0=NO,1=ERRORS,2=ALL) -MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM +MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM ; FDENABLE .EQU FALSE ; FD: ENABLE FLOPPY DISK DRIVER (FD.ASM) FDMODE .EQU FDMODE_DYNO ; FD: DRIVER MODE: FDMODE_[DIO|ZETA|ZETA2|DIDE|N8|DIO3|RCSMC|RCWDC|DYNO|EPFDC|MBC] @@ -194,7 +194,7 @@ SNMODE .EQU SNMODE_NONE ; DRIVER MODE: SNMODE_[NONE|RC2014|VGM] ; AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 -AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC] +AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC|MBC] ; SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; diff --git a/Source/HBIOS/cfg_ezz80.asm b/Source/HBIOS/cfg_ezz80.asm index 022236ca..59ee6c98 100644 --- a/Source/HBIOS/cfg_ezz80.asm +++ b/Source/HBIOS/cfg_ezz80.asm @@ -163,7 +163,7 @@ MDENABLE .EQU TRUE ; MD: ENABLE MEMORY (ROM/RAM) DISK DRIVER (MD.ASM) MDROM .EQU TRUE ; MD: ENABLE ROM DISK MDRAM .EQU TRUE ; MD: ENABLE RAM DISK MDTRACE .EQU 1 ; MD: TRACE LEVEL (0=NO,1=ERRORS,2=ALL) -MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM +MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM ; FDENABLE .EQU FALSE ; FD: ENABLE FLOPPY DISK DRIVER (FD.ASM) FDMODE .EQU FDMODE_RCWDC ; FD: DRIVER MODE: FDMODE_[DIO|ZETA|ZETA2|DIDE|N8|DIO3|RCSMC|RCWDC|DYNO|EPFDC|MBC] @@ -236,7 +236,7 @@ SNMODE .EQU SNMODE_NONE ; DRIVER MODE: SNMODE_[NONE|RC2014|VGM] ; AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 -AYMODE .EQU AYMODE_RCZ80 ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC] +AYMODE .EQU AYMODE_RCZ80 ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC|MBC] ; SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; diff --git a/Source/HBIOS/cfg_master.asm b/Source/HBIOS/cfg_master.asm index 8e17d028..42a39766 100644 --- a/Source/HBIOS/cfg_master.asm +++ b/Source/HBIOS/cfg_master.asm @@ -308,7 +308,7 @@ SNMODE .EQU SNMODE_NONE ; DRIVER MODE: SNMODE_[NONE|RC2014|VGM] ; AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 -AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC] +AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC|MBC] ; SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; diff --git a/Source/HBIOS/cfg_mbc.asm b/Source/HBIOS/cfg_mbc.asm index e17de8c3..a5cae23b 100644 --- a/Source/HBIOS/cfg_mbc.asm +++ b/Source/HBIOS/cfg_mbc.asm @@ -152,7 +152,7 @@ MDENABLE .EQU TRUE ; MD: ENABLE MEMORY (ROM/RAM) DISK DRIVER (MD.ASM) MDROM .EQU TRUE ; MD: ENABLE ROM DISK MDRAM .EQU TRUE ; MD: ENABLE RAM DISK MDTRACE .EQU 1 ; MD: TRACE LEVEL (0=NO,1=ERRORS,2=ALL) -MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM +MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM ; ; FDENABLE .EQU FALSE ; FD: ENABLE FLOPPY DISK DRIVER (FD.ASM) @@ -240,7 +240,7 @@ SNMODE .EQU SNMODE_NONE ; DRIVER MODE: SNMODE_[NONE|RC2014|VGM] ; AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 -AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC] +AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC|MBC] ; SPKENABLE .EQU TRUE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; diff --git a/Source/HBIOS/cfg_mk4.asm b/Source/HBIOS/cfg_mk4.asm index 14f9a8f2..2732bd39 100644 --- a/Source/HBIOS/cfg_mk4.asm +++ b/Source/HBIOS/cfg_mk4.asm @@ -151,7 +151,7 @@ MDENABLE .EQU TRUE ; MD: ENABLE MEMORY (ROM/RAM) DISK DRIVER (MD.ASM) MDROM .EQU TRUE ; MD: ENABLE ROM DISK MDRAM .EQU TRUE ; MD: ENABLE RAM DISK MDTRACE .EQU 1 ; MD: TRACE LEVEL (0=NO,1=ERRORS,2=ALL) -MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM +MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM ; FDENABLE .EQU FALSE ; FD: ENABLE FLOPPY DISK DRIVER (FD.ASM) FDMODE .EQU FDMODE_DIDE ; FD: DRIVER MODE: FDMODE_[DIO|ZETA|ZETA2|DIDE|N8|DIO3|RCSMC|RCWDC|DYNO|EPFDC|MBC] @@ -241,7 +241,7 @@ SNMODE .EQU SNMODE_NONE ; DRIVER MODE: SNMODE_[NONE|RC2014|VGM] ; AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 -AYMODE .EQU AYMODE_SCG ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC] +AYMODE .EQU AYMODE_SCG ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC|MBC] ; SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; diff --git a/Source/HBIOS/cfg_n8.asm b/Source/HBIOS/cfg_n8.asm index 070298a6..47dab164 100644 --- a/Source/HBIOS/cfg_n8.asm +++ b/Source/HBIOS/cfg_n8.asm @@ -153,7 +153,7 @@ MDENABLE .EQU TRUE ; MD: ENABLE MEMORY (ROM/RAM) DISK DRIVER (MD.ASM) MDROM .EQU TRUE ; MD: ENABLE ROM DISK MDRAM .EQU TRUE ; MD: ENABLE RAM DISK MDTRACE .EQU 1 ; MD: TRACE LEVEL (0=NO,1=ERRORS,2=ALL) -MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM +MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM ; FDENABLE .EQU TRUE ; FD: ENABLE FLOPPY DISK DRIVER (FD.ASM) FDMODE .EQU FDMODE_N8 ; FD: DRIVER MODE: FDMODE_[DIO|ZETA|ZETA2|DIDE|N8|DIO3|RCSMC|RCWDC|DYNO|EPFDC|MBC] @@ -239,7 +239,7 @@ SNMODE .EQU SNMODE_NONE ; DRIVER MODE: SNMODE_[NONE|RC2014|VGM] ; AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 -AYMODE .EQU AYMODE_N8 ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC] +AYMODE .EQU AYMODE_N8 ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC|MBC] ; SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; diff --git a/Source/HBIOS/cfg_rcz180.asm b/Source/HBIOS/cfg_rcz180.asm index d9306673..63000248 100644 --- a/Source/HBIOS/cfg_rcz180.asm +++ b/Source/HBIOS/cfg_rcz180.asm @@ -169,7 +169,7 @@ MDENABLE .EQU TRUE ; MD: ENABLE MEMORY (ROM/RAM) DISK DRIVER (MD.ASM) MDROM .EQU TRUE ; MD: ENABLE ROM DISK MDRAM .EQU TRUE ; MD: ENABLE RAM DISK MDTRACE .EQU 1 ; MD: TRACE LEVEL (0=NO,1=ERRORS,2=ALL) -MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM +MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM ; FDENABLE .EQU FALSE ; FD: ENABLE FLOPPY DISK DRIVER (FD.ASM) FDMODE .EQU FDMODE_RCWDC ; FD: DRIVER MODE: FDMODE_[DIO|ZETA|ZETA2|DIDE|N8|DIO3|RCSMC|RCWDC|DYNO|EPFDC|MBC] @@ -251,7 +251,7 @@ SNMODE .EQU SNMODE_NONE ; DRIVER MODE: SNMODE_[NONE|RC2014|VGM] ; AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 -AYMODE .EQU AYMODE_RCZ180 ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC] +AYMODE .EQU AYMODE_RCZ180 ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC|MBC] ; SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; diff --git a/Source/HBIOS/cfg_rcz280.asm b/Source/HBIOS/cfg_rcz280.asm index 65214adc..e79d56c7 100644 --- a/Source/HBIOS/cfg_rcz280.asm +++ b/Source/HBIOS/cfg_rcz280.asm @@ -185,7 +185,7 @@ MDENABLE .EQU TRUE ; MD: ENABLE MEMORY (ROM/RAM) DISK DRIVER (MD.ASM) MDROM .EQU TRUE ; MD: ENABLE ROM DISK MDRAM .EQU TRUE ; MD: ENABLE RAM DISK MDTRACE .EQU 1 ; MD: TRACE LEVEL (0=NO,1=ERRORS,2=ALL) -MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM +MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM ; FDENABLE .EQU FALSE ; FD: ENABLE FLOPPY DISK DRIVER (FD.ASM) FDMODE .EQU FDMODE_RCWDC ; FD: DRIVER MODE: FDMODE_[DIO|ZETA|ZETA2|DIDE|N8|DIO3|RCSMC|RCWDC|DYNO|EPFDC|MBC] @@ -267,7 +267,7 @@ SNMODE .EQU SNMODE_NONE ; DRIVER MODE: SNMODE_[NONE|RC2014|VGM] ; AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 -AYMODE .EQU AYMODE_RCZ80 ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC] +AYMODE .EQU AYMODE_RCZ80 ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC|MBC] ; SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; diff --git a/Source/HBIOS/cfg_rcz80.asm b/Source/HBIOS/cfg_rcz80.asm index 00e56501..8c4e8454 100644 --- a/Source/HBIOS/cfg_rcz80.asm +++ b/Source/HBIOS/cfg_rcz80.asm @@ -174,7 +174,7 @@ MDENABLE .EQU TRUE ; MD: ENABLE MEMORY (ROM/RAM) DISK DRIVER (MD.ASM) MDROM .EQU TRUE ; MD: ENABLE ROM DISK MDRAM .EQU TRUE ; MD: ENABLE RAM DISK MDTRACE .EQU 1 ; MD: TRACE LEVEL (0=NO,1=ERRORS,2=ALL) -MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM +MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM ; FDENABLE .EQU FALSE ; FD: ENABLE FLOPPY DISK DRIVER (FD.ASM) FDMODE .EQU FDMODE_RCWDC ; FD: DRIVER MODE: FDMODE_[DIO|ZETA|ZETA2|DIDE|N8|DIO3|RCSMC|RCWDC|DYNO|EPFDC|MBC] @@ -256,7 +256,7 @@ SNMODE .EQU SNMODE_RCZ80 ; DRIVER MODE: SNMODE_[NONE|RC2014|VGM] ; AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 -AYMODE .EQU AYMODE_RCZ80 ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC] +AYMODE .EQU AYMODE_RCZ80 ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC|MBC] ; SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; diff --git a/Source/HBIOS/cfg_sbc.asm b/Source/HBIOS/cfg_sbc.asm index f55d0b5d..2f7bedff 100644 --- a/Source/HBIOS/cfg_sbc.asm +++ b/Source/HBIOS/cfg_sbc.asm @@ -152,7 +152,7 @@ MDENABLE .EQU TRUE ; MD: ENABLE MEMORY (ROM/RAM) DISK DRIVER (MD.ASM) MDROM .EQU TRUE ; MD: ENABLE ROM DISK MDRAM .EQU TRUE ; MD: ENABLE RAM DISK MDTRACE .EQU 1 ; MD: TRACE LEVEL (0=NO,1=ERRORS,2=ALL) -MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM +MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM ; ; FDENABLE .EQU FALSE ; FD: ENABLE FLOPPY DISK DRIVER (FD.ASM) @@ -240,7 +240,7 @@ SNMODE .EQU SNMODE_VGM ; DRIVER MODE: SNMODE_[NONE|RC2014|VGM] ; AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 -AYMODE .EQU AYMODE_SCG ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC] +AYMODE .EQU AYMODE_SCG ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC|MBC] ; SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; diff --git a/Source/HBIOS/cfg_scz180.asm b/Source/HBIOS/cfg_scz180.asm index 3e4bdd4e..3fc39a3d 100644 --- a/Source/HBIOS/cfg_scz180.asm +++ b/Source/HBIOS/cfg_scz180.asm @@ -164,7 +164,7 @@ MDENABLE .EQU TRUE ; MD: ENABLE MEMORY (ROM/RAM) DISK DRIVER (MD.ASM) MDROM .EQU TRUE ; MD: ENABLE ROM DISK MDRAM .EQU TRUE ; MD: ENABLE RAM DISK MDTRACE .EQU 1 ; MD: TRACE LEVEL (0=NO,1=ERRORS,2=ALL) -MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM +MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM ; FDENABLE .EQU FALSE ; FD: ENABLE FLOPPY DISK DRIVER (FD.ASM) FDMODE .EQU FDMODE_RCWDC ; FD: DRIVER MODE: FDMODE_[DIO|ZETA|ZETA2|DIDE|N8|DIO3|RCSMC|RCWDC|DYNO|EPFDC|MBC] @@ -246,7 +246,7 @@ SNMODE .EQU SNMODE_NONE ; DRIVER MODE: SNMODE_[NONE|RC2014|VGM] ; AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 -AYMODE .EQU AYMODE_RCZ180 ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC] +AYMODE .EQU AYMODE_RCZ180 ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC|MBC] ; SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; diff --git a/Source/HBIOS/cfg_zeta2.asm b/Source/HBIOS/cfg_zeta2.asm index 42970e1b..da495739 100644 --- a/Source/HBIOS/cfg_zeta2.asm +++ b/Source/HBIOS/cfg_zeta2.asm @@ -135,7 +135,7 @@ MDENABLE .EQU TRUE ; MD: ENABLE MEMORY (ROM/RAM) DISK DRIVER (MD.ASM) MDROM .EQU TRUE ; MD: ENABLE ROM DISK MDRAM .EQU TRUE ; MD: ENABLE RAM DISK MDTRACE .EQU 1 ; MD: TRACE LEVEL (0=NO,1=ERRORS,2=ALL) -MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM +MDFFENABLE .EQU FALSE ; MD: ENABLE FLASH FILE SYSTEM ; FDENABLE .EQU TRUE ; FD: ENABLE FLOPPY DISK DRIVER (FD.ASM) FDMODE .EQU FDMODE_ZETA2 ; FD: DRIVER MODE: FDMODE_[DIO|ZETA|ZETA2|DIDE|N8|DIO3|RCSMC|RCWDC|DYNO|EPFDC|MBC] diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index 51669aad..3c5b330d 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -193,6 +193,7 @@ AYMODE_RCZ80 .EQU 3 ; RC2014 SOUND MODULE BY ED BRINDLEY ON Z80 AYMODE_RCZ180 .EQU 4 ; RC2014 SOUND MODULE BY ED BRINDLEY ON Z180 AYMODE_MSX .EQU 5 ; RC2014 SOUND MODULE REV6 BY ED BRINDLEY ON Z80/Z180 AT MSX PORTS AYMODE_LINC .EQU 6 ; LINC Z50 AY SOUND CARD +AYMODE_MBC .EQU 7 ; MBC SOUND BOARD ; ; SN SOUND CHIP MODE SELECTIONS ; From 5d81574226a9ec737f9bc528facc88ca01db3a53 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Sun, 20 Mar 2022 19:53:32 -0700 Subject: [PATCH 33/34] Preliminary Support for ROMless Booting --- Doc/ChangeLog.txt | 2 + Source/HBIOS/Build.cmd | 25 +++++++---- Source/HBIOS/Build.ps1 | 4 +- Source/HBIOS/Build.sh | 3 +- Source/HBIOS/Config/RCZ80_zrc_ram.asm | 54 ++++++++++++++++++++++++ Source/HBIOS/Makefile | 20 ++++++--- Source/HBIOS/hbios.asm | 58 +++++++++++++++++--------- Source/HBIOS/std.asm | 4 ++ Source/ZRC/Build.cmd | 36 ++++++++++++++-- Source/ZRC/Makefile | 27 +++++++++++- Source/ZRC/zrc_fill_1.bin | Bin 126464 -> 0 bytes Source/ZRC/zrc_fill_2.bin | Bin 16384 -> 0 bytes Source/ZRC/zrc_fill_3.bin | Bin 376832 -> 0 bytes Source/ver.inc | 2 +- Source/ver.lib | 2 +- 15 files changed, 193 insertions(+), 44 deletions(-) create mode 100644 Source/HBIOS/Config/RCZ80_zrc_ram.asm delete mode 100644 Source/ZRC/zrc_fill_1.bin delete mode 100644 Source/ZRC/zrc_fill_2.bin delete mode 100644 Source/ZRC/zrc_fill_3.bin diff --git a/Doc/ChangeLog.txt b/Doc/ChangeLog.txt index 7a3861a1..2afffb6e 100644 --- a/Doc/ChangeLog.txt +++ b/Doc/ChangeLog.txt @@ -60,6 +60,8 @@ Version 3.1.1 - D?T: Substantial update to TastyBasic incuding a .COM executable - PMS: Added VGM audio file player - WBW: ZPMLDR and ZPM3 fixes, credit to Lars Nelson for finding ZPM3 source! +- DDW: Add support for MBC sound card +- WBW: Add support for "romless" booting Version 3.1 ----------- diff --git a/Source/HBIOS/Build.cmd b/Source/HBIOS/Build.cmd index 43e777cd..04dad21d 100644 --- a/Source/HBIOS/Build.cmd +++ b/Source/HBIOS/Build.cmd @@ -93,8 +93,10 @@ copy /b romldr.bin + dbgmon.bin + ..\zsdos\zsys_wbw.bin osimg_small.bin || exit :: should yield a result of zero. :: -for %%f in (hbios_rom.bin osimg.bin osimg1.bin osimg2.bin) do ( - "%TOOLS%\srecord\srec_cat.exe" %%f -Binary -Crop 0 0x7FFF -Checksum_Negative_Big_Endian 0x7FFF 1 1 -o %%f -Binary || exit /b +if %ROMSize% gtr 0 ( + for %%f in (hbios_rom.bin osimg.bin osimg1.bin osimg2.bin) do ( + "%TOOLS%\srecord\srec_cat.exe" %%f -Binary -Crop 0 0x7FFF -Checksum_Negative_Big_Endian 0x7FFF 1 1 -o %%f -Binary || exit /b + ) ) :: @@ -113,17 +115,23 @@ for %%f in (hbios_rom.bin osimg.bin osimg1.bin osimg2.bin) do ( :: HBIOS on the fly for testing purposes. :: -copy /b hbios_rom.bin + osimg.bin + osimg1.bin + osimg2.bin + ..\RomDsk\rom%ROMSize%_wbw.dat %ROMName%.rom || exit /b -copy /b hbios_rom.bin + osimg.bin + osimg1.bin + osimg2.bin %ROMName%.upd || exit /b -copy /b hbios_app.bin + osimg_small.bin %ROMName%.com || exit /b +if %ROMSize% gtr 0 ( + copy /b hbios_rom.bin + osimg.bin + osimg1.bin + osimg2.bin + ..\RomDsk\rom%ROMSize%_wbw.dat %ROMName%.rom || exit /b + copy /b hbios_rom.bin + osimg.bin + osimg1.bin + osimg2.bin %ROMName%.upd || exit /b + copy /b hbios_app.bin + osimg_small.bin %ROMName%.com || exit /b +) else ( + copy /b hbios_rom.bin + osimg_small.bin %ROMName%.rom || exit /b + copy /b hbios_rom.bin + osimg_small.bin %ROMName%.upd || exit /b + copy /b hbios_app.bin + osimg_small.bin %ROMName%.com || exit /b +) :: :: Copy results to output directory :: -copy %ROMName%.rom ..\..\Binary || exit /b -copy %ROMName%.upd ..\..\Binary || exit /b -copy %ROMName%.com ..\..\Binary || exit /b +if exist %ROMName%.rom copy %ROMName%.rom ..\..\Binary || exit /b +if exist %ROMName%.upd copy %ROMName%.upd ..\..\Binary || exit /b +if exist %ROMName%.com copy %ROMName%.com ..\..\Binary || exit /b goto :eof @@ -188,6 +196,7 @@ call Build RCZ80 kio 512 || exit /b call Build RCZ80 mt 512 || exit /b call Build RCZ80 duart 512 || exit /b call Build RCZ80 zrc 512 || exit /b +call Build RCZ80 zrc_ram 0 || exit /b call Build RCZ180 ext 512 || exit /b call Build RCZ180 nat 512 || exit /b call Build RCZ280 ext 512 || exit /b diff --git a/Source/HBIOS/Build.ps1 b/Source/HBIOS/Build.ps1 index e6b62fec..a5606716 100644 --- a/Source/HBIOS/Build.ps1 +++ b/Source/HBIOS/Build.ps1 @@ -76,8 +76,8 @@ while ($true) while ($true) { - if (($RomSize -eq 128) -or ($RomSize -eq 256) -or ($RomSize -eq 512) -or ($RomSize -eq 1024)) {break} - $RomSize = (Read-Host -prompt "ROM Size [128|256|512|1024]").Trim() + if (($RomSize -eq 0) -or ($RomSize -eq 128) -or ($RomSize -eq 256) -or ($RomSize -eq 512) -or ($RomSize -eq 1024)) {break} + $RomSize = (Read-Host -prompt "ROM Size [0|128|256|512|1024]").Trim() } # diff --git a/Source/HBIOS/Build.sh b/Source/HBIOS/Build.sh index cc4d5304..818b45fa 100755 --- a/Source/HBIOS/Build.sh +++ b/Source/HBIOS/Build.sh @@ -26,6 +26,7 @@ if [ "${ROM_PLATFORM}" == "dist" ] ; then ROM_PLATFORM="RCZ80"; ROM_CONFIG="std"; ROMSIZE="512"; bash Build.sh ROM_PLATFORM="RCZ80"; ROM_CONFIG="skz"; ROMSIZE="512"; bash Build.sh ROM_PLATFORM="RCZ80"; ROM_CONFIG="zrc"; ROMSIZE="512"; bash Build.sh + ROM_PLATFORM="RCZ80"; ROM_CONFIG="zrc_ram"; ROMSIZE="0"; bash Build.sh ROM_PLATFORM="SBC"; ROM_CONFIG="std"; ROMSIZE="512"; bash Build.sh ROM_PLATFORM="SBC"; ROM_CONFIG="simh"; ROMSIZE="512"; bash Build.sh ROM_PLATFORM="MBC"; ROM_CONFIG="std"; ROMSIZE="512"; bash Build.sh @@ -71,7 +72,7 @@ if [ -z "${ROMSIZE}" ] ; then ROMSIZE="512" fi -while [ ! '(' "${ROMSIZE}" = 1024 -o "${ROMSIZE}" = 512 -o "${ROMSIZE}" = 256 -o "${ROMSIZE}" = 128 ')' ] ; do +while [ ! '(' "${ROMSIZE}" = 1024 -o "${ROMSIZE}" = 512 -o "${ROMSIZE}" = 256 -o "${ROMSIZE}" = 128 -o "${ROMSIZE}" = 0 ')' ] ; do echo -n "Romsize :" read ROMSIZE done diff --git a/Source/HBIOS/Config/RCZ80_zrc_ram.asm b/Source/HBIOS/Config/RCZ80_zrc_ram.asm new file mode 100644 index 00000000..cd68248d --- /dev/null +++ b/Source/HBIOS/Config/RCZ80_zrc_ram.asm @@ -0,0 +1,54 @@ +; +;================================================================================================== +; RC2014 Z80 ZRC CONFIGURATION +;================================================================================================== +; +; THE COMPLETE SET OF DEFAULT CONFIGURATION SETTINGS FOR THIS PLATFORM ARE FOUND IN THE +; CFG_.ASM INCLUDED FILE WHICH IS FOUND IN THE PARENT DIRECTORY. THIS FILE CONTAINS +; COMMON CONFIGURATION SETTINGS THAT OVERRIDE THE DEFAULTS. IT IS INTENDED THAT YOU MAKE +; YOUR CUSTOMIZATIONS IN THIS FILE AND JUST INHERIT ALL OTHER SETTINGS FROM THE DEFAULTS. +; EVEN BETTER, YOU CAN MAKE A COPY OF THIS FILE WITH A NAME LIKE _XXX.ASM AND SPECIFY +; YOUR FILE IN THE BUILD PROCESS. +; +; THE SETTINGS BELOW ARE THE SETTINGS THAT ARE MOST COMMONLY MODIFIED FOR THIS PLATFORM. +; MANY OF THEM ARE EQUAL TO THE SETTINGS IN THE INCLUDED FILE, SO THEY DON'T REALLY DO +; ANYTHING AS IS. THEY ARE LISTED HERE TO MAKE IT EASY FOR YOU TO ADJUST THE MOST COMMON +; SETTINGS. +; +; N.B., SINCE THE SETTINGS BELOW ARE REDEFINING VALUES ALREADY SET IN THE INCLUDED FILE, +; TASM INSISTS THAT YOU USE THE .SET OPERATOR AND NOT THE .EQU OPERATOR BELOW. ATTEMPTING +; TO REDEFINE A VALUE WITH .EQU BELOW WILL CAUSE TASM ERRORS! +; +; PLEASE REFER TO THE CUSTOM BUILD INSTRUCTIONS (README.TXT) IN THE SOURCE DIRECTORY (TWO +; DIRECTORIES ABOVE THIS ONE). +; +#DEFINE BOOT_DEFAULT "H" ; DEFAULT BOOT LOADER CMD ON OR AUTO BOOT +; +#include "cfg_rcz80.asm" +; +CRTACT .SET FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP +; +CPUOSC .SET 7372800 ; CPU OSC FREQ IN MHZ +; +RAMSIZE .SET 2048 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) +MEMMGR .SET MM_ZRC ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180] +; +MDROM .SET FALSE ; MD: ENABLE ROM DISK +; +UARTENABLE .SET TRUE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM) +ACIAENABLE .SET TRUE ; ACIA: ENABLE MOTOROLA 6850 ACIA DRIVER (ACIA.ASM) +SIOENABLE .SET TRUE ; SIO: ENABLE ZILOG SIO SERIAL DRIVER (SIO.ASM) +; +TMSENABLE .SET FALSE ; TMS: ENABLE TMS9918 VIDEO/KBD DRIVER (TMS.ASM) +TMSTIMENABLE .SET FALSE ; TMS: ENABLE TIMER INTERRUPTS (REQUIRES IM1) +; +AY38910ENABLE .SET TRUE ; AY: AY-3-8910 / YM2149 SOUND DRIVER +; +FDENABLE .SET TRUE ; FD: ENABLE FLOPPY DISK DRIVER (FD.ASM) +FDMODE .SET FDMODE_RCWDC ; FD: DRIVER MODE: FDMODE_[DIO|ZETA|ZETA2|DIDE|N8|DIO3|RCSMC|RCWDC|DYNO|EPWDC] +; +IDEENABLE .SET TRUE ; IDE: ENABLE IDE DISK DRIVER (IDE.ASM) +; +PPIDEENABLE .SET TRUE ; PPIDE: ENABLE PARALLEL PORT IDE DISK DRIVER (PPIDE.ASM) +; +PRPENABLE .SET FALSE ; PRP: ENABLE ECB PROPELLER IO BOARD DRIVER (PRP.ASM) diff --git a/Source/HBIOS/Makefile b/Source/HBIOS/Makefile index f1c5ef01..371f24d2 100644 --- a/Source/HBIOS/Makefile +++ b/Source/HBIOS/Makefile @@ -56,18 +56,26 @@ $(ROMNAME).rom $(ROMNAME).com $(ROMNAME).img &: $(ROMDEPS) if [ $(ROM_PLATFORM) != UNA ] ; then \ cat camel80.bin nascom.bin tastybasic.bin game.bin eastaegg.bin netboot.mod updater.bin usrrom.bin >osimg1.bin ; \ cat imgpad2.bin >osimg2.bin ; \ - for f in hbios_rom.bin osimg.bin osimg1.bin osimg2.bin ; do \ - srec_cat $$f -Binary -Crop 0 0x7FFF -Checksum_Negative_Big_Endian 0x7FFF 1 1 -o $$f -Binary ; \ - done \ + if [ $(ROMSIZE) -gt 0 ] ; then \ + for f in hbios_rom.bin osimg.bin osimg1.bin osimg2.bin ; do \ + srec_cat $$f -Binary -Crop 0 0x7FFF -Checksum_Negative_Big_Endian 0x7FFF 1 1 -o $$f -Binary ; \ + done \ + fi \ fi if [ $(ROM_PLATFORM) = UNA ] ; then \ cp osimg.bin $(DEST)/UNA_WBW_SYS.bin ; \ cp ../RomDsk/rom$(ROMSIZE)_una.dat $(DEST)/UNA_WBW_ROM$(ROMSIZE).bin ; \ cat ../UBIOS/UNA-BIOS.BIN osimg.bin ../UBIOS/FSFAT.BIN ../RomDsk/rom$(ROMSIZE)_una.dat >$(ROMNAME).rom ; \ else \ - cat hbios_rom.bin osimg.bin osimg1.bin osimg2.bin ../RomDsk/rom$(ROMSIZE)_wbw.dat >$(ROMNAME).rom ; \ - cat hbios_rom.bin osimg.bin osimg1.bin osimg2.bin >$(ROMNAME).upd ; \ - cat hbios_app.bin osimg_small.bin > $(ROMNAME).com ; \ + if [ $(ROMSIZE) -gt 0 ] ; then \ + cat hbios_rom.bin osimg.bin osimg1.bin osimg2.bin ../RomDsk/rom$(ROMSIZE)_wbw.dat >$(ROMNAME).rom ; \ + cat hbios_rom.bin osimg.bin osimg1.bin osimg2.bin >$(ROMNAME).upd ; \ + cat hbios_app.bin osimg_small.bin > $(ROMNAME).com ; \ + else \ + cat hbios_rom.bin osimg_small.bin > $(ROMNAME).rom ; \ + cat hbios_rom.bin osimg_small.bin > $(ROMNAME).upd ; \ + cat hbios_app.bin osimg_small.bin > $(ROMNAME).com ; \ + fi \ fi prereq: $(FONTS) camel80.bin tastybasic.bin diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index abb3ae04..24cdd573 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -513,7 +513,7 @@ HBX_BNKSEL1: BIT 7,A ; BIT 7 SET REQUESTS RAM PAGE JR Z,HBX_ROM ; NOT SET, SELECT ROM PAGE RES 7,A ; RAM PAGE REQUESTED: CLEAR ROM BIT - ADD A,$10 ; ADD 16 x 32K - RAM STARTS FROM 512K + ADD A,ROMSIZE / 32 ; STARTING RAM BANK NUMBER OFFSET ; HBX_ROM: OUT ($1F),A ; HCS WRITE TO THE BANK CONTROL REGISTER @@ -1530,16 +1530,30 @@ MBC_SINGLE: ; #ENDIF ; -; IF THIS IS NOT A ROMBOOT, THEN WE NEED TO COPY THE "APP" BANK TO +; IF THIS IS A ROM-LESS SYSTEM, THEN WE NEED TO COPY THE "APP" BANK TO ; TPA. IT IS DONE PRIOR TO COPYING HBIOS TO IT'S FINAL BANK BECAUSE ; THE SOURCE OF THE APP BANK CODE MAY BE THE BANK THAT HBIOS WANTS TO ; USE AS IT'S FINAL LOCATION (PRIMARILY IN CASE OF RAMBOOT WHERE THE ; SYSTEM HAS THE MINIMUM 128KB OF RAM). ; - - - - +#IFDEF ROMBOOT + #IF (ROMSIZE == 0) + LD A,(HB_CURBNK) + LD (HB_SRCBNK),A + LD A,BID_USR + LD (HB_DSTBNK),A + LD HL,HB_END + LD DE,0 + LD BC,$8000 + #IF (MEMMGR == MM_Z280) + CALL Z280_BNKCPY + #ELSE + CALL HBX_BNKCPY + #ENDIF +; + #ENDIF +; +#ENDIF ; ; IF ALREADY EXECUTING IN RAM, BYPASS RAM BANK INSTALLATION ; @@ -2450,6 +2464,7 @@ HB_Z280BUS1: #ENDIF ; #IFDEF ROMBOOT + #IF (ROMSIZE > 0) ; ; ROM CHECKSUM VERIFICATION ; EACH OF THE FIRST 4 ROM BANKS HAS A CHECKSUM INJECTED SUCH THAT @@ -2520,6 +2535,7 @@ HB_CKBNKSIZ .EQU $-HB_CKBNK ; SIZE OF ROUTINE ; HB_ROMCKZ: ; + #ENDIF #ENDIF ; ; LOW BATTERY DIAGNOSTIC MESSAGE @@ -2723,15 +2739,8 @@ INITSYS4: LDCTL (C),HL #ENDIF ; -; CHAIN TO OS LOADER +#IFNDEF ROMBOOT ; -#IFDEF ROMBOOT - ; PERFORM BANK CALL TO OS IMAGES BANK IN ROM - LD A,BID_IMG0 ; CHAIN TO OS IMAGES BANK - LD IX,0 ; ENTER AT ADDRESS 0 - CALL HBX_BNKCALL ; GO THERE - HALT ; WE SHOULD NEVER COME BACK! -#ELSE ; COPY OS IMAGE: BID_USR: --> BID_USR:0 LD B,BF_SYSSETCPY ; HBIOS FUNC: SETUP BANK COPY LD D,BID_USR ; D = DEST BANK = USER BANK @@ -2745,16 +2754,23 @@ INITSYS4: LD DE,0 ; TO USER ADDRESS 0 RST 08 ; DO IT ; - ; PERFORM BANK CALL TO USER BANK - LD A,BID_USR ; CHAIN TO OS IMAGES BANK +#ENDIF +; +; CHAIN TO LOADER +; +#IFDEF ROMBOOT + #IF (ROMSIZE > 0) + LD A,BID_IMG0 ; CHAIN TO OS IMAGES BANK + #ELSE + LD A,BID_USR ; CHAIN TO USER BANK + #ENDIF +#ELSE + LD A,BID_USR ; CHAIN TO USER BANK +#ENDIF LD IX,0 ; ENTER AT ADDRESS 0 CALL HBX_BNKCALL ; GO THERE HALT ; WE SHOULD NEVER COME BACK! ; -#ENDIF -; - RET -; ; CALL A LIST OF ROUTINES POINTED TO BY DE OF LENGTH B. ; CALLLIST: @@ -7025,7 +7041,9 @@ SLACK .EQU BNKTOP - $ .ECHO " bytes.\n" ; #IFDEF ROMBOOT + #IF (ROMSIZE > 0) .FILL SLACK + #ENDIF #ENDIF ; .END diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index 3c5b330d..aa9b12b4 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -529,6 +529,10 @@ BID_IMG2 .EQU BID_ROM0 + 3 ; NETWORK BOOT -+ ROM BANKS BID_ROMD0 .EQU BID_ROM0 + 4 ; FIRST ROM DRIVE BANK | ROM BID_ROMDN .EQU BID_ROMN ; LAST ROM DRIVE BANK V DRIVE ; +#IF (ROMSIZE == 0) +BID_BOOT .SET BID_RAM0 ; SPECIAL CASE ROM-LESS SYSTEM +#ENDIF +; #IF (BIOS == BIOS_WBW) ; #IF (!MDRAM) diff --git a/Source/ZRC/Build.cmd b/Source/ZRC/Build.cmd index d303209d..99b9b522 100644 --- a/Source/ZRC/Build.cmd +++ b/Source/ZRC/Build.cmd @@ -1,8 +1,38 @@ @echo off setlocal -if not exist ..\..\Binary\RCZ80_zrc.rom goto :eof +set TOOLS=../../Tools -copy /b zrc_cfldr.bin + zrc_ptbl.bin + zrc_fill_1.bin + zrc_mon.bin + zrc_fill_2.bin + ..\..\Binary\RCZ80_zrc.rom + zrc_fill_3.bin ..\..\Binary\hd1024_zrc_prefix.dat || exit /b +set PATH=%TOOLS%\srecord;%PATH% -copy /b ..\..\Binary\hd1024_zrc_prefix.dat + ..\..\Binary\hd1024_cpm22.img + ..\..\Binary\hd1024_zsdos.img + ..\..\Binary\hd1024_nzcom.img + ..\..\Binary\hd1024_cpm3.img + ..\..\Binary\hd1024_zpm3.img + ..\..\Binary\hd1024_ws4.img ..\..\Binary\hd1024_zrc_combo.img || exit /b \ No newline at end of file +if exist ..\..\Binary\RCZ80_zrc.rom call :build_zrc + +if exist ..\..\Binary\RCZ80_zrc_ram.rom call :build_zrc_ram + +goto :eof + +:build_zrc + +srec_cat -generate 0x0 0x100000 --constant 0x00 -o temp.dat -binary +srec_cat temp.dat -binary -exclude 0x0 0x100 zrc_cfldr.bin -binary -o temp.dat -binary +srec_cat temp.dat -binary -exclude 0x100 0x200 zrc_ptbl.bin -binary -offset 0x100 -o temp.dat -binary +srec_cat temp.dat -binary -exclude 0x1F000 0x20000 zrc_mon.bin -binary -offset 0x1F000 -o temp.dat -binary +srec_cat temp.dat -binary -exclude 0x24000 0xA4000 ..\..\Binary\RCZ80_zrc.rom -binary -offset 0x24000 -o temp.dat -binary +move temp.dat ..\..\Binary\hd1024_zrc_prefix.dat + +copy /b ..\..\Binary\hd1024_zrc_prefix.dat + ..\..\Binary\hd1024_cpm22.img + ..\..\Binary\hd1024_zsdos.img + ..\..\Binary\hd1024_nzcom.img + ..\..\Binary\hd1024_cpm3.img + ..\..\Binary\hd1024_zpm3.img + ..\..\Binary\hd1024_ws4.img ..\..\Binary\hd1024_zrc_combo.img || exit /b + +goto :eof + +:build_zrc_ram + +srec_cat -generate 0x0 0x100000 --constant 0x00 -o temp.dat -binary +srec_cat temp.dat -binary -exclude 0x0 0x100 zrc_cfldr.bin -binary -o temp.dat -binary +srec_cat temp.dat -binary -exclude 0x100 0x200 zrc_ptbl.bin -binary -offset 0x100 -o temp.dat -binary +srec_cat temp.dat -binary -exclude 0x1F000 0x20000 zrc_mon.bin -binary -offset 0x1F000 -o temp.dat -binary +srec_cat temp.dat -binary -exclude 0x24000 0xA4000 ..\..\Binary\RCZ80_zrc_ram.rom -binary -offset 0x24000 -o temp.dat -binary +move temp.dat ..\..\Binary\hd1024_zrc_ram_prefix.dat + +copy /b ..\..\Binary\hd1024_zrc_ram_prefix.dat + ..\..\Binary\hd1024_cpm22.img + ..\..\Binary\hd1024_zsdos.img + ..\..\Binary\hd1024_nzcom.img + ..\..\Binary\hd1024_cpm3.img + ..\..\Binary\hd1024_zpm3.img + ..\..\Binary\hd1024_ws4.img ..\..\Binary\hd1024_zrc_ram_combo.img || exit /b + +goto :eof diff --git a/Source/ZRC/Makefile b/Source/ZRC/Makefile index 3c582211..b2248ad1 100644 --- a/Source/ZRC/Makefile +++ b/Source/ZRC/Makefile @@ -1,6 +1,9 @@ HD1024ZRCPREFIX = hd1024_zrc_prefix.dat HD1024ZRCCOMBOIMG = hd1024_zrc_combo.img +HD1024ZRCRAMPREFIX = hd1024_zrc_ram_prefix.dat +HD1024ZRCRAMCOMBOIMG = hd1024_zrc_ram_combo.img ZRCROM = ../../Binary/RCZ80_zrc.rom +ZRCRAMROM = ../../Binary/RCZ80_zrc_ram.rom HD1024IMGS = ../../Binary/hd1024_cpm22.img ../../Binary/hd1024_zsdos.img ../../Binary/hd1024_nzcom.img \ ../../Binary/hd1024_cpm3.img ../../Binary/hd1024_zpm3.img ../../Binary/hd1024_ws4.img @@ -10,6 +13,10 @@ ifneq ($(wildcard $(ZRCROM)),) OBJECTS += $(HD1024ZRCPREFIX) $(HD1024ZRCCOMBOIMG) endif +ifneq ($(wildcard $(ZRCRAMROM)),) + OBJECTS += $(HD1024ZRCRAMPREFIX) $(HD1024ZRCRAMCOMBOIMG) +endif + DEST=../../Binary TOOLS = ../../Tools @@ -19,7 +26,23 @@ include $(TOOLS)/Makefile.inc DIFFPATH = $(DIFFTO)/Binary $(HD1024ZRCPREFIX): - cat zrc_cfldr.bin zrc_ptbl.bin zrc_fill_1.bin zrc_mon.bin zrc_fill_2.bin $(ZRCROM) zrc_fill_3.bin >$@ + srec_cat -generate 0x0 0x100000 --constant 0x00 -o temp.dat -binary + srec_cat temp.dat -binary -exclude 0x0 0x100 zrc_cfldr.bin -binary -o temp.dat -binary + srec_cat temp.dat -binary -exclude 0x100 0x200 zrc_ptbl.bin -binary -offset 0x100 -o temp.dat -binary + srec_cat temp.dat -binary -exclude 0x1F000 0x20000 zrc_mon.bin -binary -offset 0x1F000 -o temp.dat -binary + srec_cat temp.dat -binary -exclude 0x24000 0xA4000 $(ZRCROM) -binary -offset 0x24000 -o temp.dat -binary + mv temp.dat $@ + +$(HD1024ZRCRAMPREFIX): + srec_cat -generate 0x0 0x100000 --constant 0x00 -o temp.dat -binary + srec_cat temp.dat -binary -exclude 0x0 0x100 zrc_cfldr.bin -binary -o temp.dat -binary + srec_cat temp.dat -binary -exclude 0x100 0x200 zrc_ptbl.bin -binary -offset 0x100 -o temp.dat -binary + srec_cat temp.dat -binary -exclude 0x1F000 0x20000 zrc_mon.bin -binary -offset 0x1F000 -o temp.dat -binary + srec_cat temp.dat -binary -exclude 0x24000 0xA4000 $(ZRCRAMROM) -binary -offset 0x24000 -o temp.dat -binary + mv temp.dat $@ $(HD1024ZRCCOMBOIMG): $(HD1024ZRCPREFIX) $(HD1024IMGS) - cat $^ > $@ \ No newline at end of file + cat $^ > $@ + +$(HD1024ZRCRAMCOMBOIMG): $(HD1024ZRCRAMPREFIX) $(HD1024IMGS) + cat $^ > $@ diff --git a/Source/ZRC/zrc_fill_1.bin b/Source/ZRC/zrc_fill_1.bin deleted file mode 100644 index 705bedcddb656bcfd4ad4f83690b66be3a6d6e7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 126464 zcmeIufdBvi0K=g9Q(xf#g-~I@fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA;2#+7 C4*&rG diff --git a/Source/ZRC/zrc_fill_2.bin b/Source/ZRC/zrc_fill_2.bin deleted file mode 100644 index 294f4016d05bdd696670c4840f1f36a71f9239de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeIuF#!Mo0K%a4Pi+hzh(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM q7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjMyaxtA00031 diff --git a/Source/ZRC/zrc_fill_3.bin b/Source/ZRC/zrc_fill_3.bin deleted file mode 100644 index a461d083154fdd24c0c330b8420480aa2ff3cc5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 376832 zcmeIuF#!Mo0K%a4Pi+kkh(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DQZ&w&BJ CO8@}? diff --git a/Source/ver.inc b/Source/ver.inc index 3b25aa3f..709318d5 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,4 +2,4 @@ #DEFINE RMN 1 #DEFINE RUP 1 #DEFINE RTP 0 -#DEFINE BIOSVER "3.1.1-pre.160" +#DEFINE BIOSVER "3.1.1-pre.161" diff --git a/Source/ver.lib b/Source/ver.lib index 364713e9..dd51943f 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 1 rup equ 1 rtp equ 0 biosver macro - db "3.1.1-pre.160" + db "3.1.1-pre.161" endm From 7549789248d2f4b9ad55eeff4a66dec87efc504f Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Mon, 21 Mar 2022 16:20:52 -0700 Subject: [PATCH 34/34] Finalize ROM-Less Booting --- Doc/ROM Applications.pdf | Bin 193897 -> 193894 bytes Doc/RomWBW Applications.pdf | Bin 241636 -> 241633 bytes Doc/RomWBW Architecture.pdf | Bin 451609 -> 452947 bytes Doc/RomWBW Disk Catalog.pdf | Bin 134794 -> 134791 bytes Doc/RomWBW Getting Started.pdf | Bin 272671 -> 272669 bytes ReadMe.md | 2 +- ReadMe.txt | 4 +-- Source/CBIOS/cbios.asm | 57 +++++++++++++++++++++++++++++-- Source/CBIOS/config.asm | 1 + Source/CBIOS/util.asm | 59 +++++++++++++++++++++++++++++---- Source/Doc/Architecture.md | 12 +++++++ Source/HBIOS/hbios.asm | 58 ++++++++++++++++++++++++++++---- Source/ver.inc | 2 +- Source/ver.lib | 2 +- 14 files changed, 177 insertions(+), 20 deletions(-) diff --git a/Doc/ROM Applications.pdf b/Doc/ROM Applications.pdf index 0eea282c3040e6edae6c86cf3d01ca084f3a3c49..cabcf55c75c5501e602a4f12ff9b8d82d2a1cc49 100644 GIT binary patch delta 11907 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 YtysD28`llM1c28DrcRxG$((`z0amJK-T(jq delta 10578 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 Ps6yIj&YXWBjnAk diff --git a/Doc/RomWBW Applications.pdf b/Doc/RomWBW Applications.pdf index 7b8f44ed78bb1b43424891e840edadf9f0a4a74d..2f03b23c4701f4f6d7c8a76cede8680cb0dffa7f 100644 GIT binary patch delta 16893 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 Z|A8y_U-Yi6+ynF9dg6)a{Pv!${|7&b9!>xN delta 17009 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 KWA{5w-1>j|Jvom6 diff --git a/Doc/RomWBW Architecture.pdf b/Doc/RomWBW Architecture.pdf index f72f69b4cc2176589c218373a62c254ccd3814ea..56c5def434ea1262eb796ccf298284090fd59fe7 100644 GIT binary patch delta 59948 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

G8%{-X(*sRJi>M8)Y_ zzPmarSl7n(;yL5Y^y1X2C1+IIjoLg8?Vq(^mF`<%quW`m6&GO>G8zncU-aH(9gb^*OBrDM;p$?curYTmEd@l`%H^9sGBy%o7Nfw0P*vj>*4v!1a()ufSsc?SM6>VmdC=?R}V+@S!av z@UszOrnc6pr?Rxy!q0TJ$DRGF4L0W&o!)S#V&cn9CoPN5=(qEm_1Onv`!*bG6}E=Y zn|SLGJHIqYcfjc2UaucLyhApUG7?KqKGa-Z^D=yS$#TWso43zL|7J#!9=lt8IXvy# zlWLFCcV&y+&QYRnNj3d)S>krGC0%RA6>@Id&fP|q-uKgdGr!Xh?dNS%JmN)`$X^`2 zu5*2aT9EtM6|A|FI|Ftd>Pde8>USoEi5~j2|crNup_(7Md z9m}TXwUicCnJ7l8S2g-s=6?=XM8}`)6WgjL&r#AeID4e*$l~pdhkv$28cwm-fy>9m5n@R@ugWxYq!z= z>R+~e2e7&VJw_PvyT|?qgqwzJu`I=4FI_}aW-)~{kvm&}@>@xVhY5Bqk*1fhY zlT}_h5(%x?%qu5S~Gu6=eel2c?TWVKI!NkcXnd(PeDNSZb{93Ww}Pw_@G5whCp>o@m`~vg6Z+=Nu{rq+vgqL=B3r8t{ED4RhQg|=mc2@ znvUHp?imtyHIkMjZEF!L@Y0g9wF!+gG)#+^wzb}(0{0SY@?@P8&T1){{HjIzpIdJ- zcA6ad32b9HOu=HdEThZOeSG_o#$-h>wHk*gevHn~PJDE5%Fn+;3FY#7WyY#;SVh zF5I&+*vDbjxn$`+DeFj686#4|dLIXm;8bb8&2{TwFEuwprApr^m7K|{+fI@F&eHOf z%`Y3M$X359`PB25ExpsckJu&N$Cdw&# zEI(DcuOa>o^mtXf*z|i=<(5NExeH<$Uhjp9X@v)Kiiyc^sooO0ezny~(=Usq9oPF@ zonm$7&15HcWz}tK#@wDi=gyq?G%vMKDW!!x>#4Gam7m(QgC8X^pA%IRvYn@%%-9~8 zcF@^`z*@|^C{0V96x;LbFtq$-F>OPd*Hp<3cb)^3pdI{K@6N?||4CG`c;;$qoZN&K$58FqSC1WHb=HM~ zdQ_GuDJC1T3`;_Z0iLm5izQvu%DmSr2%n!lqnPtWOEXkKKBw}GVjZ{pPG}t8!SVTt z`8n>-Wi>*`7w6BhT4klJx-AcRZA{JCu#63t;y_{TFXOD2m(up+RJKbNC5X**n--Sbc*5e*xJ+SWA4Vn+G%;- zS<|y&S><)f?GrSc7ZB^l#H~gZ)z2lboCewfNv+hB zI1?A?0^-0TqTzTF+D<0%_ocrca|6TeN`=Haq2p-q%Kp7@htwWoc= zUQrd#KAmk#wF3Eg+1!x!vC(#e6!!3eIZI>wbk;fGf15A?B?d$2u>1~z0`bh=+YmaK-XSO`;$ga$*&+{5JYHmT8K}!2lClwq(gEcpG+Y! zXmF7Y)iUQ@ZIucaAaa--s5MW!FlniMWcefiEsX{T2|vnOY~~6-t*WeQ`tY#m#h)If znT?yKaWt33ZPc0RI=8#qVb;v+VVzT&`+~cBezcqMQ%WYe>s;yhvG(1Pjy=+^*&Bqd z9nJmATV_{%tvvU3Z?9G1$E$76qR!90oO}Ahge%9J`os9%B*n#BU2-aec|r_34|V1D)^pMFgJit9HqP2Kk|uhP#wR{HeY*%yj4O_#j3x@IP{&=#=A|lSX6+c+UBE&~_9rMxiop>t#T!*K0$d8n!xCb|1 zWPcps&ADvSKuM`ivv)|ZTJ7U@?Q_K3XVtGW%<2-h=Ssibm2GqX_41$30wXC)Ci6Qc z%@6#2G-BZ0p~u#`iJnC_&t%B7j~9K+cOE+2dTw%u zaGpHcU6sqOE}mW5*KVC0@{zW&xV)xsx$QK5QpU9Wnb&!qo4@u5Y^EfK-M2lrT6eP9 zoL50p8^!kh>9SLwWl4{jp#13e`GPkgYu>zhvEhXA@y=rpeLZ_TZk+86QNNWQQ_eS^ zJpPRI_>`FP(pUBK{G!%OGu!B4hR*)E>*s;+#N38m^aVFFx!)wZwrVY<`;VV`*=am) zv6s`lE`F$`#itcX>Ab_{RsAe))2gb#SABPGeM&9%63TrWd(vA;{phaGucr|fJu=wa z-n|R;?E4n)O_+FeTd?LX=?z(%-BNPZL$oZp!@bFNxn)k~Y<^Q!9ylHl6>l|Lbq1#&S1mxKXP~U+5lF z4&8Fjy@P)i9{o`I!cu$%W8vZ2wI<&rk&BGx$pj03k-uJx9l=p6Imlq zKn@y;?IPaZs~n&bc_cjPW!lfWJuc6u@o$calb*@9D}OdAz%JyfedvVx{vR32$U({O zvBuRgUUnhd#|I?t$-dx|V_xUGFt_El;~rPdmsZ+G%JobgFk9r1Q>{Y{ok^|dRv{Kc!0BdX5OKcr_! zH$J4Loo1laYm>MAI@Q5puWnLbZpoGzJl2$#z})Y71yS*~M+*#p*lV{`Y?gUVp4qRq z1F6s5@8EMtcsQ4lWK-^9mrv2#47BFf)fH@r*W+u46`0R;ELb!v&du7@aOPzz*Q+kk z+cNUgYVS!ta&;(>WHrwWHIxcCs_6Rqw&R3-bFRjbPoJ0>nm6VK^|fu;TwC6}xO_^I zu6*zI#nU8B4!GH;>{BdY zz+)FD7#CpIVqFDMGoH8`)A$BbFhk(c1W(5t&w`uft30 zI+G1~Q2qbBmh5K21W4OLLC6q&)eJdD4vPFC8KC{22@0xAJc0Sw8v)0~l*Qnps;>wW z`B=7cR0k%*6iNl7d=V%P{+st4`5=o+H)TU2b@Y=X)3ZZQ$_{x`EGQZBP*)m4Az{Qp zF$vxG9n!Q>Ed;@TH8V)lvPP$AS$HAoKVF!05XRw2SQZOaxC4&dZG<$Ih~0D$3>8O| zD(COGWQ~MW~ZR%ft{J6*_x#7Mg`+q5pE94>OW6Mxu0a#7J=@ zt!zC1Y)IhYR8b-MjTb|NIUR(}2wK=lR20zs78d_jL^ybL0xN?Ep$y`{ z0-T>lbfe2A0nSd7h^A z$P7H2g%Z9H4HdCU#qi8Lz^8s8nqbRI!|D!-P=0fLMVN#}ijic|0~v^<@Z%SvucRP{ zsjWii;DwHVHW~-^;5>bUp%oa8GUntDpNj*v$z}qTf>%>VG)VRm4bcldL>YAaae|(p zY=SlsN-heg2^1mPOH7qSB>*2m5mQ--&J`7ahSmS+f-jbaVqAP1qjwcaBJqas0~hZ= zMUsLb#EJ?}Vr(5gF?7)oBT>-|J=g)F8v|@!>l#rp(o9rNr3hb&k@BVRY9yQn7*&p> ziz=$(^g$HL#|@!?*CnZxk#$u%6kKf-NmRvA2$`c%07s`$NTNasbUdR-GDI&@kR>EI zsepbxO`-^0DWuEDu-c6I=$!#&ReTE$qBK^05G8X_DF&7qmRuM8;!K)Cq>DFNT z+#G$Q2lS2%1OYxlAIN*APm&qxxCjGa^rEZGNOI_be6qN(OP`c30rg&7-Q(rde^KKN zs{29I_L~7}xVopJPt8b*aBX7->Ry#bqQG@DcI_&<7Gl@UQwQ|fK`wbI!`059%dRC^ifj6 zpo^pg;%{uV(Q9^q4GYDwNp=;(MUX)U)!~2`pf{XFOu_&qcEF?&`x}G52RLeIN0LE{ z|Bze>4AkckqAc8EPdbDU8E__msin+-b21|&i@`v1eMwZYK`bWD5y>h8;DCxDwjGzC zj*Etb!Ez4iiv;>;AxQ>P2r3N5DDw~JYj7?P(Y1Ne5SITnB7&t|6(SWi--MA~*!OH6&%BaWE-N0-d!PkjB$f z4ECt>6oVy7PYtbf*=AU2o=AevZW&xG77ynbN{t_sU;w0J6bu>F!J|P8fZql^OrGHi+HT6u^!xVwB_lK}K=d==v0ple7CoYK{Sb;uKh*wW)u5yn`N~Byhc#jl%43 zQb1f7mrCMFfDIMx@zFLK{AqlT4^Dp_1wjIfi>sQk`$-DeO&I!rqzB-o07rKm8pH_z zA27g){eJc=7gmUi;Nug(skGCB z%W2L*l?nmrQN(c2IRHoHiw1cN9k&AjlbAx1H+uXO>`5R&La19rI{e?J7;TvugO+)S zgomg8BLUSsjbjvd3b30GZVg!GD(u>_W^fyTk?jV65*()-q0pek?DYS^8{n$|4rsy# zUP7dCgy1hZiHr0ubMTncFwc=m1O0}O4a7v}g;3{ed{Q*Hn`XDE}Qf8q^?68XL{WI@MegaTo(Us~(Lh1|L@g94@*bQps)vI-bE6R@9Ip zCD4|u0B##gR#B#p5(_4s{SVTX*KnTVNN>G{^ArpOm4choVIsn$bI`zZpgoS?7BLtD zcwYl-CtM%I76ALN0agdG>A_IU0|ww8C-XXKlgQ&lV-d29^61k*aQ^iltg`Nq#$jjk zm<+U*K{iCy?|{@}M-?)EgO3GI29L91|D==bA(B z;5q}Kz7rTT!i2-|W^|wv1Y%PsEY?nak}Ept58yQUGC@L^`Gr&}1pyI;jWTOgB*BJ1b*2NsJfnzr3d`_Jzj&KjhAySNt**J`J3VVbb#bgg|ZK~qn z)Bso}20cfbXRK%PbdWhu@xMJEh{4i6hMj=z5;r0oHV$baC<%kb$;%|s2nB${=2cY^ zEzNL+1F3*vTza7Z7&1i|;x>EuszF*{rviCYN`?vWrFGy>G4XKx-zWAdlBu9a@zb>6 zOHDx+Xp-^MgDCASX_Bx(kz6bR%Ys`%CU;ck2F}Xk=;`8%I9$3%9&2WDF+*sG-q0k2 z?WSQ4)+m393GhIGqaFriJiNmId0590E+Phh3UKh;FujdVqmrQ_iD`&UNe2IOICL{$_{GtE)$%ODK<4avtO(GLufFsLZQvG|ergIOIW4K7T;U$kc^ zyb(S;)0~U;Vw%r$+MpByfXxJXg;Vzbc>7q-ASR%taGYQw+CI~#ljTs@K9WLd7THAt z&m4&K_~;YQOdiN%CYVIg$zpWPbn*m|20u9+SjQ5v@ssGR(^!_cr_3{b6E zWIX!E0QDH)s{LQU06dA_mEwTI3*-Rbi$DnI?){(dYJLS*1~dD+|iJ!;x%t z0M3cdV55#MA_lR*wnsw07s`d09tqe%R=w&fdDpr7Fk*h z<#~|t6qGV+@R0JbeGQ5ebg_XrR-?uu>D?}5-1-4L?IpnwJNXPLTM`QlEN)NXjm|*a zEzwaPI%WL#6fX-RX^c93(O|>2Aq)2ghSLJR0QN3`B7KB@gNZ{RdVtWif=*|DVO|5$cP@=He_yozigZ;RP5f zx>a=Dj$LbH59$}_sFwyvC1nm`2>@>lFmd-^zXp2&<=$b6peR%B0*iBwElqh83 zFDd>^!a)Oc#pS{M34o{P z$W$VaCQ67o)eXr+L>2k7IF_gbPf|yjHp-D?@xYbCya*AlXha=Z6YGw@bW&Xhh5>Gp zu{ThD!3~K`qhUVnC>INZXVd}1N0<)`eh=$ELVz&1Og-@T(d9uoCb7Zv!n=jSWA)_s zk|^&E!0}`vz(+EeO~ZxgKcsW+;8KKDktn#yA0|3%nkcEL#HNqnJ=U`I4&XMzjl|$J z0LMI3EW0StHlzwX?vfjaQ~`T*yw3*Hjqy@%)Vi}rT75Ph9Sc*Sk!>LJ9Q0)?U_LSp zzy=>gvyH4z!CxO5P7*Y@w_#6UqBo);wGA+5qjCBqFA|in(cNt%C86;Xa-BH3{|)eT z=tV{qtiC-$aM_R=7%mL`Z-B3Z#b?{MfGG=w%qV0@-@*>VeKP}8_?Aq8>+x>^ZrUZ% zxNOK;F9g7-{5;mM8*dniIW)WwM=0piw`3*M8$%S+DkL_P&@rJ1ct1q3*L$Wd$9KYR}-*VBc%>7$QAtb)9iisk99p%x1KAR&-dH){{kBs!etHHIllP02wMfzY%0CP>i9Bw|s z&B(Zz4RC!;=(K}6ND%;*0$>zH0MEcWdXE3w@jd`Vc>qu}=5&SB$im<;{6AhD8{SC9GWtVU zPNX52pMnc;01X6~hh8^>(Q{}B=8u5q48>_U^8?owG=Nj+ID8X!ojiRAcOH6@_J8EX zoQHnIIu`v$BoEc610V)N5zFq8I5axwK_%fuIua~}2@swb0_Z3;$P>v6=f78lhfZK~ zMkeQB6pZUioRKfNa=t|lj?xTp$B&%68q?o%rde- zGzYWC9NMVd5Qm1p<}N;nF}lD3nSkoJfTqZD0EU`lMeWgModYfa6t@A#k!Brh33C7( zN8xUcmI7RKWWit=V2Jzovt}XRq|viJxR(2WX?zY{RNWau&}0FEhnyTR!`PP#&=d0! zIqc&IsI(6vI(Fr}0C_A4k+*1-M!){c!C(K?|Bq&KAJ_zgZ~8|2z$ReO(AUcV*Xw~I z+2H_Sf)B{fi0BrBFZ6+qYQBFv?#2N7mkr7ecBl#a)PT^$7l{)WrRX?}(aXTVm%-rw z2+qhLo&#xloN$#52=1t20IXz+Qdj>4;KekJKwvXu++5Kf=!+joo4y)p6=k;IdkX(2 zWyE2M&N>XS+b9gSp6DA9=(;eF2o_#HE5I-DREZL2WQCmrHrpW#l!%PCD5H%5;sHPz z8INNP=fi+s+cyBez~}fIwtfvnxaj3@L>nqTZ^98>G(8+KL#;O=S^_O4vH!LeguHR# zh!QHX5#gc8CPWL2o53dNzI7wQN2@m>+JZUCV(6qzh$Pyv2~kF8Z9>8^?`aca3a%gi ztYCFfo-G*IBMgT8`5%4bi?Z*GS&#pq%OZdm8zT`l{KG2P2UF1fkuYRq1bi!ER}}on zM#A71qF``(Br+4FMkC|UU6F9RC>nmMB9Z&(QGf|bl_an)pva>w(J!J~JRFMzkU&CNFe1Lt9My$}M7!1C1B0oeojLSxk#~^`dUM!-6viUG@ zQ!EVZ!AG{D+u{&iFzqMcAF3aV#GsUTxN3-nF>T{v%=TF10E~pq4j(oVLrdcjNx%l@ zXk#2=kGh77D3+2pH`4m+dx15J4Tnj9>yDUhbbSZA<6JxU-2!kL>B9GmHAOv*JF7ROulaN+am71(pM~KwcRtmISmn3kGpXN9xh8Y@on+AM6v< z`ykBmBom&DMv*S;h>sEq$eW<0`;ix@Wez-@mx1ULQ2AWAgpLyl=-9&;UfIYiRQd=2 z#Sb8h2&h3Gpb&Zx`GR`pLv#2c=&dxw2(>=OA&x~~okk9$ z(;UPU;42&=J8QGjC)6c0$Zx$Cca%rZW$}a;&LE)#h?s@+N~DH>8g(JEd>_aSat9N{ zWQxVXIqcf$t~c3eDjh~MzwX3(Dd!06neLZT0w0XJCiigkkzAaU{70l#6v&0r|x z10FY*h51Ez3kPnnpqr21ap7*Ts^J5PG%jw~u@=a*aECrI;scc}?ojRB2U1uIQ zP{HDgJ}rVhgAFifKztyV#T|;!eZYU^4t*=c2mDhmoxvYO2u_-CaZ`=W3W+A}U||++ zV4|TTZ$4a@XeiO{1BE2+P?+rlxg;(gMq>lOsSYlE2nG184Oes|4QqjCh72yexueDB z4yDO`cv#aAAF=PYU|)+8v5O9#6!rzBp*uhw(yc>xFc|~mB{nl1SjS}y@sbX_;|>{9 zXanqVYbojp^D+5DOA4Pqf!o1kkq;f%#2w0R!yODWbT%69fIUMIF5Cfsh6>zphfVPx zGC(#LKX`^u2y}A?v)2D22$x7?vxUEFkf}t_p6pAAo(7jC zWi~rt-HHt>fjvW)TJYTx9vnYSAW`|nn*&@l+xBqg1aBnT1aEA9-qFFSC2y4M=$O#< zM1N)QM)-?=`zpHg>4n8VTbEY#`ki>Y;pgU_4>3I(oSV`Fh9~au*{9iJNv)5~?=qRR zuVY?YKWw;_YHY_j`Tf$F1xI7$b*E0_o!w5lb5+uRwQk^R@@vA%G0ud;R+KT)()`$r ztSpU#np(cA-*t>(2!n|($BkCI+`o6P??%@`iQ1OFLkD+drE0C$7*l^mRW&EQ_yGG( z!w1q!ev~UBK{odoLs+ggNz2OC+SSR?n`ou4T`HC~=JA;EJB!97-D+5%MTs@JN?!R& zB2R4pqbXyG`a{O-Z+W~wzTdcU_Y2a;LcVUT#PgNnEJCyw>0HK`&;6ly37=x+9%|WN z+0{8FO}Dn~;?;%^N5tox8IzW>Bfa9oQnJOT(T5 z_Lzwt$}{T+F5bU(>FS5lw$vPXZtcTQy7wMDtovQMr~gNEZPca%JFPgWW2iY<_m`gC z88?PMFYU;I^xeJo9rCoP;&-00vd3F<-VXR$i3g9#)ZoFlZN`tcTxL-=(0;3?o%{!F zPxpDBE_pE$nA zic>2;d0-u1H}+u0fxc%^Csed3PFXdXw=VVxrC0j(bl$Xl{X2_$q%1podx6B~nxOkN zN0cnxH@bxhd$oQ{47>U$v;W--GZ`PB#oXGB5zFT+7&Cnm<=quOKVKxcA|$ep`@3Jv zx4+rr*41l-*J5{m8)okK-Fa`|)wfc?)0&IhAMJ0+>}ON?#&hgAM<*WXKD4c-&ES@t z+{C2*zQ>l1{qKHvYKs$}#2S3LA$`W+eB3iPejcysxxf6*9qr#Y&~4<%kCdAWRbKyI z@Tk9Qmh6+4rrfAvIp3B0pKlHdIb>NL*(x~tXkz=NGl&1A%bdTe|6M1)M(~J9WbWfWdcRFZh@Mz2U zlfqe!OJo*I4J4^WIQL&OntAE&D^kF-FVC$8N>{({m`;3Lq-GxKt*hCYN7-Xb-Ds0o z6(Qg*>@hxgGa)BLQE*UOZQHRxMuI7$ps$oX)u2PqH!~&Xp6>G$rc~Io?nM2 zY`r|YX6@`5nUP|)yxM^bAKlxI-}@h4+0)<{@jc1vJ#j_JQ4jsN*q@JkmT-S|3A?Mj z9x7KAA8gpGMVy|r@~A@DR{pJG>9)#;4c`w!b9)WW9sSTUHWz&x7C-OXyRS)4 zEjaZ*6lcgureEZ_s%1Wq9OJy|Q*76Hm(NqOTXykk)KuS%yOgoEJbT=F+vTZ;V_Mgz zu9&ydYT=GfL3`fK9fHLMZ-c){{GpfsA(Lk`e$rd_si5~{<@#MED|Yj|y%hP|&Ogz2 zbMoz3xOkJ{?$y&~@6k|Ek#Hq_o;s^Hd8^*)3H{@v&Meu^i?2`4B1%lCSk`c(OhNE` z&xOvdJ!gChJ-6EwbcQ{f>~NWI{Z^uSn~GNT#+SjD8v-x-JXhbacr6Lq7o)v${6FfONdvkq^mt1tWx>1J%M%;ovx8ndJhr>| zB>TSRq%zO=H&1MeSGwIuxU}=-uS*`38I6}+%uSxZz47Swj`F#0E)>+|c^;4_aToPv zp3^SUrR5*#_+!_vcq`n1U;U$I-MfniR{AAWmYC>wO?l}V9%)ludy04@Y*Fq;zb74B zH-5m=7n|Bu`^wYCZK>NPE4f@M!|BVKvMAr+i_^6;Y`*d@ntp#yud(RUb8k;Lc)W#a zD(~F74`Ynqgk% zey_J~efRBrE_~c)?tMe+aG~FsOWRc!w>*xM+i~xZC(Gnot{;7~-N`d2=hsYa6ED}i zC1$hlNJkid%?Y{r-g$Bdvi!P3d~V#5scLCEw?EP7S$m)KH>VdrrW)?prck|jRuR8T zt~l>*;nVrQLUSK+H@7Q)XT)5ZE;YSA+{wXHm%o!?tiDLjh36^$=71L|>GABT4-)Qa zWG1D4$oRh1%|9(>%f%;?uV_x3pIv(Lk=<0P;^D3H*~pV6{JW$-d8&`Yd(HiiiYqa; z-wpO{KA_T)?z1fE@jRVaKWF>TLG;4;O4Np`hiT@4M^}ll%Gyi@=9I8V#1W!xI)9Yt{+xgU^TGuv=Sp+9BU4!Cb7i zCV3$>AaZq-?37;({4LHK=4Ahv*S`3NKeA1!uS)Bh*^Ii|>rKqAXFsQvjj?~dCV#oj zfYav0jI8^{@?{kzpYNGTYkZ4dSkFP@Ig8{9ek0HFGVUm8ty*7zj+x;3((;;G;^NAt zJ@YjZN!zbajx2F%FnV(6!Mq?7?#3Su4F;1`5?;- z6MQvM@ea~$&X1Nk*ZdrIKJcFR!;}4MY^tq#ZiiXRT>d^ilQE_bioNEJ&HIv88rP*d z*UZ=Ff#2PP;|hB?<5vG!rXOlwvrJd2MErM5;{DSEsWbO=wU18q`lMZ@qa&>0tD~vM zoU>{^lsx_RWBI%5`zGnq>Xt;fOp;$O)BBP6`Cx_agoWn@a*DQIwqN%82_Yf0QE_K8 z>ijL|SeV{}rRbCmMmfK&Hu@X6ab=Gl*wZ;7vFy!Ghu&+yZ*-;Gz|xxqT*~{OgfY=Hxut z`t1k(f}TV#>#aymke{*nd7DLW>z}>1S46mwGs+LYjqXb&nN`NlSn|j4bw{G(%*Uyh z_HN>Tj!=HF;XrDubFiAmlb(Z1zi&#+I_a*ydUrl-iQ}jFOV-9oyXmb?^qIawkg3^4*f9OTt~RH#=da(JK2py@f5#naDa$k|_})J8 z;EzNlLPYVwzd4BfJpATk+c&6#iWIyD`D|Q_wC5g*e&fn3Lzx=J$@!d@N zq5G(q=F)|a&nytPZg*Ig;iT||plG`hF-m+<8(rs27 z=3BUa3Re`X!+SjI6m{e(gx?zX9r@zQ^xph*VoOSosOSha;Oef^s^xt&> zI}2}Yd137>qwBkOz>(j5S#!lq&7ZfPj(vJ@a{6A^W;?HG9Y4AkSz8#!Tk#=d(qO_@0T2bmEds5mSq9RN7HL{e*_7=*LB_!F`Y+17Y&OFb(b?-Bu*Y}q{ zu6ypBnRCv}oH=vO%$btDU0?O`eVljsyLd#=b&nes-V?68yf^2=%xe{EPD~GvZ0KeX zz%|&i_MOe;#rZ`atW*z<^qP^*db8z1$-$Pe)b@?GJ10-S-*xV~i?253&rEgM_cXsK zaFY5hYsXX0nKvsRc|O=*mPh_^D(@D)cU#c4>Y@=l`-dyVImFBldcR$NW$})M8S#fp zbZ>f&7oXDn6rFo0^Y28*x6|uSO;2X4-KjA(_^)L_drDLO_RH2LQ~x-p4d=uTxApq& z6gOae_e|5s2UQN64=L;l>OQEQwPvT%o-3N-EpKbvrY36#|Fb=&a(ZH@vSY{~U#_Lc zdd-q_vSrz$J4!7fpZvA5RP06!Pun~=N#|VJwkKEnl%E!N(SAPQ@R;!#bBKD~SM@um z$IV)Asi9c6)h&5-Q(slbb?5J=M-JIr(fnV;!p7b$w(a{<%;rY-?p|RzAm>D%WZ}#4 z!L5;=_M8yc)60k4by80@v^4B_Iil&l;=Eoix*s|1i3>&9^CohS<45WJYnZ6ocz8pUEALQqv7umc68lp zqa!aq{uz3w$?~3t&^`aKyZtZUkkjK$=blWi`S55!sdK@z2Xid_z3rOCccKog^s_&6 zcHL{sn3;d?u}t2cUcWaqRaAdvhEJCZo>#A@cOSKM@Y;y{t0tHAX1sYA=52MO$h*w^ zM1h-q$<=`E{@1hJ51)%0*uZ?<>rseIocz)5YZjIwH=R1R!lxE&h zjS~ljohi4r=(X4VU+$8dn|JKZSzIUH_4AcO?^CWXlEWCy3)uyu>t zUON>8=1xBT>WIgcQO{GhC%+o~Rv~qI1h+Z=SjLP|bA;re-=D0D92fVrU*@!UK;O6a zyGsIfzbjwe@4$WIYu_Go@DVPWcjTQxRcm}Ez$ z`4!DOx^Z5xwocX1Q&-ko?u%{7@AtWW&A062(TmK6I>q*IGV^vDKDEs>a5jE7^9$BU|{dnE#cF%(A z;||~YTB(_YQ8EICuTRA=_s+>Ir&fTw3UqlTxy7H__5W7mD@f(_@Pa-!@qEg=heQV5N9ncbFuqqdEe@$ zj*pjPR@_E2`*Y0~Ha_nYd$+v5{epcn#{Amd%RVPi=f6cMJ4Y|PwX|*6vO9~sO4p35 z4GHrbGV0Zn>>aD`Dqh-eb7f0vu)>WttqQjc_L}d*Fa8avJUXcD;LC|iHy;|=BgAp@ zt4$UI+LsKEh^%(`T;|)H)INL9g69#Z71v}sF27@#uadyhP9EH*ux><*gU4C>6{(+JANVG& z|J389i~h{C>tV#Mk#U+ivx`j6%|4XAEzwNjN@Vj4{WkY)E_?d7bnBJqebp!JhilCu zvliv=|1Li3Z~0@}8LQwm%aqO@DmyXVApPNyAxTHGyy~idAI;m*ylfE9b#lmd->Uu| zI_ol?tM2{GZQ$IvX}{KE{;I*JukWz`$nR6oZGw2(6E99p=Hs@^GxygirR5D&{LYHH zcVOKFgNxOM9(#P7>n2rKeO*xaN4cy=s`EOYVu;S*bA5j_y{crl6wkh~hu0GS)-3+X zmZT{=xH|qHueJWX?pFM@eniG^{bjxllPoQIJLWso6YR?gwJ)Q(d3~BTNAu%`KkSUt zX?16H{%f`u-|c;Co?Q-5Ot%C$7nP9kQjs(7c>Hw1l_a*>3T-N$fXM4YGchJSaGqzITaY!+G^s z?H9Q-Zoimyv&gz=&8nYWb0-+AiTJQMPnFkhG3(pX!syaF-gV--1^Qtd4Xs35(+?4& zJR|Pf6}0Qw9;m#sCV(4o_-Fo-L53$z6|K78=hWu4)~q<*+_KUUC*2kL9}E7F)bsll zi}l`LTNYm0IbrLLrK)|WjSmzY+0}2TZ?_V?ZclnI`fcj)F!0)M=fv2TiVw9Xf15U^ z?enQqca+YJKiUv`vn6Dc%6f6!YqedgJyUwVJ3s!F&z^xP-D0znN7-{!O_qdwS85Tg zvW>5|AM}s7z4G$Doe#7||M69PwYl%aDVYjAmY4c{=e~G6YVglbs-<5GcUayDjraAc zJG4^KQ?IvaRllF#9fvDEZT7gq zF^N-~kGnqmG>^|(wt)pMsx#n5o`QI!~#AWV&_cU#l>Z|h`$$=H^`)e-y z`>px&I{i?9(bY#`Y+7jdS~Be!*zM&eH!D-5u+Zap;Gt!mz&1yyMe;-rsXvGud!P zN|?psUCjY2BXVEPIXOu~+4{X;_PNAE3%AcnS=;yD+w^)5UQPGAm76bK`D#8%W7VI# zW*HYPgs0o*m4UDsWFr!M{J?L!Nk*S+e| z_4-aN-y1qfRt-ZA5AS)P)HcSu?DPB|yBE0^_W1bznqbw|#HlCW-@SjUM@hozong*q zPtI`mruTBv&aVCEq*H6yOLyv z(Aekv%Jqki9<%$qe0lVneHG=d`4xR~o|%-mXr7wuTlebJ-^oVn6m&n&j zvg?)LH_i>pum70kJi0b-_w|nx-fZ}GGIXrfnLabVtK>yoiOnu7b$&u#yHlL2E;`zy z-=}Zqj7@FZjNS`l3orHi5>!$(ef8s@AG`YYy1uu|y8dZ{mStDmUVL^Uckz(>TdY=R zU2E#&pVQRkoqB?ZnDq3E`+*;kw|35ctvBcK_laWl>1Ex8aU%ngl&5bJe}1NVtLEXO zE;sZ)3%ljk-BERV^TQ_C_@_&+4bQnRCvmRbO>N3B77efx2wg**q zIq|B;rqZ)LH;JDNsBrF=FB%&7+BG6JyD5K$zmMm)f47c~EWL3+ZRzBn7n=3$XA@s8 z7ienRWm*r|>N7L_)HAg>h48Zezf;Y-23St-5&Y_$lg1N`(j(Q^+O>y`G``9UuHG8g z_$%W5y@f72|J`1DIZFQRMuAEn-%UU6rne*kufIg-w`j0)A_q{di zb96;hufG>wD4zRgcj<=eXI9pcr=Mr!?TEY=^pIC7i1K|MzNkmN+E?Oo+U|+B#Qmz< zyyG~J{oIn8|234I^>oSlZvVFXy0(fF`-<$~_2NlgZQg0t*N^GZ>)Q9fPU|->V;dYfp}n(2 z_2W%m-|gS;P1o%A>O+3v#GHLo9!HfeHoP5CdOD$RuNS9yg$wkz&V3)%mUnw=X`1TF zQ^RU1Z_hk#cItJ=YGJ>Tst?Cr;?`6g-elV{S1q8|OK0Ub_Zrx%4_oke%*?hP;u}5f zX4y>@P4VfAuS>#SEFQaK>(muH)0@jrUf!`K<)prIOXa7DefqZ9er~w6__gnpjH(+Z zAJ$~AtbZs9@f!2JW&6W7g{{Y@Ijkuk3T%ZlFjO>8x~e&*ItQStpuhlaPK z0yN`mCj>f1YmGf}aBOMK(7&y(^|Y3(*s!RG@3G;l(P{5N1K2l*U0q+ri6dQ)dGr^S zf7%w6l)v~%h{3OEbJlt{^6HFc)+&72b8yh!9p@a>6LWlCRetU_K7R8BVX~Qq#=UQ< zUIq@qC8?Xg9(k8AIC_g%b#Sk%JFTYtxJB+eS~2yKdY=i;ec_J&)wVIUk18kk37S93 z>`OsSPR5?xH@XWZOtGBOsUKJ(XHGI^6QpTHYMooE*#vd=v zNLqNwYh}fbg*Tn!-DcFREp>7DTeH*1=1tIDt;n%4k*|7}hMj6RZ4*EHHBNl?#O^%5 zu=LE))|F2!UC#`0&)qWYR@|%Kb=O&0s>#O(XrFBUFZ0#1oHFHGBZG4|>u)yvj4wK= zwJ+Rm^(ODUN4@(iUD!DC#lw%uaQ+$%?O6>c3mu(~h4Z&aphV zEY(E(^4|1hjg{AIeoT9inVK`PK-D`|=Y?9Na%)7N)9DAF&HBFZV#DtwtDVHNIlkjc z%RQ3c+NykPyzc+%TFCL6PD3Y#Wv34=U9oJ>e`jturLDhpXt%$SpYl;<#apviwUif+ zugzJ$Q{U)i$6 zhQyVj`>)j=7hV|Q<9Du4ROai?BMkyh>zv)yt3RQ(MOgVgO)b~>^2(8S^~IA@ZvVI1 zEY`R()%%X2`!he+xIN-4*YB;Z7_jYX{@Ie&iyFU_jB-+~%e%H8P>&in*0aELZrR}G zbN_l47@Xeg(9YhrO?;|$Zmf5Fw{5~z-@jhkbdpSc_i+BMtPLl8L{{$ylN(ZP)`!&9 zjpXT`dw#s{gu%L%ws}dL(hYa5x^`xQ!Wxgz{JJhC?wsaNElO@d;lFA$52U%jC7;HA z8MJ85_mQdI!Er5pZ0gFDyXjxv_b+ez?>DK@=KTuBy1ZD}&d!TnnrA3JxiX0zY_c+_ z&)k=1{4Z*KesSG1Ht_8!xd0}2Dox8I!AW7iPO{GjB`7^d_{d_zT&~=esYM zxXiy;abkCROx(-;_j+d>4vAEY&0aNk`FESgz3;DFUOlf&WzWzT3wOFz2Bc0YpRuj7 zdxS#MFx~fgMGnft9vctqX}2`D^>bxRMO66jhrfr|DYsWBswsr(?YR>*cF6Mn*AMWr z@B53D?!?csdD+wP#o(iX2QSrS7f(GE_}J>K{jJ-pbQPu_+T7%lrFP3B$z(xc!-B#+ zTJLt1UA@03%0Rm%)MX6s?UsDL-Uc6s=%B5sGx=(3ik^jTeRJkhYHi7?_q!hI zyq&nU{%tC3eJ(f8SP*Yh0L!9}Q(9SQVB4LrrG{U?%k zc=`ve%l_B)gf^;N$*TXYt)^$(=lUbFXMeBh_vmY0as14TA5S#2^SaMS_h7qjWT|d* zF}>w5J&ae;Yii+UyO)WLRi}pVW9A9lnkYV$`E$h6J~8WN-gxArxq4@Ub-2H8eiy%a$9xWpUWT1lD$!9GaQ0E` z$7d>YFS@HH?m2GeFtqzyyW955o(?zbe|gq}LZ^7GZB^yFJZg{kTlnYVh6b0=#a$;{ zUURo#)?C*J_LY~7hXyJS6Wuy{?zqjfcVj$OTqAB-*^PIP%PF#c>>zH5Q%ig5HF*8@ zA$<++b&FU1a=BOF3gSXm%AF&9?^g_pKfk~B52UxNXxbgL`{w<+Ft5#D2L76yd3wO- zoaQYHUw_McWKcMA*FV4G??-%F&+=b<`ee8M^CQO=4<3FZGI&Ov_P>Y6VkZso4EtzU z(%*V(iB++n>c7*QPET?>ZK0mGTSsiKv2{>4YmbIi{3#~38rN#GcREjYGJnW7>aLo0 zm~ClQCsa7+KEiOpPuh5_|10W!fA2e5+TE0M{`Z>K_%f}}R~Gjnm9w@@S^CJ(rG4MgA8X%DT3y@gKw#d*AwgzZtuq?F z_-bsj(&0s&n)j!hj2kh4cBzVf1@lnjWPMPw%2L<1LVulzrR>7jZCIL4i(nz zSfizI{_ccf7e|O6MmL1NQ#vAQD)o6L8k4p!by-v8Ll5swGj~kpjxqUP5Q~-*8e+&kNdyrU6^6 zaNFIaL&b))_Z*O#H5wLd5J zT%_YXZ~GfBaed^W!y^~vuH7>+T{~H)+GO8>wf%J-Y#GHd)_L;v&#^K2jr)%;?yY~m zan_6e){Y7{bsMdYda>MM9yCoK9;@x&nyWT%h;c)c$^if0Dayh`^~2hO{%Vn3Yz8k~ z6w|}-okzFWE*88g-+v^gHNO9{zD9Y(V15HvsaMF5AFflwE^3J@t!B9OSo!>F>0B-2 z(;qn9Z1)!TI-cnKZP$&<@iVVp5u8t+bfW6Tuf4-^OMA{y-d=pV{*U7JZtYnMBlFMH z&5Skw?|ko^Aa-N5g4oQZy^1I~GuVUJrceC-FJcw3w72=eX8qRKg2TEo#`}-P-l+Ps z?)^RWr$U3a^{u%-A|`$9F0ND0Su#U#hUNV)ckGgfWA>F^t?|qIHG8zdvZJXVU6smI zC#^U&QfJ!i>vleA0SfoWoS30d^?u8A_xB#%{=5;qKcL{8IDgxo2h9qPyLv<1>Z|-lD;1vGdr>o8C-mmM+mk{o-R}4;^PJb>^10WJZ@q6iI$xide)5Y= zX=qtl>e<*M4iS9o^7gcCbG7?%(zU&%dn+Tx`_5{@{2mL(XoGe`{YYu};3! zrAo(QiBegb>-wJC{Z*GP^;b*k)_?E4#GQ}C3d=ll%l`3qsHi+1rSqrkq@|7i)A5ZZ zAJ1Rp&oI=n$y+=qwuW87>ly00&?(XPq4)f-k4sJrawy1AaVC#ei_6EC4aso}AGQ4X z>g?+d<8rV4RLM5aRqdnsE=aXW*RQg7Z1LBSv!k~*Hl(MTEcm2cw=1D+Ug%qro4-)A zcg2Cv;{6xKYgf;>@X+he*=Xh11HBKbTvPQTPoDhj;OvnWqF4Ne`)%gSh8g$S<+sHT zKJSYtoAK~^RNKmCn_ml5KHg1ZIgIL)5tufsVBny2zmLrGdb8N1?*-MGby`EKH@ppS zei!GV9{*{|fr{kOZjPIKI{ymsYYAvNb?3kLy|&D|+`VeM`2P6Ot-S__n@>)>`Jgr{ z!=yl?zj0jC^rVzO+#MAPE6!BTnrgziuNe8p;91+UV@}&sm4@y;>fN5+8bcj0Gj=RW#!^1It6=gXyeqlzA$*1WfThvmfjQB1*pKqjA zTt4D?a!RZJEX|t}<0h{-sQ&Rsep}BY*Gp?hcx0sLZkd$Oe3nyCu_Rp}PB>w`WxJKP z>Zo6dKW^`A)u@V}bZWfP=6M+xa|f+A9$>q3Y?!NQT>8gR5o7wV9k}`M^ShOylUTF0 zS|`<}cu&+TS*`!|#EHq@W;}AboWnLKi25_^P5IjCwZZN;wjZ_FP8_bPsfiJ8X5SAmrz>*I_@bUJoqTHsTTYXVa!ne-yeVMP3|O-mhe8(ucyvwIke; zCpYx$)%h-X2+D ze2pDe@bN_D+6|76HV;=nKh_~#BPUm|ru&eGP6yr{`tf9Q@(aDQ{xJ{z`9p8c@tS%v zGfPQjNQKd2HKQMO4jYP$!&-s|8g3NaxnsKh!jYfd#9BkODzAJi8uj`*f1s9oJAcB; z2jlfOCntnd57xJ?;~E^=aDWqRr~gBk*h@uy?w(VmUBJrQ{2LxAX*0I1nAKy?w6w32 z2Tm#-w2~*x@=tmn-bB9Es||a6s!YKy=n{X-?j5ghIQK8>)w9pSllL#`T#@Yb zbQIs?vSr zrl^>Wt`C~e@9}=Prm^IOwoi`;LH8LuU%8|w{+&Fp?N67ul}-U%apJOBWJ~#O))!BU zo;xG+R(sc;Z~k}Redg29;m<7CN(&$T;vzu$U zyQ%|xUq?7RopY~t*`cj#Gkrz|o8D&#hXJ@X0G}%Av_qA9|mC%5L=(KK*Sv+NOP{ zOMf$7R*C3*RO`x`+0C~vU+b%_>^te#i>%oG?-Mq#Z)`oZpx#G)^wozC$DZ7z7(PY& zW7?gs-=}*__i7cMxv4Sg_2;nG2YUmZdf1MCb!qstt?{o`P2HdWag^Qr{LG)?s@`|S zZ|us0hTe}Z-s%^hYM1=J)&JwP(4iaiEsN@(Pck?Av#dQ_S+vt6d}C(#+@d8wc-9hT!fIUI z|0!4b6nEN3|CJ9dk^@V&ZabEg>0+4m{$*dTso1btJA0LVZ3rtaZP}Xg z-zNv-WLL|17W%5uo8BJ(aW|u~NME`5$I$kvy=OmLu)8_*^vmoyZFTJr7VqkFr>$|# z#0O(F*5zE#tyfoB$6avi%-3+kPoIr5oO2)a>*D4<>33mkrgQVg3yJRb#iPPr2Uf4( zRyquBa!&OWk9;yXX8WrWj!WF;8C%}%8(nH0bXar4*}>cQoHBb+?0D#|10+da9j=EZwd;7eSx@=9|XcWZOMwDx^Bto^q12>;`FbJGW%(|T#$ zwC<%R_g}5)P~1N5*X*F0iLWY}w9o#UQFY15?#?aOHlI-YC(Yt2CAVgMlY^@ds)s-E zy}dMQw8o>HVN=9a8BW$F%_)wT-9Ns4Fl~`$iI?bt@}4RC+Af>Ta@p^jtXMMHA-37& z+YP@$wUuj5X3l;)ZRncgQ&nD`O&V(#XQtzMUn4|kb3sK(MUca}3JtfSKSTZf^x;0m zkYn~E_dIxdLVZ>GfWIGo#24;{Zu=%$#G1q-476V7mMDqpgHm=`-f2I+p{>Q1)u3I} zFs}8#LZ86_M%$V%zDb;YF_bg7m)S_STa$m~+;7M-u&kmX%#R zT0igX{fLH!k^l8c+aYjO-(nR$WlR3JUVY8C)cj3sec^ZaNvy(9haCyO{&nf*ynEm* zvg>Lk4F$Mm+>ryFuyS;?wy`FCKP!DEW-pjKJ0u#;oGGQkwSpcF#PEvNFG__b%yFx9sU*ImN#c`!U6%(zA z3}3UaAd`4uiWol3N#@&({j* z+u-C-PeLpA(ctbRRB2IBGnx3R0C!lSF2j-1+wT8&HKe^iF}Pxc17V?vE{F#?6Go%p ziVk&G9{fL@PEBjW}acu=i+a6tw>WS>@o z++=~%2qS53ak?TZ?Wvm{oyts4MB~B*7*qv|zAOWu6qr=I*Hs(kg%~_eo*3!#Pttc4 z;Ee$qpS}*I$D&098TqOEDCAi}Q9HNTPK69`Cp0bO_+n9))uCyce0Zr`Qk8^27WGiG zn;xXmMoo}`c8c0$FE@-N$X!j504b*>pHz80$ec`nr!P&xi|Z7tr0PvYaJ%>rZv7e5H`hibj@D3pttS@3eIEAWsne zolXfTD@VwD1J9n*m0HMA3TbaBB*+mX`J{&}kGp#pAR)88dM3>S&f zcUcw%kjhFTH)YbogXlGeszTbulA$aaYLbT;V203KN)lzm5T&#U`CukNk*7h`WFc1* zM^Y6GC5k3Vayv*DCh1!`A&s6io576$x~?I^=8BL5~l@2=pWd+6gFmN)v;)hbPPlf!lpPV&)VwKLJ{$dXS9v zBrFC=(dbqrC#3MMmInnoI#A~!gj8?dL1ARfM^xg0pbFPo>mH z=tmw5fVQs81o{(a(@m=y(AR`JD-;;&(bh;O2=1oC5?~%c7z0y&0mLwr2yAfxff9~v z4j{&pKf?)4*WkGDq>wn1sF>i8IY?o01d}e2gf7B!CznS-4bOv#fr@O%%hVb~7y|0R zVEEvXR>8z*;50gzFo9|}p$~X4DU#4Z2vbSL7-9(N975lk5LBTP$Hp zmUYx&77xP;Qqz!raexOyaa9~K#+6?A48lU9L*fGGn817p4~sU5PlyXl2nkzYs3)Bo zvuB0J#GAy0goeQS5)=aSLt+mYghwaE1O+C9$3!Ebga>GhMLNwRG-pM}Bv5lqVw@Yq zz;sLs51D5OYZSHW8q5t03qg}hvNTG*n?r5%U2;7M1WiinnCN5{TT7K!>p5dOXG1+9Y6VQ!=4FlLL%! z=(Gt^RA7WdCoYgefDw+|kl+9#a4TMB7;%6RI#a!LkU)FVe&eAbVv|B>Lv9HuCS9~B z32=cM4!zt;n&SdD9Eo90)6NBMI1)on0)g5&l1-2Vf*64YW9P$C+>9E00}amPB5r7l zSz0~fMzVdApaM5sdLt(-1Ke=w><<{?*JM(~ zM(mM`RuDSss39377Wo;PpGm2FiEBaTSEOJh8)q3P^fdiMj4X>t^>d_)MhB^EV4MR( z=wKSr4^m-K0zhra)FvQLr4zMd*6c_7TF7!AT>oK&l zaHR^bvt{6%D>V!{p};v;sv$a|Km(W75_IQ~DoY4;HK0L;GRVyglu`DE#1q!}BM)T2 zm9C~8)$(8@a3NuD>=KX+v%h#q22zFFiGuj%Q<6~wW@TF7l6zJV##5*TN#fFz`4x!( zo69^T0;!hnYyyb@Z5q-E&Hj=VtK&zghs`oa149k9)Y$@`OjrrC7OhZRsX5b$g&4)= zGFqCr(j}m?Ebz_41V}AW@Dif=(#~0n+L9rFM~+)X7>SKc`9LI3;<%Fe9hl`wTx&8= zV3sFcBRXk-{^nt011ezC?>@*hORZY;fT4y4sSG1S9g)!42xNlmx|%Q=Vq}U|G#>2- zmHizA!Gkqm@iL;H4W{x1(B(W#9;N_E>%ZYv_lI6AIM{55*?pFu3bU& zMo9!^OOXfHNqR~w0&(!Mu`B{{@FmV_8AK2VAJcOp7!rJ(Y>*CL;$xSo0SMvK1F%!i zsi`9(WDAjnxio!**px^4yX1urK;V=yH~|RNNR4O7SOFmFS;_uH3KXI`B_SYbyQV@^ zC#?^q!i(1VTIeQ6?OOOihM9TW;tyVC7!XA`Jh2H8SWYCzGpUuQ`)rzDnMClJXG zBO8g2G96_o)JsDYQbfp5C?s_Yh~Z>r1~HJ#UQO`2OLpJ|nXn&vzM3#3XoCs9Tle5f zTB3gZm_g`i(m_V(6y%sRiAT;!$Y2z>7Cbc**APae{xWzXOCggOfGX#b)|s%?f*(ea zO$Ed-a&so^4zgB*PjT%UVvqtjsrIcQtieG7AG)Mt7NG~}(M9N+4%wDTpseqM))F>Q z06uidw6zcy6_EzH#E6bsbm=xy*AhcXl9aYlwU#g>x2y%flfre(1-}#zRxpbkU|>iNp$i@%_&*=`pg?PL2yMhQa4?d*g<6`J0|El@ zz}~X)1|gg53X33lIu`_~mjm*u2TX#tddNQc&{g7GLRT4vIz5sQj1NvP^E_}a^~ocK zAn#gq9#G+!2kt2@`oAT3pcL{6gN_OZlJR+jKux}3u;oGDl1K9hGdro$T@VkhYHCAa zG8a-s!tMfgP|_hx{}{gjU|i`oD!oDdj#Fq>Gw%a(ki-v~)%9Y4Wu9NO{JIc9yx zBhap@L1!WI6Y{wAN+NoYmIZ_|0aK9!PSnRx<8;Z?=qL;mi%SP1^*U>SiN%#fojZXr zvA9xI-+>Mjiwl8~Sdtj1#)5V_i^JP0g+N7Ss)PzFN?S>`YEpc_V9^g}bYjB%hlGRl zw3e0wD%l)!awth?Xfk91WU;|JiYVyKLaJGc!zb$z0Tv-N0X^)1R*uwokQM?2j#S-B zVX$&==#-35Sya48#1fj&Zg-@GMdV|cF=#-dCSjHhEru!Vx)B_w&({-U$=)-;XImN! zQ{%)&m?^6^5R;G_Tbs1qK(NV(O)%B_7D73_4Fu&(WsyV?z{G_RY;h}ua-l^~)kjps zd>(iRz)gVi$gc2rF{YBBF-^jH-#5 zpu&)Dksrb6ZG$2h^LpfhBAB+uxu6)NDo5A2L!_|xlN0T$VChK;Y<;sJdP`3)P?4Td|g6G&j=;GA(S|LgdB2RI&g-n9)yMi z6OFcmh4AJbM1XY3WyOTSC^Vv^Hwg_3bg$P6sIB*KMB@dir+Q=xqH_HIQBHvNK#X!C zbizR%2D$7p=J?>>fsD6|g769+2BTinV3eaW@iJgSWd6v*AY6_~29oAV+YomQCjoUF zg@FuSPpm@fFax8U0EL$sFcI=W$iujlr%o0I@@G@2er18?<^mDQuPX;*nTybFS02Xa zBb!nV1`!10aFvJgL}*7N3xk}xA~3g6|91{JNUaO6&M*rKg*dWMgjQrZTsUsjAy$c0 z;m{NpB|nxg2RVQ{W}TRx%@7(9q0OmWL6OKD`4?nipd)}pCX6p+_A#uDB4ohG;c_7z zaYw^+yKFHyiIG(=S5PQqGsO>K3O-uwWy`_H;v)y4Jd9x=58k5b1*Qu~_B6NyP9+xjRXBLDJBf=GkfRA#E zGmu$mXDAB;Tp@C#Ghxg@h}uBr3ao!J;s*tcVhys$=HRSG_6!q-jSmjn9BsMf%dx4G zjtm$)d@ECql0U>3@kZDprm_IzM1(@0@)g3VMdn}yg~{X?3Fd#46N<6iVA9$@&o zAu>lhGxSH#I*>miMjnV@JWSm}IqD&SPGkxf%t_e_DHvMWWEwFCO9(u;j2QtL+xa3f z4#WlxNE)JL@)ZIyhiT;ijEfv(as!O7}_JEzYhBkQG<30=ufJUVELpRxeORY zDwyS10&LoWPC*eF1}<2haxgI%ldzUE#04=w>Ug9)GCWWqj|{lr$H9n(cLSJX1|~5s zEg_g|7$@*}1G5oO6->PVT7iVSTN+|m^qB2)+0+9Batx2_Q360a(KDPsTQ( zOcQ`n5eoS>V3R-*BeQ%!b)a@J3aO(T^2i(!3J}S|;E@jumrn)v<;%goPjh13c;951;|Cn+(rV7BbFTus4=!V>?UL>q+qa=Vd59@nDz=( zh)qaz$Xd1jA6$54aP}mai!gSW+8H)3*wBIdUd%l;8(^4T0&4(k3SdlI9B^Uq zfFMzKb@UdPi_GZ^Hai!a7-;Xp9AaSGV-o{x($0w?ac==kcIHyU1scJXA2=YenF}yX zjX=Z;og|d&X;|Hu8wlk0!`3%0PYi216B#rHV@ATJ0yddgIqK}We8X@Q5|a$PugO%V zFmGu`BJeL2KTLaUe*_mHVV}-ySO{ht69%q&3l;M!nOYn!se+?}i3`U}I&~FnCqVvC5Nu>-LFf{>f~Xt} zex}9-%Mf!GgQ1C;l`tVN{Q)pOdf!ftJ3d6jn2ms^O-94gn;;M>HfH!NA*NtKu``_m zY=B8ORUO_2HVA>~DS{b+g*(7x7GPF5AG8W{dcsU(y1W3Fy3#7cFqn&AgJXjRVA!DH zgQj6lCm;r$l$WUx>Vw3P^W zU~2@5%-bS_#e}IH;Yb5!4GCHJV1*+Om^B1}G|V&uZ#%AhgwO^?HH5lx81*o% zTsMIO6SE0H&11_pm4xN|_=|C8korWigxAY9a`e840} z@&|<}iG9ftBgCd1g!?hWLIfdMrVaoYHcP;o#MT#piKStOPAP!SWGWgFtcr|A;C>23 zznG#1cOeE7fFXvJ<4g7jGWH)#2y`u5R)pY~5`s)H80I_^fy0}rd;rE=DPb8B$G2<+NjHz2FN1e!*=NOb8L;O&VdPtg4PQWnT#UOqG zoH%202P+K5od6uv%yL5PFb{BN&OD<7jvs6`A!iVF+6a)bpgj}><VlJpLzNK!I--mfKlgp^PaZ+L=_8(LTH%g>H+EoGtnP=nB;RD#2W92y5=!abwb4LWY*e;p_ z?pp9RF)D;u0COz|WX!(i6Tq-A6Tq;LID#P?f?EHjx*vepDKi9Pn%Xd8u#^7_*Ey zu>N7YAJ`9>GXtQ2jD-yWMqRF!=U6~pcV@sa6CZGC6CcUHQ~UzV#z#~$=P~FC7+nl0 zz!1b1ELdTfn-!=}deDPvm+F7GJ5ODfm!leBm6bQK3nJzb2a}1>3mb%R>la(?K%-+i01m!0loZ&10K{}Zxb-mI z55!=)p9fAUrU3%RGIL`B-T*dpH^qU|@LVnz=eG@Ru0z{aCZ&5j#_^@RWJat=>!Zj{Wd@h_*t+43 z6uXcw2e_12WxEa*R4ix?Fe>wmxj*U|359?R+DE=ZRFLTn0~mJE32?zg#c;_!jVQ*A z`5vG+3<|6`ZZ<#+jky8=wZY#HfdyaBcTI+rH6?h4oxxi zAdGTQnM^|yBKnv*0*@(Xxe5fB1q1h0IGCtK=-e=aK)5&3v3rslnqYJZnY&WhN??0^ zpc*?q0Wi#siVin14H&Rwu`Rq96d`tA2VmI75@1x4ZP^)tV9coqFe;CWd^xy0#u!^* z{UDt}Edm{S5P(?B7IG?eimPKu7GX*X%3*i%U_*snaR3+`S&(*##L(n|l4n}30OK;3 z5`aMvO^QrABw_es{f>q-bK3?6Aa*c~D~1Er|DzywQWtbQwy^{l91dX;0~3NV-_iQO zRLcOPE)7!hmo7s9gfKO;LfDYuFz|(9<-k*b!Ttwx5R2+0kTx_Skt-PWOk}XJm~$46 z!(g@@K$xK!*unFep;&-nJ6|q18ZoCLbuEQ4X90#qt^o#nZYI$X{KsGriN#^yK?GbR z|4#7>F}FBm3B#fn0K*OxapA}ZbF~8)wh;jsSJtaS^*;dlOwTsJ;36D@J8(2IS21)s zhw0x(mvfjWbs+;kMERKY!L?rIh5!oUnh;!}%rFex_QB4Fp&LNVMGRm(W*7!w68A0e z-yweF>SAgsq=7N2k-Lh?38*f-95`IDa`GDyB!6_46c-KnMwrtM4$Uw_v4AVWB?xYi z&M8K@=;0hHzHY#_MuE>K=RYNM#ayx*z^qas MMvSm^o}}{s04CzSIRF3v delta 59029 zcmZ@=c_3Bo^Y1RlzGP3OkezUMB5TUhhU}>*O9~+^ii;>wp&REdinOW7?pDfDiFTxg zva~Bn(x$?1&bin774PpKp6#6H^UTaM&pb18?!%TDhZ|?4IiZy00y^x-gASn&Eo2ja zjL2<$?{T;9>fmPkM zf#G0RTidy&o7_3?e zX={ra9d_H!m!FBEWN_ILiq5L6+ZE`Vhp}5+4V}ZT-n+g0s_Wu!ueS6&zOJ&h%s4j8 zYUXz8qJ{nSrY~nW-|ceAyL`vsSxiy+-m{gBrv?~X=WSiq@xjlY^j2U-fMwP~_BP*= ztQ9w&+_t}K{eGHV4q^J5J&zF@q4DOe+hJ7#c292)MOuGSu+rOMBtKde^JC{U^103E zC3Dl%?Jk!JuN*Gw^Y@6;_^P&iW=Toqf?27HxX zCRg^9AcM+g)NwgUrc9R@B1E8}QX(W7GR25$$SD!gVJ``tc}ePOuiMwKx48k21wCFj zADr1>wQ+hLex( z{$V|RRsX4uf$q)y^*Q#_TcsH5jD{oAR_s|R=Q}TZl~}+3p7U?~OP)W!&o&;u^L?FE zd3L0!vG{MF&!5@vR~+tV{b(C#sE?{PSpR(>oPwJErguGYD*xJLa`UOJsOha%+cOIV z1Kvd}DU8106^G4+qo+R|dilMQogS3z@vN=fwEQgjNL#Ui#E(+a&A|4~Gu$~h2P7p+ z3QsD&{cT(#**X1(NXN9*rV-n?1}~YMuRnXgdR^~X_YcZqxuNd@vhFThx0eIIW!;6In8CPSTG1wC&XP z8?7HcuMX%f8@v~NUE$%2N8fC3SDhEU&;9-8%$=0_AcfTGgd2kc%)RI87ymh%^60%U z+iY9JPAVg&>StuM7?@4>;3yb_rxSP4$ruF{YZ}Dmd;bsDZj70|LX81 zVq3+L(&EtrBYn?XK7QR)YBBg-ob6uwQBm~JEu!SLh#zrT=gY$Ks|xzx)VJMJcrd%~ z^TXyV%L)y)9&0N45-EPkjQ0AU-8)Mi3byW=H#88qXw}&+mw)bjS^Up=lO3kEkGKLu zL+hwXkN-p~zAo8i+ITqXS6Y)3XOXdUaQN?I z*{h4(wz8gy+U`*rH52=hGjjRIht2(6RkPPMsoHw(?x7!g@h7Uk!(jcz9`kReLWLPG z9)7>kYpFb3LtiPbxnuNa%ZoFgXUFTVNJKi(%hGzA`txrSALK`SFC$8xT&MT>*p}zqC4MHkP8oP9y{2cQcUoSQixQDtOJ-XwiZxY>FTim-3tjI==)p>68 zVC#I&_UMi~n24-$JnENOoxSw_%QT_Zc;v#SwPChmHXa`py38&p$0?}!l&mJ|=tIukPlUT1J z^ZMG$G;P&~cYOm7*Q?x_8W7efa@T{FkFZNijMmBd=zaIHUh7f6L)S08OYUZi%;gix zK$A~Gna9=~YnDzKo|U#>Ff+M2-an3I}@r9a7hPdNE76$*pGVN3xq_54+f{ zxi^(=eB5~Y`Gd8daZRriSoFS* z`sYKA=SpftbX^jN7i>AxN%TsCAHOK=0Re>En)pQ zUp)ys8^2q^7liFRW;(@{ekHph=jk^d&C^M-{*Zs|h-HOx$!qeHSdAn1boZ%iUSu=Z zWo~?%IaSZNZb_4Ss&0o^fo4F6#M-$s9aO5r(oMQT?O!*>-8?Ase0qY5efP07Fwi^A z;}rQ*@|s)1^UqqW&5*trAmp%YlYwFTu-LlH?Cw=k1x~~tyKkOz`tsZhTafO)QxZFv z>s+Q)v9h7ElZb(nUqonR z_*%aRWg6P7P1fLqNoSTx$Rv@)DMk!^CWEF-V;bvIIYqMaoTBMMoH~V7oLV^{IT}@; z!ZcQ<7#r);=oDodou+R{gHf~4?ifUXGc-+<6FkjX-jJcsVj4j=L!WNQQl?Ru`b-*? zQ!J~*Nmi8NkQJTfS?~rXOPNZAp~mpv*ifHJqhLb_Mw}EyFHZMNK?N$4u5UzTDpL)O z^l2<(Wh#rI&oIJ9$pNex9O`sW35t=v5tFV=Wm5F%l(8-m0+n-l`Z_V1K9dP+fye0# zj?N4%PVWpU&e|ECl2mMd8daGJD`HTL`EL~AB+QiJ{F$+m%mQ>A@0psMnMzWejG3O2 zG((m?i^>2f@J=cVdjL&MK&EmoD~WREDtQQED`5bD{YsjgC9|YB^-3$njrHlqRAmZ_ zuFrzkVULU^!Xv%2L^(%9#E=EbUNj?4oSz1f#^Sv2TTWo2CH7#laAuzp=5V#8(KL5t zsx)mP%a|zT2uXu;P+MBo5bIO+7BMp$V>Hu{(q&Gg+Ub%@F78n=MqfUH6d?8pj~3$N)d zOh%^=O9|NSl&6^-*FYjK|INT4dhBrVP*`gr^^?8H&;B9c&9p(RHE4f7OQFXe(o&KLvWzj|ysbD!4$k(~;%M+8 zvT&KVi={A1Um+mRFd)Gc-BXD57y$WB55%U`D4UPw**mROBo{tnBa(O#*?&soQBxpu=A+ zbhZI;D$$UEQVfWTIdReYm>3%nbp#CYC2;z7&dxL>lFtcqz%OEL`1(zoL&M<(JOUWFK@nf{IGsVE zz$xHKa3IjJCCTv+*?AG_Kq1w55)@Ijl>}`96Pt<~xss5vm|%#0`a-mnGM=#KjnS#F z>Cq);2~t3lf6fwgI7WWhhEYS?28j}6sm$C06f23HUyP$dzP5O={jf-Sa%ENoTe zD3nRZ6NQ4GPwJE8k3yZGStu0PZ+>J=&L%%e5>&8_g-%~d5aIOr*`qPn3F7Egdy*jc zQ3WAYj3@4L6zU{-r%-W$|E~!rNIZo~MWsfFnlf-I{G~Xsj@j1<8YrUz=s-o?t`oHW zC;kKqO36cH$y8$ioNi9iVLNc1EtIH!P}JljnXMz)BKftq$4%5dB8T*l1Q z#|QH>^0ysbU1PD8llQu$p~B^2(mj6}a?{T#^yWOzD_;5al5X6sZe2V3AE{b?xoPle zmb_=Z&2kC)<@%1{m+0Fi+?lS!-+$dqcxrU9df+BK)NI!75a(YZzhkrt**V{zEMyFq zn#{ZqTK=exUiACk1FkuG$6)Zyn+n%^uY#0I8=|)kKkHasR9#i|>p_Ob?p7-|0oiTA z@^|h%GN?IQKi~UjuT|WVumKgxXL=jIY+h;5xpH{W{;1t61yAen`^82gPT{oMotn!J zsCA?T-q~{1%rNw<;;gD`uX932zpy_ndG8hMcKw`p(MaGT^+Yvs~%raadF># z@5lMM=|i?oXW!Z!FPVP3`+C!-qR{1x>qE{hiv!sG&whujjxsmBkeOPL?x6kl^1uN< zdz<)<>aLF>-?klmu}w>M?ck>1^;X{%o;(>Yoquor=%%p47h|5de3vNOyDGSS>#MYC z_Dqx0qpL^WXEq!^mq=C)3EfAMNfE!=u3uHQC*f`1$+&MP374+~^agVG+}*}CKU8-o z#^mGgZ$o98POIOd?op06o9WRy1J3ONes4wG2v?riyfB|%DHv6tZvA+{W6$~h)Qa;R zo#=sQBc3cht(<+%_xk+U4}JuemRi4G-__#H9}hm6KuXlV=OM^V$2}*7XJ5zjP}iH#q(CMNdi7)YoqV=iQ!CIn6BdR&M%hfh`Tk zH;bNxGd2NL$8ea@wZX<^Lu)7m5zj6K6s=RVu8;vUyLdT{Ofih!WJ z1FJKfgM)K+mE5~lP!%p-9qnQ_byxqkYqtx67gF_zY^jHB=M$w$(lxWAf0bmLR_=7w zdrgzBzhn`oukEF-Ds4vJ=vr+Y!mVGGec;P$x%H!Swa0f8*P9J3#-{$)&xA#&n@O@a%d0;2(2hD+*)-^w%A~Xr1{UQ8 zOnIIgaj%cvKrN_ZzNedb{PcCKU-;G5Yb~d6Sq}ZdE3<;9I|eRFXYLLuEqMO>i{kOO z(jI~;H&vUprIjRQ;x#w3Zw{B4hqyhvbz-AI$OeOE(+`CU8mzhZN0iJ2lW8FpM5}Et zzOSzG{rT(K)AyDJ_UsobA4F5Flw6#G<`W3s&wc6YGdtK%s)Hq%t?ipZ@-K>YG}t*Rhn}tYjqZ`*iSi;X}4oz{h~Sox;I8Z-(_B zr;C~eu31ue@o)*-x`FGhXnkXMW{5{o*}HX=@INP1)Wwvz+1sO5D>S3X!*-!V(you5d<}atO9F{le>?u>N?NaOKw-tMW5cz7WZCT-*+H$L8-nH$e!n;U zQQThexNqc-hx4yrN8UUjoO)YoaBR@{P;D&bbffdNj|$K4-+i<=C}-&K69aZakwuoB zkg#rh=f}%$k~^BHXH2v+3!3&xRxs3GT@aI+=P#6@vFP-dZ4P>2N4_3k`H%7L=_iP! zgqA|<_5JoyjjSUrwA0n6P1#@8Tdp|bAZ>cXJKmsL-QTZ=#Y#nJo|p4Qvu9sfR< zFmEy0&01ol@{+F3fM#d(i{V3+zwNwZ4t>|vxM7oYS|iA#KmSjU{6&v3!$GsKPv#%yY#xm4MZBJf z&TKBdwIpS9S*tIhSx<{|J0)Rf&2F|q7nSDbuy`A{Dc>?{`n=A9ku^(783U!ij?dKe z`I+GVVSdHp$i|^4rrU?JPx8;JMLd5w<)5O+JJC=4`|o#bB<_5^#ru1VX+ps;bz$n_ z>7utA!d_S$9z0!RpqR&fGxT_^_}S;zb@SZJGdUkjdI+=c7<%rhHb4*Tk^XWvA}XC- ztEry%FxIqu@o!WtVx6u5HGWw?Z^}p+%{(3gltMSU?c#M>4)AZ4oiOzYCp8mYH_ha{7 zx24OPb7WYu-^yjfN;i3a7m;fCBd|2-;;zOb_RzW{!Q^AE$=gm=9h4n7^e|ZQWn8AC z)4qpP^97nV&zA@3C8~J7=uu7_u^7;?^+|HFdUvX6Hj!+QsFHUiTlUup;(eurqz%Pd zNM2y=aoME2#8@ZgF2j;1;6IIr}*Vq0!gFNGu;kua@wGvfcsgSkB z4o}gx^=VW~i+UeWNbH3!h7qiIgR&8&!rgYMi1p()zjjXzlaxQDnlIj6AiH~G!kSY} zp)zXPg|Fk&Wq&ruW}MSZJ0APcsb|sML_3w25(f`jnF}=8-}O{&67fvlMm%&*)BQ~C zBDVHd6LH6LxoeIhXJ2w6g%+MWw&o~F%&BMVtSc+#*Ik~{>~OqmAT#Ey@Hdft9IKiq zu}I@%_ZLQa*^GZTQ&-GlPMDlerr%Q`!-iMp;!lSEdgiR3z3Pu102K)U4+XRaDp z5^lA5&8aOFPkZY2K9cdBQsTCNVkNDssfKudR1axcQ-53dRxGF8ZVe|<*>!36{*O*3 z!W+NjLbG;k1~fa9OAfBIpL&uho%>Shf@ktYf_g>9lneyWa`Lina?jIARM|DPVg;Eo3wvzIloK~L&l+6hl#ryk$;ppa zE)ox|g}c?hU6w9H&awgm*-{0qR4_!lPu>;|oKG(KyphB%vIYLk1-OoJ89JKEL7SYs zgr|y=&xRA#<J)LpAJ&X;Qn0b6l2n_op6jHJ71G`wTF|m~0)Jq>ChV zmu0oxbxCuRtfu@K?G;8F-tRho#$f51mNzvnhv)~BZwFX^ZCj*+8L_ih(F=}Zmnra) zp-F87xDenj4!99ax`x7y0CRGvQ)s-)!vB0N6zYWg4-CaFKr*z6cM~cLo!dmvL~X7U zq?Y5?d1V844^Oyt8YweaRPbCel|v#oZXEB)q0lH3?-diCq*4v_DaK6Hs);a1eqtZ^ z;FwG!RH%udCO4sv!eqj8C_#%PL!>gn^W=y&cah|XbS4_M2QDPp4xuv^$tV8!BX?CT zuKDog)XUr;V+m6NHOo#3pfPlt2B>_fAiJwwy`0e=f_r;Gv86kKQMj z9{K$;%y|F%QC9CG^HC+g4?V{z-ZeQV%e5U6w;jFEe|q)f{z~qdju$==r`jINWu0H{ zUGsaVY4DFbm8?D2*L(bC_di^C=hvpH`LkGVz6URlye}Rdy7$0gpyqx(cZPQF?~e72 zX6C`HnpLC4Q9G{w>at(B>$VyyAe+#$xoY+BmkozMEv%Dtj{C-po;Mn7?vYyZ$LOlp z@I@W8^H5Qg97iasFzQpL$n(hL9xX=Z1?~G)?6cp4kH(kOIGoTs?l@Y&uAcp#H=kn#yUDWvZ>u{f8^e8gRkC5ZXN8u+&RoX zQPOF)vxKsWY3BVsJmPHlWp-QtdTv+9!aj!-o>poEI{mZF@>GiR=69iP9zeD1(dhtKHGo$d2?y2r$fZr&DSy1`(&->>K>5BBc| zPblYAw07leoU^fJf4iCLH}xRoi~aNJ)1#*@`iiMLJnufJ7iPY8v2;=3U~c#gnN!mo zuI%?bs@~bKy~XY&geb(9SytYbeiB9vpd6C0lOKL{((jh97K!2hH9&P&ebe&33>&s? z+HK!_;kzDF88(sf3+|=ekIy&0T%sIAU{mB5%=Nh)pU+s~XW2T>$$jd#<0^Vdm#suZ z^FoTR#pjy@w#YSm2z|5Y)%&@_dc9skRD+R0_>ExGvr){wcbN)uf<%Cmm(~AYhNM1W`hH#^>(W*Pq3*`Tj4&{ zj!o*-XgxVcBt>OzVB(|jjN^5_w!y8w%|#L$^mdo$G3BkNH?E_c+j-8gkdeZMnmWwUl+@>-ByWo+vwzoa%Wy9zs1|WESS; ziloGBRlBpyu&5`|rbhE*Q{E{bQ_Hd&CfV#an(lLxZsyg9Ouw_dIB3n`Wv)uMzsMB0 zZY%96id!=z>?$+Y{p*vqrvc)DvVnfhvm^XTDaV&5l=VoG`Z`T@l1sW%W2dJaw>9ef z<|^jmN0C+9@2BZ5l3YB^KC$#8*Q(BUam3AMzFWtW!N)B;?qN;4E;wvHwHs|SKi+tLI_2oVQbGr3R>eQuf`r1yP zerM^XxmveFsW9PKZPvS-=Aqgy)v8?YvJbw0)_R;g@wuP7R)r z+5EWIo<-`tcR1_1d+Od0xePzei^#z(+bgp*=a=3vNyxD8UbO}$@m}u1J_~W4b#210 zP7{w}%_@54b@SJh4=i4hd9=GTtzZT5$ASB|oxaQqDsd9NqO7BXo+=e}6&?Za1v+VO!`s3CGlGZ*$!m}j&mMr<2zbP}PTS^ETQ^~qM zH{Tg(7W->N$!p!QT=rSkXoG*=8CCa~_%p{#pw(3t#wspvCpl{T>HjUv9;!$;H=p;y zJM)qYD!KIT>={zSA57#zi`>{#-rml!LgU&9vIGX^mzJl{aL4BOm=A?U=MenVHU8s7 zqhUwII43xT#=xCiD7l>=4R6GpYV+F(G6V)HMng1+;5l?m=lhe16gut|=iYoqND)SR z+X-Tv#kO*?6#69BI0cRULedoE13*{5B`9J}c6b5i8b=$N2vdo4+&2zSPxQOdDd@tt z1Py{AesZ<_AYgF{VQ%YN!gXPAVPc^Qcxv)Fj@FKhn=@p9peTUP$wGa;k~Pt7?bxI& zY>6Zaop&q>4uIQGDGL$gz8D}xA?P)CaLHQ`Mdc`r$!lWZ{(iMFs*X9V8Dp;Jf1S4w zi(0*L(?s_*>iLu43?A1DKM7jkXkJZHo6At9Fz~Zm!~pkVGkA+KGyB_%&A{EJ|GKWZ z{zHU0bnw?6*zpZz>l00h3>NsUjnJS$a5CTBsf0VQ(WJRVan#g+xEZ{;;J(&HFmuBR zEz&1q?&}w`c?%q8?J&pe5ibbaF;S@-hyquELKGu#nqsxM4pd@ZE$a1yAdQZGAyUz^ zgG4c$z6=Uag6;t=#~PvsiF)WipFu$QzF|zZz%fjuFj1d-BpI&mSK>Nh)bR~LRhG$f zSC5NX!l3jY1g$xf>@g-L>f@ysQ09|0WhoG8oX|l>9WYn*Cj+7w8vTu|j7LOJ)(BAo z3wm+eM~M4{ff->B2&yu85bLj~DTpRrOMry~Kud&4Jn3bk%~V7S{q+U}iD``Q6@MX; z1iomdG3qT$(v-%i`WHgHT?3W>N|Zpwn+Xe1MHc})@WxdaA)ORK9fV2vHj<~XCU0aG zelI@Z8_j;zhzVD3f6tO`P3`FD*uLBym(si3B@>6E|Ci z8=*u>6dqG)Mw2OF^#4-AXd>^8_$uv(28kz-Mm)W?OPC}@P6#AAoNXSE!7ZTgdm@_sDwEQ z*QyXEM^(asZb|cbh_MD6GiaDg|6caF{!edFDHCLj3PB|t+mJ0E3N%#O0X?G3d3ysJ@fm9f zvIAmKP#t?H2b+P|>&cTG(fuw066i-~vJki4o|J>23ic#%PPL2xXANCa9xi2*hy?qD zVn@K_v+Xqz+%1IkD$L8PY;@#p2kfa_FHjEnHF=!Yz&hHY1D)=Lb5M3A zQ0#ygE^14m%oi_o-bz>(9*65$Nvap($Kj~_tMxb?5ATC42hIN=8Et|+03(&dNpR_& zxI!8gUA_&`kfq`l(0H)WbHX3M&h!VcRJ6k%z&3gTdm;P55xwOP7){R+gt^-TNa`XW zn=f{dRORTC`3hMz{|{dwIp%MwLWC9gDoe#}p}(*gqh0`iq8g^sjL{{dWI#XB{=s@4 zz}5m>gl2*snzoosL94<6^IUC`Fn2=)X^Rk+?w~45=WT`YRHb8?1DXOn`9Srec_$Z@ zjwcGhToZIY6kw_lz-)KENcG0yeJq3@~1V2$MkX91agi3<}4EzKlEoR z9~#AfjshnpOl=+I$49l*@s0_;iB1nmRRj&3+Y!fX>%Hw!AK_!Yk_kS6B; zq=`gj@lrG@vq`rF&}mt46k|CWa?n0W<*;z?*uTi0pWyS1#o{U1+j)GtK*OFBFzd%G zK3$*zc&3GR9T`)sg(rYZSJFX>y-$+d{#A5i86e}hW5ic6O({1gVn4;rX7M|o25}tZh2uJ6fLR^SuUH}Gq^UAIlfWQ;C1B_3Dc2wj7uJdkV zWs?(Q3#+`q+XBK||02@yf49J7qksx|G`I$zys(Kz0ToVq>==_Vo~Xg0<2o0N1L{QM z0DEK@deBHNZXB>KLb-@n4!a15d$~CJ^H2u8NKhiJMA3@?9W=HOci|=lj`TD`Jas}tmWC(bOz6QC4h_%8nb5Pj4!F=) zi*KU~b%0&74llohcA0(rZffh+jMbn`vZcCfv9T%k^~z2T?>yGToI5>N2d zm+=!~h8Dml(cl{iNJd1x9+I%TkT7@jA*mlsZ+r$h++6s}j-`QZg4wbEK_cn|bE4MEe1HFsnlbzwZ8pif5bm02u5Zg}p(k3rMl56PU_C-LUeQ2SNjmL@c8XeV0$x zTK0J{{JLCY+(f6c6AtFB$SC)of+Q*x)Fc@-i;c&)zg{~YNLj$)gU<_*a zg--)`h2S7YgZDg5N`nT=L6DV|J)o&^6Lsz&$Vc@vf)MxlAgM?MyGg6aK|bz8^-ZH= zS7{A38h*b2wQ1=S*N8U1fkdXgBYYHeI_lUCSxz@$Dx5XY5H|`aevN>{($T6>fLQef z=mGa@NAx4M=`hQ$!iDT6gq|H8;|nAkPq;6F&k4?6;0q5FN)aLBmkJu#2fQ7|n4sjb z9^MXPOhgSmdBWh{nITNZY`uFHU=6GgCd)usUIctip%@U%?jzD5n>7_~8YLoRA7S*i zFd0`0^0K(!<8P5?poA0S0D8-jaSs5zAx;~tJQ{9Kj2C03A$ngHW;-fE=H>k|(cA{` zOwe%e#)Oepa)38g7_xCOUXo}`NM?g8FbL68%t8PM7kEV`ox~XY5t0_dvz<(o$%ZNAZpAegNeXG-(rkNP|$b|3JvtIHXjf)@OV1W6M+p)*8xDHI%G@<+`-B= zyfUH-Wj3#Dj+Kwh2GHQG;N7H9U0t#S8hj5D0o!!R`M8S-HU@4q{LNxW&V!BduMFO0 z@>vX<5pyZgCb|`9Ms##OldLH-F$ovz*ot>dFs`wV5+*>rqyrG~O>&e8=s>LtaTl}5 zjzVK<9g@f=ZV_Wlt!oP48JJG!N=yC@G3F_8&@L0qR2uYP)I^yqK6#;mV*#^^TL2L$ zyp3UF0ULvY3R=P@Ve`tCmM}(_2?z_y$WGuZgxk0rx5JWb0Jm{8{R}u;4JW~)8{+WP zc<{!V0(9JN7$@&A5_9>=Of(Vbh7`0W2KGUNB^me9U=3g{YM@aLI7ZXOWGz60IW17F z#TeN{fT@oclf?vxhQK@=*d!eb)8RUnPq$cS9^L5h1eQEXG{h6}!S{?GB%BK(y4=|- z$mW>YgTE2?CHy5QFqEgP_^%9I$$upTgRxi2Otcf|U{b(QCyT{=|2p!a17{I7JJ>0! zfV|k@!R=p3mJ~t-SAsssK0}rVpU*^TfCt8}YD2&n1bkJK99DFGc5G%LSiWPGwv{}& zfI6!0Po8vzz}f?$9X;y@`T;6=SY@U^ukswLxbiFV0hs>sCre?&mSdHBUH~4GA9Q{I zlsd1&!PFZ-eju)sCX3L-xHw#19}u);>F_zn-}Iy!qwI+P zSP8VlWk>^U^aru|*U17$7DT~ixz3x(#hAH+@mp?k@Py6_o(R%;Q4Mq{n@?;wwQzpZ zCRlQG=)fdd20!t~i#~J=#Q@zRVsJG^V?!Bi86#mxNC!KM4s1=&A?u<~+yun2!(5R2 zj7=63LJwU+q|r@Y1Ya8M)u<6daNAwjjW1FCX)rw zI9;+ek|F@9Bmop%w|H^`64qq0SG@dL>3`o$SBk35(!o+|C)^QCwP?KW- zmWKYp%8|S>GY2#s&piwADW1o@DTiDuh<-Q*s6i(v$V}G2EKCDysQ(8+aewo85n%CD z@Wk(H=qw7lI3I{pj7@`^l}7onW3Z2ExL{%n;%+7tIr`+!Y5*qoUCn>aK5={SzO#{~ zPdw%6@W~ApZfxqrv=px*OE;Qu@rDjeUBTtN1PI5(RFo!)^2+I@0A92dxXeWFltQ}= zuS_n3b~dkUhLtbz%GH9kEvgoa&n#!(TI1X$QVslzMSS&nu2uvdhUdp zRP#ju9>CRs@dQsG9Xco$a1ald@#Pd6;0_3e*HzG^P=RZo2D<7hSsJS-R|D=kEs`4U z2u2;;$6U`<)#OitL^{|35bujKj3Y5iZrsxEL^KIz1_cqVkp;Ai=G#PC#87a-g5aBRB5W~ECwCaO};4z zRsld$oxJ1WqJu|3Ci9yy@vhH+yFLb11`i>OpB_5Ev8pLO;eLfZfEi!1jEUg_tY`Im zSY}%ftcrpj#>&#~@$y5gyqH%O|A3Xd#uhd7p0_ArZvF={3$r9KdV^nJk~DxO#o{{u zu`2vRKOQ^{UzL{h1k;xR?O9(z3MMWJ+8<%<6YMZ-yyQ24oAec5hTXS+Elm=GZpdx^ zMoz?jQlhzq{9jQ427J?r9SRIy3PQ$m1iu@ChZ>6x%S;RaFu@ z?rRwDg@98NyW6Vs;g3@r3_RyyJi)=@(S{}AH~7EW4bdVIL@VP8f`^(Juyx-<9bGGe zNWsi=M4^0?S3WKe(XO6R{#_Tf6Gd=KUWofs6fqYjGC)~kg2791_zNck|1wPDKXBr{ z)4%W-@%AQ54#Dpd40!EVIYet>G#+c$mj`h9a>!I{?m$2{Nt~b^P=oC&&l~g%1_5oA zn$r3;|$|AIApGn9UpX46C^CD{{&Rrl>KGFNp!(e~3naBSaZl zDug!9M)>Z3=$N!U`R;!{7tm@Q{wlz^kFR3ldChLI(Ij3#yP*yU z$2o1l3zhXcfcG`OassQQ&PI6J8)KDY5g<0xMWhA!CkuW-|I1v%7>8LU{~A<>1E`aNYVa#*=5E)3A2&za2;lcwk&_0P1yyISw$@9#kwHAC%z!8mo z|1D!U!E$0i2XF#%VCejnK*I*C;f*;W2~)GsQ&8he1^lC20t%a3BDQ0B7);(bv*ULq z(-0zzYY|NZcj}>Hi+LcJ@U<)t#02XP>wwU^2C8Gp69=pTLhl;rH+uxjGUGacXiSiI zY|H?(qaGGOC@d2N?QlSN4yk>MkuReB5F>N)@y&!g_BebqJoxzF*v0UnK@JH1DK`4i z9e<%PH_ZcS6Gpc#9@_*=+*ALTTruHr1WW5*(tlbv_EsM0(e-P2dWT72p&IJ|_zn*q z$+3nt>tNpYwIJkBIgItnuH#i6LIvoKSx@kdKHBX}mg9!{A+dt|JQyZ^82=3gLb>DC zHyX@G0&a7h{uBM~Oz6NPsqTJ!`a=WmW?8%rgbmN~fvXAb^N9^X+J(@=!3ds@BnQ9f zFi{4vYY%o<^JQ?{*}k?=T<%`;MX58bANpZ9|#Nphm{t3dn@c13YxqP z$VA$PU`ECbtURAr9)U4DKhRwG4F>+LS&qyk0+`wuM43dL8VbJNHPXN(6k*$ z7`kW&jAWpJJ78pPBDC7?L;_GkJfh4=lNUlYcOtW}(UPb@G@^I}v#_ zG#c?lwXu%gXc*!d4X@4xnCPu&WE#492O@<1l!gR46b*yPY{Uljh(Q#29YJj9NREMy z18n3WI28~T0t9MfV1m=Jhzn}ZMyA2pc*90JE)ETRZaB4~CTJew8^&(_8v z7U-{7WDcx$RvbJFFJquPi6W$GUKb-(yxsOpx1>Ls`7V5Pd znTfh5!X9piuQ<4=yAe?W$h)#ONse2*2N5KYnEc-gK<_0XPqDZ)_A_4S<-JG|upB?5 zVv-Rt0%q69adT1-Ljt;eHzLb@wGTlEX!agN2K~Jsd4^t00+b&QAg$=>z0lp7is%#2 zz+?~#`E=wGx;F(%uhNlX^!`35ojHhHMc?g*f!jEsgwQ7kpqO(AA>$K4Zq!*s4}F<| zTt`Xi&~qshArjE0bV!7|k0KTXlyeY~L+2bu>d|!^M4mfx7=#v0J_K(rJ_b)N&qBVS zc^OdMnGDtVY~%%cG8103^(dlFKrf^4w0ahzi#|Vw45E^UF>E==EA%~-xb3-!I|26r zpf-8PXVf|y)@XYIxs9$p3IjDxB3IDtV^I2j68VVU&w+RSIEB1L>vIt~?w8Yu00IB} zoGX?OLX6T+KtDGF=91Wt2&0i_k;|yeNqE}&9P$!Z~|&u27;)$NI;3J zcLhNSY<%e0+3o}RJxn~54)61U{2eA9J;y6X$}BwV2(K7Jg*S(R517yJ%Pu@M=mX|4 z3(ud%hJj7Y!aad_g$@dqKp~g4DeZZx~;<**EHy8s1{xR8i@9vPvO5kkmTua*;d#8n zrmb7I2IdNX`ULg(9h>%af4WdN{~|KFt;>YA_3`lACwGUNH+(yLu55!_-@J-h_Du-NLH zJG}bBgDE?5Plz|(djHCN%4>4*CVFM$NKagu(v)=@g8F>FE5u1wUFzsc_^8xprn=E= z=j=81TbABmdisF!j)2-luIiM%?9ZDk>03s0xiUT1#fxd9N%S&WG}8*}%@ubF7!l|0Q@U3Ww{$5y z_LLp@E+>*W;`Qz3_wSEqvAZgNn|!D-ip@S6`}pm?&w2&3jh7rX5BG}Q_~P)$blLS@ z5hhba2hBhF>wh18AA!sp=}f+G4QA`S3uO z=9e1Fm+X|jejKPG};kgOVFK(##x@kyZZ~x zqrP&zJ06Sm1d5j;F@Zx{XAsz8dNXH^zH}}lAC9RQKL0-ZIlC&h(tq^!AM0Z^+iBYN zjT_Ddwv6^NhfVC?TSo>kB!5f#jymqSa^_MegMEu#w4!n~YK%4*&&c*Jgd`uOA8 z@{v2A(Pypo%>&lWHLHIwx;46eWJhD1#nxQyKezLaYKIoPc=}(C5MTPK`{F+#p)AqY zYm%bvu6p`Zvnx85)s%mp`$^;kI$LF*IL9=!aF(d%_o5xt&A+dAJbm11?i~BBOE|i5 z{f;lq%>4G6rhY-H;vwZzIYBXlm;Yg-&k|Z*tb6>lYnGcUMJpyw<;cc>h(DVLEP9uH zI?|tN7Z#fOal;W$g_K8e?NfHIa^4hfpRw)hrez)GRJzgUL6OS=sj+67@&^t+nbyD> zN}%6ryWTiZ+4=R+{^Lh9O(^T)Tg$gj+dVKKh*+_Z)@sAJsp)Sn#Y{JU=6`bi!*l)Y zD?KVBC1Sm5j)m0@rVE`ny=#28TdMZLDo)lpp;h(kRDMUC6?R_Ktk6N98=-R9% z0ehmvv|BONJ%Z^%wDYT-)8soXn-6^MFZ+1N*sj`jxZwT9*NY5<5-x0#|KR!PpwKph z;8jsw1|v_e+cf6mF&IX$242q zb0RXM=lNo~W80Gl7g`%FU9_#9kSR%(@`_~E&|akhcRv(KOVyUY5m?#k#LU9DjC z`JX*h?*;pg?9TkOT~6_-O~Lv(5+|x3ZTC31h`3^<1mn_N%blTW=?nLplNZJIHuYs( zKFZuD8J_&l^4FIti0A8$*hFeLorp?|U^@lf-e&2y{PO2s_95{|Z`&rXTHzAvU)IQsUYa||7l)K5jZmw&1&cT2ti=~?luRV7~IopnIs`>uY%ItbM zVeRI&+^w&k_s5*NRn4v&Xf;55RcMJxsnewH%9k8^+2%V`|1y4ub!oz@(FE_0^=r3p z->9M^Y`0{&KTVPqV0pH-|QUuy{|tg*j+pP@o7!k{OF5r zMl-}oORVoDQ?t{B8D;h_o*hbJXH{gZ`&4wSCvJaR^oY;=-WH2TX1Cd~Pqo88Bqm$r zM{3_*LQP9E`7r;j_4H1<@zd(J5?R+T^;kT6wLRVI+KRk$mmCxN?(8W){m+`12*QV> zcj*U0Q#92SrJWq?wYLs8`<}np9Bq9tH+b5k4r90VcT?v2zWS-ScV3#So@!f3gtnjS zxyp0*ay45dONjU7tq+ua^4octE#YEWE^#y~qR%JnPUp<38`n-J?739?YyZACmjZu_ zA6nc%?mD4oW*C{`+TP>buMuAI^kWWnm>6};=*6sE$NXzl)QTL97Ane!UYL?UD>(Mc zvI|q{`}~i7uu>FXQr{qUSHS9QsV%#;nJ&Afz0Yo?!Ik{im#%w%+QhZAdZT!=#-GbRT>ht1$}`I&wOzci$3%a2 zS^Z-T^tklPndBb_f2L>mp4XlkzNUWH686r82Rl`RGfZ6es@(gmVf%|SH9hdyH;*@> zMq+xk!p3fw+O$4f)rEckRo*W1aqEvQifu285=ZVxKNGd|(p%ITZ>6i~Pq(rCW!ml+ zd!}-MDDu!&mm8Jr`O0=`SpAdE^DV+bsf+fP_ZDTD>^S+#*~LLHGtd7NN8(7bn7q#O z9qi?jL9fjc*G@0Bj{GChetE&2?MuW~SJih;^Z+};oWxAw!D)8(18TuHy;Zmzz;;q<5vCKp2Fv$ntMlgy18@^H5m)jWOw<}TR>f(!H;?V(d-_s8t z5lT%yJgY3WW4A5%wXgnsXS-79>Q7rQiO7*}{uEv2nIUyQ-GcNMezE1oE1lHEA3TkA zk~KP&ER3GatXmL0BqkXZ72rGUa(FFQ^~mha0SBamA1?o;{pM5Hv>l!Ki(_}@UhB*c zYU+N^+Ay%GG)a42#)5i(HyerloQKTmU!o0ba(~BPdg&}%Bf;+6=6Vv&)uRGo`&OT+ zt@pD!nLFjS#NyGRlbL(FBF_!oeQ?WmYf(ZGYc7N2y8WqR_nZ2#_V{&I1uFf@YCd|k z%QR>nNC@z{HN$@D)rQqOe${<{mnqbr_@(aBaCha<*_@bOYpHb&dp*8N8i|{|A|`+R zd?J0vr}Kw;Oj4X=Hh*Bd*ibi{gfi=VHh%lCgH7#L3c1}Jcx3CdOiwf4VC}W97xy*o zFSm7nuW&=lP<`{-mK8U(9cZXhin2X-kz4rP%$b60o4d&&OL|&YQ&uk8_xP$=c1TrE z&b|)9rybip*ePA#Kd*02HK`YGh?Db5;p(@!^euP4(>H1+SsQrbu>yNr*r~h6#S-78 z9g7nYe6mvX?F?#mQ{C4+p<(hXl~CFh`i!deWs%_lqL$19D@)QAovph*KSeQr_j zvS04at-sv69nuxgmW7CLMIT&GEC2BJ@bX;mipTVNZQ}%?b&0mzLzmwEnmV_@MBICy zocBJx#}Pt`u^N{;5i8H&tvlGC^XTt?`7G$~*PgpHG55h$Z^`F(in|Z>T)1>3O983N zd0KKrZ~fQa{@FkFWK8)L-1#>0{L~RiiHle6F5X&RKhU0bvYx^0SJ^v6u~gr+Fy~x- zZ%gT5ZmafTkNeYZ#~&y<_pv=D!Qz9x@BX!p2NwN)F{tw6#JV^8Zob!g)A6{okX_gE za=MAHX@bZ~>&CcRF7z zZ_W8`VOiexp>p-mr*zr2I^}-xvnv>*J6J(PdNw^S$@H7(vFQ4kQ;X&WY_F+U+uOq%FOHn)ir@)H6zpXM)ho`KY8bwktioET; zUV&X6DYi`FbFcHt3;hq?&N$uw=zVWFS!>N^trtsY-q5ad@eZ|0DL(DqZe23{g?di$ zi+6v9vTW8jx|mGa)U~*Ybv|Kud9d_~m1`DC(XQQ#TDt#Xbm!ytqSG#}#HHoP`vSk0 zdId3>=j1jBM%@4NrM}%^iLA+zisY?Z{+Z5PJ`_EN{o$GZ1_h3tL%;KbDwi##Qy$+| z(Q14jJrHnxf5k25`HNm%%}q}{nXZ!;pm}OW4rgg<;qX%C(*^0z&koYwQ1<qV4UXv{KC6HGz?HBDML_$YbLdHn&z8r|JaA$;1?!Z83Q@ z!aCJ9Cy+#-vxBI~^UUt7T-a|KsM;E|J?w7g$=tG@)=udkCsk=`0|%PgcVzXsB~NF6 zx86pnK3^S?-Fy9baGt8jR;y)b|Btrc^IWKRjav=U8!9*nW;&_K*TdUc61CpevWxy~ zjG5ng>s*?jUjDNAE34;yY*y1+UH#?T{bc*5+SML-?>Z6#Tu&GfM6e_XfBJM`nZoaV&bhbl-RJZD|Gm6kx4Z5h)>?b*wbovH@3n6@&7Y9rx&2b%-^rGvh9~7c zxtB+&?ZrNXdEPC<&b8qd+pp6?V zj%>F%c-u}U$jb5^c`wu^_vXP*Lz*`UJ(oP>Slg5IvQ18Dq04QzjqKK>v+#oV$E0sV zmt+a2b#w1qRBk7o_I&rpqp9E9Jvuiret&HASce{4wf1gkEpHL{?%MkD1D5dv<4tF- z@b6%B?V;_sf0u7a&nmV!T~^^de)<@sqm zh;qz{-1m>I+tS<4O=otmkl!0Kw%@pl%Uh2)>^$T$qpIMoSBz=v%ir$>?5iuNI(xxy z{>7~6#m}tNvDF~ao5WO&ogZq1xJ z&WSnTR=l%F3*50uyDzREJ{%B+KuubP8 zuB|cb(^9j1vAOVL)0_!U9_5(!*xkHs+r}^QZ;oDS9rt0@>1VwHoBYj)F}$DJqiMvl z?AH=dM^4Py(IU@&vV45jmdUwYG|%?jN^OW<+s(22l$PbceHUC>?6#mq zdhgJ*sqTp_+)UpzvBVc<3ZbBnMAFv{da%r zQ+c5CFpKCJ_75Jt9q{Jc@v_z%p61Ax8e~xJ*A9B`GvD%Mm&2&uPg-A3wC?*y<6hB} zC6+n!=G)vqYc z|MmPgQKz)kvReIidp|v2Kl94L;XP*N&PdiR(c0{_(o*jG^GWLLyz4qMgF3xQHGVwq zgL`CD(Xd@lc3XV1Iu!iax3J@_g0_0qHj%)a%b`(`#ivfoBCXMm?&fZ_W!pZm2x*nQa>OOJy~3_P^^ADzDI`=Bnj z{Th$_-RMhYu#?{0ihXqJ*K7J-efh%H|5IA=^B2)(MsqzM89FtYv1Zjkm+23D-0oEq}fZevCG%&t1UTk!8bo^(s;p*%0+q6$nsvE5OJ!M4qHEL>JECVba}1Th8Y7B zJx*-;(+IWQ-p!4_wD?wb=QC^kcbBE+{F-i)Uio5a2i>ptP8<=9FSz^g!?h7-PgPGC zK4)LD*-7&QuX_FXFd^{X;Xi%m83}`DjCvw>Xzh}7efimd;>7F`A-hdVqI0Dqn;SMV zZF5y8=EdT#?V3;iBHWj`vvH%nsq5|cn|(Oc;h4 zVd>l+6Gv2^8PGVV=;j zDDgX8oozcgrOu?;hECRBT9`Y?|NAg&PrIzLpU-z@{TaB=`Ta+^bKs9q>vQgv8~W9R zdv|oud4II}(fl);wqDWN(s4m|Sx&3o{bOqn&#R$&=RW*Uu&b)8?V^evNM<;zxaXIu zoWbr_rM7+3KhC&wKzRRNVgB{C=i6*PaA)HD$z@loN@j*EiNG}2RMKQ##I62%pUzIC zHin__84X+BIhJPL^>n2aXke|Khn^mdP#dkwWwnuMmTt2mA zQADfu|ClV3e{x9IU2|&2o}jsBJzrcu^-@sz)OO}Tk8U6SO*^LD{hzm6n$KQbCwqCa z?qtIE(ql*Fr7v0-)6)6v)`?$!KmGRHKz?Axq4dN(C*L19rdvKX@q2v9-}E_O#eVOe zt=)6U{Mhk!Yo{B?uMg@aYj=6hPMOc2Tdlnho~<~$^2CwXE!?|>x!>&;_0(XL?uHFR z^5>_$dNar9b@k-sV?yl)4{f(@_ryn^o6aZ^#)h>1piw$yis3BdNiXLg@%+2nE5LSc z=ediL!*$z;mN=&6Y@X9^W{LFBokx`sO-0APO|v+V7I-LRUOT=2d|mtOk#BU$p)U8? zzvk!m`;j%zezmOq>>fEjd*#PAHZSjnwK!lj$28g2Ri`fcu%n00)iW)JZb)*ub9%rH z|3gKd+R2MTrX6$kT>8Yn(JTXt*vQa_tq$L>T=#aCecgvLk6zh2KmDBScAkD&HqgcV z-iBZQnlJCtG`*(Lh?1p7n>+5i^syp;lUzFY!KSC*G>8B0P}k(^G`szx^pNe(OH=Ny zsW=waKuMYKCfAv|>%g%di-*@VEW_PufZrIj&$1N64Tpu%lUiLZhk-tFL zu1V|tW8{16Us#BbRDL&)UDo;Hu6y6&cFpQ_e&E%yi%-Ol88*VdV0cQ~!8^^Cmdq-)|F*Bz8*2pH2Fh|s`d|m zy)n|-GO+c8Zt{phFE$^D{qkRsURwWYU)HZk3eoKFE@o*DoNAD_?R>EM>N=6}>qibd zO5$Jj>OFD9=2?fnx$3t0GVs&Q|K`6MKP>C;&229;mbssQ;27f5>vMJCgV*`5j*J?T zu{QDG;@t1Z2^l{2Z1VcTs!d}awLTuOt^JD43&!vHcKN|+Q^~UXCwrKt_q1HE~HLc3m5-yZK(;wY%Ftef{+4v0s+cb9$UbuK{s3Pd-~)Mb+GF z^6$!3Cr!WY8lSn>WZ#ANkF~9;epsJasrPc`rAz*Iulhf>fB37@oXGsAp`T(G`P97h zm!H)i+O^At12_Hba!VA7`3!a3Q_#W}U5`S>m=L5oVe+KQmIW(_ABYOL@<5M%{CP!Ks{}tQquzAvr zI%8xpr+CPA!K@Yg%RiT8zPI=`z4Z8s$G!o_JLYa1FFzA$dwrADC5Oj)26ZQNw7i2; zJnr`%SJt-1!fy*5>orS)@)vM zxJB?A%av!Agm{MJSsA&nid`Ei?|4p(a@kWR+4I5w zRC4dRGdA>Zp;xTY-zdM!!zs%OrN)Z}%bSdQH*)4;ao~kcP3Vnvmy*|3`Sr3C9^4au zqR*Z3%dzsQ_kVm^wC~lH_&?)UnbL=ji#v~QI#btMgG%oEyW;-o-F_z|XS@!kO}%S6 z$n`}hu6ai?y3b`_qSr*Zbez_4Ya?PbrwN=uY?ZXIhHNgwb-zTce->-$FJ7mJYvj zVR@%vyGDKNwCc;j0Q2p#_1*NevoC!6DSMT3`_uiX9>q2Vf1<|rS=ci#cK^AE4)f|> z&uZHDi@|hryF(`;Z!e7qpYiN)_k((Pj3m+eRh&j#frsmvw_~%yPdsD+01 z(qaFcUotZ(rf-)IYlm)2+|pb={JMSOlf8G{y-UVAlm!UW?!4D1Zu-R|N$d8A3-c$x zZQ=1XuhzY##=RYB|NSao;r!v`=nYZStNHhCU!CStS%+3lK2dbVsPO2;;LBr6bC0GKo^75}TTy^VrEG3*x#yNtK6#`( z=~=>E>cOOlMb})1R2`0flI8G0Z-sx!mr#?IqpZ@hZ+w25;hi_RqD@-&q7Por9{wj! zGSkztnc`);SJxwIaM|zoZ)RCsyiRT3f2IG~xjNB<-`qRp^Q2qo&fe+fQ?qR*Jusa0 zWWn#*C*I82da}ckgZuIfu3c|hRg?OySVP~x?v%GY^~x_%N6%ZM-d5{Ps>&>ht_WCi z;Jx$Zx#g8}$G*RGu{iH?$LRESo`P$aT?59_Q||}c{n*`X&e-K+Vjb6dO|TYyZDo@X zTk9rjd&}qP3%h$OI=flu-%b=4jQ_l6;!vB?a!dWvkM6zBYDI3n>GiYFTfhIkyf|sa zDM{OnKMf9O&639!9Jv$IE&f*HmX8*`=oohWLCM|r_j+BNbL4QMyX}?p&r6$CyYxDc zRMh0&?8bN3=SG)Ia=YvG{beWTgyB2Cy^nu4deE(FRpOg%TYlOSvd^ihpzW>RgIam+ zn$w|I#0$G-SB%{1Cg^NF5tNa7z`JUn-J-@+TDQlSBd#S(s=m~C#^|B)qlMlHfA){D z+;HIP^m}uDj9Rw*`I!{68(+p88F*)n&*7=@RRI&9<^0SYGqg?Yua4Ejz48;qL9SWf zpWm5%zhKelh{VLm)mPIzK8?Fm^wjLZzWXOu#8m7{GCiL#cf8wR|DV@Z7p&4h?Dr|I za|hq&(xR5XuLd2ni8X5!G^Io9ggGzF(bhcXs#<6-md4;y#YVJ7{BPP6%qAr zQKxGO9p8swBI~~8g>;1)&^*36qe;YdVV)g!yI|g?Nn_qA| z?C-fhvQ6?sPosn81kN7sts8c+&39T{sA(2-wA{xoZSxt?7~RPy`pP%D1|M(j z)~m_Uve|v}eZ>nty&i7%y{h92YKfO|zfG+i9%WD3z2iVc;bnPoz&^3<-qZSTJ7gYB z{qRp<)$v=}qwR*ed`Wxp-{159n#b?QwPin{c6=%v#XQjk>4IXf``BtfK z+x8~M9_@T_*SBYnm1!eBb!)LBq-AYqm5f;0NpeznNb-`Q+R z^tx`tv$t5hdv7+SHnZ7TtLZ=Fl|%BYro6Uq)O32t!;rrR-X2_Yz2hY5%^lswF6`9d z=Y?@;o=5fjK6XyHZ~xr;d)@JO^ySKSbDT2Etln3<=oYp5`~BTNO~*ee@qgrBlbAzVKDM+O?@6#Vfa0E$(Q)XxYwqNli`b2Tr3i?50uj zcJqHY#bsH%i@emRUEQ;Tk0^O&$+JMCxtr?t_B(kq@9@Oo$@gCE*=i(Mv2T)T?(|d9 zdRe*VhYTjRekio|xpmaEe1Uz(F_#~fuRE-rP&hBvzVyw_-5%p7wF~@Jx@t-PA1UvB zm*+PQ_wVv;(IMe$gX}|HYJ!_JJ~sLC=aK;%r=7Bvx6v9n;$ZoOhs`#fHjtjSy*Oyh zqgF5JfyM5kj8p6PJNfO(*mmMx@!mE1V=|M%&w7t2s+qjC?}&DRYa`pl>s2nhS!(zF z_u>|HtzOz1vx`$A8Ke z7o&gTM^0I~(C6Z@x4HLX2I_LUu3=Vrv83%;rx+h_auJa8&91cdn77oui+3wEf=kngaLo! za|+gs6-%QNQT4%-Z$?iA$(E}|W_y~MQTz=9rxLLo@GpBp~ z+*;vb)m$T|VB-+|s6(d?R3=H6+F2L(65sR>(`yv^uupZH6&5c)h&~TL_UUbmc1VQP zQmfzEKU!P*ExjE&=KFNRUtX79zTA2~O`hE%`c9w9-ebF8p0;2s2s#{d#eg5`1nd~An5DRjnfqg~fLT$WggJ48%urt{+bk#)xmV&?1^mlJhpi0J$H zZBO_3ZkMOGo!n-Y(@BjcMOTY|z47XLa*@%%v>P*HKKQ2FZYr z*ZM7dWim=!aJKEfq0NgQ>`FR+H!mpAX8Xh%lhOA^z5D#L?N9lK6D^Kj8NceVXYbf0 z$4?)5vDDM2mGiu$IPuNM|zVYtDS@^}3yS;D=de^bD zD`~ffX~dXpJGy)Omz}!`U+s}+jI?lmqqCqqw{&II_~D%2exOUu*S5~^mTAcF<891!^(LgON>wvCt?en{xuoyY>{OOqNB`@Uj zy6&Dhp~vl{(K#st*O^~!V%ezmLyvV93ychwXdg~3nz&;0$Mx<_8^5?Srgz+=!G;fa zOzR}QKUFt#?x3>pjYjv|ezkOw$`@tZJF${rJe!z2CNFTTY`# z_Iez%z{k{hUfis?b!D&3T}MuRb?I$%n;I1z(EY5xBQ0aI(Y|mT^NwVeHcM?j^ zZOF~-ac!o>`W(^_H2qz5IK^*&%b9}>kNPM4Ok5eiKQvKqu4eYs9z7Oa*P2xJEv7@^ zb>qvY-OMKUt9v6ox*_nxkv10(-ONs}IJog`(}=B$Ui+GF?&Q^`f55^&g;S08M;)8r zGWgTN&wH|;=6sRI{>_^D!8ADRiN_Dm0k1=4wRQ<_57v}7er7v!e)mHiw0eEeoHFG4 zj1ylUy|Q~Y=5hX5Gs6srEzu)36nmydTp4qy*}f*{zO0=&a;)@cKljEHLKbc({uoytaJ8zI^x2OM-XeQH#FExsfM=P9t5=u1w3MGJDYY9_d{1BSsqMc%&x{-L zF6>B^e7eR>gXIGT7wB}KkUx29@S)PWsG7^ooa-EYJd74c?!5nqzFguG^Lu2EOXuBw zba~$9L3^vMH)dKn^bRln6?oRuV#(;sx5K7?Np5p$ePFPpmA3Qh8o|~5$Gfz&3(K?~ zdZV_c_PvwOuqoclyBu2cxw<0TwQB6XwXTOJhJQ3%lQ2#o*ZAYGZ`s@}hASdwkG`Mh z>2h5G#!C*8`5Wz8$a z-mg|&oz`7CqiU~4boqaxZxZ_C{5`!>aY5q8fuOe{`L-?*Cr;c96zt#r`q-q$Nh|w~ zUwdt9>N~d-=hMO2g+JxKA+5v(fz3S(`qUJd{kU`~T1WGKw-BSywL^c#)qGhN896xf znlvhZzO_}m`#*fXRD0YQ^7`lKu%z%^xvq!*jBj&#_SrdI?rZORy=%~fIQA}gqb11vE=S}YSvOFA4^{5ah=vuE%@0+)xo13lI3wdHn`+EXk z;f9;bPyX@IKX=5XR_ns1e7CGd=f6D7o^n^1+gxXOZ2bBc#m?PRhK$@2lJP0$y|w}PUk-8_%(-fS82Ve`#>5v^y9Z`LMv?{16!15^FSglTUuo1FjqhfF`Eu47dU8)V8US3>uu1gf9<9TI!@0#oZ6eSy>A9ym&D9G~Ktl=RO>76lS21Z3} zNIWeM3f@?5-#@u&P0GoZtG3&R_BZT#((8h(tWnbY$WzTNEWT*h)#&M0e|Em}Ex&(6 zzkj3Rdui`o+Rfu&kFi#HwHZ{|^%j=rov#_ZzP`{Tb|-Dww6}AIyw(%Tf|@6G^WCKH z=f6V#_zTxYRZGToE6!|DczELU+lAkb&b3^rdCng^+SlAN7i z>1YLJT(#TPa_940I~RE`n<-JFCQMti+HTX9y0 z%)fSXykD_>3)yj>S?dbp0*~b_yK+V-`DVEO_3X`^+*-ArR9GY%^|WwWMQrY~>IeM? zI-9Le>OB7NhS7a>_kT=!U324DXlBrul^Oj9*t86KoEza9QgL|HfyyZTbpmYvS$%WbSF3a>@3x&)wg)>rZ?P*|ccQv^w*$K^3<>x4o(BI-^fd4V~g+?oXqS z+UgbDsnKzHdqeZ%u>Lt)2vb3R zhiehrYyV_^NPaq8aCc9{%OL^r8r`o1JIkErZWCnB6pU$k`Srb92G)Z@^O{PM915p) zTeD7LetDesk_)EIbEdhDS(bOg`>d#E?uB_TG@4cWKj|5H#N<)Gd0YH)enl2nY6b1v zRkUOA!Y0d>Q`V)i7CKATEY0qtVY=CuzFHF-#Tes3~^Za$FeT>9pFlL8xD=Tg4j*|xN_ zJ5{Hl$6e4Dyhh6hg_*eot;*BvCZi6t_< zr@K=EP2i3OEX|c!`&DlEC~nuNHig_2-xO&#mwDit`L5b5 zQam8ZNL!Zbp6ab4Q#M;$$X&|8!vJh;=3Q+L&Ru&lMp|IzJKZNu^Z%w?$fW|rTi%Mw z3Y3Lhf*E5ZY2_N_P*p_{DIDu5Z!wfjfv081jV|(lvbB(fll$cE2pJ=lB==o`DzYdt z-_=@$Kr8v#!bQDR?&_H_G7oaCa0y%SZaOD8$Wh0^x#YF5;haT&`ndWcT5|b6NZ7 z#YY=Aj0{06a@KHV74nSyDeQOTIN?4OEJfxF<~zOq@BiHv@>+0pxa5w;$hp9MS1=Cw z0J!hmOrmxBG*Q8;58HuqXmLlKEsG1`+@}H`T&w23D~1@CjhXKZ=jhqpDWjE4LapB8 zsg{G;!BaNJT~0IRMhx?hBTkXp-dK@Y9@5DQg6c3hAiX2xq(>jM<`ii~AtG!AV?`=6 zCQSdor^#jc`1i=AOtwU!k3snxsWM&8yzrbOR?o0`VJhNa$tOI)c|i`Lag zvM<*OR2w6OIJ*bLCm2iFWE0TXuF;8j9$Q9t@}XRG6eUK)g(Ttjp@2^Eq59w|TB#4^ zgAaXQ_9K@2xPlLDl?t@^L~2CW`gXZC6fYgvd4wc0eX@c;@100F(X|sPPbZe&T6SDn zP8_uC287442r7Q$&{ZZ*=Fqi~(UE?XQx^wi8gE4lifq1$-t6gvepD}Aq7bs?H1(%E zbQJvNY9jkXoIhw4(!>0y4)ihnZ6M_)x|RZYPHO4F0hG%iHN4pr>fj{Tt1@Spf(m8c zGmZ*nVo?PZB6>4ggDI>I0B1#XpFqk-N4;%(Ixmpwq$x!jL)}11&r&fP`Wj1>*GoqP z#D!o4>#5|>5Yt*CU>0)2sb+L#Ak|S%q4O*TCxk@W3N0b*GWt&-Wsjt8c0p7J15Sc0 z0t133Pr|$FQNfnD{7LuCqm1a3AgVpRZ5(FM<*8`SH<)Tl?+l_Se?^_3uz;9^kT_f1 zyH{8)3nd60DP+GMBm#(~(YPKY28h#D^&kmAl9eG;JGw_O)d_dRv%@KUrfY2rj^7Qn z9W0F%^R2$N3?KoW9ZXq+yraRCDU(?1aWK_cLy9(gF&R^qhEsZ;!Exb9A#pa5c%gj? z!xBzWS%k#JMaS7N@3zMS%H=>Ywg?TMlo%IcD`x0quBAf1)B_z@AUu;zA(V|GA#0aV z%A&C`^ITt}P|B+jp5{ZJo#|tfC{s-VuDP!crKFfum7$a~=xZ^F5;AEl`%I!FO;~2o zk0w!OjbUJsoF$s-$W-)3!GIJnB07rFru&Ce?KOqS!tD`8S>l&u<^#!Z!>Ar0`$`yP zgXZg)4`je+T0n)N^pQYi{gQC1Ba=ww64sa~@*|uQp}KVhB|!Cw%!fUl9YNVJ%wy}L zLI?Uw1SO_(f|QL6oQ&bIr$Z)Fcz}prGno=<3PIe}$&>`(CR0ES=Li%`Vb~!8iELY_ z*O6Y2pXtHD%C=fXQAU~~0W?h{)uR!TWAu%r?BHs~MpBkcBD`Go(~&-hpOrMB&M>-n z2-k!iCegYmN{0Lex1un!1hhdkzKLj$Xv%?7sGoPylqnFwyE8y!GVL8o8PhH?RJ%qp z2YOTtWz|TA6l*ac2Z>5z;Hrv{7v*&fB?MDC#ZrR-Mm;0CXAEUPuZpESXuUAB&_13r z)D#Pav}qj6eh=nDN~gq8R$yvj94J6ar%FH>N>~=4$`Cp$9F-U4QynzLQYpPI9_)ss zT)`(Zc+7{8wn|{f!iV_~a&=LoBYipn>@%N?1`HD^W8mkM2sG{K$V7I`*Cv7(B;-7o z2)RJcOy)zxRY&>Gw09C^OW&A+>RD4ENmArnJ(`3n7@}86l#{1odQS?83W*DtVuRTb zJ}Jru4`>D?giM+S{h*jGVS(Y%@iuWGp&`&jK_QqO3d?R09+eaw6p#=e9mUKe1?uQb zK#z~23<9H~6WAHX8Ea#UXiUbW@Q|sN#@rK7#uhOFlR}uO#c5ULcYCzPy@jHLFjJCq zmXr`y#W~Op$)K@Q48+4fm1;uIN~Wj@3hl$S4c#M9Y7`Cv)gw^&rHcNgfUt=jG2yu~ z&^ZEyJEed?zplc@eAV)KB1u-xQuKR~pDEJYB_ih9WL~k)j77LlKu@ zPzgaLp~CG^)PgF-TQ^*vxzo^RP`r}R%4r}}p`%!og&<3)@QxJKL6(rqa-i%2WC@ij zoT~-0aA}p(bsPl52$^+c3T03KN>I`WRM>2iN)CxYkx*^aM4(8h#xoH^ky41*#zhQ8 ziscE1qzL09bY#0Tpx>uZhV+~yaF`j)i6W51y);nYD@YP?IR+FYi9nJ_u|!d{2$DpK z6_)}6l0<5ZK&Qw>l|r?pS4>Bj$EPZ~^cRCH5%(^Pq60C=5^-xCB?M%N6uvjtff!_o z6iXZh1U-nc(! zOVE{=Tl*`^fCjNtF@)JOVL}d|!-*0QBIf)42K%UQ4A6 z+9^uKhXgT(!OB(u8if#jmVtGtR4bV6Pcx{lwC!w4O9*m>N`JAT3Zo~KTDt)Xl7;a5 zQfE{8Hf*wBkk#-jh!rXpOe#=}0bc$&RzP)VEkIwYztFie6t7YdN9vPlMUn-zlwiW;jmC8ceZ5D@L zbGeXVh+=K5QiNfMay;wNW-I~s42vpzgkX<|%LAj@3D_gza=@rUfe82J30Bw)hV;b( zN~bl0gi7Z!`h5d_U={b`iE5uH&pl_S1_Y}_%0)vx(v0;GDGgBr6wDTJODvV187m^< z#$Ulex}tz;)mjK78t}v88!P4DU+4LhmJt{wQd+Bq))_`&5tKcTGH~Tq@G8|A&M1{t zLluTIYz9O%k{IgofYI>+%20=~Xe!OnE~!*EM%0@N@q>UjTCBxU>V*1!SgYeGrlaRm z1~y!1rlC#N+;EA6RC*Glc`@?nu}G-lfZX5OvnlJrj0xg$)T<)Tm>{vzf;J!k^2N#t z-v9;qVmy65JdHAFt8laGe?;p-xR_l3_|kx|gua3P<*ZRs8rOzu7bF2nrA3i1f5i%47JM04lBey84zLy3DrV${v5DI!Z1PU)i!j;FhQx~8=wpm zcynC>84%;msK*N^z4p9$#+os_D#mhMhCaMi1`Imrpeq#wWc26-5KtLItJ0sTuLqz|xiV`2Vvyw2o$8M@)^$PcpV*dr&1O94i`c`9l-=C_B4!_PzK(l z95{k%DIY_OxRfVQj$ndR=>RM6ww2fl=+;aOqq2Z%-kRx4i2?i5%Y~Gc9DjifLaqP= z6@+TDl`-pGLWcp!2!J~305U_aEBhLC*O79`wm~NFtY3Z^!)Z>PN^zL-Zsu`*< z;(+YLnUsDHE{?8JiV=Oq0#He@%$5}f+BO?egpb*jSW}GL^X#`nS(GLHHsW zs6I$}2qQZz3(FdfYy>}$#0&*{wXOHWm{_AtJQHseV~F}LgGZZ}ji8B?``a#u>Z&P0 z42=Ed_EHK@Wz*-gDGR1KE7~gui!?yH)BP8rpY1sqhfd3=u3U9jgiF|Z1}-T> z!g45+#^9Qw`QtfkP=qbiWI5Fh(H)Z&Xbo+caE$|MLhCG6Hr^j!;h?e=<}63lMa2DG z&Q)gNf0k3G$})Xu27heRvA=X!3Dgu_prtNc7l0bmx9YnXx033J>O1g3XRoA;5YfTk zQqaPJ{;s4tFgfAg(cpds4RnOe-#uyL6_go`%7*kO8iAn=OMvq}8jK&jit0jfs);_a z8VsAaiZX7ha6CE42|y?=Ucdq5t0|M_n9rQdF)%@ArRP2^9zkT*>$izP4#tr9cq|)O zs`TgsG}g-Ku#>(;JiiN=u(1fknZhp&V_Q1)g19Lp6`WED|d=h#LxEo`|^^ zzHtK(`a`VLyY)?B)`*q5upY>255-(k0)emqE2HDNRC_G}qdV9i=zvV@6-O_HGy|Jv z5uiZGrAut+7=?vOTd8af2nv<4GbIf836-%WB@F0^l!jUf19l?D$^w&?=&znY8NCp5 zkj0}5)T@X~d5GU5;~gCZG8-<4&L~DHotukTJ7kk-q>-Z~U6702t&P|@C|Ndm2qUbK!frCl~)nx8J9 z3^d`IDjC{})+vC1_-w$8AGndSFl45wGO?*!NPI#(;yvt=h3>c>3Ss?5s-3A~$7^_E z!j$l+ka(3Xqku?!m0?A6XCoEfNF*ukzlkzx)Erw6$i^wNNB)JT?R4jY-sjDf&=cB)`DYwuti}FeZ_j2gRfi#13F#+bB4+EBfJv}vlC*^~m-CBDn57|6 z+@1+5s=~wq0aPvt6G|ArTfLl!-J2y~tl?*1@&FvnR4m?PthtHTgb;t?XnU?X8F zQBcI_W&$Q*Gy(yWGT}x7CSz1M0dr)Qw(2mXj8$@4UN25ayUJ@2$$)uchb?h_gEDg5 z?d_q)dB`9-O~Al^2M6A`3+x@3w83gv<7^J&Wvjv9k5|}8wSg2l3B)5kgk!(e3U!?j~YtUX` zFJoM0)lL8t@uk{9#<)F1IVp1hgn+Rbo4cz6MeGq90tTm5P)zB`nGFQuCwAk3gz+X2 zGz;U#sF%Y579LE5H8!uDnAr%!KY4@h#R0GS8Kj&**nc8N&>nkQ%t0gdj%8v}oa_ZM zF|#M5Rt~bQE@D0KGxR&N@=z-%kV%=~ks6GC%rHzWz+<5#(}ZFn;|8b|7mDr4`GKya zJl%_}D_-|#k69(Ew}-Qd5@K%IBQ(rxuBjKq(w&qR1f!Y2Gf|FB15UtXWH|__tYK6Y zbIV=`CXk{FWEhW4wLw&7Q-BjN_Du!?#vZ*?h1rV)VxAV0!|*bmGEqBE6^t^kwCq=ajL$t>el7D6i% zQi9zio@XWyIARtM9SfoQiTQ}SNbRpEr*sVflre{K)UX!f1!Y3C1=#8)CphXll5-E` zcxo0f-aL~FV8fUIw0g(z5_uFuiIC%o{VpC`VWD|4<0zCeCmhxLkl90{60U(z%0|xA z3OZtojI0b8>HY~I)1-EQ3x=sfbd1w2Ow5k!L!rI|0Fqh+FrM`Sj6FlDh9I^INM$d; z%dkAoI3kEk%7WZc!k&*-YtT`MEdNRjIrRk}o!#|QF9)ZZ6gW6O%tBPXoCEkp!Volu zY_a@TE)U=}*^@RLF!tcKYJ-?1j^w(8Sul`w0kh|^-%+M&dF1Rm3kBITA*!7)Fy>q& z0b@6-)L~dz5ESDqxIOa}f_gbPb;Jx4+QWR1sufcf|H;aTNfT2Mod`)+4^+sQ%^3BL z@xm6bE{?`B#4-F=vLC&|oRF3A7!VRRHJ3usS7>J*eya|YP)XMm(?1&n=? zM4b{D1cXEoT9n6DnIow`(4Hgd$HJ$PL)M7~87o0d6DT+V=|H108^cyZ5HRMn5dm}H zdGk>IoIeHn>)Fp(4npe*F*!*C0~mWIUA+?~sz7#(10dl45emUCk`Q3clYXdCbp*kG)P-~rSOZ4tZ**c$ z`q2!GH*v4ikZDODT>e@4Bnbqn7 z#zP5O4*N%}Dr=a{umHRTJ78qQ36l!`7}*I9p^y>*LFA1-j_ox}K4p{vr}D^kD?DKb z=17D(B{(AZKRPCZH*nhPQ>DGP9kcoRc}8z8*8@Ucj-gD0%wv?*K(+*aYK2RIEpArwQ9 zNbQW9Ow2~48mkfb;aLToQ{<^7Ol7`af-6jV<_H5w8vIX1WD4#gPmLgiz_X3m|KVwN zxS#ASVfbIqegJvXL=1uBu@Ei{Dd`BE@N^##;KA4(GxcGT$l3Fx1dtanKqu@m5!G_g0V1CA5zB;pS#aRR=g^*% zBLws}upgmSo*-etL%IlvwvzEySPH&N3K(Bl9UaxQBg22jdhn%H&Ew`AZoIqBob6HN z0&4(N#*_ICFgUbiImTv^Frie=Ganc_axskt5&h*=cH{{c&Z+Rcb*%4rRv!9Iq0&`c z2^?+Zsa7a1o@xb*r{{6Zgj}(sF~0hiFxaRP0{$~$aWYQFz<5J~PIz-0PrQ;rRb1I~ zj_&LrKhH zpA5BODTla#dM6BwCo}Nrc`_r#Ef+ObGZc$t#HNrOK-|sabt2{MuP`ABo1Q~cXACDCB%rRb#R3 z0OL6-Sj&+CX=oYjFOvQrUPj~z4K~4ejs;*m$HD(6#U`a~Ae?E+_f@Rp#C)WqiZ#==o z?jlbx5vO6f%J9E|{g@N{jwSptcEAQX4{0f%3-IwtiXE{MtCxObEq447-{*&tWDbZ2 z5uG@KV3J}-SYFbIp%b3jhSK9%Sx1pv%^PL4lp}UtcvvIT0k31Y0lbcJMu3<(*u0lD z%y(`Y!_q0%kDy=4eoQg`Y6V)9r+ge?;CaZvIFUl=h;yGj4&oVg)w&G-g^rktJW60I zd6d8^s*D}SEh&50n)zEv2-@Q>&v0CdH*>HVCFcu>lzos^y+If|9(6K|JSiVC@QZ|D zgN4+hj;P8Bu!{c&3`u8$2?vlf0&xTOZDDl;;foTSK{?)jA_G(R1HgX(5wKFnnt_p; z5Xjh*nh>!BtU}1T5H5mZ)J15VS571#w-V7H&kcjK%-h95)PT3?g1S6)i*mek8w^b8 z3aTu%a#wU+~Jonh^dU3Oe$~&Jibw4+VJ(3BW|8hGSr)h67B@({Q*EM_NFXLo7!fX>6t7paD5{2K!vMculPRsn=WxIY7mc1!Y1$Ov1k4t&R-NcoE76?O~*N?TMAr zZycrY|4^`gNu*Sx42)bx;~)!rvskTTW^0&WE9!Fb9Tco@kJ+&y1yj!Kl8}`FBb^9z z%2;*gyo%7GdLxU@PR3 zxhcW?Q)$nUT!f%w)ny##|1m)F&>n(yJkJ;~-s%T+vEm>*M#PPWpj5&WR-s%fB_p2b zgy-WkFw(~djOXJsFw#*0qyGnI9J#Z24F4P0#rQ}hB@P$@66Pr3sbE}G=c!;g0_0i| zyPr`04ehbx51<1Xu@J!}`5!Rsnm1Ht#u{~TB!hr40>X#!mh|WY7w^dViBwsnx__Ax1h?zio6pSe^_<4`24^Ece*+MU3zGdf3CWvIxC_dgPJoe{a_HEx zVWUCecmk#t!ejW4>jk_m6DWS3s|^@0n1H(2f+N|FO<+EZZx0Z)k&^}io$##~V7%!G z1j%3%uw$?Ms9nN5qo)5DJKx#c~H1Lpym&o(~0F%ghm2vWnlxlQK+5;RnMC6R* z0@e|vnHA&W93Sa=W7pvS;XW#Fz5~W{tC`cw`EDzN60{lPRRUua< zNNU06gHRt5Xfx7$N?;^Nim@NTXFm)oiL?Yphv)wRNG`V#EJc$9tC?6eIdnjV=dQu= zA%l_34qd%*s`vlkaq$)$I6FtK_fXl9CrE&iQBa)1hWA1u4eL(8ysDXDai&R+J+*n9v}b0!39=Q5V0QwE-7xCTEU zwoY3JXwGS9Z26B zb=mBp4GqFTFt-f|sRT^+Ke#2phNdbuY-PR)Ls}Jb^wBX+k`Z-rPnq0f6Jgm;>RK3s z`f1ak&{2@50i<9KfgmaqF%ck*ay%al_>uY-brD-uLz@0@mue#Ctr(>6?+F&7GVf#o zI>yN~wFVhvuzFXAF?C5UVB0~tKi43H0J7=2)W#F1^XeDiic1P8$2;N<81D!-QYqm+ ziaIiY;iSJRjPWXP4uHHOgp<5V3>#D)WR;AWp&akD0bnwo6=Jr;2(Dts4oO^yF$Rzy zrozGp*=O<}P-b$T$wL5Lg*kK*KkXZ;3!9zHh7j?$DYu=V9V7$9gfDy>B!-Z%!j}k{V^_n_$j?nES#g2U00feV@(JgPN zvD6f}kgRb)oSozXj1d`i79q4JqL)5mZUCt%L5Lp=AGv8MLZFSO1F_@A8!Z@Ip5en@ zDKE%@1)^dfS!DzfkyF>m3^F);Nz7otc-O1oN->)~V}7W(47j@SSY@UzI+Ggb<`lckt~A}M)U6j&IQ2gPnXwgeE_jA;}ztceMLD5smCDLNI68-#YG)Lwos0=hjQ2zI3+v` zag0$-F*3#(kugFR5YyqsiUET^O(KJ(9|^;;O|c}1CkkL87*u0GD1B1hUJY9k`ZDbe^r~TLrRBDxR%9b?72v0ys5JSRjK=5Jp z>)r-kf}1ovikXl)vG8SL8>IaKjJNUv41o+18QjfLpHt8!aEW+2f;pkfugr_6qb~1m zFoc~K#{dj*MiLnjlrOO*go6CDhd9c}o4KHkkF~q%iZcyb-MjZ6K0xdL E0eQE9CjbBd diff --git a/Doc/RomWBW Disk Catalog.pdf b/Doc/RomWBW Disk Catalog.pdf index e204ef9866104b46baf21121a2eaec13bba19b5f..16622fc95e11b2dfdc19c96bae9e07286455c565 100644 GIT binary patch delta 5639 zcmai2d5qmt6!xB?ebvoSTESG%ox3l^q#d0pVws6OjH(!-n3x)(Eqw-Qr6IPdOD3g* zYVAa0h@FavB@wa2nlYBrMvcl;Th#Ys-WzkyBs%{z_ub!j&-u=GmV1}49J*}f(A(^ymQhUVsy>cZOhL(Z1^bMebKYu)wiD7Q#WMz`uk_D9X&nQx%QjQ&GYx2 zve(<)>$e{G_0`o+?Q;FaH9M!Qx&6A<$5(ala{B%czWU3$N2;dQ9-rR3=H=?tPk#LBh=-3p?SS(pHeA{A{m`4=s{FQNajxgas_Q-;d(0&ri5MQ8sy>d{-DJh9Mr(3AP`JL&WB%buIG{*Sr2Q)Z?`tJlr>et~#qb7$lG zmyf$|&c=?$xhKEy(;n|GzqhW?*mS`aEy?TLh#Q9GJBQ_S?Z54*m6T2d>81;xp6bo* zJ8c=Xu! zJ~Ky_W#WxAHjUX1x0nmwdwRaGmaEE#Akw@Hf|@3RFw`_Dyrn^q!Umt7&LHTCQn*Mx zky;w69I1j-DYpXyA1&21@Fek6Ducg&rO+Q@C4{zV)*rcwF=W4xDK|V{aj}e1F>_<|^hl+Q zqv2FaYD%O64^&MGADh$#E11ymi=>1jeGJWPWqi;{{s{zM~eX?DDG+$*O--?#lj(?*Aw#_WVm?0jdK&{4NI;UNZgeh88(Q9CcG z>Tq~Tb%k=Cqht@uSEN^W=7tnmXrc(zP=i)Wl>xULJlA6+PgEF+1*q{ad*1>{-Hemr-!PbJYECungz@P)0Sbakh^N~RM67gl; z9oh=AW>-K^7aS%rnjEOHES}D2sij*{{Tr-a`7BN_(*dXYPBGJN-i&SD~I9U>X ze{pigD3!(xfm>89&S@4ctZ`;CiKlrP1V7R;5jq5yy5)t6Iz0^tHXk^|lUj!DEM^|J z0h)YX@^0xNcbY3+K}!GTPnj7E4KBu1zuO?u@;dUfvW`!3&>Q&0*8;QCUu0HLzRmeU&ho52+B0J zqgD@O6}hehKg!TZLsXFxgKsU%Gu$x*kG{w7nI;T{TO_K&2gBxeA23N!J3*jG%^3vy zDWcxc?GX|tYe8VrORoWfRWV#^SPMm;r}4oGASkRnm*!!l z;WjDDT2xSh^}L`l;?T1&Q_%hbaZ1_%z^Uz9`;SdVdEC4TgNQI-{$RM4kD|dE^ql$( zf<*ysn^A~@O(O^mc#%3X2=8BfS7iJi^e-#Ip=?jRXbLDI+f;fvMRj(WQOmpk%rWE_J~sS{d-PAxitpg#@Dk zr2}?4CzIS05X3aR{wP{U@%kepsSKzBm@iT*ASg2^F6>^9HH2j#3sT|bi@`bovwe8U zU~9HiM*Epj&Rdlxj2O%&&t739v|YOCl-a^9l3wMp4_%a=?@<8QTKTU1ADeKOH|aIl zv=1qGc-DY;(~l$av(Bsbcnb?*cI`2ywlxlXwAvBg}(tEXUOmX delta 6311 zcmai2ZH!gb70nxrz!;UZX;f;b6DSl6*7N;A?SxTgszjwUnoLM($BNoSN+M9JP4zY! ziy@GrG<}VV38PVJ+SC}*(J(2b5c?H+Iz2a*KVG&Zu69lOB$)U<(kG-#j+=ET)az7d-UX)&#k`clAgQ9{=W1V-Cx>0 z@>tKbwOw1T+jhahk#)u1=kD7w0a(dp?jY(hK@XX9~$Kx}0 z?R)X#UtfM>PjlAfzl{w&eR$U!XV$&HeCx_X?_Kk&uif^A;V&=y!I~peSM1z6cfokq z{AoX(vL~(o%_AqSIB~Ri_sEv*Z%@5>;qkH0Ke}h;tG&lIA9``gx8G{+_`{@;@$WtS z-bHtBSas{-`;H&`*=v{2Jh0>|SGqSJetGb_dydV2VA&48XzkD!_r_C)Uz&5vrSB{{ zxbwh2zA^dUAI;r(uTNK_Z!ev+X!JAB z|7Ylr^ZM>7)(`ibTDWQdtOXaXcw^|dKWr?2Yx#5ge>d>NidXOd@9c{=y&0eU@cRdL zz4Ys6a&*HB)Av30(7X>` z_|BZ|)7NgBv-`)RKbbqyJoU}ly{qT`>G1fw=I&P(?S1z2>o1>Ny#2$;<42$QwENDL z&0B{W(;m67YxKgd##0|nH704Lk`9{|Oup<=V^n3hTBYXe|7`rc&!}Ei{`Icx?QZ>} zRPaICjLMd5HmT;wcw=@E4gY4&bB2labs9H{;#_SkZY}Z|ScEU%|ad{n-aH5pX zT5K+Dkpg#!vhG+ZX9KVEx)yLz;^smiCoXA62j<|V&1+3)c@roQ?;@Y4Y(b8V%M^)s zTEMDQ%$Y6&#z@E7Dl69+WBpklMa3N(5Q>P-D{rOa04B;yN2i@!S5jB5Q!&Q+WlH?L zXVS)$cyqRdOj2H68W?y9wN^e87m{(l5D{w?vW!Gq?Fd#>XFU?|QYAt`n@niI7TbY* zt6jRtQXl`5I=QN#6=wwgXS~wSjQY{1%&+JJV{S& z9Kda1+fm_0DWa3kNp8kzI!+2V;C7n@d@8*2F;6G10Xvw<=uY)mf;|^->dkJ9QluUUozgomGbT zVPd3|00Sd02wRd7W0fde;BSqgR$$RuYI#DMtg-dnwQP<@kF#FZg>|SZ863upl@)G{ zkFvtC+0kV};E01syw_$)LK|##nWD{L8yuAwnr=H!RX%OX)Cp`#hMhz$s|0%`sSD*W zt0jXSIwIvWt0W^4@*bQuGIb!j6xS-C+B=Y$sK0=LMK^Q^MIaNU=O^qu! zM{*^E!c=0XT~3hOlw;T!!t+!~NSdBAA$THn06$s*BmN5hs7#hbib|8P2;hf=8ha`4 z(P(;up()pNKnwq8;wqp7>1JxxH{1S z)d>ak1+rlrlMVcs;8BPEi@{3S1cB>`=~yR`Q4uXzI4Sqa^RO<|wQz|)jFQ#Z%K3o=*ts4s`MW=s~R%_ z3?5_{=8|w25frh@5<%?sRK|GViKz(uV=8-K>8_&`lcClclcQb{Q;>Pbd5KZLTS*{| zCocP{UEB9rb< zo}XfPjD&b;^dF1_A#M$6QFp8%N%*~o_oL`=_|yp5B=@3y2oh>j@Y5QdkiPQ3 zhMdR)F-yovKp&-bPF4v-1rEfz68|>*Fh(iEU_%1rfswxCX%p%32^)P@gsr9_mX;*} zBeXU-p-(E>;9HKU_tM6fF1t_j$i-d#!vhNk)SwQ7USFRVhQaIcnCS11z90HG1=p|o mdawPzOP2Na^>wdabNi|__piG1u5P$Qx9pxZYhdwU_x}L(1~_p5 diff --git a/Doc/RomWBW Getting Started.pdf b/Doc/RomWBW Getting Started.pdf index 71978e4279ee99b6b19191e9596d4f3e63e4c042..56aff8a351f5d3de02705dba845f07ed26c05b46 100644 GIT binary patch delta 14377 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 delta 14415 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 diff --git a/ReadMe.md b/ReadMe.md index b2abe703..8f8bbc8e 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -3,7 +3,7 @@ ## Z80/Z180 System Software Version 3.1 Pre-release -28 Feb 2022 +21 Mar 2022 Wayne Warthen diff --git a/ReadMe.txt b/ReadMe.txt index 5f17c6dc..70410157 100644 --- a/ReadMe.txt +++ b/ReadMe.txt @@ -1,6 +1,6 @@ RomWBW Getting Started Wayne Warthen (mailto:wwarthen@gmail.com) -28 Feb 2022 +21 Mar 2022 @@ -17,7 +17,7 @@ RomWBW Z80/Z180 System Software Version 3.1 Pre-release -28 Feb 2022 +21 Mar 2022 Wayne Warthen wwarthen@gmail.com diff --git a/Source/CBIOS/cbios.asm b/Source/CBIOS/cbios.asm index 197cee9c..e1e16b13 100644 --- a/Source/CBIOS/cbios.asm +++ b/Source/CBIOS/cbios.asm @@ -302,6 +302,13 @@ BOOT: ; STANDARD BOOT INVOCATION ;LD SP,STACK ; STACK FOR INITIALIZATION LD SP,CCP_LOC ; PUT STACK JUST BELOW CCP +; +#IF DEBUG + CALL PRTSTRD + .DB "\r\nCBIOS Starting...$" + CALL PRTSTRD + .DB "\r\nCopying INIT code to 0x8000...$" +#ENDIF ; ; COPY INITIALIZATION CODE TO RUNNING LOCATION $8000 LD HL,BUFPOOL @@ -311,6 +318,11 @@ BOOT: PUSH HL ; SAVE START ADR AGAIN FOR BELOW PUSH BC ; SAVE LENGTH FOR BELOW LDIR ; COPY THE CODE +; +#IF DEBUG + CALL PRTSTRD + .DB "\r\nClearing disk buffer...$" +#ENDIF ; ; CLEAR BUFFER POP BC ; RECOVER LENGTH @@ -320,10 +332,30 @@ BOOT: INC DE ; OFFSET DEST DEC BC ; REDUCE LEN BY ONE LDIR ; USE LDIR TO FILL +; +#IF DEBUG + CALL PRTSTRD + .DB "\r\nStarting INIT routine at 0x8000$" +#ENDIF ; CALL INIT ; PERFORM COLD BOOD ROUTINE +; +#IF DEBUG + CALL PRTSTRD + .DB "\r\nResetting CP/M...$" +#ENDIF CALL RESCPM ; RESET CPM +; +#IF DEBUG + CALL PRTSTRD + .DB "\r\nPerforming Auto Submit...$" +#ENDIF CALL AUTOSUB ; PREP AUTO SUBMIT, IF APPROPRIATE +; +#IF DEBUG + CALL PRTSTRD + .DB "\r\nLaunching CP/M...$" +#ENDIF ; JR GOCPM ; THEN OFF TO CP/M WE GO... ; @@ -444,6 +476,12 @@ GOCPM: CURDSK: LD A,(CDISK) ; GET CURRENT USER/DISK GOCCP: +; +#IF DEBUG + CALL PRTSTRD + .DB "\r\nTransfer to CCP...$" +#ENDIF +; LD C,A ; SETUP C WITH CURRENT USER/DISK, ASSUME IT IS OK JP CCP_LOC ; JUMP TO COMMAND PROCESSOR ; @@ -2011,6 +2049,12 @@ BUFPOOL .EQU $ ; START OF BUFFER POOL HEAPEND .EQU CBIOS_END - 64 ; TOP OF HEAP MEM, END OF CBIOS LESS 32 ENTRY STACK ; INIT: +; +#IF DEBUG + CALL PRTSTRD + .DB "\r\nStarting INIT....$" +#ENDIF +; DI ; NO INTERRUPTS FOR NOW ; ADJUST BOOT VECTOR TO REBOOT ROUTINE @@ -2068,12 +2112,21 @@ INIT: LD (BNKBIOS),A ; ... AND SAVE IT LD A,E ; GET USER BANK RETURNED IN E LD (BNKUSER),A ; ... AND SAVE IT - +; + #IF DEBUG + CALL PRTSTRD + .DB "\r\nReseting HBIOS....$" + #ENDIF +; ; SOFT RESET HBIOS LD B,BF_SYSRESET ; HB FUNC: RESET LD C,BF_SYSRES_INT ; WARM START RST 08 ; DO IT - +; + #IF DEBUG + CALL PRTSTRD + .DB "\r\nCopying HCB....$" + #ENDIF ; CREATE A TEMP COPY OF THE HBIOS CONFIG BLOCK (HCB) ; FOR REFERENCE USE DURING INIT LD B,BF_SYSSETCPY ; HBIOS FUNC: SETUP BANK COPY diff --git a/Source/CBIOS/config.asm b/Source/CBIOS/config.asm index 180feaeb..3df64569 100644 --- a/Source/CBIOS/config.asm +++ b/Source/CBIOS/config.asm @@ -4,6 +4,7 @@ CLRRAMDISK .EQU CLR_AUTO ; CLR_ALWAYS, CLR_NEVER, CLR_AUTO (CLEAR IF INVALID DIR AREA) WRTCACHE .EQU TRUE ; ENABLE WRITE CACHING IN CBIOS (DE)BLOCKING ALGORITHM DSKTRACE .EQU FALSE ; ENABLE TRACING OF CBIOS DISK FUNCTION CALLS +DEBUG .EQU FALSE ; MISCELLANEOUS DEBUG TRACING ; CPM_LOC .EQU $D000 ; LOCATION OF START OF CCP ; diff --git a/Source/CBIOS/util.asm b/Source/CBIOS/util.asm index 1d32990e..3ef5e9e8 100644 --- a/Source/CBIOS/util.asm +++ b/Source/CBIOS/util.asm @@ -105,14 +105,61 @@ WRITESTR2: POP AF RET ; +#IF DEBUG +; +; PRINT A STRING AT ADDRESS SPECIFIED IN HL +; STRING MUST BE TERMINATED BY '$' +; USAGE: +; LD HL,MYSTR +; CALL PRTSTR +; ... +; MYSTR: .DB "HELLO$" +; +PRTSTR: + LD A,(HL) + INC HL + CP '$' + RET Z + CALL COUT + JR PRTSTR ; +; PRINT A STRING DIRECT: REFERENCED BY POINTER AT TOP OF STACK +; STRING MUST BE TERMINATED BY '$' +; USAGE: +; CALL PRTSTRD +; .DB "HELLO$" +; ... ; -TSTPT: - PUSH DE - LD DE,STR_TSTPT - CALL WRITESTR - POP DE - JR REGDMP ; DUMP REGISTERS AND RETURN +PRTSTRD: + EX (SP),HL + PUSH AF + CALL PRTSTR + POP AF + EX (SP),HL + RET +; +; PRINT A STRING INDIRECT: REFERENCED BY INDIRECT POINTER AT TOP OF STACK +; STRING MUST BE TERMINATED BY '$' +; USAGE: +; CALL PRTSTRI(MYSTRING) +; MYSTRING .DB "HELLO$" +; +PRTSTRI: + EX (SP),HL + PUSH AF + LD A,(HL) + INC HL + PUSH HL + LD H,(HL) + LD L,A + CALL PRTSTR + POP HL + INC HL + POP AF + EX (SP),HL + RET +; +#ENDIF ; ; PANIC: TRY TO DUMP MACHINE STATE ; diff --git a/Source/Doc/Architecture.md b/Source/Doc/Architecture.md index cff5522d..ed9a33e5 100644 --- a/Source/Doc/Architecture.md +++ b/Source/Doc/Architecture.md @@ -223,6 +223,18 @@ initialization routine. At this point, the prior HBIOS code has been discarded and overwritten. Finally, the Boot Loader is invoked just like a ROM Boot. +ROM-less Boot +------------- + +Some hardware supported by RomWBW has a special mechanism for loading +the initial code. These systems have no ROM chips. However, they +have a small hardware bootstrap that loads a chunk of code from a +disk device directlly into RAM at system startup. + +The startup then proceeds very much like the Application Boot +process described above. HBIOS is installed in it's operating bank +and control is passed to the loader. + Notes ----- diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index 24cdd573..4382b343 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -1530,21 +1530,51 @@ MBC_SINGLE: ; #ENDIF ; -; IF THIS IS A ROM-LESS SYSTEM, THEN WE NEED TO COPY THE "APP" BANK TO -; TPA. IT IS DONE PRIOR TO COPYING HBIOS TO IT'S FINAL BANK BECAUSE -; THE SOURCE OF THE APP BANK CODE MAY BE THE BANK THAT HBIOS WANTS TO -; USE AS IT'S FINAL LOCATION (PRIMARILY IN CASE OF RAMBOOT WHERE THE -; SYSTEM HAS THE MINIMUM 128KB OF RAM). +; IF THIS IS A ROM-LESS SYSTEM, THEN WE NEED TO COPY THE PAYLOAD +; (LOADER, MONITOR, ZSDOS) THAT HAS BEEN LOADED TO PHYSICAL RAM +; BANKS 0 AND 1 TO THE USER TPA BANK TO RUN AFTER BOOT. +; IT IS DONE PRIOR TO COPYING HBIOS TO IT'S FINAL BANK BECAUSE +; THE PAYLOAD MAY EXTEND INTO THE HBIOS OPERATING BANK. THIS +; HAPPENS PRIMARILY IN THE CASE WHERE THE +; SYSTEM HAS THE MINIMUM 128KB OF RAM. ; #IFDEF ROMBOOT #IF (ROMSIZE == 0) - LD A,(HB_CURBNK) + ; + ; THE PAYLOAD IS LIKELY TO CROSS OVER THE RAM BANK 0/1 + ; BOUNDARY. BNKCPY DOES NOT HANDLE THIS BECAUSE IT ASSUMES + ; THE COMMON BANK IS USED AFTER PASSING OVER THE BANK + ; BOUNDARY. WE WORK AROUND THAT HERE BY DOING TWO COPIES. + ; THE FIRST ONE HANDLES THE PORTION OF THE PAYLOAD FROM THE + ; END OF HBIOS TO THE BANK BOUNDARY ($8000). THE SECOND + ; ONE HANDLES THE PORTION THAT EXTENDS INTO THE SECOND + ; PHYSICAL RAM BANK. +; + ; COPY PORTION OF PAYLOAD FOLLOWING HBIOS TO THE BANK + ; BOUNDARY AT $8000 INTO START OF TPA. + LD A,BID_RAM0 LD (HB_SRCBNK),A LD A,BID_USR LD (HB_DSTBNK),A LD HL,HB_END LD DE,0 - LD BC,$8000 + LD BC,$8000-HB_END +; + #IF (MEMMGR == MM_Z280) + CALL Z280_BNKCPY + #ELSE + CALL HBX_BNKCPY + #ENDIF +; + ; COPY REMAINDER OF PAYLOAD EXTENDING INTO THE SECOND PHYSICAL + ; RAM BANK. NOTE THAT THE DESTINATION ADDRESS (DE) IS + ; ALREADY CORRECT FROM THE PRIOR COPY. + LD A,BID_RAM0+1 + LD (HB_SRCBNK),A + LD HL,$0000 + ; DE IS ALREADY CORRECT + LD BC,$8000-($8000-HB_END) +; #IF (MEMMGR == MM_Z280) CALL Z280_BNKCPY #ELSE @@ -3697,6 +3727,11 @@ SYS_RESINT: ; GO BACK TO ROM BOOT LOADER ; SYS_RESWARM: +; +#IF (ROMSIZE == 0) + JR SYS_RESCOLD +#ENDIF +; CALL SYS_RESINT ; #IF (MEMMGR == MM_Z280) @@ -3713,6 +3748,14 @@ SYS_RESWARM: ; RESTART SYSTEM AS THOUGH POWER HAD JUST BEEN TURNED ON ; SYS_RESCOLD: +; +#IF (ROMSIZE == 0) + LD DE,STR_RESTART + CALL Z,WRITESTR + DI + HALT +#ENDIF +; #IF (MEMMGR == MM_Z280) JP Z280_RESTART #ELSE @@ -7015,6 +7058,7 @@ STR_LOWBAT .DB "\r\n\r\n+++ LOW BATTERY +++$" STR_PANIC .TEXT "\r\n>>> PANIC: $" STR_SYSCHK .TEXT "\r\n>>> SYSCHK: $" STR_CONTINUE .TEXT "\r\nContinue (Y/N)? $" +STR_RESTART .TEXT "\r\n\r\n>>> Press hardware reset button to restart system\r\n\r\n$" ; #IF (DSKYENABLE) ; 'H','B','I','O',' ',' ',' ',' ' #IF (DSKYMODE == DSKYMODE_V1) diff --git a/Source/ver.inc b/Source/ver.inc index 709318d5..d011272e 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,4 +2,4 @@ #DEFINE RMN 1 #DEFINE RUP 1 #DEFINE RTP 0 -#DEFINE BIOSVER "3.1.1-pre.161" +#DEFINE BIOSVER "3.1.1-pre.162" diff --git a/Source/ver.lib b/Source/ver.lib index dd51943f..5fc0acbd 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 1 rup equ 1 rtp equ 0 biosver macro - db "3.1.1-pre.161" + db "3.1.1-pre.162" endm

_C0|gU$HxEye|X*e|7TrvogB_A2%dR9ATk_!LX~`eJBr zFw3~g%XvblexFE)c{`>u)5vqv;5=8Fc`TLJ8O753lWs7QPBoKaDrXx>Bl?r(8cE;7 z#|;2t-nLZUY9zJyC*5HrHTEanZ6tkQCdE|d8%ci>NpWw-hOOT1vR8)w^I6mcPG0pS zbN3eEbRyw&38V?fDW=PCwY=C2aTvl(LUNymRUSypC!n7|kz~Ho;N_pOSyIKKMEI>p zEtm0HXoU!i^sls{jv8LaBvA)#PevW1QJuy=iW+DiC0`Hv-;ECGhB*$&i?AADJ;HYg zX*W3}2SPqVF+z5ZLwX3ohwuSH7s9x?4k;7iA%s^E)+1~|_&Y+{%?@cM!a@W;!acV* zq{k5c2Vo<^hzZg5%O{!n6@~i>+f<%JqVZ0 zcVHb4?{@=Ug!KrU5sn~CzsDh6htQ7j_`MEkFTx>&$$1Xx9|-n*hjcl@BM5&&s79dv z@4@o`!a;;ygtYq{(rkp+5&nWed1~;iL--h>8)0&RLt291MR*E<@|5EFEJ8iPL4=#` zcSyG*Jb>^J0_Abx`8+}$!Wj=Zq;nB|iSR1IZUo9R@#hXHh%o6vhjb&tGKAL=wjo#- zh&*rOIrZxEahIiytxod{IVH4g(v2!BR+8=(T>eFPn0%p)StgLoc6`0GO8 z?oo&I6~Z4}4(VREL&{j>kU|LeKIV{O7lRKFW;~AgFHt8#`L7((-Af#jr4a2PT<`?& zgRpX`L&{Yg(odEF#|UxD9n$X+W_r*^gq2>0G^YstU*V8mLD-D2AK`>29nw^U1u-2X7b2 zSiKhQA{6`qJc`hT5c5a$4IvBR0fZ$8Cw>SVBK#g<9l}n8ZUjrnA_Rw#aQ3s{Eri<< zya>NXcn{(42)5?{55g4)w<5R^N)TR0s6%K)=tfBX9qK`FAl!mbgzz@PW`tb`N#&>q zAp_wi1OJkqzPZ?bo(xq3Pbw|p%?C!^E* zw4!D_)m1LYd3Dt!{x_BXok)LkUs7{FQ*&3Vt7sym<~FFS#`8$2np>jgdevM-%~jRh zVl}s1%`H=NJMy(vGz(%^-bk7mc9V}gs#K?{bvq1*$V}y+c|s$^=lnkY&I-m+DW9|0 zw3nT#t-+U5<_RUT@D1>n7OI|5LhnYkP?d{XkXfs&t5ZBx+u{>TF=~sLK-?iIuUO^e#-fa!P$p)xHS_ z0&_}KXQ|RA=LdDGO3Ssm#raybvP-sL6<6J6smH2`{Css)Tb$2buI#C`Zp9G>cR7|w zbBj^f(!#zN0sGN{HFFN@D0KVm!-lj*(XW1ZCVrNBr>iH+P3T< zJ>_R=eYxepl(MVVx(igtR_skwb(V^PjJAh@-#73q9A8AvpPWL7P8(+BfSy2&wHB<_Rnt$;?Gbt&QrNj*Isie$3=SaX#~|j% zAm##b-SnPOZ%V#xQ_lKm=>8Qm9C*5wZnP9ug?K z(u8moN7+1ZGf}+^Q-@lqmJcXUE)Qd(JhfJ7KN|zX+G-_UXOGSs7B@-knJFgwKNews z@38C--nTURaukdR;YmN%006=;04xpI6}3reJ6m;@s8}ixtd8kRJ88!wwM6 z=!!4P3r0Vl;bGro-Q~-Ie8d>RmI`04mxU6j!=PM5ym^_9={>&nZl-aN>s1b6AS7Hz z13_WE*9rn=c|pLS`cY&cWO+H48-i_9WFQ<=*pJ{UA*zBAcygQ|D|iJ1p&qo&@zOx( zF$Y2e9|)#wY_&Se*^_9N%kF3a=VgEA$(*#*iSouC?2CeU&MNDda%U?$!9mtKHVOQN z;$6;ihfCHDW|~9lT(fR-JREXZYG^!U{Df#e0wV9S0eYi!7`U%V#XmtRmQdbd^N|qC_i()w!(3>D?)*I>6*tr7fY78E&H>(zox4L+`NqskHJ;Sd-KAe?~KAw+Xa<)SxGpcmMB z6;Eh@Bxqe~fjxtF#JSY=BM$aK!IQu^zN`|Zomj7qxJ1n=VP3ezhH4K1A4ZV+nJ=fj zw^nJhsC$$>Ypq+mYQcu2j;vd~?L3xX-Krdh0!Cttbt`lesv9Gek=jbbodrk3lf;#X zk?;u;1W*@sIZFodb&1K>(2RnwNnEL)VX&|t{SdU=K8R>bi*=t;AJhAhnp3VE#sDD@ zjebOc-)GGM#IpA~2s$HU(M1UC^satBoIEHC(V#yI zXF+UFFqqYMbvf;NitO-h1d2(3ftx7<(@R=;z*@>LX z4q^|0v?$h7br((;Fso;$#aM-e6o93q?y1_70B#A9z#nVH25vHUly&faK*9JzJ+AwMiBPEhagXM?Q<0L^WN9jwxpPTriAKItd=3t*S{ae^~ zd#(8z>^j@Qqg!^=F{3;>hlc!IG65~=eJI5(LrXpNQ-*KXkg3@5q0|00PwUy-!3{;C zoJUxYi0N#1H@nmg{ofMLr6Si3j^8po_ABU=TaBPZv;;YKJ<2ZWoNf z6Cps^&oNGiBe*USqB=a!T2+_6>)5J~yF!pDAs}tt3VnN}`RuY>g<0Hb%Ss zg>twQLzhnw`loVVK{bAr~EMWY#8ff z*_#JUQwsy~HyDuYclcveVKB<@rV#lBaDuWL2d>W->;jmMTB3muCrod}E*7mj9upp* zeiS?5LT*4%b>Jg*^%aHycaOu|)mf6>rPW~AgI8@$;Y%?;;wa~~2d1B#2WhkrjKVKq z=mSfG;TO2S@Higvik9840vw+8bCAJr^x4G zN${7HVM1nYWe;JH3at#oX6APTwX$~5VF{96p33=*oDz4CFehqrVg7?^jdDUrlUi%^ z9E5uU11MT8)AlBabIQif69Z(3cf!AlK0{K|L-cEqq>l1cz;ZR+6*cg^*f&+}iZhB@ zcZix$81!Lj7*szrQUu?F&td%w_eC{k$Yt!iG%f}?*zqtl$zEOnj9Pj>RN-ELOoGY0 zpe!=KhV$r~$V}~s!WMr+2!wB|-%BOtYU)-_|PEEuu!9AY)vD<a#E&zOaTZ9Gcq0{S$J85@awp0zamm!T}0-p++Z_&H%6|EEVAy8;px z9b%X8C;9N;Lt>x6+4BETccRB>!@nXt3~9<4YMAb@8$~8B`|(sFlS*8t{Fk}z zzegs4V7QEm*)PB4^f;~G*e_1+;#$QpjoGDeXwg?1KPb`vmD^t@a(5REC{(Aib47Kd z`m0mJZ}gW|!&Q;C;UWT?fEP|9iA;tcd|~PBq&&#FgE8*pl(q2|2N+ z<>kAg`ty6)ji8+|n)2q0S zV6)H{PVwU^NmMsWPUWEfcO(~@i42r7mVwu39G9_G@Y|a7C}VcKMO58?O6Y(my5Nic z&)2K6-~U(YRoKk`O1{+B#Z|y#X%Q=~*p69^-FpJUz5NhwHXuA?wYAuKjtwEN|ENI1 z#K&}&W{_3t=T)r<)(_PM<*WsBZ?5#yv0Yeg^0{gCS=l37n$_>rt@iDRs{1Y5&;v2` z!d!Y&`d;-rOh(bMI*nHD(>x}#agv#w2F?eoX#p-SAV{{^x0}3gJLv!CIesQ_yt9nZJp~9* zs|R44l7s{iqsDaZ4=2=wv>?vsf=R=$vI-gXL*i`}HN#HAnhG|*(AdL>jf_6Hr@+Q= zPLWWE3`V$NEt{1+7V!CS<8dICh8vRtRU`SBw0$MUA;;eEqmiWpI+FV;m;3GM?H2gD zuycnCSz46m8lZguvY-;MfMXeiIxO6$?}2n{TZkWW#0_5?NeS z;I@^(V0F+wm{0jJ14EW_)LCi(9VBY1h0A~e@{4e{jc^B{HjFHb#@$dMyN%XVIHE>! zum*`&W;gKU<#>AMD0q73hw&t^hT97acB-~-2ikyWpe;y;kBGl)Eq;z98xV;Gp~-~m z{6gazKz_IIooJ14F$dgUziclT{5=r-5LC7nmJO(*1kOGeu^=Vq(4!9Ge;UQZDGN3yssq48Dc2Fhn?_(i3^BEVz|Z}+!5?1Z z9bMv^WmA zF$W78hI~EGkgph-mMw!M$4dJ6FAR#olB5yC(-a?{YJnYOM`AG0Q-1e-YDA0-KTo=t zkCOiJAdC}ZR5U?j3zO}C*)`M)$YxSl*euzQRs-3h4YG^?K8&+=%hb(sd1$b{A`xb? zIzc1UmXIdgSmUr7(nO4Xz{L$T`?kqsqS<<|!y($PXe7HLsAiS3k~7I{Q~&P*?+XGC z`#sCqcd4|943{C7i52PXY4{xv#JSoatU*y!0C5q!W@@8cPP@Bcl5+t_2pXz2IIXw& zg$mnjSi*cKK$$PM!oC^!i=Hh|CBPt?&uQuXH<2}9+!H~$rE3`8t0=+Hss=4v2AJDJ zXt|Y;6~aaVR(r+(8}Znpn9P=+fvJJafmj7fSJHaV^vt1 z`47&e4Z{}(j#$hW@&wW(tp=8g7CrSNQL^m^L&636TBl48!gc_GvSX23~;>HOUT%Qw)haGE{7eOf^FX$#I|A@NX*+p%nK!%b+nbme{H*kAUt;~_0RXynlYU5 z+hTiYly|1#ZXrw@Ff@0`T)9HUL=SUy|4}Jq+EtvBjBf{8U| z)i`AVF_MO({?XzEQ|&0}GCX^j&657>_d-O^w?^{$7D-~Yk%hP=TnxdLf(^cL*dpNV z!VVL4A2z;V1Y6sb`ee4`9CAmf*x!*thhVV#-rT3ex6JS@nUqgEi}GPldszy0c*Ln$ zWnSzhuT|^K%5X-vF8n#X%Mc?ewCImRJ~$SNEG%IjO!DTWtuxant5-gM|I<+fGE^9 zB9pTgBCL9GGuktT56R(KU`b+``-ci;E|Moo5X zO6RkPhRJoo?s!{s67E3CFTxna+A4ZnJLh&RDU z9JoYu*xqPw5Cf1c!3GEnXySRbM#TxoxHRO&#@iaTmeXoDrYHJ<=}mHRHlop{Mf=Ao zl^Z`nW2|wGw{K&K98>Xh#7r(~8jGE@?~muZn2o)uTyJArAm6!2yEOT6W7^(~V_ozf z!@9TfR8hsqaX-8Vns#aPbB_0*Jwnm3HcSHxBf_8H57qCUC-$!5$~P9{;c@>IppaWC4ytJOI;>7u^kbQ!jLMh>j;ov@77+xSTW;}`*}$C*{JmliF39Rnf) zWa=$kdy&cnhC~aPG2^riD@HjE1SBNK9A}nvR6k%XixL1vWUgzjWkpRKh^j~Tv(Z=6 zx5}Mv+GhAvsoL+G?1v)Wwx-~rcp>n}^e|?@P}u4YYpuDJc>$Da6jFgRf!9bkariHS zPV~`X@8dYd`8+~MzQzyLvZs?tp$b0o(vKej4FW+xg^6yF5OtQ&+koBV%Hg{$2A#deot1Fu_&Ha|AMnYIxyc;Iy0LYcc+R(m3{iC# zHoGXh5|#FDb=6{^P5CGxdeZZL9IF?b?Que!F=#pZsv5ae zBNuEX)yP$-VlO^aFyD*+8B}TyD@qWh6r+@4lu~?oicu<8K`EMAkcCL4TG)+7DX&q= zYn1Z(^1PxHraOgRslO0*9k7#(QYA(yoDbstDDmatWDp%1@GU4|yW#~zrADq&BUh;} z56A0yuB=i(MDrmNqI&i|mBM;)qo4(0E-=YPkKn;X+cx#(B_N2p87FmjQ56^{I3yq7 ziJ$VSuob;MK|N^Q;d_>!h@&I)Vp^->2YzwRXWd8vSD679T_iwMz%>GJj0ot<*qH+Q zJnWyrZ3hWPwLr8JY!zSgXy!sZl4~gL)LrUMX_q)sVBG}3|NF@{340o0BT%@*Ex`E;YdGoH)L$ za?a)GFc>}WBlRO+E*<3B_6XH*G#+QCW1QgZ4a$8(W=n?w z(}FTcaGbe`Nbs+HPjj)`#&*Zjb=y#Gxy6k=1Nf3nz?mR?QgQ!C^V^mOO$1ia)Qom2R=b%0~hTi>prq@Y8JEU-IT71bk$5(*|j{K=!yJ_nXa(=csfxN z>0UG4%Zhk1z7g};B7~x>N$Cqp8^C>~Dpieo)di)j zkmPq1*X|-t+uQK1fr7)7jZ0zcF7_ymo&{x82RImYu&KN>*%q-%`$o^sM0J;P*ds3w zU zE&i72x}J>HqE*ONiTsk--__IxQJGa-)aXiF535=V$FIK$59m4j7Sa-JV18R84mOfa zMCMRAyKT4{)MM44hTj{~q;jkRO4vW7fcIDhyzFLZ-yvm6j#Z|FoiSXQ(qok=W#5ts zMAK^Di+lpX2OGa0!a(RQ+W$!NinyZ9uEY%jsT)kBZX%@a^zl-*&4gDNVo*(4hT$r{ zsC@3hz5^wO^r`Gv@Re~(^&QKWcH*aE{zJIto66RpKJ!gs|ARMm2j%m!Cn?T(5QoeW z7gn^G0vW^WBcUOYf2a1P(4TDO0T}4KSXuaLYgTc1hBZqKUvAA(!c(kS-tfiNtdj5r z)~wQS+JG8&i#n|zqo&u%Zc_h9$PC9?v1o#kG6yW?dwnrJC`V!!p0Ma@|tC;YeX;E7>SO0Hxm7@E)q>zABn!Q zITF=Bjd(I#H;N;!nE!_(o`&Y5dm5UDcp6}wz@0#IWY&qpT;hm$434GcdtT>`6S!c7 z2SZGYk6O3*JWTy#*fXejsK0?u&JVxaaV32MVEvwlVK;_G`60-0bo9Li+^uA6c;t)Q za67G}L^?4*Pq;HzQJWWww}IP$$csUa31dG#923@R(=GAP$#6?>>~RXv!F7(T;oK6< z4)`U6Q(_~(YRD=Xm^X6co-bVU&dVEf`Y-5`+N%Yl8!ilzbbYBS-_3FujtmR?x`U%v z5I{I|_~l}TXJe=6otIVRy@!lnyoHl*GSE>16z@CIA$kCtyq5-ESf&at#Ap z3VhH>nU_;Q1>A0^7Ey#R@2-ZGt~yuKqF~-y zEusi67Vy1H_d7z?t9hkr5yjavAdx{d_EWxOkE44;0#F&oNQBJ4dYCgkXVI8rmutxS|3935X~)IWE_QCumvUFc2L>G_f}?!O*`bS{D}RG5b{2WO(5i3jH&KH;y~Pa5%E-Z z_lpFL7t0rtVWPxzz8i!*m2u3*IMJ{~aY4jiX^!*KsFVTz?uNJcF-E#!&6EsL*L{ej zC?6;8sWLs~7u5`qC&yXpWRwz|5yxKPz>fpK_YG~HF8C15lh2hjD=y^QWi`@ln06ai zs73M_&TCvl3X?nPb~P+js5vF92G%q@t-~}$-t}R68cFpX^%k~B7SXnOxO)MR8u=8t zKc&A%=!YN-E}-jA^@$74`lVneIK*TE0iW57xKTBXd7Xhv+4~&a8Z1tyl##&b`A6~i zmkyS)Z26lUFINl|$=oF!mH)s|;9++IkiiU1z(A{;Ha8H zq^6xLiN;QrYV4d)4~S`5J>3!CNta{Nq&?G$l?-t&=d{G5t#KSp(MBT_C^Lpsio{lS z6As0YS`40nU<5u-pluH&v99hSv3B7&dBtIh{Sm+Z zgB3G&Emp!ZUX;BG5?LALenMXUB?r$(Z);?4GNu$6t1)ksk;P4kk1V`VUXg;uhm1v3 z^?XWuoT_dajo7d7D+iSIOL|!>dw+u`yPWboDlb0~rQ{XcsjM3|1{z}NlN$!ai_d|5z5Ld zbZ~ISeAzn{^)vcCos3%+PL@|JqXurpuUO$Jub^L$&$wOoTJU6#P^KJt`2o287cI}Y z86>6TAEUaAYZuOxSGe0kzD6Wq z0o*uCR)dQV!`2{6Ubbs3xQ2FwknsTJFBUdS!~}wtEJ*fem7-m~XVqSB4^GB;3`wDd zOEM>dUyrgi=KleBE{$xvz;(!QCF3$Z+Cup@7(__Rh(*X>qqQ`Cc^A82fhhGk5~o@Z zM>($bau}=C{2ge+ZFB4;+?fE$+w~<0Be8oBmkSv(w^r@MuSiwN&mal67b(38-$fOJ z=tnWwX!uMO>jHhS&<~lZ7EL0)na3|-7)bhA`9ykk5b0@wFmSope21{?x#~x`;^1W8uMj@Gr>|g*OibkE*O$P|eK}obAW`GtTg;=Eo=toXl zqt+v6kG&&;7_`?o`e5O*9)7{~^R#n2Xpo#)u>)c!5g8X7iX9L*WX|Uj=28K1Uk>Pn zJwltlZ_3vW+NKzbM8CjQ_ifUSixL@xhR1&kmVreWd=K-1d3 zio623WnFyBy4a4%2}svu%ZU3-2YGDuZZB%eO>RpIf1gs3uX>PIewllqj0QXKu)aOjLxa;$*ZTZg(c_NHhW| zK{9AfkPLUSi7hB;LF~W>W$BlJL5H*;jqIb0X&O;{OdoAPQ-*;9n&<;Ff5?EQ^ymT2 z^Zmep=CnQs-9AoQB$7GgCJ1j9ztc;QgzB*Q&nI&RHn6QKT!RHb6`horj|;rAK7+V3KN^zi%?+bkN?yrVJsZ5H-U{Uhbs8#o8Q2#+c>e znqBzA3YH9{@j~A1Tkk;dCs-v+Xd7k9TMcn9~g%8YQfilZSY!Ul%~;lfQyb zDrhwnmpIUNJm@s+546?>d*Jjavsc;bQB1{+A`vBm>*z;A8;Icu?Zy!eAqyMD{FMP@ zR-4()Sm+r{tb6YyVwDae7VRPt#42TNd}3iWZJJWni3Fk7@WT#RN`ttAsv_m~|DIMO z(h>gn0{9PTHOf2GbO92AZ3!@3u7#ir^7iX{&`pnO`4D%Z^y<=u~%dMHB4Cc4J7)!85@+vV6G82E(uh z?m8Q2{M?jFerF*`$Qw~>*-Dm1`&w`W)}yPU)}yP<^=N)i=^)&*tN%pf1?)yVvZ@wsH>Cqc}V}z(NB1TBHGH5=4dQM8B|Y z;fKetExQRfe@B@{LUO}s-4zF;6}v__nYZ+~anfVuJf# zqb|NDFB|z#j0^L%gQQP`LZ3p2nErzetHDpWO1GI@_;logh(dah>r;H`SEyhStMP*| z(2t114&K7{V-;zz7|6Yi#6Z~~F<^+21!XMBu#=664K8%*qJ9EZ!%~d(!C!WK!-qTL zx*$1t+kz?3+w^wWj&#*Lcj6nnK-nMh3xk7g=mz29rR1oerm#UOCeea6H&Sp}b55x{ z7QY{Wg>n2MK$e$Y;CNPXUp_XA9PYz=7PcLr7Cu3oF)X$%anrs^Vmp_{nf^yf#cj?O+``BaUB{U zhoiHc|8Ron^a8c_WBiDWa^z_J#3qv%>Qv7NXC3=3XON@;^Wltn!2IBWAucA4Fpay^ z66(bXZWGhRbQ^au9Vz-K>PS(Ym@8l8R5998eyV7VRA(t=AlV+rs7}PZ%@@62R{HyI7iaE8OLZi zQ{X3BL?`|kmZ)MLT-pn02e3pM_5hGvCv^5Z8|#FAiD(e$4|gg3rckNUYvS*R7~_&S z)(U+76AbakxxmJP(%z3PA#7bS_#7TgW5;A~J@JHbuX{0M;9g$+@iBs7SQT=1z-Ls@o*UEZrO@!s}~qh

Firstly, build the compiler. It should not be necessary to rebuild bios.bin; +but if you have to, it assembles using the z80asm assembler (part of +the z80pack emulation package which can be found on the Walnut Creek +CP/M CDROM) or the +ZMAC assembler +(downloadable from <http://www.nenie.org/cpcip/index.html#zmac>). +

8$Qv|5nOrD!g6(`uX4kiEx{Nkmo31{is>`?DfW-%37ydYVkSkt1@j`yw z@G4{a`{At8FP+Ve`9s>P3qM%%DNlnM$K0D9p8u_ z^}gNmxM^{GX}B^lM)Ar0-xusyx_|b{rs{^^za>0!@tW<+7d|=i;rnyMdmdifP?_eI z9VFMN6aLBdn4jq0)i>vlMbCP?p*`5U;`F?x>c6hrG;*QGlqCPipU!{UcKpVR)~e_4 zd34(0k#D_L{7B6gceUIb8s(I{#%ubhcYB`v>1&=BBH!^my7uw8FZ`|Uy%N)^s|x~B zCr2+Dv(e|J{$rPfi$8u8ay)6*@|P-~-1gKP54P^HzT(wB!LZ=6-cs-P3ez0Z$vQ6# zOPjs1aLvJop4on5=ed0;#!(+X(7Ec$9{HdBuY`6?j!PeQcSX+9(tkC!z54o&KW;7Q z%@m_d-YuWU8ppjn>_O*(@{GK3OI&82Z@Av{>>~&Mw))GuYok9*{^aBE@8X|Q><(O3 zaR2?oXU8tR%e;Z}>6_Sn^4ab`{^{UbZ_KpMUe{qwjq60{3`$jcak1~# zgacnbHTw9U^Zc4df5+}#H)qqqD;K68`$O&Nb0e)^2pbkPp1%6w){h@r`b=@aiPzWX zRrlrm^fj0Nr_6h0!_38s+}sr3>%HD?kDp{qrmgZTy6cPSYfPn^3jfjmg;R3IY3JYl zwAH&~eWS;#*I#dpD}H8g`Wf!<`LwIR&iiD?*^~|MxBt(Lt7kr5*IhK@M{`N+>}`eboI0@PT-gNYnc`@t zDXZ`Dc$2H~7Lqr)EPQjie7v8Z=dp)bFD|Tc?XrDa^{o5pf`c!8k^R3ueHT_e!5M^C%=Xwy5zhfc5$9q4&)-|^?XK7Y^YxsE;Mi5aGU?W*W_ zVR-m?=Z6A6E%W!x?fk>EyuYNb+u;5BigneVANhRoLcja=@$WJodtP*{ow?oj+m4-X zkF5PpHpbShD7tT1&b79}{Q6Dt#lc@H)|cELa@zKp_TxXUs6OZS&v`f6_eZqf?EKzG#jb{qBX8yPNZ#5C1Or z>%Z?@x7lO+2KgHb_rL4neXLsxT}uO&F)qKKcYMdN>I0v@tKG9DA>=);=bz|!+WVME zY`XMmjq2ig&(j?rKb-#g>B~Rt6V{eIbZ#skcoi5dy`C~<|BLxg7QLJE!^i#WvuAx&99a3e$IIVzcz?3wA?F3n`dKGHb^-nV?fM%Be&fJz9Qcg`zj5F<4*bS}-#G9a2mb%#!2bg>Zy3M; From 48c5f4da9d86c2fb283422f65630e2b9cc679dfa Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Tue, 25 Jan 2022 16:35:59 -0800 Subject: [PATCH 05/34] Cleanups and CPUSPD App - Added very preliminary CPUSPD app which works only on MBC and SBC - HBIOS initialization code cleanup - Prep work on RAM size detection --- Source/Apps/Test/Build.cmd | 1 + Source/Apps/Test/Clean.cmd | 1 + Source/Apps/Test/Makefile | 2 +- Source/Apps/Test/cpuspd/Build.cmd | 10 + Source/Apps/Test/cpuspd/Clean.cmd | 6 + Source/Apps/Test/cpuspd/Makefile | 7 + Source/Apps/Test/cpuspd/cpuspd.asm | 392 +++++++++++++++++++++++++++++ Source/HBIOS/ctc.asm | 2 +- Source/HBIOS/hbios.asm | 362 +++++++++++++++++++------- Source/HBIOS/sio.asm | 4 +- Source/ver.inc | 2 +- Source/ver.lib | 2 +- 12 files changed, 693 insertions(+), 98 deletions(-) create mode 100644 Source/Apps/Test/cpuspd/Build.cmd create mode 100644 Source/Apps/Test/cpuspd/Clean.cmd create mode 100644 Source/Apps/Test/cpuspd/Makefile create mode 100644 Source/Apps/Test/cpuspd/cpuspd.asm diff --git a/Source/Apps/Test/Build.cmd b/Source/Apps/Test/Build.cmd index fb322d6b..f8e126d4 100644 --- a/Source/Apps/Test/Build.cmd +++ b/Source/Apps/Test/Build.cmd @@ -22,6 +22,7 @@ pushd rzsz && call Build || exit /b & popd pushd vdctest && call Build || exit /b & popd pushd kbdtest && call Build || exit /b & popd pushd ps2info && call Build || exit /b & popd +pushd cpuspd && call Build || exit /b & popd goto :eof diff --git a/Source/Apps/Test/Clean.cmd b/Source/Apps/Test/Clean.cmd index 9e1f36d9..7cedf243 100644 --- a/Source/Apps/Test/Clean.cmd +++ b/Source/Apps/Test/Clean.cmd @@ -17,3 +17,4 @@ pushd rzsz && call Clean || exit /b 1 & popd pushd vdctest && call Clean || exit /b 1 & popd pushd kbdtest && call Clean || exit /b 1 & popd pushd ps2info && call Clean || exit /b 1 & popd +pushd cpuspd && call Clean || exit /b 1 & popd diff --git a/Source/Apps/Test/Makefile b/Source/Apps/Test/Makefile index aed32df2..db9b6b34 100644 --- a/Source/Apps/Test/Makefile +++ b/Source/Apps/Test/Makefile @@ -1,5 +1,5 @@ OBJECTS = -SUBDIRS = DMAmon I2C inttest ppidetst ramtest tstdskng rzsz vdctest kbdtest ps2info +SUBDIRS = DMAmon I2C inttest ppidetst ramtest tstdskng rzsz vdctest kbdtest ps2info cpuspd DEST = ../../../Binary/Apps/Test TOOLS =../../../Tools diff --git a/Source/Apps/Test/cpuspd/Build.cmd b/Source/Apps/Test/cpuspd/Build.cmd new file mode 100644 index 00000000..c99af191 --- /dev/null +++ b/Source/Apps/Test/cpuspd/Build.cmd @@ -0,0 +1,10 @@ +@echo off +setlocal + +set TOOLS=../../../../Tools +set PATH=%TOOLS%\tasm32;%PATH% +set TASMTABS=%TOOLS%\tasm32 + +tasm -t180 -g3 -fFF cpuspd.asm cpuspd.com cpuspd.lst || exit /b + +copy /Y cpuspd.com ..\..\..\..\Binary\Apps\Test\ || exit /b diff --git a/Source/Apps/Test/cpuspd/Clean.cmd b/Source/Apps/Test/cpuspd/Clean.cmd new file mode 100644 index 00000000..9ecb428f --- /dev/null +++ b/Source/Apps/Test/cpuspd/Clean.cmd @@ -0,0 +1,6 @@ +@echo off +setlocal + +if exist *.com del *.com +if exist *.lst del *.lst +if exist *.bin del *.bin diff --git a/Source/Apps/Test/cpuspd/Makefile b/Source/Apps/Test/cpuspd/Makefile new file mode 100644 index 00000000..aedcb761 --- /dev/null +++ b/Source/Apps/Test/cpuspd/Makefile @@ -0,0 +1,7 @@ +OBJECTS = cpuspd.com +DEST = ../../../../Binary/Apps/Test +TOOLS =../../../../Tools + +USETASM=1 + +include $(TOOLS)/Makefile.inc \ No newline at end of file diff --git a/Source/Apps/Test/cpuspd/cpuspd.asm b/Source/Apps/Test/cpuspd/cpuspd.asm new file mode 100644 index 00000000..4ce9e457 --- /dev/null +++ b/Source/Apps/Test/cpuspd/cpuspd.asm @@ -0,0 +1,392 @@ +; +;======================================================================= +; HBIOS CPU Speed Selection Tool +;======================================================================= +; +; Simple utility that sets CPU speed on RomWBW systems that support +; software speed selection. +; +;======================================================================= +; +#include "../../../HBIOS/hbios.inc" +; +cpumhz .equ 8 ; for time delay calculations (not critical) +; +; General operational equates (should not requre adjustment) +; +stksiz .equ $40 ; Working stack size +; +rtc_port .equ $70 ; RTC latch port adr +; +restart .equ $0000 ; CP/M restart vector +bdos .equ $0005 ; BDOS invocation vector +; +; primary hardware platforms +; +plt_sbc .equ 1 ; SBC ECB Z80 SBC +plt_zeta .equ 2 ; ZETA Z80 SBC +plt_zeta2 .equ 3 ; ZETA Z80 V2 SBC +plt_n8 .equ 4 ; N8 (HOME COMPUTER) Z180 SBC +plt_mk4 .equ 5 ; MARK IV +plt_una .equ 6 ; UNA BIOS +plt_rcz80 .equ 7 ; RC2014 W/ Z80 +plt_rcz180 .equ 8 ; RC2014 W/ Z180 +plt_ezz80 .equ 9 ; EASY Z80 +plt_scz180 .equ 10 ; SCZ180 +plt_dyno .equ 11 ; DYNO MICRO-ATX MOTHERBOARD +plt_rcz280 .equ 12 ; RC2014 W/ Z280 +plt_mbc .equ 13 ; MULTI BOARD COMPUTER + +; +;======================================================================= +; + .org $100 ; standard CP/M executable +; +; + ; setup stack (save old value) + ld (stksav),sp ; save stack + ld sp,stack ; set new stack +; + call crlf + ld de,str_banner ; banner + call prtstr +; + call main ; do the real work +; +exit: + ; clean up and return to command processor + call crlf ; formatting + ld sp,(stksav) ; restore stack + jp restart ; return to CP/M via restart +; +; +;======================================================================= +; Main Program +;======================================================================= +; +main: +; +; Get HBIOS platform ID +; +; + ; Get platform id from RomWBW HBIOS + ld b,BF_SYSVER ; HBIOS VER function 0xF1 + ld c,0 ; Required reserved value + rst 08 ; Do it, L := Platform ID + ld a,l ; Move to A +; + cp plt_sbc + jr set_spd + cp plt_mbc + jr set_spd + jp err_not_sup ; Platform not supported +; +set_spd: + ; Use first char of FCB for speed selection + ld a,($5D) + cp ' ' + jr z,show_spd + and $5F ; make upper case + cp 'F' ; fast + jr z,set_fast + cp 'H' ; high + jr z,set_fast + cp 'S' ; slow + jr z,set_slow + cp 'L' ; low + jr z,set_slow + jr usage +; +set_slow: + ld a,(HB_RTCVAL) + and ~%00001000 + jr new_spd +; +set_fast: + ld a,(HB_RTCVAL) + or %00001000 + jr new_spd +; +new_spd: + ld (HB_RTCVAL),a + out (rtc_port),a + call show_spd + xor a + ret +; +show_spd: + ld a,(HB_RTCVAL) + and %00001000 + jr z,show_spd1 + ld de,str_fast + jr show_spd2 +show_spd1: + ld de,str_slow +show_spd2: + call crlf2 + call prtstr + ret +; +usage: + call crlf2 + ld de,str_usage + call prtstr + or $FF + ret +; +; Error Handlers +; +err_not_sup: + ld de,str_err_not_sup + jr err_ret +; +err_ret: + call crlf2 + call prtstr + or $FF ; signal error + ret +; +;======================================================================= +; Utility Routines +;======================================================================= +; +; +; Print character in A without destroying any registers +; +prtchr: + push af + push bc ; save registers + push de + push hl + ld e,a ; character to print in E + ld c,$02 ; BDOS function to output a character + call bdos ; do it + pop hl ; restore registers + pop de + pop bc + pop af + ret +; +prtdot: +; + ; shortcut to print a dot preserving all regs + push af ; save af + ld a,'.' ; load dot char + call prtchr ; print it + pop af ; restore af + ret ; done +; +; Print a zero terminated string at (de) without destroying any registers +; +prtstr: + push af + push de +; +prtstr1: + ld a,(de) ; get next char + or a + jr z,prtstr2 + call prtchr + inc de + jr prtstr1 +; +prtstr2: + pop de ; restore registers + pop af + ret +; +; Print a hex value prefix "0x" +; +prthexpre: + push af + ld a,'0' + call prtchr + ld a,'x' + call prtchr + pop af + ret +; +; Print the value in A in hex without destroying any registers +; +prthex: + call prthexpre +prthex1: + push af ; save AF + push de ; save DE + call hexascii ; convert value in A to hex chars in DE + ld a,d ; get the high order hex char + call prtchr ; print it + ld a,e ; get the low order hex char + call prtchr ; print it + pop de ; restore DE + pop af ; restore AF + ret ; done +; +; print the hex word value in hl +; +prthexword: + call prthexpre +prthexword1: + push af + ld a,h + call prthex1 + ld a,l + call prthex1 + pop af + ret +; +; print the hex dword value in de:hl +; +prthex32: + call prthexpre + push bc + push de + pop bc + call prthexword1 + push hl + pop bc + call prthexword1 + pop bc + ret +; +; Convert binary value in A to ascii hex characters in DE +; +hexascii: + ld d,a ; save A in D + call hexconv ; convert low nibble of A to hex + ld e,a ; save it in E + ld a,d ; get original value back + rlca ; rotate high order nibble to low bits + rlca + rlca + rlca + call hexconv ; convert nibble + ld d,a ; save it in D + ret ; done +; +; Convert low nibble of A to ascii hex +; +hexconv: + and $0F ; low nibble only + add a,$90 + daa + adc a,$40 + daa + ret +; +; Print value of A or HL in decimal with leading zero suppression +; Use prtdecb for A or prtdecw for HL +; +prtdecb: + push hl + ld h,0 + ld l,a + call prtdecw ; print it + pop hl + ret +; +prtdecw: + push af + push bc + push de + push hl + call prtdec0 + pop hl + pop de + pop bc + pop af + ret +; +prtdec0: + ld e,'0' + ld bc,-10000 + call prtdec1 + ld bc,-1000 + call prtdec1 + ld bc,-100 + call prtdec1 + ld c,-10 + call prtdec1 + ld e,0 + ld c,-1 +prtdec1: + ld a,'0' - 1 +prtdec2: + inc a + add hl,bc + jr c,prtdec2 + sbc hl,bc + cp e + ret z + ld e,0 + call prtchr + ret +; +; Start a new line +; +crlf2: + call crlf ; two of them +crlf: + push af ; preserve AF + ld a,13 ; + call prtchr ; print it + ld a,10 ; + call prtchr ; print it + pop af ; restore AF + ret +; +; Add hl,a +; +; A register is destroyed! +; +addhla: + add a,l + ld l,a + ret nc + inc h + ret +; +; Delay ~10ms +; +delay: + push af + push de + ld de,625 ; 10000us/16us +delay0: + ld a,(cpuscl) +delay1: + dec a + jr nz,delay1 + dec de + ld a,d + or e + jp nz,delay0 + pop de + pop af + ret +; +; +; +;======================================================================= +; Constants +;======================================================================= +; +str_banner .db "RomWBW CPU Speed Selector v0.1, 25-Jan-2022",0 +str_slow .db " CPU speed is SLOW",0 +str_fast .db " CPU speed is FAST",0 +str_err_not_sup .db " ERROR: Platform not supported!",0 +str_usage .db " Usage: CPUSPD [F|S]",0 +; +;======================================================================= +; Working data +;======================================================================= +; +stksav .dw 0 ; stack pointer saved at start + .fill stksiz,0 ; stack +stack .equ $ ; stack top +; +cpuscl .db cpumhz - 2 +; +;======================================================================= +; + .end \ No newline at end of file diff --git a/Source/HBIOS/ctc.asm b/Source/HBIOS/ctc.asm index 9d0d69f7..b1698699 100644 --- a/Source/HBIOS/ctc.asm +++ b/Source/HBIOS/ctc.asm @@ -173,6 +173,7 @@ CTC_PRTCFG1: PRTS("TIM256$") #ENDIF ; + #IF (CTCDEBUG) PRTS(" DIVHI=$") LD A,CTC_DIVHI & $FF CALL PRTHEXBYTE @@ -181,7 +182,6 @@ CTC_PRTCFG1: LD A,CTC_DIVLO & $FF CALL PRTHEXBYTE ; - #IF (CTCDEBUG) PRTS(" PREIO=$") LD A,CTC_PREIO CALL PRTHEXBYTE diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index 7ed0e96e..198b6fcc 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -70,6 +70,8 @@ ; #DEFINE HBIOS ; +;;;#DEFINE TESTING +; ; MAKE SURE EXACTLY ONE OF ROMBOOT, APPBOOT, IMGBOOT IS DEFINED. ; MODCNT .EQU 0 @@ -170,16 +172,14 @@ MODCNT .SET MODCNT + 1 ; ; ; -#IF (CTCENABLE) -CTCA .EQU CTCBASE + 0 ; CTC: CHANNEL A REGISTER ADR -CTCB .EQU CTCBASE + 1 ; CTC: CHANNEL B REGISTER ADR -CTCC .EQU CTCBASE + 2 ; CTC: CHANNEL C REGISTER ADR -CTCD .EQU CTCBASE + 3 ; CTC: CHANNEL D REGISTER ADR -#ENDIF -; -; THIS EQUATE IS UPDATED BY DRIVER INCLUDES THAT SHARE THE RTC LATCH. -; AS DRIVER IS INCLUDED, IT WILL USE .SET TO SET ANY BITS THEY OWN -; AND WANT TO SET AS DEFAULT. +; THE RTCDEF EQUATE IS INITIALIZED HERE AND UPDATED BY DRIVER INCLUDES +; THAT SHARE THE RTC LATCH. AS EACH DRIVER FILE IS INCLUDED, IT CAN +; USE .SET TO SET ANY BITS THEY OWN WITHIN THE RTC LATCH BYTE. +; SINCE RTCDEF IS CHANGED AFTER IT NEEDS TO BE USED BY THE CODE, IT +; CANNOT BE USED DIRECTLY TO SET THE LATCH. INSTEAD, THE FINAL VALUE +; OF RTCDEF IS USED TO INITIALIZE A STORAGE BYTE CALLED RTCDEFVAL AT +; THE END OF HBIOS.ASM. SO (RTCDEFVAL) CAN BE USED ANYWHERE IN +; HBIOS.ASM TO ACCESS THE FINAL RTCDEF VALUE. ; RTCDEF .EQU 0 ; ALLOWS DRIVERS TO SET BITS ; @@ -188,19 +188,19 @@ RTCDEF .SET RTCDEF | %00000001 ; SC128 I2C SCL BIT #ENDIF ; #IF ((CPUSPDCAP==SPD_HILO) & (PLATFORM==PLT_MBC)) -#IF (CPUSPDDEF==SPD_HIGH) + #IF (CPUSPDDEF==SPD_HIGH) RTCDEF .SET RTCDEF | %00001000 ; DEFAULT SPEED HIGH -#ELSE + #ELSE RTCDEF .SET RTCDEF & ~%00001000 ; DEFAULT SPEED LOW -#ENDIF + #ENDIF #ENDIF ; #IF ((CPUSPDCAP==SPD_HILO) & (PLATFORM==PLT_SBC)) -#IF (CPUSPDDEF==SPD_HIGH) + #IF (CPUSPDDEF==SPD_HIGH) RTCDEF .SET RTCDEF & ~%00001000 ; DEFAULT SPEED HIGH -#ELSE + #ELSE RTCDEF .SET RTCDEF | %00001000 ; DEFAULT SPEED LOW -#ENDIF + #ENDIF #ENDIF ; ; @@ -470,6 +470,7 @@ HBX_RAM: RLCA ; SCALE SELECTOR TO RLCA ; ... GO FROM Z180 4K PAGE SIZE RLCA ; ... TO DESIRED 32K PAGE SIZE + AND %11111000 OUT0 (Z180_BBR),A ; WRITE TO BANK BASE LD A,N8_DEFACR | 80H ; SELECT RAM BY SETTING BIT 7 OUT0 (N8_ACR),A ; ... IN N8 ACR REGISTER @@ -491,6 +492,7 @@ HBX_ROM: HBX_BNKSEL1: RLCA ; CONTINUE SHIFTING TO SCALE SELECTOR RLCA ; FOR Z180 4K PAGE -> DESIRED 32K PAGE + AND %11111000 OUT0 (Z180_BBR),A ; WRITE TO BANK BASE RET ; DONE #ENDIF @@ -962,7 +964,7 @@ HBX_BUF_END .EQU $ .DB BID_USR ; HB_DSTBNK: BNKCPY DESTINATION BANK ID .DW 0 ; HB_CPYLEN: BNKCPY LENGTH .FILL 4,0 ; FILLER, RESERVED FOR FUTURE HBIOS USE - .DB RTCDEF ; SHADOW VALUE FOR RTC LATCH PORT + .DB 0 ; SHADOW VALUE FOR RTC LATCH PORT .DB $FE ; HB_LOCK: HBIOS MUTEX LOCK JP HBX_INVOKE ; HB_INVOKE: FIXED ADR ENTRY FOR HBX_INVOKE (ALT FOR RST 08) JP HBX_BNKSEL ; HB_BNKSEL: FIXED ADR ENTRY FOR HBX_BNKSEL @@ -1085,10 +1087,12 @@ Z280_BOOTERR .TEXT "\r\n\r\n*** Application mode boot not supported under Z280 n DI ; NO INTERRUPTS IM 1 ; INTERRUPT MODE 1 -#IF ((PLATFORM=PLT_MBC) | (PLATFORM=PLT_SBC)) - LD A,(HB_RTCVAL) ; SET DEFAULT - OUT (RTCIO),A ; SPEED -#ENDIF +;#IF ((PLATFORM=PLT_MBC) | (PLATFORM=PLT_SBC)) + ; INITIALIZE RTC LATCH BYTE + ; FOR SOME PLATFORMS THIS CONTROLS HI/LO SPEED CIRCUIT + LD A,(RTCDEFVAL) ; GET DEFAULT VALUE + OUT (RTCIO),A ; SET IT +;#ENDIF ; #IF (DIAGENABLE) LD A,%00000001 @@ -1099,13 +1103,15 @@ Z280_BOOTERR .TEXT "\r\n\r\n*** Application mode boot not supported under Z280 n XOR A ; LED IS INVERTED, TURN IT ON #ENDIF #IF (LEDMODE == LEDMODE_RTC) - LD A,(HB_RTCVAL) - OR %00000001 ; LED 0 - LD (HB_RTCVAL),A ; SAVE TO SHADOW REGISTER + LD A,(RTCDEFVAL) ; DEFAULT LATCH VALUE + OR %00000001 ; LED 0 ON #ENDIF OUT (LEDPORT),A #ENDIF ; + ; WARNING: ALTHOUGH WE ARE INITIALIZING SP HERE, IT IS NOT YET + ; SAFE TO PUSH VALUES TO THE STACK BECAUSE SOME PLATFORMS WILL + ; NOT YET HAVE RAM MAPPED TO THE UPPER 32K YET! LD SP,HBX_LOC ; SETUP INITIAL STACK JUST BELOW HBIOS PROXY ; #IF (CPUFAM == CPU_Z280) @@ -1288,25 +1294,54 @@ Z280_INITZ: ; AT THIS POINT, RAM SHOULD BE AVAILABLE IN THE COMMON BANK ; (TOP 32K). ; - DIAG(%00000011) +; NOTIFICATION THAT WE HAVE MADE THE JUMP TO RAM BANK! +; THE DIAG() MACRO IS NOT USED BECAUSE IT USES THE STACK AND WE DO +; NOT WANT TO EFFECT RAM UNTIL AFTER THE BACKUP BATTERY STATUS CHECK +; IS PERFORMED NEXT. +; + LD A,%00000011 + OUT (DIAGPORT),A +; +; WE USE THE TWO BYTES IMMEDIATELY BELOW THE PROXY TO STORE A COUPLE +; VALUES TEMPORARILY BECAUSE WE MAY BE OPERATING IN ROM AT THIS POINT. +; (HBX_LOC - 1) = BATCOND, (HBX_LOC - 2) = APPBANK +; THERE IS NOTHING ON THE STACK AT THIS POINT SO, HERE, WE JUST RESET +; THE STACK TO HBX_LOC - 2. +; + LD SP,HBX_LOC - 2 ; -; CHECK BATTERY BACKUP STATUS BEFORE WE COPY PROXY TO UPPER MEMORY +; CHECK BATTERY BACKUP STATUS BEFORE WE TOUCH RAM (UPPER MEMORY) ; ; IF A DS1210 POWER CONTROLLER IS INSTALLED AND BATTERY BACKUP IS NOT INSTALLED ; OR IS LESS THAN 2V THEN THE DS1210 WILL BLOCK THE SECOND RAM ACCESS. ; FAILURE TO COMPLETE TWO RAM ACCESSES BEFORE INSTALLING PROXY WILL RESULT ; IN THE ROM ID BYTES NOT BEING COPIED CORRECTLY AND CP/M APPLICATIONS ; WILL NOT START CORRECTLY WHEN THEY CHECK THE ROM ID VERSION BYTES. -; THE BATTERY CONDITION VALUE IS TEMPORARILY STORED AT HBX_LOC - 1. +; THE BATTERY CONDITION VALUE IS TEMPORARILY STORED AT HBX_LOC - 1 +; BECAUSE WE ARE CURRENTLY RUNNING IN ROM. AFTER WE TRANSITION HBIOS +; TO RAM, THE VALUE IS MOVED TO IT'S REAL LCOATION AT HB_BATCOND. ; IF THERE IS NO DS1210 IN THE SYSTEM, THE CODE BELOW DOES NO HARM. ; - DEC SP ; RESERVE A STACK BYTE + LD HL,HBX_LOC - 1 ; POINT TO BYTE XOR A ; ZERO MEANS LOW BAT - LD (HBX_LOC - 1),A ; WRITE IT (SHOULD ALWAYS WORK) + LD (HL),A INC A ; 1 MEANS BAT OK - LD (HBX_LOC - 1),A ; OVERWRITE IF NVC ALLOWS IT + LD (HL),A ; -; IF APPBOOT, SAVE CURRENT BANKID +; INSTALL PROXY IN UPPER MEMORY +; THE HB_CURBNK MUST BE PRESERVED IF THIS IS AN APPBOOT. +; + LD A,(HB_CURBNK) ; SAVE EXISTING HB_CURBNK + LD DE,HBX_LOC ; AS PER ABOVE + LD HL,HBX_IMG + LD BC,HBX_SIZ + LDIR +; +#IFDEF APPBOOT + LD (HB_CURBNK),A ; RESTORE HB_CURBNK +#ENDIF +; +; SAVE CURRENT BANKID ; ; THIS IS NOT GOING TO WORK IF THE APP BOOT IMAGE IS LOADED ; USING THE UNA FAT32 LOADER. SHOULD PROBABLY CHECK THAT THERE @@ -1314,23 +1349,101 @@ Z280_INITZ: ; THIS USE CASE IS PROBABLY NON-EXISTENT. THE IMG BOOT IMAGE ; SHOULD WORK FINE WITH THE UNA FAT32 LOADER. ; -#IFDEF APPBOOT - LD A,(HB_CURBNK) - DEC SP ; RESERVE A STACK BYTE - LD (HBX_LOC - 2),A ; SAVE BANK - PUSH AF ; ALSO ON STACK -#ENDIF +; THIS VALUE IS TEMPORARILY STORED AT HBX_LOC - 2 +; BECAUSE WE ARE CURRENTLY RUNNING IN ROM. AFTER WE TRANSITION HBIOS +; TO RAM, THE VALUE IS MOVED TO IT'S REAL LCOATION AT HB_APPBNK. ; -; INSTALL PROXY IN UPPER MEMORY + LD A,(HB_CURBNK) ; GET HB_CURBNK + LD (HBX_LOC - 2),A ; ... AND SAVE TEMP FOR APPBNK ; - LD DE,HBX_LOC ; AS PER ABOVE - LD HL,HBX_IMG - LD BC,HBX_SIZ - LDIR +; THE RTCVAL FIELD OF THE PROXY DATA NEEDS TO BE INITIALIZED HERE +; BECAUSE IT CANNOT BE PRE-INITIALIZED (SEE COMMENTS ABOVE WHERE +; RTCVAL EQUATE IS DEFINED). ; -; THIS IS WHERE WE SHOULD PROBE FOR THE ACTUAL NUMBER OF RAM -; BANKS AVAILABLE IN THE SYSTEM. THE PROBE CODE WOULD NEED + LD A,(RTCDEFVAL) + LD (HB_RTCVAL),A +; +#IFDEF TESTING +; +; THIS IS WHERE WE PROBE FOR THE ACTUAL NUMBER OF RAM +; BANKS AVAILABLE IN THE SYSTEM. THE PROBE CODE NEEDS ; TO BE COPIED TO AND RUN FROM THE COMMON RAM BANK. +; + LD DE,$F000 + LD HL,RS_IMAGE + LD BC,RS_LEN + LDIR + CALL RS_START + JP RS_IMAGE + RS_LEN +; +; CODE THAT IS COPIED TO $F000 TO PERFORM RAM SIZE DETECTION +; +RS_IMAGE: + .ORG $F000 +RS_START: + LD A,(HB_CURBNK) ; GET CURRENT BANK + PUSH AF ; SAVE IT + + LD C,0 ; RUNNING BANK COUNT + LD IX,RS_ARY ; ORIG BYTE STORAGE ARRAY PTR +RS_LOOP1: + LD A,C + ADD A,$80 ; OFFSET BY START OF RAM BANKS + CALL HBX_BNKSEL ; SELECT THE BANK + + LD A,($7FFF) ; GET ORIGINAL VALUE + LD (IX),A ; SAVE IT TO RESTORE LATER + INC IX ; BUMP IX + + LD A,$AA ; TEST LOC WITH $AA + LD ($7FFF),A + LD A,($7FFF) + CP $AA + JR NZ,RS_DONE + + LD A,$55 ; TEST LOC WITH $55 + LD ($7FFF),A + LD A,($7FFF) + CP $55 + JR NZ,RS_DONE + + ; STORE A UNIQUE VALUE + LD A,C + LD ($7FFF),A + OR A ; ZERO? + JR Z,RS_NEXT ; SKIP STORED VALUE CHECK + + ; VERIFY ALL STORED VALUES + LD B,C ; INIT LOOP COUNTER + LD E,0 ; INIT BANK ID +RS_LOOP3: + LD A,E + ADD A,$80 + CALL HBX_BNKSEL + LD A,($7FFF) + CP E ; VERIFY + JR NZ,RS_DONE ; ABORT IF MISCOMPARE + INC E ; NEXT BANK + DJNZ RS_LOOP3 +; +RS_NEXT: + INC C ; ADD 1 TO RAM BANK COUNT + JR RS_LOOP1 ; AND LOOP TILL DONE +; +RS_DONE: + LD E,C ; FINAL BANK COUNT TO E + ; RESTORE SAVED VALUES + LD IX,RS_ARY + LD B,C ; LOOP COUNT + LD C,$80 ; BANK ID +RS_LOOP2: + LD A,C + CALL HBX_BNKSEL + INC C + LD A,(IX) ; GET VALUE + LD ($7FFF),A ; RESTORE IT + INC IX + DJNZ RS_LOOP2 ; ALL BANKS ; ; MBC RUNTIME MEMORY SIZE ADJUSTMENT ; @@ -1348,21 +1461,59 @@ Z280_INITZ: ; AND THEN POKES THE MASK INTO AN XOR INSTRUCTION IN THE MBC ; MEMORY MANAGER. ; -#IF (MEMMGR == MM_MBC) - LD HL,CB_RAMBANKS ; IN NUMBER OF RAMBANKS DETECTED FOR MBC + #IF (MEMMGR == MM_MBC) +; + ;LD HL,CB_RAMBANKS ; IN NUMBER OF RAMBANKS DETECTED FOR MBC LD A,%11101011 ; IS 4 (128KB) OR 16 (512KB) THEN - AND (HL) ; ZERO THE LAST BANK MASK OTHERWISE + ;AND (HL) ; ZERO THE LAST BANK MASK OTHERWISE + AND E ; ZERO THE LAST BANK MASK OTHERWISE JR Z,MBC_SINGLE ; CALCULATE THE LAST BANK MASK (BANKS/2) RRA ; 256K = %00000100, 1024K = %00010000 MBC_SINGLE: LD (HBX_MBCMSK),A -#ENDIF ; -; IF APPBOOT, RESTORE CURRENT BANK ID + #ENDIF ; -#IFDEF APPBOOT + ; RETURN TO ORIGINAL BANK POP AF - LD (HB_CURBNK),A + CALL HBX_BNKSEL + LD A,E ; RETURN BANK COUNT + LD ($FFEA),A ; STASH HERE FOR A BIT + RET +; +RS_ARY .EQU $ +; +RS_LEN .EQU $ - RS_START + .ORG RS_IMAGE + RS_LEN +; +#ELSE +; +; MBC RUNTIME MEMORY SIZE ADJUSTMENT +; +; THE MBC RAM BOARD CAN CONTAIN 1 OR 2 RAM CHIPS. THEY CAN BE +; EITHER 128K OR 512K EACH. SO THE MBC RAM BOARD CAN HAVE A +; TOTAL OF 128K, 256K, 512K, OR 1024K. THE COMMON (HIMEM) RAM +; IS ALWAYS MAPPED TO THE LAST 32K OF THE FIRST CHIP ON THE BOARD. +; IF THERE ARE TWO CHIPS ON THE BOARD, THIS MEANS THE COMMON +; BANK WILL APPEAR IN THE "MIDDLE" OF THE PHYSICAL RAM BANKS. +; ROMWBW NEEDS THE COMMON BANK TO BE AT THE LAST BANK OF PHYSICAL +; RAM IN ORDER TO HAVE SEQUENTIAL RAM BANKS AVAILABLE FOR THE +; RAM DISK. TO WORK AROUND THIS, WE FLIP THE HIGH BIT OF THE +; BANK ID FOR AN MBC SYSTEM IFF IT HAS 2 CHIPS (256K OR 1024K). +; THE CODE BELOW GENERATES THE CORRECT MASK TO ACCOMPLISH THIS +; AND THEN POKES THE MASK INTO AN XOR INSTRUCTION IN THE MBC +; MEMORY MANAGER. +; + #IF (MEMMGR == MM_MBC) + LD HL,CB_RAMBANKS ; IF NUMBER OF RAMBANKS DETECTED FOR MBC + LD A,%11101011 ; IS 4 (128KB) OR 16 (512KB) THEN + AND (HL) ; ZERO THE LAST BANK MASK OTHERWISE + JR Z,MBC_SINGLE ; CALCULATE THE LAST BANK MASK (BANKS/2) + RRA ; 256K = %00000100, 1024K = %00010000 +MBC_SINGLE: + LD (HBX_MBCMSK),A + #ENDIF +; #ENDIF ; ; IF ALREADY EXECUTING IN RAM, BYPASS RAM BANK INSTALLATION @@ -1382,39 +1533,6 @@ MBC_SINGLE: LD BC,$8000 CALL HBX_BNKCPY ; -#IF (1) -; -; POPULATE THE CRITICAL RAM BANK NUMBERS. -; -; ASSUME THAT CB_RAMBANKS IS THE NUMBER OF 32K RAM BANKS THAT HAS BEEN SET EITHER -; AT ASSEMBLY TIME OR BY PROBING THE ACTUAL AVAILABLE MEMORY (NOT IMPLEMENTED YET). -; - LD A,(CB_RAMBANKS) ; CALCULATE START - DEC A ; RAMBANK AFTER - ADD A,($80 + (PLT_RAM_R / 32)) ; RESERVED BANKS -; - LD HL,CB_BIDCOM - LD B,4 -CB_IDS: LD (HL),A ; POPULATE CB_BIDCOM - INC HL ; POPULATE CB_BIDUSR - DEC A ; POPULATE CB_BIDBIOS - DJNZ CB_IDS ; POPULATE CB_BIDAUX - - LD A,(CB_BIDUSR) - LD (HB_SRCBNK),A ; POPULATE HB_SRCBNK - LD (HB_DSTBNK),A ; POPULATE HB_DSTBNK -; - LD A,+($80 + (PLT_RAM_R / 32)) ; POPULATE CB_BIDRAMD0 ; START RAMBANK - LD (HL),A - INC HL -; - LD A,(CB_RAMBANKS) ; POPULATE CB_BIDRAMDN ; END RAMBANK - DEC A - SUB TOT_RAM_RB - LD (HL),A -; -#ENDIF -; ; TRANSITION TO HBIOS IN RAM BANK ; #IF (MEMMGR == MM_Z280) @@ -1435,15 +1553,30 @@ HB_RAMFLAG .DB FALSE ; INITIALLY FALSE, SET TO TRUE BELOW AFTER RAM TRANSITION ; HB_START1: ; BNKCALL ARRIVES HERE, BUT NOW RUNNING IN RAM BANK ; + ; WE RESET THE STACK HERE BECAUSE WE ARE NOT GOING TO RETURN + ; FROM THE BNKCALL. REMEMBER THAT WE STORED A COUPLE BYTES + ; RIGHT BELOW HBX_LOC, SO THE STACK IS SET TO START JUST BELOW + ; THAT. + LD SP,HBX_LOC - 2 ; RESET STACK +; + ; NOTIFY THAT WE MADE THE TRANSTION! DIAG(%00000111) LED(%00000010) ; - LD A,(HBX_LOC - 1) ; RECALL BATTERY STATE AND SAVE - LD (HB_BATCOND),A ; FOR FUTURE REFERENCE -; - LD SP,HBX_LOC ; RESET STACK SINCE WE DO NOT RETURN + ; SET THE IN-RAM FLAG LD A,TRUE ; ACCUM := TRUE LD (HB_RAMFLAG),A ; SET RAMFLAG +; + ; RECOVER DATA PASSED PRIOR TO RAM TRANSITION + ; (HBX_LOC - 1) = BATCOND, (HBX_LOC - 2) = APPBNK + POP HL ; POP 2 BYTES + LD A,H ; GET FIRST BYTE PUSHED + LD (HB_BATCOND),A ; ... AND SAVE AS BAT COND +; +#IFDEF APPBOOT + LD A,L ; GET SECOND BYTE PUSHED + LD (HB_APPBNK),A ; ... AND SAVE AS APPBNK +#ENDIF ; #IF (MEMMGR == MM_Z280) ; NOW POINT TO RAM COPY OF Z280 INT/TRAP TABLE @@ -1457,10 +1590,6 @@ HB_START1: ; BNKCALL ARRIVES HERE, BUT NOW RUNNING IN RAM BANK ; IF APPBOOT, WE NEED TO FIX UP A FEW THINGS IN PAGE ZERO ; #IFDEF APPBOOT -; - ; GET AND SAVE APP BOOT BANK ID - LD A,(HBX_LOC - 2) - LD (HB_APPBNK),A ; ; MAKE SURE RST 08 VECTOR IS RIGHT LD A,$C3 @@ -1484,6 +1613,39 @@ HB_START1: ; BNKCALL ARRIVES HERE, BUT NOW RUNNING IN RAM BANK #ENDIF #ENDIF ; +#IF FALSE +; +; POPULATE THE CRITICAL RAM BANK NUMBERS. +; +; ASSUME THAT CB_RAMBANKS IS THE NUMBER OF 32K RAM BANKS THAT HAS BEEN SET EITHER +; AT ASSEMBLY TIME OR BY PROBING THE ACTUAL AVAILABLE MEMORY (NOT IMPLEMENTED YET). +; + LD A,(CB_RAMBANKS) ; CALCULATE START + DEC A ; RAMBANK AFTER + ADD A,($80 + (PLT_RAM_R / 32)) ; RESERVED BANKS +; + LD HL,CB_BIDCOM + LD B,4 +CB_IDS: LD (HL),A ; POPULATE CB_BIDCOM + INC HL ; POPULATE CB_BIDUSR + DEC A ; POPULATE CB_BIDBIOS + DJNZ CB_IDS ; POPULATE CB_BIDAUX + + LD A,(CB_BIDUSR) + LD (HB_SRCBNK),A ; POPULATE HB_SRCBNK + LD (HB_DSTBNK),A ; POPULATE HB_DSTBNK +; + LD A,+($80 + (PLT_RAM_R / 32)) ; POPULATE CB_BIDRAMD0 ; START RAMBANK + LD (HL),A + INC HL +; + LD A,(CB_RAMBANKS) ; POPULATE CB_BIDRAMDN ; END RAMBANK + DEC A + SUB TOT_RAM_RB + LD (HL),A +; +#ENDIF +; ;================================================================================================== ; RECOVERY MODE ;================================================================================================== @@ -2137,6 +2299,20 @@ HB_Z280BUS1: CALL PRTSTRD .TEXT "KB RAM$" ; +#IFDEF TESTING +; + CALL PRTSTRD + .TEXT ", RAMBANKS=0x$" + LD A,($FFEA) + CALL PRTHEXBYTE +; + CALL PRTSTRD + .TEXT ", RTCDEF=0x$" + LD A,(RTCDEFVAL) + CALL PRTHEXBYTE +; +#ENDIF +; #IF 0 ; ; DIAGNOSTIC DISPLAY OF BANK IDS IN HCB @@ -6245,6 +6421,8 @@ IOPRVAL .DW 0 ; TEMP STORAGE FOR IOPR ; HB_BATCOND .DB 0 ; BATTERY CONDITION (0=LOW, 1=OK) ; +RTCDEFVAL .DB RTCDEF ; STORAGE FOR RTC DEFAULT VALUE +; #IF (BT_REC_TYPE != BT_REC_NONE) HB_BOOT_REC .DB 0 ; BOOT MODE (0=NORMAL, 1=RECOVERY MODE) #ENDIF diff --git a/Source/HBIOS/sio.asm b/Source/HBIOS/sio.asm index 8e7e323a..f1de029c 100644 --- a/Source/HBIOS/sio.asm +++ b/Source/HBIOS/sio.asm @@ -716,7 +716,7 @@ SIO_INITDEV4: ; ; ALL GOOD. PROGRAM THE CTC CHANNEL LD A,(IY+13) ; GET CTC CHANNEL - ADD A,CTCA ; ADD TO CTC BASE PORT ADR + ADD A,CTCBASE ; ADD TO CTC BASE PORT ADR #IF (SIODEBUG) PRTS(" CTC=$") CALL PRTHEXBYTE @@ -815,7 +815,7 @@ SIO_INITSAFE: ; IF A CTC CHANNEL IS CONFIGURED, PROGRAM IT FOR ; SIMPLE 1:1 SCALING. LD A,(IY+13) ; GET CTC CHANNEL - ADD A,CTCA ; ADD TO CTC BASE PORT ADR + ADD A,CTCBASE ; ADD TO CTC BASE PORT ADR LD C,A ; AND PUT IN C FOR I/O LD A,%01010111 ; CTCC CONTROL WORD VALUE OUT (C),A ; PREP CTC CHANNEL diff --git a/Source/ver.inc b/Source/ver.inc index 1176d907..50edcccd 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,4 +2,4 @@ #DEFINE RMN 1 #DEFINE RUP 1 #DEFINE RTP 0 -#DEFINE BIOSVER "3.1.1-pre.148" +#DEFINE BIOSVER "3.1.1-pre.150" diff --git a/Source/ver.lib b/Source/ver.lib index 496282d8..091ba1e6 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 1 rup equ 1 rtp equ 0 biosver macro - db "3.1.1-pre.148" + db "3.1.1-pre.150" endm From 21a38aed6e3bc8b957890668222a39a74849e40d Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Wed, 26 Jan 2022 18:10:18 -0800 Subject: [PATCH 06/34] CPU Speed Change API - Moved the CPU speed changing mechanism into the HBIOS as an API call. - Added support for CPU speed changing on Z180 platforms. --- Doc/ROM Applications.pdf | Bin 193895 -> 193895 bytes Doc/RomWBW Applications.pdf | Bin 229563 -> 229563 bytes Doc/RomWBW Architecture.pdf | Bin 447508 -> 451133 bytes Doc/RomWBW Disk Catalog.pdf | Bin 134793 -> 134793 bytes Doc/RomWBW Getting Started.pdf | Bin 277975 -> 272619 bytes ReadMe.md | 50 +++++----- ReadMe.txt | 36 +++---- Source/Apps/Test/cpuspd/cpuspd.asm | 152 +++++++++++++---------------- Source/Doc/Architecture.md | 37 +++++++ Source/HBIOS/API.txt | 16 ++- Source/HBIOS/cfg_dyno.asm | 2 + Source/HBIOS/cfg_ezz80.asm | 2 + Source/HBIOS/cfg_master.asm | 2 + Source/HBIOS/cfg_mbc.asm | 2 + Source/HBIOS/cfg_mk4.asm | 2 + Source/HBIOS/cfg_n8.asm | 2 + Source/HBIOS/cfg_rcz180.asm | 2 + Source/HBIOS/cfg_rcz280.asm | 2 + Source/HBIOS/cfg_rcz80.asm | 2 + Source/HBIOS/cfg_sbc.asm | 2 + Source/HBIOS/cfg_scz180.asm | 2 + Source/HBIOS/cfg_una.asm | 4 +- Source/HBIOS/cfg_zeta.asm | 2 + Source/HBIOS/cfg_zeta2.asm | 2 + Source/HBIOS/hbios.asm | 120 +++++++++++++++++++++++ Source/HBIOS/hbios.inc | 18 ++++ Source/HBIOS/std.asm | 30 +----- Source/ver.inc | 2 +- Source/ver.lib | 2 +- 29 files changed, 336 insertions(+), 157 deletions(-) diff --git a/Doc/ROM Applications.pdf b/Doc/ROM Applications.pdf index b1533de561942db48a49ad84e44d78774af6fa38..62badcd653f20aefc5e0f14e0be67b3f3ffe85de 100644 GIT binary patch delta 139 zcmaFuhLXXkcV%WM=MS;9_CnEdkR}IE6LrBSV Iudht90IN;M1& diff --git a/Doc/RomWBW Applications.pdf b/Doc/RomWBW Applications.pdf index 26ec75ca18037af31c9b8c10f376338dd04ee71f..e1e22c70906cba88cce9e2243cae46b525d5280f 100644 GIT binary patch delta 287 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 diff --git a/Doc/RomWBW Disk Catalog.pdf b/Doc/RomWBW Disk Catalog.pdf index b9cc152b188cd2efe025292aa6ab4e2ae4659c02..5853df285d8d123146dd46b31f3eb6a7a7b2c1de 100644 GIT binary patch delta 137 zcmeC2%h5TPV?#M3)6vw)m5dcE4EpoArW@Ka3O92wZRcQOob!dl$js2x#M01Y`kHTy z(s17P^WPYw#GRd7oeZ2z&7BQQj7?lDEQ|~c%p6V4OpRQe3|vesEKTebYzQftp2No^ F3jlkABiH}{ delta 137 zcmeC2%h5TPV?#M3lV|$mO2!J7->malryJTb3O92wZRcQOob!dlz}V2t*xb}~`kHTy z(s17P^WPYw#GPGDjLh8JOidikEnO@P9Gwi!EzQl%9UaZhot-R9j1BA*YzQftp2No^ F3jnFCBzgb< diff --git a/Doc/RomWBW Getting Started.pdf b/Doc/RomWBW Getting Started.pdf index 59f3eccdaa52cfb0f581e9920748bea249999c1c..2d296759251cf2fe00017563745629f0623fae9a 100644 GIT binary patch delta 49639 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