IMD 1.18: 6/10/2017 21:33:45 MS-DOS Operating System TDD Version 2.0 - Disk 1 Series #86 Copyright 1979-1983 by Seattle Computer Products, Inc.  3؎мx v X0z{Wx|r_$uǁǀ@x |ux3؎м@` @`! #@%`')+-/1 3@5`79;=?A C@E`GIKMOQ S@U`W[]_a c@e`gikmoq s@u`wy{} @` @ ` @ `  O `  @ ` ɠ @ ` ׀ ٠  @ @`!Aa   !Aa!!#A%a')-/1!3A5a79;=?A!CAEGIKMOQ!SAu~t }uF~ƃ@` @`! #@%`')+-/1 3@5`79;=?A C@E`GIKMOQ S@U`W[]_a c@e`gikmoq s@u`wy{} @` @ ` @ `  O `  @ ` ɠ @ ` ׀ ٠  @ @`!Aa   !Aa!!#A%a')-/1!3A5a79;=?A!CAEGIKMOQ!SAu~t }uF~ƃIO SYS'ˊ MSDOS SYS'vPCOMMAND COM $o:x<MSDOS_201 FLIB EXE Y}CREF EXE %6FUNKEY EXE iyn CONFIG SYS eIOSEG &WcMAKIOSYSBAT -[lLINKIO BAT Y[PUTIO BAT |tHDISK DEV NIODEF ASM \2FDISK ASM ~u':IO ASM *vwINIT ASM r tCONIO ASM `g+AUXIO ASM TX:PRNIO ASM TX>TIME ASM `g@$ HDISK ASM foF1 M@]hCON *@]nAUX <@]tPRN N@]zCLOCK @ ].Y.[VMVV VVPQRWUS.YGg OWG2< w%.YG)O[]_ZYX^3ɴôð>DH& u:u Px$ Xu?F׊ й|P{X$t Ԁp YgøÊ:t y{tYwO3ɴIr!QYr6rQYrʬtഁ@ &طw$ |t @uƊ†y:t'Y&E V6;6t; ^tV66^. . Fmr   $tTVPQRWL_ZYXϋ&Q>Y2ABCDHJKfmsu%<uP$tXP<[u1 <;u<0r<9wW>_P[묿=t:uG<t9t-g@˃3P!$%!6 tʴ!3۴>!>!C=!sP>!XشE!E!3+ uO 5OOO 3K!H!H!MI7!=!r,v;GI>}U>G&&E(GG3t/>GG&G&EG&E_GqIM+شJ!H&úF33ҸB!C3ҸB!ʡC+Ѓڎ36C?!P>!Xr;t z;rBu (t"Cttt&U &]t&U&] .\ u .GȊ&U&E.a..&n&~t&n.G&F.I&F..G.G^&F&F7CC&VS!&F.>&;Ev ^mR.&V&^ZB.>&M&U.6&u&]. T^@tFu tWuи7!lAuC36EOr< uFQV3!^ZY[Xs3D!€u>!=!ÃX[YZ^_]P!X\DEV\NUL\DEV\CON\DEV\AUX\DEV\PRN\CONFIG.SYS\COMMAND.COMBUFFERSBBREAKCSHELLSDEVICEDFILESFSWITCHARWAVAILDEVA Unrecognized command in CONFIG.SYS $ Sector size too large in file $ Bad or missing $Command Interpreter0^*ƍpǍ^*~}򤊆^]Udž^ ;s]΍PRv+Pa u^ +^ p򤋆@P^딉]U ]Ul ]U ]U ]U ]U8 ]U GP:PPa F~tx ȴ9Fti Fd FF;FsQƋ @,0FF<r< v'>d w>d t@P~w@Y"sP5g  ]ˡd Nd U~t PP ]U^PPPa ]U6< ^PSg P$ Pg ]U6< v Pg ]U6< ^GPP$ Pg ]UF<v3B t F]U~vP6: vFPFP2 B >B t v: vNFYFF)^ )F몉]U~v16: vFPFP2 B >B t F)^ )Fɉ]UQFPPrg F]UP6t  Fg F^ HF=v P  RPvrg ^QF <t ѴÊ X: w@"s   ^FBL ^ X Fn s[> uTn R\ >n v1< F< P 6L  ~tF< Fۋ>n R]U< ]UQ4 s 6> F> t8g s 6< F ]UQ s 6< Fv5g ]UQb > t 8g  v5g ]U3 sZ2P5g / 6: FPn F?P5g vPg vPg FP5g  PPg 8g s 6< Fv2 ]UP6F P$ F^G F^tP7P$ FFFÍGPrg ~t-(PYg PvP$ F^GPrg )PYg ]Uvv]UQQ~tUgP{P^Pw$ F8g 3 v]U|PEP5g vPg 8g vu]U 3 @ FFuF QPP$ F^GFGFu@FGFG F^tH QPP$ FFR F0 ;Fu Fr0 ;FtFs 6: FR GPGP : tR :uG,AF< F< P5g R GPrg 8g F:5 t@P~u@Y"P~u@Y" ,PQ8Ft@Y"Y Pv6>Y s 8g 2 P5g P"<PPRF>"< uښ8g F< Ft" FFF6: FP[ F^F0 Fs6: Ftv  ~t2 s 6: F3 ]U^ t7Fs8g ^GPrg P5g PYg ^ GF / ] U < P5g FF=w ñ XBDÈVFs؃>< tG s P5g >l u P5g >d t P5g 6d $g !P5g 8g 0 P6 }  5  F~?w^LJFLJFFs0 AP6 sF8 s?< F< (P5g FP5g P"<PPRF8g F< y P P( < F s5< _P5g aPP( 8g ~t F< Fу>b th~t.b {P5g >b uP5g 6b $g P5g >b tsPYg P5g s 6< F 2 ]U~ }6t+JVu P5g v PP( F sL^t4^utG;FuG;FtjP^7P$ F6V P( F^G FGFG6 FT 6 >@ u@ PvP$ F6 ^G]UQ 9 ]U 9 ]U ]U ]U^?tPa ^:u?u G AƆ:ƆPP $ P^P $ 3 s> t ƆZPPP( uE> r P`P PPP(  V   ]UQ^^:u8^F~t.FȈFƋ^H^:Htࠗ s @2< tа]UQQ^FF~v#FȈFFȊN΋^H 2ԊF]UQQ H%F F;FvF FF r PP PvP$ F]UPvP$ F~,F^PuT FF^8FwFƋ^FuފF^GvDT Dv F]UQF V QPP$ R R GT  sNP6T P$ F^G:Fu-^T uˊFs 6V v( ]UQQv MF^㋇ V  >V upFrb ^ PYV R ^㋏ ÉGV Gv ^V ~t Pv( HCx>DEV/$,.| NUL ȦȥȥU.&.&6&& 2&D&D^^&D>&&> &E&E&&EBP.&&H&Z&+HX   MS-DOS version 2.00 Copyright 1981,82,83 Microsoft Corp. $(rWvXX.P.6$w.8.6ˎ-" XP&&.0ˎӼ2>01 t v QtPu >.u ./2tP"X6.68.-.&.F.".. ..~X[YZ^_].6~.~UWVRQSP.6a33333  33455 '(&(&0&z('Z z|ZZ Z@&H&" ` P&X& %%%%s 2   "  = ` 9H8%9::g:i9:;j;::O}  <<2u ...>u&..=r&V J&F&NLTlD\L tR_36$6 u 62Du 62ðD-TDTr$3һ&N IQuBC[&F2&NOL\T26>6&>6</\3 # rR x+&E&E&E&E>:u  t%2&E9$rEm x]RP6.6 X5 _ll rƒ!&M u3FF%DP Zt@uBª@s&%bE!U#}@su$66$\L66ò%rlD2ðf53E}tEu6*6 :s6*Ê3ru &M@2&e3rt2SvrDtVtD^t)[TrPKtX.<$t(.(.*S.(&O[v!VD&\D&&_3ێÊ6.t.\3.t63۹5-rW,r&_&&C6[S&.3Ɏَ¾ &+=v +رڣ P!R..6Dt 2tD+r...hru>#+Vu63rQ]>#&E. e..Z].Z2_>#^3҉TTE&FOZZ.2/>#^9*rZRmrOuM&^ ^t.>tFF.>tFA+ t)3&=tGC/.:u\CXXC@3۬ tf<.t-@r&E!uO2&Fά t?<.u# t3Ws<t usX_OK;tP&E XtOKOU)rru!> t&NuhBT\XX(;u>#+Su? 2%=. uă=..u+s.Z2>#[N uuu uðTËЬȪ2uĪإH‹3GG&F&F&F &+F ؊@&F &F..&6-r t6-6&6..&6-r 6$s9u>Zt@&>Mt &>ZtÀ>Ztr&>u&A&3P6r>t>Zt sX-5[\rZ;vR;wt%@+I&M&&6@[H=r & 럌H(s뇎5rQ;vy6a6_6c6Du{3ۉT^Q tttR tKQ.S6>TtX<t6&Uu^&UԀ6ô t&ttt!t#D#D!#PQY ?6u6I6666a_cD46I66_6&ItD6M6O6MD6M6MVWQu DtV ^t4uY_^6|66.$?: r &:Ft&n.WQP7XP3XઆPëثYX_7WQP6ơ=uv>uË  tr u +>r2|&N2Q4&N>#W3s_&EYBء+@ù 󫪋6 DD«3rR_rrX>u*%' t36:&t,G t6' t/&}?t.sM+;s:&t1,&t t2tltt.&fá++3&^Si[#&Vá+;t%@ ;r:rsrã+È+>#UBJ3&^ tr8vs&&F3H&F &V+¢á&F t&F >2ۈPY6su u2:t,6u xQ6%o u-Yt2 6tP>.u>W Xt>GV% ^<w 366tC<:teNNV6>tsH6P6X6^2r V^6<t@V@s^XX6 ,`VP=Xs^rrtNVc236t N&:EtìEu <.t3t tà yVȀɀ_;uV>tMr ut^^WQY_rp>#G tU6>t׌_=tPW؋++SPVQuZ2)Y^X[>#_ tGudN2_ t^ .3+'HP6"$XWVS8!162&u&]&]3!06,&u&]&]01[^_WVS013 &]0&u66,6.66\t&]&u&] &]1&u6626466\t&]&u&]{ x/>@tt923366t״6>:t <t׋6>Iv ut؋3ҋQY66t7)W6>:t_6I<t2_6>Iu6G6E6:G<t< O< u < u3 K6>u >&e:6 u>tQWa_Y<uO j3 xe<&E&UX-Q<t>X+)366.״6>:t <tI>3&uÀ@33Ҩ uuug€?tZQY66tW6>:tR_6I<t _6>ItB6EG6G=t 6:ⶋkW?r_68 ry6*6Ê&2Ԁ*߁s׊2f Ë&N&F2RQP XYtZt6<tZQ&f&FSV"t6n<tQ&f&FSe>v[6I_+6:P6Eu uu6> y2Xs 3[Ã@r2R[Ãu^С&^;sN  &"F&NtuH3>&]3>[á  t&+F+s3ۣ3&v u=u&F&E&]+ru t;s.l t >t>tr7WPSRQ[Z&FhE:EuA9Ur<9]s7}t.XPWR+Uڋ&N6sZ_&FG4uYY[s 낡 tr  6+3&L;t" t+3s@ȋ&Ex&e& E&EIAÀ?&].Gx&v uH&NPR>&E&U&v t@ 3!X+r_t8ʓ&f+Ã+Is3>] +v!3ң!>t>t Xn+t QXrȋBItn>t te WPRS&FUE:Eu9Ur 9]sEcPu[Z6Y[  t J>! u t&E&M7 t;-&v&Nur>&E&E3 3>&]&]&e tc&;^ w=sQYP Xb5s QY 566#D6>tPSQ%$P2>#EO&~XY[XPSQR3&N&FIPRQ26#|YXZ;u)B2~6#|ZY[XÁ c&f79:&FD7&v>:u2&f &Ext> ;Et=uE:EuE6#u&~E us># U6> ]6G>E&f79:&FD&v&v7^,>:u1&F6I:D t6>E&F&fE&Fu&F=uE!U#>&]&U t+s3&]sBAJË 6>>#> Îۇs6>#]+&;vrOá @ ; w2s6#Gw+&;vr t%&:Fvs>RS&F*‹ѹȀ;s-C;tK+R&f6ƣXZ+[+*̈&Q&NJJ &V YË=uE U ؊ֶS37>[RQSËC&;^ ~+=+[{X+ZbB&VB+w3t H~Ɠt뽇ڋⰺ[YZ u>&]&e& ]SRW3ۋ_Z[3t=rs6> P3E=u6> XÃt}u=5W tM66 zu 6 6.V4etXX^ lV4tXX^ 6&5&]V4tXX^D;uQRٌ;ZY3&F>3t ;Uu:Euo6> ;Uu:EuI=u6> VRU]Z^6u]VWR t=YZ_^Um E2&FE t&F&fE 6%65>#>3> 8et&:t:Eu}tPuX26:/uEX=uøE#6u G t6E' t &;^ wEsZrcrzr x侩 󤿩 #&E ZsrVP2 x%@3 ХDDX^ @x'«P3X6&Q Ī6YĪ3&=uEu\ rZR\S[y_r>#L &M &UT&UT&UT&UTG.&F2ðr) ?t6R .sOr9ZZYRQu xv># u&;N w+SVZ2[#t>'u%󥠵3 3W6#&D.&FPS[X^_q6>-tQSV3igjg66ju.6t<u(6i6g6t6jA6y^[Yo2^[Y<tI<tE<tAÜ6>1t 6>.u(S3[r't<u2 6 tS3[r2<t<t<u۰ >0t&Z.-...&:#.X.;&:u.@..:.;&:t L.P.sx* Divide overflow igjg6uy6v.u.y66.VW^×u P&F6/X+R&fZ2&;Vr&;Vr &;V r6 &&F66.&v6>.uM6&6.6-6&&$&&&Ď6&6-6.6.<t 6/2>0t>"666ۡY;t";uP6>>tQKQ Y69-/0&.XXX P.6.662Ҩu&G t3t3󪑫t stuFjIv<:uF,@v6: vFONG<.uF NvN r#u 6t< uI<*u?t<+t<=t<;t<,t< t< %.u..=MZt=ZMt}.+!...t)>-&5.&E.x P6. XIPXr;wԀ>.u#.r;w+#.%.r;v؉.r.>.t .+.-.5.!.RX ȋ.2 .r).Sˋ.5.3QeC hY;[u 5.>.u.'..)..-. . .3ɋ1..3 s.R.6. Zr߹.66.u&Ǝ؋J6.t 66-65.0 t6.S[6.65.sñP6.3ɋ3 6.Y65.3QcA f^;t6.u"65.-6 .6 .N66.6.6.&)6.tK6.6. tH؉6.H؉R6\Z66.&,66.&666-Vt Q\3Y^Vt l<󤫫^t6:> v26: v2tttt& & 3؏6666.t&66.6>-&]NN&u6 .&]&EV66 .6-6..&.VŽڋS [S.[P.. tH؉.. tH؉XP6>6sS+[rãX$126& 6>t6>66D~ZSVTWUEJDPQRR<4>555454E5x5K5n5P55PXÊ< rC<t6V66&uPX^6tSVXr Dt}}< t <t&< u6 Qȵ Y66< s< tP^vX @pr2t2+SSPXVt^[Vt2^Ë<$tЎ2 t܊:v8 t݊J66V6.< u<t6:2t8<t+<t'< t@< t`<tb:s26>u:sFXa W2_2_uƌŌێÎݾð i d|\Y^6M tR&< s< tG6>u tNBWOΰ Sv &} t 6**ˀ[_tO 62*46:t:t 5:tFa*tItWG_u*]@s_W^ 6zt PR3rZX<t<t<t <t< tQ  ΋ѡ$Y #VS3ҋ}6[^;'tB=6s='VQR3ҹȾ}#s$$B#ZY^ô;r+A%uƻ:°rt#鸵%}RϾIIIђ'VSP3ҋS6[ڏ6 [^'3ҹ@@)2ôPQV t):u|t t6t&+E|&=&ES([XP?r&)r6->/1$ s؎%&3Āu$&G tut>4u >(u V>/1g &e^>/&3>/&( &E3&E$&E&@&E>)-&j sh&#G tE؁t&FsR4kZ t<t̰o6769656S665*6667696566665QRʎZY;r &}uN̋D6;L(ur&}t;o;UrWW^r&G뵰뛰SQgY[qsΰ<rrEt33||EUE$U&ˉT띒E$U&<vrفtQPaZYr6># t&g &O &E3&O ?ˉL<wNR}Zs<s2<&Et t ꨀtS&U2䨀t&}&eʋЉT&Et.&}I<v(,tuPXrԊuɰ룰QRPVr&&~^XZYr&E@ttS SQ3T^c_6aQ6cSV?A6Cst*6%wwwwww 6666AXr 6:t 66AXP666r66#XG GGGGGD66=j66#D st뚋Q667Y6s6%o t 66+66>66 S6+666G GGGG^< uO< t.< uO2Z66BV^sP͋D l x\6P6.6Xy-..&.0AȎ666V  Ȫ2 ê^ƫثL6664Dt6662A4thDu6D2L 6 26 V6I7CC&V&vSQR&F6; v6 ZY[^&v&^VŽ؃^^. {>Ё{>U2A 2^\^ջ͉&w3؎p*{2 3G>UR3EZ]Y2A>+;vIA(6768696:SP7}X[  m =t=t=t = tɎѼ!rδM!.eȎش !,t3pp >ltl>du˺>kt>lu>ku %.L!l I!#P!e>du3d...!X@Q!.#P!.l.d.>dt=H!. ;sKH!r.d. .`.+.\Ȏм}3n=t.!>lu"Z@;bt+/;bt7! /u \+ H+\`.ZP3X3ۋh:t>!C:t>!.>!CSPQ!ۡ.)X[$SPQ!)ۣX[ú4&^u6>^u>K !E2=!s=u  غp3ɸB!r-\?!P>!Xr;t\(3ҭú"%!#%!$%!j3 !$_'狽t  !>+tzqo !d ltl>'t>'up>ltlċϺ  뺦PSRVP$<0r<9w,0؋д!Xt^Z[X#,8<KO[ks~,Write protecBad uniNot readBad commandDatBad call formaSeeNon-DOS disSector not founNo papeWrite faulRead faulDisreadwrit e5writin drive A device $ COMMAN allocation filerrorCannotemor batcInserAbort, Retry, Ignore?0File3table bad0Invalid1.COM091.COM disk indrive Adefault driv0and strike any key when ready0Terminate8 job (Y/N)?EXEC failureE5in EXE4Program too big to fit in m70Bad or missing Command Interprete0No free4handle0M73e06load1, system halte06start1, exiting2or4name,_:/%PIPE1.$$$_:/%PIPE2.$$$  \lU-/LPATH=\BINCOMSPEC=\COMMAND.COM     `.+£\, t £ 7! /u\>u&\\:^@<@t">u&<E2C< t< t: u4I) !42D![[Q3۴>!CڴE!E!E!>!Y]X £ D ^Y>I< t < tVQ&E{uFI=!r ش>!Y^-< !>k>u>kt'Pێ! ثثZ.%!%h  ! 26>t W_s 6  u J!>u H!  3;b>lu( !>u_H!rF,3>u !A =!rش>!,I!,\ > /tlu9Ȏм.6J+6)63* t 6) >jt *;!>q t >p udjȎ+L+  tg+J+gtTr !6Z+gt=r~ p t pt H G ,t>lt6l5*3ɬA< uI4*3) !)2)3*VW+0 < t <%u&E=+ _s+ t< t <=t%^< tw <%t< u,0r< wW,3ɋI&5_tf< ta'$6T+t#,I!,pp $-% !{r5* <:u < u ,u <%uZ< u6*&4* 1gt 5*[!t35*+)!<ta+ _+c+< t F+ c++f+ tuOJ+>lt"3= :N+uF/ < tF 8u  VBAPWk%(+ 2񞬢X+uЀ>X+t [+ \+,COu> ,MuY+>,EXu> ,EuY+Ɓ>,BAu> ,TuY+Y+t,EX ,EY+t,BA ,T+! t*;!J+j*֎ t2۪ t <;t&E;N\OSVR2Ҁ|:u@+W _s1'Z^[\;!\6J+jrL+I!ûH!H!& L+،+ú tg+J+&p&p &,uH!&,&,+3T 3IOO+&:Et,_ ߹ 5*# < t# &,&?CCt< t I23.0>luljN=tEtO+ +@:, L+I!J+&d&j\R* K.P+e$ >lt>lðJ+jn+u$Ӡm+:l+tx6n+3S%6\!=tf]%R A! A!3p gZús''oJ+q !A 3ɴ! !g6r >lul#g6r <|uw =!rذG5*3ɀ< up<|t< t8A<|u&E I64*N6r  Q3ɸlulJ+3ɾ5*< t<"u<"ut G<"u<>u2<>u&G < u &H hWH < tDt?:N+t9<p tt &>r 5*< u4*&>p À>N+/tX,t \+׹ ! 'PPX u ,tU[r&t?] 6Z,\)!U!PTXU!uon+,N,u,tL&Y, tvp+P Xб$i -$_ -P%,3؋ וOJp+' 3p+5 PZրt"̀0*ъª''ú,( t< t!s >X,t& s >X,t6R,l)!>m ,(t\!PlX$ukþ< u=!$r؎L+36g+?!=S@![r ;tI;t)D!€uo J+>jt *;!2Ã.0S_6v-?![r _<u(,I!,7 >lulgìtN< t<=t <,t<;t< þ>\t FF;u < tk%oU3G ?+!U!Pf&j \@<@uZ+A X t }&N x&E , p+ 33 V& p+0!P2  Ĺ.X2  Ĺ3p+ r&=u : 8&G t0<$t &Gk( tE:t?uWW_  úe( = ><| 2P,6R,\,X,6R,P,;QV/T,[+Yˋ)IduX,Y+À< t 7?<=uþ t< ÎJ+& 3 &=uð=2!P')2D!S3۴>!C[E!E!E!>!J+hP˾i(2!á]+ c+%u5J< tF=: u\,u;!sW$u9!sI&,( < t]+ c+%ua\,u:!s&% !2ÿ*@<@uZ+&O+:G!rù< t< t.Ī< t2p>lul->tO+!>t! u+r&>@<@t &>qt:u&E ?t< u־5*3ɬ<%u&:$uFV< tA^A< uI64*gt&E$5*&E J+'>lulF3ɎJ+r2&q&p u&>&q<%um&&d< t$=INt=inuVR<(uNJ<)uJ+< tB<)t<*t< u&p&>lu&l&>ur|:uq)!Xs'^Y+< t( G3u&%G:t :GGu۬< twujY+V3ɬ< t_tA<=t< t<=u?< t_t| t< t0u&u2+)!!Y+t t΁(4*5* 2۬< tt ,0ÆJ+&e2:s뢎J+,t33ɋIFF =t56J+< u<t&5ÎJ+,t3҉.0~] uA 6+<:t!< u<:t,u=a']6+QY &:u, &:uG< w< t< u.v->!,3Ҹ=!r6v-؋.0B!Ëڊ,@Ȏ 3*4* ˾< t9-/ CWp+*!Ƽ%ٹ ËʲdĒ-%%-/t6r5:t:u,r'l< t drĴȬ< u +! uú%붾< t::t,!:&3ɺ$&::?tfr33< t":u&.^r< t:uNrԬ< u-! t1&\I 3*!5*< tr:t:uN:ur r Ê,0r< rFWp+ŷ)ê!ê:u. 3p+_ 00<0u*ǷÒPXRPSQ.J+>p u *Y[XZÀ> t =!$r ذGH>H t6>G tH =!r 33ɋظB!H 3ɴp tp ' ]J+g((W3r u!2!Ê u2!ں'' u'".r u!!Ê uT!غ'˾] ,t 6h-6,,36h-+-ǀt#u5+)!C,+>,3e+i+f+6,6h-tP3c+\+q-m-p-n+n-[+,-],,B,++Hk+,X,+3-rGǀtq-t .a+ .c+ǀu\+Vx--+ƿ],ǣZ,Y,A>\,a+^믠q-[+j-,(\+ t<vf  X,<u Z+A:F],a+FF~u>^,:uN_,Fu~=u&}:uFNY%c+=ttT!J+2n.!3+-u .a+u >[+tp-Vx--+ƿ,ǣ,,A>,^ ]6n+3HA%>[+u[,ﺗ$Vx--+ƿ,ǣ,,A>,^P>[+u 3e+i+f+6h-*,6,À>q-u36h-+-ǀtu\)!,:t@,@\tT2k+ t B,+2l->,,O>[+u,t ,CQ>[+u re+>[+t ,t uf+D,u P+!X\! Y+,=!r؉-W!r-t-D! -t >m-t'M-g+i++u@>o-ueg+L+?!rUQ>-u>p-tы>i+L+uY+A+ыi+i+;g+r >o-u돀>-t>Y+t->!À>f+ua+t6i+;g+u t3L+i+l-n-2i+r=tcvuԀ>n-tW,t-r->j-t1,! Q*! ֊YW!>!n+f+Ë,],A!n+[+PX:[+o->e+t<u>-u>[+$t[l-=>l-u<3ɺ],!$r>,e+ظD!,€t2a+$ u p- m-tz tD2 ,! up-j->l-uu>-u%2i+o-Ë,3ɇi+n->l-uU3L+@!$r+t,t, u >j-u?Ite+t,>!],A!e+3҇ѸB!>Y+t@!$ zP$m-X$p-j-p- À>X,u *X,62, u6Z,+)!],:t@p-,@+\,&,% t:u>q-t,24" q-[+j->m-u$p- u ti+3L+uO>i+,>[+tC,+>Z,!€uAFt;V:t@@Ճ~uv|:uFFN^uFô;!r&!3IOO+F:EtFN<F~tFv<t <.t|:tFN2ۆ;!r~F ?.Īı2QP,],Z+|:u,AȀ}:uGG,A:u [tDMP"Xu<.u .u XY3x-{-|-W3ɬu< t< t|- t:uπ< u:N+u<:u>x-z->x-z-4uPZ+A:X>x-z-<.u {-z-{-t?*&z-rR uu<>x-x-z-{-i*t(< t$:N+t:t<:uD (;2N_N.xF< t#WQ8u Y__êAz- Batch file missing $ Insert disk with batch file and press any key when ready $Bad command or file name $Duplicate file name or File not found $Insufficient disk space $Out of environment space $File creation error $File cannot be copied onto itself $Content of destination lost before copy $ File(s) copied $ File(s) $ bytes free $Invalid drive specification $Strike a key when ready . . . $Invalid parameter $SunMonTueWedThuFriSat Invalid date$Current date is $ Enter new date: $ Invalid time$Current time is $ Enter new time: $Are you sure (Y/N)? $ $MS-DOS Version $ Volume in drive $ is $ has no label$Invalid directory $Unable to create directory $Invalid path, not directory, or directory not empty $Must specify ON or OFF $ Directory of $No Path $PATH=PROMPT=Invalid drive in search path $Invalid device $Label not found $Syntax error $ FOR cannot be nested $Intermediate file error during pipe $Cannot do binary reads from a device $off $on $BREAK is $VERIFY is $ECHO is $Invalid path or file name $Invalid number of parameters $Error writing to device $ DTkP/NV GLB_ $dEH QNOT ERRORLEVELoEXIST1DIR RENAMEM RENM ERASE& DEL& TYPE REMCOPYPAUSEfDATETIMEXVER VOLd CDCHDIRMD MKDIR RDURMDIRUBREAKVERIFY(SETPROMPTPATH<EXITeCTTYECHOGOTOSHIFTIFFORCLSM_[MZ?^`#1=HS\jo(Z}%-2@NSfty~ 6.6H6V6^6f666666L6c6l66666636F6]66666p6}666666<6F6K6T6[6p66666666(696K6n66666666666jew$Mbx+I2E[nHZhz5j%3FO]4DTi )fvl@F^c!2Sy k/;\v4FYn*.555I5b5{55e5x555#5%565Z555555555M5u5555555$0{V[j^p(SF]]<]Y]u]]]]]]]],]C],yyEyyyywy$y6y?yHyUy2y>yCyi2:CP Licensed Material - Program Property of Microsoft Inc..8 ZP-5Ps ; >u>tPP Us 6]Us 6]Us 6v-]Uv-]UsqP-6P{GPg6FP5FP-vPvPP-PPns 6Fnv]U+Pv-vB]U9Pv]UQ;  ]U^ utZP-^GPgoP-] U  >u6P{F^G^tPP{FFQÍOQGPPPF~t%PGPgn  ss^ s  6F~tv]UQFF%tVRYFF]UF~uFFFFFFFF K PPF^FG]U OHu > wt(Ɔ8wΈuݚ;v sPPPsSPgP-G HG P{GPgP- HG]U6FP5FF%uFF%+ȉN~v=6F1BӍPPF~t PvN6FP5FF%t #PFV ‰]U> r PPt(8wΈuݠr6P{>}O.QWOtI_Y:OtIu G+H6t򤊆;vPPP6rGstsPPW5u*ЊO"s6G6Pt!wP{GPGGGt#7P-PgnOP-6G6P   ]U FF  >u69>usv>u\6FP5FFFF)F^N^6FPF6P/F6FPF>u?6!>t>t@"Fs Fs6>u^6  s sFrl6FP5FF%t FF8F0>t1>uF HP> tF]UQPCF~w^LJ Fs]U P1Y%H%1PFPCG%~vPCFG%NhPPhPP6FF FFF6FPF6PPF~tv%6F6FP5FFVfFF6FPF6FPPF6PPF~tv%6FPF~tv%FF~v=6vP{P QSPF~tv%FN뽉]UQ~v PF^q9FvF^q]U^ tl^GÊƍ^ u^Ƃ!#^ t'^ _ PPF^GuPPPPP PP{Ɔ%s$8t+O%;rG%;r)뜋G%G%Ǎ򤊆@ ǹ򤋞G%G%%r%?] U^FNȉNFFFF~vT^ F^ NFV3‰FF^3ÉFF3ÉFF3‰FNFN릋F16^ F%1^F16^ F1^^ ?u^?u] UQ^ ^:u8^ F~t.FȈFƋ^ H^:HtFs @2< tа]UQQ^FF~v#FȈFFȊN΋^H 2ԊF]UQQH%FF;FvFFFr@s PPvP{F]UvP{F^lPCFF^l8FwFƋ^FuފF^G^G^^GF]UQF PP{G6P{F^G:Fu/^uԊFs6v]UQQv bF^㋇ >tFrr^ PC^㋏ ÉGG^ >}^ ~t PvHC6P{v GPPs6vv 3]UF~v^㋇ F~tpvP{FF^FGFvP{F^FF:Gt<uvvvvFP^^t FF봋F뇃Frk]U]Us gg9sFFF;Fr3sƆhƆhv^FFspF;FthFnvP{F^GF6ÍOQPFP-vPPF^wPP- ig+Ȋh;v F;Frv^FFs F;FtvP{F^GFÊNwhǍis|hFV+AǍi.vPPF^tB_ P{F^GFÊN6hGj6hƂi*ghFh<w@hɵPi t@Z"sh6iPhPF~un~t Pv]UHFFHFFF+Fr~u ~tF@FF;FwaHFv^FFv^PFPusv^@@N͋vF^@@F뗀~u>FȈFƋJ҉NBFMFFFƋ^FFFFFFPFPusr PPFËN ^ _㋇ ^G^wPPF ^ Gs] UPP>tXrOP6P-P6P6P-P6]UQQFF<uFFFF~rn^FF8Fw,^㋇"FtPPQFF^Fuʉ]U^Ƈ]UQQFFȊN:w/˃"u F^:FwFFuŊsSNLJ"0]UsrF FF^FPPFP(F~u PFPvPPF~t Pv^㋇"F;r= FF6 FPF~t "PvF FFF6 ^ QSPFPF~t ;Pv^Ƈ]UF%FF F9"uFrzlvPFF~t ^jvP"F^ËN";v P0F;u)F Q߸F@NF FFF6  QSPFPF~t QPv<utFFȊN:w#˃"t^:FsFFuFȊN:w-˃"t^*F񈇹:rFuǠFsƇF]U F8>dsNLJ"PFPtF~u)ƇƇF=wF뫰]UQs6 F~tv]U~=u+J]UQ6^PS P]U6v/]UQQ6^GPP]UF~vEFFF%Fn~ sF0FA, NΈB~u~wN6FƍJQ*ȵQ]U F F F~v4FȈFF 1FN+ȃ0FƈJFFu6FPP]U6fPP]UQ >u8>uF]UF) F;w ))F8>uۚ]UQFFF]UhPP]U츈Pv]UQ6PPP5tt QP s&6P6>t 6% s&6P6>t 6%]U>t,6FP5F)F^6FPF ]U^7^Ǎ򤊆PQPP(Yt PPPPPPt P6P6t % ]U 6FF FFF6FPF~tv%6v/F^F6FPPF6^PPF6P/F6@P QSHPF~tv% ]U>t,6FP5F)F^6FPF 6F~t Pv]U6P56ĆP>t 6%r 6]UQQ:u+JVtVB;tMF9Fs0v@F<0r*<9w& N0=w FÃ>@s]U]UQQvPPFs6PFF>uvP{F^G]UF<-t <+t<*t< u]U  PPyƆPQPnyu `PP&u+JtBdž9r@P4Y"sӋ򤍆P.u+Ju|򤋆FPPPPPuvP3PPW5PPP(Ɔ+Ɔ9u>,u@P>;u@Y"rw9ukF&t r"ƆPPnyu8s.&u+JtBdžƆs tdž; r@P7Y"s벋;uF&uHP+u P45"-u Ph*u P5ƆsPPnytlscPPPP(PPPPPt PsTPPPPPt P6PP]UVF~tvgFNFPvny~Nu  ~t~YuċF]UQ^?t!PPPF^G]UQQ^?t=PPPFF^PPPFF^G]UQ^<tD.u+JVu^^P]Uc&_]U ]U ]UQQ^ ~ } ~:Nu+JVtF^&,A^ FF~r@VNP;Ѱr@Y"^P&8.u@Y"s&^ v@FF뺊F9Fr@^vP&8.u@Y"sF׊F9FsL^v&8.u@FF~r@NP9Nr@Y"s^v&^ v@ FFȉ]UF~wF2Êr FuOF2ÍFPF Pv ^P]F~u^G%^G&vFF] UQ~t~u(vF~uv QS]FF]UF~wF2Êr FuiF2ÍF^PF Pv ~}6t+Ju ^&&~}6t+Ju ^&^Sd]F~}6t+Jt~}6t+JYu ^&G'^&G'~tFF^&G*FFF^&G(^&G%^&G&^&G,F^&G'sP^PvFPF~t~t~=N^^&]UF^G%s_G,%FuF^G. F^G.Fv^w( QSvFPF^G,^G%F]UQ~ tN~ tHv mF~tF5FVfv FPF^ PP2]F]UQ~t~t ^G&s&vF^P{] F^G&F]U~ t;~ t5^ G. ^&G^ G.^&^ G0^&^&W]U~t~uF%^G0F%V ‰F^G.F^G#F FF Ff ~vvF P]F^G!F;FvFF^Pv]F>t5~u FFF~vF@Fu^G#NFN܋F] U^G0;G*ucSF~tFR^G*G.FFF FFPw( QS^w*FPFFtu]UQQ~ t~ u3v gF~tF^ G(Fw0Ê^&^ G0]UQ~t~u[vF~tFG^G*+G0^&^F&9v&^G(G0P Qv &Z&T^&^G0] U ~ t~ t}^ G. PFZV9Frd9Ft@P9Vr@Y"rLF^ G*FFF9Fw29Ft@NP;Ns@Y"r^ G.FN+ȉO0\v F~tFIF Pw( QS^w*FPF^ G(F~t~tO*Ǎ=]U~u~uvF Pv F%V ‰FF%^G0F^G.F^G#F FF Ff ~vdF P]F^G!F;FvFF^Pv2]F~u$~vF@Fu^G#NFN܋F] U ^G0;G*tSeF~tFt^G*G.FFF F^G's Sw( QS^w*FPFF^G(F~t~tO*Ǎ=]UQQ~tR~u v]Bv=F~tF1^G(Fw0ÊN^G0^G0;G, vG,^G%]U~ u~ u)FF;FrQ^&0/FF܋^ G(FF~vsv F~tFb^ G*+G0F;FvFF^v0~ }0^9N^ G%^ FG0^ G0;G,vG,FF)F뇸]UFFw"2Ês PFFs։]6_Udž^ ;s_+΍xFu+Ju +Ɖ^ p򤋆@P^뒉]U&]UPP%q]UQPv%qF]UQ PFPP qF]UQ PFPP qF]UPFPP q]UPFPP q]UPFPP q]UPFPP q]UPP%q]UQPFPP qF]U!PFPP q]U"PFPP q]U'PFPv q]U(PFPv q]UQRf VN!ZY]UfV!]U졘&&;Gs,^&Z&WF &;Gr]UQFF,&G&FFw@vNP&x t@Y"sv֋F&F&9Fr@vP&x t@Y"sF&8u &G]UQs 6F]UF t@Z"P> t@P8t@Z"Z "Fs F~;u~u ~;u]U^/u+Jt;+I֍p^+HPqP/PR]U F^:u+JVuF^FFF^ヿ"t%"vs~tRFFFρ~u fP-/F^F^ć(FF^>t'}P-vgP-PP]UQ^?t6^^:w&^vtt+JVt]6Input File: pos: Record Type: Fatal Error: An internal error has occured. Fatal Error: Module is not in the library Fatal Error: Cannot open input file  ZJM is previously defined in old definition is ignored. Library disk is full.Too many object modules already exists. Replace?Duplicate module name: File is being ignored. ;  %)+/5;=CGIOSYaegkmqSymbol table capacity exceededf (Length H bytes) Listing file write errorToo many PUBLIC symbols VM.TMPCannot open VM.TMPAllocate error on VM.TmpWrite error on VM.TmpRead error on VM.Tmp Invalid object module/library Write error on library/extract file Input file read error .OBJCannot create extract  file Cannot open extract file Close error on extract file 0E55REMOVELIBRARYRECORDS WIDTHOFLINELibrary File: No library file specified .LIBLibrary does not exist. Create?Operations: List file: Cannot create list file. Cannot write library file .OBJCON NUL LPT1 AUX Cannot nest response files. "" Cannot open response file. Ambiguous switch: Unrecognized switch: "" Invalid switch. Microsoft Library Manager V1.02 (C) Copyright 1981 by Microsoft Inc. (  8   MZ@k"$)/vPd .kx &?HQV_|RZnuz  R_t!cs>YaV8\gEL5LLLLLELtLLLJLWLzLLLL;LlLwL LT L L Lt L L L. o     6j66D6h666666)6;6@66 RR S3SV2R f] ~F~t F30~SF3FVJVuԺRVRjf]) F~2;V|v2;V|~v:uF׋~2;V}~2;V}FF4~2;V}F"~~2~~ 2;}FFFf] VVVF~taFu[VV6z6x]S/FV2%VV N&F VVMN.hw}뙃~uh RAF~~ERA>>E~U~x]E~u vV ~VU~E>}tERA>E>E>E>t>vu tڋ>f]Gf]7Wu-VtF2RRڎSLFFFFf]>||Z|BBRA|V~|F~}>VBVJ;Vu>||f]>||X|zzBBRAx>x||V~|F~}>xVBVJ;Vu|f]RRjRRjRRjt>2RGW1R RjRS3S6f];vYf]o~uj~u;FuN~}U:t t~}E2rrF~|'pR~UpRjp@pH;FuߋrV~ }?Fpp#uRVRj RXRjp@p= uNj~}E>u}>pE;w RZRjR^Rjp#yR>p}R`Rj RbRjyi~5f]2RPRR||RA6PRR| RRRr62R2RڎSL62RڎSL2R"64 RA>>ERA>U>E>>E>UBBRA>E>}P8'|t2tA#r~Xvm vctZUP~22|8>|P}|>|}|.!V+49>g62RL6Lf][2.C+;wFud>t@ ;Fs1BBVV>FF;Fv +F>n@@;uO>uFK>t6>u VBBR%;usFf]URvF~s~u-Ff]UR-f]UFf]U ^ڎ‰^FV+€V~s ~rFV;Vs N^&Vf]Uf] FFf]3&f]&2s">r &>r &f]`f]U ~~:uANFt:~2V~r*F~~~~:tF VBVJ;VuۋFf] ~~:sAN~2VFt ~2VVV~r?F~~~~:t~~~~:sAN VBVJ;VuƋFf]j&~2RGW f]8RRff] RRff]f][2.Cu!܋_ݍFG_U]F;rU؎v ~Ns]U؎v ~NNO]U؎~ NFs]UF؋v F ~Ns] UF FnFr@]UF fnFr@]UF FnFp~t@]UF nnFp~t@]U^@%]U^];>r;>s E;vA؎X>u[X&.&XX[PSXX[PSXX[PSXX[PSUv ;vwvN ,r3]U^Ӌ^~ vn &FE< t<t &C3 2ڋ+щ] j<Lv^ڎS f]~U2#ta~U2dR6RRR vR^ڎSeLFV2RVR 4&f]@~U~U~E!~E$~E~E~Ev;L~U~Uv)f] ~EvvVBڌَSL~U"~~U"~U~U$r)~U2#uvR^ڎSL~Ev)f]g ~E~E~E~E~E~E~VU ~E~~VU v Ef]v L~Ev R Lf]2>t 6f] vv^ڎS LV~U~U rvv)f]y >uVV~sFF~~UV~ u232+222;r mF~ u>0 u6RR&6RVR&Ft~ uB22@2F0VBVJ;VtYf]>2t62vv&f]VV>t6RVR&f]Y F3FF3V~t vv~EV 0~Mvtf]  FUvVVN#tV#tQV2RVRN#tV^f]~UsvL~E%~E~E~Ev~Us$~U rv~u ~]ڎSLv)f]H~E%~E~Evf]0 2f]f][2.Cu~}t~U\~UB>tB>tA#ʋ~M%~U2 ҹuA~E~#E%4#FFf]U~Ur1~}u(~U s~}<tvRڎS L~U2#t~}<tvRL~Urs~}uj~U\~U@~Um~E^~U\~;Ums~Uo2~Up~EZ~E[(RVLRf]UF~}<uRVLRFf]Uv^L~}<uRVLR~U2VFf]U ~E"~U%~ Ur~U%~Er~U%r~uFX~U r~E$~U";VrC~UB~;U@wT~}<u8 RVtRR R~}u~Ev ~E@vqLr~Ev~F+E"~vTB+U@;s~vDB+E@~U@vVڌَS~U"^SR~U"~M@>t@2‹~E@> u~E$~}<u ~UB~U@;>u1~U~U" ҹuA~M%~E%4~Er~E$~U$s8~}<u/~U@~;UBuvqL~}@~Uv2 u~E@~U";Vr~UB~;U@wvqLr~E%~E"j~F+E"~vTB+U@;s~vDB+E@~U@vVڌَS~U"^S6~U"~U@]~U2VFf]U ~U&2;Vs ~U&2VVV~r,F^ڋU&&@H;FuڋVVFf]U V^&2 u ~rF߃~rB~Us~Uss ~E& ~VU&~U&2V~rO^&FM&^&2QRXRr~Es@H;Fuf]U~E~E~=U&2~;U|Rv4u|&.tDv4u|&:t6vT2BvT֋v4uT&~M֋vtց~E뜋~=U&2~;U|v4uT&~U~Ef]U*F~Uss~E~EVLR$R3Rx~EtFU~E<~:tBVFu\V2Vԃ~r(>{ar S2S֡@H;FuދV2u~ArV2~ULFUV2#t |~E~EV2;|>S~UL FEL @= uπ~r3V2;|#>{`sSֈS>S2S>C @=u~uBr~tBr9~U s~E=~E>~E=~E>~E~E<~tBr~E=~E>~E~E<L~uBr~tBr~E=~E>~E~E<~.u"UV2|~E~E:FV2;|>S~UT FET @=uϋ~}<uq~Ur ~}tRVLR2=rG~Us~E~E )RVLR2=r~E~E~EZ~E[~}u~}<t~E~E~E?~Em~E$~E4~E%~EB~Er~E~E!~E@~U2VFf]U~}t~U rڎ‰V2/F > ڎ‰'1w+r.w 7 ^ ^ ^ ^ ? G ~U2#uv666 L~E$~U2VFf]U~U s#~}tvRڎS LFF~E$Ff]U ~E$~VU"~}<tU~U>2u?VV~r3~U>2R^&2Q@H;Fu;Fr~UB~;U@wvqLriF+~vTB+U@;s~vDB+E@^S~U@vVڌَS6~E?~U@p~U2VFf]Uf]U VVR^&2R@H;Fuݍf]U ~s VrƆr RrRtڎSvvs2RR ڎS s2VFf]Uf]UX$xD󥿀Lf]UR RR Rf]Uf] Hˌ˃++Z~02~;.rAv0.:Vu@#FFt~.Ff] ~0v.V~ar V2VFf] v Rlsv/R\r~02~;.sv2PR~usbvi2~"~.~Uv"V2VN3b2 N~~ vE~.f]  vv RxFVV~rbF~02~;.r v0.2RRvr)v~~EF~.VBVJ;VuFf]yv~$sv~t~j~02~;.rv^ڎS F~{ tRVߌڎS VBV uպRrڎS R^ڎS RvڎS R~1ڎSD ~0~Dž.~E .~02~;.vWv1.<:uGvR~(RRFs-~(~~E:~.v~t ~zvRVBBRRFv:Rs~|] E vD Bv.Rws(vRV RRv~t ~^] E Fu~GGvv~VVF~~2 t~2B~~~ VBVuʋFf],~uB~uA ʈNFf] ^Fdž*,Ğ*&2B dž"Ğ*"&"0"B"J; udž.Ɔ$~辔URRvVR66rU,RURRvVR66UbU;RUV~ؾuBr V2V~ȾuBr V2V~uBr V2VUVRs V2VUVRts V2V02;.s ^~EhRڎS 02+.B""r"0.َS RڎS  dž.s{f]f][2.C ( 1) Put a CTRL-Z in the template $< > ( 2) Copy one character from template $< > ( 3) Skip over one character in template $< > ( 4) Copy up to specified character $< > ( 5) Skip up to specified character $< > ( 6) Copy rest of template $< > ( 7) Kill line with no change in template (Ctrl-X) $< > ( 8) Re-edit line $< > ( 9) Backspace (same as Ctrl-H) $< > (10) Toggle insert mode $< > (11) Toggle insert mode $< > (12) Represent escape character $ ^ |_ 2nd char present escape char --> hexadecimal $MSDOS SYS MSDOS.SYS not found$ Unsuccessful Read$ Select menu item number $ Press function key to $>>$ Aw C'mon! Re-enter (0-12)$ Continue ? (Y/N)$ Input escape character differs from that on the MSDOS system file$ Re-enter function key$ $ Save on disk? (Y/N)$،x;!z!"t  !23@!'!"t  !`.~' !q !"y  !u j ! ! !!!:.t"u z !Lj. |~w LD D*j !!$./.1V PQRWUS./Gg OWG2< w%./G)O[]_ZYX^3ɴôð/G**3.,.މlPDRTǣ#%>&uR3B)3( Ҁ=rʀ=s@"Ї&+аsڰ Zyu#%B)< )돴<vu&< rt״    ')#u'  &&*ó Q3+U+ uuY <þ/G wO`<ȋرÀ,./GO  FUNCTION KEY MENU ( 0) End program $< > ( 1) Put a CTRL-Z in the temp; Basic I/O System definition - INCLUDEd in each module ; Assumes a CPU Support card at F0 hex for character I/O ; Select whether console input is interrupt-driven or polled. INTINP EQU 1 QSIZE EQU 100 ; Input queue size. ; Select whether the auxiliary port is the Support Card parallel port ; or the second channel of a Multiport Serial card addressed at 10H. PARALLELAUX EQU 0 SERIALAUX EQU 1 ; Select whether the printer is connected to the Support card parallel ; output port (standard) or the first channel of a Multiport Serial card ; addressed at 10H. PARALLELPRN EQU 0 SERIALPRN EQU 1 ; If the Multiport Serial was chosen for either the auxiliary or the ; printer, select the baud rate here, using a hex value from this table: ;  ; 50 0 150 4 1800 8 4800 C ; 75 1 300 5 2000 9 7200 D ; 110 2 600 6 2400 A 9600 E ; 134.5 3 1200 7 3600 B 19200 F PRNBAUD EQU 0EH ; 9600 baud AUXBAUD EQU 0EH ; 9600 baud ; Disk options for MS-DOS 2.0 selected here ;************************************************************ ; If you have a hard disk select it here. If you want the driver ; to be installable (installed at boot time) then select INSTALL ; also. IMI EQU 0 SCRIBE EQU 1 HARD EQU IMI OR SCRIBE INSTALL EQU 1 ;************************************************************ ; Select disk controller here. SCP EQU 0 TARBELL EQU 1 ;Select only LARGE below ; Select disk configuration: LARGE EQU 1 ; Two large drives. COMBIN EQU 0 ; Two 8-inch and one 5-inch. SMALL EQU 0 ; Three 5-inch drives. MAXLARGE EQU 2 ;Number of 8" when LARGE is selected MAXSMALL EQU 3 ;Number of 5" when SMALL is selected MAXLARGECOMB EQU 2 ;Number of 8" when COMBIN is selected MAXSMALLCOMB EQU 1 ;Number of 5" when COMBIN is selected LARGDRV EQU LARGE OR COMBIN SMALLDRV EQU SMALL OR COMBIN LDRVMAX EQU MAXLARGE*LARGE+MAXLARGECOMB*COMBIN ; # of 8" drives SDRVMAX EQU MAXSMALL*SMALL+MAXSMALLCOMB*COMBIN ; # of 5" drives HDRVMAX EQU HARD ; # of hard disk drives ;************************************************************ ; If your disk drives support DISKCHANGE signal and 2 SIDED signal and ; you have a SCP disk controller, then select these options here. ; MS-DOS will use these signals to automatically select single or ; double sided drives. These are ignored for PerSci drives. DISKCHG EQU 0 TWOSIDE EQU 0 ;************************************************************* ; Select double-sided operation of 8-inch disks in double-density mode.   ; Select this option only if TWOSIDE is not used (or PERSCI is set). LARGEDS EQU 1 ;************************************************************ ; Select whether FORMAT defaults to single- or double-sided for 5" disks. ; (This can always be overridden with the /1 or /2 switches.) SMALLDS EQU 1 ;*********************************************************** ; If 8-inch drives are PerSci, select here: PERSCI 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 ;************************************************************ SIDECHK EQU TWOSIDE AND (PERSCI-1) AND SCP AND LARGDRV DSKCHG EQU DISKCHG AND (PERSCI-1) AND SCP AND LARGDRV BIOSSEG EQU 40H ; I/O system segment. BASE EQU 0F0H SIOBASE EQU 10H STAT EQU BASE+7 DATA EQU BASE+6 DAV EQU 2 TBMT EQU 1 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 ;define offsets for IO data packet IODAT STRUC CMDLEN DB ? ;LENGTH OF THIS COMMAND UNIT DB ? ;SUB UNIT SPECIFIER CMD DB ? ;COMMAND CODE STATUS DW ? ;STATUS DD 2 DUP (?) MEDIA DB ? ;MEDIA DESCRIPTOR TRANS DD ? ;TRANSFER ADDRESS COUNT DW ? ;COUNT OF BLOCKS OR CHARACTERS START DW ? ;FIRST BLOCK TO TRANSFER IODAT ENDS ;rU؎v ~Ns]U؎v ~NNO]U؎PAGE 60,132 ; Floppy disk I/O System for MS-DOS version 2.00 and later INCLUDE IODEF.ASM IO GROUP CODE CODE SEGMENT BYTE PUBLIC 'IOSYS' ASSUME CS:IO,DS:IO EXTRN EXIT:NEAR, CMDERR:NEAR, BUS$EXIT:NEAR, PTRSAV:DWORD EXTRN ERR$EXIT:NEAR  EXTRN SELECT:BYTE IF LARGDRV PUBLIC LDSKTBL LDSKTBL: DW LDSK$INIT DW LMEDIA$CHK DW GET$BPB DW CMDERR DW LDSK$READ DW BUS$EXIT DW EXIT DW EXIT DW LDSK$WRIT DW LDSK$WRIT ENDIF IF SMALLDRV PUBLIC SDSKTBL SDSKTBL: DW SDSK$INIT DW SMEDIA$CHK DW GET$BPB DW CMDERR DW SDSK$READ DW BUS$EXIT DW EXIT DW EXIT DW SDSK$WRIT DW SDSK$WRIT ENDIF ; ************ 1793-type controller disk I/O ***************** READCOM EQU 80H WRITECOM EQU 0A0H 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 DLYTIM EQU 10 ; 24 usec delay after force interrupt ENDIF CURDRV DB -1 ; SIDE has media byte ; Bit 7=1 for 5", 0 for 8" drives ; Bit 6=1 for two-side, 0 for one-side drives ; DDENBIT set for double density, reset for single density SIDE DB 0 ; Explanation of tables below. ; DRVTAB is a table of bytes which are sent to the d  isk controller as drive- ; select bytes to choose which physical drive is selected for each disk I/O ; driver. Always select side 0 in the drive-select byte if ; a side-select bit is available. 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. Drives such as PerSci 277s which use ; the same head positioner for more than one drive should share entrys ; in TRKTAB. .SALL BYTELST MACRO INITVAL,COUNT,INC,DUPCNT LOCAL X X = INITVAL REPT COUNT DB DUPCNT DUP(X) X = X+INC ENDM ENDM DRVTAB LABEL BYTE IF SCP BYTELST 0,LDRVMAX,1,1 BYTELST 10H,SDRVMAX,1,1 ENDIF IF TARBELL BYTELST 0,LDRVMAX,10H,1 ENDIF TRKPT LABEL BYTE IF PERSCI BYTELST 0,LDRVMAX/2,1,2 BYTELST LDRVMAX/2,SDRVMAX,1,1 TRKTAB DB (LDRVMAX/2+SDRVMAX) DUP (-1) ELSE BYTELST 0,LDRVMAX+SDRVMAX,1,1 TRKTAB DB (LDRVMAX+SDRVMAX) DUP (-1) ENDIF IF LARGDRV LINITTAB LABEL WORD IF LARGEDS OR SIDECHK DW LDRVMAX DUP(LDSDRIVE) ELSE DW LDRVMAX DUP(LSSDRIVE) ENDIF ENDIF IF SMALLDRV SINITTAB LABEL WORD DW SDRVMAX DUP(SDSDRIVE) ENDIF IF SMALLDRV SSSDRIVE: ; This is the IBM Personal Computer DW 512 ; disk format. DB 1 DW 1 DB 2 DW 64 DW 320 DB 80H+DDENBIT DW 1 DW 512 SDSDRIVE: ; The IBM PC format for double sided disks DW 512 DB 2 DW 1 DB 2 DW 112 ; # of directory entries DW 640 DB 0C0H+DDENBIT ; Media DW 1 ; Sectors for 1 fat DW 512 ; Reserve space ENDIF IF LARGDRV LSDRIVE: ; Single density / single sided DW 128 ;SECTOR SIZE DB 4 ;SECTORS/ALLOC UNIT DW 1 ;NUMBER OF RESERVED SECTORS DB 2 ;NUMBER OF FATS DW 68 ;NUMBER OF DIRECTORY ENTRIES DW 77*26 ;TOTAL NUMBER OF SECTORS DB 0 ;MEDIA BYTE DW 6 ;SECTORS FOR ONE FAT IF SIDECHK OR LARGEDS LDSDRIVE: ; Double density / double sided DW 1024 DB 1 DW 1 DB 2 DW 192 DW 77*8*2 DB 40H+DDENBIT ; Media byte DW 2 ENDIF IF SIDECHK OR (LARGEDS-1) LSSDRIVE: ; Double density / single sided DW 1024 DB 1 DW 1 DB 2 DW 96 DW 77*8 DB DDENBIT ; Media byte DW 1 ENDIF ENDIF ;********************************************************* ; Disk change function. ; On entry: ; AL = disk unit number. ; AH = media byte ; On exit: ; AX = status (done or error code) ; [TRANS] set as follows: ; = -1 (FF hex) if disk is changed. ; = 0 if don't know. ; = 1 if not changed. ; [SIDE] has media byte for GETBPB call SMEDIA$CHK: IF COMBIN ADD AL,LDRVMAX ; Convert unit # ENDIF LMEDIA$CHK: MOV [SIDE],AH MOV AH,0 MOV SI,AX XCHG [SELECT+SI],AH ; Has drive been selected before? OR AH,AH JNZ DENCHECK ; If no, go check density ; First try head load test. If head is loaded on the drive we want, ; then disk must not have been changed. CMP AL,[CURDRV] ; Same drive? JNZ CHGCHK ; Try disk change signal if not PUSH AX ; Save unit number IF SCP IN AL,DISK+4 ; Head load byte for SCP controller ELSE IN AL,DISK ; Head load byte for Tarbell ENDIF !  AND AL,20H ; Look at head load bit POP AX MOV AH,1 ; AH = 1, disk not changed. JNZ MEDIA$EXIT CHGCHK: ; Now look at disk change bit if enabled and not a 5" drive. IF SMALLDRV MOV AH,0 ; Not sure if disk changed TEST [SIDE],80H JNZ MEDIA$EXIT ; If small drive, don't use disk change signal ENDIF IF DSKCHG CALL CHKNEW MOV DL,AL MOV BX,OFFSET IO:DRVTAB XLAT ; Get drive select byte OUT DISK+4,AL IN AL,DISK+1 ; Get current track number OUT DISK+3,AL ; Make it the track to seek to MOV AL,18H ; Seek and load head CALL DCOM CHKLOOP: IN AL,DISK ; Read type I status TEST AL,20H ; Check head load bit JZ CHKLOOP ; Wait until head-load time out TEST AL,80H ; Is disk ready? 1= not ready JNZ NOTRDY IN AL,DISK+4 ; Bit 7=1 if disk not changed TEST AL,80H MOV AH,1 JNZ MEDIA$EXIT MOV AL,DL ; Restore unit number ENDIF MOV AH,0 ; Disk may not have been changed ; Perform density check on 8" drive ; AH has current disk changed status, either 0 or -1 DENCHECK: IF LARGDRV IF COMBIN TEST [SIDE],80H JNZ MEDIA$EXIT ; If small drive, don't need density check ENDIF MOV DH,AH CALL CHKNEW ; Unload head if selecting new drive. MOV BX,OFFSET IO:DRVTAB XLAT ; Get drive select byte  MOV DL,[SIDE] AND DL,[DDENBIT] OR DL,AL MOV CX,4 ; Try each density twice MOV AH,0 ; Disk may not have been changed CHKDENS: MOV AL,DL OUT DISK+4,AL ; Select disk MOV AL,0C4H ; READ ADDRESS command CALL DCOM PUSH AX IN AL,DISK+3 ; Eat last byte to reset DRQ POP AX AND AL,98H JZ HAVDENS ; Jump if no error in reading address. NOT AH XOR DL,DDENBIT ; Try other density LOOP CHKDENS MOV AH,AL JMP ERROR HAVDENS: AND DL,DDENBIT IF SIDECHK IN AL,DISK+4 AND AL,40H ; Get side bit (1=two sided) OR DL,AL ENDIF MOV [SIDE],DL OR AH,DH ENDIF ;IF LARGDRV MEDIA$EXIT: LDS BX,[PTRSAV] MOV BYTE PTR DS:[BX.TRANS],AH MOV AH,1 ;No error RET NOTRDY: MOV AX,8102H ;Return NOT READY error RET CHKNEW: MOV AH,AL ; Save disk drive number in AH. XCHG AL,[CURDRV] ; Make new drive current, AL = previous CMP AL,AH ; Changing drives? JZ RET3 ; Changing drives, unload head so the head load delay one-shot ; will fire again. Do it by seeking to same track the H bit reset. IN AL,DISK+1 ; Get current track number OUT DISK+3,AL ; Make it the track to seek to MOV AL,10H ; Seek and unload head CALL DCOM MOV AL,AH ; Restore current drive number RET3: RET GET$BPB: ; This is the equivalant of the old MAPDEV routine in MS-DOS 1.25. ; Using the media byte and/or FAT ID byte ,set the proper DPT for ; the driver. IF COMBIN TEST [SIDE],80H ; Is it 5" drive ? JZ GET8INCH ENDIF IF SMALLDRV MOV SI,OFFSET IO:SDSDRIVE MOV AL,ES:[DI] ; Get FAT ID byte TEST AL,1 ; Is it double sided? JNZ SETBPB MOV SI,OFFSET IO:SSSDRIVE JMP SHORT SETBPB  ENDIF IF LARGDRV GET8INCH: TEST [SIDE],DDENBIT ; 0=single density, 1=double density MOV SI,OFFSET IO:LSDRIVE JZ SETBPB IF SIDECHK OR LARGEDS MOV SI,OFFSET IO:LDSDRIVE ENDIF IF SIDECHK TEST [SIDE],40H JNZ SETBPB ENDIF IF SIDECHK OR LARGEDS-1 MOV SI,OFFSET IO:LSSDRIVE ENDIF ENDIF ;IF LARGDRV SETBPB: LDS BX,[PTRSAV] SETBPBPT: MOV [BX." COUNT],SI MOV [BX.COUNT+2],CS XOR CX,CX ; Don't change count field MOV AH,1 ;No error RET ; Disk read function. ; ; On entry: ; AL = Disk I/O driver number ; AH = Media byte ; ES:DI = Disk transfer address ; CX = Number of sectors to transfer ; DX = Logical record number of transfer ; On exit: ; CX = number of sectors transferred. ; AH = 1 if success, 81H if fail ; AL = disk error code ; 0 = write protect error ; 2 = not ready error ; 4 = CRC error ; 6 = seek error ; 8 = sector not found ; 10 = write fault ; 12 = "data error" (any other error) SDSK$READ: IF COMBIN ADD AL,LDRVMAX ENDIF LDSK$READ: CALL SEEK ; Position head JC ERROR RDLP: PUSH CX CALL READSECT ;Perform sector read POP CX JC ERROR INC DH ;Next sector number LOOP RDLP ;Read each sector requested MOV AH,1 ;No error RET ; Disk write function.  ; Registers same on entry and exit as read above. SDSK$WRIT: IF COMBIN ADD AL,LDRVMAX ENDIF LDSK$WRIT: CALL SEEK  ;Position head JC ERROR WRTLP: PUSH CX CALL WRITESECT ; Perform sector write POP CX JC ERROR INC DH ; Bump sector counter LOOP WRTLP ; Write CX sectors MOV AH,1 ; No error RET ERROR: MOV BL,[CURDRV] MOV BH,0 MOV DL,-1 MOV [BX+SELECT],DL MOV [SI],DL ; Indicate we don't know where head is. MOV SI,OFFSET IO:ERRTAB GETCOD: INC DL ; Increment to next error code. LODSB TEST AH,AL ; See if error code matches disk status. JZ GETCOD ; Try another if not. MOV AL,DL ; Now we've got the code. SHL AL,1 ; Multiply by two. MOV AH,81H ; Return error code RET 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 ; Data error ; 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 ; DI = Disk transfer address in ES ; SI = pointer to drive's track counter in DS ; CX unchanged (number of sectors) SEEK: MOV [SIDE],AH MOV BL,AL MOV BH,0 CALL CHKNEW MOV AL,[SIDE] AND AL,DDENBIT OR AL,[DRVTAB+BX] ;Get drive select byte OUT DISK+4,AL ;Select drive 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 TEST DH,DDENBIT ; Check for double-density. JZ HAVSECT MOV DL,16 TEST [SIDE],40H JNZ HAVSECT ; Disk is double-sided MOV DL,8 ; Disk is single sided HAVSECT: DIV DL ; AL = track, AH = sector. XCHG AX,DX ; AH has drive-select byte, DX = track & sector. INC DH ; Sectors start at one, not zero. MOV BL,[BX+TRKPT] ; Get this drive's displacement into track table. ADD BX,OFFSET IO:TRKTAB ; BX now points to track counter for this drive. MOV SI,BX MOV AL,DL ; Move new track number into AL. XCHG AL,[SI] ; Xchange current track with desired track OUT DISK+1,AL ; Inform controller chip of current track CMP AL,DL ; See if we're at the right track. JZ RET4 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,AL MOV AL,# 1CH+STPSPD ; Seek command. CALL MOVHEAD AND AL,98H ; Accept not ready, seek, & CRC error bits. JZ RET4 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 RET4 ; Status is OK for Not Ready error. MOV AH,2 ; Everything else is seek error. RET4: RET SETUP: MOV BL,DH ; Move sector number to BL to play with TEST AH,DDENBIT ; Check for double density. JZ CHECK26 ; Not DD. MOV AL,AH ; Select front side of disk. OUT DISK+4,AL CMP BL,8 ; See if legal DD sector number. JBE PUTSEC ; Jump if ok. TEST [SIDE],40H ; Get media byte to see if double sided JZ STEP ; Must step 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. MOV AL,AH ; Move drive select byte into AL. OR AL,BACKBIT ; Select back side. OUT DISK+4,AL JMP SHORT PUTSEC 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 INC BYTE PTR CS:[SI] ; 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,AL RET5: RET READSECT: CALL SETUP MOV BL,10 PUSH DX MOV DX,DISK+3 RDAGN: MOV AL,READCOM CLI OUT DISK,AL MOV BP,DI JMP SHORT RLOOPENTRY RLOOP: STOSB RLOOPENTRY: IF SCP IN AL,DISK+5 SHR AL,1 IN AL,DX JNC RLOOP ENDIF IF TARBELL IN AL,DISK+4 SHL AL,1 IN AL,DX JC RLOOP ENDIF STI ; Interrupts OK now CALL GETSTAT AND AL,9CH JZ RDPOP MOV DI,BP MOV BH,AL ; Save error status for report DEC BL JNZ RDAGN MOV AH,BH ; Put error status in AH. STC RDPOP: POP DX IF TARBELL FORCINT:  MOV AL,0D0H ; Tarbell controllers need this force interrupt OUT DISK,AL ; so that Type I status is always available MOV AL,DLYTIM ; at the 1793 status port so we can find out INTDLY: ; if the head is loaded. SCP controllers have DEC AL ; head load status available at the DISK+4 JNZ INTDLY ; status port. ENDIF RET WRITESECT: CALL SETUP MOV BL,10 XCHG SI,DI PUSH ES POP DS ;DS must have transfer segment ASSUME DS:NOTHING PUSH DX MOV DX,DISK+3 WRTAGN: MOV AL,WRITECOM CLI OUT DISK,AL MOV BP,SI WRLOOP: IF SCP IN AL,DISK+5 SHR AL,1 LODSB OUT DX,AL JNC WRLOOP ENDIF  IF TARBELL IN AL,DISK+4 SHL AL,1 LODSB OUT DX,AL JC WRLOOP ENDIF STI DEC SI CALL GETSTAT AND AL,0FCH JZ WRPOP MOV SI,BP MOV BH,AL DEC BL JNZ WRTAGN MOV AH,BH ; Error status to AH. STC WRPOP: POP DX PUSH CS POP DS ;Restore local DS ASSUME DS:IO XCHG SI,DI IF TARBELL JMP FORCINT ELSE RET ENDIF HOME: MOV BL,3 TRYHOM: MOV AL,0CH+STPSPD CALL DCOM AND AL,98H JZ RET6 JS HOMERR ; No retries if not ready MOV AL,58H+STPSPD ; Step in with update CALL DCOM DEC BL JNZ TRYHOM HOMERR: STC RET6: RET MOVHEAD: DCOM: OUT DISK,AL PUSH AX AAM ; Delay 10 microseconds POP AX GETSTAT: IN AL,DISK+4 TEST AL,DONEBIT IF SCP JZ GETSTAT ENDIF IF TARBELL JNZ GE$ TSTAT ENDIF IN AL,DISK RET IF LARGDRV LDSK$INIT: MOV AL,LDRVMAX MOV SI,OFFSET IO:LINITTAB ENDIF SETDRV: LDS BX,[PTRSAV] MOV [BX.MEDIA],AL JMP SETBPBPT IF SMALLDRV SDSK$INIT: MOV AL,SDRVMAX MOV SI,OFFSET IO:SINITTAB JMP SETDRV ENDIF CODE ENDS END ~ uFsB&9r&&G 6&@F< s< u; I/O System for MS-DOS version 2.00 and later. Revised 12-22-82. ; Contains data packets and init code only BIOSIZ EQU 8*400H ;Size of BIOS in bytes BIOSIZS EQU BIOSIZ/10H ;Size of BIOS in Paragraphs MAXBUF EQU 10 ; # of buffers for files MAXFIL EQU 10 ; # of files to be opened at one time INCLUDE IODEF.ASM PUBLIC PTRSAV,EXIT,BUS$EXIT,CMDERR,ERR$EXIT PUBLIC RE_INIT PUBLIC SELECT EXTRN SYSINIT:FAR EXTRN CURRENT_DOS_LOCATION:WORD EXTRN FINAL_DOS_LOCATION:WORD EXTRN DEVICE_LIST:DWORD EXTRN MEMORY_SIZE:WORD EXTRN DEFAULT_DRIVE:BYTE EXTRN BUFFERS:BYTE,FILES:BYTE EXTRN CONTBL:WORD,AUXTBL:WORD,TIMTBL:WORD,PRNTBL:WORD IF LARGDRV EXTRN LDSKTBL:WORD ENDIF IF SMALLDRV EXTRN SDSKTBL:WORD ELSE SDSKDEV EQU HDSKDEV ENDIF  IF HARD AND (INSTALL-1) EXTRN HDSKTBL:WORD ELSE HDSKDEV EQU -1 ENDIF IO GROUP CODE,INITSEG,LASTSEG CODE SEGMENT BYTE PUBLIC 'IOSYS' ASSUME CS:IO,DS:IO ORG 0 ZERO: JMP INIT SELECT DB (LDRVMAX+SDRVMAX+HARD) DUP (-1) ; ************ DEVICE HEADERS ***************************************** DEVSTART LABEL WORD CONDEV: ;Header for device CON DW AUXDEV,BIOSSEG ;Link to next device DW 8013H ;Attributes - console input, output device DW STRATEGY ;Interrupt service (Used in future versions) DW CON$IN ;Entry point DB "CON " ;Device name AUXDEV: ;Header for device AUX DW PRNDEV,BIOSSEG DW 8000H DW STRATEGY DW AUX$IN DB "AUX " PRNDEV: ;Header for device PRN DW TIMDEV,BIOSSEG DW 8000H DW STRATEGY DW PRN$IN DB "PRN " TIMDEV: ;Header for clock device DW DSKDEV,BIOSSEG DW 8008H DW STRATEGY DW TIM$IN DB "CLOCK " DSKDEV: ;Header for floppy disk device IF LARGDRV DW SDSKDEV,BIOSSEG DW 2000H DW STRATEGY DW LDSK$IN DB ? ENDIF IF SMALLDRV SDSKDEV: DW HDSKDEV,BIOSSEG DW 0 ; IBM compatable DW STRATEGY DW SDSK$IN DB ? ENDIF IF HARD AND (INSTALL-1) HDSKDEV: ;Header for 5.25 hard disk device DW -1,BIOSSEG DW 2000H DW STRATEGY DW HDSK$IN DB ? ENDIF ;************************************************************************ PTRSAV DD 0 STRATEGY PROC FAR MOV WORD PTR CS:[PTRSAV],BX MOV WORD PTR CS:[PTRSAV+2],ES RE_INIT: RET STRATEGY ENDP ;******************************************************** CON$IN: PUSH SI MOV SI,OFFSET IO:CONTBL JMP SHORT ENTRY AUX$IN: PUSH SI MOV SI,OFFSET IO:AUXTBL JMP SHORT ENTRY PRN$IN: PUSH SI MOV SI,OFFSET IO:PRNTBL JMP SHORT ENTRY TIM$IN: PUSH SI MOV SI,% OFFSET IO:TIMTBL JMP SHORT ENTRY IF LARGDRV LDSK$IN: PUSH SI MOV SI,OFFSET IO:LDSKTBL JMP SHORT ENTRY ENDIF IF SMALLDRV SDSK$IN: PUSH SI MOV SI,OFFSET IO:SDSKTBL JMP SHORT ENTRY ENDIF IF HARD AND (INSTALL-1) HDSK$IN: PUSH SI MOV SI,OFFSET IO:HDSKTBL JMP SHORT ENTRY ENDIF DISPATCH PROC FAR ENTRY: PUSH AX PUSH CX PUSH DX PUSH DI PUSH BP PUSH DS PUSH ES PUSH BX LDS BX,CS:[PTRSAV] ;GET POINTER TO I/O PACKET MOV AL,[BX.UNIT] ;AL = UNIT CODE MOV AH,[BX.MEDIA] ;AH = MEDIA DESCRIP MOV CX,[BX.COUNT] ;CX = COUNT MOV DX,[BX.START] ;DX = START SECTOR XCHG DI,AX MOV AL,[BX.CMD] XOR AH,AH ADD SI,AX ADD SI,AX CMP AL,11 JA CMDERR XCHG AX,DI LES DI,[BX.TRANS] PUSH CS POP DS  CALL [SI] ;GO DO COMMAND LDS BX,CS:[PTRSAV] MOV [BX.STATUS],AX ;MARK OPERATION COMPLETE SUB [BX.COUNT],CX ;Subtract amount transfered POP BX POP ES POP DS POP BP POP DI POP DX POP CX POP AX POP SI RET ;RESTORE REGS AND RETURN DISPATCH ENDP ; Standard return types used by all functions EXIT: XOR CX,CX ;Transfer complete MOV AH,00000001B ;All done RET BUS$EXIT: ;DEVICE BUSY EXIT MOV AH,00000011B RET CMDERR: MOV AL,3 ;UNKNOWN COMMAND ERROR ERR$EXIT: MOV AH,10000001B ;MARK ERROR RETURN RET CODE ENDS ;*********************************************** ; INIT CODE INITSEG SEGMENT PARA PUBLIC 'IOSYS' ASSUME CS:IO,DS:IO INIT: XOR BP,BP ; Set up stack just below I/O system.  MOV SS,BP MOV SP,BIOSSEG*16 PUSH CS POP DS ;Fall into init code of other modules INITSEG ENDS LASTSEG SEGMENT BYTE PUBLIC 'IOSYS' ASSUME CS:IO, DS:SEG SYSINIT ;Fall into this segment from init code of other modules MOV AX,SEG SYSINIT MOV DS,AX MOV AX,CS ADD AX,BIOSIZS MOV [CURRENT_DOS_LOCATION],AX MOV WORD PTR [DEVICE_LIST],OFFSET IO:DEVSTART MOV WORD PTR [DEVICE_LIST+2],CS MOV [FINAL_DOS_LOCATION],INITSEG MOV [FILES],MAXFIL MOV [BUFFERS],MAXBUF JMP SYSINIT LASTSEG ENDS END nnFp~t@]U^@%]U^];>r;>s E;vA؎X>u[X&.PAGE 60,80 ; ; SCP's OEM disk initialization module to link with ; Microsoft's FORMAT.OBJ and FORMES.OBJ disk formatting program. ; Use this for MS-DOS 2.0 disks. ; Revised 3-11-83. ; INCLUDE IODEF.ASM BOOTER EQU 200H ; "B" command puts boot sector here. SEGBIOS SEGMENT AT BIOSSEG BIOS LABEL FAR SEGBIOS ENDS CODE SEGMENT BYTE PUBLIC 'CODE' ASSUME CS:CODE,DS:CODE,ES:CODE PUBLIC FATID,STARTSECTOR,SWITCHLIST,FREESPACE,FATSPACE,HARDFLAG PUBLIC INIT,DISKFORMAT,BADSECTOR,WRTFAT,DONE EXTRN SWITCHMAP:WORD,DRIVE:BYTE ; ; ******************************************************************* ; IF SCP DISK EQU 0E0H DONEBIT EQU 01H SMALLBIT EQU 10H BACKBIT EQU 04H DDENBIT EQU 08H ENDIF &  IF TARBELL DISK EQU 78H DONEBIT EQU 80H BACKBIT EQU 40H DDENBIT EQU 08H ENDIF GET_DPB EQU 50  GET_CDPB EQU 81 RETRY EQU 3 ONE_BIT EQU 40H TWO_BIT EQU 20H C_BIT EQU 10H ; This must be up here instead of near D_BIT EQU 08H ; SWITCHLIST because the assembler O_BIT EQU 04H ; Can't handle the forward references V_BIT EQU 02H S_BIT EQU 01H INIT: IF SMALLDRV CALL DRIVESELECT TEST AL,SMALLBIT ; See if small drive JZ INIT3 OR [SWITCHMAP],D_BIT ; Force double-density on 5.25 ; drives because controller can't ; handle single-density well. INIT3: ENDIF IF (SIDECHK-1)*(LARGEDS OR SMALLDS) OR [SWITCHMAP],TWO_BIT ; Force double sided if set ENDIF TEST [SWITCHMAP],ONE_BIT JZ INIT4 AND [SWITCHMAP],NOT TWO_BIT ; Turn off 2 sided line INIT4: TEST [SWITCHMAP],TWO_BIT ; Is it double sided JZ INIT1 OR [SIDE],0FFH ; Set flag INIT1: OR [SWITCHMAP],V_BIT ; Always ask for volume ID IF HARD  MOV AL,[DRIVE] CMP AL,LDRVMAX+SDRVMAX ; Is it hard disk ? JB INIT2 ; Exit MOV HARDFLAG,0FFH ; Set flag ENDIF  INIT2: CLC ; No errors. RET DISKFORMAT: MOV BL,[DRIVE] MOV BH,0 PUSH DS MOV AX,BIOSSEG MOV DS,AX  MOV BYTE PTR [BX+3],-1 ; Flag disk as unknown POP DS IF HARD CMP HARDFLAG,0FFH ; Is it a hard disk ? JNZ FT1 JMP HDFORMAT ; Format the hard disk FT1: ENDIF TEST [SWITCHMAP],C_BIT JNZ CHKDENS MOV DX,OFFSET FRMT_MSG CALL MESSAGE JMP KNOW_DENSITY1 ; ; If we are just clearing the disk, it is not necessary for the operator ; to specify the correct density. Therefore, look at the disk to figure ; out what it really is. ; CHKDENS: MOV CX,4 ; Try each density twice CHK: CALL DRIVESELECT ; Select drive. OUT DISK+4,AL ; Select disk MOV AL,0C4H ; READ ADDRESS command CALL DCOM AND AL,98H IN AL,DISK+3 ; Eat last byte to reset DRQ JZ CHK1 ; Jump if no error in reading address. XOR BYTE PTR [SWITCHMAP],D_BIT ; Try other density LOOP CHK MOV DX,OFFSET READ_ERROR ; Error message. JMP ERROR CHK1: IF SIDECHK CALL DRIVESELECT AND AL,SMALLBIT JNZ CHK2 ; Make sure it is not a small drive TEST SWITCHMAP,D_BIT JZ CHK2 ; Make sure it is not single density IN AL,DISK+4 AND AL,40H ; Get side bit OR [SIDE],AL ; Set it ENDIF CHK2: ; Force a disk read to get proper DPB MOV CX,RETRY CHK3: PUSH CX MOV DL,DRIVE INC DL MOV AH,GET_DPB INT 21H ; Media check PUSH CS POP DS MOV AL,DRIVE MOV CX,1 MOV DX,1 MOV BX,OFFSET PATTERN ; Temp buffer INT 25H ; Direct read POP DX POP CX JNC CHK4 LOOP CHK3 ; Read until good CHK4: JMP BOOTRET KNOW_DENSITY1: CALL HEADUNLOAD ; So I/O system thinks disk may be changed. KNOW_DENSITY2: CALL DRIVESELECT ; Select drive. OUT DISK+4,AL ; Select disk IF SIDECHK AND AL,SMALLBIT ; Make sure it is not a small drive JNZ KNOW_DENSITY3 MOV AL,0C4H ; READ ADDRESS command CALL DCOM ; Just read disk, don't care if error IN AL,DISK+4 AND AL,40H ; Get side bit OR [SIDE],AL ; Set it KNOW_DENSITY3: ENDIF MOV WORD PTR [TKCNT],0 MOV BYTE PTR [TKCNT+2],0 CALL TABLE ; SI points to table of info for disk format. MOV AL,[SI+10] ; G' et FATID byte for this format. MOV [FATID],AL MOV AX,[SI+11] ; Get STARTSECTOR for this format. MOV [STARTSECTOR],AX DOIT: MOV BX,OFFSET PATTERN MOV DX,[SI+6] ; DX points to index pattern. CALL MAKE ; Make pattern for index mark and one sector MOV CL,[SI] ; Get sector count for this sector. DEC CL ; Repeat sector pattern for remaining sectors. MAKSEC:  MOV DX,[SI+8] ; DX points to sector pattern. CALL MAKE DEC CL JNZ MAKSEC CALL MAKE ; Fill out rest of track.  ; Put in sequential sector numbers. ; MOV AL,1 ; Start with sector number 1 MOV CL,AL ; Add one to each succeeding sector number MOV BX,[SI+2] ; Get offset from beginning of pattern to first INC BX ; track number. Increment to side, INC BX ; then sector. ADD BX,OFFSET PATTERN ; Compute actual memory address. CALL PUTSEC CALL RESTORE  ; Move the head to track 0. JZ TRACK0 ; Jump if no problem with restoring. MOV DX,OFFSET SEEK_ERROR ; Error message.  JMP ERROR TRACK0: XOR DL,DL ; Start with track 0. TRACKLOOP: PUSH BX MOV BX,OFFSET TRK_MSG CALL INCTRK POP BX  MOV AL,DL ; Get track number. MOV BX,[SI+2] ; Address of first track number in pattern. ADD BX,OFFSET PATTERN MOV CL,0 CALL PUTSEC ; Put track number in each sector. CALL DRIVESELECT ; Get drive-select byte. OUT DISK+4,AL ; Select side. SUB DH,DH ; Start with side 0. SIDELOOP: MOV AL,DH ; Get side number. MOV BX,[SI+2] ; Get offset from beginning of pattern to first INC BX ; track number. Increment to side. ADD BX,OFFSET PATTERN ; Compute actual memory address. MOV CL,0 CALL PUTSEC ; Put side byte in each sector ; ; Write a track. ; CALL TRACK JNC CHECK_SIDE ; Jump if no error. MOV DX,OFFSET WRITE_ERROR ; Error message. JMP ERROR CHECK_SIDE: TEST [SIDE],0FFH ; Check two sided bit JZ NEXTRACK CALL DRIVESELECT ; Get drive-select byte. TEST AL,DDENBIT ; See if double-density. JZ NEXTRACK ; Jump if not (single-density always SS). CHKS1: INC DH ; Next side. CMP DH,2 ; See if too big. JAE NEXTRACK ; Finished this track, on to the next. OR AL,BACKBIT ; Select back side. OUT DISK+4,AL JMP SHORT SIDELOOP ; Do the back side. NEXTRACK: INC DL ; Next track. CMP DL,[SI+1] ; See if done. JAE FINIS MOV AL,58H+STPSPD ; Step in with update, no verify. CALL DCOM TEST AL,098H ; Check for errors, Not Ready, JZ TRACKLOOP ; Seek Error, CRC Error. MOV DX,OFFSET SEEK_ERROR JMP ERROR FINIS: MOV DX,10 CALL CONOUT CALL RESTORE ; Move the head back. MOV DX,OFFSET SEEK_ERROR ; Error message in case of error. JZ F2 JMP ERROR F2: CALL HEADUNLOAD ; Make the I/O system think the disk is changed F3: JMP BOOT_SECTOR ; Set SI to point to a table of data for the selected disk format. ; ; [SI+0] = number of sectors/track ; [SI+1] = number of tracks (or cylindars) on disk. ; [SI+2] = number of bytes from beginning of format pattern track number is. ; [SI+4] = number of bytes in pattern for each sector. ; [SI+6] = address of pattern for index address mark. ; [SI+8] = address of pattern for each sector. ; [SI+10] = FATID byte for this format. ; [SI+11] = STARTSECTOR for(  this format. ; [SI+13] = number of sectors boot sector should load. ; [SI+15] = number of bytes/sector. ; TABLE: TEST HARDFLAG,0FFH MOV AH,6 JNZ DENSITYOK IF SCP AND (SMALL OR COMBIN) SUB AH,AH ; Zero out bit pattern for indexing. CALL DRIVESELECT ; Get drive-select byte. AND AL,SMALLBIT ; See if small disk. JNZ SIZEOK ; Jump if small. ENDIF  TEST [SWITCHMAP],D_BIT MOV AH,3 JZ DENSITYOK ; It is single density MOV AH,4 TEST [SIDE],0FFH ; Is it double/sided? JZ DENSITYOK MOV AH,5 ; Set to double/sided JMP DENSITYOK SIZEOK: TEST [SWITCHMAP],D_BIT MOV AH,0 ; Turn on bit 0 if single-density. JZ DENSITYOK ; Jump if single-density. MOV AH,1 TEST [SIDE],0FFH ; Is it double sided?  JZ DENSITYOK MOV AH,2 ; Set to double sided DENSITYOK: MOV AL,AH ; Computed number to AL. MOV AH,17 ; And multiply by number of bytes in table. MUL AH ; AX = AL*AH. ADD AX,OFFSET DATATABLE ; Add the address of the table. MOV SI,AX RET DRIVESELECT: MOV AL,[DRIVE] ; Get drive-select byte for drive [DRIVE]. PUSH BX MOV BX,OFFSET DRVTAB XLAT TEST [SWITCHMAP],D_BIT ; See if double-density. JZ SPUTNIK ; Jump if not. OR AL,DDENBIT ; Turn on double-density. SPUTNIK: POP BX RET PUTSEC: PUSH DX MOV CH,[SI] ; CH = number of sectors. MOV DX,[SI+4] ; DX = number of bytes in sector pattern. SEC: MOV [BX],AL ; Poke number in sector ID. ADD BX,DX ADD AL,CL ; Increment sector, side, or track number. DEC CH JNZ SEC POP DX RET MAKE: PUSH SI MOV SI,DX MAKELOOP: CLD ; a.k.a. "UP" LODSB ; Get byte count. OR AL,AL ; Return if zero. JZ MAKERETURN MOV CH,AL ; Count to CH. LODSB ; Get byte for pattern. PUTPAT: MOV [BX],AL ; Put byte in pattern. INC BX DEC CH JNZ PUTPAT JMP SHORT MAKELOOP MAKERETURN: MOV DX,SI POP SI RET ; ; Subroutine to restore head to track 0. ; On return, Z flag set if errors. ; RESTORE: MOV AL,08H+STPSPD ; Restore without verify CALL DCOM TEST AL,098H ; Check for errors, Not Ready, RESTORE_RETURN: ; Seek Error, CRC Error. RET TRACK: MOV DI,SI ; Save SI (pointer to DATATABLE). MOV SI,OFFSET PATTERN MOV BP,DX ; Save DX. MOV DX,DISK+3 ; Disk controller data port. MOV AL,0F4H ; Write Track command.  CLI ; Interrupts off. OUT DISK,AL WRTLP: IF SCP IN AL,DISK+5 ; Wait for DRQ or INTRQ. SHR AL,1 LODSB ; Get a byte of the pattern. OUT DX,AL ; Send to controller. JNC WRTLP ENDIF IF TARBELL IN AL,DISK+4 ; Wait for DRQ or INTRQ. SHL AL,1 LODSB ; Get a byte of the pattern. OUT DX,AL ; Send to controller. JC WRTLP  ENDIF STI ; Interrupts back on. MOV DX,BP ; Restore DX. MOV SI,DI ; Restore SI. CALL WAIT ; Wait till status ready. AND AL,0E4H ; Accept "not ready", "write protect", "write JZ WRITERET ; fault", & "lost data" errors. STC ; Set CY flag if error. WRITERET: RET DCOM: OUT DISK,AL AAM ; 10 Microsecond delay. WAIT: IN AL,DISK+4 TEST AL,DONEBIT IF SCP JZ WAIT ENDIF IF TARBELL JNZ WAIT ENDIF IN AL,DISK )  ; Get status from disk. RET HEADUNLOAD: IN AL,DISK+1 ; Read current track. OUT DISK+3,AL ; Make it the track to seek to. MOV AL,10H ; Seek with head unloaded. CALL DCOM RET ; ; Transfer the boot sector to the disk. ; BOOT_SECTOR: TEST [SWITCHMAP],C_BIT JZ SECTOR1 JMP BOOTRET SECTOR1: TEST SWITCHMAP,D_BIT JZ POKE_SINGLE TEST [SIDE],0FFH ; Read 2 sided bit JZ POKE_SINGLE ; Do single sided boot POKE_DOUBLE: MOV AX,[SI+13] ; Poke number of sectors to load into boot. MOV WORD PTR [B2POKE_SECTOR+1],AX MOV AL,[SI+11] ; Poke STARTSECTOR into boot sector. INC AL ; First sector on a track is 1, not 0. MOV BYTE PTR [B2POKE_FIRSECT+1],AL MOV AL,[SI] ; Poke sectors/track two places into boot. MOV BYTE PTR [B2POKE_HALFSECT_1+1],AL MOV BYTE PTR [B2POKE_HALFSECT_2+1],AL SAL AL,1 ; Compute number of sectors/"cylinder". MOV BYTE PTR [B2POKE_MAXSECT_1+2],AL MOV BYTE PTR [B2POKE_MAXSECT_2+2],AL CALL DRIVESELECT ; Get drive-select byte. IF SCP AND AL,0FCH ; Force drive 0 ENDIF IF TARBELL AND AL,0CFH ENDIF MOV BYTE PTR [B2POKE_DRIVESELECT+1],AL MOV AX,[SI+15] ; Poke sector size into boot sector. MOV WORD PTR [B2POKE_SECSIZE+2],AX MOV BX,OFFSET BOOT2SIDED JMP SHORT WRITE_BOOT POKE_SINGLE: MOV AX,[SI+13] ; Poke number of sectors to load into boot. MOV WORD PTR [B1POKE_SECTOR+1],AX MOV AL,[SI+11] ; Poke STARTSECTOR into boot sector. INC AL ; First sector on a track is 1, not 0. MOV BYTE PTR [B1POKE_FIRSECT+1],AL MOV AL,[SI] ; Poke sectors/track two places into boot. MOV BYTE PTR [B1POKE_MAXSECT_1+2],AL MOV BYTE PTR [B1POKE_MAXSECT_2+2],AL MOV AX,[SI+15] ; Poke sector size into boot sector. MOV WORD PTR [B1POKE_SECSIZE+2],AX MOV BX,OFFSET BOOT1SIDED WRITE_BOOT: CALL HEADUNLOAD MOV CX,RETRY WRT1: PUSH CX  MOV AL,[DRIVE] ; Which drive to write the boot to. PUSH BX PUSH AX MOV AH,GET_DPB MOV DL,AL INC DL INT 21H  ; Force a media check. Set density PUSH CS POP DS POP AX POP BX MOV CX,1 ; One sector. MOV DX,0 ; Write sector number 0. INT 38 ; Call I/O system to write boot sector. POP DX POP CX JNC WTRET LOOP WRT1 MOV DX,OFFSET BOOT_ERROR ; Error message in case it didn't work. JMP MESSAGE WTRET: IF SCP AND (SMALL OR COMBIN) CALL TABLE CALL DRIVESELECT AND AL,SMALLBIT ; Is it small drive JZ WTRET1 MOV BX,OFFSET SMALLDATA MOV AL,[SI+10] MOV [BX],AL ; Put fatid  MOV CX,1 MOV DX,1 MOV AL,[DRIVE] INT 38 ; Write Fatid byte POP DX ; Restore flags WTRET1: ENDIF BOOTRET: ; Calculate the number of sectors and buffer size here for bad sector ; checking. Initialize the memory parameters. TEST HARDFLAG,0FFH JNZ BOOT0 CALL RESTORE BOOT0: CALL TABLE MOV AL,[SI] CBW MOV CX,[SI+1] ; # of tracks on disk TEST HARDFLAG,0FFH ; Hard disk has 2 bytes for this parameter JNZ BOOT2 MOV CH,0 BOOT2: MUL CX ; Calculate # of sectors on disk  MOV [SCCNT],AX ; Save MOV AX,[SI+15] ; Sector size MOV [SECSZ],AX MOV [SCTN],30 ; Start with 30 sectors to try BOOT1: MOV AX,[SECSZ] MOV CL,[SCTN] ; #of sectors to read MOV CH,0 MUL CX ; Test for maximum reads CMP AX,4096 ; Don't make b* uffer any bigger JBE BOOTRET1 DEC [SCTN] JMP BOOT1 ; Keep calculating until 4k or smaller BOOTRET1: MOV [SCTN],CL ; This is the number of sectors to read MOV DL,[DRIVE] INC DL MOV AH,50 INT 21H ; Get DPB MOV AL,[BX+0FH]  ; Get size of fat in sectors MOV AH,[BX+8] ; Get number of fats MOV DX,[BX+6] ; First sector of fat MOV BX,[BX+0BH] ; First sector of data PUSH CS POP DS MOV [STARTSECTOR],BX MOV [STRT],BX MOV CX,[SCCNT] SUB CX,BX MOV [SCCNT],CX ; Calculate true remaining sectors MOV  [FATCNT],AH MOV [FATSTART],DX XOR AH,AH MOV [FATSIZE],AX TEST [SWITCHMAP],C_BIT JZ BOOTEXIT MOV CX,RETRY RET2: PUSH CX MOV CX,1 MOV DX,0 MOV BX,OFFSET PATTERN MOV AL,[DRIVE] INT 25H POP DX POP CX JNC BOOTEXIT LOOP RET2 BOOTEXIT: MOV DX,OFFSET BDSCT_MSG CALL MESSAGE CLC RET SMALLDATA: DB 0 DB 0FFH DB 0FFH ERROR: CALL HEADUNLOAD MESSAGE: MOV AH,9 ; Function 9, print string. INT 33 STC RET  INCTRK: PUSH DX PUSH AX PUSH SI MOV DX,BX CALL MESSAGE MOV SI,OFFSET CODE:TKCNT INC WORD PTR [SI] MOV AX,[SI] INC SI INC SI CMP AL,10 JB C2 ADD AH,1 C2: AAM CMP AH,10 JB C1 MOV AX,0 MOV SI,OFFSET CODE:TKCNT MOV [SI],AX INC SI INC SI INC BYTE PTR [SI] C1: CMP BYTE PTR [SI],0 ;Is 100's unit clear ? JZ C3 ; If so,don't print PUSH AX MOV DL,[SI] ADD DL,30H CALL CONOUT POP AX C3: ADD AL,30H ADD AH,30H PUSH AX MOV DL,AH CALL CONOUT POP AX  MOV DL,AL PUSH AX CALL CONOUT POP AX MOV DL,13 CALL CONOUT POP SI POP AX POP DX RET CONOUT: MOV AH,2 INT 21H RET ;------------------------------------------------------------ IF HARD ;Initialize Winchester disk using Morrow HDC-DMA controller IF SCRIBE NHEADS EQU 4 ; Number of heads NSECT EQU 8 ; Number of sectors per track NTRACKS EQU 480 ; Number of cylinders LCTRK EQU 0 ; First track of low write current PRECOMP EQU 0 ; First track to set precomp bit ENDIF IF IMI NHEADS EQU 6 ; Number of heads NSECT EQU 8 ; Number of sectors per track NTRACKS EQU 306 ; Number of cylinders LCTRK EQU 0 ; First track of low write current PRECOMP EQU 256 ; First track to set precomp bit ENDIF ;Controller parameters RESET EQU 54H STRTHDC EQU 55H STATBYT EQU 12 NEXTAD EQU 13 HDFORMAT: MOV DL,10 CALL CONOUT MOV DL,13 CALL CONOUT MOV DX,OFFSET HDISK_MSG CALL MESSAGE MOV AH,1 INT 21H ; Console input CMP AL,'Y' ; Accept a yes only JZ HFMT2 JMP HDFORMAT HFMT2: MOV DL,10 CALL CONOUT MOV DL,13 CALL CONOUT TEST [SWITCHMAP],C_BIT JZ BEGIN JMP BOOTRET BEGIN: MOV DX,OFFSET FRMT_MSG CALL MESSAGE MOV WORD PTR [TKCNT],0 MOV BYTE PTR [TKCNT+2],0 OUT RESET,AL ;Reset the HDC XOR AX,AX MOV ES,AX MOV DI,50H ;First pointer is at 0:50H MOV DX,OFFSET CODE:LOADCONS CALL SETADDR ;Set initial pointer to LOADCONS PUSH DS POP ES MOV DX,OFFSET CODE:HRESTORE MOV DI,OFFSET CODE:LOADCONS+NEXTAD CALL SETADDR ;Set chain pointer to RESTORE MOV SI,OFFSET CODE:LOAD+ CONS+STATBYT CALL DOCOM ;Execute LOADCONS MOV DX,OFFSET CODE:FORMAT MOV DI,OFFSET CODE:HRESTORE+NEXTAD CALL SETADDR ;Set chain pointer to FORMAT MOV DI,OFFSET CODE:FORMAT+NEXTAD CALL SETADDR ;Set FORMAT to loop to itself MOV SI,OFFSET CODE:HRESTORE+STATBYT CALL DOCOM ;Execute RESTORE MOV DX,OFFSET CODE:FORMATDATA MOV DI,OFFSET CODE:FORMATDMA CALL SETADDR NEWCYL: MOV BL,0 ;Initial head number FORMATLOOP: MOV CX,NSECT MOV SI,OFFSET CODE:FORMATDATA+2;Point to head field SETHEAD: MOV [SI],BL ADD SI,4 LOOP SETHEAD MOV AL,BL SHL AL,1 SHL AL,1 NOT AL AND AL,1CH CMP [FORMATDATA],PRECOMP ; Precomp track? JB STHD1 OR AL,80H ;Turn it on STHD1: CMP [FORMATDATA],LCTRK ;Are we at low current track? JAE LOWCUR OR AL,40H ;If not, turn off low write current LOWCUR: MOV BYTE PTR [HEADSEL],AL MOV SI,OFFSET CODE:FORMAT+STATBYT CALL DOCOM ;Format the track MOV [FORMAT+1],0 ;Zero step count (if any) INC BL CMP BL,NHEADS ;Completed the cylinder? JNZ FORMATLOOP MOV [FORMAT+1],1 ;Step in to next track MOV SI,OFFSET CODE:FORMATDATA MOV AX,[SI] ;Get current track number INC AX MOV CX,NSECT SETTRK: MOV [SI],AX ADD SI,4 LOOP SETTRK PUSH AX PUSH DX PUSH BX MOV BX,OFFSET TRK_MSG CALL INCTRK POP BX POP DX POP AX CMP AX,NTRACKS ;All done? JNZ NEWCYL MOV DL,10 MOV AH,2 INT 21H ; Output a linefeed JMP BOOTRET DOCOM: MOV BYTE PTR [SI],0 ;Zero status byte OUT STRTHDC,AL ;Start up HDC HWAIT: TEST BYTE PTR [SI],-1 ;Loop until completion JZ HWAIT  RET SETADDR: MOV AX,DS ;Get current segment XOR CX,CX SHL AX,1 ;Convert to 20-bit number RCL CX,1 SHL AX,1 RCL CX,1 SHL AX,1 RCL CX,1 SHL AX,1 RCL CX,1 ADD AX,DX ;Add in offset STOSW XCHG AX,CX ADC AL,0 ;Ripple the carry STOSB RET LOADCONS: DB 0 DW 0 DB 0DCH DB 0,0,0 DB 0,1EH,0,7 ;Set up slow stepping DB 4 ;Load constants DB 0 ;status DB 0,0,0 ;Next address HRESTORE: DB 10H ;Step out DW 0FFFH ;Maximum number of cylinders DB 0DCH DB 0,0,0 DB 0,0,0,0 DB 6 ;No-op DB 0 ;status  DB 0,0,0 ;Next address FORMAT: DB 0 ;Step in DW 0 HEADSEL: DB 0DCH FORMATDMA: DB 0,0,0 ;DMA address (filled in later) DB 24 ;Gap 3 DB -NSECT-1 ;Complement of number of sectors DB 0F8H ;Sector Size code (1024 bytes) DB 0 ;Fill byte DB 3 ;Format opcode DB 0 ;Status DB 0,0,0 ;Next address FORMATDATA: ;CYL, cyl-H, head, sector for nine sectors DB 0,0,0,1 DB 0,0,0,2 DB 0,0,0,3 DB 0,0,0,4 DB 0,0,0,5 DB 0,0,0,6  DB 0,0,0,7 DB 0,0,0,8 DB 0,0,0,9 ENDIF ;---------------------------------------------------------- BADSECTOR: MOV AL,DRIVE MOV CL,[SCTN] MOV CH,0 MOV DX,[STRT] CMP [SCCNT],0 JZ BDRET MOV BX,OFFSET PATTERN ; Set up read buffer PUSH CX PUSH DX INT 25H ; Read sectors POP BP POP DX POP CX JC BDRPT ; Report bad sector MOV AL,SCTN CBW ADD [STRT],AX ; Increment sector start SUB [SCCNT],AX MOV CX,[SCCNT] MOV AL,SCTN CBW CMP AX,CX ; Test fo, r last few sectors JB BADSECTOR MOV SCTN,CL ; Reset sector count to final sectors JMP BADSECTOR BDRPT: MOV BX,[STRT]  MOV AL,[SCTN] CBW SUB AX,CX ; Find out how sectors were read ADD BX,AX ; Set up first bad sector INC AX ADD [STRT],AX SUB [SCCNT],AX MOV AX,1 CLC RET BDRET: CALL HEADUNLOAD MOV AX,0 CLC RET ;------------------------------------------------------------------ WRTFAT: MOV AL,[FATCNT] MOV [CURCNT],AL ;SET UP FAT COUNT MOV AX,[FATSTART] MOV [CNT],AX FATLOOP: MOV AL,DRIVE CBW MOV CX,[FATSIZE] MOV DX,[CNT] MOV BX,[FATSPACE] INT 26H POP AX JC GORET MOV CX,[FATSIZE] ADD [CNT],CX DEC BYTE PTR [CURCNT] JNZ FATLOOP CLC  ;Good return GORET: CALL HEADUNLOAD RET DONE: CALL HEADUNLOAD CLC ; No errors. RET DATATABLE: DB 16 ; Number of sectors/track 5.25-inch SD/SS. DB 40 ; Number of tracks/disk 5.25-inch SD/SS format. DW 11 ; Beginning of pattern to first ID mark. DW 186 ; Number of bytes/sector in pattern. DW OFFSET SSINDEX ; Address of index pattern 5.25-inch SD/SS. DW OFFSET SSSECTOR ; Address of sector pattern 5.25-inch SD/SS. DB 0FEH ; FATID byte for 5.25-inch SD/SS format. DW 1+4+4+17 ; STARTSECTOR for 5.25-inch SD/SS format. DW 256 ; Number of sectors boot sector should load. DW 128 ; Bytes/sector. DB 8 ; 5.25-inch DD/SS format. DB 40 DW 162 DW 652 DW OFFSET SDINDEX DW OFFSET SDSECTOR DB 0FEH DW 1+1+1+4 DW 64 DW 512 DB 8 ; 5.25-inch DD/DS format. DB 40 DW 162 DW 652 DW OFFSET SDINDEX DW OFFSET SDSECTOR DB 0FFH DW 1+1+1+7 DW 64 DW 512 DB 26 ; 8-inch SD/SS format. DB 77 DW 80 DW 186 DW OFFSET LSINDEX DW OFFSET LSSECTOR DB 0FEH DW 1+6+6+17 DW 256 DW 128 DB 8 ; 8-inch DD/SS format. DB 77 DW 162 DW 1138 DW OFFSET LDINDEX DW OFFSET LDSECTOR DB 0FFH DW 1+1+1+3 DW 32 DW 1024 DB 8 ; 8-inch DD/DS format. DB 77 DW 162 DW 1138 DW OFFSET LDINDEX DW OFFSET LDSECTOR DB 0FEH DW 1+2+2+6 DW 32 DW 1024  IF HARD DB NSECT ; Hard disk format DW NTRACKS DB ? DW ? DW ? DW ? DB 0FFH DW ? DW ? DW 1024 ENDIF LDINDEX: ; Pattern for 8-inch double-density. DB 80,4EH DB 12,0 DB 3,0F6H DB 1,0FCH DB 50,4EH LDSECTOR: DB 12,0 DB 3,0F5H DB 1,0FEH DB 3,0 ; Track, side, and sector DB 1,3 ; Sector size=1024 DB 1,0F7H DB 22,4EH DB 12,0 DB 3,0F5H DB 1,0FBH DB 255,0E5H DB 255,0E5H DB 255,0E5H DB 255,0E5H DB 4,0E5H DB 1,0F7H DB 54,4EH DB 0 DB 255,4EH DB 255,4EH DB 255,4EH DB 0 LSINDEX: ; Pattern for 8-inch single-density. DB 40,-1 DB 6,0 DB 1,0FCH DB 26,-1 LSSECTOR: DB 6,0 DB 1,0FEH DB 4,0 DB 1,0F7H DB 11,-1 DB 6,0 DB 1,0FBH DB 128,0E5H DB 1,0F7H DB 27,-1 DB 0 DB 255,-1 DB 255,-1 DB 0 SDINDEX: ; Pattern for 5.25-inch double-density. DB 80,4EH DB 12,0 DB 3,0F6H DB 1,0FCH DB 50,4EH SDSECTOR: DB 12,0 DB 3,0F5H DB 1,0FEH DB 3,0 ; Track, side, and sector. DB 1,2 ; Sector size = - 512. DB 1,0F7H DB 22,4EH DB 12,0 DB 3,0F5H DB 1,0FBH DB 255,0E5H DB 255,0E5H DB 2,0E5H DB 1,0F7H DB 80,4EH  DB 0 DB 255,4EH DB 255,4EH DB 255,4EH DB 255,4EH DB 255,4EH DB 255,4EH DB 0 SSINDEX: ; Pattern for 5.25-inch single-density. DB 4,-1 ; No index mark. SSSECTOR: DB 6,0 DB 1,0FEH DB 4,0 DB 1,0F7H DB 11,-1 DB 6,0 DB 1,0FBH DB 128,0E5H DB 1,0F7H DB 27,-1 DB 0 DB 255,0 DB 255,0 DB 255,0 DB 255,0 DB 0 .SALL BYTELST MACRO INITVAL,COUNT,INC LOCAL X X = INITVAL REPT COUNT DB X X = X+INC ENDM ENDM DRVTAB LABEL BYTE IF SCP BYTELST 0,LDRVMAX,1 BYTELST 10H,SDRVMAX,1 ENDIF IF TARBELL BYTELST 0,LDRVMAX,10H ENDIF ; Error messages. ; READ_ERROR DB "Read Error - can't determine density",13,10,'$' SEEK_ERROR DB 'Seek Error - disk not ready',13,10,'$' WRITE_ERROR DB 'Write Error - not ready, write protect, ' DB 'write fault, or lost data',13,10,'$' BOOT_ERROR DB 'Error writing boot sector',13,10,'$' FRMT_MSG DB 'Formatting',13,10,'$' TRK_MSG DB 'Cylinder : $' BDSCT_MSG DB 'Testing for bad sectors',13,10,'$' HDISK_MSG DB 'Are you sure you want to format this hard disk ? $' FATSIZE DW ? FATSTART DW ? CNT DW ? STARTSECTOR DW ?  SPC DB ? ;SECTORS PER CLUSTER FATCNT DB ? ;NUMBER OF FATS ON THIS DRIVE CURCNT DB ? DSKSIZE DW ? ;NUMBER OF SECTORS ON THE DRIVE STRT DW 0 ;CURRENT TEST SECTOR SCCNT DW 0 ; # of sectors on disk SCTN DB 0 ; # of sectors to read SECSZ DW 0 ; Sector size SIDE DB 0 TKCNT DW 0 DB 0 SWITCHLIST DB 7,'12CDOVS' FATID DB 0 FIRSTFLAG DB 1 HARDFLAG DB 0 FATSPACE DW BUFFER FREESPACE DW FREE ; ; Boot sectors, one for single-sided boot, a second for double-sided boot. ; Both have various variables such as STARTSECTOR and number of sectors to ; load poked in before the boot sector is written to the disk. The boot ; sectors should be ORGed at 200 hex, but since all jumps and calls are ; reletive, it doesn't matter that it is ORGed at a random location. ; BOOT1SIDED: CLI ; Interrupts off. XOR AX,AX MOV DS,AX MOV ES,AX MOV SS,AX MOV SP,BOOTER ; For debugging purposes. CLD ; a.k.a. "UP" MOV DI,BIOSSEG*16 B1POKE_SECTOR: MOV CX,0 ; CX = number of sectors/track. B1POKE_FIRSECT: MOV BL,0 ; BL = first sector to load. B1SECT: MOV AL,0D0H ; Force Interrupt command. OUT DISK,AL ; To force Type I status AAM ; Give force interrupt time. AAM AAM AAM B1SEEKLP: B1POKE_MAXSECT_1: CMP BL,0  ; Compare with number of sectors/track. JBE B1NOSTEP MOV AL,58H ; Step in with update. CALL B1DCOM B1POKE_MAXSECT_2: SUB BL,0 ; Subtract number of sectors/track. JMP SHORT B1SEEKLP B1NOSTEP: MOV AL,BL ; Get sector number. OUT DISK+2,AL ; Output sector number to disk controller. MOV DX,DISK+3 ; Disk controller data port. PUSH DI MOV AL,88H ; Read Sector command. OUT DISK,AL JMP SHORT B1READ B1READLOOP: STOSB ; Put in memory. B1READ: IF TARBELL IN AL,DISK+4 ROL AL,1 IN AL,DX ; Read data from disk controller chip. JC B1READLOOP ENDIF IF SCP IN AL,DISK+5 ; Input from auto-wait port. ROR AL,1 IN AL,DX ; Read data from disk controller chip. JNC B1READLOOP ENDIF POP DI CALL B1STAT AND AL,9CH.  JNZ B1SECT B1POKE_SECSIZE: ADD DI,128 ; Add sector size to load next sector. INC BL LOOP B1SECT JMP BIOS B1DCOM: OUT DISK,AL AAM B1STAT: IN AL,DISK+4 TEST AL,DONEBIT IF TARBELL JNZ B1STAT ENDIF IF SCP JZ B1STAT ENDIF IN AL,DISK RET BOOT2SIDED: CLI ; Interrupts off. XOR AX,AX MOV DS,AX MOV ES,AX MOV SS,AX MOV SP,BOOTER ; For debugging purposes. CLD ; a.k.a. "UP" MOV DI,BIOSSEG*16 B2POKE_SECTOR: MOV CX,0 ; CX = number of sectors/track.  B2POKE_FIRSECT: MOV BL,0 ; BL = first sector to load. B2SECT: MOV AL,0D0H ; Force Interrupt command. OUT DISK,AL ; To force Type I status AAM ; Give force interrupt time. AAM AAM AAM B2SEEKLP: B2POKE_MAXSECT_1: CMP BL,0 ; Compare with number of sectors/track. JBE B2NOSTEP MOV AL,58H ; Step in with update. CALL B2DCOM B2POKE_MAXSECT_2: SUB BL,0 ; Subtract number of sectors/track. JMP SHORT B2SEEKLP B2NOSTEP: MOV AL,BL ; Get sector number. MOV AH,0 ; Assume side 0. B2POKE_HALFSECT_1: CMP AL,0 ; Find out which sector and side to use. JBE B2SIDE B2POKE_HALFSECT_2: SUB AL,0 ; Compute sector number for back side. MOV AH,BACKBIT ; Side 1 bit. B2SIDE: OUT DISK+2,AL ; Output sector number to disk controller. MOV AL,AH ; Get side-select byte. B2POKE_DRIVESELECT: OR AL,0 ; Add the rest of the drive-select bits. OUT DISK+4,AL ; And send the mess out. MOV DX,DISK+3 ; Disk controller data port. PUSH DI MOV AL,88H ; Read Sector command. OUT DISK,AL JMP SHORT B2READ B2READLOOP: STOSB ; Put in memory. B2READ: IF TARBELL IN AL,DISK+4 ; Input from auto-wait port. ROL AL,1 IN AL,DX ; Read data from disk controller chip. JC B2READLOOP ENDIF IF SCP IN AL,DISK+5 ; Input from auto-wait port. ROR AL,1 IN AL,DX ; Read data from disk controller chip. JNC B2READLOOP ENDIF POP DI CALL B2STAT AND AL,9CH JNZ B2SECT B2POKE_SECSIZE: ADD DI,128 ; Add sector size to load next sector. INC BL LOOP B2SECT JMP BIOS B2DCOM: OUT DISK,AL AAM B2STAT: IN AL,DISK+4 TEST AL,DONEBIT IF TARBELL JNZ B2STAT ENDIF IF SCP JZ B2STAT ENDIF IN AL,DISK RET PATTERN LABEL BYTE BUFFER EQU PATTERN+12*1024 FREE EQU BUFFER+6*1024 CODE ENDS END } Q `5 }0} ;Console I/O for MS-DOS 2.0 INCLUDE IODEF.ASM IO GROUP CODE,INITSEG INITSEG SEGMENT BYTE PUBLIC 'IOSYS' ASSUME CS:IO, DS:IO IF INTINP ; SS and BP are zero CLI ; Set up keyboard interrupt vector. MOV WORD PTR [BP+64H],OFFSET IO:KBINT MOV [BP+66H],CS STI ELSE MOV AL,0FFH OUT BASE+3,AL ; Mask all interrupts ENDIF ;Set up vector 29H for fast console output MOV WORD PTR [BP+0A4H],OFFSET IO:CON$INT MOV [BP+0A6H],CS INITSEG ENDS CODE SEGMENT BYTE PUBLIC 'IOSY/ S' ASSUME CS:IO, DS:IO PUBLIC CONTBL,RDNDEXIT EXTRN EXIT:NEAR, CMDERR:NEAR, BUS$EXIT:NEAR, PTRSAV:DWORD ; Command table CONTBL: DW EXIT ; Init DW EXIT DW EXIT DW CMDERR DW CON$READ DW CON$RDND DW EXIT DW CON$FLSH DW CON$WRIT DW CON$WRIT DW CON$WRST ; Console keyboard interrupt handler. KBINT PROC FAR PUSH AX PUSH SI MOV AL,20H ;End of Interrupt command OUT BASE+2,AL ;Send to slave IN AL,DATA ;Get the character AND AL,7FH CMP AL,"C"-"@" JZ FLSH CMP AL,"S"-"@" JZ FLSH CMP AL,"F"-"@" JNZ SAVKY FLSH: CALL FLUSH ; Call I/O system keyboard buffer flush. SAVKY:  MOV SI,CS:[REAR] ;Pointer to rear of queue CALL INCQ CMP SI,CS:[FRONT] ;Any room in queue? JZ QFULL MOV CS:[SI],AL ;Put character in queue MOV CS:[REAR],SI ;Save pointer LEAVINT: POP SI POP AX IRET KBINT ENDP QFULL: MOV AL,7 ; BELL character. CALL OUTCHR ; Call I/O system console output function. JMP SHORT LEAVINT BUSEXIT:JMP BUS$EXIT CON$RDND: CALL CSTATUS JZ BUSEXIT RDNDEXIT: LES DI,[PTRSAV] MOV ES:[DI.MEDIA],AL JMP EXIT CSTATUS: IF INTINP-1 IN AL,STAT AND AL,DAV JZ REPEAT PUSHF ;Look like an INT CALL KBINT REPEAT: ENDIF PUSH SI CLI ; Disable interrupts while checking queue. MOV SI,[FRONT] CMP SI,[REAR] ; Anything in queue? JZ NOCHR ; Jump if nothing in queue. CALL INCQ  LODSB ;Get character (if there is one) OR SI,SI NOCHR: STI POP SI RET CON$READ: CALL INP STOSB LOOP CON$READ JMP EXIT INP: CALL CSTATUS ; Get I/O system console input status. JZ INP PUSH SI CLI ; Disable interrupts while changing queue pointers. MOV SI,[FRONT] CALL INCQ ; Permanently remove char from queue MOV [FRONT],SI STI POP SI RET CON$FLSH: CALL FLUSH JMP EXIT FLUSH: CLI MOV CS:[REAR],OFFSET IO:QUEUE MOV CS:[FRONT],OFFSET IO:QUEUE STI RET INCQ: INC SI CMP SI,OFFSET IO:ENDQ ;Exceeded length of queue? JB RET1 MOV SI,OFFSET IO:QUEUE RET1: RET FRONT DW OFFSET IO:QUEUE REAR DW OFFSET IO:QUEUE QUEUE DB QSIZE DUP(?) ENDQ LABEL BYTE ; ************ Console Output ************ CON$WRST: IN AL,STAT AND AL,TBMT JZ BUS$EXITV JMP EXIT BUS$EXITV: JMP BUS$EXIT CON$INT: STI ;INTS back on PUSH AX PUSH CX PUSH DX PUSH DI PUSH DS PUSH CS POP DS CALL CONOUT POP DS POP DI POP DX POP CX  POP AX IRET CON$WRIT: MOV SI,DI CONOUTLP: LODS BYTE PTR ES:[SI] PUSH CX CALL CONOUT POP CX LOOP CONOUTLP JMP EXIT ESC EQU 1BH STATE DW ST1 PRMPNT DW PARMS PARMS DB 0,0,0,0,0,0,0 LASTPRM DB 0 BUFF DB 0,0,0,0,0,0,0,0,0,0 ; Cursor control table CMDTABL DB 'A' ;Cursor up DW CUU DB 'B' ;Cursor down DW CUD DB 'C' ;Cursor forward DW CUF DB 'D' ;Cursor backward DW CUB DB 'H' ;Cursor position DW CUP DB 'J' ;Erase display DW ED DB 'K' ;Erase line DW EL DB 'f' ;Cursor position DW CUP DB 'm' ;Exit/Enter reverse video mode DW SGR DB 's' ;Save cursor position DW PSCP DB 'u' ;Set cursor to saved position DW PRCP DB 00 CONOUT: MOV DI,OFFSET IO:STATE JMP WORD PTR [DI] ;JUMP TO THE CURRENT ANSI STATE ST1: CMP AL,ESC JNZ OUTCHR MOV WORD PTR [DI],OFFSET IO:ST2 RET OUTCHR: PUSH AX OUTLP: I0 N AL,STAT AND AL,TBMT JZ OUTLP POP AX OUT DATA,AL MOV [STATE],OFFSET IO:ST1 RET SENDESC: PUSH AX MOV AL,ESC  CALL OUTCHR JMP OUTLP ST2: CMP AL,'[' JNZ SENDESC MOV BX,OFFSET IO:PARMS MOV [BX],BYTE PTR 31H MOV WORD PTR [PRMPNT],BX MOV IO:[STATE],OFFSET IO:ST3 RET ST3: CMP AL,';' JNZ ST3A INC WORD PTR [PRMPNT] RET ST3A: CMP AL,'0' JB ST3B CMP AL,'9' JA ST3B PUSH DI MOV DI,[PRMPNT] MOV [DI],AL POP DI RET ST4: PUSH AX MOV AL,ESC CALL OUTCHR  MOV AL,'[' CALL OUTCHR JMP OUTLP ST3B: MOV DI,OFFSET IO:CMDTABL-3 ST3C: ADD DI,3 CMP BYTE PTR [DI],0 JZ ST4 ;Output characters in buffer CMP AL,[DI] JNZ ST3C INC DI ;Point to translate characters MOV BX,WORD PTR [DI] MOV SI,OFFSET IO:BUFF ;Set up temp buffer MOV CX,1 ;Set counter to at least 1 time MOV DL,0 ;Set # of characters TLOOP: MOV AL,[BX] ;Fetch xlate char CMP AL,0 JZ TEXIT ;End of characters TEST AL,80H ;Test for special character JZ NEXTCHR CMP AL,0F1H ;Is it 1st parm JNZ SCHR MOV AL,IO:[PARMS] ;Fetch it JMP NEXTCHR SCHR: CMP AL,0F2H ;Is it 2nd parm JNZ TCHR MOV AL,IO:[PARMS+1] JMP NEXTCHR TCHR: CMP AL,0FEH ;Use special driver ? JZ TDRIV CMP AL,0FFH ;Is it count char  JNZ NEXTCHR MOV CL,IO:[PARMS] CMP CL,31H JAE TCHR1 MOV CL,31H TCHR1: SUB CL,30H INC BX JMP TLOOP NEXTCHR: MOV [SI],AL ;Put to buffer INC SI ;Temp buffer INC BX ;Xlate table INC DL ;# of char in BUFF JMP TLOOP ;Get next character TEXIT: ;All charcters are fetched MOV SI,OFFSET IO:BUFF MOV DH,DL ;Save # of char TEXITL: MOV AL,[SI] CALL OUTCHR INC SI DEC DH JNZ TEXITL ;Output until empty DEC CL ;Do CX count JNZ TEXIT RET TDRIV: ;User defined driver for SGR CMP WORD PTR [DI],OFFSET IO:SGR JZ DRIVOUT MOV AL,0 ;Dummy char JMP OUTCHR DRIVOUT: MOV BX,OFFSET IO:PARMS CMP BYTE PTR [BX],37H ;Is it enter mode JZ SGRN MOV AL,'q' ;Heath exit video mode JMP SENDESC SGRN: MOV AL,'p' JMP SENDESC ;Heath enter video mode ; ; Cursor controls translation table. This table below contains that ; actual ASCII code sequences used by your terminal to perform basic ; cursor control commands. MS-DOS 2.0 normally expects to see ANSI ; standard sequences for these commands, however this table is set ; up so that the user can re-define the ASCII codes for his specific ; terminal. The table has some specifiers that will tell the code ; to use certain parameters that are passed, such as row or column ; number, or the number of moves. ; ; Specifer action ; 0F1H Use parameter #1 here (the row or line #) ; 0F2H Use parameter #2 here (the column #) ; 0FEH Use special driver routine (User defined) ; 0FFH Use parameter #1 as a count ; 00H end of code ; ESC Outputs the 'esc' character HEATH: CUP: DB ESC ;Cursor position  DB 'Y' DB 0F1H DB 0F2H DB 0 CUU: DB ESC ;Cursor up DB 'A' DB 0FFH DB 0 CUD: DB ESC ;Cursor down DB 'B' DB 0FFH DB 0 CUF: DB ESC ;Cursor forward DB 'C' DB 0FFH DB 0 CUB: DB ESC ;Cursor backward DB 'D' DB 0FFH DB 0 ED: DB ESC ;Erase display DB 'E' DB 0 EL: DB ESC ;Erase line DB 'L' DB 0 PSCP: DB ESC ;Save cursor posit1 ion DB 'j' DB 0 PRCP: DB ESC ;Set cursor to saved position DB 'k' DB 0 SGR: DB 0FEH ;User defined driver DB 0  CODE ENDS END R~U"~M@>t@2‹~E@> u~E$~}<u ~UB~U@;>u1~U~U"; Auxiliary I/O for MS-DOS 2.0 INCLUDE IODEF.ASM IO GROUP CODE,INITSEG,LASTSEG INITSEG SEGMENT BYTE PUBLIC 'IOSYS' ASSUME CS:IO, DS:IO IF SERIAL MOV CX,4 MOV SI,OFFSET IO:SERTAB SERINIT: LODSB OUT SIOBASE+1,AL OUT SIOBASE+3,AL LOOP SERINIT LODSB ;Baud rate for channel 0 OUT SIOBASE+8,AL LODSB ;Baud rate for channel 1 OUT SIOBASE+9,AL ENDIF INITSEG ENDS LASTSEG SEGMENT BYTE PUBLIC 'IOSYS' IF SERIAL SERTAB DB 0B7H, 77H, 4EH, 37H, PRNBAUD, AUXBAUD ENDIF LASTSEG ENDS CODE SEGMENT BYTE PUBLIC 'IOSYS' ASSUME CS:IO, DS:IO PUBLIC AUXTBL EXTRN EXIT:NEAR, CMDERR:NEAR, BUS$EXIT:NEAR, RDNDEXIT:NEAR AUXTBL: DW EXIT DW EXIT DW EXIT DW CMDERR DW AUX$READ DW AUX$RDND DW EXIT DW AUX$FLSH DW AUX$WRIT DW AUX$WRIT DW AUX$WRST AUX$RDND: CALL AUXISTAT JZ BUS$EXITJ JMP RDNDEXIT AUXISTAT: MOV AL,[AUXCHAR] TEST [AUXBST],1 JNZ RET2 IN AL,AUXSTAT AND AL,DAV JZ RET2 IN AL,AUXDATA MOV [AUXCHAR],AL MOV [AUXBST],1 RET2: RET BUS$EXITJ:JMP BUS$EXIT AUX$READ: CALL AUXIN STOSB LOOP AUX$READ JMP EXIT AUXIN: CALL AUXISTAT  JZ AUXIN AUXFLUSH: MOV [AUXBST],0 RET AUX$FLSH: CALL AUXFLUSH JMP EXIT AUX$WRST: IN AL,AUXSTAT AND AL,TBMT  JZ BUS$EXITJ JMP EXIT AUX$WRIT: MOV SI,DI AUXOUTLP: LODS BYTE PTR ES:[SI] CALL AUXOUT LOOP AUXOUTLP JMP EXIT  AUXOUT: PUSH AX AUXLP: IN AL,AUXSTAT AND AL,TBMT JZ AUXLP POP AX OUT AUXDATA,AL RET AUXCHAR DB 0 AUXBST DB 0 CODE ENDS END SEXIT RDNDEXIT: LES DI,[PTRSAV] MOV ES:[DI.MEDIA],AL JMP EXIT CSTATUS: IF INTINP-1 IN AL,S; Printer I/O for MS-DOS 2.0 INCLUDE IODEF.ASM IO GROUP CODE CODE SEGMENT BYTE PUBLIC 'IOSYS' ASSUME CS:IO, DS:IO  PUBLIC PRNTBL EXTRN EXIT:NEAR, CMDERR:NEAR, BUS$EXIT:NEAR PRNTBL: DW EXIT ;INIT DW EXIT DW EXIT DW CMDERR DW EXIT DW BUS$EXIT DW EXIT DW EXIT DW PRN$WRIT DW PRN$WRIT DW PRN$STAT DW EXIT PRN$STAT: IN AL,PRNSTAT AND AL,TBMT JZ BUS$EXITJ JMP EXIT BUS$EXITJ: JMP BUS$EXIT PRN$WRIT: MOV SI,DI PRNOUTLP: LODS BYTE PTR ES:[SI] CALL PRINT LOOP PRNOUTLP JMP EXIT PRINT: PUSH AX PRINLP: IN AL,PRNSTAT AND AL,TBMT JZ PRINLP POP AX OUT PRNDATA,AL RET CODE ENDS END  AUXTBL: DW EXIT DW EXIT DW EXIT DW CMDERR DW AUX$READ DW AUX$RDND DW EXIT DW AU2 ; Time & date for MS-DOS 2.0 PAGE 60,132 INCLUDE IODEF.ASM IO GROUP CODE,INITSEG,LASTSEG INITSEG SEGMENT BYTE PUBLIC 'IOSYS' ASSUME CS:IO, DS:IO ; Initialize time-of-day clock. MOV SI,OFFSET IO:STCTAB MOV CX,4 ;Initialize 4 registers CLD INITSTC: LODSB OUT STCCOM,AL ;Select register to initialize LODSB OUT STCDATA,AL LODSB OUT STCDATA,AL LOOP INITSTC INITSEG ENDS LASTSEG SEGMENT BYTE PUBLIC 'IOSYS' 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 LASTSEG ENDS CODE SEGMENT BYTE PUBLIC 'IOSYS' ASSUME CS:IO, DS:IO PUBLIC TIMTBL EXTRN EXIT:NEAR, CMDERR:NEAR, BUS$EXIT:NEAR TIMTBL: DW EXIT DW EXIT DW EXIT DW CMDERR DW TIM$READ DW BUS$EXIT DW EXIT DW EXIT DW TIM$WRIT DW TIM$WRIT TIM$READ: MOV AL,0A7H ;Save counters 1,2,3 OUT STCCOM,AL MOV AL,0E0H ;Enable data pointer sequencing OUT STCCOM,AL MOV AL,19H ;Select hold 1 / hold cycle OUT STCCOM,AL CALL STCTIME ;Get seconds & 1/100's XCHG AX,DX  CALL STCTIME ;Get hours & minutes XCHG AX,CX IN AL,STCDATA MOV AH,AL IN AL,STCDATA XCHG AL,AH ;Count of days CALL POINTSTAT STOSW MOV AX,CX STOSW MOV AX,DX STOSW JMP EXIT STCTIME: CALL STCBYTE MOV CL,AH STCBYTE: IN AL,STCDATA MOV AH,AL SHR AH,1 SHR AH,1 SHR AH,1 SHR AH,1 AND AL,0FH ;Unpack BCD digits AAD ;Convert to binary MOV AH,AL MOV AL,CL RET TIM$WRIT: MOV DX,ES:[DI] ;Put date in DX MOV AL,0BH ;Select Counter 3 load register OUT STCCOM,AL XCHG AX,DX OUT STCDATA,AL MOV AL,AH OUT STCDATA,AL MOV AL,44H ;Load counter 3 OUT STCCOM,AL CALL LOAD0 ;Put 0 into load registers to condition timer MOV AL,43H ;Load counters 1 & 2 OUT STCCOM,AL MOV CX,ES:[DI+2] MOV DX,ES:[DI+4] CALL LOAD MOV AL,43H OUT STCCOM,AL ;Load counters 1&2 CALL LOAD0 MOV AL,27H ;Arm counters 1,2,3 OUT STCCOM,AL CALL POINTSTAT JMP EXIT 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,AL ;Select a load register MOV AL,DL CALL OUTBCD MOV AL,DH OUTBCD: AAM ;Convert binary to unpacked BCD SHL AH,1 SHL AH,1 SHL AH,1 SHL AH,1 OR AL,AH ;Packed BCD OUT STCDATA,AL RET POINTSTAT: PUSH AX MOV AL,1FH ;Point to status register OUT STCCOM,AL ; so power-off glitches won't hurt  POP AX RET CODE ENDS END FSET IO:QUEUE QUEUE DB QSIZE DUP(?) ENDQ LABEL BYTE ; ************ Console Output ***3 ; Hard disk I/O for MS-DOS 2.0 PAGE 60,132 INCLUDE IODEF.ASM IO GROUP CODE CODE SEGMENT BYTE PUBLIC 'IOSYS' ASSUME CS:IO, DS:IO ;---------------------------------------- IF INSTALL HDSKDEV: ;Header for hard disk DD -1 DW 2000H DW STRATEGY DW HDSK$IN DB ? ELSE PUBLIC HDSKTBL EXTRN EXIT:NEAR, CMDERR:NEAR, BUS$EXIT:NEAR, PTRSAV:DWORD ENDIF ;----------------------------------------- HDSKTBL: DW HDSK$INIT DW HARDCHG DW GET$HBPB DW CMDERR DW HARDREAD DW BUS$EXIT DW EXIT DW EXIT DW HARDWRITE DW HARDWRITE ;************************************************************* DIRENT EQU 96 ALLOCSIZ EQU 4 FATSIZ EQU 6 IF IMI NHEADS EQU 6 ; Number of heads NSECT EQU 8 ; Number of sectors per track NTRACKS EQU 306 ; Number of cylinders LOWCURTRK EQU 0 ; First track of low write current PRECOMTRK EQU 256 ; First track to set precomp bit ENDIF IF SCRIBE NHEADS EQU 4 ; Number of heads NSECT EQU 8 ; Number of sectors per track NTRACKS EQU 480 ; Number of cylinders LOWCURTRK EQU 0 ; First track of low write current PRECOMTRK EQU 0 ; First track to set precomp bit ENDIF RESETHDC EQU 54H STARTHDC EQU 55H HARDRDOP EQU 0 HARDWROP EQU 1 RETRY EQU 3 ; # of times to try disk command TIMEOUT EQU 10 ; 0.2 sec/loop--set 2 seconds for 10 MHZ CPU HDCPARAM: HDIR DB 0 ; Direction HSTEP DW 1 ; Amount to step HDRIVE DB 0DCH ; Drive/head select DMAAD DW 0 ; DMA address DMAHI DB 0 ARG1: HCYL DW -1 ; Current cylinder HHEAD DB 0 ; Current head HSECT DB 0 ; Current sector OPCODE DB 0 ; Read/write code HSTAT DB 0 ; Return status IF INSTALL NEXTAD DW HDCPARAM ELSE NEXTAD DW HDCPARAM+10H*BIOSSEG ENDIF NEXTADHI DB 0 ;--------------------------------------------- IF INSTALL PTRSAV DD 0 STRATP PROC FAR STRATEGY: MOV WORD PTR CS:[PTRSAV],BX MOV WORD PTR CS:[PTRSAV+2],ES RET STRATP ENDP HDSK$IN: PUSH SI MOV SI,OFFSET IO:HDSKTBL DISPATCH PROC FAR ENTRY: PUSH AX PUSH CX PUSH DX PUSH DI PUSH BP PUSH DS PUSH ES PUSH BX LDS BX,CS:[PTRSAV] ;GET POINTER TO I/O PACKET  MOV AL,[BX.UNIT] ;AL = UNIT CODE MOV AH,[BX.MEDIA] ;AH = MEDIA DESCRIP MOV CX,[BX.COUNT] ;CX = COUNT MOV DX,[BX.START] ;DX = START SECTOR XCHG DI,AX MOV AL,[BX.CMD] XOR AH,AH ADD SI,AX ADD SI,AX CMP AL,11 JA CMDERR XCHG AX,DI LES DI,[BX.TRANS] PUSH CS POP DS CALL [SI] ;GO DO COMMAND LDS BX,CS:[PTRSAV] MOV [BX.STATUS],AX ;MARK OPERATION COMPLETE SUB [BX.COUNT],CX ;Subtract amount transfered POP BX POP ES POP DS POP BP POP DI POP DX POP CX POP AX  POP SI RET ;RESTORE REGS AND RETURN DISPATCH ENDP ; Standard return types EXIT: XOR CX,CX ;Transfer complete  MOV AH,00000001B ;All done RET BUS$EXIT: ;DEVICE BUSY EXIT MOV AH,00000011B RET CMDERR: MOV AL,3 ;UNKNOWN COMMAND ERROR MOV AH,10000001B ;MARK ERROR RETURN RET ENDIF ;--------------------------------------- HARDCHG: LDS BX,[PTRSAV] MOV BYTE PTR [BX.TRANS],1 ;Disk not changed JMP EXIT HARDREAD: MOV OPCODE,HARDRDOP JMP SHORT HARDIO  HARDWRITE: MOV OPCODE,HARDWROP HARDIO: PUSH DS XOR SI,SI MOV BP,[NEXTAD] MOV AL,[NEXTADHI] MOV DS,SI MOV WORD4  PTR [SI+50H],BP MOV BYTE PTR [SI+52H],AL OUT RESETHDC,AL ; Reset hard disk controller POP DS MOV AX,ES SHL AX,1 RCL SI,1 SHL AX,1 RCL SI,1 SHL AX,1 RCL SI,1 SHL AX,1 RCL SI,1 ADD AX,DI MOV DMAAD,AX XCHG AX,SI ADC AL,0 MOV DMAHI,AL CMP HCYL,-1 ; Is current track invalid? JNZ COMPPOS CALL RESTORE ; Home disk head COMPPOS: PUSH DX MOV SI,NSECT ; Sector/track on hard disk XCHG AX,DX XOR DX,DX DIV SI ; AX=track, DX=sector INC DX ; Sector numbers start with 1 MOV HSECT,DL MOV SI,NHEADS XOR DX,DX DIV SI ; AX=cylinder, DX=head MOV HHEAD,DL SHL DL,1 SHL DL,1 NOT DL  AND DL,9CH CMP AX,PRECOMTRK JB SAVHEAD1 OR DL,80H ; Turn on precomp SAVHEAD1: CMP AX,LOWCURTRK ; Need low write current? JAE SAVHEAD OR DL,40H ; Turn off low write current SAVHEAD: MOV HDRIVE,DL ; Drive/head select byte MOV DX,AX XCHG HCYL,AX ; Set current cyl, get previous SUB DX,AX ; Amount to move MOV AL,0 ; Assume movement IN JAE HAVSTEP NEG DX ; Get absolute value MOV AL,10H ; Set movement OUT HAVSTEP: MOV HDIR,AL MOV HSTEP,DX POP DX ; BX,CX,DX have orignal command parameters ; All set for hard disk operation! HARDREADWRITE: MOV AH,RETRY ; Retry count HCOM: CALL HDCCOM  JNZ NOTNEXT ; If not successful, don't bump to next sector ADD DMAAD,1024 ADC DMAHI,0 INC DX MOV AL,HSECT INC AL CMP AL,NSECT+1 ; Stay on this track? MOV HSECT,AL LOOPNZ HARDREADWRITE JCXZ OKRET JMP COMPPOS ; Re-compute everything  OKRET: MOV AH,1 ;No error RET NOTNEXT: CMP AL,1 ; Is drive not ready? JBE HARDERR ; Don't retry if not ready or time out DEC AH JNZ HCOM ; Hard disk error on hard disk. AL has the error code. Convert disk ; error code to MSDOS 2.0 error code HARDERR: MOV HCYL,-1 ; Force restore next time CMP AL,10 ; Is it a reasonable error code? JB NEXT1 MOV AL,0 ; General disk failure NEXT1: MOV BX,OFFSET IO:ERRTAB ; Set DOS error table XLAT MOV AH,81H ; ERROR RET ; CX = number of sectors to go ERRTAB: DB 12 ; General failure DB 2 ; Drive not ready DB 12 DB 12 DB 8 ; Sector not found DB 8 ; Data not found DB 12 ; Data overrun DB 4 ; Data CRC error DB 10 ; Write fault DB 4 ; Header CRC error ;Restore head on hard disk. RESTORE: MOV ARG1+1,30 ; 3 ms step time, no head settle delay MOV AX,7+100H*4 ; 1024 byte sector, LOAD CONSTANTS command XCHG AX,ARG1+3 ; Previous opcode in AH MOV BL,1 CALL QUICKCOM ; Execute command JNZ EXITREST ; Abort if controller failure MOV ARG1+1,0 ; Set to fast step (after restore) MOV HSTEP,0FFFH ; Maximum number of steps  MOV HDIR,10H ; Step out CALL HDCCOM ; Restore and set fast seek MOV HCYL,0 ; Now on track zero EXITREST: MOV OPCODE,AH RET HDCCOM: MOV BL,TIMEOUT QUICKCOM: PUSH CX XOR CX,CX MOV HSTAT,0 OUT STARTHDC,AL HWAIT: MOV AL,HSTAT OR AL,AL LOOPZ HWAIT ; Try for 2 seconds JNZ HRET DEC BL JNZ HWAIT HRET: POP CX MOV HSTEP,0 CMP AL,-1 RET GET$HBPB: ; Set up BPB for Hard disk controller. Real simple isn't it? MOV SI,OFFSET IO:HARDDRIVE ; Hard disk Parm table SETBPB: LDS BX,[PTRSAV] MOV [BX.MEDIA],1 ;One hard disk MOV [BX.COUNT],SI MOV [BX.COUNT+2],CS JMP EXIT ; ***********5 **************************************************************** HINITTAB: DW HARDDRIVE HARDDRIVE: DW 1024 ; Sector size DB ALLOCSIZ ; Allocation unit DW 1 ; Reserved sectors DB 2 DW DIRENT ; Directory entries DW NSECT*NHEADS*NTRACKS DB 1 ; Media descriptor DW FATSIZ ; Number of sectors for 1 Fat BREAK LABEL BYTE ; Break address ;************************************************************** ; Code below this point is thrown away for installable versions HDSK$INIT:  IF INSTALL MOV AX,CS MOV BX,AX MOV CL,4 SHL AX,CL ROL BX,CL AND BL,0FH ADD [NEXTAD],AX ADC [NEXTADHI],BL LDS BX,[PTRSAV] MOV WORD PTR [BX.TRANS],OFFSET IO:BREAK MOV WORD PTR [BX.TRANS+2],CS PUSH CS POP DS ENDIF MOV SI,OFFSET IO:HINITTAB JMP SETBPB CODE ENDS END 8~}<u/~U@~;UBuvqL~}@~Uv2 u~E@~U";Vr~U6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L