CBMx >ÍLLINK COM{SUBMIT COM*XREF COMyF+Copyright (C) 1982, Digital Researchn2$ BNKBIOS3 SPR F000 0C00 BNKBIOS3 SPR C800 1800 RESBDOS3 SPR EA00 0600 BNKBDOS3 SPR 9A00 2E00 58K TPA $$$$$CPM+ SYSD CCP COMPIP COMDSHOW COMBREAD ME CPM3 LIB GENCPM DAT !GENCPM COM("#$%&'()*+,F1F2dir dir F5F6F728 May 87 F9F10F11F16F17F18F19F20F21F22F23F24F25F26F27F28F29F30F31Help CXROM02 ASM9-./0CXROM1 ASM2123456789:;<CXROM80 ASM\=>?@ABCDEFGHIJCXROMINTASMKLCXROMK ASMMNCXROM SUBOMAKEROM DOCPFORMAT ASMQRSTUVWXYZ[\]^_`FORMAT ASMhabcdefgCALLVERSASMhDUMP ASM ijECHOVERSASMkRANDOM ASMVlmnopqADDBIOS ASMArstuvMAC COM\wxyz{|RMAC COMj}~ 33#wWWaAA44$zZZsSSeEE55%rRRdDD66&cCCfFFtTTxXX77'yYYgGG88(",!."*K6*}ʴ}<ʴ.}o|g "($Kt>=2(*f*(}DɯQ"(>QKQKQ>Q"%Q!*$K*"x!*!@$@hK\K:K ~#~ w*NK*NK^#V#N#F!2!"*"!!***)0&(K|loÈÍjQ>2y :y y:D< y2Dx2E"!91*x(%:D !:E ױ(:D !:E >2D:PRT2 6551 RS232   (Bx2'$ > 2G:aOx2a0 *#" x2 x2 x:2a( > 8'y :A!"A!7>w!S~=2 !"A!6: :( 4((!"A>2:S2:2!"A:[/(>G:Z/G:U/怰Gx(2!6>=2 ">2!"A:2G*$(~wx2!"AxW(  ,>@)x  !>x(' (  > x < 2y2!"bBBhHHuUUvVV99)iII jJJ 000mMM kKK oOOnNN+++pPPlLL ---..>::[{@@@,,<###`***;;]}===~^^||//?\11!___ 022" ! qQQ🟟888555 222444777111+++--- 666999333000..."3DUfwx>QGQx3ڰbڼqҼo5p5"""*!yb! ~G*!NKկ2}!,"**NK6 :+OK2$^#V#N#FxNp:$p:Gjxj Y# A>QFQÃ1Oj$|Ãà à Ão"?!91*A*?:2Ͱ2C2:C"?*?KEYS 80COL 40COL PRT1 Aq˳99Ҝvʅq\˅˅˅˅˲ˆq˅˅˅˅˻#˅qʅq˗˗˗˗ ˗>X0_~#f!O˶!"07>y( 2!S 2>!2>!S/y20x4nFw27!6"Aɯ2u!"A!"A>!= 6!"Aw:S"0>2!"0>8>2%!L5 !)"0!0"0:N0,!T"00:>M>2%!["0!b"0!y"0>2%:N >#w>=2z ڷmBj?'^d( o@:f( ow"߾h(KK{<<ʽ! ~6 69BK! OSn2$$Nwy!"(9"f1f! Ҕ2! ~#foCOPYRIGHT (C) 1982, DIGITAL RESEARCH 151282BB6! :2~2/w x 2% BIOS Err on A: No CCP.COM file !!,!CCP COMͺ!ͨ*2 ͨ2x2"="A_>t,0>O+V!0 2~2w/ x ɯ2!"<(!s4,~< >vwo>w!"-> â>8!Ow!N"-:O!"0>2%>22>2%!O!"0:P2!O~w:N2L!"0!:N!l0!,"-: 2!#"-!"-Q!5"-Q!c"-:N80 0?:!O!l"-Q:O! :2Q!"-ݮ`( o2b( o @(y2 ~y# xzxy>2y2 xxy x( Pxyz2* : 2o+"}{_}o>2~77ø~7"9:OG#Q{ozg# ""!2*%DM**ѵ+)) H~#+}#<:<ʲ<77:<ʢU | %~( O #>/<033O _ W{ !ͨ:AO !ͨ* ***)>&| h&)))~^U~g > >w^8^%**)>URɯ!s5.O ˮ>C2Rɯ2R!>w>28 !O!"-!N"-ɯ2:N2K!"-!"-:s0!>w>2>2!"-!K5 "* 2=2 xxy xaNʹ%!MD5 :Rw͌!60:O >2R!u4~6v!"-:O!un~2Q>02  x( x2 $xy©( HYʪ Û2%>2y2ܯy >yxUy x: >@2xH :"A*a~<6,>w,}s >c2a!""A:y >y<2$U:$(=2$:$<2$:2!,"#:"2">2$ͱ~a> 2$͊8ws)ͱ80G̯2$|!"$s)!+| !|B!PÀ:$O!l pG~!D/(:$O!l ~!(:*J!y*H!:4^w (~P~26#"xx! $ ̓x>@͋ ̀#= y(0!Dx G6 #ͣx! $ GWx̀#= _y(0.pG{@x(!D wͣ͋ 3>_>͘ :ڧ: ( (>>>C>͘N:; = :ڧ*"":++~G2#2<2~'k:G: >͘›կ_:ڧC>͘ hN%xy:|: F= :ڧ(xyk:G:P  None P  None P  None P  None L(? KayPro II c(?Osborne DDK ? Slicer 9@ Epson Euro ů]  f>2$>2$!~t#( ?Pause:"@2":$=:$(<2$.bf:2:2:2:Q2Q !"$x( * +#"$Ⱦ(#0րG.40֠G.6!*L_^#Vȍ:"2"¦H ϦϦϵϵϼϼς*3"7/&"* * `" >2$> ͉>@y> ͉>y!" $>2$>yy(0x!D 6#= ͣddg )  @H8@x/O8 ϵϼKϦϾ=TtYy:*EQRW)(GBCDLrU :=:=2@] w#N#F#=F:bڰw#s#r2bͿ*^#VV :G:< ͡P  Epson QX10I ? IBM-8 SS I ? IBM-8 DS L(  KayPro IV p{O<2گ]!D/( ? "?( 9@ Epson QX10p tx|6Tcr2$>:q$ ˷2q$>y y 2$y!Su!c"_"a6d*$| 1y xVEUPW:"z0.GF#~y2P!O:O#(:Q!Oˆ:OO>z>y*=>~y8*o*=}!k >͉(:q$2q$:"w : $G:$0&0>d*$## w <2$d _*$##V..ͼ.  T(0$,dddg0ЁO!]dd~  ;8#>!$!$2>O"$*#*$~#foy(!? !J( Wdg!`!s ~#fo!*$s#rd dG.4w!q"r6!>2> %:G xG(>G:G:*FG~x *s#r#"!4 :ڧʠ= #*q#~*+0 6$O.6>:ӯ2<2!"է.R<*+6 -*q#p `BF#~#fox2b"c(2b:G*+y :8s O{22:"Ħ>H2:R=( =(=(=W@:0::-:/ 0:G!:_=2$(:(2:?2>2:N?2:G0ƀ<2_(.:(8G(8>O2?20 B:2:2BWINE VONk k *%DMy> y:yͻ( x*%DMxy( y*%DMx'E܁l"2!"u, ͷ!|  3.~ , e"n!| !"ͥn:<2 !x(!"!6 ERT,6v,6v!:$(!:8>2_^#V#~2RY Q>yxyɢ  p8   G# (6>G^>:$oxyy!k "* ^#V#"^#V"! ^#V"!@i i a a>2??>~ 2O!s6>@ >]͕؇_ͱx!y7j7?(6:$!!2$*_~G<}s >c2_x=(,:$ Oy :$-6h&))Oo*  ͸r:$<2$*$:$o|g~>2$>>t*$:$8#=2$~#( t:$ > j0:8G:$O<2$:$2!`"F>G (x8T*+x2y2> ("(@`8 {0 `[0ƀ>'\>".P**s#r#"*,} !":G:(/:G#~2+~2 ##":ڐ2x2:*ڄg"*~2#~2#":G:( :2:G:x2A26.T!*Ͱ>xInsert Disk X in Drive A** ~G*+~( _<W*>2!"*)) :*( b  :*(*b!i a y* i a! i azȯ ߯y y!P  None P  None P  None Missing T`y CP/M 3.0 On the Commodore 128 28 MAY 87 !@+0>42& %80 column display ">2D>2!"!Q Y Q Q Y Y Y Q2::O >>2!u  ~y+  >2"2N!"%!"H"J!O"L!`"&"&"&""%q~wɯ22ù*~2~w#~2~wZ!""2=2*~2=2߸2k:*wX/ 6X*W#x#W{s+p+q7r#r#r>@˷ >2 ˷!!q#p#w2wW*e_3ҫ-!s:!¾xQ*͚Aت=:<~?¯kü?~?ʾZT͐ڼ*>o"͒"!ì:Oݮ"Ý͐6͚ ~2Asv@NN~v$̓W+vw̚v$̓rrͅ:r߹>2+A@2N͆p# Þ͐*6!¿?~p*6 >2ͱݺԺ߹ͷw*oq͋"@6͚Xͤ͋͗wO~<:· g~w#w#6##)͋@ * g~?G++a##)""xx!"""XC*~<*":¾!:·ľ*}*"x"*"g*3:= :Oi :=H:Gi a6:G/O**W :T=2i`z n&*&)~#fo*&)~#fo~#fo2 2ɯ BIOS Error on : T-, S-2:O :2 1 0!^#V#{(++~2 y2+V+^ cy2i&) ~#fo{ !~2 !~#foi`"i`"i`"::<œ. ʩ.ʩAܧrr##sܧ<}rcN! ~态O>G~G!~G~o>_yG~.|°! w:ck[!x?[! ~ʤ͆[͗PPvqO-á=.:<ʰ! Vq##~_@wr!Z2!"ög:2T͐-:ʹ>2<2ڱ!¾w: >2*6ݮݱO~<w:*)@ u:G*g`~!x_<_@*oy<:/G?~##~? 6K@?F6##N6⺯2p##q:!o#~>T}! 6**#K"G*~ xr͐-xą@˷7(͚Sʀw :<RHͥ:·>~c!o#~E^#V)G#~#~!~ b k##N#F#^#V#~#fo~oҍ ïaʚ~6*:X)!:¾T>qk!:¾6>X*{Q:_2{2Ē"͂"X~<ڗ>2#×:#<ï2#*Ͷ:WMںʛ>úͶ >TJ:!¦ʷ͞x!¾Ƕw4 ϶PW޶PܧÂէÂ*!!~~#~O~#FsO s#r:(„y==„*!^W*y^#Vx7=2wͼկw#KWK*"J T͞*:¥["#*~w>2*p@! ~*"v@*w# ) 6#̺͙N#FxT]## #~ ȷ  *4# ' 4! *~^ ^33G# Pv:dv6 y2{2g*wޭʪҢÞ+}*#}o|g:O*s#r#w!~w/~@w//Hͥ*e>=)_g:0"ök*w)*c)-͐ͤÀk*s":;:r2͚Ϊù͚Ϊ·͚}/_|/*e¤W}_*c"e}o|g"c>2{#cdfg!"()*N!r)!N!)z<*)"!":X*:w:¶w#:¶w*2*}D=‡*":*}®:=::<>2*i^#V+ d!K*}@*)): K:) O "!w [O?WGzO:VxGyOGxwq*}}2ܧͤ2ѵO ̩DM͸}޵>r""¯2:2* :·::29:·>:·>*2@ !)#w*~"ҹ!Fw乨ҹ̓ҹ:w̚":>彯2̓*~wć"̀!~$6:03i"!~6*e>=)Q!QX2—͇ͱ* «>2͙wBp+ҽ:w͚AP{ 2W>O2ø͐R*e):r͚Ϊc2ZT͐-ڱ3͗@YsY̓Y׺Yͅ:߹Asҽ:@ҽ@ҽ$̓̓¡>2ͱԺ߹?~¾¾>w͙=2͜:wÚ~̓ʑpá!6NwͧBpͧÚgsr͐-͜ĩͤS)_ͤ̓~?w͐s-?F͜p|:w:ʴ>2d:#>29ů2~2#!   )xð*}*}"*x"xm*^#V* s#r**s#r*:¾Y4Y̓**~#ng* s#r ^#Vڈ>F6:_/G:·ʧ:¢ڨ|OͤG:¸_O̩̩zW{´|:·*}|BKN´ zyG:!¾vq:vէvMڂ?Ͷ >T͓Â!">Â:G:O:h=27ryy/W!:l9ʌ^: ~x ):*:ţţ>*(+"(w++2+2+ɟp؟!" >2+2*jx.#NzW::!2W!5=^x^z:m:*;#wO:rrorFile Exists? in Filenameòò>2a.":2:<:55;:2ɯ22{_zW{_zW )7CP/M Error On : Disk I/OInvalid DriveRead/Only FileRead/Only DiskPassword Eozg**|g͸*u* ƫ ѫR>22Zw*q>ww:c *#*is#r*:!:)e:O!*c:Oͫ}@2æ ~á*g:…o$*~K6?~wKw**i{#zir+s{G:<ޯ2x# W:<­:22G?>Grx~:·2Ô##~*$*">2̀2kºʺ**iҺ@:O~2~WW:2Ôyʛ?ʔx ʔ |̷ǯÔN=:<>w##~2 4~?ɳ¹:<ɳɳüޱAX2rK:w++~=wv4͗O5:2X!"*>o+"! *!b"ݮ": r#~?w#>r# L=J Lv wbܧ?~O ͆ڳ͂^2¢ů͠Ģ:!ڽ*(~ݠנ5Wèբ؟jנM2ͨx΢*(+w"(j͞ !%"(^-:*$P:<\:W:2xM s:<9>2:*9x~+q’x2:*O:w:Ғ4~:w?r##rp# ä |g}oì*g #G ¾1*q¾:·*w***> r 2":O:¡G2!¶w*~zWw+ !z?#~*!* *G!O~2~m͗O~t>2?:¦2:r:/GyOOA +¬ ¢y2:·x¹o&:W>OͫE:¸ڟ?N/*"y2ͦ>2 ݮwޭDM*w6# x *ow**ws#r̀*i6#6*}"w@*|<ď>!8>8> t>nͦv8 ~*own†wŒ~è# # x ͗w ٲڲٲڲw@ ~wb͐Úݬ!x>w~6:·6~#+w#w+~;wɯ2KOFq-yl?Npg:·ʓ~*&~2+o#"&!+6Mš:W:2x ͺ*(+"(w  :ܡ>2*2:*(:+w"(ͺ:G::+̜2 5*(~o#"(Mš*(~`Uoj*(~#"(Ñ!*~6s!+6:+‚xog͝DM*0MD"!*MD$:Oë!N:· «G>O: ©ù*ĩ :·کn` ~#foͤ2O̩"}:O*¯"!s#r#p*kN#F*m^#V#F*:O}|y9*+"*}|yP#9**DM"*ks#r*ms#r#pyoxT] KKͦޭ*w"wͦ"w@ :·íNɭ N#Fyح*}|h#ð*ͫ# 6RX*q¾6!"@**#":&2·͒:È0:+Òy<_W`iͫDM*w ~bNpwޭDM*w¯( ˆʀHÈ2xą ):@αO~#w͚ʀôb_++V@* )͗Os++r~Gw#* #~$%+@*9>  #>? ;*~ w-xąH"0 *ĊHڊ{2Ó#w:2.+:.2-!%"(2*!¥"&!*~4:2-Ԃ:Gͳͨ^2+>2:2*N#G2 2GH)+6:2,:!- ͞:,!͞+*(~L#Bxz:*:*(~ʓO)"!z<~rs^#V#N#FxN:oʲ̀õ(# Þry< <<%zrͷr6r9rMDÌ:o!6!h: ʚnt2 r62>rz<**kw#w*mw#w#w>2'å2*OͶyڲò<*eͲ:0!:¾:·ò2*>*ͫ"ª4#4#4)7 #  w#*J|^#V#"i##"k##"m###"o#"q##"!s )*s!)*|!6~67e ^#V#~2>â9͆>!"*y³*X*ÿ͂"*g*K!~<:wb##>w#wĩ> r!~#2: *~w *" ݮ2>ʄ@~k:(s~*9~Ês~Ժ~ͅ<r ͞ ͞! O(Ì*(~2**}ʷ!#¶!""÷:_:*(#wΟxH!¥)6"&:!¥ x5~y 5 6y(^͞@O:=7:͞y ͞:I ͞:=e: zz#͂͞:! ͞LOADER y; !91""|0!~ʞz=_: _* ""*og*%|}D S#N#F:ʒ#4ʝ^#V{‚:¿*.~w*DM!&_*.& >k s#rr+6.""1`  E * 7  L L )` (- )* L3),3* ( i(L{'I- -) f( I& {' ` ( f( I&) I&)  I&)!J ^#V̀:#!"(COPYRIGHT (C) 1982, DIGITAL RESEARCH 151282/(+17Ƞ=} ӫn2$"y2;!":2=2:=;!~;4#.{2!""9"2!;y3]K!ƚo\b!,_^#V* G:Ҏ>xʝʝw>ɯw̩z:»!>wɯ:=zxzz::G:=/ͽx:Āy!4 šn!6@G:x: P:<: P n6 t6! ^6 t6u:)<͠^!*D`.45. F.~. ^#Vx>`. s#rz 6#N#fi%$g1:=<@v_}v=p{_3;{<g"T=X3*j ~P#~R#~L{gbk#N#Fk$&Zcx {~#o}o1!ݭ $L ( *  1 .( ) L L0) ( ))* )$ )x? 2L.( 7&x> L.&]&&&'''N'''4& (#( *ll  iG&l&xIݩ, `) *hh@`U1:8 0 tt ss #N0:CP/M DISK,65 B-P 8 0 U0Ó*"r*r"ÿ<:g:!͐*f}D! ~6t!rͷ֝O(^ƝƝƝ  :Function = File = !,!"h!9"f! ͉:2t™:!=Hgo:O*;*;!"Ï:= w*wWx ~#&*.~s*"ѷ\ Cannot load Program 221282 COPYR '82 DRI <bHA$@DH   A@!" $$@ ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0L* `  L& 3) 0` i) ` i) ` 3) * ` *  hL ܭ ݩhhj3*)i3*i i  ) `آ08 i:` ( *   4* hL (1* / *), p#   h͂:A2=/::0! dگ61#d ڸïp#:w#6 !6:6 *#!)6.#)͂ O(BDOS > wM  2*7w#6?#7 .,:;[]=<>|!?]45#Ra{i_p# l s s1-! j 1".~2.~2 :Xck*kͮ  b < .~=>$.w.6#w.6#w.61.~  .~~w@.p T~º>+~.~~! yͮ Ë.~~w2g !PROFe USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Th , P, ` ,  {'L&*j3*` )**0 )**L(L&6*4* 3* 3*)5*0J**)WR2*Ȯ3* f(L',?ߍ` * ) * )L& , *L ( 1*  l ls:¬MA> ͧ  N Ĩ –.~+w.~2  9 : ! ~##~ !7 : !Կ : x*l " !ZXچ! 6  z2m#}1͖-m:m#8ͺk 2#2$M 2"!\#6!z#6:z#b:m#2}#!$6+6+6!o#6!"6!"_#"X#}2d#2g#2h#2c#2z#!n#6!e#6#6!j#6!"6:m#ҹ*ͨͺ!#6:}#͑ ͖%#:d#%# :p#=:p#_HH  (12/06/82) CP/M 3 PIP VERS 3.0 DISK READ$DISK WRITE$VERIFY$INVALID DESTINATION$INVALID SOURCE$USER ABORTED$BAD PARAMETER$INVALID USER NUMBER$INVALID FORMAT$HEX RECORD CHECKSUM$FILE NOT FOUND$START NOT FOUND$QUIT NOT FOUND$INVALID HEX DIGIT$CLOSE FILE$UNEX _{ozg^#V) "^#V|g}o "_{ozgO{ozgi`N#Fogo&og D ;! : .44 #4"l ~[* 2 a7 {7 w!Y #! *l "l " ~ U #D ]T!̷ 6*%.w#w!} 6 r 6 #w.6#6 #t#6.wo*.s#r.rͧ ̧ m . ^#V45+ w#w.f.5\A "l " l |F# !( |z: 6 : %2p  ͆ : =̀ 2r  DIR TYPE ERASE RENAME DIRSYS USER u"Q}:\=p:r Aæ R ÂN ͙ʸ} !M 545 x ]  ̵ 6 : oG! ~怹>2M  xf>:ͦ ͤ ͍ ͤ f ¹2 ":S# N:"H ͵!S#6:d#<"$\( K"#&#( Az:S#:" H҃͵!"6&#,"( Az>!S#Ҕͥ z:S#ʡ!e#6:j#z!f#6:p#,:p# Hͥ :p#,2j#!c#w:S#!$6:$!$6:$!PECTED END OF HEX FILE$INVALID SEPARATOR$NO DIRECTORY SPACE$INVALID FORMAT WITH SPARCE FILE$MAKE FILE$OPEN FILE$PRINTER BUSY$CAN'T DELETE TEMP FILE$ *5<P_lz)<\fp}NO DIRECTORY SPACE$NO DATA BLOCK$CAN'T CLOSE CURRENT EXTENT$SE ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0L !( : x. +"l ! ͮ   ͮ ~!G8 * ~;#1 կA *l ~:g X #I ѯ*l  *l ~0څ :҅ q X x<Ü AX QX X ~@#~:k #^ *jT~# ® wy#ù ! 4 : !Ͱ ~@*h~ yw y/w*hw*lf   ͫR  L͞L I *  *  A }_Yl !ͮ ͒6 \&đ %* "l ͍  ûȷ45: w ? A I N   SUBMIT COM ! ͮ ! 6 #"l  !cͿ  O!$6:"> !"H!d#"ͥ :"/!f#6:" T!f#6>'!f#Q!f#4<g:" dgA2:j#w"á:m#2}#b! $p+q*$}2{#|2x#!!$q:!$_ ͨ ͨ!#$p+q*"$ !%$p+qͺ*$$DM!|#6|#  !'EK TO UNWRITTEN EXTENT$RANDOM RECORD OUT OF RANGE$RECORDS DON'T MATCH$RECORD LOCKED$INVALID FILENAME$FCB CHECKSUM$2FTe$NONRECOVERABLE$R/O DISK$R/O FILE$INVALID DISK SELECT$INCOMPATIBLE MODE$INVALID PASSWORD$ALREADY EXISTS$LIMIT EXCEEDED$e USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Thh~I E> ͦ > æ % 0  < : ~ȹͦ #* A !g ~6*  * >? A *l " ~0: :: q "l x~0 xG#Gs : &͘ ͤ &ͦ %˜ >  Ʌo$>?· !  > # ͮ x> # ~ Enter User #::r :ͦ ͍ !~B I !pͰ ^#VCOM SUB PRL y!cͰ  î !" * %.2P#ͮ !g 4*l +"l ͷ 2 "Qx2Sl "Tx2V!q ~ :p ͆ .ڶ2* og$2| .w#w#w#w$p+q*&$!)$p+q$*($ DM!+$p+q**$DM **$DM̈́:{#**$ ~Hi **$!{#6!x#6!-$p+q*,$DM̈́!/$p+q*.$DM̈́DM̈́!1$p+q*0$DM *0$DM̈́!3$p+q*2$DM̈́!5$p+q*4$DM̈́!7$p+q$*6$ ~ *eT     =.:;,<> _[]OUTPRNLSTAXOAUXCONAXIINPNULEOFERROR: $ - $$$$DESTINATION IS R/O, DELETE (Y/N)? $**NOT DELETED**$COPYING -$ (Y/N)? $REQUIRES CP/M 3$CP/M 3 PIP VERSION 3.0$:"Q}#( :}#1"CP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282n2$͈͋> $No File$ required$ERASE $ (Y/N)? $ Press RETURN to Continue $ (User 0)$NON-SYSTEM FILE(S) EXIST$: $$$ SUBڜ!*$&!*$& !$sr!*$&$ :$w:$!>!$ҿ!ͥ -*|$ :$w 2p#_og_{ozg_og^#V))).~ .w#w~?w; ; ! ~#49 w#~$ A  < > _I  ! 6 ! ~#Ͱ 6 m   _  ! 6=  { *.pѯ:r x , \<=!Ͱ =ɯ2 \s 2 !6$ >w! *6$ >w$*6$ DM*6$DM̈́!9$p+q*8$DM *8$DM̈́!;$p+q*:$DM̈́ !<$q!<$:$ʐ :<$2$_ *#Mt *R#Mt *"Mt !>$p+q*=$!DM̈́:{#!@$p+q*?$"DM̈́:{#!B$p+q*A$#!D$p+q*C$$!E$q!E$k#!i# RG: $!$$5Ͱ5*p#M$:j#!c#G*_#"X#:e#QO͡ "  "ͩ 2{#n Hґ*""#:"2#!i#6:{#°*"#"">'"­!"4:{#*"!"">'"!"4" f:z#!"t$"x$͡ !h*j$M2j$2j$2l$:j$2k$2j$!l$w:l$D!o$6I!o$6: $!o$x:j$::j$Hu2j$T:*k$M*j$M:l$2m$"p$2n$:l$ʲ!l$52k$Ý" 2j$:j$0O> :j$0:j$AO>" :j$A 2j$$:$w>!]$!]$5 :\$ (!"6!^$q:^$!$wF ͹O:^$0O͹!_$q:_$O):_$O)!`$6:$2$:$'2$:$'2$:$'2$*$MP*$MP*$MP:$¿:͹ ͹ ͹!a$q:$:a$ :n#9:a$ :a$H9:$2b$6!"]#:g#ͬ !_#!"Y$>'")!"W$͙ :k#!l#we *W$$ DM" b" k" :a#Ҁ!@"Z# Ë!"Z# W$Y$;">'"W$Y$;"!@*"!a#W$Y$;""Z#!Z#"}O *W$$ DM" :{#" *Z#*W$"W$Ë::\# :E$2\#_,0!J$s+p+q+p+q:J$=2J$^ *F$*H$ w*F$#"F$*H$#"H$7  !z#6:h#~ ͡ "j !h#6:g#Ҕ ͙ "j "͢ !}#6!"6l!K$q_ *K$&) N#Fͺ!N$r+s+q:{#2Q$:x#2R$_ :L$:Q$H !R$6 :R$2R$6\ !"v$:{#t$v$;"H6*v$#"v$͔ :{#]>x$H"R\ : $\ͺ*v$#"t$:{#_!#&#( &#"( f#!1#6!"6:/#/!$#: $>x$H"!{#6:{#Y:{#NH':$͟O[2{#!{#6OH!m$wO`i"">!$@ ͥ >!$N ͥ *_#}bO2 ͙ "j :{#" :y#:.#:$:{#Y:{#NH{͟O[2{#Ø:{#Yͺ"͢ ͺ:.#2.#:/#2/#%#V %#͢ %#(:b$!b$6<:"<2"!b$(!"6 ͹>!$4k!n#6:a$ F!"6*a$M͹:a$ Z!n#6!c$q:c$a/>z!c$/H~:c$_2c$:c$!d$q:d$A/>Z!d$/Hҥ:d$ 2d$:d$!f$6*"M!N ^#Vͥ `"]#;" :e#/!b#!"X#]#@" $ң !"W$ Y$W$;"ҝ"ͩ 2V$*##"#>'"G!#4!U$6:U$ր!V$ҁ*U$& :U$W$!$ 2V$!U$4L*W$"W$:V$ښ" "Ϳ " *W$$ W$_#;"+s#r{_$( N :a#!@"Z# !"Z# ͡ *X#"]#X#";">*L$& N! N#F> !L$~H:Q$H> !Q$/H^  ͨ:Q$=O!r N#F!R$6:R$ {  ͨ*R$&) N#Ft>M$H" *M$~A=Oͨ:ͨ!P$6> !P$ *P$&*M$>2O$ :P$ .ͨ*O$Mͨ!P$4¢ ͺ:Q$:Q$H:Q$H:Y*x$#"x$!g#6:{#Y! $#Aͺ!z$6> !z$e*z$&%# ~2{$ ^:z$ W.ͨ*{$Mͨ!z$4/:$p>͡ !"6?" :{#ʲ:{#_!# "( :"ڬ>͔ ~>!":R#!":%#HH :#<2#!}#> *#&~# N[2p# #( "0 :&#!r#2&#:'##2'#:(##2(#:)##2)#:-#2-#:.##2.#:/##2/#:0#20#%#V :$}͡ :"2"!"6"V :b#ڦ!$""K"!>1"""""$@""!>1"""""$ """_#;" !"X#:$/>X#H"H@>*_#"X#*]#*"~2e$*]##"]#`5!f$62e$`2e$`̀2e$`"5E:f$ҕ:$Ҁ:o#<2o#2f$Ë:e$ 2f$:f$ҕN :$Ҥ:e$2e$:$ҳ*e$M[: $*e$M͂:e$>!":"=2"> >>!"!"5+N!~# ~2g$!"4'"X#";"!@*"!a#=X#";"!"Z#!Z#"}O *X#*"DM:"2W#"Ϳ :{#:{#n" :a#҇*x#&"*X#"X#!W#:":"րHҦ!"6" n /2k#:a#/!c#" "j !h#6!i#6*X#*"6*Z#*X#"X#![$q:Q$H :d#2z#D :R$>!R$~ HH> HD :d#2z#ͥ  m m ͥ !V#:"{ >!V#:"© !U#:"Ғ >!U#:"© !T#:"ҩ >>͙ %#-"( x"( :+#2+#%#! :{#2y# %#j :x# %# "͢:p# H !}$p+q.*|$ 6 !p#6 #6:q#,T:q# A!p#6N:q#$N!p#6 ͒ )$*|$ 6,*|$ 6:"<*|$w*|$ :#w!~$6>!~$ڗ*~$&$ 6!~$4|!"6#6#6!q#6*p#Mc :q#ھ:p#*Ͳ ͒ 2p#ê:p#:¿:q#(*|$#~A<*|$wO>X#H"""!r$6>!r$@:r$"!*"~9:r$"!"X#!r$4:e#!f#2a#!i#6!b#6!l#6+6!s$6>!s$ڶ*s$&$ ~ʯ*s$&$ ~‘!a#6ï*s$&$ ~¯:e#!f#2b#!a#6!s$4b~:f#W:a#:i#:c#!i#*X#"_#:j#*X#"_# *_#"X#:2g$ >>!$;*$Mk8:$2"!$6:"<2"!"6g>!$c*$Mk\!$6!"6> :g$g:g$!h$q:"!h$wO!~# ~2i$—*h$&~# :g$w>!g$:i$¨!"4í!"6>2p#:$X#]#;"!i#:p#!o$62j$:j$::j$:o$" [$ !"4>!$:$!":$1*[$&*S#M! ^#V*[$M̈́ø*[$&ø*[$&ø*[$&ø"_#;"ڄ *_#$ :[$w*_##"_#øg*[$&øAKYgu!\$q:\$ *\$M:$*\$M:"2]$!$:]$!$:]$2]$!] :{#:x#H!" " :{#L:x#D" L" !#6!g#6͡ :"2""! :{#u!h#6:$/:"HҊ!{#6:{#¯:x#§" ï" :"2r#:"2s#:"2t#:"2u#:"2v#:"2w#" 2{#"T#( !"6#6#6#*p#Mc %:p#[ !#5.*|$ 6 ñ:q#1!$6#6> !$ڰ!$6:$<2$O>/:$!$O!J *$&*|$ H~G:$¡.*|$ :$w[œ !#5:$2$!$49:p#[¼ _ :q#!q#6+~. 2p#Oc  :q# :p#* Ͳ ͒ ! p+q* !Z 6Z 1!Z 6,Z 1!Z 6]Z 1|"  ! q* &.! q* &e! p+qi* DM! q: <2 O* : w! p+q* ~$* : <2 O* w* #" ! q: 0Oͦ! q:continue.: Drive Characteristics128 Byte Record CapacityKilobyte Drive Capacity32 Byte Directory EntriesChecked Directory EntriesRecords / Directory EntryRecords / BlockSectors / TrackReserved TracksBytes / Physical Record, Space: e USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Th!q#6+~;= 2p#Oc = :q#$ *q#&$ *|$:p#w!q#4 :p#[H !#5.*|$ 6 *|$ 6å!$q!$6> !$ڏ *$&> :$ˆ >!$4l >:q#<2q#O*|$ :p#w:p#?± !d#6!$q!p#6?!$:q# ͒ û 2p#:p# :p#]H!:p#A2$O>!:p# O: O! q* M:ͦ! q* &! ͆K* &! ͆M! q* M& /ͦ: e : s ! 6: <2 O* ~2 : ” \ Æ : 0 ! s+q! 6͆ ͕ ڶ ͕  : : : H2  : 0! w \ ö ! :Number of time/date directory entries: Number of free directory entries: Active User : Active Files: # of files : Label for drive AccessCreate on off on on off on off 1}1}{o&" >0 1}CP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321 Copyright (c) 1982, Digital Research 10/27/82Show 3.1ERROR: INPUT: OPTION: DRIVE: Unrecognized Option.Unrecognized drive.!2p#!ͥ !:p#S:p#QHX!:#<2$2p#:p# HO!1!2p#Ü!2p#02$O> r!!$6Ü!2p#02$O> ڜ!*$&!*$& !$sr!*$&$ :$w:$!>!$ҿ!ͥ -*|$ :$w 2p#_og_{ozg_og^#V))) #~! H : ! s+q+q͆ ! : 4 \ * M* ͞ ! s+q: 2 : * &) >;H{ : =: ! q* &! ͆))))* &͈ } ͞ =2 : 2! !!6 * & ~2!/*! 2 /cN 2 : !!: ֑*!& ~ :!<2!*!& " 2 h2 !!6>!!Y*!& 6:!<2!;6f!$ 6(2! 6D~!% 6ͱ!!6>!!*!& ~2 ʺ*!& N*!Mz:!<2!†v! q* & ! p+q* ~* N* #" Requires CP/M 3 or higher.No directory label exists on drive Unrecognized input.A:0B:0C:0D:0E:0F:0G:0H:0I:0J:0K:0L:0M:0N:0O:0P:SPACE0DIRECTORY0DRIVES0LABEL0USERS0PAGE0NOPAGE !$'*-/#(.[]=, :;<>%\|"()/#!@&+-*? _{ozg^#V) "^#V|g}o "_{ozgO{ozgi`N#Fogo&ogH * &) : N_!mͥq* & NC * M* C _* #q#p͞ O * w:; O * w* ~¬ : :  :; 2!* 6 :; O * w!!s+q:!!!! 6N!m"!:  !n"!!  !    :$ e! 4~<<+~He  MC]! 6  ! p+q * DM }! q* &:~ҝ:}¦:}`O! : ½2}Õ! p+q* ~?2~* 2}͕2}͕;Zx0NSun$Mon$Tue$Wed$Thu$Fri$Sat$?????????????Directory Passwds Stamp StampLabel Reqd Update Label Created Label Updated------------ ------- ------ ------ -------------- --------------Press RETURN to  ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0L +s#r! 4 ! 6 >! P : =2 2 ! !6* &) : !m! M  * ~2!*  ~2!*  ~2!* #^#V" +!͆! !s ! !6: >;! HҮ ! !6 * &) : !m ! s+4* ~ : !O! DMͽ ͦ* MK * MK * M* &ͥ^ : =O 6-͑iE!: :>!: G>Zʹ2!_Þ:!=2 * & : w* &ͥ^ *V& 6!: ʝ* +" ͑iE! 6* Ny2 !* &ͥ^ *V& 6! 6!: ;2 -: y2 ?:!2 ͩ:!:!2 : 2!:!2!!!6:!2!?:!Jñ*!& *!*!&*!=2!!!:!£!!6!!6:!!!ڠ]:!/Җ6:!<2!~æ6!!6ͩ>:!2!:  l+s#r): * #" :2 :!:!2!*!&*!~2!*!&*#6:!<2!!"X 5!"!:}:}2!*!& ~2!:!!*!& "!*!##"!*!#"!:!2!:!2!O!& 6>!!Ґ*!* ~Ҥ*!~*!&6 ) N#F*!&6 ) q#p*X #"X %* & 6>!X * N#F`i* *!##* ##NH*!##w*!* ##N*!q#p: AO !!r+s+p+q*!/!a*!q#p*!ڒ*!*!q#p*!N#F*!q#pc!!q!"!"!!!6!"!* !:!*!DM2!:!/!!H*!"!ҫ*!!"! i8&  ͦ*!M *!M * ~& *!M! !p+q!" !* !"  " * ~~He Q ! 6 Þ * ~~Hқ ! 6* ~2 ͢ * &* " !Þ !-!p+q!!6.*,!DM! -¶ !' !.!6> !.! *.!& ! N:.!<2.! \* ##N! K-!: !!: !L! 6* #" !: K* Ny2 !K?͑iEi`N#Fog_og_ogDM!>))덑o|gҟ =DM!>))Ҵ =¬~ º~ ^#V) ^#V|g}o _{ozgO{ozgi`N#Fo!:9:!<2!:!2!*!&*!:!(*!&*!~2!!!6* ~2!:!2!!!6* #~2!:!<2!*!&*!:}!!6Ó*!&*!:!ʓ!!6:!<2!*!&* ~2!*!&* ~2!*!My2 : : H: H: H:!<2!*!&*"X * N#FPY*X *!"V 8QhOg 8`* & ~/\!!6>!!ڐ*!&& ~҆*!&g:!<2!a 8o!!6>!!*!&& ~*!&6 ) N#Fg:!<2!¡͘* & ~/͘!!qD*!##6* N#F*!q#p,ͦE* N#F^ * ^#V))DMy* ~* N!!+s#r*!DM  1:ͥ"/!!1!q:1!2 Oͅ !3!p+q!2!* >2!y#M͹!7!s+q+p+q:7!=27!f*4!:6!w*4!#"4!I!!s+p+q+p+q>!*!*!͆!!s*!*!͆"!*!! ͆"!>!º:!:!!!6:!0Ov!!p+q!'"!!!6>!8go&og_{_z#W ~2!*!My2 :!2 :  l#+s#r* Ny2 !D* #" ):  +"!!!6: !!y*!N*!#"!:!<2!W!!q*!&ͥ^ *V& ~ʞ*!&ͥ^ *U& ~ʾ1*!&ͥ^ *T& ~*!&ͥ^ *W& ~#>!! :}0:}`O! ~ * * Ḿ2!>!!/:}o&"!~i8 Eiji:!@@†Ìi B:% /:!րHҽ:!@@:!:! !!p+q*!##6*!*!s#r!!p+q!'"!!!6>!ʚ*!*!͆{2!*!*!͆"!*!! ͆"!>!!!+~Hҗ!!6:!0O5>0 ҹ" ͓DM$* Mqͦ1k!!p+q 8R*!}OW*!*!͆:!=2!O!8! s*!*!͆"!*!! ͆"!!!6#6:!=2!}*!&8! ~0O~:!:!Hz,~A!!q*!&8! ~¤:!Ҥ:!ʤ*!M!!6!!r+s+p+q!!6#6>!!0*!&*!*!&*!~!!#N*! w*!&*!^! *!&ͥ^ *S& ~: :: 2 * & : w* #" * Ny2 : ZÔ!: q!: qÔ* &ͥ^ *V& 6* #" >* &ͥ^ *V& ~* &ͥ^ *V& 6ʹ2 !X: !$ 6!Y: !$ 6*! DM͟ *! DM͟ >͑: AO !!6> !!x:! ].*!&*!>O:!<2!G!!q!!6*!& :•>*!& :!©:!:!<2!Â!!r+s+p+q)!!6?:!:!2!*!My2 !!6: ]:!/ *!M͛: : 2!"!S"!!!6>!ʈ*!}g: /X!!:!U*!DMg*!M*!DM!!+s#r!!+s#r#~!X *X g 8)*V g !!6>!! *!&& 6*!&6 ) >w͆!!s#N*! ^! ͆*!&*!q:!<2!!!p+q8!<?!<*!N#F*!##~2!!!6>!!ڙ:!҇*!&w!) N#F?!ͱ:!2!:!<2!d8!?!ͱ9!!p+q*!##~2!*!##~*!##w*!*!q#p*!#:!*!#w!!p+q*!#* ##N͹  F!M!T![!b!i!p!!F-6*G-*G-^#V#)))"I-*B,*G-^#V))W+"B,*B,>og"@,:F-f!,,> c!y0ͷ~!{0!+Q/>r2K-*I-w#w2P/>2O/2N/!/(,>t!"N-:F-X!D,LG!),>y :#!#6!Q/D,>_:O/!N/:N/2O/2N/!P/4!}0O2:eel !6>!ڜ2 K*&l :w: T:_:…:r:=2O!l 6 3:•!4**& ~ ~ H!4Ýl :S*Q*Sl.l\P"*}= below: USER 0 --> contains the utilities. USER 1 --> contains the CPM+.SYS source. USER 2 --> contains the ROMBIOS source. USER 3 --> contains misc. source files. Instructions for building a system are found in the .DOC files in _{ozg^#V) "^#V|g}o "_{ozgO{ozgi`N#Fogo&og!0*L-#"L-!0A !/*!/>X!/>Xt!D,KLG!.,>y:O/!N/f:N/2O/2N/!/>X!.,!,@!D,KL(,tî!N/4!,/>c!0!0!0n !N-~#!0̓ ã!0ͬ!D,/,>c!0~U!9"0:#*|&el\P"=*|5.*& 6!6͝*& ~( 2*& 6e!"!\" "\p.e.:\2O>:2\USER areas 1 and 2. Read them for details about system generation. Use PIP to backup this disk. DO NOT use this disk for a work disk!  ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0LZ!#6!#"/r*/>$Gt!##>Gt!#0,>Gt!#6!#6!#"0!0T!F-6!"#!D,6!06:0}͐3>!D,ͧd*0!F-6!#6*##"#*# |.!"0}20!0>!#*0"0!0U!#"0!0+!#*06*0 "0!04í!"#:*& ~ ~H~ H.!4͝*& ~2!6>!`\̓[>!6:<2=O! ~2 ½:<2O>9ҽ!60+~9ҽ!60+~9ҽ!60+~9ҽ!60+4:͓ͪ!"!6:= !6!6#6D2:e USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> The USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Th+.!+6:# :# :#.~!#*#~20:0 20:0Q~:0Þ:K-z"/!0Ur"/*/ 3,>Gt!0#!D,6,> c!0ͷ~Ͳ"0~# ¦*0^#V"0*0^#V"0͕!1"1!216>261251:!12:1::1!51!!1:51og~271:21i!v"/!Q/+>c!K-6*/K>XG!+>yC!Q/+>c!+Q/>r–!}o|g}ʖ!#"/!/–!/ʖ!/+>c!/ͷ~g"B,U"G-!,,> c!o0ͷX:F-!,,> c!q0ͷ~*G-w#w:F-X!s0͡+q:2!6*&"1!p+q*<!s+p+q+p+q:=2d** w*#"*#"=  !s+q+p+q:=2ʩ*:w*#"Ì!p+qe*DM!\.\s!q:a:{: : 28May87 CP/M 3.0 on the Commodore 128 supporting the 1581 disk drive This single disk contains the various utility programs, library files and source files needed to generate a new CPM+.SYS. These files are found in the USER areas described!216{:71!61281*0:61o:81OLG!1>c:81og>og}281*0:81ogW"0*0:81og####"0*0*0W*00>c*0";1!;1ͷ~>291!1n&}2=1:=1!91*1:91og"1*1~og |*1>ߦw*1~?*16_*1~@*16`!914ådirs,?off,?ncks local ?spt,?bsh,?blm,?exm,?dsm,?drm,?al0,?al1,?cks,?psh,?psm local ?n ;; physical sector mask and physical sector shift ?psh set 0 ?n set ?psize/128 ?psm set ?n-1 rept 8 ?n set ?n/2 if ?n = 0 exirive Table. Contains 16 one word entries. dtbl macro ?list local ?n ?n set 0 irp ?drv, ?n set ?n+1 dw ?drv endm if ?n > 16 .' Too many drives. Max 16 allowed' exitm endif if ?n < 16 rept (16-?n) dw!/3>XG!3>y.!/3>X3t!/3>XG!3>y[!/3>X3t*3!3>}23:3ʐ!/3>S*3:3<_Lt*3"3!3ö*33>_*3"3!3!;3"93!3*3>!t!<3"53!L33>Gt!Q33>Gt!"'32.3*'3* !16!"1*1n&"1*1"1' *1#"1*1*1W7 *1*1>Ó*1~og |c !1>ߦw !1~?t !16_ !1~@‚ !16`Y2 ~# ˆ *_2^#V"e2*c2^#V"g2!"2*[2^#V"2*2*2W *]2*2ͯ"2!2 :2 *e2*2)))~# *g2^#V#**0++*0)"1*11>_*0^#V"31*0^#V#r+s*1*0*0^#V)))s#r*0:61_L*0*0^#V)))>t*0*0^#V)))w#w!31#`*0*31)))^#V1j`*0*0^#V)))"1*1!1>Gt*0*31)))"1*1*1>Gt*31+"31*0tm endif ?psh set ?psh + 1 endm ?spt set ?pspt*(?psize/128) ?bsh set 3 ?n set ?bls/1024 rept 8 ?n set ?n/2 if ?n = 0 exitm endif ?bsh set ?bsh + 1 endm ?blm set ?bls/128-1 ?size set (?trks-?of 0 endm endif endm dph macro ?trans,?dpb,?csize,?asize local ?csv,?alv dw ?trans ; translate table address db 0,0,0,0,0,0,0,0,0 ; BDOS Scratch area db 0 ; media flag dw ?dpb ; disk parameter block if not nul ?csize dw ?#3^#VW*'3#"'3*#3*'3)))^#V!<3>p!")3*)3 |*53+*)3"73*73~ ]Æ*73~_n*736?|*73~`|*736@*)3#")38*#3*'3)))!M3>Gt*#3*'3)))^#V")32-3!)3~#ʖ:-3 ͟!<33>t!M33>t2-3!-34*%3++*)3))^#V"e2*2)))s#rc *e2*2)))^#V"2*g2*2))~#K *g2*2))^#V"2% *g2^#V#*g2*2))s#r*g2^#V#r+s*a2^#V*g2^#VW !i272>!c!2ͷ~*2+|´ *Y2^#VO"2þ *Y2^#V"2*2*g2++*g2^#V))s#r*g2*g2^#V))w#w*2#"2ô 2~# *31)))^#V1j!31#T*1"1*0*31)))"1*1*1>Gt*31+"31*11>Gt:71%^}2C1:C1!A1$ *0:A1_LG!>1>t!0>1xy!0>1xy !B14:A1!!1:B1of)*?spt ?dsm set ?size/(?bls/128)-1 ?exm set ?bls/1024 if ?dsm > 255 if ?bls = 1024 .'Error, can''t have this size disk with 1k block size' exitm endif ?exm set ?exm/2 endif ?exm set ?exm-1 ?all set 0 ?n csv ; checksum vector else dw 0FFFEh ; checksum vector allocated by endif ; GENCPM if not nul ?asize dw ?alv ; allocation vector else dw 0FFFEh ; alloc vector allocated by GENCPM endif dw 0fffeh,0fffeh,0fffeh ; dirb; Macro Definitions for CP/M3 BIOS Data Structures. ; dtbl - drive table ; dph translate$table, - disk parameter header ; disk$parameter$block, ; checksum$size, (optional) ; alloc$size (optional) ; skew sectors, - sk *26*2LG!X2>yC *2"3*3#~>!3w:3og2~C :2 !26*e2^#V#"3!3"323!3> *3++| !"3Ñ *3>og"3*3:3og)2s#r!34d !" 3*e2^#V" 323*2"3!3"3* 3* 3W_!34:3og)2^#V" 3*e2*3)))gw!0>1xy :B12!1!A14ì*00>c*0"D1!D1ͷ~^#V"F1*F1^#V> ͍!H1 *!H1> XÓ1~# s !9"2!1"1!16*1w#w*1ng | *1KLG!1>yº !1**1~ogQ1~og)1^#V*1^#V#r+sH !11>c ! set (?ndirs*32+?bls-1)/?bls rept ?n ?all set (?all shr 1) or 8000h endm ?al0 set high ?all ?al1 set low ?all ?drm set ?ndirs-1 if not nul ?ncks ?cks set ?ncks else ?cks set ?ndirs/4 endif dw ?spt ; 128 byte rcb, dtabcb, hash alloc'd ; by GENCPM db 0 ; hash bank if not nul ?csize ?csv ds ?csize ; checksum vector endif if not nul ?asize ?alv ds ?asize ; allocation vector endif endm dpb macro ?psize,?pspt,?trks,?bls,?new table ; skew$factor, ; first$sector$number ; dpb physical$sector$size, - disk parameter block ; physical$sectors$per$track, ; number$tracks, ; block$size, ; number$dir$entries, ; track$offset, ; checksum$vec$size (optional) ; D^#V"3*2*3j/*3+" 3* 3* 3"3!36\*3*2jY*3#" 3* 3* 3W"3!36\Û :3o* 3"3u* 3"3*e2*3)))^#V"3*2*3jʛ*26*3*2s#r3 ~# ±*3^#V"#3*!3^#V"%3! ÷>2.3*3~ʟ*34*3~og"3!3A !/3*1*>22*1~ogQ1~Y !11xyK !24H :2K !1!1> !1* *1*1^#Vͯ1>_ *1~ogQ1~ !1*{ !1*!11xy !1*é !1**1~ogQ1~ !1* *2:1ecords per track db ?bsh,?blm ; block shift and mask db ?exm ; extent mask dw ?dsm ; maximum block number dw ?drm ; maximum directory entry number db ?al0,?al1 ; alloc vector for directory dw ?cks ; checksum size dw ?off ; offset for syse USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> ThRVK = A ODTADRVL = A ODTADRVM = A ODTADRVN = A ODTADRVO = A ODTADRVP = A OVLYDIRA = Y OVLYDIRB = Y OVLYDIRC = Y OVLYDIRD = Y OVLYDIRE = Y OVLYDIRF = Y OVLYDIRG = Y OVLYDIRH = Y OVLYDIRI = Y OVLYDIRJ = Y OVLYDIRK = Y OVLYDIRL = Y OVLYDIRM D = N ALTBNKSE = N ALTBNKSF = N ALTBNKSG = N ALTBNKSH = N ALTBNKSI = N ALTBNKSJ = N ALTBNKSK = N ALTBNKSL = N ALTBNKSM = N ALTBNKSN = N ALTBNKSO = N ALTBNKSP = N NDIRRECA = 04 NDIRRECB = 04 NDIRRECC = 00 NDIRRECD = 00 NDIRRECE = 00 NDIRRE set ?nelts-1 if ?nelts = 0 ?nxtbas set ?nxtbas+1 ?nxtsec set ?nxtbas ?nelts set ?neltst endif endm endm tem tracks db ?psh,?psm ; physical sector size shift ; and mask endm ; gcd macro ?m,?n ;; greatest common divisor of m,n ;; produces value gcdn as result ;; (used in sector translate table generation) ?gcdm set ?m ;= Y OVLYDIRN = Y OVLYDIRO = Y OVLYDIRP = Y OVLYDTAA = Y OVLYDTAB = Y OVLYDTAC = Y OVLYDTAD = Y OVLYDTAE = Y OVLYDTAF = Y OVLYDTAG = Y OVLYDTAH = Y OVLYDTAI = Y OVLYDTAJ = Y OVLYDTAK = Y OVLYDTAL = Y OVLYDTAM = Y OVLYDTAN = Y OVLYDTAO = Y CF = 01 NDIRRECG = 01 NDIRRECH = 00 NDIRRECI = 01 NDIRRECJ = 01 NDIRRECK = 01 NDIRRECL = 01 NDIRRECM = 04 NDIRRECN = 01 NDIRRECO = 01 NDIRRECP = 01 NDTARECA = 01 NDTARECB = 00 NDTARECC = 00 NDTARECD = 00 NDTARECE = 00 NDTARECF = 01 NDTARECPRTMSG = Y PAGWID = 4F PAGLEN = 17 BACKSPC = N RUBOUT = N BOOTDRV = A MEMTOP = FB BNKSWT = Y COMBAS = E0 LERROR = Y NUMSEGS = 01 MEMSEG00 = 60,3B,00 MEMSEG01 = 00,C0,02 MEMSEG02 = 00,C0,03 MEMSEG03 = 00,C0,04 MEMSEG04 = 00;variable for m ?gcdn set ?n ;;variable for n ?gcdr set 0 ;;variable for r rept 65535 ?gcdx set ?gcdm/?gcdn ?gcdr set ?gcdm - ?gcdx*?gcdn if ?gcdr = 0 exitm endif ?gcdm set ?gcdn ?gcdn set ?gcdr endm endm ske OVLYDTAP = Y CRDATAF = N DBLALV = Y G = 01 NDTARECH = 00 NDTARECI = 01 NDTARECJ = 01 NDTARECK = 01 NDTARECL = 01 NDTARECM = 00 NDTARECN = 01 NDTARECO = 01 NDTARECP = 01 ODIRDRVA = A ODIRDRVB = A ODIRDRVC = B ODIRDRVD = B ODIRDRVE = B ODIRDRVF = A ODIRDRVG = A ODIRDRVH = B O,C0,05 MEMSEG05 = 00,C0,06 MEMSEG06 = 00,C0,07 MEMSEG07 = 00,C0,08 MEMSEG08 = 00,C0,09 MEMSEG09 = 00,C0,0A MEMSEG0A = 00,C0,0B MEMSEG0B = 00,C0,0C MEMSEG0C = 00,C0,0D MEMSEG0D = 00,C0,0E MEMSEG0E = 00,C0,0F MEMSEG0F = 00,C0,10 HASHDRVA = Y HASw macro ?secs,?skf,?fsc ;; generate the translate table ?nxtsec set 0 ;;next sector to fill ?nxtbas set 0 ;;moves by one on overflow gcd %?secs,?skf ;; ?gcdn = gcd(?secs,skew) ?neltst set ?secs/?gcdn ;; neltst is number of el ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0LDIRDRVI = A ODIRDRVJ = A ODIRDRVK = A ODIRDRVL = A ODIRDRVM = A ODIRDRVN = A ODIRDRVO = A ODIRDRVP = A ODTADRVA = A ODTADRVB = A ODTADRVC = A ODTADRVD = A ODTADRVE = A ODTADRVF = A ODTADRVG = A ODTADRVH = A ODTADRVI = A ODTADRVJ = A ODTADHDRVB = Y HASHDRVC = Y HASHDRVD = Y HASHDRVE = Y HASHDRVF = Y HASHDRVG = Y HASHDRVH = N HASHDRVI = Y HASHDRVJ = Y HASHDRVK = Y HASHDRVL = Y HASHDRVM = Y HASHDRVN = Y HASHDRVO = Y HASHDRVP = Y ALTBNKSA = Y ALTBNKSB = Y ALTBNKSC = N ALTBNKSements to generate ;; before we overlap previous elements ?nelts set ?neltst ;;counter rept ?secs ;;once for each sector db ?nxtsec+?fsc ?nxtsec set ?nxtsec+?skf if ?nxtsec >= ?secs ?nxtsec set ?nxtsec-?secs endif ?nelts&:U2!V!""V*!VM"V͟:!V2U! U6Û*U|!U2!V* U|!Uo&)##""V*T&+SDM*!V*!VM"V͟:!V2 U:U2!V!""V>T͇S+s#r*!VM"V͟:!V2U* U|!$V2T:T2T U(T(TͩC*$V&+ST͊S+s#r* U|!$V2!V:-Q/ *T&+SDMV6? ͜*VDMN*V~  (7*VN !V6>!Vn *V#"V:V:-Q/HX *V6d ,7*VN :V<2V, *V++"VNÊ *VN*V !V6!V6Te!Vr+s+q:-Q/Ү >!V6#q#p!V6:5Q!Vڳ*V&+SFQ  VzSک:VM*V&+SFQ +q *T 6 *T 6*T!Tp+q*T!Tp+q*T!Tp+q*T] ͧ!Tp+q*T} ͧ!Tp+q*T ͧ *T 6!Tp+q*T!Tp+q*T! ͧ!Tp+q*T" ͧ!Up+q*T$ CP/M 3 Sys $ Memseg No. $ Bank $ Accept new memory segment table entries $Default entries are shown in (parens). Default base is Hex, precede entry with # for decimal $ Use GENCPM.DAT for defaults $Create a new GENCPM.DAT file $Display Load Map at1TdCP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282nLT`0123456789ABCDEF ERROR: $Reading file: $Writing file: $Directory full$Reading file: $Writing file: $Invalid drive.$) ? $) ?*!V"*T&+SDM*!V*!VM"V͟:!V!Uw:-QҢ!T6:T2TULTLTͩ*U|2!V*U|!Uo&)*"V""V*T&+SDM*!V*!VM"V͟:!V! Uw:,Q/Ҳ:V2V *V&U  :T2T*T&! S!0*V& U q*T&! S0*V& ~*V&+SFQ  VzSHJ:V2V*V&+SFQ  ^#V"Vé*V&+SFQ  ~*V&+SFQ  VzSHҩ:V2V*V&+SFQ  ^#V"V:V<2V¿ :V:VH`!V6:5Q!V`*V&+SFQ  VzS/*V&$!Vr+s+p+q+q:V *V*VDM*V -- !Vs+p+q:VJ *V*VM!VLS!Vq:V e > :Va/>z!V/H҄ :V_2V:V!Vq:V/>!V/HҦ >ͧ>!Vp+q(7*V~ Y7 N7NTe:T *TMV Y*Vw!Vq: Cold Boot $Number of console columns $Number of lines in console page $Backspace echoes erased character $Rubout echoes erased character $Initial default drive ($:) ? $Top page of memory $Bank switched memory $Common memory base page $Long error messages $) ? $Bad character, re-enter $ $ Disk read error: $File cannot fit into GENCPM buffer: $Unable to open: $BDOS3 BIOS3 Setting up directory hash tables: $ Enable hashing for drive $: $Unable to allocate space for hash table.$ S!U q:V 2V*T&+S"!U$-U RUW !T6#6#6:.Q2U:/Q2UTqT TyT Uͧ pT !T6Uͧ pT pT :;Rһ!;R6:%V2.Q:4Q/24QTT TT L!U6N!Vr+s+p+q*V6 *V#6 *V|O! *V## w*V|O!+SFQ  ~H*V&+SFQ  VzSHV:V2V*V&+SFQ  ^#V"V:V<2V:V!$V6!U6ͬ#Q$!H> U͇Sʔ* U|2Uß*U|2U!U:.Q2T*U|!UO:/Q2T*U|O:T2TUTI:-Q/!$V>O:T2T* U|O:T!$VVO! N7:VO! N7!Vp+q 7*V|O *V}O H7!Vq*V&+SDM$ !Vp+q!V6!V60!'"V>V͇S† *VM7 !V6>!V VVzSڽ !V6:V<2VVVzS+s#rÔ :V *VM7!V60*V! S"V:V<2V‹ !Vs+q(7:V  #7$Double allocation vectors $Accept new system definition $ CP/M 3.0 System Generation Copyright (C) 1982, Digital Research $ BNKBIOS3 SPR$BIOS3 SPR$BNKBIOS3 SPR$BDOS3 SPR$RESBDOS3 SPR$BNKBDOS3 SPR$ 64K TPA Copyright (C) 1982, Digital Reseaetting up Allocation vector for drive $ Setting up Checksum vector for drive $ *** Bank 1 and Common are not included *** *** in the memory segment table. *** $Number of memory segments $ CP/M 3 Base,size,bank ($) $ Enter memory segment tabl *V w*V}O! *V w*V}O! *V w!T:TO`iPSW "V*V :0Qw*V :2Qw*V :1Qw.*V :3Qw*V :4QwX*V   :+Q/ҼW*V >*V w:@*V wW*V >*V w^*V :/Qw!)X"V*2T:T=2T* U|O:T2TҮ:-Qқ*nV*U*V |!UO:/Q2T*U|O:T2T2Uͬ:U/Ҙ!!V6>!!Vژ*!V&$SQ  6:!V<2!Vsà!U6:V/ҫ*:U2T:T2TTͩ:-Q*T&+SDM*U*T&+SDM*U:-Q/*V&DMZ  *VM N!Vs+p+q+p+q :T: ͜*V6:V<2VO!T NV 2V  :V,u *V#"V*V6!V6 :V#… !V6  :V02V:V> !VHҽ >!VҸ :V2Vý !V6!V:V *V^*V&+S*V& *Vq !V6*V6ͧ *rch *** CP/M 3.0 SYSTEM GENERATION DONE ***$!Tq:UM*T&!Tp+q:Ud*T !Tp+q*T#6:UҀ:Tڀ*T *T#N! *T6 7 7!Tr+s+q+q!U6N*TDMN:TTN͜:T.:T/!U!]6 !m6 !Tpe: $ Base,size,bank $Zero length segment not allowed.$Bank one not allowed.$ ERROR: Memory conflict - segment trimmed. $Memory conflict - cannot trim segment.$ ERROR: Memory conflict - segment trimmed. $ ERROR: Memory conflict - segment trimmed. VN#F!W "V*V"V*V͕S(!$V6-!$V6*VSD*VWR!"&V!V6&VS!V6>!Vڷ*V&)*&V>͒Sʭ*V&)*&VWR"(V*(V ͕Sʭ!V6:V<2Vf:-Q/!V!$V6!$V6V>X W*V"V*V~>>!Vs+p+q+d value in the DPH directory BCB address field.$ Setting up Blocking/Deblocking buffers: $ The physical record size is$: $ *** Directory buffer required *** *** and allocated for drive $: *** $ Overlay Directory buffer for drN;Rʹ :=R2T͜͜N,Qʹ ͜͜:>R2T:2Q<22Q  2Q :2Q=22Q:?R2T:1Q<21Q' 1Q :1Q=21Q:@R2THN3Qʹ ͜:AR2TkN4Qʹ ͜͜:BR2TN:0QAO7NTe:T"*TMV A2W*WM͈ /"Þ":W20Q͜͜:CR2T.Q *.Q&7*HQM N:V/҈!N!V6:5Q!V !V6:V/ :V =O!=R ~2T*V&+SFQ DM *V&+SFQ  N`iPS*V&+SFQ  q#p*V&+SFQ  ~ͧ *V&+SFQ  ~7ͧ *V&+SFQ ~2V*V&*V&)*&VWR"(V*V&)*&V>͒S*(V S?!V6*(V ͕S:V/c!V6N:VO!=R ~2T *(V WR"*V**V N#F`i))"VN:VAO7N*V&6Q DMʹ ͜*V&6Q ~/*(V q#p:-Q/!V6*V&,V) *Vs#r*V*Lp+q%N*VDMN 7*VDM$  7*VME :,QҨ *V&U *VDM :V 2V*V&U DM*V:V2V*V&U *V&+S:V2V*V&U ) :V2V!Vp+q*V"TͣN,ͧ*VDM !Vr+s+p+q*V^#V"T*V##^#V"T*V ^#V"Tive $: $ Number of directory buffers for drive $: $Minumum number of buffers is 1. $ Number of directory buffers for drive $: $ *** Maximum number of directory buffers *** *** for the current drive is$. *** *** Number of PS"U:DR2TN-Qʹ ͜:-Q/2T:-Q[#:ER2T/Q ͜:FR2TN+Qʹ ͜x#:R2T͜N!W#*W&U 6:W<2W#!W6>!W $*W&U 6$:*V&+SFQ  N "V*V|*V}O:/QH҆MN!V:/Q*V&+SFQ  Hq!V:/QO`iPS*V&+SFQ  q#p *V}2V!V6!V6!V:V# *V&+SFQ ~2V*V&+SFQ  :V2V*V&+SFQ  *V&+SFQ  !V"LV*V͛ 2V'ͧ*V&+SFQ  *(V w*V&+SFQ N`iPS*V&+SFQ  N`iPS*V&+SFQ  ͕S *(V q#p*V&+SFQ  VzS*V&+SFQ  q#p:V<2V:-Q/!V!$V6:T<<2T:T<<2T*V#DMT  *VDMT *TZSU͊S@?ͧ*T+ZS}<2V!V6!V:V҆*V&+SW "TDMͧ *VDM> :V<2VS*TDMO W*T"T!Vr+s+q:VGTqT TyT *Vn}2T*V#~2TpT WTS}pS}TR+s#r*V&)+directory buffers reduced *** *** accordingly. *** $ Share buffer(s) with which drive ($:) ? $ *** Data buffer required and *** *** allocated for drive $: *** $ Overlay Data buffer for driveW<2W#!V6*V&U  !V6TqT TyT Wͧ pT^ pT^ WS#ZS"U!W6>!Wڋ$*W&,V) >w#6:W<2Wh$!"LV:]A$!U6#6!W6>!W$*W&=R 6:W<2W¦$$!U6#6:mD$!U6!T6 Available space in 256 V:V/+~!V/H+ |ͧ!V6 :V!V+~!VHc N*V&+SFQ :Vw!V6 :V!V+~!VH N!V:V*V&+SFQ  Hq!V:VO`iPS*V&+SFQ  q#p!V6:V<2V×1:V<2V"͜!V6:5Q!Vo!:V!!V6>!V8*V&NV) >w#6*V&pV) >w#6:V<2V:!Vڡ*V&)*&V>͒Sʗ*V&)*&VWR"(V *(V WR"*V*(V ͕SN:VAO7:7!V6**V ^#V!S*V&+S*V&NV) q#p*!Vs+6:V!V4>T͇S+s#rBKͧ pT^ :V<2VpT *VT :-Q/k)Tw T z!LT"V!U"V͙!T"V!U"V͙!(T"V! U"V͙*V#DMT  *VDMT *VDMeͧWͧ *VDM> *V*Ws#r*V##*Ws#r*V $: $ Number of data buffers for drive $: $Minumum number of buffers is 1. $ Number of data buffers for drive $: $ Share buffer(s) with which drive ($:) ? $ Allocate buffers outside of Common $ Accepbyte pages: $TPA =$, Bank 0 =$, Other banks =$Unable to allocate Dir deblocking buffer space.$Unable to allocate Data deblocking buffer space.$Unable to allocate Data deblocking buffer space.$Drive specified has not been defined. $0FFFFH is an invaliN!N:V=O *V&+SFQ NE *V&+SFQ  NE :-Qb!N*V&+SFQ  N ͜:V<2V !T6!V6%NVʹ ͜PNT2V!TT TT N!V6Vʹ ͜:V!FT !!U6+6!W6͌!:W/җ#:R2T͜V&NV) nVR+s#r*(V ͕S—'N:VAO7:7!V6**V >R!S*V&pV) s#r*V&) VR+s#r **V R*V&pV) CS **V q#p:V<2Vk:Vҫ͜:T2FQ!T:/Q2GQ!"IQ!HQ6!V6ON:GR2T 5Q N*FQM ,7*GQM , *Ws#r*VDM> !V6&VS(>!V6>!V*V&)*&V>͒S*V&)*&VWR"(V *(V## *(V ͕S*(V ͕SH*(V ͕SH*(V ͕SH*(V ͕SH!V6:V<2V-:V!V6!V6!V6>!Vt new buffer definitions $!W6>!W**W&)*&V>͒S**W&)*&VWR"(V ͕S*(V ͕SHҸ* *(V WR"*V**V ^6 *W&$SQ q#p*W&$SQ  6*(V ͕S*%ͧ!W4*!W6>!W+!"HW}2W>!W=+*W&|O:/Q2T*U}pS}URW"\W*T&PS"XW*T&PS*U "VWÇ;*RW*`W|O:/Q2TW*U"\WO`iPS*`W "XW*T&PS* U "VW*RW*\W"T*U|O:T2T*W&)*\W"jW*XW"ZWWTS"U*T"`W*`WW !T͕S;*`WW 6*`W#"`W;!W6!W6!W6:5Q!Q  ~h7*jW6 *jW *VWs#r*W&$SQ VWR+s#r*(V *ZWs#r:fWZWR+s#r:fWjWR+s#rë7*(V"LW*W&$SQ  n&)*&VWR"(V ^#V"NW*LW"(V *NWs#r*W&$SQ  >£8*W&$SQ  ~48*jW6 *jW *VWs#r*W&$SQ VWR  : Ww͜*W&$SQ  :Wwn3:U!W]3:W+O!=R ~2T)N*W&$SQ  DMʹ ͜*WMTCn3 4! W6*W6 dWDS+s#r!W4>JWR>fS:WHҿ3!JWVS+s#r!W4Ì3!JWVS+s#rç-!W4n&))lW  ^#V"JW-!T6!W6:W 4bB>'*W&$SQ  DM  : Wt/! W6*W&$SQ  ~t/A'ͧb'N:WAO7'*W&$SQ  DM  &/*W&$SQ  ~^W͇Sҹ/'N*^WDM$ 'N*W&$SQ  *^Ws*W&$SQ  ~R0:W[O!=R ~2TM(N*W&$SQ  ~AO7($SQ HW|S ~H6+*W&$SQ ^#V"HW!W4**W&))lW *HWs#r*W&))  >w#6!W6>!W+*W&$SQ HW|S>͇SH+*W&))lW  *W6 DS+s#r*W&$SQ  6!W4h+!W4*!W6>!W7,*W&+SFQ  *WS<*W&+SFQ  2W!FQ  ~:W!WHL<:W2W:W2W!W4;:T2FQ!T:/Q2GQ:W<*W&+SFQ  O:T<*W&+SFQ  N`iPS!͕S"`W!FQ :T w*W&+SFQ  N`iPS*`WiS!q#p!W6n&))+s#r*(V *ZWs#r:fWZWR+s#r:fWjWR+s#rã8*(V"LW*W&$SQ  >o&)*&VWR"(V!Q  >ʂ8*(V ^#V"NWÐ8*(V ^#V"NW*LW"(V *NWs#r!W4>JWR>fS:WH8!JWVS+s#r!W4ç8!JWVS+s#r6!W4n&))lW  ^#V")NWʹ ͜P,!"PW}2Wo&"TW2W>!Wu5*W&$SQ  ~n5*W&$SQ  ~ >Hһ4:-Q|4!W4á4*W&$SQ !^N#F-S*TW"TW*W&$SQ  ^*PW"PW*W&$SQ  ~ >Hn5:-Q/5!W4*W&$SQ NTe:TL0*TMV A2 W* WM͈ *0/* WMF80/*W&$SQ  : Ww͜c0*WMTCc0 4*(V ͕Sn3!W6*W&$SQ >͒S°0*(V q#p*W&$SQ  6n3bB*W&$SQ  >w:-Qګ1: W1:W1! W6!W6*W&$SQ  6(N:W&W) N#Fq#p*W&+SFQ  *W&7W w!W4+:-QF,!fW6K,!fW6 !W6:W4:fW=2iW!"gW"dW}2 W! W6*T&PS*LViS"bW:-Qڞ,nVbWzS*ViS"bW!W6>!W,*W&W) *W&+SKQ  N#Fq#p*W&$SQ  6!W4£,!W6! W6#6!W6n&lW  ^#V"JW*W&))lW >͒S:WHғA!W6>JWR>fS:WHh=!JWVS+s#r!W45=!JWVS+s#r:WxA*W&)*&VWR"(V*W&$SQ  >0?*W&$SQ  ~>*(V"LW*W&$SQ  n&)*&VWR"(V ^#V"NW*LW"(V *NWsJW\6!W6>!Wc9*W&,V) >͒S\9*W&)*&VWR"(V *VWs#r*W&,V) VWR+s#r!W4 9!W6>!W9*W&)*&VWR"(V*W&NV) >͒Sʽ9*(V *VWs#r*W&NV) VWR+s#r*W&pV) >͒S9*(V *VWs#r*W&pV) VWR+s#r!W4h9aB! ~,5*W&$SQ !^N#F-S*TW"TWT5*W&$SQ !^N#F-S*TW"TW*W&$SQ  ^*PW"PW!W4#4*fW&*PW+S*W&) "RW:-Q9W*U"jW*RW*U*TW *LV *V *nV |O:.QO:T2UO:T2T:T2T:T2T|2U!T2.QW"T*TWAO7(N1: W1!W6! W6:Wʨ1:WƋO!=R ~2T(N:WAO7)N*W&$SQ  DMʹ ͜*W&$SQ  ~ґ1*W&$SQ  6è1*W&$SQ  6! W6S2:WKO!=R ~2T)N:WAO76)*W&$SQ  DM  *W&$SQ  >w: WS2))lW  ^#V"JW*W&))lW >͒S:WH3:WE-1&N!W6]&N*W&))lW N#F$ {&N!W6>JWR>fS:WHҚ-!JWVS+s#r!W4g-!JWVS+s#r:W3*W&)*&VWR"(V WR"*V >RZS"^W **V ͕S-!W6-!W6#r0?*\W*ZWs#r*(V *XWs#r*XW##"XW*\W##"\W!W6*W&$SQ  ~!W ?*W&$SQ ^#V͛ 2W*jW6*W&+SFQ N`iPS!N`iPS!͕S  *jW q#p *jW 6*W&+SFQ  *W&$SQ |S+s#r:fWZWR+s#r *jW s#r:fWjWR+W6>!W::*W&W) *W&+SFQ  N#Fq#p!W4:*V*RW*nV "RW> U͇SUzSH҇:*TW*U|O:.QO:T2Uá:*TW* U|O:.QO:T2U!U:T2T:T2T:T2T:.Q2.Q* U}pS} URU͊S"`W> U͇SUzSHB;*RW&PS*U "ZW*RW "VW*T"`W*`WW !T͕SC6*`WW 6*`W#"`W6!W6n&))lW  ^#V"JW*W&))lW >͒S:WH9!W6>JWR>fS:WHҶ6!JWVS+s#r!W4Ã6!JWVS+s#r:W8*W&)*&VWR"(V*W&$SQ  >«7*W&$S! W6*W&$SQ  ~S29)ͧZ)N:WAO7)*W&$SQ  DM  2*W&$SQ  ~$3: WҌ2! W6*W&$SQ  :Ww 3:WkO!=R ~2T)N*W&$SQ  ~AO7)NTe:T 3*TMV A2 W* WM͈ 2Ü2* WMF2Ü2*W&$SQ*(V ͕Sc0bB*W&$SQ  >w:-Q.: Wd.! W6*W&$SQ  6&N:WAO7&N.:W{O!=R ~2T&N:WAO7'N*W&$SQ  DMʹ ͜*W&$SQ  ~.*W&$SQ  6.*W&$SQ  6t/:W;O!=R ~2T'N:WAO7s#r!W46>:fWjW͇S+s#r! >w#6:fWjWR+s#r*W&$SQ  >1A*W&$SQ  ~¤?*(V"LW*W&$SQ  n&)*&VWR"(V ^#V"NW*LW"(V *NWs#r1A*\W*ZWs#r*(V *XWs#r*XW##"XW*\W##"\W!W6*W&$SQ  ~!W A*W&$SQ  ~PRTMSG ,QPAGWID 2QPAGLEN 1QBACKSPC 3QRUBOUT 4QBOOTDRV 0QMEMTOP .QBNKSWT -QCOMBAS /QLERROR  +QNUMSEGS  5QMEMSEG00 KQHASHDRVA6QALTBNKSA +QNDIRRECA ;QNDTARECA KQODIRDRVA [QODTADRVA kQOVLYDIRA L>:WWͧ T. T~ !W6!W6>!WN!W6#n& +S P  ~2W!W6:W:W/H N!W6>!WڞL'N *W&+S P *W& *W&W w!W4gL:W°L!W6L:WL:WA*W&W wL:W L:W0*W&W wL:WA *W&W w'N*W&W/:W/HI!W6>!W/H*W&W 6 !W4HtG2W!W6:W:W=H:W H:W/H~H*W&W :WwtG2W!W4:H:W=:W H:W/HҧHtG2W~H:W I:W=>!WHH!W6 I:W=HHF GH:WHcF G:W :W/H 2W!FQ  ~:W!WH0D:W2W:W2W!W4C*W&+SFQ  S+s#rcD!fW:iW2iW*W͛ 2W…D4%ͧ>äD*W&+SFQ  WzS+s#r!W4±CF*W&$SQ  ~2W!W6:W!WF!fW:iWoE!iW6*gW#"gW!W6!W6!W6:5Q!WME@*W&$SQ ^#V͛ 2W*jW6*W&+SFQ N`iPS!N`iPS!͕S  *jW q#p*W&+SFQ   *jW w*W&+SFQ  *W&$SQ |S+s#r@*jW6 *jW *VWs#r*W&$SQ VWR+s#r *jW 6:fWZWR+s#r *jW s#r:fWjWR{QOVLYDTAA QCRDATAF ;RDBLALV !W҇K *W&+S P  ^#V"W! P  ~2WJ:WI:WA2WI:W0/>9!W/HI:W02WI:WA 2W *W&*W&+SFQ  2W!FQ  ~:W!WHFE:W2W:W2W!W4D*W&+SFQ  S+s#ryE!fW:iW2iW*W&$SQ  ~ڼEWbWzS+s#rYS:/QpSҹEd%ͧ>E*W͛ 2WE%ͧ>E*W&+SFQ  WzS+s#r!W+s#r!W4?:fWjW͇S+s#r! >w#6:fWjWR+s#r!W4>JWR>fS:WHhA!JWVS+s#r!W45A!JWVS+s#ru=!W4n&))lW  ^#V"JW=!W6>!WA*W&7W *W&+SFQ  w!W4˜A!W6>!WaB*W&)*&VWR"(V*W&NV) >͒S"Bi`N#Fog_og_og 6 !W4PL!W4'L>!W NT^ T :W]NT^ !W6>!WUN*W&W 6!W4:N!W6aN!W4!Wq'N:WO! *W&W w'N:WO! *W&W wO*TDM}oN*T†O]!O> 2 PW:TgxʀO { O: PO*T!+S P  ^*W&+S*W"W*W&T ~?[J *W&+S P  :WO!=R 6!U6!W4!T5>!T҇K:WʧJ*W&T ~A/>P/HҜJ*W&T ~A*WwäJF GÇK:WJ*W&T ~Y*WwÇK!W6*W6!W6:T=!WڇK:W!WO!T ~2W, K*W#"W64D>!Wq*W6 dWR>fS'F>%ͧ>ERROR: $ at line $Missing parameter variable$Equals (=) delimiter missing$Invalid drive ignored$Invalid character$Invalid parameter variable$!"WWͧ !W6!W6:W GG:WG͈K2W:WFIG*(V *ZWs#r*W&NV) ZWR+s#r*W&pV) >͒SZB*(V *ZWs#r*W&pV) ZWR+s#r!W4A!"W"W!W6:5Q!WB*W&+SFQ  ~¶B*W&+SFQ  VS*W"WB*W&+SFQ  VS*W"W!W4pB$N%N!bWVSDM$ :-QMC%DM!>))덑o|gS =S^#V))) DM!>)):S =2S_og^#V) PS^#V|g}o ZS_{ozgO{ozgi`N#Fogo&og_{_z#WO†O~#o}o|O<O:TzO<.O:TƜzO<8O:TzO:TzO:TotOzO:TgN!|!|!W6ÀK:W#K!W6 ÀK:W02W:W> !WHQK>!WLK:W2WQK!W6!W:WxK*W^*W&+S*W& sÀKF G!W4J!W6!W6:W:W/HK!W6:W *W&+S P *W& *W&W HK!W4éK:WK!W6K!W4ÒK:WF GF!Wr+s+q:U2W!U65FN*WDMN>FN*WDMZ :WCG.͜:W2U:WoG!W6TlG!W6sG!W4MG*W&W ~2W:W :W H:W HG:W ·G*W#"WMG*W&W ~2WÄG:Wa/>z!W/HG:W_2W:WG!W6:W!W6:N*WDM$ :U C$%N*WDM$ >W͇S>W͇SHHC!W6MC!W6͜͜!Ws+q*W&$SQ ^#V"W:-QڋC:fWWRbW͊S+s#rF!iW55:W®D*W&$SQ  ~2W!W6:W!WګD!fW:iWYD!iW6*gW#"gW!W6!W6!W6:5Q!W7D*W&+SFQ  ACP/M PLUS652A ;I A=logical file # ; X=device # (0-31) ; Y=seconday command (FF if nane) K$setnam equ 0FFBDh ; set up file name for OPEN ;I A=name length ; X=low byte pointer to name ; Y=high byte pointer to name K$open equ 0FFC0h THE COMMAND LOOP **** ; boot$02$code: @lda 0,# ; turn on the kernal @sta force$map ; @jmp (0fffch) ; jmp to its start boot$size equ $-boot$02$code BB equ bios$02-$ ; BIOS BIAS ; bios$65$code: @lda 0,# ;-K @sta vic$data ;-K @JSR V*** ; READ: @lda @dma ;-K @sta pointer ;-K @lda @dma+1 ;-K @sta pointer+1 ;-K setdrv: @lda vic$trk ;-K @sta F$rd$trk+BB ;-K @JSR BINASC+BB ;-K @STX dskcmd$T$h+BB ;-K @STA dskcmd$T$l+BB ;-K @lda vic$sect ;-K @sta F$rd$sect+BBNKBIOS3SPRRESBDOS3SPRBNKBDOS3SPRCPM3 SYSGENCPM DAT . $; open a logical file (after SETLFS & SETNAM) ;O A = error # (1,2,4,5,6,240) K$chkout equ 0FFC9h ; open a channel for output ;I X = logical file # ;O A = error #(0,3,5,7) K$clrchn equ 0FFCCh ; clears ALL I/O channel K$chkin equ 0FICIO+BB ;-K go find and do requested operation CMDLP: @sei @lda 3eh,# ;?K set up Z80 memory map as required @sta force$map ;-K @jmp enable$z80 ;-K PAGE ; ; ; ; ; **** IO COMMAND DISPATCH ROUTINE **** ; VICIO: @CLD ;-K clear to bB ;-K @JSR BINASC+BB ;-K @STX dskcmd$S$h+BB ;-K @STA dskcmd$S$l+BB ;-K @lda fast ;-K @bne read$F ;-K @sta force$map ;-K A=0 if we did not branch @ldx datchn,# ;+K @jsr K$chkin ;+K @bcs disk$changed ;+K @jsr K$clrchn ;+K clear the page ; ************************************************* ; - - ; - BIOS8502 code (for read only) - ; - - ; ************************************************* ; ; 10 May 85 ; ; COMMON EQUATES ; pointer equ 20h datchn equ 11 FC6h ; open a channel for input ;I X = logical file # ;O A = errors #(0,3,5,6) K$chrin equ 0FFCFh ; get a character from input channel ;O A=input character K$chrout equ 0FFD2h ; output a character to output channel ;I A =output inary mode @LDA vic$cmd ;-K get the command @bne read ;-K 0=initialize ; 1=read page ; ; ; initilize: ; initialize the 8502 @ldx 0,# ;-K @stx force$map ;-K enable the kernal @stx VIC+26 ;+K turn off VIC interrupts input channel for now @JSR SETUP+BB ;+K @JSR CKINDT+BB ;+K @ldy 0,# ;+K READ1: @JSR K$chrin ;+K get a byte from the KERNAL @STA (pointer),y ;-K save it to the DMA pointer @iny ;+K advance the buffer pointer @BNE READ1 ;+K loop b; use data channel #11 cmdchn equ 15 ; use comand channel #15 ; ; KERNAL EQUATES ; serial equ 00A1Ch D2PRA equ 0DD00h D1SDR equ 0DC0Ch D1ICR equ 0DC0Dh clk$bit equ 10h K$set$bnk equ 0FF68h K$setlfs equ 0FFBAh ; setup a logical file char K$clall equ 0FFE7h ; close all open files K$close equ 0FFC3h ; close a logical file ;I A = logical channel # to be closed ;O A = error #(0,240) K$readst equ 0FFB7h ; read status byte ;O A = status PAGE ; ; ; **** THIS IS@ldx low(irqs+BB),# @ldy high(irqs+BB),# @stx 314h ;+K IRQ vector @sty 315h @stx 316h ;+K BRK vector @sty 317h @stx 318h ;+K NMI vector @sty 319h @jmp opencm+BB ;+K go open channel to disk drive PAGE ; ; **** DISK SECTOR READ *ack if not past buf end @jmp K$clrchn ;+K CLEAR CHANNEL DISK$CHANGED: @lda 0FFh,# ;?K @skip2 fst$error: @lda 0dh,# @sta vic$data ;?K @jmp CMDLP+BB ; ; ; read$F: @lda 0,# ;-K @sta force$map ;-K @ldx cmdchn,# ;+K @jsr K$c opencm: @LDA cmdchn,# ;+K @CLC ;+K @JSR K$close ;+K @LDA cmdchn,# ;+K @sta fast ;+K set fast flag @LDX 8,# ;+K @TAY ;+K @JSR K$setlfs ;+K @LDA 0,# ;+K @sta serial ;+K clear fast serial indicator @TAX ;+K @JSR K$set$ ; SETUP: @JSR CKOTCM+BB ;+K @LDY dskcmd$lng,# ;+K SETUP2: @LDA DSKCMD+BB-1,y ;+K @JSR K$chrout ;+K @DEY ;+K @BNE SETUP2 ;+K @JSR K$clrchn ;+K @JSR CKINCM+BB ;+K @BEQ SETUP3 ;+K SETUP5: @LDA 0dh,# ;+K get error flag @STAES **** ; CKICM: @JSR OPENCM+BB ;+K CKINCM: @LDX cmdchn,# ;+K @JSR K$chkin ;+K @BCS CKICM ;+K @JSR K$chrin ;+K @CMP '0',# ;+K @RTS ;+K ; ; ; CKIDT: @JSR OPENDT+BB ;+K CKINDT: @LDX datchn,# ;+K @JSR K$chkin ;+K @BCS CK _{ozg^#V) "^#V|g}o "_{ozgO{ozgi`N#Fogo&oghkout ;+K @bcs fst$error ;+K ; @ldx 0,# ;+K @ldy Fcmd$lng,# ;+K sendf: @lda Fcmd$buf+BB-1,y ;+K @jsr K$chrout ;+K ; @inx @dey @bne sendf @jsr K$clrchn ;+K @bit D1ICR ;+K @ldx F$rd$count+BB ;+K rd$sector: @jsr read$byte+BB ;+K bnk ;+K @LDA 4,# ;+K @LDX low(U0POINT+BB),# ;+K @LDY high(U0POINT+BB),# ;+K @JSR K$setnam ;+K @JSR K$open ;+K @bcs misdsk @jsr K$readst @ROL A ;+K GET MSB TO CARRY @BCS MISDSK ;+K DEVICE MISSING IF CARRY SET @bit serial ;+ vic$data ;+K writes to RAM under ROM setup3: @JMP K$clrchn ;+K page ; ; ; read$byte: @sei @lda d2pra @eor clk$bit,# @sta d2pra @lda 8,# in$1: @bit d1icr @beq in$1 @lda d1sdr @rts page ; ; handle all interrupts in IDT ;+K @RTS ;+K ; ; ; CKOCM: @jsr OPENCM+BB ;+K CKOTCM: @LDX cmdchn,# ;+K @JSR K$chkout ;+K @BCS CKOCM ;+K @RTS ;+K PAGE dskcmd: db CR ; dskcmd$S$l: db 's' ; dskcmd$S$h: db 's ' ; dskcmd$T$l: db 't' ; dskcmd$T$ ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0L@and 0eh,# ;+K mask off error bits @bne fst$error @ldy 0,# rd$buffer: @jsr read$byte+BB ;+K @sta (pointer),y ;+K @iny ;+K @bne rd$buffer ;+K @inc pointer+1 ;+K @dex ;+K @bne rd$sector ;+K clk$hi: @lda d2pra ;+K @and 0ffK test for fast device @bvs no$dt$open ;+K do not open data channel if fast page ; ; **** OPEN DISK DATA CHANNEL **** ; OPENDT: @LDA datchn,# ;+K @CLC ;+K @JSR K$close ;+K @LDA datchn,# ;+K @LDX 8,# ;+K @LDY 8,# ;+K @JSR K$seBIOS 8502 (throw them away) ; irqs: @lda CIA$1+int$ctrl @lda CIA$2+int$ctrl @lda 0fh,# @sta VIC+25 ; ; system saved memory config, Y, X and A before getting here ; @pla @sta force$map @pla @tay @pla @tax @pla @rti ; ; Ph: db 't 0 8:1' U0POINT: db 'U' ; dskcmd$lng equ $-DSKCMD db '0',4Ch,0 ; reset disk change status (open) POUND: db '#' F$cmd$buf: F$rd$count: db 1 ; 5 1st read always one sector F$rd$sect: db 0 ; 4 filled in F$rd$trk: db 0 ; 3 filled ine USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Thh-clk$bit,# ;+K @sta d2pra ;+K @rts ;+K ; ; * DEVICE MISSING, CLEAN UP ERROR * ; MISDSK: @LDA 00fh,# ;+K SET ERROR CODE @STA vic$data ;+K writes to RAM under ROM @JMP CMDLP+BB ;+K PAGE ; ; **** OPEN DISK COMMAND CHANNEL **** ;tlfs ;+K @LDA 0,# ;+K @sta fast ;+K clear fast flag @TAX ;+K @JSR K$set$bnk ;+K @LDA 1,# ;+K @LDX low(POUND+BB),# ;+K @LDY high(POUND+BB),# ;+K @JSR K$setnam ;+K @JSR K$open ;+K @bcs misdsk no$dt$open: @rts PAGE ;AGE ; ; **** CONVERT BINARY TO ASCII **** ; BINASC: @CLD ;-K @LDX '0',# ;-K @SEC ;-K BA0: @SBC 10,# ;-K @BCC BA1 ;-K @INX ;-K @BCS BA0 ;-K BA1: @ADC 3Ah,# ;-K @RTS ;-K PAGE ; ; **** SELF CORRECTING CHECK IO ROUTIN F$cmd: db 0 ; 2 read=0 db '0U' ; 1 Fcmd$lng equ $-F$cmd$buf bios$size equ $-bios$65$code ڜ!*$&!*$& !$sr!*$&$ :$w:$!>!$ҿ!ͥ -*|$ :$w 2p#_og_{ozg_og^#V))) title 'CP/M 3 ROM loader 13 May 85' maclib z80 maclib cpm3 maclib cxequ maclib x6502 boot$8502 equ 1100h lines equ 24 ; number of user lines on screen(s) rownum macro row,col db row+80h,col endm ; ; p,4,8,C,....,44) ; RST 4 ; ; org 20h ; RST 4 lda fun$offset ; =0 if 80 column, <>0 if 40 column ana a ; is this an 80 column function? jrz 28h ; yes, no offset required inr l ; no, advance to next vector inr l ; ; * RCALL * us lxi b,mode$reg ; get EXROM and GAME bits mvi a,z80$on outp a ; set bit high inp a ; see if they went high cma ; make highs low ani 30h ; EXROM or GAME enabled? jrz test$key ; no, now test the commodore key ; ; This is a one wa$start+11-1 ; and work forward mvi d,11 ; for all 11 bytes init$mmu$next: mov a,m ; get table value outp a ; send to MMU dcx h dcr c dcr d jrnz init$mmu$next ; ; install 8502 code that will enable C128 mode and ; execute at t/sector check$next: shld @dma lxi d,sys$name ; point to system name push psw call name$match cz found pop psw lhld @dma ; get current buffer pointer lxi d,32 dad d dcr a jrnz check$next ret page ; ; compare the strings (ower on location ; org 00h ; RST 0 mvi a,3eh sta force$map jmp power$up ; continue init somewhere else ; ; boot CP/M entry point ; ; org 08h ; RST 1 lxi sp,boot$stack mvi a,3Fh ; MMU enable RAM bank 0 no I/O jmp loader$started to call a ROM routine ; user code: ; mvi l,fun# (0,2,4,6,.....,7E) ; RST 5 ; ; org 28h ; RST 5 mvi h,01h ; vectors on page 1 mov a,m inx h mov h,m mov l,a pchl nop page ; ; RST 6 is NOT defined.. this area is used for y trip, no return flights. ; Thus we do not have to do the transfer from RAM ; (as in C128 mode). We just enable C64 and run. ; go$c64: mvi a,enable$c64 outp a ; should never get here RST 0 ; unless there are hardware problems page he location pointed to by FFFC (reset vector) ; lxi h,boot$02$code lxi d,boot$8502 lxi b,boot$size ldir lxi h,swap$code lxi d,enable$z80 lxi b,swap$size ldir ; ; Get ready to enter C128 mode. Install vectors in ram that will ; forc11 bytes each) pointed to by ; DE and HL. Return with Zero flag set if equal. ; name$match: mvi b,12 ; number of bytes to match xchg ; [HL]=search name [DE]=dir entry match$next: ldax d ; get string 1 character ani 7fh ; remove a page ; ; * TJMP * user to jmp to a Terminal ROM routine ; user code: ; RST 2 ; db fun# (0,4,8,C,....,44) ; ; org 10h ; RST 2 pop h mov l,m jmp 020h nop nop nop ; ; * RJMP * user to jmp to a ROM routine ; user code: ; the ROM date ; ONLY.... ; ; org 30h ; RST 6 db '05/12/85' ; org 38h ; RST 7 (interrupt mode 1 start adr) jmp 0fdfdh page ; ; ; power$up: lxi b,VIC$key$row lxi d,0fffch ; D=ff, E=fc outp d ; set extra 3 scan lines off inx test$key: lxi b,0dc0fh ; D1CRB mvi a,8h ; turn off timers outp a dcr c ; D1CRA outp a mvi c,03h ; D1DDRB = inputs xra a ; A=00 outp a dcr c ; D1DDRA = outputs dcr a ; A=FF outp a dcr c ; dc01 dcr c ; dc00 me the processor to execute RAM code in low memory. ; The RAM code in low memory ENABLES the kernal and does ; an indirect JMP to FFFC (reset vector). ; lxi h,boot$8502 ; C128 start adr shld 0fffah ; install NMI vector shld 0fffch ; install REny attr. cmp m ; compare to string 2 rnz ; exit if they don't match inx h inx d djnz match$next lda block$size ; cpi 64 ; 2K block? ldax d ; get the dir ext# jrnz ext$1k ; no, ext # ok ; yes, (carry=0) rar ; div RST 3 ; db fun# ; ; org 18h ; RST 3 pop h ; get the return address mov l,m ; get user function # (0,2,...,fe) jmp 028h ; nop nop nop page ; ; * TCALL * used to call a Terminal ROM routine ; user code: ; mvi l,fun# (0b ; point to clock speed reg outp e ; bits 7-2 unused ; bit 1 enable test mode (1) ; bit 0 2 Mhz (1) / 1 MHz (0) ; ; continue the check to see if a C64 type chartrage is installed ; (EXROM or GAME active) if so we enter C64 mode ;vi a,01111111b ; bit 7 for commodore key outp a inx b ; dc01 point to key$col inp a ani commodore$key lxi b,mode$reg jrz go$c64 go$c128: ; ; set MMU registers to a known state ; lxi h,mmu$init$data+11-1 ; start at the End lxi b,mmuSET vector shld 0fffeh shld return$z80+1 jmp enable$6502 page ; ; scan buffer for CPM+.SYS file ; scan$dir: call update$buffer ; returns HL=block$buffer lda block$size ; 32 for 1K block, 64 for 2K block ; ..number director entrieside by 2, ext could be 0 or 1 ; ..for the 1st and 2 or 3 for the ext$1k: ; ..second entry sta ext$num null$code: xra a ; return with zero flag set ret page ; ; ; sys$name: ; 12345678901 db 0,'CPM+ SYS' ; must be in us; function # 26 dw char$del$80 ; function # 28 dw char$del$40 ; function # 2A dw line$ins$80 ; function # 2C dw line$ins$40 ; function # 2E dw line$del$80 ; function # 30 dw line$del$40 ; function # 32 dw set$color$80 ; function # 34dw line$paint ; function # 64 dw screen$paint ; function # 66 dw prt$msg$both ; function # 68 dw prt$de$both ; function # 6A dw update$it ; function # 6C dw null$code ; function # 6E dw ASCII$to$petASCII ; function # 70 dw cur$adr$40$system area. ; lxi h,3000h lxi d,3001h lxi b,0ff00h-3000h-1 mov m,l ldir ; ; move bios and swap code into ram ; lxi h,bios$65$code lxi d,bios$02 lxi b,bios$size ldir lxi h,swap$code lxi d,enable$z80 lxi b,swap$size ldir set ; mvi a,26 call wait mvi a,90h ; foreground red background black outp a mvi a,83h ; set attr and color (lt. blue) sta current$atr ; ..for 80 column display mvi a,0eh ; set color (lt. blue) sta attr$40 ; ..for 40 column displayer 0's space db 0 ; ; ; ; org 0100h-6 cmp$hl$de: mov a,h cmp d rnz mov a,l cmp e ret page ; org 0100h dw wr$char$80 ; function # 00 dw wr$char$40 ; function # 02 dw crs$pos$80 ; function # 04 dw crs$pos$40 ; functi dw set$color$40 ; function # 36 dw set$attr$80 ; function # 38 dw set$attr$40 ; function # 3A dw rd$chr$80 ; function # 3C dw rd$chr$40 ; function # 3E page dw wr$chr$80 ; function # 40 dw wr$chr$40 ; function # 42 dw rd$colorhl$sz$a ; function # 72 dw cur$adr$80$hl$sz$a ; function # 74 dw lookup$color ; function # 76 dw null$code ; function # 78 dw blk$fill ; function # 7A ret adr, HL on stack dw blk$move ; function # 7C ret adr, HL on stack dw char$install mvi a,RET ; get z80 return adr sta return$6502 ; store the RET ; ; initilize the 8502 bios ; ; xra a ; cleared by memory fill ; sta vic$cmd call enable$6502 page ; ; set MMU registers to a known state (for CP/M to use) ; lxi h, call install$ASCII ; convert char set to true ASCII mvi a,25 ; number of lines on the 40 col display sta paint$size ; ; Let the user know we are booting CP/M ; call prt$msg$both db -1 ; clear both screens rownum 1,10 db 'BOOTING CPon # 06 dw crs$up$80 ; function # 08 dw crs$up$40 ; function # 0A dw crs$down$80 ; function # 0C dw crs$down$40 ; function # 0E dw crs$left$80 ; function # 10 dw crs$left$40 ; function # 12 dw crs$rt$80 ; function # 14 dw crs$rt$40$80 ; function # 44 dw rd$color$40 ; function # 46 dw null$code ; function # 48 dw null$code ; function # 4A dw null$code ; function # 4C dw null$code ; function # 4E dw convert$record ; function # 50 dw check$cbm ; function # 52 $gp ; function # 7E ret adr, HL on stack ; the last 3 function are called by 1st pushing HL on the stack ; and then doing the call ; user code as follows: ; lxi h,xyz ; value to be passed in HL ; push h ; extra value on stack ; RCALL ..mmu$init$data+11-1 ; start at the End lxi b,mmu$start+11-1 ; and work forward mvi d,11 ; for all 11 bytes init$mmu$cpm: mov a,m ; get table value outp a ; send to MMU dcx h dcr c dcr d jrnz init$mmu$cpm ; re-enabled RAM bank /M PLUS',0 ; ; point 40 column screen to CP/M screen area ; lxi b,VIC+24 mvi a,vic$screen*4/256+6 ; upper and lower case set (+6) outp a page call check$dsk ; is this a C128 disk ? jnz tell$user ; no, tell the user ; ; ; lxi h,d ; function # 16 dw crs$cr$80 ; function # 18 dw crs$cr$40 ; function # 1A dw CEL$80 ; function # 1C dw CEL$40 ; function # 1E dw CES$80 ; function # 20 dw CES$40 ; function # 22 dw char$ins$80 ; function # 24 dw char$ins$40 dw bell ; function # 54 dw null$code ; function # 56 dw null$code ; function # 58 dw null$code ; function # 5A dw null$code ; function # 5C dw null$code ; function # 5E dw trk$40 ; function # 60 dw set$cursor$40 ; function # 62 .. ; ; stack clean page ; ; org 180h ; jmp write$memory jmp read$memory jmp set$update$adr jmp wait ; ; ; loader$start: ; ; setup the MMU for booting CP/M ; sta force$map ; ; clear bank 0 RAM 3000h to feffh. This is the 0 (no I/O) ; ; Clear the work area ; lxi h,1000h lxi d,1000h+1 lxi b,3000h-1000h-1 ; number of bytes to clear mov m,l ; clear the 1st one ldir ; copy 1st to all page ; ; set 80 column colors and set up Video memory with ASCII char ir$ptrs shld ld$blk$ptr call scan$dir ; check 1st block call scan$dir ; check 2nd block (1K or 2K) lhld block$ptrs ; 1st pointer <>0 if file mov a,h ; name exist ora l ; pointer = 0 jz tell$user ; yes, inform user there is a error ******* ; * * ; * load keyboard data to system RAM * ; * * ; ************************************************* call prt$msg$both rownum 3,12 ; db 'LOADING DATA TABLES',0 db 'DATA TABLES',0 lhld info$buffer+10 shld key$tbl ; inscall load$reverse page ; ************************************************* ; * * ; * now load the bios8502 code * ; * * ; ************************************************* call prt$msg$both rownum 6,12 ; db 'LOADING BIOS8502 CODE with zero flag set if bootable disk in drive ; check$dsk: lxi h,@buffer shld @dma xra a sta vic$sect ; set track 1 sector 0 (1st sector inr a ; on the disk) sta vic$trk call read$sector ; a=0 if no errors call check$cbm ; disk have ck pointers lda ext$num ora a jrz ext$num$0 lxi d,block$ptrs+16 dcr a jnz ext$error ext$num$0: lhld @dma ; get current pointer lxi b,16 ; number of bytes to move dad b ; also advance to block pointers ldir lda block$ptr ; no, file found, process it page ; ************************************************* ; * * ; * load 1st group to 1K buffer * ; * * ; ************************************************* ; ; ; file$found: lxi h,block$ptrs shldtall keyboard translation pointer lxi h,info$buffer+9 call get$size$adr ; HL=adr DE=# (128 btye) records shld fun$tbl load$next$forward: call load$record ; HL =load address (in and out) lxi d,128 ; move pointer back to buf start dad d',0 db 'BIOS8502 CODE',0 lxi h,info$buffer+7 ; load banked code call load$reverse lda info$buffer+7 ; get code size (in 256 byte blocks) mov b,a lda info$buffer+6 ; get page pointer (pointer to end) sub b ; find the start ; insCBM in first sector ? rnz ; no, exit inr a ; yes, is it double sided? lxi h,block$buffer+1024 ; buffer end address (1K blocks) mvi a,32 ; number of dir entries per block jrnz set$block$size ; yes, set it ; no, set 2K block pars ora a ; 1st block present ? rz ; no, read more dir. lhld block$ptrs+15 ; extent full? xra a ; get a zero cmp l ; cmp to block$prt+15 jrz go$boot$it ; no, this is it then cmp h ; cmp to block$prt+16 ; 2nd block present ld$blk$ptr call update$buffer ; ************************************************* ; * * ; * extract boot info * ; * * ; ************************************************* ; ; ; get$boot$info: lxi h,block$buffer lxi d,info$b jrnz load$next$forward page ; ************************************************* ; * * ; * transfer CP/M code to load address * ; * * ; ************************************************* ; ; ; load$common: call prt$msg$both rotall jmp adr to BIOS02 sta return$z80+2 ; (jmp) (low) (high) xra a sta return$z80+1 ; (jmp) (low) (high) ; ************************************************* ; * * ; * now let's start executing CP/M Plus * ; * * ; ****************ameters mvi h,high(block$buffer+2048) add a ; 64 dir entries set$block$size shld block$end sta block$size ; 32=1K, 64=2K (# dir entries/block) xra a ; set zero flag (is CP/M disk) ret page ; *************************************** ? rz ; no, read more dir. go$boot$it: jmp file$found ; two parms are still on the stack ; but at this point who cares page ; ; ; load$reverse: call get$size$adr ; HL=adr DE=# records (128 byte) load$next: lxi d,-128 ; mouffer lxi b,12 ldir call prt$msg$both rownum 10,0 db 0 ; end of string marker lxi h,block$buffer+80h call prt$hl$both lxi h,block$buffer+256 ; set scan pointer shld blk$unld$ptr page ; ******************************************wnum 4,12 ; db 'LOADING COMMON CODE',0 db 'COMMON CODE',0 lxi h,info$buffer+1 ; load common code call load$reverse call prt$msg$both rownum 5,12 ; db 'LOADING BANKED CODE',0 db 'BANKED CODE',0 lxi h,info$buffer+3 ; load banked code ********************************* lhld info$buffer+4 ; get start address pchl ; transfer control to CP/M page ; ********************************* ; - - ; - SUBROUTINES - ; - - ; ********************************* ; ; returns********** ; - - ; - save CPM+.SYS group numbers - ; - - ; ************************************************* ; ; found a dir entry that has the right name ; add block pointers to list ; found: lxi d,block$ptrs ; point to start of blove pointer back to buf start dad d call load$record jrnz load$next ret ; ; ; get$size$adr: mov e,m mvi d,0 ; get buffer size (#256 byte) mov a,e ; get size to A ora a jz table$error ; exit if count=0 xchg dad h ; HL=#12get block number to HL ; ; read the block pointed to by the HL ; into the data buffer ; dad h ; 2x dad h ; 4x 256=1K lda block$size ; =32 for 1K, =64 for 2K rrc rrc rrc ; 32/8=4, 64/8=8 cpi 32/8 ; 1K block size? jrz is$1K$blo lxi h,vic$count dcr m jrnz check$next$trk pop h not$same$trk: shld vic$trk ; save the 1st track sector # rd$1541: call read$sector ; read the sector to the buffer lxi h,@dma+1 ; point to dma high byte lda F$rd$count+BB add m mov arry bit dsbc d ; jrc too$much ; inx h ; add 1 to skip track 18 sector 0 lxi d,490-357 ; get first value to subtract lxi b,19*256+18-1 ; b=sectors/track c=track offset-1 dsbc d ; jrc too$much ; lxi d,598-490 ; get first value35), DE and B still has the ; # sectors/track for the current track. ; lda temp$1 ; get track offset add c ; add to current track sta vic$trk ; save it push h lxi h,special$skew lxi b,21 ; number of sectors in 1st region mov a,e c8 byte blocks shld load$count xchg dcx h mov h,m mvi l,0 ret page ; ; ; load$record: push h ; save to address lhld block$end ; get buffer end adr xchg lhld blk$unld$ptr call cmp$hl$de cz update$buffer xchg lxi h,128 ck dad h ; 8x 256=2K is$1K$block: shld @trk next$block: dcr a ; 3 or 7 sectors left to read sta vic$count ; ..1st sector is read anyway push psw mvi a,1 sta F$rd$count+BB ; call convert$record ; set track, sector (adjust for offm,a ; adjust for next read lda vic$count ana a ; test if all sectors read? jrnz next$block ; no loop back pop h ; recover block buffer adr ret page ; ; convert block number to sector and track ; convert$record: mvi a,35 sta t to subtract lxi b,18*256+25-1 ; b=sectors/track c=track offset-1 dsbc d ; jrc too$much ; lxi d,0 lxi b,17*256+31-1 ; b=sectors/track c=track offset-1 page ; ; at this point B= number of sectors/track and C=track offset ; after DE imp c jrz correct$region dad b ; move past current region dcx b dcx b ; 19 adjust$loop: cmp c jrz correct$region dad b dcx b jr adjust$loop ; ; ; correct$region: pop b ; get logical sector # in BC dad b mov a,m ; get tra dad d shld blk$unld$ptr pop h ; recover save address push h xchg ; HL=source DE=dest. lxi b,128 ; size of move ldir lhld load$count dcx h shld load$count mov a,l ora h pop h ret page ; ; ; update$buffer: lxi h,set) lhld @trk inx h shld @trk ; save for later pop psw jrz rd$1541 lda fast ana a ; 0=1541, 0<>1571 jrz rd$1541 lhld vic$trk ; get track and sector # push h ; save on stack check$next$trk: call convert$record ; convertemp$1 ; store a track offset of 35 lhld @trk ; get start block # lxi d,680 ; 0 to 680 sectors per side ora a ; clear the carry dsbc d ; negative if <680 jrnc side$1 ; jump if still positive >=680 xra a ; sta temp$1 ; store a ts added back to HL (1st inst), HL is the number of ; sector past the current track (in C). ; too$much: dad d ; add back what made sum go negitive mvi d,0 ; number of sectors/track in DE mov e,b ora a ; clear the carry bit sect$pos: inr nslated sector number to A sta vic$sect ; value from 0 to 20 will be returned inr a ; A is required to be non-zero on ret ret page ; ; ; read$sector: mvi a,3 sta retry read$again: mvi a,vicrd ; read a sector of data sta vic$cmblock$buffer shld @dma push h ; save block buffer adr for ret lhld ld$blk$ptr ; get the current block pointer mvi d,0 ; zero MSB of block pointer mov e,m ; get LSB of block pointer inx h ; advance pointer shld ld$blk$ptr xchg ; next track and sector pop h ; recover 1st trk and sector # lda vic$trk ; get trk$number cmp l ; same trk as 1st sector jrnz not$same$trk push h ; resave 1st trk and sect lhld @trk inx h shld @trk lxi h,F$rd$count+BB inr m rack offset of 0 dad d ; add it back side$1: inx h ; skip 1st sector (both sides) inx h ; skip 2nd sector (both sides) lxi d,357 ; get first value to subtract lxi b,21*256+1-1 ; b=sectors/track c=track offset-1 ora a ; clear the cc ; add one to the current track (1-35) dsbc d ; remove a track's worth of sectors jrnc sect$pos ; less then one?, no jmp dad d ; make HL positive again ; ; at this point HL has the remainder (sector # 0-20) and ; C has the track number (1-d call disp$dsk$info call enable$6502 mvi a,3fh ; mmu ram bank 0 (no I/O) sta force$map lda vic$data ora a ; problems? jrnz read$error ; yes, check for disk error or media change ; no, go move buffer to DMA address ret page ; ;row mvi a,11111110b ; bit 0 for RETURN key outp a inr c ; point to key$col inp a ani 2 ; on bit 1 (0-7) jrz try$again inp a ani 1 ; delete key down jrnz wait$key ; no, wait for RETURN key rst 0 ; yes, reboot C128-mode h h cpi LF rz page ; ; ; check$both$CR: cpi CR jrnz check$erase$both ; ; do$crlf$both: call crs$cr$40 call crs$cr$80 call crs$down$40 RJMP FR$cursor$down ; cursor down 80 ; ; ; check$erase$both: cpi -1 jrnz check$both disp$dec: mvi b,'0'-1 conv$loop: inr b sui 10 jrnc conv$loop adi '0'+10 push psw mov a,b call disp$A pop psw disp$A: mov d,a ; ; ; out$d$both: push d call wr$char$40 pop d RJMP FR$wr$char  ; check$cbm: lxi h,@buffer mov a,m cpi 'C' ; C ? rnz ; no, return inr l ; @buffer+1 mov a,m cpi 'B' ; B ? rnz ; no, return inr l ; @buffer+0 mov a,m cpi 'M' ; M ? rnz mvi l,0ffh ; @buffer+0ffh ; po page ; ; CPM+.SYS file not on this disk test user to install ; a system disk and wait for a CR to continue ; tell$user: call prt$msg$both rownum 19,5 db 'NO',0 error$1: call prt$msg$both db ' CPM+.SYS FILE',0 jr error$2 ; ; ; tabl$CUR$$POS ; ; Erase both screens ; lxi d,24*256 ; erase the status line 1st call curpos$BC$both call CEL$40 call CEL$80 lxi d,0 ; erase main screen call curpos$BC$both call CES$40 RJMP FR$CES check$both$CUR$POS: ani 80h jrz oݭ $L ( *  1 .( ) L L0) ( ))* )$ )x? 2L.( 7&x> L.&]&&&'''N'''4& (#( *ll  iG&l&xIݩ, `) *int to the double sided flag mov a,m ; read it, 0FFh if double sided ret page ; ; ; ext$error: call prt$msg$both rownum 19,5 db '32K MAX CPM+.SYS SIZE',0 try$again: rst 1 ; ; ; read$error: inr a ; test for -1 jrz try$agae$error: call prt$msg$both rownum 19,5 db 'BAD',0 jr error$1 page ; ; ; prt$msg$both: xthl call prt$hl$both xthl ret update$it: lxi h,-1 shld old$offset ; force an update ; ; ; prt$de$both: push d ; ; ; prt$hl$bout$d$both ; curpos$D$both: pop b ; get return adr in BC pop h ; get pointer in HL mov e,m ; E=column # inx h push h ; save new pointer push b ; save return adr res 7,d ; D=row # curpos$BC$both: push d ; save cursor addres$ Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0Lin lda retry dcr a sta retry jrnz read$again call prt$msg$both rownum 19,5 db 'READ ERROR',0 error$2: call prt$msg$both db ' - HIT RETURN TO RETRY' rownum 20,15 db 'DEL TO ENTER C128 MODE',0 ; ; ; wait$key: lxi b,key$th$loop: pop h ; ; ; prt$hl$both: mov d,m inx h ; advance the pointer lda prt$flg ana a jrz no$flag xra d sta prt$flg mov d,a no$flag: mov a,d ora a rz cpi '$' rz ; yes, return push h lxi h,prt$hl$both$loop puss call crs$pos$40 pop d RJMP FR$cursor$pos ; 80 column page ; ; ; disp$dsk$info: lxi d,24*256+80-6 call crs$pos$80 lxi d,24*256+40-6 call crs$pos$40 lda vic$trk call disp$dec mvi d,' ' call out$d$both lda vic$sect e USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Th ; get color to A sui 20h ; remove the BIAS cpi 20h ; physical color ? (00h-1Fh) jrc ?col$80 ; yes, go set it mvi c,20h ; max color value+1 (00h-1Fh) call lookup$color$1 ; convert char in A to color (ret in A) ; C=max color charac ; returns with cursor set and current ROW, COLUMN in BC ; and character screen address in HL ; compute$adr: lhld char$col call cur$adr$hl ; HL=cursor address on return shld char$adr jr set$cursor ; call/ret page ;* ;* Move cursor up o ; no, fall thru and set background ; ; set background color (10-1F) ; ani 0Fh ; get value of 0 to F sta bg$color$80 push psw mvi a,26 ; color register call wait pop psw outp a ret ;* ;* ;* rd$color$80: lda bg$color$80 movall block$move$80 ; ; ; clear$bottom$line: lxi h,80*(lines-1) lxi b,80 call block$fill$space$80 jr compute$adr page ;* ;* B= bit position to set or clear ;* C= new bit value ;* ;* attr byte def. (in B and C) ;* bit 7-alternate char ; 13 May 85 ;** ;** 80 COLUMN FUNCTION CODE ;** fixed$8563 equ false ;* ;* Write character in D to current cursor address ;* Advance cursor next position ;* wr$char$80: lhld char$adr call write$char$80 lda char$col ; get cursor colter rc ; return if error mov a,m ; get color bytes ani 0fh ; LSB is 80 column color add b ; Add color offset back ; 0-f set forground color ; 10-1f set background color page ; ; set color in A (00-0F sets the character cne line; do nothing if on the ;* top line ;* crs$up$80: lda char$row ora a rz dcr a set$row$80: sta char$row jr compute$adr do$crlf: xra a sta char$col ;* ;* ;* ;* crs$down$80: lda char$row cpi lines-1 ; on bottom lin b,a lda current$atr mov d,a lda char$color$80 ret page ; ; set character color ; chr$col$80: mov b,a lda current$atr ani 0f0h ; remove old color ora b ; merge new color sta current$atr ; save new attr lda temp1 sta char$col set (uper case set) ;* bit 6-reverse video ;* bit 5-underline ;* bit 4-blink ;* bit 0-full intensity ;* ;* set$attr$80: lda current$atr cma ; invert A ora b ; force new bit to 1 cma ; restore A ora c sta current$atr ret umn number cpi 80-1 jrz do$crlf inr a sta char$col ; update column number lhld char$adr ; get cursor address inx h shld char$adr ; update cursor address ; ; input: ; HL=current cursor address ; set$cursor: mvi a,14 ; call wait olor) ; (10-1F sets the background color) ; ; This routine first calls lookup color to convert the 40 column ; color (normal color) to the 80 column RGBI color ; ?col$80: sta temp1 mvi c,20h ; max color value+1 (00h-1Fh) adi 30h ; restore ? jrz scroll$up ; yes, scroll the screen jrnc set$24$80 ; past it, set it to line 24 inr a jr set$row$80 ;* ;* ;* ;* crs$left$80: lda char$col ora a rz dcr a set$col$80: sta char$col jr compute$adr page ;* ;* ;* ;* or$80 ; ; set current char position color to new color ; lhld char$adr ; get current cursor adr lxi d,800h ; offset to attr dad d ; pointing to current char attr call set$update$adr ; point to attr byte lda current$atr outp a ret pa page ;* ;* ASCII codes(B) 20h to 2Fh set character color ;* 30h to 3Fh set background color ;* 50h to 5Fh set logical character color ;* 60h to 6Fh set logical background color ;* all others code do nothing ;* ;* set$color$80: mov a,b ; outp h mvi a,15 ; call wait ; outp l ret page ;* ;* Set current ROW and COL (supplied in DE) ;* ;* crs$pos$80: mov a,d cpi 25 rnc mov a,e cpi 80 rnc xchg ; cursor row # in D,column # in C shld char$col ;e a bias lxi h,color$convert$tbl ; table to use call lookup$color$2 ; convert to same color as 40 Column mov a,m ; get character color add b ; add color offset back cpi 10h ; character color? (0-f) jrc chr$col$80 ; yes, go do it crs$rt$80: lda char$col inr a cpi 80 jrnz set$col$80 ret ;* ;* ;* ;* crs$cr$80: xra a jr set$col$80 page ; ; ; set$24$80: mvi a,lines-1 sta char$row ; ; ; scroll$up: lxi h,80 lxi d,0 lxi b,80*(lines-1) cge ;* ;* ;* ;* CEL$80: call cur$adr$80$hl$sz$a ; HL=cur adr, DE=line start adr ; BC=count to move, A=BC+1 inx b ; 1 to 80 to fill jr cont$space$fill ;* ;* ;* ;* CES$80: call cur$adr$80$hl$sz$a ; HL=cur adr, DE=line start adr ; yes, exit call cur$adr$80$hl$sz$a ; HL=cur adr, DE=line start adr ; BC=count to move, A=BC+1 lxi h,80 ; line length dad d ; HL=start of next line xchg ; move from address in DE push h ; save TO address lxi h,lines*80 xra a b insert$low: push b call set$update$adr inp a xchg push psw call set$update$adr pop psw outp a xchg pop b dcx h dcx d dcx b mov a,b ora c jrnz insert$low lhld char$adr char$ins$80$end: jmp write$space$80 pagata$80 pop b pop d pop h inr h djnz block$fill$cont$80 page ; ; ; fill$less$256: mov a,c ; get LSB of count to A ana a ; is it zero ? rz ; yes, none left to fill, return ; ; count in A (1 to 256) (0=256) ; HL=fill adr ; past, lxi h,(lines-2)*80 lxi d,(lines-1)*80 mvi b,lines move$next$down: call move$line$down lda char$row cmp b jrnz move$next$down call cur$adr$80$hl$sz$a ; HL=cur adr, DE=line start adr ; BC=count to move, A=BC+1 xchg ; get l ; BC=count to move, A=BC+1 xchg ; cursor address in DE lxi h,lines*80 xra a ; clear the carry dsbc DE ; count will be minus if on status line rm ; return if on status line mov b,h mov c,l ; count to BC xchg ; cursor addr; clear the carry dsbc DE mov b,h mov c,l ; count to BC pop h ; recover TO address xchg ; move from address back to HL call block$move$80 ; DE points to last position jmp clear$bottom$line page ; ; user interface point ; ble ;* ;* ;* ;* char$del$80: call cur$adr$80$hl$sz$a ; HL=cur adr, DE=line start adr ; BC=count to move, A=BC+1 push d ; save line start address mov d,h mov e,l ; DE=HL=cursor address inx h ; [HL++]->[DE++] count BC call block$moDE=fill character, and attribute ; fill$data$80: push psw ; save count push h ; save adr push d ; save fill character call fill$half$80 pop d ; recover fill character lxi b,800h ; offset to attributes pop h ; recover adr dad ine start adr lxi b,80 jr block$fill$space$80 ; ; ; line$ins$cont: inr a cmp l rnz jmp update$it page ; ; INPUT: ; HL=source ; DE=dest ; B=line number ; OUTPUT: ; HL=source-80 ; DE=dest-80 ; B=line number - 1 ; moveess back to HL cont$space$fill: jmp block$fill$space$80 page ;* ;* ;* char$ins$80: call cur$adr$80$hl$sz$a ; HL=cur adr, DE=line start adr ; BC=count to move, A=BC+1 (1-80) lxi h,80-1 dad d ; point to end of line dcr a ; A=1k$fill: pop h ; get the return addres xthl ; get HL, ret adr to stack. jr block$fill$80 ; ; INPUT: ; HL=start address ; BC=count ; block$fill$space$80: lda current$atr mov e,a mvi d,' ' ; ; 80 block fill ; ; INPUT: ; HL=startve$80 ; DE points to last position pop h ; recover line start address lxi d,80-1 dad d ; point to end of line jmp write$space$80 page ;* ;* ;* Moves one line at a time, down one line, starting with the next ;* to the bottom line. Oncb ; HL=attr adr call do$twice? pop psw ; recover count mov d,e ; get the attr to D page ; ; fill$half$80: push psw ; save the count call set$update$adr ; write address to chip R18,R19 outp d ; write update data (R31) pop p$line$down: push b push h push d lxi b,80 call block$move$80 lxi b,-80 pop h dad b xchg pop h dad b pop b dcr b ret page ;* ;* ;* line$del$80: lda char$row cpi lines ; is the cursor past the bottom line ? rnc if at end of line jrz char$ins$80$end mov d,h mov e,l ; HL=DE= end of line address dcx h ; [HL--] -> [DE--] count BC push b push h push d call insert$low lxi b,800h ; attribute offset pop h dad b xchg pop h dad b pop address ; BC=count ; D=fill character, E=attribute ; block$fill$80: mov a,b ; get MSB of count to A ana a ; is it zero jrz fill$less$256 ; yes, move less than 256 bytes block$fill$cont$80: push h push d push b xra a call fill$de the cursor line is moved down, the ;* cursor line is cleared. ;* line$ins$80: lxi d,new$offset mvi a,lines-1 ; cursor on or past the last line ? lhld char$col cmp h jz clear$bottom$line ; no bottom, clear bottom line jrc line$ins$cont ; sw dcr a ; already wrote one above rz ; return if only one required push psw mvi a,24 call wait inp a ; get old value in reg 24 ani 7fh outp a ; clear R24(7), enabling block writes mvi a,30 call wait pop psw ; recoveradr, D=char to write, A=attr to write ; write$memory: push h push d ; save character lxi d,800h ; offset to attribrute dad d mov d,a call wr$mem pop d pop h wr$mem: call set$update$adr outp d ret ;* ;* input: ;* D=Char t return adr xthl ; get HL save ret adr ; ; block move 80 column chip memory ; ; INPUT: ; HL=source ; DE=dest ; BC=count ; block$move$80: mov a,b ; get MSB of count to A ana a ; is it zero jrz move$less$256 ; yes, move less than inp a ; check if chip is ready yet ral ; (MSB=1 when ready) jrnc wait$loop ; not ready, loop pop psw outp a ; set chip register inr c ; point to data register ret ; ; ; set$update$adr: mvi a,18 call wait outp h mvi a,et$update$adr ; write dest address to chip R18,R19 mvi a,24 call wait inp a ; get old value in reg 24 ori 80h outp a ; set R24(7), enabling block copy ; call set$source$adr ; write source address (R32,R33=DE) ;set$source$adr: mvi a, the count outp a ; write count to R30 if fixed$8563 ret else mvi b,0 mov c,a inx b ; add back the one removed above dad b push d ; save fill char (in D) push h ; HL=end address mvi a,18 call wait inp h mvi a,19ROW, E=Char COLUMN ;* output: ;* B=Char, C=attribute (true RGBI color) ;* rd$chr$80: call crs$pos$80 lhld char$adr call read$memory mov c,a ; attr was in A ret ;* ;* input: ;* D=Char ROW, E=Char COLUMN ;* B=Char, C=attribute (true 256 bytes block$move$cont$80: push h push d push b xra a call move$data$80 pop b pop d pop h inr h inr d djnz block$move$cont$80 move$less$256: mov a,c ; get LSB of count to A ana a ; is it zero ? rz ; yes, none left19 call wait outp l mvi a,31 call wait dcr c update$wait: inp a ral jrnc update$wait inr c ret page ;** ;** 40 COLUMN TERMINAL FUNCTION CODE ;** ;** ;* ;* ;* wr$char$40: mov b,d call ascii$to$petascii ; convert to32 call wait outp d mvi a,33 call wait outp e ; ret mvi a,30 call wait pop psw ; recover the count outp a ; write count to R30 ret page ; ; ; do$twice?: mov a,h ; HL=video memory address cpi DS$char$def/256 ; Cha call wait inp l ; HL=current pointer pop d ; DE=end adr pop b ; get fill char (to B) finish$fill: call cmp$HL$DE ; compare dest with chip dest ; HL [DE--] count BC push b push d lddr ; DEda attr$40 mov m,a ldir ; set color attribute jr cont$compute$adr$40 page ;* ;* ;* ;* crs$left$40 lda char$col$40 ora a rz dcr a set$col$40: sta char$col$40 jr compute$adr$40 ;* ;* ;* ;* crs$rt$40: lda char$col$40tribute (40 col attr and color) ;* rd$chr$40: call crs$pos$only$40 lhld char$adr$40 mov b,m lxi d,800h dad d mov c,m ret ;* ;* input: ;* D=Char ROW, E=Char COLUMN ;* B=Char, C=attribute (40 col attr and color) ;* output: ;* H=CBC DE ; result is minus if on status line rm ; return if on status line xchg jrz write$space$40 ; at end, clear cursor position mov b,d mov c,e ; count in BC mov d,h mov e,l ; start adr in HL inx d ; start adr+1 in DE pushchar$row$40 cont$compute$adr$40: lxi h,old$offset setb 6,m jr compute$adr$40 ; ; ; crlf$40: xra a sta char$col$40 ;* ;* ;* ;* crs$down$40: lda char$row$40 cpi lines-1 jrz scroll$up$40 jrnc set$24$40 inr a jr set$row$40 =cursor position xchg call write$space$40 ; write a space at the cursor adr pop h lxi b,800h ; now move the attributes dad b pop b mov d,h mov e,l ; HL=DE= end of line address dcx h ; [HL--] -> [DE--] count BC lddr ; DE=cursor inr a cpi 80 jrnz set$col$40 ret ;* ;* ;* ;* crs$cr$40: xra a jr set$col$40 page ;* ;* ;* ;* CEL$40: lxi h,line$paint push h call cur$adr$40$hl$sz$a ; HL=cursor adr, DE=start of line adr ; BC=DE+80-HL-1, A=BC+1 (1-8har ROW, L=Char COLUMN ;* wr$chr$40: push b call crs$pos$only$40 pop b lhld char$adr$40 mov a,b ani 7fh ; remove reverse video bit bit 6,c jrz not$rev$vid$bit adi 80h ; set reverse video not$rev$vid$bit: mov m,a lxi d,800h da b ; save number of bytes to move push h ; save start address call space$fill$40 ; move space thru screen ; ; ; clear$attr$also: lxi b,800h pop h dad b ; 1st attribute pop b ; get the count mov d,h mov e,l inx d ; 2nd attri page ; ; ; set$24$40: mvi a,lines-1 sta char$row$40 ; ; ; scroll$up$40: lxi h,screen$40+80 lxi d,screen$40 lxi b,80*(24-1) ldir ; move characters up one line xchg ; get start of last line in HL lxi d,screen$40+80*23+1 lxi position ret ; ; ; write$space$40: lda rev$40 adi ' ' ; clear character, enable cursor mov m,a ret page ;* ;* ;* ;* char$del$40: lxi h,line$paint push h call cur$adr$40$hl$sz$a ; HL=cur adr, DE=line start adr ; BC=co0) lxi d,screen$40 ; get start of screen dad d ; HL=cursor position in memory call write$space$40 ; place a space at the cursor adr mov a,c ana a rz push b push h mov d,h mov e,l ; DE=HL=cursor pos inx d ; point to next locatd d mov m,c jmp set$cursor$40 ;* ;* ;* crs$pos$40: lxi h,old$offset setb 6,m ; force page paint crs$pos$only$40: mov a,d cpi 25 rnc mov a,e cpi 80 rnc xchg shld char$col$40 ; ; ; compute$adr$40: lhld char$col$40 cbute lda attr$40 mov m,a ldir ; move current attribute to screen ret page ;* ;* ;* ;* char$ins$40: lxi h,line$paint push h call cur$adr$40$hl$sz$a ; HL=cur adr, DE=line start adr ; BC=count to move, A=BC+1 (1-80) lxi h,sc b,80-1 call space$fill$40 ; clear the bottom line lxi h,screen$40+800h+80 lxi d,screen$40+800h lxi b,80*(lines-1) ldir ; move attributes up one line xchg ; get start of last line in HL lxi d,screen$40+800h+80*23+1 lxi b,80-1 lunt to move, A=BC+1 lxi d,screen$40 dad d ; point to screen memory location dcr a ; at end of line ? jrz write$space$40 ; yes, then just erase cursor pos mov d,h mov e,l ; DE=HL=cursor address push b push h inx h ; [HL++]->[D ;* bit 6-reverse video * ;* bit 5-underline ;* bit 4-blink ;* bit 0-full intensity (masked off) ;* ;* set$attr$40: mov a,b ani 070h mov b,a mov a,c ani 070h mov c,a lda attr$40 cma ora b cma ; bits in B cleared A ornes ; end of screen address xra a ; clear the carry bit (and A) dsbc DE ; HL=HL-DE mov b,h mov c,l ; count in lxi h,screen$40+80*(lines-1)-1 ; HL=end of screen-80 lxi d,screen$40+80*lines-1 ; DE=end of screen push b lddr pageSB ?col$40: cpi 10h ; character color? (0-f) jrc char$color$40 ; yes, go do it ; no, fall thru test background, border cpi 20h ; background color? (10-1f) jrc back$color$40 ; yes, go do it ; no, fall thru and set border color ve cursor line start adr lxi d,80 dad d ; point to start of next line xchg ; cursor line(+1) start address in DE lxi h,screen$40+80*lines ; end of screen address xra a ; clear the carry bit (and A) dsbc DE ; HL=HL-DE mov b,h mov E++] count BC ldir ; DE points to last position xchg call write$space$40 ; place a space at the end of line pop h lxi b,800h+1 ; now move the attributes dad b pop b mov d,h mov e,l ; HL=DE= cursor attr address inx h ; [HL++] ->a c ; add new value sta attr$40 ral ; get reverse attr in bit 7 ani 80h sta rev$40 ret page ;* ;* ASCII codes 20h to 2Fh set character color ;* 30h to 3Fh set background color ;* 40h to 4Fh set border color ;* 50h to 5Fh set pop b lxi h,screen$40+80*(lines-1)-1+800h lxi d,screen$40+80*lines-1+800h lddr ; scroll the attributes pop h ; get cursor line start address mov d,h mov e,l inx d lxi b,80-1 jr space$fill$40 ; ; ; clear$bottom$line$40: l ; ; set border color ; ani 0fh ; color from 0-f sta bd$color$40 lxi b,VIC+32 outp a ret page ; ; set background color (10-1F) ; back$color$40: ani 0Fh ; get value of 0 to F sta bg$color$40 lxi b,VIC+33 outp a ret ;*c,l ; count in xchg ; HL=start of line after cursor line pop d ; start of cursor line push b ; save count push h ; save source push d ; save dest ldir lxi b,800h ; get attribute offset pop h ; recover dest dad b ; [DE++] count BC ldir ; ret page ;* ;* ;* ;* line$ins$40: lxi h,screen$paint push h lda char$row$40 cpi lines-1 jrz clear$bottom$line$40 rnc ; return if on status line call cur$adr$40$hl$sz$a ; HL=cur adr, DE=line start adrlocical character color ;* 60h to 6Fh set logical background color ;* 70h to 7Fh set logical border color ;* all others code do nothing ;* ;* All colors are assigned from color lookup table ;* set$color$40: mov a,b sui 20h cpi 30h jrcxi h,screen$40+(lines-1)*80 lxi d,screen$40+(lines-1)*80+1 lxi b,80-1 space$fill$40: lda rev$40 adi ' ' mov m,a ldir ret page ;* ;* ;* ;* line$del$40: lxi h,screen$paint push h lda char$row$40 cpi lines-1 ; on or past last ;* ;* rd$color$40: lda bg$color$40 mov b,a lda bd$color$40 mov c,a lda attr$40 mov d,a ani 0fh ret ; ; set character color ; char$color$40: mov b,a lda attr$40 ani 0f0h ora b sta attr$40 lhld char$adr$40 lxi d,800h attr dest xchg ; dest belongs in DE pop h ; recover source dad b ; attr source pop b ; recover count ldir jr clear$bottom$line$40 page ;* ;* B=bits to set or clear ;* C=bits new value ;* ;* attr byte def. (in B) ;* bit 7- ; BC=count to move, A=BC+1 lxi h,screen$40 dad d ; point to line start memory location push h ; save start address lxi d,80 dad d ; point to start of next line xchg ; cursor line(+1) start address in DE lxi h,screen$40+80*li ?col$40 mvi c,30h ; max color value+1 (00h-2Fh) call lookup$color$1 ; HL points to table entry on ret rc ; exit if error mov a,m ; get table value again rrc rrc rrc rrc ; get upper 4 bits to lower ani 0fh add b ; get old M line ? jrz clear$bottom$line$40 ; on, just clear it rnc ; past it, return call cur$adr$40$hl$sz$a ; HL=cur adr, DE=line start adr ; BC=count to move, A=BC+1 lxi h,screen$40 dad d ; point to line start memory location push h ; sa dad d mov m,a ; jmp line$paint page ; ; ; line$paint: lda old$offset mov b,a ora a cm trk$40 lda @off40 ; cmp b sta old$offset jrnz screen$paint call cur$adr$40$hl$sz$a ; DE=start of row adr (REL) lxi h,screen$40 ; mov a,b cpi 40h jrz is40 ; get at sign rc ; ret if code was 20h - 3fh cpi 'Z'+1 ; is it an upper case letter ? rc ; yes, code was 41h - 5Ah sui 40h cpi 60h-40h jrz was$60 ; 60h converted to 27h jrc was$5b$to$5f sui 20h page ; ; hl=offset (0 to 39) ; screen$paint: lhld @off40 lda paint$size ; number of lines to move push h push psw ; save the count lxi d,screen$40 dad d ; point to start of visible screen lxi d,vic$screen ; place to move it to ; ; OUTPUT: ; HL=cursor address ; DE=cursor line start address ; BC=# character to end of line ( <80 ) ; (not counting the cursor position) ; A=BC+1 ; cur$adr$hl$sz$a: mvi a,80-1 ; get line length sub l ; A= mov c,a cur$adr$hl: screen paint if required lda @off40 ; get screen offset mov b,a ; save offset (0 to 39) lhld char$col$40 ; H=row, L=col mov a,l ; get col # in A sub b ; remove offset jrc no$cursor cpi 40 jrnc no$cursor mov c,a mvi b,0 ; get start of screen dad d ; HL=row start address (ABS) xchg ; save in DE lhld @off40 ; get current screen offset (0-39) dad d ; screen source adr in HL push h ; save for later lda char$row$40 ; get current row # mov l,a ; HL= cpi 'z'+1-60h rc ; code was 61h - 7Ah cpi '{'-60h jrz is$left$brace cpi '|'-60h jrz is$vert$bar cpi '}'-60h jrz isright$brace cpi '~'-60h rnz mvi a,64 ; commodore horz bar ret was$60: mvi a,126 ; solid upper left corner call update$window$fun pop psw pop h lxi d,screen$40+800h dad d ; add the screen offset lxi d,vic$color ; ; Always called from bank 0, Placed in common so that IO ; will not overlay this code. Can go in ROM ; update$window$fun: sta mov b,l ; save column # mov l,h mvi h,0 ; HL=row # dad h ; 2x dad h ; 4x dad h ; 8x dad h ; 16x mov d,h mov e,l ; save 16x dad h ; 32x dad h ; 64x dad d ; 64x+16x=80x xchg ; DE=row start address mov l,b ; get saved cBC=cursor column # mov l,h ; get row # in L call Lx40$plus$VIC dad b jr set$flash ; no$cursor: lxi h,0 ; if H=0 (L=xx) then cursor off ; set$flash: shld flash$pos ret page ; ; ; Lx40$plus$VIC: mvi h,0 dad h ; 2X dad h row # (H=0) call Lx40$plus$VIC xchg ; place screen adr (25X40) in DE pop h ; recover logical screen adr (25X80) push h ; save for attr move push d mvi a,1 ; one line only call update$window$fun pop h ; recover screen pointe ret is$left$brace: mvi a,115 ; ret is$vert$bar: mvi a,93 ; commodore vertical bar ret is$right$brace: mvi a,107 ; ret was$5b$to$5f: cpi '\'-40h jrz is$back$slash cpi '_'-40h rnz mvi a,100 ; commodore under line reio$0 update$window$loop: lxi b,40 ; number of bytes to move ldir push d lxi d,80-40 ; advance pointer to next line dad d pop d dcr a jrnz update$window$loop sta bank$0 ret page ; ; ; trk$40: lda char$col$40 ; get theolumn # mvi h,0 ; HL=column # dad d ; HL=cursor address mvi b,0 ; BC= count (if call to cur$adr$hl$sz$a:) inr a ; number of bytes to end of line (1-80) ret page ; ; destroys DE,HL,B,A ; lookup$color: mov a,b ; color supplied in ; 4X dad h ; 8X mov d,h mov e,l ; DE=8X dad h ; 16X dad h ; 32X dad d ; 8X+32X=40X lxi d,vic$screen dad d ; point to screen area ret page ; ; input: ; range 20h to 7fh in B ; output: ; in A ; ascii$to$petascii: r (25X40) lxi b,vic$color-vic$screen dad b ; point to Vic color memory xchg ; DE=color memory pointer pop h ; recover screen pointer (25X80) lxi b,800h ; offset to attributes dad b mvi a,1 ; one line only jr update$window$fun ; t is$back$slash: mvi a,127 ; upper left and lower right corners ret is40: xra a ret page ; ; ; cur$adr$40$hl$sz$a: lhld char$col$40 jr cur$adr$hl$sz$a ; ; ; cur$adr$80$hl$sz$a: lhld char$col ; ; INPUT: ; H=row L=col current column number sui 40-8 ; remove 1st 32 columns jrnc use$offset ; if pass column 32, set an offset xra a use$offset: ani 0f8h ; move sta @off40 ret page ; ; ; set$cursor$40: call no$cursor call line$paint ; will do a B lookup$color$1: lhld color$tbl$ptr ; ; HL=table adr ; A= color input ; C= max allowable color value ; lookup$color$2: sui 30h ; remove bias rc cmp c ; above limit cmc rc ; yes, return input out-of-range mov b,a ; save adjn dcr b ; ..install$ascii has been done rz ; ..so just exit Chr$fill 180h,64,0 ; fill 180-1bf with 0 Chr$move 17ah,18ah,1 Chr$move 169h,189h,1 Chr$move 15eh,18eh,2 ; move 2 character definitions Chr$move 101h,161h,26 ; move 16 chara$adr ; mvi h,8 ; set the loop count install$char$loop: ldax d ; get the input data outp a ; save to video memory dcr c ; point to status register inx d ; advance the input pointer write$wait: inp a ; wait for the chip to write USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Thy into the video (character def) memory. ; ; INPUT: ; DE=system memory character definition ; HL=character code adr to install ; B=number of characters to install (should be > 2) ; OUTPUT: ; DE=eight more then on entry ; HL=character code adrusted color # ani 0fh ; get only the color # mov e,a mvi d,0 dad d ; get converted color address mov a,b ; get the ASCII char back ani 30h ; keep only char/background/borber bits mov b,a ; save char/background bit ret page cter definitions Chr$fill 100h,32,0 Chr$move 000h,140h,1 Chr$move 01bh,15bh,3 ; move 3 character definitions Chr$move 01ch,180h,1 Chr$move 01eh,181h,2 Chr$move 040h,1c0h,64 ; move 16 character definitions ; now install characters that are ral ; the data to memory (with auto jrnc write$wait ; incrment) inr c ; point to the data register dcr h ; dec the loop count jrnz install$char$loop ret page  page chr$move macro xx,yy,zz lxi h,xx*16+DS$char$def lxi d,yy*16+DS$char$def lxi b,zz*16-8 call block$move$80 endm chr$fill macro xx,yy,zz lxi h,xx*16+DS$char$def ; start adr lxi b,yy*16 ; count mvi d,zz ; character to fill wi to install + B*16 ; B=0 ; char$install$group: push b push h call char$install pop h lxi b,16 dad b ; advance to the next character pop b djnz char$install$group ret page ; ; this routine will install the character pointed ; ; ; bell: lxi b,sid+24 lhld sound$1 outp h mvi c,5 outp l lhld sound$2 inr c outp h mvi c,1 outp l lhld sound$3 mvi c,4 outp h outp l ret e NOT already defined lxi d,extra$char$table lxi h,15ch*16+DS$char$def call char$install lxi h,15eh*16+DS$char$def mvi b,3 ; install 5e, 5f and 60 call char$install$group lxi h,17bh*16+DS$char$def mvi b,5 jr char$install$group ;e USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Thth call block$fill$80 endm newoffset equ 179*11*2 ; ; 1st move pet-asc characters to ASCII positions ; install$ASCII: lxi h,100h*16+DS$char$def+4 ; point to center of @ char call rd$mem ; ..read it to B inr b ; ..if it is a zero theto by DE ; into the 8563 ASCII char set, character number pointed ; to by HL. ; INPUT: ; DE=system memory character definition ; HL=character code adr to install ; OUTPUT: ; DE=eight more then on entry ; H=0 ; char$install: call set$update ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0L call/ret page ; ; user function, HL supplied on the stack under the stack ; char$install$gp: pop h ; get return address xthl ; get HL from stack (ret adr to stack) ; ; this routine will install a group of characters form ; system memorreen db 02h ; 6 blue db 0dh ; 7 yellow db 0ah ; 8 orange db 0ch ; 9 brown db 09h ; A light red db 06h ; B gray 1 db 01h ; C gray 2 db 05h ; D light green db 03h ; E light blue db 0eh ; F gray 3 ; ; org 1000h-86 ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0L PAGE swap$code: @sei ; ffd5 @lda 3eh,# ; ffd0 @sta force$map ; ffd2 @lda z80$on,# ; ffd6 @sta mode$reg ; ffd8 @nop ; ffdb @jmp bios$02 ; ffdc @nop ; ffdf di ; ffe5 mvi a,3eh ; ffe0 sta force$map ; ffe2 049h,025h ; 15 db 017h,013h,045h,068h,029h,018h,017h,007h ; 16 db 00ch,068h,04bh,034h,013h,00fh,005h,04bh ; 17 db 070h,031h,00dh,00dh,008h,008h,06ch,00dh ; 18 org 1000h-75-11 ; -86 mmu$init$data: db 3fh,3fh,7fh,3eh,7eh ; config regs db -144 ; 8*18 ; -230 ; extra$char$table: db 000h,060h,030h,018h,00ch,006h,003h,000h ; 1 db 018h,03ch,066h,000h,000h,000h,000h,000h ; 2 db 000h,000h,000h,000h,000h,000h,07fh,000h ; 3 db 060h,030h,018h,000h,000h,000h,000h,000h ; 4 db 01ch,030h,030e USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Th lxi b,mode$reg ; ffe6 mvi a,z80$off ; ffe9 outp a ; ffeb nop ; ffed rst 1 ; ffee jump to load CP/M swap$size equ $-swap$code free$space equ 1000h-230-16-$ page ; ********************************* ; * * ; * Fixed data tables z80$on,common$16K db 00 dir$ptrs: ; part of both MMU data and db 00,01 ; dir$ptrs db 00 org 1000h-75 ; -75 special$skew: skew 21,5,0 skew 19,5,0 skew 18,5,0 skew 17,5,0 org free$space end h,060h,030h,030h,01ch,000h ; 5 db 018h,018h,018h,018h,018h,018h,018h,000h ; 6 db 038h,00ch,00ch,006h,00ch,00ch,038h,000h ; 7 db 000h,01bh,02ah,066h,000h,000h,000h,000h ; 8 db 000h,000h,000h,000h,000h,041h,07fh,000h ; 9 db 000h,0f2h,05bh,039h,001h* ; * * ; ********************************* ; ; org 1000h-230-16 ; -246 ; ; 40 column color to RGBI ; color$convert$tbl: db 00h ; 0 black db 0fh ; 1 white db 08h ; 2 red db 07h ; 3 cyan db 0bh ; 4 purple db 04h ; 5 g; ; ; bell: lxi b,sid+24 lhld sound$1 outp h mvi c,5 outp l lhld sound$2 inr c outp h mvi c,1 outp l lhld sound$3 mvi c,4 outp h outp l ret ,04eh,065h,037h ; 10 db 006h,003h,01eh,007h,00bh,068h,04bh,034h ; 11 db 017h,001h,044h,062h,02dh,018h,012h,00bh ; 12 db 063h,059h,031h,017h,000h,00bh,059h,072h ; 13 db 02bh,018h,00fh,063h,000h,04fh,02bh,005h ; 14 db 04ch,068h,02dh,017h,016h,069h, SUBMIT.COM From USER 2: CXROM.SUB CXROM1.ASM CXROM02.ASM CXROM80.ASM CXROMINT.ASM CXROMK.ASM ; ; ; bell: lxi b,sid+24 lhld sound$1 outp h mvi c,5 outp l lhld sound$2 inr c outp h mvi c,1 outp l lhld sound$3 mvi c,4 outp h outp l ret  MAKEROM.DOC CP/M 3.0 on the Commodore 128 28May87 To create the ROM BIOS used by CP/M on the Commodore 128 follow the procedure listed below. You will need a 1571 or 1581 disk drive, or a 1750 RAM disk, for this task. If you do CPM3.LIB CXEQU.LIB X6502.LIB Z80.LIB 3. To assemble new ROM code, select the drive which contains your work disk (eg, A:) and enter: 'SUBMIT CXROM' and t ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0Lnot have one of these devices, you will have to make modifications to suit your system. Slightly more than a 200K space is needed for the procedure described. 1. Create a work diskette by using the FORMAT utility. If you are using a 1571 drhe automatic process will begin. The output is in the file CXROM.HEX. 4. This code should be regarded as an invariant portion of CP/M for the Commodore 128, and is available as source for informational purposes only. For alternate USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Thive select the C128 double sided option. If you are using a 1750 RAMdisk (drive M:), make sure it is empty. 2. Copy the following files to your work disk, using the PIP utility: From USER 0: PIP.COM MAC.COM pip cxrom.asm=cxrom1.asm,cxromint.asm,cxrom80.asm,cxrom02.asm,cxromk.asm[v mac cxrom $$pz-s  special$skew: skew 21,5,0 skew 19,5,0 skew 18,5,0 skew 17,5,0 org free$space end ives to the 'ROM Loader', see the source for the FORMAT utility (to support the 1581 disk drive, it was necessary to place a new Loader on the 1581 system track). p$line: equ 0 ; screen top row for signon message use$line: equ 2 ; screen row for "using source" message keynam$line: equ 4 ; screen row for showing keyname lots$line: equ 6 ; screen row for showing big messages prompt$line: equ 10 ; screen row for shequ 0FFC0h ; open a logical file (after SETLFS & SETNAM) K$chkout equ 0FFC9h ; open a channel for output K$clrchn equ 0FFCCh ; clears ALL I/O channel K$chkin equ 0FFC6h ; open a channel for input K$chrin equ 0FFCFh ; get a character from input chann ; ext$error equ 00480h ; tell$user equ 004FFh ; table$error equ 0051Bh ; prt$msg$both equ 00526h ; prt$HL$both equ 00534h ; install$ASCII equ 005BDh ; wait equ 00945h ; ;BIOS$65$code equ 00D22h ; ;BIOS$size equ 001C3h ; ;F$rd$count buf 7) ; memory location jobs equ 002h ; list of jobs to be done hdrs equ 00Bh ; header info (track and sector) buf$use equ 06Dh ; bit X set allocates buffer X next$job equ 083h ; pointer to next job to be done hdrjob equ 099h vtrans$ts equ 1e USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Thowing menus spec$line: equ 23 ; status line row for special messages crlf: equ 0ffh ; code to do cr,lf do$6502$fun: equ 4 scrsz40: equ 20h ; flag value that this is a 40 column screen scrsz80: equ 40h ; flag value that this is an 80 column screen el K$chrout equ 0FFD2h ; output a character to output channel K$clall equ 0FFE7h ; close all open files K$close equ 0FFC3h ; close a logical file K$readst equ 0FFB7h ; read status byte page ;"""""""""""""""""""""""""""""""""" ;m a c r o d e equ 031BDh ; swap$code equ 00EE5h ; swap$size equ 0001Fh ; MMU$init$data equ 00FAAh ; page ;""""""""""""" ;E Q U A T E S ;""""""""""""" cret: equ 01 ; matrix position of return key disk$ready$key: equ 11 ; matrix position of $ ctrlB8h ; sector x-lat vector drv$buf equ 300h ; buffer 0 start adr ;boot$ret equ 0d35Ah ; will change with next ROM boot$ret equ 0FF5Ah ; return from drive boot code page ; pointer equ 20h ; DMA pointer used by 8502 cmdchn equ 15 ; use comand cha title 'C128 Format Program 08 June 1987' ; modified 08June87 by V.Ertwine & F.Bowen: add 1581 support ; modified 07May86 by V.Ertwine: add more MFM formats ; original 15May85 by V.Ertwine: original release maclib z80 maclib cxequ both: equ scrsz40+scrsz80 ; both of the above user$offset: equ 3*(30-1) page ;""""""""""""""""""" ;CP/M function calls ;""""""""""""""""""" bdos: equ 05 ;bdos call entry point conin: equ 01 ;char returned in a conout: equ 02 ;char sent inf i n i t i o n s ;"""""""""""""""""""""""""""""""""" define macro label,for org ramalc label equ $ ramalc set ramalc+for endm save$top$bottom macro toprow,number mvi a,toprow+number-1 sta bottom$choice mvi a,toprow sta top$choice endmc: equ 20 ; matrix position of c key yes$key: equ 25 ; yes - matrix position of 'y' key no$key: equ 39 ; 'no' - matrix position of n key cursor$up$key: equ 53h ; matrix position of up arrow cursor$dn$key: equ 54h ; matrix position of down arrow tonnel #15 ; ; KERNAL EQUATES ; serial equ 00A1Ch D2PRA equ 0DD00h D1SDR equ 0DC0Ch D1ICR equ 0DC0Dh clk$bit equ 10h K$set$bnk equ 0FF68h ; K$setlfs equ 0FFBAh ; setup a logical file K$setnam equ 0FFBDh ; set up file name for OPEN K$open maclib x6502 format$1581 equ true $*MACRO boot$code$02 equ 00B00h boot$code$80 equ 0E000h ; ; RAM loader equates ; rownum macro row,col db row+80h,col endm sys$name equ 000EDh ; cmp$hl$de equ 000FAh ; read$sector equ 0044Fh e constat: equ 11 ;console status cur$dsk: equ 25 ;get current disk to A getscb: equ 49 ;get system control block ;""""""""""""""""""""""""" ; 1581 Drive equates ;""""""""""""""""""""""""" ; constants buf$alc equ 081h ; allocate buffer 0 (no skip$and$destroy$hl macro db 21h endm zero? macro r1,r2 mov a,r1 ora r2 endm fmt macro fmtdef1,fmtdef2 DW fmtdef1 IF NOT NUL fmtdef2 DW fmtdef2 ELSE DW 0 ENDIF ENDM wrdef macro ?trk,?sect,?pointer db ?trk,?sect dw ?t$next sta fmt$drv sta vic$drv mov a,b ; get current drive select (0-3) sta sel$drv adi 'A' sta dsp$drv$1 sta dsp$drv$2 sta dsp$drv$3 ; ;***** login requested drive ; call get$disk$info ani 0Eh cpi 0Eh jz select$drv page db crlf,'C128 Double sided' db crlf,'C128 Single sided' db crlf,'C64 Single sided' db crlf,'IBM Single Sided' db crlf,'IBM Double Sided' db crlf,'KAYPRO II' db crlf,'KAYPRO IV' db crlf,'EPSON QX10' db crlf,'OSBORNE DD' db crlf,'Select Difmy parameter block mvi c,getscb ;..CP/M function to determine screen size call bdos mov a,h ani both ;..save whether 40,80 or both sta scrsiz ;NOW we are ready to start ;""""""""" ;SAY$HELLO: ;""""""""" call clear$screen ;set up to db 'Drive ' dsp$drv$1: db 'A is a 15' a$15xx: db 'x1',eom mvi a,use$line call highlight$line re$start: lxi sp,stack ; set up stack lda a$15xx cpi '4' jz get$1541$choices if format$1581 cpi '7' jz get$1571$choices ; cpi '8' pointer endm defstart macro fillbyte IF NOT NUL fillbyte db fillbyte ELSE db 0 ENDIF ENDM defbuf macro ?count,?offset,?pointer dw ?count dw ?offset dw ?pointer endm definline macro ?count,?offset db ?count,-1 dw ?offset ;-------------- ;show$disk$type: ;-------------- lda fast ;first tell user what type disk lxi h,fmt$drv ;point to format drive ana m ;..drive a= lst bit lxi h,3134h ; 0=1541 jrz show$slow$fast ; ; ;***** test for 1581 or 1571 ; ; ferent Drive' db eom save$top$bottom promptline+1,10 call menu$response dw c128$ds dw c128$ss dw c64$ss ; dw c1571$ibm$ss ; dw c1571$ibm$ds ; dw c1571$kp$2 ; dw c1571$kp$4 ; dw c1571$epson ; dw c1571$osborne ; dw select$ call posit$top ;..print signon message call print$msg db 'C128 CP/M FORMAT PROGRAM' db crlf db ' 08 JUNE 1987' db eom page mvi c,cur$dsk ; RETURN CURRENT DISK call bdos ; ..in A cpi 4 jrc select$new xra a ; if not A,B; jz get$1581$choices ; page ;--------------- ;get$1581$choices: ;--------------- call show$prompt ; db 'Please select disk type to format' db crlf,'Commodore 1581 (Double Sided)' db crlf,'Write system track only' db crlf,'Select Different endm defexec macro ?adr db 0,-1 dw ?adr endm defend macro dw -1 endm page ;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" ;S T A R T H E R E ;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" or if format$1581 mvi l,'8' ;assume 1581 lda vic$data cpi 0A3h ;horrible hack for *blank* disks! jrz show$slow$fast ; it is an empty 3.5" drive cpi 0A9h jrz show$slow$fast ; it is a virgin 3.5" diskette ani 0B0h ; cpi 020h ;Residdrv ; page ;---------------- get$1541$choices: ;---------------- call show$prompt ; db 'Please select disk type to format' db crlf,'C128 single sided' db crlf,'C64 single sided' db crlf,'Select Different Drive' db eom save$top$bott,C or D set A page ;---------- select$new: ;---------- mov b,a ; save in B for later mov c,a ; A=B=C= selection # (0-3) inr c ; (1-4) mvi a,80h ; rlc will give 01 select$next: rlc ; drive byte 0000dcba binary dcr c jrnz selec Drive' db eom save$top$bottom promptline+1,3 call menu$response dw c128$ds$81 dw c128$sys$81 dw select$drv endif page ;--------------- get$1571choices: ;--------------- call show$prompt db 'Please select disk type to format' g 100h ;"""""""""""""" ;initialization ;"""""""""""""" lxi sp,stack ;set up stack lhld 0001 ;read jump vector for i/o lxi d,user$offset ;..add this dad d shld go$user$fun+1 ;install vector to user BIOS functions lxi d,scbpbrd ;point to ent fmt with 512 byte sectors? jrz show$slow$fast ; yes, gotta be a 1581 endif mvi l,'7' ;none of the above, set as a 1571 show$slow$fast: shld a$15xx ;..store the type in message call clear$lots ; call posit$using call print$msg her?: ;--------------- call print$msg db crlf,lf,lf db 'Do you want to format another disk?' db eom call get$yes$or$no jc re$start ;----------- exit$format: ;----------- call clear$screen call posit$prompt call print$msg db '..... jrnz data$inline call get$DE$from$HL xchg ; HL=code adr, DE=DEF pointer push d ; save DEF pointer call ipchl pop h ; recover DEF pointer jmp next$fill data$inline: mvi b,0 mov c,e ; BC=number of bytes to move call get$DE$from$et track & sect mov a,d ; DE=-1 ? ana e inr a jz format$another? mov a,e sta trk mov a,d sta sect call print$msg db '..writing sector',cr,eom call get$DE$from$HL ; get DEF pointer xchg ; HL=DEF pointer, DE=MAIN pointer pus1571$osborne: lxi h,osborne$dsk$def jr format$str ; ; c1571$kp$2: lxi h,kp$2$dsk$def jr format$str ; ; c1571$kp$4: lxi h,kp$4$dsk$def jr format$str ; ; c1571$ibm$ss: lxi h,ibm$dsk$def$ss jr format$str ; ; C1571$ibm$ds: lxi h,iexiting format program',cr,lf,lf,eom exit$clean: mvi c,13 call bdos ; reset disk system mvi c,constat call bdos ana a jz 0 mvi c,conin call bdos jmp 0 ;--------- quit$prog: ;--------- push psw push b push d push h call pHL ; get offset push h ; save DEF pointer lxi h,sect$buf dad d ; HL=buffer+offset xchg ; DE=buffer+offset pop h ; recover DEF pointer ldir jmp next$fill page ; ; ; format$DE$tbl: push h ; save MAIN pointer xchg ; HL=formath d ; save MAIN pointer ; ; ; mov a,m ; get fill byte inx h call init$buf$with$A ; (HL saved) next$fill: call get$DE$from$HL ; get word count to DE jm count$minus mov b,d ; save count in BC mov c,e call get$DE$from$HL ; get offset inbm$dsk$def$ds ; jr format$str page ; ; ; format$str: ; call print$msg ; db 'Formatting',crlf,eom call print$what shld fmt$tbl$ptr call clear$prompt call print$msg db 'Insert diskette TO BE FORMATTED' db crlf,'in drive ' dsp$drv$2: om promptline+1,3 call menu$response dw c128$ss dw c64$ss dw select$drv ;---------- select$drv: ;---------- call show$prompt ; db 'Please select drive you wish to format with' db crlf,'Drive A' db crlf,'Drive B' db crlf,'Drive C' osit$spec ;for special messages call print$msg db 'Are you sure? [ ]',bs,bs,eom call get$yes$or$no jrc exit$clean call posit$spec call clear$eol pop h pop d pop b pop psw ret page ;-------------- get$DE$from$HL: ;------------ table pointer mov c,m ; get count mvi b,0 ; count will be 1 to 255 inr c ; move count also lxi d,@buffer ; point to command buffer area ldir ; move format data to buffer lda fmt$drv ;..bit 0==drive a, MSB=unit 0 sta vic$drv mvi a,do$ buffer push d call get$DE$from$HL ; get pointer to data xthl ; save DEF pointer get offset push d ; save DATA pointer lxi d,sect$buf dad d ; HL= buffer+offset pop d ; DE= DATA pointer xchg ; HL= DATA ptr, DE= buffer+offset ldir db 'A. Type $ when ready,' db crlf,'any other key to abort ',eom call scan$for$key mov a,b cpi disk$ready$key jnz user$panics call clear$prompt call print$msg db '..formatting diskette in drive ' dsp$drv$3: db 'A',crlf,eom lhld fmtdb crlf,'Drive D' db eom save$top$bottom promptline+1,4 call menu$response dw 0 ; continue execute inline jmp select$new page ; ; if format$1581 c128$ds$81: lxi h,c1581$dsk$def jr format$str c128$sys$81: lxi h,c1581$sys$def -- mov e,m inx h mov d,m inx h mov a,d ora e rz mov a,d ana a ret ipchl: pchl ;--------------- init$buf$with$A: ;--------------- push h lxi h,sect$buf shld dma mov m,a lxi d,sect$buf+1 lxi b,1024 ldir pop h r6502$fun mvi l,vic$frmt call go$user$fun ;call,ret ora a jrnz format$error pop h ret page ;------------ format$error: ;------------ call print$msg db ' format error',cr,lf,eom user$panics: pop h ;--------------- format$anot; move data to buffer pop h ; recover DEF pointer jr next$fill page ; ; ; count$minus: inr e ; test for -1 jrnz cnt$not$minus$1 call write$data pop h ; recover MAIN pointer jmp format$1 cnt$not$minus$1: dcr e ; test for 0 $tbl$ptr ; do the format call get$DE$from$HL ; get format table pointer (side 1) cnz format$DE$tbl call get$DE$from$HL ; get format table pointer (side 2) cnz format$DE$tbl call set$dsk$type page ; ; ; format$1: call get$DE$from$HL ; g jr format$str endif ; ; c128$ds: lxi h,c128$ds$dsk$def jr format$str ; ; c128$ss: lxi h,c128$ss$dsk$def jr format$str ; ; c64$ss: lxi h,c64$ss$dsk$def jr format$str ; ; c1571$epson: lxi h,epson$dsk$def jr format$str ; ; cet ; ; set disk type to TYPE 0 (GCR direct sector I/O) ;------------ set$dsk$type: ;------------ push h mvi c,13 call bdos ; reset disk system lxi d,sel$pb call BIOS$ind dcx h call get$disk$info bit a,7 ; MFM disk? jrnz size$ok jrz back$to$?? dcx h dcx h dad d ;+ beginning of jump table mov a,m inx h mov h,m mov l,a back$to$??: mov a,b ;a=0-x pchl page ;""""""""""""""""""""""""""""""""""""""""""""""""""""" ;s c r o l l u p & d o w n t h r o u gget$yes$or$no ;""""""""""""""""""""""""""""""""""""""""""""" ;s c a n f o r k e y b o a r d i n p u t ;""""""""""""""""""""""""""""""""""""""""""""" scan$for$key: mvi a,2 call go$user$fun inr b jrz scan$for$key dcr b ret page $editing: lxi d,keynam$line*256+0 jr set$fx$cp$cmd posit$top: lxi d,top$line*256 jr set$fx$cp$cmd posit$using: lxi d,use$line*256 ; B=row C=col jr set$fx$cp$cmd clear$lots: call posit$lots call clear$eos posit$lots: lxi d,lots$$con$out mvi e,lf do$con$out: mvi c,conout jmp bdos BIOS$ind: mvi c,50 jmp bdos print$what: push h call clear$lots pop h call print$hl push h mvi a,lots$line call highlight$line pop h ret show$prompt: call clear$lots ; yes, then size is ok ani 30h ; no, 1571 GCR reports jrnz size$ok ; ...128 byte sectors mvi a,10h ; set 256 byte sectors size$ok: ani 00110000b ; set disk type to DSK$none mov m,a ; this will allow direct sector access pop h re h m e n u ;""""""""""""""""""""""""""""""""""""""""""""""""""""" scroll$values: push psw lda current$choice ;unhighlight the current menu line mvi h,0 ;..dont set any additional attributes call write$hi$line ;..common routine for writing ;""""""""""""""""""""""""""""""" ;c l e a r t h e s c r e e n ;""""""""""""""""""""""""""""""" clear$screen: call print$msg db 1ah,eom ret ;""""""""""""""""""""""""""""""""""""""""" ;g e t r e s p o n s e t o m e n u ;""""""""""""line*256 jr set$fx$cp$cmd posit$spec: lxi d,spec$line*256 set$fx$cp$cmd: ;set up to position cursor mvi l,FR$cursor$pos jr go$screen$fun clear$eos: mvi l,FR$CES jr go$screen$fun clear$eol: mvi l,FR$CEL go$screen$fun: push b ; call posit$prompt ;----------------------------------------------------- print$msg: ;print a message on the screen ;----------------------------------------------------- xthl call print$hl xthl ret print$hl: push h print$lp: pop ht ;------------- get$disk$info: ;------------- push h mvi a,do$6502$fun mvi l,vic$test call go$user$fun ;call,ret mov b,a ;save status from drive in B also pop h ret page ;---------- write$data: ;---------- lxi d,dma$bnk$pb ccurrent line pop psw ;get flags back jrc scroll$up lda bottom$choice mov b,a lda current$choice cmp b ;current==bottom && scrolldown?? jrz force$top inr a sta current$choice jr highlight$line ;call,ret scroll$up: lda top$choic""""""""""""""""""""""""""""" menu$response: sta current$choice call highlight$line wait$ans: call scan$for$key mov a,b cpi cret jz made$selection cpi ctrlc cz quit$prog call up$or$down? cz scroll$values jr wait$ans made$selec lda scr$siz mvi c,FR$40 cpi scrsz40 jrnz set$fx$eighty set$fx$forty: mov a,l add c mov l,a set$fx$eighty: mvi a,3 ; direct to screen fun # pop b go$user$fun: jmp 0000 ; address filled in page ;""""""""""""""""""""""""""""""""" mov a,m ;..get the message mov e,a ;in a for call to bdos inx h ;..update pointer ana a ;if char was 0, pointer = return address rz ;..end message push h ;..restore pointer inr a ;..FF==cr,lf jrz char$eq$cr$lf call do$con$out all BIOS$ind lxi d,dma$pb call BIOS$ind lxi d,trk$pb call BIOS$ind lxi d,sect$pb call BIOS$ind lxi d,wr$pb call BIOS$ind ana a rz pop h call posit$spec call print$msg db 'Disk write error',crlf,eom jmp exit$format page ;"e mov b,a lda current$choice cmp b ;current==top && scroll up?? jrz force$bottom dcr a sta current$choice jr highlight$line ;call,ret force$top: lda top$choice ;to scroll down from bottom==top sta current$choice jr highlight$line tion: lda top$choice mov b,a lda current$choice sub b ;a=0-x for choices mov b,a ;..save it pop d mov l,a mvi h,0 ;first test if de is pointing to a 00 dad h ;*2 xchg ;(00--> just return) mov a,m inx h ora m inx h """""""""""""""" ;s c a n f o r y e s o r n o a n s w e r ;""""""""""""""""""""""""""""""""""""""""""""""""" get$yes$or$no: call scan$for$key mov a,b cpi yes$key stc rz sui no$key ana a ;clear carry for no rz call beep jr jr print$lp ;..loop char$eq$cr$lf: call do$cr$lf jr print$lp clear$prompt: call posit$prompt call clear$eos posit$prompt: lxi d,prompt$line*256+0 ; B=row C=col jr set$fx$cp$cmd clear$edit: call posit$editing call clear$eos posit"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" ; ;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" beep: mvi e,7 jr do$con$out do$cr$lf: mvi e,cr call do ;call,ret force$bottom: lda bottom$choice ;to scroll up from top==bottom sta current$choice highlight$line: ;a=row # to be highlighted call read$this$row ;to highlight, read current row and mvi h,40h ;..write it out with rev vid attrib0 wrdef 39,1,ST$sect$39$1 wrdef 39,2,ST$sect$39$2 wrdef 39,3,ST$sect$39$3 wrdef 39,4,ST$loader$start$1 wrdef 39,5,ST$loader$start$2 defend endif page ; ; ; c64$ss$dsk$def: db 'C64 single sided',eom fmt fmt$tbl$c64$ss wrdef 1,0,ST 11 ; set sector # db 0 sect: dw 0001h ; sector # dw 0 dw 0 dma$pb: ;dma parameter block db 12 db 0 dma: dw 4000h ; dma pointer dw 0 dw 0 dma$bnk$pb: ;dma bank parameter block db 28 db 1 ; dma bank 1 dw 0 dw 0 dw 0 te functions call go$screen$fun ;go do it pop d ;cursor position back inx d ;..next pop b ;get counter back djnz wr$hi$li$loop ;..loop ret ;...line is rewritten up$or$down?: mov a,b ;get matrix row in a cpi cursor$up$key ;is it cnz scan$space$lp ;keep looking end$scan: mov a,b inr a sta read$count ;store # of non-white chars to restore pop psw ;restore a=row # ret page write$hi$line: mov d,a ;current row passed in a mvi e,0 ;..start at column 0 mov a,h ute jr write$hi$line page read$this$row: push psw ;save the row number for others mov d,a ;d=row mvi e,0 ;column (e) = 0 lxi h,save$buffer ;a place to read into shld temp$ptr ;save a pointer xra a ;..initialize count to 0 sta rea$c64$1$0 ; track, sector, DEF wrdef 3,0,ST$E5s ; track, sector, DEF wrdef 3,1,ST$E5s ; track, sector, DEF wrdef 3,2,ST$E5s ; track, sector, DEF wrdef 3,3,ST$E5s ; track, sector, DEF wrdef 3,4,ST$E5s ; track, sector, DEF wrdef 3,5,ST$E5s page ; ; 39-1 | 39-2 | 39-3 | ;"""""""""""""""|"""""""""""""""|"""""""""""""""| ; disk | BAM | BAM | disk | DRV | SYS | ; lable | 1 | 2 | DIR | boot | boot | ;"""""""|"""""""|"""""""|"""""""|"""""""|"""""""| ; 40-0 | 40-1 | 40-2 | 40ursor up? stc rz ;..return if cursor up sui cursor$dn$key ana a ;clear carry flag ret ;return something to caller page ;------------------------------- ;p a r a m e t e r b l o c k s ;------------------------------- scbpbrd: db 2 ;..additional attribute bits passed in h sta temp ;save attribute value to be ored lxi h,save$buffer ;where the current line was read into shld temp$ptr ;..save pointer to it lda read$count ;number of bytes actually in line (no trailing spaces) d$count read$row$lp: push d ;..save it to loop mvi l,FR$rd$chr$atr ;read char and attribute from (de) call go$screen$fun ;go read a character lhld temp$ptr ;get buffer pointer mov m,b ;buffer the character inx h mov m,c ;..and the attri; track, sector, DEF wrdef 3,6,ST$E5s ; track, sector, DEF wrdef 3,7,ST$E5s ; track, sector, DEF defend page ; ; ; c128$ss$dsk$def: db 'C128 Single Sided',eom fmt fmt$tbl$c64$ss wrdef 1,0,ST$c128$1$0$ss ; track, sector, DEF wrdef 1,-3 | 40-4 | 40-5 | ; ; ; 39-4 | 39-5 | ;"""""""""""""""|"""""""""""""""| ; LDR | LDR | LDR | | ; #1 | #2 | #3 | | ;"""""""|"""""""|"""""""|"""""""| ; 40-6 | 40-7 | 40-8 | 40-9 | ; if format$1581 c1581$dsk$def: db 'Formatting C14h ;set offset for conout db 0 ;..get (read)scb (hl =returnedword,a=byte) dw 0 ;just for the hell of it wr$pb: ;write parameter block db 14 ;write sector db 0 dw 0 dw 0 dw 0 sel$pb: ;select parameter block db 9 ; select driv mov b,a ;..count in b wr$hi$li$loop: push b ;save the counter push d ;save the cursor position lhld temp$ptr ;get pointer mov b,m ;get char in b inx h ;point to attribute mov a,m ;..get attribute inx h ;update to next character bute inx h ;to next character shld temp$ptr ;save the pointer pop d ;current row,column inx d ;next row,column mov a,e ;when count(column)=, we have read maximum cpi 40 jrnz read$row$lp dcx h ;point to last character written mov b,e 3,ST$E5s wrdef 1,4,ST$E5s wrdef 1,9,ST$E5s wrdef 1,10,ST$E5s wrdef 1,14,ST$E5s wrdef 1,15,ST$E5s wrdef 1,19,ST$E5s wrdef 1,20,ST$E5s wrdef 18,0,ST$sect$18$0 defend page ; ; ; c128$ds$dsk$def: db 'C128 Double Sided',eom fmt fmt28 CP/M on C1581',eom fmt fmt$tbl$c1581 wrdef 39,1,ST$sect$39$1 wrdef 39,2,ST$sect$39$2 wrdef 39,3,ST$sect$39$3 wrdef 39,4,ST$loader$start$1 wrdef 39,5,ST$loader$start$2 defend c1581$sys$def: db 'Formatting C128 CP/M on C1581',eom fmt e function db 0 ; a sel$drv: dw 0 ; bc drive # dw 1 ; de lsb=0 means 1st time select dw 0 ; hl trk$pb: ;track parameter block db 10 ; set track db 0 trk: dw 0001h ; track # dw 0 dw 0 sect$pb: ;sector parameter block dbshld temp$ptr ;..save the pointer mov h,a ;..put attribute here for a moment lda temp ;get the attribute passed (either rev vid or none) ora h ;..set it mov c,a ;..attribute must be passed in c mvi l,FR$wr$chr$atr ;write character and attribu ;# of characters to scan for trailing spaces mvi a,' ' ;..space character to scan for scan$space$lp: dcx h ;char, not attribute cmp m ;..is char a space?? jrnz end$scan ;if not, we are done dcx h ;..else decrement to previous attribute dj$tbl$c64$ss wrdef 1,0,ST$c128$1$0$ds ; track, sector, DEF wrdef 1,1,ST$E5s wrdef 1,2,ST$E5s wrdef 1,3,ST$E5s wrdef 1,4,ST$E5s wrdef 1,7,ST$E5s wrdef 1,8,ST$E5s wrdef 1,9,ST$E5s wrdef 1,10,ST$E5s wrdef 1,12,ST$E5s wrdef 1,13,ST$E5s w 40,4 ; logical trk 40 sector 4 db 'COPYRIGHT CBM 86' definline 1,11Eh db 1 defend page ; ; ; ST$sect$39$3: defstart 0 definline 5,0 db 0,lng$drv$cd+5 dw drv$buf ; exec adr in drv db lng$drv$cd defbuf lng$drv$cd,5,drv$cod ; ST Starting track logical (def 0) ; S Starting Offset Physical (def 0) ; FL Fill byte (def E5) ; ; ; fmt$tbl$ibm$ds: db 6 db 01100110b ; N cmd 4 format DS db 10000001b ; MD Mode MFM (start sector 1) db 0 ; CP interleave of 0 ; -- bottom of KAYPRO II and KAYPRO IV disk ; fmt$tbl$kp$2: db 6 db 01000110b ; N cmd 4 db 10000000b ; MD Mode MFM (start sector 0) db 0 ; CP interleave of 0 db 2 ; SZ 512 byte sectors db 39 ; LT last track 39 db 10 ; NS 10 sectors/trrting track # db 0E5h ; fill byte db 38 ; gap 3 endif ; ; GCR Format parameters ; fmt$tbl$c64$ss: table$ds: db 4 db 00000110b ;parameter N (cmd 4) db 00000000b ;parameter MD (Mode GCR) db '8' ;parameter ID low db '0' ;parameterdef 1,14,ST$E5s wrdef 1,15,ST$E5s wrdef 1,17,ST$E5s wrdef 1,18,ST$E5s wrdef 1,19,ST$E5s wrdef 1,20,ST$E5s wrdef 18,0,ST$sect$18$0 wrdef 53,0,ST$sect$18$0 defend page ; ; ; epson$dsk$def: db 'EPSON QX10 512 byte sectors',eom fmte$1581 defexec boot$check$sum ; compute Check SUM defbuf 0c9h,100h,boot$1581$sector defend ; ; ; ST$loader$start$1: defstart 0 defbuf 512,0,loader$start defend ; ; ; ST$loader$start$2: defstart 0 defbuf loader$size-512,0,loader db 2 ; SZ 512 byte sectors db 39 ; LT last track 39 db 8 ; NS 8 sectors/track ; ST Starting track logical (def 0) ; S Starting Offset Physical (def 0) ; FL Fill byte (def E5) page ; ; ; if format$1581 ST$sect$39$1: defstarack ; ST Starting track logical (def 0) ; S Starting Offset Physical (def 0) ; FL Fill byte (def E5) ; ; KAYPRO IV (double sided) ; -- uses this format data to format the top of the disk (side 1) ; fmt$tbl$kp$4: db 6 db 01010110b ; r ID high ; ; ; fmt$tbl$epson: db 6 db 01100110b ; N cmd 4 db 10000001b ; MD Mode MFM (start sector 1) db 0 ; CP interleave of 0 db 2 ; SZ 512 byte sectors db 39 ; LT last track 39 db 10 ; NS 10 sectors/track ; ST Starting trac fmt$tbl$epson defend ; ; no sector to be set-up ; osborne$dsk$def: db 'OSBORNE Double Density',eom fmt fmt$tbl$osborne defend ; ; ; kp$2$dsk$def: db 'KAYPRO II',eom fmt fmt$tbl$kp$2 defend kp$4$dsk$def: db 'KAYPRO IV',eom fmt $start+512 defend endif page ; ; ; ST$c64$1$0: defstart 0E5h definline 4,0 db 'KMBE' defend ; ; ; ST$c128$1$0$ss: defstart 0 defbuf 24h,0,sect$1$0 defend ; ; ; ST$c128$1$0$ds: defstart 0 defbuf 24h,0,sect$1$0 deft 0 defbuf 29,0,sect$39$1 definline 8,100h db 40,2 ; next BAM track and sector db 44h,not(44h) ; DISK version # db '80' ; Disk ID db 40h ; verify off, check header ID on db 80h ; enable auto load defend ; ; ; ST$sect$39$2: dN cmd 4 db 10001010b ; MD Mode MFM (start sector 10) db 0 ; CP interleave of 0 db 2 ; SZ 512 byte sectors db 39 ; LT last track 39 db 10 ; NS 10 sectors/track ; ST Starting track logical (def 0) ; S Starting Offset Physical (def 0) k logical (def 0) ; S Starting Offset Physical (def 0) ; FL Fill byte (def E5) ; ; ; fmt$tbl$osborne: db 6 db 01000110b ; N cmd 4 db 10000001b ; MD Mode MFM (start sector 1) db 0 ; CP interleave of 0 db 3 ; SZ 1024 byte sectors fmt$tbl$kp$2,fmt$tbl$kp$4 defend page ; ; IBM -- single sided disk definition ; ibm$dsk$def$ss: db 'IBM SS',eom fmt fmt$tbl$ibm$ss wrdef 0,1,ST$ibm$ss ; track, sector, DEF defend ; ; ; ibm$dsk$def$ds: db 'IBM DS',eom fmt fmt$tbl$inline 1,255 db -1 defend page ; ; ; ST$sect$18$0: defstart 0 definline 4,0 db 1,5,41h,80h definline 4,48h db 11h,0fch,-1,7 definline 27,90h db 'CP/M PLUS' db 0a0h,0a0h,0a0h db 0a0h,0a0h,0a0h db 0a0h,0a0h,0a0h db '65',0a0efstart 0 definline 7,1 db -1 ; mark end of BAM db 44h,not(44h) ; Disk Version # db '80' ; ID db 40h ; verify off, check header ID on db 80h ; enable auto load definline 20,101h db -1 ; next track sector (end) db 83h ; type USR db ; FL Fill byte (def E5) page ; ; ; fmt$tbl$ibm$ss: db 6 db 01000110b ; N cmd 4 db 10000001b ; MD Mode MFM (start sector 1) db 0 ; CP interleave of 0 db 2 ; SZ 512 byte sectors db 39 ; LT last track 39 db 8 ; NS 8 sectors/track db 39 ; LT last track 39 db 5 ; NS 5 sectors/track ; ST Starting track logical (def 0) ; S Starting Offset Physical (def 0) ; FL Fill byte (def E5) page ; ; KAYPRO II (single sided) ; -- uses this format data to format the top andibm$ds wrdef 0,1,ST$ibm$ds ; track, sector, DEF defend page ; ; ; if format$1581 fmt$tbl$c1581: db 1 db 10000110b ;parameter N (cmd 4) db 2 ; sector size =512 db 79 ; last track # 79 db 10 ; number sectors/track db 0 ; stah,'2A' db 0a0h,0a0h db 0a0h,0a0h defend ; ; ; ST$E5s: defstart 0E5h defend ; ; IBM single sided ; -- Track 0, Sector 1 last byte =0 ; ST$ibm$ss: defstart 0E5h definline 1,512-1 ; last byte=0 for IBM single sided db 0 defend dy 6,# sendf: @lda R$cmd+BB,y @jsr 0FFD2h ; CHROUT @dey @bne sendf @jsr 0FFCCh ; CLRCHN @bit 0DC0Dh ; D1ICR @jsr read$byte+BB ; read status @ldx 2,# ; 2 256 byte blocks/sector @ldy 0,# @sty 20h ; low byte of DMA adr rd$bu ; open command chanel to drive 8 ; @lda 15,# ; (2A,2B) @ldx 8,# ; (2C,2D) @tay ; (2Eh) @jsr 0FFBAh ; (2F-31) SETLFS @lda 0,# ; (32,33) @tax ; (34) @jsr 0FF68h ; (35-37) SETBNK @lda 4,# ; (38,39) @ldx low(u0point+BB),#ctor (logical) db 44h,0 ; Disk versions and null flag db 'CP/M PLUS',0a0h,0a0h,0a0h db 0a0h,0a0h,0a0h,0a0h,0a0h,0a0h db '80',0a0h,'3D',0a0h,0a0h page ; 1581 Boot sector ; track 1 sector 0 sector definition (256 bytes) ; BB equ boot$code$0s+CV) my$trans$low set low(my$trans+CV) ; ; drv$code$1581: @sei @lda VTRANS$TS ; get old vector and save it @sta CV+code$exit$2+1 @lda VTRANS$TS+1 @sta CV+code$exit$2+2 @lda my$trans$low,# ; install new vector @sta VTRANS$TS @lda my; ; IBM double sided ; -- Track 0, Sector 1 last byte =1 ; ST$ibm$ds: defstart 0E5h definline 1,512-1 ; last byte=0 for IBM single sided db 1 defend page ; ; Computes and sets the check SUM for the 1581 Drive Boot sector ; if format$ff: @jsr read$byte+BB @sta (20h),y ; at dma adr @iny @bne rd$buff @inc 21h ; advance DMA pointer @dex @bne rd$buff @lda 0DD00h ; D2PRA @and 0EFh,# ; @sta 0DD00h ; set clk hi @rts ; read$byte: @sei ; disable inte ; (3A,3B) @ldy high(u0point+BB),# ; (3C,3D) ;;;*** @jsr 0FFBDh ; (3E-40) SETNAM @jsr 0FFC0h ; (41-43) OPEN ; ; read sector 39-4 ; dma0 equ high(boot$code$80) @lda 39,# @ldx 4,# @ldy dma0,# @jsr rd$sector+BB ; ; read sector 39-5 2-$ ; boot$1581$sector: db 'CBM',0,0,0,0,0,0 ; bytes 0 to 8 @sei ; (9) @jsr 0ff84h ; (A-C) reset I/O ; ; Clear Bank 0 memory ; @lda 3Fh,# ; (D,E) Enable RAM 0 @sta 0FF00h ; (F-11) @lda 10h,# ; (12,13) high byte of page poin$trans$hi,# @sta VTRANS$TS+1 @lda buf$alc,# @sta buf$use ; protect this code @jmp boot$ret my$trans: @ldx next$job @lda jobs,x ; get current job @cmp 80h,# ; is it a READ @bne code$exit$1 @ldy hdrjob ; get index @ldx hdrs1581 boot$check$sum: lxi h,sect$buf+2 lxi d,sect$buf+2+lng$drv$cd+3 mvi b,0 ; start SUM =0 sum$next: mov a,m add b aci 0 ; add carry to LSB mov b,a ; return sum to B inx h mov a,l cmp e jrnz sum$next mov a,h cmp d jrnz sum$rrupts @lda 0DD00h ; D2PRA @eor 10h,# ; clock bit @sta 0DD00h @lda 8,# in$1: @bit 0DC0Dh ; D1ICR @beq in$1 @lda 0DC0Ch ; D1SDR @rts R$cmd equ $-1 db 1 ; count sect02: db 0 ; sector # trk02: db 0 ; track # db 0,'0' ; @lda 39,# @ldx 5,# @jsr rd$sect$buf+BB ; ; install JMP BOOT$CP/M ; low$start equ low(boot$code$80) hi$start equ high(boot$code$80) @lda 0c3h,# @sta 0FFEEh @lda low$start,# @sta 0FFEFh @lda hi$start,# @sta 0FFF0h @lda 3eh,# ;ter @sta 21h ; (14,15) save hiagh byte of pointer @lda 0,# ; (16,17) low byte of page pointer @sta 20h ; (18,19) save low byte of pointer @ldx 0EFh,# ; (1A,1B) from 1000h to FEFFh @tay ; (1Ch) start at 0 era$loop: @sta (20h),y +1,y ; get logical sector @bne code$exit$1 @ldx hdrs,y ; get logical track @dex ; was it one @bne code$exit$1 @ldx 40,# @stx hdrs,y ; change to logical TRK=40 @ldx 5,# @stx hdrs+1,y ; change to logical SECT=5 code$exit$1: @lnext mov m,b ; save sum to end of buffer ret endif page ; ; 1541 and 1571 BOOT sector ; track 1 sector 0 sector definition (256 bytes) ; sect$1$0: db 'CBM',0,0,0,0,0,0 ; bytes 0 to 8 @sei ; byte 9 @jsr 0ff84h @lda 3eh,# ; s; read comand =00h u0point: db 'U0',4Ch,0 ; Inquire Status page ; ZZ equ boot$code$80-$ LOADER$START: ; ; setup the MMU for booting CP/M ; lxi sp,boot$stack mvi a,3Fh sta force$map ; ; move bios and swap code into ram ; lxi h,bio set MMU to bank 0 @sta 0ff00h ; .. RAM and IO only @jmp 0FFD0h ; swap to Z80 (RST1 location) rd$sector: @sty 21h ; hi byte of DMA adr rd$sect$buf: @sta trk02+BB @stx sect02+BB @ldx 15,# ; CMD chan # @jsr 0FFC9h ; CHKOUT @l; (1D,1E) @iny ; (1Fh) @bne era$loop ; (20,21) @inc 21h ; (22,23) point to next page @dex ; (24) @bne era$loop ; (25,26) @sta 0FF00h ; (27-29) re-enable kernal and I/O ; ; load sectors that contain CP/M boot code (RAM version) ;da CV+code$exit$2+1 @sta VTRANS$TS ; get old vector and save it @lda CV+code$exit$2+2 @sta VTRANS$TS+1 code$exit$2: @jmp 0000 lng$drv$cd equ $-drv$code$1581 page ; ; 1581 Directory Sector ; sect$39$1: db 40,3 ; directory track & seet MMU to bank 0 @sta 0ff00h ; .. RAM and IO only @lda 0c3h,# @sta 0FFEEh @lda 08,# @sta 0FFEFh @lda 0,# @sta 0FFF0h @jmp 0ffd0h ; swap to Z80 (RST1 location) page if format$1581 CV equ drv$buf-$ my$trans$hi set high(my$trans$65$code+ZZ lxi d,bios$02 lxi b,bios$size ldir lxi h,swap$code lxi d,enable$z80 lxi b,swap$size ldir mvi a,RET ; get z80 return adr sta return$6502 ; store the RET ; ; initilize the 8502 bios ; xra a ; cleared by memory finum xra a ret page ;---------------------------- ; save CPM+.SYS group numbers ;---------------------------- ; found a dir entry that has the right name ; add block pointers to list ; FOUND: lxi d,block$ptrs ; point to start of block poin256 byte blocks) mov b,a lda info$buffer+6 ; get page pointer (pointer to end) sub b ; find the start ; install jmp adr to BIOS02 sta return$z80+2 ; (jmp) (low) (high) xra a sta return$z80+1 ; (jmp) (low) (high) ;-------------------------- call prt$msg$both rownum 3,12 db 'DATA TABLES',0 lhld info$buffer+10 shld key$tbl ; install keyboard translation pointer lxi h,info$buffer+9 call GET$SIZE$ADR+ZZ ; HL=adr DE=# (128 btye) records shld fun$tbl LOAD$NEXT$FORWA+24 mvi a,vic$screen*4/256+6 ; upper and lower case set (+6) outp a ; ; ; mvi a,64 sta block$size ; 64 dir entries/2K allocation lxi h,DIR$PTRS+ZZ shld ld$blk$ptr call SCAN$DIR+ZZ ; check 1st block call SCAN$DIR+ZZ ; check 2nd blockll sta vic$cmd call enable$6502 page ; ; set MMU registers to a known state (for CP/M to use) ; lxi h,mmu$init$data+11-1 ; start at the End lxi b,mmu$start+11-1 ; and work forward mvi d,11 ; for all 11 bytes INIT$MMU$CPM: mov a,m ters lda ext$num ora a jrz EXT$NUM$0 lxi d,block$ptrs+16 dcr a jnz ext$error EXT$NUM$0: lhld @dma ; get current pointer lxi b,16 ; number of bytes to move dad b ; also advance to block pointers ldir lhld block$ptrs mo----------------- ; now let's start executing CP/M Plus ;------------------------------------ lhld info$buffer+4 ; get start address pchl ; transfer control to CP/M page ;-------------; ; SUBROUTINES ; ;-------------; ; scan buffer for CPRD: call LOAD$RECORD+ZZ ; HL =load address (in and out) lxi d,128 ; move pointer back to buf start dad d jrnz LOAD$NEXT$FORWARD page ;----------------------------------- ; transfer CP/M code to load address ;------------------------------ (1K or 2K) lhld block$ptrs ; 1st pointer <>0 if file mov a,h ; name exist ora l ; pointer = 0 jz tell$user ; yes, inform user there is a error ; no, file FOUND, process it page ;---------------------------- ; load 1st group to 1K; get table value outp a ; send to MMU dcx h dcr c dcr d jrnz INIT$MMU$CPM ; re-enabled RAM bank 0 (no I/O) ; ; set 80 column colors and set up Video memory with ASCII char set ; mvi a,26 call wait mvi a,90h ; foreground red bav a,h ora l ; 1st block present ? rz ; no, read more dir. lhld block$ptrs+14 ; extent full? mov a,h ora l jrz GO$BOOT$IT ; no, this is it then lhld block$ptrs+16 ; 2nd block present ? mov a,h ora l rz ; no, read more dir.M+.SYS file ; SCAN$DIR: call UPDATE$BUFFER+ZZ ; returns HL=block$buffer mvi a,64 ; 64 for 2K block ; ..number director entries/sector CHECK$NEXT: shld @dma lxi d,sys$name ; point to system name push psw call name$match+ZZ cz FOUND----- call prt$msg$both rownum 4,12 db 'COMMON CODE',0 lxi h,info$buffer+1 ; load common code call LOAD$REVERSE+ZZ call prt$msg$both rownum 5,12 db 'BANKED CODE',0 lxi h,info$buffer+3 ; load banked code call LOAD$REVERSE+ZZ page buffer ;---------------------------- FILE$FOUND: lxi h,block$ptrs shld ld$blk$ptr call UPDATE$BUFFER+ZZ ;-------------- ;GET$BOOT$INFO: ;-------------- lxi h,block$buffer lxi d,info$buffer lxi b,12 ldir call prt$msg$both rownum ckground black outp a mvi a,85h ; set attr and color sta current$atr ; ..for 80 column display mvi a,green ; set color sta attr$40 ; ..for 40 column display call install$ASCII ; convert char set to true ASCII mvi a,25 ; number of GO$BOOT$IT: jmp FILE$FOUND+ZZ ; two parms are still on the stack ; but at this point who cares page ; ; ; LOAD$REVERSE: call GET$SIZE$ADR+ZZ ; HL=adr DE=# records (128 byte) LOAD$NEXT: lxi d,-128 ; move pointer back to buf star+ZZ pop psw lhld @dma ; get current buffer pointer lxi d,32 dad d dcr a jrnz CHECK$NEXT ret page ; ; ; name$match: mvi b,12 xchg match$next: ldax d ani 7fh cmp m rnz inx h inx d djnz match$next ldax d sta ext$ ;--------------------------- ; now load the bios8502 code ;--------------------------- call prt$msg$both rownum 6,12 db 'BIOS8502 CODE',0 lxi h,info$buffer+7 ; load banked code call LOAD$REVERSE+ZZ lda info$buffer+7 ; get code size (in 10,0 db 0 ; end of string marker lxi h,block$buffer+80h call prt$hl$both lxi h,block$buffer+256 ; set scan pointer shld blk$unld$ptr page ;--------------------------------- ; load keyboard data to system RAM ;--------------------------lines on the 40 col display sta paint$size page ; ; Let the user know we are booting CP/M ; call prt$msg$both db -1 ; clear both screens rownum 1,10 db 'BOOTING CP/M PLUS',0 ; ; point 40 column screen to CP/M screen area ; lxi b,VICt dad d call LOAD$RECORD+ZZ jrnz LOAD$NEXT ret ; ; ; GET$SIZE$ADR: mov e,m mvi d,0 ; get buffer size (#256 byte) mov a,e ; get size to A ora a jz table$error ; exit if count=0 xchg dad h ; HL=#128 byte blocks shld load$ at buffer start @jsr read$256+BZ ;+K read 1st 256 byte block @jsr read$256+BZ ;+K read 2nd 256 byte block @dex ;+K @bne rd$sect ;+K clk$hi: @lda d2pra ;+K @and 0ffh-clk$bit,# ;+K @sta d2pra ;+K @rts ;+K PAGE ; ; read$256: ; ; * DEVICE MISSING, CLEAN UP ERROR * ; MISDSK: @LDA 00fh,# ;+K SET ERROR CODE @skip2 fst$error: @lda 0dh,# ;?K @skip2 DISK$CHANGED: @lda 0FFh,# ;?K @STA vic$data ;?K writes to RAM under ROM @JMP CMDLP+BZ ;?K PAGE ; 80 memory map as required @sta force$map ;-K @jmp enable$z80 ;-K ; ; **** IO COMMAND DISPATCH ROUTINE **** ; VICIO: @CLD ;-K clear to binary mode @LDA vic$cmd ;-K get the command @bne read ;-K 0=initialize ; 1=read page nd 1K block pop h ; recover block buffer adr ret ; ; convert block number (in HL) to sector and track ; read$1K: mvi a,2 sta F$rd$count+BZ ; lxi d,10 ; 10 sectors per side lxi b,-1 compute$trk: inx b ora a ; clear the carry dcount xchg dcx h mov h,m mvi l,0 ret page ; ; ; LOAD$RECORD: push h ; save to address lxi h,block$buffer+2048 xchg lhld blk$unld$ptr call cmp$hl$de cz UPDATE$BUFFER+ZZ xchg lxi h,128 dad d shld blk$unld$ptr pop h @jsr rd$byte+BZ ;+K @sta (pointer),y ;+K @iny ;+K @bne read$256 ;+K @inc pointer+1 ;+K @rts ; rd$byte: @lda d2pra @eor clk$bit,# @sta d2pra @lda 8,# rd$1: @bit d1icr @beq rd$1 @lda d1sdr @rts page ; ; handle all interru; **** DISK SECTOR READ **** ; READ: @ldx 0,# ;-K get read command (side 0) @lda VIC$sect @cmp 11,# @bmi on$side$0 @ldx 10h,# ; get read command (side 1) @sbc 10,# ; remove bias of 10 on$side$0: @stx F$cmd+BZ @sta F$rd$sect+BZ @lda ; ; ; initilize: ; initialize the 8502 @ldx 0,# ;-K @stx force$map ;-K enable the kernal @stx VIC+26 ;+K turn off VIC interrupts @ldx low(irqs+BZ),# @ldy high(irqs+BZ),# @stx 314h ;+K IRQ vector @sty 315h @stx 316h ;+K BRK sbc d ; negative if <10 jrnc compute$trk ; jump if still positive >=10 dad d ; add it back mov a,c ; get trk # (0 to 159) cpi 39*2 jrc bump$trk inr a inr c bump$trk: rrc ; move bit 0 to carry mvi a,1 ; sector numbers are 1 to ; recover save address push h xchg ; HL=source DE=dest. lxi b,128 ; size of move ldir lhld load$count dcx h shld load$count mov a,l ora h pop h ret page ; ; ; UPDATE$BUFFER: lxi h,block$buffer shld @dma push h ;pts in BIOS 8502 (throw them away) ; irqs: @lda CIA$1+int$ctrl @lda CIA$2+int$ctrl @lda 0fh,# @sta VIC+25 ; ; system saved memory config, Y, X and A before getting here ; @pla @sta force$map @pla @tay @pla @tax @pla @rti PAVIC$trk @sta F$rd$trk+BZ @lda @dma ;-K @sta pointer ;-K @lda @dma+1 ;-K @sta pointer+1 ;-K @lda 0,# ;-K @sta force$map ;-K @ldx cmdchn,# ;+K @jsr K$chkout ;+K @bcs fst$error ;+K @ldy Fcmd$lng,# ;+K sendf$rd: @lda Fcmd$buf+BZ-vector @sty 317h @stx 318h ;+K NMI vector @sty 319h ; ; **** OPEN DISK COMMAND CHANNEL **** ; @LDA cmdchn,# ;+K @CLC ;+K @JSR K$close ;+K @LDA cmdchn,# ;+K @LDX 8,# ;+K @TAY ;+K @JSR K$setlfs ;+K @LDA 0,# ;+K @TAX ;+ 10 jrnc side$0 mvi a,11 ; or 11 to 20 side$0: add l ; get sector # (0-9) sta VIC$sect mov a,c ; get trk # (0 to 159) rar ; divide by 2 (carry was cleared) sta VIC$trk jmp read$sector ; read the sector to the buffer DIR$PTRS: save block buffer adr for ret lhld ld$blk$ptr ; get the current block pointer mov e,m ; get LSB of block pointer inx h ; advance pointer mov d,m ; zero MSB of block pointer inx h shld ld$blk$ptr xchg ; get block number to HL ; ; GE F$cmd$buf: F$rd$count: db 2 ; 5 F$rd$sect: db 0 ; 4 filled in F$rd$trk: db 0 ; 3 filled in F$cmd: db 0 ; 2 read=0 db '0' U0PT: db 'U' ; 1 Fcmd$lng equ $-F$cmd$buf db '0',4Ch,0 ; reset disk change status (open) bios$size equ $-bios1,y ;+K @jsr K$chrout ;+K @dey ;+K @bne sendf$rd ;+K @jsr K$clrchn ;+K @bit D1ICR ;+K @ldx F$rd$count+BZ ;+K rd$sect: @sei ;+K @jsr rd$byte+BZ ;+K @and 0eh,# ;+K mask off error bits @bne fst$error ;+K @ldy 0,# ;+K start indexK @JSR K$set$bnk ;+K @LDA 4,# ;+K @LDX low(U0PT+BZ),# ;+K @LDY high(U0PT+BZ),# ;+K @JSR K$setnam ;+K @JSR K$open ;+K @bcs misdsk @jsr K$readst @ROL A ;+K GET MSB TO CARRY @BCS MISDSK ;+K DEVICE MISSING IF CARRY SET @rts dw 0,1 page ; ; ; **** THIS IS THE COMMAND LOOP **** ; BZ equ bios$02-$ ; BIOS BIAS ; bios$65$code: @sei @lda 0,# ;-K @sta vic$data ;-K @JSR VICIO+BZ ;-K go find and do requested operation CMDLP: @sei @lda 3eh,# ;?K set up Zread the block pointed to by the HL ; into the data buffer ; dad h ; 2X (1k blocks) dad h ; 4x (512 byte blocks) push h call read$1K+ZZ ; read 1st 1K block lda @dma+1 adi 4 sta @dma+1 pop h inx h inx h call read$1K+ZZ ; read 2$65$code loader$size equ $-loader$start if loader$size > 2048 ' loader size error' endif endif page endofcode: ramalc set endofcode define top$choice,1 ; top row of these choices define bottom$choice,1 ; bottom row of these choicefcb+0 ;disk name fcbfn equ fcb+1 ;file name fcbft equ fcb+9 ;disk file type (3 characters) fcbrl equ fcb+12 ;file's current reel number fcbrc equ fcb+15 ;file's record count (0 to 128) fcbcr equ fcb+32 ;current (next) record number (0 to 127) fcbln e0 jmp bdos call$msg: db cr,lf,'**** CALLVERS **** $' curvers db 0 end  to place a new Loader on the 1581 system track). s define current$choice,1 ; current row of these choices define fmt$drv,1 ; drive to do format on define fmt$tbl$ptr,2 ; pointer to current format table define save$buffer,80*2 ; save a row here define scrsiz,1 ; current screen size flag define tequ fcb+33 ;fcb length ; ; set up stack lxi h,0 dad sp ; entry stack pointer in hl from the ccp shld oldsp ; set sp to local stack area (restored at finis) lxi sp,stktop ; read and print successive buffers call setup ;set up input file cpi e USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Thmp,1 ; miscellaneous define temp$ptr,2 ; temporary ptr for moving tables define read$count,1 ; # of characters in saved line define top$of$stack,300 define stack,0 define sect$buf,1024 ; largest sector is 1024 end 255 ;255 if file not present jnz openok ;skip if open is ok ; ; file not there, give error message and return lxi d,opnmsg call err jmp finis ;to return ; openok: ;open operation ok, set buffer index to end mvi a,80h sta ibp ;set buffer poi; Dump program, reads input file and displays hex data ; org 100h bdos equ 0005h ;dos entry point cons equ 1 ;read console typef equ 2 ;type function printf equ 9 ;buffer print entry brkf equ 11 ;break key function (true if char ready) openf equ 1 ; CALLVERS program bdos equ 5 ; entry point for BDOS prtstr equ 9 ; print string function vers equ 12 ; get version function cr equ 0dh ; carriage return lf equ 0ah ; line feed org 100h mvi d,5 ; Perform 5 times loop: push d ;nter to 80h ; hl contains next address to print lxi h,0 ;start with 0000 ; gloop: push h ;save line position call gnb pop h ;recall line position jc finis ;carry set by gnb if end file mov b,a ; print hex values ; check for line fold mov5 ;file open readf equ 20 ;read function ; fcb equ 5ch ;file control block address buff equ 80h ;input disk buffer address ; ; non graphic characters cr equ 0dh ;carriage return lf equ 0ah ;line feed ; ; file control block definitions fcbdn equ save counter mvi c,prtstr lxi d,call$msg ; print call message call bdos mvi c,vers call bdos ; try to get version # ; CALLVERS will intercept mov a,l sta curvers pop d dcr d ; decrement counter jnz loop mvi c, a,l ani 0fh ;check low 4 bits jnz nonum ; print line number call crlf ; ; check for break key call break ; accum lsb = 1 if character ready rrc ;into carry jc finis ;don't print any more ; mov a,h call phex mov a,l call phex nont test$msg: db cr,lf,'**** ECHOVERS **** $' ret$stack: dw 0 ds 32 ; 16 level stack loc$stack: end to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Th; variable area ibp: ds 2 ;input buffer pointer oldsp: ds 2 ;entry sp value from ccp ; ; stack area ds 64 ;reserve 32 level stack stktop: ; end uffer function call bdos ret ; ; gnb: ;get next byte lda ibp cpi 80h jnz g0 ; read another buffer ; ; call diskr ora a ;zero value if read ok jz g0 ;for another byte ; end of data, return with carry set for eof stc ret ; g0: ;rum: inx h ;to next line number mvi a,' ' call pchar mov a,b call phex jmp gloop ; finis: ; end of dump call crlf lhld oldsp sphl ; stack pointer contains ccp's stack location ret ;to the ccp ; ; ; subroutines ; break: ;check b;*************************************************** ;* * ;* sample random access program for cp/m 3 * ;* * ;*************************************** ; ECHOVERS RSX pstring equ 9 ; string print function cr equ 0dh lf equ 0ah ; ; RSX PREFIX STRUCTURE ; db 0,0,0,0,0,0 ; room for serial number jmp ftest ; begin of program next db 0c3H ; jump dw 0 ; next module in line prevead the byte at buff+reg a mov e,a ;ls byte of buffer index mvi d,0 ;double precision index to de inr a ;index=index+1 sta ibp ;back to memory ; pointer is incremented ; save the current file address lxi h,buff dad d ; absolute character addreak key (actually any key will do) push h! push d! push b; environment saved mvi c,brkf call bdos pop b! pop d! pop h; environment restored ret ; pchar: ;print a character push h! push d! push b; saved mvi c,typef mov e,a call bdos p************ org 100h ;base of tpa ; reboot equ 0000h ;system reboot bdos equ 0005h ;bdos entry point ; coninp equ 1 ;console input function conout equ 2 ;console output function pstring equ : dw 0 ; previous module remov: db 0ffh ; remove flag set nonbnk: db 0 db 'ECHOVERS' space: ds 3 ftest: ; is this function 12? mov a,c cpi 12 jz begin ; yes - intercept jmp next ; some other function begin: lxress is in hl mov a,m ; byte is in the accumulator ora a ;reset carry bit ret ; setup: ;set up file ; open the file for input xra a ;zero to accum sta fcbcr ;clear current record ; lxi d,fcb mvi c,openf call bdos ; 255 in accum if opop b! pop d! pop h; restored ret ; crlf: mvi a,cr call pchar mvi a,lf call pchar ret ; ; pnib: ;print nibble in reg a ani 0fh ;low 4 bits cpi 10 jnc p10 ; less than or equal to 9 adi '0' jmp prn ; ; greater or equal to 10 p109 ;print string until '$' rstring equ 10 ;read console buffer version equ 12 ;return version number openf equ 15 ;file open function closef equ 16 ;close function makef equ 22 ;make file functioni h,0 dad sp ;save stack shld ret$stack lxi sp,loc$stack mvi c,pstring lxi d,test$msg ; print message call next ; call BDOS lhld ret$stack ; restore user stack sphl lxi h,0031h ; return version number = 0031h reen error ret ; diskr: ;read disk file record push h! push d! push b lxi d,fcb mvi c,readf call bdos pop b! pop d! pop h ret ; ; fixed message area signon: db 'file dump version 2.0$' opnmsg: db cr,lf,'no input file present on disk$' : adi 'a' - 10 prn: call pchar ret ; phex: ;print hex char in reg a push psw rrc rrc rrc rrc call pnib ;print nibble pop psw call pnib ret ; err: ;print error message ; d,e addresses message ending with "$" mvi c,printf ;print b readr equ 33 ;read random writer equ 34 ;write random wrtrzf equ 40 ;write random zero fill parsef equ 152 ;parse function ; fcb equ 005ch ;default file control block ranrec equ fcb+33 ;random record positiracters lxi h,buff ;destination rloop1: ;read next character to buff push b ;save counter push h ;next destination call getchr ;character to a pop h ;restore counter mov m,a inx h ;next to fill dcr c ;counter goes down jnz rloop ;end of buffer? erloop: ; end of read loop, store 00 mvi m,0 ; ; write the record to selected record numbebecomes 0 jz error ;error message, retry jmp reboot ;back to ccp ; ;*************************************************** ;* * ;* end of quit command, process write jnz ready ; ; cannot open file, so create it mvi c,makef lxi d,fcb call bdos inr a ;err 255 becomes zero jnz ready ; ; cannot create file, directory full on ranovf equ fcb+35 ;high order (overflow) byte buff equ 0080h ;buffer address ; cr equ 0dh ;carriage return lf equ 0ah ;line feed ; ;*************************************************** ;* pop b ;restore next to fill cpi cr ;end of line? jz erloop1 ; not end, store character mov m,a inx h ;next to fill dcr c ;counter goes down jnz r mvi c,writer lxi d,fcb call bdos ora a ;error code zero? jnz error ;message if not jmp ready ;for another record ; ; ;********************************************** * ;* * ;*************************************************** notq: ; not the quit command, random write? cpi 'W' jnz notw ; ; this is a random write, fill buffer u lxi d,nospace call print jmp reboot ;back to ccp ; ;*************************************************** ;* * ;* loop back to "ready" after each command * ;* * ;* load SP, set-up file for random access * ;* * ;*************************************************** lxi sp,stack ; ; version 3.1? m rloop1 ;end of buffer? erloop1: ; end of read loop, store 00 mvi m,0 ; ; write the record to selected record number mvi c,wrtrzf lxi d,fcb call bdos ora a ;error code********** ;* * ;* end of write command, process write random zero fill * ;* * ;******************************************************** notw: ;ntil cr lxi d,datmsg call print ;data prompt mvi c,127 ;up to 127 characters lxi h,buff ;destination rloop: ;read next character to buff push b ;save counter push h * ;*************************************************** ; ready: ; file is ready for processing ; call readcom ;read next command shld ranrec ;store input record# lxi vi c,version call bdos cpi 31h ;version 3.1 or better? jnc versok ; bad version, message and go back lxi d,badver call print jmp reboot ; versok: ; correct zero? jnz error ;message if not jmp ready ;for another record ; ;*************************************************** ;* * ;* end of write commands, process read not the quit command, random write zero fill? cpi 'F' jnz notf ; ; this is a random write, fill buffer until cr lxi d,datmsg call print ;data prompt mvi c,127 ;up to 127 cha ;next destination call getchr ;character to a pop h ;restore counter pop b ;restore next to fill cpi cr ;end of line? jz erloop ; not end, store character h,ranovf mov m,c ;set ranrec high byte cpi 'Q' ;quit? jnz notq ; ; quit processing, close file mvi c,closef lxi d,fcb call bdos inr a ;err 255 version for random access mvi c,openf ;open default fcb rdname: lda fcb+1 cpi ' ' jnz opfile lxi d,entmsg call print call parse jmp versok opfile: lxi d,fcb call bdos inr a ;err 255 becomes zero * ;* * ;*************************************************** notf: ; not a write command, read record? cpi 'R' jnz error ;skip if not ; ; read random record * ;* fixed and variable data area * ;* * ;*************************************************** conbuf: db conlen ;length of console buffer consiz: ds 1 ;resulting size b pop b adc b pop b ;+digit mov c,b mvi b,0 dad b aci 0 mov c,a jnc readc jmp readcom endrd: ; end of read, restore value in a adi '0' ;command cpi 'a' ;translate case? rcd by de until $ push d call crlf pop d ;new line mvi c,pstring call bdos ;print the string ret ; readcom: ;read the next command line to the conbuf lxi ******** ; error: lxi d,errmsg call print jmp ready ; ;*************************************************** ;* * ;* utility subroutines for console i/o * mvi c,readr lxi d,fcb call bdos ora a ;return code 00? jnz error ; ; read was successful, write to console call crlf ;new line mvi c,128 ;max 128 characteafter read conlin: ds 32 ;length 32 buffer conlen equ $-consiz ; pfncb: dw conlin dw fcb ; ds 32 ;16 level stack stack: end  ; lower case, mask lower case bits ani 101$1111b ret ;return with value in chl ; ;*************************************************** ;* * ;* string data area for console med,prompt call print ;command? mvi c,rstring lxi d,conbuf call bdos ;read command line ; command line is present, scan it mvi c,0 ;start with 00 lxi h,0 ; 0000 ;* * ;*************************************************** getchr: ;read next console character to a mvi c,coninp call bdos ret ; putchr: ;write characrs lxi h,buff ;next to get wloop: mov a,m ;next character inx h ;next to get ani 7fh ;mask parity jz ready ;for another command if 00 push b ;save countere USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Thssages * ;* * ;*************************************************** badver: db 'sorry, you need cp/m version 3$' nospace: db 'no directory space$' datmsg: db lxi d,conlin;command line readc: ldax d ;next command character inx d ;to next command position ora a ;cannot be end of command rz ; not zero, numeric? sui '0' cpter from a to console mvi c,conout mov e,a ;character to send call bdos ;send character ret ; crlf: ;send carriage return line feed mvi a,cr ;carriage return call push h ;save next to get cpi ' ' ;graphic? cnc putchr ;skip output if not pop h pop b dcr c ;count=count-1 jnz wloop jmp ready ; ;*** 'type data: $' errmsg: db 'error, try again.$' prompt: db 'next command? $' entmsg: db 'enter filename: $' ; ;*************************************************** ;* i 10 ;carry if numeric jnc endrd ; add-in next digit push psw mov a,c ;value = ahl dad h adc a ;*2 push a ;save value * 2 push h dad h ;*4 adc a dad h ;*8 adc a pop b ;*2 + *8 = *10 dadputchr mvi a,lf ;line feed call putchr ret ; parse: ;read and parse filespec lxi d,conbuf mvi c,rstring call bdos lxi d,pfncb mvi c,parsef call bdos ret ; print: ;print the buffer addresse************************************************ ;* * ;* end of read command, all errors end-up here * ;* * ;*******************************************e) blocks lhld buffer$keys mov a,l push h put CPM ; key definition adr (low) pop h mov a,h put CPM ; Key definition adr (high) ; ; only move 256 bytes total (128 bytes info, 128 message) ; mvi b,256-6-6 ; number of bytes leftbuffer$keys mov a,l sub e mov l,a mov a,h sbb d mov h,a mov a,l ora a jz keys$size$ok inr h keys$size$ok: mov a,h sta keys$size cpi (1024/256)+1 jnc size$error ret page ;; ;; ;; add$vectors: mvi b,6 ; use firsmov a,h sta bios$addr cma mov h,a inr h ; two's comp of start adr lxi d,buffer$bios$8502 dad d shld bias pop h call finish$load hex$load: jc done$bios8502 ; done when carry set call load$record jmp hex$load done$bios$8502: ointers lxi h,inst$key$msg call disp$loop call insert$key$defs ; add FUNCTION KEYS and KEY definition lxi h,inst$cpm$msg call disp$loop call finish$rest ; transfer rest of system over lxi h,inst$bios$msg call disp$loop call add$bi to move get$2nd: push b ; read in the header info GET CPM3 PUT CPM pop b dcr b jnz get$2nd ret page ;; ;; add FUNCTION KEYS and KEY definition ;; insert$key$defs: lxi h,buffer$keys+2 ; 1st two bytes point to the ; ..kt 6 bytes of old header get$1st: push b ; read in the header info GET CPM3 PUT CPM pop b dcr b jnz get$1st ; remove next six bytes from old header get CPM3 ; bios8502 top page # get CPM3 ; bios8502 # of blocks (256 bytes) getlhld hex$addr ; get last address lxi d,buffer$bios$8502 mov a,l sub e mov l,a mov a,h sbb d mov h,a mov a,l ora a jz size$ok inr h size$ok: mov a,h sta bios$size cpi 4096/256 jnc size$error ret page load$keys: mos$8502 ; save bios8502 to CP/M file lxi h,closing$msg call disp$loop finis CPM jmp 0 ; exit back to CP/M page load$bios$msg: db 'Loading 8502 BIOS .HEX file',cr,lf,0 load$key$msg: db 'Loading Key definition .HEX file',cr,lf,0 ey definition insert$keys$loop: mvi c,0 ; save 256 bytes call save$loop lda keys$size dcr a sta keys$size jnz insert$keys$loop ret ;; ;; transfer rest of system over ;; finish$rest: get CPM3 ; save CPM3.SYS to CPM.SYS rz CPM3 ; KEYS bottom page # (function key adr) get CPM3 ; KEYS # of blocks (256 bytes) get CPM3 ; key definition adr (low) get CPM3 ; key definition adr (high) lda bios$size ; install load info into header mov b,a lda bios$addr avi a,-1 sta file$num ; use KEYS file for HEX input call read$header ; get KEYS start adr mov a,l ; LSB should be zero ora a jnz adr$error push h mov a,h sta keys$addr cma mov h,a inr h ; two's comp of start adr lxi d,buffer$ add$vect$msg: db 'Adding new vectors to CPM+.SYS',cr,lf,0 inst$key$msg: db 'Adding Key def. to CPM+.SYS',cr,lf,0 inst$cpm$msg: db 'Adding CPM3.SYS to CPM+.SYS',cr,lf,0 inst$bios$msg: db 'Adding BIOS8502 to CPM+.SYS',cr,lf,0 closing$msg title 'Add bios8502 to CPM3.SYS file 2 June 85' maclib seqio lxi sp,stack call disp$sign$on FILE outfile,CPM,,CPM+,SYS,16*1024 FILE infile,CPM3,,CPM3,SYS,4*1024 FILE infile,BIOS8502,,1,HEX,1024 FILE infile,KEYS,,CXKYCODE,HEX,1024 put CPM jmp finish$rest page ;; ;; ;; add$bios$8502: lda bios$size mov h,a mvi l,0 lxi d,buffer$bios$8502 xchg dad d ; HL=next free address DE=size mov a,d ; number of 256 byte blocks add a ; number of 128 byte blocks modd b put CPM ; bios8502 top page # mov a,b put CPM ; bios8502 # of (256 byte) blocks ; ; install MSG tbl and FUN tbl pointers ; lda keys$addr put CPM ; function key start adr (high only) lda keys$size put CPM ; KEYS # of (256 bytkeys dad d shld bias pop h call finish$load hex$load$keys: jc done$keys ; done when carry set call load$record jmp hex$load$keys done$keys: lhld hex$addr ; get last address dcx h dcx h ; two byte header for key def adr lxi d,: db 'Closing CPM+.SYS file',cr,lf,lf,lf,0 page ;; ;; ;; load$bios$8502: xra a sta file$num ; use bios8502 file for HEX input call read$header ; get BIOS8502 start adr mov a,l ; LSB should be zero ora a jnz adr$error push h lxi h,load$bios$msg call disp$loop call load$bios$8502 ; load hex file to buffer lxi h,load$key$msg call disp$loop call load$keys ; load hex file to buffer lxi h,add$vect$msg call disp$loop call add$vectors ; add the new vector pv d,a ; save count in D save$next: lxi b,-128 dad b ; back up the pointer push h push d call save$128$bytes pop d pop h dcr d jnz save$next ret ; ; ; save$128$bytes: mvi c,128 save$loop mov a,m push h put CPM pop he USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> ThFile can NOT be larger than 4K',cr,lf,0 keys$size: ds 1 keys$addr: ds 1 bios$size: ds 1 bios$addr: ds 1 bias: ds 2 hex$count: ds 1 hex$addr: ds 2 hex$sum: ds 1 file$num: ds 1 buffer$bios$8502: ds 4096 buffer$keys: ds 1024+2 dnx h push h PUT CON pop h jmp disp$loop message: db cr,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf db ' This program will create a CPM+.SYS file from',cr,lf db ' The CPM3.SYS file (created by GENCPM) and',cr,lf db ' The 6502hexadecimal value rlc rlc rlc rlc ; move to upper 4 bits push psw call read$hex$val ; get a hexadecimal value mov b,a pop psw ora b ; make a data byte from two hex digits mov b,a lda hex$sum ; add to sum add b sta hex$sum inx h dcr c jnz save$loop ret page ; ; ; load$record: call read$header ; record adr in HL finish$load: xchg lda hex$count cpi 0+1 ; see if length=0 stc ; set END OF FILE rz ; null record marks the end lhld bias s 60 stack: buffers equ stack end nter filename: $' ; ;*************************************************** ;* BIOS File supplied in Intel HEX format',cr,lf db ' And CXKYCODE File supplied in Intel HEX format',cr,lf db ' (1st HEX address is FUNCTION table address)',cr,lf db ' (1st two bytes point to ASCII table)',cr,lf db lf,lf db ' mov a,b ; return byte value ret read$hex$val: call get$upper ; force to upper case mov b,a sui '0' ; remove number bias jm hex$error cpi 9+1 ; return if a number rc sui 'A'-'0' ; remover extra if A to F jm hex$error adi 10dad d shld hex$addr call read$byte ; this byte should be a zero ana a jnz hex$error hex$record$read: lda hex$count dcr a sta hex$count jz hex$record$done call read$byte lhld hex$addr mov m,a inx h shld hex$addr jmp hex$recor* ;* fixed and variable data area * ;* * ;*************************************************** conbuf: db conlen ;length of console buffer consiz: ds 1 ;resulting size The ROM boot code will load the CPM+.SYS file',cr,lf,lf db 0 hex$mess: db 'HEX file error - first record must be start adr and',cr,lf db ' last record must contain the last adr' db cr,lf db ' All other addr cpi 0fh+1 rc ; return if valid hex number (0-F) hex$error: lxi h,hex$mess jmp dsp$and$exit get$upper: call read$hex$byte jz hex$error cpi 'a' rc ani 5fh ret read$hex$byte: lda file$num ora a jz read$hex$fst get KEYSd$read hex$record$done: call read$byte lda hex$sum ana a ; clears carry (marks end of record) jnz hex$error ret read$header: xra a sta hex$sum call read$hex$byte ; get input character jz hex$error ; missing char is a proafter read conlin: ds 32 ;length 32 buffer conlen equ $-consiz ; pfncb: dw conlin dw fcb ; ds 32 ;16 level stack stack: end ess must be between',cr,lf db ' the start and end adr',cr,lf db ' also HEX file must be ended with a NULL record',cr,lf,lf db ' and ' adr$mess: db 'Start address must be on a page boundary',cr,lf,lf db ' and ' size$mess: db ' ret read$hex$fst: get BIOS8502 ret adr$error: lxi h,adr$mess jmp dsp$and$exit size$error: lxi h,size$mess dsp$and$exit: call disp$loop jmp 0 page disp$sign$on: lxi h,message disp$loop: mov a,m ora a rz iblem cpi ':' jnz read$header call read$byte ; get record length inr a sta hex$count call read$byte ; get high address mov h,a push h call read$byte ; get low address pop h mov l,a ret read$byte: call read$hex$val ; get a P'!5^!/~ !~620͕%2.|z}z> u!.~w:.W=*u!.4C*V0^#V"V0ý!.5¯:20͕%!^4!/w>R͘%>V͘%>Dý>Pý>Lý>Oý>Bý>Sý>N͘%*6".~ 6nLT` 'd ! ^#V#*0}o|g*  ":D x=D y0P 2!0^4! 0q :0Ė: 0,; Ė*I0m |}$† ͌oy Ԍ͋ 8O͖ Ăy01y 1m X:0 : 0, >C͘%:0 : 0 v;:0:0!4 :0& : 0::0!xI !4̨ e ::̮>͞ } !~5:Į ͵ !4̨!~5 G!~Ҩ4_!p!~ʮ5^!~> >2\0:0N *K0"+"X0:0 >''!::0 : 0 -Ͳ !/6+:.;?*$/*."$/?"$/:.l*.^#V{r+s5*.^#V ʓ:. r+s!06#wÚ> 209!e/~6![0~6".~,#!0w9 9*.~6 *: 0,Ĵ2f/*.s#r2( COPYRIGHT (C) 1977 DIGITAL RESEARCH 112O02Z0̀%!"K2.>2.*M0"$/̓%!"":g0i!"P0"R0"2:0v: 0$  :[0-ʬ+ʬ* :[0!_0M!f0P p  !   :O0Ĝ!":O0-!2~B6~44O!! s#r!1~ _6^4! w!p!2~~!55N!! N#fiooo&)^#fk9BIO[ov ͌z{>ɯo>g͌"!6ů{_zW5> : 0 v-!v !v-ʹ {ozg:.7ͮ2Z0!O0~4l!"*|>"V0*""J͊!/6 !/͒%:^0ʏ>2.͡%ͱ*K0*T0&*M0*T0&\ ͍!/w#õH USE FACTOR !/͒%*"P0Þ%z{*P0"R0*"V0 !":O0N : 0,N :0 >  > !0N#~' ) > ''*K0"V0:\0x ʹ:\0" m }*K0"+"X0''*K0"V0>"4ͬ:2T/:[0 “ 2/-*M0"$/*X0!{#zڿ ~+"X0*M0+"M0wß #"K0*M0".:\0 N]T s#r+*V0*{_zW".:\02.R  [02e/*.#"X0$<5ͬ*$/"M00:T/2:/2[0 v>20*.".2[0v*R0m "R0͍"R0!/w >=G*R0*I0"R0"R0 m :/ }>͞ ¥͢ :O0*V0*ʿ͜">2:O0:0:O0!!4:0: 0,*V0}|<r ͪ*|Ĵ:O0_͑H *V0"Ù*V0"E V» ͪ»**»"Ù*K0"X0!0NA#~' ~p"K0*K0N"X0!0q#*w œ:0!x ͜ *V0*R0:_0̍"V02*M0r; !:r )D*OxG !?DM!xGyO23)#͌)=R|g}o=^͌͌roz{͉͌͌}|͉͌Þ͌Þ͌ë͉͌!!o#Ã͌zg{o͌zg{o͌zg{0Ģ*R0̜*R0ĜG:O0xě%:/ *R0̍:xz*P0#"P0E2D20:b!^4!/wjj*R0!6zz{z4A_A?ɯ2.2*T0"V0!.8w# *V0*K0{zҤ*b0+"X0 =$*   % *I0:/ ͪ% ͬ:O0ĭ%  :.ʢ :0¢ *K0+"X0!2<20*#"" : 00Ĩ!??" 09"K0+"X0$< :0¢ : 0,? ʹ  *} :]0 :O0 :0 ͤ%:e0ĭ%:0 : 0  ͬͧ%vʹ >"4:O0: 2\0:0=: 0 F!Fʹ%*X0"`0>2Z0*X0":0k: 0T!T:\0¦:O0¦:0=ʦ ʦ*"X0 !':[0'Tx»!Z04TT!Z05T:\0!":]0!**V0":O0*X0~ Ĵ*:0F: 0e%;m ">2:0b: 020 W,F:0b: 0e,ʹ:re*X0#![0~ʇww2/ͬ:2T/-"."$/2/>2.v:.ʸ!/6+͕%>20:.ʮ:.0209$<!5*}Ģ*V0":0­oolo&3:0: 0 ;!,ɯ2122=2 !"I0&q!1~\5_! ~͔D:2:/ *!"I0:/ :0:0! 0^#=ʙV¨*0!҂ :0:0& !!>O: >*X0#Þ!.*V0".#"X0$:d0<:0<! 0~?<#ʐ: 0͡!.".^#V"V0}{##~2.*.^#V#"."V0*V0}d##~<2.G*V0##"X0:.> u!.~w>w> u:.  ͺ :0: 0 !;* _!5 ^#fkS \ h n 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1X06 '>#G*I0!" :0 :Z0 !0N*K0:O0Ÿ"b0+"X0yʛ 'É' Ͳ >ͮ 222:0: 0 !ͮ-:0y: 0:yv! X! ^#fkX _~ 0^ Z   2 5 8  :0‰:0=ʉG! 0ʃF#2sÖ*I0| E2V ,[ ͊m *R0"R0"P0 m E2D2V ,ʾ ͊:/ m :/ "> 2/:Į2 yU`:10_!~0!1s! ~͔ yU!1~N=w_! ~QZP>2 ypP͘% >U̘%>: 2 3>E͘%PRNFTYPEsHEX&FTYPEB&!%w_:%M&:%M&:%M&:%M&:%M&~*~# x&> *\ ?=)$=)w#Ž&!\60 ڱ&>GO#w ³&>O # &6 &6L#6I#6B#w2|r&\u'>2]0!"%![0~2%wG&!,x&>GCALLCSEGDSEGELSEENDMHIGHIRPCLDAXLHLDNAMEPAGEPCHLPUSHREPTSHLDSPHLSTAXXCHGXTHLENDIFEXITMEXTRNLOCALMACROSTKLNTITLEINPAGEMACLIBPUBLIC7 PF FPA A A* A A A(#&&#&2#/?&#' '( v'( %:P!@"5~wN#Fq#p>BØ%!0" * F#%2NG*V0##~w*V0##~<͉:.t!.N!. yq~t +a20![0:0/ʦg¦´/ʦA¦:[0O<QA>HHR>22[0m:B_>fD> j!052!"0!0N#~#A҄0Æ7O!~*0!ʩң)Ú "0 x:[0 '¦́'æ:[0 :[0,;%:[0 !:[0; ,óf:.O*.~H:.=!4>͕%0:/#". ͆%2G:0xa{_ ʇ ʇ:0x҇_<20!/w:e/S:e/9ɯ2f/2d/2e/:0:e/ !2f/g/~#»S͉!f/~4!g/_:e/w2e/ɯ<*V0"3682%2%!"b0*"M0!1"%"&"@&#"K0"T0' _#~6' D':%A6'>:6'D'>.6'D'>-6'x&!,N'!k-x&!,N':% '> ':%'_!% '6 4ɯ2%2]02e02d02g02%:\<& #*)&# PP%27&#(&#  $ %*%"$  NZZ NCC POPEP M x#_BH!™# 0#³# £#{ڽ#KÅ#CÅ#<: 0 JCR:0 $# $! 06 p#! 0$#!0^*K0"V0*M0{z"K0!N"O1#w#w*V0!NN*O N#Fr+sq#p0U>G=#w#wY*M0!0n& {ozg"V0!K0{#z"M0b*M0!0N#yʢ ~Õb!."O1:N *M0!$/{#z"V0$ _!.*V0~#~1 ~#"M0û1 !͒%Þ%SYMB202́/>20:[02́:0G:0::0l:[0'́:[0' 20/:[0'|>20^—́:[0  <¨!~4 >¼!~5 : >20>V>O>I>B͘%*"V0ɯ2!4!f/6".!f/~55!d/^4!g/~f:.:e/JGwf^l͗^{:e/&{!f/4#ww&ʞGʱ2e/xf͗ :e/&ʕ:0  ý͗&{&{ý͗  !e/~&>62/-!.6*M0"$/B".2f/*"V0͗ 2f/2e/2[020 =)!%w#w#w#w#w#w#>2^02_0:m$(!~#$,(~(# 3(%Aʩ(Pʩ(Sʩ(Hʩ(Lʩ(*t(+t(-¶(^0~Sʣ(Mʣ(e0Lʣ(d0Qʣ(g0Rʣ(%1¶(x#3(~AҶ(#3(#6 !)-x&!x&!%͉&!%͉&ͳ'(`&͛'͠':%)!&͉&l&͛' # ɯ<:0O=_^$!"F!!V#fjQ̀#G$2!!!^#Vo&)O~#F##xGyѯ?; ><>; ;<=R>>>F>;>G==<==>=s;=P=*>=$?P:-?]>*<<==<;=>>y> ;:> 2͕%>20ɯ202!0~@$6^4#:[0w~$w:[00 6:[0A:[0?e@eAɷP6 o2[0:Z0ʦ:\0 :O0¦:[0':[0 !20:[0 R;/>20:Z0?:\0:O0?́;B*`0*X0++{z~ ͠'!%60#60#60#>2f0!"&:O0*!"%2%2%2%Z&%u'!-x&z{:]0ʢ)*%F)w)!"%r&\‰)*%#"%+~):.2]0ʢ)r&\!~-N'*%F))Z&!"%*%B&%)¼))*)6# )G&*%*%#"%~0000000000000000000@@@@@@@@@@@@@@@@AA AAQQQ"Q'Q,Q1Q6a?>P?<=?>>=<<i;m=>c==>o>v<=<;8?N!Nw#w#W!"V0!.w#w#l2N!.~4^!.~w!.ͼ!.ͼ!.ͼ!/~w!$/ͼ!D/~w!T/~wN#Fp+q!.~^!.!. !. !. !/!$/ !D/!T/++!+"X0:Z02Z0́ͪ'2Z0X:[0*K: ḰͪX? X́ö20Pg>ã6r>ã:[0'ƒ2[0>ã ¡:.ʔ>+2/͕%!/6 >20>20:[02́:0:Z0: 0=!EQ<!LT:[0=!LE>!GT:[0=!GE2[0" 0!04!<-x&G:%7*$*x*7*x2*Ϳ'5*9**&*&w#"&!F)`&!"&*&%~ʅ*B&Œ*`*G&`*!S-x&ö,͟**>&*@&w#">&!F)l&!">&*@&&`*_!%~ - :)5%͉}*5" +"%5ͫ%ͫ%*5"#5>@:2(4:(5 H 23y"*5"3*%5! {#zt ~+"%5*5+"5wT #"5*5"3:)5ʑ N]T s#r+*#5* {_zW"3:)52v3 > > >2 5n2"5 %: 5*#5* 5"#5*55%"#5:5KBn2: 5O0>=n2*5~2%! 5%~2͉:K4 v }>v S M:5p*#5*gu>%"u> %2 :5O%:4©:5[%! 4:4©:4,ʀ>:5: O%% 2)5:4:4 !*%5"-5>2'5*%5"R"A*5"%5!4NA#~ͫ% p"5*5N"%5!4q#͢%w 3:4(x *#5:,5o"#5V%2*5Ô; !:V :4:4{%͉"">2!:4:424*o,kÊo:4:4{,ʊ: ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0L*2%*b0}!,~ +*#+> *>#**> **b0~>+*#2+> *> *> *}2%!%*O*:/ :O0:%y*:%!O0•+:e0!]0+~,:/ ,!/~ +:f0,:/++:_0,+:/#,:/ ,:_0=+!/~ +!0s!%~!%*4:0!/,G~Y+!*", ++ *5:K4 0@:5Ĩ/ú>2) :u3ʭ :4­ *5+"%5[%2!<24*$#"$""*:40!??"4͋$"5+"%5͇%ͩ$+:4­ :4,J "*} :*5 :5%:4 +:25Ĩ/:4 :4  @&:4:4(:)5N:5N:4=N N*&"%52)ͫ%:(5ī%x;c!'54!'55:)5ž!":*5ʍ!5%Ù*5%*#5":5*%5~ *%56 ͫ%<͉:K4 "5~2o M%(>@%>#*55%!".!/k*%5#!(5~́ w23@:2(4y""3"323>2v3 :u3L!P46+(0>24:u3:v3"U24͋$͇%ͩ$!5*}*#5":4:4: =X!^#fk:Vj&AW y ~   8 ; C :4:4=e USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Th#x=+> Y+> Y+20!/>x6 #=,G!/~ pͳ'*&}?,>*/,`&%͈':^0*+,!&6S#6Y#6M#w!&w:%2%!"&ͳ'*2%`&%͛'͠'+,:%ʶ,:%.*P0"%.*>&}ʶ,>͕*æ,:%,l&&͈'!-x&CP/M MACRO ASSEM 2.0 NO SOURCE FILE PRESENT NS+ >2):4„ ͣ#v#: :5$:)%k %G I k :)%:)c %k %+:4„ :4, " :4 :4/ :4 :5 $*#5^#V*S"s#r*5*#5s#r+"5 |#v#*#5" 5:4 :4/ !"5:55",:4M:'5M*,~#T :5T !4N*5*,s#r+"%5yP  ͫ%> ͫ%%g >v % 222:4¦ :4 – ì !ʬ ¦ À :4:4€ ( :4 :4:€ :4€ (€ € x !4À G!4F#I ,*5͘EIr,o͉n2"5~2 r,Yo :K4 ͉:K4 " : 52> 2K4::4M:4 Mg %U!P46+:v3Ϳ$ý*3*3"3Ϳ$"3½:v3*3^#V{ʽè COPYRIGHT (C) 1980 DIGITAL RESEARCH @: 5@%nLT`15252'5h+U"!""*"5j"2u3>2v3*5"3-ͩ-:5Z!""$"5"5"5"5"5" " O DIRECTORY SPACE SOURCE FILE NAME ERROR INVALID PARAMETER: SOURCE FILE READ ERROR OUTPUT FILE WRITE ERROR CANNOT CLOSE FILES UNBALANCED MACRO LIB END OF ASSEMBLY G:%x-!%~--.-*P0*%O {-z-.*P0"%!%^4!%w.ͷ> %AB,#*#5 :4:4 !;*M_!Q^#fkox Iͻ8ʗy0IͻGͰͻHIͻ(yIͰͻͻy0 :€ :>S %2 !~5€ :%j B !4À € !~5€ úG!~4_!p!~5^!~>À >2)5:4 *5" +"%5:4ڥ >ͫ%ͫ%[%:4 :4, V :4  + !4N#~ͫ% > ͫ%ͫ%*5"#5:)5r+s*3^#V ʽ-:v3:r+s!46#w4> 24͋$í!94~6!(5~6"3~,_#!4w͋$ÏV *3o6͋$*3~6 Þ*3:4,"3~ š62:4*3s#r2(5294*3#"%5͇%ͩ$@*3"5":(42:32(5Ģ >24*3"32(5 ͉r!Q4wM522>2 5:4 b:4$M:(5-C+C*M:(5!,5M[!35PMp%M(ʡͣ#v#ƒ$:5}% }!"&:5ʦ>%*#5}| V AX*|:5(#$*#5"A*#5"&#v#% RØV AR*&*.WƐ'@'Õ*>:͕*!%^Ww*%{-|-}--{?.!%~#-6.-> ͕*> ͕*͞*> ͞*wsͻIH'd ! ^#V#*"0}o|gF 9"":!`x=`y0l2!!4^4!4q/:4:4,; *5͉: 5ª|}$ªo͕Ͱ8Oͻy0H͕H͉: 5në:4:4,>C0 "4 :(5 5!'':(5 :(5,;%:(5 !:(5; ,J242Z$ l ` / ‰ >24#!:(52S:4; ¡ :4/!:Z/!)!:4 :(5'#!R:(5'z 24É :(5' >24#!^ :(5 #! #!;!)!<!!Z~4z !͜,!:4~*4!;4_:94w]294ɯ<*#5"W͉#4#*W"#5ɯ2[![4Y5!!:46"3!:4~q5!84^4!;4~â:u3:94†G³]âʻ^¨^·:94&·!:44#wó&G294xâG:94&:4G/G&ʷ/&ʷG/G!94~&o*p"rOxKxGyKxGy0KG*p*r}|K\\z{W¢Ü}|ڜâWʜllyWœâ!!#Qzg{ozg{ozg{ol&:oO:n2m*p" 52n2ox:4@B%GFB>%%O0*#5##~<##ò*#5"|3#"%5͇%:15^:4^!4~?^#ʲ:4͆!~3"z3^#V"#5}ʝ##~2v32w322(!~38w# ͖!~3"z3>2y3*z3^#V#"z3"#5*#5}:4M:4  ;C:4#:4 ! #! #{ozgBB**}j!]~ } #ymy>2(>2v3͖*5|EB"#5>%0,# ^#VÕJB*50MB*50!".*5} "#5^#V"5*.#!>!!Z~#!5z #!:Z#!G )!Rz >24>VG!>OG!>IG!>BG!0>623y"!v36*5"3$"32:4*W"#5GJ2:42942(524> 2S(0>24ɯ242T!4~@`65!^4#:(5O:4yD(w~$w:(50 |:(5D(A:(5?ʱ@ʱD(Aɷ͙| ;!Cͻ2(5:'5:)5:5:(5ͫ%:(5 !:4 ;!,ɯ2t2u2 52o=20!"5" 52m{!t~Q5_!1~9:uK:K4 *E"5:U2 5*]" 5*v"#5:K4 $:4§:4KK!4^#=ʣV²*4(—ҌV :4:4V !!*/O:0ʩ##~<2x3G*#5###"%5:w37> ͺ!w3~w7>w> ͺ:w3Pd!5^!K4~ B!~624(02w3%!>%|_}_> ͺ!w3~w:x3ʜ=͢%ͺ!w34È*#5^#V"#5!y35:24(0!^4!K4w>R0>V0>D>P>L>O>B>Ss#r+".*."5:u32'5!5~4P!"*|"#5>%*5%"".o!P46 !L4*>2(>2v3͖>2(>2v3͖NB:O* 0:+5ʘ0*5*!5S*5*!5S\gr!P4w#þH USE FACTOR !M4** "5A1z{*5~2*"#5v#!P!w#w#["!"#5!U3w#w#p"!u3~#4^!v3~w!3ͷ"!3ͷ"!3ͷ"!3~w!3ͷ"!4~w!(4~wN#Fp+q!u3~#^!v3"!3#!3#!3#!3"!3#!4"!(4"5J24:(5 ʞ;{>24:'5ʋ:)5.:5‹;Ž*-5*%5++{Iz]~ T++]!]+?"%5:'52'5hͫ%2'5ä:(5*—:S —ʤË ¤24͙ʳ>|ʾ>:(5'2(5> :u3>+2P4(0!K46 >24>24:(52SR:K>20y_j:t:_!;~:!ts!1~y_!t~X=w_!1~[Kdͪ>20$y$zU0!%2m*#5"v:mP>U0%4>N0!u~ڇK6N4!E s#r!U :mw* 5!] s#r!t~ ڹ6K^4!1w!;p!u~K!5N!E ~#fo!U ~2n!] ^#V"p!":5(%! 5%n25%%%>%n2G:5x:L4 o:x_*5#"5:5ʽ*5|ʉIB0>%%O%O: 5%*55%ý:5ʽ: 5O*5*5ESS͎2O=>O͎2N=#y{~wN#Fq#p>B0!4"%*%F# #2P"*#5##~I!LTM>!GT:(5=M!GE2(5"4!44>24!(5:4ruͳ u͇:(5D(OʓQ˜>ßH©>2T2(5:SD(B¹>D> !452T!"4!4N#~#A07O!T/!~*4! )>%:m!>2m*202m!" 5/:0Kx*#5DM*5" 5}|^#V<>E0:u3ʛ*3~Œ:v3ʁ!\4>A!(0":3]#"3,ž"3Þ-2\  :4x_<24!K4w:94͜:94ɯ2:4284]294:4:94K)2:4;4~#K2oo&) ^#fkN]ivKzV{K>ɯo>g"!6ů{_zW5>)D*OxGғ !?uDM!xGyOڱò)â͝ddJ)=J|g}o=2o2#* 5* 5 "#5" 5͎21͎2=HÎ2Î20:G!^4!K4wOOn2!6z_{_4A_A?*!5"#5*#5*5{z*/5+"%5**+"%5% V%=͇%͢%*%5#þ!v3ʲ:(O! ^#V4ACP/M PLUS652AXXCHGXTHLENDIFEXITMEXTRNLOCALMACROSTKLNTITLECOMMONINPAGEMACLIBPUBLIC7 PF FPA A A* A A A(#&&#&2#/?&#' '( v'( %:P!@"<& #*)&# PP%27&#(&#  ?-$-w#+!\64 #+>GO#w %+>O # <+6 2+6L#6I#6B#w2|*\+>2*5!"B*!(5~2A*w͹*!1*>826*27*!"/5*"5!5"h*"*"*#"5"!5\, _#~ͨ+ ¶+:;*Aͨ+>:ͨ+Ͷ+>.ͨ+Ͷ+>-ͨ+*!1+j*!*-/~5/ʹ*9//͹*!2*1L/****w#"*!-*!"****/_!5*~ ͳ.27**/5}!1~ /ͳ.#/> ͳ.>#ͳ.ͅ/> ͳ.*/5~/ͳ.#/> ͳ.> ͳ.> ó  MXList WAITING FOR PRINTER $PRINTER READY $!4^*5"#5*5{z$"5!P!"Q"/$#w#w*#5!P"N*Q" "S"N#Fr+sq#p4V$>G=#w#6#w]$*5!4n& {ozg"#5!5{#z$"5f$*5!4N#yʦ$ ~Ù$f$!U3"Q"/$:P"%*5!3{#z"#5%_!U3*#5~#~&%~#$"5ÿ$&%!%*A1$ %*%"$  NZZ NCC POPEP M a{xʑ(_BH!f(4D(#ƒ( p({ڍ(KR(CR(<:4 JCR:4(ʿ((!46 4(!4(# ( ɯ<:4O=_.)!D'F!%V#fjQM()!32*!1+:=* D,> D,:D*6,_!D* W,6 4ɯ2D*2*522521528*:\ -2;*2@*O:\ʋ,=Ì,y!<*w#w#w#w#>2+52,5:m$>-!~#$ª,~>-# ʱ,<*A-P-S-R-L-*,+,-,-+5~S-M.}26*!7*è/Oͳ.:K4 :5:=*yx/:8*!5I0:25!*5—0~0:K4 0!K4~ —0:350:P4+—0:,50ʗ0:Q4#0:L4 0:,5=ʗ0!K4~ ʇ0!4s!7*~!6*Ԩ/4:4!K4ʺ0G~ 0#x=ë0> 0> 024!K4>x6 #=0G!K4~ p%,**}0>ͳ.0*j*+:+5SYMBOL TABLE OVERFLOW *#5###w*#5###~,#*#5_####&%s#r&%^#V&%##"%5F%wF%~#!4~l%6~=ͫ%ͫ%!4N#~ͫ% y%͢%͢%2P"*…-2:?*ʨ-!***ѯ2:*29* ,,!3*60#60#60#>235!"*:5ͨ/-!"f*2Q*2e**E*+!1*z{:*5G.*B*ʨ/0!s*6S#6Y#6M#w!*w:>*2=*!"*%,ʨ/26**j*կ ,,0:?*1::*Z1ͬ2L1͎2**}1}w1>B/a1}|Gd/:?*ʓ1**+![2*CP/M RMAC ASSEM 1.1 NO SOURCE FILE PRESENT NO DIRECTORY SPACE SOURCE FILE NAME ERROR INVALID PARAMETEQGEGTIFINLELTNEORSPACIADCADDADIANAANDANICMACMCCMPCPIDAADADDCRDCXENDEQUHLTINRINXIRPJMPLDALOWLXIMODMOVMVINOPNOTNULORAORGORIOUTPOPPSWRALRARRETRLCRRCRSTSBBSBISETSHLSHRSTASTCSUBSUIXORXRAXRIASEGCALLCSEGDSEGELSEENDMHIGHIRPCLDAXLHLDNAMEPAGEPCHLPUSHREPTSHLDSPHLSTA@@@@@@@@@@@AA AAQQQ"Q'Q,Q1Q6a*ÿ*:?*ÿ*:@*ÿ*~x/~# *> x/\ -.!"B**\..*B*#"B*+~¤.:u32*5G.*\!F2+*f*-•.*!"f**h*ʹ*E*€.a.Ò.Ҫ.ʒ.6# ‹.͹**h**f*#"f*~!2*G:=*..xx/.x.1,..****w#"*!-*!"***ER: SOURCE FILE READ ERROR OUTPUT FILE WRITE ERROR CANNOT CLOSE FILES UNBALANCED MACRO LIB END OF ASSEMBLY : 5O!5 ~#fo: 5O!5 s#r:?*yʟ2š2ͬ2Ž2G:9*29*!:*4>6:9*L/29*2%#333/3 3333#332E3 3 _{ozg^#V) "^#V|g}o "_{ozgO{ozgi`N#Fogo&og:u9 ͥ6**=;"`:"b:q:b:͞8.96`:q:͞8"9|!96wj1:9R,v!5!B".:ͬ . ":\ -ˆ*.:~=Ÿͬ ï.+: -§:9ҹ'*.:~*.:~(H*.:~,Dͬ :9'ù:w92y9:9F:9!"&<͵͊6 - *&<))))*<& "&<0 D͵ *&<:/͵: W :ZD͵:ڎ : >!:*!^:6+":^:$t 8'> *0< ~L*0< DMB5*0< 6*0w#6!4!]:ڤ*]:&f;) N#F͋41!]:4:u92:2:2;2E;2u;2;2;2;!D:6+6!E:6!"p9!"m9}2o9!z962v92x92w9!t96X!"y:"{:"}:"(C(͆7:9):o9:o9H4!"p9>:o929*p9"95*.:~(*.:~ʐn*.:~)p̀^*.:~*.:~(HҍDO:9ʛD*Ͳ!6~̈́6*& 6:!Q: D*Q:&J: :w#6*0<##N#F*.< ~O`i~8p8!6Ͷ8ikS*0< DMv5*0< DMd5*0< *0<##N#Fq#pä*0<##q#p*u:#^#V*u: ^#V*u: ^#V*u:~*u:~*u:>*u:~*u: ^#V*w: ^#Ve USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Th:":":":":":":":":":":":":"i:"k:"m:"o:}2:!:6#6#6*9"q:2C:2D:2E:2R:!"X:o&"Z:|!"s:!"p;";";";":":";"7;*+":*+":*+" ;*+"9;!":":";"?;!":":";"A;:9*b::9=o&))9  ^#V!!<4*<&^<) ͜*.:#".: =.:<>[],()?$! : @: <_2 <: !#<ڲ*#<& :<«>!#<4>*.:#".:*.:N2<&õ͵:< ͵!<6 !%<6+6:%< :%<  !c ::=<Hw!>:><Hw!?:?<Hw!@:@<Hw!B͔8>ͥG<çCOPYRIGHT (C) 1980 DIGITAL RESEARCH nLT`? OVL LINKING $ $ 1L9M9!96w:o9!9D:!""!""!"9*9^#V"9"q:<͞8-*<&^<) ^#V"d:M*<&^<) q#p!<4*9&))9  *`:s#r*A:)8"p9*9&))9 q#p:9<29O>D:9=29D:9ڗ*9&))9 ^#V"p9  ^#V"`:*`:DM!96#~ͬ . ":\ -:+: .+: -:9<6͸ !\6͊ !!%<6͊> :%<5 !͸ ͵" :<:„ :\:%<Hb !:]A<2\O>v !*%<&\ 6 ô !%<6:<.° ͵͊ڰ :%< ڧ !͸ ͵Ô ! :%<<2% :<02<> : :>:DM9͏5*:@ ~ !92(< !92)<7 :)<ր2)͔8$>ͥG<ͮ8!TJ<ͫ8:P<Hr:Q<ҁ!U<6 Æ!U<6:U<q:ͫ8+s#r!`:͹8ң96:T<Һ*JE<ͫ8*P<&i:) N#F,DM,*Ld:ͫ8ʆh!q=}*o=*d: DM*q=>*}U!r=}>M"d:<>!|=r+s+q+q+q+p+q+q+p+q:u=2}=:z=Һ!}=44*`:"d:*}=& "`:q:ͮ896<*s=DM*u=̈́*^=&^<) N#FU*^=&^*p9"::D:*H:":8*:*:"::r98*:)8":*:*:":Z:X:͞8_X:Z:͞8#"y:e!"y:!:6*X:":!=6>!=ڞ*=&y:) >Ͷ8Ҕͥ:=<2=v!":::2=!=6:=#w:==2= *=&:) *=&: N!: ͠8*=&: ~2=*=& :=w:=2!=6>=08>͔8'6!~=6w*=#"=>&8)))M`̈́d:8+s#r>!=Ͷ8\66!=q!=:~=v d!=6h!=ڤ:==O! *d:N:=<2=|:E:J:*Q:M2"V:!"V:|!=6:Q:!=:==O!J: NͲ:=<2=6D*>DM*>h!ͮ"!>2>:>>!>ͫ8HA!ͱ!">G!*!>">*>DM*>MC:>e!*]:M͋!*>*>*]:*>*>5:=Ҭ!ͱ!"!>>͔8ž!*!>">!>6í!!:]:2%>*>M^ *>DM4*>#DM4O`i~8p8"#>*%>M^ *#>*b:"d:`:d:͞8%"*RE<ͫ8F*P<&i:) *q:s#rN*q:DMͷ!V<6>!V<ڷ!"Y<*V<&i:) ^#V"u:>u:ͫ8ʝͺ"W<*Y![<,*[<&i:) ^#V"u:*[<&<) N#F.>u:ͫ8%Okͥ<) *d:s#r*}=M͍*v=DM>*y=M*u=Ms*x=Mf*u=*d: *s=DM -B:z=Y*{=DM*d: ~#k!{96 MODULE TOP $UNDEFINED START SYMBOL: $YY???? $$$XX???? $$$RQST$ UNDEFINED SYMBOLS: $ABSOLUTE $CODE SIZE $DATA SIZE $COMMON SIZE $U=:=<2=õ*=&: :=w::<2:*b:"d:`:d:͞8q͜/!9H`2UO!: 8DM>ͪ̈́d:8+s#r&!]:6>!]:7*]:&f;) N#F͋4:*]:&<) N#F.B2=:="="=:=O>"=n2=ð-*]:&i:) ^#V"u:>u:ͫ8:R:*U:&:) S:8"V:D>!{:Ͷ81*:"V:DX:ͣ8D*X:"V:Z:X:͞8mX:Z:͞8#DM*X:v6*:DM*:6*:DM*:6*:DM*:6`:s:͞89ͮ8*9|=ͫ8*d: ~#"*d: 6̈́d:8+s#r!!{96:*:MH"H"!^:6:*:Mi"2"g:͜2f:o"=6*:::: -y"::29:*::ͺ/Ҵ":*:͉:*:M"!:͹8"/Ͳͯ/Ͳ Ͳ=6#:*:*:*:DMͪͮDMͪDMͪͺ"u:![<4!"i:"k:"m:"o:*d:##6*d: 6*d:^#V!`=p+q*d:*_=s#r*d: >!a=q*d: :a=w*d:##>?!b=q*d:##:b=w*d:##~*d:##>w*d:##~*d:##>w*d: ~!c=q*d: >:c=Hẅ́dSE FACTOR $!=q*=MͲ!~=4!=q> !=8:=0OͲC:= AOͲ!=q:=O:=O!=p+q!=̈́8MD>=08MD:;!t;!;!;:u;2\. ] -Ÿ\ͩ6!t;6!;6!;6!;6!=6+6>!=*=&f;) ^#V"= *= ~ *= DMv5 *-2=ͥ"=ͮ"=!"=nͺ"u::]:<2]:w!=r+s+p+q*=}*=_DM͘4*=#*=|_͘4!=p+q*="d:2:=2=:=O>Ґ*=DM^"=ã*=&:) =8"=:=O>:=O>==͞8UO!: ͹8"=*=*="=*=DM*=8*d: ~* Ͳ(Ͳ*=DM_-Ͳ*=*=+DM_)Ͳl*|9DM_68f ͥOr:t9Z^E.:n~:x9ZyU/?OVLAY?OVLA0RELIRLIRLREL))O`i~8p8>!:!>6::!>:>=O!: NͲ!>4½)2:͕":)2::: !:*:͉*:*:"::*:M/I#:*:͉*d:DM :*:Mҟ#{#=ͯ6Ü#*:&:) :8DM>*:Mf#:*:*:&:) :8*:͉*]:&y:) N#F*]:*:DM5!=6#!=6:8++"\<*\<^#V!e=p+q̈́d:8++"\<*\<*d=s#r*d: ^#V!g=p+q*d: *f=s#r*d: ~!h=q*d: >:h=Hw!k=s+p+q!^=6:k==2k=ʱ*i=:^=2^=*i=#"i=Ñ:^=2^=!n=s+p+qͽ"d:`:d:͞8͹h!n=*l=*d: DM*n=>*>= 6!=6:=<2=:=7::2\. ] -)\ͩ6*p9###H:ͮ8!D:U!\:6*p9###F:ͮ8!C:r!\:6*p9###X:ͮ8҉!\:6:R:>S:ͫ8:U:H:C:/HҼ!\:6!\:6:E:!C:!\:6!\:6:C:*F:"::\:*p9###":d: :!z9/H!"=ͽ"d:`:d:͞8HҴ>=08>͔8S6!~=6U`/wUp/>=08 \8 M`͹ҖÞ2DM_   *=#"=̈́d:8+s#r >!=Ͷ86!=6>#w#62~=ͽ"d:`:d:͞8N/=:=6!>6::!>. ):>=O!: Hq!>4 *h&\8*|& "9>*7:DM\͏5*9+"9!>q:>2]:*]:&f;) N#F͋4!>q:]:!f:Ҏ *]:&y:) N#F*>͘4:]: Z:y:͞8Ҽ *y:"Z:X:y:͞8 *y:"X:*]:&y:) N#F+q#p!>s+p+q::2>O!: :8">*:":*:M^ :]:$$*g:*:":C$*]:&:) :8*]:&y:) q#p:]:P$!=6*]:&y:) N#F *:":>!:Ͷ8::HҲ$:R:Ҕ$=6ò$*:&:) :8"S:::2U:!R:6:0:$)$ò$!&>6>!&>%%*&>&:) *&>&:) 8*&>&:) q#p*&>&e>*2!:\d5I'}/B(}͉ͽ"d:`:d:͞8)͹(:v92\!0>6>!0>گ(h!0>҈(*0>&\ 6 å(:0>=O! *d:*0>&\ w:0><20>g(!!:6.e -¼(\W5/(!!:6.e -(\d5*d:"1>!_:6I'*1>"d:̈́,*X:DM',,',|9A:͞8&,*A:"|9!G>p+q*F>"H>*C>&y:) F>8+!H>͹8g,*H>DM4O**H>"H>3,::=O!: N!: !y: 8*p9͗8"A>**A>DM**:o9,***p9DM*,*m9DM****:r9,*:DM*,*!J>6>!J> -0 q* q*0 q*̈́d:8+s#râ/ q* q*ͥ.!S>q> !S>O0:S>0Oq*Z0:S> AOq*!T>q:T>O60:T>O60!V>p+q*U>|O[0*U>}O[0*9>!=8"W>*W>!=8!Y>s:h0:Y>2h\͕60\>645*W>!=8!|s2*9͗8"9>. \~9 -0:9 14_2*l>DM2ͦ3Ê4*[>##l>͞8Ҋ4 *[> ~34_2*l>DM2:n>j4*[>  *[> N#FPY͹8d463g4ͦ3Ê4*[>  *[> ͞8҇41Ê4ͦ3!p>p+q*o>"[>!s>s+p+q*q>DM3*[> ^#V"]>*[> N#F*q>?8*]>:s>w *[> 6!u>p+q*t>DM3*[> ^#V"]>*[>y:) q#p*&>&:) >w#6:&><2&>$s:q:͞87%*q:"s::G%͸*9"q:^ :_:/2^::{9]%!!)>s+p+q:)>ˆ%*g:*'>"'>:f:҅%!)>6Ý%*)>&:) '>8+s#r*]:&y:) N#F*]:%*'>DM*)>M͋%*]:&y:) N#F*'>*)>*]:5y y !*>q:*d:8+s#rI(.: -)!:6!:6^ ͽ"d:`:d:͞8)/)*{:DM>fy ^%y !":y y *d:"4>#*4>"d:!3>6>!3>)h!3>ڶ):3>=O! *d:Ny û) y :3><23>Œ)*:"::)͸*9"q:̈́d:8+s#r5)!0:4~ (*6**!J>4,*p9"A::\:(-ͦ-ͦ-ͦ-!L>6::=!L>|-*L>&: ~2K>u-*K>&:) A:͠8e-ͦ-J-:r-.u--!L>4--*p9*A>A:ͮ8ҕ-ͦ-|-:7>ʥ-ͦ-Õ-!O>q*O>Mͧ**A:#"A:M>A:͞8-ͦ-ù-ͦ-*K>&i:) ^#V"u:>u:ͫ8.ͥ*K>&:) *9>"9>\d5͍0C\͏5!Z>s*9>!=8C "9*9*|9s#r͍0C*Z>&\8DM\͔5:j2j\v5:9ҁ1*|9)8"|9:y9ZŠ1a9ҟ10ñ1g9ұ10!_>q.*[> :_>w*[> ~!`>q*[> :`>w*[> *[> ^#VN#FR* *[> 6*[ N#F*t>?8*]>~   +5{>.+55OͲ5w66ͩ6́5;6<566́5͕6<>́5͕6<>645͜6<H66! w #ˆ5>Ö5>2,6""6"$6yo`"&6!"*6͋6-66*&6|6 "&6*"6MD6*$6DM:,65ͷ6g666Ͱ66**6|6U6*$6> &>!*>&:*>#&+"ÿ&:*>1&p"ÿ&:*>?&k$ÿ&:^:ҿ&:*>=O!& ^#VI"ÿ&ÿ&͈"ÿ&>ÿ&͵"ÿ&#ÿ&T#ÿ&#ÿ&#ÿ&$ÿ&$ÿ&Q$ÿ&d$ÿ&W&]&`&f&o&u&{&&&&&&&!+>6)&)2->:^:&*->My (')2,>')2+>:+>1:#"1:*7:{z*!"1:/ *1:!>~26>xG:6>26>G )x{_ P*#B*>ɯ`iq#zV*COMPRLRSPSPROVLSYM!;>q*5:> :;>w*5:#"5:!3:͹8ڦ*>*3:DM\͔5!"5:!<>q:8>!<>28>:7><27>*!7>6*8>Mq*!8>6!=>q*=>Mq**A:#"A:!?>p+q*>>}O**>>|O*:8"M>͹-ͺ"u:-*K>&<) N#F.*0< ~R.*0< DMd5*0< *0<##N#Fq#p].*0<##q#p2P>:P>ʤ.*K>&:) 8"M>"9:P>O>Ҙ."9͹-2P>c.>5:08>͔8ʾ.q*å.>*5:DM\͔5\v5:w9Z.. \": -.:e /.*o9&>^#V!=8"b>?8!a>s1!a>P2*[> DMv5*a>M1*[> DM͕6P2*[> DML5*b>!=8MͲ1*[>  *[> ͞8ҍ2*[>  *[> N#Fq#p *[> ~ڮ2*[> DMB5 *[> 61*[> N#F*[> *[> N#F͔51!e>p+q*[> N#F*d>?8^8*[>q#p*[>45*"6""6**6#"*6ú56**6ABORTED$NO SPACE$NO FILE: $CANNOT CLOSE$DISK READ ERROR: $DISK WRITE ERROR$YYYP   YP6YPYPYPYPYPYP Ͳ ò!>6#6͐6">*>|$7> '*+>M%('͕".>:^:('*.>DM*,>^%:+>&7','!0:6&H'='!0:6!"1:"7::!:'*:͗8"1:"7:. 9\ -u')29!hʦ':92h\͕6¦'\=45)2|29!:6*7:"1:!"9"9^ :_:/2^::!:!_:' ',':e (.e -':+:o9+h,*p9"A::\:,+**V:DM**X:":!@>6::=!@>q+*@>&: N!: p9͞8j+*@>&: N͍+!@>47+:o9:o9HҌ+ -!C>q:C>¢+*X:"D>ó+*C>&:) ^#V"D>D>A:͞8+96D>A:͞8+*+*C>&f;) N#F͋4*C>&y:) >Ͷ8,:C>\8_* DMe - /:w9#/:w92\\B5:9 A/. ~9\ -9/!"5:}28>27>*ͥ.:x9Z^/. \": -f/.en* -v/:x9ʌ/:x92\\B5!"5:}2R>ͽ"d:`:d:͞8(0͹/H02DMv0 q*!Q>6h!Q>/:Q>=O! *d:Nq*:Q><2Q>/:R><2R>*[> 8+*[>##q#p*[>*[> N#F^#V?8*[> s#r *[> N#F`i"h>*[> N#F `i"j>*h>"f>j>f>͞8ڐ3*f>+*[> ^#V\8DM2_2*f>"f>\3*[> ^#V*j>\8DM2*[>  *[> ͞8Ҿ31*[> N#F*[> *[> N#F͏5!n>s+p+q*[>l>͠84 *[> ~9ͫ8"|>##*|> ~!7!>6D7*>|?7!>66"|>D7!>6:>Y7!~>6#6#6Å7*|>~2~>*|> ~2>:>z7:>2>*|> ~2>!>6>!>ڰ7*>&v> ~/*>&: w!>4‹7:72"g:^ *:"|> *g:":*9My *9My *9My *~>My *>My *XXDATA $$$XXCOMM $$$::;7;YYABS $$$YYPROG $$$YYDATA $$$YYCOMM $$$ ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0L$SUBDisk Write Error$Random Read $.$Invalid ASCII Character$Parameter Error$ERROR: Directory Full$Requires CP/M 3.0 $11G"*}0|HҤbP2IK 1">d*++"~"!\. v!q*&*|&el\P"=*|5.*& 6!6͝*& ~( 2*& 6e!"!\" "\p.e.:\2O>:2\>My *|>":i`N#Fog_og_{ozg_ogDM!>))덑o|gV8 =D8DM!>))k8 =c8_{ozg^#V) ~8^#V|g}o ˆ8_{ozgi`N#Fogo&og_{_z#Wn;;;;e USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Th!p+q* !s+p+q*:w#6* *#"N#Fy !p+q*!p+q*2 !p+q*!p+q*!p+q*!p+q*!!p+q*2 !p+q*!q*-!q:2!61!s*& ~ ~H~ H.!4͝*& ~2!6>!`\̓[>!6:<2=O! ~2 ½:<2O>9ҽ!60+~9ҽ!60+~9ҽ!60+~9ҽ!60+4:͓ͪ!"!6:= !6!6#6D2: LINK 1.31 $01/04/83?MEMRY$MEMRYX MEMORY OVERFLOW, USE [A] SWITCH$INSUFFICIENT MEMORY$OVERLAPPING SEGMENTS$INDEX ERROR$MULTIPLE DEFINITION: $MAIN MODULE ERROR$FIRST COMMON NOT LARGEST$COMMON ERRASUB +q:2!6*&"1!p+q*<!s+p+q+p+q:=2d** w*#"*#"=  !s+q+p+q:=2ʩ*:w*#"Ì!p+qe*DM!\.\s!q:a:{: : H% : " :#$ͪ:;!6+~<;!6:$¨D2$X*M å:02O> p<ͪå!6͝:ʔ!5K ҎÄ͝xK ҥ*M Ô" :^D2:^^ :@: O :`:@O :`O " :! XXABS $$$XXPROG $$$OR$UNRECOGNIZED ITEM $1xCP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282nLT`Invalid file name $Error On Line $Enter Password: $ERROR: No 'SUB' File Found$CP/M 3 SUBMIT Version 3.0 $Enter File to SUBMIT: O2:eel !6>!ڜ2 K*&l :w: T:_:…:r:=2O!l 6 3:•!4**& ~ ~ H!4Ýl :S*Q*Sl.l\P"*}=:/H     " *M : 2    *++" *& ~2 :Ht !4>>!""\ !6>!ڷ :+ ~° !4‘ * DM*"À * DM!" }2 ͣ2 N#F##"^q#Vp" 4! 7o |  ! 6   \\ ? >_ 1m :~# yo ɍWARNING: Cannot redirect from BIOS $ERROR: Auxiliary device redirection not implemented $ERROR: Insufficient Memory $""w :&/3͖!~6 :~wucy! ʎB d{<ʑ  '*2.2+6.w  _{ozg^#V) "^#V|g}o "_{ozgO{ozgi`N#Fogo&og<:F4!F46*<KLG!H<>y+!E46ð!E46!4"$Gt!'4I<>Gt!*46!>46z"!4*<@*<"r2<:E4:<>2<>2<*))덑o|gQ =?i`N#Fogo&og_{_z#W00001 : $SYSIN $$$22*2$*.6#6*.~w#~=~#4Ʌo$͖O̓!54  !F6#ȷxO҃>^̓@_: N#͖§>  *.>wÔ#wt~xڔp> ̓ 8>"" ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0L:Gt!^<<xy;!<8!<5!<͛#E!<͛!<5:22%^}2<:!4*<@*<"a{ SYSIN SUB hhhhhhhhhhhhhhWARNING: PROGRAM INPUT IGNORED $e USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Th*B4!}2G<:G<!"B4*B4 |!"<}2<:G<2<:!4*<@*<"2<*t!<͆!<4!<͆_o     `i~< #~2#~2#~2*| W \!\~R 2 .n~ >2 6!.t~: +  >2 6!N#F#*" ^q#Vp"FGET :<***.n6.t6 LL!p:~y !6 <ʊ~"x!=F#fh!:~!«!>w~:!5*.~w:; :~!9"1A#u.t.~@ 151282 COPYR '82 DRI gggggggggggggggggggggggggggggg"D! BH!H@ $!!$"A! D$DHH$B!"  @A  +3:,31!Q3:-3ogͯ3>Gt*+3O"+3M!Q3:-3ogͯ3>Gt!3A !/3*!/3>S!L3:-3ogͯ>t*%3*)3))^#V")3ø͟!.34*3~!.3!t:-3ogͯ}!;3w!;3~w*93:;3=_L3t*93!3>_!3^#V"^#V^#V  $ "/  Later CP/M or MP/M Version Required$*#=**#={ozgY|g}o!\!l!ÍÝ3>Ý!*3>K* !*   >  iO>`G>0 <  DM0 > Ew#E~#X~#W #Ý!9Oo>gy~#o>gxGGtwF#"WOi`~sw#r##q#p i`N#F#^#V~;q4#p+i`##s#rA"]" FREE Request Out-of-Range$ Free Space Overwrite$GKҜMbkÜiFhNhN#Fh^#V"#y2#xүi&ͩ x>!J#{#z*#*# xyxM_#V"J#~#.~# !*#)))))# )| !*~#|}*#"#:L#*J#~#w# F!*#{ `! d!!#"#Ö!Copyright (c) 1980 Digital Research, v1.3 !"!="="%=2]#2L#*'= !"=q#p##}o"#=*}o|!""+w+w+r+s4w#w#s#r<2)=++*!=s  !"#$%(^#V^#Vbk++~+ y~#/(Iỳ>)I|*<|6<ͤͶò">,IG> _O! O! O!0:IIWWG|e}e ڐdԒ ͒ڝÔxWN #~Iæ!wͤ*=!9{_z{ G>#I*=>=^#V#q#r"!=*=#"=*=DM!!=x~¨"#~+¨"+F+Nq#p*=+"=ʣ"Ҧ"=Y"!+~O~#~G!>w!/x"yʞ" >O6# x" h"=ɯ ~#fo++"!=~#"*!="²""""  Insufficient Memory$ Invalid I/O List EF3O3*# 72gl*<"~!>)< D=M)6ɯo>g{ozg!dÄlmnpr Conversion2!Ä*%=|^#V"%=###^#V#N#Fxʿ #~ò*%=|^#V#N#F!9yx"%=:L# !9!#{z#>: >?I!oͤͤ>=I^#V|A}8.))ä#F>A> #\~ >.~ =M^#V# File: Traceback: ERROR FIXED OVERFLOW OVERFLOW UNDERFLOW ZERO DIVIDE END OF FILE UNDEFINED FILE KEYNULCONCONRDRnd of Execution$#dd(Copyright (c) 1980 Digital Research V1.3MXList SYMw#60#60! 9~ .!97>?'w#-!9~sG~#s4! 9~.Y+60e0e6 #M+r>o&9y>o&90w+Š6./G! >0 >-3T]))  !!9:]#O!^# {#z!]#5#}OD*#=~r##~#fo9!NÄVWXZ\ Free Space Exhausted##^#V#{_zW;{_zW>4z˜{##^#V# ##s#rs#r#s#r+++~sw#r####}*#=}|5*{z5+F+N+V+5^{;{z;}|;{PUNLSTBADG!]#~8  " Condition Stack Overflow$4Ox!< w#s#r#s#r!9!^# s#r!]#N!< +++++q #{Š #zʏ ++~q ++!]#5!~# ž Ú !]#N!< +++++¹ #~# +{ #z ++~ù #^#V=!L#~9!5:L#_!M#^ 0# +333sy XREF 1.3 no SYM file no PRN file CP/M PRNXRFABORTED. V́ + 1@+>,,D,B,G-,Q/D,D,L-,D,D,N-P-L-N-P-G-@,I-P/O/Q/G-I-D,000//D,symbol table overflow ' invalid SYM file format  FG1"z*QS cE5T @ { *$'symbol table reference overflow 22i2d$PlPRINTER bu/// _{ozg^#V) "^#V|g}o "_{ozgO{ozgi`N#Fogo&og ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0LlXRF.XRF make error  '.XRF close error .XRF write error <<<_<<bUSER Enter User#:5 5A> Th*=ڜ!*$&!*$& !$sr!*$&$ :$w:$!>!$ҿ!ͥ -*|$ :$w 2p#_og_{ozg_og^#V)))