From fce0f75959b9806f4016beb7b19e19b37cc97b6c Mon Sep 17 00:00:00 2001 From: Rich Turner Date: Wed, 3 Mar 1982 16:51:26 -0800 Subject: [PATCH] MS-DOS v1.25 Release --- v1.25/Tim_Paterson_16Dec2013_email.txt | 23 + v1.25/bin/ART.BAS | Bin 0 -> 1920 bytes v1.25/bin/BALL.BAS | Bin 0 -> 2048 bytes v1.25/bin/BASIC.COM | Bin 0 -> 11392 bytes v1.25/bin/BASICA.COM | Bin 0 -> 16768 bytes v1.25/bin/CALENDAR.BAS | Bin 0 -> 3840 bytes v1.25/bin/CHKDSK.COM | Bin 0 -> 1720 bytes v1.25/bin/CIRCLE.BAS | Bin 0 -> 1664 bytes v1.25/bin/COLORBAR.BAS | Bin 0 -> 1536 bytes v1.25/bin/COMM.BAS | Bin 0 -> 4352 bytes v1.25/bin/COMMAND.COM | Bin 0 -> 4959 bytes v1.25/bin/COMP.COM | Bin 0 -> 1649 bytes v1.25/bin/DEBUG.COM | Bin 0 -> 5999 bytes v1.25/bin/DISKCOMP.COM | Bin 0 -> 1640 bytes v1.25/bin/DISKCOPY.COM | Bin 0 -> 2008 bytes v1.25/bin/DONKEY.BAS | Bin 0 -> 3584 bytes v1.25/bin/EDLIN.COM | Bin 0 -> 2392 bytes v1.25/bin/EXE2BIN.EXE | Bin 0 -> 1280 bytes v1.25/bin/FORMAT.COM | Bin 0 -> 3816 bytes v1.25/bin/LINK.EXE | Bin 0 -> 41856 bytes v1.25/bin/MODE.COM | Bin 0 -> 2509 bytes v1.25/bin/MORTGAGE.BAS | Bin 0 -> 6272 bytes v1.25/bin/MUSIC.BAS | Bin 0 -> 8704 bytes v1.25/bin/PIECHART.BAS | Bin 0 -> 2304 bytes v1.25/bin/SAMPLES.BAS | Bin 0 -> 2432 bytes v1.25/bin/SETCLOCK.COM | Bin 0 -> 853 bytes v1.25/bin/SPACE.BAS | Bin 0 -> 1920 bytes v1.25/bin/SYS.COM | Bin 0 -> 605 bytes v1.25/source/ASM.ASM | 4006 +++++++++++++++++++++++ v1.25/source/COMMAND.ASM | 2166 +++++++++++++ v1.25/source/HEX2BIN.ASM | 214 ++ v1.25/source/IO.ASM | 1934 ++++++++++++ v1.25/source/MSDOS.ASM | 4031 ++++++++++++++++++++++++ v1.25/source/STDDOS.ASM | 23 + v1.25/source/TRANS.ASM | 1213 +++++++ 35 files changed, 13610 insertions(+) create mode 100644 v1.25/Tim_Paterson_16Dec2013_email.txt create mode 100644 v1.25/bin/ART.BAS create mode 100644 v1.25/bin/BALL.BAS create mode 100644 v1.25/bin/BASIC.COM create mode 100644 v1.25/bin/BASICA.COM create mode 100644 v1.25/bin/CALENDAR.BAS create mode 100644 v1.25/bin/CHKDSK.COM create mode 100644 v1.25/bin/CIRCLE.BAS create mode 100644 v1.25/bin/COLORBAR.BAS create mode 100644 v1.25/bin/COMM.BAS create mode 100644 v1.25/bin/COMMAND.COM create mode 100644 v1.25/bin/COMP.COM create mode 100644 v1.25/bin/DEBUG.COM create mode 100644 v1.25/bin/DISKCOMP.COM create mode 100644 v1.25/bin/DISKCOPY.COM create mode 100644 v1.25/bin/DONKEY.BAS create mode 100644 v1.25/bin/EDLIN.COM create mode 100644 v1.25/bin/EXE2BIN.EXE create mode 100644 v1.25/bin/FORMAT.COM create mode 100644 v1.25/bin/LINK.EXE create mode 100644 v1.25/bin/MODE.COM create mode 100644 v1.25/bin/MORTGAGE.BAS create mode 100644 v1.25/bin/MUSIC.BAS create mode 100644 v1.25/bin/PIECHART.BAS create mode 100644 v1.25/bin/SAMPLES.BAS create mode 100644 v1.25/bin/SETCLOCK.COM create mode 100644 v1.25/bin/SPACE.BAS create mode 100644 v1.25/bin/SYS.COM create mode 100644 v1.25/source/ASM.ASM create mode 100644 v1.25/source/COMMAND.ASM create mode 100644 v1.25/source/HEX2BIN.ASM create mode 100644 v1.25/source/IO.ASM create mode 100644 v1.25/source/MSDOS.ASM create mode 100644 v1.25/source/STDDOS.ASM create mode 100644 v1.25/source/TRANS.ASM diff --git a/v1.25/Tim_Paterson_16Dec2013_email.txt b/v1.25/Tim_Paterson_16Dec2013_email.txt new file mode 100644 index 0000000..45c4055 --- /dev/null +++ b/v1.25/Tim_Paterson_16Dec2013_email.txt @@ -0,0 +1,23 @@ +From: Tim Paterson +To: Len Shustek +Date: Mon, 16 Dec 2013 10:34:17 -0800 +Subject: RE: Source code to MS-DOS 1.0 + + +I have found and attached the source code for MS-DOS 1.25 as shipped by Seattle Computer Products. Version 1.25 was the first general release to OEM customers other than IBM so was used by all the first clone manufacturers. + +IBM's DOS 1.1 corresponds to MS-DOS 1.24. There is one minor difference between 1.24 and 1.25, as noted in the revision history at the top of MSDOS.ASM. + +Of the file attached, only STDDOS.ASM/MSDOS.ASM (DOS main code) and COMMAND.ASM (command processor) would have been used by an OEM other than Seattle Computer. The other files: + +IO.ASM - I/O system unique to SCP (equivalent to ibmbio.sys). +ASM.ASM & HEX2BIN.ASM - Old 8086 assembler developed by SCP (used to assemble older version of DOS). +TRANS.ASM - Z80 to 8086 assembly source code translator developed by SCP. + +I also have a 6” stack of printouts of assembly listings for some of these and probably other related programs. + +Tim Paterson +Paterson Technology +http://www.patersontech.com/ + + diff --git a/v1.25/bin/ART.BAS b/v1.25/bin/ART.BAS new file mode 100644 index 0000000000000000000000000000000000000000..2de324aa4c26300152c9cf1a6a573f7d10125b7a GIT binary patch literal 1920 zcmaJ?Uu;uV82?D`UFq7|+bzx*L){81u(sZH z2^ckz2Qo7f|4hIKBRr^>=>u^}kOwv+4|55aC?XF!6B4(z5JQIguo&idZrlCAU>{D; z{l4Gt_nq^7-#KULocnXvTbSriq1oDrv6MZS%_I+EFguVN%BO5J>^v0R=LpkHzH~N& z%}veQ&>z%-+1z0}y{|v-FoRh;hs{rJZ`S$P0`;Cr;)K(^smx%i4?B}2mL}n?7_+nc z?BoFd&!z1AVa)F33b4~NO$=iw-=DP!)_yRR$)J@VO4@mBOWJ+u-UDEHzIUBOE7Tr9 zd>`3822o=zQbPwQz+?j zU;-J_C0z=fM&=Jp2BvYN&XmAAsM4xbxaRrCHH|eoa}$J&|4ESwF7JAQR5lP`n*Y@~ z$fXm0_LEk)=4aJ9yQ~%X_jwJrdwl|-9$1AM*9t0Denvb|nWE~D#x;1+TgOT6wWN|X zmZS+a>TTpG&svlty{33ve_8r#ZxbhZSCOvXv+9c)-0^PbTckwsElPTIDH+rT)GGhe z2P$l4t(@sCF*oToC1%V{4G!X9F4>#Hmy$N-v)G%>X`B_!P%Se?B z3(g^>uy+aWUpnb``veXDK=(G#=4WXvDOQQ_8~Z?@rinRCQ>Dvrn|&fsi*!W8 zZD=MQQDLj^EI0H-yEex|7>OpZ%Q7SFnCJ*$FdB}=A8(Hvu?{n6VP`aACZcgP+KgBt z6escl-vv%ibeI;#;!#3&5-NV2(6eA z3}LGg$3&EZM-pbFD@4E#eOF4GhA({AY0In9eqDeG-;I^D|LnW9Duv|?-Vor9@9!1+ zJ!yAKAg+|El6I=cMrngcX(u{LRicx2Xp*YM<9LRbyhen8v{Ae}it4~#722dt99=6y zM5+-#b!IO}wG}h~WTXah3T0}q39O}Y5{4zecozM#E^9@9{mykdo6>YeZ`}nSNiE#N z8g$mceJc6JG`a=IcR_k;wU4u@v_DF_xYa>A6q0isMJZN+kCBw@1d&0IpI^pvdnLRK z56gWHp-*Sy~I!=B97HO*8 zs=@-&1kTH+MYE^G&J@@a@U1*XhL$<@G0e$d^5qjpCkSnT2sCTabc&@EWS&A%xp*H8 zWf-<7Q)MrqNu$8aLn=l7MWd4p2rEB`ra{YFI_h6u;Y~l`i#(bJY2_D@P6n<2A=u`9 zyJ#BPt@{3Tv<3DUv4BcfntZuzrGG4F0A}2Hv37tgE|U G{C@!qr6{`q literal 0 HcmV?d00001 diff --git a/v1.25/bin/BALL.BAS b/v1.25/bin/BALL.BAS new file mode 100644 index 0000000000000000000000000000000000000000..132087a79902931b22f08a44b43503532facab70 GIT binary patch literal 2048 zcmb_dTWl0%6#ko?*+ja#|6CSaY6-`ou`_WBw1$GykTAPD(8ayEyRBOuj1?9rw%xj2 zjA%4c5&|hnt;S*u(fXnWZzx2KF>N1wz(&L<7`#=(1JiDeF+eolTF*b*8<_ayKFsC+ zzVFOA-+%tIv+sM}a1B6aZw?~C7$kFr-h6j^Cxr4{J^PEf0tDMTJIS=?JtVav*pcss z`nC1zK@Dl4e9wVG$DX}KM;gi(dZ7O9P4zmvHjq``G1NpmcILW!bGsncj?p?WavdZK z`8|d9E_Uz96^aKSzneuM>%8Y($02QPGvIlk`*e|*-V3g@8B0d3bd9aV6AHPBzjty8)@G#@((k?M`UJi=&Vr~*#wbv#i@InG167SNV;olKR5k`d!H+5AE$?5h zaR}(tgA`o+SLq7**6Zdl$}%L3vs;zJoE=i>MQ!RUl`hxmIcK-g}3T~vM^c5_4Yz~mGF$Lx#AK}O&^hplCf$~0jgmW6p7Rl@M8KkST$5oHOY49_6))Q^= z3SKc{x%*I5$&-)h2@X3a>2!`?m&iH#3Wt5toQQ@YlDS)w_~3Rg4DW@cW!Rv`}yA2W3lA%p?r7{&3y2F#doko+k6`2liG>~qTM+TD3q zLvelMMuiB{G5$?3OFIlW3_-OzP@%CWQ>8;1xkDP_$8cUr7-bYz;+0utNW=WhAgFX$ zr@J&ACyz{G(n)@1U|~(hrQOmQeH4e4};R#NFnopx)wNe)UQ81)n)vMwS}eP@ME z-_dkENM4Z6@(jR+W`K^syACiSeZk`dzBr zwW*)^7^r~ru$=rRUEzajR|u5GsG6N#_1M?&gf^YkuFD#^MgE0H&!cw0 zfVKvk4v{tTA5I=W=zf;@-#UF;)BSpIE7>e_ZkFL_8JTbpnIZSdJ_i{tBO?wXF(fAk z+nUN!?H2elJiW4WF3iFJB>t(rC(Y(9VQp$Mt7UdiZCE< zqmQMw2JQL^gEeS$bF?Ybuwg?}d~>`>F`yr|vSv5}YPLZ~8ruE4yv6M-=xz9FK(@io zI(4=gu+=U}1{@+D|8{rOR-;n^4Xy#*VjLp1{)F4Cu_ugvz}v#XVr{wIpK+J}0v&K} WVEPhn)^&JN0&eWqs;d9t`~Lt8g-R^| literal 0 HcmV?d00001 diff --git a/v1.25/bin/BASIC.COM b/v1.25/bin/BASIC.COM new file mode 100644 index 0000000000000000000000000000000000000000..d6b32cf829ba52a63ee11269bb824ec19b4a88f8 GIT binary patch literal 11392 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 NLR2g(TmK*a{uf!w|D6B; literal 0 HcmV?d00001 diff --git a/v1.25/bin/BASICA.COM b/v1.25/bin/BASICA.COM new file mode 100644 index 0000000000000000000000000000000000000000..dc085788ba4c092c21ff2ced24ae0198a4671c32 GIT binary patch literal 16768 zcmch8d0Z4n_IS;7&vY}KqT&sR1P>4ujEOK_j5i(wlOV%nF-9?QV@!6YCmVP7yBUAD z!gPCNv&kmkT@Q{VUvq6ngBl>CgDscFfM6nm2cnx)*@!4I!{yBH^^jzDzn|aVKln^_ zb=B)vuc}_XdhgXMa%bVdSI~9p}63`%iSB>8e6e4G%ngX8>36aT^Z4sa#*8>O}(11T-wZT>jf6ONG zj85aSc8Qg0gu~d#WWZ4zsY+Fc(WPN@RMB|Gs!ma_L>yg)E{2seYTLr`3}dCrg97a# zFCk0?;15O(R7^&lL1Vl8U&j?kFr^5^6^~^~mGB5>O2gnWiYX08#p6|_Z=vFes?xVn zafGULJ1QQlD&2vK!&RlPq2f`hQZp+4nktP&#iyy#I21J~=7waQ{@a?Y)5x9m?1ckr z#GHP2jnw^9>9e9|&chi2$)6^f<9Ed8C!Gze344%4O+Wa=t*}!g-W&JL*s&90qq>53 zPXEL7H>c-L-!y&8^g^Xw$t#a4k1M}ao>rb!ipq1!YUO!lgYug4ma;>6U)il3P%0>f zVyOU1Lj_Vn6hbSPton9uR=pytS($Z?TEBMf`fr8x7vEZysasS1XSC#*WgqOzTyo`Y zgjOwEbMF7FTC=Qq7g~1Nj^J|#DzwRYJD`(-5X*T6HeZ%ToK+Q(e4)@$wNncR(s zDhrf6KDO9frQH-fr_sa9wvSk`zGLe#OhM2tWU}BX&Tqg4mpGKRN6$2!Y`{F$V`z-Y_?pgaT#-V zQiMW5wtl_CI}wpDS<}zodD5hh$YECdU)(tDAFZQwJfkfF?CqnpCGhAQmG1as1N0oq z6Ly)uSGtn!2;Ii=NkJKjzOoo4386i^7coAcRnf3<;~{^AuWS)R+?3Gc+1>naHO`<6 zUs*FF4r*_}%AgR*4bWa2&h-atTZeO_L$qE_1!Er3AXBmrNcbj5yB{7~g422C7fMc` zMi`k4e1O8&>D+=FSryKpOoyW6C@u5=VJnp)TAKIzw#|9b&+gdt`lfB$H@&bu59wZg zvEL@&?V#97UG==dt4Wd>~nOD&3q z+}uO9fz@W!-IrM8w%yg8zDUcnVIA-DUSyNCh|`;j4*bqU@(5A#*b7MisYybCr0oWGY(=&r9blqUHMN{ zIgN%A1?E$ouA@)5nVycXs9tAqiz?ge(r1%I^g3qgP zdKeU}WJ}hwCF|G{J?o%w^F#+-vWzX!v5q%Nma?XXLEFMS7QtNG7Otldr)a?6hBV-` z5L`bIf2zXbMAD?v7fnYcGf=iXS2>vnH)QG4F;;LaKBMsAO2ymRgZfMZo<|7}OgWkS zSzP->PIiOkF+gV+9zB+^Pze}7P z4~=)l+JY1%^Hhfpj(3&Zrw_rrz8`~EtCC!Jj*^Us!N(}^Csgu!OUEV1s>acX{51w! zP=Z!(4ZsHw4n^c2)A0*v305H>Dp6thAkV-R_PE*ey7S#O>EFUqS{uF*zwkIbxgcCXh3rNGmJ+CcNG+DPl7B1CCi zqFz^msDz1@l!RUj1M+nO$V7XjS9uEYE%rzy(co}(k*S6RTKbF z`m5K~=mMb3j0zDK)#!9O zevFQPs-PABh@_8;6jX`a6)s$^wnvuILL?2(4{2#%rINzI3h7VTd(Is;0Y%zP=6>z( zExoZDMXW)V0qtzFTbt4=YL}P?wWeMmF_jW!6wr}DrDzZ$HIyvKsjHs0d@;owKwSgc zl*lBKPDBd&oHO)NpYsoTsmHlkKjq~1Osmj@$Eq(3uERs$+i?>L}of%=$=g!nE(otu^da2a;eVlaIxiC)p zZ|B4@(mT$jTciWdPhuqAc_K#olXEaYvN>lwP3S)7#3#*ksmzH;uO;EalXfpR*y4(0=evQzQ2Wh>v4X>kUEd^$yjpM9HmpsnjB#;+8&cz&g&f{!+hGco1-_Ig?kMlS~R(qVK3|Z=N zP8~xQdYrRIkf%M)Z?}*nk8?jm5oH`=?R#<97b~X;R~M=IDsa?d)GpD%{Sa%SoBrsfi;0a68Ega@6ho{R&dzc6Mwg2i;C> z9{H==`L|W%Ew_{3LU_0H^UY+p+nMn)`6J|CCU3Z%bG8t(+qq;j+3t2u+f25)ou9l$ zo_9M-eou1T&Z<|*Gj8Xm|03($&br@|m2M}qlBBtvFRmb3x3g?Dndf$nTtsHOoe_)3 z47c;jI1=l2wvHo_ZfEi;GS=(j_M!FMy;;E?c_< zlAt_D_QgT+b^;_j7)Y97|GWES6eNF^Ut8qlNBPw!!+B-6)BcJ;$Sn$nWXyCqw+NCV zx#GH<`)(X0hh*T6XCWELg5FG;N#^%DpPEUMd!3G%WM;4PX@*Sgb-th>lY5;rHDp4s zGj0nR-D_L;5sj>>8uf=DIPO`MN%aji>Isa(pCZ`qCNT202g{hy{ERtwtXwbFuzr0^2y|r>0ESFfC&Z(r0Ai$BGlf)Dy_Yum-WpBl!U~(vY z2^W&ah3L4DrCi7|E@U|uvVsd)n-Ti$vmp(uLK^3XT%Hy3O;kvB&tzoL+Xj|c(lt%o zio%FxtY{mEHZLfQSjvi)dCB#1-7KgJA%8)ZINJbYnOqp5gSzqjSrGqAw9i_?-d}k< z$o-J-=FfRuN|!W;{BzJo7Ax!Vp>S@bb_zE_8_xx6XL2h1MYyE&)_d#us>(lvCSK9F z-e~6M=~#Vc5vU`}S-d@*3&W0ZxzP$}lrD@|&gNvlFSNj@g(M0`?4ifhGrnz>@|%%x zfrrYXrL4OnL#V4zqOVYl=YcWM#cjyY<0;|XSZ$(pM0PoaJhv|4OLqgCI84?I;)L*Q zV_-d(Y+Ja3Rd5OV3_fH9TS*~XzmlUW8RWU$j00U(#bP6@jBL5G87J4vC8E$sK0<^Y z#AikvQ)t(4le|@012+cJb=-)gdhK#f?XB0QS+5m_tYpPP_*4uZ6*1PQq}8m(7Zef} zo)cymVG1{o{M)F@qoc>z#`cc0O_(z2Mr3(3RbfNYDqK96Kk$S(H4|^^OThG?0lNk( zKcZoZttwLvc~fm$^k>T?8>51!Ij9z_(l_6#EqLrhKFkaV%_gIyCNB+;fLQ!jWZ3gC zGqB!DpHNCc72)WsYjZshgt|Q>Lx^0%3I`Cv-%Q~yryfuuuGg47fM1`&pTobIB2?k+ za_+?`ZuLsm$1(W}w<2U+ss^LhRna{<&K?ns;`WBbAf{q53_9DzpX+j~^N`OPT%kjb zlU)^?z>cN5@H|wJhU8j%$W~MX5NOaO`jJ{Ez*1Pl=ATgl=6;jE1&)zHe9}V^H^soN ze=&xy!*wxyI}u|X3JH`SP&j|<(Jtm#Z39PZr&;N2ax*BKq(@?{=SO^{-+)d1e5kEo zVO}YmQXu{+PDA`79FK4c;xFSV2q&TP?Tn_43vg_4-x2C?4C2p~A*!w{{^Dd%=SG-B zs0{R8_)I&C8v_hGl1%6aE-?4;?U+Gk`a2EZF7h%^KTjvjHuq>Xz2+|Oh2 zvS!b@;MudW5{N2fbRypB{t+vnSAXgo?$uL2^=iA1@5JK}-s0oG!6OiU&c{DWYAT!Q z??d>%`j7&nln87~vik7rN}LMhvG^NLW?90;$+m$c^C)kP&8syBpG4j&Tff#!9|J|w z1T=9zM+*ME4+#6UocoOr`trPwL=ND$`m{9YH>y59ax-XRT)4N63*jT@Gw@XNkty)> ziuj~Q^v!!p<(oGjehc82s>0v)9Z;vL4yYHvZ$A8)B#3!fFb7o1M2CFESv!;MV9sBQyx6C7p&1m{n*vV*SH(OxTZ*|hi}Zp zLyr>h6?cwpfZo$?3Dg@h8#~HI=}BaNu5aFSMsIKo&Zuc@FGE6K(ipxl^mMU}L7C za?&W_0bj@CEI!sYw8_lchJJ6MY@N}vCt-QYIqNcSz4eaY9kDaTWXjPFm}i_oV6=c} z43cH!ME<C{gn1B~oz&;6A=4~Kj|RBmO<7bCD$bR7eQA$hDg0Hzon zq)1^38IF#nt&0ccA^?yA;HeK%7Bbm$Ra}a{I94UYSx5U{j#6A$5S_wsnnLEN(nyhhO&{qw$1C#vD`rIo9BtmxwaT_UVPzbbF+Z(vdnhrjeUbh=8(; za^Im^#6jR4zguyCWSGj|B)7WadDN**HK!${YBlC4uu`7p+Z`HiwAW=D3gbfLM>xmG zkI~jiG`JIeTm&BDOY7v@gKV<+tcXVaj_58)(HE6t$~G%6-ftMxM`p_2OSu`m4eY~` zUn6f_NiNEX%5KpAi-cjx8sGx~46AGc@`kKpZE>sED62XuC;MV|1K zOy-jC&Vm0eyp5(@5rF)HT!>r^TZjq??=j#OUBhC-Byb^sFrOg{|Jb2nC#DeTq6X}d z(ExH5?5!9S1v^GpSFIX06f`K~dv-(CFT-V9I2V)}3RaJ8;WB^DfTD6Y{;I){ky%Dx z4Ab1=BDl(L9uNj!V$oDU6$kxLAASQ&2S@sum!J5^wf$LHN?+{4)wb zrIbKDdJ_3^j3&{LQTZztyeaaY8j!(%p+F#mjo?=4k}L57mg6w1z+YH!{9{5LtG;Y7$WN?Xsx>A=zr;+Yf5V@UfJH%8KHebzNR zQ?5kXA};C#eQX4H-BL5~N@Vob+4@IVX)to@QmQRUJWkKR#ohRK-TUz79?(%({B*By z$z++3ZBU-WA3WCC$G|xKqEBvqL<%302M_Tp-FSKTG(7pC9xv>ko-G2W{^kLW?lJoL zw0tWovuZgG$sqBM>|nH>^x>G@kQ7#DzW(`x+2qA(mH;QBn#lRebAywn6(YsCaL2 zA=>NK>@y#alGrnU9VJm`j*Ti0K^Yqyl(NcOclys`vo?^%p^e6lPB6A-fu8o!ee3jW zqd{4P%ZF@_uXCZc$8X8WyVh`g4b%mES5EFhLf(2nzU_f+zaP^+S&Ull9YazD=zB_U z9gVPg2!wn4pooP*tiKOluwzR6cc00&=q)RQ7v0Y#qk7UwMGxLSi09k~G%K*vYiO*~ z(v}bP$421SeAxi|t~EI6&S{wWcB;EDR+?g4blp0};1~h?qQ_xF*;dfRJ9=x>z@H|3 zw=0*Nd6-Uq-80Ov@h}5g))H%wogHpb!3FVO{EEfrAM;ft0PzLCVr$@s@U{ogo3q_` z>O)ZcCq684tNBLo40mx1wsa-nb={ya+|z&?@NjpI(SYMr_!3(IY&urKjWOUS6ggCD zK`VHZdXYncyOCp;Gy}%SHxBl>u<=FnSeT$tA@V5}WZsiya3CvDIF8LR-@;DBU6Y+hEUrO(Gw%Tuk?HAttQ^Ey4xN(m4$Jc$(F>kCj46WF+~OF&HakZW3~#P4|gkMDw13U zt*Nb+@S>SA>CD_+90gxEd@NwDYVm~allOOZ6e56aOwCMgUG!M~lLwy5z*6@E_z+oHD)dIC)Y zJ>U!r@&yd*ov^4wGMe_uyqv zjsH%Y@FSQufL^H*A_mnk!Bi^@)PQiIf`M#7>!rK$zW|?R2p90mdq!}uQmuXg155=X zXhJ7!d%D6|Iw9h*+CD}HN~H9<0WSvB|BW)!@ekyLikpZlNkTzu<&>yI(8>bRy%()+ z7=K_aTtmDU`D%HL^a6aH2`dd((tIPFlu+PJxg<%w=|TjscdI!}xL_KF0gCeP_=$y==ESX_c_DsH!Q^Y2%{TjgAJtiMTtuc~&&?w3Z_zt?;x8=V8*M zg>puES~%}%m6H5Mj%*VScU4@j;X+ zTms`AhObBu`l)4_e5&#~#b1ya8h?b0CRozL6M4}(V8HJn6HJ(=H5*`QPaCY%_{T-- zLB^W{WWQ42V;DMk0r{A!60X`|1^D|ZIu=VxhplowtARx(S~UDw*a>Mk9}-~tqSn_X{6^d%i~LI%rX>mf7f#K?Eb2;4 zjKKpZr{vg>IzLvrX)c}PN-lmFKJV`>)I4cJscZU^R2uW zL?8%3sx4tQ-+0o$;;`MvRlowdBt_$y2wQy>9!2JfX?QC#hYACqqyYvE-sl5}2jnm| zk@0sy2xAxV3nrOFIQ)QZ(7P|I$0Q1wZp6 zdB^K%l@Btg;e(7Gby2Tcv`6-+OW;}Dqh6p#7FEBTvkgU?8L&f3d(@)J5hXw5`tF71 zf2*H4Twy!s2ji>wkY`box>wED0fD{{_-1d-8T8fuS^=7fPLZI9?t3*YhQ-RftN0u*s3rp{q&!a(9Ns`;)0YDEVX zQ>UzVxQ0uWKa~ReP8j|uC|2QaDRHa&MDpB^$DVcH^5=`5l^quMH22RaJUkV(NIWbiH;KvhM`i45_b3@SE%t7xBx%YjAKJ>KZZ7ThSv%=mME*V<6upX zSk9DCMk`hF4uWKG1$zp-IQz-omflNr%IV>RVi!VR$d@zs+sotAlJj2IJ*-w;c#} zWorOPv}x9$L((>Xh9V!|HsOZbu%%BLhOPKEF0&JCUmVK*M;cGq^!3DSAGrdo43(vWQHMge2`(htf+)5z1 zKCliFkr0tX36a?pXr|c)J`@g-VQ)Ant8zMgr9(dDJ!E{NBLf^1LSzml>$W*?Ky8v5 zWb5WR_)K{C8MJ>S?eLK$has}4YKF)+^3~&O`R>)LQKnrwO*8A7N0s1V;9{D_tU+EC8!p=C0D%uK>QQTMo*hw}*UZinhhde-X zukmZQfCFBp`R<}TIsteJ*lE0roWB9w|FX>S{*J;|>u3swNuGsSlujPi=V=-D{~p<& z22+UG4qpN;KTAA$8^3f5_WSQ{K{c6r8+xkK>2c((Y%L{{+qdAvW(ubeGr)7613b!T zX<+c}w=lYy!1wZ(>=A?p?LOkB>@UWlH*vu&TyhH{zHZVfXF+XQdF!OS5ZYRQy3ubn|3huV6zsY z@O$mzNd*LUoKxa%8X9QmfHkBl*+NU;3k1@B2V6EA;T>RjXH!L6M`_l1~H#jxE z<0JX<*Y|16$!!}tyz*DMKpi|bKpzNQJ_8uu%aEr!@Yb7n*-eKJ@1=*iU^W7FDuw~h z#5?I6>7fDdxn@aqJjO4>eCR3s1cIP8+3QC$Iq|I^tqWQs_d^BGMB$aRPS)4&6XqH( z;uM;%B~Q}i&P@YOyJqp=k0|Y9Yd1bZ@s0Rz6yJ^CrT7;77RC2rfr0~}Jrs|No(Eqi zrxqgg6tu%pk^5TVz8YKv_l@N9HvFU)`tk0~1bL1NZ-T=7C3HrJvPb69ek*qp z!`BwHR(uVVQCE36ypI9V3I=2be*T6YcV1h9@ihaUbrbKq0pUv^NBFu-nEpwOyr#g6 zW@PTnrTsRN^QH;RHZYUGRVV!;2uX_mgZR-6oOvS?zi`9y)!pQG1tQoFyo41@H4AQ)>>I)2=i2`7}CDht1UJvTKXmU*2b-s|>= zI3`CV&)$$vQ7#Qxdvn0%h*9MjGY*1^an5&0c0HOSG)>lU+roZ2+8S7^?x)k1)Tjq( z0|;F>b+6H%?xuyo73D#4^lf2qe(fls>eEj@5qhwK&em&LSdPiG@O_$A2|mH;blJ#@ zlglD5P6k$;M6@@`LjBqBYyea{lzP(PgO%M!60T<#(zUz6nT(R_?R%#p``+mYYQi86 zXtGuTNSA_`fnc6}UnisT`pFwy&rAJ>TCeGciT&dq;uF!Y)qE z5xnK&0Krhtr=^63a~+c@mt1HWv@KF{NkUJOYxuJ$h@0akKD~Q}98b1Y3Eil)p&18f zAlp~TXuK8Nq`2!EInY90zvge077k8DR!C1F`9Q6^nOIr|_q{g)RUW40gPIdG{{C8F z;{VY0(Aokxsr?FOP03>YHIm-)bC@1QRv{ptn_>HU22ei6kle-}obGScyLSfSZOO<4 z5nICqs&J#iTHWs$FXGca^MH1IpS8DUH}tp$Xh!{D!87nhCF(PY!odoZ3ZZ|TT4#r> zNV2a%zadHs4rAnaJ_WikOo9TMhHlT2Td-MGdi-}q_D@6<%8h#gKSXJ(YhdINgs=75 z-jOo~e9%`2O_|6oAKBVQrnZsUZDhywk|_-C>lYpX(_@<)Lud{yn!+5}b53s%Za8S- zxn^6GU=6c{OktE+_~q8zbbPzTT4MkpIErF~cTS-+NezDd&;RfbJG`u}-3`VelA{<6 zy9QwaMf}Cn@fWIXWRu2i-3vjHR~n@xpQKD~14kdTZ|~R09umdm?Ax1+s0;Rx$xOKo z#a~E0Z&nKDk1Dw2UHvu$OLzs!$`Iy7F~Y*h%q7zEp+)h5F&DVdr=G+p073kvIs(-y{4@gJiwc}Frfku-dn)+%%NGNC$}6eo(~U;F3YAU9>%rV|AS*Z-3IS6g z-~m4H&o-FoWifab()zgZAjrpoM=H3G{+ZcHbgPV0B+s{!>bA^%?BehAaZ&>f{o&@SF<;I>vrDB&B+$wGz210Glh3XAXBCR{6!U6V7I4& zD2DC(M4u_gkSR+Q1QmrVh*x>tw1SO)#s~L`9oA|Aw*UDr0?ME z#8sbZqs?DI0C>nJtF7HN>LD5(+L&V$A?h@LAdowpKR}uPo4ewO{$w?|=aV1S0dmD> z4F&YIsu_v3e^R0uND6}UOeg^%TcbiCbI*i>E2wPx#mN=jwA>frO4$g%ETzc(E2kgO z<$>t4EL?LXH@}~@2Je`I@Qfer^EzrRA*7W{+vUvQix zJOm<#HwF{l@ZAz@_|AaEe*>{z5FRc+Gerfo_Ive0Q^QY#{8AW+*(QHjLe>R2Xcgq4)D1z-l2nw7U{4GwPDG_EsKuP@ z=YwG2;h;4kZW-)$I*Nq09A64zURLn(#bhyG1P7YCQ9Onm+wlJHhKrL#e>hyhEChD> z3kc2wiZ-J{hV1cW>-U_KgH`_It9)jz0iu*EHzTqM0UaeT$iS%#F7p-52ah5#{sNrs ztK0>^FQUr%44LZ(PGtaC%iscEk$hB75`F=W_f`G_fES_46oxQ;<97UN8d6#v!VtgJ8(w764W zLR@|mxjeKE+Yp$#*o?H9pg!gy>+|wtz)}i@S%k3jrPdJGs;sNQk!}aoM{3aO0B!-| zWink+?%4zu|ujawCQ#^zJ3s zcX%PvjD%kvfT;LEXKoNaTTe;{ar;pISvtuD6Z<4HES>Php)@EEg#&PJquI0}6D~MZ zHGpI4{e}dbd&!sqy3q(DC^S=r^HB9s1FR%ZvoUvLHUwsTji?)Y+QEVihFcZjcIoJo z0?GTAz|zD%1ovL{eu;A8&vR;7JM9=Sk@zOtA_bR{FDCgVQyXY{T!btn77WTlVzOUI zOn|E*RbadOmo9YO5{BR_rWQF#zo2oWR4b&C{cwE3^OxaJs^{t z{blbdk#Gc|_*N1&TmT|kb1p$K-t|6zPG}(mP5w3t4+Mf%dAtH;NnmA`;A^A0HndOH@sRksC7oVpNDw(h&10h5cIzqJa#(AxjQr zN=xem$2^2!2;G^9zIQI9A zdNp3x*9F=t45uFmxZE$9hWkt(wQ&){BSIgI<^qSuD*%R0RruZ*B-+jZO0KU4b^x@x zGd7wV1Q9145}$b~FM3tl+Gu^A+4Aa+P1~d4;@WFg4lb*uZL)0J>z6d@aw+?TmhPtBj|9>Dc{>vHSix=3V2MbDxG*mxi9&II_qc{-+JW zj;+Dy@2kU0UKoc4_FgSkqWG!>D9lWKg~H%~rhVngQVk`vpSGbh9!0rcw${Hw?)@#N z{{~)tRKEY`%d>k!lniz%&n#lfUmZ4DPX}wu7cqFW;&g(xyqUp4idr=U!i3eTH?nAP zt$GuSqHEQgS!AnGPh%id7^3p!s7eI-Vpz#aR5G3^n+9={!DV`gmuG&uHCqVUXRR9U z^eP7Sw*1?5-eR~mTN=Rt{c)vZnPRv$TN=(3hr?qOywRnRs^Yg$>3CJ~+o*J+s(3pp zjZhWuK&4|<#jl~#a8B z=QC#$al9C#Tu$K0pYZU zLGrRPk)LRjc3Bi61WvY5SC=P#Zf6Mb)j;$$jKT^QT&SzrUE)MI6NR|#3%jcJqKsOQ z*)|A)m*enuRRw`|2(fsVcAW)N?dOQRs$P@-4uL~olFF25nOgOH1|e96!g>4~@DQBV zC1VqU5VbV8WCpLsWV{AJoKqTXWbpcGGHik{ucyZ(JO7e`CnH$5r)MTRcctLb;P`ig zbr~!S;G1%WwnxM>;_&_I00X`tmrXN)Xi2Q4L+0k!C_CKZX_lrQM8aA5{;NVz6v#Do znd0J@za{GOo9(cycbyGF zGT88fhFz=%WSh?pL7ehU%pVDfR;l^53dnXmcuP${JL5-<~)d?F~snlBUdK zPfUP(B19*`1?-q}U8X^?a;!4Bet%W@uOZSM#Bf|Kvq6zB((MmU?^q;X_2fn+-Jx8R zOK3^_JkHMefutYyw(NI_f7wlyj-uWjqW&7A{^FjhXdQiIEB)R)`sntNpC&V(G0ewH zMv;|F`{9{4f3Lo#W$ylkkv7ff{BXvd0rl{nbcOCvVpT~=M_+=|Lm5QduqMg7VWH5zunmrO&Iz&nw#Ol1i0TM$+G zJ9u`jL~*$?Gb;7hfBC-ea% zhtWetj9j6E7Y#lsSM?H3js(UZ*W$f(ptP>g>NtaT?LlzLF9&r1U%&@y@k_NS*i?Ur z8}m~r!k_CQL;<7`DXa&YB*q@0p-QGP>3DN37l%`7XGzC#b}gO*pT*YO!9gkA!7FR= zWOyG1@9~UuIbFW32d5Q~7{C=!`4J14;QlOrdnnsr2jBki(F(*}-Q+4nsDQKLpE?LBg3d0Za`>~c-F%~=Xc`QRb!=sOP;op15s6ggTWUFe1$@ov z5PD?-FfSYhorMFT7QO}!g!;hg{!Ja6XiI!82sQvz{;%49)X8+p(Mt)?lziGETX3_1 ztoiT;pF7XTx2C5Tc@)5nK}CJ?18#?x{01GwN%e=UqYRbyRGfFlguCi0gVV6-4E}Q+ Zai5M(+sWlwqPLp!@=!i3ng0)e{}(nzYMcN7 literal 0 HcmV?d00001 diff --git a/v1.25/bin/CALENDAR.BAS b/v1.25/bin/CALENDAR.BAS new file mode 100644 index 0000000000000000000000000000000000000000..34860ec1be5938ade45997d2c7d819b1c8adc71f GIT binary patch literal 3840 zcmb_feQX?85uf5a-;o$^@AkewM_W_fqHS$oqAuw_A6#C+}jlz?dTRkqQYfAwYuZV6TU~tRaO3_DFEer2{$P zH*)7hP6#W)F}cIu56ke~;ME?|TIZ_S|3`e#a*wc3iIA|Js_@QM*S|MH&;ddq71i)8(4}&6iYFnge@|tzO)do zP+$qZCJr;pe#)!mC)AOTRm`9 zXpfW6JbX0tkY_)Z2XcZaE9GjXHa?IOX${azMJ;P2?~|1gwPCUWG(+F_*z%yv))Y>t zmAYy)Xp~1A5jird4I35$PlbNwScNPrEUQLgoGP(w6}AyoH;N@f;8&s79IJ?pky(S) zZ`mqpBNO$C#t`s@|KM1~x>#wIRop_<`dHnpF{{nt3yxKSW2UCpwDPcKxaJbp$SmV( zp;je;tY*V&ybeoiIaaA|y~L`IAtPFW17!8naL&sJ#T;@Dg)F6G3pjN`YFWVfa%*s! zgbXZ&H#uH7J8m6LijZ0M!kKVuZ~}xZXc67jB z$A+dFv`RuUJQbPt@;4{NFoog>c#091fTtLB33!SD_CUzhYUn{k*P1p zo!Y>q|9R2~$%|YM9*e$WxjB)e26)`+QYURc;Vb%q!_l|Ad$C9{MDQq5Hzt=w#x#4L z3Ca0=ScD_de|i@%qy*u2(RaPnnzc%e*5n}8sz_Z_g7eXTF>!5NL*1y38ESc*MC~g` z7Ma+4-skW^$A%RKbL?EYj(#@ExOwxZH%lt0D3dU$(C&4%3`z;U8#J|D@t4sRJ_>)Y$qNK18 z|DI*^>-e+Q;O+R~UMj(RUifSLNNij^_!-bY5O22X;~s8~B= zNKz#Dbn-UKfF;ke)XV~I(HeXYZZFoTq^;y`-(J*-?f~s&5k8;%tnX=LAqesiJeRzm z-t6lSvI`?|qc@D=*m%vlF;)$|YN(uTzQy3hqt}VApQlb<*7molKVCMfHR*R;QAtDgDP5L_ zx@^<2-xYU)GGx>5+U}ATU!z3SVEO}os~0nV1rf&6eSZ6v6jZuhS%zEF5l1e%<-5}8 zXZ`wt^he0if3DP%=^F@}AQIRld{35Tm`~sA-@=G#bSBQwS@jQ$$}+MsAAAe8x(pEU+@l(Xk!{$)N3 zD4E+YiH9*{WM=+{i0;qa>xzh`y<$WUWgg%W9m+hqDk7TE71L7Y34eF1nDq)GrHojs z)2(ltHbSHEI^w8NL^M^p(y_n)swTlr+3&2VZ{D7RmWFi|W<};}rYm9P1wH$MpLHWD z$I4sw_Ut^b_r2K#cfG@|MNgNBeOQKXW=~yFLx-2M=V%h=>yGB)UvSi%FFt~jEtZtj a=^i+decw+Xbo4pLzA)wiAd&cg%>QpS^(21) literal 0 HcmV?d00001 diff --git a/v1.25/bin/CHKDSK.COM b/v1.25/bin/CHKDSK.COM new file mode 100644 index 0000000000000000000000000000000000000000..bf88ed2f4aad31d204e978c4d1d2ce4af472a743 GIT binary patch literal 1720 zcmeHF-)|H}9G|=Eep`C!T`kfOG&0vTmGlQ8HffY%p(+Qw9U2J`H7>nv+;H5Hy}1&I zz%`d(w&RlxKKP)v*N_I92AWOf_RwA}El9FSm#ARi0q+5(oN23#JwWX`dsitM{secj zo7wN@GoSD0Gc%Vimd4xOML6ay&yY2Gi{M$WtulND*54Fz3%V)fX1{y~_5W4UGp#*u z_}sV1t@zdl%H0=Wy;|K5s%HQ+lsp6U+StX?=FGx5dNnx&$w5e-hvWz(HAs#Eol`fS z1$skUXZW;d^u-dxx0ET3xn|;y_QaLOWuR&qh~-qzAfz0K@&>P|)x(gOtZB~BF4WpG z3}YvSBOBa{WG#JY-u>v3R%*_=t=QIWtjbBmZtHUXOC5<0Fo zqMi9Hopx291#PwA<6&Jh*s|a}=qH8TOZsO*z|Kvtu&@3sLq4*d51mlzoZG#`acj<%nx$ zaH%=-^~KU}oQQh*A@4_)6?=|dMWnjh%6ntwmhGC`%t7;YW}t1`xBIg{xibXPIf4C& zmKFQ@AuRy=1tr=vKx9py2I=*{ZX?<<3e8qJ0PH)|Hv|nlcmr2_6(O?DX6T$T2n{Xg z`CDMt1N(xjjBu4zeIt;58Q7Gy%DsLzS?O2m(Ho<2$+2X@M?e0;6p+m&iB z-yft^*q4|tnRBkCI{Hd}%7I9kIaeIr_bl&3-P8`tv4=BeT??+fIaf!wL_KD9-4PQs#CYTH^EQk5A&{hBeysOO@brm&DRZpeHOM6cE@^)U(lPBr7*Htr&%XD z-OEJO`z*@NrYcv*+nNLvbEhiTe!}WeFRMg!lDUzsh4$MQY$DL}J#(P_J-NKBQb z%8=&dO-8WcyWrw-`zD5ZrVU^A;e>_k2hi4)r%-v?=YSX_ir8@wV~j8s!$FK|cZIve zkQ~H8MedSt^sv++cgh_ikt5;9*kMr-4@pE)YTHAhND;)6qC^zjX}@wv!nJS6iqt_O z%F!ayRH$y|t#GZM6Qa07iA1AKAvt_d3U0;~4=YvM9RGXTk^Emne*@|nQUw42 literal 0 HcmV?d00001 diff --git a/v1.25/bin/CIRCLE.BAS b/v1.25/bin/CIRCLE.BAS new file mode 100644 index 0000000000000000000000000000000000000000..611fc0da8ef0633fbbbe92cb21c0e54d9236b89b GIT binary patch literal 1664 zcmaJ>Uuaup6hD~z`7o2*+?)Q{x^6waD>Q-I+T=mzMa0|N+a{8K<|c*uWNhP>(Iz3u zU{e%rAFQ-cy0KNzhwepvP!tAZ%Gio1XtCSNl!01w5529cJ{0sprS*JC)3h6yhg`n% z{eHjioZmU$xAVF4W5*n(PG>RPAH_trR4(K*<7gBnif1d?5*oSE=y(=>cU~jdFm2}w zc?|Rh`p{?ijY9E!DR=60rAjsmr6LBNJ{eH?e-JucOT>xfMzi^Hb_}B#(#w%{4<<^5 zQ>DxV{}!{Q%6Tlj!WAIky5m?t%N)}1T@=r#5$sq*?ay^+mL5$+OsmUQVsQmh zu2si7=-zTb-nITHWW=--c+a)v_!fWGzClTqwOc5Ps-#NVB8on3Nn6GiRrG4}sL;_0 z+;sixSjNMu=p+aQAF)D#2d>8jQaMC`W&UZaB6lwP#P9tZKlsFERb26J@bz^+pxYx5 z>WO`*tNslIYd<5LG$Q8i0+lN1svid3ZJgvhNUBL=O`1@zxw|;Zbr4mRKF}d9zbAdg z-OEYteWbe&Wqs2RKe|uy63HlDqNFz0%%EP=Nc>N;6%fUK&UDw9t?J<#Gf~Qx%UCXE zMzi>Gri7IOju!HjT>flUffHgxn8DTcHATS{q;^IG=o5zpBRbH9Hm*WQe2DaPhPgV)7MV^6_djn6l6oQ(HY|+BW8qXhiTZ$^NSR3@k9fY|*Pc(NsuJ)!DrYOnScJ>;!G`Jrk{jZkX7wCovVL!(*v%ENv2S)^od7 zIxKqbQQ`Z{zbC*ap8E~+zxHhIGji9*`vUyx`Ku9s$o#)Oz#0v!n@?R4q(h8+B)U^- zVstB^O=@PB@I&7A;|#i`7Pfs6m15v21p-nl2m2U2D;;MvRUQ1|!WF55J#5jQA^O0u z9y81Vs@Vz~*we$^qspUE?pt>?s&^}mXJ8V;wv69lyYGZHrQt{DrZhj5u$~kE{3La< z+T$^Ujpv8IEi@b3vr0KLQ5?^f6}5fc0h^LSsnXcf;4f)!!ItD>bMTn_3`xioyM;%n zhIV<7SpoYPslU0gGyR}Nvw}8#y`abmwgmlhn$gWWLJ!uwQoB5+W$@#pSY-sV}3QM zdR1N3gKEoWD_oP$F`d(coZevD`Y!i|Jjtfuwmi$W=jsYgsuzBdFH27A0 z*;&jY^r0#!7D9cf3VkRD1*M=+E&h@2gF+kn1EK!Wnuk6lSzD;&!KZ3GccZt~o*2ME{UbfQ&LvjG;zY_5*_Ltva5Eg|J}}~VI**K5 zJar0LBGpRGW531vQpeGtWDHnP?#AXZZn0j1(Bj|9W5Am7s6-l@2rw_Efev!*M1p;1 zw!crX%@(_CwnhB83D2pTM5vy1sIz9zWv7GcaF5=1(8U|iQYGY1>xqzg$CY39g*NwcKE@DsQFeiQdp4T4HinIH6g)qc7(DLxwPPY_NGK; zfDhO^QpXT*hMkmz8{ix}O)yUO`kH+rwcrx_QaXxR%7Eh~jKg*I4aK9&eH5`CXtOI+ z%TX(PtG}&7kM<*xvsRXDBNDl8?%p^-pLSDv4M$(bWHcQziW9qDcgSBqVGd*Eb{}hxUs^gXwE{M zdm_~>mJZwaOgGg6KPpn4vV#g%#l!MXL({1ux?V_`9^}V_O5D<^Qx$%qt88 zX+FGiq7>cAo#r2rkWSfr%Rd#=$flV>8Y`qhCUs_9apDa=CzC^0mLi9BEIKE{FZ_a> zn*C`clgsSSz$#ym$xv{Y-=K`hZ19M_B)7oSe4=AU_P4ec z2;GH`mR+Hdp^;&V#G)~KVcD?`%~hpp%yt%N#S zn$V|m#wzsk*@Cfp)qB_I?)1dO;OhEQ5hWZIZz=DkGpapFKcq(}cp;$Wp=QJ;2Uj^~ z9YKXXO*vzaFm-|=>rY48IyOe>Luwml(N+ARi^9(gw3IF_nT{LKo8g*N(qQnDj75SS zAL(&1*vZb5(x)n|Yx%#2wG}=wLZ7D{!xT$T6_P2c|2Hv;Gq*FOc8mR(j?*vC7w@K|<%L`c^ zo3m}#B)fwD4^kC)IcS&5_L5aOq;a-Exf9a;(p@P&LUGeAIo3i|AO;!>UeY<+s!T9{ z?@@}|OSBhe-EApz$)&7Wbu9C6vCLUs$uvoB|7d`6R#6T#iS3{qa0Y85oE=wYo4$OG z@{oSauXjAepbBs2I*-CSKJ`NFY%_Sa0+CJdAtMzx;y$9?>yK-6OeRX=zmYn~p@y;d5ysX# zR~Qa>oGn}Ft{38z)$<1NF%2QO9MCA2F^u@&>i8i0V(1jadwlVXo=xPZn`FHO zDg12cB?!xc^$?gUB*)=OdV z@-m;1YMa78hgzSn*4QIQpvp8NhPdQnS;I(CWO`c)iEA8Haw!hFKm1D=QCe$OP*yx% ztQN_vplP6alx)W_OV#r7trlWg>BNKKw~%h}!c!cWkxvy_YAX_E2<`g;b|!p9Y=ih~ z$jL-v3i5aWKdyN}U*jrYtHo44%jn3b9L~$GhX2e?i+l=Q(sOiMh_!cJ^Gc%|Xhh0<%7pfzy(De^bGhEkfa3KjU+~#xPM_a1ddA#f2o}He$ zohG9DpPE1J+8BU$$WBV*sFQRd52VV2h1pNLf&rjg4YA*M^#(FJs$f<2PQM|t)h-?Y z4+(O^k4J9118i@%8j$1$GP)*8Q1TAgYTRQhFjO3?!8ZbeBZ9l-k2Hb)+b60W8?UcK zI-}P^9+(Aan%CHo?wx@Z#9tjB925Q5Ys=Fj``+WSNdL-hVIjbdckdPseJ>J{+`|Lx z)$YAwcR(={Xe%%)$AK~So9=u7wEeZgh!j)HX zML@0|B`4HSH2Q(^DNFuwH+*F%?7?T{?%GmIx3$XS_FNu;Yl{U4nHYnsL6Cj&xdQVnQQr7rFA(1t5 zqV;mL#Y-M@>$&MvY%-fpr3<;6`$vxSxSjz+4T%oIezobMw^Oa}pnBVYNYP+*F!EiA zm_hkO(g1MD$Y#@7nnY=(W3fUuYs6s#f=PWJ+I}GmN%Vg(V0^!h7kC* zC3zhney#T^BJ2AKq&Ay}&iLS(KFCh@{vq(1_87a``*xt-7u&p4gY2{w_OZVA11lQ- z)su?>zg#Stv}`XrR4SIsDitw3S-1u`RWUhoc1PcJfVTz)qJ=pzR)XP8>oA5et5UV) zggI}|n)52z4(8gv8_gQ-l2t9ud0WhiPT`tWI_TK*R4tb8qpHo>_xt|UtRbX^#672i zInH!lFSn4S8S{`;8Nxt~^oj9;{jTpnz9vp1p)i3v4;tB?wD>DWWSsp^eXIo>e>uSZ z(zl`IF~<5sE%hKNwR(sfpw~o3%+{Rk=pSgQ4FF=0;d+IN?sBCx=hzi{(M6-1pI@w4 zrJ@|0%U0z+&Sv^Q)6xjml2tClV=~=pai(m!bLfsUW_8KLxnyV`=^yr`U9*g~36a`d zD-$8bPWNlRn7sMjI;|jUZf(YQG2#EUKMv3PMTeH2j~5qb$-$+Lk6lvQF^_SyH_q7R zly5gvbgb&K5C{qZOx=9*-Tr6U;%BU?TbCH)x3haT&-fC#s=YurON@|zW01AlnCO=_ zmxZR>i})xtT?AgGCvO2hlKyqCDNT}EUl0j0Qx9K^j7(V^mueHbWxck{!(E2X)j zQ$#Es%dJ`^*8>i@iwg^7OXOggv*5sSUtZW*MA(Jkta;D^z>7Dhmot6f312}ZTL|0G zY+OWKfM00IySO{V+5UkiTW-D;1fOeRj}ClGoUf~KzG-_ArB^}T1pvgov1FGQ=PNX8 zxeMhYuH2}pGXp36?Qw^^MPz2#s}$Vu2)9q6@!`O;zQ)8TkcW_&wOxeVyjj7<^6CR; zw`_S%xFu&w2^z1I^wc!%Gp27Tr!h9R<@pxDqhgxy_*8VS=UW8Hp|)6m|Nnpg{{p3~ BG0Fe{ literal 0 HcmV?d00001 diff --git a/v1.25/bin/COMMAND.COM b/v1.25/bin/COMMAND.COM new file mode 100644 index 0000000000000000000000000000000000000000..751326fc092d1859d10b8b184fc4e33bf9cf0781 GIT binary patch literal 4959 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 literal 0 HcmV?d00001 diff --git a/v1.25/bin/COMP.COM b/v1.25/bin/COMP.COM new file mode 100644 index 0000000000000000000000000000000000000000..0d161190fac293e83aad60546e2f19b4eb255020 GIT binary patch literal 1649 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 Pkcxz(_Y8?J@!9sjF9}YP literal 0 HcmV?d00001 diff --git a/v1.25/bin/DISKCOPY.COM b/v1.25/bin/DISKCOPY.COM new file mode 100644 index 0000000000000000000000000000000000000000..e2436d1c70d1534c2df35a5ee4a7479c54d78aa9 GIT binary patch literal 2008 zcmZ`)ZD<@t7@pnB>|Ku}ZK;Nef)fcxVr!ZYlBO{^`-L>phLEOGLk`*8ZIUIq+jDLv z_57fh6*WC;5d5Kkl(dLqk56&ujamXvCV{`Oa=ENz}mX zWaggtd7tN<*?03_Dt#jw>DqsU^k_6;#MCizz=*~<(!kqX6291-(J#CFU#j}YV*27vXp+(3M707fTeunf=W0E^ zlEfHtV)t=2Vo(4aRLAuQgfa$stdn?lQ?7bhX~PopTREJow%9W_T*nHxp}5+85K@}qJqcz+@%(JX3H-~x#~HA{UfXF!6;odfSQ(P zq;!1?mg`&bWc_aZG|W><5TBkmgS&CN`+ldodw(uQdlKCtCJDiwB zi9epIY{Nb207$w$3D3#EZU{c=ZL%qvm`Bpo{5!3k*uTubF3z_@CVpB38N*RA*;*OvZdA2kyJ5oe~MtdtNe3E&9?T@5< zsAT^v<-1G0R+m%F{<(Bj=%Gv3SypMsD62f{mNdn@Aj)IgND%vkRS#ILvp+><5HQ?c z)h!q2T_28mD-Hf811)%si$ms$hjkT!-VC;bmGcj!2ZX59Hfw2267e0&l)X{ z7Qvt}P{#9_LyG-6I-YMS*_Tk^n&VTc^!8?z4!8yLv+i}`a&aO3+r=P$Yp(2+*E}iv z`0p3@T#-LTPA7-!fPHbW;%)=52rBo-gpKVi}463%R6! z&Ur8T=X%X6`zEWt@LF%WrTD-rO6y}D>tk=O+L{)Rt?*cdqcwjLLXwP-48sGX3t*F++uaBh`A2jla5X;?!VTm}!v;e}y0VI248LBurEZ-)9D+Ftw)xV`wrELbBsbU9oX>48DnR6+WDBZ|VANx1@=<7STJXW;BQOD$3Xx9 literal 0 HcmV?d00001 diff --git a/v1.25/bin/DONKEY.BAS b/v1.25/bin/DONKEY.BAS new file mode 100644 index 0000000000000000000000000000000000000000..8b6ac8afd3dd0783654a869e7fbae851d652a391 GIT binary patch literal 3584 zcmai0eQZR_Vq%hQ*r%GXPcx*IRq-tU4(cEUZ zUVj43x==k(7^2cDsf7j>Xt5aIQGInHC;m5kRuMU3-{jqU&Y)93_v4c2F#rYBS+@sy&)% zEb)mX4{^(t+TGOpK`m^wOfAx7qZuBavV2hcTY6cZpmvdyPg6ofyJ(kRq$D7Z%jc+D zBo6riSq42Q`k$IiY=~y78_H`=uM5y>^)sjXo1OH~R1b|-gVsi7Wx3f( z3w_g_u<-Mt4_Q|+C+i}oOSfcwN`MR2R#qYc#Y(h`E*%WKU2K9+xLzJ=NQ8M>bx)7z z)jdH{H^G>0P>7q1~ z3M)|>38!gC5)V&w#1frRG~8P|%1;0Q8 z+i0xB(etz+uw33Q(^se!(|pO!%_Ri@m+cOtP9A&c0`D+x!QPnJ%a8O94(D?tyx1^R zOXZj7Y2**aFyr!f;4gNkaX(Dkw_*Nv_=kP3@uxIg$%2u45o2;_b(;FHiyYjm#+~$m zra;4u8UfaF$8o1hO#$+(AgV!qRoH$)5EZtc5Fo~#VpfR_=p~|8hMO=xMXgWQ!B@E7 zv#%Q_=;Qum9EZoaNwkbq?GA8%GqSQBtZcDHMtMvqRT|*FG8vb*!^_;ijVQAVB?r@S zLW%qej&cUmemKclO-gr(49Vkgky~RrMgv%>Pzf|hH6l4Hh++iF+$5j`j;y(0Ow zAaY{lelR$`$Q0xaO{00tseFzO(>dxC-Hdbf=Y@y69ADLhscH*no%_VTnE2#^fN6!4a^q_EccCpQQaFOUw3RWZKK(e3o#{U>D!osd@MlridhB% zE@iSrKy3f(D4LXPi44dL#sT1+TQp4iH55rd1Cco%*Z0TS9`1GS#G~D!2XV-#`jfSc zeaGQT&hN5#O19#XapJO5j^UqI=^R{*@Z81x2R;XX~O9y@hoh2{@A3llgs4J z>Dea&v%97p0=(dSP0OBbD=uN$$Ew(ZRe0c4=SkBU+CUT7q_?@=G=&>WSMVfU=4T!! zhPA!^I-_p(U?AKmOxiIKyl(yc3a(|+fT@&;DByTR?$;3bsG@YsA4^j{L&*dlxYl*v zvB9zl#W z!C_a$v|Yy3FdEr{_oHHJR3y(-^Fq$qX@cinH%#O36W5Gs<{;%WtxAZ8OD=QW%t1a9 zmx7{H3=OW7#87`QEhW_8m{bh*ug>F|mw5P>i(`iUcc-PH{@_@!80ue>4~+%$Qh#W$ zSrVl@MqBP~U`A};ERBUw7et#iXd6VQqBM3lillsyhqdlInB~}NJc9*HOPwffbGI;Q z9J6S~aGTsR+eTEWMGdAyox!*kxLsl^=CsqT>iUo>VF0OJili};iXWX49C0UfZ7|Xv z{C@@$?(R=ExZ-}W?pT!$NI)d_XlyX;&ezTCrvXmn1o)5p@w%OqwPK)QN38%(&$sJl zc56DElG{bntT!t7Jx|u{1L}FYZX86<3+&)bODhledS1bA%5Gq_D50R&^E0N5uMCRK ztJAF-7FZ5jSK@z^O0dK8OU;JCz!V`35Dgs-BZTs(=PhQUh7b!~tp@Qk*dEeX9ZDYF z^jw^``+U4PD26%_*>^mD)M{kJViiOuOnd%XcNUqhNn}&cz7UTk0@QlnpOY`0moF9I zv)+Fq4rpf4$G#a!MsIUy^nS*?55nGhb4D#?)H26@ky$k=;3LUo9Dg%x^t#Q=TN@6& zn{AA6SO}>JzU8H6Rbo>jt5UX>niMtkXTu%vdk5u9+J+R*QWwXW+5^|Zu$V_TN(gK+ft`ySGauv9FYv4n1f z)mHatbl5js&1AYq(&1nqS~|h*a-d;(O$9f?bPt^OeX|OiX2J57vgH8zeubql-J`>( zIo(lH!Bd#i-+eniJyW-T-=}9P_@6T)3pSOJl93Bt_;#%G{|KSV>OWU5)}ds*|EPIf zM!qtbAn!k6&csWZxYi>2Gd1^?(tKegH-fFQ)jz%vVyYHHJn26-9|FMd$J+h}9AE*4 literal 0 HcmV?d00001 diff --git a/v1.25/bin/EDLIN.COM b/v1.25/bin/EDLIN.COM new file mode 100644 index 0000000000000000000000000000000000000000..5ed51488e2bbede19eb8ab2cd4e078047bf608bc GIT binary patch literal 2392 zcmYjT3v5%@89w$+F68(D8^UPWWNy?j9&WO*sI(=PAu*3SP{N}H(g9hT+<@D}j;`-b z#4`;Tp^ z%94GK&;R|;@Bh!4IBvqP91#Uq(aXY4QSx~`<<)}ITT`pZq9knICHLVYasub{O0~k;7hhOw!r9y16{5!{Rthhdg90}w%Mo@;-osLP z4g0MXCHbh}tztO!Kt^mHeE($3 zWs1hgiamvJje81eu!_x2o3TL819foFH*&ogP4*~O^0)Ji*f1dT z1z=WM6dl*zE9PPWt=lfhvtjjN21{P-ryBiIv**gs*`JZ0R}s31?0J&a{$hRR$(i4L z$M?lW-LrXQG&&X?<35XywR1PRC;r(OM{=LxrhF+(EG@V@tUl4Y!@Kqs?%BO*yKA%Q z7YiZ_Eep-*I~KI1ujFgFWoZ`{?%Ng2oa`a-(%;)g&Xt8@&8ajzB9^nb$#DWBg)e}N z`tCoiK|8h$%g0g~hKlc^s-~n5LP>P_H;MHGHr!E`k|FML0pEt}48+lf$yM9PB^{!- z(F>b3**IT9poo(_TelX^l@6t6BHPF*C=eH4?Px$v*5e2jj4EcP5rx&Y2`+_`#d+`u zxTq-)Vh_2LrSB0aJpr^WUN?GDbD8Qs&%eoRy@@8$oKP1s0{j7w|H2pq1PrZWw1X;4 z_XAfPt(cere7$h0vxKoENr-T0F$ni2DiIM_G6_f)jLQG6HyiHASk)mw!~RwRJrV@o zj}K4w6oKQ@;XOftR;SS=D7c8KmbWGxv!tcMHWEV4=raV_X77wdgc%pz- zBPE|%PB?`$x*o|krjnSOaS+(1EcL_A?>K|~@Q=m^Fl|M0L^US~cK!_RXvOCPxT6IF z+ZwPYKUOmnXCYlAYbX7cem|t`zP(hwXFnS5w;E^%f~r6Co8Q9u*WifnKWCutAU}l2 zs?;>AYx)e)%ky8GwSaTh#>BxLjs9_-jMyMTqc(og20Ela6*9;EV1*<#1K&<#g9cu| zOQPg1fpb^ia>M$8sS9M7%qsVpC>dd@2}EQA1`<$TMD9-Z$nj!7to_zA_=f}G{A=Cz zO!+bR_rI>fiK!HSfJZHuu9#Qu?%BtDf}YirQ72t8Pi~jlZr2&#fx*bSBmdgOtFbp` zQ?PUfbJ8#8$h04t!oRK+E59pPcNWX<(cyVND;)eq8|UfFTnMXHV`6CjSQjuaH-3!9 zH?Y$73C2V-4a>QE_w6Fn+$0x24=s3wO^kNz`|c_JESnhD3#RMSxd&W)9(r@GwCvDS zXITA5ayTBGVe`3RA>0Ycfs>5q)j39a^1wDyNF42Weya1-lew+rzhsn!;s@XTxo0sw zGzXrsflfa~;7udsXGLJU_Aw&2xM)$qUw!RUot;74<(#;B=4$g7%>&Ih;6?zp5I{5E z$-^ydg4rUep%IJ3)y-d1CA-XCs#LL214AUVB$5>o*af3$v}1j#9(lD{_^LG$*phPp39Oq>Ji+_qp1%QS7}5DnqWi(@$S};K9be?TKJp( zj%l&y;zfnqT%Nk}YImhjDY@%J!7B+>?rKr+l-G#aTb{0j8pS6IuZx1OR;+MWxy8zC zXSv7Yl?AcVEepAzCIQRIkwk_}Y_fNF1YSW}#d^stgI&;B0k4;8Q3fL>?DF`Osw#JdTlC06jaUOJ;E}S~BZDeYlDrb^c8K)} zgKP=#DzDow%iQ@JZLCoq literal 0 HcmV?d00001 diff --git a/v1.25/bin/EXE2BIN.EXE b/v1.25/bin/EXE2BIN.EXE new file mode 100644 index 0000000000000000000000000000000000000000..d43a3f2692b219b2bb8fe9d0071b48d647dc6b4d GIT binary patch literal 1280 zcmeH`&ubGw6vy9Y)72zx6GRG@kW3)j2D=~zFWM9=M(Cm9NwfzgO{N+&yJdga3W`aE ziU#rz41zR@rA0JNks3v$NY=?FMLgu>O`PSiZ+M@1Z@yoc z;gKbv!2}2Zbe)AbNP{E=CkZjUTHxz__j!`f*hwL^qS)0mOQD^SEr!zMco9YJMURw9smW| zZXl@AllLSBHeq-~ew+CQZEgsFLtNUwsy{LpSMNQA>F0${$*wIpxSZIIgZOy5T3E|` z2Ad|?0%nky#0Hq?O$Sg&aEAh#1Xpuqt=*oIAf-Wwx%CS4>2NZZrDbb zi?t*%glMFnrL+SSt9MpGE-78AW)L#_yZ-|7k~nEh(Lm{~`!4TR90s|l9*6Rcn#w|X zqINQR1tX4^&=@as5$_Nu%41{Ea1?VAis2Y9T=N=8Sim7E%5w+{0x$f@MWW(mB#wu| zn6Q(qJT4**;|Pu*7LA5Pj6{4fR&UsQ2~YZtB5#Ma*)+t}M~`9@=DDj_kZ{BcsJVh? UgRS4s4m3D)swLFcvhvr3Uk{7|kN^Mx literal 0 HcmV?d00001 diff --git a/v1.25/bin/FORMAT.COM b/v1.25/bin/FORMAT.COM new file mode 100644 index 0000000000000000000000000000000000000000..c1cc45e56de15563933446551013971ddaa17c1e GIT binary patch literal 3816 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%0AvIV>hpGo(R(!x^Jj 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 literal 0 HcmV?d00001 diff --git a/v1.25/bin/MODE.COM b/v1.25/bin/MODE.COM new file mode 100644 index 0000000000000000000000000000000000000000..b9f69e3ec18a2605777b2e3524ae750a47635e2c GIT binary patch literal 2509 zcmeHI-A^3X6+d@p=MJ-ccv)jRktO@ajV89dA-g~@ICyItgW@FA8)~`EhoWrRvDs?b zA+vXokfL;4+K57mtSC|?D-U={EBPf#VJpEB2o4cxt0KF3h*0ukIju5u9!izUNg-i- z?hM3^@-K8B=6u}Wx%ce3=lt%wKvowB{Qvj83Y_iL+3AyAEUBA$BbUmucB8M~;=0MY zjI_>rjK029F3ry2a>mH9czry^4z?d^H~I(7%*9^r1-Bb!Ka01vG_a>KJ$f#$r&(7D z_sHOW53{6cTr^XCLiXz>A7sV_FY1KFdkr&>h%P&Rv38O0;xrQOLo?S?hc{%p#CLwCFgB$mC_Zds4hRS2tZ=- zhQ_8xn~$`#K3E+(Ww1fRVtHL>9P8&5qR+^4*7`$s@R>(`bcj`lz7Nal7r2LteFt?q zH;~F^(yTv)Mbfcqc?F~CG{D%(=)M6M+BnYlzIPd>kHgr)XfuajCpf%D2Vm^e83tec zPWV@p#W_lx!9a1xJFpxsM2Nj{(Av2~Pe@>E5kiVE9wEzNcelNfv}%2SO@sut{7dvW z0&Bve9${iy2Rwu`SRQ{JqNMOTj29ppC=_6PQrMH=J|ckGZD3LWgImDh77%R&(t5Eu zdF@YQD|P}E-urEiMNHMMsTGIT5^f#0F(Wcl0d@kVCCvn(bke(k+h6)=$t5niQmM;x zPLrzT2dY@xpe1`JxW4cYkyc}6JAwb6-*bs~o4-2rRPro4%1k|-G4&pf4a*JIex{2Z z^={5z%^Cb2L_MxJ8FF}GY++m_g!t;N9LWWZIsx3JIJ>%jMFA#F|8hVirc7j5{B zHQ6}~rLZhEQ*bZK+iQ>gpR#sf8|bJ|s^3Cr;~2d}Kak}j+`KiqR(?ySyXZdp5RK7R zdXhd#&rkS!rx43M>?r~69`F^*z29HrZrD>K%T+uDTpSL7bZ80^ z_A3G4)d?KRXzY&mA`Pr`Y#XV&MqmXaszcp+K9kmSob?+f7tDgB&~@fi2g@3%w4UCc zfQ9#L`D(4AJtp%fw5v&&*rRAyyJ6yf6wkxNPf)x76VE8~waN^K%U`^;K5fg|L=td( zw25w*UO?-4-+BQyN|&i$!8`907yjA$Ijkl3CGkpEZ0)7s&(H6F^NQ~it~>OlpuPV* zr}kg%Q>Sj+`M~C1op*0|UF64q^e3uW$Bapkv+?G&mz1S=7FO6 z+{of{e$c)BcN*F5BGO}8A3(}vIUId4_SK=JnaK(I)lJhdeV5;jd7ZNhhRIrD_q6D? zGv3(no#-sGXPzP5vP`b07nzFVGQj9=TCu#x{`)nNwNkp~HRqz82$7>)TD^jkS4oap z)Oq@w)lqPM`whY@Y1M|gN+Npxx>ER9iN=dCK`Wf9O~ECVrFXqerXp^{-uNZjfAj4f zZeR-R4eW^N`@s2CxdNs#s#U6Q1a}{f|YDg%`%D`ky$$+|-7}!n$OsI1xj#E4x3i*8^LYCA+)qb+Tn~*&7=KfwDNdTUBRo zR?Gt+Z$Ax!H;g)i5fL$1+cuR7*?>V!c~@NjjC7OheW9& zdsGDl_eIn=7E*0NTM~${dZa3VPZ}cR5;7D%g;b4~0G8_ZO1CP6 z;WvU+V<%J+=OG~)uq|E%$NXAcKUFc=*-K!zFiYxmzxvIauYx8XnstMio9rt`_> Kw~z4M7Wf~mvFYdl literal 0 HcmV?d00001 diff --git a/v1.25/bin/MORTGAGE.BAS b/v1.25/bin/MORTGAGE.BAS new file mode 100644 index 0000000000000000000000000000000000000000..80c062e5ce5353aff1e3b1ebffb8df0167e1ca3a GIT binary patch literal 6272 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 B5hVZs literal 0 HcmV?d00001 diff --git a/v1.25/bin/PIECHART.BAS b/v1.25/bin/PIECHART.BAS new file mode 100644 index 0000000000000000000000000000000000000000..943b398803051e41bf7e5b786ac52959b10e3dd7 GIT binary patch literal 2304 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 literal 0 HcmV?d00001 diff --git a/v1.25/bin/SETCLOCK.COM b/v1.25/bin/SETCLOCK.COM new file mode 100644 index 0000000000000000000000000000000000000000..3bf8501eb9d7f2c3ef66bcba4fe04b77417d97cd GIT binary patch literal 853 zcmZuvTSyd97@nEE<;GG}&+-dW*0!@#4^iUF?l_gD?mBLp7Ydf0QI}T7W@iPV2P@lb zZHq4S5WR%ZLn*8vq??zGSxgBriXK9cP@$u315wzEv(r)Wsm?k4=kk63?fn009Yx^L zv*CzG(VE@mFEXAjSbe%KlW) z{=_wI(;EEA+&L{3v^r-S{HTo3ybZ}50zzB1dY!Yu?`xMYH8nOnv-7X*M^-ArT~s=} z{wI-Bk!E~Y*`D^Cx*5y%n7mK+7dEgTb?D*H19hZmu0(w_W+n#FgkfQrL=NpGu-Hu` zRb(ZW(5S<%_F2xTp85drTs`OE*|SHXs+Ohk)l&_Dsu~X1Y9D(ZKL$Adw1?%u&->2s zo*HP8WKh~fsPfi;pX2L&wOE7o)%Y)9CJklmVOHwwmLsig3jFKfC>%R=@;D9Ek+9ei z69s4wDWV(+MZpD~veYVv+Bf%3QC7M^YWa@^2*s5)9D@rgJ$z#|T=WD2zFIae%VLKD zN~B$cNDLUJd~4AR0}gxX4lH1A+pwEq+$R|Ix?vk43VE-;ZrJ=0H8#JtuYc=V-b1M`m)26j1Nq);0(jX38@P+CuyPYqHxr%gH<)u%ZF zCLfa<{pLjOjyYLLnf-m0RN6iDoI^&frsm7_gAVw# literal 0 HcmV?d00001 diff --git a/v1.25/bin/SPACE.BAS b/v1.25/bin/SPACE.BAS new file mode 100644 index 0000000000000000000000000000000000000000..52ba147e7935692f53aca58b4008854dd3363a72 GIT binary patch literal 1920 zcmbVNU2GIp6ux9Ni^LdWG%;rDxii~ti-`~J z!~A^b`@XsNoO91EUGZM@oPpG!4OVLe;&!2!%ch4RlpDz(E!hP~=F`14dEosVS=|`T z(KR67LKro61TwrjU|v-g6R!haU2lZ(&vJNI0pG%f5%6>+rKN z3!*L=*ML%8)J0ya?W zZuJgxX+ov9wZ$J)x>2V$v_T44(M<++ z0rtv&w1GlY+RBuItK6h-c9rphT`WS8wHNfH3sA~IZ!TNPWRKbkd6sr^r(k~Jo}$1F zz&dtv#G>6?DALvhWtb;v`U(=Nugj!vj=V~TYB)>y7R@z~crrmtwU`1`=P`~<($_fr z2FfqeG0y3%vPf>zvq)E$&Z%BMr@^n_4G?YN9$wMWZ9f!k;K@CDp2OCOJFQcvOXN@b z5r>V^9_wraEA^B@cKfFoa3t2XBN2vZECpRjD|!f0?O_PTI%A1v4kgTZyA?`8Bo?(& zu>_cHW;_*6pt#__%EYO5D+%#L44Dy>hm)|PF{5pe2*1!}B@j)uo2g}WvqC=bf5p^s z46#@k+y-kk6OfAG$D=7L+7(9P1^;*M*2$OtJGk*x$-l#qul;vx$)EQ>Se3|X9`ADG zFaIAk{E_6#BH?QVTTVV!WvjTJ$2_8ZySRbJQ%QD-Uj9A!n3bLKKOG({^3G26P$XeitUt!B~+!Oop5d${vRgyn6AgPJ>( z+87uGt1Q8{(4aONCk*%m1YG8SZqp@Q*SGff_rGpb&Md$=!nE6e{ zat&~WSo@Kl;k~;{EqnIlo*O#Q+uPXJ*J$_mHx3Lmrqhi*igALRmuLBoV0mfmmj=%| zqoajA(YKAtnA#E4J6dpC`ftoM=v06Yu`h XIKk>z5^nOWw!$=z9Z_HZzrOzuSa~Zi literal 0 HcmV?d00001 diff --git a/v1.25/bin/SYS.COM b/v1.25/bin/SYS.COM new file mode 100644 index 0000000000000000000000000000000000000000..7f478fac0a37dd4eaf1bab0531f478fb58556f26 GIT binary patch literal 605 zcma)$L2DC19L4|cO3`3jFIsFZ&T7D5O9{=Tpp;mZF<^{PJt(oT%}(f$W;e`ETH+~q zTleHQC@Fpd=U^uwsku6r6cmphge|$)gQUG!r&|lX2+m=6yqVv7uYX-WHFmc_&KbLH z*w{DDW?QcfSvJIZWqmkzL0Pk%=KM=Q^{;mh`M2hL5rFr^6=nVIwDyg;p(60E7?lTx zvJ##8M>%DR(OAA0<8tYS4mksxBj#q-Y#$g~(2NMkB~y$mt373I0g9f%MiE-GW(&+W zmx~~-Dr@ALfWh~-8i?{xPwS7-16WV#xR}%S^HU+wBalDhy$Z>9M*o-mZ1jJMo8gYK zfa8%T_v0_?f8Uo zq>!1yT1edv`ctyAJX>qZNW|w}C38f!0@uix{z;#&9C}*h9?os;KO-lMGMe z#OKtFE8|GrQu3-bZ7i?qNylA2eMORs$C@+S^~;1Y;w0e^j?NI|7V-=C0), then the one byte will be saved as pure code. Otherwise, +;the details of the addressing mode will be investigated and the optional one- +;or two-byte displacement will be added, as described by [ADDR] and [ALABEL]. + PUSH CX + PUSH DX + PUSH BX + MOV CH,0 + MOV CL,AL + CALL GEN ;Save the addressing mode as pure code + MOV AL,CL + MOV CH,80H + AND AL,0C7H + CMP AL,6 + JZ TWOBT ;Direct address? + AND AL,0C0H + JZ PRET ;Indirect through reg, no displacement? + CMP AL,0C0H + JZ PRET ;Register to register operation? + MOV CH,AL ;Save whether one- or two-byte displacement +TWOBT: + MOV BX,[ADDR] + MOV DX,[ALABEL] + JP PUTCHK + +GRP2: + CALL GETOP + MOV CX,0FF30H + CMP AL,UNDEFID + JZ PMEM + MOV CH,50H + CMP AL,XREG + JZ PXREG + MOV CH,6 + CMP AL,SREG + JNZ $+5 + JMP PACKREG + MOV CL,20 + JMP ERROR + +PMEM: + MOV AL,CH + CALL PUT + MOV AL,CL + OR AL,DL + JMP PUTADD + +PXREG: + MOV AL,CH + OR AL,DL + JMP PUT + +GRP3: + CALL GETOP + PUSH DX + CALL GETOP2 + POP BX + MOV CX,8614H + MOV AL,SREG + CMP AL,BH + JZ ERR6 + CMP AL,DH + JZ ERR6 + MOV AL,CONST + CMP AL,BH + JZ ERR6 + CMP AL,DH + JZ ERR6 + MOV AL,UNDEFID + CMP AL,BH + JZ EXMEM + CMP AL,DH + JZ EXMEM1 + MOV AL,BH + CMP AL,DH + MOV CL,22 + JNZ ERR6 + CMP AL,XREG + JZ L0008 + CALL RR1 +L0008: ;RR1 never returns + MOV AL,BL + OR AL,AL + JZ EXACC + XCHG DX,BX + MOV AL,BL + OR AL,AL + MOV AL,BH + JZ EXACC + CALL RR1 +EXACC: + MOV AL,90H + OR AL,DL + JMP PUT + +EXMEM: + XCHG DX,BX +EXMEM1: + CMP AL,BH + JZ ERR6 + MOV CL,1 ;Flag word as OK + CALL NOTAC ;NOTAC never returns +ERR6: JMP ERROR + +GRP4: + PUSH AX + CALL GETOP + POP CX + XCHG CL,CH + CMP AL,CONST + JZ FIXED + SUB AL,XREG + DEC DL + DEC DL + OR AL,DL + MOV CL,20 + JNZ ERR6 + MOV AL,CH + OR AL,8 + JMP PUT +FIXED: + MOV AL,CH + CALL PUT + JMP PUTBYT + +GRP5: + PUSH AX + CALL GETOP + MOV CL,20 + CMP AL,CONST + JNZ ERR6 + MOV BX,[DLABEL] + MOV AL,BH + OR AL,BL + MOV CL,30 + JNZ ERR6 + MOV BX,[DATA] + POP AX + OR AL,AL + JZ ORG + DEC AL + JZ DSJ + DEC AL + JZ EQU + DEC AL + JZ $+5 + JMP IF +PUTOP: + MOV AL,-3 + JP NEWLOC +ALIGN: + MOV AL,[PC] + AND AL,1 + JZ RET + MOV BX,1 +DSJ: + XCHG DX,BX + MOV BX,[PC] + ADD BX,DX + MOV [PC],BX + XCHG DX,BX + MOV AL,-4 + JP NEWLOC +EQU: + XCHG DX,BX + MOV BX,[LABPT] + MOV AL,BH + OR AL,BL + MOV CL,34 + JZ ERR7 + MOV [BX],DL + INC BX + MOV [BX],DH + RET +ORG: + MOV [PC],BX + MOV AL,-2 +NEWLOC: + CALL PUTCD + MOV AL,BL + CALL PUTCD + MOV AL,BH + CALL PUTCD + MOV CH,0C0H + JMP GEN1 +GRP6: + MOV CH,AL + MOV CL,4 + CALL MROPS + MOV CL,23 +ERR7: JMP ERROR +GRP7: + MOV CH,AL + MOV CL,1 + CALL MROPS + MOV CL,80H + MOV DX,[DLABEL] + MOV AL,DH + OR AL,DL + JNZ ACCJ + XCHG DX,BX + MOV BX,[DATA] + MOV AL,BL + CBW + CMP AX,BX + XCHG DX,BX + JNZ ACCJ + OR CL,002H +ACCJ: JMP ACCIMM +GRP8: + MOV CL,AL + MOV CH,0FEH + JP ONEOP +GRP9: + MOV CL,AL + MOV CH,0F6H +ONEOP: + PUSH CX + CALL GETOP +ONE: + MOV CL,26 + CMP AL,CONST + JZ ERR7 + CMP AL,SREG + MOV CL,22 + JZ ERR7 + POP CX + CMP AL,UNDEFID + JZ MOP + AND AL,1 + JZ ROP + TEST CL,001H + JZ ROP + MOV AL,CL + AND AL,0F8H + OR AL,DL + JMP PUT +MOP: + MOV AL,[FLAG] + AND AL,1 + OR AL,CH + CALL PUT + MOV AL,CL + AND AL,38H + OR AL,DL + JMP PUTADD +ROP: + OR AL,CH + CALL PUT + MOV AL,CL + AND AL,38H + OR AL,0C0H + OR AL,DL + JMP PUT +GRP10: + MOV CL,AL + MOV CH,0F6H + PUSH CX + CALL GETOP + MOV CL,20 + MOV AL,DL + OR AL,AL + JNZ ERRJ1 + MOV AL,DH + CMP AL,XREG + JZ G10 + CMP AL,REG +ERRJ1: JNZ ERR8 +G10: + PUSH AX + CALL GETOP + POP AX + AND AL,1 + MOV [FLAG],AL + MOV AL,DH +ONEJ: JP ONE +GRP11: + CALL PUT + MOV AL,0AH + JMP PUT +GRP12: + MOV CL,AL + MOV CH,0D0H + PUSH CX + CALL GETOP + MOV AL,[SYM] + CMP AL,',' + MOV AL,DH + JNZ ONEJ + PUSH DX + CALL GETOP + SUB AL,REG + MOV CL,20 + DEC DL + OR AL,DL + JNZ ERR8 + POP DX + MOV AL,DH + POP CX + OR CH,002H + PUSH CX + JMP ONE +GRP13: + MOV CH,AL + MOV CL,1 + CALL MROPS + MOV CL,80H +ACCIMM: + CALL IMMED + OR CH,004H + AND CH,0FDH +AIMM: + MOV AL,BH + AND AL,1 + LAHF + PUSH AX + OR AL,CH + CALL PUT + POP AX + SAHF + JNZ $+5 + JMP PUTBYT + JMP PUTWOR + +ERR8: JMP ERROR + +GRP14: +;JMP and CALL mnemonics + LAHF + XCHG AH,AL + PUSH AX + XCHG AH,AL + MOV B,[MAXFLG],3 ;Allow "L" flag + CALL GETOP + CMP AL,CONST + JZ DIRECT + MOV CL,20 + CMP AL,REG + JZ ERR8 + CMP AL,SREG + JZ ERR8 + CMP AL,XREG + JNZ NOTRG + OR DL,0C0H +NOTRG: +;Indirect jump. DL has addressing mode. + MOV AL,0FFH + CALL PUT + POP AX + XCHG AH,AL + SAHF + AND AL,38H + OR AL,DL + MOV CH,[FLAG] + CMP CH,3 ;Flag "L" present? + JZ PUTADDJ ;If so, do inter-segment + MOV CL,27H + CMP CH,-1 ;Better not be a flag + JNZ ERR8 + AND AL,0F7H ;Convert to intra-segment +PUTADDJ: + JMP PUTADD +DIRECT: + MOV AL,[SYM] + CMP AL,',' + JZ LONGJ + POP AX + XCHG AH,AL + SAHF + DEC AL + CMP AL,0E9H + JZ GOTOP + MOV AL,0E8H +GOTOP: + CALL PUT + MOV DX,[PC] + INC DX + INC DX + SUB [DATA],DX + JMP PUTWOR +LONGJ: + POP AX + XCHG AH,AL + SAHF + CALL PUT + CALL PUTWOR + CALL GETOP + MOV CL,20 + CMP AL,CONST + JNZ ERR8 + JMP PUTWOR + +GRP16: +;RET mnemonic + LAHF + XCHG AH,AL + PUSH AX + XCHG AH,AL + CALL GETSYM + CMP AL,5 + JZ LONGR + CMP AL,EOL + JZ NODEC + CMP AL,';' + JZ NODEC +GETSP: + CALL GETOP1 + POP CX + CMP AL,CONST + MOV CL,20 + JNZ ERR9 + MOV AL,CH + AND AL,0FEH + CALL PUT + JMP PUTWOR +LONGR: + CMP DL,3 ;Is flag "L"? + MOV CL,27H + JNZ ERR10 ;If not, bad flag + POP AX + XCHG AH,AL + SAHF + OR AL,8 + LAHF + XCHG AH,AL + PUSH AX + XCHG AH,AL +NOTLON: + CALL GETSYM + CMP AL,EOL + JZ DORET + CMP AL,';' + JZ DORET + CMP AL,',' + JNZ L0011 + CALL GETSYM +L0011: + JP GETSP +NODEC: +;Return is intra-segment (short) without add to SP. +;Record position for RET symbol. + MOV BX,[PC] + MOV [LSTRET],BX + XCHG DX,BX + MOV BX,[RETPT] + MOV AL,BH + OR AL,BL + JZ DORET + MOV B,[BX],1 + INC BX + MOV [BX],DX + MOV BX,0 + MOV [RETPT],BX +DORET: + POP AX + XCHG AH,AL + SAHF + JMP PUT + +GRP17: + CALL PUT + CALL GETOP + CMP AL,CONST + MOV CL,20 +ERR9: JNZ ERR10 + MOV BX,[DATA] + MOV DX,[PC] + INC DX + SUB BX,DX + MOV [DATA],BX + CALL PUTBYT + MOV BX,[DLABEL] + MOV AL,BH + OR AL,BL + JNZ RET + MOV BX,[DATA] + MOV AL,BL + CBW + CMP AX,BX ;Signed 8-bit number? + JZ RET + MOV CL,31 +ERR10: JMP ERROR + RET +GRP18: + CALL GETOP + CMP AL,CONST + MOV CL,20 + JNZ ERR10 + MOV BX,[DLABEL] + MOV AL,BH + OR AL,BL + JNZ GENINT + MOV BX,[DATA] + MOV DX,3 + SBB BX,DX + JNZ GENINT + MOV AL,0CCH + JMP PUT +GENINT: + MOV AL,0CDH + CALL PUT + JMP PUTBYT + +GRP19: ;ESC opcode + CALL GETOP + MOV CL,20 + CMP AL,CONST + JNZ ERRJ ;First operand must be immediate + MOV CL,1EH + TEST [DLABEL],-1 ;See if all labels have been defined + JNZ ERRJ + MOV AX,[DATA] + CMP AX,64 ;Must only be 6 bits + MOV CL,1FH + JNB ERRJ + MOV BL,AL ;Save for second byte + SHR AL + SHR AL + SHR AL + OR AL,0D8H ;ESC opcode + CALL PUT + PUSH BX + CALL GETOP2 + POP BX + AND BL,7 ;Low 3 bits of first operand + SHL BL + SHL BL + SHL BL + CMP AL,UNDEFID ;Check for memory operand + JZ ESCMEM + CMP AL,CONST ;Check for another immediate + JZ ESCIMM + MOV CL,20 +ERRJ: JMP ERROR + +ESCMEM: + OR BL,DL ;Combine mode with first operand + MOV AL,BL + JMP PUTADD + +ESCIMM: + MOV CL,1EH + TEST [DLABEL],-1 ;See if second operand is fully defined + JNZ ERRJ + MOV AX,[DATA] + MOV CL,1FH + CMP AX,8 ;Must only be 3 bit value + JNB ERRJ + OR AL,BL ;Combine first and second operands + OR AL,0C0H ;Force "register" mode + JMP PUT + +GRP20: + MOV CH,AL + MOV CL,1 + CALL MROPS + MOV CL,0F6H + CALL IMMED + MOV CH,0A8H + JMP AIMM +GRP21: + CALL GETOP + CMP AL,SREG + MOV CL,28 + JNZ ERRJ + MOV CH,26H +PACKREG: + MOV AL,DL + ADD AL,AL + ADD AL,AL + ADD AL,AL + OR AL,CH + JMP PUT +GRP22: + CALL GETOP + MOV CX,8F00H + CMP AL,UNDEFID + JNZ $+5 + JMP PMEM + MOV CH,58H + CMP AL,XREG + JNZ $+5 + JMP PXREG + MOV CH,7 + CMP AL,SREG + JZ PACKREG + MOV CL,20 +ERR11: JMP ERROR +GRP23: + MOV [DATSIZ],AL +GETDAT: + CALL GETSYM + MOV AL,2 + CALL VAL1 + MOV AL,[SYM] + CMP AL,',' + MOV AL,[DATSIZ] + JNZ ENDDAT + CALL SAVDAT + JP GETDAT +ENDDAT: + CMP AL,2 + JNZ SAVDAT + MOV BX,[DATA] + LAHF + OR BL,080H + SAHF + MOV [DATA],BX +SAVDAT: + OR AL,AL + JZ $+5 + JMP PUTBYT + JMP PUTWOR +IF: + OR BX,BX + JZ SKIPCD + INC B,[IFFLG] + RET + +SKIPCD: + INC B,[CHKLAB] +SKIPLP: + XOR AL,AL + CALL NEXLIN + CALL NEXTCHR + CMP AL,1AH + JZ END + CALL GETLAB + JC SKIPLP + MOV DI,LENID + MOV SI,IFEND + MOV CH,0 + MOV CL,[DI] + INC CL + REPE + CMPB + JZ ENDCOND + MOV DI,LENID + MOV SI,IFNEST + MOV CL,[DI] + INC CL + REPE + CMPB + JNZ SKIPLP + INC B,[CHKLAB] + JP SKIPLP + +ENDCOND: + DEC B,[CHKLAB] + JNZ SKIPLP + RET + +ENDIF: + MOV AL,[IFFLG] + MOV CL,36 + DEC AL + JS ERRJMP + MOV [IFFLG],AL + RET + +ERRJMP: JMP ERROR + +;********************************************************************* +; +; PASS 2 +; +;********************************************************************* + +END: + MOV DL,4 +WREND: + MOV CH,0FFH + MOV AL,CH + CALL GEN + DEC DL + JNZ WREND + MOV [BUFPT],SRCBUF + MOV B,[HEXCNT],-5 ;FLAG HEX BUFFER AS EMPTY + MOV [LSTPNT],LSTBUF + MOV [HEXPNT],HEXBUF + XOR AX,AX + MOV [ERRCNT],AX + MOV [PC],AX + MOV [LINE],AX ;Current line number + MOV [HEXADD],OBJECT + MOV DX,FCB + MOV AH,OPEN + INT 33 ;Re-open source file + XOR AX,AX + MOV [FCB+12],AX ;Set CURRENT BLOCK to zero + MOV [FCB+20H],AL ;Set NEXT RECORD field to zero + MOV [FCB+14],BUFSIZ + MOV [COUNT],AL + MOV CH,1 + MOV SI,START +FIXLINE: + MOV DI,START ;Store code over used up intermediate code + XOR AL,AL + MOV [SPC],AL ;No "special" yet (ORG, PUT, DS) + MOV [ERR],AL ;No second pass errors yet +NEXBT: + SHL CL ;Shift out last bit of previous code + DEC CH ;Still have codes left? + JNZ TESTTYP + LODB ;Get next flag byte + MOV CL,AL + MOV CH,4 +TESTTYP: + SHL CL ;Set flags based on two bits + JO FIXUP + LODB + JC EMARK +OBJBT: + STOB + JP NEXBT + +FIXUP: +;Either a word or byte fixup is needed from a forward reference + LODW ;Get pointer to symbol + XCHG AX,BX + LODW ;Get constant part + ADD AX,[BX+1] ;Add symbol value to constant part + CMP B,[BX],0 ;See if symbol got defined + JNZ HAVDEF + MOV B,[ERR],100 ;Undefined - flag error + XOR AX,AX +HAVDEF: + OR CL,CL ;See if word or byte fixup + JS DEFBYT + STOW + JP NEXBT + +DEFBYT: + MOV DX,AX + CBW ;Extend sign + CMP AX,DX ;See if in range +127 to -128 + JZ OBJBT ;If so, it's always OK + NOT AH ;Check for range +255 to -256 + CMP AH,DH + JNZ RNGERR ;Must always be in this range +;Check for short jump. If so, we're out of range; otherwise we're OK + CMP DI,START+1 ;Only one other byte on line? + JNZ OBJBT ;Can't be short jump if not + MOV AL,[START] ;Get the first byte of this line + CMP AL,0EBH ;Direct short jump? + JZ RNGERR + AND AL,0FCH + CMP AL,0E0H ;LOOP or JCXZ instruction? + JZ RNGERR + AND AL,0F0H + CMP AL,70H ;Conditional jump? + MOV AL,DL ;Get code byte in AL + JNZ OBJBT ;If not, we're OK +RNGERR: + MOV B,[ERR],101 ;Value out of range + JP OBJBT + +FINIJ: JMP FINI + +EMARK: + CMP AL,-1 ;End of file? + JZ FINIJ + CMP AL,-10 ;Special item? + JA SPEND + PUSH CX + PUSH SI + PUSH AX ;Save error code + MOV AH,[LSTDEV] + AND AH,0FEH ;Reset error indicator + OR AL,[ERR] ;See if any errors on this line + JZ NOERR + OR AH,1 ;Send line to console if error occured +NOERR: + MOV [LSTDEV],AH + MOV CX,DI + CALL STRTLIN ;Print address of line + MOV SI,START + SUB CX,SI ;Get count of bytes of code + JZ SHOLIN +CODLP: + LODB + CALL SAVCD ;Ouput code to HEX and PRN files + LOOP CODLP +SHOLIN: + MOV AL,0 + XCHG AL,[COUNT] + MOV CX,7 ;Allow 7 bytes of code per line + SUB CL,AL + MOV AL,' ' + JZ NOFIL +BLNK: ;Put in 3 blanks for each byte not present + CALL LIST + CALL LIST + CALL LIST + LOOP BLNK +NOFIL: + CALL OUTLIN + POP AX ;Restore error code + CALL REPERR + MOV AL,[ERR] + CALL REPERR + POP SI + POP CX + MOV AL,[SPC] ;Any special funtion? + OR AL,AL + JNZ SPCFUN + JMP FIXLINE + +SPEND: + MOV [SPC],AL ;Record special function + LODW ;Get it's data + MOV [DATA],AX + JMP NEXBT + +SPCFUN: + MOV DX,[DATA] + CMP AL,-2 + JZ DORG + CMP AL,-3 + JZ DPUT +DDS: +;Handle DS pseudo-op + ADD [PC],DX + ADD [HEXADD],DX + JMP FIXLINE + +DORG: +;Handle ORG pseudo-op + MOV [PC],DX + JMP FIXLINE + +DPUT: +;Handle PUT pseudo-op + MOV [HEXADD],DX + JMP FIXLINE + +OUTLIN: +;Copy the source line to the ouput device. Line will be preceded by +;assembler-generated line number. This routine may be called several times +;on one line (once for each line of object code bytes), so it sets a flag +;so the line will only be output on the first call. + MOV AL,-1 + XCHG AL,[LINFLG] + OR AL,AL + JNZ CRLF ;Output line only if first time + MOV AX,[LINE] + INC AX + MOV [LINE],AX + MOV BH,0 ;No leading zero suppression + CALL OUT10 + MOV AL," " + CALL LIST + MOV AL,[LSTFCB] + CMP AL,'Z' + JZ CRLF ;Don't call NEXTCHR if listing suppressed + PUSH SI ;Save the only register destroyed by NEXTCHR +OUTLN: + CALL NEXTCHR + CALL LIST + CMP AL,10 ;Output until linefeed found + JNZ OUTLN + POP SI + RET + +PRTCNT: + MOV AX,[ERRCNT] + MOV BX,ERCNTM +PRNT10: + PUSH AX + CALL PRINT + POP AX + MOV BH,"0"-" " ;Enable leading zero suppression + CALL OUT10 +CRLF: + MOV AL,13 + CALL LIST + MOV AL,10 + JP LIST + +OUT10: + XOR DX,DX + MOV DI,10000 + DIV AX,DI + OR AL,AL ;>10,000? + JNZ LEAD + SUB AL,"0"-" " ;Convert leading zero to blank +LEAD: + ADD AL,"0" + CALL LIST + XCHG AX,DX + MOV BL,100 + DIV AL,BL + MOV BL,AH + CALL HIDIG ;Convert to decimal and print 1000s digit + CALL DIGIT ;Print 100s digit + MOV AL,BL + CALL HIDIG ;Convert to decimal and print 10s digit + MOV BH,0 ;Ensure leading zero suppression is off + JP DIGIT + +HIDIG: + AAM ;Convert binary to unpacked BCD + OR AX,3030H ;Add "0" bias +DIGIT: + XCHG AL,AH + CMP AL,"0" + JZ SUPZ + MOV BH,0 ;Turn off zero suppression if not zero +SUPZ: + SUB AL,BH ;Convert leading zeros to blanks + JP LIST + +STRTLIN: + MOV B,[LINFLG],0 + MOV BX,[PC] + MOV AL,BH + CALL PHEX + MOV AL,BL +PHEXB: + CALL PHEX + MOV AL,' ' +LIST: + PUSH AX + PUSH DX + AND AL,7FH + MOV DL,AL + TEST B,[LSTDEV],3 ;See if output goes to console + JZ PRNCHK + MOV AH,2 + INT 33 ;Output to console +PRNCHK: + TEST B,[LSTDEV],4 ;See if output goes to printer + JZ FILCHK + MOV AH,5 + INT 33 ;Output to printer +FILCHK: + MOV AL,DL + POP DX + TEST B,[LSTDEV],80H ;See if output goes to a file + JZ LISTRET + CALL WRTBUF +LISTRET: + POP AX + RET + +WRTBUF: + PUSH DI + MOV DI,[LSTPNT] + STOB + CMP DI,LSTBUF+LSTBUFSIZ + JNZ SAVPT + PUSH AX + PUSH CX + PUSH DX + CALL FLUSHBUF + POP DX + POP CX + POP AX +SAVPT: + MOV [LSTPNT],DI + POP DI + RET + +PHEX: + PUSH AX + CALL UHALF + CALL LIST + POP AX + CALL LHALF + JP LIST + +FINI: + OR B,[LSTDEV],1 + CALL PRTCNT + MOV BX,SYMSIZE + MOV AX,[6] + SUB AX,[HEAP] ;Size of symbol table + CALL PRNT10 + MOV BX,FRESIZE + MOV AX,[HEAP] + SUB AX,[CODE] ;Free space remaining + CALL PRNT10 + AND B,[LSTDEV],0FEH + MOV AL,[HEXFCB] + CMP AL,'Z' + JZ SYMDMP + MOV AL,[HEXCNT] + CMP AL,-5 + JZ L0012 + CALL ENHEXL +L0012: + MOV AL,':' + CALL PUTCHR + MOV CH,10 +HEXEND: + PUSH CX + MOV AL,'0' + CALL PUTCHR + POP CX + DEC CH + JNZ HEXEND + MOV AL,13 + CALL PUTCHR + MOV AL,10 + CALL PUTCHR + MOV AL,1AH + CALL PUTCHR + CALL WRTHEX ;Flush HEX file buffer + MOV DX,HEXFCB + MOV AH,CLOSE + INT 33 +SYMDMP: + MOV AL,[SYMFLG] + CMP AL,'S' + JNZ ENDSYM + MOV AL,[LSTDEV] + OR AL,AL ;Any output device for symbol table dump? + JNZ DOSYMTAB + OR AL,1 ;If not, send it to console + MOV [LSTDEV],AL +DOSYMTAB: + MOV BX,SYMMES + CALL PRINT + MOV DX,[BASE] + MOV AL,DH + OR AL,DL + JZ ENDSYM + MOV B,[SYMLIN],SYMWID ;No symbols on this line yet + MOV BX,[HEAP] + MOV SP,BX ;Need maximum stack for recursive tree walk + CALL NODE +ENDSYM: + TEST B,[LSTDEV],80H ;Print listing to file? + JZ EXIT + MOV AL,1AH + CALL WRTBUF ;Write end-of-file mark + MOV DI,[LSTPNT] + CALL FLUSHBUF + MOV AH,CLOSE + INT 33 +EXIT: JMP 0 + +NODE: + XCHG DX,BX + PUSH BX + MOV DL,[BX] + MOV DH,0 + INC BX + ADD BX,DX + MOV DX,[BX] + OR DX,DX + JZ L0014 + CALL NODE +L0014: + POP BX + MOV AL,[BX] + INC BX + MOV CH,AL + ADD AL,24 + SHR AL + SHR AL + SHR AL + MOV CL,AL + INC CL ;Invert last bit + AND CL,1 ;Number of extra tabs needed (0 or 1) + SHR AL ;Number of positions wide this symbol needs + SUB [SYMLIN],AL + JNC WRTSYM ;Will it fit? + SUB AL,SYMWID + NEG AL + MOV [SYMLIN],AL + CALL CRLF ;Start new line if not +WRTSYM: + MOV AL,[BX] + INC BX + CALL LIST + DEC CH + JNZ WRTSYM + INC CL +TABVAL: + MOV AL,9 + CALL LIST + LOOP TABVAL + INC BX + INC BX + PUSH BX + MOV AL,[BX+4] + CALL PHEX + MOV AL,[BX+3] + CALL PHEX + CMP B,[SYMLIN],0 ;Will any more fit on line? + JZ NEXSYMLIN + MOV AL,9 + CALL LIST + JP RIGHTSON +NEXSYMLIN: + CALL CRLF + MOV B,[SYMLIN],SYMWID +RIGHTSON: + POP BX + MOV DX,[BX] + OR DX,DX + JNZ NODE + RET + +SAVCD: + MOV [PREV],AL + PUSH BX + PUSH CX + PUSH AX + PUSH DX + CALL CODBYT + POP DX + MOV BX,COUNT + INC B,[BX] + MOV AL,[BX] + CMP AL,8 + JNZ NOEXT + MOV B,[BX],1 + CALL OUTLIN + MOV AL,' ' + MOV CH,5 +TAB: + CALL LIST + DEC CH + JNZ TAB +NOEXT: + POP AX + CALL PHEXB + POP CX + INC [PC] + INC [HEXADD] + POP BX + RET + +REPERR: + OR AL,AL ;Did an error occur? + JZ RET + INC [ERRCNT] + PUSH AX + MOV BX,ERRMES ;Print "ERROR" + CALL PRINT + POP AX +;We have error number in AL. See if there's an error message for it + MOV DI,ERRTAB + MOV BL,80H +ERRLOOK: + SCASB ;Do we have the error message + JBE HAVMES ;Quit looking if we have it or passed it + XCHG AX,BX ;Put 80H in AL to look for end of this message +NEXTMES: + SCASB ;Look for high bit set in message + JA NEXTMES ; which means we've reached the end + XCHG AX,BX ;Restore error number to AL + JMPS ERRLOOK ;Keep looking + +HAVMES: + MOV BX,DI ;Put address of message in BX + JZ PRNERR ;Do we have a message for this error? + CALL PHEX ;If not, just print error number + JMP CRLF + +PRNERR: + CALL PRINT + JMP CRLF + +PRINT: + MOV AL,[BX] + CALL LIST + OR AL,AL + JS RET + INC BX + JP PRINT + +OUTA: + MOV DL,AL +OUT: + AND DL,7FH + MOV CL,2 +SYSTEM: + CALL 5 + RET + +CODBYT: + CMP B,[HEXFCB],"Z" + JZ RET + PUSH AX + MOV DX,[LASTAD] + MOV BX,[HEXADD] + MOV [LASTAD],BX + INC DX + MOV AL,[HEXCNT] + CMP AL,-5 + JZ NEWLIN + CMP BX,DX + JZ AFHEX + CALL ENHEXL +NEWLIN: + MOV AL,':' + CALL PUTCHR + MOV AL,-4 + MOV [HEXCNT],AL + XOR AL,AL + MOV [CHKSUM],AL + MOV BX,[HEXPNT] + MOV [HEXLEN],BX + CALL HEXBYT + MOV AL,[HEXADD+1] + CALL HEXBYT + MOV AL,[HEXADD] + CALL HEXBYT + XOR AL,AL + CALL HEXBYT +AFHEX: + POP AX +HEXBYT: + MOV CH,AL + MOV BX,CHKSUM + ADD AL,[BX] + MOV [BX],AL + MOV AL,CH + CALL UHALF + CALL PUTCHR + MOV AL,CH + CALL LHALF + CALL PUTCHR + MOV BX,HEXCNT + INC B,[BX] + MOV AL,[BX] + CMP AL,26 + JNZ RET +ENHEXL: + MOV DI,[HEXLEN] + MOV CH,AL + CALL UHALF + STOB + MOV AL,CH + CALL LHALF + STOB + MOV AL,-6 + MOV [HEXCNT],AL + MOV AL,[CHKSUM] + ADD AL,CH + NEG AL + CALL HEXBYT + MOV AL,13 + CALL PUTCHR + MOV AL,10 + CALL PUTCHR +WRTHEX: +;Write out the line + MOV DX,HEXBUF + MOV [HEXPNT],DX + MOV AH,SETDMA + INT 33 + SUB DI,DX ;Length of buffer + MOV CX,DI + MOV DX,HEXFCB + MOV AH,BLKWRT + INT 33 + OR AL,AL + JNZ DSKFUL + RET + +PUTCHR: + MOV DI,[HEXPNT] + STOB + MOV [HEXPNT],DI + RET + +FLUSHBUF: + MOV CX,DI + MOV DX,LSTBUF + MOV DI,DX + SUB CX,DX + JZ RET ;Buffer empty? + MOV AH,SETDMA + INT 33 + MOV DX,LSTFCB + MOV AH,BLKWRT + INT 33 + OR AL,AL + JZ RET +DSKFUL: + MOV BX,WRTERR + JMP PRERR + +UHALF: + RCR AL + RCR AL + RCR AL + RCR AL +LHALF: + AND AL,0FH + OR AL,30H + CMP AL,'9'+1 + JC RET + ADD AL,7 + RET + +NONE: DB 0 + +; 8086 MNEMONIC TABLE + +; This table is actually a sequence of subtables, each starting with a label. +; The label signifies which mnemonics the subtable applies to--A3, for example, +; means all 3-letter mnemonics beginning with A. + +A3: + DB 7 + DB 'dd' + DW GRP7 + DB 2 + DB 'nd' + DW GRP13 + DB 22H + DB 'dc' + DW GRP7 + DB 12H + DB 'aa' + DW PUT + DB 37H + DB 'as' + DW PUT + DB 3FH + DB 'am' + DW GRP11 + DB 0D4H + DB 'ad' + DW GRP11 + DB 0D5H +A5: + DB 1 + DB 'lign' + DW ALIGN + DB 0 +C3: + DB 7 + DB 'mp' + DW GRP7 + DB 3AH + DB 'lc' + DW PUT + DB 0F8H + DB 'ld' + DW PUT + DB 0FCH + DB 'li' + DW PUT + DB 0FAH + DB 'mc' + DW PUT + DB 0F5H + DB 'bw' + DW PUT + DB 98H + DB 'wd' + DW PUT + DB 99H +C4: + DB 3 + DB 'all' + DW GRP14 + DB 9AH + DB 'mpb' + DW PUT + DB 0A6H + DB 'mpw' + DW PUT + DB 0A7H +C5: + DB 2 + DB 'mpsb' + DW PUT + DB 0A6H + DB 'mpsw' + DW PUT + DB 0A7H +D2: + DB 5 + DB 'b' + DW GRP23 + DB 1 + DB 'w' + DW GRP23 + DB 0 + DB 'm' + DW GRP23 + DB 2 + DB 's' + DW GRP5 + DB 1 + DB 'i' + DW PUT + DB 0FAH +D3: + DB 4 + DB 'ec' + DW GRP8 + DB 49H + DB 'iv' + DW GRP10 + DB 30H + DB 'aa' + DW PUT + DB 27H + DB 'as' + DW PUT + DB 2FH +D4: + DB 1 + DB 'own' + DW PUT + DB 0FDH +E2: + DB 1 + DB 'i' + DW PUT + DB 0FBH +E3: + DB 3 + DB 'qu' + DW GRP5 + DB 2 + DB 'sc' + DW GRP19 + DB 0D8H + DB 'nd' + DW END + DB 0 +E5: + DB 1 + DB 'ndif' + DW ENDIF + DB 0 +H3: + DB 1 + DB 'lt' + DW PUT + DB 0F4H +H4: + DB 1 + DB 'alt' + DW PUT + DB 0F4H +I2: + DB 2 + DB 'n' + DW GRP4 + DB 0E4H + DB 'f' + DW GRP5 + DB 4 +I3: + DB 4 + DB 'nc' + DW GRP8 + DB 41H + DB 'nb' + DW GRP4 + DB 0E4H + DB 'nw' + DW GRP4 + DB 0E5H + DB 'nt' + DW GRP18 + DB 0CCH +I4: + DB 4 + DB 'mul' + DW GRP10 + DB 28H + DB 'div' + DW GRP10 + DB 38H + DB 'ret' + DW PUT + DB 0CFH + DB 'nto' + DW PUT + DB 0CEH +J2: + DB 10 + DB 'p' + DW GRP17 + DB 0EBH + DB 'z' + DW GRP17 + DB 74H + DB 'e' + DW GRP17 + DB 74H + DB 'l' + DW GRP17 + DB 7CH + DB 'b' + DW GRP17 + DB 72H + DB 'a' + DW GRP17 + DB 77H + DB 'g' + DW GRP17 + DB 7FH + DB 'o' + DW GRP17 + DB 70H + DB 's' + DW GRP17 + DB 78H + DB 'c' + DW GRP17 + DB 72H +J3: + DB 17 + DB 'mp' + DW GRP14 + DB 0EAH + DB 'nz' + DW GRP17 + DB 75H + DB 'ne' + DW GRP17 + DB 75H + DB 'nl' + DW GRP17 + DB 7DH + DB 'ge' + DW GRP17 + DB 7DH + DB 'nb' + DW GRP17 + DB 73H + DB 'ae' + DW GRP17 + DB 73H + DB 'nc' + DW GRP17 + DB 73H + DB 'ng' + DW GRP17 + DB 7EH + DB 'le' + DW GRP17 + DB 7EH + DB 'na' + DW GRP17 + DB 76H + DB 'be' + DW GRP17 + DB 76H + DB 'pe' + DW GRP17 + DB 7AH + DB 'np' + DW GRP17 + DB 7BH + DB 'po' + DW GRP17 + DB 7BH + DB 'no' + DW GRP17 + DB 71H + DB 'ns' + DW GRP17 + DB 79H +J4: + DB 6 + DB 'mps' + DW GRP17 + DB 0EBH + DB 'cxz' + DW GRP17 + DB 0E3H + DB 'nge' + DW GRP17 + DB 7CH + DB 'nae' + DW GRP17 + DB 72H + DB 'nbe' + DW GRP17 + DB 77H + DB 'nle' + DW GRP17 + DB 7FH +L3: + DB 3 + DB 'ea' + DW GRP6 + DB 8DH + DB 'ds' + DW GRP6 + DB 0C5H + DB 'es' + DW GRP6 + DB 0C4H +L4: + DB 5 + DB 'oop' + DW GRP17 + DB 0E2H + DB 'odb' + DW PUT + DB 0ACH + DB 'odw' + DW PUT + DB 0ADH + DB 'ahf' + DW PUT + DB 9FH + DB 'ock' + DW PUT + DB 0F0H +L5: + DB 4 + DB 'oope' + DW GRP17 + DB 0E1H + DB 'oopz' + DW GRP17 + DB 0E1H + DB 'odsb' + DW PUT + DB 0ACH + DB 'odsw' + DW PUT + DB 0ADH +L6: + DB 2 + DB 'oopne' + DW GRP17 + DB 0E0H + DB 'oopnz' + DW GRP17 + DB 0E0H +M3: + DB 2 + DB 'ov' + DW GRP1 + DB 88H + DB 'ul' + DW GRP10 + DB 20H +M4: + DB 2 + DB 'ovb' + DW PUT + DB 0A4H + DB 'ovw' + DW PUT + DB 0A5H +M5: + DB 2 + DB 'ovsb' + DW PUT + DB 0A4H + DB 'ovsw' + DW PUT + DB 0A5H +N3: + DB 3 + DB 'ot' + DW GRP9 + DB 10H + DB 'eg' + DW GRP9 + DB 18H + DB 'op' + DW PUT + DB 90H +O2: + DB 1 + DB 'r' + DW GRP13 + DB 0AH +O3: + DB 2 + DB 'ut' + DW GRP4 + DB 0E6H + DB 'rg' + DW GRP5 + DB 0 +O4: + DB 2 + DB 'utb' + DW GRP4 + DB 0E6H + DB 'utw' + DW GRP4 + DB 0E7H +P3: + DB 2 + DB 'op' + DW GRP22 + DB 8FH + DB 'ut' + DW GRP5 + DB 3 +P4: + DB 2 + DB 'ush' + DW GRP2 + DB 0FFH + DB 'opf' + DW PUT + DB 9DH +P5: + DB 1 + DB 'ushf' + DW PUT + DB 9CH +R3: + DB 6 + DB 'et' + DW GRP16 + DB 0C3H + DB 'ep' + DW PUT + DB 0F3H + DB 'ol' + DW GRP12 + DB 0 + DB 'or' + DW GRP12 + DB 8 + DB 'cl' + DW GRP12 + DB 10H + DB 'cr' + DW GRP12 + DB 18H +R4: + DB 2 + DB 'epz' + DW PUT + DB 0F3H + DB 'epe' + DW PUT + DB 0F3H +R5: + DB 2 + DB 'epnz' + DW PUT + DB 0F2H + DB 'epne' + DW PUT + DB 0F2H +S3: + DB 11 + DB 'ub' + DW GRP7 + DB 2AH + DB 'bb' + DW GRP7 + DB 1AH + DB 'bc' + DW GRP7 + DB 1AH + DB 'tc' + DW PUT + DB 0F9H + DB 'td' + DW PUT + DB 0FDH + DB 'ti' + DW PUT + DB 0FBH + DB 'hl' + DW GRP12 + DB 20H + DB 'hr' + DW GRP12 + DB 28H + DB 'al' + DW GRP12 + DB 20H + DB 'ar' + DW GRP12 + DB 38H + DB 'eg' + DW GRP21 + DB 26H +S4: + DB 5 + DB 'cab' + DW PUT + DB 0AEH + DB 'caw' + DW PUT + DB 0AFH + DB 'tob' + DW PUT + DB 0AAH + DB 'tow' + DW PUT + DB 0ABH + DB 'ahf' + DW PUT + DB 9EH +S5: + DB 4 + DB 'casb' + DW PUT + DB 0AEH + DB 'casw' + DW PUT + DB 0AFH + DB 'tosb' + DW PUT + DB 0AAH + DB 'tosw' + DW PUT + DB 0ABH +T4: + DB 1 + DB 'est' + DW GRP20 + DB 84H +U2: + DB 1 + DB 'p' + DW PUT + DB 0FCH +W4: + DB 1 + DB 'ait' + DW PUT + DB 9BH +X3: + DB 1 + DB 'or' + DW GRP13 + DB 32H +X4: + DB 2 + DB 'chg' + DW GRP3 + DB 86H + DB 'lat' + DW PUT + DB 0D7H + + +; 8087 MNEMONIC TABLE +; Similar to 8086 table above, except NOT distinguished by opcode length + +XM1: ;F2XM1 + DB 1 ;One opcode + DM "xm1" + DB 1,0F0H + +NDPA: + DB 3 + DM "dd" + DB 6+ARITH,0C1H + DM "ddp" + DB NEEDOP+STACKOP,0 + DM "bs" + DB 1,0E1H + +NDPB: + DB 2 + DM "ld" + DB 7+NEEDOP+MEMORY,20H + DM "stp" + DB 7+NEEDOP+MEMORY,30H + +NDPC: + DB 5 + DM "om" + DB 0+ONEREG+REAL,0D1H + DM "omp" + DB 0+ONEREG+REAL,0D9H + DM "hs" + DB 1,0E0H + DM "ompp" + DB 6,0D9H + DM "lex" + DB 3,0E2H + +NDPD: + DB 6 + DM "iv" + DB 6+ARITH,0F1H + DM "ivp" + DB NEEDOP+STACKOP,30H + DM "ivr" + DB 6+ARITH,0F9H + DM "ivrp" + DB NEEDOP+STACKOP,38H + DM "ecstp" + DB 1,0F6H + DM "isi" + DB 3,0E1H + +NDPE: + DB 1 + DM "ni" + DB 3,0E0H + +NDPF: + DB 1 + DM "ree" + DB 5+NEEDOP+ONEREG,0 + +NDPI: + DB 13 + DM "add" + DB 2+NEEDOP+INTEGER,0 + DM "ld" + DB 3+NEEDOP+INTEGER+EXTENDED,0 + DM "sub" + DB 2+NEEDOP+INTEGER,20H + DM "stp" + DB 3+NEEDOP+INTEGER+EXTENDED,18H + DM "st" + DB 3+NEEDOP+INTEGER,10H + DM "mul" + DB 2+NEEDOP+INTEGER,8 + DM "div" + DB 2+NEEDOP+INTEGER,30H + DM "subr" + DB 2+NEEDOP+INTEGER,28H + DM "divr" + DB 2+NEEDOP+INTEGER,38H + DM "com" + DB 2+NEEDOP+INTEGER,10H + DM "comp" + DB 2+NEEDOP+INTEGER,18H + DM "ncstp" + DB 1,0F7H + DM "nit" + DB 3,0E3H + +NDPL: + DB 10 + DM "d" + DB 1+NEEDOP+ONEREG+REAL+EXTENDED,0 + DM "dz" + DB 1,0EEH + DM "d1" + DB 1,0E8H + DM "dpi" + DB 1,0EBH + DM "dl2t" + DB 1,0E9H + DM "dl2e" + DB 1,0EAH + DM "dlg2" + DB 1,0ECH + DM "dln2" + DB 1,0EDH + DM "dcw" + DB 1+NEEDOP+MEMORY,28H + DM "denv" + DB 1+NEEDOP+MEMORY,20H + +NDPM: + DB 2 + DM "ul" + DB 6+ARITH,0C9H + DM "ulp" + DB NEEDOP+STACKOP,8 + +NDPO: + DB 1 + DM "p" + DB NEEDOP+1,0 ;Flag special handling + +NDPN: + DB 1 + DM "op" + DB 1,0D0H + +NDPP: + DB 3 + DM "rem" + DB 1,0F8H + DM "tan" + DB 1,0F2H + DM "atan" + DB 1,0F3H + +NDPR: + DB 2 + DM "ndint" + DB 1,0FCH + DM "stor" + DB 5+NEEDOP+MEMORY,20H + +NDPS: + DB 12 + DM "t" + DB 5+NEEDOP+ONEREG+REAL,0D0H + DM "tp" + DB 7+NEEDOP+ONEREG+REAL+EXTENDED,0D8H + DM "ub" + DB 6+ARITH,0E1H + DM "ubp" + DB NEEDOP+STACKOP,0E0H + DM "ubr" + DB 6+ARITH,0E9H + DM "ubrp" + DB NEEDOP+STACKOP,0E8H + DM "qrt" + DB 1,0FAH + DM "cale" + DB 1,0FDH + DM "ave" + DB 5+NEEDOP+MEMORY,30H + DM "tcw" + DB 1+NEEDOP+MEMORY,38H + DM "tenv" + DB 1+NEEDOP+MEMORY,30H + DM "tsw" + DB 5+NEEDOP+MEMORY,38H + +NDPT: + DB 1 + DM "st" + DB 1,0E4H + +NDPW: + DB 1 + DM "ait" + DB NEEDOP,0 ;Flag special handling + +NDPX: + DB 3 + DM "ch" + DB 1+ONEREG,0C9H + DM "am" + DB 1,0E5H + DM "tract" + DB 1,0F4H + +NDPY: + DB 2 + DM "l2x" + DB 1,0F1H + DM "l2xp1" + DB 1,0F9H + + +OPTAB: +; Table of pointers to mnemonics. For each letter of the alphabet (the +; starting letter of the mnemonic), there are 5 entries. Each entry +; corresponds to a mnemonic whose length is 2, 3, 4, 5, and 6 characters +; long, respectively. If there are no mnemonics for a given combination +; of first letter and length (such as A-2), then the corresponding entry +; points to NONE. Otherwise, it points to a place in the mnemonic table +; for that type. + +; This table only needs to be modified if a mnemonic is added to a group +; previously marked NONE. Change the NONE to a label made up of the first +; letter of the mnemonic and its length, then add a new subsection to +; the mnemonic table in alphabetical order. + + DW NONE + DW A3 + DW NONE + DW A5 + DW NONE + DW NONE ;B + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;C + DW C3 + DW C4 + DW C5 + DW NONE + DW D2 ;D + DW D3 + DW D4 + DW NONE + DW NONE + DW E2 ;E + DW E3 + DW NONE + DW E5 + DW NONE + DW NONE ;F + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;G + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;H + DW H3 + DW H4 + DW NONE + DW NONE + DW I2 ;I + DW I3 + DW I4 + DW NONE + DW NONE + DW J2 ;J + DW J3 + DW J4 + DW NONE + DW NONE + DW NONE ;K + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;L + DW L3 + DW L4 + DW L5 + DW L6 + DW NONE ;M + DW M3 + DW M4 + DW M5 + DW NONE + DW NONE ;N + DW N3 + DW NONE + DW NONE + DW NONE + DW O2 ;O + DW O3 + DW O4 + DW NONE + DW NONE + DW NONE ;P + DW P3 + DW P4 + DW P5 + DW NONE + DW NONE ;Q + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;R + DW R3 + DW R4 + DW R5 + DW NONE + DW NONE ;S + DW S3 + DW S4 + DW S5 + DW NONE + DW NONE ;T + DW NONE + DW T4 + DW NONE + DW NONE + DW U2 ;U + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;V + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;W + DW NONE + DW W4 + DW NONE + DW NONE + DW NONE ;X + DW X3 + DW X4 + DW NONE + DW NONE + DW NONE ;Y + DW NONE + DW NONE + DW NONE + DW NONE + DW NONE ;Z + DW NONE + DW NONE + DW NONE + DW NONE + +NDPTAB: +;Lookup table for 8087 mnemonics. There is one entry for each letter of the +;alphabet + DW NDPA + DW NDPB + DW NDPC + DW NDPD + DW NDPE + DW NDPF + DW NONE ;G + DW NONE ;H + DW NDPI + DW NONE ;J + DW NONE ;K + DW NDPL + DW NDPM + DW NDPN + DW NDPO + DW NDPP + DW NONE ;Q + DW NDPR + DW NDPS + DW NDPT + DW NONE ;U + DW NONE ;V + DW NDPW + DW NDPX + DW NDPY + DW NONE ;Z + +;Error message table + +ERRTAB: + DM 1,"Register not allowed in immediate value" + DM 2,"Index or base register must be BP, BX, SI, or DI" + DM 3,"Only one base register (BX, BP) allowed" + DM 4,"Only one index register (SI or DI) allowed" + DM 5,"Only addition allowed on register or undefined label" + DM 6,"Only one undefined label per expression allowed" + DM 7,"Illegal digit in hexadecimal number" + DM 8,"Illegal digit in decimal number" + DM 10,"Illegal character in label or opcode" + DM 11,"Label defined twice" + DM 12,"Opcode not recognized" + DM 20,"Invalid operand" + DM 21,'"," and second operand expected' + DM 22,"Register mismatch" + DM 23,"Immediate operand not allowed" + DM 24,'"]" expected' + DM 25,"Two memory operands not allowed" + DM 26,"Destination must not be immediate value" + DM 27,"Both operands must not be registers" + DM 28,"Operand must be segment register" + DM 29,"First operand must be register" + DM 30,"Undefined label not allowed" + DM 31,"Value out of range" + DM 32,"Missing or illegal operand size flag" + DM 33,"Must have label on same line" + DM 35,"Zero-length string illegal" + DM 36,"ENDIF without IF" + DM 37,"One-character strings only" + DM 38,"Illegal expression" + DM 39,"End of string not found" + DM 100,"Undefined label" + DM 101,"Value out of range (forward)" + DB 255 + +ERRMES: DM '***** ERROR: ' +NOSPAC: DB 13,10,'File creation error',13,10,"$" +NOMEM: DB 13,10,'Insufficient memory',13,10,'$' +NOFILE: DB 13,10,'File not found',13,10,'$' +WRTERR: DB 13,10,'Disk full',13,10,'$' +BADDSK: DB 13,10,'Bad disk specifier',13,10,'$' +ERCNTM: DM 13,10,13,10,'Error Count =' +SYMSIZE DM 13,10,'Symbol Table size = ' +FRESIZE DM 'Free space = ' +SYMMES: DM 13,10,'Symbol Table',13,10,13,10 +EXTEND: DB 'ASM',0,0 +IFEND: DB 5,'endif' +IFNEST: DB 2,'if' +RETSTR: DM 'ret' +HEXFCB: DB 0,' HEX',0,0,0,0 + DS 16 + DB 0,0,0,0,0 +LSTFCB: DB 0,' PRN',0,0,0,0 + DS 16 + DB 0,0,0,0,0 +PC: DS 2 +OLDPC: DS 2 +LABPT: DS 2 +FLAG: DS 1 +MAXFLG: DS 1 +ADDR: DS 2 +ALABEL: DS 2 +DATA: DS 2 +DLABEL: DS 2 +CON: DS 2 +UNDEF: DS 2 +LENID: DS 1 +ID: DS 80 +CHR: DS 1 +SYM: DS 1 +BASE: DS 2 +HEAP: DS 2 +SYMFLG: DS 1 +SYMLIN: DS 1 +CODE: DS 2 +DATSIZ: DS 1 +RELOC: DS 1 +BCOUNT: DS 1 +COUNT: DS 1 +ERR: DS 1 +LINE: DS 2 +HEXLEN: DS 2 +HEXADD: DS 2 +LASTAD: DS 2 +HEXCNT: DS 1 +CHKSUM: DS 1 +LINFLG: DS 1 +PREV: DS 1 +IFFLG: DS 1 +CHKLAB: DS 1 +ERRCNT: DS 2 +LSTRET: DS 2 +RETPT: DS 2 +LSTDEV: DS 2 +SPC: DS 1 +NOWAIT: DS 1 +IX: DS 2 +IY: DS 2 +HEXPNT: DS 2 +LSTPNT: DS 2 +HEXBUF: DS HEXBUFSIZ +LSTBUF: DS LSTBUFSIZ +BUFPT: DS 2 +SRCBUF: DS BUFSIZ + DS 100H + ALIGN +STACK: EQU $ +START: EQU $ + \ No newline at end of file diff --git a/v1.25/source/COMMAND.ASM b/v1.25/source/COMMAND.ASM new file mode 100644 index 0000000..830bf73 --- /dev/null +++ b/v1.25/source/COMMAND.ASM @@ -0,0 +1,2166 @@ +; COMMAND version 1.17 +; +; This version of COMMAND is divided into three distinct parts. First +; is the resident portion, which includes handlers for interrupts +; 22H (terminate), 23H (Cntrl-C), 24H (fatal error), and 27H (stay +; resident); it also has code to test and, if necessary, reload the +; transient portion. Following the resident is the init code, which is +; overwritten after use. Then comes the transient portion, which +; includes all command processing (whether internal or external). +; The transient portion loads at the end of physical memory, and it may +; be overlayed by programs that need as much memory as possible. When +; the resident portion of command regains control from a user program, +; a checksum is performed on the transient portion to see if it must be +; reloaded. Thus programs which do not need maximum memory will save +; the time required to reload COMMAND when they terminate. + +;Use the following booleans to set assembly flags +FALSE EQU 0 +TRUE EQU NOT FALSE + +IBMVER EQU FALSE ;Switch to build IBM version of Command +MSVER EQU TRUE ;Switch to build MS-DOS version of Command + +HIGHMEM EQU TRUE ;Run resident part above transient (high memory) + +LINPERPAG EQU 23 +NORMPERLIN EQU 1 +WIDEPERLIN EQU 5 + + IF IBMVER +SYM EQU ">" +COMDRV EQU 1 + ENDIF + + IF MSVER +SYM EQU ":" +COMDRV EQU 0 + ENDIF + +FCB EQU 5CH +DSKRESET EQU 13 +SETBASE EQU 38 +SRCHFRST EQU 17 +SRCHNXT EQU 18 +RENAM EQU 23 +INCHAR EQU 1 +GETFAT EQU 27 +OPEN EQU 15 +CLOSE EQU 16 +MAKE EQU 22 +DELETE EQU 19 +RDBLK EQU 39 +WRBLK EQU 40 +SETDMA EQU 26 +SELDRV EQU 14 +GETDRV EQU 25 +PRINTBUF EQU 9 +OUTCH EQU 2 +INBUF EQU 10 +GETDATE EQU 2AH +SETDATE EQU 2BH +GETTIME EQU 2CH +SETTIME EQU 2DH +RR EQU 33 +RECLEN EQU 14 +FILLEN EQU 16 +OFFDATE EQU 20 + + +;The following are all of the segments used in the load order + +CODERES SEGMENT +CODERES ENDS + +DATARES SEGMENT BYTE +DATARES ENDS + +INIT SEGMENT BYTE +INIT ENDS + +TAIL SEGMENT PARA +TAIL ENDS + +TRANCODE SEGMENT PARA +TRANCODE ENDS + +TRANDATA SEGMENT BYTE +TRANDATA ENDS + +TRANSPACE SEGMENT BYTE +TRANSPACE ENDS + +RESGROUP GROUP CODERES,DATARES,INIT,TAIL +TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE + +;Data for resident portion + +DATARES SEGMENT BYTE + ORG 0 +ZERO = $ +MESBAS DW OFFSET RESGROUP:ERR0 + DW OFFSET RESGROUP:ERR2 + DW OFFSET RESGROUP:ERR4 + DW OFFSET RESGROUP:ERR6 + DW OFFSET RESGROUP:ERR8 + DW OFFSET RESGROUP:ERR10 + DW OFFSET RESGROUP:ERR12 +ERR0 DB "Write protect$" +ERR2 DB "Not ready$" +ERR4 DB "Data$" +ERR6 DB "Seek$" +ERR8 DB "Sector not found$" +ERR10 DB "Write fault$" +ERR12 DB "Disk$" +READ DB "read$" +WRITE DB "writ$" +ERRMES DB " error " +IOTYP DB "writing" +DRVNUM DB " drive " +DRVLET DB "A" +NEWLIN DB 13,10,"$" +REQUEST DB "Abort, Retry, Ignore? $" +BADFAT DB 13,10,"File allocation table bad,$" +COMBAD DB 13,10,"Invalid COMMAND.COM" +NEEDCOM DB 13,10,"Insert DOS disk in " + IF IBMVER + DB "drive A" + ELSE + DB "default drive" + ENDIF +PROMPT DB 13,10,"and strike any key when ready",13,10,"$" +NEEDBAT DB 13,10,"Insert disk with batch file$" +ENDBATMES DB 13,10,"Terminate batch job (Y/N)? $" +LOADING DB 0 +BATFCB DB 1,"AUTOEXECBAT" + DB 21 DUP(?) + DW 0 + DW 0 ;Initialize RR field to zero +PARMTAB DW 10 DUP(-1) ;No parameters initially +BATCH DB 1 ;Assume batch mode initially +COMFCB DB COMDRV,"COMMAND COM" + DB 25 DUP(?) +TRANS DW OFFSET TRANGROUP:COMMAND +TRNSEG DW ? +BATBYT DB ? +MEMSIZ DW ? +SUM DW ? +INITADD DB 4 DUP(?) +RESDATASIZE EQU $-ZERO +DATARES ENDS + +;Data for transient portion + +TRANDATA SEGMENT BYTE + ORG 0 +ZERO EQU $ +BADNAM DB "Bad command or file name",13,10,"$" +MISNAM DB "Missing file name$" +RENERR DB "Duplicate file name or " +NOTFND DB "File not found$" +EXEBAD DB "Error in EXE file$" +NOSPACE DB "Insufficient disk space",13,10,"$" +FULDIR DB "File creation error",13,10,"$" +OVERWR DB "File cannot be copied onto itself",13,10,"$" +LOSTERR DB "Content of destination lost before copy",13,10,"$" +COPIED DB " File(s) copied$" +DIRMES DB " File(s)$" +TOOBIG DB "Program too big to fit in memory$" +BADDRV DB "Invalid drive specification$" +PAUSMES DB "Strike a key when ready . . . $" +BADSWT DB "Illegal switch",13,10,"$" +WEEKTAB DB "SunMonTueWedThuFriSat" +BADDAT DB 13,10,"Invalid date$" +CURDAT DB "Current date is $" +NEWDAT DB 13,10,"Enter new date: $" +BADTIM DB 13,10,"Invalid time$" +CURTIM DB "Current time is $" +NEWTIM DB 13,10,"Enter new time: $" +SUREMES DB "Are you sure (Y/N)? $" + +COMTAB DB 4,"DIR",1 + DW OFFSET TRANGROUP:CATALOG + DB 7,"RENAME",1 + DW OFFSET TRANGROUP:RENAME + DB 4,"REN",1 + DW OFFSET TRANGROUP:RENAME + DB 6,"ERASE",1 + DW OFFSET TRANGROUP:ERASE + DB 4,"DEL",1 + DW OFFSET TRANGROUP:ERASE + DB 5,"TYPE",1 + DW OFFSET TRANGROUP:TYPEFIL + DB 4,"REM",1 + DW OFFSET TRANGROUP:COMMAND + DB 5,"COPY",1 + DW OFFSET TRANGROUP:COPY + DB 6,"PAUSE",1 + DW OFFSET TRANGROUP:PAUSE + DB 5,"DATE",0 + DW OFFSET TRANGROUP:DATE + DB 5,"TIME",0 + DW OFFSET TRANGROUP:TIME + DB 0 ;Terminate command table + +COMBUF DB 128,1,13 + +TRANDATASIZE EQU $-ZERO +TRANDATA ENDS + +;Uninitialized transient data +TRANSPACE SEGMENT BYTE + ORG 0 +ZERO = $ + DB 128 DUP(?) +TPA DW 1 DUP(?) +RESSEG DW 1 DUP(?) +CHKDRV DB 1 DUP(?) +FILTYP DB 1 DUP(?) +CURDRV DB 1 DUP(?) +PARM1 DB 1 DUP(?) +PARM2 DB 1 DUP(?) +COMSW DW 1 DUP(?) +ARG1S DW 1 DUP(?) +ARG2S DW 1 DUP(?) +FLAGER DB 1 DUP(?) +CFLAG DB 1 DUP(?) +SPECDRV DB 1 DUP(?) +BYTCNT DW 1 DUP(?) +NXTADD DW 1 DUP(?) +LINCNT DB 1 DUP(?) +LINLEN DB 1 DUP(?) +FILECNT DW 1 DUP(?) +EXEFCB LABEL WORD +IDLEN DB 1 DUP(?) +ID DB 8 DUP(?) +COM DB 3 DUP(?) +DEST DB 37 DUP(?) +DESTNAME DB 11 DUP(?) +DIRBUF DB 37 DUP(?) +BITS DW 1 DUP(?) +FULLSCR DW 1 DUP(?) +EXEEND DW 1 DUP(?) +;Header variables for EXE file load +;These are overlapped with COPY variables, below +RUNVAR LABEL WORD +RELPT DW 1 DUP(?) +RELSEG DW 1 DUP(?) +PSIZE LABEL WORD +PAGES DW 1 DUP(?) +RELCNT DW 1 DUP(?) +HEADSIZ DW 1 DUP(?) + DW 1 DUP(?) +LOADLOW DW 1 DUP(?) +INITSS DW 1 DUP(?) +INITSP DW 1 DUP(?) + DW 1 DUP(?) +INITIP DW 1 DUP(?) +INITCS DW 1 DUP(?) +RELTAB DW 1 DUP(?) +RUNVARSIZ EQU $-RUNVAR + + DB 80H DUP(?) +STACK LABEL WORD + +PRETRLEN EQU $-ZERO ;Used later to compute TRNLEN + + ORG RUNVAR-ZERO ;Overlaps EXE variables + +SRCPT DW 1 DUP(?) +INEXACT DB 1 DUP(?) +APPEND DB 1 DUP(?) +NOWRITE DB 1 DUP(?) +ASCII DB 1 DUP(?) +PLUS DB 1 DUP(?) +SOURCE DB 11 DUP(?) +TRANSPACESIZE EQU $-ZERO +TRANSPACE ENDS + + +;START OF RESIDENT PORTION + +CODERES SEGMENT +ASSUME CS:RESGROUP,DS:RESGROUP,ES:RESGROUP,SS:RESGROUP + ORG 0 +ZERO = $ +PARMBUF LABEL WORD + + ORG 100H + +RSTACK LABEL WORD + +PROGSTART: + JMP CONPROC + +LTPA DW 0 ;WILL STORE TPA SEGMENT HERE +MYSEG DW 0 ;Put our own segment here + +CONTC: + MOV AX,CS + MOV DS,AX + MOV SS,AX + MOV SP,OFFSET RESGROUP:RSTACK + STI + CALL SETVECT + MOV AH,DSKRESET + INT 33 ;Reset disks in case files were open + TEST [BATCH],-1 + JZ LODCOM +ASKEND: + MOV DX,OFFSET RESGROUP:ENDBATMES + MOV AH,PRINTBUF + INT 33 + MOV AX,0C00H+INCHAR + INT 33 + AND AL,5FH + CMP AL,"N" + JZ LODCOM + CMP AL,"Y" + JNZ ASKEND + MOV [BATCH],0 +LODCOM: + MOV AX,CS + MOV SS,AX + MOV SP,OFFSET RESGROUP:RSTACK + MOV DS,AX + CALL SETVECT + CALL CHKSUM + CMP DX,[SUM] + JZ HAVCOM + MOV [LOADING],1 + CALL LOADCOM +CHKSAME: + CALL CHKSUM + CMP DX,[SUM] + JZ HAVCOM + CALL WRONGCOM + JMP SHORT CHKSAME +HAVCOM: + MOV [LOADING],0 + MOV SI,OFFSET RESGROUP:LTPA + MOV DI,OFFSET TRANGROUP:TPA + MOV ES,[TRNSEG] + CLD + MOVSW ;Move TPA segment to transient storage + MOVSW ;Move resident segment too + MOV AX,[MEMSIZ] + MOV WORD PTR ES:[2],AX + JMP DWORD PTR [TRANS] + +RESIDENT: + ADD DX,15 + MOV CL,4 + SHR DX,CL ;Number of paragraphs of new addition + ADD CS:[LTPA],DX + XOR AX,AX + MOV DS,AX + JMP DWORD PTR DS:[80H] ;Pretend user executed INT 20H + +DSKERR: + ;****************************************************** + ; THIS IS THE DEFAULT DISK ERROR HANDLING CODE + ; AVAILABLE TO ALL USERS IF THEY DO NOT TRY TO + ; INTERCEPT INTERRUPT 24H. + ;****************************************************** + STI + PUSH DS + PUSH CS + POP DS ;Set up local data segment + PUSH DX + CALL CRLF + POP DX + ADD AL,"A" ;Compute drive letter + MOV [DRVLET],AL + TEST AH,80H ;Check if hard disk error + JNZ FATERR + MOV SI,OFFSET RESGROUP:READ + TEST AH,1 + JZ SAVMES + MOV SI,OFFSET RESGROUP:WRITE +SAVMES: + LODSW + MOV WORD PTR [IOTYP],AX + LODSW + MOV WORD PTR [IOTYP+2],AX + AND DI,0FFH + CMP DI,12 + JBE HAVCOD + MOV DI,12 +HAVCOD: + MOV DI,WORD PTR [DI+MESBAS] ;Get pointer to error message + XCHG DI,DX ;May need DX later + MOV AH,PRINTBUF + INT 33 ;Print error type + MOV DX,OFFSET RESGROUP:ERRMES + INT 33 + CMP [LOADING],0 + JNZ GETCOMDSK +ASK: + MOV DX,OFFSET RESGROUP:REQUEST + MOV AH,PRINTBUF + INT 33 + MOV AX,0C00H+INCHAR + INT 33 ;Get response + CALL CRLF + OR AL,20H ;Convert to lower case + MOV AH,0 ;Return code for ignore + CMP AL,"i" ;Ignore? + JZ EXIT + INC AH + CMP AL,"r" ;Retry? + JZ EXIT + INC AH + CMP AL,"a" ;Abort? + JNZ ASK +EXIT: + MOV AL,AH + MOV DX,DI + POP DS + IRET + +FATERR: + MOV DX,OFFSET RESGROUP:BADFAT + MOV AH,PRINTBUF + INT 33 + MOV DX,OFFSET RESGROUP:DRVNUM + INT 33 + MOV AL,2 ;Abort + POP DS + IRET + +GETCOMDSK: + MOV DX,OFFSET RESGROUP:NEEDCOM + MOV AH,PRINTBUF + INT 33 + MOV AX,0C07H ;Get char without testing or echo + INT 33 + JMP LODCOM + +CRLF: + MOV DX,OFFSET RESGROUP:NEWLIN + PUSH AX + MOV AH,PRINTBUF + INT 33 + POP AX +RET10: RET + +LOADCOM: + PUSH DS + MOV DS,[TRNSEG] + MOV DX,100H + MOV AH,SETDMA + INT 33 + POP DS + MOV DX,OFFSET RESGROUP:COMFCB + MOV AH,OPEN + INT 33 ;Open COMMAND.COM + OR AL,AL + JZ READCOM + MOV DX,OFFSET RESGROUP:NEEDCOM +PROMPTCOM: + MOV AH,PRINTBUF + INT 33 + MOV AX,0C07H ;Get char without testing or echo + INT 33 + JMP SHORT LOADCOM +READCOM: + MOV WORD PTR[COMFCB+RR],OFFSET RESGROUP:TRANSTART + XOR AX,AX + MOV WORD PTR[COMFCB+RR+2],AX + MOV [COMFCB],AL ;Use default drive + INC AX + MOV WORD PTR[COMFCB+RECLEN],AX + MOV CX,COMLEN + MOV DX,OFFSET RESGROUP:COMFCB + MOV AH,RDBLK + INT 33 + OR AL,AL + JZ RET10 +WRONGCOM: + MOV DX,OFFSET RESGROUP:COMBAD + JMP SHORT PROMPTCOM + +CHKSUM: + CLD + PUSH DS + MOV DS,[TRNSEG] + MOV SI,100H + MOV CX,COMLEN + SHR CX,1 + XOR DX,DX +CHK: + LODSW + ADD DX,AX + LOOP CHK + POP DS + RET + +SETVECT: + MOV DX,OFFSET RESGROUP:LODCOM + MOV AX,2522H ;Set Terminate address + INT 21H + MOV DX,OFFSET RESGROUP:CONTC + MOV AX,2523H ;Set Ctrl-C address + INT 21H + MOV DX,OFFSET RESGROUP:DSKERR + MOV AX,2524H ;Set Hard Disk Error address + INT 33 + MOV DX,OFFSET RESGROUP:RESIDENT + MOV AX,2527H ;Set Terminate and Stay Resident address + INT 33 + RET +RESCODESIZE EQU $-ZERO +CODERES ENDS + +;******************************************************************* +;START OF INIT PORTION +;This code is overlayed the first time the TPA is used. + +INIT SEGMENT BYTE + + ORG 0 +ZERO = $ +CONPROC: + MOV SP,OFFSET RESGROUP:RSTACK + + IF HIGHMEM + MOV AX,WORD PTR DS:[2] + SUB AX,((RESCODESIZE+RESDATASIZE)+15)/16 ;Subtract size of resident + MOV WORD PTR DS:[2],AX + MOV ES,AX + MOV SI,100H + MOV DI,SI + MOV CX,((RESCODESIZE+RESDATASIZE)-100H+1)/2 ;Length of resident in words + REP MOVSW ;Move to end of memory + MOV DS,AX + MOV [LTPA],CS + ENDIF + + IF NOT HIGHMEM + MOV AX,CS + ADD AX,((RESCODESIZE+RESDATASIZE)+15)/16 ;Compute segment of TPA + MOV [LTPA],AX + MOV AX,WORD PTR DS:[2] + ENDIF + + MOV [MYSEG],DS + MOV [MEMSIZ],AX + SUB AX,TRNLEN ;Subtract size of transient + MOV [TRNSEG],AX + CALL SETVECT + CALL LOADCOM + CALL CHKSUM + MOV [SUM],DX + + IF MSVER + IF HIGHMEM + PUSH DS + PUSH CS + POP DS + ENDIF + MOV DX,OFFSET RESGROUP:HEADER + MOV AH,PRINTBUF + INT 33 + IF HIGHMEM + POP DS + ENDIF + ENDIF + + MOV DX,OFFSET RESGROUP:BATFCB + MOV AH,OPEN + INT 33 ;See if AUTOEXEC.BAT exists + MOV WORD PTR[BATFCB+RECLEN],1 ;Set record length to 1 + OR AL,AL ;Zero means file found + JZ DRV0 + MOV [BATCH],0 ;Not found--turn off batch job + MOV AX,OFFSET TRANGROUP:DATINIT + MOV WORD PTR[INITADD],AX + MOV AX,[TRNSEG] + MOV WORD PTR[INITADD+2],AX + CALL DWORD PTR DS:[INITADD] + + IF IBMVER + MOV DX,OFFSET RESGROUP:HEADER + MOV AH,PRINTBUF + INT 33 + ENDIF + +DRV0: + JMP HAVCOM + + + IF MSVER +HEADER DB 13,10,"Command v. 1.17" + IF HIGHMEM + DB "H" + ENDIF + DB 13,10,"$" + ENDIF + + IF IBMVER +HEADER DB 13,10,13,10,"The IBM Personal Computer DOS",13,10 + DB "Version 1.10 (C)Copyright IBM Corp 1981, 1982",13,10,"$" + DB "Licensed Material - Program Property of IBM" + ENDIF + +INITSIZE EQU $-ZERO +INIT ENDS + +;This TAIL segment is used to produce a PARA aligned label in the resident +; group which is the location where the transient segments will be loaded +; initialy. + +TAIL SEGMENT PARA + ORG 0 +TRANSTART LABEL WORD +TAIL ENDS + +;******************************************************************** +;START OF TRANSIENT PORTION +;This code is loaded at the end of memory and may be overwritten by +;memory-intensive user programs. + +TRANCODE SEGMENT PARA +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:TRANGROUP + +WSWITCH EQU 1 ;Wide display during DIR +PSWITCH EQU 2 ;Pause (or Page) mode during DIR +VSWITCH EQU 4 ;Verify during COPY +ASWITCH EQU 8 ;ASCII mode during COPY +BSWITCH EQU 10H ;Binary mode during COPY + + ORG 0 +ZERO = $ + + ORG 100H ;Allow for 100H parameter area + +SETDRV: + MOV AH,SELDRV + INT 21H +COMMAND: + CLD + MOV AX,CS + MOV SS,AX + MOV SP,OFFSET TRANGROUP:STACK + MOV ES,AX + MOV DS,AX + STI + MOV AX,46*100H + MOV DL,0 + INT 33 ;Turn off verify after write + MOV AX,CS ;Get segment we're in + SUB AX,[TPA] ;AX=size ot TPA in paragraphs + MOV DX,16 + MUL DX ;DX:AX=size of TPA in bytes + OR DX,DX ;See if over 64K + JZ SAVSIZ ;OK if not + MOV AX,-1 ;If so, limit to 65535 bytes +SAVSIZ: + MOV [BYTCNT],AX ;Max no. of bytes that can be buffered + CALL CRLF2 +GETCOM: + MOV AH,GETDRV + INT 21H + MOV [CURDRV],AL + ADD AL,"A" + CALL OUT ;Print letter for default drive + MOV AL,SYM + CALL OUT + MOV DS,[RESSEG] ;All batch work must use resident seg. +ASSUME DS:RESGROUP + TEST [BATCH],-1 + JNZ READBAT + PUSH CS + POP DS ;Need local segment to point to buffer +ASSUME DS:TRANGROUP + MOV DX,OFFSET TRANGROUP:COMBUF + MOV AH,INBUF + INT 21H ;Get a command + JMP DOCOM + +;All batch proccessing has DS set to segment of resident portion +ASSUME DS:RESGROUP +NEEDPARM: + CALL GETBATBYT + CMP AL,"%" ;Check for two consecutive % + JZ SAVBATBYT + CMP AL,13 ;Check for end-of-line + JZ SAVBATBYT + SUB AL,"0" + JB RDBAT ;Ignore parameter reference if invalid + CMP AL,9 + JA RDBAT + CBW + MOV SI,AX + SHL SI,1 ;Two bytes per entry + MOV SI,[SI+OFFSET RESGROUP:PARMTAB] ;Get pointer to corresponding parameter + CMP SI,-1 ;Check if parameter exists + JZ RDBAT ;Ignore if it doesn't + MOV AH,OUTCH +RDPARM: + LODSB ;From resident segment + CMP AL,0DH ;Check for end of parameter + JZ RDBAT + STOSB ;To transient segment + MOV DL,AL + INT 33 ;Display paramters too + JMP SHORT RDPARM + +PROMPTBAT: + MOV AH,PRINTBUF + MOV DX,OFFSET RESGROUP:NEEDBAT + INT 33 ;Prompt for batch file + MOV AH,PRINTBUF + MOV DX,OFFSET RESGROUP:PROMPT + INT 33 + MOV AX,0C00H+INCHAR + INT 33 + JMP COMMAND + +BADCOMJ1:JMP BADCOM + +READBAT: + MOV DX,OFFSET RESGROUP:BATFCB + MOV AH,OPEN + INT 33 ;Make sure batch file still exists + OR AL,AL + JNZ PROMPTBAT ;If OPEN fails, prompt for disk + MOV WORD PTR [BATFCB+RECLEN],1 + MOV DX,OFFSET RESGROUP:BATBYT + MOV AH,SETDMA + INT 33 + MOV DI,OFFSET TRANGROUP:COMBUF+2 +RDBAT: + CALL GETBATBYT + CMP AL,"%" ;Check for parameter + JZ NEEDPARM +SAVBATBYT: + STOSB + CALL OUT ;Display batched command line + CMP AL,0DH + JNZ RDBAT + SUB DI,OFFSET TRANGROUP:COMBUF+3 + MOV AX,DI + MOV ES:[COMBUF+1],AL ;Set length of line + CALL GETBATBYT ;Eat linefeed + PUSH CS + POP DS ;Go back to local segment +ASSUME DS:TRANGROUP +DOCOM: +;All segments are local for command line processing + MOV AL,10 + CALL OUT + MOV SI,OFFSET TRANGROUP:COMBUF+2 + MOV DI,OFFSET TRANGROUP:IDLEN + MOV AX,2901H ;Make FCB with blank scan-off + INT 21H + CMP AL,1 ;Check for ambiguous command name + JZ BADCOMJ1 ;Ambiguous commands not allowed + CMP AL,-1 + JNZ DRVGD + JMP DRVBAD +DRVGD: + MOV AL,[DI] + MOV [SPECDRV],AL + MOV AL," " + MOV CX,9 + INC DI + REPNE SCASB ;Count no. of letters in command name + MOV AL,9 + SUB AL,CL + MOV [IDLEN],AL + MOV DI,81H + MOV CX,0 + PUSH SI +COMTAIL: + LODSB + STOSB ;Move command tail to 80H + CMP AL,13 + LOOPNZ COMTAIL + NOT CL + MOV BYTE PTR DS:[80H],CL + POP SI +;If the command has 0 parameters must check here for +;any switches that might be present. +;SI -> first character after the command. + MOV [FLAGER],0 ;Set error flag before any calls to switch + CALL SWITCH ;Is the next character a "/" + MOV [COMSW],AX + MOV DI,FCB + MOV AX,2901H + INT 21H + MOV [PARM1],AL ;Save result of parse + CALL SWITCH + MOV [ARG1S],AX + MOV DI,FCB+10H + MOV AX,2901H + INT 21H ;Parse file name + MOV [PARM2],AL ;Save result + CALL SWITCH + MOV [ARG2S],AX + MOV AL,[IDLEN] + MOV DL,[SPECDRV] + OR DL,DL ;Check if drive was specified + JZ OK + JMP DRVCHK +OK: DEC AL ;Check for null command + JNZ FNDCOM + JMP GETCOM + +RETSW: + XCHG AX,BX ;Put switches in AX + RET + +SWITCH: + XOR BX,BX ;Initialize - no switches set +SWLOOP: + CALL SCANOFF ;Skip any delimiters + CMP AL,"/" ;Is it a switch specifier? + JNZ RETSW ;No -- we're finished + INC SI ;Skip over "/" + CALL SCANOFF + INC SI +;Convert lower case input to upper case + CMP AL,"a" + JB SAVCHR + CMP AL,"z" + JA SAVCHR + SUB AL,20H ;Lower-case changed to upper-case +SAVCHR: + MOV DI,OFFSET TRANGROUP:SWLIST + MOV CX,SWCOUNT + REPNE SCASB ;Look for matching switch + JNZ BADSW + MOV AX,1 + SHL AX,CL ;Set a bit for the switch + OR BX,AX + JMP SHORT SWLOOP + +BADSW: + MOV [FLAGER],1 ;Record error in switch + JMP SHORT SWLOOP + +SWLIST DB "BAVPW" +SWCOUNT EQU $-SWLIST + +DRVBAD: + MOV DX,OFFSET TRANGROUP:BADDRV + JMP ERROR + +FNDCOM: + MOV SI,OFFSET TRANGROUP:COMTAB ;Prepare to search command table + MOV CH,0 +FINDCOM: + MOV DI,OFFSET TRANGROUP:IDLEN + MOV CL,[SI] + JCXZ EXTERNAL + REPE CMPSB + LAHF + ADD SI,CX ;Bump to next position without affecting flags + SAHF + LODSB ;Get flag for drive check + MOV [CHKDRV],AL + LODSW ;Get address of command + JNZ FINDCOM + MOV DX,AX + CMP [CHKDRV],0 + JZ NOCHECK + MOV AL,[PARM1] + OR AL,[PARM2] ;Check if either parm. had invalid drive + CMP AL,-1 + JZ DRVBAD +NOCHECK:CALL DX +COMJMP: JMP COMMAND + +BADCOMJ:JMP BADCOM + +SETDRV1: + JMP SETDRV + +DRVCHK: + DEC DL ;Adjust for correct drive number + DEC AL ;Check if anything else is on line + JZ SETDRV1 +EXTERNAL: + MOV AL,[SPECDRV] + MOV [IDLEN],AL + MOV WORD PTR[COM],4F00H+"C" ;"CO" + MOV BYTE PTR[COM+2],"M" + MOV DX,OFFSET TRANGROUP:IDLEN + MOV AH,OPEN + INT 33 ;Check if command to be executed + MOV [FILTYP],AL ;0 for COM files, -1 for EXE files + OR AL,AL + JZ EXECUTE + MOV WORD PTR[COM],5800H+"E" ;"EX" + MOV BYTE PTR[COM+2],"E" + INT 33 ;Check for EXE file + OR AL,AL + JZ EXECUTE + MOV WORD PTR[COM],4100H+"B" ;"BA" + MOV BYTE PTR[COM+2],"T" + INT 33 ;Check if batch file to be executed + OR AL,AL + JNZ BADCOMJ +BATCOM: +;Batch parameters are read with ES set to segment of resident part + MOV ES,[RESSEG] +ASSUME ES:RESGROUP + MOV DI,OFFSET RESGROUP:PARMTAB + MOV AX,-1 + MOV CX,10 + REP STOSW ;Zero parameter pointer table + MOV SI,OFFSET TRANGROUP:COMBUF+2 + MOV DI,OFFSET RESGROUP:PARMBUF + MOV BX,OFFSET RESGROUP:PARMTAB +EACHPARM: + CALL SCANOFF + CMP AL,0DH + JZ HAVPARM + MOV ES:[BX],DI ;Set pointer table to point to actual parameter + INC BX + INC BX +MOVPARM: + LODSB + CALL DELIM + JZ ENDPARM ;Check for end of parameter + STOSB + CMP AL,0DH + JZ HAVPARM + JMP SHORT MOVPARM +ENDPARM: + MOV AL,0DH + STOSB ;End-of-parameter marker + CMP BX,OFFSET RESGROUP:PARMTAB+20 ;Maximum number of parameters? + JB EACHPARM +HAVPARM: + MOV SI,OFFSET TRANGROUP:IDLEN + MOV DI,OFFSET RESGROUP:BATFCB + MOV CX,16 + REP MOVSW ;Move into private batch FCB + XOR AX,AX + PUSH ES + POP DS ;Simply batch FCB setup +ASSUME DS:RESGROUP + MOV WORD PTR[BATFCB+RR],AX + MOV WORD PTR[BATFCB+RR+2],AX ;Zero RR field + INC AX + MOV WORD PTR[BATFCB+RECLEN],AX ;Set record length to 1 byte + MOV [BATCH],AL ;Flag batch job in progress + JMP COMMAND +ASSUME DS:TRANGROUP,ES:TRANGROUP + +EXECUTE: + MOV AX,WORD PTR[IDLEN+16] + OR AX,WORD PTR[IDLEN+18] ;See if zero length + JZ BADCOM ;If so, error + XOR AX,AX + MOV WORD PTR[IDLEN+RR],AX + MOV WORD PTR[IDLEN+RR+2],AX ;Set RR field to zero + INC AX + MOV WORD PTR[IDLEN+RECLEN],AX ;Set record length field to 1 + MOV DX,[TPA] + MOV BX,DX + MOV AH,SETBASE + INT 21H + TEST [FILTYP],-1 ;Check if file is COM or EXE + JZ COMLOAD + JMP EXELOAD +COMLOAD:PUSH DS + MOV DS,DX + MOV DX,100H + MOV AH,SETDMA + INT 21H + POP DS + MOV CX,[BYTCNT] + SUB CX,100H + MOV DX,OFFSET TRANGROUP:IDLEN + MOV AH,RDBLK + INT 21H + DEC AL + MOV DX,OFFSET TRANGROUP:TOOBIG + JNZ ERROR +;Set up exit conditions + MOV CX,[BYTCNT] + MOV DS,BX + MOV ES,BX + CLI + MOV SS,BX + MOV SP,CX + STI + SUB CX,100H ;Allow some stack space + XOR AX,AX + PUSH AX + MOV AX,100H + PUSH BX + PUSH AX + CALL SETUP +XXX PROC FAR + RET +XXX ENDP +BADCOM: + MOV DX,OFFSET TRANGROUP:BADNAM +ERROR: + MOV AH,PRINTBUF + INT 21H + JMP COMMAND + +CHKCNT: + TEST [FILECNT],-1 + JNZ ENDDIR + MOV DX,OFFSET TRANGROUP:NOTFND + JMP ERROR + +ENDDIR: +;Make sure last line ends with CR/LF + MOV AL,[LINLEN] + CMP AL,[LINCNT] ;Will be equal if just had CR/LF + JZ MESSAGE + CALL CRLF2 +MESSAGE: + MOV SI,[FILECNT] + XOR DI,DI + CALL DISP32BITS + MOV DX,OFFSET TRANGROUP:DIRMES + MOV AH,PRINTBUF + INT 21H + RET + +CATALOG: + MOV AL,"?" ;*.* is default file spec. + MOV DI,5DH + MOV CX,11 + REP STOSB + MOV SI,81H + CALL SWITCH + MOV DI,5CH + MOV AX,41*100H+0DH ;Parse with default name and extension + INT 33 + +;Begin by processing any switches that may have been specified. +;BITS will contain any information about switches that was +;found when the command line was parsed. + +SETSWT: + MOV AX,[COMSW] ;Get switches from command + OR AX,[ARG1S] ;OR in switches from first parameter + MOV [BITS],AX + MOV BYTE PTR[FULLSCR],LINPERPAG + TEST AL,1 ;Look for /W + MOV AL,NORMPERLIN + JZ DIR + MOV AL,WIDEPERLIN +DIR: + MOV [LINLEN],AL ;Set number of entries per line + MOV [LINCNT],AL + MOV [FILECNT],0 ;Keep track of how many files found + MOV DX,OFFSET TRANGROUP:DIRBUF ;Set Disk transfer address + MOV AH,SETDMA + INT 21H + MOV AH,SRCHFRST +SHOWDIR: + MOV DX,5CH ;DX -> Unopened FCB + INT 21H ;Search for a file to match FCB + INC AL ;FF = file not found + JNZ AGAIN ;Either an error or we are finished + JMP CHKCNT +AGAIN: + INC [FILECNT] ;Keep track of how many we find + MOV SI,OFFSET TRANGROUP:DIRBUF+1 ;SI -> information returned by sys call + CALL SHONAME + TEST BYTE PTR[BITS],1 ;/W set? + JNZ NEXENT ;If so, no size, date, or time + CALL DISPSIZE ;Print size of file + CALL TWOSPC + MOV AX,WORD PTR[DIRBUF+25] ;Get date + OR AX,AX + JZ NEXENT ;Skip if no date + MOV DX,AX + MOV CL,5 + SHR AX,CL ;Align month + AND AL,0FH + MOV BH,"0"-" " ;Enable zero suppression + CALL OUT2 + MOV AL,"-" + CALL OUT + MOV AL,DL + AND AL,1FH ;Mask to day + CALL OUT2 + MOV AL,"-" + CALL OUT + MOV AL,DH + SHR AL,1 ;Align year + ADD AX,80 ;Relative 1980 + CMP AL,100 + JB MILLENIUM + SUB AL,100 +MILLENIUM: + CALL OUT2 + MOV BX,WORD PTR[DIRBUF+23] ;Get time + OR BX,BX ;Time field present? + JZ NEXENT + CALL TWOSPC + SHR BX,1 + SHR BX,1 + SHR BX,1 + SHR BL,1 + SHR BL,1 ;Hours in BH, minutes in BL + MOV AL,BH + MOV DH,"a" ;Assume A.M. + CMP AL,12 ;In the afternoon? + JB MORN + MOV DH,"p" + JE MORN + SUB AL,12 ;Keep it to 12 hours or less +MORN: + OR AL,AL ;Before 1 am? + JNZ SHOHOURS + MOV AL,12 +SHOHOURS: + MOV BH,"0"-" " ;Enable zero suppression + CALL OUT2 + MOV AL,":" + CALL OUT + MOV AL,BL ;Output minutes + CALL OUT2 + MOV AL,DH ;Get "a" or "p" + CALL OUT +NEXENT: + DEC [LINCNT] + JNZ SAMLIN +NEXLIN: + MOV AL,[LINLEN] + MOV [LINCNT],AL + CALL CRLF2 + TEST BYTE PTR[BITS],2 ;/P switch present? + JZ SCROLL ;If not, just continue + DEC BYTE PTR[FULLSCR] + JNZ SCROLL + MOV BYTE PTR[FULLSCR],LINPERPAG + MOV AH,PRINTBUF + MOV DX,OFFSET TRANGROUP:PAUSMES + INT 33 + MOV AX,0C08H ;Wait for any character to be typed + INT 21H + CALL CRLF2 +SCROLL: + MOV AH,SRCHNXT + JMP SHOWDIR + +SAMLIN: + MOV AL,9 ;Output a tab + CALL OUT + JMP SHORT SCROLL + +SHONAME: + MOV CX,8 + CALL OUTCNT + CALL ONESPC + MOV CX,3 +OUTCNT: + LODSB + CALL OUT + LOOP OUTCNT + RET + +TWOSPC: + CALL ONESPC +ONESPC: + MOV AL," " + JMP OUT + +CRLF2: + MOV AL,13 + CALL OUT + MOV AL,10 + JMP OUT + +DISPSIZE: + MOV SI,WORD PTR[DIRBUF+29] + MOV DI,WORD PTR[DIRBUF+31] +DISP32BITS: +;Prints the 32-bit number DI:SI on the console in decimal. Uses a total +;of 9 digit positions with leading blanks. + XOR AX,AX + MOV BX,AX + MOV BP,AX + MOV CX,32 +CONVLP: + SHL SI,1 + RCL DI,1 + XCHG AX,BP + CALL CONVWRD + XCHG AX,BP + XCHG AX,BX + CALL CONVWRD + XCHG AX,BX + ADC AL,0 + LOOP CONVLP +; Conversion complete. Print 9-digit number. + MOV CX,1810H ;Allow leading zero blanking for 8 digits + XCHG DX,AX + CALL DIGIT + XCHG AX,BX + CALL OUTWORD + XCHG AX,BP +OUTWORD: + PUSH AX + MOV DL,AH + CALL OUTBYTE + POP DX +OUTBYTE: + MOV DH,DL + SHR DL,1 + SHR DL,1 + SHR DL,1 + SHR DL,1 + CALL DIGIT + MOV DL,DH +DIGIT: + AND DL,0FH + JZ BLANKZER + MOV CL,0 +BLANKZER: + DEC CH + AND CL,CH + OR DL,30H + SUB DL,CL + MOV AH,OUTCH + INT 21H + RET + +CONVWRD: + ADC AL,AL + DAA + XCHG AL,AH + ADC AL,AL + DAA + XCHG AL,AH +RET20: RET + +ERASE: + MOV CX,11 + MOV SI,FCB+1 +AMBSPEC: + LODSB + CMP AL,"?" + JNZ ALLFIL + LOOP AMBSPEC +ALLFIL: + CMP CX,0 + JNZ NOPRMPT +ASKAGN: + MOV DX,OFFSET TRANGROUP:SUREMES ;"Are you sure (Y/N)?" + MOV AH,PRINTBUF + INT 21H + MOV AX,0C00H+INCHAR + INT 21H + AND AL,5FH + CMP AL,"N" + JZ RET20 + CMP AL,"Y" + CALL CRLF2 + JZ NOPRMPT + JMP SHORT ASKAGN +NOPRMPT: + MOV AH,DELETE + MOV BX,OFFSET TRANGROUP:NOTFND + CMP BYTE PTR DS:[FCB+1]," " ;Check if parameter exists + JMP SHORT OPFILE +RENAME: + MOV AH,RENAM + MOV BX,OFFSET TRANGROUP:RENERR + CMP BYTE PTR DS:[FCB+16+1]," " ;Check if parameter exists +OPFILE: + MOV DX,OFFSET TRANGROUP:MISNAM + JZ ERRJ ;Error if missing parameter + MOV DX,FCB + INT 21H + INC AL + JNZ RET20 + MOV DX,BX +ERRJ: JMP ERROR + +TYPEFIL: + MOV DS,[TPA] + XOR DX,DX + MOV AH,SETDMA + INT 21H + PUSH CS + POP DS + MOV DX,FCB + MOV AH,OPEN + INT 21H + OR AL,AL + MOV DX,OFFSET TRANGROUP:NOTFND + JNZ ERRJ + XOR AX,AX + MOV WORD PTR DS:[FCB+RR],AX ;Set RR field + MOV WORD PTR DS:[FCB+RR+2],AX + INC AX + MOV WORD PTR DS:[FCB+RECLEN],AX ;Set record length + MOV ES,[TPA] +TYPELP: + MOV DX,FCB + MOV CX,[BYTCNT] + MOV AH,RDBLK + INT 21H + JCXZ RET30 + XOR SI,SI ;Start at 0 in TPA +OUTLP: + LODS BYTE PTR ES:[SI] ;In TPA segment + CMP AL,1AH + JZ RET30 + MOV AH,OUTCH + MOV DL,AL + INT 21H + LOOP OUTLP + JMP SHORT TYPELP + +RET30: RET ;Need a nearby RET + +COPY: + XOR AX,AX + MOV [PLUS],AL ;Will keep track of "+"s + MOV [FILECNT],AX + MOV SI,81H ;Point to input line + CALL SWITCH ;Skip over switches on command + MOV BP,AX + MOV DI,FCB + CALL PARSNAM ;Scan first source + MOV [PARM1],DL ;Save ambiguous flag + MOV [SRCPT],SI ;Save pointer to command line +;Parse each name to find destination and check for /V switch +SCANNAM: + CALL PARSE + JNZ SCANNAM +GETDEST: + MOV DI,OFFSET TRANGROUP:DEST + MOV BX,BP ;Remeber switches so far + XOR BP,BP ;Must have dest. swtiches alone + CALL PARSNAM + MOV [ARG2S],BP ;Remember switches on destination + JNZ HAVDESTNAM ;File name present? + INC DI ;Point to file name spot + MOV AL,"?" ;Substitute *.* + MOV CX,11 + REP STOSB +HAVDESTNAM: + OR BX,BP ;BX = all switches combined + AND BL,VSWITCH ;Verify requested? + JZ NOVER + MOV AX,46*100H+1 ;Set verify + MOV DL,0 + INT 33 +NOVER: + MOV DI,OFFSET TRANGROUP:DESTNAME + MOV SI,OFFSET TRANGROUP:DEST+1 + MOV BX,FCB+1 + CALL BUILDNAME ;See if we can make it unambiguous + MOV DI,OFFSET TRANGROUP:DESTNAME + MOV AL,"?" + MOV CX,11 + REPNE SCASB ;Scan for "?" to see if ambiguous + MOV AL,1 ;Flag if ambig. + JZ AMBIG + DEC AX ;AL=0 if unambig. +AMBIG: + MOV DL,AL + MOV AH,[PLUS] ;1=found "+" + XOR AL,1 ;0=ambig, 1=unambig destination + AND AL,[PARM1] ;Source ambig. AND dest unambig. + OR AL,AH ;OR found "+" means concatenation + MOV [ASCII],AL ;Concatenation implies ASCII mode + MOV [INEXACT],AL ;ASCII implies inexact copy + SHL AL,1 + OR AL,DL ;Combine multiple and concat flags + MOV [PARM2],AL + MOV AL,BYTE PTR[COMSW] + CALL SETASC ;Check /A,/B on command + MOV AL,BYTE PTR[ARG1S] + CALL SETASC ;Check for ASCII on first filename + MOV BYTE PTR[COMSW],AL ;Save starting switch values + MOV AH,SRCHFRST + CALL SEARCH ;Search for first source name +MULTDEST: + JZ FIRSTSRC ;Find a first source name? + TEST [PARM2],1 ;If multiple, we're done + JNZ ENDCOPY + XOR AX,AX + MOV [NXTADD],AX + MOV [CFLAG],AL ;Flag nothing read yet +NEXTSNG: + MOV DI,FCB + MOV SI,[SRCPT] + CALL PARSESRC ;Parse next file name into FCB + MOV [PARM1],DL ;Remember if it's ambiguous + MOV [SRCPT],SI + JZ SNGCLOS + MOV AH,SRCHFRST + CALL SEARCH ;Search for new file name + JNZ NEXTSNG ;If none, skip it and move to next name +READSNG: + CALL CHECKREAD +SNGLOOP: + CALL SEARCHNEXT ;See if any more of this name + JZ READSNG + JMP SHORT NEXTSNG + +SNGCLOS: + CALL CLOSEFIL +ENDCOPY: + MOV SI,[FILECNT] + XOR DI,DI + CALL DISP32BITS + MOV DX,OFFSET TRANGROUP:COPIED + MOV AH,PRINTBUF + INT 21H + JMP COMMAND ;Stack could be messed up + +FIRSTSRC: + MOV SI,OFFSET TRANGROUP:DIRBUF+1 + MOV DI,OFFSET TRANGROUP:SOURCE + MOV CX,11 + REP MOVSB ;Copy first source name to SOURCE + MOV SI,OFFSET TRANGROUP:DESTNAME + MOV DI,OFFSET TRANGROUP:DEST+1 + MOV BX,OFFSET TRANGROUP:SOURCE + CALL BUILDNAME ;Build destination name + XOR AX,AX + MOV [NXTADD],AX + MOV [CFLAG],AL + MOV [APPEND],AL + MOV [NOWRITE],AL + TEST [PARM2],1 ;Multiple destinations? + JZ NOPRT + MOV SI,OFFSET TRANGROUP:DIRBUF+1 + CALL SHONAME ;If so, show first source + CALL CRLF2 +NOPRT: + CALL COMPNAME ;Source and dest. the same? + JNZ DOREAD ;If not, read source in + TEST [PARM2],2 ;Concatenation? + MOV DX,OFFSET TRANGROUP:OVERWR + JZ COPERRJ ;If not, overwrite error + MOV [APPEND],1 ;Set physical append + MOV AH,OPEN + MOV DX,OFFSET TRANGROUP:DEST + INT 33 ;Open (existing) destination + CMP [ASCII],0 ;ASCII flag set? + JZ BINARYAPP +;ASCII append. Must find logical EOF, then seek there with dest. FCB + MOV [NOWRITE],1 + CALL READIN ;Find EOF + CALL FLSHFIL ;Seek there + MOV [NOWRITE],0 + CALL FLSHFIL ;Truncate file + JMP SHORT SNGLCHK + +SNGLOOPJ:JMP SNGLOOP + +COPERRJ:JMP COPERR + +BINARYAPP: + MOV WORD PTR[DEST+RECLEN],1 ;Set record length to 1 + MOV SI,OFFSET TRANGROUP:DEST+16 ;Point to file size + MOV DI,OFFSET TRANGROUP:DEST+RR + MOVSW + MOVSW ;Seek to end of file + MOV [CFLAG],1 + JMP SHORT SNGLCHK +DOREAD: + CALL READIN +SNGLCHK: + TEST [PARM2],1 ;Single or multiple destinations? + JZ SNGLOOPJ + MOV SI,[SRCPT] +MULTAPP: + CALL PARSE + JZ MULTCLOS + PUSH SI + MOV SI,OFFSET TRANGROUP:DIRBUF+1 + MOV DI,SI + MOV BX,OFFSET TRANGROUP:SOURCE + CALL BUILDNAME + CALL CHECKREAD + POP SI + JMP SHORT MULTAPP +MULTCLOS: + CALL CLOSEFIL + MOV AL,BYTE PTR[COMSW] + MOV [ASCII],AL ;Restore ASCII flag + CALL SEARCHNEXT + JMP MULTDEST + +PARSE: + MOV DI,OFFSET TRANGROUP:DIRBUF +PARSESRC: + CALL SCANOFF + CMP AL,"+" + JNZ RETZF + MOV [PLUS],1 ;Keep track of "+" signs + INC SI ;Skip over it +PARSNAM: + MOV AX,2901H + INT 33 ;Parse file name + CMP AL,-1 ;Illegal? + MOV DX,OFFSET TRANGROUP:BADDRV + JZ COPERRJ + XCHG AX,DX ;Save parse flag in DL + MOV AL,BYTE PTR[DI] ;Get drive number + OR AL,AL ;Is it default? + JNZ PARSW + MOV AL,[CURDRV] ;Substitute actual drive + INC AX + MOV BYTE PTR[DI],AL +PARSW: + PUSH BX + PUSH DI + CALL SWITCH ;Process switches + OR BP,AX ;Combine all switches + CALL SETASC ;Check for /A or /B + POP DI + POP BX + CMP BYTE PTR[DI+1]," " ;Did we even get a file name? + RET + +RETZF: + XOR AX,AX +RET35: RET + +SEARCHNEXT: + MOV AL,[PARM1] ;Is name ambiguous? + DEC AL + JNZ RET35 ;Don't perform search if not + MOV AH,SRCHNXT +SEARCH: + PUSH AX + MOV AH,SETDMA + MOV DX,OFFSET TRANGROUP:DIRBUF + INT 33 ;Put result of search in DIRBUF + POP AX ;Restore search first/next command + MOV DX,FCB + INT 33 ;Do the search + OR AL,AL + RET + +SETASC: +;Given switch vector in AX, +; Set ASCII switch if /A is set +; Clear ASCII switch if /B is set +; Leave ASCII unchanged if neither or both are set +; Also sets INEXACT if ASCII is ever set. AL = ASCII on exit, flags set + AND AL,ASWITCH+BSWITCH + JPE LOADSW ;PE means both or neither are set + AND AL,ASWITCH + MOV [ASCII],AL + OR [INEXACT],AL +LOADSW: + MOV AL,[ASCII] + OR AL,AL + RET + +BUILDNAME: +; [SI] = Ambiguous input file name +; [BX] = Source of replacement characters +; [DI] = Destination +; File name is copied from [SI] to [DI]. If "?"s are encountered, +; they are replaced with the character in the same position at [BX]. + MOV CX,11 +BUILDNAM: + LODSB + CMP AL,"?" + JNZ NOTAMBIG + MOV AL,BYTE PTR[BX] +NOTAMBIG: + STOSB + INC BX + LOOP BUILDNAM + RET + +COMPNAME: + MOV SI,OFFSET TRANGROUP:DEST + MOV DI,OFFSET TRANGROUP:DIRBUF + MOV CX,6 + REPE CMPSW + RET + +CHECKREAD: +;Read file in (with READIN) if not identical to destination + CALL COMPNAME ;See if source and destination the same + JNZ READIN + CMP [APPEND],0 ;If physical append, it's OK + JNZ RET40 + MOV DX,OFFSET TRANGROUP:LOSTERR ;Tell him he's not going to get it + MOV AH,PRINTBUF + INT 33 +RET40: RET + +READIN: +;Open source file and read it in. If memory fills up, flush it out to +;destination and keep reading. If /A switch set, chop file at first ^Z. +; Inputs/Outputs: +; [NXTADD] has current pointer in buffer +; [CFLAG] <>0 if destination has been created + + MOV DX,OFFSET TRANGROUP:DIRBUF + MOV AH,OPEN + INT 21H + OR AL,AL ;Successful open? + JNZ RET40 ;If not, just ignore it + XOR AX,AX + MOV WORD PTR[DIRBUF+RR],AX + MOV WORD PTR[DIRBUF+RR+2],AX + INC AX + MOV WORD PTR[DIRBUF+RECLEN],AX +COPYLP: + MOV DX,[NXTADD] + MOV AH,SETDMA + PUSH DS + MOV DS,[TPA] + INT 33 + POP DS + MOV CX,[BYTCNT] + SUB CX,DX ;Compute available space + MOV DX,OFFSET TRANGROUP:DIRBUF + MOV AH,RDBLK ;Read in source file + INT 21H + JCXZ RET40 + CMP [ASCII],0 + JZ BINREAD + MOV DX,CX + MOV DI,[NXTADD] + MOV AL,1AH + PUSH ES + MOV ES,[TPA] + REPNE SCASB ;Scan for EOF + POP ES + JNZ USEALL + INC CX +USEALL: + SUB DX,CX + MOV CX,DX +BINREAD: + ADD CX,[NXTADD] + MOV [NXTADD],CX + CMP CX,[BYTCNT] ;Is buffer full? + JB RET40 ;If not, we must have found EOF + CALL FLSHFIL + JMP SHORT COPYLP + +CLOSEFIL: + MOV AX,[NXTADD] + MOV BX,AX + OR AL,AH ;See if any data is loaded + OR AL,[CFLAG] ; or file was created + JZ RET50 ;Don't close or count if not created + MOV AL,BYTE PTR[ARG2S] + CALL SETASC ;Check for /B or /A on destination + JZ BINCLOS + CMP BX,[BYTCNT] ;Is memory full? + JNZ PUTZ + CALL FLSHFIL ;Empty it to make room for 1 lousy byte + XOR BX,BX +PUTZ: + PUSH DS + MOV DS,[TPA] + MOV WORD PTR[BX],1AH ;Add End-of-file mark (Ctrl-Z) + POP DS + INC [NXTADD] +BINCLOS: + CALL FLSHFIL + CMP [INEXACT],0 ;Copy not exact? + JNZ NODATE ;If so, don't copy date & time + MOV SI,OFFSET TRANGROUP:DIRBUF+OFFDATE + MOV DI,OFFSET TRANGROUP:DEST+OFFDATE ;Make date & time same as original + MOVSW ;Copy date + MOVSW ;Copy time +NODATE: + MOV DX,OFFSET TRANGROUP:DEST + MOV AH,CLOSE + INT 21H + INC [FILECNT] +RET50: RET + +FLSHFIL: +;Write out any data remaining in memory. +; Inputs: +; [NXTADD] = No. of bytes to write +; [CFLAG] <>0 if file has been created +; Outputs: +; [NXTADD] = 0 + + MOV AL,1 + XCHG [CFLAG],AL + OR AL,AL + JNZ EXISTS + CMP [NOWRITE],0 + JNZ SKPMAK ;Don't actually create if NOWRITE set + MOV DX,OFFSET TRANGROUP:DEST + MOV AH,MAKE + INT 21H + MOV DX,OFFSET TRANGROUP:FULDIR + OR AL,AL + JNZ COPERR +SKPMAK: + XOR AX,AX + MOV WORD PTR[DEST+RR],AX + MOV WORD PTR[DEST+RR+2],AX + INC AX + MOV WORD PTR[DEST+RECLEN],AX +EXISTS: + XOR CX,CX + XCHG CX,[NXTADD] + CMP [NOWRITE],0 ;If NOWRITE set, just seek CX bytes + JNZ SEEKEND + XOR DX,DX + PUSH DS + MOV DS,[TPA] + MOV AH,SETDMA + INT 33 + POP DS + MOV DX,OFFSET TRANGROUP:DEST + MOV AH,WRBLK + INT 21H + OR AL,AL + JZ RET60 + MOV DX,OFFSET TRANGROUP:DEST + MOV AH,CLOSE + INT 21H + MOV AH,DELETE + INT 33 + MOV DX,OFFSET TRANGROUP:NOSPACE +COPERR: + MOV AH,9 + INT 21H + JMP ENDCOPY + +SEEKEND: + ADD WORD PTR[DEST+RR],CX + ADC WORD PTR[DEST+RR+2],0 ;Propagate carry +RET60: RET + +GETBATBYT: +;Get one byte from the batch file and return it in AL. End-of-file +;returns and ends batch mode. DS must be set to resident segment. +;AH, CX, DX destroyed. +ASSUME DS:RESGROUP + MOV DX,OFFSET RESGROUP:BATFCB + MOV AH,RDBLK + MOV CX,1 + INT 33 ;Get one more byte from batch file + JCXZ BATEOF + MOV AL,[BATBYT] + CMP AL,1AH + JNZ RET70 +BATEOF: + MOV AL,0DH ;If end-of-file, then end of line + MOV [BATCH],0 ;And turn off batch mode +RET70: RET +ASSUME DS:TRANGROUP + +SCANOFF: + LODSB + CALL DELIM + JZ SCANOFF + DEC SI ;Point to first non-delimiter + RET + +DELIM: + CMP AL," " + JZ RET80 + CMP AL,"=" + JZ RET80 + CMP AL,"," + JZ RET80 + CMP AL,9 ;Check for TAB character +RET80: RET + +PAUSE: + MOV DX,OFFSET TRANGROUP:PAUSMES + MOV AH,PRINTBUF + INT 33 + MOV AX,0C00H+INCHAR ;Get character with KB buffer flush + INT 33 +RET90: RET + +;Date and time are set during initialization and use +;this routines since they need to do a long return + +DATINIT: + PUSH ES + PUSH DS ;Going to use the previous stack + MOV AX,CS ;Set up the appropriate segment registers + MOV ES,AX + MOV DS,AX + MOV WORD PTR DS:[81H],13 ;Want to prompt for date during initialization + CALL DATE + CALL TIME + POP DS + POP ES +YYY PROC FAR + RET +YYY ENDP + +; DATE - Gets and sets the time + +DATE: + MOV SI,81H ;Accepting argument for date inline + CALL SCANOFF + CMP AL,13 + JZ PRMTDAT + MOV BX,2F00H+"-" ;"/-" + CALL INLINE + JMP COMDAT + +PRMTDAT: + MOV DX,OFFSET TRANGROUP:CURDAT + MOV AH,PRINTBUF + INT 33 ;Print "Current date is " + MOV AH,GETDATE + INT 33 ;Get date in CX:DX + CBW + MOV SI,AX + SHL SI,1 + ADD SI,AX ;SI=AX*3 + ADD SI,OFFSET TRANGROUP:WEEKTAB + MOV BX,CX + MOV CX,3 + CALL OUTCNT + MOV AL," " + CALL OUT + MOV AX,BX + MOV CX,DX + MOV DL,100 + DIV DL + XCHG AL,AH + XCHG AX,DX + MOV BL,"-" + CALL SHOW +GETDAT: + MOV DX,OFFSET TRANGROUP:NEWDAT + MOV BX,2F00H+"-" ;"/-" in BX + CALL GETBUF +COMDAT: JZ RET90 + JC DATERR + LODSB + CMP AL,BL + JZ SEPGD + CMP AL,BH + JNZ DATERR +SEPGD: CALL GETNUM + JC DATERR + MOV CX,1900 + CMP BYTE PTR[SI],13 + JZ BIAS + MOV AL,100 + MUL AH + MOV CX,AX + CALL GETNUM + JC DATERR +BIAS: + MOV AL,AH + MOV AH,0 + ADD CX,AX + LODSB + CMP AL,13 + JNZ DATERR + MOV AH,SETDATE + INT 33 + OR AL,AL + JNZ DATERR + JMP RET90 +DATERR: + MOV DX,OFFSET TRANGROUP:BADDAT + MOV AH,PRINTBUF + INT 33 + JMP GETDAT + +; TIME gets and sets the time + +TIME: + MOV SI,81H ;Accepting argument for time inline + CALL SCANOFF + CMP AL,13 + JZ PRMTTIM + MOV BX,3A00H+":" + CALL INLINE + JMP COMTIM + +PRMTTIM: + MOV DX,OFFSET TRANGROUP:CURTIM + MOV AH,PRINTBUF + INT 33 ;Print "Current time is " + MOV AH,GETTIME + INT 33 ;Get time in CX:DX + MOV BL,":" + CALL SHOW +GETTIM: + XOR CX,CX ;Initialize hours and minutes to zero + MOV DX,OFFSET TRANGROUP:NEWTIM + MOV BX,3A00H+":" + CALL GETBUF +COMTIM: JZ RET100 ;If no time present, don't change it + JC TIMERR + MOV CX,DX + XOR DX,DX + LODSB + CMP AL,13 + JZ SAVTIM + CMP AL,BL + JNZ TIMERR + MOV BL,"." + CALL GETNUM + JC TIMERR + MOV DH,AH ;Position seconds + LODSB + CMP AL,13 + JZ SAVTIM + CMP AL,BL + JNZ TIMERR + CALL GETNUM + JC TIMERR + MOV DL,AH + LODSB + CMP AL,13 + JNZ TIMERR +SAVTIM: + MOV AH,SETTIME + INT 33 + OR AL,AL + JZ RET100 ;Error in time? +TIMERR: + MOV DX,OFFSET TRANGROUP:BADTIM + MOV AH,PRINTBUF + INT 33 ;Print error message + JMP GETTIM ;Try again + +GETBUF: + MOV AH,PRINTBUF + INT 33 ;Print "Enter new date: " + MOV AH,INBUF + MOV DX,OFFSET TRANGROUP:COMBUF + INT 33 ;Get input line + CALL CRLF2 + MOV SI,OFFSET TRANGROUP:COMBUF+2 + CMP BYTE PTR[SI],13 ;Check if new date entered + JZ RET100 +INLINE: + CALL GETNUM ;Get one or two digit number + JC RET100 + MOV DH,AH ;Put in position + LODSB + CMP AL,BL + JZ NEXT + CMP BL,":" ;Is it a date seperator? + JNZ DATESEP + DEC SI + MOV DL,0 +RET100: RET ;Time may have only an hour specified +DATESEP: + CMP AL,BH + STC + JNZ RET100 +NEXT: CALL GETNUM + MOV DL,AH ;Put in position + RET + +GETNUM: + CALL INDIG + JC RET100 + MOV AH,AL ;Save first digit + CALL INDIG ;Another digit? + JC OKRET + AAD ;Convert unpacked BCD to decimal + MOV AH,AL +OKRET: + OR AL,1 +RET110: RET + +INDIG: + MOV AL,BYTE PTR[SI] + SUB AL,"0" + JC RET110 + CMP AL,10 + CMC + JC RET110 + INC SI + RET + +SHOW: + MOV AL,CH + MOV BH,"0"-" " ;Enable leading zero suppression + CALL OUT2 + MOV AL,BL + CALL OUT + MOV AL,CL + CALL OUT2 + MOV AL,BL + CALL OUT + MOV AL,DH + CALL OUT2 + CMP BL,":" ;Are we outputting time? + JNZ SKIPIT + MOV AL,"." + CALL OUT +SKIPIT: MOV AL,DL +OUT2: ;Output binary number as two ASCII digits + AAM ;Convert binary to unpacked BCD + XCHG AL,AH + OR AX,3030H ;Add "0" bias to both digits + CMP AL,"0" ;Is MSD zero? + JNZ NOSUP + SUB AL,BH ;Suppress leading zero if enabled +NOSUP: + MOV BH,0 ;Disable zero suppression + CALL OUT + MOV AL,AH +OUT: +;Print char in AL without affecting registers + XCHG AX,DX + PUSH AX + MOV AH,OUTCH + INT 33 + POP AX + XCHG AX,DX + RET + +EXELOAD: + MOV AX,CS + ADD AX,LOADSEG + MOV [EXEEND],AX ;Store in EXEEND + MOV DX,OFFSET TRANGROUP:RUNVAR ;Read header in here + MOV AH,SETDMA + INT 33 + MOV CX,RUNVARSIZ ;Amount of header info we need + MOV DX,OFFSET TRANGROUP:EXEFCB + MOV AH,RDBLK + INT 33 ;Read in header + OR AL,AL + JNZ BADEXE ;Must not reach EOF + MOV AX,[HEADSIZ] ;Size of header in paragraphs +;Convert header size to 512-byte pages by multiplying by 32 & rounding up + ADD AX,31 ;Round up first + MOV CL,5 + SHR AX,CL ;Multiply by 32 + MOV [EXEFCB+RR],AX ;Position in file of program + MOV WORD PTR[EXEFCB+RECLEN],512 ;Set record size + ADD BX,10H ;First paragraph above parameter area + MOV DX,[PAGES] ;Total size of file in 512-byte pages + SUB DX,AX ;Size of program in pages + MOV [PSIZE],DX + SHL DX,CL ;Convert pages back to paragraphs + MOV AX,DX + ADD DX,BX ;Size + start = minimum memory (paragr.) + MOV CX,[EXEEND] ;Get memory size in paragraphs + CMP DX,CX ;Enough memory? + JA SHRTERR + MOV DX,[INITSP] + ADD DX,15 + SHR DX,1 + SHR DX,1 + SHR DX,1 + SHR DX,1 + ADD DX,[INITSS] + ADD DX,BX ;Adjusted value of SP + CMP DX,CX ;Is it valid? + JA SHRTERR + CMP [LOADLOW],-1 ;Load low or high? + JZ LOAD ;If low, load at segment BX + SUB CX,AX ;Memory size - program size = load addr. + MOV BX,CX +LOAD: + MOV BP,BX ;Save load segment +LOAD1: +LOADSEG EQU (LOAD1-ZERO)/16 + PUSH DS + MOV DS,BX + XOR DX,DX ;Address 0 in segment + MOV AH,SETDMA + INT 33 ;Set load address + POP DS + MOV CX,[PSIZE] ;Number of records to read + MOV DX,OFFSET TRANGROUP:EXEFCB + MOV AH,RDBLK + INT 33 ;Read in up to 64K + SUB [PSIZE],CX ;Decrement count by amount read + JZ HAVEXE ;Did we get it all? + TEST AL,1 ;Check return code if not + JNZ BADEXE ;Must be zero if more to come + ADD BX,1000H-20H ;Bump data segment 64K minus one record + JMP SHORT LOAD1 ;Get next 64K block + +BADEXE: + MOV DX,OFFSET TRANGROUP:EXEBAD + JMP ERROR + +SHRTERR: + MOV DX,OFFSET TRANGROUP:TOOBIG + JMP ERROR + +HAVEXE: + MOV AX,[RELTAB] ;Get position of table + MOV [EXEFCB+RR],AX ;Set in random record field + MOV WORD PTR[EXEFCB+RECLEN],1 ;Set one-byte record + MOV DX,OFFSET TRANGROUP:RELPT ;4-byte buffer for relocation address + MOV AH,SETDMA + INT 33 + CMP [RELCNT],0 + JZ NOREL +RELOC: + MOV AH,RDBLK + MOV DX,OFFSET TRANGROUP:EXEFCB + MOV CX,4 + INT 33 ;Read in one relocation pointer + OR AL,AL ;Check return code + JNZ BADEXE + MOV DI,[RELPT] ;Get offset of relocation pointer + MOV AX,[RELSEG] ;Get segment + ADD AX,BP ;Bias segment with actual load segment + MOV ES,AX + ADD WORD PTR ES:[DI],BP ;Relocate + DEC [RELCNT] ;Count off + JNZ RELOC +;Set up exit conditions +NOREL: + MOV AX,[INITSS] + ADD AX,BP + CLI + MOV SS,AX ;Initialize SS + MOV SP,[INITSP] + STI + ADD [INITCS],BP + MOV AX,[TPA] ;Get pointer to parameter area + MOV CX,[BYTCNT] ;Size of TPA segment + MOV ES,AX + MOV DS,AX ;Set segment registers to point to it + CALL SETUP + JMP DWORD PTR CS:[INITIP] ;Long jump to program + +SETUP: + AND CL,0F0H ;Adjust to even paragraph boundary + MOV AX,WORD PTR DS:[6] ;Get current memory size + SUB AX,CX ;Find out how much we're changing it + MOV WORD PTR DS:[6],CX + MOV CL,4 + SAR AX,CL ;Convert to a segment address + ADD WORD PTR DS:[8],AX ;Adjust long jump to go to same place + MOV DX,80H + MOV AH,SETDMA + INT 33 ;Set default disk transfer address + MOV AX,WORD PTR CS:[PARM1] ;Pass on info about FCBs + XOR CX,CX + MOV DX,CX ;Assume no batch file +ASSUME CS:RESGROUP + TEST CS:[BATCH],-1 ;Batch file in progress? +ASSUME CS:TRANGROUP + JZ RET120 ;If not, all set up + MOV CX,CS:[RESSEG] + MOV DX,OFFSET RESGROUP:BATFCB ;CX:DX points to batch FCB +RET120: RET +TRANCODESIZE EQU $-ZERO +TRANCODE ENDS +COMLEN EQU TRANDATASIZE+TRANCODESIZE-102H ;End of COMMAND load. ZERO Needed to make COMLEN absolute +TRNLEN EQU (PRETRLEN+TRANCODESIZE+TRANDATASIZE+15)/16 ;Length of transient in paragraphs + END PROGSTART + \ No newline at end of file diff --git a/v1.25/source/HEX2BIN.ASM b/v1.25/source/HEX2BIN.ASM new file mode 100644 index 0000000..d7ba742 --- /dev/null +++ b/v1.25/source/HEX2BIN.ASM @@ -0,0 +1,214 @@ +; HEX2BIN version 1.02 +; Converts Intel hex format files to straight binary + +FCB: EQU 5CH +READ: EQU 20 +SETDMA: EQU 26 +OPEN: EQU 15 +CLOSE: EQU 16 +CREATE: EQU 22 +DELETE: EQU 19 +BLKWRT: EQU 40 +GETSEG: EQU 38 +BUFSIZ: EQU 1024 + + ORG 100H + PUT 100H + +HEX2BIN: + MOV DI,FCB+9 + CMP B,[DI]," " + JNZ HAVEXT + MOV SI,HEX + MOVB + MOVW +HAVEXT: +;Get load offset (default is -100H) + MOV CL,4 ;Needed for shifts + MOV [OFFSET],-100H + MOV SI,FCB+11H ;Scan second FCB for offset + LODB + CMP AL," " ;Check if offset present + JZ HAVOFF + MOV B,[SIGN],0 ;Assume positive sign for now + CMP AL,"+" + JZ GETOFF ;Get a positive offset + CMP AL,"-" + JNZ GETOFF1 ;If not + or -, then not signed + MOV B,[SIGN],1 ;Flag as negative offset +GETOFF: + LODB ;Eat sign +GETOFF1: + CALL HEXCHK ;Check for valid hex character + JC HAVOFF ;No offset if not valid + XOR BX,BX ;Intialize offset sum to 0 +CONVOFF: + SHL BX,CL ;Multiply current sum by 16 + OR BL,AL ;Add in current hex digit + LODB ;Get next digit + CALL HEXCHK ;And convert it to binary + JNC CONVOFF ;Loop until all hex digits read + TEST B,[SIGN],-1 ;Check if offset was to be negative + JZ SAVOFF + NEG BX +SAVOFF: + MOV [OFFSET],BX +HAVOFF: + MOV DX,STARTSEG + MOV AX,DS + ADD DX,AX ;Compute load segment + MOV AH,GETSEG + INT 33 + MOV ES,DX + SEG ES + MOV CX,[6] ;Get size of segment + MOV [SEGSIZ],CX + XOR AX,AX + MOV DI,AX + MOV BP,AX + SHR CX + REP + STOW ;Fill entire segment with zeros + MOV AH,OPEN + MOV DX,FCB + INT 21H + OR AL,AL + JNZ NOFIL + MOV B,[FCB+32],0 + MOV [FCB+14],BUFSIZ ;Set record size to buffer size + MOV DX,BUFFER + MOV AH,SETDMA + INT 33 + MOV AH,READ + MOV DX,FCB ;All set up for sequential reads + MOV SI,BUFFER+BUFSIZ ;Flag input buffer as empty +READHEX: + CALL GETCH + CMP AL,":" ;Search for : to start line + JNZ READHEX + CALL GETBYT ;Get byte count + MOV CL,AL + MOV CH,0 + JCXZ DONE + CALL GETBYT ;Get high byte of load address + MOV BH,AL + CALL GETBYT ;Get low byte of load address + MOV BL,AL + ADD BX,[OFFSET] ;Add in offset + MOV DI,BX + CALL GETBYT ;Throw away type byte +READLN: + CMP DI,[SEGSIZ] + JAE ADERR + CALL GETBYT ;Get data byte + STOB + CMP DI,BP ;Check if this is the largest address so far + JBE HAVBIG + MOV BP,DI ;Save new largest +HAVBIG: + LOOP READLN + JP READHEX + +NOFIL: + MOV DX,NOFILE +QUIT: + MOV AH,9 + INT 21H + INT 20H + +ADERR: + MOV DX,ADDR + JMP SHOWERR + +GETCH: + CMP SI,BUFFER+BUFSIZ + JNZ NOREAD + INT 21H + CMP AL,1 + JZ ERROR + MOV SI,BUFFER +NOREAD: + LODB + CMP AL,1AH + JZ DONE + RET + +GETBYT: + CALL HEXDIG + MOV BL,AL + CALL HEXDIG + SHL BL + SHL BL + SHL BL + SHL BL + OR AL,BL + RET + +HEXCHK: + SUB AL,"0" + JC RET + CMP AL,10 + JC CMCRET + SUB AL,"A"-"0"-10 + JC RET + CMP AL,16 +CMCRET: + CMC + RET + +HEXDIG: + CALL GETCH + CALL HEXCHK + JNC RET +ERROR: + MOV DX,ERRMES +SHOWERR: + MOV AH,9 + INT 21H +DONE: + MOV [FCB+9],4F00H+"C" ;"CO" + MOV B,[FCB+11],"M" + MOV DX,FCB + MOV AH,CREATE + INT 21H + OR AL,AL + JNZ NOROOM + XOR AX,AX + MOV [FCB+33],AX + MOV [FCB+35],AX ;Set RR field + INC AX + MOV [FCB+14],AX ;Set record size + XOR DX,DX + PUSH DS + PUSH ES + POP DS ;Get load segment + MOV AH,SETDMA + INT 21H + POP DS + MOV CX,BP + MOV AH,BLKWRT + MOV DX,FCB + INT 21H + MOV AH,CLOSE + INT 21H +EXIT: + INT 20H + +NOROOM: + MOV DX,DIRFUL + JMP QUIT + +HEX: DB "HEX" +ERRMES: DB "Error in HEX file--conversion aborted$" +NOFILE: DB "File not found$" +ADDR: DB "Address out of range--conversion aborted$" +DIRFUL: DB "Disk directory full$" + +OFFSET: DS 2 +SEGSIZ: DS 2 +SIGN: DS 1 +BUFFER: DS BUFSIZ + +START: +STARTSEG EQU (START+15)/16 + \ No newline at end of file diff --git a/v1.25/source/IO.ASM b/v1.25/source/IO.ASM new file mode 100644 index 0000000..3b9f181 --- /dev/null +++ b/v1.25/source/IO.ASM @@ -0,0 +1,1934 @@ +; I/O System for 86-DOS version 1.20 and later. Revised 8-02-82. +; +; Assumes a CPU Support card at F0 hex for character I/O, +; with disk drivers for SCP, Tarbell, or Cromemco controllers. +; +; Select whether console input is interrupt-driven or polled. +INTINP: EQU 1 +; +; Select whether the auxiliary port is the Support Card parallel port +; or on channel 1 of a Multiport Serial card addressed at 10H. +PARALLELAUX: EQU 1 +SERIALAUX: EQU 0 +; +; Select whether the printer is connected to the Support card parallel +; output port (standard) or channel 0 of a Multiport Serial card +; addressed at 10H. +PARALLELPRN: EQU 1 +SERIALPRN: EQU 0 +; +; If the Multiport Serial was chosen for either the auxiliary or the +; printer, select the baud rate here. Refer to Multiport Serial manual +; page 11 to pick the correct value for a given baud rate. +PRNBAUD:EQU 7 ; 1200 baud +AUXBAUD:EQU 0FH ; 19200 baud +; +; Select disk controller here. +SCP: EQU 1 +TARBELLSD: EQU 0 +TARBELLDD: EQU 0 +CROMEMCO4FDC: EQU 0 +CROMEMCO16FDC: EQU 0 +; +; Select if you want a special conversion version which can read/write +; both the new Microsoft format and the old SCP format. +; For a two drive system, drives A and B are the new Microsoft format, +; and drives C and D are the old SCP format (where C is the same physical +; drive as A, and D is the same drive as B). CONVERT has no effect +; on 5.25-inch drives. +CONVERT:EQU 1 +; +; Select disk configuration: +LARGE: EQU 1 ; Large drives. +COMBIN: EQU 0 ; Two 8-inch and one 5.25-inch. +SMALL: EQU 0 ; Three 5.25-inch drives. +CUSTOM: EQU 0 ; User defined. +; +; If 8-inch drives are PerSci, select FASTSEEK here: +; (Fastseek with Tarbell controllers doesn't work yet). +FASTSEEK: EQU 1 +; +; For double-density controllers, select double-sided operation of +; 8-inch disks in double-density mode. +LARGEDS: EQU 0 +; +; For double-density controllers, select double-sided operation of +; 5.25-inch disks in double-density mode. +SMALLDS: EQU 0 +; +; Use table below to select head step speed. Step times for 5" drives +; are double that shown in the table. Times for Fast Seek mode (using +; PerSci drives) is very small - 200-400 microseconds. +; +; Step value 1771 1793 +; +; 0 6ms 3ms +; 1 6ms 6ms +; 2 10ms 10ms +; 3 20ms 15ms +; +STPSPD: EQU 0 +; +; ****** End of selections ******************************************** +; +BIOSSEG:EQU 40H ; I/O system segment. +BIOSLEN:EQU 2048 ; Maximum length of I/O system. +DOSLEN: EQU 8192 ; Maximum length of MS-DOS. +QSIZE: EQU 80 ; Input queue size. +PBUFSIZ:EQU 128 ; Size of print buffer +BASE: EQU 0F0H ; CPU Support card base port number. +SIOBASE:EQU 10H ; Base port number of Multiport Serial card. +STAT: EQU BASE+7 ; Serial I/O status port. +DATA: EQU BASE+6 ; Serial I/O data port. +DAV: EQU 2 ; Data available bit. +TBMT: EQU 1 ; Transmitter buffer empty bit. +SERIAL: EQU SERIALPRN+SERIALAUX +STCDATA:EQU BASE+4 ; Ports for 9513 Timer chip. +STCCOM: EQU BASE+5 + + IF SERIALAUX +AUXSTAT:EQU SIOBASE+3 +AUXDATA:EQU SIOBASE+2 + ENDIF + + IF PARALLELAUX +AUXSTAT:EQU BASE+13 +AUXDATA:EQU BASE+12 + ENDIF + + IF SERIALPRN +PRNSTAT:EQU SIOBASE+1 +PRNDATA:EQU SIOBASE+0 + ENDIF + + IF PARALLELPRN +PRNSTAT:EQU BASE+13 +PRNDATA:EQU BASE+12 + ENDIF + + ORG 0 + PUT 100H + + JMP INIT + JMP STATUS + JMP INP + JMP OUTP + JMP PRINT + JMP AUXIN + JMP AUXOUT + JMP READ + JMP WRITE + JMP DSKCHG + JMP SETDATE + JMP SETTIME + JMP GETTIME + JMP FLUSH + JMP MAPDEV +MAPDEV: + RET L + +INIT: + XOR BP,BP ; Set up stack just below I/O system. + MOV SS,BP + MOV SP,BIOSSEG*16 + + IF INTINP-1 + MOV AL,0FFH ; Mask all interrupts. + OUTB BASE+3 + ENDIF + + IF INTINP + DI ; Set up keyboard interrupt vector. + MOV [BP+64H],KBINT + MOV [BP+66H],CS + EI + ENDIF + + MOV [BP+4*38H],PRNFCB + MOV [BP+4*38H+2],CS + PUSH CS + POP DS +; +; Initialize time-of-day clock. +; + MOV SI,STCTAB + MOV CX,4 ;Initialize 4 registers + UP +INITSTC: + LODB + OUT STCCOM ;Select register to initialize + LODB + OUT STCDATA + LODB + OUT STCDATA + LOOP INITSTC + + IF SERIAL + MOV CX,4 +SERINIT: + LODB + OUT SIOBASE+1 + OUT SIOBASE+3 + LOOP SERINIT + LODB ;Baud rate for channel 0 + OUT SIOBASE+8 + LODB ;Baud rate for channel 1 + OUT SIOBASE+9 + ENDIF +; +; Move MS-DOS down to the first segment just above the I/O system. +; + MOV SI,BIOSLEN ; Source points to where MS-DOS currently is. + MOV AX,DOSSEG ; Destination is beginning of DOSSEG. + MOV ES,AX + SUB DI,DI + MOV CX,DOSLEN/2 ; CX is number of words to move. + REP + MOVSW + + MOV SI,INITTAB + MOV DX,1 ; Do auto memory scan. + CALL 0,DOSSEG +; +; Change disk read and write vectors (INT 37 and INT 38) to go to +; DIRECTREAD and DIRECTWRITE rather than READ and WRITE. +; + SUB BP,BP + MOV W,[BP+37*4],DIRECTREAD + MOV W,[BP+38*4],DIRECTWRITE + + MOV DX,100H + MOV AH,26 ;Set DMA address + INT 33 + MOV CX,[6] ;Get size of segment + MOV BX,DS ;Save segment for later +; +; DS must be set to CS so we can point to the FCB. +; + MOV AX,CS + MOV DS,AX + MOV DX,FCB ;File Control Block for COMMAND.COM + MOV AH,15 + INT 33 ;Open COMMAND.COM + OR AL,AL + JNZ COMERR ;Error if file not found + XOR AX,AX + MOV [FCB+33],AX ; Set 4-byte Random Record field to + MOV [FCB+35],AX ; beginning of file. + INC AX + MOV [FCB+14],AX ;Set record length field + MOV AH,39 ;Block read (CX already set) + INT 33 + JCXZ COMERR ;Error if no records read + TEST AL,1 + JZ COMERR ;Error if not end-of-file +; +; Make all segment registers the same. +; + MOV DS,BX + MOV ES,BX + MOV SS,BX + MOV SP,5CH ;Set stack to standard value + XOR AX,AX + PUSH AX ;Put zero on top of stack for return + MOV DX,80H + MOV AH,26 + INT 33 ;Set default transfer address (DS:0080) + PUSH BX ;Put segment on stack + MOV AX,100H + PUSH AX ;Put address to execute within segment on stack + RET L ;Jump to COMMAND + +COMERR: + MOV DX,BADCOM + MOV AH,9 ;Print string + INT 33 + EI +STALL: JP STALL + +STCTAB: DB 17H ;Select master mode register + DW 84F3H ;Enable time-of-day + DB 1 ;Counter 1 mode register + DW 0138H + DB 2 + DW 0038H + DB 3 + DW 0008H ;Set counter 3 to count days + + IF SERIAL + DB 0B7H, 77H, 4EH, 37H, PRNBAUD, AUXBAUD + ENDIF + +BADCOM: DB 13,10,"Error in loading Command Interpreter",13,10,"$" +FCB: DB 1,"COMMAND COM" + DS 25 +; +; ************ Time and Date ************ +; +GETTIME: + MOV AL,0A7H ;Save counters 1,2,3 + OUT STCCOM + MOV AL,0E0H ;Enable data pointer sequencing + OUT STCCOM + MOV AL,19H ;Select hold 1 / hold cycle + OUT STCCOM + CALL STCTIME ;Get seconds & 1/100's + XCHG AX,DX + CALL STCTIME ;Get hours & minutes + XCHG AX,CX + IN STCDATA + MOV AH,AL + IN STCDATA + XCHG AL,AH ;Count of days + JP POINTSTAT + +STCTIME: + CALL STCBYTE + MOV CL,AH +STCBYTE: + IN STCDATA + MOV AH,AL + SHR AH + SHR AH + SHR AH + SHR AH + AND AL,0FH ;Unpack BCD digits + AAD ;Convert to binary + MOV AH,AL + MOV AL,CL + RET + +SETTIME: + PUSH CX + PUSH DX + CALL LOAD0 ;Put 0 into load registers to condition timer + MOV AL,43H ;Load counters 1 & 2 + OUT STCCOM + POP DX + POP CX + CALL LOAD + MOV AL,43H + OUT STCCOM ;Load counters 1&2 + CALL LOAD0 + MOV AL,27H ;Arm counters 1,2,3 + OUT STCCOM + JP POINTSTAT + +LOAD0: + XOR CX,CX + MOV DX,CX +LOAD: + MOV AL,09 ;Counter 1 load register + CALL OUTDX + MOV AL,0AH ;Counter 2 load register + MOV DX,CX +OUTDX: + OUT STCCOM ;Select a load register + MOV AL,DL + CALL OUTBCD + MOV AL,DH +OUTBCD: + AAM ;Convert binary to unpacked BCD + SHL AH + SHL AH + SHL AH + SHL AH + OR AL,AH ;Packed BCD + OUT STCDATA + RET + +SETDATE: + XCHG AX,DX ;Put date in DX + MOV AL,0BH ;Select Counter 3 load register + OUT STCCOM + XCHG AX,DX + OUT STCDATA + MOV AL,AH + OUT STCDATA + MOV AL,44H ;Load counter 3 + OUT STCCOM +POINTSTAT: + PUSH AX + MOV AL,1FH ;Point to status register + OUT STCCOM ; so power-off glitches won't hurt + POP AX + RET L +; +; ************ CONSOLE INPUT ************ +; + + IF INTINP-1 ; Non-interrupt driven input. +STATUS: + IN STAT + AND AL,DAV + JZ NOTHING ; Jump if nothing there. + PUSHF ; Save Z flag. + INB DATA + AND AL,7FH + SEG CS + MOV [QUEUE],AL ; Put new character in buffer. + POPF ; Return with Z flag clear. + RET L +NOTHING: + SEG CS + MOV AL,[QUEUE] ; See if there's anything in the buffer. + NOT AL ; Set up the Z flag. + TEST AL,80H + PUSHF + NOT AL + POPF + RET L + +INP: + MOV AL,-1 + SEG CS + XCHG AL,[QUEUE] ; Remove the character from the buffer. + AND AL,AL + JNS INRET ; Return if we have a character. +INLOOP: + IN STAT ; Wait till a character is available. + AND AL,DAV + JZ INLOOP + IN DATA + AND AL,7FH +INRET: +FLUSH: + RET L + +QUEUE: DB -1 ; For storing characters from STATUS to INP. + ENDIF + + IF INTINP ; Interrupt-driven input. +; +; Console keyboard interrupt handler. +; +KBINT: + PUSH AX + PUSH SI + MOV AL,20H ;End of Interrupt command + OUT BASE+2 ;Send to slave + IN DATA ;Get the character + AND AL,7FH + CMP AL,"C"-"@" + JZ FLSH + CMP AL,"S"-"@" + JZ FLSH + CMP AL,"F"-"@" + JNZ SAVKY +FLSH: + CALL 13*3,BIOSSEG ; Call I/O system keyboard buffer flush. +SAVKY: + SEG CS + MOV SI,[REAR] ;Pointer to rear of queue + CALL INCQ + SEG CS + CMP SI,[FRONT] ;Any room in queue? + JZ QFULL + SEG CS + MOV [SI],AL ;Put character in queue + SEG CS + MOV [REAR],SI ;Save pointer +LEAVINT: + POP SI + POP AX + IRET +QFULL: + MOV AL,7 ; BELL character. + CALL 3*3,BIOSSEG ; Call I/O system console output function. + JMPS LEAVINT + +STATUS: + PUSH SI +;See if printer ready + IN PRNSTAT + AND AL,TBMT + JZ NOPRN + SEG CS + MOV SI,[PFRONT] + SEG CS + CMP SI,[PREAR] ;Anything in print queue? + JNZ SENDPRN + SEG CS + CMP B,[PRNFCB],-1 ;Print spooling in progress? + JZ NOPRN ;If not, nothing to print +;Print spooling in progress. Get next buffer + PUSH DS + PUSH CS + POP DS + PUSH AX + PUSH CX + PUSH DX + PUSH [STKSAV] + PUSH [STKSAV+2] + PUSH [DMAADD] + PUSH [DMAADD+2] + MOV DX,PQUEUE + MOV AH,26 ;Set DMA address + INT 33 + MOV DX,PRNFCB + MOV CX,PBUFSIZ + MOV AH,39 ;Read buffer + INT 33 + OR AL,AL + JZ NOTEOF + MOV B,[PRNFCB],-1 ;Turn off print spooling at EOF +NOTEOF: + POP [DMAADD+2] + POP [DMAADD] + POP [STKSAV+2] + POP [STKSAV] + MOV SI,CX + POP DX + POP CX + POP AX + POP DS + OR SI,SI + JZ NOPRN + ADD SI,PQUEUE-1 + SEG CS + MOV [PREAR],SI + MOV SI,ENDPQ-1 +SENDPRN: + CALL INCPQ + SEG CS + MOV [PFRONT],SI + SEG CS + LODSB ;Get character to print + OUT PRNDATA +NOPRN: + DI ; Disable interrupts while checking queue. + SEG CS + MOV SI,[FRONT] + SEG CS + CMP SI,[REAR] ; Anything in queue? + JZ NOCHR ; Jump if nothing in queue. + CALL INCQ + SEG CS + LODSB ;Get character (if there is one) + OR SI,SI ;Reset zero flag +NOCHR: + EI + POP SI + RET L ;Zero clear if we have a character + +INP: + CALL STATUS,BIOSSEG ; Get I/O system console input status. + JZ INP + PUSH SI + DI ; Disable interrupts while changing queue pointers. + SEG CS + MOV SI,[FRONT] + CALL INCQ ; Permanently remove char from queue + SEG CS + MOV [FRONT],SI + EI + POP SI + RET L + +FLUSH: + DI + SEG CS + MOV [REAR],QUEUE + SEG CS + MOV [FRONT],QUEUE + EI + RET L + +INCQ: + INC SI + CMP SI,ENDQ ;Exceeded length of queue? + JB RET + MOV SI,QUEUE + RET + +INCPQ: + INC SI + CMP SI,ENDPQ ;Exceeded length of queue? + JB RET + MOV SI,PQUEUE + RET + +FRONT: DW QUEUE +REAR: DW QUEUE +QUEUE: DS QSIZE +ENDQ: EQU $ +PFRONT: DW PQUEUE +PREAR: DW PQUEUE +PQUEUE: DS PBUFSIZ +ENDPQ: EQU $ +PRNFCB: DB -1 + DS 36 + ENDIF + +; +; ************ Console and Printer Output ************ +; +OUTP: + PUSH AX +OUTLP: + IN STAT + AND AL,TBMT + JZ OUTLP + POP AX + OUT DATA + RET L + +PRINT: + PUSH SI + SEG CS + MOV SI,[PREAR] + CALL INCPQ +PRINLP: + SEG CS + CMP SI,[PFRONT] + JNZ PRNCHR +;Print queue is full + PUSH AX + CALL STATUS,BIOSSEG ;Poll and maybe print something + POP AX + JMPS PRINLP +PRNCHR: + SEG CS + MOV [PREAR],SI + SEG CS + MOV [SI],AL + POP SI + RET L +; +; ************ Auxiliary I/O ************ +; +AUXIN: + IN AUXSTAT + AND AL,DAV + JZ AUXIN + IN AUXDATA + RET L + +AUXOUT: + PUSH AX +AUXLP: + IN AUXSTAT + AND AL,TBMT + JZ AUXLP + POP AX + OUT AUXDATA + RET L +; +; ************ 1771/1793-type controller disk I/O ************ +; +TARBELL:EQU TARBELLSD+TARBELLDD +CROMEMCO:EQU CROMEMCO4FDC+CROMEMCO16FDC + +WD1791: EQU SCP+TARBELLDD+CROMEMCO16FDC +WD1771: EQU TARBELLSD+CROMEMCO4FDC + + IF WD1791 +READCOM:EQU 80H +WRITECOM:EQU 0A0H + ENDIF + + IF WD1771 +READCOM:EQU 88H +WRITECOM:EQU 0A8H + ENDIF + + IF SCP +SMALLBIT:EQU 10H +BACKBIT:EQU 04H +DDENBIT:EQU 08H +DONEBIT:EQU 01H +DISK: EQU 0E0H + ENDIF + + IF TARBELL +BACKBIT:EQU 40H +DDENBIT:EQU 08H +DONEBIT:EQU 80H +DISK: EQU 78H + ENDIF + + IF CROMEMCO +SMALLBIT:EQU 10H +BACKBIT:EQU 0FDH ; Send this to port 4 to select back. +DDENBIT:EQU 40H +DONEBIT:EQU 01H +DISK: EQU 30H + ENDIF + + IF SMALLDS-1 +SMALLDDSECT: EQU 8 + ENDIF + + IF SMALLDS +SMALLDDSECT: EQU 16 + ENDIF + + IF LARGEDS-1 +LARGEDDSECT: EQU 8 + ENDIF + + IF LARGEDS +LARGEDDSECT: EQU 16 + ENDIF +; +; Disk change function. +; On entry: +; AL = disk drive number. +; On exit: +; AH = -1 (FF hex) if disk is changed. +; AH = 0 if don't know. +; AH = 1 if not changed. +; +; CF clear if no disk error. +; AL = disk I/O driver number. +; +; CF set if disk error. +; AL = disk error code (see disk read below). +; + IF WD1771 +DSKCHG: + MOV AH,0 ; AH = 0 in case we don't know. + SEG CS + CMP AL,[CURDRV] + JNZ RETL + PUSH AX ; Save drive number. + + IF CROMEMCO + INB DISK+4 + ENDIF + + IF TARBELL + INB DISK + ENDIF + + AND AL,20H ; Look at head load bit + POP AX + JZ RETL + MOV AH,1 ; AH = 1, disk not changed. +RETL: + CLC ; No disk error. + RET L + ENDIF ; End of 1771 DSKCHG. + + IF WD1791 +DSKCHG: + MOV AH,0 ; AH = 0 in case we don't know. + SEG CS + CMP AL,[CURDRV] + JNZ DENSCHK ; Check density if not same drive. + PUSH AX + + IF SCP+CROMEMCO + INB DISK+4 + ENDIF + + IF TARBELL + INB DISK + ENDIF + + AND AL,20H ; Look at head load bit + POP AX + JZ DENSCHK ; Check density if head not loaded. + MOV AH,1 ; AH = 1, disk not changed. + MOV BX,PREVDENS + SEG CS + XLAT ; Get previous density + CLC ; No disk error. + RET L +DENSCHK: + CALL CHKNEW ; Unload head if selecting new drive. + CBW + XCHG AX,SI + ADD SI,PREVDENS + MOV CX,4 ; Try each density twice + MOV AH,0 ; Disk may not have been changed. +CHKDENS: + SEG CS + MOV AL,[SI] ; Get previous disk I/O driver number. + MOV BX,DRVTAB + SEG CS + XLAT ; Get drive select byte for previous density + + IF CROMEMCO16FDC + CALL MOTOR ; Wait for motor to come up to speed. + ENDIF + + OUT DISK+4 ; Select disk + MOV AL,0C4H ; READ ADDRESS command + CALL DCOM + AND AL,98H + IN DISK+3 ; Eat last byte to reset DRQ + JZ HAVDENS ; Jump if no error in reading address. + NOT AH ; AH = -1 (disk changed) if new density works. + SEG CS + XOR B,[SI],1 ; Try other density + LOOP CHKDENS + MOV AX,2 ; Couldn't read disk at all, AH = 0 for don't + STC ; know if disk changed, AL = error code 2 - + RET L ; disk not ready, carry set to indicate error. + +HAVDENS: + SEG CS + LODSB ; AL = disk I/O driver number. + CLC ; No disk error. + RET L + +PREVDENS:DB 1,3,5,7,9,11,13 ; Table of previous disk I/O driver numbers. + ENDIF ; End of 1793 DSKCHG function. + +CHKNEW: + MOV AH,AL ; Save disk drive number in AH. + SEG CS ; AL = previous disk drive number, + XCHG AL,[CURDRV] ; make new drive current. + CMP AL,AH ; Changing drives? + JZ RET +; +; If changing drives, unload head so the head load delay one-shot will +; fire again. Do it by seeking to the same track with the H bit reset. +; + IN DISK+1 ; Get current track number + OUT DISK+3 ; Make it the track to seek to + MOV AL,10H ; Seek and unload head + CALL DCOM + MOV AL,AH ; Restore current drive number + RET + + IF CROMEMCO16FDC +MOTOR: + PUSH AX + MOV AH,AL + IN DISK+4 ; See if the motor is on. + TEST AL,08H + MOV AL,AH + OUTB DISK+4 ; Select drive & start motor. + JNZ MOTORSON ; No delay if motors already on. + PUSH CX + MOV CX,43716 ; Loop count for 1 second. +MOTORDELAY: ; (8 MHz, 16-bit memory). + AAM ; 83 clocks. + AAM ; 83 clocks. + LOOP MOTORDELAY ; 17 clocks. + POP CX +MOTORSON: + POP AX + RET + ENDIF +; +; Disk read function. +; +; On entry: +; AL = Disk I/O driver number +; BX = Disk transfer address in DS +; CX = Number of sectors to transfer +; DX = Logical record number of transfer +; On exit: +; CF clear if transfer complete +; +; CF set if hard disk error. +; CX = number of sectors left to transfer. +; AL = disk error code +; 0 = write protect error +; 2 = not ready error +; 4 = "data" (CRC) error +; 6 = seek error +; 8 = sector not found +; 10 = write fault +; 12 = "disk" (none of the above) error +; +READ: + CALL SEEK ;Position head + JC ERROR + PUSH ES ; Make ES same as DS. + MOV BX,DS + MOV ES,BX +RDLP: + CALL READSECT ;Perform sector read + JC POPESERROR + INC DH ;Next sector number + LOOP RDLP ;Read each sector requested + CLC ; No errors. + POP ES ; Restore ES register. + RET L +; +; Disk write function. +; Registers same on entry and exit as read above. +; +WRITE: + CALL SEEK ;Position head + JC ERROR +WRTLP: + CALL WRITESECT ;Perform sector write + JC ERROR + INC DH ;Bump sector counter + LOOP WRTLP ;Write CX sectors + CLC ; No errors. +WRITERET: + RET L + +POPESERROR: + POP ES ; Restore ES register. +ERROR: + MOV BL,-1 + SEG CS + MOV [DI],BL ; Indicate we don't know where head is. + MOV SI,ERRTAB +GETCOD: + INC BL ; Increment to next error code. + SEG CS + LODB + TEST AH,AL ; See if error code matches disk status. + JZ GETCOD ; Try another if not. + MOV AL,BL ; Now we've got the code. + SHL AL ; Multiply by two. + STC + RET L + +ERRTAB: + DB 40H ;Write protect error + DB 80H ;Not ready error + DB 8 ;CRC error + DB 2 ;Seek error + DB 10H ;Sector not found + DB 20H ;Write fault + DB 7 ;"Disk" error +; +; Direct disk read and write from INT 37 and INT 38. Subroutine GETIODRIVER +; calls DSKCHG to convert disk drive number to I/O driver number. +; +; Setting CURDRV to -1 before calling DSKCHG forces DSKCHG to check the disk's +; density before returning the I/O driver number. This is necessary because +; programs such as FORMAT could change the density of a disk and leave the +; head loaded. If the head is loaded DSKCHG assumes the disk hasn't been +; changed and returns the old I/O driver number which could be wrong. +; +; CURDRV is set to -1 before returning so when DSKCHG is called by the +; operating system, it will tell the operating system the disk may have +; been changed (because it may have been). +; +DIRECTREAD: + + IF WD1791 + CALL GETIODRIVER ; Convert drive number to I/O driver number. + JC DIRECTRET ; Return if DSKCHG returned error. + ENDIF + + CALL 7*3,BIOSSEG ; Call READ. + JMPS DIRECTRET + +DIRECTWRITE: + + IF WD1791 + CALL GETIODRIVER ; Convert drive number to I/O driver number. + JC DIRECTRET ; Return if DSKCHG returned error. + ENDIF + + CALL 8*3,BIOSSEG ; Call WRITE. +DIRECTRET: + SEG CS + MOV B,[CURDRV],-1 ; Force DSKCHG to do density check. + RET L + + IF WD1791 +GETIODRIVER: + SEG CS + MOV B,[CURDRV],-1 ; Force DSKCHG to do density check. + PUSH BX + PUSH CX + CALL 9*3,BIOSSEG ; Call DSKCHG. + POP CX + POP BX + RET + ENDIF +; +; Function: +; Seeks to proper track. +; On entry: +; Same as for disk read or write above. +; On exit: +; AH = Drive select byte +; DL = Track number +; DH = Sector number +; SI = Disk transfer address in DS +; DI = pointer to drive's track counter in CS +; CX unchanged (number of sectors) +; +SEEK: + MOV SI,BX ; Save transfer address + CBW + MOV BX,AX ; Prepare to index on drive number + + IF WD1791 ; If two disk formats per drive. + SHR AL ; Convert to physical disk drive number. + ENDIF + + CALL CHKNEW ; Unload head if changing drives. + SEG CS + MOV AL,[BX+DRVTAB] ; Get drive-select byte. + + IF CROMEMCO16FDC + CALL MOTOR ; Wait for the motors to come up to speed. + ENDIF + + OUTB DISK+4 ; Select drive. + + IF CROMEMCO + OR AL,80H ; Set auto-wait bit. + ENDIF + + MOV AH,AL ; Save drive-select byte in AH. + XCHG AX,DX ; AX = logical sector number. + MOV DL,26 ; 26 sectors/track unless changed below + + IF SCP + TEST DH,SMALLBIT ; Check if small disk. + JZ BIGONE ; Jump if big disk. + MOV DL,18 ; Assume 18 sectors on small track. + TEST DH,DDENBIT ; Check if double-density. + JZ HAVSECT ; Jump if not. + MOV DL,SMALLDDSECT ; Number of sectors on small DD track. + JP HAVSECT +BIGONE: + TEST DH,DDENBIT ; Check if double-density. + JZ HAVSECT ; Jump if not. + MOV DL,LARGEDDSECT ; Number of sectors on big DD track. + ENDIF + + IF TARBELLDD ; Tarbell DD controller. + TEST DH,DDENBIT ; Check for double-density. + JZ HAVSECT + MOV DL,LARGEDDSECT ; Number of sectors on DD track. + ENDIF + + IF CROMEMCO4FDC + TEST DH,SMALLBIT ; Check if small disk. + JNZ HAVSECT ; Jump if not. + MOV DL,18 ; 18 sectors on small disk track. + ENDIF + + IF CROMEMCO16FDC + TEST DH,SMALLBIT ; Check if small disk. + JNZ BIGONE ; Jump if big disk. + MOV DL,18 ; Assume 18 sectors on small track. + TEST DH,DDENBIT ; Check if double-density. + JZ HAVSECT ; Jump if not. + MOV DL,SMALLDDSECT ; Number of sectors on small DD track. + JP HAVSECT +BIGONE: + TEST DH,DDENBIT ; Check if double-density. + JZ HAVSECT ; Jump if not. + MOV DL,LARGEDDSECT ; Number of sectors on big DD track. + ENDIF + +HAVSECT: + DIV AL,DL ; AL = track, AH = sector. + XCHG AX,DX ; AH has drive-select byte, DX = track & sector. + INC DH ; Sectors start at one, not zero. + SEG CS + MOV BL,[BX+TRKPT] ; Get this drive's displacement into track table. + ADD BX,TRKTAB ; BX now points to track counter for this drive. + MOV DI,BX + MOV AL,DL ; Move new track number into AL. + SEG CS + XCHG AL,[DI] ; Xchange current track with desired track + OUT DISK+1 ; Inform controller chip of current track + CMP AL,DL ; See if we're at the right track. + JZ RET + MOV BH,2 ; Seek retry count + CMP AL,-1 ; Head position known? + JNZ NOHOME ; If not, home head +TRYSK: + CALL HOME + JC SEEKERR +NOHOME: + MOV AL,DL ; AL = new track number. + OUT DISK+3 + MOV AL,1CH+STPSPD ; Seek command. + CALL MOVHEAD + AND AL,98H ; Accept not ready, seek, & CRC error bits. + JZ RET + JS SEEKERR ; No retries if not ready + DEC BH + JNZ TRYSK +SEEKERR: + MOV AH,AL ; Put status in AH. + TEST AL,80H ; See if it was a Not Ready error. + STC + JNZ RET ; Status is OK for Not Ready error. + MOV AH,2 ; Everything else is seek error. + RET + +SETUP: + MOV BL,DH ; Move sector number to BL to play with + + IF SCP+CROMEMCO16FDC + TEST AH,DDENBIT ; Check for double density. + JZ CHECKSMALL ; Not DD, check size for SD. + ENDIF + + IF TARBELLDD + TEST AH,DDENBIT ; Check for double density. + JZ CHECK26 ; Not DD. + ENDIF + + IF WD1791 + + IF (SCP+TARBELL)*LARGEDS+SCP*SMALLDS + MOV AL,AH ; Select front side of disk. + OUT DISK+4 + ENDIF + + IF CROMEMCO*(LARGEDS+SMALLDS) + MOV AL,0FFH ; Select front side of disk. + OUT 04H + ENDIF + + CMP BL,8 ; See if legal DD sector number. + JBE PUTSEC ; Jump if ok. + + IF (LARGEDS-1)*((SMALLDS*(SCP+CROMEMCO))-1) + JP STEP ; If only SS drives, we gotta step. + ENDIF + + IF SCP*LARGEDS*(SMALLDS-1) + TEST AH,SMALLBIT ; Check for 5.25 inch disk. + JNZ STEP ; Jump if small because SMALLDS is off. + ENDIF + + IF SCP*SMALLDS*(LARGEDS-1) + TEST AH,SMALLBIT ; Check for 8 inch disk. + JZ STEP ; Jump if large because LARGEDS is off. + ENDIF + + IF CROMEMCO16FDC*LARGEDS*(SMALLDS-1) + TEST AH,SMALLBIT ; Check for 5.25 inch disk. + JZ STEP ; Jump if small because SMALLDS is off. + ENDIF + + IF CROMEMCO16FDC*SMALLDS*(LARGEDS-1) + TEST AH,SMALLBIT ; Check for 8 inch disk. + JNZ STEP ; Jump if large because LARGEDS is off. + ENDIF + + IF LARGEDS+SMALLDS*(SCP+CROMEMCO) + SUB BL,8 ; Find true sector for back side. + CMP BL,8 ; See if ok now. + JA STEP ; Have to step if still too big. + + IF SCP+TARBELLDD + MOV AL,AH ; Move drive select byte into AL. + OR AL,BACKBIT ; Select back side. + OUT DISK+4 + ENDIF + + IF CROMEMCO16FDC + MOV AL,BACKBIT ; Select back side. + OUT 04H + ENDIF + + JP PUTSEC + ENDIF + + ENDIF + + IF SCP +CHECKSMALL: + TEST AH,SMALLBIT ; See if big disk. + JZ CHECK26 ; Jump if big. + ENDIF + + IF CROMEMCO +CHECKSMALL: + TEST AH,SMALLBIT ; See if big disk. + JNZ CHECK26 ; Jump if big. + ENDIF + + IF SCP+CROMEMCO + CMP BL,18 ; See if legal small SD/SS sector. + JA STEP ; Jump if not. + ENDIF + +CHECK26: + CMP BL,26 ; See if legal large SD/SS sector. + JBE PUTSEC ; Jump if ok. +STEP: + INC DL ; Increment track number. + MOV AL,58H ; Step in with update. + CALL DCOM + SEG CS + INC B,[DI] ; Increment the track pointer. + MOV DH,1 ; After step, do first sector. + MOV BL,DH ; Fix temporary sector number also. +PUTSEC: + MOV AL,BL ; Output sector number to controller. + OUT DISK+2 + DI ; Interrupts not allowed until I/O done + + IF SCP+CROMEMCO + INB DISK+4 ; Get head-load bit. + ENDIF + + IF TARBELL + INB DISK + ENDIF + + NOT AL + AND AL,20H ; Check head load status + JZ RET + MOV AL,4 + RET + +READSECT: + CALL SETUP + MOV BL,10 ; Retry count for hard error. + XCHG DI,SI ; Transfer address to DI. + PUSH DX ; Save track & sector number. + MOV DL,DISK+3 ; Disk controller data port. +RDAGN: + OR AL,READCOM + OUT DISK + + IF CROMEMCO + MOV AL,AH ; Turn on auto-wait. + OUT DISK+4 + ENDIF + + MOV BP,DI ; Save address for retry. + JMPS RLOOPENTRY +RLOOP: + STOB ; Write into memory. +RLOOPENTRY: + + IF SCP + IN DISK+5 ; Wait for DRQ or INTRQ. + ENDIF + + IF TARBELL+CROMEMCO + IN DISK+4 + ENDIF + + IF TARBELL + SHL AL + INB DX ; Read data from disk controller chip. + JC RLOOP + ENDIF + + IF SCP+CROMEMCO + SHR AL + INB DX ; Read data from disk controller chip. + JNC RLOOP + ENDIF + + EI ; Interrupts OK now + CALL GETSTAT + AND AL,9CH + JZ RDPOP + MOV DI,BP ; Get origainal address back for retry. + MOV BH,AL ; Save error status for report + MOV AL,0 + DEC BL + JNZ RDAGN + MOV AH,BH ; Put error status in AH. + STC +RDPOP: + POP DX ; Get back track & sector number. + XCHG SI,DI ; Address back to SI. + + IF TARBELL +FORCINT: + MOV AL,0D0H ; Tarbell controllers need this Force Interrupt + OUT DISK ; so that Type I status is always available + MOV AL,10 ; at the 1771/1793 status port so we can find +INTDLY: ; out if the head is loaded. SCP and Cromemco + DEC AL ; controllers have head-load status available + JNZ INTDLY ; at the DISK+4 status port. + ENDIF + + RET + +WRITESECT: + CALL SETUP + MOV BL,10 + PUSH DX ; Save track & sector number. + MOV DL,DISK+3 ; Disk controller data port. +WRTAGN: + OR AL,WRITECOM + OUT DISK + + IF CROMEMCO + MOV AL,AH ; Turn on auto-wait. + OUT DISK+4 + ENDIF + + MOV BP,SI +WRLOOP: + + IF SCP + INB DISK+5 + ENDIF + + IF TARBELL+CROMEMCO + INB DISK+4 + ENDIF + + IF SCP+CROMEMCO + SHR AL + LODB ; Get data from memory. + OUTB DX ; Write to disk. + JNC WRLOOP + ENDIF + + IF TARBELL + SHL AL + LODB ; Get data from memory. + OUTB DX ; Write to disk. + JC WRLOOP + ENDIF + + EI ; Interrupts OK now. + DEC SI + CALL GETSTAT + AND AL,0FCH + JZ WRPOP + MOV SI,BP + MOV BH,AL + MOV AL,0 + DEC BL + JNZ WRTAGN + MOV AH,BH ; Error status to AH. + STC +WRPOP: + POP DX ; Get back track & sector number. + + IF TARBELL + JMPS FORCINT + ENDIF + + IF SCP+CROMEMCO + RET + ENDIF +; +; Subroutine to restore the read/write head to track 0. +; + IF SCP+CROMEMCO+TARBELL*(FASTSEEK-1) +HOME: + ENDIF + + IF FASTSEEK*CROMEMCO + TEST AH,SMALLBIT ; Check for large disk. + JNZ RESTORE ; Big disks are fast seek PerSci. + ENDIF + + MOV BL,3 +TRYHOM: + + IF SCP*FASTSEEK + MOV AL,AH ; Turn on Restore to PerSci. + OR AL,80H + OUTB DISK+4 + ENDIF + + MOV AL,0CH+STPSPD ; Restore with verify command. + CALL DCOM + AND AL,98H + + IF SCP*FASTSEEK + MOV AL,AH ; Restore off. + OUTB DISK+4 + ENDIF + + JZ RET + JS HOMERR ; No retries if not ready + MOV AL,58H+STPSPD ; Step in with update + CALL DCOM + DEC BL + JNZ TRYHOM +HOMERR: + STC + RET +; +; RESTORE for PerSci drives. +; Doesn't exist yet for Tarbell controllers. +; + IF FASTSEEK*TARBELL +HOME: +RESTORE: + RET + ENDIF + + IF FASTSEEK*CROMEMCO4FDC +RESTORE: + MOV AL,0C4H ;READ ADDRESS command to keep head loaded + OUT DISK + MOV AL,77H + OUT 4 +CHKRES: + IN 4 + AND AL,40H + JZ RESDONE + IN DISK+4 + TEST AL,DONEBIT + JZ CHKRES + IN DISK + JP RESTORE ;Reload head +RESDONE: + MOV AL,7FH + OUT 4 + CALL GETSTAT + MOV AL,0 + OUT DISK+1 ;Tell 1771 we're now on track 0 + RET + ENDIF + + IF FASTSEEK*CROMEMCO16FDC +RESTORE: + MOV AL,0D7H ; Turn on Drive-Select and Restore. + OUTB 4 + PUSH AX + AAM ; 10 uS delay. + POP AX +RESWAIT: + INB 4 ; Wait till Seek Complete is active. + TEST AL,40H + JNZ RESWAIT + MOV AL,0FFH ; Turn off Drive-Select and Restore. + OUTB 4 + SUB AL,AL ; Tell 1793 we're on track 0. + OUTB DISK+1 + RET + ENDIF +; +; Subroutine to move the read/write head to the desired track. +; Usually falls through to DCOM unless special handling for +; PerSci drives is required in which case go to FASTSK. +; + IF SCP+CROMEMCO+TARBELL*(FASTSEEK-1) +MOVHEAD: + ENDIF + + IF CROMEMCO*FASTSEEK + TEST AH,SMALLBIT ; Check for PerSci. + JNZ FASTSK + ENDIF + +DCOM: + OUT DISK + PUSH AX + AAM ;Delay 10 microseconds + POP AX +GETSTAT: + IN DISK+4 + TEST AL,DONEBIT + + IF TARBELL + JNZ GETSTAT + ENDIF + + IF SCP+CROMEMCO + JZ GETSTAT + ENDIF + + IN DISK + RET +; +; Fast seek code for PerSci drives. +; Tarbell not installed yet. +; + IF FASTSEEK*TARBELL +MOVHEAD: +FASTSK: + RET + ENDIF + + IF FASTSEEK*CROMEMCO +FASTSK: + MOV AL,6FH + OUT 4 + MOV AL,18H + CALL DCOM +SKWAIT: + IN 4 + TEST AL,40H + JNZ SKWAIT + MOV AL,7FH + OUT 4 + MOV AL,0 + RET + ENDIF + +CURDRV: DB -1 +; +; Explanation of tables below. +; +; DRVTAB is a table of bytes which are sent to the disk controller as drive- +; select bytes to choose which physical drive is selected for each disk I/O +; driver. It also selects whether the disk is 5.25-inch or 8-inch, single- +; density or double-density. Always select side 0 in the drive-select byte if +; a side-select bit is available. There should be one entry in the DRVTAB +; table for each disk I/O driver. Exactly which bits in the drive-select byte +; do what depends on which disk controller is used. +; +; TRKTAB is a table of bytes used to store which track the read/write +; head of each drive is on. Each physical drive should have its own +; entry in TRKTAB. +; +; TRKPT is a table of bytes which indicates which TRKTAB entry each +; disk I/O driver should use. Since each physical drive may be used for +; more than one disk I/O driver, more than one entry in TRKPT may point +; to the same entry in TRKTAB. Drives such as PerSci 277s which use +; the same head positioner for more than one drive should share entrys +; in TRKTAB. +; +; INITTAB is the initialization table for 86-DOS as described in the +; 86-DOS Programer's Manual under "Customizing the I/O System." +; + IF SCP*COMBIN*FASTSEEK +; +; A PerSci 277 or 299 and one 5.25-inch drive. +; +DRVTAB: DB 00H,08H,01H,09H,10H,18H,00H,08H,01H,09H +TRKPT: DB 0,0,0,0,1,1,0,0,0,0 +TRKTAB: DB -1,-1 +INITTAB: + IF CONVERT-1 + DB 6 ; Number of disk I/O drivers. + ENDIF + + IF CONVERT + DB 10 + ENDIF + + DB 0 ; Disk I/O driver 0 uses disk drive 0. + DW LSDRIVE ; Disk I/O driver 0 is 8-inch single-density. + DB 0 ; Disk I/O driver 1 uses disk drive 0. + DW LDDRIVE ; Disk I/O driver 1 is 8-inch double-density. + DB 1 ; Etc. + DW LSDRIVE + DB 1 + DW LDDRIVE + DB 2 + DW SSDRIVE + DB 2 + DW SDDRIVE + + IF CONVERT + DB 3 + DW OLDLSDRIVE + DB 3 + DW OLDLDDRIVE + DB 4 + DW OLDLSDRIVE + DB 4 + DW OLDLDDRIVE + ENDIF + ENDIF + + IF SCP*LARGE*FASTSEEK +; +; PerSci 277 or 299. +; +DRVTAB: DB 00H,08H,01H,09H,00H,08H,01H,09H +TRKPT: DB 0,0,0,0,0,0,0,0 +TRKTAB: DB -1 +INITTAB: + IF CONVERT-1 + DB 4 + ENDIF + + IF CONVERT + DB 8 + ENDIF + + DB 0 + DW LSDRIVE + DB 0 + DW LDDRIVE + DB 1 + DW LSDRIVE + DB 1 + DW LDDRIVE + + IF CONVERT + DB 2 + DW OLDLSDRIVE + DB 2 + DW OLDLDDRIVE + DB 3 + DW OLDLSDRIVE + DB 3 + DW OLDLDDRIVE + ENDIF + ENDIF + + IF TARBELLDD +; +; Two 8-inch Shugart-type drives. +; +DRVTAB: DB 0,8,10H,18H,0,8,10H,18H +TRKPT: DB 0,0,1,1,0,0,1,1 +TRKTAB: DB -1,-1 +INITTAB: + + IF CONVERT-1 + DB 4 + ENDIF + + IF CONVERT + DB 8 + ENDIF + + DB 0 + DW LSDRIVE + DB 0 + DW LDDRIVE + DB 1 + DW LSDRIVE + DB 1 + DW LDDRIVE + + IF CONVERT + DB 2 + DW OLDLSDRIVE + DB 2 + DW OLDLDDRIVE + DB 3 + DW OLDLSDRIVE + DB 3 + DW OLDLDDRIVE + ENDIF + ENDIF + + IF TARBELLSD +; +; Four 8-inch Shugart-type drives. +; +DRVTAB: DB 0F2H,0E2H,0F2H,0E2H +TRKPT: DB 0,1,0,1 +TRKTAB: DB -1,-1 +INITTAB: + + IF CONVERT-1 + DB 2 + ENDIF + + IF CONVERT + DB 4 + ENDIF + + DB 0 + DW LSDRIVE + DB 1 + DW LSDRIVE + + IF CONVERT + DB 2 + DW OLDLSDRIVE + DB 3 + DW OLDLSDRIVE + ENDIF + ENDIF +; +; Cromemco drive select byte is derived as follows: +; Bit 7 = 0 +; Bit 6 = 1 if double density (if 16FDC) +; Bit 5 = 1 (motor on) +; Bit 4 = 0 for 5", 1 for 8" drives +; Bit 3 = 1 for drive 3 +; Bit 2 = 1 for drive 2 +; Bit 1 = 1 for drive 1 +; Bit 0 = 1 for drive 0 +; + IF CROMEMCO4FDC*LARGE +; +; PerSci 277 drive. +; +DRVTAB: DB 31H,32H,31H,32H +TRKPT: DB 0,0,0,0 +TRKTAB: DB -1 +INITTAB: + + IF CONVERT-1 + DB 2 + ENDIF + + IF CONVERT + DB 4 + ENDIF + + DB 0 + DW LSDRIVE + DB 1 + DW LSDRIVE + + IF CONVERT + DB 2 + DW OLDLSDRIVE + DB 3 + DW OLDLSDRIVE + ENDIF + ENDIF + + IF CROMEMCO4FDC*COMBIN +; +; A PerSci 277 and one 5.25-inch drive. +; +DRVTAB: DB 31H,32H,24H,31H,32H +TRKPT: DB 0,0,1,0,0 +TRKTAB: DB -1,-1 +INITTAB: + + IF CONVERT-1 + DB 3 + ENDIF + + IF CONVERT + DB 5 + ENDIF + + DB 0 + DW LSDRIVE + DB 1 + DW LSDRIVE + DB 2 + DW SSDRIVE + + IF CONVERT + DB 3 + DW OLDLSDRIVE + DB 4 + DW OLDLSDRIVE + ENDIF + ENDIF + + IF CROMEMCO4FDC*SMALL +; +; Three 5.25-inch drives. +; +DRVTAB: DB 21H,22H,24H +TRKPT: DB 0,1,2 +TRKTAB: DB -1,-1,-1 +INITTAB:DB 3 + DB 0 + DW SSDRIVE + DB 1 + DW SSDRIVE + DB 2 + DW SSDRIVE + ENDIF + + IF CUSTOM +; +; Cromemco 4FDC with two 8-inch Shugart-type drives. +; +DRVTAB: DB 31H,32H,31H,32H +TRKPT: DB 0,1,0,1 +TRKTAB: DB -1,-1 +INITTAB: + IF CONVERT-1 + DB 2 + ENDIF + + IF CONVERT + DB 4 + ENDIF + + DB 0 + DW LSDRIVE + DB 1 + DW LSDRIVE + + IF CONVERT + DB 2 + DW OLDLSDRIVE + DB 3 + DW OLDLSDRIVE + ENDIF + ENDIF + + IF CROMEMCO16FDC*SMALL +; +; Three 5.25-inch drives. +; +DRVTAB: DB 21H,61H,22H,62H,24H,64H +TRKPT: DB 0,0,1,1,2,2 +TRKTAB: DB -1,-1,-1 +INITTAB:DB 6 + DB 0 + DW SSDRIVE + DB 0 + DW SDDRIVE + DB 1 + DW SSDRIVE + DB 1 + DW SDDRIVE + DB 2 + DW SSDRIVE + DB 2 + DW SDDRIVE + ENDIF + + IF CROMEMCO16FDC*COMBIN +; +; A PerSci 277 or 299 and one 5.25-inch drive. +; +DRVTAB: DB 31H,71H,32H,72H,24H,64H,31H,71H,32H,72H +TRKPT: DB 0,0,0,0,1,1,0,0,0,0 +TRKTAB: DB -1,-1 +INITTAB: + IF CONVERT-1 + DB 6 + ENDIF + + IF CONVERT + DB 10 + ENDIF + + DB 0 + DW LSDRIVE + DB 0 + DW LDDRIVE + DB 1 + DW LSDRIVE + DB 1 + DW LDDRIVE + DB 2 + DW SSDRIVE + DB 2 + DW SDDRIVE + + IF CONVERT + DB 3 + DW OLDLSDRIVE + DB 3 + DW OLDLDDRIVE + DB 4 + DW OLDLSDRIVE + DB 4 + DW OLDLDDRIVE + ENDIF + ENDIF + + IF CROMEMCO16FDC*LARGE +; +; A PerSci 277 or 299. +; +DRVTAB: DB 31H,71H,32H,72H,31H,71H,32H,72H +TRKPT: DB 0,0,0,0,0,0,0,0 +TRKTAB: DB -1 +INITTAB: + IF CONVERT-1 + DB 4 + ENDIF + + IF CONVERT + DB 8 + ENDIF + + DB 0 + DW LSDRIVE + DB 0 + DW LDDRIVE + DB 1 + DW LSDRIVE + DB 1 + DW LDDRIVE + + IF CONVERT + DB 2 + DW OLDLSDRIVE + DB 2 + DW OLDLDDRIVE + DB 3 + DW OLDLSDRIVE + DB 3 + DW OLDLDDRIVE + ENDIF + ENDIF + + IF SMALL+COMBIN +SSDRIVE: + DW 128 ; Sector size in bytes. + DB 2 ; Sector per allocation unit. + DW 54 ; Reserved sectors. + DB 2 ; Number of allocation tables. + DW 64 ; Number of directory entrys. + DW 720 ; Number of sectors on the disk. + + IF SMALLDS-1 +SDDRIVE: ; This is the IBM Personal Computer + DW 512 ; disk format. + DB 1 + DW 1 + DB 2 + DW 64 + DW 320 + ENDIF + + IF SMALLDS +SDDRIVE: + DW 512 + DB 2 + DW 1 + DB 2 + DW 112 + DW 640 + ENDIF + ENDIF ; End of small drive DPTs. + + IF COMBIN+LARGE +LSDRIVE: + DW 128 ; Size of sector in bytes. + DB 4 ; Sectors per allocation unit. + DW 1 ; Number of reserved sectors. + DB 2 ; Number of File Allocation Tables. + DW 68 ; Number of directory entrys. + DW 77*26 ; Number of sectors on the disk. + + IF CONVERT +OLDLSDRIVE: + DW 128 + DB 4 + DW 52 ; Old format had two tracks reserved. + DB 2 + DW 64 ; 64 directory entrys. + DW 77*26 + ENDIF + + IF LARGEDS-1 +OLDLDDRIVE: +LDDRIVE: + DW 1024 + DB 1 + DW 1 + DB 2 + DW 96 + DW 77*8 + ENDIF + + IF LARGEDS +LDDRIVE: + DW 1024 + DB 1 + DW 1 + DB 2 + DW 192 ; 192 directory entrys in new 8-inch DD/DS format. + DW 77*8*2 + + IF CONVERT +OLDLDDRIVE: + DW 1024 + DB 1 + DW 1 + DB 2 + DW 128 ; 128 directory entrys in old 8-inch DD/DS format. + DW 77*8*2 + ENDIF + ENDIF + + ENDIF ; End of large drive DPTs. + +DOSSEG: EQU ($+15)/16+BIOSSEG ; Compute segment to use for 86-DOS. +DOSDIF: EQU 16*(DOSSEG-BIOSSEG) +STKSAV: EQU 1701H+DOSDIF +DMAADD: EQU 15B4H+DOSDIF + END + \ No newline at end of file diff --git a/v1.25/source/MSDOS.ASM b/v1.25/source/MSDOS.ASM new file mode 100644 index 0000000..8538b76 --- /dev/null +++ b/v1.25/source/MSDOS.ASM @@ -0,0 +1,4031 @@ +; 86-DOS High-performance operating system for the 8086 version 1.25 +; by Tim Paterson + + +; ****************** Revision History ************************* +; >> EVERY change must noted below!! << +; +; 0.34 12/29/80 General release, updating all past customers +; 0.42 02/25/81 32-byte directory entries added +; 0.56 03/23/81 Variable record and sector sizes +; 0.60 03/27/81 Ctrl-C exit changes, including register save on user stack +; 0.74 04/15/81 Recognize I/O devices with file names +; 0.75 04/17/81 Improve and correct buffer handling +; 0.76 04/23/81 Correct directory size when not 2^N entries +; 0.80 04/27/81 Add console input without echo, Functions 7 & 8 +; 1.00 04/28/81 Renumber for general release +; 1.01 05/12/81 Fix bug in `STORE' +; 1.10 07/21/81 Fatal error trapping, NUL device, hidden files, date & time, +; RENAME fix, general cleanup +; 1.11 09/03/81 Don't set CURRENT BLOCK to 0 on open; fix SET FILE SIZE +; 1.12 10/09/81 Zero high half of CURRENT BLOCK after all (CP/M programs don't) +; 1.13 10/29/81 Fix classic "no write-through" error in buffer handling +; 1.20 12/31/81 Add time to FCB; separate FAT from DPT; Kill SMALLDIR; +; Add FLUSH and MAPDEV calls; allow disk mapping in DSKCHG; +; Lots of smaller improvements +; 1.21 01/06/82 HIGHMEM switch to run DOS in high memory +; 1.22 01/12/82 Add VERIFY system call to enable/disable verify after write +; 1.23 02/11/82 Add defaulting to parser; use variable escape character +; Don't zero extent field in IBM version (back to 1.01!) +; 1.24 03/01/82 Restore fcn. 27 to 1.0 level; add fcn. 28 +; 1.25 03/03/82 Put marker (00) at end of directory to speed searches +; +; ************************************************************* + + +; Interrupt Entry Points: + +; INTBASE: ABORT +; INTBASE+4: COMMAND +; INTBASE+8: BASE EXIT ADDRESS +; INTBASE+C: CONTROL-C ABORT +; INTBASE+10H: FATAL ERROR ABORT +; INTBASE+14H: BIOS DISK READ +; INTBASE+18H: BIOS DISK WRITE +; INTBASE+40H: Long jump to CALL entry point + + IF IBM +ESCCH EQU 0 +CANCEL EQU 1BH ;Cancel with ESC +TOGLINS EQU TRUE ;One key toggles insert mode +TOGLPRN EQU TRUE ;One key toggles printer echo +NUMDEV EQU 6 ;Include "COM1" as I/O device name +ZEROEXT EQU TRUE + ELSE +ESCCH EQU 1BH +CANCEL EQU "X"-"@" ;Cancel with Ctrl-X +TOGLINS EQU FALSE ;Separate keys for insert mode on and off +TOGLPRN EQU FALSE ;Separate keys for printer echo on and off +NUMDEV EQU 5 ;Number of I/O device names +ZEROEXT EQU FALSE + ENDIF + +MAXCALL EQU 36 +MAXCOM EQU 46 +INTBASE EQU 80H +INTTAB EQU 20H +ENTRYPOINTSEG EQU 0CH +ENTRYPOINT EQU INTBASE+40H +CONTC EQU INTTAB+3 +EXIT EQU INTBASE+8 +LONGJUMP EQU 0EAH +LONGCALL EQU 9AH +MAXDIF EQU 0FFFH +SAVEXIT EQU 10 + +; Field definition for FCBs + +FCBLOCK STRUC + DB 12 DUP (?) ;Drive code and name +EXTENT DW ? +RECSIZ DW ? ;Size of record (user settable) +FILSIZ DW ? ;Size of file in bytes +DRVBP DW ? ;BP for SEARCH FIRST and SEARCH NEXT +FDATE DW ? ;Date of last writing +FTIME DW ? ;Time of last writing +DEVID DB ? ;Device ID number, bits 0-5 + ;bit 7=0 for file, bit 7=1 for I/O device + ;If file, bit 6=0 if dirty + ;If I/O device, bit 6=0 if EOF (input) +FIRCLUS DW ? ;First cluster of file +LSTCLUS DW ? ;Last cluster accessed +CLUSPOS DW ? ;Position of last cluster accessed + DB ? ;Forces NR to offset 32 +NR DB ? ;Next record +RR DB 3 DUP (?) ;Random record +FCBLOCK ENDS +FILDIRENT = FILSIZ ;Used only by SEARCH FIRST and SEARCH NEXT + +; Description of 32-byte directory entry (same as returned by SEARCH FIRST +; and SEARCH NEXT, functions 17 and 18). +; +; Location bytes Description +; +; 0 11 File name and extension ( 0E5H if empty) +; 11 1 Attributes. Bits 1 or 2 make file hidden +; 12 10 Zero field (for expansion) +; 22 2 Time. Bits 0-4=seconds/2, bits 5-10=minute, 11-15=hour +; 24 2 Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 +; 26 2 First allocation unit ( < 4080 ) +; 28 4 File size, in bytes (LSB first, 30 bits max.) +; +; The File Allocation Table uses a 12-bit entry for each allocation unit on +; the disk. These entries are packed, two for every three bytes. The contents +; of entry number N is found by 1) multiplying N by 1.5; 2) adding the result +; to the base address of the Allocation Table; 3) fetching the 16-bit word at +; this address; 4) If N was odd (so that N*1.5 was not an integer), shift the +; word right four bits; 5) mask to 12 bits (AND with 0FFF hex). Entry number +; zero is used as an end-of-file trap in the OS and as a flag for directory +; entry size (if SMALLDIR selected). Entry 1 is reserved for future use. The +; first available allocation unit is assigned entry number two, and even +; though it is the first, is called cluster 2. Entries greater than 0FF8H are +; end of file marks; entries of zero are unallocated. Otherwise, the contents +; of a FAT entry is the number of the next cluster in the file. + + +; Field definition for Drive Parameter Block + +DPBLOCK STRUC +DEVNUM DB ? ;I/O driver number +DRVNUM DB ? ;Physical Unit number +SECSIZ DW ? ;Size of physical sector in bytes +CLUSMSK DB ? ;Sectors/cluster - 1 +CLUSSHFT DB ? ;Log2 of sectors/cluster +FIRFAT DW ? ;Starting record of FATs +FATCNT DB ? ;Number of FATs for this drive +MAXENT DW ? ;Number of directory entries +FIRREC DW ? ;First sector of first cluster +MAXCLUS DW ? ;Number of clusters on drive + 1 +FATSIZ DB ? ;Number of records occupied by FAT +FIRDIR DW ? ;Starting record of directory +FAT DW ? ;Pointer to start of FAT +DPBLOCK ENDS + +DPBSIZ EQU 20 ;Size of the structure in bytes +DIRSEC = FIRREC ;Number of dir. sectors (init temporary) +DSKSIZ = MAXCLUS ;Size of disk (temp used during init only) + +;The following are all of the segments used +;They are declared in the order that they should be placed in the executable + +CODE SEGMENT +CODE ENDS + +CONSTANTS SEGMENT BYTE +CONSTANTS ENDS + +DATA SEGMENT WORD +DATA ENDS + +DOSGROUP GROUP CODE,CONSTANTS,DATA + +SEGBIOS SEGMENT +SEGBIOS ENDS + + +; BOIS entry point definitions + + IF IBM +BIOSSEG EQU 60H + ENDIF + IF NOT IBM +BIOSSEG EQU 40H + ENDIF + +SEGBIOS SEGMENT AT BIOSSEG + ORG 0 + DB 3 DUP (?) ;Reserve room for jump to init code +BIOSSTAT DB 3 DUP (?) ;Console input status check +BIOSIN DB 3 DUP (?) ;Get console character +BIOSOUT DB 3 DUP (?) ;Output console character +BIOSPRINT DB 3 DUP (?) ;Output to printer +BIOSAUXIN DB 3 DUP (?) ;Get byte from auxilliary +BIOSAUXOUT DB 3 DUP (?) ;Output byte to auxilliary +BIOSREAD DB 3 DUP (?) ;Disk read +BIOSWRITE DB 3 DUP (?) ;Disk write +BIOSDSKCHG DB 3 DUP (?) ;Dsik-change status +BIOSSETDATE DB 3 DUP (?) ;Set date +BIOSSETTIME DB 3 DUP (?) ;Set time +BIOSGETTIME DB 3 DUP (?) ;Get time and date +BIOSFLUSH DB 3 DUP (?) ;Clear console input buffer +BIOSMAPDEV DB 3 DUP (?) ;Dynamic disk table mapper + +SEGBIOS ENDS +; Location of user registers relative user stack pointer + +STKPTRS STRUC +AXSAVE DW ? +BXSAVE DW ? +CXSAVE DW ? +DXSAVE DW ? +SISAVE DW ? +DISAVE DW ? +BPSAVE DW ? +DSSAVE DW ? +ESSAVE DW ? +IPSAVE DW ? +CSSAVE DW ? +FSAVE DW ? +STKPTRS ENDS + +; Start of code + +CODE SEGMENT +ASSUME CS:DOSGROUP,DS:DOSGROUP,ES:DOSGROUP,SS:DOSGROUP + + ORG 0 +CODSTRT EQU $ + JMP DOSINIT + +ESCCHAR DB ESCCH ;Lead-in character for escape sequences +ESCTAB: + IF NOT IBM + DB "S" ;Copy one char + DB "V" ;Skip one char + DB "T" ;Copy to char + DB "W" ;Skip to char + DB "U" ;Copy line + DB "E" ;Kill line (no change in template) + DB "J" ;Reedit line (new template) + DB "D" ;Backspace + DB "P" ;Enter insert mode + DB "Q" ;Exit insert mode + DB "R" ;Escape character + DB "R" ;End of table + ENDIF + IF IBM + DB 64 ;Crtl-Z - F6 + DB 77 ;Copy one char - --> + DB 59 ;Copy one char - F1 + DB 83 ;Skip one char - DEL + DB 60 ;Copy to char - F2 + DB 62 ;Skip to char - F4 + DB 61 ;Copy line - F3 + DB 61 ;Kill line (no change to template ) - Not used + DB 63 ;Reedit line (new template) - F5 + DB 75 ;Backspace - <-- + DB 82 ;Enter insert mode - INS (toggle) + DB 65 ;Escape character - F7 + DB 65 ;End of table + ENDIF + +ESCTABLEN EQU $-ESCTAB + IF NOT IBM +HEADER DB 13,10,"MS-DOS version 1.25" + IF HIGHMEM + DB "H" + ENDIF + IF DSKTEST + DB "D" + ENDIF + + DB 13,10 + DB "Copyright 1981,82 Microsoft, Inc.",13,10,"$" + ENDIF + +QUIT: + MOV AH,0 + JMP SHORT SAVREGS + +COMMAND: ;Interrupt call entry point + CMP AH,MAXCOM + JBE SAVREGS +BADCALL: + MOV AL,0 +IRET: IRET + +ENTRY: ;System call entry point and dispatcher + POP AX ;IP from the long call at 5 + POP AX ;Segment from the long call at 5 + POP CS:[TEMP] ;IP from the CALL 5 + PUSHF ;Start re-ordering the stack + CLI + PUSH AX ;Save segment + PUSH CS:[TEMP] ;Stack now ordered as if INT had been used + CMP CL,MAXCALL ;This entry point doesn't get as many calls + JA BADCALL + MOV AH,CL +SAVREGS: + PUSH ES + PUSH DS + PUSH BP + PUSH DI + PUSH SI + PUSH DX + PUSH CX + PUSH BX + PUSH AX + + IF DSKTEST + MOV AX,CS:[SPSAVE] + MOV CS:[NSP],AX + MOV AX,CS:[SSSAVE] + MOV CS:[NSS],AX + POP AX + PUSH AX + ENDIF + + MOV CS:[SPSAVE],SP + MOV CS:[SSSAVE],SS + MOV SP,CS + MOV SS,SP +REDISP: + MOV SP,OFFSET DOSGROUP:IOSTACK + STI ;Stack OK now + MOV BL,AH + MOV BH,0 + SHL BX,1 + CLD + CMP AH,12 + JLE SAMSTK + MOV SP,OFFSET DOSGROUP:DSKSTACK +SAMSTK: + CALL CS:[BX+DISPATCH] +LEAVE: + CLI + MOV SP,CS:[SPSAVE] + MOV SS,CS:[SSSAVE] + MOV BP,SP + MOV BYTE PTR [BP.AXSAVE],AL + + IF DSKTEST + MOV AX,CS:[NSP] + MOV CS:[SPSAVE],AX + MOV AX,CS:[NSS] + MOV CS:[SSSAVE],AX + ENDIF + + POP AX + POP BX + POP CX + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES + IRET +; Standard Functions +DISPATCH DW ABORT ;0 + DW CONIN + DW CONOUT + DW READER + DW PUNCH + DW LIST ;5 + DW RAWIO + DW RAWINP + DW IN + DW PRTBUF + DW BUFIN ;10 + DW CONSTAT + DW FLUSHKB + DW DSKRESET + DW SELDSK + DW OPEN ;15 + DW CLOSE + DW SRCHFRST + DW SRCHNXT + DW DELETE + DW SEQRD ;20 + DW SEQWRT + DW CREATE + DW RENAME + DW INUSE + DW GETDRV ;25 + DW SETDMA + DW GETFATPT + DW GETFATPTDL + DW GETRDONLY + DW SETATTRIB ;30 + DW GETDSKPT + DW USERCODE + DW RNDRD + DW RNDWRT + DW FILESIZE ;35 + DW SETRNDREC +; Extended Functions + DW SETVECT + DW NEWBASE + DW BLKRD + DW BLKWRT ;40 + DW MAKEFCB + DW GETDATE + DW SETDATE + DW GETTIME + DW SETTIME ;45 + DW VERIFY + +INUSE: +GETIO: +SETIO: +GETRDONLY: +SETATTRIB: +USERCODE: + MOV AL,0 + RET + +VERIFY: + AND AL,1 + MOV CS:VERFLG,AL + RET + +FLUSHKB: + PUSH AX + CALL FAR PTR BIOSFLUSH + POP AX + MOV AH,AL + CMP AL,1 + JZ REDISPJ + CMP AL,6 + JZ REDISPJ + CMP AL,7 + JZ REDISPJ + CMP AL,8 + JZ REDISPJ + CMP AL,10 + JZ REDISPJ + MOV AL,0 + RET + +REDISPJ:JMP REDISP + +READER: +AUXIN: + CALL STATCHK + CALL FAR PTR BIOSAUXIN + RET + +PUNCH: + MOV AL,DL +AUXOUT: + PUSH AX + CALL STATCHK + POP AX + CALL FAR PTR BIOSAUXOUT + RET + + +UNPACK: + +; Inputs: +; DS = CS +; BX = Cluster number +; BP = Base of drive parameters +; SI = Pointer to drive FAT +; Outputs: +; DI = Contents of FAT for given cluster +; Zero set means DI=0 (free cluster) +; No other registers affected. Fatal error if cluster too big. + + CMP BX,[BP.MAXCLUS] + JA HURTFAT + LEA DI,[SI+BX] + SHR BX,1 + MOV DI,[DI+BX] + JNC HAVCLUS + SHR DI,1 + SHR DI,1 + SHR DI,1 + SHR DI,1 + STC +HAVCLUS: + RCL BX,1 + AND DI,0FFFH + RET +HURTFAT: + PUSH AX + MOV AH,80H ;Signal Bad FAT to INT 24H handler + MOV DI,0FFFH ;In case INT 24H returns (it shouldn't) + CALL FATAL + POP AX ;Try to ignore bad FAT + RET + + +PACK: + +; Inputs: +; DS = CS +; BX = Cluster number +; DX = Data +; SI = Pointer to drive FAT +; Outputs: +; The data is stored in the FAT at the given cluster. +; BX,DX,DI all destroyed +; No other registers affected + + MOV DI,BX + SHR BX,1 + ADD BX,SI + ADD BX,DI + SHR DI,1 + MOV DI,[BX] + JNC ALIGNED + SHL DX,1 + SHL DX,1 + SHL DX,1 + SHL DX,1 + AND DI,0FH + JMP SHORT PACKIN +ALIGNED: + AND DI,0F000H +PACKIN: + OR DI,DX + MOV [BX],DI + RET + +DEVNAME: + MOV SI,OFFSET DOSGROUP:IONAME ;List of I/O devices with file names + MOV BH,NUMDEV ;BH = number of device names +LOOKIO: + MOV DI,OFFSET DOSGROUP:NAME1 + MOV CX,4 ;All devices are 4 letters + REPE CMPSB ;Check for name in list + JZ IOCHK ;If first 3 letters OK, check for the rest + ADD SI,CX ;Point to next device name + DEC BH + JNZ LOOKIO +CRET: + STC ;Not found + RET + +IOCHK: + IF IBM + CMP BH,NUMDEV ;Is it the first device? + JNZ NOTCOM1 + MOV BH,2 ;Make it the same as AUX +NOTCOM1: + ENDIF + NEG BH + MOV CX,2 ;Check rest of name but not extension + MOV AX,2020H + REPE SCASW ;Make sure rest of name is blanks + JNZ CRET +RET1: RET ;Zero set so CREATE works + +GETFILE: +; Same as GETNAME except ES:DI points to FCB on successful return + CALL MOVNAME + JC RET1 + PUSH DX + PUSH DS + CALL FINDNAME + POP ES + POP DI +RET2: RET + + +GETNAME: + +; Inputs: +; DS,DX point to FCB +; Function: +; Find file name in disk directory. First byte is +; drive number (0=current disk). "?" matches any +; character. +; Outputs: +; Carry set if file not found +; ELSE +; Zero set if attributes match (always except when creating) +; BP = Base of drive parameters +; DS = CS +; ES = CS +; BX = Pointer into directory buffer +; SI = Pointer to First Cluster field in directory entry +; [DIRBUF] has directory record with match +; [NAME1] has file name +; All other registers destroyed. + + CALL MOVNAME + JC RET2 ;Bad file name? +FINDNAME: + MOV AX,CS + MOV DS,AX + CALL DEVNAME + JNC RET2 + CALL STARTSRCH +CONTSRCH: + CALL GETENTRY + JC RET2 +SRCH: + MOV AH,BYTE PTR [BX] + OR AH,AH ;End of directory? + JZ FREE + CMP AH,[DELALL] ;Free entry? + JZ FREE + MOV SI,BX + MOV DI,OFFSET DOSGROUP:NAME1 + MOV CX,11 +WILDCRD: + REPE CMPSB + JZ FOUND + CMP BYTE PTR [DI-1],"?" + JZ WILDCRD +NEXTENT: + CALL NEXTENTRY + JNC SRCH +RET3: RET + +FREE: + CMP [ENTFREE],-1 ;Found a free entry before? + JNZ TSTALL ;If so, ignore this one + MOV CX,[LASTENT] + MOV [ENTFREE],CX +TSTALL: + CMP AH,[DELALL] ;At end of directory? + JZ NEXTENT ;No - continue search + STC ;Report not found + RET + +FOUND: +;Check if attributes allow finding it + MOV AH,[ATTRIB] ;Attributes of search + NOT AH + AND AH,[SI] ;Compare with attributes of file + ADD SI,15 + AND AH,6 ;Only look at bits 1 and 2 + JZ RET3 + TEST BYTE PTR [CREATING],-1 ;Pass back mismatch if creating + JZ NEXTENT ;Otherwise continue searching + RET + + +GETENTRY: + +; Inputs: +; [LASTENT] has previously searched directory entry +; Function: +; Locates next sequential directory entry in preparation for search +; Outputs: +; Carry set if none +; ELSE +; AL = Current directory block +; BX = Pointer to next directory entry in [DIRBUF] +; DX = Pointer to first byte after end of DIRBUF +; [LASTENT] = New directory entry number + + MOV AX,[LASTENT] + INC AX ;Start with next entry + CMP AX,[BP.MAXENT] + JAE NONE +GETENT: + MOV [LASTENT],AX + MOV CL,4 + SHL AX,CL + XOR DX,DX + SHL AX,1 + RCL DX,1 ;Account for overflow in last shift + MOV BX,[BP.SECSIZ] + AND BL,255-31 ;Must be multiple of 32 + DIV BX + MOV BX,DX ;Position within sector + MOV AH,[BP.DEVNUM] ;AL=Directory sector no. + CMP AX,[DIRBUFID] + JZ HAVDIRBUF + PUSH BX + CALL DIRREAD + POP BX +HAVDIRBUF: + MOV DX,OFFSET DOSGROUP:DIRBUF + ADD BX,DX + ADD DX,[BP.SECSIZ] + RET + +NEXTENTRY: + +; Inputs: +; Same as outputs of GETENTRY, above +; Function: +; Update AL, BX, and [LASTENT] for next directory entry. +; Carry set if no more. + + MOV DI,[LASTENT] + INC DI + CMP DI,[BP.MAXENT] + JAE NONE + MOV [LASTENT],DI + ADD BX,32 + CMP BX,DX + JB HAVIT + INC AL ;Next directory sector + PUSH DX ;Save limit + CALL DIRREAD + POP DX + MOV BX,OFFSET DOSGROUP:DIRBUF +HAVIT: + CLC + RET + +NONE: + CALL CHKDIRWRITE + STC +RET4: RET + + +DELETE: ; System call 19 + CALL MOVNAME + MOV AL,-1 + JC RET4 + MOV AL,CS:[ATTRIB] + AND AL,6 ;Look only at hidden bits + CMP AL,6 ;Both must be set + JNZ NOTALL + MOV CX,11 + MOV AL,"?" + MOV DI,OFFSET DOSGROUP:NAME1 + REPE SCASB ;See if name is *.* + JNZ NOTALL + MOV BYTE PTR CS:[DELALL],0 ;DEL *.* - flag deleting all +NOTALL: + CALL FINDNAME + MOV AL,-1 + JC RET4 + OR BH,BH ;Check if device name + JS RET4 ;Can't delete I/O devices +DELFILE: + MOV BYTE PTR [DIRTYDIR],-1 + MOV AH,[DELALL] + MOV BYTE PTR [BX],AH + MOV BX,[SI] + MOV SI,[BP.FAT] + OR BX,BX + JZ DELNXT + CMP BX,[BP.MAXCLUS] + JA DELNXT + CALL RELEASE +DELNXT: + CALL CONTSRCH + JNC DELFILE + CALL FATWRT + CALL CHKDIRWRITE + XOR AL,AL + RET + + +RENAME: ;System call 23 + CALL MOVNAME + JC ERRET + ADD SI,5 + MOV DI,OFFSET DOSGROUP:NAME2 + CALL LODNAME + JC ERRET ;Report error if second name invalid + CALL FINDNAME + JC ERRET + OR BH,BH ;Check if I/O device name + JS ERRET ;If so, can't rename it + MOV SI,OFFSET DOSGROUP:NAME1 + MOV DI,OFFSET DOSGROUP:NAME3 + MOV CX,6 ;6 words (12 bytes)--include attribute byte + REP MOVSW ;Copy name to search for +RENFIL: + MOV DI,OFFSET DOSGROUP:NAME1 + MOV SI,OFFSET DOSGROUP:NAME2 + MOV CX,11 +NEWNAM: + LODSB + CMP AL,"?" + JNZ NOCHG + MOV AL,[BX] +NOCHG: + STOSB + INC BX + LOOP NEWNAM + MOV BYTE PTR [DI],6 ;Stop duplicates with any attributes + CALL DEVNAME ;Check if giving it a device name + JNC RENERR + PUSH [LASTENT] ;Save position of match + MOV [LASTENT],-1 ;Search entire directory for duplicate + CALL CONTSRCH ;See if new name already exists + POP AX + JNC RENERR ;Error if found + CALL GETENT ;Re-read matching entry + MOV DI,BX + MOV SI,OFFSET DOSGROUP:NAME1 + MOV CX,5 + MOVSB + REP MOVSW ;Replace old name with new one + MOV BYTE PTR [DIRTYDIR],-1 ;Flag change in directory + MOV SI,OFFSET DOSGROUP:NAME3 + MOV DI,OFFSET DOSGROUP:NAME1 + MOV CX,6 ;Include attribute byte + REP MOVSW ;Copy name back into search buffer + CALL CONTSRCH + JNC RENFIL + CALL CHKDIRWRITE + XOR AL,AL + RET + +RENERR: + CALL CHKDIRWRITE +ERRET: + MOV AL,-1 +RET5: RET + + +MOVNAME: + +; Inputs: +; DS, DX point to FCB or extended FCB +; Outputs: +; DS:DX point to normal FCB +; ES = CS +; If file name OK: +; BP has base of driver parameters +; [NAME1] has name in upper case +; All registers except DX destroyed +; Carry set if bad file name or drive + + MOV CS:WORD PTR [CREATING],0E500H ;Not creating, not DEL *.* + MOV AX,CS + MOV ES,AX + MOV DI,OFFSET DOSGROUP:NAME1 + MOV SI,DX + LODSB + MOV CS:[EXTFCB],AL ;Set flag if extended FCB in use + MOV AH,0 ;Set default attributes + CMP AL,-1 ;Is it an extended FCB? + JNZ HAVATTRB + ADD DX,7 ;Adjust to point to normal FCB + ADD SI,6 ;Point to drive select byte + MOV AH,[SI-1] ;Get attribute byte + LODSB ;Get drive select byte +HAVATTRB: + MOV CS:[ATTRIB],AH ;Save attributes + CALL GETTHISDRV +LODNAME: +; This entry point copies a file name from DS,SI +; to ES,DI converting to upper case. + CMP BYTE PTR [SI]," " ;Don't allow blank as first letter + STC ;In case of error + JZ RET5 + MOV CX,11 +MOVCHK: + CALL GETLET + JB RET5 + JNZ STOLET ;Is it a delimiter? + CMP AL," " ;This is the only delimiter allowed + STC ;In case of error + JNZ RET5 +STOLET: + STOSB + LOOP MOVCHK + CLC ;Got through whole name - no error +RET6: RET + +GETTHISDRV: + CMP CS:[NUMDRV],AL + JC RET6 + DEC AL + JNS PHYDRV + MOV AL,CS:[CURDRV] +PHYDRV: + MOV CS:[THISDRV],AL + RET + + +OPEN: ;System call 15 + CALL GETFILE +DOOPEN: +; Enter here to perform OPEN on file already found +; in directory. DS=CS, BX points to directory +; entry in DIRBUF, SI points to First Cluster field, and +; ES:DI point to the FCB to be opened. This entry point +; is used by CREATE. + JC ERRET + OR BH,BH ;Check if file is I/O device + JS OPENDEV ;Special handler if so + MOV AL,[THISDRV] + INC AX + STOSB + XOR AX,AX + IF ZEROEXT + ADD DI,11 + STOSW ;Zero low byte of extent field if IBM only + ENDIF + IF NOT ZEROEXT + ADD DI,12 ;Point to high half of CURRENT BLOCK field + STOSB ;Set it to zero (CP/M programs set low byte) + ENDIF + MOV AL,128 ;Default record size + STOSW ;Set record size + LODSW ;Get starting cluster + MOV DX,AX ;Save it for the moment + MOVSW ;Transfer size to FCB + MOVSW + MOV AX,[SI-8] ;Get date + STOSW ;Save date in FCB + MOV AX,[SI-10] ;Get time + STOSW ;Save it in FCB + MOV AL,[BP.DEVNUM] + OR AL,40H + STOSB + MOV AX,DX ;Restore starting cluster + STOSW ; first cluster + STOSW ; last cluster accessed + XOR AX,AX + STOSW ; position of last cluster + RET + + +OPENDEV: + ADD DI,13 ;point to 2nd half of extent field + XOR AX,AX + STOSB ;Set it to zero + MOV AL,128 + STOSW ;Set record size to 128 + XOR AX,AX + STOSW + STOSW ;Set current size to zero + CALL DATE16 + STOSW ;Date is todays + XCHG AX,DX + STOSW ;Use current time + MOV AL,BH ;Get device number + STOSB + XOR AL,AL ;No error + RET +FATERR: + XCHG AX,DI ;Put error code in DI + MOV AH,2 ;While trying to read FAT + MOV AL,[THISDRV] ;Tell which drive + CALL FATAL1 + JMP SHORT FATREAD +STARTSRCH: + MOV AX,-1 + MOV [LASTENT],AX + MOV [ENTFREE],AX +FATREAD: + +; Inputs: +; DS = CS +; Function: +; If disk may have been changed, FAT is read in and buffers are +; flagged invalid. If not, no action is taken. +; Outputs: +; BP = Base of drive parameters +; Carry set if invalid drive returned by MAPDEV +; All other registers destroyed + + MOV AL,[THISDRV] + XOR AH,AH ;Set default response to zero & clear carry + CALL FAR PTR BIOSDSKCHG ;See what BIOS has to say + JC FATERR + CALL GETBP + MOV AL,[THISDRV] ;Use physical unit number + MOV SI,[BP.FAT] + OR AH,[SI-1] ;Dirty byte for FAT + JS NEWDSK ;If either say new disk, then it's so + JNZ MAPDRV + MOV AH,1 + CMP AX,WORD PTR [BUFDRVNO] ;Does buffer have dirty sector of this drive? + JZ MAPDRV +NEWDSK: + CMP AL,[BUFDRVNO] ;See if buffer is for this drive + JNZ BUFOK ;If not, don't touch it + MOV [BUFSECNO],0 ;Flag buffers invalid + MOV WORD PTR [BUFDRVNO],00FFH +BUFOK: + MOV [DIRBUFID],-1 + CALL FIGFAT +NEXTFAT: + PUSH AX + CALL DSKREAD + POP AX + JC BADFAT + SUB AL,[BP.FATCNT] + JZ NEWFAT + CALL FATWRT +NEWFAT: + MOV SI,[BP.FAT] + MOV AL,[BP.DEVNUM] + MOV AH,[SI] ;Get first byte of FAT + OR AH,0F8H ;Put in range + CALL FAR PTR BIOSMAPDEV + MOV AH,0 + MOV [SI-2],AX ;Set device no. and reset dirty bit +MAPDRV: + MOV AL,[SI-2] ;Get device number +GETBP: + MOV BP,[DRVTAB] ;Just in case drive isn't valid + AND AL,3FH ;Mask out dirty bit + CMP AL,[NUMIO] + CMC + JC RET7 + PUSH AX + MOV AH,DPBSIZ + MUL AH + ADD BP,AX + POP AX +RET7: RET + +BADFAT: + MOV CX,DI + ADD DX,CX + DEC AL + JNZ NEXTFAT + CALL FIGFAT ;Reset registers + CALL DREAD ;Try first FAT once more + JMP SHORT NEWFAT + +OKRET1: + MOV AL,0 + RET + +CLOSE: ;System call 16 + MOV DI,DX + CMP BYTE PTR [DI],-1 ;Check for extended FCB + JNZ NORMFCB3 + ADD DI,7 +NORMFCB3: + TEST BYTE PTR [DI.DEVID],0C0H ;Allow only dirty files + JNZ OKRET1 ;can't close if I/O device, or not writen + MOV AL,[DI] ;Get physical unit number + DEC AL ;Make zero = drive A + MOV AH,1 ;Look for dirty buffer + CMP AX,CS:WORD PTR [BUFDRVNO] + JNZ FNDDIR +;Write back dirty buffer if on same drive + PUSH DX + PUSH DS + PUSH CS + POP DS + MOV BYTE PTR [DIRTYBUF],0 + MOV BX,[BUFFER] + MOV CX,1 + MOV DX,[BUFSECNO] + MOV BP,[BUFDRVBP] + CALL DWRITE + POP DS + POP DX +FNDDIR: + CALL GETFILE +BADCLOSEJ: + JC BADCLOSE + MOV CX,ES:[DI.FIRCLUS] + MOV [SI],CX + MOV DX,ES:WORD PTR [DI.FILSIZ] + MOV [SI+2],DX + MOV DX,ES:WORD PTR [DI.FILSIZ+2] + MOV [SI+4],DX + MOV DX,ES:[DI.FDATE] + MOV [SI-2],DX + MOV DX,ES:[DI.FTIME] + MOV [SI-4],DX + CALL DIRWRITE + +CHKFATWRT: +; Do FATWRT only if FAT is dirty and uses same I/O driver + MOV SI,[BP.FAT] + MOV AL,[BP.DEVNUM] + MOV AH,1 + CMP [SI-2],AX ;See if FAT dirty and uses same driver + JNZ OKRET + +FATWRT: + +; Inputs: +; DS = CS +; BP = Base of drive parameter table +; Function: +; Write the FAT back to disk and reset FAT +; dirty bit. +; Outputs: +; AL = 0 +; BP unchanged +; All other registers destroyed + + CALL FIGFAT + MOV BYTE PTR [BX-1],0 +EACHFAT: + PUSH DX + PUSH CX + PUSH BX + PUSH AX + CALL DWRITE + POP AX + POP BX + POP CX + POP DX + ADD DX,CX + DEC AL + JNZ EACHFAT +OKRET: + MOV AL,0 + RET + +BADCLOSE: + MOV SI,[BP.FAT] + MOV BYTE PTR [SI-1],0 + MOV AL,-1 + RET + + +FIGFAT: +; Loads registers with values needed to read or +; write a FAT. + MOV AL,[BP.FATCNT] + MOV BX,[BP.FAT] + MOV CL,[BP.FATSIZ] ;No. of records occupied by FAT + MOV CH,0 + MOV DX,[BP.FIRFAT] ;Record number of start of FATs + RET + + +DIRCOMP: +; Prepare registers for directory read or write + CBW + ADD AX,[BP.FIRDIR] + MOV DX,AX + MOV BX,OFFSET DOSGROUP:DIRBUF + MOV CX,1 + RET + + +CREATE: ;System call 22 + CALL MOVNAME + JC ERRET3 + MOV DI,OFFSET DOSGROUP:NAME1 + MOV CX,11 + MOV AL,"?" + REPNE SCASB + JZ ERRET3 + MOV CS:BYTE PTR [CREATING],-1 + PUSH DX + PUSH DS + CALL FINDNAME + JNC EXISTENT + MOV AX,[ENTFREE] ;First free entry found in FINDNAME + CMP AX,-1 + JZ ERRPOP + CALL GETENT ;Point at that free entry + JMP SHORT FREESPOT +ERRPOP: + POP DS + POP DX +ERRET3: + MOV AL,-1 + RET + +EXISTENT: + JNZ ERRPOP ;Error if attributes don't match + OR BH,BH ;Check if file is I/O device + JS OPENJMP ;If so, no action + MOV CX,[SI] ;Get pointer to clusters + JCXZ FREESPOT + CMP CX,[BP.MAXCLUS] + JA FREESPOT + PUSH BX + MOV BX,CX + MOV SI,[BP.FAT] + CALL RELEASE ;Free any data already allocated + CALL FATWRT + POP BX +FREESPOT: + MOV DI,BX + MOV SI,OFFSET DOSGROUP:NAME1 + MOV CX,5 + MOVSB + REP MOVSW + MOV AL,[ATTRIB] + STOSB + XOR AX,AX + MOV CL,5 + REP STOSW + CALL DATE16 + XCHG AX,DX + STOSW + XCHG AX,DX + STOSW + XOR AX,AX + PUSH DI + MOV CL,6 +SMALLENT: + REP STOSB + PUSH BX + CALL DIRWRITE + POP BX + POP SI +OPENJMP: + CLC ;Clear carry so OPEN won't fail + POP ES + POP DI + JMP DOOPEN + + +DIRREAD: + +; Inputs: +; DS = CS +; AL = Directory block number +; BP = Base of drive parameters +; Function: +; Read the directory block into DIRBUF. +; Outputs: +; AX,BP unchanged +; All other registers destroyed. + + PUSH AX + CALL CHKDIRWRITE + POP AX + PUSH AX + MOV AH,[BP.DEVNUM] + MOV [DIRBUFID],AX + CALL DIRCOMP + CALL DREAD + POP AX +RET8: RET + + +DREAD: + +; Inputs: +; BX,DS = Transfer address +; CX = Number of sectors +; DX = Absolute record number +; BP = Base of drive parameters +; Function: +; Calls BIOS to perform disk read. If BIOS reports +; errors, will call HARDERR for further action. +; BP preserved. All other registers destroyed. + + CALL DSKREAD + JNC RET8 + MOV CS:BYTE PTR [READOP],0 + CALL HARDERR + CMP AL,1 ;Check for retry + JZ DREAD + RET ;Ignore otherwise + + +HARDERR: + +;Hard disk error handler. Entry conditions: +; DS:BX = Original disk transfer address +; DX = Original logical sector number +; CX = Number of sectors to go (first one gave the error) +; AX = Hardware error code +; DI = Original sector transfer count +; BP = Base of drive parameters +; [READOP] = 0 for read, 1 for write + + XCHG AX,DI ;Error code in DI, count in AX + SUB AX,CX ;Number of sectors successfully transferred + ADD DX,AX ;First sector number to retry + PUSH DX + MUL [BP.SECSIZ] ;Number of bytes transferred + POP DX + ADD BX,AX ;First address for retry + MOV AH,0 ;Flag disk section in error + CMP DX,[BP.FIRFAT] ;In reserved area? + JB ERRINT + INC AH ;Flag for FAT + CMP DX,[BP.FIRDIR] ;In FAT? + JB ERRINT + INC AH + CMP DX,[BP.FIRREC] ;In directory? + JB ERRINT + INC AH ;Must be in data area +ERRINT: + SHL AH,1 ;Make room for read/write bit + OR AH,CS:[READOP] +FATAL: + MOV AL,[BP.DRVNUM] ;Get drive number +FATAL1: + PUSH BP ;The only thing we preserve + MOV CS:[CONTSTK],SP + CLI ;Prepare to play with stack + MOV SS,CS:[SSSAVE] + MOV SP,CS:[SPSAVE] ;User stack pointer restored + INT 24H ;Fatal error interrupt vector + MOV CS:[SPSAVE],SP + MOV CS:[SSSAVE],SS + MOV SP,CS + MOV SS,SP + MOV SP,CS:[CONTSTK] + STI + POP BP + CMP AL,2 + JZ ERROR + RET + +DSKREAD: + MOV AL,[BP.DEVNUM] + PUSH BP + PUSH BX + PUSH CX + PUSH DX + CALL FAR PTR BIOSREAD + POP DX + POP DI + POP BX + POP BP +RET9: RET + + +CHKDIRWRITE: + TEST BYTE PTR [DIRTYDIR],-1 + JZ RET9 + +DIRWRITE: + +; Inputs: +; DS = CS +; AL = Directory block number +; BP = Base of drive parameters +; Function: +; Write the directory block into DIRBUF. +; Outputs: +; BP unchanged +; All other registers destroyed. + + MOV BYTE PTR [DIRTYDIR],0 + MOV AL,BYTE PTR [DIRBUFID] + CALL DIRCOMP + + +DWRITE: + +; Inputs: +; BX,DS = Transfer address +; CX = Number of sectors +; DX = Absolute record number +; BP = Base of drive parameters +; Function: +; Calls BIOS to perform disk write. If BIOS reports +; errors, will call HARDERR for further action. +; BP preserved. All other registers destroyed. + + MOV AL,[BP.DEVNUM] + MOV AH,CS:VERFLG + PUSH BP + PUSH BX + PUSH CX + PUSH DX + CALL FAR PTR BIOSWRITE + POP DX + POP DI + POP BX + POP BP + JNC RET9 + MOV CS:BYTE PTR [READOP],1 + CALL HARDERR + CMP AL,1 ;Check for retry + JZ DWRITE + RET + + +ABORT: + LDS SI,CS:DWORD PTR [SPSAVE] + MOV DS,[SI.CSSAVE] + XOR AX,AX + MOV ES,AX + MOV SI,SAVEXIT + MOV DI,EXIT + MOVSW + MOVSW + MOVSW + MOVSW + MOVSW + MOVSW +ERROR: + MOV AX,CS + MOV DS,AX + MOV ES,AX + CALL WRTFATS + XOR AX,AX + CLI + MOV SS,[SSSAVE] + MOV SP,[SPSAVE] + MOV DS,AX + MOV SI,EXIT + MOV DI,OFFSET DOSGROUP:EXITHOLD + MOVSW + MOVSW + POP AX + POP BX + POP CX + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES + STI ;Stack OK now + JMP CS:DWORD PTR [EXITHOLD] + + +SEQRD: ;System call 20 + CALL GETREC + CALL LOAD + JMP SHORT FINSEQ + +SEQWRT: ;System call 21 + CALL GETREC + CALL STORE +FINSEQ: + JCXZ SETNREX + ADD AX,1 + ADC DX,0 + JMP SHORT SETNREX + +RNDRD: ;System call 33 + CALL GETRRPOS1 + CALL LOAD + JMP SHORT FINRND + +RNDWRT: ;System call 34 + CALL GETRRPOS1 + CALL STORE + JMP SHORT FINRND + +BLKRD: ;System call 39 + CALL GETRRPOS + CALL LOAD + JMP SHORT FINBLK + +BLKWRT: ;System call 40 + CALL GETRRPOS + CALL STORE +FINBLK: + LDS SI,DWORD PTR [SPSAVE] + MOV [SI.CXSAVE],CX + JCXZ FINRND + ADD AX,1 + ADC DX,0 +FINRND: + MOV ES:WORD PTR [DI.RR],AX + MOV ES:[DI.RR+2],DL + OR DH,DH + JZ SETNREX + MOV ES:[DI.RR+3],DH ;Save 4 byte of RECPOS only if significant +SETNREX: + MOV CX,AX + AND AL,7FH + MOV ES:[DI.NR],AL + AND CL,80H + SHL CX,1 + RCL DX,1 + MOV AL,CH + MOV AH,DL + MOV ES:[DI.EXTENT],AX + MOV AL,CS:[DSKERR] + RET + +GETRRPOS1: + MOV CX,1 +GETRRPOS: + MOV DI,DX + CMP BYTE PTR [DI],-1 + JNZ NORMFCB1 + ADD DI,7 +NORMFCB1: + MOV AX,WORD PTR [DI.RR] + MOV DX,WORD PTR [DI.RR+2] + RET + +NOFILERR: + XOR CX,CX + MOV BYTE PTR [DSKERR],4 + POP BX + RET + +SETUP: + +; Inputs: +; DS:DI point to FCB +; DX:AX = Record position in file of disk transfer +; CX = Record count +; Outputs: +; DS = CS +; ES:DI point to FCB +; BL = DEVID from FCB +; CX = No. of bytes to transfer +; BP = Base of drive parameters +; SI = FAT pointer +; [RECCNT] = Record count +; [RECPOS] = Record position in file +; [FCB] = DI +; [NEXTADD] = Displacement of disk transfer within segment +; [SECPOS] = Position of first sector +; [BYTPOS] = Byte position in file +; [BYTSECPOS] = Byte position in first sector +; [CLUSNUM] = First cluster +; [SECCLUSPOS] = Sector within first cluster +; [DSKERR] = 0 (no errors yet) +; [TRANS] = 0 (No transfers yet) +; [THISDRV] = Physical drive unit number +; If SETUP detects no records will be transfered, it returns 1 level up +; with CX = 0. + + PUSH AX + MOV AL,[DI] + DEC AL + MOV CS:[THISDRV],AL + MOV AL,[DI.DEVID] + MOV SI,[DI.RECSIZ] + OR SI,SI + JNZ HAVRECSIZ + MOV SI,128 + MOV [DI.RECSIZ],SI +HAVRECSIZ: + PUSH DS + POP ES ;Set ES to DS + PUSH CS + POP DS ;Set DS to CS + OR AL,AL ;Is it a device? + JNS NOTDEVICE + MOV AL,0 ;Fake in drive 0 so we can get SP +NOTDEVICE: + CALL GETBP + POP AX + JC NOFILERR + CMP SI,64 ;Check if highest byte of RECPOS is significant + JB SMALREC + MOV DH,0 ;Ignore MSB if record >= 64 bytes +SMALREC: + MOV [RECCNT],CX + MOV WORD PTR [RECPOS],AX + MOV WORD PTR [RECPOS+2],DX + MOV [FCB],DI + MOV BX,[DMAADD] + MOV [NEXTADD],BX + MOV BYTE PTR [DSKERR],0 + MOV BYTE PTR [TRANS],0 + MOV BX,DX + MUL SI + MOV WORD PTR [BYTPOS],AX + PUSH DX + MOV AX,BX + MUL SI + POP BX + ADD AX,BX + ADC DX,0 ;Ripple carry + JNZ EOFERR + MOV WORD PTR [BYTPOS+2],AX + MOV DX,AX + MOV AX,WORD PTR [BYTPOS] + MOV BX,[BP.SECSIZ] + CMP DX,BX ;See if divide will overflow + JNC EOFERR + DIV BX + MOV [SECPOS],AX + MOV [BYTSECPOS],DX + MOV DX,AX + AND AL,[BP.CLUSMSK] + MOV [SECCLUSPOS],AL + MOV AX,CX ;Record count + MOV CL,[BP.CLUSSHFT] + SHR DX,CL + MOV [CLUSNUM],DX + MUL SI ;Multiply by bytes per record + MOV CX,AX + ADD AX,[DMAADD] ;See if it will fit in one segment + ADC DX,0 + JZ OK ;Must be less than 64K + MOV AX,[DMAADD] + NEG AX ;Amount of room left in segment + JNZ PARTSEG ;All 64K available? + DEC AX ;If so, reduce by one +PARTSEG: + XOR DX,DX + DIV SI ;How many records will fit? + MOV [RECCNT],AX + MUL SI ;Translate that back into bytes + MOV BYTE PTR [DSKERR],2 ;Flag that trimming took place + MOV CX,AX + JCXZ NOROOM +OK: + MOV BL,ES:[DI.DEVID] + MOV SI,[BP.FAT] + RET + +EOFERR: + MOV BYTE PTR [DSKERR],1 + XOR CX,CX +NOROOM: + POP BX ;Kill return address + RET + +BREAKDOWN: + +;Inputs: +; DS = CS +; CX = Length of disk transfer in bytes +; BP = Base of drive parameters +; [BYTSECPOS] = Byte position witin first sector +;Outputs: +; [BYTCNT1] = Bytes to transfer in first sector +; [SECCNT] = No. of whole sectors to transfer +; [BYTCNT2] = Bytes to transfer in last sector +;AX, BX, DX destroyed. No other registers affected. + + MOV AX,[BYTSECPOS] + MOV BX,CX + OR AX,AX + JZ SAVFIR ;Partial first sector? + SUB AX,[BP.SECSIZ] + NEG AX ;Max number of bytes left in first sector + SUB BX,AX ;Subtract from total length + JAE SAVFIR + ADD AX,BX ;Don't use all of the rest of the sector + XOR BX,BX ;And no bytes are left +SAVFIR: + MOV [BYTCNT1],AX + MOV AX,BX + XOR DX,DX + DIV [BP.SECSIZ] ;How many whole sectors? + MOV [SECCNT],AX + MOV [BYTCNT2],DX ;Bytes remaining for last sector +RET10: RET + + +FNDCLUS: + +; Inputs: +; DS = CS +; CX = No. of clusters to skip +; BP = Base of drive parameters +; SI = FAT pointer +; ES:DI point to FCB +; Outputs: +; BX = Last cluster skipped to +; CX = No. of clusters remaining (0 unless EOF) +; DX = Position of last cluster +; DI destroyed. No other registers affected. + + MOV BX,ES:[DI.LSTCLUS] + MOV DX,ES:[DI.CLUSPOS] + OR BX,BX + JZ NOCLUS + SUB CX,DX + JNB FINDIT + ADD CX,DX + XOR DX,DX + MOV BX,ES:[DI.FIRCLUS] +FINDIT: + JCXZ RET10 +SKPCLP: + CALL UNPACK + CMP DI,0FF8H + JAE RET10 + XCHG BX,DI + INC DX + LOOP SKPCLP + RET +NOCLUS: + INC CX + DEC DX + RET + + +BUFSEC: +; Inputs: +; AL = 0 if buffer must be read, 1 if no pre-read needed +; BP = Base of drive parameters +; [CLUSNUM] = Physical cluster number +; [SECCLUSPOS] = Sector position of transfer within cluster +; [BYTCNT1] = Size of transfer +; Function: +; Insure specified sector is in buffer, flushing buffer before +; read if necessary. +; Outputs: +; SI = Pointer to buffer +; DI = Pointer to transfer address +; CX = Number of bytes +; [NEXTADD] updated +; [TRANS] set to indicate a transfer will occur + + MOV DX,[CLUSNUM] + MOV BL,[SECCLUSPOS] + CALL FIGREC + MOV [PREREAD],AL + CMP DX,[BUFSECNO] + JNZ GETSEC + MOV AL,[BUFDRVNO] + CMP AL,[THISDRV] + JZ FINBUF ;Already have it? +GETSEC: + XOR AL,AL + XCHG [DIRTYBUF],AL ;Read dirty flag and reset it + OR AL,AL + JZ RDSEC + PUSH DX + PUSH BP + MOV BP,[BUFDRVBP] + MOV BX,[BUFFER] + MOV CX,1 + MOV DX,[BUFSECNO] + CALL DWRITE + POP BP + POP DX +RDSEC: + TEST BYTE PTR [PREREAD],-1 + JNZ SETBUF + XOR AX,AX + MOV [BUFSECNO],AX ;Set buffer valid in case of disk error + DEC AX + MOV [BUFDRVNO],AL + MOV BX,[BUFFER] + MOV CX,1 + PUSH DX + CALL DREAD + POP DX +SETBUF: + MOV [BUFSECNO],DX + MOV AL,[THISDRV] + MOV [BUFDRVNO],AL + MOV [BUFDRVBP],BP +FINBUF: + MOV BYTE PTR [TRANS],1 ;A transfer is taking place + MOV DI,[NEXTADD] + MOV SI,DI + MOV CX,[BYTCNT1] + ADD SI,CX + MOV [NEXTADD],SI + MOV SI,[BUFFER] + ADD SI,[BYTSECPOS] + RET + +BUFRD: + XOR AL,AL ;Pre-read necessary + CALL BUFSEC + PUSH ES + MOV ES,[DMAADD+2] + SHR CX,1 + JNC EVENRD + MOVSB +EVENRD: + REP MOVSW + POP ES + RET + +BUFWRT: + MOV AX,[SECPOS] + INC AX ;Set for next sector + MOV [SECPOS],AX + CMP AX,[VALSEC] ;Has sector been written before? + MOV AL,1 + JA NOREAD ;Skip preread if SECPOS>VALSEC + MOV AL,0 +NOREAD: + CALL BUFSEC + XCHG DI,SI + PUSH DS + PUSH ES + PUSH CS + POP ES + MOV DS,[DMAADD+2] + SHR CX,1 + JNC EVENWRT + MOVSB +EVENWRT: + REP MOVSW + POP ES + POP DS + MOV BYTE PTR [DIRTYBUF],1 + RET + +NEXTSEC: + TEST BYTE PTR [TRANS],-1 + JZ CLRET + MOV AL,[SECCLUSPOS] + INC AL + CMP AL,[BP.CLUSMSK] + JBE SAVPOS + MOV BX,[CLUSNUM] + CMP BX,0FF8H + JAE NONEXT + MOV SI,[BP.FAT] + CALL UNPACK + MOV [CLUSNUM],DI + INC [LASTPOS] + MOV AL,0 +SAVPOS: + MOV [SECCLUSPOS],AL +CLRET: + CLC + RET +NONEXT: + STC + RET + +TRANBUF: + LODSB + STOSB + CMP AL,13 ;Check for carriage return + JNZ NORMCH + MOV BYTE PTR [SI],10 +NORMCH: + CMP AL,10 + LOOPNZ TRANBUF + JNZ ENDRDCON + CALL OUT ;Transmit linefeed + XOR SI,SI + OR CX,CX + JNZ GETBUF + OR AL,1 ;Clear zero flag--not end of file +ENDRDCON: + MOV [CONTPOS],SI +ENDRDDEV: + MOV [NEXTADD],DI + POP ES + JNZ SETFCBJ ;Zero set if Ctrl-Z found in input + MOV DI,[FCB] + AND ES:BYTE PTR [DI.DEVID],0FFH-40H ;Mark as no more data available +SETFCBJ: + JMP SETFCB + +READDEV: + PUSH ES + LES DI,DWORD PTR [DMAADD] + INC BL + JZ READCON + INC BL + JNZ ENDRDDEV +READAUX: + CALL AUXIN + STOSB + CMP AL,1AH + LOOPNZ READAUX + JMP SHORT ENDRDDEV + +READCON: + PUSH CS + POP DS + MOV SI,[CONTPOS] + OR SI,SI + JNZ TRANBUF + CMP BYTE PTR [CONBUF],128 + JZ GETBUF + MOV WORD PTR [CONBUF],0FF80H ;Set up 128-byte buffer with no template +GETBUF: + PUSH CX + PUSH ES + PUSH DI + MOV DX,OFFSET DOSGROUP:CONBUF + CALL BUFIN ;Get input buffer + POP DI + POP ES + POP CX + MOV SI,2 + OFFSET DOSGROUP:CONBUF + CMP BYTE PTR [SI],1AH ;Check for Ctrl-Z in first character + JNZ TRANBUF + MOV AL,1AH + STOSB + MOV AL,10 + CALL OUT ;Send linefeed + XOR SI,SI + JMP SHORT ENDRDCON + +RDERR: + XOR CX,CX + JMP WRTERR + +RDLASTJ:JMP RDLAST + +LOAD: + +; Inputs: +; DS:DI point to FCB +; DX:AX = Position in file to read +; CX = No. of records to read +; Outputs: +; DX:AX = Position of last record read +; CX = No. of bytes read +; ES:DI point to FCB +; LSTCLUS, CLUSPOS fields in FCB set + + CALL SETUP + OR BL,BL ;Check for named device I/O + JS READDEV + MOV AX,ES:WORD PTR [DI.FILSIZ] + MOV BX,ES:WORD PTR [DI.FILSIZ+2] + SUB AX,WORD PTR [BYTPOS] + SBB BX,WORD PTR [BYTPOS+2] + JB RDERR + JNZ ENUF + OR AX,AX + JZ RDERR + CMP AX,CX + JAE ENUF + MOV CX,AX +ENUF: + CALL BREAKDOWN + MOV CX,[CLUSNUM] + CALL FNDCLUS + OR CX,CX + JNZ RDERR + MOV [LASTPOS],DX + MOV [CLUSNUM],BX + CMP [BYTCNT1],0 + JZ RDMID + CALL BUFRD +RDMID: + CMP [SECCNT],0 + JZ RDLASTJ + CALL NEXTSEC + JC SETFCB + MOV BYTE PTR [TRANS],1 ;A transfer is taking place +ONSEC: + MOV DL,[SECCLUSPOS] + MOV CX,[SECCNT] + MOV BX,[CLUSNUM] +RDLP: + CALL OPTIMIZE + PUSH DI + PUSH AX + PUSH DS + MOV DS,[DMAADD+2] + PUSH DX + PUSH BX + PUSHF ;Save carry flag + CALL DREAD + POPF ;Restore carry flag + POP DI ;Initial transfer address + POP AX ;First sector transfered + POP DS + JC NOTBUFFED ;Was one of those sectors in the buffer? + CMP BYTE PTR [DIRTYBUF],0 ;Is buffer dirty? + JZ NOTBUFFED ;If not no problem +;We have transfered in a sector from disk when a dirty copy of it is in the buffer. +;We must transfer the sector from the buffer to correct memory address + SUB AX,[BUFSECNO] ;How many sectors into the transfer? + NEG AX + MOV CX,[BP.SECSIZ] + MUL CX ;How many bytes into the transfer? + ADD DI,AX + MOV SI,[BUFFER] + PUSH ES + MOV ES,[DMAADD+2] ;Get disk transfer segment + SHR CX,1 + REP MOVSW + JNC EVENMOV + MOVSB +EVENMOV: + POP ES +NOTBUFFED: + POP CX + POP BX + JCXZ RDLAST + CMP BX,0FF8H + JAE SETFCB + MOV DL,0 + INC [LASTPOS] ;We'll be using next cluster + JMP SHORT RDLP + +SETFCB: + MOV SI,[FCB] + MOV AX,[NEXTADD] + MOV DI,AX + SUB AX,[DMAADD] ;Number of bytes transfered + XOR DX,DX + MOV CX,ES:[SI.RECSIZ] + DIV CX ;Number of records + CMP AX,[RECCNT] ;Check if all records transferred + JZ FULLREC + MOV BYTE PTR [DSKERR],1 + OR DX,DX + JZ FULLREC ;If remainder 0, then full record transfered + MOV BYTE PTR [DSKERR],3 ;Flag partial last record + SUB CX,DX ;Bytes left in last record + PUSH ES + MOV ES,[DMAADD+2] + XCHG AX,BX ;Save the record count temporarily + XOR AX,AX ;Fill with zeros + SHR CX,1 + JNC EVENFIL + STOSB +EVENFIL: + REP STOSW + XCHG AX,BX ;Restore record count to AX + POP ES + INC AX ;Add last (partial) record to total +FULLREC: + MOV CX,AX + MOV DI,SI ;ES:DI point to FCB +SETCLUS: + MOV AX,[CLUSNUM] + MOV ES:[DI.LSTCLUS],AX + MOV AX,[LASTPOS] + MOV ES:[DI.CLUSPOS],AX +ADDREC: + MOV AX,WORD PTR [RECPOS] + MOV DX,WORD PTR [RECPOS+2] + JCXZ RET28 ;If no records read, don't change position + DEC CX + ADD AX,CX ;Update current record position + ADC DX,0 + INC CX +RET28: RET + +RDLAST: + MOV AX,[BYTCNT2] + OR AX,AX + JZ SETFCB + MOV [BYTCNT1],AX + CALL NEXTSEC + JC SETFCB + MOV [BYTSECPOS],0 + CALL BUFRD + JMP SHORT SETFCB + +WRTDEV: + PUSH DS + LDS SI,DWORD PTR [DMAADD] + OR BL,40H + INC BL + JZ WRTCON + INC BL + JZ WRTAUX + INC BL + JZ ENDWRDEV ;Done if device is NUL +WRTLST: + LODSB + CMP AL,1AH + JZ ENDWRDEV + CALL LISTOUT + LOOP WRTLST + JMP SHORT ENDWRDEV + +WRTAUX: + LODSB + CALL AUXOUT + CMP AL,1AH + LOOPNZ WRTAUX + JMP SHORT ENDWRDEV + +WRTCON: + LODSB + CMP AL,1AH + JZ ENDWRDEV + CALL OUT + LOOP WRTCON +ENDWRDEV: + POP DS + MOV CX,[RECCNT] + MOV DI,[FCB] + JMP SHORT ADDREC + +HAVSTART: + MOV CX,AX + CALL SKPCLP + JCXZ DOWRTJ + CALL ALLOCATE + JNC DOWRTJ +WRTERR: + MOV BYTE PTR [DSKERR],1 +LVDSK: + MOV AX,WORD PTR [RECPOS] + MOV DX,WORD PTR [RECPOS+2] + MOV DI,[FCB] + RET + +DOWRTJ: JMP DOWRT + +WRTEOFJ: + JMP WRTEOF + +STORE: + +; Inputs: +; DS:DI point to FCB +; DX:AX = Position in file of disk transfer +; CX = Record count +; Outputs: +; DX:AX = Position of last record written +; CX = No. of records written +; ES:DI point to FCB +; LSTCLUS, CLUSPOS fields in FCB set + + CALL SETUP + CALL DATE16 + MOV ES:[DI.FDATE],AX + MOV ES:[DI.FTIME],DX + OR BL,BL + JS WRTDEV + AND BL,3FH ;Mark file as dirty + MOV ES:[DI.DEVID],BL + CALL BREAKDOWN + MOV AX,WORD PTR [BYTPOS] + MOV DX,WORD PTR [BYTPOS+2] + JCXZ WRTEOFJ + DEC CX + ADD AX,CX + ADC DX,0 ;AX:DX=last byte accessed + DIV [BP.SECSIZ] ;AX=last sector accessed + MOV CL,[BP.CLUSSHFT] + SHR AX,CL ;Last cluster to be accessed + PUSH AX + MOV AX,ES:WORD PTR [DI.FILSIZ] + MOV DX,ES:WORD PTR [DI.FILSIZ+2] + DIV [BP.SECSIZ] + OR DX,DX + JZ NORNDUP + INC AX ;Round up if any remainder +NORNDUP: + MOV [VALSEC],AX ;Number of sectors that have been written + POP AX + MOV CX,[CLUSNUM] ;First cluster accessed + CALL FNDCLUS + MOV [CLUSNUM],BX + MOV [LASTPOS],DX + SUB AX,DX ;Last cluster minus current cluster + JZ DOWRT ;If we have last clus, we must have first + JCXZ HAVSTART ;See if no more data + PUSH CX ;No. of clusters short of first + MOV CX,AX + CALL ALLOCATE + POP AX + JC WRTERR + MOV CX,AX + MOV DX,[LASTPOS] + INC DX + DEC CX + JZ NOSKIP + CALL SKPCLP +NOSKIP: + MOV [CLUSNUM],BX + MOV [LASTPOS],DX +DOWRT: + CMP [BYTCNT1],0 + JZ WRTMID + MOV BX,[CLUSNUM] + CALL BUFWRT +WRTMID: + MOV AX,[SECCNT] + OR AX,AX + JZ WRTLAST + ADD [SECPOS],AX + CALL NEXTSEC + MOV BYTE PTR [TRANS],1 ;A transfer is taking place + MOV DL,[SECCLUSPOS] + MOV BX,[CLUSNUM] + MOV CX,[SECCNT] +WRTLP: + CALL OPTIMIZE + JC NOTINBUF ;Is one of the sectors buffered? + MOV [BUFSECNO],0 ;If so, invalidate the buffer since we're + MOV WORD PTR [BUFDRVNO],0FFH ; completely rewritting it +NOTINBUF: + PUSH DI + PUSH AX + PUSH DS + MOV DS,[DMAADD+2] + CALL DWRITE + POP DS + POP CX + POP BX + JCXZ WRTLAST + MOV DL,0 + INC [LASTPOS] ;We'll be using next cluster + JMP SHORT WRTLP +WRTLAST: + MOV AX,[BYTCNT2] + OR AX,AX + JZ FINWRT + MOV [BYTCNT1],AX + CALL NEXTSEC + MOV [BYTSECPOS],0 + CALL BUFWRT +FINWRT: + MOV AX,[NEXTADD] + SUB AX,[DMAADD] + ADD AX,WORD PTR [BYTPOS] + MOV DX,WORD PTR [BYTPOS+2] + ADC DX,0 + MOV CX,DX + MOV DI,[FCB] + CMP AX,ES:WORD PTR [DI.FILSIZ] + SBB CX,ES:WORD PTR [DI.FILSIZ+2] + JB SAMSIZ + MOV ES:WORD PTR [DI.FILSIZ],AX + MOV ES:WORD PTR [DI.FILSIZ+2],DX +SAMSIZ: + MOV CX,[RECCNT] + JMP SETCLUS + + +WRTERRJ:JMP WRTERR + +WRTEOF: + MOV CX,AX + OR CX,DX + JZ KILLFIL + SUB AX,1 + SBB DX,0 + DIV [BP.SECSIZ] + MOV CL,[BP.CLUSSHFT] + SHR AX,CL + MOV CX,AX + CALL FNDCLUS + JCXZ RELFILE + CALL ALLOCATE + JC WRTERRJ +UPDATE: + MOV DI,[FCB] + MOV AX,WORD PTR [BYTPOS] + MOV ES:WORD PTR [DI.FILSIZ],AX + MOV AX,WORD PTR [BYTPOS+2] + MOV ES:WORD PTR [DI.FILSIZ+2],AX + XOR CX,CX + JMP ADDREC + +RELFILE: + MOV DX,0FFFH + CALL RELBLKS +SETDIRT: + MOV BYTE PTR [SI-1],1 + JMP SHORT UPDATE + +KILLFIL: + XOR BX,BX + XCHG BX,ES:[DI.FIRCLUS] + OR BX,BX + JZ UPDATE + CALL RELEASE + JMP SHORT SETDIRT + + +OPTIMIZE: + +; Inputs: +; DS = CS +; BX = Physical cluster +; CX = No. of records +; DL = sector within cluster +; BP = Base of drives parameters +; [NEXTADD] = transfer address +; Outputs: +; AX = No. of records remaining +; BX = Transfer address +; CX = No. or records to be transferred +; DX = Physical sector address +; DI = Next cluster +; Carry clear if a sector to transfer is in the buffer +; Carry set otherwise +; [CLUSNUM] = Last cluster accessed +; [NEXTADD] updated +; BP unchanged. Note that segment of transfer not set. + + PUSH DX + PUSH BX + MOV AL,[BP.CLUSMSK] + INC AL ;Number of sectors per cluster + MOV AH,AL + SUB AL,DL ;AL = Number of sectors left in first cluster + MOV DX,CX + MOV SI,[BP.FAT] + MOV CX,0 +OPTCLUS: +;AL has number of sectors available in current cluster +;AH has number of sectors available in next cluster +;BX has current physical cluster +;CX has number of sequential sectors found so far +;DX has number of sectors left to transfer +;SI has FAT pointer + CALL UNPACK + ADD CL,AL + ADC CH,0 + CMP CX,DX + JAE BLKDON + MOV AL,AH + INC BX + CMP DI,BX + JZ OPTCLUS + DEC BX +FINCLUS: + MOV [CLUSNUM],BX ;Last cluster accessed + SUB DX,CX ;Number of sectors still needed + PUSH DX + MOV AX,CX + MUL [BP.SECSIZ] ;Number of sectors times sector size + MOV SI,[NEXTADD] + ADD AX,SI ;Adjust by size of transfer + MOV [NEXTADD],AX + POP AX ;Number of sectors still needed + POP DX ;Starting cluster + SUB BX,DX ;Number of new clusters accessed + ADD [LASTPOS],BX + POP BX ;BL = sector postion within cluster + CALL FIGREC + MOV BX,SI +;Now let's see if any of these sectors are already in the buffer + CMP [BUFSECNO],DX + JC RET100 ;If DX > [BUFSECNO] then not in buffer + MOV SI,DX + ADD SI,CX ;Last sector + 1 + CMP [BUFSECNO],SI + CMC + JC RET100 ;If SI <= [BUFSECNO] then not in buffer + PUSH AX + MOV AL,[BP.DEVNUM] + CMP AL,[BUFDRVNO] ;Is buffer for this drive? + POP AX + JZ RET100 ;If so, then we match + STC ;No match +RET100: RET +BLKDON: + SUB CX,DX ;Number of sectors in cluster we don't want + SUB AH,CL ;Number of sectors in cluster we accepted + DEC AH ;Adjust to mean position within cluster + MOV [SECCLUSPOS],AH + MOV CX,DX ;Anyway, make the total equal to the request + JMP SHORT FINCLUS + + +FIGREC: + +;Inputs: +; DX = Physical cluster number +; BL = Sector postion within cluster +; BP = Base of drive parameters +;Outputs: +; DX = physical sector number +;No other registers affected. + + PUSH CX + MOV CL,[BP.CLUSSHFT] + DEC DX + DEC DX + SHL DX,CL + OR DL,BL + ADD DX,[BP.FIRREC] + POP CX + RET + +GETREC: + +; Inputs: +; DS:DX point to FCB +; Outputs: +; CX = 1 +; DX:AX = Record number determined by EXTENT and NR fields +; DS:DI point to FCB +; No other registers affected. + + MOV DI,DX + CMP BYTE PTR [DI],-1 ;Check for extended FCB + JNZ NORMFCB2 + ADD DI,7 +NORMFCB2: + MOV CX,1 + MOV AL,[DI.NR] + MOV DX,[DI.EXTENT] + SHL AL,1 + SHR DX,1 + RCR AL,1 + MOV AH,DL + MOV DL,DH + MOV DH,0 + RET + + +ALLOCATE: + +; Inputs: +; DS = CS +; ES = Segment of FCB +; BX = Last cluster of file (0 if null file) +; CX = No. of clusters to allocate +; DX = Position of cluster BX +; BP = Base of drive parameters +; SI = FAT pointer +; [FCB] = Displacement of FCB within segment +; Outputs: +; IF insufficient space +; THEN +; Carry set +; CX = max. no. of records that could be added to file +; ELSE +; Carry clear +; BX = First cluster allocated +; FAT is fully updated including dirty bit +; FIRCLUS field of FCB set if file was null +; SI,BP unchanged. All other registers destroyed. + + PUSH [SI] + PUSH DX + PUSH CX + PUSH BX + MOV AX,BX +ALLOC: + MOV DX,BX +FINDFRE: + INC BX + CMP BX,[BP.MAXCLUS] + JLE TRYOUT + CMP AX,1 + JG TRYIN + POP BX + MOV DX,0FFFH + CALL RELBLKS + POP AX ;No. of clusters requested + SUB AX,CX ;AX=No. of clusters allocated + POP DX + POP [SI] + INC DX ;Position of first cluster allocated + ADD AX,DX ;AX=max no. of cluster in file + MOV DL,[BP.CLUSMSK] + MOV DH,0 + INC DX ;DX=records/cluster + MUL DX ;AX=max no. of records in file + MOV CX,AX + SUB CX,WORD PTR [RECPOS] ;CX=max no. of records that could be written + JA MAXREC + XOR CX,CX ;If CX was negative, zero it +MAXREC: + STC +RET11: RET + +TRYOUT: + CALL UNPACK + JZ HAVFRE +TRYIN: + DEC AX + JLE FINDFRE + XCHG AX,BX + CALL UNPACK + JZ HAVFRE + XCHG AX,BX + JMP SHORT FINDFRE +HAVFRE: + XCHG BX,DX + MOV AX,DX + CALL PACK + MOV BX,AX + LOOP ALLOC + MOV DX,0FFFH + CALL PACK + MOV BYTE PTR [SI-1],1 + POP BX + POP CX ;Don't need this stuff since we're successful + POP DX + CALL UNPACK + POP [SI] + XCHG BX,DI + OR DI,DI + JNZ RET11 + MOV DI,[FCB] + MOV ES:[DI.FIRCLUS],BX +RET12: RET + + +RELEASE: + +; Inputs: +; DS = CS +; BX = Cluster in file +; SI = FAT pointer +; BP = Base of drive parameters +; Function: +; Frees cluster chain starting with [BX] +; AX,BX,DX,DI all destroyed. Other registers unchanged. + + XOR DX,DX +RELBLKS: +; Enter here with DX=0FFFH to put an end-of-file mark +; in the first cluster and free the rest in the chain. + CALL UNPACK + JZ RET12 + MOV AX,DI + CALL PACK + CMP AX,0FF8H + MOV BX,AX + JB RELEASE +RET13: RET + + +GETEOF: + +; Inputs: +; BX = Cluster in a file +; SI = Base of drive FAT +; DS = CS +; Outputs: +; BX = Last cluster in the file +; DI destroyed. No other registers affected. + + CALL UNPACK + CMP DI,0FF8H + JAE RET13 + MOV BX,DI + JMP SHORT GETEOF + + +SRCHFRST: ;System call 17 + CALL GETFILE +SAVPLCE: +; Search-for-next enters here to save place and report +; findings. + JC KILLSRCH + OR BH,BH + JS SRCHDEV + MOV AX,[LASTENT] + MOV ES:[DI.FILDIRENT],AX + MOV ES:[DI.DRVBP],BP +;Information in directory entry must be copied into the first +; 33 bytes starting at the disk transfer address. + MOV SI,BX + LES DI,DWORD PTR [DMAADD] + MOV AX,00FFH + CMP AL,[EXTFCB] + JNZ NORMFCB + STOSW + INC AL + STOSW + STOSW + MOV AL,[ATTRIB] + STOSB +NORMFCB: + MOV AL,[THISDRV] + INC AL + STOSB ;Set drive number + MOV CX,16 + REP MOVSW ;Copy remaining 10 characters of name + XOR AL,AL + RET + +KILLSRCH: +KILLSRCH1 EQU KILLSRCH+1 +;The purpose of the KILLSRCH1 label is to provide a jump label to the following +; instruction which leaves out the segment override. + MOV WORD PTR ES:[DI.FILDIRENT],-1 + MOV AL,-1 + RET + +SRCHDEV: + MOV ES:[DI.FILDIRENT],BX + LES DI,DWORD PTR [DMAADD] + XOR AX,AX + STOSB ;Zero drive byte + SUB SI,4 ;Point to device name + MOVSW + MOVSW + MOV AX,2020H + STOSB + STOSW + STOSW + STOSW ;Fill with 8 blanks + XOR AX,AX + MOV CX,10 + REP STOSW + STOSB +RET14: RET + +SRCHNXT: ;System call 18 + CALL MOVNAME + MOV DI,DX + JC NEAR PTR KILLSRCH1 + MOV BP,[DI.DRVBP] + MOV AX,[DI.FILDIRENT] + OR AX,AX + JS NEAR PTR KILLSRCH1 + PUSH DX + PUSH DS + PUSH CS + POP DS + MOV [LASTENT],AX + CALL CONTSRCH + POP ES + POP DI + JMP SAVPLCE + + +FILESIZE: ;System call 35 + CALL GETFILE + MOV AL,-1 + JC RET14 + ADD DI,33 ;Write size in RR field + MOV CX,ES:[DI.RECSIZ-33] + OR CX,CX + JNZ RECOK + MOV CX,128 +RECOK: + XOR AX,AX + XOR DX,DX ;Intialize size to zero + OR BH,BH ;Check for named I/O device + JS DEVSIZ + INC SI + INC SI ;Point to length field + MOV AX,[SI+2] ;Get high word of size + DIV CX + PUSH AX ;Save high part of result + LODSW ;Get low word of size + DIV CX + OR DX,DX ;Check for zero remainder + POP DX + JZ DEVSIZ + INC AX ;Round up for partial record + JNZ DEVSIZ ;Propagate carry? + INC DX +DEVSIZ: + STOSW + MOV AX,DX + STOSB + MOV AL,0 + CMP CX,64 + JAE RET14 ;Only 3-byte field if RECSIZ >= 64 + MOV ES:[DI],AH + RET + + +SETDMA: ;System call 26 + MOV CS:[DMAADD],DX + MOV CS:[DMAADD+2],DS + RET + +NOSUCHDRV: + MOV AL,-1 + RET + +GETFATPT: ;System call 27 + MOV DL,0 ;Use default drive + +GETFATPTDL: ;System call 28 + PUSH CS + POP DS + MOV AL,DL + CALL GETTHISDRV + JC NOSUCHDRV + CALL FATREAD + MOV BX,[BP.FAT] + MOV AL,[BP.CLUSMSK] + INC AL + MOV DX,[BP.MAXCLUS] + DEC DX + MOV CX,[BP.SECSIZ] + LDS SI,DWORD PTR [SPSAVE] + MOV [SI.BXSAVE],BX + MOV [SI.DXSAVE],DX + MOV [SI.CXSAVE],CX + MOV [SI.DSSAVE],CS + RET + + +GETDSKPT: ;System call 31 + PUSH CS + POP DS + MOV AL,[CURDRV] + MOV [THISDRV],AL + CALL FATREAD + LDS SI,DWORD PTR [SPSAVE] + MOV [SI.BXSAVE],BP + MOV [SI.DSSAVE],CS + RET + + +DSKRESET: ;System call 13 + PUSH CS + POP DS +WRTFATS: +; DS=CS. Writes back all dirty FATs. All registers destroyed. + XOR AL,AL + XCHG AL,[DIRTYBUF] + OR AL,AL + JZ NOBUF + MOV BP,[BUFDRVBP] + MOV DX,[BUFSECNO] + MOV BX,[BUFFER] + MOV CX,1 + CALL DWRITE +NOBUF: + MOV CL,[NUMIO] + MOV CH,0 + MOV BP,[DRVTAB] +WRTFAT: + PUSH CX + CALL CHKFATWRT + POP CX + ADD BP,DPBSIZ + LOOP WRTFAT + RET + + +GETDRV: ;System call 25 + MOV AL,CS:[CURDRV] +RET15: RET + + +SETRNDREC: ;System call 36 + CALL GETREC + MOV [DI+33],AX + MOV [DI+35],DL + CMP [DI.RECSIZ],64 + JAE RET15 + MOV [DI+36],DH ;Set 4th byte only if record size < 64 +RET16: RET + + +SELDSK: ;System call 14 + MOV AL,CS:[NUMDRV] + CMP DL,AL + JNB RET17 + MOV CS:[CURDRV],DL +RET17: RET + +BUFIN: ;System call 10 + MOV AX,CS + MOV ES,AX + MOV SI,DX + MOV CH,0 + LODSW + OR AL,AL + JZ RET17 + MOV BL,AH + MOV BH,CH + CMP AL,BL + JBE NOEDIT + CMP BYTE PTR [BX+SI],0DH + JZ EDITON +NOEDIT: + MOV BL,CH +EDITON: + MOV DL,AL + DEC DX +NEWLIN: + MOV AL,CS:[CARPOS] + MOV CS:[STARTPOS],AL + PUSH SI + MOV DI,OFFSET DOSGROUP:INBUF + MOV AH,CH + MOV BH,CH + MOV DH,CH +GETCH: + CALL IN + CMP AL,"F"-"@" ;Ignore ^F + JZ GETCH + CMP AL,CS:ESCCHAR + JZ ESC + CMP AL,7FH + JZ BACKSP + CMP AL,8 + JZ BACKSP + CMP AL,13 + JZ ENDLIN + CMP AL,10 + JZ PHYCRLF + CMP AL,CANCEL + JZ KILNEW +SAVCH: + CMP DH,DL + JAE BUFFUL + STOSB + INC DH + CALL BUFOUT + OR AH,AH + JNZ GETCH + CMP BH,BL + JAE GETCH + INC SI + INC BH + JMP SHORT GETCH + +BUFFUL: + MOV AL,7 + CALL OUT + JMP SHORT GETCH + +ESC: + CALL IN + MOV CL,ESCTABLEN + PUSH DI + MOV DI,OFFSET DOSGROUP:ESCTAB + REPNE SCASB + POP DI + SHL CX,1 + MOV BP,CX + JMP [BP+OFFSET DOSGROUP:ESCFUNC] + +ENDLIN: + STOSB + CALL OUT + POP DI + MOV [DI-1],DH + INC DH +COPYNEW: + MOV BP,ES + MOV BX,DS + MOV ES,BX + MOV DS,BP + MOV SI,OFFSET DOSGROUP:INBUF + MOV CL,DH + REP MOVSB + RET +CRLF: + MOV AL,13 + CALL OUT + MOV AL,10 + JMP OUT + +PHYCRLF: + CALL CRLF + JMP SHORT GETCH + +KILNEW: + MOV AL,"\" + CALL OUT + POP SI +PUTNEW: + CALL CRLF + MOV AL,CS:[STARTPOS] + CALL TAB + JMP NEWLIN + +BACKSP: + OR DH,DH + JZ OLDBAK + CALL BACKUP + MOV AL,ES:[DI] + CMP AL," " + JAE OLDBAK + CMP AL,9 + JZ BAKTAB + CALL BACKMES +OLDBAK: + OR AH,AH + JNZ GETCH1 + OR BH,BH + JZ GETCH1 + DEC BH + DEC SI +GETCH1: + JMP GETCH +BAKTAB: + PUSH DI + DEC DI + STD + MOV CL,DH + MOV AL," " + PUSH BX + MOV BL,7 + JCXZ FIGTAB +FNDPOS: + SCASB + JNA CHKCNT + CMP ES:BYTE PTR [DI+1],9 + JZ HAVTAB + DEC BL +CHKCNT: + LOOP FNDPOS +FIGTAB: + SUB BL,CS:[STARTPOS] +HAVTAB: + SUB BL,DH + ADD CL,BL + AND CL,7 + CLD + POP BX + POP DI + JZ OLDBAK +TABBAK: + CALL BACKMES + LOOP TABBAK + JMP SHORT OLDBAK +BACKUP: + DEC DH + DEC DI +BACKMES: + MOV AL,8 + CALL OUT + MOV AL," " + CALL OUT + MOV AL,8 + JMP OUT + +TWOESC: + MOV AL,ESCCH + JMP SAVCH + +COPYLIN: + MOV CL,BL + SUB CL,BH + JMP SHORT COPYEACH + +COPYSTR: + CALL FINDOLD + JMP SHORT COPYEACH + +COPYONE: + MOV CL,1 +COPYEACH: + MOV AH,0 + CMP DH,DL + JZ GETCH2 + CMP BH,BL + JZ GETCH2 + LODSB + STOSB + CALL BUFOUT + INC BH + INC DH + LOOP COPYEACH +GETCH2: + JMP GETCH + +SKIPONE: + CMP BH,BL + JZ GETCH2 + INC BH + INC SI + JMP GETCH + +SKIPSTR: + CALL FINDOLD + ADD SI,CX + ADD BH,CL + JMP GETCH + +FINDOLD: + CALL IN + MOV CL,BL + SUB CL,BH + JZ NOTFND + DEC CX + JZ NOTFND + PUSH ES + PUSH DS + POP ES + PUSH DI + MOV DI,SI + INC DI + REPNE SCASB + POP DI + POP ES + JNZ NOTFND + NOT CL + ADD CL,BL + SUB CL,BH +RET30: RET +NOTFND: + POP BP + JMP GETCH + +REEDIT: + MOV AL,"@" + CALL OUT + POP DI + PUSH DI + PUSH ES + PUSH DS + CALL COPYNEW + POP DS + POP ES + POP SI + MOV BL,DH + JMP PUTNEW + +ENTERINS: + IF TOGLINS + NOT AH + JMP GETCH + ENDIF + IF NOT TOGLINS + MOV AH,-1 + JMP GETCH + +EXITINS: + MOV AH,0 + JMP GETCH + ENDIF + +ESCFUNC DW GETCH + DW TWOESC + IF NOT TOGLINS + DW EXITINS + ENDIF + DW ENTERINS + DW BACKSP + DW REEDIT + DW KILNEW + DW COPYLIN + DW SKIPSTR + DW COPYSTR + DW SKIPONE + DW COPYONE + + IF IBM + DW COPYONE + DW CTRLZ +CTRLZ: + MOV AL,"Z"-"@" + JMP SAVCH + ENDIF +BUFOUT: + CMP AL," " + JAE OUT + CMP AL,9 + JZ OUT + PUSH AX + MOV AL,"^" + CALL OUT + POP AX + OR AL,40H + JMP SHORT OUT + +NOSTOP: + CMP AL,"P"-"@" + JZ INCHK + IF NOT TOGLPRN + CMP AL,"N"-"@" + JZ INCHK + ENDIF + CMP AL,"C"-"@" + JZ INCHK + RET + +CONOUT: ;System call 2 + MOV AL,DL +OUT: + CMP AL,20H + JB CTRLOUT + CMP AL,7FH + JZ OUTCH + INC CS:BYTE PTR [CARPOS] +OUTCH: + PUSH AX + CALL STATCHK + POP AX + CALL FAR PTR BIOSOUT + TEST CS:BYTE PTR [PFLAG],-1 + JZ RET18 + CALL FAR PTR BIOSPRINT +RET18: RET + +STATCHK: + CALL FAR PTR BIOSSTAT + JZ RET18 + CMP AL,'S'-'@' + JNZ NOSTOP + CALL FAR PTR BIOSIN ;Eat Cntrl-S +INCHK: + CALL FAR PTR BIOSIN + CMP AL,'P'-'@' + JZ PRINTON + IF NOT TOGLPRN + CMP AL,'N'-'@' + JZ PRINTOFF + ENDIF + CMP AL,'C'-'@' + JNZ RET18 +; Ctrl-C handler. +; "^C" and CR/LF is printed. Then the user registers are restored and the +; user CTRL-C handler is executed. At this point the top of the stack has +; 1) the interrupt return address should the user CTRL-C handler wish to +; allow processing to continue; 2) the original interrupt return address +; to the code that performed the function call in the first place. If the +; user CTRL-C handler wishes to continue, it must leave all registers +; unchanged and IRET. The function that was interrupted will simply be +; repeated. + MOV AL,3 ;Display "^C" + CALL BUFOUT + CALL CRLF + CLI ;Prepare to play with stack + MOV SS,CS:[SSSAVE] + MOV SP,CS:[SPSAVE] ;User stack now restored + POP AX + POP BX + POP CX + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES ;User registers now restored + INT CONTC ;Execute user Ctrl-C handler + JMP COMMAND ;Repeat command otherwise + +PRINTON: + IF TOGLPRN + NOT CS:BYTE PTR [PFLAG] + RET + ENDIF + IF NOT TOGLPRN + MOV CS:BYTE PTR [PFLAG],1 + RET + +PRINTOFF: + MOV CS:BYTE PTR [PFLAG],0 + RET + ENDIF + +CTRLOUT: + CMP AL,13 + JZ ZERPOS + CMP AL,8 + JZ BACKPOS + CMP AL,9 + JNZ OUTCHJ + MOV AL,CS:[CARPOS] + OR AL,0F8H + NEG AL +TAB: + PUSH CX + MOV CL,AL + MOV CH,0 + JCXZ POPTAB +TABLP: + MOV AL," " + CALL OUT + LOOP TABLP +POPTAB: + POP CX +RET19: RET + +ZERPOS: + MOV CS:BYTE PTR [CARPOS],0 +OUTCHJ: JMP OUTCH + +BACKPOS: + DEC CS:BYTE PTR [CARPOS] + JMP OUTCH + + +CONSTAT: ;System call 11 + CALL STATCHK + MOV AL,0 + JZ RET19 + OR AL,-1 + RET + + +CONIN: ;System call 1 + CALL IN + PUSH AX + CALL OUT + POP AX + RET + + +IN: ;System call 8 + CALL INCHK + JZ IN +RET29: RET + +RAWIO: ;System call 6 + MOV AL,DL + CMP AL,-1 + JNZ RAWOUT + LDS SI,DWORD PTR CS:[SPSAVE] ;Get pointer to register save area + CALL FAR PTR BIOSSTAT + JNZ RESFLG + OR BYTE PTR [SI.FSAVE],40H ;Set user's zero flag + XOR AL,AL + RET + +RESFLG: + AND BYTE PTR [SI.FSAVE],0FFH-40H ;Reset user's zero flag +RAWINP: ;System call 7 + CALL FAR PTR BIOSIN + RET +RAWOUT: + CALL FAR PTR BIOSOUT + RET + +LIST: ;System call 5 + MOV AL,DL +LISTOUT: + PUSH AX + CALL STATCHK + POP AX + CALL FAR PTR BIOSPRINT +RET20: RET + +PRTBUF: ;System call 9 + MOV SI,DX +OUTSTR: + LODSB + CMP AL,"$" + JZ RET20 + CALL OUT + JMP SHORT OUTSTR + +OUTMES: ;String output for internal messages + LODS CS:BYTE PTR [SI] + CMP AL,"$" + JZ RET20 + CALL OUT + JMP SHORT OUTMES + + +MAKEFCB: ;Interrupt call 41 +DRVBIT EQU 2 +NAMBIT EQU 4 +EXTBIT EQU 8 + MOV DL,0 ;Flag--not ambiguous file name + TEST AL,DRVBIT ;Use current drive field if default? + JNZ DEFDRV + MOV BYTE PTR ES:[DI],0 ;No - use default drive +DEFDRV: + INC DI + MOV CX,8 + TEST AL,NAMBIT ;Use current name fiels as defualt? + XCHG AX,BX ;Save bits in BX + MOV AL," " + JZ FILLB ;If not, go fill with blanks + ADD DI,CX + XOR CX,CX ;Don't fill any +FILLB: + REP STOSB + MOV CL,3 + TEST BL,EXTBIT ;Use current extension as default + JZ FILLB2 + ADD DI,CX + XOR CX,CX +FILLB2: + REP STOSB + XCHG AX,CX ;Put zero in AX + STOSW + STOSW ;Initialize two words after to zero + SUB DI,16 ;Point back at start + TEST BL,1 ;Scan off separators if not zero + JZ SKPSPC + CALL SCANB ;Peel off blanks and tabs + CALL DELIM ;Is it a one-time-only delimiter? + JNZ NOSCAN + INC SI ;Skip over the delimiter +SKPSPC: + CALL SCANB ;Always kill preceding blanks and tabs +NOSCAN: + CALL GETLET + JBE NODRV ;Quit if termination character + CMP BYTE PTR[SI],":" ;Check for potential drive specifier + JNZ NODRV + INC SI ;Skip over colon + SUB AL,"@" ;Convert drive letter to binary drive number + JBE BADDRV ;Valid drive numbers are 1-15 + CMP AL,CS:[NUMDRV] + JBE HAVDRV +BADDRV: + MOV DL,-1 +HAVDRV: + STOSB ;Put drive specifier in first byte + INC SI + DEC DI ;Counteract next two instructions +NODRV: + DEC SI ;Back up + INC DI ;Skip drive byte + MOV CX,8 + CALL GETWORD ;Get 8-letter file name + CMP BYTE PTR [SI],"." + JNZ NODOT + INC SI ;Skip over dot if present + MOV CX,3 ;Get 3-letter extension + CALL MUSTGETWORD +NODOT: + LDS BX,CS:DWORD PTR [SPSAVE] + MOV [BX.SISAVE],SI + MOV AL,DL + RET + +NONAM: + ADD DI,CX + DEC SI + RET + +GETWORD: + CALL GETLET + JBE NONAM ;Exit if invalid character + DEC SI +MUSTGETWORD: + CALL GETLET + JBE FILLNAM + JCXZ MUSTGETWORD + DEC CX + CMP AL,"*" ;Check for ambiguous file specifier + JNZ NOSTAR + MOV AL,"?" + REP STOSB +NOSTAR: + STOSB + CMP AL,"?" + JNZ MUSTGETWORD + OR DL,1 ;Flag ambiguous file name + JMP MUSTGETWORD +FILLNAM: + MOV AL," " + REP STOSB + DEC SI +RET21: RET + +SCANB: + LODSB + CALL SPCHK + JZ SCANB + DEC SI + RET + +GETLET: +;Get a byte from [SI], convert it to upper case, and compare for delimiter. +;ZF set if a delimiter, CY set if a control character (other than TAB). + LODSB + AND AL,7FH + CMP AL,"a" + JB CHK + CMP AL,"z" + JA CHK + SUB AL,20H ;Convert to upper case +CHK: + CMP AL,"." + JZ RET21 + CMP AL,'"' + JZ RET21 + CMP AL,"/" + JZ RET21 + CMP AL,"[" + JZ RET21 + CMP AL,"]" + JZ RET21 + + IF IBM +DELIM: + ENDIF + CMP AL,":" ;Allow ":" as separator in IBM version + JZ RET21 + IF NOT IBM +DELIM: + ENDIF + + CMP AL,"+" + JZ RET101 + CMP AL,"=" + JZ RET101 + CMP AL,";" + JZ RET101 + CMP AL,"," + JZ RET101 +SPCHK: + CMP AL,9 ;Filter out tabs too + JZ RET101 +;WARNING! " " MUST be the last compare + CMP AL," " +RET101: RET + +SETVECT: ; Interrupt call 37 + XOR BX,BX + MOV ES,BX + MOV BL,AL + SHL BX,1 + SHL BX,1 + MOV ES:[BX],DX + MOV ES:[BX+2],DS + RET + + +NEWBASE: ; Interrupt call 38 + MOV ES,DX + LDS SI,CS:DWORD PTR [SPSAVE] + MOV DS,[SI.CSSAVE] + XOR SI,SI + MOV DI,SI + MOV AX,DS:[2] + MOV CX,80H + REP MOVSW + +SETMEM: + +; Inputs: +; AX = Size of memory in paragraphs +; DX = Segment +; Function: +; Completely prepares a program base at the +; specified segment. +; Outputs: +; DS = DX +; ES = DX +; [0] has INT 20H +; [2] = First unavailable segment ([ENDMEM]) +; [5] to [9] form a long call to the entry point +; [10] to [13] have exit address (from INT 22H) +; [14] to [17] have ctrl-C exit address (from INT 23H) +; [18] to [21] have fatal error address (from INT 24H) +; DX,BP unchanged. All other registers destroyed. + + XOR CX,CX + MOV DS,CX + MOV ES,DX + MOV SI,EXIT + MOV DI,SAVEXIT + MOVSW + MOVSW + MOVSW + MOVSW + MOVSW + MOVSW + MOV ES:[2],AX + SUB AX,DX + CMP AX,MAXDIF + JBE HAVDIF + MOV AX,MAXDIF +HAVDIF: + MOV BX,ENTRYPOINTSEG + SUB BX,AX + SHL AX,1 + SHL AX,1 + SHL AX,1 + SHL AX,1 + MOV DS,DX + MOV DS:[6],AX + MOV DS:[8],BX + MOV DS:[0],20CDH ;"INT INTTAB" + MOV DS:(BYTE PTR [5]),LONGCALL + RET + +DATE16: + PUSH CX + CALL READTIME + SHL CL,1 ;Minutes to left part of byte + SHL CL,1 + SHL CX,1 ;Push hours and minutes to left end + SHL CX,1 + SHL CX,1 + SHR DH,1 ;Count every two seconds + OR CL,DH ;Combine seconds with hours and minutes + MOV DX,CX + POP CX + MOV AX,WORD PTR [MONTH] ;Fetch month and year + SHL AL,1 ;Push month to left to make room for day + SHL AL,1 + SHL AL,1 + SHL AL,1 + SHL AX,1 + OR AL,[DAY] +RET22: RET + +FOURYEARS EQU 3*365+366 + +READTIME: +;Gets time in CX:DX. Figures new date if it has changed. +;Uses AX, CX, DX. + CALL FAR PTR BIOSGETTIME + CMP AX,[DAYCNT] ;See if day count is the same + JZ RET22 + CMP AX,FOURYEARS*30 ;Number of days in 120 years + JAE RET22 ;Ignore if too large + MOV [DAYCNT],AX + PUSH SI + PUSH CX + PUSH DX ;Save time + XOR DX,DX + MOV CX,FOURYEARS ;Number of days in 4 years + DIV CX ;Compute number of 4-year units + SHL AX,1 + SHL AX,1 + SHL AX,1 ;Multiply by 8 (no. of half-years) + MOV CX,AX ;<240 implies AH=0 + MOV SI,OFFSET DOSGROUP:YRTAB ;Table of days in each year + CALL DSLIDE ;Find out which of four years we're in + SHR CX,1 ;Convert half-years to whole years + JNC SK ;Extra half-year? + ADD DX,200 +SK: + CALL SETYEAR + MOV CL,1 ;At least at first month in year + MOV SI,OFFSET DOSGROUP:MONTAB ;Table of days in each month + CALL DSLIDE ;Find out which month we're in + MOV [MONTH],CL + INC DX ;Remainder is day of month (start with one) + MOV [DAY],DL + CALL WKDAY ;Set day of week + POP DX + POP CX + POP SI +RET23: RET + +DSLIDE: + MOV AH,0 +DSLIDE1: + LODSB ;Get count of days + CMP DX,AX ;See if it will fit + JB RET23 ;If not, done + SUB DX,AX + INC CX ;Count one more month/year + JMP SHORT DSLIDE1 + +SETYEAR: +;Set year with value in CX. Adjust length of February for this year. + MOV BYTE PTR [YEAR],CL +CHKYR: + TEST CL,3 ;Check for leap year + MOV AL,28 + JNZ SAVFEB ;28 days if no leap year + INC AL ;Add leap day +SAVFEB: + MOV [MONTAB+1],AL ;Store for February + RET + +;Days in year +YRTAB DB 200,166 ;Leap year + DB 200,165 + DB 200,165 + DB 200,165 + +;Days of each month +MONTAB DB 31 ;January + DB 28 ;February--reset each time year changes + DB 31 ;March + DB 30 ;April + DB 31 ;May + DB 30 ;June + DB 31 ;July + DB 31 ;August + DB 30 ;September + DB 31 ;October + DB 30 ;November + DB 31 ;December + +GETDATE: ;Function call 42 + PUSH CS + POP DS + CALL READTIME ;Check for rollover to next day + MOV AX,[YEAR] + MOV BX,WORD PTR [DAY] + LDS SI,DWORD PTR [SPSAVE] ;Get pointer to user registers + MOV [SI.DXSAVE],BX ;DH=month, DL=day + ADD AX,1980 ;Put bias back + MOV [SI.CXSAVE],AX ;CX=year + MOV AL,CS:[WEEKDAY] +RET24: RET + +SETDATE: ;Function call 43 + MOV AL,-1 ;Be ready to flag error + SUB CX,1980 ;Fix bias in year + JC RET24 ;Error if not big enough + CMP CX,119 ;Year must be less than 2100 + JA RET24 + OR DH,DH + JZ RET24 + OR DL,DL + JZ RET24 ;Error if either month or day is 0 + CMP DH,12 ;Check against max. month + JA RET24 + PUSH CS + POP DS + CALL CHKYR ;Set Feb. up for new year + MOV AL,DH + MOV BX,OFFSET DOSGROUP:MONTAB-1 + XLAT ;Look up days in month + CMP AL,DL + MOV AL,-1 ;Restore error flag, just in case + JB RET24 ;Error if too many days + CALL SETYEAR + MOV WORD PTR [DAY],DX ;Set both day and month + SHR CX,1 + SHR CX,1 + MOV AX,FOURYEARS + MOV BX,DX + MUL CX + MOV CL,BYTE PTR [YEAR] + AND CL,3 + MOV SI,OFFSET DOSGROUP:YRTAB + MOV DX,AX + SHL CX,1 ;Two entries per year, so double count + CALL DSUM ;Add up the days in each year + MOV CL,BH ;Month of year + MOV SI,OFFSET DOSGROUP:MONTAB + DEC CX ;Account for months starting with one + CALL DSUM ;Add up days in each month + MOV CL,BL ;Day of month + DEC CX ;Account for days starting with one + ADD DX,CX ;Add in to day total + XCHG AX,DX ;Get day count in AX + MOV [DAYCNT],AX + CALL FAR PTR BIOSSETDATE +WKDAY: + MOV AX,[DAYCNT] + XOR DX,DX + MOV CX,7 + INC AX + INC AX ;First day was Tuesday + DIV CX ;Compute day of week + MOV [WEEKDAY],DL + XOR AL,AL ;Flag OK +RET25: RET + +DSUM: + MOV AH,0 + JCXZ RET25 +DSUM1: + LODSB + ADD DX,AX + LOOP DSUM1 + RET + +GETTIME: ;Function call 44 + PUSH CS + POP DS + CALL READTIME + LDS SI,DWORD PTR [SPSAVE] ;Get pointer to user registers + MOV [SI.DXSAVE],DX + MOV [SI.CXSAVE],CX + XOR AL,AL +RET26: RET + +SETTIME: ;Function call 45 +;Time is in CX:DX in hours, minutes, seconds, 1/100 sec. + MOV AL,-1 ;Flag in case of error + CMP CH,24 ;Check hours + JAE RET26 + CMP CL,60 ;Check minutes + JAE RET26 + CMP DH,60 ;Check seconds + JAE RET26 + CMP DL,100 ;Check 1/100's + JAE RET26 + CALL FAR PTR BIOSSETTIME + XOR AL,AL + RET + + +; Default handler for division overflow trap +DIVOV: + PUSH SI + PUSH AX + MOV SI,OFFSET DOSGROUP:DIVMES + CALL OUTMES + POP AX + POP SI + INT 23H ;Use Ctrl-C abort on divide overflow + IRET + +CODSIZ EQU $-CODSTRT ;Size of code segment +CODE ENDS + + +;***** DATA AREA ***** +CONSTANTS SEGMENT BYTE + ORG 0 +CONSTRT EQU $ ;Start of constants segment + +IONAME: + IF NOT IBM + DB "PRN ","LST ","NUL ","AUX ","CON " + ENDIF + IF IBM + DB "COM1","PRN ","LPT1","NUL ","AUX ","CON " + ENDIF +DIVMES DB 13,10,"Divide overflow",13,10,"$" +CARPOS DB 0 +STARTPOS DB 0 +PFLAG DB 0 +DIRTYDIR DB 0 ;Dirty buffer flag +NUMDRV DB 0 ;Number of drives +NUMIO DB ? ;Number of disk tables +VERFLG DB 0 ;Initialize with verify off +CONTPOS DW 0 +DMAADD DW 80H ;User's disk transfer address (disp/seg) + DW ? +ENDMEM DW ? +MAXSEC DW 0 +BUFFER DW ? +BUFSECNO DW 0 +BUFDRVNO DB -1 +DIRTYBUF DB 0 +BUFDRVBP DW ? +DIRBUFID DW -1 +DAY DB 0 +MONTH DB 0 +YEAR DW 0 +DAYCNT DW -1 +WEEKDAY DB 0 +CURDRV DB 0 ;Default to drive A +DRVTAB DW 0 ;Address of start of DPBs +DOSLEN EQU CODSIZ+($-CONSTRT) ;Size of CODE + CONSTANTS segments +CONSTANTS ENDS + +DATA SEGMENT WORD +; Init code overlaps with data area below + + ORG 0 +INBUF DB 128 DUP (?) +CONBUF DB 131 DUP (?) ;The rest of INBUF and console buffer +LASTENT DW ? +EXITHOLD DB 4 DUP (?) +FATBASE DW ? +NAME1 DB 11 DUP (?) ;File name buffer +ATTRIB DB ? +NAME2 DB 11 DUP (?) +NAME3 DB 12 DUP (?) +EXTFCB DB ? +;WARNING - the following two items are accessed as a word +CREATING DB ? +DELALL DB ? +TEMP LABEL WORD +SPSAVE DW ? +SSSAVE DW ? +CONTSTK DW ? +SECCLUSPOS DB ? ;Position of first sector within cluster +DSKERR DB ? +TRANS DB ? +PREREAD DB ? ;0 means preread; 1 means optional +READOP DB ? +THISDRV DB ? + + EVEN +FCB DW ? ;Address of user FCB +NEXTADD DW ? +RECPOS DB 4 DUP (?) +RECCNT DW ? +LASTPOS DW ? +CLUSNUM DW ? +SECPOS DW ? ;Position of first sector accessed +VALSEC DW ? ;Number of valid (previously written) sectors +BYTSECPOS DW ? ;Position of first byte within sector +BYTPOS DB 4 DUP (?) ;Byte position in file of access +BYTCNT1 DW ? ;No. of bytes in first sector +BYTCNT2 DW ? ;No. of bytes in last sector +SECCNT DW ? ;No. of whole sectors +ENTFREE DW ? + + DB 80H DUP (?) ;Stack space +IOSTACK LABEL BYTE + DB 80H DUP (?) +DSKSTACK LABEL BYTE + + IF DSKTEST +NSS DW ? +NSP DW ? + ENDIF + +DIRBUF LABEL WORD + +;Init code below overlaps with data area above + + ORG 0 + +MOVFAT: +;This section of code is safe from being overwritten by block move + REP MOVS BYTE PTR [DI],[SI] + CLD + MOV ES:[DMAADD+2],DX + MOV SI,[DRVTAB] ;Address of first DPB + MOV AL,-1 + MOV CL,[NUMIO] ;Number of DPBs +FLGFAT: + MOV DI,ES:[SI.FAT] ;get pointer to FAT + DEC DI ;Point to dirty byte + STOSB ;Flag as unused + ADD SI,DPBSIZ ;Point to next DPB + LOOP FLGFAT + MOV AX,[ENDMEM] + CALL SETMEM ;Set up segment + +XXX PROC FAR + RET +XXX ENDP + +DOSINIT: + CLI + CLD + PUSH CS + POP ES + MOV ES:[ENDMEM],DX + LODSB ;Get no. of drives & no. of I/O drivers + MOV ES:[NUMIO],AL + MOV DI,OFFSET DOSGROUP:MEMSTRT +PERDRV: + MOV BP,DI + MOV AL,ES:[DRVCNT] + STOSB ;DEVNUM + LODSB ;Physical unit no. + STOSB ;DRVNUM + CMP AL,15 + JA BADINIT + CBW ;Index into FAT size table + SHL AX,1 + ADD AX,OFFSET DOSGROUP:FATSIZTAB + XCHG BX,AX + LODSW ;Pointer to DPT + PUSH SI + MOV SI,AX + LODSW + STOSW ;SECSIZ + MOV DX,AX + CMP AX,ES:[MAXSEC] + JBE NOTMAX + MOV ES:[MAXSEC],AX +NOTMAX: + LODSB + DEC AL + STOSB ;CLUSMSK + JZ HAVSHFT + CBW +FIGSHFT: + INC AH + SAR AL,1 + JNZ FIGSHFT + MOV AL,AH +HAVSHFT: + STOSB ;CLUSSHFT + MOVSW ;FIRFAT (= number of reserved sectors) + MOVSB ;FATCNT + MOVSW ;MAXENT + MOV AX,DX ;SECSIZ again + MOV CL,5 + SHR AX,CL + MOV CX,AX ;Directory entries per sector + DEC AX + ADD AX,ES:[BP.MAXENT] + XOR DX,DX + DIV CX + STOSW ;DIRSEC (temporarily) + MOVSW ;DSKSIZ (temporarily) +FNDFATSIZ: + MOV AL,1 + MOV DX,1 +GETFATSIZ: + PUSH DX + CALL FIGFATSIZ + POP DX + CMP AL,DL ;Compare newly computed FAT size with trial + JZ HAVFATSIZ ;Has sequence converged? + CMP AL,DH ;Compare with previous trial + MOV DH,DL + MOV DL,AL ;Shuffle trials + JNZ GETFATSIZ ;Continue iterations if not oscillating + DEC WORD PTR ES:[BP.DSKSIZ] ;Damp those oscillations + JMP SHORT FNDFATSIZ ;Try again + +BADINIT: + MOV SI,OFFSET DOSGROUP:BADMES + CALL OUTMES + STI + HLT + +HAVFATSIZ: + STOSB ;FATSIZ + MUL ES:BYTE PTR[BP.FATCNT] ;Space occupied by all FATs + ADD AX,ES:[BP.FIRFAT] + STOSW ;FIRDIR + ADD AX,ES:[BP.DIRSEC] + MOV ES:[BP.FIRREC],AX ;Destroys DIRSEC + CALL FIGMAX + MOV ES:[BP.MAXCLUS],CX + MOV AX,BX ;Pointer into FAT size table + STOSW ;Allocate space for FAT pointer + MOV AL,ES:[BP.FATSIZ] + XOR AH,AH + MUL ES:[BP.SECSIZ] + CMP AX,ES:[BX] ;Bigger than already allocated + JBE SMFAT + MOV ES:[BX],AX +SMFAT: + POP SI ;Restore pointer to init. table + MOV AL,ES:[DRVCNT] + INC AL + MOV ES:[DRVCNT],AL + CMP AL,ES:[NUMIO] + JAE CONTINIT + JMP PERDRV + +BADINITJ: + JMP BADINIT + +CONTINIT: + PUSH CS + POP DS +;Calculate true address of buffers, FATs, free space + MOV BP,[MAXSEC] + MOV AX,OFFSET DOSGROUP:DIRBUF + ADD AX,BP + MOV [BUFFER],AX ;Start of buffer + ADD AX,BP + MOV [DRVTAB],AX ;Start of DPBs + SHL BP,1 ;Two sectors - directory and buffer + ADD BP,DI ;Allocate buffer space + ADD BP,ADJFAC ;True address of FATs + PUSH BP + MOV SI,OFFSET DOSGROUP:FATSIZTAB + MOV DI,SI + MOV CX,16 +TOTFATSIZ: + INC BP ;Add one for Dirty byte + INC BP ;Add one for I/O device number + LODSW ;Get size of this FAT + XCHG AX,BP + STOSW ;Save address of this FAT + ADD BP,AX ;Compute size of next FAT + CMP AX,BP ;If size was zero done + LOOPNZ TOTFATSIZ + MOV AL,15 + SUB AL,CL ;Compute number of FATs used + MOV [NUMDRV],AL + XOR AX,AX ;Set zero flag + REPZ SCASW ;Make sure all other entries are zero + JNZ BADINITJ + ADD BP,15 ;True start of free space + MOV CL,4 + SHR BP,CL ;First free segment + MOV DX,CS + ADD DX,BP + MOV BX,0FH + MOV CX,[ENDMEM] + CMP CX,1 ;Use memory scan? + JNZ SETEND + MOV CX,DX ;Start scanning just after DOS +MEMSCAN: + INC CX + JZ SETEND + MOV DS,CX + MOV AL,[BX] + NOT AL + MOV [BX],AL + CMP AL,[BX] + NOT AL + MOV [BX],AL + JZ MEMSCAN +SETEND: + IF HIGHMEM + SUB CX,BP + MOV BP,CX ;Segment of DOS + MOV DX,CS ;Program segment + ENDIF + IF NOT HIGHMEM + MOV BP,CS + ENDIF +; BP has segment of DOS (whether to load high or run in place) +; DX has program segment (whether after DOS or overlaying DOS) +; CX has size of memory in paragraphs (reduced by DOS size if HIGHMEM) + MOV CS:[ENDMEM],CX + IF HIGHMEM + MOV ES,BP + XOR SI,SI + MOV DI,SI + MOV CX,(DOSLEN+1)/2 + PUSH CS + POP DS + REP MOVSW ;Move DOS to high memory + ENDIF + XOR AX,AX + MOV DS,AX + MOV ES,AX + MOV DI,INTBASE + MOV AX,OFFSET DOSGROUP:QUIT + STOSW ;Set abort address--displacement + MOV AX,BP + MOV BYTE PTR DS:[ENTRYPOINT],LONGJUMP + MOV WORD PTR DS:[ENTRYPOINT+1],OFFSET DOSGROUP:ENTRY + MOV WORD PTR DS:[ENTRYPOINT+3],AX + MOV WORD PTR DS:[0],OFFSET DOSGROUP:DIVOV ;Set default divide trap address + MOV DS:[2],AX + MOV CX,9 + REP STOSW ;Set 5 segments (skip 2 between each) + MOV WORD PTR DS:[INTBASE+4],OFFSET DOSGROUP:COMMAND + MOV WORD PTR DS:[INTBASE+12],OFFSET DOSGROUP:IRET ;Ctrl-C exit + MOV WORD PTR DS:[INTBASE+16],OFFSET DOSGROUP:IRET ;Fatal error exit + MOV AX,OFFSET BIOSREAD + STOSW + MOV AX,BIOSSEG + STOSW + STOSW ;Add 2 to DI + STOSW + MOV WORD PTR DS:[INTBASE+18H],OFFSET BIOSWRITE + MOV WORD PTR DS:[EXIT],100H + MOV WORD PTR DS:[EXIT+2],DX + IF NOT IBM + MOV SI,OFFSET DOSGROUP:HEADER + CALL OUTMES + ENDIF + PUSH CS + POP DS + PUSH CS + POP ES +;Move the FATs into position + MOV AL,[NUMIO] + CBW + XCHG AX,CX + MOV DI,OFFSET DOSGROUP:MEMSTRT.FAT +FATPOINT: + MOV SI,WORD PTR [DI] ;Get address within FAT address table + MOVSW ;Set address of this FAT + ADD DI,DPBSIZ-2 ;Point to next DPB + LOOP FATPOINT + POP CX ;True address of first FAT + MOV SI,OFFSET DOSGROUP:MEMSTRT ;Place to move DPBs from + MOV DI,[DRVTAB] ;Place to move DPBs to + SUB CX,DI ;Total length of DPBs + CMP DI,SI + JBE MOVJMP ;Are we moving to higher or lower memory? + DEC CX ;Move backwards to higher memory + ADD DI,CX + ADD SI,CX + INC CX + STD +MOVJMP: + MOV ES,BP + JMP MOVFAT + +FIGFATSIZ: + MUL ES:BYTE PTR[BP.FATCNT] + ADD AX,ES:[BP.FIRFAT] + ADD AX,ES:[BP.DIRSEC] +FIGMAX: +;AX has equivalent of FIRREC + SUB AX,ES:[BP.DSKSIZ] + NEG AX + MOV CL,ES:[BP.CLUSSHFT] + SHR AX,CL + INC AX + MOV CX,AX ;MAXCLUS + INC AX + MOV DX,AX + SHR DX,1 + ADC AX,DX ;Size of FAT in bytes + MOV SI,ES:[BP.SECSIZ] + ADD AX,SI + DEC AX + XOR DX,DX + DIV SI + RET + +BADMES: + DB 13,10,"INIT TABLE BAD",13,10,"$" + +FATSIZTAB: + DW 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + +DRVCNT DB 0 + +MEMSTRT LABEL WORD +ADJFAC EQU DIRBUF-MEMSTRT +DATA ENDS + END + \ No newline at end of file diff --git a/v1.25/source/STDDOS.ASM b/v1.25/source/STDDOS.ASM new file mode 100644 index 0000000..1216b4c --- /dev/null +++ b/v1.25/source/STDDOS.ASM @@ -0,0 +1,23 @@ + TITLE MS-DOS version 1.25 by Tim Paterson March 3, 1982 + PAGE 60,132 +; Use the following booleans to set the switches +FALSE EQU 0 +TRUE EQU NOT FALSE + +; Use the switches below to produce the standard Microsoft version of the IBM +; version of the operating system +MSVER EQU TRUE +IBM EQU FALSE + +; Set this switch to cause DOS to move itself to the end of memory +HIGHMEM EQU FALSE + +; Turn on switch below to allow testing disk code with DEBUG. It sets +; up a different stack for disk I/O (functions > 11) than that used for +; character I/O which effectively makes the DOS re-entrant. + +DSKTEST EQU FALSE + + INCLUDE MSDOS.ASM + + \ No newline at end of file diff --git a/v1.25/source/TRANS.ASM b/v1.25/source/TRANS.ASM new file mode 100644 index 0000000..6b06619 --- /dev/null +++ b/v1.25/source/TRANS.ASM @@ -0,0 +1,1213 @@ +; Z80 to 8086 Translator version 2.21 +; Runs on the 8086 under 86-DOS +; by Tim Paterson +; + ORG 100H +EOF: EQU 1AH ;End of file +EOL: EQU 0DH +FCB: EQU 5CH +SYSTEM: EQU 5 +OPEN: EQU 15 +CLOSE: EQU 16 +SETDMA: EQU 26 +CREATE: EQU 22 +DELETE: EQU 19 +READ: EQU 20 +WRITE: EQU 21 +PRNBUF: EQU 9 + MOV SP,STACK + MOV DX,HEADER + MOV CL,9 + CALL SYSTEM + MOV BX,FCB+12 + XOR AL,AL + MOV CH,4 +CLRFCB: + MOV [BX],AL + INC BX + DEC CH + JNZ CLRFCB + MOV [FCB+32],AL + MOV BX,FCB + MOV DX,PUTFCB + MOV CX,16 + UP + MOV SI,BX + MOV DI,DX + REP + MOVB + MOV DX,DI + MOV BX,SI + MOV [PUTFCB+32],AL + MOV BX,"A"+5300H ;"AS" + MOV [PUTFCB+9],BX + MOV AL,'M' + MOV [PUTFCB+11],AL + MOV DX,FCB + MOV CL,OPEN + CALL SYSTEM + INC AL + MOV DX,NOFILE + JZ ABORTJ + MOV DX,PUTFCB + MOV CL,DELETE + CALL SYSTEM + MOV DX,PUTFCB + MOV CL,CREATE + CALL SYSTEM + INC AL + MOV DX,NOROOM +ABORTJ: + JZ ABORT + MOV DX,PUTFCB + MOV CL,OPEN + CALL SYSTEM + MOV BX,PUTBUF + MOV [PUTPT],BX + MOV BX,GETBUF+80H + MOV [GETPT],BX +TRANLN: + XOR AL,AL + MOV [OP1],AL + MOV [OP2],AL + MOV BX,OPCODE + CALL LOAD + MOV BX,OP1 + CALL GETOP + MOV B,[BX],0 + MOV BX,OP2 + CALL GETOP +DOLIN: + MOV B,[BX],0 + CALL FINDOP +ENLIN: + MOV SP,STACK + MOV AL,[CHAR] + CMP AL,';' + JNZ NOCOM + MOV AL,9 + CALL PUTCH + MOV AL,';' +NOCOM: + CALL PUTCH +PUTLIN: + CMP AL,EOF + JZ END + CALL GETCH + CALL PUTCH + CMP AL,10 + JNZ PUTLIN + JP TRANLN +END: + MOV CH,127 + MOV AL,1AH +FILL: + CALL PUTCH + DEC CH + JNZ FILL + MOV DX,PUTFCB + MOV CL,CLOSE + CALL SYSTEM + MOV DX,ENDMES +ABORT: + MOV CL,PRNBUF + CALL SYSTEM + JMP 0 +DELIM: + CALL GETCH +DELCHK: + CMP AL,EOL + JZ DOLIN + CMP AL,EOF + JZ DOLIN + CMP AL,';' + JZ DOLIN + CMP AL,' ' + JZ RET + CMP AL,':' + JZ RET + CMP AL,',' + JZ RET + CMP AL,9 + RET +HEX: + AND AL,0FH + ADD AL,90H + DAA + ADC AL,40H + DAA +PUTCH: + PUSH BX + PUSH DX + PUSH CX + LAHF + XCHG AH,AL + PUSH AX + XCHG AH,AL + AND AL,7FH + MOV BX,[PUTPT] + MOV [BX],AL + INC BX + MOV [PUTPT],BX + CMP BX,PUTBUF+80H + JNZ POPRET + MOV DX,PUTBUF + MOV [PUTPT],DX + MOV CL,SETDMA + CALL SYSTEM + MOV DX,PUTFCB + MOV CL,WRITE + CALL SYSTEM + OR AL,AL + MOV DX,WRTERR + JNZ ABORT +POPRET: + POP AX + XCHG AH,AL + SAHF +NOTAF: + POP CX + POP DX + POP BX + RET +; +; Get character from source file. +; +GETCH: + PUSH BX + PUSH DX + PUSH CX + MOV BX,[GETPT] ; Get buffer pointer. + CMP BX,GETBUF+80H ; Past end-of-buffer? + JNZ GETIT ; Jump if not. + MOV DX,GETBUF ; Set `DMA address'. + MOV CL,SETDMA + CALL SYSTEM + MOV DX,FCB ; Read the next record from source file. + MOV CL,READ + CALL SYSTEM + CMP AL,0 ; Entire record read OK? + JE OKRECORD + CMP AL,3 ; Partial record read? + JE OKRECORD + MOV AL,EOF ; Force end-of-file character in case + JP TESEND ; there is nothing in the record. +OKRECORD: + MOV BX,GETBUF ; Reset buffer pointer. +GETIT: + MOV AL,[BX] ; Get next character from buffer. + INC BX ; Point to next character. + MOV [GETPT],BX ; Save new pointer. +TESEND: + MOV [CHAR],AL + JP NOTAF ; Pop registers and return. +LOAD: + CALL DELIM + JZ LOADOP +EATLAB: + CALL PUTCH + CALL DELIM + JNZ EATLAB +ENLAB: + MOV AL,':' + CALL PUTCH +LOADOP: + MOV BX,OPCODE +EATEM: + CALL DELIM + JZ EATEM +LOADLP: + CALL IDCHK + JNC $+5 + JMP OPERR + MOV [BX],AL + INC BX + CALL DELIM + JNZ LOADLP + MOV B,[BX],0 + CMP AL,':' + JNZ RET + MOV BX,OPCODE + CALL TRANS + JP ENLAB +GETOP: + XOR AL,AL + LAHF + XCHG AX,BP + SAHF +GETLP: + CALL DELIM + JZ GETLP +OPCHAR: + CMP AL,'(' + JNZ NOTLEF + LAHF + XCHG AX,BP + SAHF + INC AL + LAHF + XCHG AX,BP + SAHF + MOV B,[BX],'[' + JP NEXCH +NOTLEF: + CMP AL,')' + JNZ NOTRIT + LAHF + XCHG AX,BP + SAHF + DEC AL + LAHF + XCHG AX,BP + SAHF + MOV B,[BX],']' + JP NEXCH +NOTRIT: + MOV [BX],AL + CMP AL,'''' + JZ EATQUO + CALL IDCHK + JNC GETID +NEXCH: + INC BX + CALL GETCH +IDRET: + CALL DELCHK + JNZ OPCHAR + CMP AL,' ' + JZ OPCHAR + RET +EATQUO: + INC BX + CALL GETCH + MOV [BX],AL + CMP AL,';' + JZ L0000 + CALL DELCHK +L0000: + CMP AL,'''' + JNZ EATQUO + JP NEXCH +IDCHK: + CMP AL,'0' + JC RET + CMP AL,'9'+1 + CMC + JNC RET + CMP AL,40H + JC RET + AND AL,5FH + CMP AL,'A' + JC RET + CMP AL,'Z'+1 + CMC + RET +GETID: + MOV [BX],AL + MOV CH,1 +LODID: + INC BX + CALL GETCH + CALL IDCHK + JC RWCHK + MOV [BX],AL + INC CH + JP LODID +RWCHK: + LAHF + XCHG AH,AL + PUSH AX + XCHG AH,AL + PUSH BX + DEC BX + DEC CH + MOV DL,CH + JZ LOOKRW + MOV DL,[BX] + DEC BX + DEC CH + JNZ NORW +LOOKRW: + MOV AL,[BX] + MOV DH,AL + PUSH BX + MOV BX,RWTAB + MOV CX,LENRW +RWLK: + UP + MOV DI,BX + REPNZ + SCAB + MOV BX,DI + JNZ NOTRW + PUSH BX + PUSH CX + MOV CX,LENRW-1 + LAHF + ADD BX,CX + RCR SI + SAHF + RCL SI + MOV AL,[BX] + POP CX + POP BX + CMP AL,DL + JZ HAVRW + MOV AL,CL + OR AL,AL + MOV AL,DH + JNZ RWLK +NOTRW: + POP BX +NORW: + POP BX +ENDRW: + POP AX + XCHG AH,AL + SAHF + JMP IDRET +HAVRW: + POP BX + INC CL + MOV [BX],CL + INC BX + POP DX + PUSH BX + MOV AL,CL + MOV BX,IXSI + CMP AL,RSI + JZ IXIY + MOV BX,IYDI + CMP AL,RDI + JNZ NORW +IXIY: + LAHF + XCHG AX,BP + SAHF + JZ NOTENC + LAHF + XCHG AX,BP + SAHF + CALL OUTSTR + JP NORW +NOTENC: + LAHF + XCHG AX,BP + SAHF + POP BX + DEC BX + MOV B,[BX],'[' + INC BX + ADD AL,RIX-1 + MOV [BX],AL + INC BX + MOV B,[BX],']' + INC BX + JP ENDRW + RET +FINDOP: + MOV BX,OPCODE + MOV CX,5 + XOR AL,AL + UP + MOV DI,BX + REPNZ + SCAB + MOV BX,DI + JNZ OPERR + MOV AL,4 + SUB AL,CL + JZ RET + DEC AL + JZ OPERR + MOV CL,AL + DEC BX + DEC BX + OR B,[BX],080H + MOV AL,[OPCODE] + SUB AL,'A' + JC OPERR + ADD AL,AL + MOV DL,AL + MOV DH,0 + MOV BX,OPTAB + LAHF + ADD BX,DX + RCR SI + SAHF + RCL SI + MOV DL,[BX] + INC BX + MOV DH,[BX] + XCHG DX,BX + MOV AL,9 + CALL PUTCH +LOOKOP: + MOV AL,[BX] + OR AL,AL + JZ OPERR + MOV DX,OPCODE+1 + MOV CH,CL +LOOKLP: + MOV SI,DX + LODB + CMP AL,[BX] + JNZ NEXOP + INC DX + INC BX + DEC CH + JNZ LOOKLP + MOV DX,[BX] + MOV BX,[BX+2] + JMP DX +NEXOP: + RCR SI + TEST B,[BX],080H + RCL SI + LAHF + INC BX + SAHF + JZ NEXOP + MOV DX,4 + LAHF + ADD BX,DX + RCR SI + SAHF + RCL SI + JP LOOKOP +OPERR: + MOV BX,OPCODE + CALL OUTSTR + CALL TWOOPS + MOV BX,OPCDER + CALL OUTSTR + JMP ENLIN +LD: + CALL OUTSTR + MOV BX,OP1 + MOV DX,OP2+1 + CALL LCHECK + JNZ $+5 + JMP LDAX + XCHG DX,BX + DEC BX + INC DX + CALL LCHECK + JNZ $+5 + JMP STAX +;If immediate move, check for byte memory reference + MOV AL,[OP2] + CMP AL,20H ;Could be immediate? + MOV AL,9 + JC L0001 + CALL BYTCHK ;Add "B," if memory reference +L0001: + CALL TRAN1 + JP TRNOP2 +TWOOPS: + CALL TRNOP1 +TRNOP2: + MOV AL,',' +TRAN2: + MOV BX,OP2 +PTRANS: + CALL PUTCH +TRANS: + MOV AL,[BX] + LAHF + INC BX + SAHF + OR AL,AL + JZ RET + CALL TRNTOK + JP TRANS +LCHECK: + MOV AL,[BX] + CMP AL,RAL + JNZ RET + MOV SI,DX + LODB + CMP AL,RCX + JZ RET + CMP AL,RDX + RET + +ONEOP: + CALL OUTSTR + MOV AL,9 + CALL BYTCHK ;If memory reference, add "B," flag + JMPS TRAN1 + +TRNOP1: + MOV AL,9 +TRAN1: + MOV BX,OP1 + JP PTRANS +IN: + MOV AL,[OP1] + CMP AL,RAL + XCHG DX,BX + MOV BX,OP2 + JZ GETPORT + MOV BX,SAVEAX + CALL OUTSTR + CALL OUTSTR + MOV BX,OP2 + CALL GETPORT + MOV BX,MOV0 + CALL ONEOP + MOV AL,',' + CALL PUTCH + MOV AL,RAL + CALL TRNTOK +IODONE: + MOV BX,RESTAX + JMP OUTSTR +OUT: + MOV AL,[OP2] + XCHG DX,BX + MOV BX,OP1 + CMP AL,RAL + JZ GETOUT + MOV BX,SAVEAX + CALL OUTSTR + MOV BX,MOVAL + CALL OUTSTR + CALL TRNOP2 + MOV BX,CRLFTB + CALL OUTSTR + MOV BX,OP1 + CALL GETOUT + JP IODONE +GETPORT: + MOV AL,[BX] + CMP AL,'[' + JNZ NOBRAK + LAHF + INC BX + SAHF + PUSH BX + MOV CX,80 + MOV AL,']' + UP + MOV DI,BX + REPNZ + SCAB + MOV BX,DI + LAHF + DEC BX + SAHF + MOV B,[BX],0 + POP BX +NOBRAK: + MOV AL,[BX] + CMP AL,RGCL + JNZ FIXPOR + MOV BX,IO1 + CALL OUTSTR + XCHG DX,BX + CALL OUTSTR + MOV AL,RDX + CALL TRNTOK + MOV BX,IO2 + JMP OUTSTR +GETOUT: + CALL GETPORT + JNC RET + MOV BX,BADIO + JMP OUTSTR +FIXPOR: + XCHG DX,BX + CALL OUTSTR + XCHG DX,BX + JMP TRANS +LDAX: + MOV BX,LDAX1 +LSAX: + CALL OUTSTR + MOV SI,DX + LODB + CALL TRNTOK + JP OUTSTR +STAX: + MOV BX,STAX1 + JP LSAX +TRNTOK: + CMP AL,' ' + JC $+5 + JMP PUTCH + PUSH BX + PUSH CX + MOV CL,AL + MOV CH,0 + MOV BX,TOKTAB-2 + LAHF + ADD BX,CX + RCR SI + SAHF + RCL SI + LAHF + ADD BX,CX + RCR SI + SAHF + RCL SI + MOV AL,[BX] + CALL PUTCH + INC BX + MOV AL,[BX] + POP CX + POP BX + OR AL,AL + JZ RET + JMP PUTCH +PUSH: + MOV DX,PUSHAF + JP AFCHK +POP: + MOV DX,POPAF +AFCHK: + MOV AL,[OP1] + CMP AL,RAX + JNZ ONEOPJ + XCHG DX,BX +OUTSTR: + MOV AL,[BX] + OR AL,AL + JNZ L0002 + CALL NEWOP +L0002: + CALL PUTCH + INC BX + ADD AL,AL + JNC OUTSTR + RET +NEWOP: + MOV AL,13 + CALL PUTCH + MOV AL,10 + CALL PUTCH + MOV AL,9 + RET +LDDR: + CALL OUTSTR + MOV BX,BLMOVE + JP OUTSTR +CPDR: + CALL OUTSTR + MOV BX,CMPREP + JP OUTSTR +ADD: + MOV AL,[OP1] + CMP AL,RBX + JZ DAD +ARITH: + CALL OUTSTR + MOV AL,[OP2] + OR AL,AL + JZ $+5 + JMP TWOOPS + MOV AL,9 + CALL PUTCH + MOV AL,RAL + CALL TRNTOK + MOV AL,',' + JMP TRAN1 +ACCUM: + CALL OUTSTR + MOV AL,9 + CALL PUTCH + MOV AL,RAL + JMP TRNTOK +ONEOPJ: JMP ONEOP +DAD: + MOV BX,DAD1 + CALL OUTSTR + CALL TWOOPS + MOV BX,DAD2 + JP OUTSTR + +INCDEC: + MOV AL,[OP1] + CMP AL,RCX+1 ;16-bit? + JNC ONEOPJ + MOV BX,LAHF + CALL OUTSTR + XCHG DX,BX + MOV BX,OPCODE-1 + CALL ONEOP + XCHG DX,BX +OUTSTRJ: + JMP OUTSTR +JUMP: + MOV AL,[OP1] + CMP AL,'[' + JNZ DIRECT + MOV AL,[OP1+1] + MOV [OP1],AL + XOR AL,AL + MOV [OP1+1],AL +DIRECT: + MOV AL,[OP2] + OR AL,AL + JZ ONEOPJ + CALL FIXCON + MOV BX,OP2 +OUTCON: + MOV CH,AL + MOV AL,'J' + CALL PUTCH + MOV AL,CH + CALL TRNTOK + MOV AL,9 + CALL PTRANS + MOV AL,CH + CMP AL,ODDPAR + MOV BX,WARNPA + JZ OUTSTRJ + CMP AL,EVEPAR + JZ OUTSTRJ + RET +FIXCON: + MOV AL,[OP1] + CMP AL,RGCL + JNZ RET + MOV AL,CY + RET +RETURN: + MOV AL,[OP1] + OR AL,AL + JZ OUTSTRJ + MOV BX,'R'+4500H ;"RE" + MOV [OP2],BX + MOV BX,'T' + MOV [OP2+2],BX + JP DIRECT +ONEOPJ1: + JMP ONEOP +DOCALL: + MOV AL,[OP2] + OR AL,AL + JZ ONEOPJ1 + CALL FIXCON + DEC AL + XOR AL,1 + INC AL + MOV BX,LABEL + CALL OUTCON + MOV BX,OPCODE-1 + CALL OUTSTR + MOV AL,[OP2] + OR AL,AL + MOV AL,9 + MOV BX,OP2 + JZ L0003 + CALL PTRANS +L0003: + MOV BX,CRLF + CALL OUTSTR + CALL TRANS + CALL OUTSTR + MOV BX,LABEL+4 +NEXLAB: + INC [BX] + MOV AL,[BX] + CMP AL,'9'+1 + JNZ RET + MOV B,[BX],'0' + LAHF + DEC BX + SAHF + JP NEXLAB +EX: + MOV AL,[OP1] + CMP AL,RAX + JZ OUTSTRJ1 + MOV AL,[OP1+1] + CMP AL,STP + JZ XTHL + MOV BX,XCHG + CALL OUTSTR + JMP TWOOPS +XTHL: + MOV BX,XTHL1 + CALL OUTSTR + CALL TRNOP2 + MOV BX,XTHL2 +OUTSTRJ1: + JMP OUTSTR +PSEUDO: + CALL ONEOP + MOV AL,[OP2] + OR AL,AL + JZ RET + JMP TRNOP2 + RET +BITSET: + MOV CL,0 + JP SETRES +RES: + MOV CL,-1 +SETRES: + CALL OUTSTR + PUSH BX + MOV AL,[OP2] + CMP AL,'[' + MOV AL,9 + JNZ L0004 + CALL BFLAG +L0004: + CALL TRAN2 + MOV AL,',' + CALL PUTCH + CALL GETBIT + MOV BX,BITERR + JNC L0005 + CALL OUTSTR +L0005: + POP BX + JMP OUTSTR + +BYTCHK: +;Check if memory reference and add "B," for byte mode + CMP B,[OP1],"[" ;Memory reference? + JNZ RET + CMP B,[OP1+1],RIX ;Referencing IX as a word? + JZ RET + CMP B,[OP1+1],RIY + JZ RET +BFLAG: + CALL PUTCH + MOV AL,'B' + CALL PUTCH + MOV AL,',' + RET + +GETBIT: + MOV AL,[OP1+1] + OR AL,AL + STC + JNZ RET + MOV AL,[OP1] + SUB AL,'0' + JC RET + CMP AL,8 + CMC + JC RET + MOV CH,AL + INC CH + XOR AL,AL + STC +SHFT: + RCL AL + DEC CH + JNZ SHFT + XOR AL,CL + MOV CH,AL + MOV AL,'0' + CALL PUTCH + MOV AL,CH + RCR AL + RCR AL + RCR AL + RCR AL + CALL HEX + MOV AL,CH + CALL HEX + MOV AL,'H' + JMP PUTCH +OPTAB: + DW AOPS,BOPS,COPS,DOPS,EOPS + DW FOPS,GOPS,HOPS,IOPS,JOPS + DW KOPS,LOPS,MOPS,NOPS,OOPS + DW POPS,QOPS,ROPS,SOPS,TOPS + DW UOPS,VOPS,WOPS,XOPS,YOPS + DW ZOPS +AOPS: + DM 'DD' + DW ADD,OPCODE + DM 'DC' + DW ARITH,OPCODE + DM 'ND' + DW ARITH,OPCODE + DB 0 +BOPS: + DM 'IT' + DW BITSET,TESBIT + DB 0 +COPS: + DM 'ALL' + DW DOCALL,OPCODE + DM 'P' + DW ARITH,CMP + DM 'PL' + DW ACCUM,NOT + DM 'PIR' + DW OUTSTR,CPIR + DM 'PDR' + DW CPDR,DOWN + DM 'CF' + DW OUTSTR,CMC + DB 0 +DOPS: + DM 'EC' + DW INCDEC,OPCODE + DM 'JNZ' + DW ONEOP,DJNZ + DM 'AA' + DW OUTSTR,OPCODE + DM 'I' + DW OUTSTR,OPCODE + DM 'W' + DW PSEUDO,OPCODE + DM 'B' + DW PSEUDO,OPCODE + DM 'M' + DW PSEUDO,OPCODE + DM 'S' + DW ONEOP,OPCODE + DB 0 +EOPS: + DM 'X' + DW EX,EXAF + DM 'I' + DW OUTSTR,OPCODE + DM 'XX' + DW OUTSTR,EXX + DM 'QU' + DW ONEOP,OPCODE + DM 'NDIF' + DW OUTSTR,OPCODE + DB 0 +FOPS: + DB 0 +GOPS: + DB 0 +HOPS: + DM 'ALT' + DW OUTSTR,HLT + DB 0 +IOPS: + DM 'NC' + DW INCDEC,OPCODE + DM 'N' + DW IN,INB + DM 'F' + DW ONEOP,OPCODE + DB 0 +JOPS: + DM 'R' + DW JUMP,JR + DM 'P' + DW JUMP,JMP + DB 0 +KOPS: + DB 0 +LOPS: + DM 'D' + DW LD,MOV + DM 'DIR' + DW OUTSTR,UP + DM 'DDR' + DW LDDR,DOWN + DB 0 +MOPS: + DB 0 +NOPS: + DM 'EG' + DW ACCUM,OPCODE + DB 0 +OOPS: + DM 'R' + DW ARITH,OPCODE + DM 'UT' + DW OUT,OUTB + DM 'RG' + DW ONEOP,OPCODE + DB 0 +POPS: + DM 'OP' + DW POP,OPCODE + DM 'USH' + DW PUSH,OPCODE + DB 0 +QOPS: + DB 0 +ROPS: + DM 'ET' + DW RETURN,OPCODE + DM 'LA' + DW ACCUM,RCL + DM 'RA' + DW ACCUM,RCR + DM 'LCA' + DW ACCUM,ROL + DM 'RCA' + DW ACCUM,ROR + DM 'L' + DW ONEOP,RCL + DM 'R' + DW ONEOP,RCR + DM 'LC' + DW ONEOP,ROL + DM 'RC' + DW ONEOP,ROR + DM 'ES' + DW RES,RESBIT + DM 'ETI' + DW OUTSTR,IRET + DM 'ETN' + DW OUTSTR,IRET + DM 'ST' + DW ONEOP,CALL + DB 0 +SOPS: + DM 'UB' + DW ARITH,OPCODE + DM 'BC' + DW ARITH,SBB + DM 'LA' + DW ONEOP,SAL + DM 'RA' + DW ONEOP,SAR + DM 'RL' + DW ONEOP,SHR + DM 'CF' + DW OUTSTR,STC + DM 'ET' + DW BITSET,SETBIT + DB 0 +TOPS: + DB 0 +UOPS: + DB 0 +VOPS: + DB 0 +WOPS: + DB 0 +XOPS: + DM 'OR' + DW ARITH,OPCODE + DB 0 +YOPS: + DB 0 +ZOPS: + DB 0 +LDAX1: DM 9,'SI,' + DM 0,'LODB' +STAX1: DM 9,'DI,' + DM 0,'STOB' +PUSHAF: DB 'LAHF',0,'XCHG',9,'AH,AL',0,'PUSH',9,'AX',0 + DM 'XCHG',9,'AH,AL' +POPAF: DM 'POP',9,'AX',0,'XCHG',9,'AH,AL',0,'SAHF' +DOWN: DM 'DOWN' +UP: DB 'UP' +BLMOVE: DB 0,'MOV',9,'SI,BX',0,'MOV',9,'DI,DX' + DB 0,'REP',0,'MOVB',0,'MOV',9,'DX,DI' + DM 0,'MOV',9,'BX,SI' +CPIR: DB 'UP' +CMPREP: DB 0,'MOV',9,'DI,BX',0,'REPNZ',0,'SCAB' + DM 0,'MOV',9,'BX,DI' +DAD1: DM 'LAHF',0,'ADD' +DAD2: DM 0,'RCR',9,'SI',0,'SAHF',0,'RCL',9,'SI' +LAHF: DM 'LAHF' + DM 0,'SAHF' +DJNZ: DB 'DEC',9,'CH',13,10 + DB '; *** WARNING: DJNZ does not affect flags - DEC does.',0 + DM 'JNZ' +WARNPA: DM 13,10,'; *** WARNING: Parity flag not always same as Z80.' +IO1: DB 'MOV',9,'DI,DX',0,'MOV',9,'DL,CL',0 + DM 'XOR',9,'DH,DH',13,10,9 +IO2: DM 0,'MOV',9,'DX,DI' +BADIO: DM 13,10,'; *** WARNING: Flags not same as Z80.' +BITERR: DM 13,10,' *** ERROR: Cannot determine bit number.' +SETBIT: DM 'LAHF',0,'OR' + DM 0,'SAHF' +RESBIT: DM 'LAHF',0,'AND' + DM 0,'SAHF' +TESBIT: DM 'RCR',9,'AH',0,'TEST' + DM 0,'RCL',9,'AH' +XTHL1: DM 'POP',9,'SI',0,'XCHG',9,'SI' +XTHL2: DM 0,'PUSH',9,'SI' +EXX: DB 'XCHG',9,'BX,[HL]',0,'XCHG',9,'DX,[DE]',0 + DM 'XCHG',9,'CX,[BC]' +EXAF: DM 'LAHF',0,'XCHG',9,'AX,BP',0,'SAHF' +MOVAL: DM 0,'MOV',9,'AL' +IXSI: DM 9,'MOV',9,'SI,[IX]',13,10 +IYDI: DM 9,'MOV',9,'DI,[IY]',13,10 +RESTAX: DB 0 +SAVEAX: DM 'XCHG',9,'AX,SI' +CRLFTB: DM 13,10,9 +INB: DM 'INB',9 +OUTB: DM 'OUTB',9 +XCHG: DM 'XCHG' +JMP: DM 'JMP' +JR: DM 'JMPS' +RCL: DM 'RCL' +RCR: DM 'RCR' +ROL: DM 'ROL' +ROR: DM 'ROR' +SAL: DM 'SAL' +SAR: DM 'SAR' +SHR: DM 'SHR' +STC: DM 'STC' +IRET: DM 'IRET' +HLT: DM 'HLT' +CMC: DM 'CMC' +NOT: DM 'NOT' +MOV0: DB 0 +MOV: DM 'MOV' +CMP: DM 'CMP' +SBB: DM 'SBB' +CALL: DM 'CALL' +TOKTAB: + DB 'SIDI' + DB 'PEPOS',0,'NSNZZ',0,'NCC',0 + DB 'AXSPBXDXCX' + DB 'BLBHDLDHCLCHALIXIY' +RWTAB: + DB 'ABCDEHLBDHSACNZNPMPPII' +LENRW: EQU $-RWTAB + DB 0,0,0,0,0,0,0,'CELPF',0,'C',0,'Z',0,0,'OEYX' +HEADER: DB 13,10,'Z80 to 8086 Translator version 2.21',13,10,'$' +NOROOM: DB 13,10,'File creation error',13,10,'$' +NOFILE: DB 13,10,'File not found',13,10,'$' +ENDMES: DB 13,10,'Translation complete',13,10,'$' +WRTERR: DB 13,10,'Out of disk space',13,10,'$' +OPCDER: DM 13,10,'*** Opcode Error ' +CRLF: DM 13,10 +LABEL: DB 'L0000',0 + DM ':',9 +PUTPT: DS 2 +GETPT: DS 2 +CHAR: DS 1 + DB 0 +OPCODE: DS 80 +OP1: DS 80 +OP2: DS 80 +PUTBUF: DS 128 +GETBUF: DS 128 +PUTFCB: DS 33 + DS 50 +STACK: EQU $ + ORG 1 ;This is really just for equates without EQU +RSI: DS 1 +RDI: DS 1 +ODDPAR: DS 1 +EVEPAR: DS 1 + DS 5 ;MINUS,PLUS,NOT ZERO,ZERO,NOT CARRY +CY: DS 1 +RAX: DS 1 +STP: DS 1 +RBX: DS 1 +RDX: DS 1 +RCX: DS 1 +RBL: DS 1 +RBH: DS 1 +RDL: DS 1 +RDH: DS 1 +RGCL: DS 1 +RCH: DS 1 +RAL: DS 1 +RIX: DS 1 +RIY: DS 1 + \ No newline at end of file