IMD 1.17: 17/01/2010 8:18:44 cpm 2.2 california computer systems distribution diskette  >@:JG!(!Nx@(+G:Qo~2D!+Hx4> 0400 {23x4>0#3w40+0 |B{ :DO:JG4>] \/X/RLOCBIOS COPYRIGHT (C) 1979, DIGITAL RESEARCH ,_͌,> ͒,> Ò,> Ò,͘,~#͌,ì, _23<,233,,,,3,,3,,, -!32:32a{_:3ʖ-:3>Ľ,3,ʖ-:3=233,–-,!B0!36#53,ʖ-:3Ľ,!,ͬ,-ʧ--Â/-- ,)-!,F#xʺ-~0-wë-w!,", !3~6ͽ,3,:3ý,(/!4/#-͘,*,~ ".".͌,#.>?͌,͘,-Â/ .=_.:;<> O.o$>!3Y.23*,O.",ʉ.@G:ʐ.:3wÖ.x23p0.ʹ.#*©.6?ë.w˜.0..ï.#6 ¹...0..#*.6?.w.0...#6 .#6.", #~? / /xDIR ERA TYPESAVEREN USERz!/y3O/#>͌,9---23^. .:3¥2./!/_~#fow01]11222!v",!,/ç,READ ERROR/ç,NO FILE^.:3 .!3 ~ 30#0 .Wx .x . . .G 0~ .# 30x~#B0!Y.~ɯ23:3=!3ý,:3=!3:3ý,^.T0!3~ 0 6?#ˆ0,/1:3`O> K01{0͘,-A͒,>:͒,0͢,>:͒,͢,xK0 00> K0 1> ͒,x 1 0͢,0-1,Ø0Æ3^. B1R1ͧ,9-!,5‚/#~Y‚/#",T03,`.~2323\!3!B0!,~>3 >3#03~O3#C3x2͘,--13)-ͽ,Â/f0 .z3ͧ,Æ3BAD LOADCOMf0^.:3 !3 .Â/$$$ SUBz44444"C7{2A!"E79"71A72A2A!tAy)K!G4_^#V*C7B656BB666656~@@E@@@@@@@@@@@A AA,9AA&A-AAAGAMA@SA77A!44!4ô4!4ô4!44Bdos Err On : $Bad Sector$Select$File R/O$5:B7A24455!7~6 B45O͐5  :7E5B BB5 B27>: 7b5#5 B: 7By! 74 5~yy55 6y5Ґ5^H5@Oy H5 H5: 7–5ͬ5 B B#H55: 7! 7 H5ù5 H5 H5 $O͐55: 72 7*C7N#4 6 66x5: 72 7p6&6x5~+é67652 75H6! 7>w5_6: 7! 755ͤ5N6k6ͱ55¦6ͱ5xʊ6#N5x6: 75! 72 7ͤ5! 75™65#wO5~x½65p H557B7y<6<B BBʑA B7:7!qMD5#52E7>7! 4^#V w#P7:B7OB|^#V#"A##"A##"A##"A!AO7*A!AO7*A|!A6ʝ76>B*Aw#w*Aw#w'Bû7*B! 4J7*A8"A"A!AN#F*A^#V*A~#foyx7*A{_zW+7*A8yx8#7*ADMB*As#r*As#ryOxG*A0BMD!B!AN:A E8G>O:A \8S8*C7 :Aq8n& ^#V>8O^8 "A*A}:A*A)=8"A:AO:Ao"A*C7 *C7!ͮ8~2A~2Aͦ8:A2Aͮ8:A8O:Aw:Aw |g}o8*A# 8 )9:B7O!9yoxg*A:B7O8}!AN#F 9"A*A#*As#r^9 ~!4J79! 4J7*A:Ao$*C7~i96i9w*A*A{#z9r+s{ozg*A*A͕98*A*A 99,9w͜99͸799Ͳ7!A9!AN#F$B*A*AO7!A~#::A7:#~$:=2E7k:͌9::A7:A/GyO>2A!Aq*C7"A9͡7:9ʔ;*AJ;9Ҕ;^9:AOyʃ;?|;x |; s;-;|;N;-;# S;:A2E7!A~Яw9>7T9 ;9D9^96k:9-;ä;PYy; 5:;*A{z;BK5:;;ڋ<>*C7w~#+w#w+ɯ2E72A2A9i9;9^9 *C7 :A<~2A2A>2Aͻ8:A!A==Z=2A:E7=w8̈́8=͊87Ͳ787>2A>2AT9*C7G9ͻ8:A7w8̈́8n>>82A;>O ^8DM;;}H>>7"A*C7 :A:Ad>d9sl>O s#r:E7͊8:A==»>y==»>*AWw#>9*A"A7͸7*A:AG#š>"A97͸7:A!A>w4!,i9w?:A?8Z=!E7~>=2A682A*C7!!~~#~O~G#n,-.‹?! w! yG?!x?͢<.:E7<ʄ?! q!pQ<:E7<?. ʄ?$=.:E7<ʄ?7i96}2E7x9?=?>N! ~态O>G~G!~G} ;*C7!r#r#r9 @^9ͥ?_y#x#{@s+p+q-;?*C7 ͥ?!!q#p#w*A:B7O8Y7G7}*AMD 9"Aã::A!B7w!@>2A*C7~=2Au@:B72A~2AwE@:A7*C7w>"7!"A"A2B7!"A9!@r9Q@Q2A?>BhB3B;BNBNBNB;BËCCpCuCÅCíCîCFBC%%;B % ƿFBNBy mB!D͐C B͐C1 go"@!"B! Ew#~BOC:J–B!,"LͭCXB"L:BڷB:A<2A<2B|BڜB>22!B"!4"!"L:O,4@C>$>#>!> >#!%!D͐C!"B!y2@o))))!Dy!E_~2JmC,"IFD+:Fw#:JwBEXCEw#w w#wyy2A>2Cy2B n&i`"Lɗ2A͠CN B#yҔC!C͓C >2K DC´C_:K{C02H3w# CC 02H~3# CC:F2H04C02GFDC:B21O:A)D3CpD4 >8Dƈ*LXC*I|pDD!N>C21AD~2I!J~žD:@G7D w4C>қD>w>2F3~濱4:CCANNOT BOO 20k CP/M vers 2.2 gEcFEgEsFFgEF%FgEFDF(EE?     UEFEG?     MOVCPM COMP RLOCBIOSCOM PIP COM:SUBMIT COM 6ͤê INPUT FILE NOT PRESENT$0ͤê INVALID RELOCATION BASE$Sͤê BAD INPUT RECORD$oͤêMISSING FILE NAMECCBIOS ASMrstuvwxyz{|}~CCBIOS ASMtDISKDEF LIB1=!v"z!w6!u#+w+wz >Zx G}o|g"|! :m c p!"xp ~#c*|!:m XSUB COMED COM4 ASM COM@!"#$%&'(DDT COM&)*+,-$ͤêCANNOT CREATE OUTPUT FILE$ ^"&CPM COM=stuvwyz{=h xä SYNCRONIZATION ERROR$ {°~#o}oҼüÅ*zZ# :m m! ~ #* DM! x  wLOAD COM./STAT COM)012345SYSGEN COM6DUMP COM7&;&q#!N#F! D!_>0w#w1!`4~:60+4*"e@u READY FOR "SYSGEN" OR "SAVE 00 CPM00.COM"$*| \ CCSYSGENCOM 89CCSINIT COM :;DUMP ASM!<=>?@BIOS ASM`ABCDEFGHIJKL,COPYRIGHT (C) DIGITAL RESEARCH, 1979 1] ʑ?ʑ! __0 r))) O @|r}r.g))å{u INVCONSTRUCTING 32k CP/M vers 2.2$ê BAD HEX DIGIT$:] f:m f!lw#ʁ2\!CBIOS ASMEMNOPQRSTUDEBLOCK ASMPVWXYZ[\]^_STDBIOS ASMu`abcdefghijklmnCCBOOT ASMopqALID MEMORY SIZE$!$ʡ~/w/wʔ|g*"z|?¸>@G!>0w#w!4~:60+4~u!N#F! x, #  G:ʐ:wÖx2p0ʹ#*©6?ëw˜0ï#6 ¹.0#*6?w0#6 #6" _͌> ͒> Ò> Ò͘~#͌ì _2<2=qf^!~2>`~22\!!B!~> >#0~O#Cx2͘1)ͽÂf zͧÆBAD LO!p+q*2!p+q*22!p+q*!p+q*!p+q*!p+q*2!p+q* ͢ØÆ^ BRͧ9!5‚#~Y‚#"T<ÆALL (Y/N)?^ Tʧ͘!6!~ڇ#~?  xDIR ERA TYPESAVEREN USERz!yO#< Ty#O 321y_͸2y2ͽ: !2:2a{_:ʖ:>Ľʖ:=2–!B!6#5ʖ:ADCOMf^: ! Â$$$ SUB w4!Y~ʆ͌†t=ʆf ^ T 2o&)|+!<ͧ1͘A͌>>͌92^ :¥.!_~#fow]!v"!çREAD ERRORçNO FILE^:Ľ!ͬʧ )!F#xʺ~0wëw!" !~6ͽ:ý(!z"C {2!"E 9" 1A 22!ty)K!G_^#V*C   ~E ,>@:JG!(!Nx@(+G:Qo~2D!x4> 0400 {23x4>0#3w40+0 |{ :DO:JG4>] ÆNO SPACE^ :Ty!B*O=?_s#"^sG!~Ypsp2mÆÆf ͧ !8 ! ~ 3#0 Wx x   G ~ # 3x~#B!Y~ɯ2:=!ý:=!:ý^T!#͘*~ ""͌#>?͌͘ =_.:;<> Oo$>!Y2*O"ʉ@ &-AGMS  !!ô!ô!Bdos Err On : $Bad Sector$Select$File R/O$ :B A2 ! ~6\XRLOCBIOS COPYRIGHT (C) 1979, DIGITAL RESEARCH FILE EXISTS _: É: :ʉ=2)ͽÉ T!@k!}|q>ͦ!q:_  !p+q.*   !q*&!p+q*2~  6?#ˆ:`O> K{͘A͒>:͒͢>:͒͢xK > K > ͒x    O͐  : E  B 2 >: b # : y! 4 5~yy 5 6yS:2E !~Яw > T   D ^ 6k -äPYy 5*{zBK52*C ~=2u:B 2~2wE:A *C w>"O *!O *|!6ʝ 6>*w#w*w#w'û *! J * ""!N#F*^#V*~#foyx *{_zW+ *2>2T *C G ͻ : w ̈́ n> 2;O ^ DM;}H> "*C  ::dd slO s#r:E ͊ :==» Ґ ^H @Oy H  H : – ͬ   #H : !  H ù  H  H $O͐ : 2 *C N#  *C ^ O T  *C ~w D  -'   -@ ͦ ~^ *C  O x ! N!Fwy"**#"͕  : 2 Þ y<_WyOxOxG* ~V5dw^  :ʈ !""2B !" !r QQQâ~?ͦ ~?r Q *"C Q- Q͜QüQr Q$Q* yx # *DM*s#r*s#ryOxG*0MD!!N: E G>O: \ S *C  :q n& ^#V> O^ y==»*Ww# *" ͸ *:G#š" ͸ :!w4!i w: Z!E ~=26  x : 2 p & x ~+é 7 2 H ! >w _ : ! 5ͤ N k ͱ ¦ ͱ xʊ #Nxʋ>ڋ>*C w~#+w#w+ɯ2E 22 i  ^ *C :~w~͔͔# # NÎ N#Fyʝ*}|\#u* #DM*6# x±**s#r͡ *6#6  ^ >:A #~$=2E k͌ ):B  " *)*)Q;*"E :;:A  2A QÓQÜQ*C }/_|/*W}_*"}o|g":ʑ*C 6"*}:*)= ":O:o"*C  *C !ͮ ~2~2ͦ :2ͮ : O:w:w |g}o *#  2*C !!~~#~O~G#n,-.‹! w! yG!x͢.:E <ʄ! q!pQ:E <. ʄ$.:E <ʄ x : ! 2 ͤ ! 5™ #wO ~x½  p H    y< < ʑ  : !qMD # w ~>2!E 5T *C !"C  "C !w# F! w͌ x 2͢ *C  ~<wʃG:!ʎ: :/GyO>2!q*C " ͡  ʔ*J Ҕ^ :Oyʃ?|x | s-|N-# :ʑw:2E* *E }DQ>2 ) :B O! yoxg*:B O }!N#F "*#*s#r^  ~!J  ! J *:o$*C ~i 6i w* i 6}2E x N! ~态O>G~G!~G} *C !r#r#r ^ ͥ_y#x#{ 2E > ! ^#V w#P :B O|^#V#"##"##"##"!ì 4~ʶ ¬:<ʶ$ ʶïZͻ   x >2>2ͻ :!Z2:E w ̈́ ͊ Ͳ  > h3;NNN;ËpuÅíîF%%; % ƿFNy m!͐ ͐1 go"@!"B! w#@@BHH  !$$A"D@ "A" "BHA " !$ D B I $ !$$ H@BD D$!'_~2¹,"I*@*By2@>2CM+:Fw#:J2Gw#:QwO!"xʈ!.@ˆ!x@ʒ w#w w#w w4>қ>w>2F3~濱4:CCANNOT BOO 20k CP/M vers 2.2 gcgsg%HCOPYRIGHT (C) 1980 CALIFORNIA COMPUTER SYSTEMS. ALL RIGHTS RESERVED.1H*.+~/w/w¡$T!~# xl! zg~O:J–!"LͭX"L:Bڷ:A<2A<2B|ڜ>22!"!"!"L:O4@>$>#>!> ># HI DIA!$$$ $" "$D ! $"  $AB " BDD $$D!"DI$!$BH!"IB I$"D HD@$@B B HH II$@DI ABI$"$H$H"B"@yy2y=2y>>2:_P_!(Vy2B_V# # o<2g#7)ïÿ+0ü*5@!%!͐!"!y2@o))))!y!_~2Jm,"IF+:Fw#:JwBXw#w w#wyy2A>2Cy2B" " $"! @H !BI " I  $I$I$DI$ !I$@"$"$! $I$I I@ @@$$I! H*  $H@@A I $D!!$I"BI"I"@$BIIH$$$$BBI$@BI!"$$2>22}2y2h\*"*"}M<2!ʁ5\{2<22!6ʥ\@{: \z2Q*" H!D D1 go"@!"B !&w#YO!"Lv͊3"L:Bڮ:A<2Aʭ:J@­:Q= ʭ<2 n&i`"Lɗ2A͠N #yҔ!͓ >2K ´_:K{02H3w#  02H~3# :F2H04@I!  @((((A DI$@ A$@$$@H! "!$$" @B$!!!DH$$"H @*"B:2J:Ċ!w2*P%7*! =*:<2w# :=:2͋!w:M:v>22!"!"!["L!"2:2O4@ >$>#>!> >#!%!D!"úy2!o))))!y02GF:B21O:A)3p4 >8ƈ*LX*I|p!N>21A~2I!J~ž:@G7 &8&:oF!4!"Â!=S^#V:__!(V:o<2!#€>2K ̟‘_:K{2H03w$I$I"I B @ B@ H@$$DESTINATION IS R/O, DELETE (Y/N)?$**NOT DELETED**$$$$$$$NOT FOUND$COPYING -$REQUIRES CP/M 2.0 OR NEWER FOR OPERATION.$UNRECOGNI+  # ` h x? ? 00 FU COPYRIGHT (C) 1979, DIGITAL RESEARCH, PIP VERS 1.5$$$ SUB =.:,<> _[]INPIRDPTRUR1UR2RDROUTLPTUL1PRNLSTPTPUP1UP2PU#3w#3w#3w#­ 2H0~3#~3#~3#~3#:F2H0402GM:B21O:A3̓4 >-ƈ*   I $!HH$ "$BDA$"@ H    @UUU@ZED DESTINATION$CANNOT WRITE$INVALID PIP FORMAT$CANNOT READ$INVALID SEPARATOR$1 :2L> ̈́M9 UdsG?O???s?$G?(O?  :NTTYCRTUC1CONNULEOFDISK READ ERROR$DISK WRITE ERROR$VERIFY ERROR$NOT A CHARACTER SINK$READER STOPPING $NOT A CHARACTER SOURCE$LO1<:QG>?GyX*I|̓!N>ͨt>@ضwM21H~2I!J~±:@G7’ w4>Ү>w>2F UUUT@B@BHHI !$A H@221@:2!o6+6+6!6#6!6#6:G*o .!N6:^*M^!K6!6!6+6' :$ʤ]]:ʤ]]]:ʋ]]: ʋ]]]:ʓ]]: ʓ]]]:ʜ]]]:0ABORTED$BAD PARAMETER$INVALID USER NUMBER$RECORD TOO LONG$INVALID DIGIT$END OF FILE, CTL-Z?$CHECKSUM ERROR$CORRECT ERROR, TYPE R13~¼濱4:CCANNOT BOO 48k CP/M Vers 2.2 Ci;(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)::=2K  :ʤ\:ҷ\x'Ͳ:!\͢  :͈'! ʤ ]]]TNͯ#yH!Gɯ2!gzI/O ASGT ERROR !DRST ER %%ғ % ƿ͜ʤy ETURN OR CTL-Z$INVALID FORMAT$HEX$$$$NO DIRECTORY SPACE$NO FILE$COM$START NOT FOUND$QUIT NOT FOUND$CANNOT CLOSE DESTINATION FILERa p#p ?? ?0?4?< @(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE) :$: $͈Ͳ!N6' :!Cwͯ !6:^͢c!6{:/>!/H{ͯ :<26à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  2yʭ :yʗ ͯ *"*6:2x÷ *"!x4d !"/ !j}=2| !"*KM^'_ !z6:|!z1 **M:>!(:=2%> >>!F!5+N! ~2!4<2T>>!b}*bMͭz:b2!b6:<2é>!!p+q*2!p+q*22!p+q*!p+q*!p+q*!p+q*2!p+q*/H:_2:!q:A/>Z!/H8: 2::=O>m:W!Q} Hmd>9>!6:2*M!EŠ ::=HҮͯ !6:Ҿ:2 !6::/H͈;!6:> !/> :2!q: " *M n :c4 *M n :2!c:Q !c:2: !:cw>!n !5 Y : { !6!q "}*}DM͆ ' ͯ *"!z4 :e !"͆ !z6:|!z '? 2*H#"H!{6:{ր!Ң *{&`ҥ*`MͭҞ!`6!6> :é:(!q:!wO! ~2*& :w>!:!4!6>:N<2N!!p+q* !q*& *M *M !p+q*!!p+q*"!p+q*$!6  ^#V͎ڗO **~2*#"m2m͖ 2m!6m!6m!6 m2mHHͯ :^!w:<2:0}:@E}:!S!W6: z!]6:cm!c6:_z!_6l:!lwҙ  â :0O !q:O| :O| !6:]2l:o'2o:n'2n:m'2m*mMͣ *nMͣ *oMͣ :] :{4 2!{4m *":ڹ ͯ !z4I '2!"!q: !4>!S :S! :2*M> *N& N2 !p+q!6!6+6 !6: S: M!6g8:N2M*M8p!6!6!6>! !kp+q*j> >ڪ Þ !qp+q/ *pDM9: :M2r:N!r !:r *r& N!r4 !6:ͯ m!62m!62m!62m!62m'2:2:TҒ:2 ::,: HHҰͯ : 2ó:E:1:2v!q!*8!*6: >:   *}2D" * * *&"!q:UY: Y:ҩ: ʩ:_2ʘ:€!6<! ^#V͎ * :w*#" = = = = = ͯ  *M !6q  !6q  !6q  *& !ڕ*&P 6!4z!6!6#6#6!6*M8:ھ:*͇g2ê::¿::,͡A<2O>͔: :ͳ.!ws+p+q+p+q:w=2wN *s*u w*s#"s*u#"u' !"*M^7 !x6:!xھ **DM͆ !6*ME:2::Ҳ:<22ý: 2:} >ͯ :i:2:d*M:[ ͦ>ͦ!q:_  !p+q.*   !q*&!p+q*2:<2!ژ!6 >!]Ҥ; !6:Q::H: !6*M : !6!q:a/>z! *M8):[ͱ!N5!6ñ:5!6#6>!ڰ!6:<2O>/:!O!T *M͡H~K: !36'n::0:f9OY#9.3'ͳ.:020' 'ͳ'7 6'20O> ڒ:0:AO>Ҥ::A }}Hͬ!wͻO`idͻV[2O>2:!X!6:!& !sc*&P :w:·>!ұͯ :22:_!6=!6>'!E!4!p+q*0 !' !'6!36' :1/!aE*#">z?C9IͲÁ.!6> !ڇ*&' ~2 ʀ: y.*M¡!6[–ͱ!N5:2:2!4=:[¼ͱ4:!6:.2O8: :* ͇g!j>A+!s!"@͓1!"<**"͓n "Dn"":!Q2҂:=O!L NE!4 E E:/.*&L 6$L9k9.Xͯ *KM^020r+s+p+q*~$7*>*>H&>*#"*#"> 2:R͎:!6!6=2:ʙ!6:“H!4Q>!қ:=2á:2:Ҭ\>!ҿ:=2K:2K!:!:K\: \!p+q͈*:[ ͱ!N5!6:%:<2*6 * 6å!q!6> !d*&I :]>!4A>:<2O* :w:?†:X!Wғä:ڤ*MEÓ:ұ@@:O2Mc;!6#6>!)*&P ~"::H:H :020:121'ͳ':²ͯ !G6!"!"7 *M^n/ :a/:H!6:ͯ !&69Ž>!6-e!6ͻ2=2ʺ-é:>>"ͻ2:!!5ͻ2ͬ!\DM!  ::=H-\:N2O_og_{ozg^#V))) _{ozg^#V) d^#V|g}o n_{o!6!q!6?!:ҠgÐ!q*&*~!6:22: :]Hں:A2O>: 2ͯ :H:H"!6!4:_jYO jM*"S*" 3@bl*M1͓!""2*">!b!ͯ >!`0ͯ !q:E:24J!46*}a!44EJ *KM^'́:‚-:>>!p+q:,!6*DM9:<!6:z 2W!6D*&L :w:<2Ov*:>=zgO{ozgi`N#Fogo&og H ©=¨÷:S:QHI:N<22: H@"2Í202O> c!6Í202O> ڍ*&O*7 *M^͆ \͔!":͎H*#"ͧÝ/ :>͛9ͯ .*#":_!  *z& ~2y :yHڪ!z4>>*z& ~ !z4í!{q*v#"v͙dͧ*vv :{w:x<2xO>}|ͧ2% ͋*-"*$$$ SUBq:(=2(N *$*& w*$#"$*&#"&' !"N*M^7 !)6:!)ھ *N*DM͆ =2ʦ** w*#"*#"!p+q(+*DM*p*& 6:ep\:=W Extended Submit Vers 2.0Xsub Already Present$Requires CP/M Version 2.0 or later$:y*###ƒ# yk -!6]:ͧz2~e:~2O! 6*~& 6$>!~_z*~& w!~5Bx:yͧ*v+"v2*ʭ :*ʗ ͯ *N"P*6:2)÷ *N"N!) $@BA$! A "!$""ͧ!t6>!t%\= >!t6:t<2t=O! ~2u b:<2O>9b!60+~9b!60+4:uat:u_2u:uM  җ 4!~=ŐW!xʵ ~#èbx {~#o}où.xsubb!np+q*m2_!pp+q*o copyright(c) 1977, digital research $Error On Line $SUBNo 'SUB' File Present$Disk Write Error$Command Buffer Overflow$Commv ~_{ozg001 $$$$ SUBʉSͧ!v6!"v!|6:|Ҁ!x6 2}:} Hk:} h:}$6 2}$*}M3:}02}O> ͧ3!z ]xsub*"-!/"*"+!""1 M*!"́!"* (xsub active)$|*y ʥ*"*7*and Too Long$Parameter Error$Invalid Control Character$Directory Full$Cannot Close, Read/Only?$!9"!͇͊!p+q*6ͭ:}"!}5́ͭ́3*yM"h:}^a a2}O>Vͧ^:}!!!6 :2.t *r !up+q *tDM !wp+q*v !zp+q*y2x!|p+q*{2x!~p+q*}2x!p+q*!p+q*û :!I¬!: :H2 ҮX:h2iҐ:!ʍ:!:!H:!H,!"! 6#~ F+s#r!:* *& ~2!:<2 :!W> v :!X³ Z͎\ Ee ð :7/҃ E!76e ͕ :xƒ FILE NOT ACCESSIBLE$BAK$$$BAK$$$-(Y/N)?$NO MEMORY$BREAK "$" AT $1mM"m +!8s~!!6!6s, !6:xB!6OU2!SB!G6:҃!6:G҃*G& ~2!:G<2G!p+q*!p+q*2x!p+q*!6   >>! q* &!p+q*)ͷX:! X):i!h)9 e:!:h2jO>F L>!":i!jHҼ*"+M ~ ʼͲ!f6!h6!"- ͷ*&"K(Kڰ *KM N͔*K"KҌ :!Z ͎  ͢ : :!  'v!gq9m++s#r!9+s#r9";9;"^*mM 6*m+"o!o#s#r!6!f6!6:] :m H}- :\͢ґ Ä :!J $:2$͢ :=2:<2!*& ~2!ü*""I*M*o/!:"_ Qқ=e  b:!-®! 6:!#¿͇;J:!:!!6Lv:!:Jv: *#"͎:7 e !p+q*DM  =? ) !p+q.*DMF -L *9"`!"b!h6!j6!|6.!=\ -x ! 6F!f6:h2k!iҠ:i2k:j2h:k!hҶ9 æ:h2j!!6:j2he:! >"Ͳ*"M ~2!O :! *+":f *g&!lq:l $ !h4:l 1 !h6*lM :hB     !h55!mq:m :hO>H2ny} !m6 !o2d‘ 2dÝ:d=2d!\6:l2e±:d2eø:e=2eEU !M6 !""*o"$!h61m!6#1m!6?1m!6>1m!f6"&! 6R*I""ë :!M:H| ! 6>F ͛e: <2 O! Hqy d F : 2! 6*#s#r :!! 6:!B)! >w!"&*o"(R :!C:eR :!DKeX :!K\ͷX :!Lj^ :!Pš͎҇! 6!e:dʥ *eM \R :xʥ @ *dM \, :x \͕ :x - V :e _ :f w : !!6e*!M͛ /$^L:!@OL:! 2͑e:b:! L:h<2hb:! b:hO>!hw:! pX:! …!!6  6:n!oښ *mM !o4‚ !pq:p ڪ >:p :p H:p H!qq*qM͛  ^W :q@2q*qMW   !sp+q *M  *!M 1m! 6!6! 6: 2Ebͽ!e:d\::eH2 H҆ͽ:e2!:d2e:!2dN ͢ *o/ Ҧ Ͷn! 6!"&R! 6o$ Î Ç :!S0 $͢- :2"  =e !e:d*eM =e : =e =͕ !]6:x>- !"!76!6!6!66*dM  *dM !6:8!"&Ô""&*""&$mڸ*o"(**$"($"O26͛*"M :6w͢:6  N͒!">!"͎/Ҵ*+">>!": *#"*""*!".+",*$"**o".!",!36:3{.*FM8 *FM   Oy2F :FY5>>:!02HO> /!";u*)))*) *H& "PMaҎ:_:!q:ҥ*My:!p+q!'"!6>**ͪ{2**ͪ"*! ͪ":!!$:2*o/*!My:<2=O!s Hq**DMͷ! 6: e!"*""?k*&"?*?+M ~2A :h*`*;DM \u 2xʻ>!xҨ- *`*;6:82*`"`:<2w!"`9`h*`*;~2*`#"`!7q:*7M͒:7o$+͛ͪ*$M ~28Om:8 I͇͢u$oqo͛rP! 6!"&*22*,**"0M ~ H3*0"**+"*+">23:2/k!36,*+s#rx:3x*0"*: ! 6+s#ré! 6"DM!>))덑o|g =±^#V) ^#V|g}o _{ozgi`N#Fogo&o6:0O  ú!p+q:/(*DMͩ:  : I N* *DM:aO>!Һ x!: Hҏ *&"?(?:A ½8*#" ҽ*?M ~2AO *?"?ҕ!"*"*"^: 2B! :*eM !b+!s{!f!6:!b*b*^DM =ͅ N- *b"b:<2)f!"b!q9bڀ*$"(R͎ҔM͢ҡÔ($ҵ! 6R͇vͶ2!*!Mm$"*"M :!w͢:! “**"&*"+"(á*$#"&**#"(*"#""*$#"$*"+""*$+"$*#"!4qM*"*$: *(y"$DM}|C#~g_{_z#W H = LIB> ʡ* +" >¡! 6: <2 =O! N͒:  O͒: ! 6:h!o$O6F:B2 o(>&H6͛9!C6>!Ca R>:C<2C?! 6!"͇͢Ґq"*b*^:w*b#"b!q:6ڶZͅ ʱ- !66*6& :w:6<26!J6*b}:J<2Jm=? :x- e2!:! : /HH/Q:! @!!6 R!!6 :!KR$*& :!w:<2dn!:s+q*$";!>6 *#"*&DMyxC 1*+":4?w+"$""ͷR: —*$"("҈!X$$$$$$$LIB* ͸ ! 6 !h6!: 2 3* & 6 : <2 =O! N͒*dM  :sGsu n>!6:<2=O!ڊ͛Íq!!6 !!6 !6*!Ma2D*!M͒2!:D/!+w!6e2!͢!Eq!E:!:H:H!Fq: ;*dM .=\ -=ͨ ;: *eM =ͨ .M= -C!q:Y*M !q:a/>z!/H!q*:>/;oH*;#"(";:92=*=& *(M !::=2>/H:=<2=*(#"(æÀ:>*(+"(R:>!6    á 4êü /L9ASMPRNHEX1*" COPYRIGHT(C) 1978, DIGITAL RESEARCH   OʊQ>ÖH >2 2 û: B­>ôD> ¸!52 !"!N#~#A07O! ~*!) " ͸*"!!#^4!$wͯͯWƐ'@'ê>:ͪ!#^Ww*!{͚|͚}͚͚{!$~#͚͚> ͪ> ͪ?'  v:P@< !  PP27 ( *"  NZZ NCC POPEP~# …¡z!ͼ wʹ* ! w#" ! 8 !" ! zz_O4:  :6y{zA"*![N![ N#Fr+sq#p/>G=#w#w3#w#w!JSYMBOL TABLE OVERFLOW G*##~w*##~!4w_#~ ʸ A:4~~# ¼ > \ ?ʻ w# !ͼ ? !ͼ :  '<ͭ'<>V$>O$:Ğà\ÞØ`rÍÖ@2 0 0:x0_<2! wI2 2> 2 >2ɯ22 !~@_6^4#: w~$w: 0 q M x_BH!œ#¶ ¦{KÈCÈ<:JCR:  !6 s!:! G~#x=2> > ! >x6 #='G! ~ p( O*}O>4?:7w:#ĸ*"!͸* }w>ͪg( ʆ1 *_###s#r^#V`à 4 Wm ()*+,-/ABCDEHLMDBDIDSDWEIIFINORSPACIADCADDADIANAANDANICMACM!)ͼ !ͼ :5͡ :6:6͡ :7͡ :\ ʻ 24!dͮ 25ͮ 27ͮ 26!8 ( ʃ !Y 1 : A: A͋q: a{_2  2 - !ɯ2I:  ;*:  ͭͷ ͭ͋#  ɯ<:O=_Z!F!V#fjQ̓E!^#Vo&)~#FxGyѯ<àn8Y :7ʗ8 z !<ͼ CP/M ASSEMBLER - VER 2.0 NO SOURCE FILE PRESENT NO DIRECTORY SPACE SOURCE FILE NAME ERROR SOURCECCMPCPIDAADADDCRDCXENDEQUHLTINRINXJMPLDALXIMODMOVMVINOPNOTORAORGORIOUTPOPPSWRALRARRETRLCRRCRSTSBBSBISETSHLSHRSTASTCSUBSUIXORXRAX :7ʞ !z 8  !"2D2X2#! 8 !ͼ z{* ! !"!8 w![w#w#b!"!F#v2[>9q>9: '!2 >9 7:! 6 >2>2: 2 Qͭ:Ğ! :lj<͖<j<|<: !~ڢͅ6~44O! s#r!~ ڿ6ͅ^4!mw!wp!~ͅ!55N! N#fio&)^#fk FILE READ ERROR OUTPUT FILE WRITE ERROR CANNOT CLOSE FILES END OF ASSEMBLY G:7xʘ!#~ʄl͸Ä**!O {zʊRICALLENDMLDAXLHLDPCHLPUSHSHLDSPHLSTAXXCHGXTHLENDIFMACROTITLE  PF FP! ( 2/#  +6# *#"~!ͼ G:6QxJQS*!w#"! 1 !"!Y~G*##~w*##~<*}q!~ڬ6![^![^#fk"͎͘!G#*####*^#Vû!^*"* z'{ͅ>ɯo>g"k!m6ů{_zW5>)D*kOxGd !m?FDM!xGyOڂR{ozg!~4ʧͦ !6 ! **̈́**̈́\iͩ !w#H USE FACTOR !* "z{*"S 1:  1"" ͦ 1 |R >O U!" 1 1!|_!^#fk $8AP`ix͓Q͌Q!.ͷ6y#G͙Qà!2ͷQ͓͌Q!>ͷq eg͙Q:zJEË*>E2C!" """ :ʼ:*1 |R|ͦ0FIL: RÃO$*sy͏ , $  ͌ 9!z6 # L!zw͌j# X:z 0 ͘)sn55)=â|g}o=î--#zg{ozg{ozg{* "I !" :1 R O*UR X* G:xl :  *̩ : l x͖ *#"EH DH 0H ñññ81Ľ y0îH ñGîG  ñH ñ(Ľ yîH ñC–EQyQxQRQ** {zҷ*~#" <AOGƐ'@'OxƐ'@'ON#   R* } *" :¿::¿üX!C^#fk[@ :Œ:=ʌG!ʆF#H=N#Fy}80*z{¯#z+++ ¥ z#½# · 9!`͠ y9!rͷoÓ:: ;,!ɯ22=2l!"]!~H5_!m~0:ą:  *":  :‰:̅ԅ!^#:~ ! ^4! w͆ Æ *! 6z͖ {͖ 4>R>V>D >P >L >NîîĽ y0îîH ñG 1: :,; c*| } 8Oz8O!B N#N ¾SP.* |} !9":q!" 2  y=!z{w# % w!P͠ y͓}*w#"͌ @.@<!Eͷ~P =ʅVq”*qͦ1& O:lµ̅>2ly:_!w~!s!m~ùy !~=w_!m~ ͅ=COPYRIGHT (C) 1980, DIGITAL RESEARCH DDT VERS 2.2$10 !~=W!xe ~#Xbxʇ {z~#o}o҃Ľ y0G G t :):,.>C :|: Jü;r :R: ʼʋ!ʼR!ʼʋ>S@* ͡. ;ͣW!E# ¡ # ¬# ·@ʴʥzʖ=ʐ=|zJz?4)z z:|: |Ë  |*" ͩ !6="1 :  1}1:n:>BʋSSͦSSx!ͷ’P͌Q!ͷªP}QxQ!ͷ͓G@Q! ͷ y͓Gþ!ͷ ͓Q!ͷͰ>2lyPLnR>UX:l̅2l͓i.2_!fp+q*e2_2_!hp+q*g!jp+q*i!lp+q*k!np+q*m2_!pp+q*o O=!9 Ÿ!6q!2qC J R q!z z=naO $q$,! f  . ~ Ͷ ʻ .͓ =« f |« }w#Ä >2L͐ ! =« f }ʫ +"MD Å D  !  # DMʡڏ"=ʡͲ=ʡYPͲ1**!O~4#~#F#x~#s#r#w>͐ « f f  . ᯕo>g.)*)þ))>+><7"9.Yͯ * M^2Uâê ö  - Ð f  "J*"!"!"2O!" "]""!1!++""M>28!"9:] !í 1! _^! ^#V~ x+ >= = !~  . !   #x f L L ͓ͅ ҆ *" !6;,!Ù!;qz8O! !;,z;qyO! ͣͣW_͕qyO! ͣ͒qy ë «   Ͷ ͐ =« f xY |« }ҫ gA>S Ag}S S i |« }!w s#r:[ʔ  2|2\  !]w# ʫ .&  0 6 #& .K !e K w# ʫ : U 6 #K 6AW w#] !e~H#~E#~X :2:2ͳ:_³ͯ !6! @!!BH @@ABH B! "BHI$$BI$BI $ HI ͓ !" >- Ͷ Aګ ҫ _!7^#V~  \p Z z ů2[\͓͢ï +"_*~ #E گ ʫ ^#V. ï ~ CZMEIABDHSP!"M"+"!91*~!O~6=G#^#V#~O!b q!vz͒q.?*!9"8"͉Z*" +*'/7?v"*2:EI SPHLDI XCHGPCHLXTHLRE_!~ʦ ![4ç \͢¦ 2[ 7 >?  e͢!g"c> _͢a_!f~> 5*c~#"c 0 *}|́ "!́ ͐ !ʬ =« f kʫ j \͢F w# ͋ t ʫ : W& _& & O {D$HD$$ H B!$D$"$B$DA!ABI$H B$I $HI$H$! $I  ҫ ͐ =« f " ͓ ҫ ͐ ʻf " =ʻf "=« ý> 2͐ f "]=f =« *]}o"_  *]"x (#"!N#FW( *J>7Å*M|N+"M N:LHͅÅD Å >* *͓ b" . *"] !/~##ʁtT HLT CMC STC CMA DAA RAR RAL RRC RLC NOP CPI ORI XRI ANI SBI IN SUI OUT ACI ADI CALLJMP LDA STA LHLDSHLDMOV ADD ADC SUB SBB AN7   > >  ͢| } @ >. *_}o| , 0 ë ^#V#!Y ))))o P  `i"F & & w# & ͋ « t Y t Y GтWx ͢!o ~Z #N  *. *.  NEXT PC͐ =«$I$$A !A@$I$"!$H$I$I "! $A$  HHAA"I @BB $A"a. ~ #E }"]*a 6 *]}#|#*]E ͐ « f f f {zA|« W}d ͐ f f fZ*F#n!Is!^#V&&##&))::^#V#*^#V>+)x-8_A XRA ORA CMP INR DCR MVI LXI STAXINX DAD LDAXDCX RST PSW POP PUSHNZZ NCC POPEP M B C D E H L M A B D H SP PSW ??= M!Eq s#r#!V4 !V6# ,® >2Vñ m ͅ m ͅ m ͅ « Vʫ ! XN!~   $$$I$$H!!! BH" !I B  $$!BD! $!BI D@"!$I$$H"!I* +"8 .!2 ʞR̀* "4 4 = ͝* #" çR*6 DM+R*8 DM+R*: DM+R*< M!?  DM+;! p+q* i2 ! p+q* i2 ! p+q* i2 i2 !" p+q*! f!$ p+q*# i!& p+q*% i!5536: 128 Byte Record CapacityKilobyte Drive Capacity32 Byte Directory EntriesChecked Directory EntriesRecords/ ExtentR ADDRESS $BYTES READ:$INVALID HEX DIGIT$CHECK SUM ERROR $FIRST ADDRESS $LAST ADDRESS $BYTES READ $RECORDS WRITTEN $HEXCANNO$I$I$UUU$$A$ q=  ͝Kd*= ! ͸p!@ 6>!@ X*= }O!< *@ & w*= #"= !@ 4)!< 4\mad* }O!< :? w( p+q*' i2 !* p+q*) f!/ s+p+q+p+q:/ =2/ X*+ *- w*+ #"+ *- #"- 1* #" ͖r*   ~!" ! ͸ecords/ BlockSectors/ TrackReserved Tracks is Temp R/O Disk: d:=R/OSet Indicator: d:filename.typ $R/O $R/W $SYS $DIRDisk ST OPEN SOURCE$COMNO MORE DIRECTORY SPACE$CANNOT CLOSE FILE$*!9"!e !" !" \!""͊: ƒlR*4 DM+{R* DM+R 4 ͝*4 }¿= 4 ͝< N*4 #"4  å;*4 DM+: Y2×* " x20 º*   DM":0 Ad*   6!" Ç!" : !"6 "8 ": }2< !"4 "= ! tatus : DSK: d:DSK:User Status : USR:Iobyte Assign: =Bad DelimiterInvalid AssignmentBad Delimiter: Bytes Remaining On de"\\\͊: ²d\͝: )d;! q* &f  ! q> ! : A O3 Copyright (c) 1979, Digital Research????????????CON:RDR:PUN:LST:DEV:VAL:USR:DSK:TTY:CRT:BAT:UC1:TTY:PTR:UR1:UR2:TTY:PTPA 0O> :A 0:A AO>&R̀:A A H.2B !2 w:B !D s+q*C &͍:D _og_6Y: !2 6=21 á:1 : r+s#r==_HL"4 " >6 ͪS* "6 =23 :1 =21 v=O* #" Y8  ͝R/, Space: Invalid File Indicator** Too Many Files **File Not Found Size Recs Bytes Ext Acc65536 set to R/O Invalid: 0O! q: O: O! p+q* |O* }O! p+q*  f! p+q* DMB! p+q)R* DMB1B*:UP1:UP2:TTY:CRT:LPT:UL1:R/OR/WSYSDIRR/O R/W SYS DIR ** Aborted **Active User :Active Files: Drive Characteristics6@ COPYRIGHT (C) 1978, DIGITAL RESEARCH ERROR: $, LOAD ADDRESS $DISK READ$INVERTED LOAD ADDRESS$DISK WRITE$LOAD ADDRESS $ERROR{ozg^#V) _{ozgi`N#Fogo&og_{_z#W  Disk AssignmentWrong CP/M Version (Requires 2.0)!9"2!T OË!]6:\:] Hr3 Ë:\ʀË4- >!699 2¨ :!4: :2!6+6>! :O!9 DMi ͱ:!O!Y DMi :2vO!w 6,]!v6>!v*v&w ~һ*vM !v4˜8AO͐:͐ͱ*##N!ͽ"* N#F*͠")6> !).*)&*)*)&*) w:)<2)*)) >w#6*)) w#6*)!) w#6*)%) w#6*)) N#F*)) q#p*)%)!b/~,H~:H~*H~.H~>H~<H~=H*]& 6!]4T!]4!cq*a&Y :cw!a4͠Q" 8AO͐jͱͷDM͏ m  Z"l"!6>ʥ *}҆ *M ͱ*}x O͐} W͇͐ /ҋͺ *2!"q*"&L ͐ ͐ ͐!$p+q*#~*#N͐*##"#÷!&p+q͠*%DMͱ O O!(q*(&:2͠!4 F :® )!6>!ګ ͠:O!9 DMi 8ͱ!6> !ڤ Å :2>!H% - *DM ͱͷDM  ͱ* N#F 9ͱ * ^#V))DM Tͱ* ~!)6!)6>!)=:)!)w=*)&*)~2):!gr+s+p+q!h6>fr*d*f!is*d́"dPY! "f>!h#~Haͫo!h6:i0O͐!mr+s+p+q*lͱ !+s#r!+s#r#4D ͠:\ʹ :\=Oͳͩ !6!)6l :) :)=2) :] & !"}2\!h6?!L!*p+q*)O2'!,p+q*+O2'O2'O!.p+q*-LRRLR\Lk ä  ͐:!O!Y DMi w !4C F :¿ >F : F :=229:Y= ;>9*&Y DMDM oͱ*DM ͱ*N#F ͱ * N#F ͱ͠!p+q͠*DM':͐ͫZ"!6> *} *M)*)& *):)2):):*)!) *)) s, >X\:)“>!d!")>!)d!"TZs#r*lڶ*l+s#r*jN#F+q#pÌ!nq!"o"q}2uo&"s* s:n*sDM2u:uqosj6?\:'C:'ƀo&")!)6!"):)/)HҘ]!)6> !)ڎ*)&*)*)&*) y!)6 Ä:) R" O!/q*/& L!1p+q*0#L~*##N!ͽ͞"T!Vq*VMͳ!Xp+q!W* >Wr#MͲ!_ =2 I>!6:=28 :2:2 :!!29:Y T >:Y,e \>Ì !p+q*~:ʉ *N͐*!+s#r#4 !s+p+q!6!66:!ڄ !6!6>!r *&**&Y i !6!4+4A :} :!)!")*++!)a*)) ^#V")]*)")*)) ^#V")]!)6> !)T*)&*)~2)*)&*)~2)O;*)) ^#V"*s"s*o͊O !v6>!vQ*v&w 6`i+46)A*:'ʓ:'O!) ~2vʍ:2):)<2)M*)#")/:)ҩ*)+")`*")#"]!*)!/H!")!"]*)) *)s#r!p+q!`6>!`6*`&*^*`&Y />!`4 >*]& ~ O!]49!a6:a*]& ~2bO>z*bM >#"o :͐!p+q!'"!6> **{2*́"PY! ">!+~H !6:0O͐à k͐ )*)) *)) N#Fq#p*)) *)s#r*)#")!)6 J:)!)J!)6 :)<2)*)")҈q:tw͠ͱ! ON , THEN TYPE RETURNPERMANENT ERROR, TYPE RETURN TO IGNOREFUNCTION COMPLETEINVALID DRIVE NAME (USE A, B, C, OR D)NO SOURC-:YS:Z Hҧ!6> 2)½>!)6> !)*)&*)>2) :) .͐*)M͐:)<2):)!4f!^!*FNͷyj*DMͿ2: K!͚u c͊<2:\_/:)j*"1!u͚"))ҍ*)) ^#V")]͠.*)DM\ -°!\6:\ͣ:ͱ*}DM'ͫ*)%) N#F'ͫ*)E FILE ON DISKSOURCE FILE INCOMPLETE!?]99:Y=/9&ͩ c,Hͩ 9 EHͺ i`N#Fog_og_ogD:] \<œ!x͕c2|\ ¢! DMͿ\õ!͕c!͕u AnA2Aͦ͊!!) N#F'k͐ͫ*)) N#FͫR͐/͐ *) ~IO͐NW͐ͫ8AO͐:͐ *) ~2)t(͐:)҃)!9"1W͜Q>2!͢QG}DrYQ|͏}͏#> ex͏#r* _> e> eM!>))덑o|gҘ =†DM!>))ҭ =¥~ ³^#V) ½^#V|g}o _{ozgi`N#Fogo&og_{_z#W͚u c͊2!?͚!͕u cA7nA2Aͦ!͕u c͊!6͚>ͦ͊!Q͕SYSGEN VER ͐*)#")Ã& \!"))\Ұ*)")]͠*)M! ^#V *) >*) w *) >*) w *) >*)xCOPYRIGHT (C) 1978, DIGITAL RESEARCH  o&)))))))a{ ҉0Ë7e}} :³ʳ7_<2!~ɯ2|\\FILE DUMP VERSION 1.4$ NO INPUT FI2.0SOURCE DRIVE NAME (OR RETURN TO SKIP)SOURCE ON , THEN TYPE RETURNDESTINATION DRIVE NAME (OR RETURN TO REBOOT)DESTINATION w *) >*) w.*)DM\ -+!\6uͱ:)O! DMͱ*)#")Ù*))))))"):m w>.Yn __> ̓> ̓͊~̓#ÚO****!*$*'! ">2!4:(wNͯ>2 LE PRESENT ON DISK$!Y , <    *$A!6 # T!w $r# *`: 0 *4 >ʍƈ_:W1zŸ4{2 !P:4:C:1 v> > _~# CCS SYST ***WARNING: POSSIBLE LOST DATA*** !! DISK I/O ERROR ON <: G27 2G4> 204023!"!"1m> >0G@G42H12I! {!Dͥ_2A**2@!ͥ0BB2!mͥ_DhU<2A!{k2Bx!*A*! ~ ʰxkb))))_y‘BK{ͅ*!66!"80*{#z+++ #EM GENERATION PROGRAM VERSION 1.0 COPYRIGHT 1980 CALIFORNIA COMPUTER SYSTEMS INSUFFICIENT MEMORY SPACE - NEED 24K SOURC>24>>=0!"ͧý DRIVE NOT READY (TYPE CR WHEN READY).:024T02 „03w#3w#3w#3w#kͥ0}}2C!Xͥ_2GYµ!.{ڠ2Kx:G Y!Q 0N>M2K:A=x@2gGhy2=^#V#">^#V:C<#=1> >0G G4212!#"!!yͧ22_GA11::ڷ!ͧ½!"! "`¨":!E DRIVE: DESTINATION DRIVE: SOURCE ON , THEN TYPE RETURNDESTINATION T b> ¶ 20~3#~3#~3#~3#T > n03_#3_#3_#3_#T >:O:S~<w:Kw:B<,=,3:=12%>2L#m>20#:%:L:0:C:C203w#3w#T<y@>@O2:1y2SXK4:21O:n3K!1z:)=zE:0O:?G~ x™:G:Lʺ>>4:B<*:=X:%<,2C2B<2A:Gõ!{U0402;!V!"! "͍¨":!b:<;iG:ix2:G!:Q!#Q:@_+~<2**}|!   F#~# :gG3h*> DM!91m>0{3 z3444E02;d!!:@O 7 o4!D~͖ 579, PACIFIC GROVE ; CALIFORNIA, 93950 ; ORG 100H BDOS EQU 0005H ;DOS ENTRY POINT CONS EQU 1 ;READ CONSOLE TYPEF EQU 2 ;JMP FINIS ;TO RETURN ; OPENOK: ;OPEN OPERATION OK, SET BUFFER INDEX TO END MVI A,80H STA IBP ;SET BUFFER POINTER TO 80H ;MPN 2N N 6N# #NNNNNN NSEEKINIT BRC EQU FCB+15 ;FILE'S RECORD COUNT (0 TO 128) FCBCR EQU FCB+32 ;CURRENT (NEXT) RECORD NUMBER (0 TO 127) FCBLN EQU FCB+33 ;FCB#{͎Ɛ'@'_{x :H4:C:I12A v ʳ*O>y0?  ؀GO TYPE FUNCTION PRINTF EQU 9 ;BUFFER PRINT ENTRY BRKF EQU 11 ;BREAK KEY FUNCTION (TRUE IF CHAR READY) OPENF EQU 15 ;FILE OPEN  HL CONTAINS NEXT ADDRESS TO PRINT LXI H,0 ;START WITH 0000 ; GLOOP: PUSH H ;SAVE LINE POSITION CALL GNB POP H ;RECALL ERROR: DRIVE ; SIDE ; TRACK ; SECTOR ; STATUS-  LENGTH ; ; SET UP STACK LXI H,0 DAD SP ; ENTRY STACK POINTER IN HL FROM THE CCP SHLD OLDSP ; SET SP TO LOCAL STACK ARxGy#~#ͅ~ ͖# CCS DISK FORMATTER PROGRAM V2.0 WHICH DRIVE (A-D)? IS IT A MINI (Y/N)? SINGLE OR DOUBLE DEREADF EQU 20 ;READ FUNCTION ; FCB EQU 5CH ;FILE CONTROL BLOCK ADDRESS BUFF EQU 80H ;INPUT DISK BUFFER ADDRESS ; ; NON GRAPH LINE POSITION JC FINIS ;CARRY SET BY GNB IF END FILE MOV B,A ; PRINT HEX VALUES ; CHECK FOR LINE FOLD MOV A,L ANI 0FHEA (RESTORED AT FINIS) LXI SP,STKTOP ; READ AND PRINT SUCCESSIVE BUFFERS CALL SETUP ;SET UP INPUT FILE CPI 255 ;255 IF FINSITY (S/D)? SECTOR SIZE (0-3)? TRACK NUMBER (0-4C OR *)? IS THE DISKETTE MOUNTED (Y/N)? SINGLE OR DOUBLE SIDED (0 OR 1)? BIC CHARACTERS CR EQU 0DH ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED ; ; FILE CONTROL BLOCK DEFINITIONS FCBDN EQU FCB+0 ;DISK NA; FILE DUMP PROGRAM, READS AN INPUT FILE AND PRINTS IN HEX ; ; COPYRIGHT (C) 1975, 1976, 1977, 1978 ; DIGITAL RESEARCH ; BOX ;CHECK LOW 4 BITS JNZ NONUM ; PRINT LINE NUMBER CALL CRLF ; ; CHECK FOR BREAK KEY CALL BREAK ; ACCUM LSB = 1 IF CHARALE NOT PRESENT JNZ OPENOK ;SKIP IF OPEN IS OK ; ; FILE NOT THERE, GIVE ERROR MESSAGE AND RETURN LXI D,OPNMSG CALL ERR AD TRACK OR SECTOR SIZE/DENSITY SELECTION: NUMBER OF TRACKS (23, 28, OR 46)?   |0MME FCBFN EQU FCB+1 ;FILE NAME FCBFT EQU FCB+9 ;DISK FILE TYPE (3 CHARACTERS) FCBRL EQU FCB+12 ;FILE'S CURRENT REEL NUMBER FC CTER READY RRC ;INTO CARRY JC FINIS ;DON'T PRINT ANY MORE ; MOV A,H CALL PHEX MOV A,L CALL PHEX NONUM: INX H ;T,BUFF DAD D ; ABSOLUTE CHARACTER ADDRESS IS IN HL MOV A,M ; BYTE IS IN THE ACCUMULATOR ORA A ;RESET CARRY BIT RET ; ENDING WITH "$" MVI C,PRINTF ;PRINT BUFFER FUNCTION CALL BDOS RET ; ; GNB: ;GET NEXT BYTE LDA IBP CPI 80H JNZ G0  MVI C,TYPEF MOV E,A CALL BDOS POP B! POP D! POP H; RESTORED RET ; CRLF: MVI A,CR CALL PCHAR MVI A,LF CALL PC ; STACK AREA DS 64 ;RESERVE 32 LEVEL STACK STKTOP: ; END O NEXT LINE NUMBER MVI A,' ' CALL PCHAR MOV A,B CALL PHEX JMP GLOOP ; FINIS: ; END OF DUMP, RETURN TO CCP ; (NOTE SETUP: ;SET UP FILE ; OPEN THE FILE FOR INPUT XRA A ;ZERO TO ACCUM STA FCBCR ;CLEAR CURRENT RECORD ; LXI D,FCB MVI C, ; READ ANOTHER BUFFER ; ; CALL DISKR ORA A ;ZERO VALUE IF READ OK JZ G0 ;FOR ANOTHER BYTE ; END OF DATA, RETURN WITH CHAR RET ; ; PNIB: ;PRINT NIBBLE IN REG A ANI 0FH ;LOW 4 BITS CPI 10 JNC P10 ; LESS THAN OR EQUAL TO 9 ADI '0' JMTHAT A JMP TO 0000H REBOOTS) CALL CRLF LHLD OLDSP SPHL ; STACK POINTER CONTAINS CCP'S STACK LOCATION RET ;TO THE CCP OPENF CALL BDOS ; 255 IN ACCUM IF OPEN ERROR RET ; DISKR: ;READ DISK FILE RECORD PUSH H! PUSH D! PUSH B LXI D,FCB MARRY SET FOR EOF STC RET ; G0: ;READ THE BYTE AT BUFF+REG A MOV E,A ;LS BYTE OF BUFFER INDEX MVI D,0 ;DOUBLE PRECISIONP PRN ; ; GREATER OR EQUAL TO 10 P10: ADI 'A' - 10 PRN: CALL PCHAR RET ; PHEX: ;PRINT HEX CHAR IN REG A PUSH PSW RRC; ; ; SUBROUTINES ; BREAK: ;CHECK BREAK KEY (ACTUALLY ANY KEY WILL DO) PUSH H! PUSH D! PUSH B; ENVIRONMENT SAVED MVI C,BVI C,READF CALL BDOS POP B! POP D! POP H RET ; ; FIXED MESSAGE AREA SIGNON: DB 'FILE DUMP VERSION 1.4$' OPNMSG: DB CR, INDEX TO DE INR A ;INDEX=INDEX+1 STA IBP ;BACK TO MEMORY ; POINTER IS INCREMENTED ; SAVE THE CURRENT FILE ADDRESS LXI H RRC RRC RRC CALL PNIB ;PRINT NIBBLE POP PSW CALL PNIB RET ; ERR: ;PRINT ERROR MESSAGE ; D,E ADDRESSES MESSAGE RKF CALL BDOS POP B! POP D! POP H; ENVIRONMENT RESTORED RET ; PCHAR: ;PRINT A CHARACTER PUSH H! PUSH D! PUSH B; SAVED LF,'NO INPUT FILE PRESENT ON DISK$' ; VARIABLE AREA IBP: DS 2 ;INPUT BUFFER POINTER OLDSP: DS 2 ;ENTRY SP VALUE FROM CCP ; ; MDS-800 I/O Drivers for CP/M 2.2 ; (four drive single density version) ; ; Version 2.2 February, 1980 ; vers equ 22 ;versd/write ; setdma set subsequent dma address (initially 80h) ; ; (read and write assume previous calls to set up the io parameter in (result in reg-a) ; conout console character out (char in reg-c) ; list list out (char in reg-c) ; punch punch out (chequ 0f3h ;interrupt control port inte equ 0111$1110b ;enable rst 0(warm boot), rst 7 (monitor) ; ; mds monitor equates mon80of cpm system nsects equ cpml/128 ;number of sectors to load offset equ 2 ;number of disk tracks used by cp/m cdisk equ 0004hkdef 2,0 diskdef 3,0 ; endef occurs at end of assembly ; ; end of controller - independent code, the remaining subroutines ion 2.2 ; ; Copyright (c) 1980 ; Digital Research ; Box 579, Pacific Grove ; California, 93950 ; ; true equ 0ffffh ;valuters) ; read read track/sector to preset dma address ; write write track/sector from preset dma address ; ; jump vector for ar in reg-c) ; reader paper tape reader in (result to reg-a) ; home move to track 00 ; ; (the following calls set-up the io  equ 0f800h ;mds monitor rmon80 equ 0ff0fh ;restart mon80 (boot error) ci equ 0f803h ;console character to reg-a ri equ 0f806 ;address of last logged disk on warm start buff equ 0080h ;default buffer address retry equ 10 ;max retries on disk i/o befor ; are tailored to the particular operating environment, and must ; be altered for any system which differs from the intel mds.e of "true" false equ not true ;"false" test equ false ;true if test bios ; if test bias equ 03400h ;base of CCP in test sindiviual routines jmp boot wboote: jmp wboot jmp const jmp conin jmp conout jmp list jmp punch jmp reader jmp parameter block for the ; mds, which is used to perform subsequent reads and writes) ; seldsk select disk given by reg-c (0,1,h ;reader in to reg-a co equ 0f809h ;console char from c to console out po equ 0f80ch ;punch char from c to punch device lo ee error ; ; perform following functions ; boot cold start ; wboot warm start (save i/o byte) ; (boot and wboot are the same ; ; the following code assumes the mds monitor exists at 0f800h ; and uses the i/o subroutines within the monitor ; ; we aystem endif if not test bias equ 0000h ;generate relocatable cp/m system endif ; patch equ 1600h ; org patch cpmb ehome jmp seldsk jmp settrk jmp setsec jmp setdma jmp read jmp write jmp listst ;list status jmp sectran ; mac2...) ; settrk set track address (0,...76) for subsequent read/write ; setsec set sector address (1,...,26) for subsequent reaqu 0f80fh ;list from c to list device csts equ 0f812h ;console status 00/ff to register a ; ; disk ports and commands base e for mds) ; const console status ; reg-a = 00 if no character ready ; reg-a = ff if character ready ; conin console characlso assume the mds system has four disk drives revrt equ 0fdh ;interrupt revert port intc equ 0fch ;interrupt mask port icon qu $-patch ;base of cpm console processor bdos equ 806h+cpmb ;basic dos (resident portion) cpml equ $-cpmb ;length (in bytes) lib diskdef ;load the disk definition library disks 4 ;four disks diskdef 0,1,26,6,1024,243,64,64,offset diskdef 1,0 dis qu 78h ;base of disk command io ports dstat equ base ;disk status (input) rtype equ base+1 ;result type (input) rbyte equ basmented dma address in hl mov b,h mov c,l ;ready for call to set dma call setdma lda ios ;sector number just read cpi 2tries push b wboot0: ;enter here on error retries lxi b,cpmb ;set dma address to start of disk system call setdma mvi cged disk number mov c,a ;send to ccp to log it in ei jmp cpmb ; ; error condition occurred, print message and retry booers mod 10+'0' db cr,lf,0 ; boot: ;print signon message and go to ccp ; (note: mds boot initialized iobyte at 0003h) lxi  mvi a,inte ;rst0 and rst7 bits on out intc xra a out icon ;interrupt control ; ; set default buffer address to 80h e+3 ;result byte (input) ; ilow equ base+1 ;iopb low address (output) ihigh equ base+2 ;iopb high address (output) ; readf 6 ;read last sector? jc rd1 ; must be sector 26, zero and go to next track lda iot ;get track to register a inr a mov c,0 ;boot from drive 0 call seldsk mvi c,0 call settrk ;start with track 0 mvi c,2 ;start reading sector 2 call setsec terr: pop b ;recall counts dcr c jz booter0 ; try again push b jmp wboot0 ; booter0: ; otherwise too many retries sp,buff+80h lxi h,signon call prmsg ;print message xra a ;clear accumulator sta cdisk ;set initially to disk a jmp goclxi b,buff call setdma ; ; reset monitor entry points mvi a,jmp sta 0 lxi h,wboote shld 1 ;jmp wboot at location 00 equ 4h ;read function writf equ 6h ;write function recal equ 3h ;recalibrate drive iordy equ 4h ;i/o finished mask cr equ 0d,a ;ready for call call settrk xra a ;clear sector number rd1: inr a ;to next sector mov c,a ;ready for call call setse ; ; read sectors, count nsects to zero pop b ;10-error count mvi b,nsects rdsec: ;read next sector push b ;save sector  lxi h,bootmsg call prmsg jmp rmon80 ;mds hardware monitor ; bootmsg: db '?boot',0 ; ; const: ;console status to regpm ;go to cp/m ; ; wboot:; loader on track 0, sector 1, which will be skipped for warm ; read cp/m from disk - assuming the sta 5 lxi h,bdos shld 6 ;jmp bdos at location 5 if not test sta 7*8 ;jmp to mon80 (may have been changed by ddt) lxih ;carriage return lf equ 0ah ;line feed ; signon: ;signon message: xxk cp/m vers y.y db cr,lf,lf if test db '32' ;32k c pop b ;recall sector count dcr b ;done? jnz rdsec ; ; done with the load, reset default buffer address gocpm: ;(entercount call read jnz booterr ;retry if errors occur lhld iod ;increment dma address lxi d,128 ;sector size dad d ;incre-a ; (exactly the same as mds call) jmp csts ; conin: ;console character to reg-a call ci ani 7fh ;remove parity bit re is a 128 byte cold start ; start. ; lxi sp,buff ;using dma - thus 80 thru ff available for stack ; mvi c,retry ;max re h,mon80 shld 7*8+1 endif ; leave iobyte set ; previously selected disk was b, send parameter to cpm lda cdisk ;last logexample bios endif if not test db '00' ;memory size filled by relocator endif db 'k CP/M vers ' db vers/10+'0','.',v here from cold start boot) ; enable rst0 and rst7 di mvi a,12h ;initialize command out revrt xra a out intc ;cleared ret ; conout: ;console character from c to console out jmp co ; list: ;list device out ; (exactly the same as mds call) suming disk/trk/sec/dma set) mvi c,readf ;set to read function call setfunc call waitio ;perform read function ret ;may track address given by c lxi h,iot mov m,c ret ; setsec: ;set sector number given by c lxi h,ios mov m,c ret secbank ;set bank flags ora a ;zero if drive 0,1 and nz if 2,3 mvi a,iopb and 0ffh ;low address for iopb mvi b,iopb shr 8 ; sta dbank ;to select drive bank mov a,c ;00, 01, 10, 11 ani 1b ;mds has 0,1 at 78, 2,3 at 88 ora a ;result 00? jz setd ;set to new command mov m,a ;replaced in iopb ; the mds-800 controller requires disk bank bit in sector byte ; mask the bit jmp lo ; listst: ;return list status xra a ret ;always not ready ; punch: ;punch device out ; (exactly the same as  have error set in reg-a ; ; write: ;disk write function mvi c,writf call setfunc ;set to write function call waitio tran: ;translate sector bc using table at de mvi b,0 ;double precision sector number in BC xchg ;translate table addresshigh address for iopb jnz iodr1 ;drive bank 1? out ilow ;low address to controller mov a,b out ihigh ;high address jmrive mvi a,00110000b ;selects drive 1 in bank setdrive: mov b,a ;save the function lxi h,iof ;io function mov a,m ani from the current i/o function ani 00100000b ;mask the disk select bit lxi h,ios ;address the sector select byte ora m ;mds call) jmp po ; reader: ;reader character in to reg-a ; (exactly the same as mds call) jmp ri ; home: ;move to home ret ;may have error set ; ; ; utility subroutines prmsg: ;print message at h,l to 0 mov a,m ora a ;zero? rz ; more t to HL dad b ;translate(sector) address mov a,m ;translated sector number to A sta ios mov l,a ;return sector number in p wait0 ;to wait for complete ; iodr1: ;drive bank 1 out ilow+10h ;88 for drive bank 10 mov a,b out ihigh+10h ; wait0 11001111b ;mask out disk number ora b ;mask in new disk number mov m,a ;save it in iopb mov l,c mvi h,0 ;HL=disk numberselect proper disk bank mov m,a ;set disk select bit on/off ret ; waitio: mvi c,retry ;max retries before perm error rposition ; treat as track 00 seek mvi c,0 jmp settrk ; seldsk: ;select disk given by register c lxi h,0000h ;return 000o print push h mov c,a call conout pop h inx h jmp prmsg ; setfunc: ; set function for next i/o (command in reg-cL ret ; setdma: ;set dma address given by regs b,c mov l,c mov h,b shld iod ret ; read: ;read next disk record (as: call instat ;wait for completion ani iordy ;ready? jz wait0 ; ; check io completion ok call intype ;must be io comp dad h ;*2 dad h ;*4 dad h ;*8 dad h ;*16 lxi d,dpbase dad d ;HL=disk header table address ret ; ; settrk: ;setewait: ; start the i/o function and wait for completion call intype ;in rtype call inbyte ;clears the controller ; lda d0 if error mov a,c cpi ndisks ;too large? rnc ;leave HL = 0000 ; ani 10b ;00 00 for drive 0,1 and 10 10 for drive 2,3 ) lxi h,iof ;io function address mov a,m ;get it to accumulator for masking ani 11111000b ;remove previous command ora c lete (00) unlinked ; 00 unlinked i/o complete, 01 linked i/o complete (not used) ; 10 disk status changed 11 (not uselda dbank ora a jnz inbyt1 in rbyte ret inbyt1: in rbyte+10h ret ; instat: lda dbank ora a jnz insta1 in dstat a permanent error message if it is not ; recoverable. in any case, the not ready condition is ; treated as a separate condirt sector count ; ; jump vector for individual subroutines jmp boot ;cold start wboote: jmp wboot ;warm start jmp constmds controller has returned a bit in each position ; of the accumulator, corresponding to the conditions: ; 0 - deleted data (; Skeletal CBIOS for first level of CP/M 2.0 alteration ; msize equ 20 ;cp/m version memory size in kilobytes ; ; "bias" is d) cpi 10b ;ready status change? jz wready ; ; must be 00 in the accumulator ora a jnz werror ;some other condition,t ret insta1: in dstat+10h ret ; ; ; ; data areas (must be in ram) dbank: db 0 ;disk bank 00 if drive 0,1 ; 10 tion for later improvement trycount: ; register c contains retry count, decrement 'til zero dcr c jnz rewait ;for another  ;console status jmp conin ;console character in jmp conout ;console character out jmp list ;list character out jmp accepted as ok above) ; 1 - crc error ; 2 - seek error ; 3 - address error (hardware malfunction) ; 4 - data over/under flowaddress offset from 3400H for memory systems ; than 16K (referred to as "b" throughout the text). ; bias equ (msize-20)*1024  retry ; ; check i/o error bits call inbyte ral jc wready ;unit not ready rar ani 11111110b ;any other errors? (deif drive 2,3 iopb: ;io parameter block db 80h ;normal i/o operation iof: db readf ;io function, initial read ion: db 1 ;numtry ; ; cannot recover from error mvi a,1 ;error code ret ; ; intype, inbyte, instat read drive bank 00 or 10 intype: lpunch ;punch character out jmp reader ;reader character out jmp home ;move head to home position jmp seldsk ;select di (hardware malfunction) ; 5 - write protect (treated as not ready) ; 6 - write error (hardware malfunction) ; 7 - not ready  ccp equ 3400H+bias ;base of ccp bdos equ ccp+806h ;base of bdos bios equ ccp+1600h ;base of bios cdisk equ 0004H ;current dileted data ok) jnz werror ; ; read or write is ok, accumulator contains zero ret ; wready: ;not ready, treat as error fober of sectors to read iot: db offset ;track number ios: db 1 ;sector number iod: dw buff ;io address ; ; ; define ram areda dbank ora a jnz intyp1 ;skip to bank 10 in rtype ret intyp1: in rtype+10h ;78 for 0,1 88 for 2,3 ret ; inbyte: sk jmp settrk ;set track number jmp setsec ;set sector number jmp setdma ;set dma address jmp read ;read disk jmp ; (accumulator bits are numbered 7 6 5 4 3 2 1 0) ; ; it may be useful to filter out the various conditions, ; but we will gesk number 0=A,...,15=P iobyte equ 0003h ;intel i/o byte ; org bios ;origin of this program nsects equ ($-ccp)/128 ;warm star now call inbyte ;clear result byte jmp trycount ; werror: ;return hardware malfunction (crc, track, seek, etc.) ; the as for bdos operation endef end  write ;write disk jmp listst ;return list status jmp sectran ;sector translate ; ; fixed data tables for four-drive stahas the current track number mvi d,2 ;d has the next sector to read ; note that we begin by reading track 0, sector 2 since ed tables ; ; individual subroutines to perform each function boot: ;simplest case is to just perform parameter initializatioacks cpi 27 jc load1 ;carry generated if sector<27 ; ; end of current track, go to next track mvi d,1 ;begin with first sectors 1,2,3,4 db 25,5,11,17 ;sectors 5,6,7,8 db 23,3,9,15 ;sectors 9,10,11,12 db 21,2,8,14 ;sectors 13,14,15,16 db 20, set, dma address set call read cpi 00h ;any errors? jnz wboot ;retry the entire boot if an error occurs ; ; no error, mndard ; IBM-compatible 8" disks ; disk parameter header for disk 00 dpbase: dw trans,0000H dw 0000H,0000H dw dirbf,dpblk sector 1 ; contains the cold start loader, which is skipped in a warm start lxi h,ccp ;base of cp/m (initial load point) lon xra a ;zero in the accum sta iobyte ;clear the iobyte sta cdisk ;select disk zero jmp gocpm ;initialize and go to sector of next track inr c ;track=track+1 ; ; save register state, and change tracks push b push d push h call settr26,6,12 ;sectors 17,18,19,20 db 18,24,4,10 ;sectors 21,22,23,24 db 16,22 ;sectors 25,26 ; dpblk: ;disk parameter block, cove to next sector pop h ;recall dma address lxi d,128 ;dma=dma+128 dad d ;new dma address is in h,l pop d ;recall secto dw chk00,all00 ; disk parameter header for disk 01 dw trans,0000H dw 0000H,0000H dw dirbf,dpblk dw chk01,all01 ; disad1: ;load one more sector push b ;save sector count, current track push d ;save next sector to read push h ;save dma addrcp/m ; wboot: ;simplest case is to read the disk until all sectors loaded lxi sp,80h ;use space below buffer for stack mvk ;track address set from register c pop h pop d pop b jmp load1 ;for another sector ; ; end of load operation, set paommon to all disks dw 26 ;sectors per track db 3 ;block shift factor db 7 ;block mask db 0 ;null mask dw 242 ;disr address pop b ;recall number of sectors remaining, and current trk dcr b ;sectors=sectors-1 jz gocpm ;transfer to cp/m ik parameter header for disk 02 dw trans,0000H dw 0000H,0000H dw dirbf,dpblk dw chk02,all02 ; disk parameter header for ess mov c,d ;get sector address to register c call setsec ;set sector address from register c pop b ;recall dma address toi c,0 ;select disk 0 call seldsk call home ;go to track 00 ; mvi b,nsects ;b counts # of sectors to load mvi c,0 ;c rameters and go to cp/m gocpm: mvi a,0c3h ;c3 is a jmp instruction sta 0 ;for jmp to wboot lxi h,wboote ;wboot entry poink size-1 dw 63 ;directory max db 192 ;alloc 0 db 0 ;alloc 1 dw 16 ;check size dw 2 ;track offset ; ; end of fixf all have been loaded ; ; more sectors remain to load, check for track change inr d mov a,d ;sector=27?, if so, change trdisk 03 dw trans,0000H dw 0000H,0000H dw dirbf,dpblk dw chk03,all03 ; ; sector translate vector trans: db 1,7,13,19 ; b,c push b ;replace on stack for later recall call setdma ;set dma address from b,c ; ; drive set to 0, track set, sector t shld 1 ;set address field for jmp at 0 ; sta 5 ;for jmp to bdos lxi h,bdos ;bdos entry point shld 6 ;address field ofn first read/write ; seldsk: ;select disk given by register C lxi h,0000h ;error return code mov a,c sta diskno cpi 4 t ;null subroutine ; ; reader: ;read character into register a from reader device mvi a,1ah ;enter end of file for now (ren (usually this is similar to write ; so we will allow space to set up read command, then use ; common code in write) ds 10hconsole character into register a ds 10h ;space for input routine ani 7fh ;strip parity bit ret ; conout: ;console charac mov a,c sta sector ds 10h ;space for sector select ret ; sectran: ;translate the sector given by BC using the ;t jump at 5 to bdos ; lxi b,80h ;default dma address is 80h call setdma ; ei ;enable the interrupt system lda cdisk ;g;must be between 0 and 3 rnc ;no carry if 4,5,... ; disk number is in the proper range ds 10 ;space for disk select ; complace later) ani 7fh ;remember to strip parity bit ret ; ; ; i/o drivers for the disk follow ; for now, we will simply s ;set up read command jmp waitio ;to perform the actual i/o ; write: ;perform a write operation ds 10h ;set up write commacter output from register c mov a,c ;get to accumulator ds 10h ;space for output routine ret ; list: ;list character froranslate table given by DE xchg ;HL=.trans dad b ;HL=.trans(sector) mov l,m ;L = trans(sector) mvi h,0 ;HL= trans(sectoet current disk number mov c,a ;send to the ccp jmp ccp ;go to cp/m for further processing ; ; ; simple i/o handlers (muspute proper disk parameter header address lda diskno mov l,a ;L=disk number 0,1,2,3 mvi h,0 ;high order zero dad h ;*2 tore the parameters away for use ; in the read and write subroutines ; home: ;move to the track 00 position of current drive nd ; waitio: ;enter here from read and write to perform the actual i/o ; operation. return a 00h in register a if the operam register c mov a,c ;character to register a ret ;null subroutine ; listst: ;return list status (0 if not ready, 1 if rer) ret ;with value in HL ; setdma: ;set dma address given by registers b and c mov l,c ;low order address mov h,b ;hight be filled in by user) ; in each case, the entry point is provided, with space reserved ; to insert your own code ; const:  dad h ;*4 dad h ;*8 dad h ;*16 (size of each header) lxi d,dpbase dad d ;HL=.dpbase(diskno*16) ret ; settrk: ;set t ; translate this call into a settrk call with parameter 00 mvi c,0 ;select track 0 call settrk ret ;we will move to 00 otion completes ; properly, and 01h if an error occurs during the read or write ; ; in this case, we have saved the disk numbeady) xra a ;0 is always ok to return ret ; punch: ;punch character from register c mov a,c ;character to register a re order address shld dmaad ;save the address ds 10h ;space for setting the dma address ret ; read: ;perform read operatio;console status, return 0ffh if character ready, 00h if not ds 10h ;space for status subroutine mvi a,00h ret ; conin: ;rack given by register c mov a,c sta track ds 10h ;space for track select ret ; setsec: ;set sector given by register  r in 'diskno' (0,1) ; the track number in 'track' (0-76) ; the sector number in 'sector' (1-26) ; the dma address in 'deblocking Algorithms for CP/M 2.0 * ;* * ;******************************* * ;* BDOS constants on entry to write * ;* dat equ $ ;beginning of data area dirbf: ds 128 ;scratch directory area all00: ds 31 ;allocation vector 0 all01: ds 31 ;alloc * ;* * ;***************************************************** blksiz equmaad' (0-65535) ds 256 ;space reserved for I/O drivers mvi a,1 ;error condition ret ;replaced when filled-in ; ; the re********************** ; ; utility macro to compute sector mask smask macro hblk ;; compute log2(hblk), return @x as result  * ;***************************************************** wrall equ 0 ;write to allocated wrdir equ 1 ;write ation vector 1 all02: ds 31 ;allocation vector 2 all03: ds 31 ;allocation vector 3 chk00: ds 16 ;check vector 0 chk01: ds 16 2048 ;CP/M allocation size hstsiz equ 512 ;host disk sector size hstspt equ 20 ;host disk sectors/trk hstblk equ hstsiz/1mainder of the CBIOS is reserved uninitialized ; data area, and does not need to be a part of the ; system memory image (the s ;; (2 ** @x = hblk on return) @y set hblk @x set 0 ;; count right shifts of @y until = 1 rept 8 if @y = 1 exitm endito directory wrual equ 2 ;write to unallocated ; ;***************************************************** ;*  ;check vector 1 chk02: ds 16 ;check vector 2 chk03: ds 16 ;check vector 3 ; enddat equ $ ;end of data area datsiz equ $-be28 ;CP/M sects/host buff cpmspt equ hstblk * hstspt ;CP/M sectors/track secmsk equ hstblk-1 ;sector mask smask hstblk ;comppace must be available, ; however, between "begdat" and "enddat"). ; track: ds 2 ;two bytes for expansion sector: ds 2 ;two f ;; @y is not 1, shift right one position @y set @y shr 1 @x set @x + 1 endm endm ; ;*********************************;***************************************************** ;* * ;* Sector D * ;* The BDOS entry points given below show the * ;* code which is relevant to deblocgdat;size of data area end ute sector mask secshf equ @x ;log2(hstblk) ; ;***************************************************** ;* bytes for expansion dmaad: ds 2 ;direct memory address diskno: ds 1 ;disk number 0-15 ; ; scratch ram area for BDOS use beg******************** ;* * ;* CP/M to host disk constants  king only. * ;* * ;*****************************************************  ;***************************************************** ;* * ;* The WRITE en************************** ;* * ;* The READ entry point takes the place of jnz alloc ;skip if not ; ; tracks are the same lda seksec ;same sector? lxi h,unasec cmp m ;seksec = unasec? jnz al number to HL mvi h,0 rept 4 ;multiply by 16 dad h endm lxi d,dpbase ;base of parm block dad d ;hl=.dpb(curdsk) kdsk ;disk to seek sta unadsk ;unadsk = sekdsk lhld sektrk shld unatrk ;unatrk = sectrk lda seksec sta unasec ;una; ; DISKDEF macro, or hand coded tables go here dpbase equ $ ;disk param block base ; boot: wboot: ;enter here on systemtry point takes the place of * ;* the previous BIOS defintion for WRITE. * ;*  * ;* the previous BIOS defintion for READ. * ;* * ;*************loc ;skip if not ; ; match, move to next sector for future ref inr m ;unasec = unasec+1 mov a,m ;end of track? cpi cpret ; settrk: ;set track given by registers BC mov h,b mov l,c shld sektrk ;track to seek ret ; setsec: ;set sesec = seksec ; chkuna: ;check for write to unallocated sector lda unacnt ;any unalloc remain? ora a jz alloc ;skip i boot to initialize xra a ;0 to accumulator sta hstact ;host buffer inactive sta unacnt ;clear unalloc count ret ;  * ;***************************************************** write: ;write the selected CP/M sector xra a ;0 to a**************************************** read: ;read the selected CP/M sector xra a sta unacnt mvi a,1 sta readop ;rmspt ;count CP/M sectors jc noovf ;skip if no overflow ; ; overflow to next track mvi m,0 ;unasec = 0 lhld unatrk ictor given by register c mov a,c sta seksec ;sector to seek ret ; setdma: ;set dma address given by BC mov h,b mf not ; ; more unallocated records remain dcr a ;unacnt = unacnt-1 sta unacnt lda sekdsk ;same disk? lxi h,unadsk home: ;home the selected disk home: lda hstwrt ;check for pending write ora a jnz homed sta hstact ;clear host activeccumulator sta readop ;not a read operation mov a,c ;write type in c sta wrtype cpi wrual ;write unallocated? jnz cead operation sta rsflag ;must read data mvi a,wrual sta wrtype ;treat as unalloc jmp rwoper ;to perform the read ; nx h shld unatrk ;unatrk = unatrk+1 ; noovf: ;match found, mark as unnecessary read xra a ;0 to accumulator sta rsflov l,c shld dmaadr ret ; sectran: ;translate sector number BC mov h,b mov l,c ret ; ;***************************cmp m ;sekdsk = unadsk? jnz alloc ;skip if not ; ; disks are the same lxi h,unatrk call sektrkcmp ;sektrk = unatrk?  flag homed: ret ; seldsk: ;select disk mov a,c ;selected disk number sta sekdsk ;seek disk number mov l,a ;diskhkuna ;check for unalloc ; ; write to unallocated, set parameters mvi a,blksiz/128 ;next unalloc recs sta unacnt lda se ag ;rsflag = 0 jmp rwoper ;to perform the write ; alloc: ;not an unallocated record, requires pre-read xra a ;0 to ac secmsk ;least signif bits mov l,a ;ready to shift mvi h,0 ;double count rept 7 ;shift left 7 dad h endm ; hl haslxi h,hstsec ;sekhst = hstsec? cmp m jz match ;skip if match ; nomatch: ;proper disk, but not correct sector lda hstw * ;***************************************************** sektrkcmp: ;HL = .unatrk or .hsttrk, compare with a a ;carry = 0 rar ;shift right endm sta sekhst ;host sector to seek ; ; active host sector? lxi h,hstact ;host aced to/from host buffer lda wrtype ;write type cpi wrdir ;to directory? lda erflag ;in case of errors rnz ;no furthecum sta unacnt ;unacnt = 0 inr a ;1 to accum sta rsflag ;rsflag = 1 ; ;********************************************** relative host buffer address lxi d,hstbuf dad d ;hl = host address xchg ;now in DE lhld dmaadr ;get/put CP/M data rt ;host written? ora a cnz writehst ;clear host buff ; filhst: ;may have to fill the host buffer lda sekdsk sta hssektrk xchg lxi h,sektrk ldax d ;low byte compare cmp m ;same? rnz ;return if not ; low bytes equal, test high 1stive flag mov a,m mvi m,1 ;always becomes 1 ora a ;was it already? jz filhst ;fill host if not ; ; host buffer actir processing ; ; clear host buffer for directory write ora a ;errors? rnz ;skip if so xra a ;0 to accum sta hstwrt******* ;* * ;* Common code for READ and WRITE follows * ;*  mvi c,128 ;length of move lda readop ;which way? ora a jnz rwmove ;skip if read ; ; write operation, mark and switchtdsk lhld sektrk shld hsttrk lda sekhst sta hstsec lda rsflag ;need to read? ora a cnz readhst ;yes, if 1 xra  inx d inx h ldax d cmp m ;sets flags ret ; ;***************************************************** ;* ve, same as seek buffer? lda sekdsk lxi h,hstdsk ;same disk? cmp m ;sekdsk = hstdsk? jnz nomatch ; ; same disk, same  ;buffer written call writehst lda erflag ret ; ;***************************************************** ;*  * ;***************************************************** rwoper: ;enter here to per direction mvi a,1 sta hstwrt ;hstwrt = 1 xchg ;source/dest swap ; rwmove: ;C initially 128, DE is source, HL is dea ;0 to accum sta hstwrt ;no pending write ; match: ;copy data to or from buffer lda seksec ;mask buffer number ani * ;* WRITEHST performs the physical write to * ;* the host disk, READHST reads the ptrack? lxi h,hsttrk call sektrkcmp ;sektrk = hsttrk? jnz nomatch ; ; same disk, same track, same buffer? lda sekhst  * ;* Utility subroutine for 16-bit compare * ;* form the read/write xra a ;zero to accum sta erflag ;no errors (yet) lda seksec ;compute host sector rept secshf orst ldax d ;source character inx d mov m,a ;to dest inx h dcr c ;loop 128 times jnz rwmove ; ; data has been mov hysical * ;* disk. * ;* * ;*********************************************************************** end rk: ds 2 ;last unalloc track unasec: ds 1 ;last unalloc sector ; erflag: ds 1 ;error reporting rsflag: ds 1 ;read sectorS: ; ; BAUD RATE SBAUD ; 110 1047 ; 134.5 857 ; 150 768 ; 300 384 ; 600 192 ; 1200 96 ; 1800 64 ; 2000 58areas * ;* * ;***************************************************** ;TA: EQU 20H ;SERIAL DATA PORT SINTEN: EQU SDATA+1 ;SERIAL INTERRUPT ENABLE PORT SIDENT: EQU SDATA+2 ;SERIAL INTERRUPT IDENTIFI***************** writehst: ;hstdsk = host disk #, hsttrk = host track #, ;hstsec = host sect #. write "hstsiz" bytes ;fr; MODIFIED FOR AUTO-BOOT 8 SEPT 80 ; ; 1 JUL 80 ; TITLE 'CCS 2422 STANDARD BIOS FOR CP/M 2.2' PAGE 56 ; ; THIS BIOS IS  flag readop: ds 1 ;1 if read operation wrtype: ds 1 ;write operation type dmaadr: ds 2 ;last dma address hstbuf: ds hsts ; 2400 48 ; 3600 32 ; 4800 24 ; 7200 16 ; 9600 12 ; 19200 6 ; 38400 3 ; 56000 2 ; SBAUD: EQU 12 ; DSTAT EQU sekdsk: ds 1 ;seek disk number sektrk: ds 2 ;seek track number seksec: ds 1 ;seek sector number ; hstdsk: ds 1 ;host dCATION PORT SLCTRL: EQU SDATA+3 ;SERIAL LINE CONTROL PORT SMDMCT: EQU SDATA+4 ;SERIAL MODEM CONTROL PORT SLSTAT: EQU SDATA+5 om hstbuf and return error flag in erflag. ;return erflag non-zero if error ret ; readhst: ;hstdsk = host disk #, hsttrkSET UP FOR STANDARD 128 BYTE SECTORS ONLY ; ;"BIAS" IS ADDRESS OFFSET FROM 2C00H FOR MEMORY SYSTEMS ;THAN 20K (REFERRED TO ASiz ;host buffer ; ;***************************************************** ;*  30H ;DISK STATUS PORT DCMMD EQU DSTAT ;DISK COMMAND PORT DTRCK EQU DSTAT+1 ;DISK TRACK PORT DSCTR EQU DSTAT+2 ;DISK SECTOR Pisk number hsttrk: ds 2 ;host track number hstsec: ds 1 ;host sector number ; sekhst: ds 1 ;seek shr secshf hstact: ds 1;SERIAL LINE STATUS PORT SMDMST: EQU SDATA+6 ;SERIAL MODEM STATUS PORT ; ; WHEN THE AUTO-BOOT JUMPER IS ENABLED, THE 2810 ; = host track #, ;hstsec = host sect #. read "hstsiz" bytes ;into hstbuf and return error flag in erflag. ret ; ;******* "B" THROUGHOUT THE TEXT). ; VERS: EQU 22 ;CP/M VERSION NUMBER MSIZE: EQU 20 ;CP/M VERSION MEMORY SIZE IN KILOBYTES BIAS: EQ * ;* The ENDEF macro invocation goes here * ;* * ;******************ORT DDATA EQU DSTAT+3 ;DISK DATA PORT DFLAG EQU DSTAT+4 ;DISK FLAF PORT DCTRL EQU DSTAT+4 ;DISK CONTROL PORT BCTRL EQU 4 ;DI ;host active flag hstwrt: ds 1 ;host written flag ; unacnt: ds 1 ;unalloc rec cnt unadsk: ds 1 ;last unalloc disk unat SERIAL PORT WILL BE INITIALIZED TO 9600 BAUD. ; TO SELECT A DIFFERENT BAUD RATE, CHANGE SBAUD ; TO ONE OF THE FOLLOWING VALUE********************************************** ;* * ;* Unitialized RAM data U (MSIZE-20)*1024 CCP: EQU 2C00H+BIAS ;BASE OF CCP BDOS: EQU CCP+806H ;BASE OF BDOS BIOS: EQU CCP+1600H ;BASE OF BIOS ; SDA  SK STATUS/CONTROL PORT 2 ; STEP5: EQU 3 ;MINI STEP RATE STEP8: EQU 2 ;MAXI STEP RATE ; WBOOTV: EQU 0 ;VECTOR FOR WARM RESTADATA READY BIT INTO CARRY JNC TTYIN ;LOOP UNTIL DATA IS IN IN SDATA ;READ THE DATA ANI 7FH ;STRIP OFF THE PARITY BIT RETMP SETTRK ;SET TRACK NUMBER JMP SETSEC ;SET SECTOR NUMBER JMP SETDMA ;SET DMA ADDRESS JMP DREAD ;READ DISK JMP DWRITE ;WK XRA A LOAD3: INR A STA SECTOR MOV A,H CPI BIOS/256 ;SEE IF DONE WITH WARM BOOT JC LOAD2 ;JUMP IF MORE TO GO ; ;EQU 4BH DMAAD: EQU 4CH ;HOST BUFFER ADDRESS IDSV: EQU 4EH ;DISK ID SAVE AREA TBUF: EQU 80H ; ORG BIOS ;ORIGIN OF THIS PROGRO LXI H,0D002H ;SET THE SIDE AND SECTOR SHLD SECTOR MVI B,8 ;ZERO OUT PRMTBL LXI H,PRMTBL LOAD1A: MOV M,A INX H DCRT CR: EQU 0DH ;ASCII CARRIAGE RETURN LF: EQU 0AH ;ASCII LINE FEED IOBYTE: EQU 3 ;ADDRESS OF I/O CONTROL BYTE CDISK: EQU 4  ; TTOST: IN SLSTAT ;GET 8250 LINE STATUS ANI 20H ;ISOLATE TX BUFFER EMPTY BIT RZ ;RETURN IF NOT EMPTY ADI 0BFH ;FLAG TRITE DISK JMP TTOST ;RETURN LIST STATUS JMP SECTRAN ;SECTOR TRANSLATE ; ;INDIVIDUAL SUBROUTINES TO PERFORM EACH FUNCTION ND OF LOAD OPERATION, SET PARAMETERS AND GO TO CP/M BOOT0: MVI A,JMP ;GET A JUMP OP CODE STA WBOOTV ;RESET THE JUMP VECTORS AM ; ;JUMP VECTOR FOR INDIVIDUAL SUBROUTINES JMP BOOT ;COLD START WBOOTE: JMP WBOOT ;WARM START CSTAT: JMP TTST ;CONSOLE SR B JNZ LOAD1A PUSH B MOV C,A CALL SELDSK POP B LDA CUNIT ;GET THE SELBITS ANI 10H ;SEE IF A MINI MVI B,26 ;SET BDOSV: EQU 5 ; DISKNO: EQU 40H ;ACTIVE DISK NUMBER TRACK: EQU DISKNO+1 SECTOR: EQU TRACK+1 SIDE: EQU SECTOR+1 ;SIDE SELECTHE EMPTY STATE RET ; TTYOUT: CALL TTOST ;GET 8250 LINE STATUS JZ TTYOUT ;WAIT UNTIL ONE OF THE REGISTERS EMPTIES MOV A,C; ; I/O DRIVERS FOR THE 8250 ASYNC COMM ELEMENT ; TTST: IN SLSTAT ;GET 8250 LINE STATUS ANI 1 ;SEE IF RECEIVE DATA AVAILABL STA BDOSV LXI H,WBOOTE SHLD WBOOTV+1 LXI H,BDOS SHLD BDOSV+1 LXI H,TBUF ;SET UP DEFAULT BUFFER ADDRESS SHLD DMAAD TATUS CONIN: JMP TTYIN ;CONSOLE CHARACTER IN CONO: JMP TTYOUT ;CONSOLE CHARACTER OUT JMP TTYOUT ;LIST CHARACTER OUT JMP TT8" SECTORS PER TRACK JNZ LOAD1B ;JUMP IF 8" MVI B,18 ; ELSE, SET MINI SECTORS PER TRACK LOAD1B: LXI H,CCP SHLD DMAAD LO HOLD AREA SPT: EQU SIDE+1 ;SECTORS PER TRACK HOLD TWOSID: EQU SPT+1 ;SINGLE/DOUBLE SIDED SWITCH HOLD STPRAT: EQU 46H ;STEP R ;MOVE THE DATA OVER OUT SDATA ;OUTPUT THE DATA RET ; ; RETRY: DCR C JNZ LOAD1 LXI H,BOTMSG CALL PRTWD CALL CONINE RZ ;RETURN IF NOT ADI 0FEH ;FLAG THAT DATA IS AVAILABLE RET ; TTYIN: IN SLSTAT ;GET 8250 LINE STATUS RAR ;MOVE RX  EI ;ENABLE THE INTERRUPT SYSTEM LDA CDISK ;GET CURRENT DISK NUMBER MOV C,A ;SEND TO THE CCP JMP CCP ;GO TO CP/M FOR FURTYOUT ;PUNCH CHARACTER OUT JMP TTYIN ;READER CHARACTER OUT JMP HOME ;MOVE HEAD TO HOME POSITION JMP SELDSK ;SELECT DISK JAD2: PUSH B CALL DREAD POP B ORA A JNZ RETRY SHLD DMAAD LDA SECTOR CMP B JC LOAD3 LDA TRACK INR A STA TRACATE SAVE AREA STATUS: EQU 47H CMND: EQU STATUS+1 LUNIT: EQU 49H ;LAST USED DRIVE CUNIT: EQU LUNIT+1 ;CURRENT DRIVE RWFLG: E CALL PRTWD WBOOT: LXI SP,80H MVI C,10 ;# OF RETRIES LOAD1: XRA A MOV H,A ;SET THE UNIT AND TRACK MOV L,A SHLD DISKN! HER PROCESSING ; BOOT: IN DCTRL ;SEE IF AUTO-BOOT IN PROGRESS ANI 40H JNZ BOOTA MVI A,0FH ;TURN OFF THE HAND-SHAKE LINESNI JZ SETUP1 ;JUMP IF MINI LXI D,SELTBL ; ELSE, SET THE 8" TABLE ADDRESS SETUP1: POP H PUSH H ;GET, RESAVE DP BLOCK POIA STA CUNIT ORA A JNZ SET4 ;JUMP IF ALREADY ESTABLISHED XCHG ;ELSE, ESTABLISH NEW DISK INR L ;INSURE LUNIT<>CUNIT S ; THE STRING MUST BE TERMINATED BY BIT 7 SET IN THE ; LAST CHARACTER OF THE STRING. THE STRING WILL START ; A NEW LINE (EP =A DISKNO CPI 4 ;MUST BE BETWEEN 0 AND 3 RNC ;NO CARRY IF 4,5,... ;DISK NUMBER IS IN THE PROPER RANGE ;COMPUTE PROPER DISK ; ;TRANSLATE THE SECTOR GIVEN BY BC USING THE ;TRANSLATE TABLE GIVEN BY DE SECTRAN: XCHG ;HL=.TRANS DAD B ;HL=.TRANS(SE OUT SMDMCT MVI A,83H ;ACCESS THE BAUD RATE DIVISOR REG OUT SLCTRL MVI A,SBAUD/256 ;SET THE DIVISOR HIGH BYTE OUT SINNTER LDAX D ;MOVE THE TABLE ENTRIES MOV M,A INX D INX H LDAX D MOV M,A INX D PUSH D ;SAVE IT FOR A MOMENT LXI HLD LUNIT ; TO FORCE A READ ADDRESS PUSH B PUSH D ;SAVE THE REGISTERS CALL IDRD ;FIND OUT WHAT IS OUT THERE POP H ;REGE PRTWD) OR CONTINUE ON THE SAME ; LINE (EP = PRTWA) ; PRTWD: CALL CRLF ;START A NEW LINE PRTWA: PUSH B ;SAVE (B,C) PRTA: MO PARAMETER HEADER ADDRESS SELDSK1: MOV L,A ;L=DISK NUMBER 0,1,2,3 DAD H ;*2 DAD H ;*4 DAD H ;*8 DAD H ;*16 (SIZE OF EACTOR) MOV L,M ;L = TRANS(SECTOR) MVI H,0 ;HL= TRANS(SECTOR) RET ;WITH VALUE IN HL ; ;SET DMA ADDRESS GIVEN BY REGISTERSTEN MVI A,SBAUD MOD 256 ;SET THE DIVISOR LOW BYTE OUT SDATA MVI A,3 OUT SLCTRL ;SET NORMAL OPERATING CONDITIONS XRA AD,9 DAD D ;OFFSET THE POINTER POP D ;REGET TABLE ADDRESS LDAX D ;MOVE THE TABLE ENTRIES MOV M,A INX D INX H LDAX DT SELECT TABLE ADDRESS POP B DCX H ;POINT TO STEP RATE LDA STPRAT ;SET THE STEP RATE MOV M,A ;SAVE THE STEP RATE INX HV C,M ;GET NEXT CHARACTER FROM MEMORY CALL CONO ;OUTPUT IT INX H ;INCREMENT MEMORY POINTER MOV A,C RLC ;TEST FOR BIT 7 CH HEADER) XCHG LXI H,DPBASE DAD D ;HL=.DPBASE(DISKNO*16) ; CKSET: PUSH H ;SAVE (H,L) MOV A,C ;REGET UNIT ADD A ;OFF B AND C SETDMA: MOV L,C ;LOW ORDER ADDRESS MOV H,B ;HIGH ORDER ADDRESS SHLD DMAAD ;SAVE THE ADDRESS RET ; ;MOVE TO THE ;SET THE HAND-SHAKE LINES OUT SINTEN OUT SLSTAT BOOTA: LXI H,LOGMSG ;SIGN ON TO THE SYSTEM CALL PRTWD LXI H,0 ;SET IO MOV M,A SET4: POP H MOV A,C RET ; ;SET TRACK GIVEN BY REGISTER C SETTRK: MOV A,C STA TRACK RET ; ;SET SECTOR GI LDA CUNIT ;GET THE SELBITS MOV M,A ;SET THE TABLE ANI 10H ;ISOLATE THE MINI DRIVE BIT LXI D,MSELTB ;SET ADDRESS FOR MIDELIMITER JNC PRTA ;NO DELIMITER, GO DO NEXT CHARACTER PRTB: POP B ;RESTORE (B,C) RET ; ; ROUTINE CRLF GENERATES A CARRIASET INTO TABLE LXI H,PRMTBL+1 ;POINT TO SELBITS MOV E,A DAD D ;OFFSET THE TABLE POINTER MOV A,M ;GET THE SELBITS ORA  TRACK 00 POSITION OF CURRENT DRIVE HOME: SUB A STA TRACK RET ; ; ROUTINE PRTWD PRINTS AN ASCII STRING ONTO THE CONSOLE. BYTE, CDISK SHLD IOBYTE JMP BOOT0 ; ; ;SELECT DISK GIVEN BY REGISTER C SELDSK: LXI H,0 ;ERROR RETURN CODE MOV A,C STVEN BY REGISTER C SETSEC: MVI A,0D0H ;SET UP SIDE SELECT BITS STA SIDE ;SET THE SIDE SELECT BITS MOV A,C STA SECTOR RET" GE RETURN, LINE FEED ; SEQUENCE ON THE CURRENT CONSOLE TO START A NEW LINE ; IT INCLUDES TWO NULL CHARACTERS FOR TTY TYPE ; DI 9CH ;ISOLATE READ ERROR BITS RET ; WRDAT: ORI 20H ;ADD WRITE COMMAND OUT DCMMD ;DISK COMMAND PORT STA CMND WRT1: MOV  BIOS. ; ; DREAD: DB 3EH ;SIM. MVI A INSTR DWRITE: XRA A ;SET WRITE FLAG STA RWFLG ;SAVE IT FOR LATER USE MVI B,10 ;NUMB READ SECTOR COMMAND LHLD DMAAD ;GET THE DMA ADDRESS MVI C,80H ;SET SECTOR BYTE COUNT RDWRT2: CMP A ;CLEAR THE FLAGS RET RED DATA IS TRANSFERRED, THE DESIRED ; TRACK IS SEEKED OUT, THE DESIRED SECTOR AND SIDE IS ; SET, THEN THE ACTUAL DATA TRANSFE SECTOR OUT DSCTR ;DISK SECTOR PORT IN DTRCK ;DISK TRACK PORT MOV C,A ;SAVE IT LDA TRACK ;GET DESIRED TRACK CMP C JZEVICES FOR THE HEAD MOVEMENT TIME. ; CRLF: PUSH H ;SAVE THE CONTENTS OF (H,L) CRLFA: LXI H,CRMSG ;ADDRESS OF CR,LF MESSAGE A,M ;GET THE DATA OUT DDATA INX H ;BUMP THE MEMORY POINTER DCR C ;LOOP CONTROL JNZ WRT1 JMP EOJ ; EOJB: MVI B,8 ;BASER OF RETRIES AGN: PUSH B CALL SEEK CZ RDWR READ3: POP B RZ DCR B JNZ AGN RET ; RDWR: MOV E,A ;SAVE COMMAND LD ; IDRD5: MVI B,58H ;BUILD A STEP-IN COMMAND CALL EOJA IDRD: LHLD LUNIT MOV A,H ;GET THE CUNIT VALUE CMP L ;SEE IF SAME R. ; ; UP TO TEN TRIES WILL BE ATTEMPTED BEFORE THE DATA ; TRANSFER IS ABORTED. ON RETURN TO THE CALLING ; ROUTINE, THE A R RDWRT ;JUMP IF NO SEEK NEEDED OUT DDATA ;SET THE SEEK TRACK MVI B,1CH ;BUILD THE SEEK COMMAND CALL EOJA ;DO THE SEEK ANCALL PRTWA ; OUTPUT IT POP H ;RESTORE (H,L) RET CRMSG: DB CR,LF,0,80H ; ; ; THE FOLLOWING ROUTINES DO THE PRIMITIVE DISIS OF RESTORE COMMAND EOJA: LDA STPRAT ;GET THE STEP RATE BITS ORA B ;ADD ON THE COMMAND STA CMND OUT DCMMD ;DO THE COMMAA RWFLG ORA A MOV A,E ;REGET THE COMMAND JZ WRDAT ;WRITE IF ZERO RDAT: OUT DCMMD ;DISK COMMAND PORT STA CMND READ1: INAS LUNIT RZ ;RETURN IF SO IDRD1: MVI C,80H ;SET THE AUTO-WAIT BIT CALL SETUP CALL EOJ1 ;INSURE A DRIVE IS THERE RM ;EEGISTER WILL CONTAIN A ZERO IF THE ; OPERATION WAS SUCCESSFUL, OR NON-ZERO IF NOT ; SUCCESSFUL. THE FLAG REGISTER WILL NOT NEI 98H ;SEEK ERROR MASK RNZ ;DONE IF SEEK ERROR RDWRT: MVI C,80H ;AUTO-WAIT BIT CALL SETUP IN DFLAG ;DISK FLAG PORT ANIK ACCESSES. ; IN ALL CASES, ONE SECTOR OF DATA IS TRANSFERRED. ; IF THE DISK HAS NOT BEEN PREVIOUSLY ACCESSED, ; THESE ROUTINND EOJ: IN DFLAG ;DISK FLAG PORT RAR JNC EOJ EOJ1: IN DSTAT ;GET THE DISK STATUS STA STATUS ANI 0FCH RET ; SEEK: C DDATA ;GET THE DATA MOV M,A ;STORE IT INX H ;INCREMENT THE MEMORY POINTER DCR C ;LOOP CONTROL JNZ READ1 CALL EOJ ANRROR IF NOT PUSH H ;SAVE POINTER LXI H,IDSV ;SET UP TO READ ADDRESS MVI C,6 ;READ 6 BYTES OF HEADER MVI A,0C4H ;READ ADDCESSARILY ; CORRESPOND WITH THE A REGISTER CONTENT. ; ; THESE ROUTINES ARE CP/M COMPATABLE, AND MAY BE USED ; AS PART OF THE 20H ;SEE IF HEAD IS LOADED MVI A,4 JZ RDWRT1 ;JUMP IF NOT XRA A ;ELSE, RESET THE HEAD LOAD FLAG RDWRT1: ADI 88H ;BUILD AES WILL AUTOMATICALLY DETERMINE THE ; DISK TYPE (8" OR 5"), SINGLE OR DOUBLE DENSITY, ; AND SECTOR SIZE. ; ; BEFORE THE DESIALL IDRD ;INSURE HEADER HAS BEEN READ CNZ EOJB ;RESTORE THE DRIVE IF ERROR RM ;DONE IF NO DRIVE SEEK1: LDA SECTOR ;SET THE# RESS COMMAND CALL RDAT POP H ;RESTORE POINTER RNZ ;DONE IF ERROR ; IDRD2: IN DSCTR ;GET THE TRACK NUMBER OUT DTRCK ;S DW 0,0 DW DIRBF,0 DW CHK01,ALL01 ;DISK PARAMETER HEADER FOR DISK 02 DW 0,0 DW 0,0 DW DIRBF,0 DW CHK02,ALL02 ;DISFH ;INSURE DDEN IS RESET SU1: ORA C ;ADD ON AUTOWAIT BIT OUT DCTRL ;OUTPUT THE SELBITS LDA SIDE ;SET THE SIDE SELECT OUT RVED UNINITIALIZED ;DATA AREA, AND DOES NOT NEED TO BE A PART OF THE ;SYSTEM MEMORY IMAGE (THE SPACE MUST BE AVAILABLE, ;HOWEFT BIT INTO POSITION DCR B JNZ SET1 ;LOOP TIL BIT IS IN POSITION ORI 20H ;ADD ON MOTOR ON BIT MOV M,A ;SAVE IT OUT DCT: DB 1,7,13,19,25 DB 5,11,17,23 DB 3,9,15,21 DB 2,8,14,20,26 DB 6,12,18,24 DB 4,10,16,22 ; MSELTB: DW T5S0,DP5S0 DPET THE TRACK REGISTER ORA A ;INSURE NOT ON TRACK 0 JZ IDRD5 ;JUMP IF NOT OKAY MOV A,M ;REGET SELBITS STA LUNIT ;UPDATE LK PARAMETER HEADER FOR DISK 03 DW 0,0 DW 0,0 DW DIRBF,0 DW CHK03,ALL03 ; ;PARAMETER TABLE FOR DRIVE-UNIQUE CONSTANTS BCTRL RET ; BOTMSG: DB 7,'CANNOT BOO','T'+80H,0DH,8AH LOGMSG: DB MSIZE/10+'0',MSIZE MOD 10 + '0' DB 'k CP/M vers ' DB VVER, BETWEEN "BEGDAT" AND "ENDDAT"). ; ; ;SCRATCH RAM AREA FOR BDOS USE BEGDAT EQU $ ;BEGINNING OF DATA AREA DIRBF: DS 128 RL ;SELECT THE DRIVE CALL EOJB ;RESTORE THE DRIVE RM ;DONE IF DRIVE NOT READY IN BCTRL ;READ THE MINI TRK00 BIT RAR ;I5S0: DW 18 ;SECTORS PER TRACK DB 3 ;BLOCK SHIFT FACTOR DB 7 ;BLOCK MASK DB 0 ;EXTENT MASK DW 71 ;BLOCKS PER DISKETTE DAST USED UNIT XRA A ;RESET ERROR FLAGS RET ; ;SET UP DRIVE NUMBER SETUP: LXI H,CUNIT ;SEE IF DRIVE HAS BEEN ACTIVE MOV PRMTBL: DB 0,0 ;DRIVE 0 STEP RATE, SELECT BYTES DB 0,0 ; 1 DB 0,0 ; 2 DB 0,0 ; 3 ; SELTBL: DW T8S0,DP8S0 ERS/10+'0','.',VERS MOD 10+'0' DB 0DH,8AH ; ; ;FIXED DATA TABLES FOR FOUR-DRIVE STANDARD ;IBM-COMPATIBLE 8" DISKS ;DISK P;SCRATCH DIRECTORY AREA ALL00: DS 31 ;ALLOCATION VECTOR 0 ALL01: DS 31 ;ALLOCATION VECTOR 1 ALL02: DS 31 ;ALLOCATION VECTOR 2SOLATE IT MVI A,STEP5 ;MINI STEP RATE BITS JNC SET2 ;JUMP IF MINI DRIVE MVI A,10H ;ELSE, ADD ON MAXI BIT ORA M MOV M,AW 63 ;# DIRECTORY ENTRIES DB 192 ;ALLOC 0 DB 0 ;ALLOC 1 DW 16 ;DIR CHECK VECTOR SIZE DW 3 ;SYSTEM TRACK OFFSET T5S0: DBA,M ;GET THE SELBITS ORA A ;SEE IF SET UP YET JNZ SU0 ;YES, SKIP INIT CODE ; SETIT: LDA DISKNO ;GET THE DESIRED DRIVE MO DP8S0: DW 26 ;SECTORS PER TRACK DB 3 ;BLOCK SHIFT FACTOR DB 7 ;BLOCK MASK DB 0 ;EXTENT MASK DW 242 ;BLOCKS PER DISKETTEARAMETER HEADER FOR DISK 00 DPBASE: DW 0,0 DW 0,0 DW DIRBF,0 DW CHK00,ALL00 ;DISK PARAMETER HEADER FOR DISK 01 DW 0,0  ALL03: DS 31 ;ALLOCATION VECTOR 3 CHK00: DS 16 ;CHECK VECTOR 0 CHK01: DS 16 ;CHECK VECTOR 1 CHK02: DS 16 ;CHECK VECTOR 2 C MVI A,STEP8 ;SET MAXI STEP RATE SET2: STA STPRAT SU0: IN DDATA ;CLEAR THE STATUS BITS MOV A,M ;REGET THE SELBITS ANI 0B 1,5,9,13,17 DB 3,7,11,15 DB 2,6,10,14,18 DB 4,8,12,16 ; ;END OF FIXED TABLES ; ; ;THE REMAINDER OF THE CBIOS IS RESEV B,A ;SAVE IN WORK REGISTER INR B ;PREPARE TO CONVERT TO SELBITS XRA A ;ZERO TO A STC ;DRIVE SELECT BIT SET1: RAL ;SHI DW 63 ;# DIRECTORY ENTRIES DB 192 ;ALLOC 0 DB 0 ;ALLOC 1 DW 16 ;DIR CHECK VECTOR SIZE DW 2 ;SYSTEM TRACK OFFSET T8S0$ HK03: DS 16 ;CHECK VECTOR 3 ; ENDDAT EQU $ ;END OF DATA AREA DATSIZ EQU $-BEGDAT;SIZE OF DATA AREA ; END  ADD L ;OFFSET THE POINTER MOV L,A MOV A,M ;GET THE CORRECT SECTORS PER TRACK STA SPT ;SAVE IT LXI H,CCP-1 ;GET THE CP; START: MVI A,1 ;TURN OFF THE SHADOW ROM OUT BANK LDA CUNIT ;GET THE SELECT BITS MOV B,A ANI 10H ;SEE IF IT IS A MINI EXT TRACK MOV C,A ;SET THE CORRECT SPT LDA CUNIT MOV B,A ;RESET THE SELBIT OUT DCTRL MVI A,STEPI ;GET A STEP IN COMMANE 56 MACLIB Z80 ; ; THIS BOOT LOADER WILL LOAD THE CP/M SYSTEM IN FROM THE SYSTEM TRACKS ; OF AN 8" DISK. IT IS INDEPENDENDCMD LOAD5: INX H ;INCREMENT THE POINTER IN DDATA ;GET THE DATA MOV M,A ;STORE IT IN DCTRL ;SEE IF INTRQ RELEASED THE WAI/M LOAD ADDRESS LXI D,(BIOS+600H)+2 ;STOP PAGE ADDRESS, START SECTOR MOV A,B ;REGET THE SELBITS OUT DCTRL MVI A,RSTOR ; LXI H,MTBL ;ADDRESS OF MINI SECTORS PER TRACK JRZ LOAD2 ;JUMP IF MINI DRIVE LXI H,TBL ;ADDRESS OF 8" SECTORS PER TRACK LOD MVI E,1 ;RESET SECTOR COUNTER JR LOAD0 ;GO DO THE STEP IN ; TBL: DB 26,15,8,4 ;8" SECTORS PER TRACK TABLE MTBL: DB 18,T OF SECTOR SIZE OR DENSITY. ; ORG 80H ; MSIZE: EQU 20 ;MEMORY SIZE IN KILOBYTES BIAS: EQU (MSIZE-20)*1024 CCP: EQU 2C00HT RAR ;CHECK FOR INTRQ JRNC LOAD5 ;JUMP IF VALID DATA DCX H ;ADJUST THE MEMORY POINTER IN DSTAT ;CHECK THE STATUS ANIHOME THE DISK LOAD0: OUT DCMD LOAD1: IN DCTRL ;WAIT TIL DONE RAR JRNC LOAD1 IN DSTAT ;GET THE STATUS ANI 98H ;MASK FORAD2: MOV C,M ;GET THE TRACK 00 SPT MOV A,B ;REGET THE SELBITS ANI 40H ;SEE IF DOUBLE DENSITY JRZ LOAD3 ;JUMP IF NOT DCX 10,5,2 ;5" SECTORS PER TRACK TABLE +BIAS BIOS: EQU CCP+1600H ;BASE OF BIOS ; SPT: EQU 44H CUNIT: EQU 4AH IDSV EQU 4EH ; ; DCMD: EQU 30H DSTAT: EQU DCMD D 9CH ;MASK FOR READ ERRORS JRNZ START ;TRY AGAIN IF ERROR MOV A,H ;SEE IF ALL IN CMP D JNC BIOS ;JUMP IF SO MOV A,E ;N ERRORS JRNZ START ;TRY AGAIN IF ERRORS LOAD4: MOV A,E ;GET THE START SECTOR OUT DSCTR IN DDATA ;CLEAR ANY BOGUS STATUS BH ; ELSE, ADJUST POINTER FOR DDEN SPT LOAD3: XRA B ;BUILD TRACK 00 SELBITS MOV B,A ;SAVE IN (B) LDA IDSV+3 ;GET SECTOR SIZESCTR: EQU DCMD+2 DDATA: EQU DCMD+3 DCTRL: EQU DCMD+4 ; BANK: EQU 40H ; ; RSTOR: EQU 0DH RDSEC: EQU 88H STEPI: EQU 5DH O, CHECK FOR TRACK OVERFLOW INR E ;INCREMENT SECTOR POINTER CMP C JRNZ LOAD4 ;JUMP IF NO OVERFLOW LDA SPT ;ELSE, GO TO N; ;CP/M 2.2 BOOT FOR CCS 2442 MULTIMODE DISK CONTROLLER ; TITLE 'CCS 2422 MULTIMODE DISK CONTROLLER BOOT FOR CP/M 2.2' PAGITS MOV A,B ;GET THE SELECT BITS ORI 80H ;SET THE AUTO-WAIT BIT OUT DCTRL MVI A,RDSEC ;START THE TRACK READ GOING OUT % 047 ; 134.5 857 ; 150 768 ; 300 384 ; 600 192 ; 1200 96 ; 1800 64 ; 2000 58 ; 2400 48 ; 3600 32 ; 4800 24 ;UPT ENABLE PORT SIDENT: EQU SDATA+2 ;SERIAL INTERRUPT IDENTIFICATION PORT SLCTRL: EQU SDATA+3 ;SERIAL LINE CONTROL PORT SMDMCSTBUF: EQU 4CH ;HOST BUFFER ADDRESS IDSV: EQU 4EH ;SECTOR ID SAVE AREA TBUF: EQU 80H TPA: EQU 100H ; ORG BIOS ;ORIGIN OF T 56 ; ; ; THIS BIOS IS SET UP FOR AUTO SELECT OF DISK CHAR ; ;"BIAS" IS ADDRESS OFFSET FROM 2C00H FOR MEMORY SYSTEMS ;THAN1 WRUAL: EQU 2 ; ; CR: EQU 0DH ;ASCII CARRIAGE RETURN LF: EQU 0AH ;ASCII LINE FEED IOBYTE: EQU 3 ;ADDRESS OF I/O CONTROL B 7200 16 ; 9600 12 ; 19200 6 ; 38400 3 ; 56000 2 ; SBAUD: EQU 12 ;9600 BAUD DIVISOR FOR 2810 ; DSTAT EQU 30H ;DISK T: EQU SDATA+4 ;SERIAL MODEM CONTROL PORT SLSTAT: EQU SDATA+5 ;SERIAL LINE STATUS PORT SMDMST: EQU SDATA+6 ;SERIAL MODEM STATUHIS PROGRAM ; ;JUMP VECTOR FOR INDIVIDUAL SUBROUTINES JMP BOOT ;COLD START WBOOTE: JMP WBOOT ;WARM START CSTAT: JMP CONST  20K (REFERRED TO AS "B" THROUGHOUT THE TEXT). ; VERS: EQU 22 ;CP/M VERSION NUMBER MSIZE: EQU 20 ;CP/M VERSION MEMORY SIZE INYTE ; DISKNO: EQU 40H ;ACTIVE DISK NUMBER TRACK: EQU DISKNO+1 SECTOR: EQU TRACK+1 SIDE: EQU SECTOR+1 ;SIDE SELECT HOLD ARE; ; 17 JUL 80 ; ; MODIFIED FOR UNALLOCATED WRITE CORRECTIONS 8 SEP 80 ; MODIFIED FOR AUTO-BOOT OPERATION 7 SEP 80 ; MODIFIESTATUS PORT DCMMD EQU DSTAT ;DISK COMMAND PORT DTRCK EQU DSTAT+1 ;DISK TRACK PORT DSCTR EQU DSTAT+2 ;DISK SECTOR PORT DDATA S PORT ; ; WHEN THE AUTO-BOOT JUMPER IS ENABLED, THE 2810 ; SERIAL PORT WILL BE INITIALIZED TO 9600 BAUD. ; TO SELECT A DI;CONSOLE STATUS CONIN: JMP CONI ;CONSOLE CHARACTER IN CONO: JMP CONOUT ;CONSOLE CHARACTER OUT JMP LIST ;LIST CHARACTER OUT  KILOBYTES BIAS: EQU (MSIZE-20)*1024 CCP: EQU 2C00H+BIAS ;BASE OF CCP BDOS: EQU CCP+806H ;BASE OF BDOS BIOS: EQU CCP+1600H ;A SPT: EQU SIDE+1 ;SECTORS PER TRACK HOLD TWOSID: EQU SPT+1 ;SINGLE/DOUBLE SIDED SWITCH HOLD STPRAT: EQU 46H ;STEP RATE SAVE D FOR COMPUTED SKEW FACTORS 7 SEP 80 ; MODIFIED FOR WARM BOOTS FROM MINIS 14 AUG 80 ; MODIFIED FOR PROPER DEFAULT DISK RESTORAEQU DSTAT+3 ;DISK DATA PORT DFLAG EQU DSTAT+4 ;DISK FLAF PORT DCTRL EQU DSTAT+4 ;DISK CONTROL PORT BCTRL: EQU 4 ;DISK STATUS FFERENT BAUD RATE, CHANGE SBAUD ; TO ONE OF THE FOLLOWING VALUES: ; ; BAUD RATE SBAUD ; 50 2304 ; 75 1536 ; 110 1 JMP PUNCH ;PUNCH CHARACTER OUT JMP READER ;READER CHARACTER OUT JMP HOME ;MOVE HEAD TO HOME POSITION JMP SELDSK ;SELECT DBASE OF BIOS WBOOTV: EQU 0 CDISK: EQU 4 BDOSV: EQU 5 ; SDATA: EQU 20H ;SERIAL DATA PORT SINTEN: EQU SDATA+1 ;SERIAL INTERRAREA STATUS: EQU 47H CMND: EQU STATUS+1 LUNIT: EQU 49H ;LAST USED DRIVE CUNIT: EQU LUNIT+1 ;CURRENT DRIVE RWFLG: EQU 4BH HL ON WARM BOOT 12 AUG 80 ; MODIFIED FOR 2 MHZ 8080 OPERATION 12 AUG 80 ; TITLE 'CCS 2422 DEBLOCKED BIOS FOR CP/M 2.2' PAGE2 PORT ; STEP5: EQU 3 ;MINI DISK STEP RATE STEP8: EQU 2 ;8" DISK STEP RATE ; ;DEBLOCK PARAMETERS WRALL: EQU 0 WRDIR: EQU & ISK JMP SETTRK ;SET TRACK NUMBER JMP SETSEC ;SET SECTOR NUMBER JMP SETDMA ;SET DMA ADDRESS JMP READ ;READ DISK JMP WRIE SHLD WBOOTV+1 LXI H,BDOS SHLD BDOSV+1 LXI H,DBUF ;SET UP BUFFER ADDRESS SHLD HSTBUF LXI H,80H ;DEFAULT DMA ADDRESS ;CURRENT VALUE OK IF DDEN SET LDA IDSV+3 ;GET SECTOR SIZE INDICATOR DCR A ;SEE WHICH SIZE JM LOAD2A ;JUMP IF 128 BYTE SEC1: MOV L,A ;L=DISK NUMBER 0,1,2,3 DAD H ;*2 DAD H ;*4 DAD H ;*8 DAD H ;*16 (SIZE OF EACH HEADER) XCHG LXI H,DPBASE A POP B LXI H,CCP SHLD HSTBUF IN BCTRL ;SET # OF SECTORS FOR TRK00 ANI 2 ;ISOLATE MINI/MAXI BIT MVI B,26 ;HOLD THE SUT SDATA ;SET DIVISOR LOW BYTE MVI A,3 ;SET 8250 LINE CONTROL OUT SLCTRL XRA A ;SET HANDSHAKE LINES ACTIVE OUT SINTEN TE ;WRITE DISK JMP LISTST ;RETURN LIST STATUS JMP SECTRAN ;SECTOR TRANSLATE ; ;INDIVIDUAL SUBROUTINES TO PERFORM EACH FUNC IS 80H SHLD DMAAD EI ;ENABLE THE INTERRUPT SYSTEM XRA A ;SET UP DEBLOCK STA HSTACT ;HOST NOT ACTIVE LDA SEKDSK ;GET TORS MVI B,10 ;SPT FOR 256 BYTE SECTORS JZ LOAD2A MVI B,5 ;SPT FOR 512 BYTE SECTORS LOAD2A: XRA A LOAD3: INR A STA SEC DAD D ;HL=.DPBASE(DISKNO*16) ; CKSET: PUSH H ;SAVE (H,L) MOV A,C ;REGET UNIT ADD A ;OFFSET INTO TABLE ADD C ; * 3 LXPT IN (B) JZ LOAD2 ;JUMP IF 8" MVI B,18 ;SET MINI SPT LOAD2: PUSH B CALL DREAD POP B ORA A JNZ RETRY SHLD HSTBUF OUT SLSTAT BOOTA: LXI H,LOGMSG ;SIGN ON TO THE SYSTEM CALL PRTWD LXI H,0 SHLD IOBYTE ;SET IOBYTE, CDISK JMP BOOT0 ; TION ; ; RETRY: DCR C JNZ LOAD1 LXI H,BOTMSG CALL PRTWD CALL CONIN CALL PRTWD WBOOT: LXI SP,TBUF MVI C,10 ;# OF OLD DEFAULT DRIVE STA CDISK MOV C,A ;SEND TO THE CCP JMP CCP+3 ;GO TO CPM ; BOOT: IN DCTRL ;SEE IF AUTO-BOOT IN PROGRESSTOR MVI A,BIOS/256 SUB H ;SEE IF ENOUGH LOADED IN ANI 0FCH JNZ LOAD2 ;JUMP IF MORE NEEDED ; ;END OF LOAD OPERATION, SEI H,PRMTBL+1 ;POINT TO SELBITS MOV E,A DAD D ;OFFSET THE TABLE POINTER MOV A,M ;GET THE SELBITS ORA A STA SEKSEL JN LDA SECTOR CMP B ;SEE IF READY TO STEP IN JC LOAD3 LDA TRACK INR A STA TRACK IN BCTRL ;SET THE NEW SPT VALUE ANI; ;SELECT DISK GIVEN BY REGISTER C SELDSK: MOV A,C STA SEKDSK SELDSKA: LXI H,0 ;ERROR RETURN CODE CPI 4 ;MUST BE BETWEENRETRIES LOAD1: XRA A MOV H,A ;SET THE UNIT AND TRACK MOV L,A SHLD DISKNO LXI H,0D002H ;SET THE SIDE AND SECTOR SHLD  ANI 40H ;ISOLATE THE BOOT BIT JNZ BOOTA ;JUMP IF NOT AUTO-BOOT MVI A,0FH ;SET MODEM CONTROL REGISTER OUT SMDMCT MVI AT PARAMETERS AND GO TO CP/M BOOT0: MVI A,JMP ;GET A JUMP OP CODE STA WBOOTV ;RESET THE JUMP VECTORS STA BDOSV LXI H,WBOOTZ SET4 ;JUMP IF ALREADY ESTABLISHED XCHG ;ELSE, ESTABLISH NEW DISK INR L ;INSURE LUNIT<>CUNIT SHLD LUNIT ; TO FORCE A RE 2 ;SEE IF MINI OR MAXI JZ LOAD2A ;CURRENT VALUE GOOD FOR MAXI, JUMP LDA CUNIT ;SEE IF DOUBLE DENSITY ANI 40H JNZ LOAD2A 0 AND 3 RNC ;NO CARRY IF 4,5,... ;DISK NUMBER IS IN THE PROPER RANGE ;COMPUTE PROPER DISK PARAMETER HEADER ADDRESS SELDSKSECTOR MVI B,12 ;ZERO OUT PRMTBL LXI H,PRMTBL LOAD1A: MOV M,A INX H DCR B JNZ LOAD1A PUSH B MOV C,A CALL SELDSK,83H ;SET BAUD RATE DIVISOR ACCESS OUT SLCTRL MVI A,SBAUD/256 ;SET DIVISOR HIGH BYTE OUT SINTEN MVI A,SBAUD MOD 256 O' AD ADDRESS LHLD DISKNO ;FIRST, SAVE CURRENT DISK ASSIGNMENTS XTHL ;SAVE IN THE STACK PUSH H LHLD SECTOR XTHL PUSH HSECTOR POP H XTHL SHLD DISKNO SET4: POP H MOV A,C RET ; ;SET TRACK GIVEN BY REGISTER C SETTRK: MOV A,C STA SEKTRENTRIES DAD D DAD D DAD D SETUP3: DAD D ;OFFSET TABLE ADDRESS DCR C JP SETUP3 SET3: XCHG ;SAVE THE POINTER POP H  C,0FFH ;GET A -1 SECT2: INR C ;BUILD SECTOR OFFSET IN (C) SUB M JNC SECT2 ;LOOP TIL OFFSET IS BUILT INX H ;POINT TO SKEW ;ALSO SAVE IN REGISTER LXI D,4 ;ADDRESS TABLE ENTRY OFFSET LXI H,MSELTBL-4 ;MINI TABLE ADDRESS MOV A,B ;REGET THE SELBITADD E MOV E,A ;TABLE OFFSET NOW IN (D,E) LXI H,PRMTBL+2 DAD D MOV D,M ;SECTOR SIZE NOW IN (D) PUSH D ;SAVE FOR LATER U MOV A,C ;REGET DESIRED UNIT STA DISKNO ;SET NEW DISK NUMBER MVI A,0D0H ;SELECT SIDE 0 OF NEW DISK STA SIDE PUSH B PK RET ; ;SET SECTOR GIVEN BY REGISTER C SETSEC: MOV A,C ANI 7FH ;STRIP OFF SIDE INDICATOR DCR A STA SEKSEC MOV A,C  XTHL PUSH H ;GET, RESAVE DP BLOCK POINTER LDAX D ;MOVE THE TABLE ENTRIES MOV M,A INX D INX H LDAX D MOV M,A IN FACTOR XRA A ; AND GET A ZERO SECT3: ADD M ;BUILD THE SKEWED SECTOR NUMBER DCR E JP SECT3 SUB M ADD C ;ADD ON THE OFS ANI 10H ;ISOLATE THE MINI DRIVE BIT JZ SETUP1 ;JUMP IF MINI LXI H,SELTBL-4 ; ELSE, SET THE 8" TABLE ADDRESS IN BCTRLSE MOV A,C ;GET THE DESIRED SECTOR STA CPMSEC RAL SECT0: ORA A ;CONVERT TO PHYSICAL SECTOR NUMBER RAR DCR D JP SECTUSH D ;SAVE THE REGISTERS CALL IDRD ;FIND OUT WHAT IS OUT THERE POP H ;REGET SELECT TABLE ADDRESS DCX H ;POINT TO STEP RAT;REGET SECTOR NUMBER RAL ;ISOLATE SIDE BIT MVI A,0D0H ;SET UP SIDE SELECT BITS JNC SETSEC1 MVI A,90H ;SELECT SIDE 1 SEX D PUSH D ;SAVE IT FOR A MOMENT LXI D,9 DAD D ;OFFSET THE POINTER POP D ;REGET TABLE ADDRESS LDAX D ;MOVE THE TABLE EFSET SECT4: SUB D ;INSURE NUMBER IS IN RANGE JNC SECT4 ADD D SECT5: MOV L,A ;MOVE SKEWED NUMBER OVER TO (L) INR A ;SET P ;CHECK FOR DOUBLE SIDED DISK ANI 40H ;ISOLATE TWO-SIDED BIT JNZ SETUP1 ;JUMP IF SINGLE-SIDED LXI H,SELTBLA-4 SETUP1: MOV0 POP D POP H ;REGET TABLE ADDRESS CMP M ;SEE IF SIDE 1 JC SECT1 ;JUMP IF SIDE 0 MVI B,80H ;FLAG BIT FOR SIDE 1 SUB E LDA STPRAT ;SET THE STEP RATE MOV M,A ;SAVE THE STEP RATE INX H LDA CUNIT ;GET THE SELBITS STA SEKSEL MOV B,A ;SAVTSEC1: STA SEKSID ;SET THE SIDE SELECT BITS RET ; ;TRANSLATE THE SECTOR GIVEN BY BC USING THE ;TRANSLATE TABLE GIVEN BY DE NTRIES MOV M,A INX D INX H LDAX D MOV M,A POP H ;RESTORE THE CURRENT DRIVE POP B ;RESTORE REGISTERS XTHL SHLD YHS SECTOR FOR ANTIC. LOGIC STA NXTSCT XRA A ;CONVERT PHYSICAL TO LOGICAL SECTOR MOV H,A SECT6: DCR B JM SECT7 ;JUMP IF A,B ;CHECK FOR DOUBLE DENSITY ANI 40H ;ISOLATE THE BIT JZ SETUP3 ;JUMP IF SINGLE-DENSITY DAD D ;OFFSET TO DOUBLE DENSITY M SECT1: PUSH B MOV B,D ;SAVE SECTOR SIZE IN (B) MOV E,A ;SET UP TO BUILD SKEW MOV D,M ;GET THE SKEW FACTOR INX H MVIE THE SELBITS MOV M,A ;SET THE TABLE INX H ;POINT TO SECTOR SIZE ENTRY LDA IDSV+3 ;SET THE SECTOR SIZE MOV M,A MOV C,A SECTRAN: PUSH D ;SAVE THE TABLE ADDRESS LDA SEKDSK ;FIND THE SECTOR SIZE MOV E,A MOV D,B ;GET A ZERO FROM (B) ADD A (  DONE STC ADC A ;BUILD THE MASK DAD H ;OFFSET THE SECTOR NUMBER JMP SECT6 SECT7: POP B ANA C ;STRIP OUT THE SUB-SECTOMVI M,1 ;MARK IT ACTIVE FOR NEXT TIME JZ FILHST ;FILL THE HOST BUFFER IF EMPTY ; CALL PHYSEC ;SET THE PHYSICAL SECTOR NUMBELOCK STA UNACNT ;SAVE THE SECTOR COUNT ; CHKUNA: LXI H,UNACNT ;SEE IF ANY UNALLOCATED SPACE AVAILABLE XRA A CMP M JZ  D ;GET A BYTE MOV M,A ;PUT IT INX D INX H DCR C ;LOOP CONTROL JNZ RWMOVE ; LDA WRTYPE ;GET WRITE TYPE DCR A ;SEEWRITE OPERATION STA READOP MOV A,C ;WRITE TYPE FROM CP/M STA WRTYPE CPI WRUAL ;SEE IF UNALLOCATED JNZ CHKUNA ;JUMP IF  SIZE XRA A ;GET A ZERO MATCH1: ADC A ;BUILD SECTOR MASK DCR H STC JP MATCH1 ;LOOP TIL MASK IS BUILT LHLD SEKSEC ANR ORA L ;ADD IT TO THE SKEWED SECTOR INR A ORA B ;ADD ON THE SIDE SELECT BIT MOV L,A RET ; ; ;SET DMA ADDRESS GIVENR LXI D,DISKNO CALL COMP ;COMPARE THE UNITS JZ MATCH ; NOMATCH: LDA HSTWRT ;SEE IF HOST WRITTEN ORA A CNZ DWRITA ;PUALLOC1 ;JUMP IF NOT DCR M ;ELSE, USE SOME OF IT CALL PHYSEC ;SET THE PHYSICAL SECTOR NUMBER LXI D,UNADSK CALL COMP ;COMP IF DIRECTORY ENTRY LDA ERFLAG ;GET THE ERROR FLAG RNZ ;DONE IF NOT DIRECTORY ENTRY ; ORA A ;SEE IF ANY ERRORS RNZ ;RNOT ; ; UNALLOCATED WRITE, SET PARAMETERS CALL PHYSEC ;CONVERT TO PHYSICAL SECTOR LHLD SEKHST ;SET PHYSICAL SECTOR AND SIDA L ;FIND THE RELATIVE SECTOR LXI H,DBUF-80H ;BUILD ADDRESS FOR CPM SECTOR LXI B,80H ;# BYTES IN LOGICAL SECTOR MATCH2: DAD BY REGISTERS B AND C SETDMA: MOV L,C ;LOW ORDER ADDRESS MOV H,B ;HIGH ORDER ADDRESS SHLD DMAAD ;SAVE THE ADDRESS RET ; RGE THE BUFFER IF NEED BE FILHST: CALL PHYSEC MOV A,D STA IDSV+3 LHLD SEKDSK ;SET UP TO FILL THE BUFFER SHLD DISKNO LARE THE UNITS JZ NXTSEC ;GO DO THE WRITE ; ALLOC: XRA A ;ALLOCATED WRITE REQUIRES PREREAD STA UNACNT ALLOC1: INR A ALLOCETURN IF SO STA HSTWRT ;RESET HOST WRITTEN DWRITA: CALL DWRITE ;UPDATE THE DIRECTORY LXI H,ERFLAG ORA M ;GET THE ERROR INE SHLD UNASEC LHLD SEKDSK ;GET THE DISK NUMBER SHLD UNADSK ;SAVE IT FOR UNALLOCATED WRITE MOV A,L CALL DPFND ;GET DP T B DCR A JP MATCH2 XCHG ;BUFFER ADDRESS TO (D,E) LHLD DMAAD ;GET DMA ADDRESS LDA READOP ;SEE IF READ OR WRITE ORA A ;MOVE TO THE TRACK 00 POSITION OF CURRENT DRIVE HOME: SUB A STA SEKTRK RET ; ;DEBLOCK ROUTINES ; READ: MVI A,WRUAL ;TRHLD SEKHST ;GET THE SECTOR, SIDE SELECT SHLD SECTOR ;SET THEM LDA SEKSEL STA CUNIT LDA RSFLAG ORA A CNZ DREAD ;FILL 2: STA RSFLAG ; RWOPER: XRA A ;GET A ZERO STA ERFLAG ;RESET THE ERROR FLAG ; LXI H,HSTACT ;SEE IF HOST ACTIVE ORA M DICATIONS MOV M,A ;STORE THE ERROR FLAGS RET ; ; UNALLOCATED WRITE NEXT SECTOR ANTICIPATION LOGIC ; NXTSEC: LDA SEKDSK ;ABLE ADDRESS INX D ;OFFSET TO THE BLOCK MASK INX D INX D LDAX D ;GET THE BLOCK MASK INR A ;(A) = LOGICAL SECTORS PER B JNZ RWMOVE ;POINTERS OK IF READ ; XCHG ;ELSE, SWAP THEM INR A ; AND MARK WRITE OPERATION STA HSTWRT ; RWMOVE: LDAXEAT READ AS UNALLOCATED STA WRTYPE STA READOP ;SET A READ OPERATION JMP ALLOC ;GO DO THE READ ; WRITE: XRA A ;FLAG AS A IT IF NEED BE LXI H,ERFLAG ORA M MOV M,A XRA A ;RESET PENDING WRITE FLAG STA HSTWRT ; MATCH: LHLD IDSV+2 ;GET SECTOR) FIND ADDRESS OF DP TABLE CALL DPFND LDA CPMSEC ;GET LAST LOGICAL SECTOR NUMBER INR A XCHG ;DP TABLE ADDRESS TO (H,L)  DISK ACCESSES. ; IN ALL CASES, ONE SECTOR OF DATA IS TRANSFERRED. ; IF THE DISK HAS NOT BEEN PREVIOUSLY ACCESSED, ; THESE ROGET BASE ADDRESS DAD D ;POINT TO SECTOR SIZE MOV D,M ;GET THE SECTOR SIZE PUSH D LDA SEKSEC ;GET THE LOGICAL SECTOR NUMB: IN DDATA ;READ THE DATA MOV M,A ;PUT INTO BUFFER INX H ;INCREMENT MEMORY POINTER IN DDATA ;READ THE DATA MOV M,A ;PUT  SHLD UNASEC ;SET THE NEXT SIDE, SECTOR XRA A ;GET A ZERO JMP ALLOC2 ;GO BACK TO MAINSTREAM ; ; FIND ADDRESS OF DISK PARAMT NECESSARILY ; CORRESPOND WITH THE A REGISTER CONTENT. ; ; THESE ROUTINES ARE CP/M COMPATABLE, AND MAY BE USED ; AS PART OFCMP M ;SEE IF OVERFLOW JNC NXTSC2 ;JUMP IF SO LXI H,-11 ;SAME TRACK, NOW SEE WHICH SIDE/SECTOR DAD D MOV E,M ;GET ADDRESUTINES WILL AUTOMATICALLY DETERMINE THE ; DISK TYPE (8" OR 5"), SINGLE OR DOUBLE DENSITY, ; AND SECTOR SIZE. ; ; BEFORE THE ER RAL PHYSC1: ORA A ;RESET THE CARRY BIT RAR ;CONVERT TO PHYSICAL SECTOR DCR D JP PHYSC1 INR A ;(A) NOW HAS PHYSICAINTO BUFFER INX H ;INCREMENT MEMORY POINTER IN DDATA ;READ THE DATA MOV M,A ;PUT INTO BUFFER INX H ;INCREMENT MEMORY POIETER TABLE ; DPFND: LXI H,DPBASE-6 ;DEVELOP ADDRESS OF DPTABLE LXI D,16 DPFND1: DAD D DCR A JP DPFND1 MOV E,M ;PULL  THE BIOS. ; ; DREAD: DB 3EH ;SIM. MVI A INSTR DWRITE: XRA A ;SET WRITE FLAG STA RWFLG ;SAVE IT FOR LATER USE MVI B,10 ;S OF SKEW TABLE INX H MOV D,M MOV C,A ;SET UP TO CALL SECTRAN MVI B,0 CALL SECTRAN ;TRANSLATE THE SECTOR MVI H,0D0H DESIRED DATA IS TRANSFERRED, THE DESIRED ; TRACK IS SEEKED OUT, THE DESIRED SECTOR AND SIDE IS ; SET, THEN THE ACTUAL DATA TRAL SECTOR # STA SEKHST ;SET IT POP D RET ; ;COMPARE THE UNITS COMP: LXI H,SEKDSK MVI B,4 COMP1: LDAX D SUB M RNZ NTER IN DDATA ;READ THE DATA MOV M,A ;PUT INTO BUFFER INX H ;INCREMENT MEMORY POINTER DCR B JNZ READ1 CALL EOJ ANIUP THE ADDRESS INX H MOV D,M RET ; ; LOGICAL TO PHYSICAL SECTOR TRANSLATION ROUTINE PHYSEC: LDA SEKDSK ;GET THE LOGICALNUMBER OF RETRIES AGN: PUSH B CALL SEEK CZ RDWR READ3: POP B RZ DCR B JNZ AGN RET ; RDWR: MOV E,A ;SAVE COMMAND ;SIDE 0 SELECT JP NXTSC1 ;JUMP IF SIDE 0 MVI H,090H ;ELSE, SET SIDE 1 NXTSC1: LDA NXTSCT ;GET THE NEXT PHYSICAL SECTOR MONSFER. ; ; UP TO TEN TRIES WILL BE ATTEMPTED BEFORE THE DATA ; TRANSFER IS ABORTED. ON RETURN TO THE CALLING ; ROUTINE, THE ;DONE IF NO COMPARE INX H ;POINT TO SEKTRK INX D DCR B JNZ COMP1 RET ; ; ; THE FOLLOWING ROUTINES DO THE PRIMITIVE 9CH ;ISOLATE READ ERROR BITS RET ; WRDAT: ORI 20H ;ADD WRITE COMMAND STA CMND OUT DCMMD ;DISK COMMAND PORT WRT1: MOV A SECTOR NUMBER MOV E,A ;SAVE IT MVI D,0 ADD A ;MULTIPLY BY 3 ADD E MOV E,A ;TABLE OFFSET NOW BUILT LXI H,PRMTBL+2 ; LDA RWFLG ORA A MOV A,E ;REGET THE COMMAND JZ WRDAT ;WRITE IF ZERO RDAT: STA CMND OUT DCMMD ;DISK COMMAND PORT READ1V L,A ;SET THE SECTOR JMP NXTSC3 ; NXTSC2: LXI H,UNATRK ;SET FOR NEXT TRACK INR M LXI H,0D001H ;SIDE 0 SECTOR 1 NXTSC3: A REGISTER WILL CONTAIN A ZERO IF THE ; OPERATION WAS SUCCESSFUL, OR NON-ZERO IF NOT ; SUCCESSFUL. THE FLAG REGISTER WILL NO* ,M ;GET DATA FROM BUFFER OUT DDATA ;OUTPUT IT INX H ;ADVANCE MEMORY POINTER MOV A,M ;GET DATA FROM BUFFER OUT DDATA ;OUTI B,58H ;BUILD A STEP-IN COMMAND CALL EOJA IDRD: LHLD LUNIT MOV A,H ;GET THE CUNIT VALUE CMP L ;SEE IF SAME AS LUNIT RZRT ANI 20H ;SEE IF HEAD IS LOADED MVI A,4 JZ RDWRT1 ;JUMP IF NOT XRA A ;ELSE, RESET THE HEAD LOAD FLAG RDWRT1: ADI 88H O POSITION DCR B JNZ SET1 ;LOOP TIL BIT IS IN POSITION ORI 20H ;ADD ON MOTOR ON BIT MOV M,A ;SAVE IT OUT DCTRL ;SELECT SEEK: CALL IDRD ;INSURE HEADER HAS BEEN READ CNZ EOJB ;RESTORE THE DRIVE IF ERROR RM ;DONE IF NO DRIVE SEEK1: LDA SECTOR ACK REGISTER CPI 2 ;INSURE NOT ON TRACK 0 OR 1 JC IDRD5 ;JUMP IF SO MOV A,M ;REGET SELBITS STA LUNIT ;UPDATE LAST USED UPUT IT INX H ;ADVANCE MEMORY POINTER MOV A,M ;GET DATA FROM BUFFER OUT DDATA ;OUTPUT IT INX H ;ADVANCE MEMORY POINTER  ;RETURN IF SO IDRD1: MVI C,80H ;SET THE AUTO-WAIT BIT CALL SETUP CALL EOJ1 ;INSURE A DRIVE IS THERE RM ;ERROR IF NOT ;BUILD A READ SECTOR COMMAND LHLD HSTBUF ;GET THE DMA ADDRESS MOV C,A ;SAVE THE COMMAND IN C IN DTRCK ;SEE IF ON TRACK 0  THE DRIVE CALL EOJB ;RESTORE THE DRIVE RM ;DONE IF DRIVE NOT READY IN BCTRL ;READ THE MINI TRK00 BIT RAR ;ISOLATE IT ;SET THE SECTOR OUT DSCTR ;DISK SECTOR PORT IN DTRCK ;DISK TRACK PORT MOV C,A ;SAVE IT LDA TRACK ;GET DESIRED TRACK CMNIT XRA A ;RESET ERROR FLAGS RET ; ;SET UP DRIVE NUMBER SETUP: LXI H,CUNIT ;SEE IF DRIVE HAS BEEN ACTIVE MOV A,M ;GET TMOV A,M ;GET DATA FROM BUFFER OUT DDATA ;OUTPUT IT INX H ;ADVANCE MEMORY POINTER DCR B JNZ WRT1 JMP EOJ ; EOJB: MVI  PUSH H ;SAVE POINTER LXI H,IDSV ;SET UP TO READ ADDRESS MVI B,2 ;SET UP TO READ 6(8) BYTES OF DATA MVI A,0C4H ;READ ADDRE ORA A JZ RDWRT3 ;SET SECTOR SIZE = 0 LDA IDSV+3 ;GET THE SECTOR SIZE RDWRT3: MOV B,A ;PUT IN B FOR LOOP CONTROL MVI A,10 MVI A,STEP5 ;MINI STEP RATE BITS JNC SET2 ;JUMP IF MINI DRIVE MVI A,10H ;ELSE, ADD ON MAXI BIT ORA M MOV M,A MVI A,SP C JZ RDWRT ;JUMP IF NO SEEK NEEDED OUT DDATA ;SET THE SEEK TRACK MVI B,1CH ;BUILD THE SEEK COMMAND CALL EOJA ;DO THE SHE SELBITS ORA A ;SEE IF SET UP YET JNZ SU0 ;YES, SKIP INIT CODE ; SETIT: LDA DISKNO ;GET THE DESIRED DRIVE MOV B,A ;SAVB,8 ;BASIS OF RESTORE COMMAND EOJA: LDA STPRAT ;GET THE STEP RATE BITS ORA B ;ADD ON THE COMMAND STA CMND OUT DCMMD ;DO TSS COMMAND CALL RDAT POP H ;RESTORE POINTER JZ IDRD2 ;JUMP IF GOOD READ MVI A,40H ;SEE IF DDEN IS SET CMP M RC ;TAKH ;SECTOR BASE LENGTH RDWRT0: ADD A DCR B JP RDWRT0 MOV B,A MOV A,C RDWRT2: CMP A ;CLEAR THE FLAGS RET ; IDRD5: MVTEP8 ;SET MAXI STEP RATE SET2: STA STPRAT SU0: IN DTRCK ;ELSE, SEE IF TRACK ZERO ORA A IN DDATA ;CLEAR OUT ANY JUNK MOV EEK ANI 98H ;SEEK ERROR MASK RNZ ;DONE IF SEEK ERROR RDWRT: MVI C,80H ;AUTO-WAIT BIT CALL SETUP IN DFLAG ;DISK FLAG POE IN WORK REGISTER INR B ;PREPARE TO CONVERT TO SELBITS XRA A ;ZERO TO A STC ;DRIVE SELECT BIT SET1: RAL ;SHIFT BIT INTHE COMMAND EOJ: IN DFLAG ;DISK FLAG PORT RAR JNC EOJ EOJ1: IN DSTAT ;GET THE DISK STATUS STA STATUS ANI 0FCH RET ; E THE ERROR IF SO ORA M ;ELSE, TRY DDEN MOV M,A JMP IDRD ; IDRD2: IN DSCTR ;GET THE TRACK NUMBER OUT DTRCK ;SET THE TR+ A,M ;REGET THE SELBITS JNZ SU1 ANI 0BFH ;INSURE DDEN IS RESET SU1: ORA C ;ADD ON AUTOWAIT BIT OUT DCTRL ;OUTPUT THE SELBI MASK DB 1 ;EXTENT MASK DW 149 ;BLOCKS PER DISKETTE DW 63 ;# DIRCTORY ENTRIES DB 128 ;ALLOC 0 DB 0 ;ALLOC 1 DW 16 ;DB 7 ;BLOCK MASK DB 0 ;EXTENT MASK DW 242 ;BLOCKS PER DISKETTE DW 63 ;# DIRCTORY ENTRIES DB 192 ;ALLOC 0 DB 0 ;ALLOC 1 R SIZE DW 2 ;SYSTEM TRACK OFFSET ; SELTBLA: DW T826,DP8D1 DW T815,DP8D2 DW T88,DP8D3 DW T84,DP8D3 DW T848,DP8D0A DW 0,0 DW DIRBF,0 DW CHK02,ALL02 ;DISK PARAMETER HEADER FOR DISK 03 DW 0,0 DW 0,0 DW DIRBF,0 DW CHK03,ALL03 ; ;PAR VECTOR SIZE DW 2 ;SYSTEM TRACK OFFSET DP8D2: DW 60 ;SECTORS PER TRACK DB 5 ;BLOCK SHIFT FACTOR DB 31 ;BLOCK MASK DB 3 TS LDA SIDE ;SET THE SIDE SELECT OUT BCTRL RET ; BOTMSG: DB 7,'CANNOT BOO','T'+80H,0DH,8AH LOGMSG: DB MSIZE/10+'0',MSIZIR CHECK VECTOR SIZE DW 2 ;SYSTEM TRACK OFFSET DP8D0: DW 48 ;SECTORS PER TRACK DB 4 ;BLOCK SHIFT FACTOR DB 15 ;BLOCK MASK DW 16 ;DIR CHECK VECTOR SIZE DW 2 ;SYSTEM TRACK OFFSET DP8S1: DW 30 ;SECTORS PER TRACK DB 4 ;BLOCK SHIFT FACTOR DB 15 ;W T826,DP8D1A DW T815,DP8D2A DW T88,DP8D3A ; DP8D0A: DW 96 ;SECTORS PER TRACK DB 5 ;BLOCK SHIFT FACTOR DB 31 ;BLOCK MAAMETER TABLE FOR DRIVE-UNIQUE CONSTANTS PRMTBL: DB 0,0,0 ;DRIV 0 STP RAT, SLCT BYTS, SCTR SZ DB 0,0,0 ; 1 DB 0,0,0 ; ;EXTENT MASK DW 139 ;BLOCKS PER DISKETTE DW 127 ;# DIRECTORY ENTRIES DB 128 ;ALLOC 0 DB 0 ;ALLOC 1 DW 32 ;DIR CHECK VEE MOD 10 + '0' DB 'k CP/M Vers ' DB VERS/10+'0','.',VERS MOD 10+'0' DB 0DH,8AH ; ; ;FIXED DATA TABLES FOR FOUR-DRIVE ST DB 1 ;EXTENT MASK DW 195 ;BLOCKS PER DISKETTE DW 63 ;# DIRECTORY ENTRIES DB 128 ;ALLOC 0 DB 0 ;ALLOC 1 DW 16 ;DIR CBLOCK MASK DB 1 ;EXTENT MASK DW 139 ;BLOCKS PER DISKETTE DW 63 ;# DIRCTORY ENTRIES DB 128 ;ALLOC 0 DB 0 ;ALLOC 1 DW SK DB 3 ;EXTENT MASK DW 225 ;BLOCKS PER DISKETTE DW 127 ;# DIRECTORY ENTRIES DB 128 ;ALLOC 0 DB 0 ;ALLOC 1 DW 32 ;DI 2 DB 0,0,0 ; 3 ; ;SECTOR TRANSLATE VECTOR ; SELTBL: DW T826,DP8S0 DW T815,DP8S1 DW T88,DP8S2 DW T84,DP8S2 CTOR SIZE DW 2 ;SYSTEM TRACK OFFSET DP8D3: DW 64 ;SECTORS PER TRACK DB 4 ;BLOCK SHIFT FACTOR DB 15 ;BLOCK MASK DB 0 ;EXANDARD ;IBM-COMPATIBLE 8" DISKS ;DISK PARAMETER HEADER FOR DISK 00 DPBASE: DW 0,0 DW 0,0 DW DIRBF,0 DW CHK00,ALL00 ;DIHECK VECTOR SIZE DW 2 ;SYSTEM TRACK OFFSET DP8D1: DW 52 ;SECTORS PER TRACK DB 4 ;BLOCK SHIFT FACTOR DB 15 ;BLOCK MASK D16 ;DIR CHECK VECTOR SIZE DW 2 ;SYSTEM TRACK OFFSET DP8S2: DW 32 ;SECTORS PER TRACK DB 4 ;BLOCK SHIFT FACTOR DB 15 ;BLOCKR CHECK VECTOR SIZE DW 2 ;SYSTEM TRACK OFFSET DP8D1A: DW 104 ;SECTORS PER TRACK DB 5 ;BLOCK SHIFT FACTOR DB 31 ;BLOCK MAS DW T848,DP8D0 DW T826,DP8D1 DW T815,DP8D2 DW T88,DP8D3 ; DP8S0: DW 26 ;SECTORS PER TRACK DB 3 ;BLOCK SHIFT FACTOR DTENT MASK DW 299 ;BLOCKS PER DISKETTE DW 127 ;# DIRECTORY ENTRIES DB 192 ;ALLOC 0 DB 0 ;ALLOC 1 DW 32 ;DIR CHECK VECTOSK PARAMETER HEADER FOR DISK 01 DW 0,0 DW 0,0 DW DIRBF,0 DW CHK01,ALL01 ;DISK PARAMETER HEADER FOR DISK 02 DW 0,0 DB 1 ;EXTENT MASK DW 242 ;BLOCKS PER DISKETTE DW 63 ;# DIRECTORY ENTRIES DB 128 ;ALLOC 0 DB 0 ;ALLOC 1 DW 16 ;DIR CHECK, K DB 3 ;EXTENT MASK DW 242 ;BLOCKS PER DISKETTE DW 127 ;# DIRECTORY ENTRIES DB 128 ;ALLOC 0 DB 0 ;ALLOC 1 DW 32 ;DIR29 ;SECTORS PER TRACK DB 3 ;BLOCK SHIFT FACTOR DB 7 ;BLOCK MASK DB 0 ;EXTENT MASK DW 115 ;BLOCKS PER DISKETTE DW 63 ;# DP5S1: DW 20 ;SECTORS PER TRACK DB 3 ;BLOCK SHIFT FACTOR DB 7 ;BLOCK MASK DB 0 ;EXTENT MASK DW 79 ;BLOCKS PER DISKETTE1 ACTIVE ; CSTS: LDA IOBYTE ANI 3 ;ISOLATE CONSOLE ASGT JZ TTST ;TTY ACTIVE CPI 2 JM CRTST ;CRT ACTIVE JNZ CUST1 ;USHECK VECTOR SIZE DW 2 ;SYSTEM TRACK OFFSET ; T848 DB 48,48,1 T826 DB 26,13,6 T815 DB 15,15,4 T88 DB 8,8,3 T84 DB 4,2,2  ENTRIES DB 128 ;ALLOC 0 DB 0 ;ALLOC 1 DW 16 ;DIR CHECK VECTOR SIZE DW 3 ;SYSTEM TRACK OFFSET T529 DB 29,29,7 T518 DB  CHECK VECTOR SIZE DW 2 ;SYSTEM TRACK OFFSET DP8D2A: DW 120 ;SECTORS PER TRACK DB 6 ;BLOCK SHIFT FACTOR DB 63 ;BLOCK MASK DIRECTORY ENTRIES DB 192 ;ALLOC 0 DB 0 ;ALLOC 1 DW 16 ;DIR CHECK VECTOR SIZE DW 3 ;SYSTEM TRACK OFFSET DP5D1: DW 36 ;S DW 63 ;# DIRECTORY ENTRIES DB 192 ;ALLOC 0 DB 0 ;ALLOC 1 DW 16 ;DIR CHECK VECTOR SIZE DW 3 ;SYSTEM TRACK OFFSET DP5SER CONSOLE 1 ACTIVE ; BATST: LDA IOBYTE ANI 0CH ;ISOLATE BATCH ASGT JZ TTST ;TTY ACTIVE CPI 8 JM PTRST ;PAPER TAPE REA; MSELTBL: DW T518,DP5S0 DW T510,DP5S1 DW T55,DP5S1 DW T52,DP5S3 DW T529,DP5D0 DW T518,DP5D1 DW T510,DP5D2 DW T5518,9,4 T510 DB 10,10,3 T55 DB 5,5,2 T52 DB 2,2,1 ; ;END OF FIXED TABLES ; ; CO: LDA IOBYTE ANI 3 ;ISOLATE CONSOLE ASGT DB 7 ;EXTENT MASK DW 139 ;BLOCKS PER DISKETTE DW 127 ;# DIRECTORY ENTRIES DB 128 ;ALLOC 0 DB 0 ;ALLOC 1 DW 32 ;DIR ECTORS PER TRACK DB 4 ;BLOCK SHIFT FACTOR DB 15 ;BLOCK MASK DB 1 ;EXTENT MASK DW 71 ;BLOCKS PER DISKETTE DW 63 ;# DIRE3: DW 16 ;SECTORS PER TRACK DB 3 ;BLOCK SHIFT FACTOR DB 7 ;BLOCK MASK DB 0 ;EXTENT MASK DW 63 ;BLOCKS PER DISKETTE DW DER ACTIVE JZ RUST1 ;USER READER 1 ACTIVE JMP RUST2 ;USER READER 2 ACTIVE ; CI: LDA IOBYTE ANI 3 ;ISOLATE CONSOLE ASGT ,DP5D2 DP5S0: DW 18 ;SECTORS PER TRACK DB 3 ;BLOCK SHIFT FACTOR DB 7 ;BLOCK MASK DB 0 ;EXTENT MASK DW 71 ;BLOCKS PER DI JZ TTYOUT ;VB1 ACTIVE CPI 2 JM CRTOUT ;CRT ACTIVE JNZ CUSO1 ;USER CONSOLE 1 ACTIVE ; LO: LDA IOBYTE ANI 0C0H ;ISOLACHECK VECTOR SIZE DW 2 ;SYSTEM TRACK OFFSET DP8D3A: DW 128 ;SECTORS PER TRACK DB 6 ;BLOCK SHIFT FACTOR DB 63 ;BLOCK MASK CTORY ENTRIES DB 128 ;ALLOC 0 DB 0 ;ALLOC 1 DW 16 ;DIR CHECK VECTOR SIZE DW 3 ;SYSTEM TRACK OFFSET DP5D2: DW 40 ;SECTOR63 ;# DIRECTORY ENTRIES DB 192 ;ALLOC 0 DB 0 ;ALLOC 1 DW 16 ;DIR CHECK VECTOR SIZE DW 3 ;SYSTEM TRACK OFFSET DP5D0: DW  JZ TTYIN ;KBD ACTIVE CPI 2 JM CRTIN ;CRT ACTIVE JNZ CUSI1 ;USER CONSOLE 1 ACTIVE ; RI: LDA IOBYTE ANI 0CH ;ISOLATE BASKETTE DW 63 ;# DIRECTORY ENTRIES DB 192 ;ALLOC 0 DB 0 ;ALLOC 1 DW 16 ;DIR CHECK VECTOR SIZE DW 3 ;SYSTEM TRACK OFFSETTE LIST ASGT JZ TTYOUT ;VB1 ACTIVE CPI 80H JM CRTOUT ;CRT ACTIVE JZ LPRT ;LINE PRINTER ACTIVE JMP LUSE1 ;USER PRINTER  DB 7 ;EXTENT MASK DW 149 ;BLOCKS PER DISKETTE DW 127 ;# DIRECTORY ENTRIES DB 128 ;ALLOC 0 DB 0 ;ALLOC 1 DW 32 ;DIR CS PER TRACK DB 4 ;BLOCK SHIFT FACTOR DB 15 ;BLOCK MASK DB 1 ;EXTENT MASK DW 79 ;BLOCKS PER DISKETTE DW 63 ;# DIRECTORY- TCH ASGT JZ TTYRDR ;TTY ACTIVE CPI 8 JM PTRIN ;PAPER TAPE READER ACTIVE JZ RUSI1 ;USER READER 1 ACTIVE JMP RUSI2 ;USER RESTART ERROR MSG COMERR: CALL PRTWD ;PRINT IT ON NEW LINE JMP WBOOTV ;GO TO WARM BOOT ; RSTMSG: DB 'RST ER','R'+80H CRMS ; ROUTINE CRLF GENERATES A CARRIAGE RETURN, LINE FEED ; SEQUENCE ON THE CURRENT CONSOLE TO START A NEW LINE ; IT INCLUDES TWIGNED HIGH SPEED PUNCH HSPST: EQU IOER ;UNASSIGNED HIGH SPEED PUNCH STATUS PUSO1: EQU IOER ;UNASSIGNED USER PUNCH 1 PUST1: EQTS AN ASCII STRING ONTO THE CONSOLE. ; THE STRING MUST BE TERMINATED BY BIT 7 SET IN THE ; LAST CHARACTER OF THE STRING. THE RET ; TTYOUT: CALL TTOST ;GET 8250 LINE STATUS JZ TTYOUT ;WAIT UNTIL ONE OF THE REGISTERS EMPTIES MOV A,C ;MOVE THE DATA O READER 2 ACTIVE ; LSTAT: LDA IOBYTE ANI 0C0H ;ISOLATE THE LIST DEVICE ASSIGNMENT JZ TTOST CPI 80H JM HSPST JZ PUST1G: DB CR,LF,0,80H ; ; I/O DRIVERS FOR THE 8250 ASYNC COMM ELEMENT ; TTST: IN SLSTAT ;GET 8250 LINE STATUS ANI 1 ;SEE IF REO NULL CHARACTERS FOR TTY TYPE ; DEVICES FOR THE HEAD MOVEMENT TIME. ; CRLF: PUSH H ;SAVE THE CONTENTS OF (H,L) CRLFA: LXI HU IOER ;UNASSIGNED USER PUNCH 1 STATUS PUSO2: EQU IOER ;UNASSIGNED USER PUNCH 2 PUST2: EQU IOER ;UNASSIGNED USER PUNCH 2 STATUSTRING WILL START ; A NEW LINE (EP = PRTWD) OR CONTINUE ON THE SAME ; LINE (EP = PRTWA) ; PRTWD: CALL CRLF ;START A NEW LINEVER OUT SDATA ;OUTPUT THE DATA RET ; ; EQUATES FOR ADDITIONAL CONSOLE DEVICES ; CRTIN: EQU IOER CRTOUT: EQU IOER CRTST JMP PUST2 ; PO: LDA IOBYTE ANI 30H ;ISOLATE PUNCH ASGT JZ TTPNCH ;TTY ACTIVE CPI 20H JM HSP ;HIGH SPEED PUNCH ACTIVCEIVE DATA AVAILABLE RZ ;RETURN IF NOT ADI 0FEH ;FLAG THAT DATA IS AVAILABLE RET ; TTYIN: IN SLSTAT ;GET 8250 LINE STAT,CRMSG ;ADDRESS OF CR,LF MESSAGE CALL PRTWA ; OUTPUT IT POP H ;RESTORE (H,L) RET IOER: XRA A ;RESET IOBYTE STA 3 LXIS ; ; EQUATES FOR ADDITIONAL LIST DEVICES ; LPRT: EQU IOER ;UNASSIGNED LINE PRINTER LUSE1: EQU IOER ;LIST DEVICE 1 = CRT  PRTWA: PUSH B ;SAVE (B,C) PRTA: MOV C,M ;GET NEXT CHARACTER FROM MEMORY CALL CO ;OUTPUT IT INX H ;INCREMENT MEMORY POINTE: EQU IOER CUSI1: EQU IOER ;UNASSIGNED USER CONSOLE (INPTUT) CUSO1: EQU IOER ;UNASSIGNED USER CONSOLE (OUPTUT) CUST1: EQU IOEE JZ PUSO1 ;USER PUNCH 1 ACTIVE JMP PUSO2 ;USER PUNCH 2 ACTIVE ; ; ROUTINE CONI READS THE CONSOLE AND STRIPS OFF THE ASCIIUS RAR ;MOVE RX DATA READY BIT INTO CARRY JNC TTYIN ;LOOP UNTIL DATA IS IN IN SDATA ;READ THE DATA RET ; TTOST: IN SL H,IOMSG ;ADDRESS OF IO ERROR MESSAGE JMP COMERR IOMSG: DB 'I/O ASGT ERROR',CR,LF+80H ; RSTER: LXI H,RSTMSG ;GET ADDRESS OF; ; EQUATES FOR ADDITIONAL PAPER TAPE READER DEVICES ; TTYRDR: EQU TTYIN ;UNASSIGNED TELETYPE PAPER TAPE READER PTRIN: EQU R MOV A,C RLC ;TEST FOR BIT 7 DELIMITER JNC PRTA ;NO DELIMITER, GO DO NEXT CHARACTER PRTB: POP B ;RESTORE (B,C) RET ;R ; ; EQUATES FOR ADDITIONAL PAPER TAPE PUNCH DEVICES ; TTPNCH: EQU TTYOUT ;UNASSIGNED TELETYPE PUNCH HSP: EQU IOER ;UNASS ; PARITY BIT. ; CONI: CALL CI ;GET THE NEXT CHARACTER ANI 7FH ;STRIP OFF THE PARITY BIT RTS: RET ; ; ROUTINE PRTWD PRINSTAT ;GET 8250 LINE STATUS ANI 20H ;ISOLATE TX BUFFER EMPTY BIT RZ ;RETURN IF NOT EMPTY ADI 0BFH ;FLAG THE EMPTY STATE . IOER ;UNASSIGNED HIGH SPEED PAPER TAPE READER PTRST: EQU IOER ;UNASSIGNED HS PTR STATUS RUSI1: EQU IOER ;UNASSIGNED PAPER TAPE: DS 32 ;CHECK VECTOR 2 CHK03: DS 32 ;CHECK VECTOR 3 ; DBUF: DS 1024 ;DISK BUFFER ; ENDDAT EQU $ ;END OF DATA AREA DATSIZ ew factor" for sector translate ; bls is the data block size (1024,2048,...,16384) ; dks is the disk size in bls increments (wDMAAD: DS 2 ;DIRECT MEMORY ADDRESS ; ; HSTACT: DS 1 HSTWRT: DS 1 ; UNADSK: DS 1 UNATRK: DS 1 UNASEC: DS 1 UNASID: DS 1 def parameter-list-0 ; diskdef parameter-list-1 ; ... ; diskdef parameter-list-n ; endef ; ; where n is the number of logi READER 1 RUST1: EQU IOER ;UNASSIGNED PAPER TAPE READER 1 (STATUS) RUSI2: EQU IOER ;UNASSIGNED PAPER TAPE READER 2 RUST2: EQUEQU $-BEGDAT;SIZE OF DATA AREA ; CONST: EQU CSTS CONOUT: EQU CO LIST: EQU LO PUNCH: EQU PO READER: EQU RI LISTST: EQU LSTord) ; dir is the number of directory elements (word) ; cks is the number of dir elements to checksum ; ofs is the number of  UNACNT: DS 1 CPMSEC: DS 1 NXTSCT: DS 1 ; ERFLAG: DS 1 RSFLAG: DS 1 READOP: DS 1 WRTYPE: DS 1 ; ;SCRATCH RAM AREA FOR Bcal disk drives attached ; to the CP/M system, and parameter-list-i defines the ; characteristics of the ith drive (i=0,1,..., IOER ;UNASSIGNED PAPER TAPE READER 2 (STATUS) ; SEKDSK: DB 0 SEKTRK: DS 1 SEKHST: DS 1 SEKSID: DS 1 SEKSEC: DS 1 SEKSEL:AT END tracks to skip (word) ; [0] is an optional 0 which forces 16K/directory entry ; ; for convenience, the form ; dn,dm ; defiDOS USE ; DIRBF: DS 128 ;SCRATCH DIRECTORY AREA ALL00: DS 38 ;ALLOCATION VECTOR 0 ALL01: DS 38 ;ALLOCATION VECTOR 1 ALL02: n-1) ; ; each parameter-list-i takes the form ; dn,fsc,lsc,[skf],bls,dks,dir,cks,ofs,[0] ; where ; dn is the disk number 0 DS 1 ; ;THE REMAINDER OF THE CCBIOS IS RESERVED UNINITIALIZED ;DATA AREA, AND DOES NOT NEED TO BE A PART OF THE ;SYSTEM MEM; CP/M 2.0 disk re-definition library ; ; Copyright (c) 1979 ; Digital Research ; Box 579 ; Pacific Grove, CA ; 93950 ; nes disk dn as having the same characteristics as ; a previously defined disk dm. ; ; a standard four drive CP/M system is deDS 38 ;ALLOCATION VECTOR 2 ALL03: DS 38 ;ALLOCATION VECTOR 3 CHK00: DS 32 ;CHECK VECTOR 0 CHK01: DS 32 ;CHECK VECTOR 1 CHK02,1,...,n-1 ; fsc is the first sector number (usually 0 or 1) ; lsc is the last sector number on a track ; skf is optional "skORY IMAGE (THE SPACE MUST BE AVAILABLE, ;HOWEVER, BETWEEN "BEGDAT" AND "ENDDAT"). ; BEGDAT EQU $ ;BEGINNING OF DATA AREA ; ; CP/M logical disk drives are defined using the ; macros given below, where the sequence of calls ; is: ; ; disks n ; disk/ fined by ; disks 4 ; diskdef 0,1,26,6,1024,243,64,64,2 ; dsk set 0 ; rept 3 ; dsk set dsk+1 ; diskdef %dsk,0 ; endm nts for later tables if nul lsc ;; current disk dn same as previous fsc dpb&dn equ dpb&fsc ;equivalent parameters als&dn eqmacro data,comment ;; define a dw statement dw data comment endm ; gcd macro m,n ;; greatest common divisor of m,n ;;  > 256 extmsk set (extmsk shr 1) endif ;; may be optional [0] in last position if not nul k16 extmsk set k16 endif ;; 00h ;translate table dw 0000h,0000h ;scratch area dw dirbuf,dpb&dn ;dir buff,parm block dw csv&dn,alv&dn ;check, alloc veclls with 1's from right rept 16 ;;once for each bit position if blkval=1 exitm endif ;; otherwise, high order 1 not fou ; endef ; ; the value of "begdat" at the end of assembly defines the ; beginning of the uninitialize ram area above the biou als&fsc ;same allocation vector size css&dn equ css&fsc ;same checksum vector size xlt&dn equ xlt&fsc ;same translate table produces value gcdn as result ;; (used in sector translate table generation) gcdm set m ;;variable for m gcdn set n ;;variablnow generate directory reservation bit vector dirrem set dir ;;# remaining to process dirbks set bls/32 ;;number of entries petors endm ; disks macro nd ;; define nd disks ndisks set nd ;;for later reference dpbase equ $ ;base of disk parameter blnd yet blkshf set blkshf+1 blkmsk set (blkmsk shl 1) or 1 blkval set blkval/2 endm ;; generate the extent mask byte blkvas, ; while the value of "enddat" defines the next location ; following the end of the data area. the size of this ; area is  else secmax set lsc-(fsc) ;;sectors 0...secmax sectors set secmax+1;;number of sectors als&dn set (dks)/8 ;;size of allocate for n gcdr set 0 ;;variable for r rept 65535 gcdx set gcdm/gcdn gcdr set gcdm - gcdx*gcdn if gcdr = 0 exitm endif r block dirblk set 0 ;;fill with 1's on each loop rept 16 if dirrem=0 exitm endif ;; not complete, iterate once again ocks ;; generate the nd elements dsknxt set 0 rept nd dskhdr %dsknxt dsknxt set dsknxt+1 endm endm ; dpbhdr macro dl set bls/1024 ;;number of kilobytes/block extmsk set 0 ;;fill from right with 1's rept 16 if blkval=1 exitm endif ;; given by the value of "datsiz" at the end of the ; assembly. note that the allocation vector will be quite ; large if a largeion vector if ((dks) mod 8) ne 0 als&dn set als&dn+1 endif css&dn set (cks)/4 ;;number of checksum elements ;; generate tgcdm set gcdn gcdn set gcdr endm endm ; diskdef macro dn,fsc,lsc,skf,bls,dks,dir,cks,ofs,k16 ;; generate the set stateme ;; shift right and add 1 high order bit dirblk set (dirblk shr 1) or 8000h if dirrem > dirbks dirrem set dirrem-dirbks eln dpb&dn equ $ ;disk parm block endm ; ddb macro data,comment ;; define a db statement db data comment endm ; ddw otherwise more to shift extmsk set (extmsk shl 1) or 1 blkval set blkval/2 endm ;; may be double byte allocation if (dks) disk size is defined with a small block ; size. ; dskhdr macro dn ;; define a single disk header list dpe&dn: dw xlt&dn,00he block shift value blkval set bls/128 ;;number of sectors/block blkshf set 0 ;;counts right 0's in blkval blkmsk set 0 ;;fi0 se dirrem set 0 endif endm dpbhdr dn ;;generate equ $ ddw %sectors,<;sec per track> ddb %blkshf,<;block shift> ddb  fac test endif ;;end of nul bls test endm ; defds macro lab,space lab: ds space endm ; lds macro lb,dn,val defds l= gcd(sectors,skew) neltst set sectors/gcdn ;; neltst is number of elements to generate ;; before we overlap previous element%blkmsk,<;block mask> ddb %extmsk,<;extnt mask> ddw %(dks)-1,<;disk size-1> ddw %(dir)-1,<;directory max> ddb %dirblk shb&dn,%val&dn endm ; endef macro ;; generate the necessary ram data areas begdat equ $ dirbuf: ds 128 ;directory access bus nelts set neltst ;;counter xlt&dn equ $ ;translate table rept sectors ;;once for each sector if sectors < 256 ddb %nxr 8,<;alloc0> ddb %dirblk and 0ffh,<;alloc1> ddw %(cks)/4,<;check size> ddw %ofs,<;offset> ;; generate the translate tablffer dsknxt set 0 rept ndisks ;;once for each disk lds alv,%dsknxt,als lds csv,%dsknxt,css dsknxt set dsknxt+1 endm etsec+(fsc) else ddw %nxtsec+(fsc) endif nxtsec set nxtsec+(skf) if nxtsec >= sectors nxtsec set nxtsec-sectors endife, if requested if nul skf xlt&dn equ 0 ;no xlate table else if skf = 0 xlt&dn equ 0 ;no xlate table else ;; generanddat equ $ datsiz equ $-begdat ;; db 0 at this point forces hex record endm ;  nelts set nelts-1 if nelts = 0 nxtbas set nxtbas+1 nxtsec set nxtbas nelts set neltst endif endm endif ;;end of nulte the translate table nxtsec set 0 ;;next sector to fill nxtbas set 0 ;;moves by one on overflow gcd %sectors,skf ;; gcdn 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L