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ðì SJCCP version 1.40 $(C)SJ Research 1984.:O21!"!q חo_g]*"!"C<21*" m$DIRTYPEERA.REN^SAVEUSERLLOADGOVDUfPRINTbOLDRUNRESETVERSmSJCCP version 1.40$ZJ|1*#~ >~*&>\͹* Aborted *$1ԗ2!>":_<2@]J}>>(>]֗2!Ó![~(O  # ~#foy~# ##=e!:] :\=_!~wCOMH>}> >  0Oxy 0_!\@O#~ y͹Syntax error$!\66  6 #6#8*O: >?w33# 8 .( *w# 8 *w#:Է͹Illegal filename$>?(w#+ _A8[8 ,=  =ח2!]~  6?#:\?( 2:@27<=7o&~ O:ط ~ @ > :K>::ط( ~ ܧͧ #~x̧y=< ͧ> +͹Catalogue full$xc(7<(g(&):\(#S?7ٷ !*+| 7?Y7ٷ(͹Disc full$!\ >?ʭ\# xy 0;!oygY ..xYM ɗO:0 08  8͹Bad number$!b7<ʭۯ27ٷ!~O 0 ( :( yy2¤#¤ (=Erase all files (Y/N)?$>? !\# HY§7<ʭ!l!=( -!\lNwy#l<(͹File already exists$(<ʭ not found$=:] (!!<>2=!l@! (#w wp:۷!˾Ccc?!bZ7ٷ(<̖(7<̖(S?7ٷ *! r -!0ڏ 8ҏ)8o!\~ :G:Է((wͼ!]>.!e~ #$$$ 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>26502-Z80BBC ANIMAL BBCANIMAL DAT BBCBASICCOMn BBCBASICTXTg CONVERT COMCRC COMCRCKLISTCRCF-INDEX BBC5F-RAND0 BBC F-RAND1 BBCF-RAND2 BBC? !"#F-RSER1 BBC$F-RSER2 BBC %F-RSTD BBC &F-WESER1BBC'F-WESER2BBC()F-WSER1 BBC*F-WSER2 BBC+,F-WSTD BBC-.MERGE BBC/READ ME  0READDFS BBC1SORT BBC2SORTREALBBC3BBCBASICROM3|456789:;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"': :  ."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 binary  ;  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%=1N" T~C K=1  question  A$(K),2)<>"\Q" 'A$=query("Is it "+art(A$(K),3))) 4 A$="Y" "Why not try another one?"'' new  ; " *** , NEW ANIMAL 6 *** @ new GJ "OK, I give up."'"Tell me what animal you were thinking"'"of ",V$ TV$=strip(convlc(V$)) <^ "Please tell me a question that would"'"distinguish "; 'h art(V$);" from ";art(A$(K),3)) r X$:X$=capital(X$) "| X$,1)="?" X$=X$,(X$)-1) 6A$=query("For "+art(V$)+" the answer would be ") S%:s$=(#F%)+s$: $ s$,13) "** Bad string **"' #G%,s$  ((22<<FFPPZZddnnxx&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+ A$="Y" B$="N"  A$="N" B$="Y" Z1=(A$(0)) A$(0)=(Z1+2) A$(Z1)=A$(K) A$(Z1+1)="\A"+V$ 1A$(K)="\Q"+X$+"\"+A$+(Z1+1)+"\"+B$+(Z1)+"\"  ;  ***  PRINT QUESTIONS  ***  question Q$=A$(K) "C$=query(Q$,3,Q$,"\",3)-3)) &T$="\"+C$ 0X=Q$,T$,3) :Y=Q$,"\",X+1) DK=(Q$,X+2,Y-X-2)) N X; b *** l READ DATA FILE v ***  read % "Just let me refresh my memory" Z=0  #X,A$(Z):Z=Z+1  #X Z=MAX+1 A$(Z-1)=""  #X  ;  :@%=10: 0: 15)"ANIMAL" 2 "Creative Computing Morristown New Jersey"'' ( by Nathan Teichholtz & Steve North 0( from an original idea by Arthur Luehrmann. 52 Modified by Chris Atkinson and Richard Russell. <: ,F =17 T~C ::" at line ";: PMAX=(-P)/40 Z A$(MAX) d "Play 'Guess the Animal'" n: xX=("ANIMAL.DAT") ( X<>0 read I=0 3: A$(I): I N=(A$(0)) : ***  MAIN CONTROL SECTION ***  9 query("Are you thinking of an animal ")="  ***  PRINT NAME OF ANIMAL  ***  print  10*X);A$(I),3); X=(X+1) 4   ;  *** * LIST CONTENTS 4 *** > %H ' "Animals I already know are:" RX=0:I=0 \ I=I+1 f A$(I),2)="\A" print p A$(I)="" I=MAX )z ' "Room for ";((MAX-I)/3);" more." : query("Do you want to save these on disk")<>"Y" :  ***  DUMP FILE IF REQUESTED  *** % "ANIMAL.DAT" *ERA ANIMAL.DAT 2X="ANIMAL.DAT":Z=0: X=0 "Directory full":  # X,A$(Z):Z=Z+1  A$(Z)="" Z=MAX+1 # 0  ; 2 4,\QDoes it fly\N2\Y3\,\Agoldfish,\Asparrow, ; . NOW THE FUNCTIONS ; /$ art(noun$): Indefinite article appender ;. "AEIOUaeiou",noun$,1)) ="an "+noun$ ="a "+noun$ 8; &B strip(name$): Article stripper Lname$=nospace(name$) V AT$,Z ` tRD j Z=Z+1: AT$ t AT$=name$,(AT$)) Z=10 #~ Z<10 name$=name$,1+(AT$)) =nospace(name$) - A ,AN ,THE ,a ,an ,the ,An ,The ,THe ,, ;  nospace(name$) name$=" "+name$  name$=name$,2)  name$,1)<>" " =name$ ;  convlc(name$)  L%,A%,B$  L%=1 (name$) A%=(name$,L%))   A%<97 A%>64 A%=A%+32 B$=B$+(A%): L% =B$ (; 2 capital(name$) < A$ "Fname$=nospace(convlc(name$)) P (name$)<97 =name$ ZA$=((name$)-32) dA$=A$+name$,2) n=A$ x;  query(prompt$)  A$  ' prompt$;: A$:A$=capital(A$),1)  A$="Y" A$="N" =A$ HH H H68 \QDoes it fly\N2\Y3\ \QDoes it live in water\N9\Y8\ \QIs it an insect\Y5\N4\ \QIs it a mammal\Y7\N6\ \QDoes it have black stripes\Y37\N36\ \QIs it yellow\Y19\N18\ \Abat \QIs it a mammal\Y15\N14\ \QIs it an insect\Y11\N10\ \QIs it a mammal\N13\Y12\ \Aant \QDoes it have a long trunk\Y21\N20\ \QDoes it have a pouch\Y27\N26\ \QIs it a fish\N17\Y16\ \QIs it very big\N23\Y22\ \Agoldfish \QDoes it have a hard shell\Y29\N28\ \QDoes it have a red breast\Y25\N24\ \Acanary \QDoes it purr\Y33\N32\ \Aelephant \Awhale \QIs it furry\Y45\N44\ \QDoes it eat fish\Y31\N30\ \Arobin \QDoes it have eight legs\Y39\N38\ \Akangaroo \QDoes it have eight tentacles\N41\Y40\ \QIs its shell almost round\Y35\N34\ \QDoes it quack\Y49\N48\ \Aseagull \QDoes it eat ants\Y47\N46\ \Acat \Alobster \Acrab \QDoes it bite\Y67\N66\ \Awasp \QDoes it have a forked tongue\N43\Y42\ \Aspider \Aoctopus \QDoes it have a nasty smell\Y53\N52\ \Asnake \Aworm \Adolphin \QDoes it build dams\N57\Y56\ \QDoes it bark\N51\Y50\ \Aanteater \Asparrow \Aduck \Adog \Q*×Ä Îò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$CLEARCLOSECLGCLSCOSCOUNTDATADEGDEFDELETEDIVDIMDRAWENDPROCENDENVELOPEEDoes it have a long neck\Y55\N54\ \Afrog \Atoad \QDoes it have antlers\Y59\N58\ \Agiraffe \Abeaver \Aotter \QDoes it like cheese\Y61\N60\ \Adeer \QDoes it like mud\Y63\N62\ \QCan it talk\Y65\N64\ \Arabbit \Ahippopotamus \Amouse \Aman \Abee \Agnat 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):RLSEEVALERLERROREOFEORERREXPEXTFORFALSEFNGOTOGET$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~% ~(():##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(##^#;?=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|V#":#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 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: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- Ū #!( (+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ê >" ~>$ #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& 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. #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_>--~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}/]>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 DJNJCALo|/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$#> ͗-ͷ͈.`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/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(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}o+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>|ٴ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?!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,~#(##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}|#%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 [_!; BBC BASIC will run on the BBC Z80 Tube co-processor or Z80 Tube co-processor emulator running CP/M. To enter CP/M insert a suitable CP/M System disk and press - or type: *CPM To run BBC BASIC insert the enclosed disk (or a copy) and type: A>BBCBASIC After a couple of seconds the system will reply: Acorn BBC BASIC Version 2.20 (C) Copyright R.T.Russell 1983 > >>!M7ut66 6>!!M7s6@ 2. MEMORY UTILISATION BBC BASIC (Z80) requires about 16 Kbytes of code space, resulting in a value of PAGE of &3B00. The remainder of the user memory is available for BASIC programs, variables (heap) and stack. Depending on the system configuration, HIMEM can have a value up to &DC00. 3. COMMANDS, STATEMENTS AND FUNCTIONS The syntax of BASIC commands, statements and functions is in most cases identical to that of the BBC Micro version (BASIC 4). The few BBC BASIC (Z80) BBC BASIC (Z80) for the BBC Z80 second processor running CP/M (C) Copyright R.T.Russell 1982-1999 1. INTRODUCTION BBC BASIC (Z80) has been designed to be as compatible as possible with Version 4 of the 6502 BBC BASIC resident in the BBC Micro Master series. The language syntax is not always identical to that of the 6502 version, but in most cases the Z80 version is more tolerant. This version ofdifferences are documented here: CALL CALL sets up a table in RAM containing details of the parameters; the processor's IX register is set to the address of this parameter table. The other processor registers are initialised as follows: A is initialised to the least significant byte of A% B is initialised to the least significant byte of B% C is initialised to the least significant byte of C% D is initialised to the leas Except in the case of a movable string (normal string variable), the parameter address given is the absolute address at which the item is stored. In the case of movable strings (type 129) it is the address of a 4-byte parameter block containing the current length, the maximum length and the start address of the string (LSB first) in that order. Integer variables are stored in twos complement form with their least significant byte first. Fixed strings are storedt significant byte of D% E is initialised to the least significant byte of E% F is initialised to the least significant byte of F% H is initialised to the least significant byte of H% L is initialised to the least significant byte of L% The parameter types are: Code No. Parameter Type Example 0 Byte (8 bits) ?A% 4 Word (32 bits) !A% or A% 5 as the characters of the string followed by a carriage return (&0D). Floating point variables are stored in binary floating point format with their least significant byte first; the fifth byte is the exponent. The mantissa is stored as a binary fraction in sign and magnitude format. Bit 7 of the most significant byte is the sign bit and, for the purposes of calculating the magnitude of the number, this bit is assumed to be set to one. The exponent is st Real (40 bits) A 128 Fixed string $A% 129 Movable string A$ On entry to the subroutine the parameter table contains the following values: Number of parameters 1 byte (at IX) Parameter type 1 byte (at IX+1) Parameter address 2 bytes (at IX+2, IX+3, LSB first) Parameter type ) repeated as often as necessary Parameter address ) ored as an integer in excess 127 format (to find the exponent subtract 127 from the value in the fifth byte). If the exponent byte of a floating point number is zero, the number is an integer stored in integer format in the mantissa bytes. Thus an integer can be represented in two different ways in a real variable. For example the value +5 can be stored as: 05 00 00 00 00 Integer 5 00 00 00 20 82 (0.5 + 0.125) * 2^3 A CALmat documented under CALL; if the fifth byte is zero the value is an integer. Strings are stored as the characters of the string (in the correct order!) followed by a carriage return (&0D). PUT A statement to output data to a processor port. Full 16-bit addressing is available. PUT A%,N% : REM Output N% to port A% USR As with CALL, the processor's registers are initialised as follows: A is initialised to the least significant byte ofL to an address in the &FF00-&FFFF range accesses various OS functions as detailed in section 5. GET This function waits for a character to be typed at the keyboard, and returns the ASCII code. GET can also be used to read data from a processor I/O port; full 16-bit port addressing is available: N% = GET(X%) : REM input from port X% INPUT# The format of data files is different from that used by the BBC Micro, in part to improve compa A% B is initialised to the least significant byte of B% C is initialised to the least significant byte of C% D is initialised to the least significant byte of D% E is initialised to the least significant byte of E% F is initialised to the least significant byte of F% H is initialised to the least significant byte of H% L is initialised to the least significant byte of L% USR returns a 32-bitibility with standard CP/M files. Numeric values are stored as five bytes in the format documented under CALL; if the fifth byte is zero the value is an integer. Strings are stored as the characters of the string (in the correct order!) followed by a carriage return (&0D). PRINT# The format of data files is different from that used by the BBC Micro, in part to improve compatibility with standard CP/M files. Numeric values are stored as five bytes in the fort integer result composed of the processor's H, L, H' and L' registers, with H being the most significant. As with CALL, if the address is in the &FF00-&FFFF range, various OS functions are accessed, as detailed in section 5. 4. RESIDENT Z80 ASSEMBLER The in-line assembler is accessed in exactly the same way as the 6502 assembler in the BBC Micro version of BBC BASIC. That is, '[' enters assembler mode and ']' exits assembler mode. All standard Zilog mnemoni [filespec] List the files which match the (optional) ambiguous filespec. If the filespec is omitted, all .BBC files are listed: *DIR List all .BBC files on the disk *DIR B:*.* List all files on disk B: *DIR *.* List all files on the current disk *DRIVE d: Select drive d as the default drive for subsequent disk operations. *ERA filespec *ERASE filespec Erase (delete) the specified disk file or files. The ecs are accepted: ADD, ADC and SBC must be followed by A or HL. For example, ADD A,C is accepted but ADD C is not. However, the brackets around the port number in IN and OUT are optional. Thus both OUT (5),A and OUT 5,A are accepted. The instruction IN F,(C) is not accepted, but the equivalent code is produced from IN (HL),C The pseudo-ops DEFB, DEFW and DEFM are included. DEFM works like EQUS in the 6502 version. 5. OPERATING SYSTEM INTERFACE The folxtension defaults to .BBC if omitted. *LOAD filespec aaaa Loads the specified file into memory at address aaaa. The load address must be specified. If the extension is omitted, .BBC is assumed. *REN newfile=oldfile *RENAME newfile=oldfile Renames 'oldfile' as 'newfile'. If the extension is omitted, .BBC is assumed. *RESET Reset the disk system (CP/M function 13). This command does not close any files nor does it perform any other housekeeping functlowing resident Operating System ("star") commands are implemented. They may be accessed directly (e.g. *BYE) or via the OSCLI statement (OSCLI "BYE"). Control characters, lower-case characters, DEL and quotation marks may be incorporated in filenames by using the 'escape' character '|'. However, there is no equivalent to the BBC Microcomputer's '|!' to set bit 7. *BYE Returns control to the operating system (CP/M). *CPM Same as *BYE. *DIRion. You should use *RESET after you have changed a disk. *SAVE filespec aaaa bbbb *SAVE filespec aaaa +llll This command saves a specified range of memory to disk. The address range is specified either as start (aaaa) and end+1 (bbbb) or as start (aaaa) and length (llll). If the extension is omitted, .BBC is assumed. *TYPE filespec Type the specified file to the screen. If the extension is omitted, .BBC is assumed. *| comment This is a comment linF, H, L and A registers corresponding to the 6502's P, Y, X and A registers, most significant to least significant. Assuming that the address used is one of the legal OS entry points, the call will be communicated through the Tube to the host processor where it will be executed as normal. The Z80 Tube provides the following entries to the operating system: OSFIND, OSGBPB, OSBPUT, OSBGET, OSARGS, OSFILE, OSRDCH, OSASCI, OSNEWL, OSWORD, OSBYTE, OSCLI at &FFCE to &FFe. Anything following the | is ignored. Any other star commands are passed to the host operating system in the normal way. If you need to pass a star command to the host which happens to have the same name as one of the CP/M command (eg *DIR) then it should be preceded with another star; ie **DIR $ or OSCLI"*DIR $" will cause the host's filing system to set it's directory to '$' rather than result in a CP/M directory listing. CALLs and USRs to addresses in the ranF7. Remember that calls to the filing system entries operate on the host's filing system, not the CP/M filing system. 6. ERROR MESSAGES AND CODES Untrappable: No room RENUMBER space Silly LINE space Sorry Bad program Trappable - BASIC: 1 Out of range 24 Exp range 2 25 3 26 No suchge &FF00 to &FFFF provide access to the machine operating system, as with the BBC microcomputer on its own. In order to achieve compatability with other versions of BBC BASIC, CALL and USR behave differently when addressing this area of memory. The processor's A, H, L and E registers are initialised to the least significant bytes of the integer variables A%, X%, Y% and E% respectively. In the case of USR, the returned 32-bit value is composed of the processor's variable 4 Mistake 27 Missing ) 5 Missing , 28 Bad HEX 6 Type mismatch 29 No such FN/PROC 7 No FN 30 Bad call 8 31 Arguments 9 Missing " 32 No FOR 10 Bad DIM 33 Can't match FOR 11 DIM space 34 FOR variable 12 Not LOCAL 35 13 No PROC 36 No TOY,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½ 14 Array 37 15 Subscript 38 No GOSUB 16 Syntax error 39 ON syntax 17 Escape 40 ON range 18 Division by zero 41 No such line 19 String too long 42 Out of DATA 20 Too big 43 No REPEAT 21 -ve root 44 22 Log range 45 Missing # 23 Accuracy lost Trappable - OS: 190 Directory ful_ʦ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\mq6al 214 File not found 192 Too many open files 222 Channel 196 File exists 253 Bad string 198 Disk full 254 Bad command 200 Close error 255 CP/M error 204 Bad name  ?z:Wwf:Zd7\`{"f3~]1&7QǂmѬXKBT^)wd|tp\R]uҮRѧ>sVAV!B^DDñpOO*;-4X1ȭ)xAho}jvzaf1RvP^r-]pZ~wvn.vu1v ! !" CONVERT Version 2.3 :] ‘ CONVERT converts between BBC BASIC internal format (.BBC ) and ASCII (.BAS). Its options are as follows: CONVERT Prints this description. CONVERT filename.BBC Converts from BBC BASIC internal format to ASCII. CONVERT filename.BAS Converts from ASCII to BBC BASIC internal format.  !\$ e!( ͽ v ʶ " MC½ ͈ !6 ~#Ľ ~( 'R<0=(Ľ x()T]))7!~0:#)T]))_~$%(0:?A[?_{?#~ 0˩˙ (,(G8˙" ?a(ˡͥ|Ī ( *(80@( ( (8& ! ! :v Gv W˲xGov W˲xg6#zG{Tw#{?@w#z?@w# >b < Close errorZ >b Z >b g(3 Sorry - file protected>ͽ ǯͽ >ͽ >ͽ ! 4 !6 F v ( (( > w#([ !6 ͥ|[ " 7R6 6 R }ͽ }ͽ |ͽ !6 ~ͽ ~# M Line too long - abort. ** Line number added ** * # ** Line number out of sequence ** ɀANDABSACSADVALASCASNATNAUTOBGETBPUTCOLOURCOLORCALLCHAINCHR$CLEARCLOSECLGCLSCOSCOUNTDATADEGDEFDELETEDIVDIMDRAWENDPROCENDENVELOPEELSEEVALERLERROREOFEORERR Disk full\>b 6< File not found >b >b 6< Directory full>b OF \!6 N  ~ ˹q End of file - abort> ͽ > N ! w ˹q~>ͽ  ~# _>b +fY #ja9 cح,gOV9 nJEt`gIwO "j!Pexߕ}.GˑV]:ڴH=_g-?Ty{WAzjgAuHtH,z;-g!my@5àkR:DdgspQTYCu{*ɞ-T/×?]]Np 䍅$Lj3LuCVVw!E`BXa^{{8^IAzk9u"{=1 wX2>}g<_͔a[h ^uIk?g涚i8*^fo{`e;)9CRC.COM 6.5 14/09/86CRCKLIST???CRCKFILE???-CATALOG???!9" 1,ͫ CRC Ver 6.5 CTL-S pauses, CTL-C aborts :] ¹>2f 2_ ͫ ++ Searching for CRCKLIST file ++]! Ͱʖͫ ++ Searching for CRCKFILE file ++]!# Ͱʖͫ ++ Searching for -CATALOG file ++]!. Ͱ·e·! q‰>.‰#|‰Y‰)‰Y̀̀gK#Y*Y 3-:f --e·?!  ')V'! 3ÖÖͫ DONE Quantity of file CRC that matche+|S42(%Y Z 4CȂV W(ȳEX;Ob0ddD3="=le RIG!qc\t֋^GHY"u0≅"8;=_ADac'ӬO`MR' 4W!&(0E F&U)GgBo\IטA9V6 u1;kπ-sq=.06(K|jA'yV)7J+=LJ(vZn.qIQEpZ3N%/ŃRiqnؾE-zG4P)F;ޓqz(X}\r &'MD(n#T:MC`7* C6˳tT7.F9H5wS8Ih0R(Pd - :[ :\ Hͫ Quantity of file CRC that did not match - :\ :] ʁͫ Quantity of lines failed parse test - :] :^ ʴͫ Quantity of file(s) not found - :^ * >2e :m2_ F28 2D 2X ! " ! " !" 8 8 <ͫ Directory full÷1,M h!e !]J !eS ͫ --> FILE: XXXXXXXX.XXX CRC = Á:e ͫ File not found:_ F·8 <¯ͫ Cannot close CRCFILE8 ͫ ++ ABORTED ++>:_ F4* }" > 8 <ͫ CaWƸ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 =@ќɪ ?0nnot close CRCFILE !8   w# &ͫ DONE* * * }|ڙ!" * {zҋ* 8 …* " W* " !" * * }>* #" :\2\<2e M |2\ͫ File not found. ͫ Checking with file - ! ~QͿ #E͸ ͸ 2[ 2\ 2] 2^ ! 2 C§: :f 7ͫ *** No CRC Files found ***>  w#: <2 Pl: e6ͫ Cannot parse string ! ~Ϳ #͸ !  >  Wy 0Ϳ 0zCRCKLISTCRCsk fullÁ!CRCKLIST$$$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; 6 #6^#6! ~ Ϳ #!] 4ø #x'] #e w~VͿ #J>2e ͫ - M ҃ͫ File not found !^ 4z :c G:` µ:b G:a µͫ *Match* 2f ![ 4ͫ <-- is, was --> :b ͗ > Ϳ :c ͗ ͸ 2f !\ 4<ͤ2b ~ ͫ Not a space between CRC values <#ͤ2c G"Y ͒͒= # 2~.#͒T # I~ b #~ b b|̀.̀~0ڏ:ҏ#0~!ڡҡ#AʹOʹ~00  #ɷ\<ͫ ++ OPEN FAILED ++z !"` !&ݼ>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" * |7   ʁ\E !~2d #" }  ] :a ͗ > Ϳ :` ͗ ͫ ++ FILE READ ERROR ++ <*` ):d oғ |g}o"` ͠ Ɛ'@'ÿ ~Ϳ #~¬ > Ϳ > _ :_ F{* * }|= !" * {z/ * 8  * " ͫ Disk fullÁ!" * * #" 2h2|:e ~ !\~2s g  \æ !s \ \!g \ \<7=Ɓo&t  ] 2h2|2e ~$#~# x d  0ÿ BUĔ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~!xFxL --> FILE: BBCDIST .MAC CRC = 38 8E --> FILE: BBCBASIC.COM CRC = 65 81 --> FILE: CONVERT .COM CRC = 6F FA --> FILE: MERGE .BBC CRC = 6C 7F --> FILE: ANIMAL .BBC CRC = 53 35 --> FILE: SORT .BBC CRC = 54 C1 --> FILE: SORTREAL.BBC CRC = FA 50 --> FILE: F-RSER2 .BBC CRC = 93 54 --> FILE: F-WSER1 .BBC CRC = 4D E6 --> FILE: F-WSTD .BBC CRC = 64 73 --> FILE: F-WSER2 .BBC CRC = A9 BF --> FILE: F-RAND1 .BBC CRC = 9F 11 --> FILE: F-WESER1.BBC CRC = 1F E1 --> FILE: F-WESdG#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%ER2.BBC CRC = 8B 30 --> FILE: F-RSTD .BBC CRC = 35 14 --> FILE: F-RSER1 .BBC CRC = C1 63 --> FILE: F-RAND0 .BBC CRC = 98 C5 --> FILE: F-RAND2 .BBC CRC = B0 98 --> FILE: F-INDEX .BBC CRC = B8 BD --> FILE: READ .ME CRC = 11 E1 --> FILE: ANIMAL .DAT CRC = 08 67 --> FILE: CRC .COM CRC = BC 7B --> FILE: BBCBASIC.TXT CRC = 1F 2AO0w#qSe߅ևme_T pRf3_%v6FqVEnTm pZ5ymc"" name$="DELETE" _delete(i) i=_display(i,name$)  name$=""  : :  LIST IN ALPHABETICAL ORDER  : entry=1   curoff$; * 4 >line_count=0 H R 0,line_count); \_read_data(entry) f_print_data pentry=entry+1 zline_count=line_count+8 temp$=(0) . entry>length line_count>16 temp$<>"" 6_message("Push any key to continue or E to end ")  entry>length ="E"  curoata";55);"Type 1" 5 10);"Search For/Delete an Entry";55);"Type 2" 5 10);"List in Alphabetical Order";55);"Type 3" > 10);"Reorganise the Data File and Index";55);"Type 4";  5,11); 6 "Please enter the appropriate number (0 to 4) "; function$=  clrline$; # function$>"/" function$<"5" function=(function$) " 54,function+5);"<====<<"; &, function tZA,t^B,TVC,dhC 6 function=0 @ J_close_files T #^ "Address Book Files Closed"'' h r: |: n$;  : : ( REORGANISE THE DATA FILE AND INDEX : entry=1 5 0,13);"Reorganising the Data File and Index" ' newdata="ADDRESS.BAK" newindex="NAME.BAK" 6 newdata=0 newindex=0 "Disk Directory Full": #newdata,0 $ ._read_data(entry) 8index(entry)=#newdata B i=2 7 L#newdata,data$(i) V `entry=entry+1 j entry>length tEOFnewdata=#newdata-1 ~#newdata=0 #newdata,EOFnewdata #0 , "Re-naming the Data and Index Files" ' *REN ADDRESS.$$$=A ENTER DATA : flag= temp$="" i=1   _get_data / length=maxrec data$(1)="" flag=: T\B > data$(1)="+" data$(1)="-" _message("Bad Data"): T\B i=_find_place(0,data$(1)) ' i>0 _message("Duplicate Record") ! '"Is this data correct ? "; temp$= :  flag temp$="Y" & flag DbB %0_put_index(i,data$(1),#datanum) : i=2 7 D#datanum,data$(i) N X: b flag l v: :  SEARCH FOR AN ENTRY : i=1   0,11);cteolDDRESS.BAK *REN NAME.$$$=NAME.BAK *REN ADDRESS.BAK=ADDRESS.DTA *REN ADDRESS.DTA=ADDRESS.$$$ *REN NAME.BAK=NAME.NDX *REN NAME.NDX=NAME.$$$ indexnum= "NAME.NDX" datanum= "ADDRESS.DTA" #datanum,EOFdata #datanum=EOFdata+1   : : %( INITIALISE VARIABLES AND ARRAYS 2: <: F: P _initialise Zesc$=(27) dbell$=(7) ncteol$=(5) xcteos$=(4) return$=(13) clrline$=return$+cteol$ curoff$=esc$+"D" curon$=esc$+"C" : 7 The maximum record number, +#indexnum,index$(length),index(length)  #indexnum>EOFindex  index$(length+1)=(&FF) index(length+1)=0  #datanum,EOFdata *#datanum=EOFdata+1 4 >: H: >R WRITE INDEX, MAXREC AND NEW EOF POINTERS AND CLOSE FILES \: f _close_files pEOFdata=#datanum-1 z#datanum=0 #datanum,EOFdata #indexnum=10  i=1 length !#indexnum,index$(i),index(i)  EOFindex=#indexnum-1 #indexnum=0 #indexnum,EOFindex,maxrec #0  : :  WRITE A MESSAGE AT Lmaxrec, is set/read in  PROC_setup/PROC_read_index :  message$(7)  i=1 7  message$(i)  A Name,Phone Number,Address,-- " --,-- " --,-- " --,Post Code :  data$(7)  i=1 7 "data$(i)=30," ") , 6temp$=255," ") @temp$="" J T: ^: h OPEN THE FILES r: | _open_files indexnum="NAME.NDX" datanum="ADDRESS.DTA" 3 indexnum=0 datanum=0 _setup _read_index  : : % SET UP NEW INDEX AND DATA FILES :  _setup  & 0,13);INE 23  :  _message(line$)  x,y $ x= . y= 8 0,23);bell$;line$; B x,y); L V : ` : 'j GET INPUT DATA - LIMIT TO 30 CHAR t : ~ _get_data  i  0,13);cteos$ 2 length=maxrec _message("Address Book Full") i=1 7  10);message$(i);25); temp$  data$(i)=temp$,30)  data$(1)="" i=7    :  : ) FIND AND DISPLAY THE REQUESTED DATA  :  _display(i,name$)  0,12);cteos$ ( i=_find_place(i,name$) :2 i<0 _message("Name Not Known "Setting Up Address Book" maxrec=10 indexnum="NAME.NDX" datanum="ADDRESS.DTA" 6 indexnum=0 datanum=0 "Disk Directory Full": #indexnum,0,maxrec &#datanum,0 &0 index$(maxrec+1),index(maxrec+1) :length=0 Dindex$(0)="" Nindex(0)=0 Xindex$(1)=(&FF) bindex(1)=0 l v: : ( READ INDEX AND LENGTH OF DATA FILE :  _read_index  #indexnum,EOFindex,maxrec ' index$(maxrec+1), index(maxrec+1) index$(0)="" index(0)=0 length=0  length=length+1- Next Highest Given") < _read_data(i) F P _print_data Z =i d : n : %x DELETE THE ENTRY FROM THE INDEX  :  _delete(i)  "Are you SURE ",temp$  0,-1);cteos$;  temp$<>"YES"  i<0 i=-i  i=i length  index$(i)=index$(i+1)  index(i)=index(i+1)   length=length-1   :  :  READ DATA FOR ENTRY i  : " _read_data(i) , PTRdata=#datanum 6 i<0 i=-i @ #datanum=index(i) J data$(1)=index$(i) T i=2 7 ^ #datanum,data$(i) h r #datanum=PTRdtom+1  =i ((22<<FFPPZZddnnxx"ata |  :  :  PRINT data$() ON VDU  :  _print_data  i i=1 7 3 data$(i)<>"" 10);message$(i);25);data$(i)  data$(1)=(&FF) i=7    :  : , PUT A NEW ENTRY IN INDEX AT POSITION i  :  _put_index(i,entry$,ptr) & j 0 i<0 i=-i : j=length+1 i -1 D index$(j+1)=index$(j) N index(j+1)=index(j) X b index$(i)=entry$ l index(i)=ptr v length=length+1   :  : , FIND ENTRY IN INDEX OR PLACE TO PUT IT  :  _find_place(i,entry$)  top,bottom  i<0 i=-i entry$="+" i1 =i-1  entry$="-" i=1 =length  top=length+1  bottom=0  i=(top+1) 2 * entry$<>index$(i) i=_search(entry$)  * entry$=index$(i-1) i=i-1 4 entry$<>index$(i-1) > entry$=index$(i) =i =-i H : R : (\ DO THE SEARCHING FOR FN_find_place f : p _search(entry$) z ' entry$>index$(i) bottom=i top=i " i=(top+bottom+1) 2: round % entry$=index$(i) top=bote$,remark$  name$;" ";remark$ '  :  _modify ( '"(Enter for no change)"'  "Name ",temp$ temp$=temp$,30)  temp$<>"" name$=temp$  "Remark ",temp$ temp$=temp$,50)  temp$<>"" remark$=temp$ #& '"Confirm update record",ans$ 0 _test(ans$) :#fnum,255 D#fnum,name$,remark$ N t (2<FP Z"d$n: 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_ F_RAND0 : ' VERY SIMPLE RANDOM ACCESS PROGRAM (: :2 This program maintains a random access file of names :< and remarks. Each name can be up to a maximum of 30 :F characters long and each remark up to 50 characters. ;P The first byte of the record is set non zero (in fact 6Z &FF) if there is a record present. This gives a 8d maximum record length of 1+31+51=83. (Don't forget n the CRs.) x: : @%=10 temp$=50," ")   0 fnum= "RANDZERO"  fnum=0 fnum= "RAscr: 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, NDZERO" ! fnum=0 "Directory Full": :  " '"Enter record number: "ans$  ans$="0" #fnum:: . ans$="" record=record+1 record=(ans$) #fnum=_ptr(record) _display / '"Do you wish to change this record",ans$ "#fnum=_ptr(record) , _test(ans$) _modify 6 @ J: T: )^ _test(A$) =A$,1)="Y" A$,1)="y" h: r _ptr(record)=record*83 |:  _display  '"Record number ";record' flag=#fnum - #fnum flag=0 "Record not stored": #fnum,nam F_RAND1  SIMPLE DATABASE PROGRAM & Written by R T Russell Jan 1983 (: ;2 This is a simple database program. You are asked for 8< the name of the file you wish to use. If the file :F does not already exist, you are asked to specify the 9P number and format of the records. If the file does 8Z already exist, the file specification is read from d the file. n: x: @%=10   0 7 '"Enter the filename of the data file: "filename$ fnum=(filename$) fnum=0 _setupelds $#fnum,title$(field),size(field) length=length+size(field)+1  field  :  _display  '"Record number ";record' flag=#fnum - #fnum flag=0 "Record not stored":  field=1 fields #fnum,A$(field) ! title$(field);" ";A$(field)  field   :  _modify (  '"(Enter for no change)"' * field=1 fields 4 > title$(field);" "; H ""A$ .R A$="" (11)title$(field);" ";A$(field) \ (A$)<=size(field) f A$<>"" A$(field)=A$ p _readgen base=#fnum: :  " '"Enter record number: "ans$  ans$="0" #fnum:: . ans$="" record=record+1 record=(ans$) #fnum=_ptr(record) _display / '"Do you wish to change this record",ans$ #fnum=_ptr(record) " _test(ans$) _modify , 6 @: )J _test(A$) =A$,1)="Y" A$,1)="y" T: &^ _ptr(record)=base+record*length h: r _setup | "New file." fnum=(filename$) . fnum=0 "Sorry, disk directory full.": 1 "Enter number of fields field #z '"Confirm update record",ans$  _test(ans$) #fnum,255  field=1 fields #fnum,A$(field)  field  ((22<<FFPPZZddnnxx"",$ 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"+"FINDGBPBBPper record: "fields , title$(fields),size(fields),A$(fields)  field=1 fields 1 '"Enter title of field number ";field;": ";  ""title$(field)   6 "Maximum size of field (characters)",size(field) % size(field)>0 size(field)<256  field length=1 #fnum,fields  field=1 fields $#fnum,title$(field),size(field) &length=length+size(field)+1 0 field : D: N _readgen Xlength=1 b#fnum,fields ,l title$(fields),size(fields),A$(fields) v field=1 fiUTBGETARGSFILERDCHASCINEWLWRCRWRCHWORDBYTECLI",(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$=" F_RAND2 : & Written by Doug Mounter - Jan 82 (: %2 EXAMPLE OF A RANDOM ACCESS FILE <: 6F This is a simple inventory program. It uses the /P item's part number as the key and stores: 7Z The item description - character max length 30 'd The quantity in stock - numeric 'n The re-order level - numeric 'x The unit price - numeric 7 In addition, the first byte of the record is used 8 as a valid data flag. Set to 0 if empty, D if the 3 record has been dele":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,ted or V if the record is valid. 0 This gives a MAX record length of 47 bytes , (Don't forget the CR after the string) : : _initialise !inventry=_open("B:INVENTRY")    5,3);"If you want to:-"' + 10);"End This Session";55);"Type 0" 3 10);"Amend or Create an Entry";55);"Type 1" = 10);"Display the Inventory for One Part";55);"Type 2" =" 10);"Change the Stock Level of One Part";55);"Type 3" @, 10);"Display All Items Below Reorder Level";55);"Type 4" <63) ݤ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%:! 10);"Recover a Previously Deleted Item";55);"Type 5" -@ 10);"List Deleted Items";55);"Type 6" 1J 10);"Set Up a New Inventory";55);"Type 9" T ^ 5,15);bell$; ;h "Please enter the appropriate number (0 to 6 or 9) "; rfunction$= 3| function$>"/" function$<"8" function$="9" function=(function$) ? function dtA,t^B,TjC,DLD,DFE,TDF,djF,d~F,TpG  function=0   "Inventory File Closed" '' #inventry  : :  AMEND/CREATE AN ENTRY :   to update any more stock levels ? ";  ="N"  $: .: '8 DISPLAY ITEMS BELOW REORDER LEVEL B: Lpartno=1 V ` "j "ITEMS BELOW REORDER LEVEL"' tline_count=2 ~ flag=_getrec(partno,"V") # (flag stockmaxpartno line_count>20 temp$<>"" ; 0,23);bell$;"Push any key to continue or E to end ";   "AMEND/CREATE" partno=_getpartno flag=_getrec(partno,"V") &_display(flag) 0'"Do you wish to "; 9: flag "change this entry ? "; "enter data ? "; *D <>"N" flag=_amend(partno): cteos$ N_write(partno,flag,type)  "CHANGE STOCK" Hpartno=_getpartno Rflag=_getrec(partno,"V") \ f_display(flag) p cteos$; z  0,12);cteol$; ) "What is the stock change ? " temp$ change=(temp$) ( (change)=change stock+change>=0  temp$="" flag=: dhC stock=stock+change _display(flag) '"Is this correct ? "; temp$= :  flag temp$="Y" _write(partno,flag,"V")  return$;bell$; 7 "Do you wantline_count=2 6 @flag=_getrec(partno,"D") J flag D|F T "Part Number ";partno ^ "Description ";desc$' hline_count=line_count+3 r: |partno=partno+1 temp$=(0) 2 partno>maxpartno line_count>20 temp$<>"" ; 0,23);bell$;"Push any key to continue or E to end ";  partno>maxpartno ="E" partno=0  : : 2 DUMMMY RETURNES FOR INVALID FUNCTION NUMBERS :  :  : : * REINITIALISE THE INVENTORY DATA FILE &: 0 D: 0,3);bell$;"Are you saxpartno: =fnum fnum=(name$) ) fnum=0 "Disk Directory Full."!!:  _setup(fnum) =fnum :  SET UP THE FILE  : 5 Ask for the maximum part number required, write 3 it as the first record and then write 0 in to %$ the first byte of every record. . : 8 _setup(fnum) B L 0,12);cteos$;bell$; FV "What is the highest part number required (Max 5000) ",maxpartno ;` maxpartno>0 maxpartno<5000 (maxpartno)=maxpartno j #fnum=0 t #fnum,maxpartno ~ partno=1 maxure you want to set up a new inventory?" BD "You will DESTROY ALL THE DATA YOU HAVE ACCUMULATED so far." GN '"It would be safer to use a new disk in drive B and start a new" X "inventory file."' 4b "If you are SURE you want to do it, enter YES" "" partno=(partno$): DZJ 1F partno=maxpartno partno=0 partno=partno+1 P : Z 35,9);partno;cteol$ ') return$=(13) cteol$=(5) cteos$=(4) clrline$=return$+cteol$ rec_length=47 partno=0 desc$=30," ")  temp$=40," ") * 0 4 >: H: .R OPEN THE FILE AND RETURN THE FILE NUMBER \: 7f If the file already exists, the largest permitted )p part number is read into maxpartno. 9z If it is a new file, file initialisation is carried 2 out and the largest permitted part number is " written as the first record. :  _open(name$) fnum=(name$) $ fnum>0 #fnum,m 6d partno>0 partno   (2<(F2P<ZFdPnZxdnx+A$) A"End address: &"A$: A$="" end%=addr%+&8000 end%=("&"+A$) ?"Address for code address 0000: &"B$: B$<>"" O%=("&"" = , : 6 #inventry,desc$ @ #inventry,stock,reord,price J = T : ^ : 0h CALCULATE THE VALUE OF PTR FOR THIS RECORD r : 2| _ptr(partno)=partno*rec_length+5-rec_length  :  :  AMEND THE RECORD  :  _amend(partno)  clrline$;0,4); ; "Please Complete the Details for Part Number ";partno 4 "Just hit Return to leave the entry as it is"' flag= type="V" ) "Description - Max 30 Chars " temp$ " temp$="DELETE" type="D": =  temp$=temp$,30) " temp$<>"" desc$=t F_RSER : 0 EXAMPLE OF READING A SERIAL CHARACTER FILE (: G2 This program opens a previously written serial file and reads it. <: F: Pphonenos= "PHONENOS" 6Z "File Name PHONENOS Opened as Channel ";phonenos d n x#phonenos,name$,phone$  #phonenos _end  name$,phone$  : _end #phonenos  &;honenosPHONENOSBBC(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"+"FINDGBPBBPUemp$:flag= 3 desc$="No Record" desc$="Record Deleted" = ) "Current Stock Level " temp$ %& temp$<>"" stock=(temp$):flag= )0 "Reorder Level " temp$ %: temp$<>"" reord=(temp$):flag= )D "Unit Price " temp$ %N temp$<>"" price=(temp$):flag= X =flag b : l : v WRITE THE RECORD  :  _write(partno,flag,type)  flag  #inventry=_ptr(partno)  #inventry,type & #inventry,desc$,stock,reord,price   :  : DISPLAY THE RECORD 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$="" F_RSER2 : H EXAMPLE OF READING FROM A SERIAL MIXED NUMERIC/CHARACTER DATA FILE (: I2 This program opens a data file and reads numeric and character data < from it. F: ?P When the file is opened its length is read from the first DZ record and used to determine when the end of the data has been Fd reached. A procedure is used to open the file; it sets both the @n file number and the length of the file. In effect it is a "x function returning 2 values. : : 7_open("STATS: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"): Sets both file_num and length stats=file_num EOFstats=EOFfnum 0 "File Name STATS Opened as Channel ";stats   !#stats,name$,age,height,sex$  "Name ";name$  "Age ";age % "Height in centimeters ";height & sex$="M" "Male" "Female"   #stats>EOFstats : " _end ,#stats 6 @: J: >T Open the file and read its length from the first record. D^ Set the file number (stats) and the position of the last valid 4h data byte in the file (eof) - ) ݤ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%:!Die its length-1. r: | _open(name$) file_num=(name$) #file_num,EOFfnum  ave<FFPPZZddnnx 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%=1rs ";height sex$=_read & sex$="M" "Male" "Female"   : : > Read a data item from the file. Treat commas and CRs as A data item terminators and Control Z as the file terminator. @" Since we are not interested in reading a record at a time, B, the record terminator CR LF is of no spacial interest to us. 6: @ _read J data$,byte$,byte Tdat$="" ^ hbyte=#compat r byte=&1A #compat: =| (byte=&0A byte=&0D byte=&2C) data$=data$+(byte)  byS%: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%=1te=&0D byte=&2C =data$ +((22<<FFPPdZndnx ,@|(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 F_RSTD : / EXAMPLE OF READING A COMPATIBLE DATA FILE (: D2 This program opens a data file and reads numeric and character >< data from it. The data is read a byte at a time and the ;F appropriate action taken depending on whether it is a 1P character, a comma, or a control character. Z: d: ncompat=("COMPAT") 2x "File Name COMPAT Opened as Channel ";compat   name$=_read  "Name ";name$ age=(_read)  "Age ";age height=(_read) % "Height in centimete"+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(##^# F_WESER1 : E EXAMPLE OF WRITING A TO THE END OF A SERIAL CHARACTER DATA FILE (: F2 This program opens a file and sets PTR to the end before writing < more data to it. F: *P A function is used to open the file. Z: d: "nphonenos=_openend("PHONENOS") 6x "File Name PHONENOS Opened as Channel ";phonenos    "Name ? " name$  name$="" _end  "Phone Number ? " phone$  #phonenos,name$,phone$  : _end #phonenos  : :  Open the fV#":#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 ile 'AT END'. : E" PTR is set to the last valid data byte+1 and the file number is H, returned. If the file does not already exist, it is still opened, 6 but PTR is left at 0. @: J _openend(name$) T fnum ^fnum=(name$) #h fnum=0 fnum=(name$): =fnum r#fnum=(#fnum)-128 | last_PTR=#fnum #fnum,dummy$  #fnum dummy$="" #fnum=last_PTR =fnum ave>":";{2:!::: ;2 ;!2D>!:>*:A*:::_7>G{>H7>G#>y>> O7>xF>>*:A F_WESER2 : G EXAMPLE OF WRITING AT THE END OF A SERIAL MIXED NUMERIC/CHARACTER ( DATA FILE 2: I< This program opens a data file, sets PTR to its end and then writes (F numeric and character data to it. P: GZ If the file is being opened for the first time, a dummy length is Ed written as the first record. When the file is closed the first Cn record is changed to the value of PTR. Functions are used to Fx open and close the file. The closing function returns the final , vab: Dl Accept a name from the keyboard and make sure it consists only Cv of spaces and upper or lower case characters. Leading spaces ) are automatically ignored on input. :  _name  name$,FLAG,n  FLAG=  "Name ? " name$  name$="" TBC  I=1 (name$) n=(name$,I,1)) 3 (n=32 n>64 n<91 n>96 n<123) FLAG=  1 FLAG "No funny characters please !!!"  FLAG =name$ :  : J* Accept the age from the keyboard and round to one place of lue of PTR (the length of the file). : D Functions are also used to accept and validate the data before  writing it to the file. : : stats=_open("STATS") 0 "File Name STATS Opened as Channel ";stats   name$=_name  name$="" _end age=_age height=_height sex$=_sex  !"#stats,name$,age,height,sex$ , 6: @ _end 4J "The last byte was written at ";_close(stats) T ^: h: Dr Open the file and, if it exists, set PTR to the end and return decimals. F4 Ages of 0 and less or 150 or more are considered to be in error. >: H _age R age \ f "What age ? " age =150 "No impossible ages please !!!" z age>0 age<150 =(age*10+.5)/10 : : E Accept the height in centimeters from the keyboard and round to F an integer. Heights of 50 or less and 230 or more are considered  to be in error. :  _height  height  ' "Height in centimeters ? " height 4 height<=50 height>=230 D| the file number. If it does not exist, open it, write a dummy < length as the first record and return the file number. :  _open(name$)  fnum,ptr fnum=(name$) 3 fnum>0 #fnum,EOFfnum:#fnum=EOFfnum: =fnum fnum=(name$) #fnum,0 =fnum : : E Write the length of the file to the first record and then close / the file. Return the length of the file. :  _close(fnum)  EOFfnum &EOFfnum=#fnum-1 0#fnum=0 :#fnum,EOFfnum D#fnum N=EOFfnum X: "Verry funny !!!"  height>50 height<230 =(height+.5) : : H$ Accept the sex from the keyboard. Only words beginning with upper B. or lower case M or F are acceptable. The returned string is 8 truncated to 1 character. B: L _sex V sex$,FLAG ` jFLAG= 't "Male or Female - M or F ? " sex$ +~ sex$<>"" sex$=((sex$,1,1)) 95) $ sex$<>"M" sex$<>"F" FLAG= - FLAG "No more sex(es) please !!!"  FLAG =sex$ N GePZZddnnxx F_WSER : 8 EXAMPLE OF WRITING TO A SERIAL CHARACTER DATA FILE (: F2 This program openes a data file and writes serial character data @< to it. The use of OPENOUT ensures that, eaven if the file >#͏/% 88 OGI _ͺ-͏/, ,(>U/) x<=-#͏/zѷG  n;honenosPHONENOSBBCcFRED 0123 23445 DOUG WATTON 882110 NOEL ATTLEBOROUGH 452163 JOHN(?~(_( ~#(#~## ~_(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(Eoction returns the final value of PTR (the length of the file). : D Functions are also used to accept and validate the data before  writing it to the file. : : stats=_open("STATS") 0 "File Name STATS Opened as Channel ";stats   name$=_name  name$="" _end age=_age height=_height sex$=_sex  !"#stats,name$,age,height,sex$ , 6: @ _end 5J "The final byte was written at ";_close(stats) T ^: h: Er Open the file and write a dummy_>--~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}/ length (0) as the first record. | Return the file number. :  _open(name$)  fnum fnum=(name$) #fnum,0 =fnum : : E Write the length of the file to the first record and then close / the file. Return the length of the file. :  _close(fnum)  EOFfnum EOFfnum=#fnum-1 #fnum=0 #fnum,EOFfnum &#fnum 0=EOFfnum :: D: DN Accept a name from the keyboard and make sure it consists only CX of spaces and upper or lower case characters. Leading space F_WSER2 : ? EXAMPLE OF WRITING TO A MIXED NUMERIC/CHARACTER DATA FILE (: E2 This program opens a data file and writes numeric and character D< data to it. The use of OPENOUT ensures that, even if the file 64 n<91 n>96 n<123) FLAG=  1 FLAG "No funny characters please !!!"  FLAG =name$ : : J  Accept the age from the keyboard and round to one place of decimals. F Ages of 0 and less or 150 or more are considered to be in error.  : * _age 4 age > H "What age ? " age |ٴ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?=150 "No impossible ages please !!!" \ age>0 age<150 f=(age*10+.5)/10 p: z: E Accept the height in centimeters from the keyboard and round to F an integer. Heights of 50 or less and 230 or more are considered  to be in error. :  _height  height  ' "Height in centimeters ? " height 4 height<=50 height>=230 "Verry funny !!!"  height>50 height<230 =(height+.5) : : H Accept the sex from the keyboard. Only words beginning witB .)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}|h upper B or lower case M or F are acceptable. The returned string is  truncated to 1 character. $: . _sex 8 sex$,FLAG B LFLAG= 'V "Male or Female - M or F ? " sex$ +` sex$<>"" sex$=((sex$,1,1)) 95) $j sex$<>"M" sex$<>"F" FLAG= -t FLAG "No more sex(es) please !!!" ~ FLAG =sex$ ave<FFPPZZddnnxxշBRRP separated by commas. Each record is terminated by CR LF 0Z and the file is terminated by a Control Z. d: n: ?x Functions are used to accept and validate the data before  writing it to the file. : : 5record$=100," "): Resbe in error. b: l _age v age   "What age ? " age < age<=0 age >=150 "No impossible ages please !!!"  age>0 age<150 =(age*10+.5)/10 : : E Accept the height in centimeters from the keyboard and round to F an integer. Heights of 50 or less and 230 or more are considered  to be in error. :  _height  height  '  "Height in centimeters ? " height 4 height<=50 height>=230 "Verry funny !!!"   height>50 height<230 *=(height+.5) 4erve room for the longest 4name$=20," ") record necessary. It saves 0: on string space. compat=("COMPAT") 2 "File Name COMPAT Opened as Channel ";compat   name$=_name  name$="" _end age=_age height=_height sex$=_sex  3"record$=name$+","+(age)+","+(height)+","+sex$ ,#compat,record$ 6#compat,&0A @ J: T _end ^#compat,&1A h#compat r |: : D Accept a name from the keyboard and make sure it consists: >: HH Accept the sex from the keyboard. Only words beginning with upper BR or lower case M or F are acceptable. The returned string is \ truncated to 1 character. f: p _sex z sex$,FLAG  FLAG= ' "Male or Female - M or F ? " sex$ + sex$<>"" sex$=((sex$,1,1)) 95) $ sex$<>"M" sex$<>"F" FLAG= - FLAG "No more sex(es) please !!!"  FLAG =sex$ Necord$dBPAULINE SMITH,32,153,F only C of spaces and upper or lower case characters. Leading spaces ) are automatically ignored on input. :  _name  name$,FLAG,n  FLAG=  "Name ? " name$  name$="" TfB  I=1 (name$) n=(name$,I,1)) 3 (n=32 n>64 n<91 n>96 n<123) FLAG=  1 FLAG "No funny characters please !!!" & FLAG 0=name$ :: D: JN Accept the age from the keyboard and round to one place of decimals. FX Ages of 0 and less or 150 or more are considered to "d. MERGE UTILITY FOR BBC BASIC n. R.T.RUSSELL, 16-10-1982 x: $ A(1),B(1),C(1),F(1),L(1),A$(1) :   "FILE 1",F1$ F(0)=(F1$)  F(0)=0 "File not found" F(0)<>0 :   "FILE 2",F2$ F(1)=(F2$)  F(1)=0 "File not found" F(1)<>0 :  "OUTPUT FILE",F3$ F3=(F3$) !" F3=0 "Directory full" : ,: 6READ(0):READ(1) @ 7J L(0) ̈́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:> !/> A program using assembler code for a fast string sort. SORTREAL.BBC A program using assembler code for a fast numeric sort. F-????.BBC A set of example programs illustrating file input/output. ANIMAL.BBC An example of a 'learning' program written in BBC BASIC. ANIMAL.DAT The initial data file for ANIMAL.BBC READ.ME This file! To exit BBC BASIC (Z80) type *BYE The Z80 Tube CP/M version of BBC BASIC (Z80) is made available for free download on theHHͯ :!^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* condition that it always be distributed with the above files. BBCBASIC (Z80) and the accompanying files remain the Copyright (C) of R. T. Russell, 1982-2000. Richard Russell, 8th June 2000. Email: richard@rtrussell.co.uk Web: http://www.rtrussell.co.uk/    *}2D" * * *&"!q:UY: Y:ҩ: ʩ:_2ʘ:€!6<:<2!ژ!6 >!]Ҥ; !6:Q::H: !6*M : !6!q:a/>z!This is version 2.20 of BBCBASIC(Z80). The files supplied are as follows: BBCBASIC.COM The BBC BASIC (Z80) interpreter for Tube CP/M systems. BBCBASIC.TXT A plain text documentation file for BBC BASIC (Z80). CONVERT.COM A utility for converting .BBC files to/from .BAS files. CRC.COM A program to test the integrity of the supplied files. CRCKLIST.CRC The data file for CRC.COM. MERGE.BBC A BBC BASIC program for merging program files. SORT.BBC /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ͬ!\. . 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."':  &86: "INFO "+dfs$ : 11:A%=135: X=1 39:X,);:A$=A$+((&FFF4)256): ':size=("&"+A$,29,6-:>>!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)) = size>&8000 "Sorry, file too big for this method."': "*LOAD "+dfs$+" "+~buffer * "SAVE "+cpm$+" "+~buffer+"+"+~size  r=:[ ͱ!N5!6:%:<2*6 * 6å!q!6> !d*&I :]>!4A>:<2O* :w:?†!6!q!6?!:ҠgÐ!q*&*~!6:22: :]Hں:A2O>: 2ͯ " . SHELL SORT ON STRING ARRAYS =. (c) Richard Russell 1982, from an idea by Robin Tracy.  sort 300 (exterr=&209 2 pass=0 1 <P%=sort F[OPT pass*2 PLD A,(IX):DEC A:JP NZ,error "ZLD A,(IX+1):CP &81:JP NZ,error )dLD L,(IX+2):LD H,(IX+3):LD (start),HL HnDEC HL:LD D,(HL):DEC HL:LD E,(HL):DEC HL:LD A,(HL):DEC A:JP NZ,error ExLD HL,(start):ADD HL,DE:ADD HL,DE:ADD HL,DE:ADD HL,DE:LD (end),HL #SRL D:RR E:LD HL,&FFFF:EX DE,HL :.rotate SRL D:RR E: A:SBC HL,DE:ADD HL,DE:JR C,rotate 8EX 000 6-character strings..." r A$(999) 6| I=0 999:A$(I)="PQRS"+(64+(26))+(64+(26)): % I=0 14: A$(I),;:: "etc..."  "Sorting the strings..." : sort,A$(0) : . Call assembly language sort routine. % I=0 14: A$(I),;:: "etc..."  "Finished." Aort @~= A~ Anf"A+V+^+~= A*A"A:!:R8))"A*A"A" A~8DE,HL:ADD HL,HL:ADD HL,HL:LD (spacer),HL:EX DE,HL K.loop LD IY,(start):PUSH IY:ADD IY,DE:LD (check),IY:POP IX:LD (item),IX @.newlen LD A,(IX):CP (IY):JR C,short:LD A,(IY):.short LD B,A A A:JR Z,null:LD E,(IX+2):LD D,(IX+3):LD L,(IY+2):LD H,(IY+3) F.next LD A,(DE):CP (HL):JR C,ok:JR NZ,swap:INC DE:INC HL:DJNZ next $.null LD A,(IY):CP (IX):JR NC,ok 4.swap PUSH IX:POP HL:PUSH IY:POP DE:LD B,4:.move JLD A,(DE):LD C,A:LD A,(HL):LD (DE),A:LD (HL),C:INC HL:INC DE:DJNZ move @LD DE,(check):PUSH IX:P( . SHELL SORT ON REAL NUMERIC ARRAYS =. (c) Richard Russell 1984, from an idea by Robin Tracy.  sort 300 (exterr=&209 2 pass=0 1 <P%=sort F[OPT pass*2 PLD A,(IX):DEC A:JP NZ,error ZLD A,(IX+1):CP 5:JP NZ,error )dLD L,(IX+2):LD H,(IX+3):LD (start),HL HnDEC HL:LD D,(HL):DEC HL:LD E,(HL):DEC HL:LD A,(HL):DEC A:JP NZ,error x; CLD HL,(start):ADD HL,DE:ADD HL,DE:ADD HL,DE:ADD HL,DE:ADD HL,DE BLD (end),HL:SRL D:RR E:LD HL,&FFFF:EX DE,HL:.rotate SRL D:RR E ; A:SBC HL,DE:ADD HL,DEOP HL: A:SBC HL,DE:ADD HL,DE:JR C,ok DPUSH HL:POP IY:LD DE,(spacer):SBC HL,DE:PUSH HL:POP IX:JR newlen 3.ok LD HL,(item):LD BC,4:ADD HL,BC:LD (item),HL :PUSH HL:POP IX:LD DE,(spacer):ADD HL,DE:PUSH HL:POP IY ELD DE,(end):SBC HL,DE:JR C,newlen:LD DE,(spacer):SRL D:LD A,E:RRA 2 &FC:LD E,A: D:LD (spacer),DE:JP NZ,loop:RET =".start W 0:.end W 0:.spacer W 0:.check W 0:.item W 0 ,.error LD A,100: exterr:] 6$P%="Bad sort parameters"+0 @ pass J: T. Test program: ^: +h "Filling 1:JR C,rotate:.loop LD (space),DE GLD H,D:LD L,E:ADD HL,HL:ADD HL,HL:ADD HL,DE:LD (spacer),HL:EX DE,HL ELD IY,(start):PUSH IY:ADD IY,DE:LD (check),IY:POP IX:LD (item),IX ; .newlen EEXX:LD L,(IX):LD H,(IX+1):EXX:LD L,(IX+2):LD H,(IX+3):LD C,(IX+4) EEXX:LD E,(IY):LD D,(IY+1):EXX:LD E,(IY+2):LD D,(IY+3):LD B,(IY+4)  fcp:JR C,ok ; 4.swap PUSH IX:POP HL:PUSH IY:POP DE:LD B,5:.move JLD A,(DE):LD C,A:LD A,(HL):LD (DE),A:LD (HL),C:INC HL:INC DE:DJNZ move @LD DE,(check):PUSH IX:POP HL: A:S8L%Z80 BASIC1.26 (01 Mar 2009)(C)J.G.Harston!`6>*2! bKʩL `">+w!"!""!"ͰS#22>!>Z! u>!ùBASICs1ͷ1ʩ*þý*×Ä Îòz ë2Î221!:6 ,6 ,w, =2:!v":|4S:":ͪs Acorn BBC BASIC Version 2.20 (C) Copyright R.T.Russell 1983 7{:%!:~0w!":":*:":|( K: -":> Z !8ͱ42:!8ͧ ͏/|(":9 GK*:|BC HL,DE:ADD HL,DE:JR C,ok DPUSH HL:POP IY:LD DE,(spacer):SBC HL,DE:PUSH HL:POP IX:JR newlen ; 3".ok LD HL,(item):LD BC,5:ADD HL,BC:LD (item),HL :,PUSH HL:POP IX:LD DE,(spacer):ADD HL,DE:PUSH HL:POP IY >6LD DE,(end):SBC HL,DE:JR C,newlen:LD DE,(space):SRL D:RR E @LD A,D: E:JP NZ,loop:RET J; @T.fcp LD A,H:XOR D:LD A,H:RLA:RET M:JR NC,fcp0: fcp0:CCF:RET C^.fcp0 LD A,C:CP B:RET NZ:SBC HL,DE:RET NZ:EXX:SBC HL,DE:EXX:RET h; =r.start W 0:.end W 0:.spacer W 0:.check W 0:.item W 0 *|.space !9ʪ ͎͑ NyʘO*: $r":#RDM(#q#s#r#9 ̓ØANDABSACSADVALASCASNATNAUTOBGETBPUTCOLOURCOLORCALLCHAINCHR$CLEARCLOSECLGCLSCOSCOUNTDATADEGDEFDELETEDIVDIMDRAWENDPROCENDENVELOPEELSEEVALERLERROREOFEORERREXPEXTFORFALSEFNGOTOGET$GETGOSUBGCOLHIMEMINPUTIFINKEY$INKEYINTINSTR(LISTLINELOADLOMEMLOCALLEFT$(LENLETLOGLNMID$(MODEMODMOVENEXTNEWNOTOLDONOFFOROPENINOPENOUTOPENUPOSCLIPRINTPW 0:.error LD A,100: exterr:] $P%="Bad sort parameters"+0  pass : . Test program: : @%=20 $ "Filling 1000 real numbers..."  A(999) / I=0 999:A(I)=(0.5-(1))*10^(10-(20)): % I=0 14: A(I);:: " etc..."  "Sorting the numbers..." 9 sort,A(0) : . Call assembly language sort routine. % I=0 14: A(I);:: " etc..."  "Finished." @%=&90A DortB~=šC~šCnf"C+V+^+~=šC*C"C:!:R8SCbk))"C*C"C"CnfAGEPTRPIPLOTPOINT(PROCPOSPUTRETURNREPEATREPORTREADREMRUNRADRESTORERIGHT$(RNDRENUMBERSTEPSAVESGNSINSQRSPCSTR$STRING$(SOUNDSTOPTANTHENTOTAB(TRACETIMETRUEUNTILUSRVDUVALVPOSWIDTHHIMEMLOMEMPAGEPTRTIMEMissing No such Bad  rangevariableOut ofNo  spaceroomMistake,Type mismatch"Not ArraySubscriptSyntax errorEscapeDivision by zeroString too longToo big-ve rootLogAccuracy lostExp)HEX/callArgumentsZ x()T]))7c ~( h>~$(b!(b?(b ~( A~(##I/VN#F#%B>0= U/W~?(!(z>>!z,#m~ ~!:(C!:(<7@&0o~% ~(():##;?=ol:--7^#Vz(Ebk##~##(( +~((# 8 ((~ 0~$%<ɯ[:r+sw#w## 8w# 0(( ~((#6#Q >(=6#= ":I͏/-+|-ͧ | . L#! ħ xSillyͧ L#ħ ͑ ~$%(0:?Can't match  syntaxline #͎ ~(Q#^#Vz(++7B0@N#V}2:ØO( x  !:>~(#^#Vz(#7Bҗ":=o4Ͳͷ *:[:~(/#N#Fx(q#p# -q#p#++GN $r86#6[:*:Ny(##^#V#":#s#r# > ͱ)DM*:^#V#B^#V#8( Failed at *: S ͼ ͷ ":y2:) program ͪ*:###> }w̓Ø_> iͲ͎3> [:*:RDM!8r1×{:!8( G# ":{:2:ͪ ":( *:|ª !":":A[?_{?ɯ#{0~ 0˩˙ (,(G8˙" ?a(ˡͧ |ļ  ( *(80@( ( ( 8& !  !   :6#zG{Tw#{?@w#z?@w#*:~#s  ];jw|20FYm f=1C##0 d0 .1*CQ10OR0}#`nh M1L( _> {:i{:!:_(wwͲ!":*:>":*: ":o4͏/#:( (8oO! ~#fo͏/ͪ |ʘ×~ (*:|V^R>[S S Ø!W~F#(#~(#~ #~.(( 8~ +xN *:RDMS:[:!9RDM!8ͻ1Ԫ>͎+6+6$*:> N ( +#(i###":*:6ͣ*:":":!l:p6# ~6 6 > FZ xNĬyVĬ~6 6 ~# (F" * ͱ) C ,(s ~( D (  Q > Z > (::<2:*:Z !W~#Z *:<ЯGN#~#foR Û [:*:R0N ( R8B#^#V":!*:| at line  'R<0=(Z >]Z > Z _> !8> Gç (d(w(L2+ʪ 86X_ê ":o4K8 (!:~0w%  >!>FC!,B(!B> ":8Xx!9Y% 8{Xc ~(z rB#V| W##u#t%8F~,(U/#p8+8($($r0 ":z(+6͏/,ª #͏/> !> (PG~)x(*:!LV#*:# kC͏/,ª #Fs3>@͎2͐3͔3͘3͞3&8kѯ͎2}͎2,-(-~͎2"!:(::( (0Dͬ::OL(8ˀ#~(ª #͏/>#>*V-(~ª #͏/ª î~ #ʧ /2:ê ͪ S Øͳ1ê Ͳ*:*:L( m͑ >) >":ê 9X{Vy2ê XV.":ê &3V/ê XVͲ":":ê XV[:R[:":rª ê V}2:ê #!( (+V+":ê V}~,(; |#L ê 91ê 9I/V}͎2ê V9͏/, #͏/zs#rx29͐ê m$!!:K1N~FN V^f n0!9OVI/Viê %  XOG(qutut;(,(e(+F)J*)yԬͺ@S ê #!":͏/#ʪ +":#(V~#(>' Cx )(&G (L(#, mx(%L(1#~#( >(mL͑ ʧ >)mIͱ!Rʪ >&Iͪ !B>+ V- ê >" ~>$ #OG!L!~ #OIͪ !OB> sL% R P!9Ͷ ~ z> ͨ/!9Ͷ ,>ͨ/$ !9͏/,ª #ê !9!OB(>!I+ (9>8*:>8!#͏/ ,(u!80? {o|ٻ0eO K:B7(`iK S:*:$rدKѯG(> >#͏/% 88 OGI _ͺ-͏/, ,(>U/) x<=-#͏/zѷG& KI!EB9G( 8E,I͏/,(~ ,);\͏/: ͏/#=>( (8'S V~,(U/}!:S #VU/ 0m}G> Z !8~#Z ͏/8~ #͏/"#= +8~, #8 c s#r> G > ^#V!9͏/( ͏/(U/es#rê !B(!B( !,B> +% -Y͏/,ª #͏/!,B(!Bʪ > x!9YC͏/,ª #͏/zͫ2ʲ33333ͫ2ͫ2o&8,-ʤ3-ͫ2w>>#( #!96 Lʪ #,(M;(I" = ͺe +z~# ̚y!ˁA >?Z Z !9ͱ4G2:~ ##*:~# zO":͏/,N ( ### +7bk))!>)#0 = ͏/#>-#m#:(] +*@:!:v(*<:7+#~R ::R*@:"@:w(*<:"<:g(|}(::>Ԇ~# >͆B s - S K> Ɛ'@'s . #z-*@:#+!xH'0h 0h=U0\K 02x =y0(F x? 7y (O0CydO`y0!C$(x7y%0$Iy0> [@:7R}>}2G Iy0 x' '))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_>--~7*( /((b/7p/;͏/^b/;p/F%F,F;;,;>FU/-/8#ͅ-ͅ-ͅ-ͅ-ٵo/0>f ,|gI͏/#&(-(+((("(cҕ2Ҡ/+:000t.(p% + (?>( > + |   }x Iy0p llu0_C((j`>G\x? y >==y0w `ͺ0 \ͺu !:Ooygxm_!8~#x8x? yyC7y0h(D&>.>v7{ !xxX]>p(>Ww#~)!V}x??2/2&x07>x ?O!_7(?~(_( ~#(#~## ~_(8 xF#8D#+-NORLCEXAFAFRRCRLRRDA'CP/SC7CG(Nnfnf!&nLځ::o> ## 0!@:O8~#"(  0> ~"#(+>-+.+E>̍+|   Ȑͧ,˼ 1.c(8 D1.'>&1.'&F^V^V80 }ٷO>~# > f| ,˼m|/g}/o|/g}/oٯ0u0p92ʦ)-9ͫ2oY<&͏/( mDMhCL&vʦ)*81v+*:(*:#*:~#P*:*: *:*:&ٯOgo7v> !8o92 923O!I!!c(!'f,.ef-|¦)-,vC?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 DJNJCALRSREL@]]OP](H(I؆(IBD H I،IASNNPP( IGROAWA_(BC(DEA(B A(D)l2!c!!Y!^! $X0F!$-%"!:#!!w!|!"#!-0!+!%"S!h$$ t2p2!"0 !!E"!H#"#h!)!!/&L&<&&R&&*&!&K'&!8͏/;/b ->óv> 8!8 ͺ-!9F9!:͏/((  jj](?Om!:|7 -, S"ͧ,˼{=ٳ,,c(,,f >D+,x,Of,|> A,yր/ƀO!DM!DM>.x./͈.`i`i,,O˼f,ͥ-@#ͮ-ͥ-,N#ͮ-'f,6,{f,6,˼#h'#ͥ-͟- .6m&sy}ͮ-ͮ-c(ú#͟- .qxLpvȜ*{~ͮ- If,]$F,{( ->怳B?,,,y?Ü(||,,|,DM!DM!>͛.- z ,J, #jjJ(˼- |DM!DM!>͛.ܯ.!R,,,y8--ƀO-˼,|,H ͅ-8,L!9(4,T$#> ͗-ͨ/Ͷ ܨ/yOz,ͥ- (>8<+),n$ͮ-c(#@-- -Q@-- -@@-- -0@-- -(!@-- -@-- -!!ٯO~#g#o|#gٯOgo#f)>,8ͅ- ( (Ɛ'μͥ- .r@.seoO.v7my*{O}V~ͮ-T$?$Dƀ8--ƀ-O#,'r1f,>| 53"-y8 <-ͥ-͟- .Ht}~L~㩪*ͮ-ͮ-c(ͥ--ր(0/ #ͺ-V-}ٷ(=DC8_! x@'G͏/~(f!:~!+(!:8,|(˼>-(Gxy00%/8>1.c(G 1.'G> 1.-yO\-˹> xN ݾ( >݆*ͅ- 8 , O|?g*< >>y00(:?0u >0<=- > >8^F 2N(x(+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#| ,,+-,ͷ(# ( #((78{ٸ8m/8>7F/ͺ-V-}ٷ( =o0DOͩ&͏/,#( +U/>F/ͺ-V-U/}ٻ0k_>̓&K}obX>VI/}_U/(=O>Cb.~#> >+|g}o|g}o+|g}o|g}o+|g}o|g}o+|||,,|,DM!DM!>m.,+',,n-h-͸,zW|g h-n-͸, ,|x,x+z'h-, n-(,͕,/!B,,,˼ -͸,> |BKBK>m.z̈.8,, |>+ȷ!R!R/!BDM>>#i!y!8:BRR0 ZZ?0=8)jj0շBRR|ٴ8->gogoO,-yRR||0-?|"-|E- ( ( # 7ɷ  ͘-͋-͋-ZٷRR͘-ͅ-ͅ-h-)j <AT]T]͗-c(yAOI!8TER9W( K8I!D98 (ͥ-#x'ͮ-ͥ-,#w# ++67"M7կ_8/SW7# "[7i1"Y7"]7!"Q7"U7!"O7&"S7Q2!M7>Can't open file>@>>Î!SO7_y> >2ê c((U3Æ!*:Æ!c>lÄ!>k}/>!"O72*M7[O7!_AÌ"M7!M7~$(/ò!#!86>~_(8>~$(Xó#X_{( bkK+!8s>ê ~$ #*:8~#{  >>͎2͞3͘3͔3͐3y(<͎2Ä|Î2}Î2|Î2}Î2o3333ͫ2O ͫ2gͫ2oͫ2gͫ2o~ _*:### 4_ 4>_#b'ͮ-'!9Ͷ c(Ͷ x'x'Ͷ <#,=( I.8<<^-0͋-, >.-,˺ɷBB0 J?=<#+-+_͏/#,> ͏/#)>#{{yGͨ/~~ #Ï/!:֍! xĴ,!ŇO ~#fo>!M7!M7nf^V!M7utsr>!M7> >8~# ~# (7*: 8|~Ä>28!h4"9!d4">2>24>>.|;0&;!M7ut66 6>2!M78ɯ8!N#(6 LFZ80 needed Z80BASIC ROM Header (C)J.G.Harston BBCBASIC(Z80) code (C)R.T.Russell 9: HLQL%L 00hHL L*-zhHLݶLLh`H 0r,zm nH ) e 8  H h?*))鮌)OH K|}7>{}>]lbVI/VU/!M7srut!M7> ~oggoOm>!M7Vux ( #I/!M7>ê !M7Vut##x(I/!M7>ê . .VI/VI/V>y{z}|ê V2:>}ê >ê V>}ê VI/V>{}ê !^1~^fdn`}lghyg>"Q742>W2g> ͤ1>(ͯ1ͮ1ͮ1ͯ1  "M7SO7i12S7=Q2 ;wG#p#w<(&$(#%c++ 5## @ )hh`H @qᩎLȱåZc* [ 0)@) h` Z LV bhHH   hh` .)Z ֶ bh`H LH.) Y !M - ! 2  y z {N L3hh`ɀH hL{ |   `y z { ` `Lhɾ1ȱ%ȱPU 'U ``Z80 8080/8085 JJJH)h)Hh)iA9 L0) 0`T H hHJJJJ Ch) ii0`L*)i/`&77k`.0jɧ@-@獥<"cb$Cx XӾwo0<(tvX.ݖE]* RTOJ_1Htb%Tλnk!ezx p"iEm1p\ʥ_:U} 66ib1WŹ7dʙ}ШPqCX@F:䃚Ekql^UHQ^,(8Z8ThŒJ[%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. =================================