Acorn CPCPMDISCâîú~ÒÊæyëÏGreetings from Clean End - Ian Mark Neil Simon Dirty End - Dave Ian John TobyBoss Man - Howard >2.>ý끊P$TlLll##/M  0T!!P~#G˸ 2g:_^#V>!g(5!>͌>!} O!g6 yÞ..>} .>!>y&>.>0ɯ=.!!!y! >.!o>.!>}ȯ=:̀>"h>|!6( (!&l͎Printer off linèl͎SPACE starts Printer Sink ͢(ͮ .>.>l ͺ*hͺMͺLͺȯ{ ~#(ͣ ͬ> Oú͎ Not a CP/M system disc in Aͮ1ͧ2!C D:O8yO122C2D3͓͎ Acorn CP/M 2.2 - Bios 1.20 ͎!܆#7!R 2222Ϳ*">!>22!"!"C: 2y2`i!y2o)))) y2s12>22>2/s12y2 >2:2:2:2:(1=2:! $:! :! 4~86!422<22:2!~6(":! :! :!($::2:2:2:2:o&)))))))r[: >2::{2:-w>S(M:(:! :!(!:w:2I>2>->K w>22:2:P8 O:2>2:ͬ2!cͤ(S M͎ Bdos Err On :AOͺ͎: R/O (Disc is Write Protected)ͮR(r(>2O! ~rS"&S*j 2,:ͬ!% r>!r[w*rRR0[y*tR *{:vȯ2:!!rw:(  :8ɯ= F<(!͎Running BOOT.COM ! 9<,<(͎Submitting BOOT.SUB !͎BOOT.SUB present but no SUBMIT.COM BOOT SUBMIT BOOTSUBMIT COMBOOT SUBBOOT COM\X COPYRIGHT (C) 1979, DIGITAL RESEARCH _͌> ͒> Ò> Ò͘~#͌ì _2<ԯ2 Շ!۶2:2a{_:۷ʖ:۷>Ľʖ:=2–!B!6#5ʖ:۷Ľ!ͬʧ )!F#xʺ~0wëw!" !~6ͽ:ý(!#͘*~ "ַ"͌#>?͌͘ =_.:;<> Oօo$>!Y2*O"ʉ@G:ʐ:wÖx2p0ʹ#*©6?ëw˜0ï#6 ¹.0#*6?w0#6 #6" #~?  xDIR ERA TYPESAVEREN USERt !yO#< Ty#O 3ׯ21y_͸2y2ͽ:Է˜1͘A͌>>͌92^ :۷¥.!_~#fow]٭ڎڥ!v"!çREAD ERRORçNO FILE^:۷ ! ~ 3#0 Wx x ր ւ G ~ # 3x~#B!Y~ɯ2:۷=!۾ý:۷=!۾:ý^T!~  6?#ˆ:`O> K{͘A͒>:͒͢>:͒͢xK > K > ͒x  ͢ØÆ^ BRͧ9!5‚#~Y‚#"T<ÆALL (Y/N)?^ Tʧ͘!6!~ڇ ٯw4!Y~ʆ͌†t=ʆf ^ T ٯ2o&)|+!<ͧÆNO SPACE^ :Ty!B*O=?_s#"^sG!~Yڸpsp2mÆÆf ͧÆFILE EXISTS _: É: :۷ʉ=2)ͽÉ T!@k!}|q=qf^!~2>`~2ۯ2\!!B!~> >#0~O#Cx2͘1)ͽÂf zͧÆBAD LOADCOMf^: !۶ Â$$$ SUBt ܙܥܫܱ"C{2!"E9"1A߯22!ty)K!G_^#V*Cސ~E ,&-AGMSߛ!!ô!ô!Bdos Err On : $Bad Sector$Select$File R/O$:BA2!~6 O͐  :߷E B 2>: ߷b# : ߷y! 4 5~yy5 6yҐ^H@Oy H H: –ͬ  #H: ! ߾ Hù H H $O͐: 2 *CN# x: 2 p&>~+é7ݯ2 H! >w_: ! ߾5ͤNkͱ¦ͱxʊ#Nx: ߷! ߖ2 ͤ! 5™#wO~x½p Hy<< ʑ :!qMD#2E>! ^#V w#P:BO|^#V#"##"##"##"!O*!O*|!6ʝ6>*w#w*w#w'û*! J*""!N#F*^#V*~#foyx*{_zW+*yx#*DM*s#r*s#ryOxG*0MD!!N: EG>O: \S*C :qn& ^#V>O^"*}:*)=":O:页o"*C *C!ͮ~2~2ͦ:2ͮ:O:w:w |g}o*鯆# ):BO!yoxg*:BO}!N#F "*#*s#r^ ~!J! J*:o$*C~i6iw**{#zr+s{ozg**͕** ,w͜͸Ͳ!!N#F$**O!~#:A߾#~$=2Ek͌::/GyO>2!q*C"͡ʔ*JҔ^:Oyʃ?|x | s-|N-# S:2E!~Яw>T D^6k-äPYy 5*{zBK5ڋ>*Cw~#+w#w+ɯ2E22i^ *C :~w~͔͔# #  w ~>2!E5T*C!"C"C!w# F! w͌x2͢*C ~<wʃG:!ʎì 4~ʶ¬:<ʶ$ʶïZͻx>2>2ͻ:!Z2:E߷ẅ́͊Ͳ>2>2T*CGͻ:ẅ́n>2;O ^DM;}H>"*C ::ddslO s#r:E߷͊:==»y==»*Ww#*"͸*:G#š"͸:!w4!iw:Z!E~=262*C!!~~#~O~G#n,-.‹! w! yG!x͢.:E<ʄ! q!pQ:E<. ʄ$.:E<ʄi6}2ExN! ~态O>G~G!~G} *C!r#r#r ^ͥ_y#x#{s+p+q-*C ͥ!!q#p#w*:BOYG}*MD "ã:!B߾w!>2*C~=2u:B2~2wE:A*C߶w>"!""2B!"!rQQQâ~?ͦ~?rQ*"CQ-Q͜QüQrQ$Q*):B"*)*)Q;*"E:;:A2AQÓQÜQ*C}/_|/*W}_*"}o|g":ʑ*C6:ʑw:2E**E}DQ>2NEWFILE BBC BOOT SUBMONZ80 BBC7 ROM BBC READDFS BBC FILEHANDBBCZCPR_D&JCOM ZCPR_D&JCOMZ80-MON DFSJ !Z80-MON BBCK"#$&8ZCPR MACABCDEFGHIJKLMNOPZCPR MACQRSTUVWXYZCPR DOChZ[\]^_`abcdefgh6502-Z80BBC %ZCPRDEMOCOMijBBCBASICCOMn'()*+,-BOOT BAK.PIP COM\ H\ Open =&3237 RJP OSFIND \.openout fLD A,&80:JP &218E p.openup zLD A,&C0:JP &218E .try_first_save LD (load_block),HL:PUSH HL PUSH DE:INC DE LD (load_block+2),DE LD (load_block+10),DE EX DE,HL:INC HL:ADD HL,BC LD (load_block+14),HL  load_set_up LD (load_block+8),HL LD (load_block+12),HL LD (load_block+16),HL -LD HL,run_load_entry:LD (load_block+BBCBASIC FILEHAND : 7:'141;10;"Z80 BBC BASIC"'141;10;"Z80 BBC BASIC" ''" 1 : BBC File handler" '" 2 : CPM File handler" (::A$=:A$="1" A$="2" 2 A$="1" "NEWFILE" ;2 start=&B200  P=0 1 P%=start ([OPT P*3 2JP lang <B &4C:W &8000+&3800 FB &E8 PB copy-start ZB 0 dM "Z80 BASIC" n.copy xB 0 M "(C) 1989, J.G.Harston" B 0 W start:W 0 .lang LD HL,start+&100 LD DE,&100 LD BC,&3A00 LDIR LD A,239:LD L,8:LD H,0  &FFF4:\ Set proc. to Z80 LD A,&2A:LD (&F8E4),A LD HL,6:LD (&F8E5),HL \ Make Osbyte84 do LD HL,(6) LD A,&C3:LD (&5),A LD HL,&F200:LD (&6),HL \ Put JP at &0005 "LD DE,error:LD BC,20 ,EX DE,HL:LDIR 6EI !@XOR A:LD (&80),A:LD (&FCA3),A JLD A,90:LD L,9:LD H,2 T &FFF4 ^LD A,L: 15:JR Z,not_break hLD HL,osc_inter rLD DE,&FDB4 |LD BC,30 LDIR LD HL,&FDB4:LD (&FFF8),HL LD HL,&FDC3:LD (&FFF5),HL LD A,138:LD L,0:LD H,&CA  &FFF4:\ *FX138,0,&CA .not_break JP &100 .error )RST &38:B 255:M "Call to &0005":NOP .osc_inter LD (&FDB0),SP:LD SP,&F280  &F6B7 LD SP,(&FDB0):RET .byte_inter LD (&FDB2),SP:LD SP,&F240  &F88E &LD SP,(&FDB2):R 7 [ REG$(7),DREG$(7),ALU$(7),COND$(7),ROT$(7),BIT$(3),BLK$(3),INC$(15),IXY$(1),CALC$(&41) L=013: INC$(L): (L=07: REG$(L): 2L=07: DREG$(L): <L=07: ALU$(L): FL=07: COND$(L): PL=07: ROT$(L): ZL=03: BIT$(L): dL=03: BLK$(L): nIXY$(0)="IX":IXY$(1)="IY" xL=0&41: CALC$(L): off=O%:rst=0:asc=2 d@C "Data read" DNB  Data for instructions > INC,DEC,POP ,PUSH,RET ,CALL,IN,OUT,DAA,CPL,SCF,CCF,DI,EI  B,C,D,E,H,L,(HL),A  BC,DET 0] :'"Z80 BASIC base" !D"**SAVE Z8R ";~start;" ";~P% tartopyang-ot_breakrHL,osc_inter rLD DE,&FDB4 |LD BC,30 LDIR LD HL,&FDB4:LD (&FFF8),HL LD HL,&FDC3:LD (&FFF5),HL LD A,138:LD L,0:LD H,&CA  &FFF4:\ *FX138,0,&CA .not_break JP &100 .error )RST &38:B 255:M "Call to &0005":NOP .osc_inter LD (&FDB0),SP:LD SP,&F280  &F6B7 LD SP,(&FDB0):RET .byte_inter LD (&FDB2),SP:LD SP,&F240  &F88E &LD SP,(&FDB2):RE,HL,SP,AF,NN,IX,IY ( ADD,ADC,SUB,SBC,AND,XOR,OR ,CP ,NZ  Z,NC,C,PO,PE,P,M % RLC,RRC,RL ,RR ,SLA,SRA,SLS,SRL  ROT,BIT,RES,SET  LD,CP,IN,OUT  jump-true,exchange,delete,subtract,multiply,division,to-power,or,no-&-no,no-l-eql,no-gr-eq,nos-neql,no-grtr,no-less,nos-eql,addition { str-&-no,str-l-eql,str-gr-eq,strs-neql,str-grtr,str-less,strs-eql,strs-add,val$,usr-$,read-in,negate,code,val,len,sin I cos,tan,asn,acs,atn,ln,exp,int,sqr,sgn,abs,peek,in,usr-no,str$,chr$ " not,duplicate,n32:(?L2)>127 129 133 0 Q=127 Q=255 : Q<32 46 Q D::: -N7:" ********* Z80 Monitor *********" X 28,0,24,39,2 b:O%=off Al0,2)"PC: &";_DHEX(P%-off)20,2);"Code addr: &";_DHEX(off) v':_LIST  asc<2 1,9);"]";8,9)"" 0,0);:rst=-1:_LINE(P%) h0,15);"L List dissasembly"'"RETURNforward 1"20)"+forward 8"'"DELETEback 1"20)"-back 8" E"OSet code address TAB";: asc=1 "HEX/ASCII" "ASCII/HEX" G"MSet Program counter"'"QDUMP/LIST"16)"SPA-mod-m,jump,stk-data,dec-jr-nz,less-0,greater-0,end-calc,get-argt,truncate,fp-calc-2,e-to-fp,re-stack,series-06,stk-zero,st-mem-0,get-mem-0 ,ݤ_DREG(n) 6 n<2 =DREG$(n) @ n=3 DTA ,J ixy xyflg=1:=IXY$(ixy-1) =DREG$(n) T aflg=0 ="SP" ;^ aflg=1 ="AF" NUM=NUM+2:="&"+_DHEX(ADD?1+256*ADD?2) hݤ_REG(n) r n<>6 =REG$(n) A| ixy=0 =REG$(n) xyflg=1:="("+IXY$(ixy-1)+_IND(?xyADD)+")" ݤ_IND(n) +NUM=NUM+1: n<128 ="+"+(n) =(n-256) ݤ_HEX(n)  n<16 ="0"+~(n) =~n ݤ_DHECEMove past code" *"TEnter text"20)"YEnter message" Q$=: Q$>"/" Q$<":" DfC  Q$=13 P%=P%+1:DbB  Q$=127 P%=P%-1:DbB  Q$=" " P%=P%+NUM:DbB  Q$>"`" Q$=(Q$-32)  Q$>"@" Q$<"G" DfC  Q$="L" DzC > Q$="T" "Text: "A$:Q=?(P%+A$):$P%=A$:?(P%+A$)=Q:DbB _  Q$="Y" "Message: "A$:Q=?(P%+A$):$P%=A$:?(P%+A$)=Q:?(P%-1+A$)=&80 ?(P%-1+A$):DbB  Q$="Q" asc=asc 2:DbB 3  Q$="M" "Address: &"A$:P%=("&"+A$)+off:DbB F* Q$="O" "Address for code X(n):n=n &FFFF =_HEX(n 256)+_HEX(n 256) n_LINE(ADD):A2=ADD:add=ADD-off:NUM=1:ixy=0:Z$=_DECODE:_DHEX(add);: L=1 NUM:" ";_HEX(?(A2+L-1));:  <16 16); + L=1 NUM: ?(A2+L-1)<128 135 129 9 (?(A2+L-1)&7F)<32 ?(A2+L-1)=127 46 ?(A2+L-1) :135:(25-);Z$: _LIST: asc<2 TRB Cdata=0:rst=-1: A=P% P%+16:_LINE(A):A=A+NUM-1: =14 A=P%+20 : @ L=P%-32 P%+33 8:" ";_DHEX(L-off);"";: L2=L L+7 " asc=1 _HEX(?L2);" ";:DDB *&Q=(?L2)&7F:address 0000: &"A$:off=("&"+A$):DbB #4 Q$="+" Q$=";" P%=P%+8:DbB #> Q$="-" Q$="=" P%=P%-8:DbB H Q$="*" tvC R Q$=9 asc=asc 1:DbB \t|B :f"FX138,0,"+(Q$):"&"A$:?P%=("&"+A$):P%=P%+1:DbB pt|B z"Start address: &"A$ * A$="" START=P% START=("&"+A$)+off 7"Address for code address 0000: &"B$: B$="" tbC off=("&"+B$)-START #data=0:rst=-1: A=START &FFFF ?_LINE(A):A=A+NUM-1::"Press SPACE to continue...";:DbB  "*"A$: A$: A$="":DNB  Q=&32 NUM=NUM+2:="LD (&"+_DHEX(ADD?1+256*ADD?2)+"),A" >  Q=&3A NUM=NUM+2:="LD A,(&"+_DHEX(ADD?1+256*ADD?2)+")" / (Q &2F)=10 ="LD A,("+_DREG(Q 16)+")" 4 (Q 15)=9 ="ADD "+_DREG(2)+","+_DREG(Q 16) +( (Q 6)=4 =INC$(Q 1)+" "+_REG(Q 8) 12 (Q 7)=3 =INC$((Q 8)1)+" "+_DREG(Q 16) L< (Q &27)=&20 ="JR "+COND$((Q 8)3)+",&"+_DHEX(add+2+_IND(ADD?1)) F (Q &27)=7 =ROT$(Q 8)+"A" &P (Q &27)=&27 =INC$(8+((Q 8)3)) -Z="LD "+_REG((Q 8) 7)+","+_REG(Q 7) $d=ALU$(=17 (-57)=0 DNB : >100 =28 Q=:DNB " at line ";: : : : : ݤ_DECODE #Q=?ADD:aflg=0: rst>-1 =_RST  Q=0 ="NOP" 1$ Q=&10 ="DJNZ &"+_DHEX(add+2+_IND(ADD?1)) . Q=&C9 ="RET" #8 Q=&E3 ="EX (SP),"+_DREG(2) !B Q=&EB ="EX DE,"+_DREG(2) 7L Q=&CD NUM=NUM+2:="CALL &"+_DHEX(ADD?1+256*ADD?2) 1V Q=&18 ="JR &"+_DHEX(add+2+_IND(ADD?1)) ` Q=&CB =_CB j Q=&DD ixy=1:=_INDEX t Q=&FD ixy=2:=_INDEX ~ Q=&ED =_ED  Q=&76 ="HALT" ! Q=(Q 8)7)+" "+_REG(Q 7) ?nQ=Q 63: (Q 7)=6 NUM=NUM+1:=ALU$(Q 8)+" &"+_HEX(ADD?1)  Q=&3B ="EI" rst=Q 8 ="RST &"+_HEX(Q &38) ݤ_CB ' ixy Q=ADD?2:ADD=ADD-1 Q=ADD?1 HNUM=NUM+1: (Q 64)<>0 =BIT$(Q 64)+" "+((Q 8)7)+","+_REG(Q 7) =ROT$(Q 8)+" "+_REG(Q 7) ݤ_ED "NUM=NUM+1:Q=ADD?1 Y, (Q &CF)=&4B NUM=NUM+2:="LD "+_DREG((Q 16)3)+",(&"+_DHEX(ADD?2+256*ADD?3)+")" V6 (Q &CF)=&43 NUM=NUM+2:="LD (&"+_DHEX(ADD?2+256*ADD?3)+"),"+_DREG((Q 16)3) L@ (Q &C7)=&43 =ALU$(((Q 16)4)+1)+" "+_DREG(2)+","+_DREG((Q 16)3) J Q=&67 ="RRD" T Q=&6F ="RLD" 3^ (Q &C7)=&40 ="IN "+_REG((Q 8) 7)+",(C)" 0h (Q &C7)=&41 ="OUT (C),"+_REG((Q 8) 7) r Q=&46 ="IM 0" | Q=&56 ="IM 1"  Q=&5E ="IM 2"  Q=&45 ="RETN"  Q=&4D ="RETI"  Q=&44 ="NEG"  (Q &E4)=&A0 djF  Q=&47 ="LD I,A"  Q=&4F ="LD R,A"  Q=&57 ="LD A,I"  Q=&5F ="LD A,R" ="????" ="BLOCK STUFF" ^ݤ_INDEX:ADD=ADD+1:NUM=NUM+1:xyADD=ADD+1:xyflg=0:Z$=_DECODE: xyflg =Z$ NUM=1:="*NOP" ݤ_RST & rst=1 rst=-1:="Error &"+_HEX(Q)  rst=5 =_CALC rst=-1:=_DECODE &ݤ_CALC 0 data=1 tTG 9: data=-2 data=-1:NUM=0:="to &"+_DHEX(add+_IND(Q)) #D data>1 NUM=data-1:data=0:=" " N Q=&34 data=1 X Q=0 data=-2 b Q=&38 rst=-1 l Q>127 tJG v Q>&41 ="c???" =CALC$(Q) !Q=(((Q &60)16)+&7C)2:DvG :data=2+(Q 64):Q=(Q 64): Q=0 NUM=2:Q=ADD?1 Q=Q 64 ="exponent &"+_HEX(Q+&50) D+1:NUM=NUM+1:xyADD=ADD+1:xyflg=0:Z$=_DECODE: xyflg =Z$ NUM=1:="*NOP" ݤ_RST & rst=1 rst=-1:="Error &"+_HEX(Q) 6),HL LD HL,load_block:XOR A  OSFILE POP DE:POP HL:RET .run_load_entry $LD DE,&3B01:JP load_decode .\ Spare up to &328D 8] BP%=addr(&2192):[OPT P*3 LLD A,13:LD (DE),A:POP AF V] `P%=addr(&1D8A):[OPT P*3 jW openin:] tP%=addr(&1DC8):[OPT P*3 ~W openup:W openout ] P%=addr(&328E):[OPT P*3 \ =&328E LD H,E:JP OSBPUT ] P%=addr(&32AB):[OPT P*3 \ =&32AB LD H,E:JP OSBGET .report  &FFE7:JP &0CE2 NOP:NOP:NOP:NOP:NOP NOP:NOP:NOP:NOP:NOP \  \ .rest_of_eof  OSBYTE:LD A,L ( A:RET 2\ =&32C5 <LD A,127:LD L,E FJR rest_of_eof PNOP:NOP Z\ d\ =&32CC nLD A,2 x.call_args LD HL,0:LD (load_block),HL LD (load_block+2),HL LD HL,load_block: OSARGS LD HL,(load_block) LD DE,(load_block+2):RET \ \ read =&32E5 XOR A:JR call_args NOP:NOP:NOP:NOP:NOP:NOP NOP:NOP:NOP:NOP:NOP:NOP NOP:NOP:NOP:NOP:NOP:NOP:NOP \ \ write =&32FB LD (load_block),HL LD (load_block+2),DE LD E,A:LD A,1:y-pms-S PMsfx Version 2.00 for CP/M Copyright(C) 1990 by Yoshihiko Mino. $Header is broken. $Out of memory. $ !\!l(*}($|2Z2<2<2 2Ng:0i !m ":Zg.]zW{_0>_>Wr$s%, 1 !]> 2f~! #~+ :e 2f:A<¶.!e:j K><  ;:) ]>( (V(v > 2f >\<( ( \!h\<ʤ4 !""""*"&.w,< .w= > 2-.w=>.w=>.w=JP OSARGS "\ ,\ end of spare =&334A 6] @P%=addr(&34E5):[OPT P*3 JJP oscli T] ^P%=addr(&1460):[OPT P*3 h report:] Do NL rP%=addr(&13A3):[OPT P*3 %|JR addr(&13A8):] No SP in INPUT P%=addr(&36BE):[OPT P*3 XOR A:JP &36D9:] In init P%=addr(&0DDC):[OPT P*3 NOP:NOP:NOP:] In END P%=addr(&36D7):[OPT P*3 NOP:NOP:] [ ]  'ݤaddr(A%): test =A%+&5000 =A% ((22<<FFPPZZddnnxx>.w=:A20Q>2~Yͮ!@͜0]8(!8$ ('@8!`(8&@"̈́̈́ ͇͊W:g:-͍W{W:g:-o~ ( ͍188(/8$(8(~͐Ɓ͊!͍Ä́ ̈́G!(͜8(8#(*8*(/82͇0͍-͍@$͐ƀ~ ́̈́W͓_*}o|g0 *~#| *(͊2! ̈́2 :=2@̈́=_!^#V":G:O͇(=!@:>  >!  ̈́! ~(Y# z {2(>2!( >"". . Acorn DFS to CP/M file transfer utility ". (c) R.T.Russell, 03-02-1984 : ( 7 b2''141"Acorn DFS to CP/M file transfer utility"141"Acorn DFS to CP/M file transfer utility"' <: F buffer &7FFF P : &85::': Z: (d "Enter DFS drive/filename:"dfs$' )n "Enter CP/M drive/filename:"cpm$' #x cpm$,".")=0 cpm$=cpm$+".DFS" 1 (cpm$) "File "cpm$" already exists."': "INSERT DFS DISK":  &86: "INFO "+dfs$ : 11:A%=135: X=1 39:X,);:A$=A$+((&FFF4)256): )2{G:226=( #q##p 2x B#~:x w+4#w++~ _*##~ q{Y *w# +C><,#~(#qY *pC:2<22(~"~(!_æ~*"#~/(`8 A(L(C(Q2W2"22yYɯw#GO*W(T7>-#O>p#O>m#OF#>-# x0(2(>2A^#V#"##^#V#"^#V"!~2*##N# ~2J#~2K!] > ]~#.( (~#.( e (~#!"h"j>!m ~#"!#"} 3| (( ':size=("&"+A$,29,6)) = size>&8000 "Sorry, file too big for this method."': "*LOAD "+dfs$+" "+~buffer "INSERT CPM DISK": *RESET * "SAVE "+cpm$+" "+~buffer+"+"+~size  drive/filename:"dfs$' )n "Enter CP/M drive/filename:"cpm$' #x cpm$,".")=0 cpm$=cpm$+".DFS" 1 (cpm$) "File "cpm$" already exists."': "INSERT DFS DISK":  &86: "INFO "+dfs$ : 11:A%=135: X=1 39:X,);:A$=A$+((&FFF4)256): (!(~Y!"~(YͮO>(#o:g~qiVwo%qi~jwo$r%i:-wy2-O*&ozV$_">G y 2fY*!q#z +: @*`( pF !*""!^#V#{_0zW05~+r+s:f(:W \ j (e: J*|(`¡!! 0| p>( !e>0~w#:*(~w\*|O}A (V \\>ɯ'! ͨͨͨͨͨͨͨg>2o>02(7|^# Extract? (Y/N) $ Overwrite? (Y/N) $ Skip this fi`EWXv,Hw?%BG>b߽qg#9TH"(ς峟W0ȤX4J3pl @cQX~zM&p~hH^Æ M i+n @bTkT*kZB(AM'XQ#FӁ8#?ErK є< q<xډaD%DJ됼GnqP (1]E( Ec[$dq% h79Q"-6ޅ1`+֋pgj|3꯬7:V>׆l(b@g1]ކwPݟ hon SK+V-TWZ5Q< q8,0LIL,T n5<qL;^Y6ˆ*G[-l 6ո]ig 6ݓa~M@|RGe$ @4p啃ЩaIR*^Le+\@̛ܱ9Me\z1 TQ։ħ wDDbWgƋa?]Ze߅wj.lh+niYp%Z:s@زd 36r)zG)F296viՋg8@:5ipW2򂖄@ղ%] TIpe"gWWv:5_ c&i %Ȫ8hOFhƎo5[.TO'1J;n%L8_i;9@j*!T&U-'(IǷ k9S:[U7edA%̆ *HЋǘn|/3uqѳbpVϴZG?-!<ҝ=ji N}Jkw&;*zu |t]g=bsy%n-2s*k7R1cfle. $ Unsupported method.$ Displaying $ Checking $ Extracting $OK $ Disk full. $CRC error detected. $-pm2-I ZCPR.MAC3p3DVggr#K!2@" XdHA  _?M-> l()eR" `Gu^LW7t1:#;ۿ4j2h&%>I<&QEMѷ`nL< v1 FQΉ@幆8rC%!.! i2D R`DS.!?\DhpBejql(P+('9&E'M󞌑3vH*ovYZ2!),0ƒY)x׍[` f\Xȶf0g{rSIdQ6 `jVFXVy.pR׷ЛQ'6웆T #Fft0XӬ Wr*|*9լIK2: Tn"k,r)Nhbro#<3R_. 8XLDiC@'= p(C8 "TDcQ_$ERE`% iA^j&9h ֛0Z \r%f"pzJtV;A _C1Py߆5Ў[ !7A`']ѨQ'@(A7l%]1OlAhADgqbMߪ6Kq`@e'E8KVm~FCW:Z;|ۦǒ.k055YPEPd7>Yy^2oAhd< DTy`@;fN6[fmj%`*E^vQ[?n۪-q؉n2=%띍`\|d^ l#BS-+:UBeQ:Ʊ264KS?)|ҝ&mES% Hu},i +FE'=8cKK6NSlTo9s`cOK8mM~_VM:rgښ@?ktVL$9j~bC :Z4P&N9HJZ*)})3^iB bo[HS {bK _M|6I)&6=k-Jr\hIXJC+ۛ4SBUWfN{a/s&ZQԺVj}*lG <;߶JY-;juE^yeꨳs"^zTʺq#t^ƴ3]Ы"e}U7I\!8uSgTc]eJ/rH:|{ZH)Tz-IɧT:DKv VCp^xP%_N oLMC&nv" DJRb+xB.INmI ݷEEjG'xF ;1L`o:ȨCt΄;4t6Y&U{RtJl1u5U, 0رNGEF;?l]E%G/WzhznOTU7K518VL7dzAg7L",YNq1ק9eG*PŌj㒂lШ jE94i,(JPv `sk`*7¨PJp:vv]_|iCz7{ʎ+Φg XLh Mv )jJNp!Rj $cR%o<߬0C峲Gn^_:=.ӓ(X<" k ;@P~X(rKNopyЯ`-K}qQ5yO֙CS.'sOBpzʝwֳ)h-Zr iq]* K@>'K()Qف{YfG^qf oKUvHRpp S`9&fS1~(\QbʛM,yHWK]jL!-v 'CT,sa>J<$9~ xJZWw_r]L8euW&69yI Ŧo4&TK`qm>Xw0T/'r4~6+.:(xC G#řA@ aaN5.!# IL(D9%>a<,Y+6ƣ|Yw;Q_asJ0yB6u%D%_=3_waߔwcubv!1Q"\Gtr!ѽM#r熙h΢QfQrrQp# ,T.*_ ~=8NM֕z&% De7@(^ KG.pGU6^-+ML9礪#M |*oPEq\,jcs7/PƱodӬqWd"_$Z#EIm˵tz*1h %oR0B(E4bWoMƶ,Woy"!:{=x2i i&֙2L 3`'+)>o%c>f4d%]?R4YR9P9D op RJB_ЁwB3垊VASh<ԒC+_J{V$:4(ϥ!LrGLۧBK=?WoR97A 2[mL¿HB|@T (?P[iy DҰͱ zp/ zg )զF Z|DEX!=bA4sk3!BƈRnO asiDJ"@#4 ͧ~Tv@E,dI/E/E)y.^,X z6EP6 QQ`zL נm[Puj||t{7O -fZ}Ŵb#I\&F2p85>4"[EF k1Odg)"5@t(Bg̼>4 #vVo[ L ҎūEaZnzr.*y=t?@k8Xo #K\ߋ7ЖZ[`+w!GwYݮ+['z qb5_Ȩ[ibD6j>dG#-1y~zPw6 $/%yy9i=WfPwcy@TFY:2?AQqq(W~qW^?ki6S=o76_$eK~޿bl!=Ö\by6 z{CfΕ{]}t !:/qHgB=zA/Q*.  =ZKw9 q .d0FgߙT㩍o^_&,"q]pPrVpЯԦof<iRLo2JNl.YJɊ ͑1XȔ&'6rX  DBd ҎW (|Q~!yR8c|U i@aOĺUXY0*[e\l+p"?l0 }a;N 22s)f2řh*C`SA)8˕ckCu.Erh<.A(PF铈&Gu)}p)M8 SμsC\ɅU.5KI*.ci{&_i{`˕w*Z|SQmr E+0nҘ+)9@&|Je%Nw%W ij#̴/u5`r~>gkI]U3k־ !f@ckHTuB~16HutjW)"9(co@l!)#-7Iym.G(sV@_ .BM,\{Lω94;hZ'Ch" (} aRΈgqo\{ʾܝr?$?&f90Q͕fvmu򚲕?x j*WY)p6Չa~-*!~\ ?rIA>t ǧnys,Q6z}@eѕpɝ㽭*(AѬ [;zab۔nkB$[g}P S̩g>gd'" {a;0~i`:Z7ù\oN Vv? +*2hU96߻\y)5oҢaIEF +]x:^E쌜"]rO@{ R09[ 8@NvJ$*uU I/ ~$pHkZvUG!Rbl'~ ]y{b9hZQHwW^A7aҞD@AgX;X+Tx:CIiHqtihos/O6V|pa^7U}=?bÚ2Ƙt9$H)‡8_ î f^r]eće+đ\#D$zjN*=lB:MjM\q0cG,D)¨ԒamAy.?TbRf{l f7 ^6)4,>:_>;p9^t,6̬Yّ ɂ9o.K 03Imb'rzۙU,'YH^:Tr9q.0%@OCݱ8 0Lޡ"Խ;#r >ԑ0C+|M^@oܱ)? @8{iZC%ОvEx7ƅca"$ uO`䄁hʎ #:%MkAHykѝ[ nqזwdG9ɿe__­DҙD,:fnkd J ׂm5<[a/M :U6 %4\:Fy[֮bΠzҌ>,]X {PH( l2N2`0fv'P2ϛȒL*nbMp'ߴx~)uJ;&.2thFOA)5u1:FMBąV#Į#UO`ë O{\i\w#}0cxlx{ c78輶SvٙAEɲ[߰ KK)!nvCGf/r @z#Bk`|p;zdSzNWsSɖ3\K~qudJ|`^N(>A|8ML4w?R%fpc0w5y(v;Y @/9g?Grz*,օ2uh ~Efez6W$"C~W/&Y#-zP_^H5KHfd1j<$Tc*R=n8 jˉB5 ۱:5~f uLHWѪ|h=ǥqv ZfD(>I yD:Wஇc ((UTL!"]TMe5ȍZ)LAGU;P*qoE3 387bْOA4o?jslAD}%%4+'l zJ:|;iTʥQٴ't}@# `3ZwZyGU)l,@݃^WSqFiNP j}>y{,d6}#ѱI(얬ʆlҍn9pKCkQ%Hʢz~swDJ;PVZїiZO-QbŻ%˺ҌTPHQXΠ9L >;@z6K׹e3vߚ%|oSyN !E,q/_[5U8_v&S9*܄u< A#^LeȶޚϾmï{z߸)k\G:%Qq 1n0m46Bș tFTj:ӧ\MA1#$4Ϣ%Ge;wKoVOQ~Eb8r\OTrx:Xk7MP pp C4tY87kixR:n籠+g sq?8 E[m0az%ͯ.TE1-zI` ^Y6l+r U#-9S\7żԌ)YO͇tisY؉ h^N[[@k=.AG GQ ʓ>q"؂Ri- K5-"dht#Kr̙t L䪁/Ѽ'ޙEK0ֲcMĮϝVjC՚'Pj(M"ӄ"RʈQ18$ 8lKs/f [@P;Zr.2f iUlt>ߩtG5$}?QwXk֧NC/oQ%uF2+BI5&Bkdb|5q\+SFІӻFhPEB>r*`O,*=^w`G_Y^ϓ;8%9g^DC{RK㐩7 AuadӎO|]巭ݒvLY2̊4)ބ f=wʴS4cwIl73jk~u2܏MФ~XQjN)/ЎSJ_=S:JYƾX =}e==^fTJG]z[=F,mU~)ɣ*ב7|"ۦ/^_Cmqȇ,``XO d kx,!E@.ßBk򵰝 )νr0WKq#/^Xc^)wwno1P0DSc;|[&T^NxiIE\cܶ)McI>"kF(gEgEBgqiϽ{l8JbxNMrh7V.)|j X Ш@7+bU6 s\DXW(|yA KSسIs5I?ob֯yU /їXw| /wg4qoD%>b~{k_hG:^m<2r{[Yfwb  ~zZuwjs!yyI+o%>OL{~ȷGAnWf <V0\"'<+OZ/Gؕ8G%[Iа+}Ak)-"IŁR ]/l8MM~ii 6%B j,L*(,w9b}YjW *fxbOR{Ѫͪn ~lDoT Џ)ͨys+΢{סpbuđ|nRlquul2lHGDwG8yR@_%̵hR"HB9IRe}|4d"cӠA9ù3I/mm2n ob WL6olUY6zhr_;¦^C,VV3z5ăx2IZrxC6U,7;?lt;2l]-y7T s`}90g`vO8)f1Oo%_:$P rNo@5b*P_d+e},^^W 9~%4oƜ:T_ s:7g>9,sY5?V[#Zi$%i:Y6RI/esA&Tg&0Fc`7#4HYkj _Y?*b <fn^ mȇ3y06a Yңhn zKj5啶VȋK=/7%)WwVmj[QҬͩba,9H?27##?I%[f8>vcu P /F+tG=8)L;C:TibP[WB QN-0xFѺXND鰢Iv }1 # }Z n,8Z ,U>()&RԔ:L/VPx`G E gYZôqpIB6TswZ,vY]s;lƟs#VB J 0]Sl+SH$/Jt48 MwC@Wy΀C:n +&ppdڞ pW|;0JAjF65+&Y9uP"s>.-kRšY,a3wNE"~_S P/BZnܻJ)Ez\[Җg"J7ADXWhS][KEP0,otD@w9"-jh@ Ha7oqUH-iLOu9Θ/}'w' <[I j`{ SZSul_PsT BPt7g ?8 AAТ$,cڝZy&YКnyh8:WɧLUPDbƠ]Dq`*~ێ5SVGPQ{df؞Jq@D .PUDG2>wa'VcBS{nY <-͒e@c½+ts9`[ hTylz攤,^q10ZiTҙaB1jyY5M-|fZj?чO5)_5 ~TljSS_2"[N3A->bݛijfWk#'Rߣ~򻤙i+ = g\pB}lW]WջA=M\7E'BM^SR`rnm8tȐmȷj(>apJq׋߷+#/pL`6[227B>^+{mitsoaeMokރ'Y].YRiJ =+{CCV92;'<-xH ;Ӕ519j2J["i,{为8yZ!pzu7inaqүᷜ@SZ\(Ӧ>t5C)_ʦj4`_e;X2SeL6%ٞI-QC VдˏhPNJ''8v YƧd}:$k bH.6)H,/2 )[Z`x `F؀4gӞihc{z,ÑQ)4k V0SAw(>xO,9tq`kRZ:%-|~WCjِ~Six(?W~4GU!$f i^'?LKO)uk4ȴgsL\mq6a%<Z|0aaæ6Sc0`aƘ?z:Wwf:Zd7\`{"f3~]1&7QǂmѬXKBT^)wd|tp\R]uҮRѧ>sVAV!B^DDñpOO*;-4X1ȭ)xAho}jvzaf1RvP^r-]pZ~wvn.vus,M$h8{T>|rUx,×Q)< ~2q;umֶZUW_L`0EqOtyΆXlt>bt5|1>%_9M:8Z-e|ro~l|@F :=i:}:Lm3kMiz\88iW3ahK;lH$狧^K;'zWl2H}-.Ë!~z|eB9VR{&_ʋ-QN 9$ǵ;+&vM+Ta՝wJQ\Y o5e)4۽9~"\Q+fHN[jDVU.M!2{ ŜM;Ce$dV4\]YIq}Vj_}[M6}w_/$ȣSfbjS@Im{ ~JF~diW"a aU ".b+Cx(YU iPb.{͊UUThsn3)ehPY\Ogfu?+>_ j{;JA.ot5ŵM6!YFY#yIp 0%Jrɚntc/h2 bo3XH2%k+^"3ᲠW\uˆOl-$LrWemd}Q~*TP:OQzYԺi=N 1A&"Q{SF7BE$縧= JS'Y3zcyU n,{ƒ~[O/ /vy87qaǼQ'7Z]<~\ҁt_e @p~7K>CnȭR2dr^oC`EDIVS': )#*& }X#[0wN+Ri}ݮA2c{ossHt80ҌVs3F;PX:f[.iuG1[Z4ԪT,wyrNn<% QZ,l.EȞ{+?אgF-@8aSdV[zX"6%u^?y]ԿjUHy`)h"20 ׀ȊKW/thlhϛtP }3WcFϮYѝ/Pp=˂֫/ҽOKUXѩRsRZ[~&ύe\? JŜ1 U;E1P|#pǏO [NG+fY #ja9 cح,gOV9 nJEt`gIwO "j!Pexߕ}.GˑV]:ڴH=_g-?Ty{WAzjgAuHtH,z;-g!my@5àkR:DdgspQTYC!qHFH`E(Om L]Aݬ))(s-l,Hk$˒%u%M%,;LQ@3Œ@lZaD)Rgb#:&) txq5[}' u)}+ -0<)mTtp][5ax"փ~C #79`J&mг,{ʑRHJ.֐\-°Eŗ&*ETm& j=nw1M{_Lif/ H"'BH"G ;H8 "!::w8Mu{*ɞ-T/×?]]Np 䍅$Lj3LuCVVw!E`BXa^{{8^IAzk9u"{=1 wX2>}g<_͔a[h ^uIk?g涚i8*^fo{`e;){Eo^ )e\Li<(Esy"dE}ߡR+ŗ+|,91hFȧ0kKEZ4G4e_Ov3x< h½B[]в?ގ5ddB'?[+'6DMѝUkEkNF8*nzDyf[-sq=.06(K|jA'yV)7J+=LJ(vZn.qIQEpZ3N%/ŃRiqnؾE-zG4P)F;ޓqz(X}\r &'MD(n#T:MC`7* C6˳tT7.F9H5wS8Ih0R(P9%<0ϐ8r(sI3JYx:&_)t[_-ĪUo.~LQ~ H䘆-pm2-%'s ZCPR.DOC$DTfvx`tl p'<7 C?0ѹAP)L!T 9 O#*Iә%AL1E ͊Q #C| i(5F| DlU8! c0ta1 hWۄ#Ya"J,܉C ;(ʸ쥠H֩YWƸSTu,MY3CVT/Wev:2Ö98w4T LD3m+TkZsߦmlcd#E"#x1_(by29n"5kχnKc~arQ2s6b 2'Fx] V;c%*nH8Ǵȥ pBQ0]nXDz2`yrV8^/kθ]eouxL _>bH61 h#@ )ħ;ѩ= .KRA$2y oFN@AՂ[XƖt,grX =@ќɪ ?0WDW-pITS!-1 AL&f5LhxTTZb#i.?=Gy )X}1sH8x"(^ cD:Tpr?ԟUVMzȯyXoDP W%V{rps յz1|J?%!gCHR,C904ضp 1"d|cEev; EEHb^ŎW=l eڿYbL>y:epz0!a1PshhˀHp AѰcVw K̸̊U$={4hy/瑘cq7J o\%(g_($$ <p{y>?=J`I AD:ᨗ> |.^T@WTːD:`᭘.vT?'\s;@^ =Ù1R :zyQVA=G;u۞+VG[+[՘Aku`!:.ޒDvܑť('K̯V)'\?,C!IDGOFR2LTޅyJ3;-6 1 EAD2 3L>1|&9x rx/՟Tsff,k#Sc c*1D܅Ewj.kaJ].5o#+hعV"\rbjKA2Qd+ 땘OAVy~LZhw2]W 9$EIs3Fla؆OX'Hج\>)\;q#2]f3&4 &ݼ>y@kH~&ҺA~ejãUEWWVUгsJ;CM޸a3I: ;<$vtoƥ-ߧNjTwFH 5iYr;󚨸I1ucνT# ;ߑt հy{V>KsR yC^ ׺V@3/f4*kq JT7ֿWfYT\PdMGoEU-ebuFBwPX !x GHO3d"Y {➶d!IRUmw0(u:UEh2unNn{;݌biO_?`}XⓍٿO(+}-$IҀV@XEid`ѲɻH)*nWd<ݛ VIyW8 d)i7 g~| xM> u!KBR۠r B`8B_Q!HJ\ JT<0h,{S5Iے@[f`fFva}K{FhkMܺG?@ WeIdI8. L1#m(ȹ%'I^É[f4Dlv푏5KmqRz;>tfwIo֗K*. & * sS"oWG jbyEԫ-c1":;o^dO3xKA8<שzo@mOz\ xwgn?p}x_9SD_ݪ`Ls߀ѨqB16k> D@(঵g\Y\Zd<`jku̧d!}@m=lMuF3zy/T4-4l{O`r{5SkP,1'*,)9;u`aa_ɰAc?"/>*#Nl69H`eׇ_;jBF2ϫxnT9D6Ohy5̩DtFl-*lBUĔBk_#|#bz'9JLs˖$|.LQ6Y&77k`.0jɧ@-@獥<"cb$Cx XӾwo0<(tvX.ݖE]* RTOJ_1Htb%Tλnk!ezx p"iEm1p\ʥ_:U} 66ib1WŹ7dʙ}ШPqCX@F:䃚Ekql^UHQ^,(8Z8ThŒJ[&H+*{+LfD-^a)xxkԀN#\ACG(f;.oe|D.JlxS/?gYI6478lN)%lD #&w&s`_!='aZ@4uR"*V,ȭ'x~!xFxLBR+< hy=SsbR!.q7C`k R Mm5̅H5(v[QD+ty'B36!хS m wtI|O.7gL%rfɷ-mQnv23T3iD^ɾn~1Ki -~FIA (Y!*,zo*#gQq?Dh=#ڦ`g.FWYj79Ho]5YGBBBsLk %\DBXh1kY82]N;bZ'Mٜ̬ZCC)eJg8WqՖ>%WHh;CnMcְ f6cFN  |h~l96<%!iokWI`D̏cgiO& Nn<)d0|VW^sK_ )|" &De4dG#ix#C0~E-0iݎ JZ4Dp`k1ΐɤ+9 79? A qhk* ()@+m 7otFґ,Pa=xjٻnB=k\LuG>- 9`}d^K T;wRqP,N{ysaD$!_xv)=`%]B{/{dsO )oWl`AKuŅ- ap&߾!$3et@C0ܐ/񯴟i/!΄) Lv0+|db\XqZKmqdeQ2l `j~WL?-(T)`m<"ܳ\?yӹ??EEwPw%F+WE A$U<߹ݦXt'%)_aM+[I>A`[)&~| k}L&?B@䭛 m%|?hkB<Jq<:̯P¢PJp>>#H={cCpҀQ3- 5XSنj׻o/[2eEpK8.Ѣ:rGʺ4p$m_"dyLSIN'UQ|:м6m.@yiyzh)@tw)xfSi9IwI+6E:Wc[ԷrS9nVz8Y j`^I3]M,j}~E$'7 ˹J/BGDXe+}|Ms]Xܧex(:mzZOg0\OEM }`o03aO0w#qSe߅ևme_T pRf3_%v6FqVEnTm pZ5ymc"ڊ^ƛup@1Py[YL0Z_Zw16^8 -Ég9^4 z\zMm87J# %z1rb0 }{L~i\ m%@Z'$#G5Ae?S^H ,uP-E>h]})rq.E` ƌK XݍS'fq`F;ky[!0י OJ }F)ͮ\Z ɞoDe^Fb`AQOt<#@Z6@\zNcrjAQv!T(pC#fC@?>@;\p"+۟/Z%S&F]wzZl:K]~ }=+MzZU5AUI "ΙJ@kb˜bOn~+:I<ᛉkׇx*?)>"cY~߁D)[=c*\^ͼ*ΡlE3}TVC\jo-{Bσ֬>5eQfX^C&&.3Ʃ@m%zt;N2\nf>#Dd[2aEƭ~A *ļ6zHU5@/oF f[5iܢ'5m|~K%O(k3/ PbW 2B6B٭uJtxc'y{twOcx2˱ @c@/fbah?&^X2i Qr!FAEU|Z7I (%^Ƶ5}(O(эM$t mعFoes ıg8jB޳ɘC)wr(Á%`S)UZxr3IIWK(^wy$wuSD40BB,Ƃmv.0xT^@t,.u.KAʫފ#GmhMU/@{;J>moeᅭMHm&6.n#|ˤ`RGk^6C@ ʍCqhVǐ1ĬMӽ'nݍ:6NvL)LDzX@*=^bΤs6zza0a 0Ij,_xmSqml؉'2t+H6*Ь I 3C1 ƞb|+mi-tS|<^z*Lx弨>9` M!05HI^EKRaV>]LħQ- Ww C!Ԅ_68B4A #HZM\5QZ $`}A?17Nx hJ'LŅwe9 YZirB?fhp7ŭ8!Ud9h0"raIZpYyb%Wy,_͙x80,U&@un*5EkFvbXyHMC. U#?qzNU19 䉄wQK &wrt- IҦX%^=%BUͯΞ}u6N?;88) p^#^W1`;-sz<:(el'M[!5j: %/|Y{ĥΛJLO /yXlPѶoceMpϾf WIrVe Ȩan.OCvx'´x␹{iB!|]vӭШ|T]'ϣ0SPJZ\ۥ9f,4HI| "K{TmWkS`^!230 ,O(4lG{"#E:kj&!QVL8,0xJ JpM,`pWdZN>>",UQ3+3SI8MZ|Y+H0r*l Q̬zͼi'QEkBukh0b) w b!N)}-zUɉHd*rFE݀Yt)d Ÿ"-pm2- ZCPRDEMO.COM=!!$Xxx18E WmK€P1?5LFꦖ>: ( MbI qϑ`DFױ 6&hntÀ[rϝ~I1&e!ՔΥ쎓+\*'ͥLrҳw&-ʗuFxS~Zin* n&!R&6Hv"vQd% ,jAmy"d%DYnAӔlE|4@rA<$|Ã!e2Hח=Ic&a̪֘AKU$+U QOB׌M ֒E%Ÿ8~&b S\` U.9 "GԩjH<O,EH9a"!ӜH0C'X ` wydg4FuH/><򌨇 m? ʗUbH>C{ 1I&չ p1e%] Jm.QH>T~"O#MᱰsObЦ90t}f !FSE3;J̐΋2MU(d?ћ)=Iyb+{vN/7D&K LNE) d"7➆ ѫ @2p] ՉoXeO[&!Mx,XJcKM㘏~OT[tBL·+ fiSE>b!'4v1"+bۃ@GzmO6T@$yyGJҊn*0gBY ^B 3cCTFO5zťeT l^6#!ӓT]JkS} oB6øÝtw!y|h[XHz+>䈖2J\(m2(~wcL[hzdW0`ĉ@Sb{6~ʚ.+ّ?Ҏ- &ƺ^\u!Nm|,Rǜ&Zr;C'Pi2R'oR6FʤF2uٗ^,7+H 5FVo˚ ܃V xQ&cJPn'!K"3]\r|,5?uEnZkWph#_ok'i1)osZ~r] aAdHJcD.`J5&$#EvL!E:5\xl#ogOr WA|YXF䑸yLHNl]()%9P6kS\T(>4wFw$&z)@"j.;{βF|rԸoэ,@<=CQe3yMWPO#|"P£csmCf0l+PUU$hA8`h1؇`1 (Y-Pnkq?NmrϞQ6ƣvF޳m  NwÏ1Qs9:r 7 ml@`2]YB/.F)rA={$$hrrÌ 12兇0XUDMޒWZHtW(HD;m-f |#cMe{?IE,fƒoKV<Ԙ>W3` Zȱ0m*vTЙҋF؋+pSisw~ȇO(t8E jY$oē q̘cWGAt˪# ZptcnِGo" ? ?hgh%-11: ^4A%=P%::A%=A%+line(A%): >hgh%-11 A%>P%+90: h: rosize:wid%=osb(160,10,0)-osb(160,8,0)&FF:hgh%=osb(160,9,0)-osb(160,11,0)&FF:mde%=osb(135,0,0)256: |Bset_  > Z80-MON 1.03a  Z80 Disassembler  By J.G.Harston, (C)1987-93 (#size:wid%>38 mde%&80 &87 2* ctrl% 32,data% 16: D%<4 D%>6 D%=4 O%=0 P err Z menu d n: xXInSc:wid%=osb(160,10,0)-osb(160,8,0)&FF:hgh%=osb(160,9,0)-osb(160,11,0)&FF: 5ݤHex(A%,N%):N%=1+((N%-1)7):="0000000"+~A%,N%) : ݤrm(!&F6,Y%)=&FFB9 &FF $ݤb(ADDRscr: A$,B$:size:A$=132:B$=135:mde%<>7 A$=" ":B$=" " I26::InSc:wid%/4+(ny%>9)+2,"*");" Z80 Disassembler ";wid%-,"*") 0,hgh%-6)A$"RETURN"B$"forward 1"21)A$"+"B$"forward 8"7;A$"DELETE"B$"back 1"7;A$"-"B$"back 8"'A$"L"B$"List d"dd$"y "A$"Q"B$"DUMP/LIST"7; iA$"M"B$"Set Memory address"A$"O"B$"Set code origin"'A$"T"B$"Enter text"8;A$"Y"B$"Enter message "; 8A$"Z"B$"Set machine"4;A$"SPACE"B$"Move past code"; wid%>39 '" N Name display"7"W Address Width S Screen mode"5"0-9, %):(R%16)=0 :=ADDR%?O% 8(ADDR%&C000)=&8000:=rm(ADDR%+O%,R%15) =ADDR%?O% : ݤdump ȋHex(ADDR%,D%);" ";: z%=0 wid%5:Hex(data%?z%,2);" ";:: z%=0 wid%5:(data%?z% 127)<32 (data%?z% 127)=127 46 data%?z% ::=wid%5+1 : ݤline(ADDR%): A%,X%,Y%,Z% 0X%=((O%+ADDR%)&C000)<>&8000 (R%16)=0:Y%=0 X% Flg%<1 !data%=ADDR%!O% X% Flg%>0 Z%=0 12 4:data%!Z%=!(ADDR%+O%+Z%): A%=015+12*(Flg%<1):data%?A%=rm(ADDR%+O%+A%,R%15): Flg%>1:=dump "`" Q$<"{" Q$=(Q$-32) <13+9+127+" +;-=QWSMOLTYZUINR*0123456789ABCDEFX",Q$) Q$=13 P%=P%+1:=0 Q$=127 P%=P%-1:=0 Q$="+" Q$=";" P%=P%+8:=0 &Q$="-" Q$="=" P%=P%-8:=0 0'Q$=" "R!rom: Q$:osb(0,255,0)>6 \osb(130,0,0)<>&FFFF f.131:"Rom: "Q$: Q$="" R%=0 R%=16+(Q$) p z: 'mode: Q$,Q%:"Mode: "Q$:Q$="" AQ%=(Q$)&80:笤arc:osb(130,0,0)=&FFFF osb(133,Q%,0)< +22,Q%:set_scr:wid%<39 22,7:set_scr  : ݤarc=(-256 &F0)=&A0 : diss: A$,addr%,end% <"Start address: &"A$: A$="" addr%=P% addr%=("&"+A$) A"End address: &"A$: A$="" end%=addr%+&8000 end%=("&"+A$) ?"Address for code address 0000: &"B$: B$<>"" O%=("& P%=P%+num%-num%*10*(Flg%>0) :Q$="Q" Flg%=Flg% 2:=0 DQ$="W" D%=4+((D%-3)5):=0 N" IFQ$=CHR$9 Flg%=Flg%EOR 1:=0 X+Q$="M" "Address: &"Q$:P%=("&"+Q$):=0 bAQ$="O" "Address for code address 0000: &"Q$:O%=("&"+Q$):=0 lQ$="L" diss:=0 vQ$="S" mode:=0 ]Q$="T" A$;:"Text: "Q$:A%=?(P%+O%+Q$):$(P%+O%)=Q$:?(P%+O%+Q$)=A%:P%=P%+(Q$ -1):=0 Q$="Y" A$;:"Message: "Q$:A%=?(P%+O%+Q$):$(P%+O%)=Q$:?(P%+O%+Q$)=A%:?(P%+O%-1+Q$)=&80 ?(P%+O%-1+Q$):?(P%+O%+Q$)=A%:P%=P%+(Q$ -1):=0 )"+B$) ,:addr%=addr%+line(addr%):addr%>end%: : osc: A$ :"*"A$: A$: A$="": : $ݤerr: <>17 -1 .#ch%<>0 A%=ch%:ch%=0:O%=o%:#A% 8 <>17 B -1 " at line "; L=-1 V: `-ݤadr(A$):B$,A%,B%,C%: A$,"&FF")=0 =A$ j7A%=A$,"&FF"):B%=A$,A%,5):B%<&FFCE B%>&FFF9 =A$ tex%=3 A$=A$+" :\ &"+~B% ~%B%=B%-&FFCE:C%=B%+(B%>22)+(B%>25) CB%=(B%3-(B%>27))3-3*(B%=24)+(B%>24 B%<28)-3*(B%=27)-(B%=28) ((ex%1) B$=A$,A%-1) B$=A$+" :\ " nB$=B$+"OS"+"FINDGBPBBP IFQ$="Z" PROCmachine:PROCset_scr:=0 Q$="N" ex%=(ex%+1)3:=0 Q$="R" rom:=0 Q$="*" osc:=0 5(Q$>"/" Q$<":")(Q$>"@" Q$<"G") byte(Q$):=0 Q$="U" file1:=0 Q$="I" file2:=0  =Q$="X" : #byte(Q$): A%:"Bytes: &";Q$; :A%=: A%>96 A%=A%&DF ( A%=95 Q$<>"" 127:Q$=Q$, Q$-1)  A ((A%>47 A%<58) (A%>64 A%<71)) Q$<30 A%:Q$=Q$+A%  A%=13  > Q$<>"" :?(P%+O%)=("&"+Q$,2)):P%=P%+1:Q$=Q$,3):Q$<2 * 4: >*ݤosb(A%,X%,Y%):=(&FFF4 &FFFF00)256 H: UTBGETARGSFILERDCHASCINEWLWRCRWRCHWORDBYTECLI",(C%3)*4+1,4):B%<>0 B$=B$+"+"+(B%) (ex%1) B$=B$+A$,A%+5) =B$ : Xfile1:o%=O%:"D"dd$"e text file":"File: "f$:ch%=f$:ch%=0 f$" not found":z%=: εa$=get:a$,3)="PC=":z%=par(a$):Ptr%=("&"+a$,4,z%-4)):x%=0::Data%?x%=("&"+a$,z%+1,2)):x%=x%+1:z%=z%+3:a$,z%,1)<>",":Word%=!Data%:O%=Data%-Ptr%:a$;" \ ";DissZ80 a$ ##ch%:#ch%:ch%=0:O%=o%:z%=: : =ݤpar(a$):z%=a$,","):z%0:=z% =a$,":") : 5ݤget:a$="Data%=Word%:num%=1 ;c%=?Data%:d%=c%7:s%=(c%&38)8:=("FNz80_"+~(c%&C0)) : ݤz80_0:c%=0:="NOP" "@(c%&F7)=&10:num%=2:="DJNZJR ",s%*4-7,4)+" "+jr(Data%?1) ,)d%=7 s%<4:=rot(s%),3+(s%>1))+"A" 6%d%=7:="DAACPLSCFCCF",s%*3-11,3) @Dd%=6:num%=num%+1:="LD "+reg(s%)+",&"+Hex(?(Data%+num%-1),2) J4(d%6)=4:="INCDEC",(d%1)*3+1,3)+" "+reg(s%) T0d%=3:="INCDEC",(s%1)*3+1,3)+" "+drg(s%) ^Gc%=&22:num%=num%+2:="LD (&"+Hex(!(Data%+num%-2),4)+"),"+drg(4) hJc%=&2A:num%=num%+2:=":a$=a$+#ch%:a$,1)<" ":=a$,a$-1)  : Tfile2:"D"dd$"e object file":"File: "f$:ch%=f$:ch%=0 f$" not found":z%=: 7"Start addr: &"a$:a$="" ADDR%=0 ADDR%=("&"+a$) (p%=0:o%=O%:z%=0:#ch%=p%::data%?z%=#ch%:z%=z%+1:#ch% z%>7:O%=data%-ADDR%:num%=line(ADDR%):p%=p%+num%:ADDR%=ADDR%+num%:#ch%:#ch%:ch%=0:O%=o%:z%=: 2: < Disassembly routines: F InitZ80 P Data% 4 Z d: n3ݤalu(A%)="ADDADCSUBSBCANDXOROR CP ",A%*3+1,3) x3ݤrot(A%)="RLCRRCRL RR SLASRASLSSRL",A%*3+1,"LD "+drg(4)+",(&"+Hex(!(Data%+num%-2),4)+")" r8c%=&32:num%=num%+2:="LD (&"+Hex(Data%!1,4)+"),A" |8c%=&3A:num%=num%+2:="LD A,(&"+Hex(Data%!1,4)+")" -d%=2 (s%5)=0:="LD ("+drg(s%)+"),A" "d%=2:="LD A,("+drg(s%)+")" 2d%=1 (s%1)=1:="ADD "+drg(4)+","+drg(s%) Dd%=1:num%=num%+2:="LD "+drg(s%)+",&"+Hex(!(Data%+num%-2),4) @d%=0 s%>3:num%=num%+1:="JR "+cc(s%3)+","+jr(Data%?1) ="EX AF,AF'" : ݤz80_40:c%=&76:="HALT" ' s%=6:="LD "+reg(s%)+","+r(d%)3) ݤr(A%)="BCDEHLFA",A%+1,1) >ݤdrg(A%)="BCDEHLSPIXAFIY",(A%1)+((xy%*4)((A%6)=4)),2) $ݤreg(A%):xy%=0 A%<>6:=r(A%) A%=6 xy%=0:="(HL)" 7A%=6:num%=num%+1:="(I"+(87+xy%)+rel(Data%?2)+")" #(A%6)=4:="I"+(87+xy%)+r(A%)  =r(A%) +ݤrel(A%):A%<128:="+"+A% =(A%-256) Hݤjr(A%):A%<128:="&"+Hex(Ptr%+A%+2,4) ="&"+Hex(Ptr%+A%+2-256,4) Kݤcc(A%)="NZZ NCC POPEP M ",A%*2+1,2-((A% 1) (A%<4))-(1 (A%>5))) : (ݤDissZ80: Word%=data, Ptr%=address & s%,d%,c%,xy%:! ' d%=6:="LD "+r(s%)+","+reg(d%) "="LD "+reg(s%)+","+reg(d%) : Eݤz80_80:s%<4:=alu(s%)+" A,"+reg(d%) =alu(s%)+" "+reg(d%) /ݤz80_C0:d%=5 (s%1)=1:=("FNz80_"+~c%) c%=&CB:=z80_CB "d%=7:="RST &"+Hex(c%&38,2) &9d%=6 s%<4:num%=2:=alu(s%)+" A,&"+Hex(Data%?1,2) 00d%=6:num%=2:=alu(s%)+" &"+Hex(Data%?1,2) :H(d%3)=1 (s%1)=0:="POP PUSH",(d%4)*4+1,4)+" "+drg(s%-4*(s%>5)) D;d%=4:num%=num%+2:="CALL "+cc(s%)+",&"+Hex(Data%!1,4) N;d%=2:num%=num%+2:="JP DCHFILEARGSBGETBPUTGBPBFINDFF0CFF0DFF0EFF0F",c%*4+1,4) f&c%<&40 c%>&C0:num%=1:="DEFB &ED" p4(c%&C7)=&42:=alu(3-(s%1)*2)+" HL,"+drg(s%) zI(c%&CF)=&4B:num%=num%+2:="LD "+drg(s%)+",(&"+Hex(Data%!2,4)+")" F(c%&CF)=&43:num%=num%+2:="LD (&"+Hex(Data%!2,4)+"),"+drg(s%) ((c%&C7)=&40:="IN "+r(s%)+",(C)" %(c%&C7)=&41:="OUT (C),"+r(s%) 0(c%&E7)=&46 s%<>1:="IM "+(s%-1-(s%=0)) '(c%&F7)=&67:="RRDRLD",s%*3-11,3) ((c%&F7)=&46:="RETNRETI",s%*4+1,4) c%=&44:="NEG"  "+cc(s%)+",&"+Hex(Data%!1,4) Xd%=0:="RET "+cc(s%) b,c%=&C3:num%=3:="JP &"+Hex(Data%!1,4) lc%=&C9:="RET" v3c%=&D3:num%=2:="OUT (&"+Hex(Data%?1,2)+"),A" 3c%=&DB:num%=2:="IN A,(&"+Hex(Data%?1,2)+")" c%=&D9:="EXX" !c%=&E3:="EX (SP),"+drg(4) !c%=&E9:="JP ("+drg(4)+")" c%=&EB:="EX DE,HL" c%=&F9:="LD SP,HL" ="DIEI",(s%1)*2+1,2) : -ݤz80_CD:num%=3:="CALL &"+Hex(Data%!1,4) 5ݤz80_CB:num%=num%+1:xy%:c%=Data%?3 c%=Data%?1 9d%=c%7:s%=(c%&38)8:cP(c%&E7)=&47:="LD "+(65-8*(s%=0)-17*(s%=1))+","+(65-8*(s%=2)-17*(s%=3)) G(c%&E4)=&A0:="LDCPINOT",d%*2+1,2)+(73-5*(s%1))+(32+25*(s%2)) num%=1:="DEFB &ED" e JP new_osc+&11:JP new_osc+&E ] "'"Saving Z80 BASIC base code" , tes"+Hex(Data%!2,4)+"),"+drg(s%) ((c%&C7)=&40:="IN "+r(s%)+",(C)" %(c%&C7)=&41:="OUT (C),"+r(s%) 0(c%&E7)=&46 s%<>1:="IM "+(s%-1-(s%=0)) '(c%&F7)=&67:="RRDRLD",s%*3-11,3) ((c%&F7)=&46:="RETNRETI",s%*4+1,4) c%=&44:="NEG" %<&40:=rot(s%)+" "+reg(d%) 8="BITRESSET",(c%64)*3-2,3)+" "+(s%)+","+reg(d%) :  ݤz80_DD  ݤz80_FD -xy%:num%=1:="DEFB &"+Hex(xy%*&20+&BD,2)  ' A$:xy%=(c%&20)&20+1:num%=num%+1 *>c%=Data%?1:d%=c%7:s%=(c%&38)8:A$=("FNz80_"+~(c%&C0)) 4GA$,4),"X")+A$,"Y")=0:num%=1:="DEFB &"+Hex(xy%*&20+&BD,2) =A$ >: H6ݤz80_ED:xy%:num%=1:="DEFB &"+Hex(xy%*&20+&CD,2) R0num%=num%+1:c%=Data%?1:d%=c%7:s%=(c%&38)8 \c%<&10:="DEFW &"+Hex(c%*256+&ED,4)+":\ MOS_"+"QUITCLI BYTEWORDWRCHRta%:Ptr%=ADDR%:$(ctrl%+4)=DissZ80:ctrl%?3=num% %Hex(ADDR%,D%);: Z%=0ctrl%?3-1 &"" ";Hex(data%?Z%,2);::13+D%); Q, Z%=0ctrl%?3-1: (data%?Z%127)<32 (data%?Z%127)=127 "."; data%?Z%; 66:18+D%);:ex%=0 $(ctrl%+4) adr($(ctrl%+4)) @=ctrl%?3 J: ;Tlist(Flg%): A%:A%=P%::A%=A%+line(A%): >hgh%-11: 4^A%=P%::A%=A%+line(A%): >hgh%-11 A%>P%+90: h: orsize:wid%=osb(160,10,0)-osb(160,8,0)&FF:hgh%=osb(160,9,0)-osb(160,11,0)&FF:mde%=osb(135,0,0)256: B|set_s > Z80-MON 1.03a  Z80 Disassembler  By J.G.Harston, (C)1987-93 #(size:wid%>38 mde%&80 &87 *2 ctrl% 32,data% 16: D%<4 D%>6 D%=4 F<Flg%=0:OSWORD=&FFF1:OSBYTE=&FFF4:ny%=0:ex%=0:ch%=0:dd$="isassembl" CFset_scr:InitZ80:O%=O%&FFFFF:P%=P%&FFFF:arc O%+P%> O%=0 P err Zmenu d n: XxInSc:wid%=osb(160,10,0)-osb(160,8,0)&FF:hgh%=osb(160,9,0)-osb(160,11,0)&FF: 5ݤHex(A%,N%):N%=1+((N%-1)7):="0000000"+~A%,N%) : ݤrm(!&F6,Y%)=&FFB9 &FF $ݤb(ADDR%cr: A$,B$:size:A$=132:B$=135:mde%<>7 A$=" ":B$=" " I26::InSc:wid%/4+(ny%>9)+2,"*");" Z80 Disassembler ";wid%-,"*") 0,hgh%-6)A$"RETURN"B$"forward 1"21)A$"+"B$"forward 8"7;A$"DELETE"B$"back 1"7;A$"-"B$"back 8"'A$"L"B$"List d"dd$"y "A$"Q"B$"DUMP/LIST"7; iA$"M"B$"Set Memory address"A$"O"B$"Set code origin"'A$"T"B$"Enter text"8;A$"Y"B$"Enter message "; 8A$"Z"B$"Set machine"4;A$"SPACE"B$"Move past code"; wid%>39 '" N Name display"7"W Address Width S Screen mode"5"0-9, A):(R%16)=0 :=ADDR%?O% 8(ADDR%&C000)=&8000:=rm(ADDR%+O%,R%15) =ADDR%?O% : ݤdump Hex(ADDR%,D%);" ";: z%=0 wid%5:Hex(data%?z%,2);" ";:: z%=0 wid%5:(data%?z% 127)<32 (data%?z% 127)=127 46 data%?z% ::=wid%5+1 : ݤline(ADDR%): A%,X%,Y%,Z% 0X%=((O%+ADDR%)&C000)<>&8000 (R%16)=0:Y%=0 X% Flg%<1 !data%=ADDR%!O% X% Flg%>0 Z%=0 12 4:data%!Z%=!(ADDR%+O%+Z%): A%=015+12*(Flg%<1):data%?A%=rm(ADDR%+O%+A%,R%15): Flg%>1:=dump <Word%=!da-F enter bytes"'" R Rom number"9"U Diss text file I Diss object file X Exit";  28,0,hgh%-7,wid%,2: : ݤmenu:3:: num%,Q$,A% M0,2)"PC: &";Hex(P%,D%)18,2);"Code addr: &";Hex(O%,D%+1)':list(Flg%) # (R%16) 29,3);"Rom: ";R%15 0,0);:num%=line(P%) 6:0,hgh%-10);:Q$=:Q$>"`" Q$<"{" Q$=(Q$-32) <13+9+127+" +;-=QWSMOLTYZUINR*0123456789ABCDEFX",Q$) Q$=13 P%=P%+1:=0 Q$=127 P%=P%-1:=0 Q$="+" Q$=";" P%=P%+8:=0 &Q$="-" Q$="=" P%=P%-8:=0 '0Q$=" " Rrom: Q$:osb(0,255,0)>6 \osb(130,0,0)<>&FFFF .f131:"Rom: "Q$: Q$="" R%=0 R%=16+(Q$) p z: 'mode: Q$,Q%:"Mode: "Q$:Q$="" AQ%=(Q$)&80:笤arc:osb(130,0,0)=&FFFF osb(133,Q%,0)< +22,Q%:set_scr:wid%<39 22,7:set_scr  : ݤarc=(-256 &F0)=&A0 : diss: A$,addr%,end% <"Start address: &"A$: A$="" addr%=P% addr%=("&"+A$) A"End address: &"A$: A$="" end%=addr%+&8000 end%=("&"+A$) ?"Address for code address 0000: &"B$: B$<>"" O%=("&"P%=P%+num%-num%*10*(Flg%>0) :Q$="Q" Flg%=Flg% 2:=0 DQ$="W" D%=4+((D%-3)5):=0 "N IFQ$=CHR$9 Flg%=Flg%EOR 1:=0 +XQ$="M" "Address: &"Q$:P%=("&"+Q$):=0 AbQ$="O" "Address for code address 0000: &"Q$:O%=("&"+Q$):=0 lQ$="L" diss:=0 vQ$="S" mode:=0 ]Q$="T" A$;:"Text: "Q$:A%=?(P%+O%+Q$):$(P%+O%)=Q$:?(P%+O%+Q$)=A%:P%=P%+(Q$ -1):=0 Q$="Y" A$;:"Message: "Q$:A%=?(P%+O%+Q$):$(P%+O%)=Q$:?(P%+O%+Q$)=A%:?(P%+O%-1+Q$)=&80 ?(P%+O%-1+Q$):?(P%+O%+Q$)=A%:P%=P%+(Q$ -1):=0 )+B$) ,:addr%=addr%+line(addr%):addr%>end%: : osc: A$ :"*"A$: A$: A$="": : $ݤerr: <>17 -1 #.ch%<>0 A%=ch%:ch%=0:O%=o%:#A% 8 <>17 B -1 " at line "; L=-1 V: -`ݤadr(A$):B$,A%,B%,C%: A$,"&FF")=0 =A$ 7jA%=A$,"&FF"):B%=A$,A%,5):B%<&FFCE B%>&FFF9 =A$ tex%=3 A$=A$+" :\ &"+~B% %~B%=B%-&FFCE:C%=B%+(B%>22)+(B%>25) CB%=(B%3-(B%>27))3-3*(B%=24)+(B%>24 B%<28)-3*(B%=27)-(B%=28) ((ex%1) B$=A$,A%-1) B$=A$+" :\ " nB$=B$+"OS"+"FINDGBPBBPU IFQ$="Z" PROCmachine:PROCset_scr:=0 Q$="N" ex%=(ex%+1)3:=0 Q$="R" rom:=0 Q$="*" osc:=0 5(Q$>"/" Q$<":")(Q$>"@" Q$<"G") byte(Q$):=0 Q$="U" file1:=0 Q$="I" file2:=0 =Q$="X" : #byte(Q$): A%:"Bytes: &";Q$; :A%=: A%>96 A%=A%&DF ( A%=95 Q$<>"" 127:Q$=Q$, Q$-1) A  ((A%>47 A%<58) (A%>64 A%<71)) Q$<30 A%:Q$=Q$+A% A%=13 >  Q$<>"" :?(P%+O%)=("&"+Q$,2)):P%=P%+1:Q$=Q$,3):Q$<2 * 4: *>ݤosb(A%,X%,Y%):=(&FFF4 &FFFF00)256 H: !TBGETARGSFILERDCHASCINEWLWRCRWRCHWORDBYTECLI",(C%3)*4+1,4):B%<>0 B$=B$+"+"+(B%) (ex%1) B$=B$+A$,A%+5) =B$ : Xfile1:o%=O%:"D"dd$"e text file":"File: "f$:ch%=f$:ch%=0 f$" not found":z%=: a$=get:a$,3)="PC=":z%=par(a$):Ptr%=("&"+a$,4,z%-4)):x%=0::Data%?x%=("&"+a$,z%+1,2)):x%=x%+1:z%=z%+3:a$,z%,1)<>",":Word%=!Data%:O%=Data%-Ptr%:a$;" \ ";DissZ80 a$ ##ch%:#ch%:ch%=0:O%=o%:z%=: : =ݤpar(a$):z%=a$,","):z%0:=z% =a$,":") : 5ݤget:a$=""3 . PROGRAM TO CONVERT 6502 BBCBASIC FORMAT FILE ,. INTO Z80 INTERNAL BINARY FORMAT FILE. . R.T.RUSSELL, 04-02-1984 (: 2 7 < ':&85::': \F''141"6502 format to Z80 format converter"'141"6502 format to Z80 format converter"'' P: Z "d"6502-format file:"infile$' ,n infile$,".")=0 infile$=infile$+".DFS" xfin=(infile$) ) fin=0 "File "infile$" not found"' fin<>0 : ""Z80-format file:"outfile$' fout=(outfile$) " fout=0 "Directory full"': : :a$=a$+#ch%:a$,1)<" ":=a$,a$-1)  : Tfile2:"D"dd$"e object file":"File: "f$:ch%=f$:ch%=0 f$" not found":z%=: 7"Start addr: &"a$:a$="" ADDR%=0 ADDR%=("&"+a$) (p%=0:o%=O%:z%=0:#ch%=p%::data%?z%=#ch%:z%=z%+1:#ch% z%>7:O%=data%-ADDR%:num%=line(ADDR%):p%=p%+num%:ADDR%=ADDR%+num%:#ch%:#ch%:ch%=0:O%=o%:z%=: 2: < Disassembly routines: FInitZ80 P Data% 4 Z d: 3nݤalu(A%)="ADDADCSUBSBCANDXOROR CP ",A%*3+1,3) 3xݤrot(A%)="RLCRRCRL RR SLASRASLSSRL",A%*3+1,3 ."Enter file type (program/data):"type$' type=(type$)&5F ! type<>68 type<>80 11,11  type=68 type=80 :  type=80 program data #0  "; , program *6 #fin<>13 "Not a BASIC program"': @ Jnhi=#fin FT nhi<&80 nlo=#fin:ll=#fin:#fin,l$ nhi=&FF:nlo=&FF:ll=0:l$="" +^ l$,1)=" " l$=l$,2):ll=ll-1: D^A 2h nhi<&80 ll<>(l$)+4 "** Bad program **"' &r #fout,ll: #fout,nlo: #fout,nhi | nhi<&80 #fout,l$  #fin nhi>&7F  #fin bin) ݤr(A%)="BCDEHLFA",A%+1,1) >ݤdrg(A%)="BCDEHLSPIXAFIY",(A%1)+((xy%*4)((A%6)=4)),2) $ݤreg(A%):xy%=0 A%<>6:=r(A%) A%=6 xy%=0:="(HL)" 7A%=6:num%=num%+1:="(I"+(87+xy%)+rel(Data%?2)+")" #(A%6)=4:="I"+(87+xy%)+r(A%) =r(A%) +ݤrel(A%):A%<128:="+"+A% =(A%-256) Hݤjr(A%):A%<128:="&"+Hex(Ptr%+A%+2,4) ="&"+Hex(Ptr%+A%+2-256,4) Kݤcc(A%)="NZZ NCC POPEP M ",A%*2+1,2-((A% 1) (A%<4))-(1 (A%>5))) : (ݤDissZ80: Word%=data, Ptr%=address & s%,d%,c%,xy%:!Dary  ;  binary F%=fin:G%=fout #G%,#F%:#F%  ;  data F%=fin:G%=fout  T%=#F% D T%=&40 i T%=&FF r T%=0 s "** Bad data **"':#G%,T% #F%  ; & i #0A%=#F%:B%=#F%:C%=#F%:D%=#F% #:#G%,D%:#G%,C%:#G%,B%:#G%,A% D#G%,0 N X; b r +lA%=#F%:B%=#F%:C%=#F%:D%=#F%:E%=#F% ?v E%=0 E%=1 "** Underflow **"':A%=0:B%=0:C%=0:D%=0:E%=1 -#G%,A%:#G%,B%:#G%,C%:#G%,D%:#G%,E%-1  ;  s  s$ S%=#F% ! S% N%=1LD "+drg(4)+",(&"+Hex(!(Data%+num%-2),4)+")" 8rc%=&32:num%=num%+2:="LD (&"+Hex(Data%!1,4)+"),A" 8|c%=&3A:num%=num%+2:="LD A,(&"+Hex(Data%!1,4)+")" -d%=2 (s%5)=0:="LD ("+drg(s%)+"),A" "d%=2:="LD A,("+drg(s%)+")" 2d%=1 (s%1)=1:="ADD "+drg(4)+","+drg(s%) Dd%=1:num%=num%+2:="LD "+drg(s%)+",&"+Hex(!(Data%+num%-2),4) @d%=0 s%>3:num%=num%+1:="JR "+cc(s%3)+","+jr(Data%?1) ="EX AF,AF'" : ݤz80_40:c%=&76:="HALT" ' s%=6:="LD "+reg(s%)+","+r(d%) S%:s$=(#F%)+s$: $ s$,13) "** Bad string **"' #G%,s$  ((22<<FFPPZZddnnxx i T%=&FF r T%=0 s "** Bad data **"':#G%,T% #F%  ; & i #0A%=#F%:B%=#F%:C%=#F%:D%=#F% #:#G%,D%:#G%,C%:#G%,B%:#G%,A% D#G%,0 N X; b r +lA%=#F%:B%=#F%:C%=#F%:D%=#F%:E%=#F% ?v E%=0 E%=1 "** Underflow **"':A%=0:B%=0:C%=0:D%=0:E%=1 -#G%,A%:#G%,B%:#G%,C%:#G%,D%:#G%,E%-1  ;  s  s$ S%=#F% ! S% N%=1' d%=6:="LD "+r(s%)+","+reg(d%) "="LD "+reg(s%)+","+reg(d%) : Eݤz80_80:s%<4:=alu(s%)+" A,"+reg(d%) =alu(s%)+" "+reg(d%) /ݤz80_C0:d%=5 (s%1)=1:=("FNz80_"+~c%) c%=&CB:=z80_CB "d%=7:="RST &"+Hex(c%&38,2) 9&d%=6 s%<4:num%=2:=alu(s%)+" A,&"+Hex(Data%?1,2) 00d%=6:num%=2:=alu(s%)+" &"+Hex(Data%?1,2) H:(d%3)=1 (s%1)=0:="POP PUSH",(d%4)*4+1,4)+" "+drg(s%-4*(s%>5)) ;Dd%=4:num%=num%+2:="CALL "+cc(s%)+",&"+Hex(Data%!1,4) ;Nd%=2:num%=num%+2:="JP ata%=Word%:num%=1 ;c%=?Data%:d%=c%7:s%=(c%&38)8:=("FNz80_"+~(c%&C0)) : ݤz80_0:c%=0:="NOP" @"(c%&F7)=&10:num%=2:="DJNZJR ",s%*4-7,4)+" "+jr(Data%?1) ),d%=7 s%<4:=rot(s%),3+(s%>1))+"A" %6d%=7:="DAACPLSCFCCF",s%*3-11,3) D@d%=6:num%=num%+1:="LD "+reg(s%)+",&"+Hex(?(Data%+num%-1),2) 4J(d%6)=4:="INCDEC",(d%1)*3+1,3)+" "+reg(s%) 0Td%=3:="INCDEC",(s%1)*3+1,3)+" "+drg(s%) G^c%=&22:num%=num%+2:="LD (&"+Hex(!(Data%+num%-2),4)+"),"+drg(4) Jhc%=&2A:num%=num%+2:=""+cc(s%)+",&"+Hex(Data%!1,4) Xd%=0:="RET "+cc(s%) ,bc%=&C3:num%=3:="JP &"+Hex(Data%!1,4) lc%=&C9:="RET" 3vc%=&D3:num%=2:="OUT (&"+Hex(Data%?1,2)+"),A" 3c%=&DB:num%=2:="IN A,(&"+Hex(Data%?1,2)+")" c%=&D9:="EXX" !c%=&E3:="EX (SP),"+drg(4) !c%=&E9:="JP ("+drg(4)+")" c%=&EB:="EX DE,HL" c%=&F9:="LD SP,HL" ="DIEI",(s%1)*2+1,2) : -ݤz80_CD:num%=3:="CALL &"+Hex(Data%!1,4) 5ݤz80_CB:num%=num%+1:xy%:c%=Data%?3 c%=Data%?1 9d%=c%7:s%=(c%&38)8:c%ssing No such Bad  rangevariableOut ofNo  spaceroomMistake,Type mismatch"Not ArraySubscriptSyntax errorEscapeDivision by zeroString too longToo big-ve rootLogAccuracy lostExp)HEX/callArgumentsCan't match  syntaxline #͎ ~(Q#^#Vz(++7B0@N#V}2:ØO( x  !:>~(#^#Vz(#7Bҗ":=n6Ͳͷ *:[:~(/#N#Fx(q#p# -q#p#++GN $r86#6[:*:Ny(##^#*×Ä Îòz 4ë2Î221!:6 ,6 ,w, =2:!v":͛6S:":ͪs Acorn BBC BASIC Version 2.20 (C) Copyright R.T.Russell 1983 7{:7!:~0w!":":*:":|( K: -":> Z !872:!8ͧ ͏/|(":9 GK*:|!9ʪ ͎͑ NyʘO*: $r":#RDM(#q#s#r#9 ̓ØANDABSACSADVALASCASNATNAUTOBGETBPUTCOLOURCOLORCALLCHAINCHR$CLEARCLOSECLGCLSCOSCOUNTDATADEGDEFDELETEDIVDIMDRAWENDPROCENDENVELOPEEV#":#s#r# > ͱ)DM*:^#V#B^#V#8( Failed at *: S ͼ ͷ ":y2:) program ͪ*:###> }w̓Ø_> iͲ͎_> [:*:RDM!8r1×{:!8( G# ":{:2:ͪ ":( *:|ª !":":1S 1S Ø!W~F#(#~(#~ #~.(( 8~ +xN *:RDMS:[:!9RDM!8ͻ1Ԫ>͎+6+6$*:> N ( +#(i###":*:6ͣ*:":":!l:p6# ~6 6 > FZ xNĬyVĬ~6 LSEEVALERLERROREOFEORERREXPEXTFORFALSEFNGOTOGET$GETGOSUBGCOLHIMEMINPUTIFINKEY$INKEYINTINSTR(LISTLINELOADLOMEMLOCALLEFT$(LENLETLOGLNMID$(MODEMODMOVENEXTNEWNOTOLDONOFFOROPENINOPENOUTOPENUPOSCLIPRINTPAGEPTRPIPLOTPOINT(PROCPOSPUTRETURNREPEATREPORTREADREMRUNRADRESTORERIGHT$(RNDRENUMBERSTEPSAVESGNSINSQRSPCSTR$STRING$(SOUNDSTOPTANTHENTOTAB(TRACETIMETRUEUNTILUSRVDUVALVPOSWIDTHHIMEMLOMEMPAGEPTRTIMEMi6 ~# (F" * ͱ) C ,(s ~( D (  Q > Z > 7 (::<2:*:Z !W~#Z *:<ЯGN#~#foR Û [:*:R0N ( R8B#^#V":!*:| at line  'R<0=(Z x()T]))7c ~( h>~$(b!(b?(b ~( A~(##I/VN#F#%B>0= U/W~?(!(z>>!z,#m~ ~!:(C!:(<7@&0o~% ~(():##u#t%8F~,(U/#p8+8($($r0 ":z(+6͏/,ª #͏/> !> (PG~)x(*:!LV#*:# kC͏/,ª #F}͎2|͎2}͎2|͎2y͎2K!8 ( ~#͎2> ͎2"!:(::( (0Dͬ::OL(8ˀ#~(;(,(e(+F)J*)yԬͺ@S ê #!":͏/#ʪ +":#(V~#(>' Cx )(&G (L(#, mx(%L(1#~#( >(mL͑ ʧ >)mIͱ!Rʪ >&Iͪ !B>+ V- ;?=ol:--7^#Vz(Ebk##~##(( +~((# 8 ((~ 0~$%<ɯ[:r+sw#w## 8w# 0(( ~((#6#Q >(=6#= ":I͏/-+|-ͧ | . L#! ħ xSillyͧ L#ħ ͑ ~$%(0:?A[?_{?ɯ#{0~ 0˩˙ (,(G8˙" ?a(ˡͧ |ļ  ( *(80@( ( ( 8& !  !   :6#zG{Tw#{?@w#z?@w#*:~#s  ];jw|ê >" ~>$ #OG!L!~ #OIͪ !OB> sL% R P!9Ͷ ~ z> ͨ/!9Ͷ ,>ͨ/$ !9͏/,ª #ê !9!OB(>!I+ (9>8*:>8!#͏/ 8 c s#r> G > ^#V!9͏/( ͏/(U/es#rê !B(!B( !,B> +% -Y͏/,ª #͏/!,B(!Bʪ > x!9YC͏/,ª #͏/zͫ2oͫ2gͫ2oͦ0FYm f=1C##0 d0 .1*CQ10OR0}#`nh M1L( _> {:i{:!:_(wwͲ!":*:>":*: ":n6͏/#:( (8oO! ~#fo͏/ͪ |ʘ1×~ (*:|V^R>[Z >]Z > Z _> !844> Gç (d(w(L(+ʪ 86X_ê ":n6K8 (!:~0w%  >!>FC!,B(!B> ":8Xx!9Y% 8{Xc ~(z rB#V| W##ݫ2gͫ2O!8ͫ2 (w, #( #!96 Lʪ #,(M;(I" = ͺe +z~# ̚y!ˁA >?Z > Z !97G2:~ ##*:~# zO":͏/,ª #͏/>#>*V-(~ª #͏/ª î~ #ʧ /2:ê ͪ S Ø ê Ͳ*:*:L( m͑ >) >":ê 9X{V2ê XV.":ê XV/ê XVͲ":":ê XV[:R[:":rª ê V}2:. #z-*@:#+!xH'0h 0h=U0\K 02x =y0(F x? 7y (O0CydO`y0!C$(x7y%0$Iy0> [@:7R}>}2G Iy0 x?>( > + |   }x Iy0p llu0_C((j`>G\x? y >==y0w `ͺ0 \ͺu !:Ooygxm_!8~#x8x? yyC7y0h(D&>.>v7{ !xxX̪ #!( (+V+":ê V}7~,(; |7#L ê 91ê 9I/V}͎2ê V9͏/, #͏/zs#rx29͐ê m$!!:K1N~FN V^f n0!9OVI/Viê %  XOG(qutut,(u!80? {o|ٻ0eO K:B7(`iK S:*:$rدKѯG(> >#͏/% 88 OGI _ͺ-͏/, ,(>U/) x<=-#͏/zѷG]>p(>Ww#~)!V}x??2/2&x07>x ?O!_7(?~(_( ~#(#~## ~_(8 xF#8D#+-NORLCEXAFAFRRCRLRRDA'CP/SC7CC?HALvEXEXDEHDENEDIMFRETERETMIMVIM^RRgRLoLDɠCPɡINɢOUTɣLDĨCPĩINĪOUTīLDIҰCPIұINIҲOTIҳLDDҸCPDҹINDҺOTDһBI@REӀSERLRRRRSL SR(SR8POPUSEX(SSUANĠXOҨOҰCиADĀADÈSBØINDEI@OUAJ DJNJCAL& KI!EB9G( 8E,I͏/,(~ ,);\͏/: ͏/#=>( (8'S V~,(U/}!:S #VU/ 0m}G> Z !8~#Z ͏/8~ #͏/"#= +8~, #N ( ### +7bk))!>)#0 = ͏/#>-#m#:(] +*@:!:v(*<:7+#~R ::R*@:"@:w(*<:"<:g(|}(::>Ԇ~# >͆B s - S K> Ɛ'@'s RSREL@]]OP](H(I؆(IBD H I،IASNNPP( IGROAWA_(BC(DEA(B A(D)!!c!!Y!^! $X0F!$-%"!:#!!w!|!"#!-0!+!%"S!h$$ !!!"0 !!E"!H#"#h!)!!/&L&<&&R&&*&!&K'&' '))p)O))(n'_)X'('&H'&' '{))k)J))c(x'Z)b')'v))f)E))U)[(b/[p/lb/lp/2/G#͏/2/ #ʁGx: d/p/=ͺ-{K!9C8͚/&9O~-(+b/p/#ͺ-{K!8Ty(Eo͈.`i`i,,O˼f,ͥ-@#ͮ-ͥ-,N#ͮ-'f,6,{f,6,˼#h'#ͥ-͟- .6m&sy}ͮ-ͮ-c(ú#͟- .qxLpvȜ*{~ͮ- If,]$F,{( ->怳˼ͥ- .r@.seoO.v7my*{O}V~ͮ-T$?$Dƀ8--ƀ-O#,'r1f,>| 53"-y8 <-ͥ-͟- .Ht}~L~㩪*ͮ-ͮ-c(ͥ--ր(0/--~7*( /((b/7p/;͏/^b/;p/F%F,F;;,;>FU/-/8#ͅ-ͅ-ͅ-ͅ-ٵo/0>f ,|gI͏/#&(-(+((("(cҁҠ/+:000t.(p% + (G(Nnfnf!&nLځ::o> ## 0!@:O8~#"(  0> ~"#(+>-+.+E>̍+|   Ȑͧ,˼ 1.c(8 D1.'>&1.'&F^V^V80 }ٷO>~# > f| ,˼m|/g}/f,ͥ-͗-c(#h'"ͮ-, ͸! 'f,|˼T~-8y-8T$-ͥ-͟- .57{k|Aa|{7}Z*L}\~ͮ-ͮ-c(#x'h'F/ͺ-_K!9%U/&9goO͏/,> #ͺ-V-}ٷ(=DC8_! x(# ( #((78{ٸ8m/8>67F/ͺ-V-}ٷ( =o0DOͩ&͏/,#( +U/>F/ͺ-V-U/}ٻ0k_>̓&K}obX>VI/}_U/(=O>Cb.~#> >+|g}o|g}o+|g}oo|/g}/oٯ0u0p92ʦ)-9ͫ2oY<&͏/( mDMhCL&vʦ)*81v+*:(*:#*:~#P*:*: *:*:&ٯOgo7v> !872o92 92/O!I!!c(!'f,.ef-|¦)-,v!8͏/;/b ->óv> 8!8 ͺ-!9F9!:͏/((  jj](?Om!:|7 -, S"ͧ,˼{=ٳ,,c(,,f >D+,x,Of,|> A,yր/ƀO!DM!DM>.x./|g}o+|g}o|g}o+|||,,|,DM!DM!>m.,+',,n-h-͸,zW|g h-n-͸, ,|x,x+z'h-, n-(,͕,/!B,,,˼ -͸,> |BKBK>m.z̈.8B?,,,y?Ü(||,,|,DM!DM!>͛.- z ,J, #jjJ(˼- |DM!DM!>͛.ܯ.!R,,,y8--ƀO-˼,|,H ͅ-8,L!9(4,T$#> ͗->|ٴ8->gogoO,-yRR||0-?|"-|E- ( ( # 7ɷ  ͘-͋-͋-ZٷRR͘-ͅ-ͅ-h-)j <AT]T]͗-c(yAOI!8TER9W( K8I!D98 (ͥ-#x'ͮ-ͥ-,#b'ͮ-'!9Ͷ c(Ͷ x'x'Ͷ <#,=( I.8<<^-0͋-, >.-,˺ɷBB0 J?8<+),n$ͮ-c(#@-- -Q@-- -@@-- -0@-- -(!@-- -@-- -!!ٯO~#g#o|#gٯOgo#f)>,8ͅ- ( (Ɛ'@'G͏/~(f!:~!+(!:8,|(˼>-(Gxy00%/8>1.c(G 1.'G> 1.-yO\-˹> xN ݾ( >݆*ͅ- 8 , O|?g*< >>y00(:?0u >0<=- > >8^F 2N(x(B .)j8< BB J ~A87?:?0>=<#+-+_͏/#,> ͏/#)>#{{yGͨ/~~ #Ï/!:֍! xĴ,!ŇO ~#fo>!M7!M7nf^V!M7utsr>!M7> >|}7>{}>]lbVI/VU/!M7srut!M7> ~oggoOm>!M7Vux ( #I/!M7>ê !M7Vut##x(I/!M7>ê . .VI/VI/V>y{z}|+Pz݆_ 8x&+( ~ > 8PXxƁOz0 (;+J+>0B+6.#w#)+ M '6E#x=\+6-#D60( G>:8#604 60+4##F>y(6 # G#~;/~+/8xG~#G +d-xD#~+/#v-8 O 0#| ,,+-,,, |>+ȷ!R!R/!BDM>>#i!y!8:BRR0 ZZ?0=8)jj0շBRR}ê >ê V>}ê VI/V>{}ê !^1~^fdn`}lghyg͝5{54Ͳ3 >Directory full̈́3 B(0>X3<>Close error͝54ͨ3 >File not foundS3 ͝3 B0?{ 1 3ȯw+w!%~#Ą3!K:B S:772(_ͫ27n62 4Բ3ܨ3!L7~+(+>Too many open files[:s#rx!":!\$#q#G43xIG3x+p#N˹4# w133N˹4# FK313x3+~<3\$>#X33~++V+^+fo:U)C>>!M7ut66 6>!!M7s6@8 6̀6S :\=v5ABYŚ6CP͚6DIһ5DRIV85ERAS-5ER-5LOAĵ1RENAMG5REG5RESE45SAVi1TYP2*~#:>~Ä>:7> 7~#7 Bad sum>28!g6"9!c6">!>!-?6!_S_z6 !?7w#8!N#(6 [_!;L_3~(w+++V+^B#3+++6+p+q̈́3S3+˾+w6##ůw#͝343<3>!o3 >CP/M ErrorO$%3>(X3(>Disk full!!4#(\>X3<3\>X3>X3<\ ?(>Bad name>o33!%>Channel{ȇ_!=7^#Vz> e!4!|q#OͲ4" $#Y4"#(t>Bad string~#`?@#~:+x ~##\~.(" ( (=("(?*(  #| N4y%5~#*(. e(+~ #BBCͲ4~%508:8 A8G0))))_#Ͳ4!6%5( 8,~#(##BBCBASIC #%5.( ((~#(~#fo`_4: 64:\={5_*4= -#>\X3< /l 43\~ yX3>Bad command>File exists4ͼ4+ #ͼ4 ȷR>?4 !3\yX3S `_! ~ x> 67{6̀6S :\=v5ABYŚ6CP͚6DIһ5DRIV85ERAS-5ER-5LOAĵ1RENAMG5REG5RESE45SAVi1TYP2*~#:>~Ä>:7> 7~#7 Bad sum>28!g6"9!c6">!>!-?6!_S_z6 !?7w#8!N#(6 [_!;(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE) COPYRIGHT (C) 1979, DIGITAL RESEARCH, PIP VERS 1.5$$$ SUB =.:,<> _[]INPIRDPTRUR1UR2RDROUTLPTUL1PRNLSTPTPUP1UP2PUNTTYCRTUC1CONNULEOFDISK READ ERROR$DISK WRITE ERROR$VERIFY ERROR$NOT A CHARACTER SINK$READER STOPPING $NOT A CHARACTER SOURCE$ABORTED$BAD PARAMETER$INVALID USER NUMBER$RECORD TOO LONG$INVALID DIGIT$END OF FILE, CTL-Z?$CHECKSUM ERROR$CORRECT ERROR, TYPE RETURN OR CTL-Z$INVALID FORMAT$HEX$$$$NO DIRECTORY SPACE$NO FILE$COM$START NOT FOUND$QUIT NOT FOUND$CANNOT CLOSE DESTINATION FILE$DESTINATION IS R/O, DELETE (Y/N)?$**NOT DELETED**$$$$$$$NOT FOUND$COPYING -$REQUIRES CP/M 2.0 OR NEWER FOR OPERATION.$UNRECOGNIZED DESTINATION$CANNOT WRITE$INVALID PIP FORMAT$CANNOT READ$INVALID SEPARATOR$1 :2L> ̈́M9 221@:2!o6+6+6!6#6!6#6:G*o .!N6:^*M^!K6!6!6+6' :$::=2K  :ʤ\:ҷ\x'Ͳ:!\͢  :͈'! Ͳ:$: $͈Ͳ!N6' :!Cwͯ !6:^͢c!6{:/>!/H{ͯ :<2Š ::=HҮͯ !6:Ҿ:2 !6::/H͈;!6:> !/> "}*}DM͆ ' ͯ *"!z4 :e !"͆ !z6:|!z '? 2*H#"H!{6:{ր!Ң *{& :{4 2!{4m *":ڹ ͯ !z4I '2!"!q: !4>!S :S! :2*M! ^#V͎ * :w*#" = = = = = ͯ  *M !6q  !6q  !q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  HHͯ :!^w:<2:0}:@E}:!S!W6: z!]6:cm!c6:_z!_6l ::,: HHҰͯ : 2ó:E:1:2v!q!*8!*6: >ͦ>ͦ!q:_  !p+q.*   !q*&!p+q*2!p+q*2!p+q*22!p+q*!p+q*!p+q*!p+q*2!p+q* :2!q: " *M n :c4 *M n :2!c:Q !c:2: !:cw>!n !5 Y : { !6!q:!lwҙ  â :0O !q:O| :O| !6:]2l:o'2o:n'2n:m'2m*mMͣ *nMͣ *oMͣ :]:   *}2D" * * *&"!q:UY: Y:ҩ: ʩ:_2ʘ:€!6<:<2!ژ!6 >!]Ҥ; !6:Q::H: !6*M : !6!q:a/>z!!p+q* !q*& *M *M !p+q*!!p+q*"!p+q*$!6  !kp+q*j> >ڪ Þ !qp+q/ *pDM9: :M2r:N!r !:r *r& N!r4 !6:͔: :ͳ.!ws+p+q+p+q:w=2wN *s*u w*s#"s*u#"u' !"*M^7 !x6:!xھ **DM͆ 2yʭ :yʗ ͯ *"*6:2x÷ *"!x4d !"/ !j}=2| !"*KM^'_ !z6:|!z1 */H:_2:!q:A/>Z!/H8: 2::=O>m:W!Q} Hmd>9>!6:2*M!E ^#V͎ڗO **~2*#"m2m͖ 2m!6m!6m!6 m2mͯ m!62m!62m!62m!62m'2:2:TҒ:2!6*ME:2::^Ҳ:<22ý: 2:} >ͯ :i:2:d*M:[ ÷:S:QHI:N<22: H@"2Í202O> c!6Í202O> ڍ*&O*& !sc*&P :w:·>!ұͯ :22:_!6=!6>'!E!4!p+q*0 !r+s+p+q*~$7*>*>H&>*#"*#"> 2:^R͎:!6!6=2:ʙ!6:“H9Ž>!6-e!6ͻ2=2ʺ-é:>>"ͻ2:!!5ͻ2ͬ!\*M:>!(:=2%> >>!F!5+N! ~2!4<2T>>!b}*bMͭz!b~26!~6<+wé>!`ҥ*`MͭҞ!`6!6> :é:(!q:!wO! ~2*& :w>!:!4!6>:N<2N!> *N& N2 !p+q!6!6+6 !6: S: M!6g8:N2M*M8p!6!6!6>!ڕ*&P 6!4z!6!6#6#6!6*M8:ھ:*͇g2ê::¿::,͡A<2O>-:>>!p+q:,!6*DM9:<!6:z 2W!6D*&L :w:<2Ov*:>=20O> ڒ:0:AO>Ҥ::A }}Hͬ!wͻO`idͻV[2O>2:!X!6:!:=O!L NE!4 E E:/.*&L 6$L9k9.Xͯ *KM^020 :020:121'ͳ':²ͯ !G6!"!"7 *M^n/ :a/:H!6:ͯ !&6*M8):[ͱ!N5!6ñ:5!6#6>!ڰ!6:<2O>/:!O!T *M͡H~K:¡!6[–ͱ!N5:2:2!4=:[¼ͱ4:!6:.2O8: :* ͇g:[ ͱ!N5!6:%:<2*6 * 6å!q!6> !d*&I :]>!4A>:<2O* :w:?†!6!q!6?!:ҠgÐ!q*&*~!6:22: :]Hں:A2O>: 2ͯ 2*">!b!ͯ >!`0ͯ !q:E:24J!46*}a!44EJ *KM^'́:‚ͯ !36'n::0:f9OY#9.3'ͳ.:020' 'ͳ'7 6'!j>A+!s!"@͓1!"<**"͓n "Dn"":!Q2҂:X!Wғä:ڤ*MEÓ:ұ@@:O2Mc;!6#6>!)*&P ~"::H:H:H:H"!6!4:_jYO jM*"S*" 3@bl*M1͓!""7 *M^͆ \͔!":͎H*#"ͧÝ/ :>͛9ͯ .*#":_!' !'6!36' :1/!aE*#">z?C9IͲÁ.!6> !ڇ*&' ~2 ʀ: y.*M!4Q>!қ:=2á:2:Ҭ\>!ҿ:=2K:2K!:!:K\: \!p+q͈* copyright(c) 1977, digital research $Error On Line $SUBNo 'SUB' File Present$Disk Write Error$Command Buffer Overflow$Command Too Long$Parameter Error$Invalid Control Character$Directory Full$Cannot Close, Read/Only?$!9"!͇͊!p+q* ͊!p+q*͍2!p+q*͍2!p+q*͊!p+q*͍!p+q*͍!p+q*͍2!s+p+q+p+q:=2ʦ** w*#"*#"!p+q(+*DM*p*& 6:ep\:=DM!  ::=H-\:N2O_og_{ozg^#V))) _{ozg^#V) d^#V|g}o n_{ozgO{ozgi`N#Fogo&og H ©=¨^}'))p)O))(n'_)X'('&H'&' '{))k)J))c(x'Z)b')'v))f)E))U)[(b/[p/lb/lp/2/G#͏/2/ #ʁGx: d/p/=ͺ- K!9C8͚/&O~ɀͧ!t6>!t%\= >!t6:t<2t=O! ~2u b:<2O>9b!60+~9b!60+4:uat:u_2u:uMʉSͧ!v6!"v!|6:|Ҁ!x6 2}:} Hk:} h:}$6 2}$*}M3:}02}O> ͧ3!z6ͭ:}"!}5́ͭ́3*yM"h:}^a A2}O>Vͧ^:}>*z& ~ !z4í!{q*v#"v͙dͧ*vv :{w:x<2xO>}|ͧ COPYRIGHT (C) 1979, DIGITAL RESEARCH DISK OR DIRECTORY FULL$FILE EXISTS, ERASE IT$NEW FILE$** FILE IS READ/ONLY **$"SYSTEM" FILE NOT ACCESSIBLE$BAK$$$BAK$$$-(Y/N)?$NO MEMORY$BREAK "$" AT $1mM"m +!8s~1m!f6-!6]:ͧz2~e:~2O! 6*~& 6$>!~_z*~& w!~5Bx:yͧ*v+"vv ~_{ozg001 $$$$ SUBO=!9 Ÿ!6q!2qC J R q!z z=naO $q$,!;,!Ù!;qz8O! !;,z;qyO! ͣͣW_͕qyO! ͣ͒qy *M  *!M 1m! 6!6! 6: 2Ebͽ!e:d\::eH2 H҆ͽ:e2!:d2e:!2dû :!I¬!: :H2 ҮX:h2iҐ:!ʍ:!:!H:!H,!"! 6#~ F)ͷX:! X):i!h)9 e:!:h2jO>F L>!":i!jHҼ*"+M ~ ʼͲ!f6!h6!"! 6F!f6:h2k!iҠ:i2k:j2h:k!hҶ9 æ:h2j!!6:j2he:! 4"Ͳ*"M ~2!O :! *+"!!6e*!M͛ /$^L:!@OL:! 2͑e:b:! L:h<2hb:! b:hO>!hw:! pX:! …!!6  LÊ!!6ûô:!ʛ͑:! ҩ OҸû:!R†!6G>!!!6 :2.t -? >!!6!6s, !6:xB!6OU2!SB!G6:҃!6:G҃*G& ~2!:G<2G_ Qқ=e  b:!-®! 6:!#¿͇;J:!:!!6Lv:!:Jv: *#"͎:f *g&!lq:l $ !h4:l 1 !h6*lM :hB     !h55!mq:m :hO>H2ny} !m6 !o6:n!oښ *mM !o4‚ !pq:p ڪ >:p :p H:p H!qq*qM͛  ^W :q@2q*qMW   !sp+q*r !up+q *tDM !wp+q*v !zp+q*y2x!|p+q*{2x!~p+q*}2x!p+q*!p+q*!p+q*!p+q*2x!p+q*!6   >>! q* &!p+q*! 6:!B)! >w!"&*o"(R :!C:eR :!DKeX :!K\ͷX :!Lj^ :!Pš͎҇! 6F×͢җ:Ç :!T¨F :!U¾: 2 :!V͎"$DMͩ/ *oDMͩ : 2 :! (::H%^bF : ͎H :!Ay! 6*""&*o"(R͎an͢na! 6R :!F”͢ґ Ä :!J $:2$͢ :=2:<2!*& ~2!ü*""I*M*o/!:":7 e !p+q*DM  =? ) !p+q.*DMF -L *9"`!"b!h6!j6!|6.!=\ -x !e:dʥ *eM \R :xʥ @ *dM \, :x \͕ :x - V :e _ :f w : =e !e:d*eM =e : =e =͕ !]6:x>- !"!76!6!6!66*dM  *dM !6:8!*`*;DM \u 2xʻ>!xҨ- *`*;6:82*`"`:<2w!"`9`h*`*;~2*`#"`"&! 6R*I""ë :!M:H| ! 6>F ͛e: <2 O! Hqy d F : 2! 6*#s#r :!N ͢ *o/ Ҧ Ͷn! 6!"&R! 6o$ Î Ç :!S0 $͢- :2"+s#r!:* *& ~2!:<2 :!W> v :!X³ Z͎\ Ee ð :7/҃ E!76e ͕ :xƒ - ͷ*&"K(Kڰ *KM N͔*K"KҌ :!Z ͎  ͢ : :!  'v!gq:*eM !b+!s{!f!6:!b*b*^DM =ͅ N- *b"b:<2)f!"b!q9bڀ*b*^:w*b#"b!q:6ڶZͅ ʱ- !66*6& :w:6<26!J6*b}:J<2Jm=? :x- : ;*dM .=\ -=ͨ ;: *eM =ͨ .M= -C!q:Y*M !q:a/>z!/H!q*MaҎ:_:!q:ҥ*My:!p+q!'"!6>**ͪ{2**ͪ"*! ͪ":!!!7q:*7M͒:7o$+͛ͪ*$M ~28Om:8 I͇͢u$oqo͛rP! 6!"&*$"(R͎ҔM͢ҡÔ($ҵ! 6R͇vͶ2!*!Mm$"*"M :!w͢:! e2!:! : /HH/Q:! @!!6 R!!6 :!KR$*& :!w:<2dn!:s+q*$";!>6:>/;oH*;#"(";:92=*=& *(M !::=2>/H:=<2=*(#"(æÀ:>*(+"(R:>!66:0O  ú!p+q:/(*DMͩ:  : I N* *DM:aO>!Һ x!: ڦ> ʡ* +" >¡! 6: <2 =O! N͒:  O͒: ! 6:h!o$O* ͸ ! 6 !h6!: 2 3* & 6 : <2 =O! N͒*dM  :sGsu n>!6:<2=O! N͒!">!"͎/Ҵ*+">>!": *#"*""*!".+",*$"**o".!",!36:3{.$:2*o/*!My:<2=O!s Hq**DMͷ! 6: e!"*""?k*&"?*?+M ~2A :hHҏ *&"?(?:A ½8*#" ҽ*?M ~2AO *?"?ҕ!"*"*"^: 2B! 6F:B2 o(>&H6͛9!C6>!Ca R>:C<2C?! 6!"͇͢Ґq"ڊ͛Íq!!6 !!6 !6*!Ma2D*!M͒2!:D/!+w!6e2!͢!Eq!E:!:H:H!Fq*22*,**"0M ~ H3*0"**+"*+">23:2/k!36,*+s#rx:3x*0"*: “**"&*"+"(á*$#"&**#"(*"#""*$#"$*"+""*$+"$*#"!4qM*"*$: *(y"$DM}|C#~ *#"*&DMyxC 1*+":4?w+"$""ͷR: —*$"("҈!"&Ô""&*""&$mڸ*o"(**$"($"O26͛*"M :6w͢:6 *FM8 *FM   Oy2F :FY5>>:!02HO> /!";u*)))*) *H& "PҘ! 6+s#ré! 6"DM!>))덑o|g =±^#V) ^#V|g}o _{ozgi`N#Fogo&og_{_z#W H = LIBX$$$$$$$LIB]>p(>Ww#~)!V}x??2/2&x07>x ?O!_7(?~(_( ~#(#~## ~_(8 xF#8D#+-NORLCEXAFAFRRCRLRRDA'CP/SC7Cg_{_z#W H = LIBX$$$$$$$LIB<&40:=rot(s%)+" "+reg(d%) 8="BITRESSET",(c%64)*3-2,3)+" "+(s%)+","+reg(d%) : ݤz80_DD ݤz80_FD -xy%:num%=1:="DEFB &"+Hex(xy%*&20+&BD,2) '  A$:xy%=(c%&20)&20+1:num%=num%+1 >*c%=Data%?1:d%=c%7:s%=(c%&38)8:A$=("FNz80_"+~(c%&C0)) G4A$,4),"X")+A$,"Y")=0:num%=1:="DEFB &"+Hex(xy%*&20+&BD,2) =A$ >: 6Hݤz80_ED:xy%:num%=1:="DEFB &"+Hex(xy%*&20+&CD,2) 0Rnum%=num%+1:c%=Data%?1:d%=c%7:s%=(c%&38)8 \c%<&10:="DEFW &"+Hex(c%*256+&ED,4)+":\ MOS_"+"QUITCLI BYTEWORDWRCHRDCHFILEARGSBGETBPUTGBPBFINDFF0CFF0DFF0EFF0F",c%*4+1,4) &fc%<&40 c%>&C0:num%=1:="DEFB &ED" 4p(c%&C7)=&42:=alu(3-(s%1)*2)+" HL,"+drg(s%) Iz(c%&CF)=&4B:num%=num%+2:="LD "+drg(s%)+",(&"+Hex(Data%!2,4)+")" F(c%&CF)=&43:num%=num%+2:="LD (&"+Hex(Data%!2,4)+"),"+drg(s%) ((c%&C7)=&40:="IN "+r(s%)+",(C)" %(c%&C7)=&41:="OUT (C),"+r(s%) 0(c%&E7)=&46 s%<>1:="IM "+(s%-1-(s%=0)) '(c%&F7)=&67:="RRDRLD",s%*3-11,3) ((c%&F7)=&46:="RETNRETI",s%*4+1,4) c%=&44:="NEG" P OSFILE=&FFDD:OSBYTE=&FFF4 OSFIND=&FFCE:OSBPUT=&FFD4 newblock=&D000:=newblock ( P=0 1 2P%=newblock 9< (!6 &FFFF)<>newblock [OPT P*3:JP !6:] P%=P%+3 F[OPT P*3 P.cpm_flag:B 0 ZB 0:B 0 d\ Switch flags n.new_load_block xLD DE,(&3ADC):\ Get "LD A,(cpm_flag): 1:JP NZ,&86D LD HL,&3800 LD (load_block),HL INC DE:LD (load_block+2),DE LD A,0:LD (load_block+6),A *LD A,&82: OSBYTE:LD (load_block+4),HL LD HL,load_block:LD A,&FF OSFILE LD H,D:LD L,E:\ H(c%&E7)=&47:="LD "+(65-8*(s%=0)-17*(s%=1))+","+(65-8*(s%=2)-17*(s%=3)) G(c%&E4)=&A0:="LDCPINOT",d%*2+1,2)+(73-5*(s%1))+(32+25*(s%2)) num%=1:="DEFB &ED" e JP new_osc+&11:JP new_osc+&E ] "'"Saving Z80 BASIC base code" , tesL=DE= DEC DE:INC HL .load_loop %INC HL:INC HL:LD A,(HL):LD (DE),A %DEC HL:INC DE:LD A,(HL):LD (DE),A %DEC HL:INC DE:LD A,(HL):LD (DE),A CP &80:JR NC,end_load INC DE:INC HL:INC HL:INC HL ".middle_loop ,LD A,(HL):LD (DE),A 6INC DE:INC HL:CP 13 @JR NZ,middle_loop JJR load_loop T.end_load ^LD H,D:LD L,E hLD (HL),&FF:DEC HL rLD (HL),&FF:DEC HL |LD (HL),0:INC HL JP &883 RET .new_save_block \ HL=filename \ DE= (BC=length) #LD A,(cpm_flag): 2:JP NZ,&3172 LD A,&80: OSFIND CP 0:JR NZ,file_output +RST &38:B 214:M "Can't open file":NOP .file_output LD H,A:LD A,13: OSBPUT .save_loop $INC DE:INC DE:LD A,(DE): OSBPUT CP &80:JR NC,save_end DEC DE:LD A,(DE): OSBPUT DEC DE:LD A,(DE): OSBPUT &INC DE:INC DE:INC DE 0.save_mid_loop :LD A,(DE): OSBPUT $DINC DE:CP 13:JR NZ,save_mid_loop NJR save_loop X.save_end bLD A,0: OSFIND lRET vRET : : : : .load_block W &3800 W &3B00:W &0 W &0:W 0 W &0:W 0 W &0:W 0 ] P%=&869:[JP new_load_block:] P%=&7BB:[ new_save_block:] P%=&F8E4:[LD HL,newblock:]  P%=&5:[JP newblock:] ((22<<FFPPZZddnnxxOSBPUT &INC DE:INC DE:INC DE 0.save_mid_loop :LD A,(DE): OSBPUT $DINC DE:CP 13:JR NZ,save_mid_loop NJR save_loop X.save_end bLD A,0: OSFIND lRET vRET : : : : .load_block W &3800 W &3B00:W &0 W &0:W 0 W &0 > TEST 6?(&81+?&80)=13:A$=$&81,$&81+" "," ",2)+1):?&80=0 ("LINE: '"A$"'" "LINE: '"A$"'" "87 *2 ctrl% 32,data&ݼ>y@kH~&ҺA~ejãUEWWVUгsJ;CM޸a3I: ;<$vtoƥ-ߧNjTwFH 5iYr;󚨸I1ucνT# ;ߑt հy{V>KsR yC^ ׺V@3/f4*kq JT7ֿWfYT\PdMGoEU-ebuFBwPX !x GHO3d"Y {➶d!IRUmw0(u:UEh2unNn{;݌biO_?`}XⓍٿO(+}-$IҀV@XEid`ѲɻH)*nWd<ݛ VIyW8 d)i7 g~| xM> u!KBR۠r B`8B_Q!HJ\ JT<0h,{S5Iے@[fBBCBASIC FILEHAND$TEST BBC:FILE4 BBC9$$$ SUBBUĔBk_#|#bz'9JLs˖$|.LQ6Y&77k`.0jɧ@-@獥<"cb$Cx XӾwo0<(tvX.ݖE]* RTOJ_1Htb%Tλnk!ezx p"iEm1p\ʥ_:U} 66ib1WŹ7dʙ}ШPqCX@F:䃚Ekql^UHQ^,(8Z8ThŒJ[ cD:Tpr?ԟUVMzȯyXoDP W%V{rps յz1|J?%!gCHR,C904ضp 1"d|cEev; EEHb^ŎW=l eڿYbL>y:epz0!a1PshhˀHp AѰcVw K̸̊U$={4hy/瑘cq7J o\%(g_($$ <p{y>?=J`I AD:ᨗ> |.^T@WTːD:`᭘.vT?'\s;BR+< hy=SsbR!.q7C`k R Mm5̅H5(v[QD+ty'B36!хS m wtI|O.7gL%rfɷ-mQnv23T3iD^ɾn~1Ki -~FIA (Y!*,zo*#gQq?Dh=#ڦ`g.FWYj79Ho]5YGBBBsLk %\DBXh1kY82]N;bZ'Mٜ̬ZCC)eJg8WqՖ>%WHh;CnMcְ f6cFN  |h~l96<%!iokWI`D̏cgiO& Nn<)d0|VW^sK_ )|" &De4dG#ix#C0~E-0iݎ JZ4Dp`k1ΐɤ+9 79? A qhk* ()@+m 7otFґ,Pa=xjٻnB=k\LuG>- 9`}d^K T;wRqP,N{ysaD$!_xv)=`%]B{/{dsO )oWl`AKuŅ- ap&߾!$3et@C0ܐ/񯴟i/!΄) Lv0+|db\XqZKmqdeQ2l `j~WL?-(T)`m<"ܳ\?yӹ??EEwPw%F+WE A$U<߹ݦXt'%)_aM+[I>A`[)&~| k}L&?B@䭛 m%|?hkB<Jq<:̯P¢PJp>>#H={cCpҀQ3- 5XSنj׻o/[2eEpK8.Ѣ:rGʺ4p$m_"dyLSIN'UQ|:м6m.@yiyzh)@tw)xfSi9IwI+6E:Wc[ԷrS9nVz8Y j`^I3]M,j}~E$'7 ˹J/BGDXe+}|Ms]Xܧex(:mzZOg0\OEM }`o03aO0w#qSe߅ևme_T pRf3_%v6FqVEnTm pZ5ymc"ڊ^ƛup@1Py[YL0Z_Zw16^8 -Ég9^4 z\zMm YsueOef~o{e2$M^C?X: P¯z-֊]\Q(9WiCoU"MFqk")NYICAo-G`UlD;/ׁSm;ڸg^Rf,1_ԧ1-J8KhNe܍v_(m!dPmaP8Dۆ.tV'|_ ōv bŗsKC䔏~fWHD[w&H+*{+LfD-^a)xxkԀN#\ACG(f;.oe|D.JlxS/?gYI6478lN)%lD #&w&s`_!='aZ@4uR"*V,ȭ'x~!xFxL[2aEƭ~A *ļ6zHU5@/oF f[5iܢ'5m|~K%O(k3/ PbW 2B6B٭uJtxc'y{twOcx2˱ @c@/fbah?&^X2i Qr!FAEU|Z7I (%^Ƶ5}(O(эM$t mعFoes ıg8jB޳ɘC)wr(Á%`S)UZxr3IIWK(^wy$wuSD40BB,Ƃmv.0xT^@t,.u.KAʫފ#GmhMU/@{;J>moeᅭMHm&6.n#|ˤ`RGk^6C@ ʍCqhVǐ1ĬMӽ'nݍ:6NvL)LDzX@*=^bΤs6zza0a 0Ij,_xmSqml؉'2t+H6*Ь I 3C1 ƞb|+mi-tS|<^z*Lx弨>9` M!05HI^EKRaV>]LħQ- Ww C!Ԅ_68B4A #HZM\5QZ $`}A?17Nx hJ'LŅwe9 YZirB?fhp7ŭ8!Ud9h0"raIZpYyb%Wy,_͙x80,U&@un*5EkFvbXyHMC. U#?qzNU19 䉄wQK &wrt- IҦX%^=%BUͯΞ}u6N?;88) p^#^W1`;-sz<:(el'M[!5j: %/|Y{ĥΛJLO /yXlPѶoceMp87J# %z1rb0 }{L~i\ m%@Z'$#G5Ae?S^H ,uP-E>h]})rq.E` ƌK XݍS'fq`F;ky[!0י OJ }F)ͮ\Z ɞoDe^Fb`AQOt<#@Z6@\zNcrjAQv!T(pC#fC@?>@;\p"+۟/Z%S&F]wzZl:K]~ }=+MzZU5AUI "ΙJ@kb˜bOn~+:I<ᛉkׇx*?)>"cY~߁D)[=c*\^ͼ*ΡlE3}TVC\jo-{Bσ֬>5eQfX^C&&.3Ʃ@m%zt;N2\nf>#Dd MbI qϑ`DFױ 6&hntÀ[rϝ~I1&e!ՔΥ쎓+\*'ͥLrҳw&-ʗuFxS~Zin* n&!R&6Hv"vQd% ,jAmy"d%DYnAӔlE|4@rA<$|Ã!e2Hח=Ic&a̪֘AKU$+U QOB׌M ֒E%Ÿ8~&b S\` U.9 "GԩjH<O,EH9a"!ӜH0C'X ` wydg4FuH/><򌨇 m? ʗUbH>C{ 1I&չ p1e%] Jm.QH>T~"O#MᱰsObЦ90t}f !FSE3;J̐΋2MU(d?ћ)=Iyb+{vN/7D&K LNE) d"7➆ ѫ @2p] ՉoXeO[&!Mx,XJcKM㘏~OT[tBL·+ fiSE>b!'4v1"+bۃ@GzmO6T@$yyGJҊn*0gBY ^B 3cCTFO5zťeT l^6#!ӓT]JkS} oB6øÝtw!y|h[XHz+>䈖2J\(m2(~wcL[hzdW0`ĉ@Sb{6~ʚ.+ّ?Ҏ- &ƺ^\u!Nm|,Rǜ&Zr;C'Pi2R'oR6FʤF2uٗ^,7+H 5FVo˚ ܃V xQ&cJPn'!K"3]\r|,5?uEnZkWph#_ok'i1)osZ~r] aAdHJcD.`J5&$#EvL!E:5\xl#ogOr WA|YXF䑸yLHNl]()%9P6kS\T(>4wFw$&z)@"j.;{βF|rԸoэ,@<=CQe3yMWPO#|"P£csmCf0l+PUU$hA8`h1؇`1 (Y-Pnkq?NmrϞQ6ƣvF޳m  NwÏ1Qs9:r 7 ml@`2]YB/.F)rA={$$hrrÌ 12兇0XUDMޒWZHtW(HD;m-f |#cMe{?IE,fƒoK{"#E:kj&!QVL8,0xJ JpM,`pWdZN>>",UQ3+3SI8MZ|Y+H0r*l Q̬zͼi'QEkBukh0b) w b!N)}-zUɉHd*rFE݀Yt)d Ÿ"-pm2- ZCPRDEMO.COM=!!$Xxx18E WmK€P1?5LFꦖ>: (ޝ 918EH© bOc٨D&Ը͑nNeKl\BfP^\p,M~K؊vN +201ywT󄠝cikex,vQ;~Bb. ?t5BOcv Hx~v$MJI337^ye<3ꮏ#u  ڟ2^KȆ}qq *z Х~g^5۬_%[Rqcp?e(t8xCF$Y)K:t TW}Չ=Gj^} .r  cAY5KbUP:} m;-eY_V)'v mM^2>V<Ԙ>W3` Zȱ0m*vTЙҋF؋+pSisw~ȇO(t8E jY$oē q̘cWGAt˪# ZptcnِGo" ? ?c4: Changes to drive C/user 4 ; A>c4: Runs found on drive C/user 4 ; A>dir c4: Gives directory of drive C/user 4 ; A>ren =c4: ; Renames file found on drive C/user 4 ; Both the drive and user number are optional; 15: is a valid designation. ; S1 in the FCB is used to store the user number. If S1 contains a valid ; user number, bit 7 will be set. If no user number is specified, S1 will ; contain 0. ; ; Added POKE and changed SCL to a toggle, 12 August 1992. ; ; Added PEEK 30 August 1993. ; ;******** Structur this project consists of the following: ; RLC - Richard Conn ; RGF - Ron Fowler ; KBP - Keith Peterson ; FJW - Frank Wancho ; The following individual also provided a contribution: ; SBB - Steve Bogolub ; ; (Note by BB: SBB's and R Fisher's changes came too late in the ; history of CCPZ to be included in the first release of ZCPR) ; ; Extensive modifications to add ERAQ, DIR for all usrnum, ; LIST x.x P, and fix TYPE when FF encountered was done by Don ; Kirkpatrick, 20 September 1986. e Notes ******** ; ; This CPR is divided into a number of major sections. The following ; is an outline of these sections and the names of the major routines ; located therein. ; ; Section Function/Routines ; ------- ----------------- ; ; -- Opening Comments, Equates, and Macro Definitions ; ; 0 JUMP Table into CPR ; ; 1 Buffers ; ; 2 CPR Starting Modules ; CPR1 CPR RESTRT ; ; 3 Utilities ; CRLF PRINTC PRINT PRINTS BELL ; CONOUT BREAK CHKETX ABORT READF ; READT - TRUE to build at intermediate address to debug via debugger. ; ; COMLD - TRUE to test and execute as a .com file. ; ; REL - TRUE if integration is to be done via MOVCPM. ; ; BASE - Base Address of user's CP/M system (normally 0 for DR version). ; This equate eases modification by non-standard CP/M (eg. H89). ; ; P2DOS - Address of BDOS/P2DOS. ; TEST EQU FALSE ;SET TO LOAD/RUN AT 8000H FOR DEBUG COMLD EQU FALSE ;SET TO LOAD AND EXECUTE AS A .COM FILE REL EQU FALSE ;SET T WRITE DEFDMA DMASET SEARF ; SEARDE SEARN OPENF OPEN CLOSE ; CREATE BDOSFN SUBKIL DELETE TLOGIN ; DLOGIN LOGIN NEWUSR RSTUSR SETUSR ; BDOSEA BDOSJP BDOSBC BDOSDE ; ; 4 CPR Utilities ; PROMPT REDBUF CNVBUF UCASE SDELM ; ADVAN SBLANK ADDAH NUMBER A2NUM ; HEXNUM USRNUM ERROR DIRPTR ULOGIN ; SCANER SCANT SCANF CMDSER SETUDB ; ; 5 CPR-Resident Commands and Functions ; 5A DIR DIRPR PRFN ; 5B ERA ; 5C ERAQ PRNNF ; 5D SAK REPLY ; 5E BELL ; 5F O TRUE FOR MOVCPM INTEGRATION ;LEAVE ALL FALSE FOR SYSGEN IMAGE ; BASE EQU 0 ;BASE OF CP/M SYSTEM P2DOS EQU 0E400H ;BASE OF BDOS/P2DOS ZCPRSZ EQU 00800H ;SIZE OF ZCPR P2DOSSZ EQU 00E00H ;SIZE OF P2DOS BIOS EQU P2DOS+P2DOSSZ ;BASE OF BIOS CPRLOC DEFL P2DOS-ZCPRSZ ;STANDARD EXECUTION ADDRESS ; IF REL CPRLOC DEFL 0 ;MOVCPM IMAGE ENDIF ; IF TEST CPRLOC DEFL 8000H ELSE BOOT EQU BIOS ;BIOS COLD BOOT ENTRY LISTST EQU BIOS+002DH ;ENTRY POINT FOR LIST STATUS ENDIF ; ; The foll LIST ; 5G TYPE PAGER ; 5H EJECT ; 5I SAVE ; 5J REN ; 5K USER SUSER ; 5L DFU ; 5M SCL ; 5N PEEK ; 5O POKE ; 5P JUMP ; 5Q COM ; 5R GO CLLPRG ERRLOG ERRJMP ; 5S GET MEMLD PRNLE ; BIOS BOOT ; ; FALSE EQU 0 TRUE EQU NOT FALSE ; ; ; CUSTOMIZATION EQUATES ; ; The following equates may be used to customize this CPR for the user's ; system and integration technique. The following constants are provided: ; ; TESowing is presented as an option, but is not normally user-customize- ; able. A basic design choice had to be made in the design of ZCPR concerning ; the execution of SUBMIT files. The original CCP had a problem in this sense ; in that it ALWAYS looked for the SUBMIT file from drive A: and the SUBMIT ; program itself (SUBMIT.COM) would place the $$$.SUB file on the currently ; default drive. When the user was logged into B: and he issued a SUBMIT ; command, the $$$.SUB was placed on B: and did not execspecific drive, and A: is the choice for said drive. ; With this facility engaged as such, Indirect Command Files like: ; ; DIR ; B: ; DIR ; ; can be executed, even though the currently default drive is changed ; during execution. If the $$$.SUB file was present on the currently ; default drive, the above series of commands would not work since the ; ZCPR would be looking for $$$.SUB on the default drive, and switching ; default drives without moving the $$$.SUB file as well would cause ; proute. The CPR looked ; for $$$.SUB on A: and never found it. ; ; After much debate it was decided to have ZCPR perform the same type of ; function as CCP (look for the $$$.SUB file on A:), but the problem with ; SUBMIT.COM still exists. Hence, RGF designed SuperSUB and RLC took his ; SuperSUB and designed SUB from it; both programs are set up to allow the ; selection at assembly time of creating the $$$.SUB on the default drive ; or on drive A:. ; ; A final definition of the Indirect Command Filecessing to abort. ; ; Note that the same problem can occur if the user number of the ; $$$.SUB file is not predefined. It is assumed that the $$$.SUB file ; is located on user 0 of the specified drive. ; ; The trick of using the $ flag returned by DISK RESET is used to ; to speed the search for a $*.* file on drive A. This trick will not ; work if the $$$.SUB file is located on another drive. ; ; ; Under the ZCPR, three command levels exist: ; ; (1) that command issued by the user from his c ($$$.SUB or SUBMIT ; File) is presented as follows: ; ; "An Indirect Command File is one which contains ; a series of commands exactly as they would be ; entered from a CP/M Console. The SUBMIT Command ; (or SUB Command) reads this file and transforms ; it for processing by the ZCPR (the $$$.SUB File). ; ZCPR will then execute the commands indicated ; EXACTLY as if they were typed at the Console." ; ; Hence, to permit this to happen, the $$$.SUB file must always ; be present on a onsole at the '>' prompt ; (2) that command issued by a $$$.SUB file at the '$' prompt ; (3) that command issued by a user program by placing the command into ; CIBUFF and setting the character count in CBUFF ; ; To use CIBUFF, the user program stores the command line and character ; count; ZCPR will initialize the pointers properly, store the ending zero, ; and capitalize the command line for processing. Once the command line is ; properly stored, the user executes the command line by reenteriOMPT INDICATING SUBMIT COMMAND COMCHR EQU ';' ;BEGIN COMMENT CHARACTER CMDCHR EQU ';' ;BEGIN NEXT COMMAND CHARACTER NUMBASE EQU 'H' ;CHARACTER USED TO SPECIFY HEXIDECIMAL BASE RECFLG EQU 'R' ;CHARACTER FOR SAVE COMMAND TO SAVE RECORDS SUPRES EQU TRUE ;TRUE TO SUPPRESS USER NUMBER FOR USER 0 MULTPL EQU TRUE ;TRUE TO ALLOW MULTIPLE COMMANDS ON ONE LINE REBOOT EQU TRUE ;TRUE TO INCLUDE BOOT COMMAND ; IF TEST CPRMPT EQU '<' ;CPR PROMPT INDICATING TEST MODE ELSE CPRMPT EQU '>' ;CPR PROMPTng ZCPR ; through CPRLOC [NOTE: The C register MUST contain a valid User/Disk Flag ; (see location 4) at this time.] ; ; ; Directory customization equates ; TWOCOL EQU FALSE ;TRUE FOR TWO-COLUMN DIRECTORY DISPLAY WIDE EQU TRUE ;TRUE IF WIDE DIRECTORY DISPLAY FENCE EQU '|' ;CHARACTER BETWEEN FILES USRDLM EQU ':' ;CHARACTER BETWEEN USER NUMBER AND FILE USRFLG EQU 'A' ;LIST $SYS AND $DIR FOR ALL USER NUMBERS SYSFLG EQU 'B' ;LIST $SYS AND $DIR SOFLG EQU 'S' ;LIST $SYS ONLY ; ; List and Typ INDICATING USER COMMAND ENDIF ; ; END OF CUSTOMIZATION SECTION ; ETX EQU 03H BELL EQU 07H BS EQU 08H TAB EQU 09H LF EQU 0AH FF EQU 0CH CR EQU 0DH ; WBOOT EQU BASE+0000H ;CP/M WARM BOOT ADDRESS UDFLAG EQU BASE+0004H ;USER NUMBER IN HIGH NIBBLE, DISK IN LOW BDOS EQU BASE+0005H ;BDOS FUNCTION CALL ENTRY POINT TFCB EQU BASE+005CH ;DEFAULT FCB BUFFER TBUFF EQU BASE+0080H ;DEFAULT DISK I/O BUFFER TPA EQU BASE+0100H ;BASE OF TPA ; ; ;**** Section 0 **** ; .Z80 ASEG ORG 100H ; ; LOAe command customization equates ; NLINES EQU 20 ;NUMBER OF LINES ON CRT PAGE NLINEP EQU 60 ;NUMBER OF LINES ON LIST DEVICE FFKILL EQU TRUE ;TRUE SUPPRESSES FF UNTIL FIRST CHARACTER PGDFLG EQU 'P' ;TYPE AND LIST COMMAND DEFAULT TOGGLE NOSTAT EQU FALSE ;SET TO TRUE IF BIOS LISTST NOT IMPLEMENTED ; ; Other customization equates ; BUFLEN EQU 80 ;SIZE OF COMMAND INPUT BUFFER MAXUSR EQU 15 ;MAXIMUM USER NUMBER ACCESSIBLE DEFUSR EQU 0 ;DEFAULT USER NUMBER FOR COM FILES SPRMPT EQU '$' ;CPR PRDER FOR TEST PURPOSES ; ALLOWS ONE TO EXECUTE ZCPR AS A .COM FILE ; IF COMLD OR TEST LD HL,BGNXFR LD DE,CPRLOC LD BC,ENDLD-CPRLOC LDIR LD BC,(UDFLAG) JP CPRLOC BGNXFR EQU $ ENDIF ; .PHASE CPRLOC ; ; ENTRY POINTS INTO ZCPR ; ; If the ZCPR is entered at location CPRLOC (at the JUMP to CPR), then ; the default command in CIBUFF will be processed. If the ZCPR is entered ; at location CPRLOC+3 (at the JUMP to CPR1), then the default command in ; CIBUFF will NOT be processed. ;PUT COMMAND LINE AND DEFAULT COMMAND ; ; The command line to be executed is stored here. This command line ; is generated in one of three ways: ; ; (1) by the user entering it through the BDOS READLN function at ; the du> prompt [user input from keyboard]. ; (2) by the SUBMIT File Facility placing it there from a $$$.SUB ; file. ; (3) by an external program or user placing the required command ; into this buffer. ; ; In all cases, the command line is placed into the buffer starti ; NOTE: Entry into ZCPR in this way is permitted under ZCPR Version 4.0, ; but in order for this to work, CIBUFF and CBUFF MUST be initialized properly ; AND the C register MUST contain a valid User/Disk Flag (see Location 4: the ; most significant nibble contains the User Number and the least significant ; nibble contains the Disk Number.) ; ; Some user programs (such as SYNONYM3) attempt to use the default ; command facility. Under the original CPR, it was necessary to initialize ; a pointng at ; CIBUFF. This line contains the last character but NOT the Carriage ; Return, and the count is of all characters in the command line up to and ; including the last character. This count is placed into location CBUFF ; (immediately before the command line at CIBUFF.) If ZCPR is entered via ; CPRLOC, the command line is then parsed, interpreted, and the indicated ; command is executed. ZCPR places the terminating zero after the command ; and CIBPTR is properly initialized. ; ; WARNING: The cer located at the end of the command buffer to point to the first ; byte in the command buffer. Under Version 4.x of ZCPR, this is no longer ; the case. This pointer, CIBPTR (Command Input Buffer PoinTeR), has been ; moved and the former location is now reserved for the stack. ZCPR ; Version 4.x automatically initializes CIBPTR in all cases. ; ENTRY: JP CPR ; Process potential default command JP CPR1 ; Do NOT process potential default command ; ;**** Section 1 **** ; ; BUFFERS ET AL ; ; INommand line must NOT exceed BUFLEN characters in length. ; For user programs which load this command, the value of BUFLEN can be ; obtained by examining the byte at CPRLOC+6. ; ; It is now possible to place multiple commands on one line. Each command ; is separated from its neighbor by a ";". This feature only works for ZCPR ; commands and programs that return to ZCPR via a RET instruction. Any ; warm boot reloads ZCPR and destroys the contents of the command buffer. ; The multiple command feature mAP FCBCR: DEFS 1 ;CURRENT RECORD NUMBER ; ; Type and List Variables ; CHRCNT: DEFS 1 ;CHARACTER COUNT FOR TYPE AND LIST LNCNT: DEFS 1 ;LINE COUNT FOR TYPE AND LIST TYPLST: DEFS 1 ;FLAG FOR TYPE OR LIST TABCNT: DEFS 1 ;TAB COUNT FOR TYPE AND LIST SYSTST: DEFB 0 ;LIST SYSTEM FILES IN DIRECTORY FLAG ; ; General Variables ; CIBPTR: DEFW CIBUFF ;POINTER TO COMMAND INPUT BUFFER CIPTR: DEFW CIBUFF ;POINTER TO CURRENT CMD FOR ERROR REPORTING TMPUSR: DEFB 0 ;TEMPORARY USER NUMBER TDRIVE: DEFay be turned off with the SCL command. ; MBUFF: DEFB BUFLEN ;MAXIMUM BUFFER LENGTH CBUFF: DEFB 0 ;NUMBER OF CHARACTERS IN COMMAND LINE CIBUFF: DEFB ' ' ;DEFAULT (COLD BOOT) COMMAND DEFB 0 ;COMMAND STRING TERMINATOR DEFB ' ZCPR-D&J of 5 March 1994 ' DEFB 0 ;TERMINATOR FOR DUMP IDENTIFICATION DEFS BUFLEN-($-CIBUFF)+1 DEFW 0 ;SENTINEL FOR STACK END DEFS 24 ;STACK AREA STACK EQU $ ;TOP OF STACK ; ; SUBMIT FILE CONTROL BLOCK ; SUBDN: DEFB 1 ;DISK DRIVE (A: CONTAINS $$$.B 0 ;DEFAULT DRIVE DFUSR: DEFB DEFUSR ;DEFAULT USER LDADR: DEFW TPA ;MEMORY LOAD ADDRESS ; ; CPR BUILT-IN COMMAND TABLE ; EACH ENTRY IS COMPOSED OF THE BIT 7 TERMINATED COMMAND AND 2-BYTE ADDRESS ; CMDTBL: DC 'DIR' DEFW DIR DC 'LIST' DEFW LIST DC 'TYPE' DEFW TYPE DC 'USER' DEFW USER DC 'DFU' DEFW DFU DC 'PAGE' DEFW EJECT DC 'BELL' DEFW RING DC 'SAK' DEFW SAK DC 'GO' DEFW GO DC 'ERA' DEFW ERA DC 'ERAQ' DEFW ERAQ DC 'SAVE' DEFW SAVE DC 'REN' DEFWSUB) SUBFN: DEFB '$$$ ' ;FILE NAME SUBFT: DEFB 'SUB' ;FILE TYPE SUBEX: DEFB 0 ;EXTENT NUMBER SUBS1 EQU SUBDN+13 ;S1 SUBS2 EQU SUBDN+14 ;S2 SUBRC EQU SUBDN+15 ;RECORD COUNT SUBDM EQU SUBDN+16 ;DISK GROUP MAP SUBCR EQU SUBDN+32 ;CURRENT RECORD NUMBER ; ; COMMAND FILE CONTROL BLOCK ; FCBDN: DEFS 1 ;DISK DRIVE FCBFN: DEFS 8 ;FILE NAME FCBFT: DEFS 3 ;FILE TYPE FCBEX: DEFS 1 ;EXTENT NUMBER FCBS1: DEFS 1 ;S1 FCBS2: DEFS 1 ;S2 FCBRC: DEFS 1 ;RECORD COUNT FCBDM: DEFS 16 ;DISK GROUP M REN DC 'GET' DEFW GET DC 'JUMP' DEFW JUMP DC 'PEEK' DEFW PEEK DC 'POKE' DEFW POKE NCMNDS DEFL 17 ;NUMBER OF COMMANDS ; IF MULTPL DC 'SCL' DEFW SINGLE NCMNDS DEFL NCMNDS+1 ENDIF ; IF REBOOT DC 'BOOT' DEFW BOOT NCMNDS DEFL NCMNDS+1 ENDIF ; ; ;**** Section 2 **** ; CPR STARTING POINTS ; ; START CPR AND DON'T PROCESS DEFAULT COMMAND STORED ; CPR1: XOR A ;SET NO DEFAULT COMMAND LD (CBUFF),A ; ; START CPR AND POSSIBLY PROCESS DEFAULT COMMAND ; CPR: LD SP, ; CALL ADVAN ;GET ANY CHARACTER JR Z,RESTRT ;NONE, END OF LINE LD (CIPTR),DE ;UPDATE START OF LINE IN CASE ERROR INC DE ;NOT END OF LINE, MUST BE DELIMITER LD (CIBPTR),DE ;SAVE POINTER ; IF MULTPL LD HL,NEWCMD ;COMMAND? CP (HL) RS4: JP NZ,ERROR ;NO CALL ADVAN ;STEP OVER DELIMITER JR RS3 ELSE RS4: JP ERROR ENDIF ; ; ;**** Section 3 **** ; I/O UTILITIES ; ; OUTPUT ; CRLF: CALL PRINT ;PRINT STRING DEFB CR,LF+80H RET ; ; PRINT STRING POINTED TO BY RET STACK ;MAKE SURE WE HAVE A VALID STACK LD A,C ;C=USER/DISK NUMBER (SEE LOC 4) RRA ;EXTRACT USER NUMBER RRA RRA RRA AND 0FH LD (TMPUSR),A ;SET USER NUMBER LD A,C ;GET DISK NUMBER (SEE LOC 4) AND 0FH ;EXTRACT DEFAULT DISK DRIVE LD (TDRIVE),A ;SAVE DEFAULT DRIVE LD C,0DH ;RESET DISK SYSTEM CALL BDOS LD (SUBFLG),A ;SAVE SUBMIT FLAG CLUE DEFB 0F6H ;SET NZ FLAG (OR A,n) ; ; PROMPT USER AND PROCESS INPUT COMMAND ; RESTRT: XOR A ;SET ZERO FLAG LD SP,STACK ;RESET STACK ADR; START WITH ; PRINTC: CALL CRLF ;NEW LINE ; ; PRINT STRING POINTED TO BY RET ADR ; PRINT: EX (SP),HL ;GET POINTER TO STRING CALL PRINTS EX (SP),HL ;RESTORE HL AND RETURN ADDRESS RET ; ; PRINT STRING POINTED TO BY HL ; PRINT1: CALL CONOUT ;PRINT CHARACTER PRINTS: LD A,(HL) ;GET NEXT BYTE INC HL ;POINT TO NEXT BYTE AND A ;TEST FOR 0 OR BIT 7 SET RET Z ;DONE JP P,PRINT1 ;NOT LAST CHARACTER ; ; OUTPUT CHARACTER IN A REG ; CONOUT: PUSH BC PUSH DE LD C ; ; PROCESS INPUT LINE ; CALL REDBUF ;CAPITALIZE, NULL TERMINATE, SKIP SPACES RS3: CP COMCHR ;COMMENT? JR Z,RESTRT ;YES, SKIP REST OF LINE CALL SCANER ;PARSE COMMAND NAME FROM COMMAND LINE JR NZ,RS4 ;ERROR IF NAME CONTAINS A "?" CALL DEFDMA ;SET TBUFF TO DMA ADDRESS CALL DLOGIN ;ASSURE PROPER DRIVE CALL RSTUSR ;ASSURE PROPER USER NUMBER CALL SETUDB ;SET UD BYTE TO MATCH USER/DRIVE CALL CMDSER ;SCAN FOR CPR-RESIDENT COMMAND ; ; ENTRY POINT FOR CONTINUED SCAN OF COMMAND LINE,02H RES 7,A ;STRIP MSB IN CASE SET FOR EOS LD E,A JR BDOSDE ; ; GET CHARACTER FROM CONSOLE AND CHECK FOR ^C ; BREAK: PUSH BC LD C,0BH ;CONSOLE STATUS CHECK CALL BDOSJP LD C,01H ;GET CHARACTER FROM CON: WITH ECHO CALL NZ,BDOSJP ;GET CHARACTER POP BC RET Z ;NO CHARACTER CHKETX: CP ETX ;^C? RET NZ ;NO ABORT: CALL SUBKIL ;KILL ANY SUBMIT JR RESTRT ;AND RESTART ; ; BDOS FUNCTIONS ; READF: LD DE,FCBDN ;FALL THRU TO READ READ: LD C,14H DEFB 3AH ;SKIP NEXT TWODOSEA ;SAVE SOME CODE SPACE NEWUSR: LD (TMPUSR),A ;SET NEW USER NUMBER RSTUSR: LD A,(TMPUSR) ;RESET TEMPORARY USER SETUSR: LD C,20H ;GET/SET USER NUMBER (GET IF E=FFH) BDOSEA: LD E,A ;STUFF PARAMETER INTO REG E BDOSJP: PUSH BC BDOSBC: PUSH DE ; zcpr does not use any BDOS calls that BDOSDE: PUSH HL ; return a value in HL. Those HL calls CALL BDOS ; are: POP HL ; get active drive - #24 POP DE ; get allocation vector - #27 POP BC ; get read-only map - #29 AND A ; BYTES WRITE: LD C,15H ;FALL THRU TO BDOS CALL JR BDOSJP DEFDMA: LD DE,TBUFF ;TBUFF = DEFAULT ADDRESS DMASET: LD C,1AH ;SET DMA ADDRESS JR BDOSJP SEARF: LD DE,FCBDN ;SPECIFY FCB SEARDE: LD C,11H ;SEARCH FOR FILE DEFB 3AH ;SKIP NEXT TWO BYTES SEARN: LD C,12H ;SEARN IGNORES DE AND USES THE PREVIOUS JR BDOSFN ;VALUE FROM THE LAST BDOS CALL OPENF: XOR A LD (FCBCR),A LD DE,FCBDN ;FALL THRU TO OPEN OPEN: LD C,0FH ;OPEN FILE DEFB 3AH ;SKIP NEXT TWO BYTES CLOSE: LD get disk parameters - #31 RET ; ; ;**** Section 4 **** ; CPR UTILITIES ; ; PRINT PROMPT (DU>) ; PROMPT: CALL CRLF ;PRINT PROMPT LD A,(TDRIVE) ;CURRENT DRIVE IS PART OF PROMPT ADD A,'A' ;CONVERT TO ASCII A-P CALL CONOUT LD A,(TMPUSR) ;GET USER NUMBER ; IF SUPRES ;IF SUPPRESSING USER # REPORT FOR USER 0 AND A JR Z,PRPT1 ;ZERO, SUPRESS ENDIF ; PRUSRN: ADD A,0 ;CONVERT HEX TO BCD DAA PUSH AF ;SAVE UNITS DIGIT AND 0F0H LD A,'1' CALL NZ,CONOUT ;PRINT IF OVER 10 C,10H ;CLOSE FILE DEFB 3AH ;SKIP NEXT TWO BYTES CREATE: LD C,16H ;CREATE FILE BDOSFN: CALL BDOSJP INC A ;SET ERROR RETURN FLAG RET SUBKIL: LD HL,SUBFLG ;ABORT SUBMIT FILE LD A,(HL) ;SUB FILE IN EXECUTION? AND A RET Z ;NO LD (HL),0 ;KILL SUB FILE EXECUTION FLAG LD DE,SUBDN ;DELETE $$$.SUB DELETE: LD C,13H ;DELETE FILE JR BDOSJP ;SAVE MORE SPACE TLOGIN: LD (TDRIVE),A ;SAVE NEW DEFAULT DRIVE DLOGIN: LD A,(TDRIVE) ;LOG IN DEFAULT DRIVE LD C,0EH ;SELECT DISK JR B POP AF OR '0' ;OUTPUT 1'S DIGIT (CONVERT TO ASCII) CALL CONOUT PRPT1: JP PRINT ;GO PRINT PROMPT CHARACTER ; ; INPUT NEXT COMMAND TO CPR ; ; This routine determines if a SUBMIT file is being processed ; and extracts the command line from it if so or from the user's console. ; This routine also invokes the DU> prompt. ; REDBUF: JR NZ,CNVBUF ;PROCESS DEFAULT COMMAND IF ANY RD0: CALL DEFDMA ;SELECT TBUFF FOR READ XOR A ;SELECT USER 0 FOR SUBMIT SEARCH CALL SETUSR LD DE,SUBDN ;OPEASE $$$.SUB RB2: CALL PROMPT ;PRINT PROMPT DEFB CPRMPT+80H LD C,0AH ;READ COMMAND LINE FROM USER LD DE,MBUFF CALL BDOS ; ; CAPITALIZE STRING (ENDING IN 0) IN CBUFF AND SET POINTER FOR PARSING ; CNVBUF: LD HL,CBUFF ;POINT TO USER'S COMMAND BUFFER LD A,(HL) ;ANY CHARACTERS IN BUFFER? AND A JR Z,RD0 ;NO, FILL BUFFER INC HL LD (CIBPTR),HL ;INITIALIZE COMMAND LINE POINTER LD B,A ;INITIALIZE CHARACTER COUNTER CB1: LD A,(HL) ;CAPITALIZE COMMAND CHARACTER CALL UCASE LD (HLN $$$.SUB SUBFLG EQU $+1 ;IN LINE SUBMIT FLAG LD A,0 ;SUBMIT IN PROGRESS? AND A CALL NZ,OPEN ;CALL OPEN IF SUBMIT IN PROGRESS JR Z,RB2 ;NONE FOUND SO GET COMMAND LINE LD A,(SUBRC) ;GET VALUE OF LAST RECORD IN FILE DEC A ;POINT TO NEXT TO LAST RECORD LD (SUBCR),A ;SAVE NEW VALUE OF LAST RECORD IN $$$.SUB CALL READ ;DE=SUBDN JR NZ,RB1 ;ABORT $$$.SUB IF ERROR IN READING LAST REC LD HL,SUBS2 ;POINT TO S2 OF $$$.SUB FCB LD (HL),A ;SET S2 TO ZERO INC HL ;POINT TO RECORD COUNT D),A INC HL ;POINT TO NEXT CHARACTER DJNZ CB1 ;CONTINUE TO END OF COMMAND LINE LD (HL),B ;STORE ENDING ; ; ADVANCE INPUT POINTER TO FIRST NON-BLANK AND FALL THROUGH TO SBLANK ; ADVAN: LD DE,(CIBPTR) ; ; SKIP STRING POINTED TO BY DE (STRING ENDS IN 0) UNTIL END OF STRING ; OR NON-BLANK ENCOUNTERED (BEGINNING OF TOKEN) ; SBLANK: LD A,(DE) OR A RET Z CP ' ' RET NZ INC DE JR SBLANK ; ; CONVERT CHARACTER IN A TO UPPER CASE ; UCASE: CP 61H ;LOWER-CASE A RET C CEC (HL) ;DECREMENT RECORD COUNT OF $$$.SUB PUSH AF ;SAVE ZERO FLAG CALL Z,SUBKIL ;KILL SUBMIT IF ZERO RECORDS LEFT POP AF ;ELSE CALL NZ,CLOSE ;JUST CLOSE FILE CALL PROMPT ;PRINT SUBMIT PROMPT DEFB SPRMPT+80H LD HL,TBUFF+1 ;PRINT COMMAND LINE FROM $$$.SUB CALL PRINTS LD HL,TBUFF ;MOVE COMMAND LINE TO COMMAND BUFFER LD DE,CBUFF LD BC,BUFLEN LDIR CALL BREAK ;CHECK FOR ABORT (ANY CHARACTER) JR Z,CNVBUF ;NONE ; ; INPUT COMMAND LINE FROM USER CONSOLE ; RB1: CALL SUBKIL ;ERP 7BH ;GREATER THAN LOWER-CASE Z? RET NC AND 5FH ;CAPITALIZE RET ; ; CHECK TO SEE IF DE POINTS TO DELIMITER; IF SO, RET W/ZERO FLAG SET ; SDELM: LD A,(DE) OR A ;0=DELIMITER RET Z CP ' ' ;ERROR IF < JP C,ERROR RET Z ; =DELIMITER CP '.' ;"." =DELIMITER RET Z CP '[' ;"[" =DELIMITER RET Z CP ']' ;"]" =DELIMITER RET Z CP '>' ;">" =DELIMITER BUT GREATER NOT RET NC CP ':' ;":" ";" "<" "=" =DELIMITERS RET C ;NO DELIMITER FOUND CP A ;SET ZERO FLAG R OVERFLOW ; BASE 10 ASSUMED - MAXIMUM VALUE IS 255 ; A2NUM: LD A,(DE) ;GET DIGIT SUB '0' ;CONVERT TO BINARY (ASCII 0-9 TO BINARY) CP 10 ;ERROR IF >= 10 CCF ;FLIP CARRY RET C LD C,A ;DIGIT IN C LD A,L ;NEW VALUE = OLD VALUE * 10 RLCA ;*2 RET C ;ERROR RLCA ;*4 RET C ;ERROR ADD A,L ;*5 RET C ;ERROR RLCA ;*10 RET C ;ERROR ADD A,C ;NEW VALUE = OLD VALUE * 10 + DIGIT RET C ;DON'T INC DE IF ERROR LD L,A ;SET NEW VALUE INC DE ;GOOD DIGIT RET ; ; RET ; ; ADD A TO HL (HL=HL+A) ; ADDAH: ADD A,L LD L,A RET NC INC H RET ; ; EXTRACT DECIMAL NUMBER FROM COMMAND LINE ; RETURN WITH 8-BIT VALUE IN REG A AND 16-BIT VALUE IN HL ; ALL REGISTERS MAY BE AFFECTED ; NUMBER: CALL SCANER ;PARSE NUMBER AND PLACE IN FCBFN LD HL,FCBFN+10 ;POINT TO END OF TOKEN FOR CONVERSION LD B,11 ;11 CHARACTERS MAX ; ; CHECK FOR SUFFIX FOR HEXADECIMAL NUMBER ; NUMS: LD A,(HL) ;GET CHARACTERS FROM END, SEARCHING FOR SUFFIX DEC HL ;BACK UEXTRACT HEXADECIMAL NUMBER FROM COMMAND LINE ; RETURN WITH 8-BIT VALUE IN REG A AND 16-BIT VALUE IN HL ; ALL REGISTERS MAY BE AFFECTED ; HEXNUM: CALL SCANER ;PARSE NUMBER AND PLACE IN FCBFN HNUM1: LD HL,0 ;HL=ACCUMULATED VALUE LD DE,FCBFN ;POINT TO TOKEN FOR CONVERSION HNUM2: LD A,(DE) ;GET CHARACTER CP ' ' ;DONE? JR Z,NUM3 ;RETURN IF SO CP 'H' ;DONE IF H SUFFIX JR Z,NUM3 SUB '0' ;CONVERT TO BINARY CP 10 ;0-9? JR C,HNUM3 SUB 17 ;A-F? CP 6 ;ERROR? JR NC,ERROR P CP NUMBASE ;CHECK AGAINST BASE SWITCH FLAG JR Z,HNUM1 CP ' ' ;SPACE? JR NZ,NUM1 ;CHECK FOR LAST DIGIT DJNZ NUMS ;COUNT DOWN ; ; PROCESS DECIMAL NUMBER ; NUM1: LD HL,0 ;CLEAR GRAND TOTAL LD DE,FCBFN ;POINT TO BEGINNING OF TOKEN NUM2: LD A,(DE) ;GET CHARACTER CP ' ' ;DONE IF NUM3: LD A,L ;TOTAL TO A IN CASE DONE RET Z ;ALL DONE CALL A2NUM ;CONVERT DIGIT JR NC,NUM2 ;NO ERROR JR ERROR ; ; ASCII TO NUMERICAL CONVERSION ; RETURNS WITH CARRY SET IF INVALID O ADD A,10 HNUM3: INC DE ;POINT TO NEXT CHARACTER ADD HL,HL ;LEFT SHIFT 4 ADD HL,HL ADD HL,HL ADD HL,HL OR L ;MASK IN NEW LOW LD L,A ;NEW LOW BYTE IN L JR HNUM2 ; ; GET THE REQUESTED USER NUMBER FROM THE COMMAND LINE AND VALIDATE IT. ; USRNUM: CALL NUMBER LD E,A CP MAXUSR+1 RET C ; ; INVALID COMMAND -- PRINT IT ; ERROR: CALL CRLF ;NEW LINE LD HL,(CIPTR) ;POINT TO BEGINNING OF COMMAND LINE ERR1: LD A,(HL) ;GET CHARACTER CP ' '+1 ;SIMPLE '?' IF OR LESS CAR),DE ;SET POINTER TO NON-BLANK OR END OF LINE JR Z,SCAN3 ;END OF COMMAND LINE SBC A,'A' ;CONVERT POSSIBLE DRIVE SPEC TO NUMBER CP 16 ;VALID DRIVE? INC A ;CONVERT TO DRIVE (A=1, AND SO ON) JR C,SCAN2 ;YES XOR A ;SELECT DEFAULT DRIVE DEC DE ;DON'T MOVE TO NEXT CHARACTER SCAN2: LD H,A ;STORE NUMBER (A:=0, B:=1, ETC) IN H INC DE ;POINT TO NEXT CHARACTER LD L,0 ;ZERO TOTAL CALL A2NUM ;CONVERT FIRST DIGIT JR C,SCAN3 ;NOT VALID CALL A2NUM ;CONVERT SECOND DIGIT LD A,L SELL NC,CONOUT ;PRINT COMMAND CHARACTER OR FALL THRU INC HL ;POINT TO NEXT JR NC,ERR1 ;CONTINUE CALL PRINT ;PRINT '?' DC '?' JP ABORT ;RESTART CPR ; ; POINT TO DIRECTORY ENTRY IN TBUFF WHOSE OFFSET IS SPECIFIED BY A AND C ; DIRPTR: LD HL,TBUFF ;POINT TO TEMP BUFFER ADD A,C ;POINT TO 1ST BYTE OF DIR ENTRY CALL ADDAH ;POINT TO DESIRED BYTE IN DIR ENTRY LD A,(HL) ;GET DESIRED BYTE RET ; ; CHECK FOR VALID USER AND LOG IN IF VALID ; ULOGIN: LD A,(FCBS1) ;GET USER NUMBER ALOGIT 7,L ;MAKE VALID JUST IN CASE CP MAXUSR+1 ;TOO BIG? JR C,SCAN3 ;NO LD A,(DE) ;ANY ':'? CP ':' JP Z,NAMERR ;YES, NAME ERROR SCAN3: LD A,(DE) ;SEE IF LAST CHARACTER IS A COLON (:) INC DE ;POINT TO BYTE AFTER ':' CP ':' JR Z,SCAN4 ;YES, WE HAVE A DRIVE SPEC LD HL,0 ;NOT VALID DRIVE SPEC, SWITCH TO DEFAULT LD DE,(CIPTR) ;RESTART SCAN ; ; EXTRACT FILENAME FROM POSSIBLE FILENAME.TYP ; SCAN4: LD B,H ;MOVE DRIVE TO B EX (SP),HL ;GET BACK FCB POINTER AND SAVE USER NUMBER LN: ADD A,80H ;VALID? CALL P,SETUSR ;SET IF VALID RET ; ; EXTRACT TOKEN FROM COMMAND LINE AND PLACE IT INTO FCBDN; ; FORMAT FCBDN FCB IF TOKEN RESEMBLES FILE NAME AND TYPE (FILENAME.TYP); ; ON INPUT, CIBPTR PTS TO CHARACTER AT WHICH TO START SCAN; ; ON OUTPUT, CIBPTR PTS TO CHARACTER AT WHICH TO CONTINUE AND ZERO FLAG IS ; RESET IF '?' IS IN TOKEN ; SCANER: LD HL,FCBDN ;POINT TO FCBDN SCAN1: PUSH HL ;SAVE POINTER TO FCB CALL ADVAN ;SKIP TO NON-BLANK OR END OF LINE LD (CIPTD (HL),B ;SAVE DRIVE LD B,8 ;MAX OF 8 CHARACTERS XOR A ;CLEAR '?' COUNT EX AF,AF ;AND SAVE CALL SCANF ;GET POSSIBLE NAME CALL SCANT ;AND POSSIBLE TYPE ; ; FILL IN EX, S1, S2, AND RC ; XOR A INC HL ;POINT TO NEXT BYTE IN FCBDN LD (HL),A ;ZERO EX INC HL POP BC ;GET BACK USER NUMBER LD (HL),C ;STUFF AWAY USER NUMBER IN S1 INC HL LD (HL),A ;ZERO S2 INC HL LD (HL),A ;ZERO RC ; ; SCAN COMPLETE -- DE POINTS TO DELIMITER BYTE AFTER TOKEN ; LD (CIBPTR),DE EX AF,A; ; CMDTBL (COMMAND TABLE) SCANNER ; JUMPS TO ADDRESS OF COMMAND IF CPR-RESIDENT ; JUMPS TO COM IF NOT CPR-RESIDENT COMMAND ; CMDSER: LD A,(FCBFN) ;ANY COMMAND? CP ' ' ;' ' MEANS COMMAND WAS 'D:' TO SWITCH LD A,(FCBS1) ;GET USER NUMBER IF ANY LD HL,FCBDN ;POINT TO DRIVE JR NZ,CMS0 ;NOT , SO MUST BE COMMAND ADD A,80H ;CONVERT TO USER NUMBER CALL P,NEWUSR ;SET IF VALID USER IN FCB LD A,(HL) ;LOOK FOR DRIVE SPEC DEC A ;ADJUST FOR LOG IN CALL P,TLOGIN ;LOG IN DRIVE SETUDBF ;GET NUMBER OF '?' IN FILENAME.TYP RET ; ; EXTRACT FILE TYPE FROM POSSIBLE FILENAME.TYP ; SCANT: LD B,3 ;PREPARE TO EXTRACT TYPE CP '.' ;IF (DE) DELIMITER IS A '.', WE HAVE A TYPE JR NZ,SCAN11 ;FILL FILE TYPE WITH INC DE ;POINT TO CHARACTER IN COMMAND LINE AFTER '.' SCANF: LD C,' ' ;FILL CHARACTER SCAN11: INC HL ;STEP TO NEXT BYTE IN FCBN CALL SDELM ;CHECK FOR DELIMITER JR Z,SCAN12 ;FILL REST WITH FILL BYTE IF A DELIMITER CP '*' ;WILD? JR NZ,SCAN13 ;NO LD C,'?' : LD A,(TMPUSR) ;GET CURRENT USER NUMBER ADD A,A ;PLACE IT IN HIGH NIBBLE ADD A,A ADD A,A ADD A,A LD HL,TDRIVE ;ADD DEFAULT DRIVE NUMBER (LOW NIBBLE) OR (HL) LD (UDFLAG),A ;UPDATE USER/DRIVE BYTE RET CMS0: OR (HL) ;DRIVE OR USER NUMBER JR NZ,CMS5 ;YES, CAN'T BE BUILT IN COMMAND LD HL,CMDTBL ;POINT TO COMMAND TABLE LD B,NCMNDS ;SET COMMAND COUNTER CMS1: LD DE,FCBFN ;POINT TO STORED COMMAND NAME CMS2: LD A,(DE) ;COMPARE AGAINST TABLE ENTRY XOR (HL) ADD A,A JR NZ,CMS3 ;CHANGE FILL BYTE TO '?' SCAN12: DEC DE ;DON'T STEP OFF CURRENT SYMBOL LD A,C ;GET FILL BYTE SCAN13: CP '?' ;QUESTION MARK? JR NZ,SCAN14 ;NO, JUST STORE CHARACTER EX AF,AF ;GET QUESTION MARK COUNT INC A ;COUNT IT EX AF,AF ;AND SAVE COUNT SCAN14: INC DE ;POINT TO NEXT CHARACTER IN COMMAND LINE LD (HL),A ;STORE CHARACTER IN FCBDN DJNZ SCAN11 ;COUNT DOWN CHARACTERS IN FILE TYPE (3 MAX) SCAN15: CALL SDELM ;SKIP REST OF CHARACTERS TO RET Z ;DELIMITER INC DE JR SCAN15 ;NO MATCH INC DE ;POINT TO NEXT CHARACTER INC HL JR NC,CMS2 ;NOT END OF TABLE ENTRY LD A,(DE) ;NEXT CHARACTER IN INPUT COMMAND MUST BE CP ' ' JR NZ,CMS4 LD A,(HL) ;FOUND COMMAND, INC HL ;LOAD ADDRESS, LD H,(HL) ;AND LD L,A ;JUMP TO IT JP (HL) ;COMMAND IS CPR-RESIDENT CMS3: BIT 7,(HL) ;END OF TABLE ENTRY? INC HL JR Z,CMS3 ;NO CMS4: INC HL ;SKIP ADDRESS INC HL DJNZ CMS1 ;NOT TO END OF TABLE YET CMS5: JP COM ;COMMAND MAY BE DISK-RESIDENT ; ;**** SectD A,B ;DROP INTO DIRPR TO PRINT DIRECTORY ;THEN RESTART CPR ; ; DIRECTORY PRINT ROUTINE; ON ENTRY, A IS 80H IF SYSTEM FILES EXCLUSIVELY ; DIRPR: LD D,A ;STORE SYSTEM FLAG IN D LD A,B ;SAVE SYSTST LD (SYSTST),A XOR A ;SET COLUMN COUNTER TO 0 LD B,A ;AND USER NUMBER JUST IN CASE DIRPR1: ADD A,03H ;FORCE CRLF AND 0FCH LD E,A PUSH DE INC D ;ALL USER NUMBERS? PUSH BC ;SAVE USER NUMBER LD A,B ;AND CALL Z,SETUSR ;SET IF ALL USER NUMBERS CALL SEARF ;SEARCH FOR SPECIFIEion 5 **** ; CPR-Resident Commands ; ; ;Section 5A ;Command: DIR ;Function: To display a directory of the files on disk. ;Forms: ; DIR Display the DIR files ; DIR S Display the SYS files ; DIR B Display both DIR and SYS files ; DIR A Display both DIR and SYS files for all user numbers ; DIR: CALL SCANER ;EXTRACT POSSIBLE D:FILENAME.TYP TOKEN CALL ULOGIN ;LOG ANY USER LD HL,FCBFN ;MAKE FCB WILD (ALL '?') IF NO FILENAME.TYP LD A,(HL) ;GET FIRST CHARACTER OF FILED FILE (FIRST OCCURRENCE) DIRPR2: POP BC ;GET BACK USER NUMBER POP DE ;AND SYSTEM FLAG JR NZ,DIRPR4 ;FILE FOUND LD A,B ;AT LAST USER NUMBER? INC B ;STEP TO NEXT USER NUMBER CP MAXUSR LD A,E ;IN CASE DONE JR NC,DIRPR3 ;DONE LD E,D ;EITHER WAY, E IS GOING TO BE CHANGED INC E JR Z,DIRPR1 ;PRINT ALL USER NUMBERS DIRPR3: AND A ;ANY PRINTED? JP CHKFND ;GO CHECK ; ; ENTRY SELECTION LOOP; ON ENTRY, A=OFFSET FROM SEARF OR SEARN ; DIRPR4: DEC A ;ADJUST TO RETURNED VALUE RRNAME.TYP CP ' ' ;IF , ALL WILD JR NZ,DIR2 LD B,11 ;NUMBER OF CHARACTERS IN FN & FT DIR1: LD (HL),'?' ;STORE '?' INC HL DJNZ DIR1 DIR2: CALL ADVAN ;LOOK AT NEXT INPUT CHARACTER LD B,0FFH ;LOAD ALL FILES FLAG CP USRFLG ;ALL FILES ON DISK? JR Z,DIR4 ;YES LD B,80H ;IN CASE SYS ONLY CP SOFLG ;SYS ONLY? JR Z,DIR4 ;YES CP SYSFLG ;HAVE SYSTEM SPECIFIER? LD A,B ;SET SYSTEM BIT EXAMINATION LD B,0 ;SYSTEM TOKEN DEFAULT JR NZ,DIRPR DIR4: INC DE LD (CIBPTR),DE LCA ;CONVERT NUMBER TO OFFSET INTO TBUFF RRCA RRCA LD C,A ;OFFSET INTO TBUFF IN C (C=OFFSET TO ENTRY) LD A,10 ;ADD 10 TO POINT TO SYSTEM FILE ATTRIBUTE BIT CALL DIRPTR PUSH DE AND D ;MASK FOR SYSTEM BIT INC D ;ALL FILES? JR Z,DIRPR5 ;YES LD HL,SYSTST ;SYSTEM FILE? CP (HL) JR NZ,DIRPR9 ;NO DIRPR5: LD A,E ;WHAT TO PRINT ; IF TWOCOL AND 01H ;OUTPUT IF 2 ENTRIES PRINTED IN LINE ELSE ; AND 03H ;OUTPUT IF 4 ENTRIES PRINTED IN LINE ENDIF ; CAL INC HL ;STEP TO NEXT CHARACTER CP C ;EAT SPACES? CALL NZ,CONOUT DJNZ PRFN1 POP BC RET ; ;Section 5B ;Command: ERA ;Function: To erase files; names of the erased files are displayed. ;Forms: ; ERA ; ERA: CALL SCANER ;PARSE FILE SPECIFICATION CP 11 ;ALL WILD (ALL FILES = 11 '?')? JR NZ,ERA1 ;IF NOT, THEN DO ERASES CALL REPLY JP NZ,RESTRT ;RESTART CPR IF NOT ERA1: CALL ULOGIN ;LOG ANY USER XOR A ;PRINT ALL FILES (EXAMINE SYSTEM BIT) LD B,A ;NO SYS-ONLY OPT TL Z,CRLF ;NEWLINE ALWAYS RETURNS ZERO TRUE JR Z,DIRPR6 CALL PRINT ; IF WIDE DEFB ' ' ;2 SPACES DEFB FENCE ;THEN FENCE CHARACTER DC ' ' ;THEN 2 MORE SPACES ELSE ; DEFB ' ' ;SPACE DEFB FENCE ;THEN FENCE CHARACTER DC ' ' ;THEN SPACE ENDIF ; DIRPR6: POP DE INC E ;BUMP NUMBER OF FILES LISTED PUSH DE INC D ;PRINT WITH USER NUMBER? JR NZ,DIRPR8 ;NO LD A,B ;GET USER NUMBER AND CALL PRUSRN ;AND PRINT DEFB USRDLM+80H ;USER NUMBER DELIMITER DIRPR8: XOR A ;DO DIRPR CALL DIRPR ;PRINT DIRECTORY OF ERASED FILES ERA2: LD DE,FCBDN ;DELETE FILE SPECIFIED JP DELETE ;REENTER CPR VIA DELETE ; ;Section 5C ;Command: ERAQ ;Function: To erase files with individual query. ;Forms: ; ERAQ ; ? Y ; : ; : ; ERAQ: CALL SCANER ; parse file specification CALL ULOGIN ; log any user LD HL,01FFH ; load first flag ERAQ1: CALL SEARF ; find first entry JR NZ,ERAQ2 ; found one INC L ; ever found any? ; ; Check for File Found ; CHKFNDON'T EAT SPACES CALL PRFN DIRPR9: PUSH BC CALL SEARN ;GET NEXT FILENAME JR DIRPR2 PRFN: PUSH BC LD B,A ;SAVE EAT SPACES FLAG LD A,1 CALL DIRPTR ;HL NOW POINTS TO 1ST BYTE OF FILE NAME LD C,B ;SAVE EAT SPACES FLAG LD B,12 ;12 CHARACTER TOTAL PRFN1: LD A,B ;CHECK FOR FILE TYPE CP 04H LD A,(HL) RES 7,A JR NZ,PRFN2 ;NOT YET AT TYPE DEC HL ;ADJUST HL FOR TYPE DELIMITER CP ' ' ;NO FILE TYPE? JR Z,PRFN2 ;CONTINUE IF SO LD A,'.' ;FILE TYPE EXISTS, PRINT DOT PRFN2:: RET NZ ; yes ; ; No File Error Message ; PRNNF: CALL PRINTC ;NO FILE MESSAGE DC 'No File' RET ERAQ2: LD L,H ; restart found count ERAQ3: DEC H ; at file to erase? JR NZ,ERAQ5 ; no INC H ; reset H to 1 INC L ; step count in case don't delete PUSH HL ; save flag first DEC A ; compute offset RRCA RRCA RRCA LD C,A CALL CRLF LD A,' ' ; eat spaces CALL PRFN ; print file name CALL REPLY1 ; prompt JR NZ,ERAQ4 ; reply not 'Y' XOR A CALL DIRPTR ; getng ; LIST: ; IF FFKILL LD HL,NLINEP+0580H ; lines/page, first ff and list flags ELSE LD HL,NLINEP+0500H ; lines/page and list flag ENDIF ; JR TYPE1 ; ;Section 5G ;Command: TYPE ;Function: To display specified file on console. ;Forms: ; TYPE Display file ; TYPE P Display file without default paging ; TYPE: ; IF FFKILL LD HL,NLINES+0280H ; lines/page, first ff and type flags ELSE LD HL,NLINES+0200H ; lines/page and type flag ENDIF ; TYPE1: LD (LNCNT),HL FCB to delete LD A,(FCBDN) ; get drive specification LD (HL),A ; select drive EX DE,HL CALL DELETE ; go delete POP HL ; get flags DEC L ; reduce count since file deleted LD H,L ; update next file to process JR ERAQ1 ; and restart process ERAQ4: POP HL ; get count ERAQ5: CALL SEARN ; find next file JR NZ,ERAQ3 ; more files, go ask RET ; done ; ;Section 5D ;Command: SAK ;Function: To pause until a key is struck; ^C warm boots. ;Forms: ; SAK ; ? ; SAK: ; save list/type flag and line cnt XOR A ; initialize tab count LD (TABCNT),A ; initialize line and tab count CALL SCANER ; extract filename.typ token JP NZ,NAMERR ; error if any question mark CALL ADVAN ; get pgdflg if it's there JR Z,PGDON ; jump if no more on cmd line XOR PGDFLG ; change page flag? JR NZ,PGDON ; no INC DE ; step over pgdflg LD (CIBPTR),DE ; and save cmd buffer pointer DEC A ; no page flag is 0ffh LD (LNCNT),A ; save flag PGDON: CALL ULOGIN ; log any usCALL CRLF ; strike any key JR REPLY1 REPLY: CALL PRINTC DC 'All' REPLY1: CALL PRINT DC '? ' REPL2: CALL BREAK ; get response JR Z,REPL2 ; none CALL UCASE CP 'Y' RET ; ;Section 5E ;Command: BELL ;Function: To ring terminal bell. ;Forms: ; BELL ; RING: LD A,BELL ; load bell into A JP CONOUT ; and output it ; ;Section 5F ;Command: LIST ;Function: To print specified file on list device. ;Forms: ; LIST Print file ; LIST P Print file without default pagier CALL OPENF ; open selected file JR Z,TYPE3 ; abort if error CALL CRLF ; new line TYPE2: CALL READF ; read next block JR Z,TYPE4 ; read ok (A register is zero) DEC A ; error or eof? RET Z ; eof TYPE3: JP PRNNF ; error CHK4LF: LD A,(LNCNT) ; get line count (just in case) DJNZ CHK4VT ; not lf, try vertical tab RES 7,A ; reset first ff flag (if any) CP 07FH ; paging off? JR Z,CHK4VT ; yes DEC A ; time to page? JR Z,CHKFF ; yes! CHK4VT: DEC B ; step over vt ve character in e reg SUB BS ; backspace? LD B,A ; in case not bs JR NZ,CHK4HT ; not bs DEC (HL) ; step tab count and fall thru CHK4HT: DJNZ CHK4LF ; no, check for line feed CHKHT: LD E,' ' ; load space into bdos character reg CALL PAGER ; print space LD A,(HL) ; now in col 0 mod 8? AND 07H JR NZ,CHKHT ; go for more JR NXTCHR PAGER: CALL BREAK ; check for abort LD A,(TYPLST) ; get list/type flag LD C,A ; IF TEST OR NOT NOSTAT AND 00000010B ; list? EXX ; save rCHK4FF: DJNZ CHK4CR ; not ff, try vt BIT 7,A ; first ff? JR NZ,NXTCHR ; yes, ignore CHKFF: LD A,(TYPLST) BIT 0,A ; type or list? LD E,FF ; load ff into character reg LD A,NLINEP ; reset list count JR NZ,CHK4CR ; list CHKFF1: LD C,06H ; direct console i/o LD E,0FFH ; conditional console input CALL BDOSJP JR Z,CHKFF1 ; no character yet CALL CHKETX ; check for ^C LD A,NLINES ; type line count LD E,LF CHK4CR: LD (LNCNT),A ; save line count mmUmoegisters CALL Z,LISTST ; check busy EXX ; restore registers AND A JR Z,PAGER ; printer not ready ENDIF ; LD A,E ; check for printing character CP ' ' JR C,PAGE2 ; control character, don't count INC (HL) ; step position PAGE2: JP BDOSJP ; return via bdos ; ;Section 5H ;Command: PAGE ;Function: To eject a page on list device via a form feed. ;Forms: ; PAGE ; EJECT: CALL BREAK ; check for ^C ; IF TEST OR NOT NOSTAT CALL LISTST ; check printer ready AND A JR Z,Eer DJNZ NXTCHR ; not cr LD (HL),B ; reset tab count NXTCHR: LD A,(CHRCNT) ; get buffer pointer INC A ; step to next character CP 128 ; end-of-buffer? JR NC,TYPE2 ; yes, read next buffer TYPE4: LD (CHRCNT),A ; save buffer count LD HL,TBUFF ; point to buffer CALL ADDAH ; compute address of next character LD A,(HL) ; get character to accumulator AND 7FH ; mask out msb CP 1AH ; end-of-file (^Z)? RET Z ; yes, restart zcpr LD HL,TABCNT ; pointer to tab counter LD E,A ; saJECT ; not ready yet ENDIF ; LD E,FF ; now for form feed LD C,05H ; list output JP BDOS ; output character and return via bdos ; ;Section 5I ;Command: SAVE ;Function: To save the contents of TPA onto disk as a file. Number of ; pages or records is in decimal. Saved area begins at 100H. ;Forms: ; SAVE ; SAVE R ; SAVE: CALL NUMBER ;EXTRACT NUMBER FROM COMMAND LINE PUSH HL ;SAVE IT CALL SCANER ;EXTRACT FILENAME.TYP JP NZ,RITE ERROR SAVE4: JP PRNLE ;PRINT 'NO SPACE' ERROR ; ;Section 5J ;Command: REN ;Function: To change the name of an existing file. ;Forms: ; REN = ; REN: LD HL,FCBDN+16 ;PLACE FILENAME IN SECOND HALF OF FCB PUSH HL ;SAVE POINTER FOR SEARCH FIRST CALL SCAN1 ;EXTRACT FILE NAME JR NZ,NAMERR ;ERROR IF ANY '?' IN IT CALL ADVAN ;ADVANCE CIBPTR CP '=' ;'=' OK JP NZ,ERROR EX DE,HL ;POINT TO CHARACTER AFTER '=' IN HL INC HL LD (CIBPTR),HL ;SAVE POINTER TO OLD FILE NAMERR ;MUST BE NO '?' IN IT CALL ULOGIN ;LOG ANY USER CALL ERA2 ;DELETE FILE IF POSSIBLE CALL CREATE ;CREATE NEW FILE JR Z,SAVE4 ;UNSUCCESSFUL XOR A ;SET RECORD COUNT FIELD OF NEW FILE'S FCB LD (FCBCR),A CALL ADVAN ;LOOK FOR RECORD OPTION INC DE ;POINT TO TOKEN POP HL ;GET BACK PAGE COUNT CP RECFLG JR Z,SAVE1 DEC DE ;NO TOKEN, SO BACK UP ADD HL,HL ;DOUBLE IT FOR HL=RECORD (128 BYTES) COUNT SAVE1: LD (CIBPTR),DE ;SET POINTER TO BAD TOKEN OR AFTER GOOD TOKEN LD DE,TPANAME CALL SCANER ;EXTRACT FILENAME.TYP TOKEN JR NZ,NAMERR ;ERROR IF ANY '?' LD A,(FCBDN+16+13) ;GET POSSIBLE USER NUMBER CALL ALOGIN ;LOG ANY USER POP DE ;GET POINTER FOR SEARCH FIRST CALL SEARDE ;CHECK FOR NONE OF THAT NAME JR Z,REN1 ;NO FILE EXISTS CALL PRINTC ;DUPLICATE NAME DC 'Delete' CALL REPLY1 ;GET REPLY JR NZ,REN2 ;NOT A 'Y' CALL DELETE ;DELETE DUPLICATE REN1: LD A,(DE) ;GET POSSIBLE DRIVE LD DE,FCBDN ;POINT TO FCB LD (DE),A ;SAVE POSSIBLE DRIVE LD C,17 ;POINT TO START OF SAVE AREA (TPA) SAVE2: LD A,H ;DONE WITH SAVE? OR L ;HL=0 IF SO JR NZ,SAVE3 LD DE,FCBDN ;CLOSE SAVED FILE JP CLOSE ;AND RESTART CPR SAVE3: DEC HL ;COUNT DOWN ON RECORDS PUSH HL ;SAVE POINTER TO BLOCK TO SAVE CALL DMASET ;SET DMA ADDRESS FOR WRITE (ADDRESS IN DE) LD HL,128 ;128 BYTES PER RECORD ADD HL,DE ;POINT TO NEXT RECORD LD DE,FCBDN ;WRITE RECORD CALL WRITE EX DE,HL ;GET POINTER TO NEXT RECORD IN DE POP HL ;GET RECORD COUNT JR Z,SAVE2 ;NO WH ;BDOS RENAME FCT CALL BDOSFN JP CHKFND ;CHECK FOR FILE FOUND NAMERR: CALL PRINTC DC 'Name Error' REN2: JP ABORT ; ;Section 5K ;Command: USER ;Function: To change current user number; new user number is in decimal. ;Forms: ; USER ; USER: CALL USRNUM ;EXTRACT USER NUMBER FROM COMMAND LINE JP NEWUSR ;SET NEW USER NUMBER ; ;Section 5L ;Command: DFU ;Function: To set the Default User Number for the command/file scanner; new ; default user number is in decimal. ;F; done? RET Z ; yes DJNZ PEEK2 ; not end of line JR PEEK1 ; end of line PRHEXW: LD A,H ; print hex word in hl CALL PRHEXA LD A,L PRHEXA: PUSH AF ; save right nibble RRCA ; move left nibble to right RRCA RRCA RRCA CALL PRHEX ; display left nibble POP AF ; get back right nibble PRHEX: AND 0FH ; convert to ascii ADD A,90H DAA ADC A,40H DAA JP CONOUT ; go display value ; ; ;Section 5O ;Command: POKE ;Function: To poke a string of hex values into a set of orms: ; DFU ; DFU: CALL USRNUM ;GET USER NUMBER LD (DFUSR),A ;PUT IT AWAY RET ; ;Section 5M ;Command: SCL ;Function: To force ZCPR to parse only a single command per line; reset ; to multiple command format at the next ^C. ;Forms: ; SCL ; IF MULTPL SINGLE: LD HL,NEWCMD ; point at current command separator LD A,CMDCHR ; get default command separator XOR (HL) ; flip current separator LD (HL),A ; save new command separator RET ENDIF ; ; ;Section 5N ;Command:consecutive addresses. ;Forms: ; POKE [] ; POKE: CALL HEXNUM ; get address POKE1: PUSH HL ; save address CALL HEXNUM ; get next byte LD A,(FCBFN) ; done? CP ' ' LD A,L ; save byte POP HL ; get back address RET Z ; done LD (HL),A ; save byte INC HL ; step to next address JR POKE1 ; go for more ; ; ;Section 5P ;Command: JUMP ;Function: To call the program (subroutine) at the specified address ; without loading from disk. ;Forms: ; JUMP PEEK ;Function: To display hex values beginning at a specified address. ;Forms: ; PEEK [] ; PEEK: CALL HEXNUM ; get display address PUSH HL ; save it CALL HEXNUM ; get optional count LD C,L ; save count POP HL ; get back address PEEK1: CALL CRLF ; start new line CALL PRHEXW ; print address LD B,16 ; 16 values per line PEEK2: CALL PRINT ; space over DC ' ' LD A,(HL) ; get hex value INC HL ; step to next value CALL PRHEXA ; display value DEC C ; JUMP: CALL HEXNUM ;GET LOAD ADDRESS IN HL JR CLLPRG ;PERFORM CALL ; ;Section 5Q ;Command: COM file processing ;Function: To load the specified COM file from disk and execute it. ;Forms: ; ; COM: LD HL,FCBFT ;FILE TYPE MUST BE BLANK LD A,(HL) CP ' ' JP NZ,ERROR LD (HL),'C' ;PLACE DEFAULT FILE TYPE (COM) INTO FCB INC HL ;COPY INTO FILE TYPE LD (HL),'O' ;3 BYTES INC HL LD (HL),'M' LD HL,TPA ;SET EXECUTION/LOAD ADDRESS CR+0FF00H;INITIALIZE COUNT AND GET COMMAND FLAG LD DE,TBUFF ;DESTINATION FOR COMMAND TAIL COM2: INC DE ;POINT TO DESTINATION INC B ;INCREMENT CHARACTER COUNT LD A,(HL) ;COPY CHARACTER TO TBUFF LD (DE),A INC HL ;STEP TO NEXT SOURCE CHARACTER OR A ;END OF LINE? ; IF MULTPL JR Z,COM3 ;YES, END OF LINE XOR C ;START OF NEXT COMMAND? JR NZ,COM2 ;NO LD (DE),A ;0 TERMINATE STRING COM3: ; ELSE ; JR NZ,COM2 ;NOT END OF LINE ENDIF ; LD A,B ;SAVE CHARACTER COUNT LD (TBUALL MEMLD ;LOAD MEMORY WITH FILE SPECIFIED ;(NO RETURN IF ERROR OR TOO BIG) ; ;Section 5R ;Command: GO ;Function: To call the program in the TPA without loading from disk. ; Same as JUMP 100H, but more convenient, especially when ; used with parameters for programs like STAT. ;Form: ; GO ; GO: LD HL,TPA ;ALWAYS TO TPA ; ; ; CLLPRG IS THE ENTRY POINT FOR THE EXECUTION OF THE LOADED PROGRAM ; ON ENTRY TO THIS ROUTINE, HL MUST CONTAIN THE EXECUTION ; ADDRESFF),A DEC HL ;BACK UP ONE CHARACTER LD (CIBPTR),HL ;SAVE FOR START OF NEXT COMMAND SCAN ; ; RUN LOADED TRANSIENT PROGRAM ; CALL CRLF ;NEW LINE CALL DEFDMA ;SET DMA TO 0080 CALL RSTUSR ;RESET TO PROPER USER NUMBER ; ; EXECUTION (CALL) OF PROGRAM (SUBROUTINE) OCCURS HERE ; RET ;CALL TRANSIENT ; ;Section 5S ;Command: GET ;Function: To load the specified file from disk to the specified address ;Forms: ; GET Load the specified file at the specified page; ; GET: CAS OF THE PROGRAM (SUBROUTINE) TO EXECUTE ; CLLPRG: PUSH HL ;SAVE EXECUTION ADDRESS LD HL,(CIBPTR) ;SAVE THE COMMAND TAIL START ADDRESS PUSH HL LD HL,TFCB ;MAKE FCB FOR PROGRAM CALL SCAN1 ;SEARCH COMMAND LINE FOR NEXT TOKEN LD HL,TFCB+16 ;OFFSET FOR 2ND FILE SPEC CALL SCAN1 ;SCAN FOR IT AND LOAD IT INTO FCBDN+16 XOR A LD (TFCB+32),A ;ZERO RECORD COUNT ; ; LOAD COMMAND LINE INTO TBUFF ; POP HL ;GET LOCATION OF COMMAND TAIL NEWCMD EQU $+1 ;IN-LINE COMMAND SEPARATOR LD BC,CMDCHLL HEXNUM ;GET LOAD ADDRESS IN HL PUSH HL ;SAVE ADDRESS CALL SCANER ;GET FILE NAME POP HL ;RESTORE ADDRESS JP NZ,NAMERR ;MUST BE UNAMBIGUOUS ; ; LOAD MEMORY WITH COMMAND LINE FILE ; ON INPUT, HL CONTAINS STARTING ADDRESS TO LOAD ; IF COM FILE TOO BIG, EXIT TO ERROR. ; MEMLD: LD (LDADR),HL ;SET LOAD ADDRESS ; ; MLA is a reentry point for a non-standard CP/M Modification ; This is the return point when the .COM (or GET) file is not found the ; first time, the Default User is selST BELOW CPR CP H ;ARE WE GOING TO OVERWRITE THE CPR? JR C,PRNLE ;ERROR IF SO EX DE,HL ;MOVE LOAD ADDRES FOR DMASET CALL DMASET ;SET DMA ADDRESS LD HL,128 ;COMPUTE NEXT LOAD ADDRESS ADD HL,DE ;AND SAVE ANSWER IN HL CALL READF ;READ NEXT RECORD JR Z,MLA2 ;READ ERROR OR EOF? DEC A ;LOAD COMPLETE JP Z,RSTUSR ;GO RESET CORRECT USER ; ; LOAD ERROR ; PRNLE: CALL PRINTC DC 'Full' PRNLE1: JP ABORT ; IF (($-ENTRY) GT ZCPRSZ) *ZCPR too large!!* ENDIF ; IF TEST LISTSTected for the second attempt ; and Drive A is selected for the final attempt. ; MLA: CALL ULOGIN ;LOG ANY USER LD HL,(FCBS1) ;SAVE ANY USER NUMBER CALL OPENF ;OPEN COMMAND.COM FILE JR NZ,MLA1 ;FILE FOUND - LOAD IT ; ; FILE NOT FOUND - SELECT DEFAULT USER ; LD A,L ;GET FCB USER AND A ;DEFAULT USER? JR NZ,MLA0 ;NO LD HL,TMPUSR ;CURRENT USER SAME AS DEFAULT? LD A,(DFUSR) ;GET DEFAULT USER CP (HL) SET 7,A ;MAKE INTO VALID USER NUMBER LD (FCBS1),A ;PUT USER INTO FCB JR NZ,: LD A,2DH ;COMPUTE LIST STATUS ENTRY DEFB 0FEH ;SKIP NEXT BYTE BOOT: XOR A ;COMPUTE BOOT ENTRY LD HL,(BASE+1) ;GET PAGE ADDRESS OF BIOS LD L,A ;ADD ENTRY JP (HL) ;GO TO BIOS ROUTINE ENDIF ENDLD EQU $ END  PUSH HL ;SAVE POIT RECORD JR Z,MLA2 ;READ ERROR OR EOF? DEC A ;LOAD COMPLETE JP Z,RSTUSR ;GO RESET CORRECT USER ; ; LOAD ERROR ; PRNLE: CALL PRINTC DC 'Full' PRNLE1: JP ABORT ; IF (($-ENTRY) GT ZCPRSZ) *ZCPR too large!!* ENDIF ; IF TEST LISTSTMLA ;AND TRY AGAIN ; ; FILE NOT FOUND - SELECT DRIVE A IF DEFAULT WAS SOME OTHER DRIVE ; MLA0: LD A,(TDRIVE) ;DRIVE A DEFAULT? AND A JR Z,MLA3 ;YES, ERROR XOR A LD HL,FCBDN ;POINT AT DRIVE IN FCB OR (HL) ;DRIVE ALREADY SPECIFIED? LD (HL),1 ;SELECT DRIVE A JR Z,MLA ;NO, GO GIVE IT A TRY MLA3: CALL PRNNF ;CAN'T FIND FILE JR PRNLE1 ; ; FILE FOUND -- PROCEED WITH LOAD ; MLA1: LD HL,(LDADR) ;GET START ADDRESS OF MEMORY LOAD MLA2: LD A,ENTRY/256-1 ;GET HIGH-ORDER ADR OF JUA Personal Note =============== Somehow, I've managed to get by for the last 14 years using just ZCPR. But like some of you, I have fiddled with the standard ZCPR and modified it to suit my tastes. As I added new commands or enriched old ones, I've always remained compatible with existing programs, all the BDOS replacements, and, most important of all, stayed within the 800H space allocation of the original Digital Research CCP. Here are the fruits of my labors, I hope you enjoy this CCP replacenow have options to turn on or off page breaks. Moreover, the console check for abort has been improved. Two commands have been added for use in submit files - SAK and BELL. These commands allow you to pause or ring the bell during submit file execution. Before you install this version of ZCPR onto your boot disks, try it by running it as a .com file. Just edit the few customizing options and assemble the source. After you decide it really is better, load it onto your boot track and make it yment as much as I do. Don Kirkpatrick 17595 S.W. Pheasant Lane Beaverton, Oregon 97006 Introduction ============ This console replacement is designed to run under CP/M 2.2 or any of the 2.2 BDOS replacements. It requires a Z80 or better. If you are running DRI's CCP or older versions of ZCPR1, this program is a significant improvement. If you are running ZCPR3, CP/M 3.0, CP/M Plus, or MP/M, this will probably be a disappoiour standard. Complete instructions are located at the end of this document. The complete built-in command list is: DIR - directory command enhanced to list optionally all user areas REN - standard rename command USER- move to new user number area on same drive SAVE- save specified number of TPA pages or records in a file TYPE- display a file on the console with optional page break pauses LIST- print command plus optional form feed insertion PAGE- send form feed to ntment. If you are familiar with ZCPR3, you will recognize many of the enhancements here: comments on a command line, search path for the .com file, drive/user change with simple du:, CLEVEL3 command processing, proper SUBMIT file facility, and so on. Nothing has been removed from DRI's CCP, only new features added. AND IT ALL STILL FITS IN THE ORIGINAL 800H, THE SAME SPACE AS THE DIGITAL RESEARCH FIVE COMMAND CCP. Many of the standard commands have been enhanced. For example, TYPE and LIST list device ERA - standard file erase command ERAQ- file erase with confirmation query at each file DFU - set default user number for .com search path BELL- send a bell character to the console SAK - pause until a key is struck on the console (Strike Any Key) SCL - toggle multiple commands per line (Single Command on a Line) GET - load a file into the TPA at any specified location JUMP- process command tail and execute program at specified address GO - process c type 'junk*.'. The question mark still works as a single character wild card. Command Line Processing ======================= The current user number is included as part of the command prompt for all non-zero user numbers. The prompt is of the form du>, for example A2> or B10>. If the SUPRES equate is true, the user number is suppressed for user 0 only. Multiple commands are typed on a single line separated by a command separator character. Occasionally, you need to type the separatorommand tail and execute program loaded at 100H PEEK- display hexadecimal byte string starting with specified address POKE- load hexadecimal byte string starting with specified address BOOT- execute BIOS cold boot routine Filename Processing =================== The standard ZCPR3 du: drive/user file specification has been implemented. Any filename can be in the du:fn.ft form. For example: A>era c4:junk*.* erases files on the C drive, user area 4 without leaving drive A character in a command tail. The SCL command toggles the multiple command enable. The CMDCHR equate determines the command separator character. A ';' has been chosen as the separator character in this distribution version. Comments are allowed on a command line. When the comment separator character is encountered as the first character of a command, the remainder of the line is ignored. The COMCHR equate determines the comment separator character. A ';' has been chosen as the separator cha user 0. When a user number is found in a filename, that user number is placed in S1 of the default FCB. Bit 7 of S1 is set to inform the program using the FCB a user number was found. The * in an ambiguous file name has been improved. Now a trailing * causes the remainder of the ambiguous name to be filled with '?', not just the fn field. For example: A>era c4:junk* is the same as the example above. Previously, junk* was defined as 'junk????. '. If you need the ft field blank,racter in this distribution version. Here is an example containing comments and multiple commands on a single line: A>get 100 junk;peek 100;;this is a comment. A>;this is also a comment. There exists a built-in search path for transient commands. First, the current drive/user is searched. Next, the current drive/default user is searched. Last, drive A/default user is searched. The DEFUSR equate determines the default user number, currently set to user 0 in this distribution version. PR is entered at CPRLOC+3 jump, default command processing is suppressed. Either way, register C must contain a valid drive/user, just like the original CCP. Submit File Processing ====================== A basic design choice had to be made in the design of ZCPR concerning the execution of submit files. The original CCP had a problem. It ALWAYS looked for the $$$.SUB file on drive A and the submit program would place it on the current default drive. When the you were logged onto drive B anThe default user is temporarily changed with the DFU command. If a drive is specified in the transient command, the current and default user areas on the specified drive are searched. If a user number is specified, that user area on the current and default drive are searched. If both the drive and user number are specified, no search is performed. The same drive/user area is never searched twice. Transient commands are always "called." If a program terminates via a return rather than a warm bd you issued a submit command, the $$$.SUB was placed on drive B and not executed. After much debate it was decided to have ZCPR perform the same type of function as CCP (look for the $$$.SUB file on drive A), but the problem with SUBMIT.COM still exists. Hence, RGF designed SuperSUB and RLC took his SuperSUB and designed SUB from it; both programs are set up to allow the selection at assembly time of creating the $$$.SUB on the default drive or on drive A. If you don't have one of these newer soot, subsequent multiple commands on the command line are executed. Any program exiting by a warm boot reloads ZCPR and the subsequent commands lost. A default command can be placed in the command buffer and control passed to ZCPR for processing. The only thing required, besides placing the command in the buffer and jumping to CPRLOC, is to initialize the command character counter at the start of the buffer. The procedure is compatible with the original DRI CCP default command processing. If ZCubmit programs, a procedure for patching the standard SUBMIT.COM has been included at the end. The fixed drive choice permits a submit file to contain a series of commands exactly as they would be entered from a CP/M console. This permits things like: A>dir A>b: B>dir to be executed, even though the currently default drive is changed during execution. If the $$$.SUB file were present on the default drive, the above series of commands would not work. ZCPR would be looking for $ If there is a conflict between an internal ZCPR command and a transient program of the same name, the internal command is executed. Type the command with the du: included if the external transient command is the one desired. Here is a complete alphabetized list of all the resident commands with their syntax: ============================================================================= Command: BELL Function: To ring terminal bell. Forms: BELL Options: None. Uses: This comma$$.SUB on the default drive, and switching default drives without moving the $$$.SUB file would cause processing to abort. Note that the same problem occurs if the user number of the $$$.SUB file is not predefined. ZCPR assumes that the $$$.SUB file is located on user 0 of drive A. The trick of using the $ flag returned by the BDOS disk reset is used to speed the search for a $*.* file on drive A. This trick will not work if the $$$.SUB file were located on another drive. The '>' prompt charactnd is designed to be placed in a submit file to ring the bell to indicate significant checkpoints. ============================================================================= Command: BOOT Function: To execute BIOS cold boot routine. Forms: BOOT Options: REBOOT equate controls the inclusion/exclusion of this command. Uses: Reboots the system without pushing the reset button. The cold boot entry point in the BIOS must be supported for this commaner is replaced by a special character while a submit file is in execution. The SPRMPT equate defines this special character, currently set to '$' in this distribution version. Command Syntax ============== Multiple commands can be placed on one line. If the comment character is encountered where a command should start, the rest of the line is ignored. Any command can be renamed by editing the command table. Command names can be up to eight characters long and are terminated by bit 7 high. d to work. ============================================================================= Command: DFU Function: To set the Default User Number for transient commands. Forms: DFU Options: DEFUSR equate defines the default user choice until this command is entered. NUMBASE equate defines the character that specifies a hexadecimal number. The distribution version is set to 'H'. Uses: The default user area is searched after a transient comm FENCE equate specifies the character separator between the directory columns. USRDLM equate specifies the character between the user number and the filename. USRFLG, SYSFLG, and SOFLG equates specify the command line tail character that control the display of system and non-system files. Uses: Displays a directory listing of files in specific drive/user area. =============================================and cannot be found in the current user area. If the transient command still has not been found, the default user on the default drive is searched last. The new default user number is in decimal, but hexadecimal numbers are entered by appending an 'H'. The next warm boot will restore the original default user number. ============================================================================= Command: DIR Function: To display a directory listing of the files on a drive.================================ Command: ERA Function: To erase files. Forms: ERA Options: None. Uses: Deletes files. Names of erased files are displayed. ============================================================================= Command: ERAQ Function: To erase files with individual query. Forms: ERAQ ? y File erased ? File not erased Options: None. Uses: Deletes a subset of a set of ambi Forms: DIR Display the DIR files DIR S Display the SYS files DIR B Display both DIR and SYS files DIR A Display both DIR and SYS files for all user areas Options: TWOCOL equate controls the number of columns in the display. Forty-column terminals are limited to two-column displays. WIDE equate controls the spacing between the columns and change the horizontal width of a directory display.Acorn CPCPMDISC/M  0!KP ZCPR-D&J of 5 March 1994 $$$ SUBDI0LISmTYPrUSEۆDFPAG+BELhSAMGXERERASAV;REΆGEԕJUM;wMqz~# |}Ɛ'@'Ê: }w#!~ 66C#6O#6M!͠!*!\a!la2|;~#( x2+"qͲ^ˆ"U*Á &} !:2 :( !6( *>8͵!ͨ(=2: _q:A͊:('>1Ċ0͊z UͲs>ʁ(7:=2ͫ (!w#5ׁ́!̓!P͓(ׁ !~(#"G~͢w#p[ a{_ 6.[]>:ؿɅo$^! ~+H(1 ! }0F0 ?O}؅؁o^! (H(0 80 ))))oʂ_q*~!Ԋ#0zã!ł~:ƀ!͕S("A<8g.8}8:ˆ:(![Dp;ͷ#w#q#w#wS.  #ͫ(* ?y? <wͫ: :! wFulã>-*o x2+"qͲ^ˆ"U*Á &} !:2 :( !6( *>8͵!ͨ(=́+͵!ͮ(!a <͕=6#"^ *:Xͼ(wDeletX ҁwName Erroã//2!r>;wMqz~# |}Ɛ'@'Ê: }w#!~ 66C#6O#6M!͠!*!\a!la2|;~#( x2+"qͲ^ˆ"U*Á &} !:2 :( !6( *>8͵!ͨ(=̀~=:!2ɶ $! #0 ~#fo~#(##A^U!~  6?#͕A( S(Bx SxWx2G_x͹ x{0Z(=O> Lբ(! {q(z |  xĄͿG>LH x~˿ + (>.#Ċ^ R8UGa^U!͹ ,wNo Fill% '$,=Oq> ĄX L:w-eͿ qwAlz?͓(͢Y>Ê!!"2^ˆ͕( P S=2UÁ( qͨ(F=: ˿(=( $:G >< (͠> 2p:<02!sion, the prompt character is changed from '>' to '<' when it runs. CPRLOC for the test version is 8000H. A bootstrap loader is included at the beginning to move the image to this address. Do not try to set a breakpoint until after the loader has moved ZCPR. The easiest way to accomplish this is to single-step through the loader and then set your breakpoints. Change the execution address to something lower if 8000H does not leave enough space for the debugger. A small amount of code is also added at the end of the debug version to compute the BIOS list status and cold boot entry points at run time. This permits the demo version to execute properly without setting the BDOS location equate. Patching SUBMIT.COM =================== SUBMIT.COM is patched to run with ZCPR by the following procedure. This is recommended if the user does not have one of the newer public domain versions of submit. This patch simply makes SUBMIT.COM always place the $$$.SUB file on drive A. Illustrative terminal session follows: A>get 100 submit.com;peek 5bb 2 05BB 00 24 <-- Patch is at 5BB Hex A>poke 5bb 1 <-- Change 0 (default drive) to 1 (drive A) A>peek 5b0 20 <-- Let's check just to make sure 05B0 00 00 00 00 00 00 30 30 31 20 24 01 24 24 24 20 05C0 20 20 20 20 53 55 42 00 00 00 1A 1A 1A 1A 1A 1A A>save 5 newsubmt.com <-- Save new SUBMIT.COM file Pretty simple, huh? ny error message encountered that is not on this list came from some progl be replaced by the boot track CCP. If you like what you see, place a copy on the boot track to make it available all the time. 3) Reassemble, this time with COMLD false to make ZCPRNBLD.COM (ZCPR No Boot LoaDer). 4) Run SYSGEN to load a copy of the boot track into memory. B>; Sample terminal session for integrating ZCPR B>sysgen SYSGEN VER 2.2 SOURCE DRIVE NAME (OR RETURN TO SKIP)a SOURCE ON A, THEN TYPE RETURN FUNCTION COMPLETE DESTINATION DRIVE Nnto the boot track of a test disk, not your original, using SYSGEN, and try it out. B>sysgen SYSGEN VER 2.2 SOURCE DRIVE NAME (OR RETURN TO SKIP) <-- Use memory image DESTINATION DRIVE NAME (OR RETURN TO REBOOT)b <-- Load onto drive B DESTINATION ON B, THEN TYPE RETURN FUNCTION COMPLETE DESTINATION DRIVE NAME (OR RETURN TO REBOOT) You should now have a ZCPR system boot disk. Notice you did all your work on drive B so you wouldn't destroy theAME (OR RETURN TO REBOOT) 5) Run SAVE to save a track image to a file (eg: SAVE 32 BOOTFILE). The number on the save command depends on the size of your boot track loader; it can be as small as 31 and as large as 44. If you have extra disk space or are not sure, play it safe and use 44. B>save 44 cpm56.com <-- We now have a SYSGEN image of CP/M 6) Find the location of the stock CCP by peeking at the boot file. It is normally located at address 980H in the file. Usin original. This may seem like a great number of steps, but each is only a single CP/M command line, total time is only 5 minutes or so after you get ZCPR to run as a .com file. Debugging ZCPR ============== Special provisions have been make to ease the debugging of ZCPR. Setting the TEST equate true causes the assembler to build a version of ZCPR that executes in the TPA. This allows the use of a debugger like DDT, ZSID, or Z8E to load and monitor execution. To identify the debug verg ZCPR: B>zcpr <-- Reload zcpr.com version B>get 100 cpm56.com and search for the start of the console processor: B>peek 980 0980 C3 xx xx C3 xx xx 7F 00 43 4F 50 59 52 49 47 48 0990 54 20 ... If you don't find the start of the CCP at 980H, don't be discouraged. It is there, but at a higher address. Keep looking. 7) When you find the location of the CCP, patch it with the new ZCPR image. B>get 980 zcprnbld.com 8) Place the new file oAny response except 'Y' (either case) aborts the command, any commands remaining on the command line are ignored, and any $$$.SUB file erased. "All?" Not really an error, but a check to verify that all files on the drive/user area are to be erased. Any response except 'Y' (either case) aborts the command and any commands remaining on the command line are ignored. Installation Instructions ========================= 1) The first task is to determine the location of your '<'. This tells you the special debug version of ZCPR is running. See the debug section at the end for details. Address 0 contains a jump 3 beyond the start of the BIOS and address 5 contains a jump 6 beyond the start of the BDOS. Be careful if you attempt to execute a transient program from ZCPRDEMO. Some transient programs, like NSWP, return rather than warm boot when done. These programs don't know that ZCPRDEMO is at address 8000H rather than just under the BDOS. BDOS because you MUST set the P2DOS equate to this value. If you do not know the location of your BDOS, use ZCPRDEMO to find it. If you do not already have ZCPRDEMO.COM, assemble ZCPR with the TEST equate true to make it. A bootstrap loader will be included and you can run the .com file. This program assembles without errors using Microsoft's M80/L80: A>m80 =zcpr A>l80 zcpr,zcprdemo/n/e Other assemblers can be used, but ZCPR.MAC will probably require editing tIf they overwrite ZCPRDEMO, then the return is to random code. Of course, this is not a problem when ZCPR is installed just under the BDOS. 2) You MUST edit the code to place your BDOS/P2DOS/Z80DOS/ZRDOS start address in the P2DOS equate. Set COMLD true (and TEST false if you set it true in step 1 above) and make ZCPR.COM. A bootstrap loader will be included. Assuming you successfully assemble it, just type "zcpr" to run it. However, every time there is a warm boot, it wilo convert it to a form compatible. The major decision in converting is to determine how the .PHASE pseudo is to be handled. Probably the best solution to the .PHASE is to generate a .hex file and load it with an offset using DDT/SID/ZSID. Consult the "r" command in the DDT/SID/ZSID manaul. Run ZCPRDEMO and peek at low memory: A>zcprdemo A' to a controls the display of the user number in the prompt when the user number is zero. MAXUSR equate controls the maximum allowable user number. NUMBASE equate defines the character that specifies a hexadecimal number. The distribution version is set to 'H'. Uses: This command changes the current user number. The new user number is in decimal, but a hexadecimal number is entered by appending an 'H'. This command has been retained on't fit into the TPA or a read error was returned from the BDOS. If ZCPR was attempting to save a file, the BDOS write call returned failure. Either the disk or the directory is full. Any commands remaining on the command line are ignored and any $$$.SUB file erased. "No File" No file could be found matching the filename specified in the command. This message is also be printed if the BDOS read command returns failure. If ZCPR was looking for a transient command, anfor compatibility purposes only. It is far easier to change disk/user by typing du:. ============================================================================= Error Messages ============== If any error is encountered as a command line is being parsed, a message will be printed and, for serious errors, the remainder of the line is ignored. Below is a complete list of all ZCPR error messages. Any error message encountered that is not on this list came from some progy commands remaining on the command line are ignored and any $$$.SUB file erased. "Name Error" The specified filename has a user number larger than the allowable maximum or an ambiguous filename was entered where only an unambiguous filename is permitted. Any commands remaining on the command line are ignored and any $$$.SUB file erased. "Delete?" Not really an error, but there already exists a file with the same name as the requested new name in the REN command. ram other than ZCPR. "?" An error was detected in the command. The an item on the command line was not what was expected. The command line is echoed up to the position where the error was detected, as close as can be determined, and the "?" printed. Any commands remaining on the command the line are ignored and any $$$.SUB file erased. "Full" If ZCPR was attempting to load a transient program, one of two things has gone wrong: either the program is so large that it w=========================================== Command: SAVE Function: To save the contents of TPA onto disk as a file. Forms: SAVE SAVE R Options: RECFLG equate determines the command tail character that specifies records rather than pages. NUMBASE equate defines the character that specifies a hexadecimal number. The distribution version is set to 'H'. Uses: Saves the TPA to a file. Recordn: To display specified file on console. Forms: TYPE Display file TYPE P Display file without default paging Options: NLINES equate determines the number of lines per screen. FFKILL equate controls the suppression of form feeds before printable text. PGDFLG equate determines the command line tail character that toggles the default form feed insertion every NLINEP lines. Uses: Displays files with/without paginatios are 128 bytes long, pages are 256 bytes long. Number of pages or records is in decimal, but a hexadecimal number is entered by appending an 'H'. Saved area begins at 100H. ============================================================================= Command: SCL Function: To force ZCPR to parse only a single command per line. Forms: SCL Options: MULTPL equate determines the inclusion/exclusion of this command and whether or not multiple commands are allowed. n on CON: device. A display is aborted by a console ^C. If aborted, any submit file in process terminates and control returns gracefully to the console prompt. When page breaks are enabled, any console character except ^C will display the next page of text. ============================================================================= Command: USER Function: To change current user number. Forms: USER Options: SUPRES equate CMDCHR equate determines the character separating multiple commands. Uses: Some transient commands require the command separator in the command tail. This command turns off multiple command parsing so the entire command tail is sent to the transient program. Multiple command format is reset at the next warm boot. SCL toggles. ============================================================================= Command: TYPE Functio Options: NOSTAT equate controls the use of the BIOS list status call. Uses: Sends a form feed to the LST: device. The page eject can be aborted by a console ^C if the system hangs because the printer is not ready. If aborted, any submit file in process is terminated and control is returned gracefully to the console prompt. ============================================================================= Command: PEEK Function: To display hex values beginning at a specified afn>= REN = Existing Delete? y File deleted Options: None. Uses: Changes the names of files. Any du: on is ignored; the optional du: is on . If there already exists a , the console is queried for conformation. Any response except 'Y' (either case) aborts the command, kills any submit file in process, and returns gracefully to the command promddress. Forms: PEEK [] Options: None. Uses: Displays hexadecimal values anywhere in the entire address space. The maximum value for is 0FFH, but the default is 256. ============================================================================= Command: POKE Function: To poke a string of hex values into a set of consecutive addresses. Forms: POKE [...] Options: None. Uses: pt. ============================================================================= Command: SAK Function: To pause until a key is struck. Forms: SAK ? Options: None. Uses: Pauses a submit file until a keystroke is entered. Any character other than a ^C will resume execution. A ^C kills the submit file, any commands remaining on the command the line are ignored, and control returns gracefully to the prompt. ================================== Modifies values anywhere in the entire address space. Each represents one byte and is separated from the next by a space. The number of are limited only by the size of the command line buffer. The address is incremented for each . Excellent for hand patching code. ============================================================================= Command: REN Function: To change the name of an existing file. Forms: REN Options: None. Uses: Loads a file into the TPA for patching purposes. This command searches for the specified file along the same search path as ============================================ Command: LIST Function: To print specified file on list device. - Forms: LIST Print file LIST P Print file without default paging Options: NLINEP equate determines the number of lines per page. FFKILL equate controls the suppression of form feeds before printable text. PGDFLG equate determines the command line tail character that toggles the default form feed insertion the transient command loader. ============================================================================= Command: GO Function: To call the program in the TPA without loading from disk. Forms: GO Options: None. Uses: Most useful to rerun a program already loaded into the TPA. Saves time and wear on disk drives. The command tail is entered exactly as it would appear if GO were replaced by the program name. Same as JUMPevery NLINEP lines. NOSTAT equate controls the use of the BIOS list status call. Uses: Prints files with/without pagination on LST: device. A listing is aborted by a console ^C. Any submit file in process is terminated and control is returned gracefully to the console prompt. ============================================================================= Command: PAGE Function: To eject a page on list device via a form feed. Forms: PAGE 100H, but more convenient, especially when used with parameters for programs like STAT. ============================================================================= Command: JUMP Function: To call the program at a specified address. Forms: JUMP Options: None. Uses: Executes code not located at 100H. For example, JUMP 0 warm boots. The code must already reside at the specified address. =================================