CBMx >ÍLRESBDOS3SPRBNKBIOS3SPRJBDOS3 SPRMX6502 LIB%MODEBAUDLIBCXEQU LIBZ80 LIB/F+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 COMBSUBMIT COM*CX80 ASM5 !CXDISK ASM"#$%&'()*+,-./01CXDISK ASM2F1F2dir dir F5F6F728 May 87 F9F10F11F16F17F18F19F20F21F22F23F24F25F26F27F28F29F30F31Help CXEM ASMP34567CXEXT ASMO89:;<CXINTR ASM=>?@ABCDEFCXIO ASM@GHIJKLMNOPQRCXKEY ASMuSTUVWXYZCXKRNL ASMz[\]^_`abCXKYCODEASMcdCXPRINTEASMeCXRAMDSKASM&fghCXSCB ASMijCXVT ASMklmnopqrstFAST8502ASMuvwxyz{|}CZ SUB~MAKESYS DOCADDBIOS COM<BNKBDOS3SPRj 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!:/H     " *M : 2    *++" *& ~2 :Ht !4>>!""\ !6>!ڷ :+ ~° !4‘ * DM*"À * DM!" }2 ͣ2O2:eel !6>!ڜ2 K*&l :w: T:_:…:r:=2O!l 6 3:•!4**& ~ ~ H!4Ýl :S*Q*Sl.l\P"*}=1xCP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321Invalid file name $Error On Line $Enter Password: $ERROR: No 'SUB' File Found$CP/M 3 SUBMIT Version 3.0 $Enter File to SUBMIT: _{ozg^#V) "^#V|g}o "_{ozgO{ozgi`N#Fogo&og :  ͪõ!q!r- "w * :w:C w *#" "*#~22_! 8!0!s*&:0!s!6ͳ:  sͳ:  L!`i^#V#~#fo yo w G: xAo o *|&el\P"=*|5.*& 6!6͝*& ~( 2*& 6e!"!\" "\p.e.:\2O>:2\$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*& ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0La{ *& ~ ~H~ H.!4͝*& ~2!6>!`\̓[>!6:<2=O! ~2 ½:<2O>9ҽ!60+~9ҽ!60+~9ҽ!60+~9ҽ!60+4:͓ͪ!"!6:= !6!6#6D2:!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!se 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_o     `i~< #~2#~2#~2*| W \!\~R 2 .n~ >2 6!.t~: +  >2 6!N#F#*" ^q#Vp" H% : " :#$ͪ:;!6+~<;!6:$¨D2$X*M å:02O> p<ͪå!6͝:ʔ!5K ҎÄ͝xK ҥ*M Ô" :^D2:^^ :@: O :`:@O :`O " :!+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:{: :ASUB N#F##"^q#Vp" 4! 7o |  ! 6   \\ ? >_ 1m :~# yo ɍWARNING: Cannot redirect from BIOS $ERROR: Auxiliary device redirection not implemented $ERROR: Insufficient Memory $""creens) ; ; C=start column # B=number of characters to save ; DSEG ?save: mov a,c cpi 40 jrnc do$save$80 push b ;;;*** mov a,b lxi h,stat$line$40 mvi b,0 dad b clear$loop$40: mvi m,' '+80h ; set reverse video inx h dcr a colors ; DSEG ?int80: call setadm lhld key$tbl ; logical color assignments at end of lxi d,11*4*8 ; ..key$table, (key$tbl size=11*4*8) dad d shld color$tbl$ptr ; setup color table ptr mvi a,80h sta current$atr ; ; program the  ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0L22*2$*.6#6*.~w#~=~#4Ʌo$͖O̓!54  !F6#ȷxO҃>^̓@_: N#͖§>  *.>wÔ#wt~xڔp> ̓ 8>""SYSIN SUB_ogDM!>))덑o|gQ =?i`N#Fogo&og_{_z#W00001 : $SYSIN $$$ jrnz clear$loop$40 call paint$40$status ;;;*** pop b do$save$80: mov a,b lxi h,lines*80 ; point to status line lxi d,buffer$80$col ; point to save buffer mvi b,0 ; zero MSB dad b ; point to char position to save save$loop: pu8563 for full flashing cursor ; mvi a,10 ; point to cursor start line# call R$wait ; and mode register mvi a,40h ; start at line zero, cursor 1/16 outp a mvi a,11 ; point to cursor end line# call R$wait mvi a,7 outp a ret pae 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> ThSYSIN SUB hhhhhhhhhhhhhhWARNING: PROGRAM INPUT IGNORED $sh psw ; save count push d ; save buffer address call R$read$memory ; read char(B) and attribute(A) pop d ; recover buffer pointer stax d ; save character inx d ; advance buffer mov a,b ; get atrb to A stax d ; save atrb inx ge ; ; ; DSEG ?int40: lxi h,screen$40 shld char$adr$40 mvi a,24 sta paint$size ; set 40 column repaint to 24 lines lxi b,VIC+18h ; point to address register mvi a,vic$screen*4/256+6 ; upper and lower case set (+6) outp a ; move title 'CX40 & CX80 40 and 80 column drivers 18 Feb 86' maclib cxequ maclib z80 lines equ 24 ; public ?fundir ; function direct public ?int40,?int80 public ?stat,?save,?recov,@st40 extrn ADM31,setadm ; extrn setvt 151282 COPYR '82 DRI gggggggggggggggggggggggggggggg"D! BH!H@ $!!$"A! D$DHH$B!"  @A  FGET :<***.n6.t6 LL!p:~y !6 <ʊ~"x!=F#fh!:~!«!>w~:!5*.~w:; :~!9"1A#u.t.~@d ; advance buffer push d mvi a,01000000b ; reverse video only call get$atr$color ; returned in A mvi d,' ' ; get character call R$write$memory pop d pop psw ; recover count inx h dcr a ; adjust count jrnz save$loop ; looscreen ret ;** ;** The following code is used to maintain the status line on ;** both the 80 and 40 column displays ;** ; ; save characters on the status line (80 column only) to buffer ; reverse video the data area cleared (40 and 80 column spage ; ;** ;** This is the entry point to get to the function module ;** ; ; ; This code will perform the functions that the emulation ; code will need to do to complete function. ; ; ; ; ; enable cursor, then set foreground and background _{ozg^#V) "^#V|g}o "_{ozgO{ozgi`N#Fogo&ogw :&/3͖!~6 :~wucy! ʎB d{<ʑ  '*2.2+6.w p if not done ret page ; ; recover characters to the status line (80 column only) ; for the 40 column screen just clear status line (with spaces) ; ; C=start column # B=number of characters to restore ; DSEG ?recov: mov a,c cpi 40 jrnce 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> Thpaint$common: sta io$0 mov m,a ldir sta bank$0 ret page ; ; ; @st40: stat$line$40: ; 12345678901234567890 character locations db ' ' db ' ' ; ; MSB is 40 column status color, LSB is 80 cd ; save character to write in B lxi h,lines*80 mvi d,0 dad d ; point to character location mov d,b ; place character to write in D jmp R$write$memory ; ; using attribute in A add color to it and return in A ; ; destroys BC ; DSE, underline, reverse video ; ; for the 40 column screen only reverse video is available ; ; INPUT: ; A=attribute (7654 3210) ; 6-reverse video ; 5-underline ; 4-blink ; B=character to write (ASCII) ; C=column number to write ; (>40 d recove$80 ; skip 40 column if C>40 push b ;;;*** lxi h,stat$line$40 mov a,b mvi b,0 dad b mov b,a recov$40$loop: mvi m,' ' inx h djnz recov$40$loop call paint$40$status ;;;*** pop b recove$80: mov a,b lxi h,lines*80 olumn status color ; status$color$tbl: db 05eh ; status color #1 db 0f6h ; status color #2 db 0a6h ; status color #3 db 0b7h ; status color #4 db 0d7h ; status color #5 db 0d4h ; status color #6 db 0e7h ; status color #7 dbG get$atr$color: push h push psw lda bg$color$80 mov c,a mvi b,0 lxi h,status$color$tbl dad b ; point to status color pop psw ani 01110000b ; limit good attr mov b,a ; save in E mov a,m ; get status color ani 0fh ; only woes nothing to 40 column screen) ; DSEG ?stat: push psw push b ; save for 80 column display mov e,a ; save attribute in E mov a,c cpi 40 jrnc not$40$col$wr ;;;*** ; ; display on 40 column display 1st ; RCALL FR$ASCII$to$pet ; c; point to status line lxi d,buffer$80$col ; point to save buffer mvi b,0 ; zero MSB dad b ; point to char position to save recov$80$loop: push psw ; save count ldax d ; get attribute inx d ; advance pointer mov b,a ; save att 083h ; status color #8 db 097h ; status color #9 db 0a8h ; status color #10 db 09eh ; status color #11 db 0ffh ; status color #12 db 0bdh ; status color #13 db 058h ; status color #14 db 06fh ; status color #15 db 0ceh ; ant 80 column status color ora b ; merge with new attr ori 80h ; select alternate character set pop h ret ; ; ; DSEG paint$40$status: lxi h,stat$line$40 lxi d,vic$screen+24*40 lxi b,40 ldir lda bg$color$40 mov c,a mvi b,har to convert is in B ; returned in A mov b,a mov a,e ; get attribute byte ani 01000000b ; check for reverse video mov a,b ; get pet ascii character jrz char$not$rev ori 80h ; set MSB for reverse video char$not$rev: mvi b,0 lribute in B ldax d ; get character in A inx d ; advance pointer push d ; save buffer address mov d,a ; move character to D mov a,b ; move attribute to A call R$write$memory ; write char(D) and attribute(A) pop d ; recover buffer status color #16  ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0L0 lxi h,status$color$tbl dad b mov a,m rrc rrc ; move status color to LSB rrc ; no need to mask it rrc ; color RAM only 4 bits wide lxi h,vic$color+24*40 lxi d,vic$color+24*40+1 lxi b,40 jmp paint$common ; ; ; CSEG xi h,stat$line$40 dad b ; point to status position mov m,a call paint$40$status ;;;*** ; ; display on 80 column display now ; not$40$col$wr: pop d ; D=character E=position pop psw ; get new attribute call get$atr$color mov b,pointer pop psw ; recover count inx h dcr a ; adjust count jrnz recov$80$loop ; loop if not done ret page ; ; Places data on the system status line ; ; for the 80 column screen a number of character attributes ; are available: flash ; save BC call get$max$num$B ; used to set the pointer only mov b,m ; get size, and disk lock flag inx h mov a,m inx h mov h,m ; get last MFM$mactch$ptr mov l,a mov a,b ; get lock flag in A ani 80h ; lock bit set ? sta loce disk) sta vic$trk lxi h,@buffer shld local$DMA ; move DMA pointer to disk buffer call login$rd ana a ; read error ? rnz ; yes, just return RCALL FR$check$CBM rnz ; return if not 'CBM' ; A=0FFh if double sided inr a lhld the drive to check (DPH$pointer set) mvi a,vic$test ; ***** add code to reset 1581 drive ***** call ?fun65 mov b,a ani 0ch cpi 0ch ; fast drive ? jrz commodore$type ; no, must be 1541 type mov a,b ; yes, is a 1571 or 1581 rlc ; kyscn extrn ?fun65 extrn ?bank extrn ?di$int public ?dskst public ?dkmov extrn ?stat,@st40 page ; ; Initialization entry point. ; called for first time initialization. ; DSEG init$154X: xra a sta fast lxi h,MFM$table shld M ; ; ***************************************** ; * * ; * Commodore Disk Controller * ; * Module for CP/M 3.0 BIOS * ; * * ; ***************************************** ; ; ; title 'CXDISK Commodore C-128 Disk Controller 15 Apr 86k$flag ; (save old lock status) shld last$match ; save last match pointer jrz not$$locked$entry ; yes, then set same disk type ; set$locked$entry xra a sta lock$flag mvi c,0B0h lda vic$data ; get sector size info ana c mov b,a ; savDPH$pointer dcx h ; does not affect flags mvi m,dsk$c128 lxi d,dpb$c128$SS jrnz set$dpb$only lxi d,dpb$c128$DS page ; ; ; set$dpb$only: lxi b,0 ; set sector translation to zero set$format: lhld DPH$pointer mov m,c inx h mMSB=1 if NON-Commodore disk jrc MFM$type ; 1571 NON-Commodore disk is MFM type page ; ; Commodore Type disk is a disk that is in GCR format (1571) ; Or Standard Commodore format for 1581 (Has a Commodore dir track) ; commodore$type: lhld DPH$FM$tbl$ptr ret page ; ; This entry is called when a logical drive is about to ; be logged into for the purpose of density and type determination. ; It may adjust the parameters contained in the disk ; parameter header pointed to by ; ' ; CP/M 3 Disk definition macros maclib cpm3 maclib z80 ; C-128 system equates maclib cxequ page ; Disk drive dispatching tables for linked BIOS public cmdsk0,cmdsk1,cmdsk2,cmdsk3,cmdsk4 ; System Control Block variable disk sector size info xchg ; save HL lhld DPH$pointer dcx h mov a,c ana m ; get old disk sector size cmp b ; are they the same? jrnz not$locked$entry ; no, then unlock disk anyway xchg ; get last match pointer (in DE) pop psov m,b ; install sector translation lxi b,25-1 ; ofset to DPB dad b ; HL points to DPB now lxi b,17 ; dpb size xchg ; move to DPB location ldir ret page ; ; TEST MFM() ; save number bytes/sector ; if double sided ; mapointer dcx h if use$1581 mov a,b ; get the status byte ani 30h ; save only the sector size info cpi 20h ; 512 byte sectors? jrnz set$15x1$type ; no, set up as 1571 or 1541 ; yes, set 1581 type drive ; ; ; set$1581$type: mvi m,ds DSEG ; ; if disk type GCR or drive type 1541 or 1581(reports as GCR) ; if sector size is 256 bytes ; if 1st sector has 'CBM' (1st 3 bytes) ; if last byte = -1 (0FFh) ; set C128 double sided ; else ; es extrn @ermde ; BDOS error mode ; Utility routines in standard BIOS extrn ?wboot ; warm boot vector extrn ?pmsg ; print message @ up to 00 ; saves & extrn ?pdec ; print binary number in from 0 to 65535 extrn ?pderw ; yes, remove two data elements pop psw ; ..save on stack jr set$this$entry not$locked$entry: lxi h,MFM$match$tbl ; clear Match table shld MFM$cur$ptr lxi d,MFM$match$tbl+1 mvi m,0 lxi b,(MFM$tbl$entries*2)-1+1+1 ; table, offset anrk two sided ; endif ; find start and end sector numbers ; scan table of disk for match (if more then 1 match ask user) ; MFM$type: mvi c,01100000b ana c ; A = status(trk1) shifted left 1 push psw ; save in case bad query push bk$1581 ; yes, set up as 1581 double sided lxi d,dpb$1581 jr set$dpb$only endif set$15x1$type: mvi m,dsk$c64 lxi d,dpb$c64$cpm ; set DPB to C64 call set$dpb$only xra a sta vic$sect ; set track 1 sector 0 (1st sector inr a ; on th set C128 single sided ; endif ; else ; set C64 type ; endif ; else (512 byte sector size) ; set C1581 type ; endif ; else (must be MFM) ; TEST MFM ; endif ; login$154X: call get$drv$info ; setr ; print BIOS disk error header extrn ?conin,?cono ; con in and out extrn ?const ; get console status extrn ?sctrn ; sector translation routine extrn @covec ; status line calls extrn ?save,?recov,?stat ; System function call extrn ?d count ldir mvi a,4 sta vic$trk ; do query on track 4 mvi a,vic$query call ?fun65 pop b ; recover BC ani 0eh ; query error ? jrnz query$error ; yes, use only bits 5 and 6 lda @buffer ; get trk 4 status mov b,a ; save in B t current position inr a ; advance position cmp b ; at last position ? (n-1+1 =count) jrnz set$offset ; no, then use A as new position xra a ; yes, move back to start jr set$offset CK$dsk$user$lf: cpi SF$left ; jrnz dsk$user$sel$ pop psw jr set$offset not$last$match: inx h ; each pointer uses two bytes inr c ; advance the index djnz try$next$format ; test for more, loop if so call save$dsk$window lhld MFM$cur$ptr user$loop: mov e,m ; HL=(MFM$cur$ptrsector translation table mov c,m ; ..zero if none inx h mov b,m inx h ; HL points to DPB xchg ; DE points to DPB (HL trash) call set$format mov b,m ; get the number of sect/trk from MFM table lda lock$flag ; get the current lock flag value to mov a,m ; get type info ana c ; test only the good info cmp b ; match the current type byte mov a,b ; (recover A) pop b ; (recover BC) jrnz not$found ; no, do not queue data ; yes queue table entry address xc ani 0eh ; trk 4 status error ? jrnz query$error ; yes, use only bits 5 and 6 mov a,b ; recover B (trk 4 status) add a ; shift left ana c ; mask sector size bits mov b,a pop psw ; get trk 1 sector size bits cmp b ; same as trk 4 wait ; move window up lda MFM$offset dcr a ; back up offset (under flow?) jp set$offset ; result positive, jump lda MFM$count ; get last item number dcr a ; pointer is 0 to n-1 (not 1 to n) set$offset: sta MFM$offset ; set new list o) inx h mov d,m lxi h,22 ; offset to NAME field dad d ; point to Disk name call dsk$window$old dsk$user$sel$wait: call ?kyscn inr b ; test for key pressed jrz dsk$user$sel$wait dcr b ; adjust back mov a,b ; move matrix posivalue ora b ; combine with sect/trk xchg ; HL=to adr, DE=from adr mov m,a ; install sect/trk and lock flag pop d ; recover table pointer inx h mov m,e inx h mov m,d ; save MFM table pointer at end of DPH ret page ; ; let the hg ; save adr in DE lhld MFM$cur$ptr mov m,e inx h mov m,d inx h shld MFM$cur$ptr lxi h,MFM$count inr m ; add one to counter xchg page ; ; not$found: lxi d,32 ; table entry size dad d djnz check$next lda MFM$count sector size? mvi c,01111111b jrz trk$1$trk$4 ; yes, (then test for mult format) mvi a,80h ; set MSB to mean mult format add b ; ..(track 0 different sector size ; ..then track 4) mov b,a ; save in B mvi c,11111111b trk$1$trk$4: ffset inr a ; add one to adjust for DCR below lxi h,MFM$match$tbl ; set to the beginning adjust$dsk$loop: shld MFM$cur$ptr ; set pointer here ! dcr a ; at offset yet? jrz user$loop ; yes, go display name inx h inx h jr adjust$dsk$tion to A cpi SF$exit jrnz CK$dsk$user$rt mov a,c ani 4 ; control key down ? jrz no$cntr$key ; no, don't lock this selection mvi a,80h ; yes, lock disk type to this drive no$cntr$key: sta lock$flag ; call dsk$window$remove lhld Muser select the Disk type (s)he wants ; user$select: inr a ; number of entries to try to match mov b,a ; set in B as loop count lhld last$match ; get value to match with mov d,h mov e,l ; last match pointer is in DE lxi h,MFM$match$t ; number of matches in table ana a ; test for zero jz tell$user$no$entry ; none, tell the user dcr a ; only one ? jrnz user$select ; no, go check with user (which one) lhld MFM$match$tbl ; yes, use the only one found ; ; install da lda @buffer+1 ; get number of sectors/track sui 4 ; remove 4 to extend the range add a ; shift left add b ; combine with rest of mask mov b,a ; save in B for now lda @buffer+3 ; minimum sector number add b ; add in start sector #loop page ; ; ; tell$user$no$entry: lda vic$data ; get disk test status ani 0b0h ; save only sector size and MFM flag lhld DPH$pointer dcx h mov m,a ; set disk size and Type0 (MFM) lxi h,dsk$window*256+buff$pos lxi d,no$dsk$msgFM$cur$ptr mov e,m inx h mov d,m xchg jr set$this$entry page ; ; ; CK$dsk$user$rt: cpi SF$right ; jrnz CK$dsk$user$lf ; move window down lda MFM$count ; get number of items in list mov b,a ; save in B lda MFM$offset ; gebl shld MFM$cur$ptr mvi c,0 ; start offset at zero try$next$format: mov a,e cmp m inx h jrnz not$last$match mov a,d cmp m jrnz not$last$match ; ; match, set pointer ; mov a,c ; get offset in A push psw call save$dsk$windowta from pointer in HL ; set$this$entry: push h ; save table pointer inx h mov a,m ; get type info. xchg ; save table address in DE lhld DPH$pointer dcx h mov m,a ; save type code xchg ; get table adr to HL inx h ; HL points to push psw ; save on stack for a moment query$error: pop psw ; get value to match ana c ; test only those bits in the mask lhld MFM$tbl$ptr mvi b,MFM$tbl$entries check$next: push b ; save BC for a moment mov b,a ; move compare disp$msg$DE$HL: call dsk$window$new dsk$no$entry$wait: call ?kyscn inr b jrz dsk$no$entry$wait dcr b mov a,b cpi SF$exit jrnz dsk$no$entry$wait ; jr dsk$window$remove page ; ; ; dsk$window$remove: lhld window$info mov b,h et$up$next jr wr$fast$drive page ; ; ; get$drv$info: lhld @dma shld local$dma xchg shld DPH$pointer lda @adrv ; get drive number (0 to F) ana a cz drive$A$E cpi 'E'-'A' ; test if drive E cz drive$A$E dcx h ; point at d?dkmov ; go move DMA to buffer mvi a,vicwr ; write a sector of data call dsk$fun ; a=0 if no errors ani 0eh jrnz test$error lda sect$cnt ana a rz call set$up$next jr wr$slow test$error$pop: pop psw test$error: ei lda vic; adjust count for pre-decrement call ?di$int lxi b,0DD00h ; D2PRA inp a ; get current clock polarity xri 10h ; toggle clk$bit outp a ; to have status sent (extra clock ; supplied by rd$1571$data for multi ; sector transfersctor address in @sect (16 bits) ; pointer to XDPH in ; ; return with an error code in ; A=0 no errors ; A=1 non-recoverable error ; A=2 disk write protected ; A=FF media change detected ; DSEG read$154X: call get$drv$info jm mfmmov c,l jmp ?recov ; ; ; save$dsk$window: lxi h,dsk$window*256+buff$pos ; H=size l=pos shld window$info mov b,h mov c,l jmp ?save ; ; ; dsk$window$new: shld window$info xchg mov b,d mov c,e push h call ?save pop h dsk$wrive mask dcx h mov a,m ; get drive mask mov b,a ; save in B sta vic$drv ; save vic drive # (values 1,2,4,8) inx h ; point at disk type xra a sta sect$cnt ; clear the count inr a sta vic$count mov a,m ; get disk type ana $data ani 0fh ; check for disk error or media change cpi 0bh ; disk change ? jrz change$error cpi 08h ; test for write protect error jrz write$prot$error mvi a,1 ; get general error flag ret ; ; write$prot$error: mvi a,2 r) lda vic$count rd$multi$sect: push psw push d ; save the sector size call rd$1571$data ; read disk data to DMA address pop d lda vic$data ani 0eh jrnz test$error$pop ; A=0 if no errors pop psw dcr a jrnz rd$multi$sect ei l$rd call set$up$GCR ; compute effective track and sector login$rd: lda vic$drv mov b,a lda fast ; get fast flags ana b ; isolate fast bit for this drive jrnz rd$fast ; go handle fast drive rd$slow: mvi a,vicrd ; read a sector of daindow$old: lda window$info ; get start index inr a mov c,a ; place in C dsk$out$next: push h lhld window$info mov a,h add l ; compute max index (start+size) dcr a ; ..less 1 pop h cmp c rz mov b,m call dsk$B$out inx ha ret ; ; drive A and E share the same physical disk drive (unit 8) ; drive$A$E: mov b,a lda curdrv ; get the current drive def cmp b ; curdrv = requested drive ? rz ; yes, return ; no, tell the user to swap disk push h puset ; ; change$error: mvi a,-1 ret page ; ; ; mfm$wr: call set$up$MFM wr$fast$drive: mvi a,vic$wr$f call dsk$fun ; go send the write command call get$sector$size ; setup DMA adr and transfer count lda vic$count wr$multi$secda sect$cnt ana a ; any sectors left to read jrz done$rd$1571 call set$up$next jr rd$fast done$rd$1571: lxi b,0DD00h ; D2PRA inp a ani not(10h) ; set clk$bit hi outp a xra a ; A=0 for no errors ret page ; ; ; writta (A=1) call dsk$fun ; a=0 if no errors jnz test$error ; check for disk error or media change ; ; ; buf$move: xra a ; set direction to read call ?dkmov ; go move buffer to DMA lda sect$cnt ana a rz ; a=0 means not read errors jr dsk$out$next ; ; ; dsk$B$out: mvi a,01000000b ; set reverse video attr push b push h call ?stat ; display space pop h pop b ; recover count inr c ret page ; ; disk READ and WRITE entry points. ; These entries are h d push b send$messg: mov a,b ; get requested drive # to A sta curdrv ; make this the current drive adi 'A' ; compute drive letter sta msg$drv RCALL FR$bell ; ring BELL to alert user lxi h,swap$msg$lng*256+buff$pos lxi d,swap$mst: push psw push d ; save sector size call wr$1571$data ; write data to disk from DMA address pop d ani 0eh jrnz test$error$pop pop psw dcr a jrnz wr$multi$sect ei lda sect$cnt ana a rz ; return if no errors (A=0) call se$154X: call get$drv$info jm mfm$wr call set$up$GCR lda vic$drv mov b,a lda fast ; get fast flags ana b ; isolate fast bit for this drive jrnz wr$fast$drive ; go handle fast drive wr$slow: mvi a,-1 ; set direction to write call call set$up$next jr rd$slow page ; ; A=drive type info ; mfm$rd: call set$up$MFM rd$fast: mvi a,vic$rd$f call dsk$fun ; go read the disk ani 0eh ; mask off error bits jrnz test$error call get$sector$size inr d inr e called with the following arguments: ; relative drive number in @rdrv (8 bits) ; absolute drive number in @adrv (8 bits) ; disk transfer address in @dma (16 bits) ; disk transfer bank in @dbnk (8 bits) ; disk track address in @trk (16 bits) ; disk seg call disp$msg$DE$HL ; disp and wait for CR mvi a,vic$test call ?fun65 ; ani 0fh ; cpi 0ch ; not fast ERROR ? ; jrz exit$drv$A$E ; yes, return that's not a problem ; ani 0eh ; other error type ? ; jrnz send$messg exit$drv$A$E: pop b adjust to 1 to 9 (odd numbers only) sta VIC$sect ; ret ; endif page ; ; A=dsk$info on entry ; set$up$MFM: mvi d,0 ; D=side # (0) mov e,a ; save dsk$info in E ani TypeX ; look at Type0 to Type7 jrz do$type$0 ; cpi Type2 ; do$type$7: mvi b,255 ; no dir sector ; ; this routine will adjust the track number if necessary. ; The C64 CP/M disk has the C64 directory in the center ; of the disk. This routine checks and adds one to the track ; number if we have reached or save number to read mov a,b ; get remaining count sta sect$cnt ; save remaining count ret set$up$next: lda vic$count ; get number of sectors read lhld local$DMA ; get current DMA pointer add h ; advance pointer by number of mov h,ter dad h dad h ; make 256 byte pointer ; ; build a list of tracks and sectors ; next$sect: shld @trk RCALL FR$trk$sect lhld vic$trk ; get trk(L) and sector(H) to HL xchg lhld sect$buf$ptr mov m,e inx h mov m,d inx h shld s pop d pop h mov a,b ret swap$msg: db 'Insert Disk ' msg$drv: db 'X in Drive A' swap$msg$lng equ $-swap$msg+2 ; +2 for leading and trailing spaces page ; ; ; get$max$num$b: lhld DPH$pointer lxi b,42 ; offset to number of sectorlda @trk ; used by Type1, Type2 and Type3 jrz do$type$2 jrc do$type$1 ; cpi Type6 ; jrz do$type$6 ; jnc do$type$7 ; MSB of sector(byte) set for 2nd side of disk cpi Type7 jz do$type$7 ; MSB of sector(byte) set for 2nd side of disk ; ; onlpassed the directory track. ; set$up$c64: sta VIC$sect ; lda @trk ; cmp b ; carry=1 if A < dir$track cmc ; add one if dir$track or more (carry not set) aci 0 ; add the carry bit in sta vic$trk ret if use$1581 ; ;****** adjust ta ; sectors read shld local$DMA handle$1541: lhld sect$buf$ptr mov a,m sta vic$trk inx h mov a,m sta vic$sect inx h shld sect$buf$ptr lda vic$drv mov b,a lda fast ana b jrz set$up$next$slow lda sect$cnt sta vic$count xrect$buf$ptr lhld @trk inr l ; update saved above at next$sect mov a,l ani 3 jrnz next$sect ; ; check list of trk-sectors for number of sectors on this trk ; lxi h,sect$buffer shld sect$buf$ptr lda vic$drv mov b,a lda fast ana b s on track dad b mov a,m ; get number sectors/track/side ani 1fh mov b,a ret ; ; ; get$sector$size: lhld DPH$pointer dcx h mov a,m ; disk type in B (bit 5,4 size info) rrc ; ..00 = 080h byte sectors rrc ; ..01 = 100h byte y types 0 to 2 and 7 are currenty defined ; Type3 to Type6 will do Type2 ;do$type$3: ;do$type$6: do$type$2: mov b,a ; save a copy in B sui 40 jrc do$type$0 ; jump if still on side 0 mvi a,79 ; on back side count 39,38,37,...,0 sub b seto read multi-512 byte sectors (system sees 1K sector size) ; c1581$adj: mvi a,2 ; 2 512 byte sectors equ 1 1K sector sta vic$count lda @trk ; cpi C1581$dir$trk*2 ; carry=1 if A < dir$track cmc ; add one if dir$track or more (carry not seta a ; two reads max with fast drive jr set$up$next$exit set$up$next$slow: lda sect$cnt dcr a set$up$next$exit: sta sect$cnt ret ; ; ; tst$next: if use$1581 cpi dsk$1581 jrz c1581$adj endif tst$c64: mvi b,dir$track ; set the ; drive type 1571 jrz handle$1541 ; no, handle as 1541 lda sect$cnt ; number of sectors to rd/wr mov b,a inx h mov a,m ; get 1st sector # sta vic$sect dcx h mov a,m ; get 1st track # sta vic$trk try$next: cmp m ; test forsectors rrc ; ..10 = 200h byte sectors rrc ; ..11 = 400h byte sectors ani 3 jrz set$128 jpo not$3 ; jump if (A=) 01b or 10b inr a ; make A = 4 not$3: mvi e,0 ; set E to zero mov d,a ; set sector size (1,2 or 4) get$DMA: lh$trk: mvi d,80h ; D=side # (1) sta @trk jr do$type$0 page ; ; divide the track number by two and if Head=1 ; add #sect/side to @sect ; do$type$1: cmc ; carry was set clear it rar ; divide track by 2 (carry gets LSB) sta @trk jr) aci 0 ; add the carry bit in rar ; track=@trk/2 ; carry set if odd sta vic$trk ; lda @sect ; sector # are 0 to 9 (10 sector/trk) mov b,a ; jrnc bottom$1581 ; adi 80h ; set top of 1581 bottom$1581: add b ; make 0 to 8 inr a ; dir track number cpi dsk$c64 ; C64 type disk? lda @sect ; get sector # to set jrz set$up$c64 ; yes, go set up for C64 CP/M disk format ; no, set up as no type(direct addressing) ; ; This format is for direct track and sector addressing same trk # jrnz exit$no$match inx h inx h ; advance to next trk shld sect$buf$ptr djnz try$next exit$no$match: lda sect$cnt ; number of sectors to rd/wr sub b ; remove number left ; (leaving number matched) sta vic$count ; ld local$DMA ; get the current DMA pointer ret set$128: lxi d,128 jr get$DMA page ; ; ; DSEG set$up$GCR: cpi dsk$c128 jnz tst$next mvi a,4 sta sect$cnt lxi h,sect$buffer shld sect$buf$ptr lhld @trk ; 1 K sector poinACP/M PLUS652Ank call ?bank ; set it lxi b,0DC0Dh ; D1ICR rd$1571$stat$wait: inp a ani 8 ; data ready bit set? jrz rd$1571$stat$wait ; no, loop mvi c,0ch ; D1SDR inp a ; read the status byte sta vic$data ; save it ani 0eh ; any errors e$reg mvi a,fast$wr$en sta io$0 outp a ; set data direction to output sta bank$0 lxi b,0dc05h ; low (D1T1h) xra a outp a dcr c ; low(D1T1l) mvi a,3 ; clk = osc/3 outp a ; mvi c,0eh ; D1CRA inp a ani 80h ori 55h de$reg mvi a,fast$rd$en sta io$0 ; enable the MMU outp a ; set data direction to input sta bank$0 ; disable MMU ; spin done page lxi b,0DC0Dh ; D1ICR inp a ; clear data pending flag lxi b,0DD00h ; D2PRA inp a ori 10h the disk bank call ?bank ldir ; do the data move sta bank$0 ; current bank will ALWAYS be 0 ret ; ; ; DSEG dsk$fun: sta vic$cmd lda stat$enable ani 1 ; display of disk info enabled? cnz disp$dsk$info ; yes, go display disk innc do$type$0 call get$max$num$b ; HL and C changed lda @sect add b sta @sect do$type$0: lda @trk sta vic$trk call get$max$num$b ; B=number of sectors per track per side lda @sect ; ..HL and C changed cmp b jrc is$side$0 mvi d,80h ? jrnz rd$1571$exit ; yes, exit lxi b,0DD00h inp a ; get current clock polarity rd$1571$next: lxi b,0DD00h ; D2PRA xri 10h ; toggle clk$bit outp a ; clock the 1571 for a byte dcr e ; DE=count jnz rd$1571$more ; leave as nooutp a dcr c ; D1ICR inp a lda @dbnk ; get the disk DMA bank call ?bank ; set it mvi a,clk$in sta cur$clk page ; ; clk$wait: lxi b,0dd00h ; D2PRA inp a inp c ; debounce cmp c jrnz clk$wait lda cur$clk ; get o; set clk$bit low (hardware inverted) outp a ; lxi b,0DC0Dh ; D1ICR wait$status: inp a ani 8 jrz wait$status lxi b,0DC0Ch ; D1SDR inp d lxi b,0DD00h ; D2PRA inp a ani not(10h) ; set clk$bit hi (hardware inverted) outp a fo jmp ?fun65+3 ; go do the function page ; ; ; DSEG ?dskst: disp$dsk$info: mvi a,72 ; r/w in col 72 (col 0-79) sta offset lda vic$cmd mvi b,'R' dcr a ; ?1 normal$rd jrz out$cmd$rd dcr a ; ?2 normal$wr jrz out$cmd$wr d ; D=side # (1) bit C1$bit,e ; dsk$info in E ; sector numbering continues on side 1 ? jrnz is$side$0 ; yes, do not remove side one bias sub b ; no, remove side one bias is$side$0: mov c,a ; hold @sect in C mov a,e ; get dsk$info to A rmal jump to keep dcr d ; the transfer speed at it's max jrz rd$1571$exit ; ... ; rd$1571$more: dcr b rd$1571$wait: mvi c,0dh ; D1ICR (DC0Dh) inp c bit 3,c jz rd$1571$wait mvi c,0ch ; D1SDR ini ; (hl) <- (bc) ; hl <- hl+1 ;ld clk value xra c ; check if changed ani clk$in ; (only clock in bit) jrz clk$wait ; loop if not mov a,c ; sta cur$clk ; make this the current clk value lxi b,0dc0ch ; D1SDR mov a,m outp a ; send character to drive inx h ; mov a,d ; recover the status byte sta vic$data ei ret page ; ; This routine is used to move a sector of data ; to/from the sector buffer and the DMA pointer. ; A=0 for buffer to DMA (disk read) ; A<>0 for DMA to buffcr a ; ?3 fast$rd jrz out$cmd$rd dcr a ; ?4 fast$wr rnz out$cmd$wr: mvi b,'W' out$cmd$rd: call disp$B call disp$space mvi b,'A'-1 lda vic$drv next$drv: inr b rrc jrnc next$drv call disp$B lda vic$trk call disp$dec ldaani S1 ; A=Starting sector number (0 or 1) add c ; add back @sect ora d ; add in the side bit sta vic$sect ret page ; ; input: ; DE = number bytes to read ; HL = DMA address ; CSEG rd$1571$data: lda @dbnk ; get the disk DMA ba b <- b-1 jmp rd$1571$next rd$1571$exit: sta bank$0 ; restore current mem config ret page clk$in equ 40h ; ; input: ; DE = number of bytes to write ; HL = DMA address ; wr$1571$data: call ?di$int ; do spout inline lxi b,mod ; advance pointer dcx d ; dec the char count inr c ; D1ICR send$wait: inp a ani 8 jz send$wait mov a,d ora e jnz clk$wait ; go send the next byte ; do spin lxi b,0DC0Eh ; D1CRA inp a ani 80h ori 8 outp a lxi b,moer (disk write) ; CSEG ?dkmov: lhld local$DMA ; current DMA adr lxi d,@buffer ; location of disk read/write buffer lxi b,256 ; sector size ; ; dk$cont: ora a jrnz dsk$read ; swap pointer for read xchg ; ; dsk$read: lda @dbnk ; get vic$sect ani 80h cz disp$space mvi b,'-' cnz disp$B lda vic$sect ani 7fh page ; ; ; disp$dec: mvi b,'0'-1 conv$loop: inr b sui 10 jrnc conv$loop adi '0'+10 push psw call disp$B pop psw disp$A: mov b,a disp$B: pointer page ; ; 2nd disk Drive on the system ; dw write$154X dw read$154X dw login$154X dw init$154X db 2 ; bit 1 set (drive 1) db dsk$c128 ; format type byte cmdsk1: dph 0,dpb$1 dpb$1: dpb 1024,5,159,2048,128,0 db 0 ; maxdw init$154X db 1 ; bit 0 set (drive 0) db dsk$c128 ; format type byte cmdsk4: dph 0,dpb$4 dpb$4: dpb 1024,5,159,2048,128,0 db 0 ; max sector number and lock flag dw 0 ; MFM table pointer page ; ; NOTE: The blocking factor for allfset of 0 ; DSEG ; these tables are moved to common when used dpb$c128$SS: ; (170 allocation units) dpb 1024,1,170,1024,64,0 page ; ; DPB FOR C128 CP/M 3.0 double sided disk ( 340K ) ; 1024 byte sectors (phy=256) ( 341.5K ) ; 1 sectors/trf 1 to 35 (not 0 to 34) ; dpb$c64$cpm: ; (144 allocation units) dpb 256,17,34,1024,64,3 page ; ; DPB FOR C128 CP/M 3.0 C1581 DSDD (3.5") ( K ) ; 512 byte sectors ( 720K ) ; 10 sectors/track ; 159 tracks/disk ; 160 physi lxi h,@st40-72+40-8 lda offset mov e,a mvi d,0 dad d ; add the offset mov m,b ; save on 40 col display mov a,e mov c,a ; col # in C inr a sta offset ; advance cursor position xra a ; no attribute to write call ?stat sector number and lock flag dw 0 ; MFM table pointer page ; ; 3rd disk drive on the system ; dw write$154X dw read$154X dw login$154X dw init$154X db 4 ; bit 2 set (drive 2) db dsk$c128 ; format type byte cmdsk2: dph 0,dpb$2 of these formats is ; 1K (2K for double sided), thus the fractional ; parts are unusable by CP/M. They can be accessed ; by absolute sector addressing. ; ; NOTE: 1571 and 1541 disk drives use track numbers ; of 1 to 35 and sector numbers of 0 tack ; up to 21 physical sectors (0 to 16,17,18 or 20) ; 340 tracks/disk (usable, 1366 real) ; 70 physical tracks (0 to 34 side 0, 35 to 69 side 1) ; 2K allocation units ; 128 directory entrys ; track offset of 0 ; dpb$c128$DS: ; (170 allocation cal tracks 80 on top, 79 on bottom, 1 used for ; BAM and disk directory (1581 DOS) (10 sectors per track) ; 2K allocation units ; 128 directory entrys (2 allocation units) ; if use$1581 dpb$1581: ; (xxx allocation units) dpb 1024,5,159,2048,128lxi h,@st40 lxi d,vic$screen+40*24 ; update 40 column screen lxi b,40 ldir xra a ret disp$space: mvi b,' ' jr disp$B page ; ; Extended Disk Parameter Headers (XDPHs) ; CSEG ; place tables in common ; ; 1st disk drive on the sydpb$2: dpb 1024,5,159,2048,128,0 db 0 ; max sector number and lock flag dw 0 ; MFM table pointer page ; ; 4th disk drive on the system ; dw write$154X dw read$154X dw login$154X dw init$154X db 8 ; bit 3 set (drive 3) db dsk$c12o nn ; ; The method used to access the full disk ; is to tell the system that there is 1 sector ; per track and then to use the track # as an ; absolute sector address and do conversion in BIOS. ; ; ; DPB FOR C128 CP/M 3.0 disk ( 170K, 34K units) dpb 1024,1,340,2048,128,0 page ; ; DPB FOR C64 CP/M 2.2 disk -- ( 136K ) ; 256 byte sectors ; 17 sectors / tracks (sector numbering 0-16) ; sector 18 to n on the outer tracks are unused ; 34 tracks / disk ; tracks track 2 to 16 ,0 endif page ; DSEG MFM$table: db S256*2+(16*2-8)+1 ; 256 byte sect, 16 sect/trk db MFM+S256+Type0+C0+S1 ; DSDD dw 0 ; start on track 2 sect 1 (2 alc) dpb 256,32,40,2048,128,2 ; sect# 1 to 16 db 16 ; (top and bottom numbered the stem ; dw write$154X dw read$154X dw login$154X dw init$154X db 1 ; bit 0 set (drive 0) db dsk$c128 ; format type byte cmdsk0: dph 0,dpb$0 dpb$0: dpb 1024,5,159,2048,128,0 db 0 ; max sector number and lock flag dw 0 ; MFM table8 ; format type byte cmdsk3: dph 0,dpb$3 dpb$3: dpb 1024,5,159,2048,128,0 db 0 ; max sector number and lock flag dw 0 ; MFM table pointer page ; ; Drive E: shared with 1st drive (A:) ; dw write$154X dw read$154X dw login$154X larger then C64 CP/M) ; 256 byte sectors ( 170.75K ) ; 1 sectors/track ; up to 21 physical sectors (0 to 16,17,18 or 20) ; 680 tracks/disk (usable, 683 real) ; 35 physical tracks (0 to 34) ; 1K allocation blocks ; 64 directory entries ; track of(track numbering 0-34) ; track 17 is the C128 directory track (not counted) ; track 19 to 34 ; 1K allocation blocks ; 64 directory entrys ; track offset of 3 (1st two tracks used for CP/M 2.2 boot) plus ; one sector to adjust for sector numbering osame) db 'Epson QX10' ;1 Epson QX10 ; 160 allocation units db 80h+S512*2+(10*2-8)+1 ; 512 byte sect, 10 sect/trk ; db S256*2 ; track 0 is 256 bytes/sector db MFM+S512+Type0+C0+S1 ; DSDD dw 0 ; start on track 2 sect 1 (2 alc) dn track 0 sector 10 (2 alc) dpb 512,10,80,2048,128,1 ; sect# 0 to 9 on top (even tracks) db 10 ; sect# 10 to 19 on bottom (odd tracks) db 'KayPro IV ' ;5 ; 200 allocation units db S512*2+(10*2-8)+0 ; 512 byte sect, 10 sect/trk dbtrk db MFM+S256+Type0+C0+S1 ; DSDD dw 0 ; start on track 4 sect 1 (2 alc) dpb 256,32,40,2048,128,4 ; sect# 1 to 16 db 16 ; (top and bottom numbered the same) db 'Epson Euro' ;9 Epson European (MFCP/M ?) ; 160 allocation units b S1024*2+(5*2-8)+1 ; 1024 byte sect 5 sect/track ; db MFM+S1024+Type0+C0+S1 ; SSDD ; dw 0 ; start on trk 2, sect 1 (2 alc) ; dpb 1024,5,40,2048,128,2 ; sect# 1 to 5 ; db 5 ; ; db 'Morrow MD2' ; ; db S1024*2+(5*2-8)+1 ; 1024 byte sec title 'Terminal Emulation (ADM-31 with K-Pro support) 21 May 86' maclib z80 maclib cxequ lines equ 24 public ?out40,?out80,ADM31 ; ; ADM3A ; ; ; ESC = row col cursor position ; ESC ESC ESC color set color ; added for C128 pb 512,20,40,2048,128,2 ; sect# 1 to 10 db 10 ; (top and bottom numbered the same) db 'Epson QX10' ;2 ; 200 allocation units page db S512*2+(8*2-8)+1 ; 512 byte sect 8 sect/trk db MFM+S512+Type2+C0+S1 ; SSDD dw 0 ; start on trac MFM+S512+Type0+C1+S0 ; SSDD dw 0 ; start on track 1 sector 0 (4 alc) dpb 512,10,40,1024,64,1 ; sect# 0 to 9 db 10 ; db 'KayPro II ' ;6 ; 200 allocation units page db S1024*2+(5*2-8)+1 ; 1024 byte sect, 5 sect/trk db MFM+S102db -1 db MFM ; dw 0 ; dpb 512,20,40,2048,128,2 ; db 8 ; db ' None ' ;10 page db -1 db MFM ; dw 0 ; dpb 512,20,40,2048,128,2 ; db 8 ; db ' None ' ;11 db -1 db MFM ; dw 0 ; dpb 512,20,40t 5 sect/trk ; db MFM+S1024+Type0+C0+S1 ; DSDD ; dw 0 ; start on trk 1, sect 1, hd 0 (3 alc) ; dpb 1024,10,40,2048,192,1 ; sect# 1 to 5 ; db 5 ; ; db 'Morrow MD3' ; MFM$tbl$entries equ ($-MFM$table)/32 db -1 ; mark end of table dbCP/M ; ^H cursor left ; ^L cursor right ; ^J cursor down ; ^K cursor up ; ^Z home and clear screen ; ^M carrage return ; ^G bell ; ; ADM31 ; ; ; ESC = row col cursor position ; ESC ESC ESC color set color ; added for C128 CP/Mk 1 sector 1 (2 alc) dpb 512,8,40,1024,64,1 ; sect# 1 to 8 db 8 ; db ' IBM-8 SS ' ;3 ; 160 allocation units db S512*2+(8*2-8)+1 ; 512 byte sect 8 sect/trk db MFM+S512+Type2+C0+S1 ; DSDD dw 0 ; start on track 1 sector 1 (1 al4+Type0+C0+S1 ; SSDD dw 0 ; start on track 3 sector 1 (2 alc) dpb 1024,5,40,1024,64,3 ; sect# 1 to 5 db 5 ; db 'Osborne DD' ;7 ; 200 allocation units db S512*2+(9*2-8)+1 ; 512 byte sect 9 sect/track (uses 8) db MFM+S512+Type1+C0,2048,128,2 ; db 8 ; db ' None ' ;12 page db -1 db MFM ; dw 0 ; dpb 512,20,40,2048,128,2 ; db 8 ; db ' None ' ;13 db -1 db MFM ; dw 0 ; dpb 512,20,40,2048,128,2 ; db 8 ; db ' None ' ;1 -1 page cseg cur$clk: ds 1 dseg lock$flag ds 1 last$match ds 2 window$info: ds 2 dsk$window equ 12 no$dsk$msg: ;1234567890 db ' Missing ' MFM$match$tbl: ds 2*MFM$tbl$entries ; MFM$count MUST follow this parm MFM$count: ; ESC T clear to end of line ; ESC t clear to end of line ; ESC Y clear to end of screen ; ESC y clear to end of screen ; ESC : home & clear screen ; ESC * home & clear screen ; ESC ) Half intensity on ; ESC ( Half intensity off ; ESC G 4c) dpb 512,8,80,2048,64,1 ; sect# 1 to 8 db 8 ; (top and bottom numbered the same) db ' IBM-8 DS ' ;4 ; 160 allocation units page db S512*2+(10*2-8)+0 ; 512 byte sector, 10 sect/trk db MFM+S512+Type1+C1+S0 ; DSDD dw 0 ; start o+S1 ; DSDD dw 0 ; start on trk 0, sect 1, hd 1 (1 alc) dpb 512,8,80,2048,64,1 ; sect# 1 to 9 db 8 ; (top and bottom numbered the same) db ' Slicer ' ;8 ; 160 allocation units page db S256*2+(16*2-8)+1 ; 256 byte sect, 16 sect/4 page db -1 db MFM ; dw 0 ; dpb 512,20,40,2048,128,2 ; db 8 ; db ' None ' ;15 db -1 db MFM ; dw 0 ; dpb 512,20,40,2048,128,2 ; db 8 ; db ' None ' ;16 page ; ; not functional yet ; ; d ds 1 ; MFM$offset MUST follow this parm MFM$offset: ds 1 MFM$cur$ptr: ds 2 DPH$pointer: ds 2 sect$cnt: ds 1 sect$buf$ptr: ds 2 sect$buffer: ds 4*2 local$DMA: ds 2 status$atr equ 0 offset: db 0 end  Reverse video on ; ESC G 2 Blinking on ; ESC G 0 Rev. video and blinking off ; ESC E Insert line ; ESC Q Insert Character ; ESC R Delete Line ; ESC W Delete Character ; ^H cursor left ; ^L cursor right ; ^J cursor down ; ^K cursor up > is defined as: ; 0=reverse video ; 1= ; 2= ; 3= ; ; ; ; The following two sequences are ; use but I do not know what function ; they perform. (added 21 May 86) ; ; ESC D atribute off ; esc$C: call cont$later lxi b,4*256+4 ; max+1 num, offset jr esc$num$cont ; ; ; ^Z home and clear screen ; ^M carriage return ; ^G bell ; page ; ; KPRO II Terminal control sequences ; ; ; Cursor Control ; ; ^H cursor left (bs) ; ^L cursor right ; ^J cursor down ; ^K cursor up ; ^^ home cursor ; ^Z home cursor & 2> ; ESC L ; page dseg ; ; ; ?out40: mvi a,FR$40 lxi h,parm$area$40 jr out$cont ; ; ; ?out$80: xra a ; 80 column offset is 0 lxi h,parm$area$80 out$cont: sta fun$offset mvi a,7fh anam mov l,a pchl page ; ; ; cont$later: pop h ; get address to cont at in H jr save$exec$adr ; save it ; ; ; remove$exec$adr: lxi h,0 save$exec$adr: xchg lhld parm$base mov m,e inx h mov m,d ret ; ; ; esc$esc: clear screen lxi d,lines*256+0 ; B=24(row) C=0(col) TCALL FR$cursor$pos call esc$t ; clear the status line lxi d,0 TCALL FR$cursor$pos esc$y: TJMP FR$CES ; clear to end of screen home$cursor: lxi d,0 TJMP FR$cursor$pos esc$tESC B atribute on ; esc$B: call cont$later lxi b,4*256+0 ; max+1 num, offset jr esc$num$cont ; ; Set Attribute sequence ; esc$G: call cont$later lxi b,5*256+8 ; max+1 num, table offset esc$num$cont: call remove$exec$adr sui '0'clear screen ; ^M carriage return ; ; Cursor Positioning ; ; ESC = R C (R & C =' '+position) ; ; Line Insert/Delete ; ; ESC E Line Insert ; ESC R Line Delete ; ; Clear to End of Screen/Line ; ; ^X Clear to End of Line ; ^W Clear to End of Sc c mov c,a shld parm$base lhld emulation$adr pchl page ; ; ADM-31 terminal emulation ; ADM31: lhld parm$base ; 1st parm is exec adr (2 bytes) mov a,m inx h mov h,m mov l,a ora h ; L is in A already, test HL=0 mov a,c ; call cont$later ; ; check for ESC ESC ESC ; cpi esc ; check if 3rd char is an ESC jrnz remove$exec$adr call cont$later ; ; set current character as the attr ; mov b,a TCALL FR$color jr remove$exec$adr page ; ; ; esc$equ: cal: TJMP FR$CEL ; clear to end of line ; ; ; do$cr: TJMP FR$do$cr ; ; ; cursor$rt: TJMP FR$cursor$rt ; ; ; cursor$up: TJMP FR$cursor$up ; ; ; cursor$down: TJMP FR$cursor$down ; ; ; cursor$left: TJMP FR$cursor$left ; remove ascii bias cmp b ; number of functions rnc add c ; get offset mov c,a mvi b,0 lxi h,esc$num$tbl jmp find$exec$adr page ; ; ; esc$D: esc$L: call cont$later ; wait for num1 call cont$later ; wait for num2 call creen ; ; Set Greek or ASCII (not supported) ; ; ESC A Set ASCII ; ESC G Set Greek (lower case letters print as Greek Alphabet) ; ; KAYPRO 84 (???) screen commands ; ; ESC B turn attrubute on ; ESC C turn attrubute off ; ; where atribute o? half bright ON dw esc$b$2 ; ESC B2 ??? blink ON dw esc$b$3 ; ESC B3 ??? under line ON dw esc$c$0 ; ESC C0 reverse video OFF dw esc$c$1 ; ESC C1 ??? half bright OFF dw esc$c$2 ; ESC C2 ??? blink OFF dw esc$c$3 ; ESC C3 ??? under line Oity down jr set$atr$off ; ; Rev. Video, blink, atl char set, and underline off ; esc$G$0: mvi c,10000000b ; turn attributes off mvi b,11110000b ; attribute bit to change jr set$FR$attr ; ; Select alt character set ; esc$G$1: mvi b,set$atr$off ; ; turn reverse video off ; esc$C$0: mvi b,01000000b ; attribute to turn off set$atr$off: mov a,b cma ana b mov c,a TJMP FR$attr page ; ; table scanned top to bottom ; control$table: db 07h ; ^G bell db bs ; ^He scanned top to bottom ; esc$table: db '=' ; ESC = R C db 'T' ; ESC T clear to end of line db 't' ; ESC t clear to end of line db 'Y' ; ESC Y clear to end of screen db 'y' ; ESC y clear to end of screen db ':' ; ESC : homeff dw esc$B ; ESC B atribute on dw esc$G ; ESC G 4 Reverse video on ; ESC G 2 Blinking on ; ESC G 0 Rev. video and blinking off dw esc$lfp ; ESC ( Half intensity off dw esc$rtp ; ESC ) Half intensity on dw esc$W ; ESC WFF dw esc$g$0 ; ESC G0 clear attributes (all G functions) dw esc$g$1 ; ESC G1 alt char set dw esc$g$2 ; ESC G2 blink attr on dw esc$g$3 ; ESC G3 underline attr on dw esc$g$4 ; ESC G4 reverse video on 10000000b ; select alt character set jr set$atr$off ; ; Blinking On ; esc$B$2: ; turn flash ON ??? esc$G$2: mvi b,00010000b ; turn on blink attr jr set$atr$on ; ; ; esc$C$2: ; turn flash OFF ??? mvi b,00010000b jr set$atr$off ; cursor left db lf ; ^J cursor down db 0Bh ; ^K cursor up db 0Ch ; ^L cursor right db cr ; ^M carrage return db 1Ah ; ^Z home and clear screen db esc ; ESC db 18h ; ^X Clear to End of Line (K-Pro) db 17h ; ^W Clear to End of Screen & clear screen db '*' ; ESC * home & clear screen db 'E' ; ESC E Insert line db 'Q' ; ESC Q Insert Character db 'R' ; ESC R Delete Line db 'W' ; ESC W Delete Character db ')' ; ESC ) Half intensity on db '(' ; ESC ( Delete Character dw esc$R ; ESC R Delete Line dw esc$Q ; ESC Q Insert Character dw esc$E ; ESC E Insert line dw char$cnt$z ; ESC * home & clear screen dw char$cnt$z ; ESC : home & clear screen dw esc$y ; ESC y clear to end ; ; title 'C128 external Disk drive support 28 Apr 86' ; ; This program contains the stubs for bringing up the C128 CP/M ; for the first time. ; ; The method used to stub the system I/O is to send the ; operation request to the serial port as a; Under line ; esc$B$3: ; turn underline ON ??? esc$G$3: mvi b,00100000b ; turn on underline bit jr set$atr$on ; ; ; esc$C$3: ; turn under line OFF ??? mvi b,00100000b jr set$atr$off ; ; Reverse Video On ; esc$B$0: esc$G$4: mvi b,(K-Pro) db 1Eh ; ^^ home cursor (K-Pro) cnt$tbl$lng equ $-control$table ; ; table scanned bottom to top ; control$exec$adr: dw home$cursor ; ^^ home cursor (K-Pro) dw esc$y ; ^W CES (K-Pro) dw esc$t ; ^X CEL (K-Pro) dw char$esc ; ESHalf intensity off db 'G' ; ESC G 4 Reverse video on ; ESC G 2 Blinking on ; ESC G 0 Rev. video and blinking off db 'B' ; ESC B atribute on db 'C' ; ESC C atribute off db esc ; ESC ESC db 'D' ; ESC D ??? db 'L' ; Eof screen dw esc$y ; ESC Y clear to end of screen dw esc$t ; ESC t clear to end of line dw esc$t ; ESC T clear to end of line dw esc$equ ; ESC = RC ; ; ; esc$num$tbl: dw esc$b$0 ; ESC B0 reverse video ON dw esc$b$1 ; ESC B1 ?? command and ; recieve responce from the serial channel. ; ; The commands supported are: ; ; CMD: 'I' ; input keyboard char ; RSP: xx ; returns keybord char or 00 if none ; ; CMD 'O'xx ; send char xx to display ; RSP: xx ; echo character ; ; CM,RMdsk page ; ; DRVTBL.ASM ; CSEG ; place code in common memory @dtbl: dw cmdsk0 ;* drive A 1541/1571 dw cmdsk1 ;* drive B 1541/1571 dw cmdsk2 ;* drive C 1541/1571 dw cmdsk3 ;* drive D 1541/1571 dw cmdsk4 ;* drive E shar the command was bad. at this point extrnal system ; is ready to receive a valid command. ; CSEG resync: mvi c,0dh call send$c call get cpi '.' jrnz resync mvi c,'O' call send$c mvi c,07 ; beep the bell call send$c call get ; DE mov m,c ; save C in proper bank sta force$map ; force the old bank back ret endif page ; ; ; dseg dsk$error: call resync lda error$count dcr a sta error$count rnz ; return to retry address inr a ; A=1 if hard ef back ret endif page ; ; compute check sum and adjust byte count ; dseg do$sum: mov b,a lda check$sum ; get the current sum add b ; add in new byte sta check$sum ; save new sum lda count ; get byte count dcr a ; one leD: Rttss ; read sector of data adr by track (tt) sector (ss) ; RSP: xx..yy ; returns 128 bytes of data plus a check sum ; ; CMD: Wttssxx..yy ; write sector of data, sent with a check sum ; ; to (xx..yy) adr by track (tt) sector (ss) ; RSP: xx ;es drive A dw 0 ;* drive F dw 0 ;* drive G if EXTSYS dw @fdsd0 ;* drive H (external RS232) else dw 0 ;* drive H endif dw 0 ;* drive I dw 0 ;* drive J dw 0 ;* drive K dw 0 ;* drive L dw RMdsk ;* drive M should be a bell code cpi 07 rz call get jr resync ; ; CXDISK.ASM ; ; ; ; dseg fd$read: mvi a,10 sta error$count ; set retrys to 10 retry$read: lxi h,retry$read push h ; save retry address on the stack mvi a,'R' rror pop h ; remove retry address on error ret error$count: db 0 page ; ; ; dseg fd$write: mvi a,10 sta error$count ; set retrys to 10 retry$write: lxi h,retry$write push h mvi a,'W' call set$up$dsk ; send command, trackss to get sta count ; save for later ret ; zero flag set if DONE check$sum: db 0 count: db 0 ; ; send the command, track and sector to the external system ; set count to 128 bytes, clear the checksum and set HL to ; the DMA address ; xx=00 if no error ; page maclib cpm3 maclib z80 maclib cxequ public ?int65,?in65,?ins65,?out65,?outs65 extrn ?intbd ; Utility routines in standard BIOS extrn ?pmsg ; print message @ up to 00 ; saves & exMemory Disk (RAM disk) dw 0 ;* drive N dw 0 ;* drive O dw 0 ;* drive P if EXTSYS CSEG ; ; Extended Disk Parameter Headers (XPDHs) ; dw fd$write dw fd$read dw fd$login dw fd$init db 0 ; relative drive zero db 0 ; formcall set$up$dsk ; send command, track and sector read$loop: call get if banked call put$byte$de$bank ; save byte disk bank mov a,c else mov m,a endif inx h call do$sum jrnz read$loop call get lda check$sum cmp c jr and sector write$loop: if banked call get$byte$de$bank else mov c,m endif call send$c ; leaves sent char in A inx h call do$sum jrnz write$loop lda check$sum call send$a call get ora a ; A=0 if no errors jrnz dsk$e set$up$dsk: call send$a ; send the comand lda @trk call send$a ; send the track lda @sect call send$a ; send the sector xra a sta check$sum mvi a,80h sta count ; transfer 128 bytes lhld @dma ; HL = current DMA address if batrn ?pdec ; print binary number in from 0 to 99. extrn ?pderr ; print BIOS disk error header extrn ?conin,?cono ; con in and out extrn ?const ; get console status ; ; drive table ; public @dtbl extrn cmdsk0,cmdsk1,cmdsk2,cmdsk3,cmdsk4at type byte @fdsd0: dph sk128sssd,dpb$8$sssd ; ; DPB FOR 8 IBM 3740 format ( 243K ) ; dpb$8$sssd: dpb 128,26,77,1024,64,2 sk128sssd: skew 26,6,1 page ; ; send an illegial command, should get a period back, meaning ; that thenz dsk$error pop h ; remove retry address xra a ; A=0 (no errors) ; ; fd$init: fd$login: ret ; ; ; if banked cseg put$byte$de$bank: lda force$map ; read current MMU configuration stax d ; force to preconfig reg adr inrror pop h ; remove error address ret ; A=0 (no errors) if banked cseg get$byte$de$bank: lda force$map ; read current MMU configuration stax d ; set current disk bank (in DE) mov c,m sta force$map ; write current MMU connked lxi d,bank$0 ; start by pointing to bank 0 lda @dbnk ; get the current disk I/O bank ora a ; is it set to bank 0 rz ; yes, return inx d ; no, point to bank 1 endif ret page ;=================================================op if NOT lda key ; get the key code push psw ; save on stack xra a ; clear key sta key pop psw ; recover current key ret page ;========================================================== ; CHARACTER DEVICE INPUT STATUS ;=========== ;========================================================== ; EXTERNAL DEVICE LOW LEVEL DRIVERS ;========================================================== ; ; ; dseg get: call in$stat jrz get dcx b ; point to data reg (RxD) inp a 51 to user port ; this is done by init'ing the out data to an input ; and then setting DTR ; lxi b,CIA2+data$dir$a inp a ori 100b ; make TxD bit (2) an input outp a endif lhld usart$adr mov b,h mov c,l inx b ; point to status rut status lhld usart$adr mov b,h mov c,l inx b ; point to status register inp a ani rxrdy rz ori -1 ret ;========================================================== ; CHARACTER DEVICE OUTPUT ;================================================ ; CHARACTOR INITILIZATION ROUTINES ;========================================================== ; ; ; dseg ; ; set external system com rate to 19.2 K baud ; ?int65: init$ext: lhld usart$adr mov b,h mov c,l inx b inx b ; =============================================== ; ; ; dseg ?ins65: ; character input status lda key ; is there already a key ora a jrnz ret$true ; yes, return true mvi a,'I' ; no, test if any typed call send$a call get ; get key mov c,a ret ; ; ; send$c: mov a,c send$a: push psw ; save the character to be output send$loop: call out$stat jrz send$loop pop psw dcx b : point to data register (TxD) outp a ret ; ; ; in$stat: lhld usart$adr mov b,h meg outp a ; software reset (wr to stat reg) inx b ; point to Command register mvi a,cmd$init ; set DTR active outp a inx b ; point to Control register lda ?int$bd ; get 6551 baud rate ori 10h ; use baud rate generator outp a =================== ; the charactor to be output is in the C register ; ; ; dseg ?out65: ; character output mov a,c push psw call ?outs65 jrz ?out65 pop psw dcx b ; point to data register outp a ret ;======================point to command reg mvi a,cmd$init outp a inx b ; point to control reg mvi a,cntr$init$19200 ; baud rate equ 19200 outp a dcx b ; (02) dcx b ; (01) inp a ; read status dcx b ; (00) inp a ; read hung data ret page ora a ; =0 if none rz ; return character not advaliable sta key ; was one, save in key ?outs65: ret$true: ori 0ffh ret key: db 0 page ;========================================================== ; CHARACTER DEVICE OUTPUT ;========ov c,l inx b ; point to status register inp a ani rxrdy ret ; ; ; out$stat: lhld usart$adr mov b,h mov c,l inx b ; point to status register inp a ani txrdy ret else ;======================================================== ; 1 stop (7=0), 8 bits (65=0) ret page ;========================================================== ; CHARACTOR INPUT ROUTINES ;========================================================== ; ; ; dseg ?in65: characte input call ?ins6==================================== ; CHARACTER DEVICE OUTPUT STATUS ;========================================================== ; ; ; dseg ?outs65: ; character input status lhld usart$adr mov b,h mov c,l inx b ; point to status registe ;========================================================== ; CHARACTOR INPUT ROUTINES ;========================================================== ; ; ; dseg ?in65: characte input call ?ins65 ; check for character adv. jrz ?in65 ; lo================================================== ; the charactor to be output is in the C register ; ; ; dseg ?out65: ; character output mov a,c push psw mvi a,'O' call send$a pop psw call send$a ; jmp get ; fall thru to GET== ; CHARACTOR INITILIZATION ROUTINES ;========================================================== ; ; ; dseg ; ; set com rate to value in ?int$bd ; (may need to change rate if not supported) ?int65: init$ext: if use$6551 ; ; must gate 655 jrz ?in65 dcx b ; point to data reg inp a ret ;========================================================== ; CHARACTER DEVICE INPUT STATUS ;========================================================== ; ; ; dseg ?ins65: ; character inpr inp a ani txrdy rz ori -1 ret endif end to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Th10 ; set$test$start$bit: lxi h,test$start$bit ;10 shld recv$state+1 ;16 ret ;10 page ; ; T states 28 if DAV still set ; T states 89 to move char from que to recv$data ; que$to$data: lda RS232$status ;13 rrc ;4 rc ;5/11 push h ;11 ; lxi b,CIA$1+int$ctrl ;10 inp a ;12 clear CIA$1 interrupts ; if not use$6551 lxi b,CIA2+data$a ;10 inp a ;12 out$rs232$cia equ $+1 setb 2,a ;8 this instruction gets modified outp a ;12 inr c ;4 point t ret ;10 page ; ; test for false start ; ; T states 72 if valid start ; T states 52 if false start ; test$start$bit: rar ;4 jrc set$recv$idle ;7/(12+36) RxD in carry bit lxi h,RS232$status ;10 setb 1,m ;15 set receiving dat page ; ; T states 52 start bit ; T states no start bit, que inactive ; T states no start bit, que active, DAV set ; T states no start bit, que active, DAV cleared ; recv$idle: rar ;4 jrnc set$test$start$bit ;7/(12+36) ;11+12+31=5 title 'Interrupt handler 29 Apr 86' maclib z80 maclib cxequ public ?sysint done$scan: equ 11110111b clear$TxD$bit: equ 10010111b ; 2nd byte of res 2,a set$TxD$bit: equ 11010111b ; 2nd byte of setb 2,a buf$end equ lo lxi h,RxD$buf$get ;10 mov l,m ;7 mov a,m ;7 sta recv$data ;13 mvi a,adjust$cnt-test$que ;7 sta RxD$unque+1 ;13 set next sub state ret ;10 ; ; T states 82 count not zero ; T states 99 count becomes zero ; adjust$cnt: o data$b (C=1) inp a ;12 mov h,c ;4 set H=1 recv$state: call recv$idle ;17+(153max,54min) send$state: call send$idle ;17+(136max,28min) dcr h ;4 did H=1 ? lxi h,current$key$delay ;10 jnz skip$keyboard ;10 page ; ; Ta flag lxi h,start$idle$1 ;10 shld recv$state+1 ;16 ret ;10 ; ; T states 36 ; set$recv$idle: lxi h,recv$idle ;10 shld recv$state+1 ;16 ret ;10 ; ; T states 93 ; start$idle$1: xra a ;4 sta recv$bit+2 ;13 lda Xx4 ; RxD$unque: ;(36)+12+(105) = 153 max jr test$que ;12 ; ; T states 31 no process required ; T states 91 que count adjusted (not empty) ; t states 105 que count adjusted (empty) ; test$que: lda RS232$status ;13 no processing req if QUEw(RxD$buffer+RxD$buf$size) page ; ; The DE register is not changed by the interrupt handler ; ; maximun of T states advaliable per interrupt ; DMA uses about 10 % (or ) leaving only ; interrupt vectoring use a few more. ; ; if both r xra a ;4 lxi h,RxD$buf$count ;10 dcr m ;11 mvi l,low(RS232$status) ;7 setb 0,m ;15 set DAV flag jrnz adj$cont ;7/12 res 5,m ;15 que empty turn QUE bit(5) off mvi a,que$empty-test$que ;7 adj$cont: sta RxD$unque+1 ;13 ret ;1 states 32 if not done ; T states 56+ if key scan done ; vector$key$state: dcr m ;11 jrnz exit$int ;7/12 lda int$rate ;13 mov m,a ;7 endif key$state: call key$scan$state ;17+(191max,38min) if not use$6551 db 21h ; lxi h,(D$config ;13 ani 1 ;7 adi 7 ;7 sta RxD$count ;13 lxi h,que$full$test ;10 shld recv$state+1 ;16 ret ;10 page ; ; T states 57 RxD buffer not full ; T states 117 RxD buffer full (send XOFF) ; T states 86 RxD buffer full (XOFF ani 00100000b ;7 bit (5) is clear rz ;5/11 mvi a,que$to$data-test$que ;7 sta RxD$unque+1 ;13 set next sub state lxi h,RxD$buf$get ;10 inr m ;11 mov a,m ;7 cpi buf$end ;7 rnz ;5/11 mvi m,low(RxD$buffer) ;10 ret ;ecv$state and send$state are in idle ; T states 209+82++ (191max,38min) = (482max,329min) ; ; ; if ether recv$state and send$state are active ; T states 209+++ (289max, 82min) = (498max,291min) ; CSEG ?sysint: push psw ;11 push b ;11 0 ; ; T states 52/94 ; que$empty: xra a ;4 offset of zero for JR sta RxD$unque+1 ;13 (to get to test$que) lxi h,xon$xoff$flag ;10 mvi a,XON ;7 cmp m ;7 rz ;5/11 mov m,a ;7 mvi a,send$x-send$norm ;7 sta send$idle+1 ;13 mvi m,1) skip$keyboard: mvi m,1 ; endif exit$int: pop h pop b pop psw ei ret if not use$6551 RxD$count: db 0 ; number of bits left to receive TxD$count: db 0 ; number of bits left to transmit current$key$delay: db 1 sent already) ; que$full$test: lxi h,recv$bit ;10 shld recv$state+1 ;16 lda RxD$buf$count ;13 cpi RxD$buf$size-16 ;7 rc ;5/11 lxi h,xon$xoff$flag ;10 mvi a,XOFF ;7 cmp m ;7 rz ;5/11 mov m,a ;7 set mode to send Xoff inr l ;4 mov a,m ;7 inr a ;4 cpi buf$end ;7 jrnz put$buf$ok ;7/12 mvi a,low(RxD$buffer) ;7 put$buf$ok: mov m,a ;7 mov l,a ;4 RxD$data equ $+1 mvi a,00 ;7 mov m,a ;7 lxi h,test$RxD$stop$que ;10 shld recv$state+1 ;16t$idle: lxi h,recv$bit$idle ;10 shld recv$state+1 ;16 ret ;10 ; ; T states 36+(28/105) ; recv$bit$idle: lxi h,recv$bit ;10 shld recv$state+1 ;16 jmp RxD$unque ;10 page ; ; T states 36+(28/105) ; enter$RxD$parity: lxi rnc ;5/11 lxi h,start$send$1 ;10 shld send$state+1 ;16 mvi a,clear$TxD$bit ;7 sta out$rs232$cia ;13 send the start bit ret ;10 ; ; T states 12+118 ; send$x: xon$xoff$flag equ $+1 mvi a,XON ;7 sta send$bits+1 ;13 xtoggle it test$odd$even: ;35/ lda recv$bit+2 ;13 aci 0 ;7 ana a ;4 rpe ;5/11 parity$error: ;35 lxi h,RS232$status ;10 setb 4,m ;15 set parity error ret ;10 ; ; T states 36 ; RxD$parity$idle: lxi h,enter$RxD$stop mvi a,send$x-send$norm ;7 sta send$idle+1 ;13 ret ;10 ; ; T states 64 ; recv$bit: rar ;4 mvi a,00 ;7 RxD in carry bit rar ;4 move data bit into MSB sta recv$bit+2 ;13 lxi h,recv$bit$done$test ;10 shld recv$state+1 ;16 ret page ; ; T states no errors ; T states framing error ; test$RxD$stop$que: rar ;4 mvi a,00100000b ;7 jmp test$RxD$cont ;10 ; ; T states no errors ; T states framing error ; test$RxD$stop$dav: rar ;4 mvi ah,test$RxD$parity ;10 shld recv$state+1 ;16 jmp RxD$unque ;10 ; ; T states bit hi ; T states bit low ; test$RxD$parity: lxi h,RxD$parity$idle ;10 RxD data bit in carry shld recv$state+1 ;16 rar ;4 lda XxD$config ;13 jrc RxDra a ;4 sta send$idle+1 ;13 mvi a,clear$TxD$bit ;7 sta out$rs232$cia ;13 send the start bit lxi h,RS232$status ;10 setb 6,m ;15 flag send bussy lxi h,start$xon$xoff ;10 shld send$state+1 ;16 ret ;10 page ; ; T states 10;10 shld recv$state+1 ;16 jmp RxD$unque ;10 page ; ; T states 90 if que not in use and DAV is cleared ; T states 149/151 if data placed in que ; enter$RxD$stop: lda RS232$status ;13 ani 00100001b ;7 DAV set or data in que? jrnz pl ret ;10 ; ; T states 69 if bits still remaining ; T states ; recv$bit$done$test: lxi h,RxD$count ;10 dcr m ;11 jrnz enter$recv$bit$idle ;7/(12+36) lda XxD$config ;13 rlc ;4 lxi h,enter$RxD$stop ;10 jrnc do$test$stop ;,00000001b ;7 test$RxD$cont: jrc good$RxD$stop ;7/12 ori 00001000b ;7 set framing error good$RxD$stop: lxi h,RS232$status ;10 ora m ;7 ani 11111101b ;7 clear recv active flag bit mov m,a ;7 lxi h,recv$idle ;10 shld recv$state+1 $parity$hi ;7/12 rlc ;4 rlc ;4 mark space mode ? jrnc test$parity$space ;7/(12+15/46) yes, go test it rlc ;4 get odd even mode jr test$odd$even ;12+35/54 ; test$parity$space: ;15/ rlc ;4 rnc ;5/11 jr parity$error ;7 ; start$send$1: lda xmit$data ;13 sta send$bits+1 ;13 lxi h,RS232$status ;10 mov a,m ;7 xri 0C0h ;7 clear bit 7 and set bit 6 mov m,a ;7 start$xon$xoff: lda XxD$config ;13 ani 1 ;7 adi 7 ;7 sta TxD$count ;13 enter$sace$in$que ;7/12 yes, place new char in que lda RxD$data ;13 no, place char in data reg. sta recv$data ;13 lxi h,test$RxD$stop$dav ;10 shld recv$state+1 ;16 ret ;10 ; place$in$que: ;116/118 lxi h,RxD$buf$count ;10 inr m ;11 7/12 lxi h,enter$RxD$parity ;10 do$test$stop: shld recv$state+1 ;16 ani 1*2 ;7 A=0 if 7 bits else 8 bits lda recv$bit+2 ;13 jrnz done$adj ;7/12 rrc ;4 done$adj: sta RxD$data ;13 ret ;10 ; ; T states 36 ; enter$recv$bi ;16 ret ;10 page ;* ;* T states stay in idle state ;* T states exit idle state (recv buffer not full) ;* T states exit idle state (recv buffer full) ;* send$idle: jr send$norm ;12 send$norm: lda RS232$status ;13 rlc ;4 12+25 ; test$parity$mark: ;15/ rlc ;4 rc ;5/11 jr parity$error ;12+25 page ; RxD$parity$hi: ;4 rlc ;4 rlc ;4 mark/space mode ? jrnc test$parity$mark ;7/12 yes, go test it rlc ;4 get odd/even flag cmc ;4 end$bits: lxi h,start$bit$idle ;10 shld send$state+1 ;16 ret ;10 ; ; T states 36 ; start$bit$idle: lxi h,send$bits ;10 shld send$state+1 ;16 ret ;10 ; ; T states 94 data bit low ; T states 92 data bit hi ; send$bits: no new key and no state change ; scan$VIC: mvi a,11101110b ;7 lxi h,key$scan$tbl ;10 get current new table pointer lxi b,vic$key$row ;10 outp a ;12 rlc ;4 sta scan$VIC+1 ;13 jrnc normal$8 ;7/12 lxi b,key$col ;10 cont$read:lda XxD$config ;13 rlc ;4 jrnc TxD$stop ;7/(12+56) lxi h,TxD$parity$idle$1 ;10 shld send$state+1 ;16 rlc ;4 jrnc send$mark$space ;7/(12+16+42/44) rlc ;4 lda send$bits+1 ;13 aci 0 ;7 ana a ;4 mvi a,set$TxD$bit ;7 jnt equ $+1 mvi a,00 ;7 ora a ;4 rz ;5/11 lxi h,repeat$count ;10 dcr a ;4 yes, test for repeat yet jrnz not$repeat$yet ;7/(12+(42/56)) ; ; the following 4 lines of code may NOT be changed. ; CONF.COM looks for them to change thetop$idle+1 ;13 rnz ;5/11 lxi h,RS232$status ;10 res 6,m ;15 lxi h,send$idle ;10 shld send$state+1 ;16 ret ;10 endif page ; ; ; Key$Scan$State: jr scan$CIA ;12 ; ; T states no new key down ; T states state mvi a,00 ;7 rrc ;4 sta send$bits+1 ;13 lxi h,count$TxD ;10 shld send$state+1 ;16 send$TxD: ;42/44 mvi a,set$TxD$bit ;7 jrc send$hi$bit ;7/12 mvi a,clear$TxD$bit ;7 send$hi$bit: sta out$rs232$cia ;13 ret ;10 ; ; T s inp a ;12 0FFh if no key down inr m ;11 mov l,m ;7 mov b,m ;7 get old value in B mov m,a ;7 save new value xra b ;4 get differances ana b ;4 test for only new keys down rz ;5/11 sta matrix$byte ;13 lxi hpo send$TxD$parity ;10 mvi a,clear$TxD$bit ;7 send$TxD$parity: sta out$rs232$cia ;13 ret ;10 ; send$mark$space: rlc ;4 jr send$TxD ;12+42/44 ; ; T states 36 ; TxD$parity$idle$1: lxi h,TxD$parity$idle$2 ;10 shld send$state repeat rate. ; also looks for RET ; MVI A,xx ; STA xxxx (see set$key$parm) ; mvi m,3 ;10 lxi h,save$key ;10 shld key$state+1 ;16 ret ;10 ; not$repeat$yet: ;42/56 mov m,a ;7 matrix$pos equ $+1 lda Key$scan$tbl ;13 repeat$mask change ; T states new key down ; scan$CIA: stc ;4 mvi a,11111110b ;7 data field updated by code lxi b,key$row ;10 outp a ;12 cpi 11111111b ;7 jrz extra$3 ;7/12 carry=0 if A=11111111 ral ;4 sta scan$CIA+1+1 ;13 lxi htates if more data bits to send ; T states if done sending bits ; count$TxD: lxi h,TxD$count ;10 dcr m ;11 jrnz enter$send$bits ;7/12 lxi h,TxD$parity$wait ;10 shld send$state+1 ;16 ret ;10 page ; ; T states 36 ; TxD$par,key$found ;10 shld key$state+1 ;16 ret ;10 ; ; normal$8: ; mvi a,scan$CIA-scan$CIA ;7 xra a ;4 sta Key$Scan$State+1 ;13 mov m,l ;7 reset current table pointer lxi h,Key$Repeat$State ;10 shld key$state+1 ;16 ret ;10 +1 ;16 ret ;10 ; ; T states 36 ; TxD$parity$idle$2: lxi h,TxD$stop ;10 shld send$state+1 ;16 ret ;10 page ; ; T states 103/101 ; TxD$stop: lxi h,TxD$stop$idle ;10 shld send$state+1 ;16 mvi a,set$TxD$bit equ $+1 mvi b,00 ;7 ana b ;4 key still down? (A=0) rz ;5/11 yes, exit for now mvi m,0 ;10 ret ;10 page ; ; T states 101 flash ; T states 72 no flash ; flash$wait: mvi a,01 ;7 dcr a ;4 sta flash$wait+1 ;13 j,key$scan$tbl ;10 get current new table pointer inr c ;4 point to KEY$COL (input) jmp cont$read ;10 ; extra$3: ral ;4 sta scan$CIA+1+1 ;13 mvi a,scan$VIC-scan$CIA ;7 sta Key$Scan$State+1 ;13 ret ;10 page ; ; T states ity$wait: lxi h,TxD$parity ;10 shld send$state+1 ;16 ret ;10 ; ; ; T states 85 if no parity ; T states 124 if mark parity ; T states 126 if space parity ; T states 136 if even parity ; T states 129 if odd parity ; TxD$parity: page ; ; T states 48 repeat not active ; T states 124 testing repeat (key realeased) ; T states 110 testing repeat (not found) ; T states 109 testing repeat (found) ; Key$Repeat$State: lxi h,flash$wait ;10 shld key$state+1 ;16 repeat$cou;7 sta out$rs232$cia ;13 lda XxD$config ;13 ani 2 ;7 jrnz one$stop$bit ;7/12 mvi a,5 ;7 one$stop$bit: inx h ;6 mov m,a ;7 ret ;10 ; ; T states 35/90 ; TxD$stop$idle: mvi a,00 ;7 dcr a ;4 sta TxD$srnz no$flash ;7/(13+36) mvi a,5 ;7 sta flash$wait+1 ;13 lxi h,flash ;10 shld key$state+1 ;16 ret ;10 ;* ;* ;* T states 135 if cursor off screen ;* T states 119 if cursor on screen ;* flash: lda force$map ;13 sta bank$0 repeat$count ;13 number of counts for repeat lda key$scan$tbl ;13 sta matrix$pos ;13 lda mask$value ;13 sta repeat$mask ;13 lxi h,build$cntr$byte ;10 shld key$state+1 ;16 ret ;10 ; ; T states ; build$cntr$byte: lda key$sca ;7/(12+70) mvi a,00010000b ;7 jr is$common ;12+66 ; ; check$low$4: ;138/128/133/139 mov a,b ;4 ani 00001111b ;7 jrz exit$found ;7/12 ani 00001100b ;7 jrz check$1$and$0 ;7/12+(96/102) ani 00001000b ;7 mvi c,2 ;7 jrnz is$ointer does not equal 0ffh ; insert new character at (put pointer) ; and character control byte at (put pointer)+1 ; ; T states 38 if buffer is full ; T states 146/148 ; save$key: lhld key$put$ptr ;16 get put pointer mov a,m ;7 get byte (pointer) add a ;4 add a ;4 add a ;4 shift left 3 bits add b ;4 add in bit position sta key$code ;13 save as the key code lxi h,remove$special$keys ;10 shld key$state+1 ;16 ret ;10 page ; ; T states if not a shif ;13 mov b,a ;4 ; ; toggle 40 column screen cursor on/off ; lhld flash$pos ;16 xra a ;4 clear A ora h ;4 return if H=0 jrz exit$flash ;7/12 mov a,m ;7 xri 80h ;7 mov m,a ;7 exit$flash: mov a,b ;4 sta force$map ;13 n$tbl+1+7 ;13 get control byte row cma ;4 ani 04h ;7 test control key bit jrz not$control ;7/12 mvi a,7 ;7 not$control: mov b,a ;4 lda key$scan$tbl+1+6 ;13 get rigth shift byte row cma ;4 ani 10h ;7 test right key bit add$1 ;7/(12+70) mvi a,00000100b ;7 jr is$common ;12+66 ; check$1$and$0: ; mov a,b ;4 ani 00000010b ;7 mvi c,0 ;7 jrnz is$add$1 ;7/(12+70) inr a ;4 set A=1 jr is$common ;12+66 ; ; is$add$1: ;70 inr c ;4 is$commo from buffer inr a ;4 room in buffer? (-1 if so) rnz ;5/11 no, wait for room in buffer key$code equ $+1 mvi m,00 ;10 get matrix position inr l ;4 ctrl$byte equ $+1 mvi a,00 ;7 mov m,a ;7 inr l ;4 mov a,l ;4 cpi lt of control key ; T states 68/82/96 if cntr / rt_shift / lf_shift ; remove$special$keys: lxi h,key$found ;10 lda key$code ;13 cpi 38h+2 ;7 control key pressed ? jrz bad$key ;7/12 cpi 30h+4 ;7 jrz bad$key ;7/12 cpi 08h+7 ;7 no$flash: lxi h,Key$Scan$State ;10 shld key$state+1 ;16 ret ;10 page ; ; ; key$found: ;148/138/157/147/166/156/161/167 matrix$byte equ $+1 mvi b,00 ;7 mov a,b ;4 ani 11110000b ;7 jz check$low$4 ;10+(138/128/133/139) ani ora b ;4 mov b,a ;4 lda key$scan$tbl+1+1 ;13 get left shift byte row cma ;4 ani 80h ;7 test left key bit ora b ;4 mov b,a ;4 ani 90h ;7 either shift key down? mov a,b ;4 jrz no$shift ;7/12 no, jump ori 2 ;7 n: ;66 sta mask$value ;13 mov a,c ;4 sta bit$value ;13 lxi h,key$found$2 ;10 shld key$state+1 ;16 ret ;10 ; exit$found: lxi h,Key$Scan$state ;10 shld key$state+1 ;16 ret ;10 page ; ; T states ; key$found$2: lxi ow(key$buffer+key$buf$size) ;7 jrnz put$ptr$ok ;7/12 mvi a,low(key$buffer) ;7 put$ptr$ok: sta key$put$ptr ;13 adjust the low byte of the put ptr lxi h,Key$tick ;10 shld key$state+1 ;16 ret ;10 ; ; T states ; key$tick: lxi b,sid+2 jrz bad$key ;7/12 lxi h,set$key$parm ;10 bad$key: shld key$state+1 ;16 ret ;10 ; ; T states ; ; do not change the next 2 lines. CONF uses them to ; the set repeat rate. (also RET above here) ; set$key$parm: mvi a,8 ;7 sta 11000000b ;7 jrz check$5$and$4 ;7/(12+(110/100)) ani 10000000b ;7 mvi c,6 ;7 jrnz is$add$1 ;7/(12+70) mvi a,01000000b ;7 jr is$common ;12+66 ; check$5$and$4: ;110/100 mov a,b ;4 ani 00100000b ;7 mvi c,4 ;7 jrnz is$add$1 yes, set shift control bit no$shift: sta ctrl$byte ;13 lxi h,save$key ;10 shld key$state+1 ;16 ret ;10 page ; ; ; NOTE: character buffer MUST be on one page ; (and have even number of bytes) ; ; buffer is FULL when data at put ph,matrix$byte ;10 mask$value equ $+1 mvi a,00 ;7 xra m ;7 clear current bit mov m,a ;7 bit$value equ $+1 mvi b,00 ;7 lxi h,key$scan$tbl ;10 get the pointer mov a,m ;7 sub l ;4 remove the bias dcr a ;4 then one extra4 ;10 lda tick$vol ;13 outp a ;12 mvi c,low(sid+11) ;7 mvi a,80h ;7 outp a ;12 inr a ;4 outp a ;12 lxi h,key$scan$state ;10 shld key$state+1 ;16 ret ;10 page ; ;_____ _____ _____ _____ _____ _____ _____ ___print message @ up to 00 ; saves & extrn ?pdec ; print binary number in from 0 to 99. extrn ?pderr ; print BIOS disk error header extrn ?conin,?cono ; con in and out extrn ?const ; get console status extrn @hour,@min,@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> Thest ; ani 0fh ;;;test ; adi 90h ;;;test ; daa ;;;test ; aci 40h ;;;test ; daa ;;;test ; sta hi$test ;;;test ; call trace ;;;test ;hi$test: ;;;test ; db 31 ;;;test ;low$test: ;;;test ; db 31 ;;;test ; db ' ' ;;;test ; db 0 ;;;t__ _____ _____ __________ ; | | | | | | | | | | | | | ; | S | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | P | stop | ; |_____|_____|_____|_____|_____|_____|_____|_____|_____|_____| | sec,@date,?bnksl public ?time page ; ; keyboard scanning routine ; extrn ?get$key,?int$cia extrn Fx$V$tbl ; ; links to 80 column display ; extrn ?out80,?int80 extrn ?out40,?int40 extrn ?pt$i$1101,?pt$o$1,?pt$o$2 extrn ?convt ; eest ; ret ;;;test ; page DSEG ?fun65: sta vic$cmd ; save the command passed in A if not use$6551 fun$di$wait: lda RS232$status ani 11000010b ; char to Xmit, Xmiting or receiving ? jrnz fun$di$wait ; yes, wait for int to clean up ; title 'C128 BIOS, main I/O and sys functions 28 Apr 86' ; ; This module contains CXIO,CXINIT,CXMOVE and CXTIME. ; maclib cpm3 maclib z80 maclib cxequ maclib modebaud public ?init,?ldccp,?rlccp public ?user,?di$i |_ ; ; ; Reciever State Machine ; ; ;_____ _____ _____ _____ _____ _____ _____ _____ _____ _____ __________ ; | | | | | | | | | | | | | ; | S | 0 | 1 | 2 | 3 | 4 | 5 | 6 | xtrn ?pt$s$1101 ; ; bios8502 function routines ; public ?fun65 ; ; ; public ?intbd extrn ?int65,?in65,?ins65,?out65,?outs65 ; cseg ;trace: ; xthl ; save hl on stack ; push psw ; call ?pmsg ; DE and BC saved by ?pmsg ; pop psw ; endif di lda force$map ; get current MMU configuration push psw ; save it sta io$0 ; make I/O 0 current lxi d,1 ; D=0, E=1 if use$fast lxi b,VIC$speed inp a sta sys$speed outp d ; set slow mode (1 2 MHz Z80) endifnt extrn ?sysint bdos equ 5 extrn @civec,@covec,@aivec,@aovec,@lovec extrn ?bnksl public ?cinit,?ci,?co,?cist,?cost public @ctbl extrn ?kyscn ; Utility routines in standard BIOS extrn ?wboot ; warm boot vector extrn ?pmsg ; 7 | P | stop | ; |_____|_____|_____|_____|_____|_____|_____|_____|_____|_____| | |_ ; ; ; Transmitter State Machine (TSM) ; ; ; ; Keyboard Scan State Machine (KSSM) ; xthl ; ret ; ; CSEG ;disp$A: ; push psw ;;;test ; ani 0fh ;;;test ; adi 90h ;;;test ; daa ;;;test ; aci 40h ;;;test ; daa ;;;test ; sta low$test ;;;test ; pop psw ;;;test ; rar ;;;test ; rar ;;;test ; rar ;;;test ; rar ;;;t lxi b,page$1$h outp d dcr c outp e ; page 1, 0-1 dcr c outp d dcr c outp d ; page 0, 0-0 call enable$6502+6 ; go run the 8502 mvi c,low(page$1$h) outp e dcr c outp e ; page 1, 1-1 dcr c outp e dcr c outp d ; pageinstall mode 2 page vectors ; mvi a,JMP sta INT$vector ; install a JMP at vector location lxi h,?sysint shld INT$vector+1 ; install int$handler adr ; ; A software fix is required for the lack of hardware to force the ; LSB of the INT vector art+11-1 ; to to MMU registers mvi d,11 ; move all 11 bytes to the MMU init$mmu$loop: mov a,m outp a dcx h dcx b dcr d jrnz init$mmu$loop mvi a,1 ; enable track and sector status sta stat$enable ; on the status line ; mvi a,1 eq bit outp a ; set new config mvi c,8 ; start RTC outp a lxi h,date$hex shld @date ; set date to system data ; ; setup the sound variables ; lhld key$tbl lxi d,58*4 dad d mov e,m inx h mov d,m inx h xchg shld souown+70h ; set border color db 'Z'-'@' ; home and clear screen (to BG color) db lf,lf,lf if use$fast db 'Fast ' endif if use$6551 db '/w 6551 ' endif db 'CP/M 3.0' if not banked db ' Non-Banked' endif db 0, 1-0 if use$fast lxi b,VIC$speed lda sys$speed ; get desired system speed outp a ; set speed (2 or 4 MHz Z80) endif pop psw ; recover the MMU config. sta force$map ; restore it ei ; turn interrupts back on lda vic$data ; to 0. If the bus floats INT VECT could be ; read as 0FFh; thus ADRh=I (I=0FCh) ADRl=FF for first read, and ; ADRh=I+1 ADRl=00 for second, to ensure that control is retained ; 0FD00h will also have FDh in it. ; lxi h,int$block ; FC00h lxi d,int$blo ; no parity, 8 bits, 1 stop bit sta XxD$config ; if use$6551 lxi h,int$6551 else lxi h,usart endif shld usart$adr lxi h,?convt shld prt$conv$1 shld prt$conv$2 lxi h,Fx$V$tbl shld key$FX$function ; ; install I/O assignmnd1 ; H=SID reg 24, L=SID reg 5 xchg mov e,m inx h mov d,m xchg shld sound2 ; H=SID reg 6, L=SID reg 1 lxi h,9 dad d mov e,m inx h mov d,m xchg shld sound3 ; H=SID reg 4 then L=SID reg 4 ; ; set-up key click sound registe' On the Commodore 128 ' date warning db cr,lf db ' ',0 ; ; set CONOUT driver to correct screen ; lxi h,4000h ; 80 column screen vector call read$d505 ral jrnc set$screen mvi a,'4' sta screen$num mvi h,20h ; 40 coluget command results ora a ; set the zero flag if A=0 ret ?di$int: if not use$6551 push psw di$int$1: lda RS232$status ; character to Xmit or currently ani 11000010b ; ..transmitting or receiving ? jrnz di$int$1 ; yes, wait for int ck+1 ; FC01h lxi b,256-1+1 ; interrupt pointer block mvi m,INT$vector/256 ; high and low are equal (FD) ldir mvi a,INT$block/256 stai ; set interrupt page pointer im2 ; enable mode 2 interrupts page ; ; mvi a,vicinit ; null coments ; lxi h,4000h+2000h ; 80 and 40 column drivers shld @covec mvi h,80h shld @civec ; assign console input to keys mvi h,10h shld @lovec ; assign printer to LPT: mvi h,00h shld @aivec shld @aovec ; assign rdr/pun port page rs ; lxi b,sid+7 lxi h,0040h outp l ; (sid+7)=40h inr c outp l ; (sid+8)=40h mvi c,low(sid+12) outp h ; (sid+12)=0 Attack=2ms, Decay=6ms inr c outp h ; (sid+13)=0 Sustain=0, Release=6ms mvi a,6 sta tick$vol ; set keyclickmn screen vector set$screen: call prt$msg ; HL saved screen$num: db '80 column display',cr,lf,lf,lf,lf,0 shld @covec ; assign console output to CRT: (40/80) page ; ; mvi a,-1 ; set block move to NORMAL mode sta source$bnk ; ; to clean up pop psw endif di ret page ; ; set up the MMU for CP/M Plus ; DSEG ; init done from banked memory ?init: mvi a,3eh ; force MMU into I/O space sta force$map ; lxi h,mmu$table+11-1 ; table of 11 values lxi b,mmu$stmand just to setup BIOS8502 call ?fun65 ; ; ; lda sys$freq ; 0=60Hz 0FFh=50Hz ani 80h ; 0=60Hz 080h=50Hz mov l,a ; save in L lxi b,cia$1+0eh ; point to CRA inp a ; get old config ani 7fh ; clear freq bit ora l ; add in new fr ; ; print sign on message ; call prt$msg ; print signon message db 'Z'-'@' ; initialize screen pointers db esc,esc,esc db purple+50h ; set character color db esc,esc,esc db black+60h ; set background (BG) color db esc,esc,esc db br volumn level ; ; set up interrupts for key scan (not software usart) ; if use$6551 lxi d,2273 ; int at 150 BAUD rate lxi b,CIA1+timer$b$low ; outp e ; inr c ; point to timer$b$high outp d ; mvi a,11h ; mvi c,CIA$ctrl$b ; ; NTSC rates (1.02273 MHz) ; NTSC$baud$table: dw 6818 ; no baud rate (6666.47) db 1 dw 6818 ; 50 6666.7us (6666.47) db 1 dw 4545 ; 75 4444.4us (4443.99) db 1 dw 3099 ; 110 3030.3us (3030.13) db 1 dw 2544 ; 134 2487.6us (2487. shld de$temp ; save DE for called function mov e,a ; place function number in E mvi a,num$user$fun-1 ; last legal function number call vector ; function usr$tb: dw read$mem$0 ; 0 dw write$mem$0 ; 1 dw ?kyscn ; 2 dw do$rom$fun uffer) lxi h,NTSC$baud$table lda sys$freq ora a jrz use$NTSC lxi h,PAL$baud$table use$NTSC: lda RS232$baud cpi baud$1200 ; baud rate less then 1200 baud jrc baud$ok ; yes, go set it mvi a,baud$1200 ; no, 1200 baud is the max sta acter to send in A lxi h,RS232$status setb 7,m ; set Xmit request bit ret ; ; ; out$st$RS232: lda RS232$status ani 80h ; bit 8 set if busy xri 80h ; A cleared if busy (=80h if not) rz ori 0ffh ; A=ff if ready (not busy) ret turn on timer B outp a ; lxi b,CIA2+data$b ; setup user port for RS232 inp a ; get old data ori 6 ; set CTS and DTR outp a ; update it endif ret mmu$table: mmu$tbl$M page ; ; ; CSEG prt$msg: xthl call ?pmsg 46) db 1 dw 2273 ; 150 2222.2us (2222.48) db 2 dw 1136 ; 300 1111.1us (1110.75) db 3 dw 568 ; 600 555.6us ( 555.38) db 6 dw 284 ; 1200 277.8us ( 277.69) db 12 ; ; PAL rates (0.98525 MHz) ; PAL$baud$table: dw 6568 ; no ; 3 (L=function #) dw do$6502$fun ; 4 (L=function #) dw read$d505 ; 5 returns MMU reg in A dw code$error ; not 0 to 5 ret version number in HL num$user$fun equ ($-usr$tb)/2 page ; ; address in DE is read and returned in C ; A=0 if RS232$baud ; (change to 1200 baud) baud$ok: mov e,a mvi d,0 dad d ; +1X dad d ; +1X dad d ; +1X = +3X mov e,m inx h mov d,m inx h ; mov a,m ; get rate # sta int$rate ; lxi b,CIA1+timer$b$low ; outp e ; inr c ; ; ; ; in$RS232: call in$st$RS232 jrz in$RS232 lda recv$data lxi h,RS232$status res 0,m ret ; ; ; in$st$RS232: lda RS232$status ani 1 rz ori 0ffh ; set data ready (-1) ret endif page ; ; this routine is used to pr xthl ret ; ; placed in common memory to keep IO from stepping on this code ; always called from bank 0 ; CSEG read$d505: sta io$0 ; enable MMU (not RAM) lxi b,0d505h inp a ; read 40/80 column screen sta bank$0 ; re-enable RAM baud rate (6666.32) db 1 dw 6568 ; 50 6666.7us (6666.32) db 1 dw 4379 ; 75 4444.4us (4444.56) db 1 dw 2986 ; 110 3030.3us (3030.70) db 1 dw 2451 ; 134 2487.6us (2487.69) db 1 dw 2189 ; 150 2222.2us (2221.77) db 2 dwno error ; DSEG read$mem$0: ldax d ; read location addressed by DE mov c,a ; value returned in C xra a ; clear error flag ret ; ; address in DE is written to with value in C ; A=0 if no errors ; write$mem$0: mvi a,-1 ; get erro point to timer$b$high outp d ; mvi a,11h ; mvi c,CIA$ctrl$b ; turn on timer B outp a ; lxi b,CIA2+data$b ; setup user port for RS232 inp a ; get old data ori 6 ; set CTS and DTR outp a ; update it ei ret page ; ovide the user with a method ; of interfacing with low level system functions ; CSEG ; ; input: ; all registers except HL and A are passed to function ; ; output: ; all resisters from function are preserved ; ?user: shld user$hl$temp xchg ret page ; ; ; DSEG if not use$6551 init$RS232: di xra a sta RS232$status lxi h,RxD$buf$count ; clear the count mvi m,0 inr l ; point to RxD$buf$put mvi m,low(RxD$buffer) inr l ; point to RxD$buf$get mvi m,low(RxD$b 1095 ; 300 1111.1us (1111.39) 300*3 db 3 dw 547 ; 600 555.6us ( 555.19) 600*3 db 6 dw 274 ; 1200 277.8us ( 278.10) 1200*3 db 12 page ; ; ; out$RS232: call out$st$RS232 jrz out$RS232 mov a,c sta xmit$data ; get charr flag and 0ffh value cmp d ; do not allow write from FF00 to FFFF ; this is 8502 space, MMU direct reg. rz mov a,d cpi 10h ; do not allow write from 0000 to 0FFF ; this is ROM space mvi a,-1 ; get error flag rc ; returCP ; error if no file... lxi d,0100h call setdma ; start of TPA lxi d,128 call setmulti ; allow up to 16K bytes lxi d,ccp$fcb call read lxi h,0100h lxi b,0c80h lda force$map push psw ; ; save$ccp: sta bank$1 mov a,m sta b,page$0$l ; point to 1st page register ; outp l ; set page 0 low ; inr c ; outp h ; set page 0 high ; inr c ; outp e ; set page 1 low ; inr c ; outp d ; set page 1 high ; sta force$map ; ret ; ;; ;; ;; ;move$0$to$1: ; lda force$map ; sALL xx RET for next release (ROM FN 7A, 7C ; and 7E will not function with current code, they expect ; a return address on the stack ; ; RJMP 5Eh ; unused function, real fun# installed ; ..above do$6502$fun: lhld user$hl$temp mov a,lP (in TPA) ; ; bank 1, page 01 ; mov h,d ; mov l,d ; jr save$ccp ; ; ; ; ;?rlccp: ; lda ccp$count ; ; sui 30 ; we can only save 30 records ; jp ?ldccp ; ; lxi h,1F0h ; point to buffer ; ; bank 1, page F0 ;; lxi d,101h ; point to TPn if 00h to 0fh mov a,c stax d xra a ; clear error flag ret page ; ; This is the function code entry point for direct execution ; of driver functions. If the MSB of the function number is ; set, the 40 column driver is used; else the 80 ank$0 lxi d,ccp$buffer-100h dad d mov m,a lxi d,-ccp$buffer+100h+1 dad d dcx b mov a,b ora c jrnz save$ccp pop psw sta force$map ret page ; ; The following code does not work with the NEW MMU ; ;?ldccp: ; xra a ; sta ccta bank$1 ; force bank 1 memory ; lxi h,000h ; source ; lxi d,100h ; dest. ;; lxi b,100h ; mov b,d ; mov c,e ; count ; ldir ; sta force$map ; ret ; page ; ; ; no$CCP: ; here if we couldn't find the file call prtmsg ; report this... jmp ?fun65 ; ; ; code$error: lxi h,date$hex mvi a,-1 ret page ; ; ; CSEG ?rlccp: lxi h,ccp$buffer lxi b,0c80h load$ccp: sta bank$0 mov a,m sta bank$1 lxi d,-ccp$buffer+100h dad d mov m,a lxi d,ccp$buffer-100h+1 A space ; ; bank 1, page 01 ; mov d,h ; mov e,h ; ;save$ccp: ; mvi b,15 ; number of pages in buffer ;ccp$move$loop: ; push h ; push d ; push b ; call do$move$0$to$1 ; pop b ; pop d ; pop h ; inx h ; inx d ; djnz ccp$move$loop ; ; retcolumn drive ; is used. ; do$rom$fun: lhld user$hl$temp ; get HL (L=fun #) mvi a,7eh ; only allow even functions ana l cpi 79h jrc no$hl$req lhld @dma ; HL will be passed in @dma by push h ; ..the user no$hl$req: mov l,a rstp$fcb+15 ; zero extent ; lxi h,0 ; shld fcb$nr ; start at beginning of file ; lxi d,ccp$fcb ; call open ; open file containing CCP ; inr a ; ;; trace jz below should be jrz ; jz no$CCP ; error if no file... ; ; lda fcb$rc ; get the record cou db cr,lf,'BIOS Err on A: No CCP.COM file',0 call ?conin ; get a response jr ?ldccp ; and try again ; ; CP/M BDOS Function Interfaces ; CSEG open: mvi c,15 ; open file control block db 21h ; lxi h,(mvi c,26) setdma: mvi c,26 ; s dad d dcx b mov a,b ora c jrnz load$ccp ret page ; ; ; CSEG ?ldccp: xra a sta ccp$fcb+15 ; zero extent lxi h,0 shld fcb$nr ; start at beginning of file lxi d,ccp$fcb call open ; open file containing CCP inr a jrz no$C ; ; ;do$move$0$to$1: ; call set$0$and$1 ; call move$0$to$1 ; lxi h,100h ; bank 1 page 0 ;; lxi d,101h ; bank 1 page 1 ; mov d,h ; mov e,h ;; ;; ;; ;set$0$and$1: ; lda force$map ; get current map ; sta io ; force to i/o in bank 0 ; lxi b 5 ; call rom functon (RCALL) L=fun # ret ; mvi a,7eh ; only allow even functions ; ana l ; sta no$hl$req+1 ; cpi 79h ; jrc no$hl$req ; lhld @dma ; HL will be passed in @dma by ; push h ; ..the user ;no$hl$req: ; will be changed to RCnt ; sta ccp$count ; save for later ; lxi d,0100h ; call setdma ; start of TPA ; lxi d,128 ; call setmulti ; allow up to 16K bytes ; lxi d,ccp$fcb ; call read ; ; lxi d,1f0h ; point to buffer ; ; bank 1, page F0 ;; lxi h,101h ; point to CCet data transfer address db 21h ; lxi h,(mvi c,44) setmulti: mvi c,44 ; set record count db 21h ; lxi h,(mvi c,20) read: mvi c,20 ; read records jmp bdos ; 12345678901 ccp$fcb db 1,'CCP COM',0,0,0 fcb$rc db 0 ds 16 tput status call vector$io ; jump with table adr on stack dw ret$true ; keys dw ret$true ; 80col dw ret$true ; 40col dw ret$true ; prt1 ?pt$s$1101 dw ret$true ; prt2 dw ?outs65 ; 6551 if not use$6551 dw out$st$RS232 ; software RS232 all key$board$stat ; test if key is available jrz key$board$in lda key$buf push psw ; save on stack xra a ; clear key sta key$buf ; ;** the tracking of the display should be able to be turned off ;** this could be done with one of the ke ; 80col dw rret ; 40col dw rret ; ptr1 dw rret ; prt2 dw ?in65 ; 6551 if not use$6551 dw in$RS232 ; software RS232 endif dw null$input ; ; ; ?cist: ; character input status call vector$io ; jump with table adr on stack lxi sp,bios$stack push h ; save old stack lhld de$temp xchg lhld hl$temp ; recover exec adr lda force$map ; get current bank push psw ; save on stack sta bank$0 ; set bank 0 as current call ipchl sta a$temp ; save value to rfcb$nr db 0,0,0 page ; ; CXIO.ASM and CXEM.ASM ; ;========================================================== ; ROUITINE TO VECTOR TO HANDLER ;========================================================== ; CP/M IO routines b=device : c=output c endif dw ret$true page ; ; This entry does not care about values of DE ; vector$io: mvi a,max$devices ; check for device # to high mov e,b ; get devive # in E ; ; ; INPUT: ; Vector # in E, Max device in A ; passes value in DE$TEMP iyboard's Fx codes ; lda stat$enable bit 6,a jrnz no$update lda char$col$40 mov b,a lda @off40 cmp b jrnc do$update adi 39-1 cmp b jrnc no$update do$update: mvi a,80h sta old$offset ; store 80h to demand update no$update: pop dw key$board$stat ; keys dw rret ; 80col dw rret ; 40col dw rret ; prt1 dw rret ; prt2 dw ?ins65 ; 6551 if not use$6551 dw in$st$RS232 ; software RS232 endif dw rret ; ; ; ?co: ; character output call vector$io ; jumeturn pop psw sta force$map ; set old bank back lda a$temp ; recover value to return shld hl$temp pop h ; recover old stack sphl ; set new stack lhld hl$temp ret ipchl: pchl ; jmp to handler ds 30h bios$stack: else har : a=input char ; CSEG ; ; ; ?cinit: ; initialize usarts mov b,c call vector$io ; jump with table adr on stack number$drivers: dw ?int$cia ; keys dw ?int80 ; 80col dw ?int40 ; 40col dw ?pt$i$1101 ; prt1 dw ?pt$i$1101 ; prt2 n DE ; HL has routine's address in it on entering routine ; ; OUTPUT: ; ALL registers of returning routine are passed ; vector: pop h ; get address vector list mvi d,0 ; zero out the MSB cmp e ; is it too high? jrnc exist ; no, go get t psw ; recover current key rret: ret ; ; ; null$input: ; return a ctl-Z for no device mvi a,1Ah ret page ;========================================================== ; CHARACTER DEVICE INPUT STATUS ;================================p with table adr on stack dw rret ; keys dw ?out80 ; 80col dw ?out40 ; 40col dw ?pt$o$1 ; prt1 dw ?pt$o$2 ; prt2 dw ?out65 ; 6551 if not use$6551 dw out$RS232 ; software RS232 endif dw rret ; ; ; ?cost: ; character ou lda a$temp xchg lhld de$temp xchg pchl endif page ;========================================================== ; CHARACTER INPUT ROUTINES ;========================================================== DSEG ; ; ; key$board$in: cdw ?int65 ; 6551 if not use$6551 dw init$RS232 ; software RS232 endif dw rret ; max$devices equ (($-number$drivers)/2)-1 ; ; ; ?ci characte input call vector$io ; jump with table adr on stack dw key$board$in ; keys dw rrethe handler address mov e,a ; yes, set to max$dev$handler(last one) exist: dad d ; dad d ; point into table mov a,m inx h mov h,m mov l,a ; get routine adr in HL if banked shld hl$temp ; save exec adr lxi h,0 dad sp ========================== DSEG ; ; ; key$board$stat: lda key$buf ora a jrnz ret$true call ?get$key ora a ; =0 if none rz ; return character not advailable sta key$buf ; was one, save in key buffer ret$true: ori 0ffh ; aret ; the holding register) old$hr: ds 1 page ; ; ; set$time lda @hour sta old$hr cpi 12h ; test for noon jrz set$as$is ana a ; test for 00:xx jrnz not$zero$hundred mvi a,80h+12h ; set to midnight jr set$as$is not$z jrz exit$move push d ; save count for 2nd half ;**2 push b ; save dest adr ;**3 lxi d,@buffer lda source$bnk call ?bank ldir ; move source to buffer pop b ; recover count ;**2 pop d ; recover dest ;**1 pushg ; ; HL and DE must be presevered ; ?time: inr c lxi b,cia$hours jrz set$time ; ; update SCB time (READ THE TIME) ; inp a ; read HR (sets sign flag) jp is$am ; jmp if AM (positive) ani 7fh adi 12h ; noon=24(PM), midnight=12(AM) sp,bios$stack push h ; save old stack ;**1 lhld @buffer inter$bank$move$1: mov a,b ; get msb of count ora a jrz count$less$than$256 push b ; save the count ;**2 push d ; save the dest ;**3 lxi d,@buffer ; make buffer the dest nd return true ret page cseg @ctbl db 'KEYS ' ; device 0, internal keyboard db mb$input db baud$none db '80COL ' ; device 1, 80 column display db mb$output db baud$none db '40COL ' ; device 2, 40 column display db mb$output ero$hundred: cpi 11h+1 ; test for 1 to 11 AM jrc set$as$is sui 12h daa ; decimal adjust set$msb: ori 80h ; set PM set$as$is: outp a dcr c lda @min outp a dcr c lda @sec outp a dcr c xra a outp a ret page ; h ; save updated dest ;**2 lxi h,@buffer lda dest$bnk call ?bank ldir ; move buffer to dest pop h ;**1 ; ; ; exit$move: xchg mvi a,-1 sta source$bnk ; set MOVE back to normal lda @cbnk shld @buffer pop h ; recover daa cpi 24h ; check for noon (12+12 PM) jrnz set$hr mvi a,12h jr set$hr is$am: cpi 12h ; check for midnight (AM) jrnz set$hr xra a ; becomes 00:00 set$hr: sta @hour mov b,a lda old$hr mov c,a mov a,b sta old$hr cmp lxi b,256 ; move 256 bytes lda source$bnk call ?bank ldir ; move source to buffer pop d ; recover dest ;**2 push h ; save updated source ;**3 lxi h,@buffer ; make the buffer the source lxi b,256 ; move 256 bytes lda dest$bnk ca db baud$none db 'PRT1 ' ; device 3, serial bus printer (device 4) db mb$output db baud$none db 'PRT2 ' ; device 4, serial bus printer (device 5) db mb$output db baud$none db '6551 ' ; device 5, EXT CRT db mb$in$out+mb$serial+mb$s; CXMOVE.ASM ; public ?move,?xmove,?bank ; ; Move a block of data from DE to HL ; count is in BC (within current bank) ; ; cseg ; place code in common ?move: xchg ;* lda source$bnk ; =FFh if normal block move inr a ; jrnz inter$ old stack ;**0 sphl lhld @buffer ; call ?bank ; set current bank ; ret page ; ; switch bank to bank number in A ; cseg ; (must be in common) ?bank: if banked ora a ; bank 0 ? jrnz not$bank$0 ; go check for bank 1 sta c ; if @hour' ; display start prompt '>' call disp$status lhld msg$ptr lda string$index try$again: cpi buff$large-2 jrc parameters$ok inx h dcr a jr try$again page ; ; ; parameters$ok: adi buff$pos+1 sta cur$pos disp$mvi a,-1 move$rt: inr a sta string$index ret ; ; ; check$left: cpi SF$left rnz ; ; move cursor left ; if past left end go to right end ; lda string$index ora a jrz at$left$end dcr a sta string$index ret page ; ;he pointer xchg lhld key$tbl ; get the start of the ASCII table dad d ; HL now points to the ASCII value mov a,m ; for the input key. ora a ; set zero flag if A=0 ret page ; ; used to convert a keyboard matrix position into it's HEX d start ?wboot: jmp wboot ; reentry on program exit, warm start ?const: jmp const ; return console input status ?conin: jmp conin ; return console input character ?cono: jmp conout ; send console output character ?list: jmp list ; send list outn extrn ?cinit ; (re)initialize device in extrn @ctbl ; physical character device table ; disk communication data items extrn @dtbl ; table of pointers to XDPHs ; memory control extrn ?xmove,?move ; select move bank, and blox 579 ; Pacific Grove, CA 93950 ; ; ; This is the invariant portion of the modular BIOS and is ; distributed as source for informational purposes only. ; All desired modifications should be performed by ; adding or changing externally defined m; value (keys caps labelled with 0 to 9 and A to F) ; hex$key$tbl: db 15h ; F db 0eh ; E db 12h ; D db 14h ; C db 1ch ; B db 0ah ; A db 20h ; 9 db 1bh ; 8 db 18h ; 7 db 13h ; 6 db 10h ; 5 db 0bh ; 4 db 08h ; 3 db put character ?auxo: jmp auxout ; send auxilliary output character ?auxi: jmp auxin ; return auxilliary input character ?home: jmp home ; set disks to logical home ?sldsk: jmp seldsk ; select disk drive, return disk parameter info ?sttrk: jmp seock move extrn ?bank ; select CPU bank ; clock support extrn ?time ; signal time operation ;; user function extrn ?user ; special functions ; general utility routines public ?pmsg ; print message public ?pdec ; print numodules. ; This allows producing "standard" I/O modules that ; can be combined to support a particular system ; configuration. bell equ 7 ctlQ equ 'Q'-'@' ctlS equ 'S'-'@' ccp equ 0100h ; Console Command Processor ; gets loaded into the 3bh ; 2 db 38h ; 1 db 23h ; 0  Machine (TSM) ; ; ; ; Keyboard Scan State Machine (KSSM) ; ttrk ; set disk track ?stsec: jmp setsec ; set disk sector ?stdma: jmp setdma ; set disk I/O memory address ?read: jmp read ; read physical block(s) ?write: jmp write ; write physical block(s) ?lists: jmp listst ; return list device status ?sber from 0 to 65535 public ?pderr ; print BIOS disk error message header page ; External names for BIOS entry points public ?boot,?wboot,?const,?conin,?cono,?list,?auxo,?auxi public ?home,?sldsk,?sttrk,?stsec,?stdma,?read,?write publicTPA page cseg ; GENCPM puts CSEG stuff in ; common memory ; variables in system data page extrn @covec,@civec extrn @aovec extrn @aivec,@lovec ; I/O redirection vectors extrn @mxtpa ; addr of system entry point extrn @bnke 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> Thctrn: jmp sectrn ; translate logical to physical sector ?conos: jmp conost ; return console output status ?auxis: jmp auxist ; return aux input status ?auxos: jmp auxost ; return aux output status ?dvtbl: jmp devtbl ; return address of device de ?lists,?sctrn public ?conos,?auxis,?auxos,?dvtbl,?devin,?drtbl public ?mltio,?flush,?mov,?tim,?bnksl,?stbnk,?xmov ; BIOS Jump vector. ; ; All BIOS routines are invoked by calling these ; entry points. ?boot: jmp boot ; initial entry on colbf ; 128 byte scratch buffer ; initialization extrn ?init ; general initialization and signon extrn ?ldccp,?rlccp ; load & reload CCP for BOOT & WBOOT ; user defined character I/O routines extrn ?ci,?co,?cist,?cost ; each take device i title 'Root module of relocatable BIOS for CP/M 3.0 28 Aug 85' ; version 1.0 5 Sept 84 maclib cxequ ; C128 equates lib maclib modebaud ; define mode bits maclib Z80 ; Copyright (C), 1982 ; Digital Research, Inc ; P.O. Bf table ?devin: jmp ?cinit ; change baud rate of device ?drtbl: jmp getdrv ; return address of disk drive table ?mltio: jmp multio ; set multiple record count for disk I/O ?flush: jmp flush ; flush BIOS maintained disk caching ?mov: jmp ?move ny not ready, return false inr b ; drop device number mov a,h ora l ; see if any more selected devices jrnz cos$next ori 0FFh ; all selected were ready, return true ret coster: ; check for output device ready, ; including optional h ; recover the rest of the vector not$out$device: inr b ; next device number mov a,h ora l ; see if any devices left jrnz co$next ; and go find them... ret page ; ; CONOST ; Console Output Status. Return true if ; all selected cock equ $ page ; ; DEVTBL ; Return address of character device table devtbl: lxi h,@ctbl ret ; ; GETDRV ; Return address of drive table getdrv: lxi h,@dtbl ret ; ; CONOUT ; Console Output. Send character in ; to all selerive push h ; save @drv pointer xchg ; XDPH address in dcx h dcx h mov a,m sta @RDRV ; get relative drive code mov a,c sta @ADRV ; get absolute drive code dcx h ; point to init pointer mov d,m dcx h mov e,m ; get init ; block move memory to memory ?tim: jmp ?time ; Signal Time and Date operation ?bnksl: jmp bnksel ; select bank for code execution ; and default DMA ?stbnk: jmp setbnk ; select different bank for disk ; I/O DMA operations. ?xmov: jmp ?xmo xon/xoff support mov l,b mvi h,0 ; make device code 16 bits push h ; save it in stack dad h dad h ; create offset into device dad h ; characteristics tbl lxi d,@ctbl+6 dad d ; make address of mode byte mov a,m ani mb$xonxoff popnsole output devices ; are ready. conost: lhld @covec ; get console output bit vector jr ost$scan ; ; AUXOST ; Auxiliary Output Status. Return true if ; all selected auxiliary output devices ; are ready. auxost: lhld @aovec ; get aucted devices conout: lhld @covec ; fetch console output bit vector jmp out$scan ; ; AUXOUT ; Auxiliary Output. Send character in ; to all selected devices auxout: lhld @aovec ; fetch aux output bit vector jmp out$scan ; ; L pointer xchg call ipchl ; call init routine pop h ; recover @drv pointer d$init$next: pop b ; recover counter and drive # inr c djnz d$init$loop ; and loop for each drive jmp boot$1 cseg ; following in resident memory boot$1: cave ; set source and destination banks ; for one operation jmp ?user ; reserved for future expansion jmp 0 ; reserved for future expansion jmp 0 ; reserved for future expansion page ; ; BOOT ; Initial entry point for system startup. h ; recover console number in jz ?cost ; not a xon device, go get output status direct lxi d,xofflist dad d ; make pointer to proper xon/xoff flag call cist1 ; see if this keyboard has character mov a,m cnz ci1 ; get flag or read keyx output bit vector jr ost$scan ; ; LISTST ; List Output Status. Return true if ; all selected list output devices ; are ready. listst: lhld @lovec ; get list output bit vector ost$scan: mvi b,0 ; start with device 0 cos$next: daIST ; List Output. Send character in ; to all selected devices. list: lhld @lovec ; fetch list output bit vector out$scan: mvi b,0 ; start with device 0 co$next: dad h ; shift out next bit jrnc not$out$device push h ; save the vll set$jumps call ?ldccp ; fetch CCP for first time jmp ccp page ; WBOOT ; Entry for system restarts. wboot: lxi sp,boot$stack call set$jumps ; initialize page zero call ?rlccp ; reload CCP jmp ccp ; then reset jmp vectors and exi dseg ; this part can be banked boot: lxi sp,boot$stack mvi c,15 ; initialize all 16 character devices c$init$loop: push b call ?cinit pop b dcr c jp c$init$loop call ?init ; perform any additional system initialization ; an if any cpi ctlq jrnz not$q ; if its a ctl-Q, mvi a,0FFh ; set the flag ready not$q: cpi ctls jrnz not$s ; if its a ctl-S, mvi a,00h ; clear the flag not$s: mov m,a ; save the flag call cost1 ; get the actual output status, ana md h ; check next bit push h ; save the vector push b ; save the count mvi a,0FFh ; assume device ready cc coster ; check status for this device pop b ; recover count pop h ; recover bit vector ora a ; see if device ready rz ; if aector push b ; save the count and character not$out$ready: call coster ora a jrz not$out$ready pop b push b ; restore and resave the character and device call ?co ; if device selected, print it pop b ; recover count and character popt to ccp set$jumps: if banked mvi a,1 call ?bnksl endif mvi a,JMP sta 0 sta 5 ; set up jumps in page zero lxi h,?wboot shld 1 ; BIOS warm start entry lhld @MXTPA shld 6 ; BDOS system call entry ret ds 64 boot$stad print signon message lxi b,16*256+0 lxi h,@dtbl ; init all 16 logical disk drives d$init$loop: push b ; save remaining count and abs drive mov e,m inx h mov d,m inx h ; grab @drv entry mov a,e ora d jrz d$init$next ; if null, no d ; and mask with ctl-Q/ctl-S flag ret ; return this as the status cist1: ; get input status with and saved push b push h call ?cist pop h pop b ora a ret cost1: ; get output status, saving & push b pu ; ; SETSEC ; Set Sector. Saves sector number from ; in @sect for further operations. setsec: mov l,c mov h,b shld @sect ret ; ; SETDMA ; Set Disk Memory Address. Saves DMA address ; from in @DMA and sets @DBNK to @CBNK ocedure for drive ; if this is first select. Return ; address of disk parameter header ; in seldsk: mov a,c sta @adrv ; save drive select code mov l,c mvi h,0 dad h ; create index from drive code lxi b,@dtbl dad b ; get poiploop inx sp inx sp jr pdecl stoploop: push d push b mov c,a call ?cono pop b pop d nextdigit: pop h ldax b mov e,a inx b ldax b mov d,a inx b mov a,e ora d jrnz next ret table10: dw -1000,-100,-10,-1,0 ?n ; AUXIN ; Auxiliary Input. Return character from first ; ready auxiliary input device. auxin: lhld @aivec in$scan: push h ; save bit vector mvi b,0 ci$next: dad h ; shift out next bit mvi a,0 ; insure zero a (nonexistant devicsh h call ?cost pop h pop b ora a ret ci1: ; get input, saving & push b push h call ?ci pop h pop b ret page ; ; CONST ; Console Input Status. Return true if ; any selected console input device ; has an ava; so that further disk operations take place ; in current bank. setdma: mov l,c mov h,b shld @dma lda @cbnk ; default DMA bank is current bank ; fall through to set DMA bank ; ; SETBNK ; Set Disk Memory Bank. Saves bank number ; inter to dispatch table mov a,m inx h mov h,m mov l,a ; point at disk descriptor ora h rz ; if no entry in table, no disk mov a,e ani 1 jrnz not$first$select ; examine login bit push h xchg ; put pointer in stack & lxi pderr: lxi h,drive$msg call ?pmsg ; error header lda @adrv adi 'A' mov c,a call ?cono ; drive code lxi h,track$msg call ?pmsg ; track header lhld @trk call ?pdec ; track number lxi h,sector$msg call ?pmsg ; sector header e not ready). cc cist1 ; see if the device has a character ora a jrnz ci$rdy ; this device has a character inr b ; else, next device mov a,h ora l ; see if any more devices jrnz ci$next ; go look at them pop h ; recover bit vector jilable character. const: lhld @civec ; get console input bit vector jr ist$scan ; ; AUXIST ; Auxiliary Input Status. Return true if ; any selected auxiliary input device ; has an available character. auxist: lhld @aivec ; get aux inpun @DBNK for future disk data ; transfers. setbnk: sta @dbnk ret page ; ; ; SECTRN ; Sector Translate. Indexes skew table in ; with sector in . Returns physical sector ; in . If no skew table (=0) then ; returns phyh,-2 dad d mov a,m sta @RDRV ; get relative drive lxi h,-6 dad d ; find LOGIN addr mov a,m inx h mov h,m mov l,a ; get address of LOGIN routine call ipchl ; call LOGIN pop h ; recover DPH pointer not$first$select: ret lhld @sect jr ?pdec ; sector number (call/ret) ; ; BNKSEL ; Bank Select. Select CPU bank for further execution. bnksel: sta @cbnk ; remember current bank jmp ?bank ; and go exit through users ; physical bank select routine r in$scan ; loop til we find a character ci$rdy: pop h ; discard extra stack jmp ?ci page ; Utility Subroutines ?pmsg: ; print message @ up to a null ; saves & push b push d pmsg$loop: mov a,m ora a jrzt bit vector ist$scan: mvi b,0 ; start with device 0 cis$next: dad h ; check next bit mvi a,0 ; assume device not ready cc cist1 ; check status for this device ora a rnz ; if any ready, return true inr b ; drop device number mov sical=logical. sectrn: mov l,c mov h,b mov a,d ora e rz xchg dad b mov l,m mvi h,0 ret page ; ; READ ; Read physical record from currently selected drive. ; Finds address of proper read routine from ; extended disk parameter page ; ; HOME ; Home selected drive. Treated as SETTRK(0). home: lxi b,0 ; same as set track zero ; ; SETTRK ; Set Track. Saves track address from ; in @TRK for further operations. settrk: mov l,c mov h,b shld @trk ret xofflist: db -1,-1,-1,-1,-1,-1,-1,-1 ; ctl-s clears to zero db -1,-1,-1,-1,-1,-1,-1,-1 dseg ; following resides in banked memory ; Disk I/O interface routines ; ; SELDSK ; Select Disk Drive. Drive code in . ; Invoke login pr pmsg$exit mov c,a push h call ?cono pop h inx h jr pmsg$loop pmsg$exit: pop d pop b ret ?pdec: ; print binary number 0-65535 from lxi b,table10 lxi d,-10000 next: mvi a,'0'-1 pdecl: push h inr a dad d jrnc stoa,h ora l ; see if any more selected devices jrnz cis$next xra a ; all selected were not ready, return false ret page ; ; CONIN ; Console Input. Return character from first ; ready console input device. conin: lhld @civec jr in$sca header (XDPH). read: lhld @adrv mvi h,0 dad h ; get drive code and double it lxi d,@dtbl dad d ; make address of table entry mov a,m inx h mov h,m mov l,a ; fetch table entry push h ; save address of table lxi d,-8 dad d ) db 69h,49h,49h,09h ; I db 6ah,4ah,4ah,0ah ; J db 30h,30h,30h,00h ; 0 db 6dh,4dh,4dh,0dh ; M db 6bh,4bh,4bh,0bh ; K db 6fh,4fh,4fh,0fh ; O db 6eh,4eh,4eh,0eh ; N db 2bh,2bh,2bh,00h ; + db 70h,50h,50h,10h ; P db 6ch,4ch,4ch,0ept (number$blks*256)-msg$size-key$tbl$size-color$tbl$size db 0ffh endm page ascii$tbl: db 7fh,7fh,7fh,16h ; INS DEL db 0dh,0dh,0dh,0dh ; RETURN db 06h,06h,01h,01h ; LF RT db 86h,86h,87h,87h ; F7 F8 db 80h,80h,81h,81h ; F1 F2 d title 'CXKYCODE- function and key def file 26 May 85' maclib cxequ number$blks equ 4 ; 256 byte blocks def$per$key equ 4 key$tbl$size equ 11*8*def$per$key color$tbl$size equ 16 ; ; default Function keys and key definition ; org sys$ ; ; error message components ; drive$msg: db cr,lf,bell,'BIOS Error on ',0 track$msg: db ': T-',0 sector$msg: db ', S-',0 end  ; point to read routine address jr rw$common ; use common code ; ; WRITE ; Write physical sector from currently selected drive. ; Finds address of proper write routine from ; extended disk parameter header (XDPH). write: lhld @adrv mvi ch ; L db 2dh,2dh,2dh,00h ; - db 2eh,2eh,3eh,00h ; . > db 3ah,3ah,5bh,7bh ; : [ { db 40h,40h,40h,00h ; @ db 2ch,2ch,3ch,00h ; , < db 23h,23h,23h,60h ; pound ` db 2ah,2ah,2ah,00h ; * db 3bh,3bh,5dh,7dh ; ; ] } db 00h,00h,00h,0f5b 82h,82h,83h,83h ; F3 F4 db 84h,84h,85h,85h ; F5 F6 db 17h,17h,17h,1ah ; UP DOWN db 33h,33h,23h,0A2h ; 3 # db 77h,57h,57h,17h ; W db 61h,41h,41h,01h ; A db 34h,34h,24h,0A3h ; 4 $ db 7ah,5ah,5ah,1ah ; Z db 73h,53h,53h,13h ; S db key$area dw ascii$tbl-2 msgtbl: db 'F1',0 db 'F2',0 db 'dir',cr,0 db 'dir ',0 db 'F5',0 db 'F6',0 db 'F7',0 date db 5,18h,cr,0 ; ^E ^X ^D db 'F9',0 db 'F10',0 db 'F11',0 db 0f3h,0f3h,0f3h,0f3h,0f3h,0f3h,0f3h,0f3=================== ; the charactor to be output is in the C register ; ; ; dseg ?out65: ; character output mov a,c push psw call ?outs65 jrz ?out65 pop psw dcx b ; point to data register outp a ret ;======================h,0 dad h ; get drive code and double it lxi d,@dtbl dad d ; make address of table entry mov a,m inx h mov h,m mov l,a ; fetch table entry push h ; save address of table lxi d,-10 dad d ; point to write routine address rw$ch ; clear/home db 00h,00h,00h,00h ; (rt shift) db 3dh,3dh,3dh,7eh ; = ~ db 5eh,5eh,7ch,7ch ; ^ PI | db 2fh,2fh,3fh,5ch ; / ? \ db 31h,31h,21h,0A0h ; 1 db 5fh,5fh,5fh,7fh ; <- db 09h,15h,30h,00h ; (CONTROL) sound1 sound2 db 32h,32h,265h,45h,45h,05h ; E db 00h,00h,00h,00h ; (lf shift) db 35h,35h,25h,0A4h ; 5 % db 72h,52h,52h,12h ; R db 64h,44h,44h,04h ; D db 36h,36h,26h,0A5h ; 6 & db 63h,43h,43h,03h ; C db 66h,46h,46h,06h ; F db 74h,54h,54h,14h ; T db 78h,58hh,0f3h,0f3h db 0f3h,0f3h,0f3h,0f3h,0f3h,0f3h,0f3h,0f3h,0f3h,0f3h,0 db 0f4h,0f4h,0f4h,0f4h,0f4h,0f4h,0f4h,0f4h,0f4h,0f4h db 0f4h,0f4h,0f4h,0f4h,0f4h,0f4h,0f4h,0f4h,0f4h,0f4h,0 db 0f3h,0f3h,0f3h,0f3h,0 db 0f4h,0f4h,0f4h,0f4h,0 db 'F16',0 ==================================== ; CHARACTER DEVICE OUTPUT STATUS ;========================================================== ; ; ; dseg ?outs65: ; character input status lhld usart$adr mov b,h mov c,l inx b ; point to status registeommon: mov a,m inx h mov h,m mov l,a ; get address of routine pop d ; recover address of table dcx d dcx d ; point to relative drive ldax d sta @rdrv ; get relative drive code and post it inx d inx d ; point to DPH again ip2h,0A1h ; 2 " db 20h,20h,20h,00h ; Space db 21h,20h,00h,00h ; (Commodore) sound3 db 71h,51h,51h,11h ; Q db 00h,00h,00h,0f0h ; RUN STOP db 9fh,9fh,9fh,9fh ; /HELP/ db 38h,38h,38h,0B7h ; /8/ db 35h,35h,35h,0B4h ; /5/ db 09h,09h,09h,00h,58h,18h ; X db 37h,37h,27h,0A6h ; 7 ' db 79h,59h,59h,19h ; Y db 67h,47h,47h,07h ; G db 38h,38h,28h,0A7h ; 8 ( db 62h,42h,42h,02h ; B db 68h,48h,48h,08h ; H db 75h,55h,55h,15h ; U db 76h,56h,56h,16h ; V db 39h,39h,29h,00h ; 9 db 'F17',0 db 'F18',0 db 'F19',0 db 'F20',0 db 'F21',0 db 'F22',0 db 'F23',0 db 'F24',0 db 'F25',0 db 'F26',0 db 'F27',0 db 'F28',0 db 'F29',0 db 'F30',0 db 'F31',0 db 'Help ',0 msg$size equ $-msgtbl rr inp a ani txrdy rz ori -1 ret endif end to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Thchl: pchl ; leap to driver page ; ; MULTIO ; Set multiple sector count. Saves passed count in ; @CNT multio: sta @cnt ret ; ; FLUSH ; BIOS deblocking buffer flush. Not implemented. flush: xra a ret ; return with no error ; /TAB/ db 32h,32h,32h,0B1h ; /2/ db 34h,34h,34h,0B3h ; /4/ db 37h,37h,37h,0B6h ; /7/ db 31h,31h,31h,0B0h ; /1/ db 1bh,1bh,1bh,00h ; /ESC/ db 2bh,2bh,2bh,0F7h ; /+/ (select VT100) db 2dh,2dh,2dh,0F6h ; /-/ (select ADM31) db 0Ah,0Ah,007Fh ; MAXIMUM BLOCK NUMBER DW 003Fh ; MAXIMUM DIRECTORY ENTRY NUMBER DB 0C0h,00h ; ALLOC VECTOR FOR DIRECTORY DW 8000h ; CHECKSUM SIZE DW 0 ; OFFSET FOR SYSTEM TRACKS DB 1,1 ; PHYSICAL SECTOR SIZE SHIFT dpb$RM$512: ; dpb 256,1,2048,2048, from 0 to 99. extrn ?pderr ; print BIOS disk error header extrn ?conin,?cono ; con in and out extrn ?const ; get console status extrn @dtbl ; DMA ram bank public RMdsk extrn ?fun65 extrn ?dkmov page ; CSEG ; place code in commalues for now cpi cr jrz set$msb cpi '"' jrz is$quote cpi '@' rc cpi 60h jrc make$upper$case ; ; if it is a lower case letter subtract 20h ; cpi 'z'+1 jrnc lower$symbols sui 20h ret lower$symbols: adi 60h ret ; ; manv$2 call do$convt ; C must be unchanged A=desired code lxi h,prt$buf$2 mvi b,5 jr prt$cont do$convt: mov a,c ; A=desired code mvi c,7 ; C=secondary address pchl ; HL,DE and B may be used ?pt$o$1: lhld prt$conv$1 call do$conAh,0Ah ; /Line Feed/ db 0dh,0dh,0dh,0ffh ; /ENTR/ db 36h,36h,36h,0B5h ; /6/ db 39h,39h,39h,00h ; /9/ db 33h,33h,33h,0B2h ; /3/ db 00h,00h,00h,00h ; /Alt/ db 30h,30h,30h,00h ; /0/ db 2eh,2eh,2eh,00h ; /./ db 05h,05h,05h,12h ; /UP/ 128,0 DW 0002 ; 128 BYTE RECORDS PER TRACK DB 04,0Fh ; BLOCK SHIFT AND MASK DB 01 ; EXTENT MASK DW 00FFh ; MAXIMUM BLOCK NUMBER DW 007Fh ; MAXIMUM DIRECTORY ENTRY NUMBER DB 0C0h,00h ; ALLOC VECTOR FOR DIRECTORY DW 8000h ; CHECKSUM SIZE on memory ; ; Extended Disk Parameter Headers (XPDHs) ; dw RM$write dw RM$read dw RM$login dw RM$init db 0 ; relative drive zero db 0 ; format type byte RMdsk: ; dph 0,dpb$RM$512 dw 0 ; TRANSLATE TABLE ADDRESS db 0,0,0,0,0,0,0,0,ke$upper$case: cpi 'Z'+1 jrnc upper$symbols set$msb: adi 80h ret ; ; is$quote: mvi a,27h ; convert to tick (shifted 7) ret ; ; upper$symbols: cpi '\' rnz ; mvi a,0ffh ; ; printer initialization code ; ?pt$i$1101: retvt lxi h,prt$buf$1 mvi b,4 ; ; ; prt$cont: inr m mov e,m mvi d,0 xchg dad d ; index into buffer mov m,a xchg ; ani 7Fh ; strip MSB cpi lf ; data a CR ? jrz print$it ; yes, go print this line mov a,m ; no, get current line ldb 18h,18h,18h,03h ; /DN/ db 13h,13h,13h,08dh ; /LF/ db 04h,04h,04h,08eh ; /RT/ db 0f1h,0f1h,0f1h,0f2h ; /no scroll/ ; ; logical color table (used with ESC ESC ESC char) ; (where char is 50h to 7fh) ; db 000h,011h,022h,033h db 044h,055h DW 0 ; OFFSET FOR SYSTEM TRACKS DB 1,1 ; PHYSICAL SECTOR SIZE SHIFT page ; ; ; dseg RM$write: mvi d,VIC$RM$wr lda @dbnk ; get disk bank ana a lhld @dma jrz RM$do$rd$wr call ?dkmov+3 ; A<>0 transfers data from local$DMA to buffe0 ; BDOS SCRATCH AREA db 0 ; MEDIA FLAG DPB$ptr: dw dpb$RM$512 ; DISK PARAMETER BLOCK dw 00000h ; CHECKSUM VECTOR ALLOCATED BY dw 0FFFEh ; ALLOC VECTOR ALLOCATED BY GENCPM dw 0FFFEh ; DIRBCB dw 0FFFEh ; DTABCB dw 0FFFEh ; H ; ; printer status code ; dseg ;?pt$s$1101: ; ret prt$buf$lng equ 81 prt$buf$1: ds prt$buf$lng prt$buf$2: ds prt$buf$lng ength cpi prt$buf$lng-1 ; reach end yet ? rnz ; no, exit ; yes, print line of data print$it: mov a,m sta vic$count ; set number of bytes to send mvi m,0 ; set count back to zero inx h shld @buffer ; save location to print from m,066h,077h db 088h,099h,0aah,0bbh db 0cch,0ddh,0eeh,0ffh to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Thr mvi d,VIC$RM$wr jr RM$do$rd$wr$buf ; ; ; RM$read: mvi d,VIC$RM$rd lda @dbnk ; get disk bank ana a ; is it bank zero lhld @dma jrz RM$do$rd$wr ; yes, go read it call RM$do$rd$wr$buf ; no, transfer through buffer lhld @dma callASH ALLOC'D db 0 ; HASH BANK ; ; DPB FOR RAM disk ; dpb$RM$128: ; dpb 256,1,512,1024,64,0 DW 0002 ; 128 BYTE RECORDS PER TRACK DB 03,07 ; BLOCK SHIFT AND MASK DB 00 ; EXTENT MASK DW 0; ; title 'C128 Ram Disk support 14 Oct 85' ; maclib cpm3 maclib z80 maclib cxequ ; Utility routines in standard BIOS extrn ?pmsg ; print message @ up to 00 ; saves & extrn ?pdec ; print binary number in ov a,b sta vic$drv ; pass device # in Vic$drv mov a,c sta vic$trk ; pass secondary adr in Vic$trk mvi a,vic$prt jmp ?fun65 ; ; ; ?convt$none: mvi c,0 ; set secondary adr to 0 ret ; ; ; ?convt: ani 7fh ; only allow real ASCII v title 'CXPRINTER Commodore printer drivers 4 Dec 85' maclib z80 maclib cxequ public ?PT$I$1101,?PT$O$1,?pt$o$2 public ?convt ; public ?PT$S$1101 extrn ?fun65 ; ; printer output in register C ; dseg ?pt$o$2: lhld prt$co ?dkmov+3 ; A=0 transfers data from buffer to local$DMA xra a ret ; ; ; RM$do$rd$wr$buf: lxi h,@buffer RM$do$rd$wr: lxi b,RM$128$low outp l inr c ; RM$128$mid outp h inr c ; RM$ext$low xra a outp a lhld @trk inr c ; RM$ext$m@AIVEC equ scb$base+26h ; Auxiliary Input Redirection ; Vector (word, r/w) @AOVEC equ scb$base+28h ; Auxiliary Output Redirection ; Vector (word, r/w) @LOVEC equ fer: lxi h,@buffer mvi m,0E5h lxi d,@buffer+1 lxi b,256-1 ldir ret ; ; ; dir$label: ;123456789012 3 4 5 6 db ' ERTWINE VON',1,0,0,0 dw 0,0,0,0 dw date$hex,0 dw date$hex,0 if not ; no$match: mvi l,0 ; start back at the buffer beginning test$for$ram$dsk: mov a,m cmp l ; buffer changed? jrnz device$is$present ; yes, then device is present inr l ; no, buffer end? jrnz test$for$ram$dsk ; no, test rest of bufid outp l inr c ; RM$ext$hi outp h lxi h,256 inr c ; RM$count$low outp l inr c ; RM$count$hi outp h mov a,d ; get rd/wr command call ?fun65 xra a ; set no errors ret page ; ; ; dseg RM$init: lxi b,RM$control xra a scb$base+2Ah ; List Output Redirection ; Vector (word, r/w) @pageM equ scb$base+2Ch ; Page mode. 0=page pause ; none 0 = no page break (byte, r/w) @BNKBF equ scb$base+35h ; Address of 128 Byte Buffe 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> Thfer ; yes, L=0 ; ; device is missing, remove vector ; mov h,l ; remove vector to RAM disk shld @dtbl+('M'-'A')*2 ; .. (drive M:) ret ; ; initialize directory buffer ; device$is$present: call init$buffer ; fill buffer with E5`s lxi outp a ; increment both addresses dcr c ; point to interrupt control register outp a ; disable interrupts lxi h,0 ; point to track 0 shld @trk xra a sta @dbnk ; set DMA bank to zero lxi h,@buffer ; shld @dma test$device$er ; for Banked BIOS (word, r/o) @CRDMA equ scb$base+3Ch ; Current DMA Address ; (word, r/o) @CRDSK equ scb$base+3Eh ; Current Disk (byte, r/o) @VINFO equ scb$ public @civec, @covec, @aivec, @aovec, @lovec, @pageM public @bnkbf, @crdma, @crdsk, @vinfo, @resel, @fx, @usrcd public @mltio, @ermde, @erdsk, @media, @bflgs public @date, @hour, @min, @sec, ?erjmp, @mxtpa scb$base equ 0FE00H ; h,dir$label lxi d,@buffer lxi b,32 ldir ; install directory label in 1st record lxi h,0 shld @trk ; set track=0 clear$dir: call RM$write ; erase director sectors call init$buffer ; fill buffer with E5`s lda @trk inr a sta @trpresent: mov m,l ; place a pattern in the directory inr l ; ..buffer area jrnz test$device$present ; call RM$read ; read track 0 to DMA buffer lxi h,@buffer ; ..(buffer not changed if lxi d,dir$label ; ..device is not present) lxi base+3Fh ; BDOS Variable "INFO" ; (word, r/o) @RESEL equ scb$base+41h ; FCB Flag (byte, r/o) @FX equ scb$base+43h ; BDOS Function for Error ; Messages (byte, r/Base of the SCB @CIVEC equ scb$base+22h ; Console Input Redirection ; Vector (word, r/w) @COVEC equ scb$base+24h ; Console Output Redirection ; Vector (word, r/w) k cpi 16 ; 16 for 512K Ram disk jrnz clear$dir set$size: lxi h,dpb$RM$128 lxi b,RM$status inp a ani 10h ; mask of size bit (0=128K) jrz set$128K lxi h,dpb$RM$512 set$128K: shld dpb$ptr RM$login: ret page ; ; ; init$bufb,12 ; test if KEY has been installed test$next$key: ldax d inx d cci jrnz no$match ; KEY missing, test device present jpe test$next$key jr set$size ; KEY is in RAM DISK, go set size page ; ; test if device is present, remove vector o) @USRCD equ scb$base+44h ; Current User Code (byte, r/o) @MLTIO equ scb$base+4Ah ; Current Multi-Sector Count ; (byte,r/w) @ERMDE equ scb$base+4Bh ; BDOS Error Mode (byte, r/o) @ERDSK equ scb$base+51h ; BDOS Error Disk (byte ;; ESC ( 0 select char set ;; ESC ( 1 select char set ;; ESC ( 2 select char set ;; ESC ) A select char set ;; ESC ) B select char set ;; ESC ) 0 select char set ;; ESC ) 1 select char set ;; ESC ) 2 select char set ; page dD move cursor down one line ; ESC E move cursor to start of next line ; ESC H set horizontal tab ; ESC M move cursor up one line ; ESC Z same as ESC [ Pn c ; ESC c reset ; ESC # 3 Double height line Top ; ESC # 4 Double height line B,066h,077h db 088h,099h,0aah,0bbh db 0cch,0ddh,0eeh,0ffh to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Th,r/o) @MEDIA equ scb$base+54h ; Set by BIOS to indicate ; open door (byte,r/w) @BFLGS equ scb$base+57h ; BDOS Message Size Flag (byte,r/o) @DATE equ scb$base+58h ; Date in Days Since 1 Jan 78 seg ; ; VT-100 terminal emulation ; VT100: lhld parm$base ; 1st parm is exec adr (2 bytes) mov a,m inx h mov h,m mov l,a ora h ; L is in A already, test HL=0 mov a,c ; C is char to output jrz start$checking pchl ; ; ; start$ottom ; ESC # 5 set single width line ; ESC # 6 Double width line ; ESC # 8 files screen with E's ; ESC [ Pn A cursor up ; ESC [ Pn B cursor down ; ESC [ Pn C cursor right ; ESC [ Pn D cursor left ; ESC [ Pn ; Pn H cursor positioning ; title 'Terminal Emulation (VT-100) 18 Feb 86' maclib cxequ if use$VT100 maclib z80 lines equ 24 public VT100 ; ; VT-100 ; ; NUL 00h ignored ; ENQ 05h transmit answer back message ; BEL 07h ring bell ; BS 08h back s ; (word, r/w) @HOUR equ scb$base+5Ah ; Hour in BCD (byte, r/w) @MIN equ scb$base+5Bh ; Minute in BCD (byte, r/w) @SEC equ scb$base+5Ch ; Second in BCD (byte, r/w) ?ERJMP equ scb$base+5Fh ; BDOS Error Message Jchecking: lxi h,control$table lxi b,cnt$tbl$lng ccir lxi h,control$exec$adr jrz find$exec$adr cpi 20h rc do$direct: mov d,a TJMP FR$wr$char page ; ; ; do$ESC: ; ESC control seq call cont$later ; ; ESC char look for char inESC [ Ps J erase display ; ESC [ Ps K erase line ; ESC [ Pn c device attributes request ; ESC [ Pn ; Pn f cursor positioning ; ESC [ Ps g clear tab stop(s) ; ESC [ Ps;..;Ps h set mode ; ESC [ Ps;..;Ps l reset attributes ; ESC [ Ps;..;Ps m set apace. stop at left margin ; HT 09h do TAB ; LF 0Ah do line feed scroll at bottom ; VT 0Bh same as LF ; FF 0Ch same as LF ; CR 0Dh do CR ; SO 0Eh invoke G1 set ; SI 0Fh invoke G0 set ; XON 11h ignored ; XOFF 13h ignored ; CAN 18h abort Eump ; (word, r/w) @MXTPA equ scb$base+62h ; Top of User TPA ; (address at 6,7)(word, r/o) ; end of normal SCB equates  the ESC table ; call remove$exec$adr lxi h,esc$table lxi b,esc$tbl$lng ccir rnz ; bad esc sequence lxi h,esc$exec$adr find$exec$adr: dad b dad b mov a,m inx h mov h,m mov l,a pchl page ; ; ESC # ; esc$pn: ; ESC # ttributes ; ESC [ Ps n Device status report ; ESC [ Ps q set LED's ; ESC [ Pn ; Pn r Set Top and Bottom Margins ; ESC [ 2 ; Ps y invoke confidence test ; ESC [ x Report / Req parameters ;; ESC ( A select char set ;; ESC ( B select char setSC seq (disp error character) ; SUB 1Ah same as CAN ; ESC 1Bh control seq ; DEL 7Fh not used ; ; ; ESC = Keypad mode ; ESC > Keypad mode ; ESC 7 Save current cursor post and char set ; ESC 8 Restore cursor position and char set ; ESC db 18h,18h,18h,03h ; /DN/ db 13h,13h,13h,08dh ; /LF/ db 04h,04h,04h,08eh ; /RT/ db 0f1h,0f1h,0f1h,0f2h ; /no scroll/ ; ; logical color table (used with ESC ESC ESC char) ; (where char is 50h to 7fh) ; db 000h,011h,022h,033h db 044h,055hcontrol seq call cont$later ; ; ESC # char look for char in the ESC table ; call remove$exec$adr lxi h,esc$pnd$table lxi b,esc$pnd$tbl$lng ccir rnz ; bad esc sequence lxi h,esc$pnd$exec$adr jr find$exec$adr page ; ; ESC [ ; esncreased intensity ; Ps=4 underscore ; Ps=5 blink ; Ps=7 reverse video ; esc$br$m: ; ESC [Ps;;Ps m set character attributes call get$Pn$def0$init check$br$m: dcr c ; check # of parameters used rz ; exit if None ana a ; Ps=0 ? jrz set$atfly ???) ; esc$c: ; ESC c reset ret ; ; ; esc$8: ; ESC 8 Restore cursor position and char set ret ; ; ; esc$7: ; ESC 7 Save current cursor post and char set ret ; ; place Keypad into Numeric mode ; esc$gt: ; ESC > Keypad mode e$E: mvi b,80 ; set # of col (B) dcr d ; start with row 0 push d push b TCALL FR$cursor$pos pop b out$next$E: push b mvi d,'E' TCALL FR$wr$char pop b djnz out$next$E pop d dcr c jrnz out$next$line$E ret ; ; ; esc$pn$6or end rz inr m ; advance get counter mov l,m ; get the get counter mvi h,0 dad d mov a,m do$DEL: ; DEL not used ret page ; ; ; do$CAN: ; CAN SUB abort ESC seq (disp error character) ; ; Invoke G0 char set ; do$SI: ; SI ic$br: ; ESC [ call clear$parm call cont$later ; ; ESC [ char look for char in the ESC table ; cpi '9'+1 ; input char a parameter jrc put$buffer ; yes, save parameters in buffer call remove$exec$adr lxi h,esc$br$table lxi b,esc$br$tbl$lr$off ; set attributes off dcr a ; Ps=1 jrz bold$on ; dcr a ; Ps=2 dcr a ; Ps=3 dcr a ; Ps=4 jrz underline$on ; dcr a ; Ps=5 jrz blink$on ; dcr a ; Ps=6 dcr a ; Ps=7 jrz reverse$on ; call get$Pn$def0 jr check$br$m set$a ret ; ; place Keypad into Application mode ; esc$equ: ; ESC = Keypad mode ret ; ; ; esc$br$y: ; ESC [2;Ps y invoke confidence test ret ; ; ; esc$br$x: ; ESC [ x Report / Req parameters ret ; ; ; esc$br$r: ; ESC [Pn;Pn r Set : ; ESC # 6 Double width line ret ; ; ; esc$pn$5: ; ESC # 5 set single width line ret ; ; ; esc$pn$4: ; ESC # 4 Double height line Bottom ret ; ; ; esc$pn$3: ; ESC # 3 Double height line Top ret ; ; Set tab at current cursor cnvoke G0 set ret ; ; Invoke G1 char set ; do$SO: ; SO invoke G1 set ret ; ; move cursor to margin on current line ; do$CR: ; CR do CR TJMP FR$do$cr ; ; ; do$LF: ; FF VT LF do line feed scroll at bottom TJMP FR$cursor$down ;ng ccir rnz ; bad esc sequence lxi h,esc$br$exec$adr jr find$exec$adr ; ; put byte in buffer pointed to by the put pointer+1 (advance pointer) ; put$buffer: mov c,a ; save character in C call get$par ; get address of parameter buffertr$off: bold$on: underline$on: blink$on: reverse$on: ret ; ; Ps=1 cursor key (l=cursor ; h=application) ; Ps=2 ANSI/VT52 (l=VT52 not supported) ; Ps=3 Column (l=80 col ; h=132 col) 80 only ; Ps=4 Scrolling (l=jump ; h=smooth) smooth only Top and Bottom Margins ret ; ; Ps=0 clear all LED's (default) ; PS=1 set LED 1 ; Ps=2 set LED 2 ; Ps=3 set LED 3 ; Ps=4 set LED 4 ; esc$br$q: ; ESC [Ps q set LED's ret ; ; Ps=5 Status Report ; responce is: ESC [0n (terminal OK) ; ESolumn ; esc$HH: ; ESC H set horizontal tab ret ; ; Move cursor down one line, scroll if on bottom margin ; esc$DD: ; ESC D move cursor down one line ret ; ; Move cursor to start of next line, scroll up if cursor ; is on the bottom marg ; move cursor to next tab stop or right margin if none ; do$HT: ; HT do TAB ret ; ; move cursor to left but not past left margin ; do$BS: ; BS back space. stop at left margin TJMP FR$cursor$left ; ; Sound bell tone ; do$BEL: ; BEL ri mov e,m ; get low byte adr of input buffer inx h mov d,m ; get high byte adr of input buffer inx h inr m ; advance input count mov l,m ; get current count (with input) mvi h,0 ; dad d ; compute adr in buf to place input mov m; Ps=5 Screen (l=normal ; h=reverse) ; Ps=6 Origin (l=Absolute ; h=Relative) ; Ps=7 Auto wrap (l=off ; h=on) ; Ps=8 Auto Repeat (l=off ; h=on) ; Ps=9 interlace (l=off ; h=on) ; Ps=20 LF/NL (l=line feed ; h=new line) ; esc$br$l: ; ESC [Ps;;Ps l reC [3n (terminal not OK) ; Ps=6 Report cursor position ; responce is: ESC [ Pl ; Pc R ; where Pl is the line number ; and Pc is column number ; esc$br$n: ; ESC [Ps n Device status report ret ; ; Ps=0 attributes off (default) ; Ps=1 bold or iin ; esc$EE: ; ESC E move cursor to start of next line ret ; ; Move cursor up one line, if on top margin scroll down ; esc$MM: ; ESC M move cursor up one line ret ; ; reset VT100 to initial state (causes INIT H to be asserted ; brieng bell RJMP FR$bell ; ; transmit answerback message ; do$ENQ: ; ENQ transmit answer back message ret ; ; ; esc$pn$8: ; ESC # 8 files screen with E's lxi d,024*256+0 ; set row (D) and col (E) mvi c,24 ; set # of rows (C) out$next$lin,c ; place input character into buffer ; stc ret ; ; get byte from buffer pointed to by the get pointer+1 (advance pointer) ; get$buffer: call get$par mov e,m inx h mov d,m inx h mov a,m ; recover put counter inx h sub m ; test fset mode ret ; ; see esc$br$l ; esc$br$h: ; ESC [Ps;;Ps h set mode ret ; ; Ps=0 clear tab stop at current column (default) ; Ps=3 clear ALL tab stops ; esc$br$g: ; ESC [Ps g clear tab stop(s) ret ; ; Pn default =1 missing Pn uses defa (disp error character) db 1Ah ; SUB same as CAN db 1Bh ; ESC control seq db 7Fh ; DEL not used cnt$tbl$lng equ $-control$table ; ; table scanned bottom to top ; control$exec$adr: dw do$DEL ; DEL not used dw do$ESC ; ESC control seq ck to start ; clear$parm: call get$par inx h inx h mvi m,0 ; zero out the input count ret ; ; ; get$par: lxi h,vt100$par$80 lda fun$offset ana a rz lxi h,vt100$par$40 ret ; ; ; vt100$par$80: dw buffer$80 db 0 ; current; A=0 if ran out of input else A=last character read from string ; (DE may not be changed) ; get$in$parm: lxi b,1 ; B=0, C=1 get$next$num: lda save$count dcr a rz sta save$count lhld buff$pointer ; get input buffer adr inx h ; PRE in$br$JJ: ; ESC [Ps J erase display ret ; ; ; esc$br$DD: ; ESC [Pn D cursor left ret ; ; ; esc$br$CC: ; ESC [Pn C cursor right ret ; ; ; esc$br$BB: ; ESC [Pn B cursor down ret ; ; ; esc$br$AA: ; ESC [Pn A cursor up ret pult value(s) ; position cursor to line (1st) and column (2nd) ; uses DECOM parm to set origin mode (within margin ; or full screen) ; esc$br$f: ; ESC [Pn;Pn f cursor positioning esc$br$HH: ; ESC [Pn;Pn H cursor positioning call get$Pn$def1$init ddw do$CAN ; SUB same as CAN dw do$CAN ; CAN abort ESC seq (disp error character) dw do$SI ; SI invoke G0 set dw do$SO ; SO invoke G1 set dw do$CR ; CR do CR dw do$LF ; FF same as LF dw do$LF ; VT same as LF dw do$LF ; LF do line feed put pointer into buffer ; ; ; vt100$par$40: dw buffer$40 db 0 ; current put pointer into buffer buffer$80 equ $-1 ds 20 buffer$40 equ $-1 ds 20 page ; ; ; cont$later: pop h ; get address to cont at in H jr save$exec$adr ; savcr adr shld buff$pointer mov a,m call test$num rc slar b ; 2x add b ; A=A+2B slar b ; 4x slar b ; 8x add b ; A=A+2B+8B=A+10B mov b,a ; save in B inr c ; advance parmeter count jr get$next$num ; ; return with carry age ; ; convert number to binary ; stop conversion at end or any none number ; (DE may not be changed) ; get$Pn$def0$init: call init$get ; set up to read buffer ; get$Pn$def0: call get$in$parm mov a,b ; get input data to A ret ; ;*****cr a mov d,a call get$Pn$def1 ; DE are not changed by this call dcr a mov e,a TJMP FR$cursor$pos ; ; What are you ; response is: ESC [?1; Ps c ; where Ps is: ; 0=base VT100, no options ; 1=processor option (STP) ; 2=advanced video opscroll at bottom dw do$HT ; HT do TAB dw do$BS ; BS back space. stop at left margin dw do$BEL ; BEL ring bell dw do$ENQ ; ENQ transmit answer back message page ; ; table scanned top to bottom ; esc$table: db '=' ; ESC = Keypad mode e it ; ; ; remove$exec$adr: lxi h,0 save$exec$adr: xchg lhld parm$base mov m,e inx h mov m,d ret page ; ; table scanned top to bottom ; control$table: db 05h ; ENQ transmit answer back message db 07h ; BEL ring bell db 08h set (Cy=1) if not a number (A=input Char) ; return bianary number in A if it was a number (Cy=0) ; test$num: cpi '0' rc cpi '9'+1 cmc rc sui '0' ret ; ; set up local values to use buffer parameters ; init$get: call get$par ; get po NOTE ESC [ ;4;A is the same as ESC [ 0;4;5A ; ; ; convert number to binary ; stop conversion at end or any none number ; return 1 if input is missing or a zero ; (DE may not changed) ; get$Pn$def1$init: call init$get ; set up to read buffer ; tion (AVO) ; 3=AVO and STP ; 4=graphics processor option (GPO) ; 5=GPO and STP ; 6=GPO and AVO ; 7=GPO, STP and AVO ; esc$ZZ: ; ESC Z same as ESC [ Pn c esc$br$c: ; ESC [Pn c device attributes request ret ; ; Ps=0 from cursor to end of db '>' ; ESC > Keypad mode db '7' ; ESC 7 Save current cursor post and char set db '8' ; ESC 8 Restore cursor position and char set db 'D' ; ESC D move cursor down one line db 'E' ; ESC E move cursor to start of next line db 'H' ; ESC H se; BS back space. stop at left margin db 09h ; HT do TAB db 0Ah ; LF do line feed scroll at bottom db 0Bh ; VT same as LF db 0Ch ; FF same as LF db 0Dh ; CR do CR db 0Eh ; SO invoke G1 set db 0Fh ; SI invoke G0 set db 18h ; CAN abort ESC seqinter to buffer(s) mov e,m inx h mov d,m inx h mov a,m inr a ; adjust for PRE decr sta save$count ; inx h ; mov a,m ; sta get$count xchg shld buff$pointer ret save$count: db 0 buff$pointer: dw 0 page ; ; set buffer ba get$Pn$def1: call get$in$parm mov a,b ; get input data to A ora a ; is input =0? rnz ; no, then use it inr a ; yes, then use default of 1 ret ; ; B=converted number in binary (from input string) ; C=number of digits converted+1 line (default) ; Ps=1 from start of line to cursor ; Ps=2 all of cursor line ; esc$br$KK: ; ESC [Ps K erase line ret ; ; Ps=0 from cursor to end of screen ; Ps=1 from start of screen to cursor ; Ps=2 all of screen (cursor is not moved) ; esct horizontal tab db 'M' ; ESC M move cursor up one line db 'Z' ; ESC Z same as ESC [ Pn c db 'c' ; ESC c reset db '#' ; ESC # control seq db '[' ; ESC [ cursor up esc$tbl$lng equ $-esc$table ; ; table scanned bottom to top ; esc$exec$fp: mvi c,00000001b ; turn intensity up jr set$FR$atr$c ; ; Half Intensity On ; esc$rtp: mvi c,00000000b ; turn intensity down parn$cont: mvi b,00000001b ; attribute bit to change jr set$FR$attr ; ; Set Attribute sequence ; esc$G: 25 (A=24?) jrnz not$status$line ; no, jmp inr a ; yes, A=25 sta paint$size ; set 40 column repaint to 25 lines not$status$line: call cont$later ; ; ESC = R C (go do it) ; sui ' ' mov e,a ; column # to E lhld parm$base inx h iesc$br$n ; ESC [Ps n Device status report dw esc$br$m ; ESC [Ps;;Ps m set attributes dw esc$br$l ; ESC [Ps;;Ps l reset attributes dw esc$br$h ; ESC [Ps;;Ps h set mode dw esc$br$g ; ESC [Ps g clear tab stop(s) dw esc$br$f ; ESC [Pn;Pn f cursor posTop ; ; ; esc$br$table: db 'A' ; ESC [ Pn A cursor up db 'B' ; ESC [ Pn B cursor down db 'C' ; ESC [ Pn C cursor right db 'D' ; ESC [ Pn D cursor left db 'H' ; ESC [ Pn ; Pn H cursor positioning db 'J' ; ESC [ Ps J erase display dbadr: dw esc$br ; ESC [ cursor up dw esc$pn ; ESC # control seq dw esc$c ; ESC c reset dw esc$ZZ ; ESC Z same as ESC [ Pn c dw esc$MM ; ESC M move cursor up one line dw esc$HH ; ESC H set horizontal tab dw esc$EE ; ESC E move cursor to call cont$later ; ; ESC G char ; call remove$exec$adr sui '4' ; '4' reverse video on jrz esc$G$4 inr a ; '3' underline attr on jrz esc$G$3 inr a ; '2' blink attr on jrz esc$G$2 inr a ; '1' alt char set jrz esc$G$1 inr a ; nx h mov d,m ; row # to D TCALL FR$cursor$pos jr remove$exec$adr page ; ; ; char$cnt$z: ; ^Z home and clear screen lxi d,lines*256+0 ; B=24(row) C=0(col) TCALL FR$cursor$pos call esc$t ; clear the status line lxi d,0 TCALL itioning dw esc$br$c ; ESC [Pn c device attributes request dw esc$br$KK ; ESC [Ps K erase line dw esc$br$JJ ; ESC [Ps J erase display dw esc$br$HH ; ESC [Pn;Pn H cursor positioning dw esc$br$DD ; ESC [Pn D cursor left dw esc$br$CC ; ESC [Pn C c 'K' ; ESC [ Ps K erase line db 'c' ; ESC [ Pn c device attributes request db 'f' ; ESC [ Pn ; Pn f cursor positioning db 'g' ; ESC [ Ps g clear tab stop(s) db 'h' ; ESC [ Ps;..;Ps h set mode db 'l' ; ESC [ Ps;..;Ps l reset attributes db 'm'start of next line dw esc$DD ; ESC D move cursor down one line dw esc$8 ; ESC 8 Restore cursor position and char set dw esc$7 ; ESC 7 Save current cursor post and char set dw esc$gt ; ESC > Keypad mode dw esc$equ ; ESC = Keypad mode ; ; '0' clear attributes rnz ; ; Rev. Video, blink, atl char set, and underline off ; esc$G$0: mvi c,10000000b ; turn attributes off mvi b,11110000b ; attribute bit to change jr set$FR$attr ; ; Select alt character set ; esc$G$1: mvi c,0FR$cursor$pos esc$y: TJMP FR$CES ; clear to end of screen home$cursor: lxi d,0 TJMP FR$cursor$pos esc$t: TJMP FR$CEL ; clear to end of line ; ; ; cursor$rt: TJMP FR$cursor$rt ; ; ; cursor$up: TJMP FR$cursor$up paursor right dw esc$br$BB ; ESC [Pn B cursor down dw esc$br$AA ; ESC [Pn A cursor up endif end ; ; ; esc$esc: call cont$later ; ; check for ESC ESC ESC ; cpi esc ; check if 3rd char is an ESC jrnz remove$exec$adr call cont$later ; ESC [ Ps;..;Ps m set attributes db 'n' ; ESC [ Ps n Device status report db 'q' ; ESC [ Ps q set LED's db 'r' ; ESC [ Pn ; Pn r Set Top and Bottom Margins db 'x' ; ESC [ x Report / Req parameters db 'y' ; ESC [ 2 ; Ps y invoke confidence te ; esc$pnd$table: db '3' ; ESC # 3 Double height line Top db '4' ; ESC # 4 Double height line Bottom db '5' ; ESC # 5 set single width line db '6' ; ESC # 6 Double width line db '8' ; ESC # 8 files screen with E's esc$pnd$tbl$lng equ $-esc$pn0000000b ; select alt character set mvi b,10000000b jr set$FR$attr ; ; Blinking On ; esc$G$2: mvi c,00010000b ; turn on blink attr jr set$FR$atr$c ; ; Under line ; esc$G$3: mvi c,00100000b ; turn on underline bit jr set$FR$atr$cge ; ; delete character ; esc$W: TJMP FR$char$del ; ; delete line ; esc$R: TJMP FR$line$del ; ; insert character ; esc$Q: TJMP FR$char$ins ; ; insert line ; esc$E: TJMP FR$line$ins page ; ; Half Intensity Off ; esc$l ; ; set current character as the attr ; mov b,a TCALL FR$color jr remove$exec$adr ; ; ; esc$equ: call cont$later ; ; ESC = R ; lhld parm$base inx h inx h sui ' ' ; remove ascii bias mov m,a cpi '8'-' ' ; test for linest esc$br$tbl$lng equ $-esc$br$table esc$br$exec$adr: dw esc$br$y ; ESC [2;Ps y invoke confidence test dw esc$br$x ; ESC [ x Report / Req parameters dw esc$br$r ; ESC [Pn;Pn r Set Top and Bottom Margins dw esc$br$q ; ESC [Ps q set LED's dw d$table esc$pnd$exec$adr: dw esc$pn$8 ; ESC # 8 files screen with E's dw esc$pn$6 ; ESC # 6 Double width line dw esc$pn$5 ; ESC # 5 set single width line dw esc$pn$4 ; ESC # 4 Double height line Bottom dw esc$pn$3 ; ESC # 3 Double height line ; ; Reverse Video On ; esc$G$4: mvi c,01000000b ; turn attributes on set$FR$atr$c: mov b,c ; reverse attr set$FR$attr: TJMP FR$attr or buffer dw WRITE ;2 Write a " " " " " " dw readf ;3 Set-up for fast read (154X only) dw writef ;4 Set-up for fast write (154X only) dw dsktst ;5 test for 154x and diskette type dw query$dsk ;6 get disk characteristics dw P channel ;I A =output char ;GETIN equ 0FFE4h K$clall equ 0FFE7h ; close ALL open logical files K$close equ 0FFC3h ; close a logical file ;I A = logical channel # to be closed ;O A = error #(0,240) RESET equ 0FFFCh PA0FF68h ; set the logical bank # for open ; disk commands ;I A=load and store bank # (C128 type bank) ; X=file name bank # K$readst equ 0FFB7h ; read status byte ;O A = status K$setlfs equ 0FFBAh ; setup a logical file 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> ThRINT ;7 print data character dw FORMAT ;8 format disk as 1541 disk dw user$fun ;9 vector to user code (L=viccount,H=vicdata) dw ram$dsk$rd ;10 RAM disk read dw ram$dsk$wr ;11 RAM disk write NUMCMD equ ($-IOTBL)/2 ; NUMBER OF COMMANDS iotbGE ; org bios8502 ; ; **** THIS IS THE COMMAND LOOP **** ; start: if use$fast @ldx sys$speed ;-K get desired system speed @stx vic$speed ;-K set system speed endif @ldx -1,# ;-K @txs ;-K set the stack to the top @JSR VICIO ;-K ;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 0F title '8502 drivers 4 Mar 86' maclib x6502 maclib z80 maclib cxequ $-MACRO ; ; COMMON EQUATES ; ; page 0 variables, from 0a to 8f are usable ; prtno equ 0000Ah ; 0Ah second$adr equ prtno+1 ; 0Bh DATCHN equ secondl$low equ low(iotbl) ; ; ; sys$reset: ;**CMD ENTRY** @jsr en$kernal ;-K @JMP (RESET) ;+K ; ; ; user$fun: ;**CMD ENTRY** @jmp (vic$count) ;-K page ; ; **** IO COMMAND DISPATCH ROUTINE **** ; VICIO: @lda vic$cmd ;-K get the go find and do requested operation bios$exit: @sei ;?K DISABLE INTERRUPTS @ldx 3eh,# ;?K set up Z80 memory map as required @stx force$map ;?K @ldx 82h,# ;-K @stx CIA1+int$ctrl ;-K turn on CIA timer B interrupts if use$fast @ldx 0,# FC0h ; open a logical file (after setlfs ; and setnam) ;O A = error # (1,2,4,5,6,240) K$chkin equ 0FFC6h ; open a channel for input ;I X = logical file # ;O A = errors #(0,3,5,6) K$chkout equ 0FFC9h ; open a channel for ou$adr+1 ; 0Ch CMDCHN equ datchn+1 ; 0Dh DEVNO equ cmdchn+1 ; 0Eh adr$1 equ devno+1 ; 0Fh temp$byte equ adr$1+2 ; 11h ; equ temp$byte+1 ; 12h pal$nts equ 00a03h ; FF=PAL=50Hz 0=NTSC=60Hz serial equ 00a1ch d2pra equ 0dd00h ; serial contro command @cmp NUMCMD,# ;-K is this a valid command @bcs bad$command ;-K no, exit without doing anything ;-K yes, get vector to it @cld ;-K clear to binary mode @asl a ;-K A=2*CMD (carry cleared) @clc ;-K @adc iotbl$low+2,# ;-K a ;-K get value for 1 MHz mode (slow) @stx vic$speed ;-K set system speed endif @jmp enable$z80+6 ;-K PAGE ; ; ; iotbl: dw sys$reset ;-1 reset system (C128) dw initilize ;0 initialize the 8502 dw READ ;1 Read a sector of data to secttput ;I X = logical file # ;O A = error #(0,3,5,7) K$clrchn equ 0FFCCh ; clears ALL I/O channel K$chrin equ 0FFCFh ; get a character from input channel ;O A=input character K$chrout equ 0FFD2h ; output a character to outputl port (clk and data) d1sdr equ 0dc0ch ; Fast serial data reg. d1icr equ 0dc0dh ; serial channel interrupt control reg clkbit equ 10h ; d2pra clock bit mask ; ; KERNAL EQUATES ; K$spin$spout equ 0FF64h ; C=0 spin C=1 spout K$setbnk equ dd to vector table start address @sta VICIO2+1 ;-K modify the JMP instructions ind adr VICIO2: @jmp (IOTBL) ;-K this is the ind adr that ; is modified above ; ; ; input$byte: @sei @lda d2pra @eor clk$bit,# @sta d2pra ; @lda 8v (4,5) ; secondary address in vic$trk ; the logical file number is equal to the device # ; if VIC$count=0 then output character in VIC$data ; if VIC$count<>0 then output characters pointered to by @buffer ; PRINT: ;**CMD ENTRY** @lda vic$drv ;@sta vic$data ;+K @jsr clk$hi ;+K @sty io$0 ;+K 2/24 @lda vic$drv ;-K @ora fast ;-K set current drive as fast @sta fast ;-K @rts ;-K page ; ; ; query$dsk: ;**CMD ENTRY** @jsr set$drv$f ;-K will query track set by user ; WRITE2: @lda 0ffh,# ;+K @sta vic$data ;+K writes thru ROM to RAM @jmp opencm ;+K page ; ; Set-up for fast disk write ; writef: ;**CMD ENTRY** @lda 2,# ;-K 2=read command @skip2 ;-K ; ; Set-up for fast disk read ; readf: KERNAL @STA @BUFFER,X ;+K save it in the buffer @INX ;+K advance the buffer pointer @BNE READ1 ;+K loop back if not past buf end @jmp K$clrchn ;+K CLEAR CHANNEL ; ; disk$changed: @lda 0bh,# ;?K disk changed error code @sta vic$data ,# in$1: @bit d1icr @beq in$1 @lda d1sdr bad$command: @RTS ;-K page ; ; initialize the 8502 ; initilize: ;**CMD ENTRY** @ldx low(irqs),# ;-K @ldy high(irqs),# ;-K @stx 314h ;-K IRQ vector @sty 315h ;-K @stx 316h ;-K-K @sta prtno ;-K @lda vic$trk ;-K ;; @sta second$adr ;-K this line should be deleted and one @cmp second$adr ;-K ..below used. @sta second$adr ;-K save secondary adr @bne reopen$prt ;-K @jsr en$kernal ;-K print$cont: @ldx prtno ;+K@ldy query$cmd$lng,# ;-K command length is 4 @ldx query$cmd,# ;-K @jsr send$fast$cmd ;-K @jsr input$byte ;+K @sta vic$data ;+K @bpl clk$hi ;+K exit if not MFM @and 0eh,# ;+K test for error @bne clk$hi ;+K exit if error @jsr i ;**CMD ENTRY** @lda 0,# ;-K 0=read command @sta f$cmd ;-K @lda 0,# ;-K @sta vic$data ;-K @jsr set$drv$f ;-K @ldy f$cmd$lng,# ;-K command set above rd/wr @jsr send$fast ;-K @jmp clk$hi ;+K page ; ; test the format of the disk ret;?K @jmp en$K$open ;?K page ; ; **** DISK SECTOR WRITE **** ; WRITE: ;**CMD ENTRY** @jsr set$drv ;-K @jsr ckotcm ;-K @LDY setpnt$lng,# ;+K ; WRITE0: @LDA SETPNT,X ;+K @JSR K$chrout ;+K @INX ;+K @DEY ;+K @BNE WRITE0 ;+K BRK vector @sty 317h ;-K @stx 318h ;-K NMI vector @sty 319h ;-K @jsr en$kernal ;-K @lda 0fffeh ;+K @sta 0fffeh ;+K write to RAM under ROM @lda 0ffffh ;+K @sta 0ffffh ;+K @lda 6,# ;+K @sta CIA2+data$dir$b ;+K se @JSR K$chkout ;+K @BCS PERR0 ;+K PRINT ERROR IF CARRY SET @sty io$0 ;+K 2/24 @ldx vic$count ;-K @bne print$buffer ;-K @LDA vic$data ;-K GET CHARACTER @sta io$0 ;-K @JSR K$chrout ;+K AND PRINT IT @JMP K$clrchn ;+K CLEAR CHANNEnput$byte ;+K read offset sectors status byte @sta @buffer ;+K @and 0eh,# ;+K test for error @bne clk$hi ;+K exit if error @tax ;+K get a zero in X @ldy 5,# ;+K five info bytes are sent back query$loop: @inx @jsr input$byte urn code to CP/M ; telling the disk type. Also test for FAST disk drive. ; dsktst: ;**CMD ENTRY** @lda vic$drv ;-K @eor 0ffh,# ;-K @and fast ;-K @sta fast ;-K clear fast indicator bit for current drive @jsr set$and$open ;-K set drv @JSR K$clrchn ;+K @JSR CKINCM ;+K @BNE WRITE2 ;+K @JSR K$clrchn ;+K @JSR CKOTDT ;+K @LDX 0,# ;+K ; WRITE1: @sei ;+K disable interrupts @ldy 3fh,# ;+K enable all RAM in bank 0 @sty force$map ;+K @LDA @BUFFER,X ;-Ktup user port for RS232 @lda pal$nts ;+K -1=50Hz(PAL) 0=60Hz(NTSC) @sta sys$freq ;+K @jmp K$clall ;+K close all open files PAGE ; ; **** DISK SECTOR READ **** ; READ: ;**CMD ENTRY** @JSR set$drv ;-K @jsr en$kernal ;+K @ldx dL print$buffer: @stx temp$byte ;-K @lda @buffer ;-K @sta adr$1 ;-K @lda @buffer+1 ;-K @sta adr$1+1 ;-K @ldy 0,# ;-K @ldx 0,# ;-K print$buf$loop: @sta bank$0 ;?K enable RAM bank 0 (no I/O) @lda (adr$1),y ;rK @stx force$map ;r @sta @buffer,X @dey @bne query$loop clk$hi: @lda d2pra ;+K set clock bit HIGH @and 0ffh-clkbit,# @sta d2pra @rts PAGE ; ; **** PRINTER OUTPUT **** ; ; this routine will support two printers ; the device number is passed in vic$drclose and reopen the channel @ldx 0,# ;+K delay to allow drive to reset status tst$delay: @nop ;+K @nop ;+K @dex ;+K @bne tst$delay ;+K @ldy inq$cmd$lng,# ;+K @ldx inq$cmd,# ;+K @jsr send$fast$cmd ;+K @jsr input$byte ;+K @ldy 0,# ;-K re-enable kernal @sty force$map ;-K @JSR K$chrout ;+K write buffer character @INX ;+K @BNE WRITE1 ;+K write all 256 bytes of buffer @JSR K$clrchn ;+K clear the channel @LDA '2',# ;+K write command @JMP setup ;+K atchn ;+K @jsr K$chkin ;+K @bcs disk$changed ;+K @jsr K$clrchn ;+K clear the input channel for now @LDA '1',# ;+K read command @JSR setup ;+K send it @JSR CKINDT ;+K @LDX 0,# ;+K ; READ1: @JSR K$chrin ;+K get a byte from the K @jsr K$chrout ;+K @iny ;+K @dec temp$byte ;+K @bne print$buf$loop ;+K @jmp K$clrchn ;+K ; ; PERR0: @CMP 3,# ;+K FILE NOT OPEN? @BNE PERR1 ;+K BRANCH IF NO reopen$prt: @JSR OPNPRT ;?K OPEN PRINTER CHANNEL @BCC print$cont ;+requested drv# @bpl unit$nu$0 @inx ;-K make unit 1 unit$nu$0: @iny ;-K add one to the drive # @lsr a ;-K is drive number correct? @bcc unit$nu$0 ;-K no, loop back @stx dskcmd+5 ;-K save unit# to disk cmd string @stx fmtcmd+1 ;-K save rd$buf$1 ; @rts PAGE ; ; ; set$drv: @lda vic$trk ;-K @jsr binasc ;-K @stx dskcmd+7 ;-K @sta dskcmd+8 ;-K @lda vic$sect ;-K @bmi no$side$1 ;-K @jsr binasc ;-K @stx dskcmd+10 ;-K @sta dskcmd+11 ;-K @jmp set$drv$num ;-K no @ldx 0,# ;?K @stx force$map ;?K enable the kernal @ldx cmdchn ;+K @jsr K$chkout ;+K @bcs chan$error ;+K @ldx 0,# ;+K sendf: @lda f$cmd$buf,x ;+K @jsr K$chrout ;+K @inx ;+K @dey ;+K @bne sendf ;+K @jsr K$clrchn ;+K @bit seam$dsk$wr: ; RAM disk write @ldx 80h,# ;-K if use$fast @lda 0,# ;-K 0=slow (1 MHz) @sta vic$speed ;-K set to slow mode endif @lda 3Fh,# @stx RM$command ;-K give command to RAM DISK @sta force$map ; remove I/O area @rts K IF CARRY CLEAR, OK TO PRINT PERR1: @LDA 255,# ;+K NO DEVICE PRESENT @STA vic$data ;+K FLAG BAD ATTEMPT writes to ram under ROM PRTST: @RTS ;+K PAGE ; ; **** FORMAT DISK ROUTINE **** ; FORMAT: ;**CMD ENTRY** @jsr set$drv$num ;-K @unit# to format cmd string @txa @ror a ;-K get lsb to carry bit @lda F$cmd @and 0feh,# @adc 0,# ; set the lsb if carry set (carry cleared) @sta F$cmd @tya ;-K get device # to A @sta devno ;-K save device # @adc 3,# ;-K make the dat$side$1: @lda 04h,# ;-K @sta vic$data ;-K @jmp bios$exit ;-K ; ; ; set$drv$f: @lda vic$count ;-K @sta f$rd$count ;-K @lda vic$trk ;-K @sta f$rd$trk @lda vic$sect ;-K @bpl side$0 ;-K @tax ;-K @lda f$cmd ;-K @ora 10h,#rial ;+K @bvc not$fast ;+K @bit d1icr ;+K clear interrupts from chip @rts ;+K chan$error: @lda 0dh,# ;+K get error code @skip2 ;+K not$fast: @lda 0ch,# ;+K get error code @sta vic$data ;+K @jsr clk$hi ;+K @jmp bios$exit ;+ ;-K PAGE ; ; ; setup: @STA DSKCMD+1 ;?K @LDA 2,# ;?K RETRY COUNT @STA vic$data ;?K writes to RAM under ROM @JSR CKOTCM ;?K returns X=0 @LDY dskcmd$lng,# ;+K setup2: @LDA DSKCMD,X ;+K @JSR K$chrout ;+K @INX ;+K @DEY lda fast ;-K @and vicdrv ;-K @bne format$fast ;-K @JSR CKOTCM ;-K returns X=0 @LDY fmtcmd$lng,# ;+K FMT1: @LDA FMTCMD,X ;+K @JSR K$chrout ;+K @INX ;+K @DEY ;+K @BNE FMT1 ;+K @JSR K$clrchn ;+K fmt2: @JSR CKINCM ;+K check for a chan# (carry cleared above) @sta datchn ;-K save data chan# @adc 4,# ;-K make the cmd chan# @sta cmdchn ;-K save cmd chan# @lda serial ;-K @and 0bfh,# ;-K @sta serial ;-K clear the fast serial indicator @rts ;-K page ; ; ** ;-K @sta f$cmd ;-K @txa ;-K @and 7fh,# ;-K side$0: @sta f$rd$sect ;-K page ; ; VIC$DRV dev,dat,cmd ; 00000001 device #8-0 8,11,15 ; 00000010 device #9-0 9,12,16 ; 00000100 device #10-0 10,13,17 ; 00001000 device #K ; ; ; set$cmd: @lda dskcmd+5 ;?K check lsb of unit # @ror a ;?K get lsb to carry bit @bcc unit$0 ;?K @inx ;?K make command for unit 1 unit$0: @stx F$cmd ;?K @rts page ; ; ........not tested........ ; ;rd$buff: ; @sei ; d ;+K @BNE setup2 ;+K @JSR K$clrchn ;+K @JSR CKINCM ;+K @BEQ setup3 ;+K @sty io$0 ;+K 2/24 @DEC vic$data ;-K @BEQ setup5 ;-K @jmp disk$changed ;-k ; ; setup5: @LDA 0dh,# ;?K normal read/write error flag @skip2 ;?K ALWerrors @BEQ setup3 ;+K no errors, return good status @BNE setup5 ;+K error return error status format$fast: @ldx @buffer ;-K get command length fast$F: ;-K @lda @buffer+1-1,x ;-K @sta F$cmd-1,x ;-K @dex ;-K transfer command tail fro** 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 ; ; **** OPEN DISK COMMAND CHANNEL **** ; se11-0 11,14,18 ; 10000001 device #8-1 8,11,15 ; 10000010 device #9-1 9,12,16 ; 10000100 device #10-1 10,13,17 ; 10001000 device #11-1 11,14,18 ; set$drv$num: @ldy 8-1,# ;-K start as drive 8 @ldx '0',# ;-K ..unit 0 @lda vic$drv ;-K get isable interrupts ; @lda vic$data ; @sta adr$1+1 ; save hi part of address ; @lda 0,# ; @sta adr$1 ; save low part of address ; @tax ; get a zero for both indexes ; @tay ; ;rd$buf$1: ; @lda (adr$1),y ; @sta @buffer,x ; @inx ; @iny ; @bne AYS ; ; ; setup3: @lda 0,# ;?K get data good flag setup4: @STA vic$data ;?K writes to RAM under ROM @jsr en$kernal ;?K @JMP K$clrchn ;+K page ; ; ; send$fast$cmd: @jsr set$cmd ;?K unit # must have been set already send$fast: m buffer+1 @bne fast$F @ldy @buffer ;-K @iny ;-K @iny ;-K count is tail length plus 2 @ldx F$cmd ;-K @jsr send$fast$cmd ;-K @jmp fmt2 ;+K PAGE ; ; ; ram$dsk$rd: ; RAM disk read @ldx 81h,# ;-K @skip$2 ;-K ; ; ; rt$and$open: @jsr set$drv$num ;-K en$K$open: @jsr en$kernal ;-K opencm: @LDA CMDCHN ;+K @clc ;+K clear the carry to force true closing @JSR K$close ;+K @LDA CMDCHN ;+K @LDX DEVNO ;+K @LDY 15,# ;+K @JSR K$setlfs ;+K @lda 0,db 0 ; byte 10 db 0 ; byte 11 f$cmd$lng equ 6 ; U0+cmd+track+sector+#sectors write$stat equ 01001100b write$stat$lng equ 4 ; U0+cmd+(status to write) inq$cmd: equ 00000100b inq$cmd$lng equ 3 ; U0+cmd query$cmd: equ 10001010b query$cmd$db 0 ; byte 10 db 0 ; byte 11 f$cmd$lng equ 6 ; U0+cmd+track+sector+#sectors write$stat equ 01001100b write$stat$lng equ 4 ; U0+cmd+(status to write) inq$cmd: equ 00000100b inq$cmd$lng equ 3 ; U0+cmd query$cmd: equ 10001010b query$cmd$a prtno ;+K @TAX ;+K LDX #4 (or #5) @ldy second$adr ;+K secondary adr passed in vic$trk (normaly=7) @JSR K$setlfs ;+K @LDA 0,# ;+K @JSR K$setnam ;+K @lda 0,# ;+K bank (C128 type) for load and store @tax ;+K file name bank (C128 typ@rts page ; ; ; * DEVICE MISSING, CLEAN UP ERROR * ; MISDSK: @LDA 0fh,# ;+K SET ERROR CODE for missing drive @STA vic$data ;+K writes to RAM under ROM @LDA CMDCHN ;+K K$close CHANNEL @clc ;+K force true closing of channel @JSR K# ;+K bank (C128 type) for load and store @sta F$stat ;+K write status byte value = 0 @tax ;+K file name bank (C128 type bank#) @jsr K$setbnk ;+K @ldx write$stat,# ;+K @jsr set$cmd ;+K @lda 4,# ;+K write status command lenght @llng equ 4 ; U0+cmd+(track offset) to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Thlng equ 4 ; U0+cmd+(track offset) to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> The bank#) @jsr K$setbnk ;+K @JMP K$open ;+K page ; ; handle all interrupts in BIOS 8502 (throw them away) ; irqs: @lda CIA$1+int$ctrl @lda CIA$2+int$ctrl @lda 0fh,# @sta VIC+25 @pla @sta force$map @pla @tay @pla @tax @pl$close ;+K @JMP bios$exit ;+K PAGE ; ; **** SELF CORRECTING CHECK IO ROUTINES **** ; CKICM: @JSR OPENCM ;+K CKINCM: @LDX CMDCHN ;+K @JSR K$chkin ;+K @BCS CKICM ;+K @JSR K$chrin ;+K @CMP '0',# ;+K @RTS ;+K ; ; ; CKIdx low(f$cmd$buf),# ;+K @ldy high(f$cmd$buf),# ;+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 ;+K test for fast device @bvsera *.prn era *.rel era *.bak rmac cxkrnl $$pz-s rmac cxio $$pz-s rmac cxintr $$pz-s rmac cxramdsk $$pz-s rmac cxkey $$pz-s rmac cxem $$pz-s rmac cxvt $$pz-s rmac cx80 $$pz-s rmac cxprinte $$pz-s rmac cxdisk $$pz-s rmac cxext $$pz-s rmac cxsca @rti ; ; ; en$kernal: @ldy 0,# ;?K @sty force$map ;?K @rts ;+K page ; ; ; DSKCMD: db 'U1:8 0 tt ss',CR dskcmd$lng equ $-dskcmd POUND: db '#' FMTCMD: db 'N0:CP/M DISK,65',CR fmtcmd$lng equ $-FMTCMD SETPNT: db 'B-P DT: @JSR OPENDT ;+K CKINDT: @LDX DATCHN ;+K @JSR K$chkin ;+K @BCS CKIDT ;+K @RTS ;+K ; ; ; CKODT: @JSR OPENDT ;+K CKOTDT: @LDX DATCHN ;+K @JSR K$chkout ;+K @BCS CKODT ;+K @RTS ;+K ; ; ; CKOCM: @jsr OPENCM ;+K no$dt$open ;+K do not open data channel if fast ; ; **** OPEN DISK DATA CHANNEL **** ; OPENDT: @LDA DATCHN ;+K @clc ;+K forces true closing of channel @JSR K$close ;+K @LDA DATCHN ;+K @LDX DEVNO ;+K @LDY 8,# ;+K @JSR K$setlfs ;+b $$pz-s mac cxkycode $$pz-s mac fast8502 $$pz-s link bnkbios3[b]=cxkrnl,cxio,cxintr,cxkey,cxem,cxvt,cx80,cxprinte,cxdisk,cxramdsk,cxext,cxscb gencpm auto addbios fast8502 era *.sym era cpm3.sys 8 0',CR setpnt$lng equ $-setpnt ; ; fast command buffer ; f$cmd$buf: db 'U0' ; not set f$cmd: db 0 ; byte 3 F$stat: f$rd$trk: db 1 ; byte 4 f$rd$sect: db 0 ; byte 5 f$rd$count: db 1 ; byte 6 db 0 ; byte 7 db 0 ; byte 8 db 0 ; byte 9 CKOTCM: @jsr en$kernal ;?K @LDX CMDCHN ;+K @JSR K$chkout ;+K @BCS CKOCM ;+K @LDX 0,# ;+K @RTS ;+K PAGE ; ; **** OPEN PRINTER CHANNEL **** ; opnprt: @jsr en$kernal ;-K @lda prtno ;+K @clc ;+K @JSR K$close ;+K @ldK @lda 0,# ;+K bank (C128 type) for load and store @tax ;+K file name bank (C128 type bank#) @jsr K$setbnk ;+K @LDA 1,# ;+K @LDX low(POUND),# ;+K @LDY high(POUND),# ;+K @JSR K$setnam ;+K @jsr K$open ;+K @bcs misdsk no$dt$open: lng equ 4 ; U0+cmd+(track offset) to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> Th GENCPM.DAT 3. Enter 'SUBMIT CZ' and the rest is almost automatic. Just answer 'Y' to all the ERASE? prompts. 4. When the process is complete, you will have a CPM+.SYS file that you can copy to any disk from which you want to ility: From USER 0: (these are the utilities you will need) RMAC.COM MAC.COM LINK.COM GENCPM.COM ADDBIOS.COM SUBMIT.COM 1ͽ0CPM+ SYS@ñ*,*.}|ڡ!".*,{zғ** v*.".H  DISK FULL: CPM$!".***.#".ɯ22)!@",!".  <  NO DIR SPACE: CPM$!CPM3 be able to boot. You also need to copy the Console Command Processor (CCP.COM) from USER 0 to the disk from which you want to boot. 5. Details regarding System Generation can be found in the DRI System Guide. There are sev From USER 1: (these are the data files) CX80.ASM CXDISK.ASM CXEM.ASM CXEXT.ASM CXINTR.ASM CXIO.ASM CXKE MAKESYS.DOC 08May87 CP/M 3.0 on the Commodore 128 28May87 To generate a new CPM+.SYS file used by CP/M on the Commodore 128 follow the procedure listed below. You will need a 1581 disk drive for this task. Without a 1581, you wi SYS^Ñ**}|z!"*{zl*f*"8*"!"**}>*#"ɯ22!""<  NO CPM3 FILE$~# !\ HEXeral differences to be noted, however, such as somewhat different module names and the implementation of system utilities such as COPYSYS and CPMLDR. Y.ASM CXKRNL.ASM CXKYCODE.ASM CXPRINTE.ASM CXRAMDSK.ASM CXSCB.ASM CXVT.ASM FAST8502.ASM ll have to make modifications to the procedure to suit your system (refer to the MAKESYS instructions on the 5.25" diskette that accompanies the DRI manual offer). If you're lucky enough to possess a 1750 RAM expander, you could use it (drive M:) in nx**}|a!"*{zS*M*"*"!"**}>*#"ɯ22!""<²  NO BIOS8502 FILE$CXKYCODEHEXrL**}|5!"*{z'*db 0 ; byte 10 db 0 ; byte 11 f$cmd$lng equ 6 ; U0+cmd+track+sector+#sectors write$stat equ 01001100b write$stat$lng equ 4 ; U0+cmd+(status to write) inq$cmd: equ 00000100b inq$cmd$lng equ 3 ; U0+cmd query$cmd: equ 10001010b query$cmd$ CPM3.LIB CXEQU.LIB MODEBAUD.LIB X6502.LIB Z80.LIB BNKBDOS3.SPR RESBDOS3.SPR CZ.SUB place of the 1581 work disk. This procedure requires a 400K work space. 1. Create a 1581 work diskette, using the FORMAT utility, or start with an empty RAMdisk (drive M:). 2. Copy the following files to the work disk, using the PIP utACP/M PLUS652A>: 7* " _: =2 3_* w#" _: ɯ2 ͟ʍ:>_<2 _g_owwGG: 2 x͓G0  !L ÷͟ʍa_: ʪ !P ÷! !~#_ This program will create a C!*"*"!"**}>*#"ɯ22!""<‚ s NO KEYS FILE$!!!Bb!c͹!!!*.}",>3¾ <  CANNOT CLOSE CPM$PM+.SYS file from The CPM3.SYS file (created by GENCPM) and The 6502 BIOS File supplied in Intel HEX format And CXKYCODE File supplied in Intel HEX format (1st HEX address is FUNCTION table address) (1st two bytes poiLoading 8502 BIOS .HEX file Loading Key definition .HEX file Adding new vectors to CPM+.SYS Adding Key def. to CPM+.SYS Adding CPM3.SYS to CPM+.SYS Adding BIOS8502 to CPM+.SYS Closing CPM+.SYS file 2 >}®|2 /g$ " *nt to ASCII table) The ROM boot code will load the CPM+.SYS file HEX file error - first record must be start adr and last record must contain the last adr All other address must be between  }o|g}$|2 Ҵ>2 >}®|2 /g$" D;* ++}o|g}X$|2 Ҵ$3d$$$$$$: G: 3x3: 3: 3*}3|3$3¬!: =2 ¼$3: g. zW ~3# the start and end adr also HEX file must be ended with a NULL record and Start address must be on a page boundary and File can NOT be larger than 4K nLT`"y2;!"(:2(=2(:=;!~;4#.{2(!" "9"2!;(y3]K!o\b!,_^#V* !J ^#V̀:#!"(COPYRIGHT (C) 1982, DIGITAL RESEARCH 151282/(  + 1 7 = }!!!!"""""# ####$$ šn!6@G:x: P:<: P n6 t6! ^6 t6u:)<͠^! G:Ҏ>xʝʝw>ɯw̩z:»!>wɯ:=zxzz: :G:=/ͽx:Āy!4  ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0L$$#$-$A$J$S$@Y$u u J$u u }$$$$$*%P%$%&'('d'''(('({ A g X J v !)$*^#V#^#Vw# ll l ls:¬MAUSER Enter User#:5 5A> Th > wM  2*7w#6?#7 .,:;[]=<>|!?]45#Ra{i_p# l s s͂:(A2= / ::0! dگ61#d ڸïp#:w#6 !6:6 *#!)6.#)͂ O(BDOS 2 GH)+6:2, :!-  :, !+*( ~L#Bxz:* : *( ~ʓOڊ{2Ó#w:2. +:. 2- !% "( 2* ! "& !* ~4:2- Ԃ: Gͳͨ^2+ >2:2 *N#G2  .Function = File = !,!"h!9"f! ͉:2(t™:! =Hgo:O*;*Ó*"r*r"ÿ<:g:!͐*f}D! ~6t!r ͷO(^  ::+ ̜2 5*( ~o#"( M š*( ~`Uoj*( ~#"( Ñ!* ~6s!+ 6:+ ‚xoͳ*& ~2+ o#"& !+ 6M : W:2 x ͺ*( +"( w  : >2* 2 :*( : +w"( ͺ:G: !(s#r#p*k(N#F*m(^#V#F*(:(O}|y9*( +"*( }|yP#9*( *(DM"(*k(s#r*m(s#r#pyoxg͝DM*(0MD"(!*MD$:(Oë!(N:( «G>O:( ù* :(n` ~#foͤ2(O"(}:(O*( "(!"@*(*#":&2(͒:È0:+Òy<_W`iͫDM*w( ~bNpwDM*w(T] KKͦ*w("w(ͦ"w(@ :(N N#Fy*(}|h#ð*(ͫ# 6RX*q(6~Gw#* #~$%+@*9> # #>? ;*~ w-xąH"(0 *(#ĊH( ,ˆʀHÈ2(xą ):(@O~#w͚ʀôb_++V@* )͗Os++r !% "( ^-:* $P:<\: W:2 xM s:<9>2 :* 9x~+q ’x2 :* ͂^2 ¢ů͠: !ڽ*( ~5WèjM 2 ͨx*( +w"( j2("(:(O:(G2(!(w*~zWw+ !z?#~*!* *G!O~2(~m͗O~t>2(?:(2(O:(w:Ғ4~:(w?r##rp# ä |g}oì*g( #G ¾1*q(:(*w***> r wDM*w(6# x *o(w*(*w(s#r̀*i(6#6*}("(w@*(|<ď+>!8>8> t>nͦv8 ~*o(wn:(r :(/GyOOA +¬ ¢y2(:(x¹o&:(W>OͫE:(ڟ?N/*"(y2ͦ+>2( !x>w~6:(6~#+w#w+~;wɯ2 K,OFq-yl?Npg&:(ʓ~†wŒ~è# # x ͗w w@ ~wb͐Ú>2+ 2* jx. #NzW:  : !2 W! 5= ^x^ z: m :* ;#wO: 9ʌ ^:  ~x  ) :* :   >*( +"( w++2+ 2+ p!" CP/M Error On : Disk I/OInvalid DriveRead/Only FileRead/Only DiskPassword ErrorFile Exists? in Filenameò ò >2(a." :(2:<:5(5(;(:(2ɯ2(2{_zW{_zW ) 7)e(:(O!*c(:(Oͫ}@2æ  ~á *g(:(o$*~K6?~wKw**i({#zir+s{ozg*(*(|g͸*u(*(  R>22Z$w*q(>ww:(c( *(#*i(s#r*:(!(:̀2(k,ºʺ*(*iҺ@:O~2(~WW:2(Ôyʛ?ʔx ʔ |̷ÔN͆G:(<2(x# W:(<­:2(2 G?>Gr x~:(2(Ô##~*$*">2!"*>o+"! *!b("": r#~?w#>r# L=J! Lv w,b ?~O ͆=: <>w##~2( 4~?¹:(<üAX2(r K:(w++~=wv 4͗O5:(2(Xr y< < <% zr ͷr 6r 9r MDÌ:o !6!h : ʚnt2 r 62 >r z<*)$"!z<~r s^#V#N#FxN:oʲ ̀õ (# Þ 4#4#4)7( #  w#*J|^#V#"i(##"k(##"m(###"o(#"q(##"(!s( )*s(!()*(|!(6~67*k(w#w*m(w#w#w>2('å2(*OͶyڲ ò <*e(Ͳ:0!(:(:(ò 2*(>*ͫ"(G~#<*q(#~!;(!(!(!~6k!"2(*q(N1q*{(]*{([*y(}<^#V(t6 ^#V}e ^#V#~2(>â9͆>!"(*y(³*(X)*ÿ͂"*g(*K! ~<:wb##>w#w> r !~#<>2: *(~w *" 2(>ʄ@~k:((s~*9~Ês~ ~ͅ<Eʀ@~›:(6!¦w͚̋,ÇPY*({zBKNyʺ NúT͓Â!"(>(Â:(G:(O:(h=2(7ryy/W!(:(lڈ>F6:(_/G:(ʧ:(ڨ|OͤG:(_OzW{|:(*(}|BKN zyGW#x#W{s+p+q7r#r#r>@ >2  !!q#p#w2(wW*e(_3ҫ -!(s:(!(xQ*q(~wɯ2(2(ù*~2(~w#~2(~wZ!""2(=2*~2(=2(2(k:*wX/ 6X* ~"2(Asv"@!N"!N"~v"$̓ W"+!v"w̚v"$̓ r" r"ͅ:(r">2(+A@2! ͚A=: <%~?¯"k"?~?ʾ"ZT͐"*>o"͒"!:O"(Ý"͐6͚q&&͋"&@6,͚%Xͤ͋&͗wO~<:( g&~w#w#6##)͋&@ * g&~?G++N͆p# Þ&͐*6!¿&?~p*6 &>2ͱ ! ! ͷ w*o)**"g(*3*:= :(Oi* :=H*:(Gi* a*6:(G/O*((*(W :(T=ʞa*##()"("(x+x+!"("("(X*C+*(~<**("(*:(*!:(***(}**("(x++"(:(2(9:(>#:(>#*+S!X:(ڜq: ʺ!((ʵ>2( ͤ2(O DM͸}>r "("(2(:(2(* :(:(̀!~$6:03i"!~6*e(>=)Q!(QX<k*{(}<^#V{!~! _*o(~s̓  2@ !()#w*~"!!(Fw̓ :(w̚":>#2(̓ *~wć"͚c2(ZT͐-3#͗#@!Y#sY#̓ Y# Y#ͅ:(As#:(@#@!#$̓ —#>2—#͇ͱ * «#>2(͙ wB p'+!#:(w͚AP{" 2! W>O2 ø ͐R*e()$:(r(w'ͧ B pͧ ,Úgsr ͐-ͤ͜!S')_'ͤ̓ ~?w͐s-?F͜p!'̓ ¡'>2ͱ ?~¾'¾''''>w'͙ =2(͜!:(wÚ~̓ ʑ'pá'!(6Nð**(}+*(}+"(*(x+"(x+m+*(^#V*( s#r*(*(s#r*(:(Y+4Y+̓+*(*(~#ng+*( s#r ^#V|:(w:(ʴ+>2d,:+#++>29+2~2#! , , ,)xFsO s#r:(„y==„*(!(^W*y(^#Vx+7=2(wͼկw#KWK*("(J T͞*(:(["(Ͷ:(WMںʛ>(úͶ >TJ:(!(ʷ͞x!(w4 PWP  Â*!!~~#~O~##Fx T]## #~ ȷ   *4 # '  4 !( *~^ ^ 33G# P v :dv 6 y #*~w>2 *p@! ~*"v@*w# ) 6# ͙   !N "ök*w()$*c()$-͐ͤÀk*s(" :(;$:r 2͚ù͚͚}/_|/*e(W}_*c("e(}o|g"c(>2({2{2g*w(ʪ$Ң$Þ$+}$*(#}o|g:(O *s#r#w!~w/~@w//Hͥ*e(>=)%_g:0%N!(r )!(N !)z<*)$"!" :X(*:(w:(w#:(w*2* }D#cdfg!"()*,) ,O +"!w [,O?WGzO:(V,xGyOG,xwq*}(}2*i(^#V+ d,!(K*}(@+*)):( K:(G~.|°! w:ck[!x?[! ~ʤ͆[͗PPv qO-á=.: <ʰ! Vq##~_@w: <œ. ʩ.ʩA r r##s <}r cN! ~态O>G~G!~G~o>_y)@ u :G*g(`~!x_<_@!*o(y<:(/G?~##~? 6!K@?F6##N6 2 p##q:r !Z$2!"ög:(2T͐-:ʹ!>2<2(!!(w: >2(*6!O~(~c!o#~E%^#V)$G#~#~!%~ b%% k%%##N#F#^#V#~#fo~o!o#~>T}! 6**#K" G*~ xr ͐-xą@7(͚S!ʀ{(X)^#V!"(:(<)!~<<)^#V*(<)"("(x+)!(*(>X)*{()Q*:(_2({2(Ē*"(͂"X*~<)ҍ) -)a*ʚ)~)6*(:(X*)!(:(T>q*k)!(:()-6>)2#-×:#-<)2#-*(@!$"A$A DBIDB  @$$DD""I $BHI$IB !@"BD BBD "@B @$ $BI I B$@" ! "H !$B I$D@! !$ @H!$$D"@A@ DHII  D@@ $ DHI"D$ ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0L}!,"**NK6 :+OK2$^#V#N#FxNp:$p:Gjxj Y# A>QFQx>QGQx3ڰbڼqҼo5p5"""*!yb! ~G*!NKկ2Ãà à ÃÃ1j$|BI$"" HB@ UUUUUUUUUUUUUUUUUAPDA$! @I !@D@BDI@!B$ @$I$$ "@$$@@HHBD"D$H D@!IB@ A"B HBIB$$ "$ D$!"D$H$D$I@D BD" H$BHHBDHB"H!" @ $""@ B! @@D $$A$ $D "@I $A$$I!HI$ BA$ $DH $I$I"HI$I!$DB$"B I$$I$ !I$@DBB$@D@"I A!$ @  @  "$ $I$I$ B!$@ I @I$ HBDH$ A$H!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!*$K*"x!*!@$@hK\K:K ~#~ w*NK*NK^#V#N#F!",!."*K6*}ʴ}<ʴ.}o|g "($Kt>=2(*f*(}DɯQ"(>QKQKQ>Q"%Q@ "H$UUT$$ $I D$BA@! B$$A IA $!"  @$@$BI!!@""$DA  $I$@!!!$$HH !"BB$HHDA! "D"H $B!$!AI!$ $ H  H A$I! I" $$BD"$H "AHD @ I  B"$$D$ $I"B IIBB"$B@DH"$$ IH $$ !I"AD B!B  BI$A$"@$I$!!""@!2*%DM**ѵ+)) H~#+}#<:<ʲ<77:<ʢ2~77ø~7"9:OG#Q{ozg# "" $H @@@@" BHB  !I$ @ $@$"$AI$$IBI$I H@@I!$DA $ $@$ !$!!" !$I@I $@ $ @!H"BI"HI DIHA DD$HH $  B D$ "I$I$H$ I !  $I$I$I $@HD$nLT`$Nwy!"(9"f1f! Ҕ2! ~#foCOPYRIGHT (C) 1982, DIGITAL RESEARCH 151282KK{<<ʽ<K : >! ~6 69BK! OSBB loÈÍj < m s y Ð å Å t ÏÁ Ú7xn1xR>Q>22!"*b"!! *$*(**)0&(K|PRT2 6551 RS232   (Bx2'$ > 2ZG:aOx2a0 *X#"X x2[ x2\ x:Z2a( > 8'y :[y :\y y:D< y2Dx2E"!91*x(%:D !:E ױ(:D !:E >2D:6>=2 ">2!"A:2G*$(~wx2!"AxW(  ,>@)x  !>x(' (  > x < 2y2!"A!"A!7>w!S~=2 !"A!6: :( 4((!"A>2:S2:2!"A:[/(>G:Z/G:U/怰Gx(2 ! 1  0 ! ^#V#{(++~2 y2+V+^ cy2i&) ~#fo{ !~2 !~#fo i`"i`"i`":2i`z n&*&) ~#fo*&) ~#fo~#fo2 2ɯ BIOS Error on : T-, S-2:O :2 !"$x( * +#"$Ⱦ(#0րG.40֠G.6!*L_^#Vo:"2"¦H ů]  f>2$>2$!~t#( ?Pause:"@2":$=:$(<2$.bf: 2 : 2 : 2 :Q 2Q *$*(**)>&| h&)))~^U~g > >w^8^%*"*&)>U| *"*&)>U | %~( O #>/<033O _ W{ ! ͨ:AO ! ͨ*"* 2=2 xxy xaNʹ%!MD5 :Rw͌!60:O >2R!u4~6v!"-:O!un~2Q>02Rɯ!s5.O ˮ>C2Rɯ2R!>w>28 !O!"-!N"-ɯ2:N2K!"-!"-:s0!>w>2>2!"-!K5 "A*a~<6,>w,}s >c2a!" "A:y >y2y2ܯy >yxUy x: >@2 xH : Q Y Q Q Y Y Y Q2::O >>2!u  ~y+  >2"2N!"%!"H"J!O"L!`"$&""&"*&"&"(%T`y CP/M 3.0 On the Commodore 128 28 MAY 87 !@+0>42 & %80 column display "$>2D>2!"!: 2 !,"#:"2">2$ͱ~a> 2$͊8ws)ͱ80G2$|!"$s)!+| !|$ͱWyx + * +RDMbk#+6( * +ȯRDM* +T]+# wV :$ ><2$U:$(=2$:$<2$ͺ! ͨ*2 ͨ2x2"="A_>t,0>O+V!0 2~2w/ x ɯ2!"<(6! :2~2/w x 2% BIOS Err on A: No CCP.COM file !!,!CCP COM:N!l0!,"-: 2!#"-!"-Q!5"-Q!c"-:N80 0?:!O!l"-Q:O! :2Q!"-!s4,~< >vwo>w!"-> â>8!Ow!N"-:O!"0>2%>22>2%!O!"0:P2!O~w:N2L!"0!@(y2  ~y# x z xy>2y2 xxy x( Pxyz2* : 2o ( o ( o 6>G^> :$oxyy!k "X* ^#V#"^#V"! ^#V"!@i i a a>2??>~ 2O!s6,6v,6v!:$(!:8>2_^#V#~2RY Q>yxyɢ  p8   G# ( ͸r:$<2$*$:$o|g~>2$>>t*$:$8#=2$~#( t:$ > j0:8G:$O<2$:$>@ >]͕؇_ͱx!y7j7?(6:$!!2$*_~G<}s >c2_x=(,:$ Oy :$-6h&))Oo* Aq99vq\q#qq >X0_~#fo"?!91*A*?:2Ͱ2C2:C"?*?KEYS 80COL 40COL PRT1 "0>2!"0>8>2%!L5 !)"0!0"0:N0,!T"00:>M>2%!["0!b"0!y"0>2%:N >#w>=2z!O˶!"07>y( 2!S 2>!2>!S/y20x4nFw27!6"Aɯ2u!"A!"A>!= 6! "Aw:S( o@ ( ow ( m ? ' ^ y2P!O:O#(:Q!Oˆ:OO>z>y*=>~y8*o*=} !k >͉(:q$2q$:"w : $G:$0&0>2$>:q$ 2q$>y y 2$y!Su!c"_"a6d*$| 1y xVEUPW:"z0.GF#~~  ;8#>!$!$2>O"$*#*$~#foy(!? !J( Wdg!`!s ~#fo!*$s#rd dG.4d*$## w <2$d _*$##V..ͼ.  T(0$,dddg0ЁO!]dd0 6$O.6>:2<2!".R<*+6 -*q#p `BF#~#fox2b"c(2b:G*+y w!q"r6!>2>  %:G xG(>G:G:*FG~x *s#r#"!4 :ʠ= #*q#~*+=2$(:(2:?2>2:N?2:G0ƀ<2_(.:(8G(8>O2?20 B:2:2B:8s O{22:"Ħ >H2:R=( =(=(=W@:0::-:/ 0:G! :_"2!"u, ͷ!|  3.~ , e" n!| !"ͥn:<2 ! x(! " !6 ERTWINE VONk k *%DMy> y:yͻ( x*%DMxy( y*%DMx$I$I$I$HH$@B @I!HB B    !D$  @$  @@ Hddg )  @H8@x/O8 K=TtYy:*EQRW)(GBCDLr *3"7/&"* * `" >2$> ͉>@y> ͉>y!" $>2$>yy(0x!D  6#= ͣw#N#F#=F:bw#s#r2bͿ*^#VV :G:< U :=:=2@] p{O<2]!D /( ? "?( 9@ Epson QX10͡P  Epson QX10I ? IBM-8 SS I ? IBM-8 DS L(  KayPro IV !@" @ B! $@U@A$ @ UU*UT D D A D @H$H@D@D "DI    $H@"  !D  IHD$H$ _{ozg^#V) "^#V|g}o "_{ozgO{ozgi`N#Fogo&ogx! $ ̓x>@͋ ̀#= y(0!D x G6 #ͣx! $ GWx̀#= _y(0.pG{@x(!D wͣ͋B!PÀ:$O!l pG~!D /(:$O!l ~!(: *J!y*H!:4^w (~P~26#"x'k:G: >͘›_ :C>͘ hN% xy:| : F= :(xyk:G: 3>_ >͘ :: ( (>>>C>͘N:;  = :*"":++~G2#2<2~L(? KayPro II c(?Osborne DDK ? Slicer 9@ Epson EuroP  None P  None P  None P  None @ @@@UTPP* BHH@@@@ ! ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0L2y2>  ("(@`8 {0 `[0ƀ>'\>2!`"F> G (x8T*+xG:x2A26.T!*Ͱ> xInsert Disk X in Drive A** ~G*+~( _<W*>2!"*))".P**s#r#"*,} !":G:(/:G#~2+~2 ##":2x2:*g"*~2#~2#":G:( :2:P  None P  None P  None Missing  :*( b   :*(*b !i a y* i a! i az  ߯y y!!!!! ! $@@@B  IUU @!@  B@HAH @ A"H@I$D$BHe 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|y #*Ͱ*DM"*s#r*s#r#pyoxg[ DM*0MD"!*MD$:Oi !N: i G>O: ʀ w *͂ :ʘ n` ~#fob 2O͊ "}:O*"2":O:G2!w*~zWw+ z #~*!*?͙s! ! ?+> ws  X*]w#6?#] .,:;[]=<>|!eʃ45#xa{ҏ_p# ’ ʙ ʙ:A2'!!"!9"1!>%:25:!=g  w:͆ DM*T] KKN :@͆ *"N "  :k Nq N#Fyʀ *}| #X *i # 6  ͆ DM*6# x£ *w**s#rL*6#6͝ *"ͤ ͔  *|<>! > > >:J!2!5Jx4 J#wO͏:T~xTHp!" Iy<ʃz<*"!z<~s^#V#N#FxN:  * ! ~2~+ -O~2 >2 :2 :w:P 4~:w r##rp# b |g}oj * # G | *ġ :*w**= ҵ * >  )ý :O!ͼ *:Oi } Á ~ |*o:O*7*/*"*"[ <:g:!,*}D!~6 !S͌rOͨ͠bbb  :G:xͨ›:ͨ: !6 :<!G:N 4  ~*w::/GyO A +B 8y2:xOo&:W>Oi E:5 N/*"y2>2Í s͝ ͳ L2 ͤ ͔ *'  :O~Sy? x  - NG:2a."z:2:<:^^d{_zW{_zW ) 4#4#4 #  w#JnLT`"y27!":2:=7!~7#*{2!"z"9"1!dy3\K!n҂b&&!R_^#V* !p ^#Vͦ:ü!"(COPR. '82 DRI 151282^dj:o$*~ 6 ~w w**{#z' r+s{ozg**|g= v ** ʄ ʏ  >22ͦ w*>ww: *#*s#r*  :!:G~# <*#~!d!ͼ ʷ !ͼ &!~6̀!"2* >xw>ɯw% :7!>wɯ:= x :r:G:=Ľ9xr:y!4 5~y‰5 6y͌Ҡ^I@O:=ʯ:Iy I I:µ  #I:! I I I! O͠D2x™# 22zG?S͝ >Gx™~™:ʙ2 ##~[*$a*" ͋ʄ *!~Ê͙l͋ 6> - Ͷ ͙ÇPY*{zBK yʢ â< yº! > ~Gw#* #|^#V#"##"##"###"#"##"! *!*|!6J67*w#w*w#w#w>2'q2*O͂yڍÍ<* p :0!:® :Í2*i "!s#r#p*N#F*^#V#F*:O}|y*Ͱ+*͹}+5(.7@ U&%*gy&&%2GP+QB4``l!*^#V#^#Vw# ͒͒ ͒ ͙͒:sAF D >!"**[ + "**K!z~<:w ##>w#w͂ × ̈́ > !~#2:2*N#G2H  W W|:<ʈ:W:H2xy“:  #>? #*~ w0" *y͐}0͋  Ͷ ͙^ 2͋ :@ʕ ~#w> ͙{͆ _++V * -Os++r!x>w~6:6~#+w#w+~o!o#~*ͥ&  && > ͋͹d- j 6Ͷ > ͙F b -w ~<: ͯ~w#w#6##- a * ͯ~?G++Np# |mͥZ O ͊ DM͠}>""2:2* ::E sMO s#rͰ :(±y==±*!^W*=2wX կw#|W|*" j*:Œ"R :W>R  :!jx!w4 ͚̚͡@ NK"ɷ J>">2:N#=N>2!N2~2#! Œ t t)xu) O _"!w O?WGzO:xGyOõxwq*}<:<:*^#V=*"*DM*͆y2zp##q:!2!"R |:2 ͥ:N>2<2͡|!w:>2*6s͙ͤ|͔ ~<Œw:ҧ* ~§2& @t ͬ ͖ :z<ô~?̀ ~?  ͥ *>wɯ2z ̈́ ʹOFqy3 Np͆ͯ:Z~MwS~¹o¹#¹ # ? -Ϳw ʠʡڠ¡w  ~w 2 > y &!"*>o+"!͗ *!"s͙" ͆͂ b ͧb !B6NN!B!z<*"!"z:{*:w:w**z}D#cdfg!"()*!!~~#~O~#G~.|! w:cʇ̈́ w!x?w! ~ʽw-llqOý.:z<! Vq##~_@w͡:z<¸. . r##s}̴̭N! ~态O>G~G!~*= ѵ+)) P ͞ g #+} ͔ ͳ >2*^#V+:<ʐ <' ͞ ' ~' *+"}{_}o= :<̝ ~' ") :OG#!K* N*))KKBI"B" $$@"o"6 "!_ ʍ:OsÙ*"ͥcͬ͌ ôͬ͌ í  ͔ͥ͡ `-}͔ Pͬ yá>O2{&Óͥ:*:"R ̀**ͥq̀*"z::2ͬ͌ ͬ͌ ͬ(}/_|/*W}r#~?w#>r# =J̧ 4  wͶ ~O ʙ:z<>w##~2_4~?ʈ͆x:<ʈʈ{ͥ  2 :w++~=w4-Oҫ5:<4{͊ >2 :!3:z͞ Ͱ @ R _@ !">*:_2{2"+ "~̀~!:҈6>Ë_yW#x#W{s+p+q r#r#r͋S "͙>2z4 !!q#p#w2wW* _҆-!s:!f͐ *~wĦ ɯ2*#~2~w !"2=2*~2=22̀:*wͳ  6 UUUUUUUUUUUUUUUUUAHBI$"@!@HIA D"BB"$ "H BD!$ H$BD!!$D  D $"BHD! $ HHAII "!!!!B"D !B"I$$A"D$!!$H $$! H  BBD$A DBAHD$_*"}o|g">2{&&2{2|*͆ D<8+}7*#}o|g:O*s#r#w!~w~@w6Hq*>=)ү_|:0ʠ êͺ:<­ ‡Hq:>~c!o#~^#VG#~#~!##N#F#^#V#~#fo~@ :G:O:=27)yy/W!:#?>F6:_/G:^:_|OfKyp!VuWy/2&:ʌͺR g[ |OE w @~@w>2 :>* ͊  :3:z͞ !>2Ob 2->2$-:$<~2$*1${6 *L͝ ͪ !~+6:0 ' "!~6*>=)X!f_CÀ*}<~*~{ͧ> N Ä:G*`~!x_<_*y <:/G ~##~?  @ F6##N6IH$ B!$$H!H"$! A$A "$B"D$$$@D DB!$@H@$$DD!$$I$DH"H$A@!@ !$ " $$ @DD! !$!$$A DD"@$BD"$"I$HBI !  $$D $@I$H@X,@Y @A set @A+1 endm if @A=1 if '&@Y'='A' db @W+8 else if @Y<256 db @W+4,@Y else db @W+12 dw @Y endif endif else if @Y<256 db @W+4,@Y else db @W+12 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 macro @u db 0b0h,@u-$-1 endm @beq macro @u db 0f0h,@u-$-1 endm @bit macro @u if @u<256 db 24h,@u else db 2ch dw @u endif endm @bmi macro @u db 30h,@u-$-1 endm @bne macro @u db 0d0h,@u-$-1 endm @bpl mac db @W+20,@Y else db @W+28 dw @Y endif else if '&@Z'='Y' @A set 0 irpc @x,@y if '&@X'='(' @A set 1 endif endm if @A=1 db @W+16,@Y else db @W+" BH$DH@$ @A$ I"I$$DDH$I$ @ BD$DII !$$BD$$ @BB$H I $B IDI"@ !@$ A ! B$A@ $$ A$ $@" B"@ D! A$$D! I"!BI$dw @Y endif endif else if @Y<256 db @W+20,@Y else db @W+28 dw @Y endif endif endm xcc macro @W,@Y,@Z if NUL @Z if @Y<256 db @W+4,@Y else db @W+12 dw @Y endif else if '&@Z'= ; This macro library is to be used with DRI's MAC or RMAC ; (MAC and RMAC are registered trademarks of Digital Research) ; ; The code structure is the same as normal 6502 asmabler ; with the following differences: ; ; Hex numbers '$00' arero @u db 10h,@u-$-1 endm @brk macro db 00h endm @bvc macro @u db 50h,@u-$-1 endm @bvs macro @u db 70h,@u-$-1 endm @clc macro db 018h endm @cld macro db 0d8h endm @cli macro db 058h endm @clv macro db 0b8h 24 dw @Y endif else if '&@Z'='#' if @Y<256 db @W+8,@Y else db @W,0,0 'Error' endif endif endif endif endif endif endm xbb macro @W,@Y,@Z @A set  ! @"$I!$I$H H$I"I$I$BHDI $@@HHI$H"H $I$I$ B!I"" BDBA$@BB"$B@D! !  @@!!DD@@@I!@$"$ABD$'#' db @W,@Y else 'Error' endif endif endm xddd macro @W,@Y,@Z if NUL @Z if @Y<256 db @W+4,@Y else db @W+12 dw @Y endif else if '&@Z'='#' db @W,@Y else if @Y<256 db @W+20,@Y replaced with a number followed by an h ; i.e. normal 8080 type numbers (also have binary, and octal) ; ; The immediate instruction's format is different. Below is an ; example: ; normal 6502 ASM LIB 6502 ASM ; lda #$A5 lda 0A5h, endm @cmp macro @u,@v xaaa 0c1h,@u,@v endm @cpx macro @u,@v xcc 0e0h,@u,@v endm @cpy macro @u,@v xcc 0c0h,@u,@v endm @dec macro @u,@v xbb 0c6h,@u,@v endm @dex macro db 0cah endm @dey macro db 088h endm @eor ma0 if not nul @Z @A set 16 if (@W=86h) or (@W=84h) if @Y>256 'Error' endif endif endif if @Y<256 db @W+@A,@Y else db @W+@A+8 dw @Y endif endm xbbb macro @W,@Y,@Z if NUL @Z @A set 0 irpc $ ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0L else db @W+28 dw @Y endif endif endif endm @adc macro @u,@v xaaa 61h,@u,@v endm @and macro @u,@v xaaa 21h,@u,@v endm @asl macro @u,@v xbbb 2,@u,@v endm @bcc macro @u db 90h,@u-$-1 endm @bcs# ; ; Written by Von Ertwine ; 26 July 84 ; xaaa macro @W,@Y,@Z if nul @Z if @Y<256 db @W+4,@Y else db @W+12 dw @Y endif else if '&@Z'='X)' db @W,@Y&) else if '&@Z'='X' if @Y<256 cro @u,@v xaaa 41h,@u,@v endm @inc macro @u,@v xbb 0e6h,@u,@v endm @inx macro db 0e8h endm @iny macro db 0c8h endm @jmp macro @u @A set 0 irpc @X,@u if '&@X'='(' @A set 20h endif endm db 4ch+@A dw @U e ; equates for mode byte bit fields mb$input equ 0000$0001b ; device may do input mb$output equ 0000$0010b ; device may do output mb$in$out equ mb$input+mb$output mb$soft$baud equ 0000$0100b ; software selectable ; baud rates mb$serialu,@v xbb 86h,@u,@v endm @sty macro @u,@v xbb 84h,@u,@v endm @tax macro db 0aah endm @tay macro db 0a8h endm @tsx macro db 0bah endm @txa macro db 08ah endm @txs macro db 09ah endm @tya macro db 098h endmndm @jsr macro @u db 20h dw @u endm @lda macro @u,@v xaaa 0a1h,@u,@v endm @ldx macro @u,@v xddd 0a2h,@u,@v endm @ldy macro @u,@v xddd 0a0h,@u,@v endm @lsr macro @u,@v xbbb 42h,@u,@v endm @nop macro db 0eah endm equ 0000$1000b ; device may use protocol mb$xon$xoff equ 0001$0000b ; XON/XOFF protocol ; enabled baud$none equ 0 ; no baud rate associated ; with this device baud$50 equ 1 ; 50 baud baud$75 equ 2 ; 75 baud baud$110 equ 3 ; @skip1 macro db 024h endm @skip2 macro db 02ch endm  ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0L @ora macro @u,@v xaaa 1,@u,@v endm @pha macro db 048h endm @php macro db 008h endm @pla macro db 068h endm @plp macro db 028h endm @rol macro @u,@v xbbb 22h,@u,@v endm @ror macro @u,@v xbbb 62h,@u,@v endm 110 baud baud$134 equ 4 ; 134.5 baud baud$150 equ 5 ; 150 baud baud$300 equ 6 ; 300 baud baud$600 equ 7 ; 600 baud baud$1200 equ 8 ; 1200 baud baud$1800 equ 9 ; 1800 baud baud$2400 equ 10 ; 2400 baud baud$3600 equ 11 ; 3600 baud bae 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@rti macro db 040h endm @rts macro db 060h endm @sbc macro @u,@v xaaa 0e1h,@u,@v endm @sec macro db 038h endm @sed macro db 0f8h endm @sei macro db 078h endm @sta macro @u,@v xaaa 81h,@u,@v endm @stx macro @ud$4800 equ 12 ; 4800 baud baud$7200 equ 13 ; 7200 baud baud$9600 equ 14 ; 9600 baud baud$19200 equ 15 ; 19.2k baud # space vic$count,1 ; bios8502 sector count space vic$data,1 ;; bios8502 data byte to/from space cur$drv,1 ; current disk installed to Vir. drive space fast,1 ; bit 0 set, drv 0 is fast. ect. space key$tbl,2 ;; pointer to keyboard table ssting only. It has',cr,lf db ' been tested but has not yet passed QA.',cr,lf db esc,esc,esc,purple+50h endif endm space macro ?x,for ?x equ start start set start+for endm ; ; boot memory map (bank 0 only) ; bios02 equ 3000h ; le,1 ; status line enable ; 7 kybrd, key codes(1), functions(0) ; 6 40 column tracking on(0), off(1) ; 0 disk stat, enable(1), disable(0) space emulation$adr,2 ; address of current emulation space usart$adr,2 ; PTR to 6551 reg (not IO$0) CIA1 equ 0DC00h ; 6526 CIA2 equ 0DD00h ; 6526 USART equ 0DE00h ; 6551 (extrn card) RAM$dsk$base equ 0DF00h ; 8726 ; ; Common memory allocation ; int$block equ 0FC00h ; mode 2 interrupt pointers (to FDFDh) parm$block equ 0FD00h ; s $*MACRO false equ 0 true equ not false use$fast equ false use$6551 equ false ;true use$vt100 equ false use$1581 equ true banked equ true EXTSYS equ false ; use external system as disk and char I/O pre$release equ false ; start apace fun$tbl,2 ;; pointer to function table space color$tbl$ptr,2 ;; pointer to logical color table space fun$offset,1 ;; function # to be preformed space sound$1,2 ;; space sound$2,2 ;; space sound$3,2 ;; space @trk,2 ;; current track numbblock$buffer equ 3400h ; uses 2K boot$parm equ 3C00h ; uses about 256 bytes ; ; bank 0 low memory map ; ROM equ 0000h VIC$color equ 1000h ; I/O page only (IO$0 selected) SYS$key$area equ 1000h ; 3 256 byte blocks (allow 4) screen$40 equ 1400h ; 2 used before 6 Dec 85) ; CXIO equates space int$hl,2+20 ; interrupt HL hold location space int$stack,0 ; currently only 10*2 used space user$hl$temp,2 ; user function HL hold location space hl$temp,2 ; misc temp storage (used by VECTOR) space de$tystem parameters @buffer equ 0FE00h ; disk buffer (256 bytes) ; 0FF00h ; to 0FFFFh used by 8502 ; ; the following are C128 system equates ; enable$z80 equ 0FFD0h ; 8502 code return$z80 equ 0FFDCh enable$6502 equ 0FFE0h ; Z80 code return$6502 t Jan 1,1978 78 79 80 81 82 83 84 85 86 dt$hx$yr equ 365+365+366+365+365+365+366+365+365 ; 1985 1 2 3 4 5 6 7 8 9 10 11 12 date$hex equ dt$hx$yr+31+28+31+30+28 date macro db '28 May 87' endm ; ; this is only for Pre-Releaseer space @dma,2 ;; current DMA address ; ; below here not used by ROM ; space @sect,2 ; current sector number space @cnt,1 ; record count for multisector transfer space @cbnk,1 ; bank for processor operations space @dbnk,1 ; bank for DMA X 80 X 25 = 4000 BANK$parm$blk equ 2400h ; allow 0.5K of parameters BIOS8502 equ 2600h ; 1.5K VIC$screen equ 2C00h ; 1K ccp$buffer equ 3000h ; 0c80h (allow 4K) bank0$free equ 4000h ; start of free area in bank 0 ; ; mapped I/O locations ; VIC eqemp,2 ; misc temp storage (used by VECTOR) space a$temp,1 ; misc temp storage (used by VECTOR) space source$bnk,1 ; inter bank move source bank # space dest$bnk,1 ; inter bank move dest bank # space MFM$tbl$ptr,2 ; pointer to MFM table ; 1st releequ 0FFEEh page start set parm$block+1 ; 1st byte used as Intterrupt pointer space vic$cmd,1 ;; bios8502 command byte space vic$drv,1 ; bios8502 drive (bit 0 set, drv 0) space vic$trk,1 ;; bios8502 track # space vic$sect,1 ;; bios8502 sector d versions (done in RED) ; warning macro if pre$release db cr,lf,lf db esc,esc,esc,red+20h db 'User Beware:',cr,lf ;1234567890123456789012345678901234567890 db ' This version of the software is a',cr,lf db ' PRE-RELEASE for teoperations space @adrv,1 ; currently selected disk drive space @rdrv,1 ; controller relative disk drive space sys$speed,0 ; byte value 0=1MHz, 1=2 MHz (no 40 column disp) space ccp$count,1 ; number of records in the CCP (not used) space stat$enabu 0D000h ; 8564 SID equ 0D400h ; 6581 MMU equ 0D500h ; 8722 DS8563 equ 0D600h ; 8563 INT$6551 equ 0D700h ; 6551 (added to enginnerring units) VIC$C$H equ 0D800h ; (memory mapped only in IO$0) VIC$C$L equ 01000h ; (memory and i/o mapped inase end (3 June and 1 Aug 85) space prt$conv$1,2 ; pointer to printer 1 ASCII Conversion space prt$conv$2,2 ; pointer to printer 2 ASCII Conversion space key$FX$function,2 space XxD$config,1 ; bit 7 0 = no parity 1 = parity ; bit 6 0 = mark/spa string$index,1 ; 1st release end (3 June 85) space sys$freq,1 ; -1=50Hz, 0=60Hz ; 2nd release end (1 Aug 85) page ;===> temp ROM boot data storage blk$ptr$cnt equ 32 start set boot$parm space load$count,2 ; number of 128 byte blocks to loadl ; space key$scan$tbl,12 ; ; keyboard roll over buffer ; key$buf$size equ 8*2 ; must be an even number of bytes space key$get$ptr,2 space key$put$ptr,2 space key$buffer,key$buf$size ; ; software UART recv buffer ; RxD$buf$size equ 64 space equ 056h ; right arrow key rt$arrow equ 056h ; right arrow key buff$large equ 25 buff$small equ 7 buff$pos equ 7 page ;===> External RS232 interface controls ; rxd$6551 equ 0 ; read ; txd$6551 equ 0 ; write ; status$6551 equ 1 ; read1 ;; space char$color$80,1 ;; ; ROM uses localtions above this point ; ;===> Emulation parameters space parm$base,2 space parm$area$80,3 ; ds 2 ; 80 column exec$adr ; ds 1 ; 80 column row # space parm$area$40,3 ; ds 2 ; 40 column exec$adr ce 1 = odd/even ; bit 5 0 = space/even 1 = mark/odd ; bit 1 0 = 1 stop bit 1 = 2 stop bits ; bit 0 0 = 7 data bits 1 = 8 data bits space RS232$status,1 ; bit 7, 1=send data, 0=no data ; bit 6, 1=sending data ; bit 5, 1=recv que space ld$blk$ptr,2 ; current sector dma pointer space blk$unld$ptr,2 ; read memory block (1k,2K) pointer space block$size,1 ; block size (1K=32 or 2K=64) space block$end,2 ; allow 48K cpm.sys to load space block$ptrs,blk$ptr$cnt ; end of block loRxD$buf$count,1 space RxD$buf$put,1 space RxD$buf$get,1 space RxD$buffer,RxD$buf$size space tick$vol,1 INT$vector equ 0FDFDh ;; contains a JMP int$handler ; (in common) page ;===> 40 column misc parm start set BANK$parm$blk space temp$1, ; reset$6551 equ 1 ; write ; command$6551 equ 2 ; read/write ; control$6551 equ 3 ; read/write txrdy equ 10h rxrdy equ 08h cmd$init equ 0bh ; no parity, enable txd + rxd, interrupts off cntr$init$19200 equ 1Fh ; 1 stop, 8 bits, 19200 baud ; ds 1 ; 40 column row # space buffer$80$col,40*2 ; ;===> CXIO parameters ; int$count not used by releases past 10 Oct 85 space int$count,1 ; one added every 1/60th sec space key$buf,1 ; ;===> CXKEYS parameters space key$down$tbl,11*2 ; not used active ; bit 4, 1=parity error ; bit 3, 1=framing error ; bit 2, 1=recv over run (no used) ; bit 1, 1=receiving data ; bit 0, 1=Data byte ready space xmit$data,1 ; data byte to send space recv$data,1 ; received data byte ad buffer (+1K or +2K) space info$buffer,12 ; CPM3.sys load adr's and counts space ext$num,1 ; CPM3.SYS current ext # space retry,1+64 space boot$stack,0 ; allow 64 bytes of stack ;===> special equates used by CXKEY special equ 00010111b 2 ;; space @off40,0 ;; space cur$offset,2 ;; space old$offset,1 ;; space prt$flg,1 ;; space flash$pos,2 ;; ; ;===> 40 column position and color storage space paint$size,1 ;; space char$adr$40,2 ;; space char$col$40,1 ;; space char$row$4cntr$init$9600 equ 1Eh ; 1 stop, 8 bits, 9600 baud (internal) cntr$init$600 equ 17h ; 600 baud ;===> memory management loactions mmu$start equ MMU conf$reg equ MMU ; 3eh conf$reg$1 equ MMU+1 ; 3fh conf$reg$2 equ MMU+2 ; 7fh conf$reg$3 equ MMU+any more (int code) ;;;;; free space above, new interrupt driven code does not require this space ; control$keys equ key$down$tbl+11*2 ; byte, not used any more (int code) space commodore$mode,1 space msgptr,2 space offset,1 space cur$pos,1 space; ; The following equates are used by the interrupt driven keyboard handler ; space int$rate,1 ; ; 1st byte is a pointer into table, 2nd to 12th byte represent ; the keyboards current state (active low), NOTE: only ; current if key$buffer is not fulSF$exit equ 001h ; RETURN KEY SF$insert equ 028h ; PLUS KEY SF$delete equ 02Bh ; MINUS KEY alpha$toggle equ 03Dh ; commodore key alt$key equ 050h ; alterant key SF$left equ 055h ; left arrow key lf$arrow equ 055h ; left arrow key SF$right 0,1 ;; space attr$40,1 ;; space bg$color$40,1 ;; space bd$color$40,1 ;; space rev$40,1 ;; ; ;===> 80 column position and color storage space char$adr,2 ;; space char$col,1 ;; space char$row,1 ;; space current$atr,1 ;; space bg$color$80,3 ; 3eh conf$reg$4 equ MMU+4 ; 7eh mode$reg equ MMU+5 ; b1h ram$reg equ MMU+6 ; 0bh 16K top Common page$0$l equ MMU+7 ; 00h page$0$h equ MMU+8 ; 01h page$1$l equ MMU+9 ; 01h page$1$h equ MMU+10 ; 01h mmu$version equ MMU+11 ; ??h enabllock verify error if 1 ; note: bits 5-7 are cleared when read ; 4 128K if 0, 512K if 1 ; 3-0 Version # ; RM$command equ RAM$dsk$base+1 ;r/w ; bit 7 execute per current config. if set ; 6 reserved ; 5 enable auto reload if set (restores all re$ctrl equ 0dh cia$ctrl$a equ 0eh cia$ctrl$b equ 0fh CIA$hours equ CIA1+tod$hrs key$row equ CIA1+Data$a ; output key$col equ CIA1+Data$b ; input data$hi equ 4 ; RS232 data line HI data$low equ 0 ; RS232 data line LOW lf$shift$key equ 80tatus bits DS$ready equ 80h DS$lt$pen equ 40h ;===> display memory layout (16K) 0-3fffh DS$screen equ 0000h DS$attribute equ 0800h DS$char$def equ 2000h ; ;===> VIC equates (8564) ; VIC$blk equ VIC+17 ; bit 4 = 1 for screen on VIC$blk$msk eount$low equ RAM$dsk$base+7 ;r/w ; low byte transfer count (bits 0-7) ; RM$count$hi equ RAM$dsk$base+8 ;r/w ; hi byte transfer count (bits 8-15) ; RM$intr$mask equ RAM$dsk$base+9 ;r/w ; bit 7 1=enable chip interrupts ; 6 1=enable end of block ine$C64 equ 11110001b ; FS=0 z80$off equ 10110001b ; value to be write to enable 8502 z80$on equ 10110000b fast$rd$en equ Z80$on+0 ; fast serial read fast$wr$en equ Z80$on+8 ; fast serial write common$4K equ 09h ; top 4K common common$8K equ 0ah ;gister to ; value before command was done, else point to ; next byte to read/write.) ; 4 disable FF00 decode if set (do operation after command writen) ; 3,2 reserved ; 1,0 00 = transfer C128 --> Ram Disk ; 01 = Transfer C128 <-- Ram Disk ; 10h rt$shift$key equ 10h commodore$key equ 20h control$key equ 04h type$lower equ 0 type$upper equ 1 type$shift equ 2 type$cntrl equ 3 type$field equ 00000011b page bnk1 equ 1 page0 equ 0 page1 equ 1 MMU$tbl$M macro db 3fh,3fh,7fh,3equ 00010000b ; VIC$key$row equ VIC+47 ; output VIC$speed equ VIC+48 ; bit 0 = 1 for fast VIC$speed$msk equ 00000001b ; ; vic colors black equ 0 white equ 1 red equ 2 cyan equ 3 purple equ 4 green equ 5 blue equ 6 yellow equ 7 oterrupts ; 5 1=enable verify error interrupts ; RM$control equ RAM$dsk$base+10 ;r/w ; bit 7,6 00 Increment both addresses (default) ; 01 Fix expansion address ; 10 Fix C128 address ; 11 Fix both addresses ; page ;===> CIA equates top 8K common common$16K equ 0bh ; top 16K common ;===> preconfiguration maps force$map equ 0ff00h bank$0 equ 0ff01h ; 3fh bank$1 equ 0ff02h ; 7fh io equ 0ff03h ; 3eh io$0 equ 0ff03h ; 3eh io$1 equ 0ff04h ; 7eh page ;===> 80 col = swap C128 <-> Ram Disk ; 11 = Verify C128 = Ram Disk ; RM$128$low equ RAM$dsk$base+2 ;r/w ; bits 0 to 7 of C128 address ; RM$128$mid equ RAM$dsk$base+3 ;r/w ; bits 8 to 15 of the C128 address ; RM$ext$low equ RAM$dsk$base+4 ;r/w ; bith,7eh ; config reg's db z80$on,common$8K ; mode & mem db page0,bnk1,page1,bnk1 ; page reg's endm page ; ; ROM functions ; TJMP macro x rst 2 ! db x endm TCALL macro x mvi l,x ! rst 4 endm RJMP macro x rst 3 ! db x endm range equ 8 brown equ 9 lt$red equ 10 dark$grey equ 11 med$gray equ 12 lt$green equ 13 lt$blue equ 14 lt$grey equ 15 page RM$status equ RAM$dsk$base ;read only register ; bit 7 Interrupt pending if 1 ; 6 Transfer complete if 1 ; 5 BData$a equ 00h Data$b equ 01h Data$dir$a equ 02h Data$dir$b equ 03h timer$a$low equ 04h timer$a$high equ 05h timer$b$low equ 06h timer$b$high equ 07h tod$sec$60 equ 08h tod$sec equ 09h tod$min equ 0ah tod$hrs equ 0bh sync$data equ 0ch intumn display equates DS$index$reg equ DS8563 DS$status$reg equ DS8563 DS$data$reg equ DS8563+1 ;===> register pointers DS$cursor$high equ 14 DS$cursor$low equ 15 DS$rw$ptr$high equ 18 DS$rw$ptr$low equ 19 DS$rw$data equ 31 DS$color equ 26 ;===> ss 0 to 7 of Ram Disk address ; RM$ext$mid equ RAM$dsk$base+5 ;r/w ; bits 8 to 15 of Ram Disk address ; RM$ext$hi equ RAM$dsk$base+6 ;r/w ; bit 16 of Ram Disk address if 128K version ; bits 16 to 18 of Ram Disk address if 512K version ; RM$c RCALL macro x mvi l,x ! rst 5 endm FR$40 equ 2 ; offset to 40 column ROM functions FR$wr$char equ 00h ; D=char auto advance FR$cursor$pos equ 04h ; B=row, C=column FR$cursor$up equ 08h FR$cursor$down equ 0Ch FR$cursor$left equ 10h Ff bit 7 is 0 (GCR) ; 6 unused (set to 0) ; 5,4 01 (256 byte sectors) (for 1541or 1571) ; 10 (512 byte sectors) (for 1581) ; 3,2,1 disk type (GCR) ; Type0 = none, set track and sector as passed ; Type1 = C64 CP/M type disk (1541-71) ; ell equ 07h bs equ 08h lf equ 0ah cr equ 0dh xon equ 11h xoff equ 13h esc equ 1bh  ! Ơ0 , ܮ0x 0)Ъ 0 0)` 0 !`Iݩ, ` ܭ ݩhhhh@0U0L6Ah FR$update$it equ 6Ch ; equ 6Eh FR$ASCII$to$pet equ 70h FR$cur$adr$40 equ 72h FR$cur$adr$80 equ 74h FR$look$color equ 76h ; equ 78h FR$blk$fill equ 7Ah ; HL passed on the stack FR$blk$move equ 7Ch ; " FR$char$inst equ 7Eh ; " k$c64 equ Type1+S256 dsk$c128 equ Type2+S256 dsk$1581 equ Type2+S512 dir$track equ 18 ; C64 disk dir track c1581$dir$trk equ 39 ; C1581 disk dir track page ; ; 6510 commands ; vic$reset equ -1 ; reboot C128 vic$init equ 0 ; initilize thR$cursor$rt equ 14h FR$do$cr equ 18h FR$CEL equ 1Ch FR$CES equ 20h FR$char$ins equ 24h FR$char$del equ 28h FR$line$ins equ 2Ch FR$line$del equ 30h FR$color equ 34h ; B=color FR$attr equ 38h ; B=bit to set/clear, C=bit value FR$rd$chr Type2 = C128 CP/M type disk (1541-71) ; 0 unused (set to 0) MFM equ 1*128 C0 equ 0*64 ; 2nd side start at begining C1 equ 1*64 ; 2nd side continues from first C1$bit equ 6 Type0 equ 0*2 ; (MFM) top, bottom then next track ; (TRK# 0 te 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; ; fixed ROM locations ; R$cmp$hl$de equ 100h-6 R$write$memory equ 180h+0 R$read$memory equ 180h+3 R$set$update$adr equ 180h+6 R$wait equ 180h+9 R$status$color$tbl equ 1000h-246-16 R$color$convert$tbl equ 1000h-230-16 page ; ; Disk te bios8502 vic$rd equ 1 ; read one sector of data (256 bytes) vic$wr equ 2 ; write one sector of data vic$rdF equ 3 ; set-up for fast read (many sectors) vic$wrF equ 4 ; set-up for fast write vic$test equ 5 ; test current disk in drive vic$query$atr equ 3Ch ; in D=row, E=col ; out H=row, L=col, B=char, C=attr(real) FR$wr$chr$atr equ 40h ; in D=row, E=col, B=char, C=attr(real) ; out H=row, L=col FR$rd$color equ 44h ;FR$wr$color equ 48h ; equ 4Ch page ; FR$trk$sect eqo (34 or 39)) Type1 equ 1*2 ; (MFM) top (trk 0 even), bottom (trk 1 odd) ; (TRK# 0 to (69 or 79)) Type2 equ 2*2 ; (MFM) top TRK# 0 to 39, bottom TRK# 40 to 79 ; (TRK# on back start at 39 and go to 0) Type7 equ 7*2 ; (MFM) pass the byte vype byte definition ; ; bit 7 0=GCR, 1=MFM ; ; if bit 7 is 1 (MFM) ; 6 C0=0, C1=1 (side 2 #, 0 to (n/2)-1 or n/2 to n-1) ; 5,4 00=128, 01=256, 10=512, 11=1024 byte/sector ; 3,2,1 disk type (MFM) ; 0 starting sector # ( 0 or 1) ; ; i equ 6 ; get start sectors and #sector/trk vic$prt equ 7 ; print data character vic$frmt equ 8 ; format a disk (1541) vic$user$fun equ 9 vic$RM$rd equ 10 ; RAM disk read vic$RM$wr equ 11 ; RAM disk write ; ; control charactors ; eom equ 00h bu 50h FR$check$CBM equ 52h FR$bell equ 54h ; equ 56h ; equ 58h ; equ 5Ah ; equ 5Ch ; equ 5Eh FR$trk$40 equ 60h FR$set$cur$40 equ 62h FR$line$paint equ 64h FR$screen$paint equ 66h FR$prt$msg$both equ 68h FR$prt$de$both equ alues supplied in @trk ; and @sect TypeX equ 7*2 S0 equ 0*1 ; start at sector 0 S1 equ 1*1 ; start at sector 1 S128 equ 0*16 S256 equ 1*16 S512 equ 2*16 S1024 equ 3*16 ; dsk$none equ Type0+S256 ; access to any sector on the disk dsDW ?NNNN ENDM SBCD MACRO ?NNNN DB 0EDH,43H DW ?NNNN ENDM SDED MACRO ?NNNN DB 0EDH,53H DW ?NNNN ENDM SSPD MACRO ?NNNN DB 0EDH,73H DW ?NNNN ENDM SIXD MACRO ?NNNN DB 0DDH,22H DW ?NNNN ENDM SIYD MACRO ?NNNN DB 0FDH,22H D?D DB 0FDH,34H,?D ENDM DCRX MACRO ?D @CHK ?D DB 0DDH,035H,?D ENDM DCRY MACRO ?D @CHK ?D DB 0FDH,35H,?D ENDM NEG MACRO DB 0EDH,44H ENDM IM0 MACRO DB 0EDH,46H ENDM IM1 MACRO DB 0EDH,56H ENDM IM2 MACRO DB 0EDH,5ENDM LDY MACRO ?R,?D @CHK ?D DB 0FDH,?R*8+46H,?D ENDM STX MACRO ?R,?D @CHK ?D DB 0DDH,70H+?R,?D ENDM STY MACRO ?R,?D @CHK ?D DB 0FDH,70H+?R,?D ENDM MVIX MACRO ?N,?D @CHK ?D DB 0DDH,36H,?D,?N ENDM MVIY MACRO ?N,?D @CHK ?D ?D @CHK ?D DB 0DDH,8EH,?D ENDM ADCY MACRO ?D @CHK ?D DB 0FDH,8EH,?D ENDM SUBX MACRO ?D @CHK ?D DB 0DDH,96H,?D ENDM SUBY MACRO ?D @CHK ?D DB 0FDH,96H,?D ENDM SBCX MACRO ?D @CHK ?D DB 0DDH,9EH,?D ENDM SBCY MACRO ?D W ?NNNN ENDM SPIX MACRO DB 0DDH,0F9H ENDM SPIY MACRO DB 0FDH,0F9H ENDM PUSHIX MACRO DB 0DDH,0E5H ENDM PUSHIY MACRO DB 0FDH,0E5H ENDM POPIX MACRO DB 0DDH,0E1H ENDM POPIY MACRO DB 0FDH,0E1H ENDM EXAF MACRO DB EH ENDM BC EQU 0 DE EQU 2 HL EQU 4 IX EQU 4 IY EQU 4 DADC MACRO ?R DB 0EDH,?R*8+4AH ENDM DSBC MACRO ?R DB 0EDH,?R*8+42H ENDM DADX MACRO ?R DB 0DDH,?R*8+09H ENDM DADY MACRO ?R DB 0FDH,?R*8+09H ENDM INXIX MACRO DB 0D DB 0FDH,36H,?D,?N ENDM LDAI MACRO DB 0EDH,57H ENDM LDAR MACRO DB 0EDH,5FH ENDM STAI MACRO DB 0EDH,47H ENDM STAR MACRO DB 0EDH,4FH ENDM LXIX MACRO ?NNNN DB 0DDH,21H DW ?NNNN ENDM LXIY MACRO ?NNNN DB 0FDH,21H @CHK ?D DB 0FDH,9EH,?D ENDM ANDX MACRO ?D @CHK ?D DB 0DDH,0A6H,?D ENDM ANDY MACRO ?D @CHK ?D DB 0FDH,0A6H,?D ENDM XORX MACRO ?D @CHK ?D DB 0DDH,0AEH,?D ENDM XORY MACRO ?D @CHK ?D DB 0FDH,0AEH,?D ENDM ORX MACRO ?D @C08H ENDM EXX MACRO DB 0D9H ENDM XTIX MACRO DB 0DDH,0E3H ENDM XTIY MACRO DB 0FDH,0E3H ENDM LDI MACRO DB 0EDH,0A0H ENDM LDIR MACRO DB 0EDH,0B0H ENDM LDD MACRO DB 0EDH,0A8H ENDM LDDR MACRO DB 0EDH,0B8H ENDMDH,23H ENDM INXIY MACRO DB 0FDH,23H ENDM DCXIX MACRO DB 0DDH,2BH ENDM DCXIY MACRO DB 0FDH,2BH ENDM BIT MACRO ?N,?R DB 0CBH,?N*8+?R+40H ENDM SETB MACRO ?N,?R DB 0CBH,?N*8+?R+0C0H ENDM RES MACRO ?N,?R DB 0CBH,?N*8+?R+80DW ?NNNN ENDM LDED MACRO ?NNNN DB 0EDH,5BH DW ?NNNN ENDM LBCD MACRO ?NNNN DB 0EDH,4BH DW ?NNNN ENDM LSPD MACRO ?NNNN DB 0EDH,07BH DW ?NNNN ENDM LIXD MACRO ?NNNN DB 0DDH,2AH DW ?NNNN ENDM LIYD MACRO ?NNNN DB 0FDH,2AH HK ?D DB 0DDH,0B6H,?D ENDM ORY MACRO ?D @CHK ?D DB 0FDH,0B6H,?D ENDM CMPX MACRO ?D @CHK ?D DB 0DDH,0BEH,?D ENDM CMPY MACRO ?D @CHK ?D DB 0FDH,0BEH,?D ENDM INRX MACRO ?D @CHK ?D DB 0DDH,34H,?D ENDM INRY MACRO ?D @CHK ; @CHK MACRO USED FOR CHECKING 8 BIT DISPLACMENTS ; @CHK MACRO ?DD ;; USED FOR CHECKING RANGE OF 8-BIT DISP.S IF (?DD GT 7FH) AND (?DD LT 0FF80H) 'DISPLACEMENT RANGE ERROR - Z80 LIB' ENDIF ENDM LDX MACRO ?R,?D @CHK ?D DB 0DDH,?R*8+46H,?D CCI MACRO DB 0EDH,0A1H ENDM CCIR MACRO DB 0EDH,0B1H ENDM CCD MACRO DB 0EDH,0A9H ENDM CCDR MACRO DB 0EDH,0B9H ENDM ADDX MACRO ?D @CHK ?D DB 0DDH,86H,?D ENDM ADDY MACRO ?D @CHK ?D DB 0FDH,86H,?D ENDM ADCX MACROH ENDM BITX MACRO ?N,?D @CHK ?D DB 0DDH,0CBH,?D,?N*8+46H ENDM BITY MACRO ?N,?D @CHK ?D DB 0FDH,0CBH,?D,?N*8+46H ENDM SETX MACRO ?N,?D @CHK ?D DB 0DDH,0CBH,?D,?N*8+0C6H ENDM SETY MACRO ?N,?D @CHK ?D DB 0FDH,0CBH,?D,?N*8+0C6 ENDM RARY MACRO ?D @CHK ?D DB 0FDH, 0CBH, ?D, 1EH ENDM SLAR MACRO ?R DB 0CBH, 20H + ?R ENDM SLAX MACRO ?D @CHK ?D DB 0DDH, 0CBH, ?D, 26H ENDM SLAY MACRO ?D @CHK ?D DB 0FDH, 0CBH, ?D, 26H ENDM SRAR MACRO ?R DB 0CBH, 28H+H,0AAH ENDM INDR MACRO DB 0EDH,0BAH ENDM OUTI MACRO DB 0EDH,0A3H ENDM OUTIR MACRO DB 0EDH,0B3H ENDM OUTD MACRO DB 0EDH,0ABH ENDM OUTDR MACRO DB 0EDH,0BBH ENDM RLCR MACRO ?R DB 0CBH, 00H + ?R ENDM RLCX MACRO ?H ENDM RESX MACRO ?N,?D @CHK ?D DB 0DDH,0CBH,?D,?N*8+86H ENDM RESY MACRO ?N,?D @CHK ?D DB 0FDH,0CBH,?D,?N*8+86H ENDM JR MACRO ?N DB 18H,?N-$-1 @CHK ?N-$-3 ENDM JRC MACRO ?N DB 38H,?N-$-1 @CHK ?N-$-3 ENDM JRNC MACRO ?N D?R ENDM SRAX MACRO ?D @CHK ?D DB 0DDH, 0CBH, ?D, 2EH ENDM SRAY MACRO ?D @CHK ?D DB 0FDH, 0CBH, ?D, 2EH ENDM SRLR MACRO ?R DB 0CBH, 38H + ?R ENDM SRLX MACRO ?D @CHK ?D DB 0DDH, 0CBH, ?D, 3EH ENDM SRLY MACRO ?D @CHK ?D DD @CHK ?D DB 0DDH, 0CBH, ?D, 06H ENDM RLCY MACRO ?D @CHK ?D DB 0FDH, 0CBH, ?D, 06H ENDM RALR MACRO ?R DB 0CBH, 10H+?R ENDM RALX MACRO ?D @CHK ?D DB 0DDH, 0CBH, ?D, 16H ENDM RALY MACRO ?D @CHK ?D DB 0FDH, 0CBH, ?D, 16H EB 30H,?N-$-1 @CHK ?N-$-3 ENDM JRZ MACRO ?N DB 28H,?N-$-1 @CHK ?N-$-3 ENDM JRNZ MACRO ?N DB 20H,?N-$-1 @CHK ?N-$-3 ENDM DJNZ MACRO ?N DB 10H,?N-$-1 @CHK ?N-$-3 ENDM PCIX MACRO DB 0DDH,0E9H ENDM PCIY MACRO DB 0FDH,0E9H B 0FDH, 0CBH, ?D, 3EH ENDM RLD MACRO DB 0EDH, 6FH ENDM RRD MACRO DB 0EDH, 67H ENDM to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> ThNDM RRCR MACRO ?R DB 0CBH, 08H + ?R ENDM RRCX MACRO ?D @CHK ?D DB 0DDH, 0CBH, ?D, 0EH ENDM RRCY MACRO ?D @CHK ?D DB 0FDH, 0CBH, ?D, 0EH ENDM RARR MACRO ?R DB 0CBH, 18H + ?R ENDM RARX MACRO ?D @CHK ?D DB 0DDH, 0CBH, ?D, 1EH ENDM RETI MACRO DB 0EDH,4DH ENDM RETN MACRO DB 0EDH,45H ENDM INP MACRO ?R DB 0EDH,?R*8+40H ENDM OUTP MACRO ?R DB 0EDH,?R*8+41H ENDM INI MACRO DB 0EDH,0A2H ENDM INIR MACRO DB 0EDH,0B2H ENDM IND MACRO DB 0ED