IMD 1.16: 8/06/2007 19:17:22                    PAS2CPM ASM;RUN COM\ RUN2-2 COM\ RUN2-3 COM\BAS2-0 COM`BAS2-1 COM` !"#LIB C .$%&LINKASM DOC!'()LINKASM COM,*+,PASCAL ASM4-./0PASCAL COM123456789PASCAL DOC:PASTOCPMASM\;<=>?@SMALLC2 COMABCDEFGHIJKLMNOPSMALLC2 COMQINDXREF DATR;*********************************************** ; ; P A S 2 C P M . A S M ; PROGRAM TO BRING A PASCAL FILE OVER FROM A PASCAL DISK ; TO A CP/M DISK. CP/M=A: PASCAL=B: ; ; PAS2CPM , ; ; ; WRITTEN BY RON PARSONS ; ; REF. DDJ. VOL. 37 PG. 12 ; ; MOD'D IN ACCORDANCE WITH ; DDJ. VOL. 42 PG. 42 ; MODS SUPPLIED BY JIM WARNER UC,SANTA CRUZ ; ; MODS TO RTN.S RB THRU SETEOF ; ADD RTN. GETBYT ; ; PURPOSE OF MOD.--ELIM. ERROR WHEN A 'DLE' -SPACE CODE ; FASMALLC1 COMySTUVWXYZ[\]^_`abSMALL-C DOCcLINK COMbdefghijFUNCTIONCRLkRUNTIME COMlSTDIO H mZCMD DOCnZCMD ASMopqrstuvwxyz{|}~ZCMD ASM}ZPASS ASMFAST2MANDOC$FAST COMFORTH COM4LLS ON A 512 BYTE BLOCK BOUNDARY ; ;************************************************* ; ; STACK EQU 0ABFFH CBIOS EQU 0AE00H DLE EQU 10H CBOOT EQU 0 DENTSZ EQU 1AH DTITLE EQU 06H BLKBUF EQU 1000H DIRTOP EQU 2000H ; ORG 100H LXI SP,STACK ; LXI H,BUFF+1 LXI D,SYSTLE+1 MVI C,0 CALL SCBK CALL SCBKCH PFN2 MOV A,M CPI 0 JZ PFN3 STAX D INX H INX D INR C JMP PFN2 PFN3 MOV A,C STA SYSTLE ORA A JZ NOFLNM ; CHECK FOR .TEXT OR .CODE FILENAME LXI D,TEXT+6 DCX    H PUSH H MVI C,5 TEXTLP LDAX D CMP M JNZ NOTEXT DCX H DCX D DCR C JNZ TEXTLP LXI H,TXTFLG MVI M,2 LXI D,TEXT MVI C,WRITECB CALL BDOS NOTEXT POP H LXI D,CODE+6 MVI C,5 CODELP LDAX D CMP M JNZ NOTCODE DCX H DCX D DCR C JNZ CODELP LXI H,TXTFLG MVI M,1 LXI D,CODE MVI C,WRITECB CALL BDOS NOTCODE LXI D,FCB MVI C,OPENF CALL BDOS CPI ERNXF JZ CREF LXI D,PERMSG MVI C,WRITECB CALL BDOS RDCHR MVI C,READC CALL BDOS CPI MODE JZ  JMP SKPBL1 SKPBL2 DAD H DAD H SHLD LSN LR80B CALL R80B LDA EOFFLAG ORA A JNZ FILL1A CALL WB JMP LR80B FILL1A LDA TXTFLG CPI 2 JNZ FILL2 CALL CT CALL WB FILL2 LXI D,FCB MVI C,CLOSEF CALL BDOS JMP CBOOT ; ;************************************ ; ; SUBROUTINES ; ;************************************ ; READ$DIR EQU $ MVI E,4 LXI H,2 CALL SYSRD RET ; ; FIND$FILE EQU $ MVI C,77 LHLD DENTP FI$SCH$LP EQU $ LXI D,DTITLE DAD D LXI D,SYSTLE LD H MOV C,L CALL SETSEC MVI C,1 CALL SELDSK CALL READ POP H POP D POP B PUSH H LXI H,128 DAD B MOV B,H MOV C,L POP H INX H DCR E JNZ RR$LP RET ; ; RDSEC MVI C,DMAADD CALL BDOS LHLD LSN CALL MAP MOV C,L CALL SETSEC MOV C,H CALL SETTRK CALL READ ORA A JNZ RWERR LHLD LSN INX H SHLD LSN RET ; CT LHLD EOB INX H XCHG LHLD BOL CT1 CALL EQUAL RZ MVI M,CTRLZ INX H JMP CT1 ; EQUAL MOV A,L CMP E RNZ MOV A,H CMP D RET ; COM CPI 2 JNZ NOT$TXT RBCKLF LDA NLF ORA A JZ RBCKTB XRA A STA NLF MVI A,LF RET RBCKTB LDA NTB ORA A JZ RBFB DCR A STA NTB MVI A,' ' RET RBFB CALL GETBYT ORA A JZ RBFB CPI CR JNZ CKDLE STA NLF RET CKDLE CPI DLE RNZ CALL GETBYT SUI 32 STA NTB JMP RBCKTB NOT$TXT CALL GETBYT RET ; GETBYT EQU $ LHLD BUFADD LXI D,BLKBUF+512 CALL EQUAL CZ RBLK ;RETURN WITH HL--BLKBUF MOV A,M INX H SHLD BUFADD RET ; ; RBLK EQU $ LHLD LSN XCHG LHLD LST STA ERRMSG JMP GENERR ; MAP PUSH B PUSH D ; CALL DIV26 MOV A,L ADD A MOV B,A MVI A,12 CMP L JNC MAPC INR B MAPC MOV C,E XRA A MOV D,A MOV A,H MOV L,B MVI A,6 MAP$LOOP EQU $ DAD D DCR A JNZ MAP$LOOP PUSH B CALL DIV26 POP B INR L MOV H,C INR H POP D POP B RET ; ; DIV26 LXI B,-26 MVI E,0FFH DIVL INR E DAD B MOV A,H ORA A JP DIVL LXI B,26 DAD B RET ; ; ; NOFLNMSG DB CR,LF,'MISSING FILE NAME$' NOFMSG DB CR,LF,'FILE DOES NOT EXICBOOT CPI CR JNZ RDCHR LXI D,FCB MVI C,DELETEF CALL BDOS CREF LXI D,FCB MVI C,CREATEF CALL BDOS CPI ERNDR JZ CERROR INIT LXI H,BUFF SHLD BOL LXI H,BUFF+127 SHLD EOB LXI H,BLKBUF+512 SHLD BUFADD ; LXI B,DIRTOP CALL READ$DIR ; LXI H,DIRTOP LXI D,DENTSZ DAD D SHLD DENTP ; CALL FIND$FILE ; LHLD DENTP MOV E,M INX H MOV D,M PUSH D INX H MOV E,M INX H MOV D,M XCHG DAD H DAD H SHLD LSTLSN POP H LDA TXTFLG SKPBL1 DCR A JM SKPBL2 INX HA SYSTLE INR A MOV B,A FI$CMP$LP EQU $ LDAX D CMP M JNZ FI$CONT INX D INX H DCR B JNZ FI$CMP$LP JMP FI$FOUND FI$CONT EQU $ LHLD DENTP LXI D,DENTSZ DAD D SHLD DENTP JNZ FI$SCH$LP FI$HANG EQU $ JMP NOFILE FI$FOUND EQU $ RET ; ; SYSRD PUSH D PUSH H CALL READ$RX POP H POP D INX H DCR E JNZ SYSRD RET ; ; READ$RX DAD H DAD H MVI E,4 RR$LP PUSH B PUSH D PUSH H CALL SETDMA POP H PUSH H CALL MAP MOV C,H PUSH H CALL SETTRK POPPR MOV A,E SUB L MOV A,D SBB H RET ; R80B MVI B,80H LXI H,BUFF R80B1 PUSH B PUSH H CALL RB POP H POP B PUSH PSW LDA EOFFLAG ORA A JZ R80B2 POP PSW SHLD BOL RET R80B2 POP PSW MOV M,A INX H DCR B JNZ R80B1 RET ; WB MVI C,0 CALL SELDSK LXI D,BUFF MVI C,DMAADD CALL BDOS LXI D,FCB MVI C,WRITER CALL BDOS ORA A JNZ RWERR RET ; ; SCBKCH MOV A,M CPI ' ' JZ SCBK INX H JMP SCBKCH SCBK MOV A,M CPI ' ' RNZ INX H RET ; RB LDA TXTFLGLSN CALL EQUAL JZ SETEOF MVI C,1 ;SELECT B DISK-FOUND LAST SECTOR CALL SELDSK LXI D,BLKBUF CALL RDSEC LXI D,BLKBUF+80H CALL RDSEC LXI D,BLKBUF+100H CALL RDSEC LXI D,BLKBUF+180H CALL RDSEC LXI H,BLKBUF SHLD BUFADD RET ; SETEOF LXI H,EOFFLAG MVI M,1 RET ; ; ERROR MESSAGES ; NOFLNM LXI D,NOFLNMSG JMP GENERR NOFILE LXI D,NOFMSG JMP GENERR RWERR ORI '0' STA WERMSG LXI D,WERMSG GENERR MVI C,WRITECB CALL BDOS JMP CBOOT ; CERROR LXI D,ERRMSG ORI '0' ST$' WERMSG DB ' READ/WRITE ERROR$' PERMSG DB CR,LF,'FILE ALREADY EXISTS. $' PERMSG1 DB CR,LF,'C/R TO CONTINUE. CTRL-@ TO ABORT$' ERRMSG DB ' ERROR IN CREATE OR OPEN$' TEXT DB CR,LF,'.TEXT FILE BEING PROCESSED$' CODE DB CR,LF,'.CODE FILE BEING PROCESSED$' ; ; TXTFLG DB 0 DENTP DW 0 EOFFLAG DB 0 NLF DB 0 NTB DB 0 BUFADD DW 0 LSN DW 0 LSTLSN DW 0 BOL DW 0 EOB DW 0 SYSTLE DS 22 ; ; ; CP/M EQUATES ; BOOT EQU CBIOS WBOOT EQU BOOT+3 CONST EQU WBOOT+3 CONIN EQU CONST+3 CONOUT EQU CONIN   +3 LIST EQU CONOUT+3 PUNCH EQU LIST+3 READER EQU PUNCH+3 HOME EQU READER+3 SELDSK EQU HOME+3 SETTRK EQU SELDSK+3 SETSEC EQU SETTRK+3 SETDMA EQU SETSEC+3 READ EQU SETDMA+3 WRITE EQU READ+3 ; BDOS EQU 5 FCB EQU 5CH BUFF EQU 80H ; SYSRST EQU 0 ;SYSTEM RESET READC EQU 1 ;READ CONSOLE WRITEC EQU 2 ;WRITE CONSOLE READRD EQU 3 ;READ READER WRITEP EQU 4 ;WRITE PUNCH WRITEL EQU 5 ;WRITE LIST ; IOSTAT EQU 7 ;INTERROGATE I/O STATUS ALTIOS EQU 8 ;ALTER I/O STATUS WRITECB EQU 9 ;WRITE CONSOLE BMA ADDRESS ALLOCV EQU 27 ;GET ALLOCATION VECTOR ; ERNXF EQU 255 ;NON-EXISTANT FILE EREOF EQU 1 ;E0F RETURN CODE ERURA EQU 2 ;READ UNWRITTEN DATA EREXT EQU 1 ;ERROR IN EXTENDING FILE EREOD EQU 2 ;END OF DISK DATA ERNDR EQU 255 ;NO MORE DIR. SPACE ; CR EQU 13 LF EQU 10 ESC EQU 1BH MODE EQU 0 CTRLZ EQU 1AH ; ; END CREATE FILE RENAMEF EQU 23 ;RENAME FILE LOGINV EQU 24 ;GET LOGIN VECTOR LOGGED EQU 25 ;GTET LOGGED DISK DMAADD EQU 26 ;SET D)+ï +`iN#F#^#V#~#fo}+ !y:!$0w# =>w!$ !$͇ ,0uddvC$0 ʅw#{{6  ͏   y s{Ybw#p#q#r! N#F!q#p2!q!q{9 ~#F#N#V!Y , <    *$A!6 # TI܀1r l7s,w,p,q,r!w>!w!~{_,~,,N,Vê~{_,~,N,VoG!qG{~{̀x!~wbG{ɯ{O!>wx!Kw!Yw!gw!~,V,^B.N qkb_HJx}o|gz'}[kb_PH>}o|g{_>o|g{_>+6* |} !͌!ks͠!k̈́!ks@!os!k͠!o!o!osï!o͠ɯ!ow!"*M"o*O"q!"w կGOy !ss!k͠!oͽ*w!s!M7!os!M͠!s!o!oszWyOI܀1ŕ!Q͌!{s!Q͏ y !Qͽ́!{!{s̈́!Q!Q_!|~G{+s{É!{͠!{ͽ́!ksH!o͠!{ͽ!w,w͌͌s !o4͠!{ͽ!{s!y~HPy !Uͽ!{![N,F-R !P o ![q,p6 c o c o ɗyOxGc ~O,~G-kZQHG}!w,6,xÛ!~ʼ {Ҽ .F,N,V.~ >xAJSɯGOW^P ,6!r{ !r\ ~# . _ !#w!iͽ.s,~HPy ..~ -Fp !w _ \ ~G_? xA ,~ _ G,~ X OxG{_ G!N!qx!ʌw!i~ >h ͽ>h -P ͌!s\ 6ʶ _x{ 6~!iڿ !^sè ͽ!^sæ ̈́!mҨ !~_ w>,w{!w !iͽ͏UFFER READCB EQU 10 ;READ CONSOLE BUFFER CONSTAT EQU 11 ;CHECK CONSOLE STATUS LIFTDH EQU 12 ;LIFT DISK HEAD RSTDS EQU 13 ;RESET DISK SYS. SELECTD EQU 14 ;SELECT DISK OPENF EQU 15 ;OPEN FILE CLOSEF EQU 16 ;CLOSE FILE SEARCHF EQU 17 ;SEARCH FIRST SEARCHN EQU 18 ;SEARCH NEXT DELETEF EQU 19 ;DELETE FILE READR EQU 20 ;READ RECORD WRITER EQU 21 ;WRITE RECORD CREATEF EQU 22 ;CREATE FILE RENAMEF EQU 23 ;RENAME FILE LOGINV EQU 24 ;GET LOGIN VECTOR LOGGED EQU 25 ;GTET LOGGED DISK DMAADD EQU 26 ;SET D>^,G,N,V!~-w{ʌhxG..w.~ʷ<\Ìڷs_!~.w,^pC,^qK,^rS!~.~W-~O-~GҤGyOzW_.~wä_~W-~O-~G 3{bG!{ox{]!~.-qêG,N,V,^!~ȀGxw,~wyد{_zWyOxG. ZQHoxGyOzW{_--~wo_}W}O}G. xSAJS_}o5-{_zWyOxGF} !w!{^rx,t {_w!w!r!s_W!͟.͜.zYPFoOڰJSOҰ}o{_zWyOxGҰ{_zWyê!~w-~w-~wyy!Vw!dwz!Rw!`w{!Nw!\w5!M̈́5!s!Q͠_!~怰G{!{s!{͠!!{s!{ͽ!M͘!M!{̈́!{s!!{s!{͠!M!os!{͠!M!o!{s!{ͽ!k \ wy > !~6" \ 6 -H 1 OW 3 >\ s!à>GOW< }DQ!s!^s,fkd   !e( IN LINE $ERROR $WARNING $1)1) ͱ1) ͧv!)q*)&  !)p+q / *#)#"#) *) *) *) *) *) *) *)0 *)!)p+q*) !)p+q*)))!)p+q!*6>!* !*60**&f ) )(ڵ **&f ) )(+s#r!*4Æ **M !*4x !*r+s+p+q+p+q*! *r+s+q+p+q* *+" *ͮ( **:    *w**#"* !*p+q* *|O * *}O >!%)(=  Q *%)DMm !*p+q  Q **DM !*p+q  Q **DM *)#")*)")>͵(")!)(Ҡ >)(")*)")")!)(ھ *)")!*p+q)*Ϳ(!*p+q**N#FͿ / **N#Fa *)**q#p*)DM*)**)DM*)**)DM***)***)DM *)N#F*)**)~*)~*)>(*)>(*)#~*)#~!*q*)##:*w:ҫFO\ *)z *!"*)DM͎*) *)w*)##*)#w!*q*)**M*)͎!*q*)**M*)V"8**8*>(A*8* ~A*8**4*N#Fq#p`i"8**8**4*s#r!":*t *)"=**)"?*!<*6*)~!<*ڊ*)N#F*:*(+s#r":*| !<*4\*=*")*?*")*:*DMa *)~<_DM "=*"A**)*A* w#6!<*6*)~!<**A*##"A**)*A*N#Fq#p| !<*4͡ *)*=*s#r*)^#V"C*| *)^#V"G**C*N#F!F*q+6:F*!E*X| ͆*)*C*^#VN#F(*G* "G*!E*4'͆*C*G*(mBSA *C*##*G*DMa *)q#p*C*##"C*!I*q*)DM :I*3̀*)^#V"J**J*N#FͿ *J*N#F `i"L**L*~=w*J*N#Fͦ*)N#F `i"L*Ϳ 3*L*~/*L*#"L| ~!\*q!a*6:\*<rDH/SSA ͬ*)~2a*| r*)N#F͏!a*HDHl| ~*)>w#6ͬ*)*)N#F͏!a*#wҡ:\*š:b*<*)wá*):b*w:\*¶*)^#V"_*:\**):b*d(*)~͵("_**):a*d(+"_**_* O "]* _ *)*]* w| ~*)*]*s#r̀*)~!c*C*)DM͎!d*6>!d**c*M! ^#V*d*&*)~/w*d*&*)*d*&*)~`iw*d*&*)*d*&*)~`iw*d*&*)*d*&*)~`iwaq!d*4H>!c*| *)DM͞*) *)")*)#")!)(/>)(!l*q&*)#"))(HVREA `ͽ/7Hz͖ *) 5*):l*w*)>ҔFMA *)~ͅO!) ^#V")>ͫ(ºUFA *)N!) ^#V")&*)")")$*) ^#V")"*) ^#V")G  0 EMA !o*6:o*<2o*O!) >(5 ")*o*&)) q#p&*)")G *)#"m*  *)^#V"p**p*##~:ž*p*#>*)w*p*~==2r**p*##"p*å*p*~2r*> !r*ҳ!r*6 *p*#"p*!s*6RO*p* ~.!r*:s*Hÿ*p**m*DM*s*& R!r**s"3N!*6:*!*:**~")EQA **N3N!*4:*J"3~| **#"*ͽ jECA *)DMͦ!*6:*<2*O>ڦ**&)) ^#V")>ͫ(ʣVxs@ ?  +) :-)ͧ!,)"})*,)& 6 *,)&,) })(| *)")II\ û *')#"')!)(DOA *')~*})#"})*})~:)n>P!|)DBDA ͖*|)&,) w f&cERA k*)~5:)z!:)†!|)6-2* šÌ:)¨!,)"):)¶*})"):)*')"):*"!*6,!*6":)*)#")-2*!*:*+~ | ͎͡ *)n *ͬ!*p+q*)>w#6**|*)##w**}*) w*)DM͞*)*)Dn| >r{| >| >!!*p+q*))""*!"&*>"*(*"* ~*"*"*Ϳ(>͵("$**&*"&*> *(* *$*(*"**"*^#V""*Ó> *(MNA *&*!)*p+q>(*( !*(*DḾ",**,* 6*(**,*"0**,**0*N#Fq#p*,*N#F`i"2**,**0*s#r*2*s#r*0* 6*0*##"0**0**,*s#r*,*",**(* *,*!5*p+q>4*(#s#r"4**4* 6*4*##"4**4*^#V"4*>ͫ(*4* ~*4*"6**4*^#**L**L*~N*(¤>*N*~!P*q:P**)v **)6X| e | *)N#F͏<2Q*f*)N#F͏2R*:R*!Q*2S*f*)N#F*S*M "T*DM*Q*& *)N#F:Q*T*c(DM*R*& ~| ~*)*T*s#r:S*=*T*ẁɟqLSA X҂*)"X*Ì*)^#V"X*eҜ*)"V*æ*)^#V"V**V*~2[*!Z*6:[*!Z**V**X* >*V**X*~>*V*#"V**X*#"X*!Z*4²>~)Q!e*6:e*<2e*O!) ~  *))q#p`i:e*w!") !"f**f*~ Y*f*+"f*F !")f*)Ϳ(ڂ*)N *)")b0*)^#V"h*>ͫ(!j*6*h*~!j**j*&*h**) w*)#")ͮ(@!j*4ž*) !*) ~!k*q!*) :k*wOOOOO$*) *)s#r>)(_FEA *)#")*)")*)")))Ϳ(ʈO*)+")<û  ¢#7/ҮM# *) 4 *) > *) 5O& WDA 7*&*p**m*!s*:r*_ *)$*) q#p| *)"*) N#Fq#p| :s*<2s**)")*)")͙!")!)6| &/ҊURA XrHҞRIA *)N#F +q#p-ͽ*)}*)#~H_(*)|l_&}(!9g("v**)^}("t*!v*͑(*t* "z**)#^l&}("x**x*}*t*|v*c(͟(H !~*s>z*p(*) +")<!z*͛(#s#r *) :~*ʄ vECA  *) :~*w*|*} *) w| ңͽ͖/Ү͖*)~ºM*)~!*q:*:)/,3!)6*)^#V"***~2*:*!*5H!|)4-2*:*":-2*,:* H:͡ ͇*):|)!|)ҝ*|)M*)0*) ͎ð:)«ð*)6 )a  0* )"!)")* )")+"')* )")*)")`"))")*)")")*)*)Ϳ(*DM *))))Ϳ( *)"**)>(**q#p**##>w#6** w#6**^#V"***>w#6**##*)s#r*)~Ҵ ͡ *)#*) w*)>?*)#w*)~Ү .t Q(*)N!' ^#VQ(Q(Q(D ZD\ Q(N!D   !*)r *E!y"!ENA E!*)*)*)| ͎Q(OOͩQ(OOͩQ(OOͩQ(O/OͩQ(O/OͩQ(O/OͩQ(&Q(&Q(&Q(.Q(͏ | Q(| Q(͡ Q(Q(͏| | Q(rOͩQ(rOͩQ(rOͩQ(r/OͩQ(r/OͩQ(r/OͩQ(͏| | Q(͡ t *)*)s#r*)n&")̀Q(Q(t ͡ *)##*)q#p*)^#V")Q(*)N#F `i")| Q(BQ(Q(/"wQ(͆| Q(͆~| Q(g|Z*D/Oͩ:*% Q( Q( Q(Q(͡  |  ͡ NT%ZTA Q( Q( *)>(҃%*)>(+s#rg%*)N#F ! +s#r)(/>(Hҳ%@*)^#V")| Q(Q(͡ ́DM!Q(*#)"[Q(Q(͡ >)(DM!Q( *)NO!Q(*)^#V"*>ͫ(**~H<&CAA **#~2*~**M!Q(ͬ "***6*)**# w*)**s#r̀Q(Q(*)N#F͏2*~**M!Q(Q(Q():)w!$ !$͇ ,0uddvC$0 ʅw#{{6  ͏   y s{Ybw#p#q#r! N#F!q#p2!q!q{9 ~#F#N#V!Y , <    *$A!6 # TI܀1r l7s,w,p,q,r!w>!w!~{_,~,,N,Vê~{_,~,N,VoG!qG{~{̀x!~wbG{ɯ{O!>wQ(gZQ(#͡ Q(*)*)^N| | Q(!)6wQ(!)6>Q(ͿQ(ͿQ(Q(͡ t *)N#F*)*t Q(*)+"')Q( Q(/Ҕ#>Q(Q(Q(@Q(!*6**& ) )Ϳ(#!*4ë#!~ :*#@#**& ) ^#V")Q(iQ(D#i$*)##")| Q(UQ(BQ(*)DM͎Q(!)6*)")ʹQ(!)6>Q(!)6wQ(&[$͖ [$P$<Q(&~$*)++)(~$ 3h$ 3 3<Q(͙V*)N!) >w#6*)N!) w#6| Q(*)#>wQ(*)DM͎*)DM͞Q(͡ *) *͡ *[DM!Q(r/2Q(Q(Q( Q(*)~=w*)~=H4'IOA | *)~$I$a$$$$$$%!%)%1%\%d%%%%%%&&S&&&&&&&''''B'J'm'}'t  N#Fog_og_ogDM!>))Ҍ( =„(^#V) •(^#V|g}o Ÿ(_{ozgO{ozgi`N#Fogo&og_{_z#W712A0D47 :100D16002A7C4FCDC6NI $BASIC-E INTERPRETER - VER 2.2$NM $1-1-+,,!/ͫ-"--Ϳ-")e-2-*ʦ+!-6e-:-<2-O!- Hqy$ʆ+h+*-M-0*- *-"-X+͉-*- "-)-Ϳ-" ))-Ϳ-" )͉-* ) " )*- )-+$+,͉-))* ) ")e-,:-3",e-*-w,*-#"- ,,:-6,S-.-S-,:-d,S-*-"-*-6S-e-a,S-*-4O,,S-:-6:-7H:-^H:-HҰ,p-*- )͠-+s#r̀-,:-.,p-*-^#V))* +s#r̀-+v!.p+q*.DMQ    *. 6I*>^,G,N,V!~-w{ʌhxG..w.~ʷ<\Ìڷs_!~.w,^pC,^qK,^rS!~.~W-~O-~GҤGyOzW_.~wä_~W-~O-~G 3{bG!{ox{]!~.-qêG,N,V,^!~ȀGxw,~wyد{_zWyOxG. ZQHoxGyOzW{_--~wo_}W}O}G. xSAJS_}o5-{_zWyOxGF} !w!{^rx,t {_w!w!r!s_W!͟.͜.zYPFoOڰJSOҰ}o{_zWyOxGҰ{_zWyê!~w-~w-~wyy!Vw!dwz!Rw!`w{!Nw!\w   x!Kw!Yw!gw!~,V,^B.N qkb_HJx}o|gz'}[kb_PH>}o|g{_>o|g{_>+6* |} !͌!ks͠!k̈́!ks@!os!k͠!o!o!osï!o͠ɯ!ow!"*M"o*O"q!"w կGOy !ss!k͠!oͽ*w!s!M7!os!M͠!s!o!oszWyOI܀1ŕ!Q͌!{s!Q͏ y !Qͽ́!{!{s̈́!Q!Q_!|~G{+s{É!{͠!{ͽ́!ksH!o͠!{ͽ!w,w͌͌s !o4͠!{ͽ!{s!y~HPy !Uͽ!{![N,F-R !P o ![q,p6 c o c o ɗyOxGc ~O,~G-kZQHG}!w,6,xÛ!~ʼ {Ҽ .F,N,V.~ >xAJSɯGOW^P ,6!r{ !r\ ~# . _ !#w!iͽ.s,~HPy ..~ -Fp !w _ \ ~G_? xA ,~ _ G,~ X OxG{_ G!N!qx!ʌw!i~ >h ͽ>h -P ͌!s\ 6ʶ _x{ 6~!iڿ !^sè ͽ!^sæ ̈́!mҨ !~_ w>,w{!w !iͽ͏ *w**#"* !*p+q* *|O * *}O >!%)(=  Q *%)DMm !*p+q  Q **DM !*p+q  Q **DM *)#")*)")>͵(")!)(Ҡ >)(")*)")")!)(ھ *)")!*p+q)*Ϳ(!*p+q**N#FͿ / **N#Fa *)**q#p*)DM*)**)DM*)**)DM***)***)DM *)N#F*)**)~*)~*)>(*)>(*)#~*)#~!*q*)##:*w:ҫFO\ *)z *!"*)DM͎*) *)w*)##*)#w!*q*)**M*)͎!*q*)**M*)V"8**8*>(A*8* ~A*8**4*N#Fq#p`i"8**8**4*s#r!":*t *)"=**)"?*!<*6*)~!<*ڊ*)N#F*:*(+s#r":*| !<*4\*=*")*?*")*:*DMa *)~<_DM "=*"A**)*A* w#6!<*6*)~!<**A*##"A**)*A*N#Fq#p| !<*4͡ *)*=*s#r*)^#V"C*| *)^#V"G**C*N#F!F*q+6:F*!E*X| ͆*)*C*^#VN#F(*G* "G*!E*4'͆*C*G*(mBSA *C*##*G*DMa *)q#p*C*##"C*!I*q*)DM :I*3̀*)^#V"J**J*N#FͿ *J*N#F `i"L**L*~=w*J*N#Fͦ*)N#F `i"L*Ϳ 3*L*~/*L*#"L| ~!\*q!a*6:\*<rDH/SSA ͬ*)~2a*| r*)N#F͏!a*HDHl| ~*)>w#6ͬ*)*)N#F͏!a*#wҡ:\*š:b*<*)wá*):b*w:\*¶*)^#V"_*:\**):b*d(*)~͵("_**):a*d(+"_**_* O "]* _ *)*]* w| ~*)*]*s#r̀*)~!c*C*)DM͎!d*6>!d**c*M! ^#V*d*&*)~/w*d*&*)*d*&*)~`iw*d*&*)*d*&*)~`iw*d*&*)*d*&*)~`iwaq!d*4H>!c*| *)DM͞*)5!M̈́5!s!Q͠_!~怰G{!{s!{͠!!{s!{ͽ!M͘!M!{̈́!{s!!{s!{͠!M!os!{͠!M!o!{s!{ͽ!k \ wy > !~6" \ 6 -H 1 OW 3 >\ s!à>GOW< }DQ!s!^s,fkd   !e( IN LINE $ERROR $WARNING $1)1) ͱ1) ͧv!)q*)&  !)p+q / *#)#"#) *) *) *) *) *) *) *)0 *)!)p+q*) !)p+q*)))!)p+q!*6>!* !*60**&f ) )(ڵ **&f ) )(+s#r!*4Æ **M !*4x !*r+s+p+q+p+q*! *r+s+q+p+q* *+" *ͮ( **:| ͎͡ *)n *ͬ!*p+q*)>w#6**|*)##w**}*) w*)DM͞*)*)Dn| >r{| >| >!!*p+q*))""*!"&*>"*(*"* ~*"*"*Ϳ(>͵("$**&*"&*> *(* *$*(*"**"*^#V""*Ó> *(MNA *&*!)*p+q>(*( !*(*DḾ",**,* 6*(**,*"0**,**0*N#Fq#p*,*N#F`i"2**,**0*s#r*2*s#r*0* 6*0*##"0**0**,*s#r*,*",**(* *,*!5*p+q>4*(#s#r"4**4* 6*4*##"4**4*^#V"4*>ͫ(*4* ~*4*"6**4*^#**L**L*~N*(¤>*N*~!P*q:P**)v **)6X| e | *)N#F͏<2Q*f*)N#F͏2R*:R*!Q*2S*f*)N#F*S*M "T*DM*Q*& *)N#F:Q*T*c(DM*R*& ~| ~*)*T*s#r:S*=*T*ẁɟqLSA X҂*)"X*Ì*)^#V"X*eҜ*)"V*æ*)^#V"V**V*~2[*!Z*6:[*!Z**V**X* >*V**X*~>*V*#"V**X*#"X*!Z*4²>~)Q!e*6:e*<2e*O!) ~  *))q#p`i:e*w!") !"f**f*~ Y*f*+"f*F !")f*)Ϳ(ڂ*)N *)")b0*)^#V"h*>ͫ(!j*6*h*~!j**j*&*h**) w*)#")ͮ(@!j*4ž*) !*) ~!k*q!*) :k*wOOOOO$*) *)s#r>)(_FEA *)#")*)")*)")))Ϳ(ʈO*)+")<û  ¢#7/ҮM# *) 4 *) > *) 5O& WDA 7    *)")*)#")!)(/>)(!l*q&*)#"))(HVREA `ͽ/7Hz͖ *) 5*):l*w*)>ҔFMA *)~ͅO!) ^#V")>ͫ(ºUFA *)N!) ^#V")&*)")")$*) ^#V")"*) ^#V")G  0 EMA !o*6:o*<2o*O!) >(5 ")*o*&)) q#p&*)")G *)#"m*  *)^#V"p**p*##~:ž*p*#>*)w*p*~==2r**p*##"p*å*p*~2r*> !r*ҳ!r*6 *p*#"p*!s*6RO*p* ~.!r*:s*Hÿ*p**m*DM*s*& R!r**s"3N!*6:*!*:**~")EQA **N3N!*4:*J"3~| **#"*ͽ jECA *)DMͦ!*6:*<2*O>ڦ**&)) ^#V")>ͫ(ʣVxs@ ?  +) :-)ͧ!,)"})*,)& 6 *,)&,) })(| *)")II\ û *')#"')!)(DOA *')~*})#"})*})~:)n>P!|)DBDA ͖*|)&,) w f&cERA k*)~5:)z!:)†!|)6-2* šÌ:)¨!,)"):)¶*})"):)*')"):*"!*6,!*6":)*)#")-2*!*:*+~ !*)r *E!y"!ENA E!*)*)*)| ͎Q(OOͩQ(OOͩQ(OOͩQ(O/OͩQ(O/OͩQ(O/OͩQ(&Q(&Q(&Q(.Q(͏ | Q(| Q(͡ Q(Q(͏| | Q(rOͩQ(rOͩQ(rOͩQ(r/OͩQ(r/OͩQ(r/OͩQ(͏| | Q(͡ t *)*)s#r*)n&")̀Q(Q(t ͡ *)##*)q#p*)^#V")Q(*)N#F `i")| Q(BQ(Q(/"wQ(͆| Q(͆~| Q(g|Z*D/Oͩ:*% Q( Q( Q(Q(͡  |  ͡ NT%ZTA Q( Q( *)>(҃%*)>(+s#rg%*)N#F ! +s#r)(/>(Hҳ%@*)^#V")| Q(Q(͡ ́DM!Q(*#)"[Q(Q(͡ >)(DM!Q( *)NO!Q(*)^#V"*>ͫ(**~H<&CAA **#~2*~**M!Q(ͬ "***6*)**# w*)**s#r̀Q(Q(*)N#F͏2*~**M!Q(Q(Q():)z*p(*) +")<!z*͛(#s#r *) :~*ʄ vECA  *) :~*w*|*} *) w| ңͽ͖/Ү͖*)~ºM*)~!*q:*:)/,3!)6*)^#V"***~2*:*!*5H!|)4-2*:*":-2*,:* H:͡ ͇*):|)!|)ҝ*|)M*)0*) ͎ð:)«ð*)6 )a  0* )"!)")* )")+"')* )")*)")`"))")*)")")*)*)Ϳ(*DM *))))Ϳ( *)"**)>(**q#p**##>w#6** w#6**^#V"***>w#6**##*)s#r*)~Ҵ ͡ *)#*) w*)>?*)#w*)~Ү .t Q(*)N!' ^#VQ(Q(Q(D ZD\ Q(N!DQ(gZQ(#͡ Q(*)*)^N| | Q(!)6wQ(!)6>Q(ͿQ(ͿQ(Q(͡ t *)N#F*)*t Q(*)+"')Q( Q(/Ҕ#>Q(Q(Q(@Q(!*6**& ) )Ϳ(#!*4ë#!~ :*#@#**& ) ^#V")Q(iQ(D#i$*)##")| Q(UQ(BQ(*)DM͎Q(!)6*)")ʹQ(!)6>Q(!)6wQ(&[$͖ [$P$<Q(&~$*)++)(~$ 3h$ 3 3<Q(͙V*)N!) >w#6*)N!) w#6| Q(*)#>wQ(*)DM͎*)DM͞Q(͡ *) *͡ *[DM!Q(r/2Q(Q(Q( Q(*)~=w*)~=H4'IOA | *)~$I$a$$$$$$%!%)%1%\%d%%%%%%&&S&&&&&&&''''B'J'm'}'t  N#Fog_og_ogDM!>))Ҍ( =„(^#V) •(^#V|g}o Ÿ(_{ozgO{ozgi`N#Fogo&og_{_z#W712A0D47 :100D16002A7C4FCDC6NI $BASIC-E INTERPRETER - VER 2.2$NM $1-1-+,,!/ͫ-"--Ϳ-")e-2-*ʦ+!-6e-:-<2-O!- Hqy$ʆ+h+*-M-0*- *-"-X+͉-*- "-)-Ϳ-" ))-Ϳ-" )͉-* ) " )*- )-+$+,͉-))* ) ")e-,:-3",e-*-w,*-#"- ,,:-6,S-.-S-,:-d,S-*-"-*-6S-e-a,S-*-4O,,S-:-6:-7H:-^H:-HҰ,p-*- )͠-+s#r̀-,:-.,p-*-^#V))* +s#r̀-+v!.p+q*.DMQ    *. 6I*   . 6N*. 6T*. #-+,*. *-#"-!͸-R-!"-$-R-*-6*-*- w*-#"-.-*-~2-e-*-#we-*-w*-##"-e-O`iͲ-e-_N#Fog{ozg) ²-{ozgi`N#FogC2A712A134B :100ED600290E02CDDF012A1C2A4D2A1329\60 :100EE600D201CD8E0EC9211D2A712A1329EB0E02BD :100EF600CDDF012A1D2A4D2A1529EBCDD201CD7C45 :100F06000DCD8E0EC9CDA10D2A1329EB016E0BCD89 :100F16002A010E03CDEC0ECDAC0EC9211F2A702B73 :100F2600712A13293E00772336002A1E2A7C2A13AB :100F3600292323772A1E2A7D)+ï +`iN#F#^#V#~#fo}+ !y:!$0w# =>w!$ !$͇ ,0uddvC$0 ʅw#{{6  ͏   y s{Ybw#p#q#r! N#F!q#p2!q!q{9 ~#F#N#V!Y , <    *$A!6 # TI܀1r l7s,w,p,q,r!w>!w!~{_,~,,N,Vê~{_,~,N,VoG!qG{~{̀x!~wbG{ɯ{O!>wx!Kw!Yw!gw!~,V,^B.N qkb_HJx}o|gz'}[kb_PH>}o|g{_>o|g{_>+6* |} !͌!ks͠!k̈́!ks@!os!k͠!o!o!osï!o͠ɯ!ow!"*M"o*O"q!"w կGOy !ss!k͠!oͽ*w!s!M7!os!M͠!s!o!oszWyOI܀1ŕ!Q͌!{s!Q͏ y !Qͽ́!{!{s̈́!Q!Q_!|~G{+s{É!{͠!{ͽ́!ksH!o͠!{ͽ!w,w͌͌s !o4͠!{ͽ!{s!y~HPy !Uͽ!{![N,F-R !P o ![q,p6 c o c o ɗyOxGc ~O,~G-kZQHG}!w,6,xÛ!~ʼ {Ҽ .F,N,V.~ >xAJSɯGOW^P ,6!r{ !r\ ~# . _ !#w!iͽ.s,~HPy ..~ -Fp !w _ \ ~G_? xA ,~ _ G,~ X OxG{_ G!N!qx!ʌw!i~ >h ͽ>h -P ͌!s\ 6ʶ _x{ 6~!iڿ !^sè ͽ!^sæ ̈́!mҨ !~_ w>,w{!w !iͽ͏ *w**#"* !*p+q* *|O * *}O >!%)(=  Q *%)DMm !*p+q  Q **DM !*p+q  Q **DM *)#")*)")>͵(")!)(Ҡ >)(")*)")")!)(ھ *)")!*p+q)*Ϳ(!*p+q**N#FͿ / **N#Fa *)**q#p*)DM*)**)DM*)**)DM***)***)DM *)N#F*)**)~*)~*)>(*)>(*)#~*)#~!*q*)##:*w:ҫFO\ *)z *!"*)DM͎*) *)w*)##*)#w!*q*)**M*)͎!*q*)**M*)>^,G,N,V!~-w{ʌhxG..w.~ʷ<\Ìڷs_!~.w,^pC,^qK,^rS!~.~W-~O-~GҤGyOzW_.~wä_~W-~O-~G 3{bG!{ox{]!~.-qêG,N,V,^!~ȀGxw,~wyد{_zWyOxG. ZQHoxGyOzW{_--~wo_}W}O}G. xSAJS_}o5-{_zWyOxGF} !w!{^rx,t {_w!w!r!s_W!͟.͜.zYPFoOڰJSOҰ}o{_zWyOxGҰ{_zWyê!~w-~w-~wyy!Vw!dwz!Rw!`w{!Nw!\w5!M̈́5!s!Q͠_!~怰G{!{s!{͠!!{s!{ͽ!M͘!M!{̈́!{s!!{s!{͠!M!os!{͠!M!o!{s!{ͽ!k \ wy > !~6" \ 6 -H 1 OW 3 >\ s!à>GOW< }DQ!s!^s,fkd   !e( IN LINE $ERROR $WARNING $1)1) ͱ1) ͧv!)q*)&  !)p+q / *#)#"#) *) *) *) *) *) *) *)0 *)!)p+q*) !)p+q*)))!)p+q!*6>!* !*60**&f ) )(ڵ **&f ) )(+s#r!*4Æ **M !*4x !*r+s+p+q+p+q*! *r+s+q+p+q* *+" *ͮ( **:| ͎͡ *)n *ͬ!*p+q*)>w#6**|*)##w**}*) w*)DM͞*)*)Dn| >r{| >| >!!*p+q*))""*!"&*>"*(*"* ~*"*"*Ϳ(>͵("$**&*"&*> *(* *$*(*"**"*^#V""*Ó> *(MNA *&*!)*p+q>(*( !*(*DḾ",**,* 6*(**,*"0**,**0*N#Fq#p*,*N#F`i"2**,**0*s#r*2*s#r*0* 6*0*##"0**0**,*s#r*,*",**(* *,*!5*p+q>4*(#s#r"4**4* 6*4*##"4**4*^#V"4*>ͫ(*4* ~*4*"6**4*^#   V"8**8*>(A*8* ~A*8**4*N#Fq#p`i"8**8**4*s#r!":*t *)"=**)"?*!<*6*)~!<*ڊ*)N#F*:*(+s#r":*| !<*4\*=*")*?*")*:*DMa *)~<_DM "=*"A**)*A* w#6!<*6*)~!<**A*##"A**)*A*N#Fq#p| !<*4͡ *)*=*s#r*)^#V"C*| *)^#V"G**C*N#F!F*q+6:F*!E*X| ͆*)*C*^#VN#F(*G* "G*!E*4'͆*C*G*(mBSA *C*##*G*DMa *)q#p*C*##"C*!I*q*)DM :I*3̀*)^#V"J**J*N#FͿ *J*N#F `i"L**L*~=w*J*N#Fͦ*)N#F `i"L*Ϳ 3*L*~/*L*#"L| ~!\*q!a*6:\*<rDH/SSA ͬ*)~2a*| r*)N#F͏!a*HDHl| ~*)>w#6ͬ*)*)N#F͏!a*#wҡ:\*š:b*<*)wá*):b*w:\*¶*)^#V"_*:\**):b*d(*)~͵("_**):a*d(+"_**_* O "]* _ *)*]* w| ~*)*]*s#r̀*)~!c*C*)DM͎!d*6>!d**c*M! ^#V*d*&*)~/w*d*&*)*d*&*)~`iw*d*&*)*d*&*)~`iw*d*&*)*d*&*)~`iwaq!d*4H>!c*| *)DM͞*) *)")*)#")!)(/>)(!l*q&*)#"))(HVREA `ͽ/7Hz͖ *) 5*):l*w*)>ҔFMA *)~ͅO!) ^#V")>ͫ(ºUFA *)N!) ^#V")&*)")")$*) ^#V")"*) ^#V")G  0 EMA !o*6:o*<2o*O!) >(5 ")*o*&)) q#p&*)")G *)#"m*  *)^#V"p**p*##~:ž*p*#>*)w*p*~==2r**p*##"p*å*p*~2r*> !r*ҳ!r*6 *p*#"p*!s*6RO*p* ~.!r*:s*Hÿ*p**m*DM*s*& R!r**s"3N!*6:*!*:**~")EQA **N3N!*4:*J"3~| **#"*ͽ jECA *)DMͦ!*6:*<2*O>ڦ**&)) ^#V")>ͫ(ʣVxs@ ?  +) :-)ͧ!,)"})*,)& 6 *,)&,) })(| *)")II\ û *')#"')!)(DOA *')~*})#"})*})~:)n>P!|)DBDA ͖*|)&,) w f&cERA k*)~5:)z!:)†!|)6-2* šÌ:)¨!,)"):)¶*})"):)*')"):*"!*6,!*6":)*)#")-2*!*:*+~ !*)r *E!y"!ENA E!*)*)*)| ͎Q(OOͩQ(OOͩQ(OOͩQ(O/OͩQ(O/OͩQ(O/OͩQ(&Q(&Q(&Q(.Q(͏ | Q(| Q(͡ Q(Q(͏| | Q(rOͩQ(rOͩQ(rOͩQ(r/OͩQ(r/OͩQ(r/OͩQ(͏| | Q(͡ t *)*)s#r*)n&")̀Q(Q(t ͡ *)##*)q#p*)^#V")Q(*)N#F `i")| Q(BQ(Q(/"wQ(͆| Q(͆~| Q(g|Z**L**L*~N*(¤>*N*~!P*q:P**)v **)6X| e | *)N#F͏<2Q*f*)N#F͏2R*:R*!Q*2S*f*)N#F*S*M "T*DM*Q*& *)N#F:Q*T*c(DM*R*& ~| ~*)*T*s#r:S*=*T*ẁɟqLSA X҂*)"X*Ì*)^#V"X*eҜ*)"V*æ*)^#V"V**V*~2[*!Z*6:[*!Z**V**X* >*V**X*~>*V*#"V**X*#"X*!Z*4²>~)Q!e*6:e*<2e*O!) ~  *))q#p`i:e*w!") !"f**f*~ Y*f*+"f*F !")f*)Ϳ(ڂ*)N *)")b0*)^#V"h*>ͫ(!j*6*h*~!j**j*&*h**) w*)#")ͮ(@!j*4ž*) !*) ~!k*q!*) :k*wOOOOO$*) *)s#r>)(_FEA *)#")*)")*)")))Ϳ(ʈO*)+")<û  ¢#7/ҮM# *) 4 *) > *) 5O& WDA 7*&*p**m*!s*:r*_ *)$*) q#p| *)"*) N#Fq#p| :s*<2s**)")*)")͙!")!)6| &/ҊURA XrHҞRIA *)N#F +q#p-ͽ*)}*)#~H_(*)|l_&}(!9g("v**)^}("t*!v*͑(*t* "z**)#^l&}("x**x*}*t*|v*c(͟(H !~*s>z*p(*) +")<!z*͛(#s#r *) :~*ʄ vECA  *) :~*w*|*} *) w| ңͽ͖/Ү͖*)~ºM*)~!*q:*:)/,3!)6*)^#V"***~2*:*!*5H!|)4-2*:*":-2*,:* H:͡ ͇*):|)!|)ҝ*|)M*)0*) ͎ð:)«ð*)6 )a  0* )"!)")* )")+"')* )")*)")`"))")*)")")*)*)Ϳ(*DM *))))Ϳ( *)"**)>(**q#p**##>w#6** w#6**^#V"***>w#6**##*)s#r*)~Ҵ ͡ *)#*) w*)>?*)#w*)~Ү .t Q(*)N!' ^#VQ(Q(Q(D ZD\ Q(N!DQ(gZQ(#͡ Q(*)*)^N| | Q(!)6wQ(!)6>Q(ͿQ(ͿQ(Q(͡ t *)N#F*)*t Q(*)+"')Q( Q(/Ҕ#>Q(Q(Q(@Q(!*6**& ) )Ϳ(#!*4ë#!~ :*#@#**& ) ^#V")Q(iQ(D#i$*)##")| Q(UQ(BQ(*)DM͎Q(!)6*)")ʹQ(!)6>Q(!)6wQ(&[$͖ [$P$<Q(&~$*)++)(~$ 3h$ 3 3<Q(͙V*)N!) >w#6*)N!) w#6| Q(*)#>wQ(*)DM͎*)DM͞Q(͡ *) *͡ *[DM!Q(r/2   *D/Oͩ:*% Q( Q( Q(Q(͡  |  ͡ NT%ZTA Q( Q( *)>(҃%*)>(+s#rg%*)N#F ! +s#r)(/>(Hҳ%@*)^#V")| Q(Q(͡ ́DM!Q(*#)"[Q(Q(͡ >)(DM!Q( *)NO!Q(*)^#V"*>ͫ(**~H<&CAA **#~2*~**M!Q(ͬ "***6*)**# w*)**s#r̀Q(Q(*)N#F͏2*~**M!Q(Q(Q():):#^IFTOGOONOREQLTGTLEGENEFORLETREMDIMDEFNOTANDTANSINCOSSQRTABLOGLENFREATNABSEXPINTENDPOSRNDSGNINPASCVALXORSUBOUTTHENREADGOTOELSENEXTSTOPDATAFILECHR$MID$STEPSTR$COSHSINHPRINTINPUTGOSUBCLOSELEFT$RETURNRIGHT$REMARKRESTORERANDOMIZE    HEFIJNTLGAKBOCDPQX! )&$"%(c#RU'WYZ-,+*S.V03%| 7EJMNNAFGFADE $BASNS $!;,r+s+q!>,r+s+q>!"?,!*?,!-s+p+q+p+q:-=2-*-*- w*-#"-*-#"-!-s+q+p+!S,6!-q:+-<2+-H!+-6*+-&, :-w,-R !-q*-DM|*-ME E!-6:-!-s*-&,- NE!-4Uq,!-6::X,Hҫ *,DM;!,62X,:~-<2~-O!,- :X,w:X, *-#"-:I,!D,:~-=O8!~-6:X, !X,6 :X,*,&*,~:,<2,!,!,6.>2X, -> :X,HL1:X,\c `U1!-p+q:~-<<2-:B,~!I,6:T,ʝ:X, ʚM2X,Æ1:B,*J,#"J,*-|OE*-}OE?E:-=2- E^Eq!I,6!L,6:A,m{,;ͮQ(Q(Q( Q(*)~=w*)~=H4'IOA | *)~$I$a$$$$$$%!%)%1%\%d%%%%%%&&S&&&&&&&''''B'J'm'}'t  N#Fog_og_ogDM!>))Ҍ( =„(^#V) •(^#V|g}o Ÿ(_{ozgO{ozgi`N#Fogo&og_{_z#W712A0D47 :100D16002A7C4FCDC6NI $BASIC-E INTERPRETER - VER 2.3$NM $1-1-+,,!/ͫ-"--Ϳ-")e-2-*ʦ+!-6e-:-<2-O!- Hqy$ʆ+h+*-M-0*- *-"-X+͉-*- "-)-Ϳ-" ))-Ϳ-" )͉-* ) " )*- )-+$+,͉-))* ) ")e-,:-3",e-*-w,*-#"- ,,:-6,S-.-S-,:-d,S-*-"-*-6S-e-a,S-*-4O,,S-:-6:-7H:-^H:-HҰ,p-*- )͠-+s#r̀-,:-.,p-*-^#V))* +s#r̀-+v!.p+q*.DMQ    *. 6I*q:-=2-*-:-w*-#"-!-q:H,9*-&͕D*-&͕!-q:- j:z,<2z,g QÂ!z,4*-M :- ‚!z,6!-p+q*-~$ʣ*-NE*-#"-É̓ͯ *,DM; *, 6 *, 6*,̓ͯ͡,ͤ͡:G,*, ,;,͕,͡(ͤ!,6*,͡2-O>Dͤ:-:G,P,͕,͡h͕ͤ E E!-p+q!-6+6>!-!-60*-&) -S *-&) -S +s#r!-6#4Ø:-/!-*-ME E!-4Š!P,6#6#6!O,6!y,6#6!"-}2~-,!,6!-6:1:{,$¤!-6:-<2-O!{, ~2- ʤ:-A2-O>ڡ*-M! ^#V!C,6á!D,6á!G,6á!F,6á!E,6á!H,6áemu}/!Y,6!W,6!T,6#6:X,"!y, !T,62!y,6":X, SUd͇ :y,1:X,"͇ à HҔ!T,61:X,0.2X,/ > / :X,Ex͹ :X,+:X,-Hg͹ /uFId/ :Y,!W,60!Y,6#60= à  c  Ҩ Û:X,$»!U,62 !U,61h / :Z,F:[,NH:Y,H!T,66!T,64= `    :T, :X,  2X,M ` :T,c\ 3N *X,MN  H M*X,MN 3 ,N N *M,+"M,` = à :X,\q Mà ͹ h /҂ CIdå:y,/Ҹ :Y,<2Y,O!Y, :X,w:X,!W,?w:Y,ڸ !y,6͇ 1͇ 2X,:X,0O> /:X,a/>z!X,/H:X,. !F, :X,_2X, :X,AO>/ H  H H < / :X, H 1!y,6!-q*M,#"M,:B,g *-M> !Y,t >*Y,&O n&"-!-6*Y,&Y ~!-   *Y,&c :-O! ~2T,O>@:T,cH :T,AO!m ~2U,:T,2V,!T,65>:Y,-F +s#r#4;ͥ *2.6  *2.q#p*6.&-) *-s#r:>.0.+s#r*-~ͥ *2.>!?.qͥ *2.:?.wͥ *2.~ͥ *2.^#V!@.qͥ *2.:@.wͥ *2.~B 2C.!D.6:C.!D. Ϳ o&-"A.*A.-% *A.N#F`i"A.ù *2.*A.N#Fq#p!D.4ž B 2H.!G.6:H.!G.@ *-#"E.Ϳ O!- *E.N#Fq#pͿ O!- *-s#r!G.4 !0q:A,S*0M!"-"M,}2/20!"-!"-:A,!` "4.!6.61 1A$AI N !^ "4.!6.60 0A$AI N !0q:B,!C,b ̓*0M|q*0M! ^#V*NSdk DM,!|,*0M/B H8SId,*-DM 5*0"0͂͂5*/MҜ*-DMb*-DM B OPâUFd*V,M: 0OPeY, , , , ,,,*.. ^#V"-:0-|k DM,|:0Nk DM||:0҅||8| |9| |7|*..N#F*..##*-s#r6|*..##N#F*.. *-s#r!O,6>..0+s#r"-*-#>w# !-4,!Q,6?|!Q,64|!Q,6[|&|!Q,6[||[|%|:Q,/5|͟fͻ͆k DM`||ͻ͟͟: 0>!+0q*+0M> >*-#"-!-0p+q*,0|O|*,0}O|!/0p+q!.0DM!10p+q!00DM:E,V*-M_|!0"4.:0?26.!20q:A,҅W :20-DMI !04Wo 230͆k DM: 01: 01HFMd>>! 0: 0MMd>>* 0M: 01>FMd>: 02FM >!-6*-&*-:-<2-O!Y, :Y,!-/H= :Y,!-_ogN#Fog01PROD $ ERRORS DETECTED$:A,ғ ->@_!D0"0.*++".."-*-#6!7.q*-^*-*7.& "2.!8.6*-##"2.!9.6*-~!9. *9.&*2.:8.?28.!9.4 :8.*-^*-"-*-#"2.*6.&-) ^#V!:.q::.0.!..;H !B,6OTdͯ!<.p+qͥ *2.*;.s#r*2.+"2.*2.>w "->-0 *-~2=.*4. *=.& *-*=.&*4. :=.=2=.¿ >Ñ *2.^#V"-u >*4.>2>.O# *0."-*4.#*0.###*4.*- w_/M6` &k -3#LDd3*-DMI N ;!-6*AAoҢ1: 0µ*0DM͠* 0M| ]͠ | |*: 01* 0M|*: 0O|1L: 01G|L|͠[|et0|҆͠|͠ҕ|͠ҧ|:0½*0DM,|* 0M*/MͿ:O,IFd *0"-͉ ! 0*.. ^#V"-k DM.|ff[|^|͂k DM͟f6|͔: 02vEId7|͔ҧ*0"-* 0MN ͓ ||f6|͔*/M2;0* 0M*-DM:A,:;0DFd*-DMI  ,,*0MͿ: 01*FId*0DM,-| *0"-*0M!A,yPDdN :A,ҍDMI k DM,*-DM @|@|:Q,>|!Q,6'|!R,6GGWWqtwz}-0O^hwzHN]cir '/7ORXh :@ILRXd !'*069ASor<DL*/&K/ ~20*0& ~2 0*0& ~2 0*/&k/ ~2 0*0& ~2 0*0& ~2 0*/&.) ^#V"0*0&) ^#V"0*0&) ^#V"0*0&. ~20*0& ~20*/& ~20*/&.) ^#V"0*0&) ^#V"0!0p+q*/&.) *0s#r!0p+q*0&.) *0s#r!0q*/&d[|: 0<2 0O,*0Mx  |*0M||: 01A|F|4|!R,6;|:0g*0DM:R,x"1͑Ð:Q,҉)*͑Ð=<͑!50s+q: 02®*40M||ú*50M||[|:/<2/O!/ N\|9|*/&/ :0w:-=2-!-6UNdA6|*- N#F!-*-q#p*-#>A*-"-**0M*- -%HhnINd:-|LUd!-6*/MҞ` /!B,Ҟ!-6͂:S,ұ|ö6|k DM!60q*60MB UIdDMI N k "0DM:O,   !O,6*.. *-s#r!80p+q2|!906*70~!90N*90&*70N|!904.:y,[ͥa|).|1*/MB HҖk DM!:06:Y,!:0ڹ*:0&Y, NA!:04›$A*-#"-DM:Q,: 01+|,|: 01:0J#|$|: 0 4*0"- *-DM:0=20O>k DM: 0 W*0"-͉ ! 0SPFd1: 01!0mPFd:0O>: 0=2 0O: 0 ¬:0ʘNFd|*0"-k DM: 0ʼNFd* 0M|: 021:A,*0Mͬ DMI * 0Mx N : cj(>JJFIK!!*!&O@ G  "H}~R&JQTUE. HJ %'<$% =>?S  "H}~R&JQTU  "H}~R&JQTU-|z {  NM##''()+,"$   !"#$%-/02<=>?@$BCCCCCEFYZZZ[\Y%]^_`aaabcdgldddosvz~ddddddd$$  #&),/3579;=?ACFILOSVY\^adfhkmptvy{}2/7!;22 $$%%''))+++++---22555577BBCCDDEEFFHHHHHHHER VER 2.0$19,(̓qj+:B,!A,X+!L,6!06!y"I.!/6!/6!+/6:L,U+>x!I.+,*͌+*/&K.) *I.s#rt+"<0͟+́+*<0+">0*<0"<0>0<0+)**<0D :T, **/&+/ :/w!B06:Y,!B0)*B0&Y, Nͯ+!B04´)*/&. :W,w*/&k/ :U,w*<0(!) ^#V"I.!06*>0"<0*>0<0+*PNd*<0"<0҈)R+>!I.+*́+:/+!0s:0<20>I.+M:L,*:02/t+"<0*/&+/ ~2/*/&K.) ^#V">0*<0 n&"@0}@0>0+Hҽ**<0#"<0É**<0#) ^#V"I.>+*!L,6R+>!I.+7+t+"<0͟+*<0 n&"@0}46E1712370DF :100E2500CDBF0B4F060021AE2D099E52AAC2DEBF0 :100E3500E173237221472E34C2FA0DC921063071A0 :100E45003A412C1FD25302A:6304DCD0605C92135 :100E550000002A32D2242C7D32EF2F32053021AB :100E6500010022A72D21FFFF22A52DCDF0043A4137 :100E75002C1FD2C30ECDFC0321600B22342E21364C :100E85002E3631CDD50C0E31CD410E0E24CD410E71 :100E9500010000CD490C0E04CD4E0D215E0B223410 :100EA5002E21362E3630CDD50C0E30CD410E0E24EA :100EB500CD410E010100CD490C0E04CD4E0DC921C9 :100EC5000730713A422C21432CA61FD2E50E016250 :10 0C0D6CHHIJKLLMMMNNOPQRSSTTUVVWXXYZZ[]]^__``abbcccffggghhiijjllmnnopqqsttvvxxyyz{|}~                 #'(+7UaceijuBASIC-E COMPIL!@0:T,+H%+*<0#"<0**<0") ^#V"I.R+͌+́+*/&K.) q#pt+"I.E))!D,6j+!B,6)vy T*I.$) ^#V*I.' n&:/<2/ ž+OSd:0Ү+ͥ!06!C0q*/&/ :C0w:/<2/O>d+OVd_{ozgi`N#Fogo&og_{_z#W0DC5000D2A412E4E234603606922412EC3B90DDB :100DD500CD0C0C2A3224E2346E17135 :100DE500237021442E34C29E0DC9CD4 \ INT36013A482E21472EB00ECD28 :100E0500FA0B2AAC2D2322452ECDBF0B4F06002110 :100E1500AE2D0909E52A452EE34E230ED5000BCD83032A07304D0600CD7C04CD71046C :100EE500CD12182A07304D060021DF1609095E23A9 :100EF50056EBE9C31118C311182AFF2F4DCDC81998 :100F05001FD2360FCD600D1FD2260FCD6B0D11A34D :100F15002DCD331FB5CA230F014C44CD6406C33311 :100F25000F2AA32D444DCD490C0E08CD4E0D3BC4 :100F35000F21812D362ACD411AC31118CD411AC36F :100F45001118CD6F1CC31118C31118C31118C31183 :100F550018C31118C31118C31118C31118C31118D8 :100F6500C31118C31118C31118C31118C31118C31D :100F75001118C31118C31118C31118C31118C311BF :100F850018C31118C31   4)d END <(+*)-,=/;>:#^IFTOGOONOREQLTGTLEGENEFORLETREMDIMDEFNOTANDTANSINCOSSQRTABLOGLENFREATNABSEXPINTENDPOSRNDSGNINPASCVALXORSUBOUTTHENREADGOTOELSENEXTSTOPDATAFILECHR$MID$STEPSTR$COSHSINHPRINTINPUTGOSUBCLOSELEFT$RETURNRIGHT$REMARKRESTORERANDOMIZE    HEFIJNTLGAKBOCDPQX! )&$"%(c#RU'WYZ-,+*S.V03%| 7EJMNNAFGFADE $BASNS $!c,r+s+q!f,r+s+q>!"g,!*g,!-s+p+q+p+q:-=2-*-*- w*-#"-*-#"-!-s+q+p+!{,6!-q:S-<2S-H!S-6*S-&, :-wT-R !-q*-DM|*-ME E!-6:-!-s*-&T- NE!-4Uq,!-6: :,Hҫ *,DM;!,62,:-R:-<2-O!T- :,w:, *-#"-:q,!l,:-=O8!-6:, !,6 :,*,&*,~:,<2,!,'!,6.'>2, 5>  :,HT9:,\k h]9!-p+q:-<<2-:j,҆!q,6:|,ʥ:, ʢU2,Î9:j,*r,#"r,*-|OE*-}OE?E:-=2- E^Eq!q,6!t,6:i,m4E h :|,' :, $ 2,U h :|,cd 3V *,MV  P U*,MV ; ,V V *u,+"u,h E Ë :,\y UË p /Ҋ CIlí:,/ :,<2,O!, :,w:,!,?w:, !,6͏ 9͏ 2,:,0O> /:,a/>z!,/H:,. !n, :,_2, :,AO>/ H  H H D 7 :, P 9!,6!-q*u,#"u,:j,o *-M> !,| >*,&O n&"-!-6*,&Y ~!-  *,&c :-O! ~2|,O>@:|,cH :|,AO!m ~2},:|,2~,!|,65>:,-N *- w_;ͭ *Z.6  *Z.q#p*^.&-) *-s#r:f.X.0+s#r*-~ͭ *Z.>!g.qͭ *Z.:g.wͭ *Z.~ͭ *Z.^#V!h.qͭ *Z.:h.wͭ *Z.~J 2k.!l.6:k.!l.  o&-"i.*i.-M *i.N#F`i"i.  *Z.*i.N#Fq#p!l.4¦ J 2p.!o.6:p.!o.H *-#"m. O!- *m.N#Fq#p O!- *-s#r!o.4!.0q:i,[*.0M!"-"u,}202-0!"-!"-:i,!h "\.!^.61 1I$IQ V !f "\.!^.60 0I$IQ V !/0q:j,!k,j ̓*/0M|q:*/0M! ^#V!10 NSls DMT!ͤT9*(0M/J H@SIlT*-DM919]*A0"?0ͪ9ͪ909]09*'0MҤ*-DM͊*-DM J OxêUFl9*~,M:30Ox9͍9,A99 T9 T9 T9 T999T9T9*V. ^#V"-:005ͤs DMTͤ:00Vs DM?ͤͤ:00ҍͤ?ͤ?8ͤ ͤ?9ͤ ͤ7ͤ*V.N#F(*V.##*-s#r96ͤ*V.##N#F(*V. *-s#r9!w,6>V.X+s#r"-*-#>w+ !-49q:-=2-*-:-w*-#"-!-q:p,9*-&͕D*-&͕!-q:- j:,<2,g QÂ!,4*-M :- ‚!,6!-p+q*-~$ʣ*-NE*-#"-É̓ͯ *,DM; *, 6 *, 6*,̓ͯ͡,ͤ͡:o,*, ,;,͕,͡(ͤ!,6*,͡2-O>Dͤ:-:o,P,͕,͡h͕ͤ E E!-p+q!-6+6>!-!-60*-&) -[ *-&) -[ +s#r!-6#4Ø:-/!-*-ME E!-4Š!x,6#6#6!w,6,;ͮ!,6#6!"-}2-,!,6!-6:9:,$¬!-6:-<2-O!, ~2- ʬ:-A2-O>ک*-M! ^#V!k,6é!l,6é!o,6é!n,6é!m,6é!p,6ému}7!,6!,6!|,6#6:,"!,!|,62!,6":, SUl͏ :,9:," ͏ Ë HҜ!|,61:,062,%7 F 7 :,E€ :,+:,-Ho /}FIl7 :,•!,60!,6#60E Ë  k % Ұ ã:,$!},62 !},61p / :,F:,NH:,H!|,66 !|,6+s#r#4” >!-6*-&*-:-<2-O!, :,!-/HE  :,!-_ogN#Fog01PROD $ ERRORS DETECTED$:i,қ ->@_!l0"X.*++"V."-*-#6!_.q*-^*-*_.& "Z.!`.6*-##"Z.!a.6*-~!a. *a.&*Z.:`.?2`.!a.4 :`.*-^*-"-*-#"Z.*^.&-) ^#V!b.q:b.X.0!V.cP !j,6OTlͯ!d.p+qͭ *Z.*c.s#r*Z.+"Z.*Z.>w "->-X *-~2e.*\. *e.& *-*e.&*\. :e.=2e. >Ù  *Z.^#V"-} >*\.>2f.O+ *X."-*\.#*X.###*\.99*'0M>h .s -[+LDl;*-DMQ V C!-6*i9i9͗99999999999999999999999999ҪY9:10½*;0DM?99*20Mͤ9 9]99 ͤ99 ͤ992:301$*20Mͤ2:20Oͤ1B99T:301OͤTͤ9cͤ9m9|0ͤ99Ҏͤ9ҝͤ99үͤ9:00*90DMTͤ999*50MB9*'0M9:w,IFl1*;0"-͑ T9*V. ^#V"-s DM?.ͤ(9͎9͎9[ͤ^ͤͪs DM(999͎6ͤͼ9:502~EIl7ͤͼ9ү*;0"-*20MV ͛ ͎ͤͤ96ͤͼ*'0M2c0*30MB*-DM:i,:c0DFl*-DMQ  99T9T99999*(0M:4012FIl*90DMT-ͤ99?99@9@91*;0"-9*(0M!i,ҁPDlV :i,ҕ DMQ s DM?T*-DM9199:302FMl[ͤ@ͤ9:302FMl[ͤ@ͤ9:y,>ͤ!y,69   9'ͤ!z,69o9o999!y,699?ͤ!y,699999994ͤ9!y,6[ͤ&ͤ9!y,6[ͤͤ[ͤ%ͤ99:y,/ҧ5ͤ999͎99ͮs DM?`ͤͤ99:10>!S0q*S0M> >*-#"-!U0p+q*T0|Oͤ*T0}Oͤ!W0p+q!V0DDM(!Y0p+q!X0DDM(:m,~*-M?_ͤ!+0"\.:-0?2^.!Z0q:i,ҭ :Z0-0DMQ !-04w 2[0ͮs DM(:401:301HFMl>>!40:30MMl>>Il DMQ V s "90DM:w,@!w,6*V. *-s#r!`0p+q20ͤ!a06*_0~!a0v*a0&*_0Nͤ!a04V:,҃ͭÉͤQ.ͤ10*'0MJ HҾs DM(!b06:,!b0*b0&, NI!b04$I*-#"-DM(:y,:301 +ͤ,ͤ/:301*:00J'#ͤ/$ͤ:10 \*;0"- *-DM:70=270Ofs DM?:10 *;0"-͑ !50{PFlY:501!70ҕPFl:70Of:40=240OB:10 :70NFlͤ*?0"-s DM(:40NFl*10Mͤ:402B1B    #/7ceij' cj(>JJFIK!!*!&O@ G  "H}~R&JQTUE. HJ %'<$% =>?S  "H}~R&JQTU  "H}~R&JQTU-|z {  C0D6C"$   !"#$%-/02<=>?@$BCCCCCEFYZZZ[\Y%]^_`aaabcdgldddosvz~ddddddd$$  #&),/3579;=?ACFILOSVY\^adfhkmptvy{}2/7!;22 $$%%''))+++++---22555Mͤ9IOUX[^adgjmpsvy| 58Wfp"PVekqz /7?WZ`pBHQTZ`l%+36CIORX^ai{ #&,dlt*'0&s/ ~200*)0& ~220*(0& ~210*'0&/ ~230*)0& ~250*(0& ~240*'0&.) ^#V"90*)0&) ^#V"=0*(0&) ^#V";0*(0&. ~270*)0& ~280*'0& ~260*'0&/) ^#V"?0*(0&) ^#V"A0!D0p+q*'0&.) *C0*30MB:301>FMl>:502+FMl[ͤ:10<210OT*00M̀  ͤ*00Mͤͤ:501iͤnͤ4ͤ!z,6;ͤ:00*90DM?:z,Ҡ"1͹ø:y,ұ)*͹ø=<͹!]0s+q:302*\0Mͤͤ*]0Mͤͤ[ͤ:0<20O!0 N?\ͤ9ͤ*0&0 :00w:-=2-/!-6UNli6ͤ*- N#F(!-D*-q#p*-#>i*-"-R*)0M*- -MHҐÖINl:-ҤLUl!-6*'0Mh /!j,!-6ͪ:{,ͤ6ͤs DM(!^0q*^0MJ U:i,/*)0M DMQ *50M̀ V :10577BBCCDDEEFFHHHHHHHHHIJKLLMMMNNOPQRSSTTUVVWXXYZZ[]]^__``abbcccffggghhiijjllmnnopqqsttvvxxyyz{|}~                 #'(+7Uaceiju   BASIC-E COMPILER VER 2.1$1a,)̓q͒+:j,!i,Ҁ+!t,6!*06!y"q.!'06!&06!S/6:t,}+>x!q.,T*ʹ+*'0&s.) *q.s#r͜+"d0+ͩ+*d0+"f0*d0"d0f0d0,Q**d0l :|,1**'0&S/ :&0w!j06:,!j0)*j0&, N+!j04)*'0&. :,w*'0&/ :},w*d0P!) ^#V"q.!*06*f0"d0D*f0d0,D*PNl*d0"d0Ұ)z+>!q.,+ͩ+:'0+!(0s:(0<2)0>q.,M:t,+:(02'0͜+"d0*'0&S/ ~2&0*'0&s.) ^#V"f0*d0 n&"h0}h0f0,H**d0#"d0ñ**d0$) ^#V"q.>++!t,00E1D00D62D0909E52A6D2EE34E2346E171237087 :100E2D00CDC70B4F060021D62D0909E52AD42DE90 :100E3D00E1732372216F2E34C2020EC9212E30713F :100E4D003A692C1FD25B0E2A2E304DCD60:C921D5 :BB)5D00000022CB2D227527D32173022D302102 :100E6D00010022CF2D21FFFF22CD2DCDF0043A69B7 :100E7D002C1FD2CB0ECDFC0321680B225C2E215EE4 :100E8D002E3631CDDD0C0E31CD490E0E24CD490E51 :100E9D00010000CD510C0E04CD560D21660B225CC8 :100EAD002E215E2E3630CDDD0C0E30CD490E0E24AA :100EBD00CD490E010100CD510C0E04CD560DC921A9 :100ECD002F30713A6A /* ** lib.c -- function library ** ** Copyright 1982 J. E. Hendrix */ #define NOCCARGC /* don't pass arg count to functions */ /* called by these functions */ #include stdio.h /* ** dtoi -- convert signed decimal string to integer nbr ** returns field length, else ERR on error */ dtoi(decstr, nbr) char *decstr; int *nbr; { int len, s; if((*decstr)=='-') {s=1; ++decstr;} else s=0; if((len=utoi(decstr, nbr))<0) return ERR; if(*nbr<0) return ERR;(str[sz]!=NULL) ++sz; while(sz) { str[--sz]=(nbr%10+'0'); if((nbr=nbr/10)==0) break; } if(sz) str[--sz]=sgn; while(sz>0) str[--sz]=' '; return str; } /* ** itou -- convert nbr to unsigned decimal string of width sz ** right adjusted, blank filled; returns str ** ** if sz > 0 terminate with null byte ** if sz = 0 find end of string ** if sz < 0 use last byte for data */ itou(nbr, str, sz) int nbr; char str[]; int sz; { int lowbi if sz < 0 use last byte for data */ itox(nbr, str, sz) int nbr; char str[]; int sz; { int digit, offset; if(sz>0) str[--sz]=NULL; else if(sz<0) sz = -sz; else while(str[sz]!=NULL) ++sz; while(sz) { digit=nbr&15; nbr=(nbr>>4)&4095; if(digit<10) offset=48; else offset=55; str[--sz]=digit+offset; if(nbr==0) break; } while(sz) str[--sz]=' '; return str; } /* ** left -- left adjust and null terminate a string */ left(str) char *str; { char 6z+>!q.,_+͜+"d0+*d09 n&"h0}!h0:|,,HM+*d0#"d0+*d0") ^#V"q.z+ʹ+ͩ+*'0&s.) q#p͜+"q.m)C)!l,6͒+!j,6C)v́ \*q.%) ^#V*q.' n&:'0<2'0 +OSl:*0+ͭ!*06!k0q*&0&/ :k0w:&0<2&0O>d+OVl_{ozgi`N#Fogo&og_{_z#W92E4E234603606922692EC3C10D7B :100DDD00CD140CDu=)B92EE35 :100DED002370216C2E34C2A60DC9CD4A0D32702E42 \ INT16F2EBEDA480ECDA000E0D00020C2AD42D23226D2ECDC70B4F060021A7 :12C216B2CA61FD2ED0E016AC0 :100EDD000BCD83032A2F304D0600CD7C04CD71043C :100EED00CD3A182A2F304D060021071709095E2328 :100EFD0056EBE9C33918C339182A27304DCDF019EF :100F0D001FD23E0FCD680D1FD22E0FCD730D11CBFD :100F1D002DCD5B1FB5CA2B0F014C44CD6C06C33BC9 :100F2D000F2ACB2D444DCD510C0E08CD560DC3437C :103D000F21A92D362ACD691AC33918CD691AC3C7 :100F4D003918CD971CC33918C33918C33918C3398B :100F5D0018C33918C33918C33918C33918C3391808 :100F6D00C33918C33918C33918C33918C33918C34D :100F7D003918C33918C33918C33918C3391 if(s) {*nbr = -*nbr; return ++len;} else return len; } /* ** itod -- convert nbr to signed decimal string of width sz ** right adjusted, blank filled; returns str ** ** if sz > 0 terminate with null byte ** if sz = 0 find end of string ** if sz < 0 use last byte for data */ itod(nbr, str, sz) int nbr; char str[]; int sz; { char sgn; if(nbr<0) {nbr = -nbr; sgn='-';} else sgn=' '; if(sz>0) str[--sz]=NULL; else if(sz<0) sz = -sz; else whilet; if(sz>0) str[--sz]=NULL; else if(sz<0) sz = -sz; else while(str[sz]!=NULL) ++sz; while(sz) { lowbit=nbr&1; nbr=(nbr>>1)&32767; /* divide by 2 */ str[--sz]=((nbr%5)<<1)+lowbit+'0'; if((nbr=nbr/5)==0) break; } while(sz) str[--sz]=' '; return str; } /* ** itox -- converts nbr to hex string of length sz ** right adjusted and blank filled, returns str ** ** if sz > 0 terminate with null byte ** if sz = 0 find end of string ** *str2; str2=str; while(*str2==' ') ++str2; while(*str++ = *str2++); } cout(c, fd) char c; int fd; { if(fputc(c, fd)==EOF) xout(); } sout(string, fd) char *string; int fd; { if(fputs(string, fd)==EOF) xout(); } lout(line, fd) char *line; int fd; { sout(line, fd); cout('\n', fd); } xout() { fputs("output error\n", stderr); abort(ERR); } /* ** printf(controlstring, arg, arg, ...) -- formatted print ** operates as described by Kernigh    an & Ritchie ** only d, x, c, s, and u specs are supported. */ printf(argc) int argc; { int i, width, prec, preclen, len, *nxtarg; char *ctl, *cx, c, right, str[7], *sptr, pad; i = CCARGC(); /* fetch arg count from A reg first */ nxtarg = &argc + i - 1; ctl = *nxtarg; while(c=*ctl++) { if(c!='%') {cout(c, stdout); continue;} if(*ctl=='%') {cout(*ctl++, stdout); continue;} cx=ctl; if(*cx=='-') {right=0; ++cx;} else right=1; if(*cx=='0') {pad='0'; ++cx;} sptr==' ') ++sptr; len=-1; while(sptr[++len]); /* get length */ if((c=='s')&(len>prec)&(preclen>0)) len=prec; if(right) while(((width--)-len)>0) cout(pad, stdout); while(len) {cout(*sptr++, stdout); --len; --width;} while(((width--)-len)>0) cout(pad, stdout); } } /* ** sign -- return -1, 0, +1 depending on the sign of nbr */ sign(nbr) int nbr; { if(nbr>0) return 1; else if(nbr==0) return 0; else return -1; } /* ** strcmp -- return -1, 0, +1 ; *nbr=t; } return d; } /* /* ** xtoi -- convert hex string to integer nbr ** returns field size, else ERR on error */ xtoi(hexstr, nbr) char *hexstr; int *nbr; { int d,t; d=0; *nbr=0; while(1) { if((*hexstr>='0')&(*hexstr<='9')) t=48; else if((*hexstr>='A')&(*hexstr<='F')) t=55; else if((*hexstr>='a')&(*hexstr<='f')) t=87; else break; if(d<4) ++d; else return ERR; *nbr=*nbr<<4; *nbr=*nbr+(*hexstr++)-t; } returnLINKASM.COM 01/07/80 by Ward Christensen OVERVIEW: LINKASM is based on CP/M assembler 1.0, and is compatible with 1.0, 1.3, and 1.4 assemblers. (2.0? Dunno.) ---------------- LINKASM is a rewrite of CP/M 1.0 ASM.COM, incorporating: * A new pseudo-op code, LINK. * Smaller .COM file size (6K vs 8K). * Faster execution via larger ASM, HEX, and PRN buffers * Corrections to properly handle lower case DB values. * Prints the number of source lines read * Produces a symbol table for use under S.ASM) will take place, and the assembler will never see the ENDIF. This is not a problem as the next encountered IF will be handled properly. ---------------- USAGE: LINKASM is totally compatible with ASM.COM, and you may therefore replace ASM. Its performance will be slightly better than ASM.COM, and it takes less space on disk (6K vs 8K). Execute it just like ASM.COM, i.e. LINKASM name.p1p2p3 where: p1 is the .ASM file disk (A, B, ...) p2 is the .HEX file disk (A, B, ... or Z forelse pad=' '; if((i=utoi(cx, &width)) >= 0) cx=cx+i; else continue; if(*cx=='.') { if((preclen=utoi(++cx, &prec)) >= 0) cx=cx+preclen; else continue; } else preclen=0; sptr=str; c=*cx++; i=*(--nxtarg); if(c=='d') itod(i, str, 7); else if(c=='x') itox(i, str, 7); else if(c=='c') {str[0]=i; str[1]=NULL;} else if(c=='s') sptr=i; else if(c=='u') itou(i, str, 7); else continue; ctl=cx; /* accept conversion spec */ if(c!='s') while(*depending on str1 <, =, > str2 */ strcmp(str1, str2) char *str1, *str2; { char c1, c2; while((c1=*str1++)==(c2=*str2++)) if(c1==NULL) return 0; return sign(c1-c2); } /* ** utoi -- convert unsigned decimal string to integer nbr ** returns field size, else ERR on error */ utoi(decstr, nbr) char *decstr; int *nbr; { int d,t; d=0; *nbr=0; while((*decstr>='0')&(*decstr<='9')) { t=*nbr;t=(10*t) + (*decstr++ - '0'); if ((t>=0)&(*nbr<0)) return ERR; d++ d; } /* ** abs -- returns absolute value of nbr */ abs(nbr) int nbr; {if(nbr<0) return -nbr; else return nbr;} f((*hexstr>='0')&(*hexstr<='9')) t=48; else if((*hexstr>='A')&(*hexstr<='F')) t=55; else if((*hexstr>='a')&(*hexstr<='f')) t=87; else break; if(d<4) ++d; else return ERR; *nbr=*nbr<<4; *nbr=*nbr+(*hexstr++)-t; } returnID The LINK pseudo-op allows a file to "chain" to the next .ASM file, thereby allowing very large source files to be processed without having to PIP them together. RESTRICTIONS: All the linked .ASM files must be on the same disk. Nested IFs are not handled (ASM.COM didn't either) Note that you can use IF to conditionally link to the next module: IF CLOCK LINK CLOCKRTN ENDIF ; IF NOT CLOCK LINK OTHERRTN ENDIF For example, if CLOCK is true, then LINK CLOCKRTN (i.e. CLOCKRTN none) p3 is the .PRN file disk (A, B, ... or Z for none, or X for the console) The default is the logged in disk for all 3. If you wish to write a symbol table file, follow the command line with the disk to be written to (A, B, ...) then a colon. For example, to assemble FOO from the A: disk, put the .HEX on the A: disk, send the .SYM file to B:, and the listing to the console: LINKASM FOO.AAX B: To assemble it doing everything on the A: disk (assuming A: is the logged in disk):     LINKASM FOO A: The ":" must be specified after the .SYM disk. The .SYM file is "partially" sorted, i.e. all Axxxx then all Bxxxx etc. SID fully scans the symbol table anyway, so sorting it is not necessary, so I did this quick sort hack just to make it eaiser for YOU to find a symbol. ---------------- The LINK pseudo ops take a single operand: the name of an .ASM file to be processed next. For example: ---------------- A:TEST1.ASM: ORG 100H LXI H,MSG MVI C,9 CALL BDOS RETin an error message saying the name of the missing file, if you should accidentally LINK to a non-existant file. It just says the source file is not present. If necessary, you can find the name which was being searched for. It's in memory at 186H. If you have a PROM monitor, you can examine it. If not, do the following BEFORE executing any more COM programs following the LINKASM: SAVE 1 BADNAME.COM Save 100-1ff to disk DDT BADNAME.COM Bring in under DDT (or SID) D186,190 Dump the nall (HEX and SYM, no PRN). Ward Christensen r to put LINKASM in the CP/M UG with that problem, rather than holding it back "trying to make it perfect". ---------------- I have not encountered any problems using LINKASM as my main assembler for about the last 6 months. Among other things, I use it to assemble CBBS.ASM which, with its 14 or so LINKed files, is over 6000 lines. It takes about 5 1/2 minutes, as I rec16ÃLINKASM AS OF 7/13/79 6060ASMPRNHEX!w_#~ A:~3~# > 3\ ? w#! !x ! ::::! :l2:] 2!d222!!luOT:ʋ!|OTË!"22 LINK TEST2 ---------------- A:TEST2.ASM: MSG DB 'Linked' BDOS EQU 5 ---------------- Then assemble it: A>LINKASM TEST1.AZX LINKASM AS OF 7/13/79 0100 ORG 100H 0100 210901 LXI H,MSG 0103 0E09 MVI C,9 0105 CD0500 CALL BDOS 0108 C9 RET LINK TEST2 0109 4C696E6B65MSG DB 'Linked' 0005 = BDOS EQU 5 010F 000H use factor 8 input lines read End of assembly ---------------- I will make one apology for LINKASM - I neglected to put ame ^C Reboot (some people use G0) ERA BADNAME.COM ERA the temporary file. Sorry for that hack, but I thought it better to put LINKASM in the CP/M UG with that problem, rather than holding it back "trying to make it perfect". ---------------- I have not encountered any problems using LINKASM as my main assembler for about the last 6 months. Among other things, I use it to assemble CBBS.ASM which, with its 14 or so LINKed files, is over 6000 lines. It takes about 5 1/2 minutes, as I rece-!2 z{*he!" !6\w# M6h6# a6*#"~ z!I G:ʦxŸ3æͨ*!6'w#"!u!"!6'~~# !`  *!6+w#"!|!"!6+_O͈: :y3:!jG~@#x=[2> @> @!>x6 #=|G!~ plʤ*}ʤ>͈Ô::p*f"n*}>ülu>:|>:=2!    22uOT!"! ,ͅA@x[1!80PbvC:c:d~O#~zn+}|#|T]|##x G###*|~_##N#~y~͞#¦> ͞> ͞##~#foÈ> Þ*}>͈u>Ɛ'@'ÞSYMBOLS ! No source file present No directory space Source file name error Source file read error Output file write error Cannot close files End of assembly G:x!p~ڻ*f*nO {z*f"n!p^4!qwWƐ!"! N#~#A 0 7O!I] ~*!< 6 )- " :H c ''Á>Vi >Oi ̈́!6/w#w#y !"l! F# 2r G*l##~w*l##~<*l}͈ ! ~ 6!r ^!6/^#fk"lͯ ͥ !  G#*l### # *l^#V ! ^*c"l*{zX "c*l!r N!6/ N#Fr+sq#p F >G=#w#wJ #w#w!a ÎSymbol table overflow G*l##~w*l##~ͥ *l_###͖ s#r͖ ^#V  4  c y ()*+,-/ABCDEHLMDBDIDSDWEIIFINORSPACIADCADDADIAN !" #  ɯ<: O=_f ! F! V#fjQ͏ Q ! ^#Vo&)~#F xGyѯ<! ~ڠ ̓6~44O! s#r! ~ ڽ 6̓^4!k w!u p! ~ ̓!55N! N#fi o&) ^#fk z%{̓>ɯo>g "i!k6ů{_zW5>)D*iOxGb !k?DDM!xGyOڀÁ)q lÑ 3Ñ 3Ñ ʑ )=àʑ |g}o=ì Ñ + +Ñ # zg{oÑ zg{oÑ zg{o*}x*l":´:!:´ñ9X!8^#fkP   0ͥ:: =ʁG!!{F#kÐ*a|lE͔,SÓͥA3*h"h"fÓͥ3ED͔,ʸÓͥA: “3: "> 2::! 3!!: ZG> ZOw#& 86 #.:HZ 8ñp# &8!f U++ERROR IN LINK OPERAND++ ͛*h3"hͥD!6="hÓͥ3: “}ړ::!>B̄õµ µµxµ3~Ó3: “"h"f ! *c*j**j\6D!8Fw#-H use factor ! *"f!a#~ U Î input lines read :e> !g~0 60+Ä*f"h*"lͯ ͛!":e͉ xw *hͤ ͉ rͭ *hrG:ex͛: *hD:x1*f#"fED0:!^4!w!!*h!6z1{14>R̈́>V̈́>DÁ>PÁ>LÁ>N̈́'@'>:!p^Ww*n{|}{7!q~#.> >  n n:xn_<2!w͇2H2> 2GU>2ɯ2 2I! ~@ڝ6c ^4#:Hw~$w:H0 ͯ:HA:HAͯ:Ha{_2HJ2H: !ɯ2͇:H 9;&*2:G 2?& ? J>~ͯU>~:H'f2H>~ |:eU!6 >2>2:H2Gď:!H:±ͨʁÁG ͨʁͺ:HOQ>H>2I2H :GB>D> ! 52IAANDANICMACMCCMPCPIDAADADDCRDCXENDEQUHLTINRINXJMPLDALXIMODMOVMVINOPNOTORAORGORIOUTPOPPSWRALRARRETRLCRRCRSTSBBSBISETSHLSHRSTASTCSUBSUIXORXRAXRICALLLDAXLHLDLINKPCHLPUSHSHLDSPHLSTAXXCHGXTHLENDIFMACROTITLE  PF FP! ( 2/?'  v:P@< !  PP27 ( *"  NZZ NCC POPEP M x _BH!¨ !# ² { KÔ CÔ <:!JCR:    !#6  ::! ;,!ɯ2 2 =2j !"a[! ~F5_!k ~ .: ă: * "a: }:‡: ̃ԃ!!^#=ʃVo’*o /$ O:j ³̃>2j y : _!u ~! s!k ~ ÷y ! ~=w_!k ~ ̓ͮ >2j }y}P̈́ l͉ >Ūͭ :j ̃2j ͑ (>Ë́ɯ2es p!2p!""f"h":ʱ:!*“͛ô %͵ ͯ  :er͉ ~ôͥAÓ͉͛ x>w 3͛ͤ !"Ó~Ó!_!M^#fkkt^ys^T8ʓXy0sTGyITymmT(XysITTXy0Tm͔ͥÓ:l:!,; l*a3|b}?bI8OTXy0?3:‹:!,ʐ>C̈́ͥ::! ¬ñ;ͥ:´:! ʱ!ʱô!ʱ>S̈́ô{ozg!e~4ʒA!6   ; ; ; 'PASCAL' FIRST READS IN AND SCANS THE DIRECTORY FOR THE 8080/ ; Z80 INTERPRETER (SYSTEM.MICRO). THEN THE INTERPRETER IS ; LOADED INTO MEMORY AND STARTED AT THE SYSTEM.PASCAL BOOT VECTOR. ; ; THIS PROGRAM PROVIDED COURTESY OF NORTHWEST MICROCOMPUTER SYSTEMS, INC. ; ; ;MODIFIED ; 10/11/78 BY WINK SAVILLE TO READ IN ANY SIZE INTERPETER ; BOOT EQU 0H ;LOCATION OF CP/M BOOT VECTOR BDOS EQU 5H ;CP/M ENTRY VECTOR TPA EQU 100H ;START OF USER AREA ; RDCON EQU 1 WRBUF EQU 9 ; NBLOC JMP START ; ; ; ORG START ; ; LXI SP,100H MAIN: ;LET'S BOOT SYSTEM.MICRO CALL INIT$IO ;RESET I/O SYSTEM ; CALL REQUEST$DISK ;GET PASCAL DISK ON DRIVE A MVI C,0 ; THEN SELECT THE DRIVE CALL SELDSK ; LXI B,DIRTOP ;READ THE DIRECTORY INTO DIRTOP CALL READ$DIR ; LXI H,DIRTOP ;SET THE DIRECTORY ENTRY POINTER LXI D,DENTSZ ; TO FIRST ENTRY AFTER THE VOLUME NAME DAD D SHLD DENTP ; CALL FIND$INTERP ;THEN FIND THE INTERPRETER CALL SAY$LOADING ;GOT IT SAY WHAT WE'RE UP TOEAD$DIR: ;READ DIRECTORY'S 4 BLOCKS TO BUFFER ;BUFFER ADDRESS IS ALREADY IN BC-REG MVI E,4 ;DIR IS 4 BLOCKS LONG LXI H,2 ;AND STARTS AT BLOCK #2 CALL SYSRD ;GO GET IT RET ; ; FIND$INTERP: ;FIND 'SYSTEM.MICRO' MVI C,77 ;STOP AFTER THE 77'TH ENTRY LHLD DENTP ;GET STARTING ENTRY FI$SCH$LP: LXI D,DTITLE ;ADVANCE TO TITLE STRING DAD D LXI D,SYSTLE ;SET DE-REG TO COMPARISON STRING MVI B,LENGTH+1 ;COMPARISON LENGTH FI$CMP$LP: ;START COMPARING LDAX D CMP M JNZ FI$CONT  ;WE'VE GOT IT RET ; NOTFNDMSG: DB CR,LF,'INTERPRETER NOT FOUND',CR,LF,EOM REBOOTMSG: DB CR,LF,'REBOOTING CP/M',EOM ; LENGTH EQU 12 ;TITLE LENGTH SYSTLE DB LENGTH,'SYSTEM.MICRO' ; ; SAY$LOADING: ;WE'RE GOING TO LOAD THE INTERPRETER MVI C,WRBUF LXI D,LOADINGMSG CALL BDOS RET ; LOADINGMSG: DB CR,LF,'LOADING...',EOM ; ; READ$INTERP: ;PUT INTERP IN ITS PLACE LHLD DENTP ;GET STARTING BLOCK MOV E,M ; INTO HL-REG INX H MOV D,M ; ;COMPUTE THE LENGTH OF THE INTERPETER PUNC OK ;JIF OK ;ELSE TELL OPERATOR AND REBOOT LXI D,INTERP$TO$LARGE MVI C,WRBUF CALL BDOS ;PRINT THE MESSAGE JMP REBOOT ;REBOOT CPM INTERP$TO$LARGE: DB CR,LF,'INTERPETER TO LARGE IT WILL OVER WRITE' DB CR,LF,'THIS PROGRAM. REASSEMBLE THIS PROGRAM' DB CR,LF,'WITH A HIGHER STARTING ADDRESS',CR,LF,EOM ; OK: LXI B,INTERP$BASE ;AND SET IT LOAD POINT CALL SYSRD ;THEN READ IT RET ; ; SYSRD: ;READ BLOCKS FROM PASCAL DISKETTE PUSH D ;SAVE BLOCK COUNT PUSH H ;AND BLOCK NUMBEKS EQU 32 ;MAXIMUM # OF BLOCKS FOR THE ;INTERPETER. USED TO COMPUTE START START EQU TPA+NBLOCKS*512 ;LOCATION OF THIS PROGRAM INTERP$BASE EQU TPA ;FIRST LOC USED BY THE INTERPRETER PBEGIN EQU INTERP$BASE+100H;ENTRY TO THE PASCAL BOOTER FIRSTSP EQU INTERP$BASE+103H;PASCAL INITIAL STACK POINTER DENTSZ EQU 1AH ;DIR ENTRY SIZE IN BYTES DTITLE EQU 06H ;OFFSET TO ENTRY TITLE DIRTOP EQU PBEGIN ;TOP OF TEMP RAM DISK DIRECTORY ; CR EQU 0DH LF EQU 0AH EOM EQU '$' ; ; ; ORG TPA ; ;  CALL READ$INTERP ; AND READ IT IN ; LHLD BOOT+1 ;NOTE: LOC 2 MUST HAVE CURRENT BIOS PAGE MVI L,0 ; FOR PROPER SYSTEM OPERATION SHLD FIRSTSP ; JMP PBEGIN ;START BOOTING SYSTEM.PASCAL ; ; ; INIT$IO: ;INITIALIZE SYSTEM RET ;THAT'S IT ; ; REQUEST$DISK: ;ASK FOR PASCAL MVI C,WRBUF LXI D,DSKMSG CALL BDOS RD$LOOP: ;THEN WAIT FOR A CR MVI C,RDCON CALL BDOS CPI CR JNZ RD$LOOP RET ; DSKMSG: DB CR,LF,'INSERT PASAL DISK IN DRIVE A, THEN TYPE RETURN',EOM ; ; R ;IT'S NOT THIS ONE INX D ;HEY, WE'VE STILL GOT A CHANCE INX H DCR B ;IS THIS THE END OF THE STRING JNZ FI$CMP$LP JMP FI$FOUND ;I THINK WE FOUND IT FI$CONT: LHLD DENTP ;ON TO THE NEXT ENTRY LXI D,DENTSZ DAD D SHLD DENTP DCR C ;WAIT, IS THERE ANY DIR LEFT? JNZ FI$SCH$LP ; MVI C,WRBUF ;NO INTERP THERE LXI D,NOTFNDMSG CALL BDOS ; ; REBOOT: MVI C,WRBUF ;TRY TO REBOOT CP/M LXI D,REBOOTMSG CALL BDOS MVI C,RDCON CALL BDOS ;WAIT FOR ANY CHAR JMP BOOT ; FI$FOUND:SH D ;SAVE FIRST BLOCK ON STACK ;TAKE 2'S COMPLIMENT OF FIRST BLOCK MOV A,E CMA MOV E,A MOV A,D CMA MOV D,A INX D ;DE=2'S COMP OF FIRST BLOCK PUSH D ;SAVE ON THE STACK ;GET NEXT AVAIL BLOCK INX H MOV E,M INX H MOV D,M XCHG ; POP D ;HL=NXT BLOCK,DE=-(FIRST BLOCK) ;SO HL+DE=LENGTH OF SYSTEM.MICRO DAD D ;HL=LENGTH XCHG ;DE=LENGTH POP H ;HL=FIRST BLOCK , DE=LENGTH ; ;CHECK THAT WE WON'T OVERWRITE OURSELVES LXI B,NBLOCKS MOV A,C SUB E MOV A,B SBB D JR CALL READ$RX ;BUFFER IS ADVANCED BY 512 BYTES POP H POP D INX H ;ADVANCE TO NEXT BLOCK DCR E ;BUT, BEFORE WE GO ON JNZ SYSRD ; SEE IF WE'RE DONE RET ; ; READ$RX: ;READ A PASCAL BLOCK DAD H ;THERE ARE 4 IBM SECTORS TO A PASCAL BLOCK DAD H ; SO MULT LOGICAL BLOCK BY 4 TO GET 1ST SEC MVI E,4 RR$LP: ;THIS GETS CONFUSING PUSH B ;SET BUFFER ADDRESS PUSH D PUSH H CALL SETDMA POP H ;NOW COMPUTE PHYSICAL TRACK-SECTOR PUSH H CALL MAP ;MAP CONVERTS LOGICAL SECTOR     IN HL-REG MOV C,H ; INTO PHYSICAL TRACK, H-REG, SECTOR, L-REG PUSH H CALL SETTRK POP H MOV C,L CALL SETSEC CALL READ ;AND READ THE DATA POP H POP D POP B PUSH H ;ADVANCE THE BUFFER ADDRESS LXI H,128 DAD B MOV B,H MOV C,L POP H INX H ;ADVANCE BLOCK COUNT DCR E ;THEN SEE IF WE CONTINUE JNZ RR$LP RET ;LEAVE, WHEN DONE ; ; DENTP DS 2 ; ; HOME: ;HOME SELECTED DISK TO TRACK 00 LHLD BOOT+1 MVI L,18H PCHL ; SELDSK: ;SELECT DISK (C-REG) LHLD BOOTL TRACK ; L-REG HAS PHYSICAL SECTOR ; ; PUSH B PUSH D ; CALL DIV26 MOV A,L ADD A MOV B,A MVI A,12 CMP L JNC MAPC INR B MAPC: MOV C,E XRA A MOV D,A MOV H,A MOV L,B MVI A,6 MAP$LOOP: DAD D DCR A JNZ MAP$LOOP PUSH B CALL DIV26 POP B INR L MOV H,C INR H POP D POP B RET ; ; DIV26: LXI B,-26 MVI E,0FFH DIVL: INR E DAD B MOV A,H ORA A JP DIVL LXI B,26 DAD B RET ; ; END START A 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D y+1 MVI L,1BH PCHL ; SETTRK: ;SET TRACK (C-REG) LHLD BOOT+1 MVI L,1EH PCHL ; SETSEC: ;SET SECTOR (C-REG) LHLD BOOT+1 MVI L,21H PCHL ; SETDMA: ;SET DATA TRANSFER ADDRESS (BC-REG) LHLD BOOT+1 MVI L,24H PCHL ; READ: ;READ A SECTOR TO THE DATA AREA LHLD BOOT+1 MVI L,27H PCHL ; ; MAP: ;TURN LSN INTO IBM TRACK-SECTOR ; ; NOTE: TRACK 00 IS NOT USED SO BLOCK 0 ; IS AT TRACK 01 SECTOR 1 ; ; ON ENTRY: HL-REG HAS LOGICAL SECTOR NO. ; ON EXIT: H-REG HAS PHYSICAA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D y   A 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D y    A 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D y   A 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D y12A3ABwA!"B̀AAB*." FA ;A INSERT PASAL DISK IN DRIVE A, THEN TYPE RETURN$!ͷBM*BA œA#ŽAA*B"B …A A A INTERPRETER NOT FOUND $ REBOOTING CP/M$ SYSTEM.MICRO B LOADING...$*B^#V{/_z/W#^#V yxҰB>B òA INTERPETER TO LARGE IT WILL OVER WRITE THIS PROGRAM. REASSEMBLE THIS PROGRAM WITH A HIGHER STARTING ADDRESS $ͷBB#·B)) CCLBMCC! DM#BST*.*.*A 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D yA 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D y.*.!*.$*.'=C}G> &CKWgh>=-C=C,a$ |BC M*BA œA#ŽAA*B"B …A A A INTERPRETER NOT FOUND $ REBOOTING CP/M$ SYSTEM.MICRO B LOADING...$*B^#V{/_z/W#^#V yxҰB>B òA INTERPETER TO LARGE IT WILL OVER WRITE THIS PROGRAM. REASSEMBLE THIS PROGRAM WITH A HIGHER STARTING ADDRESS $ͷBB#·B)) CCLBMCC! DM#BST*.*.*     Bringing UCSD Pascal up for the first time ------------------------------------------ To bring up Pascal first assure yourself that you have a standard BIOS area (i.e. all i/o vectors are in order) and that the warm boot vector is in place. Next if you have a single drive system, make sure that your BIOS ignors all requests to drive B. Two drive systems will require diskettes in both drives until you modify your disk drivers to return a not ready condition (i.e. a 1 in the A register) w TITLE '"PASTOCPM" - Convert Pascal file to CP/M file' ;From DR. DOBB'S - August 1979 ;Copyright (C) 1979 Ronald G. Parsons ;Modified by T. Mueller 9/1/79 ; Changes include: ; Provisions for designating disk drives. ; Re-ordering calls to disk routines to be of the form: ; select disk, select track, select sector, read/write. ; Cleaned up handling of null codes in .TEXT files. ; Set up new stack area and data buffers. ; Changed exit to simple return, no re-boot. ; Guaranteed .TEXT file on CP/M dill be asked for permission to overwrite. ;If the Pascal file is a .TEXT file, then two blocks are skipped ; and tabs replaced by spaces. LF is added after each CR. ;If the Pascal file is a .CODE file, then one block is skipped. ;If file is neither .TEXT or .CODE, the copy is exact. ; ; DLE EQU 10H DENTSZ EQU 26 ;DIRECTORY ENTRY SIZE IN BYTES DTITLE EQU 6 ;OFFSET TO ENTRY TITLE ; ORG 100H START LXI H,0 DAD SP SHLD STACK LXI SP,STACK ;SET UP PRIVATE STACK ; MVI C,LOGGED ;GET LOGGED DIhen the drive has no diskettee. Now bring up your standard system, and run the program PASCAL.COM supplied on the 8080/Z80 support diskette. This program will prompt you with a request for a Pascal system diskette in dirve A. At that time insert the UCSD distribution Pascal diskette and if you have a second dirve place any initialized diskette in that drive as well. Type return and enter the world of pascal. isk ends in EOF. ; Memory size independance for BIOS calls. ;9/22/79 - Corrected handling of DLE as last byte of read block. ; ;Transfers a Pascal file to CP/M file. ; ;Syntax -- PASTOCPM <[d:]CP/M filename> <[d:]Pascal filename> ; ;Disk drive (d:) identifiers may be entered. If none are supplied ; defaults are: CP/M file on logged drive, Pascal file on drive B:. ; ;Transfers the Pascal filename on a Pascal disk ; to the CP/M filename on a CP/M disk. If the CP/M file already exists, ; you wSK DRIVE CALL BDOS STA LDRIVE LDA FCB ;GET CP/M DRIVE ORA A JNZ DOIT ;NOT LOGGED DRIVE LDA LDRIVE ;GET LOGGED DRIVE INR A STA FCB ;FORCE SELECTION OF DRIVE DOIT LXI H,BUFF ;GET PASCAL FILE NAME LXI D,SYSTLE+1 MVI A,1 STA RDRIVE ;SET PASCAL DEFAULT TO DRIVE B SCN1 CALL SCBLK ;FIND NON-BLANK JZ SCN1 SCN2 CALL SCBLK ;FIND BLANK JNZ SCN2 SCN3 CALL SCBLK ;FIND START OF SECOND PARM JZ SCN3 INX H MOV A,M CPI ':' ;CHECK IF DRIVE ENTERED DCX H JNZ SCN4 MOV A,M ;   GET DRIVE SUI 'A' STA RDRIVE ;SAVE READ DRIVE INX H INX H ;SKIP DRIVE SCN4 PUSH H LXI H,RDRIVE LDA FCB DCR A CMP M ;CHECK IF READ AND WRITE DRIVES ARE SAME POP H JZ DRVERR MVI C,0 PFN2 MOV A,M ORA A JZ PFN3 STAX D INX H INX D INR C JMP PFN2 ; PFN3 MOV A,C ;GET FILENAME LENGTH STA SYSTLE ORA A JZ NOFLNM ;CHECK FOR .TEXT OR .CODE FILENAME LXI D,TEXT+6 DCX H ;HL POINTS TO END OF FILENAME PUSH H MVI C,5 TEXTLP LDAX D CMP M JNZ NOTEXT ;FILENAME DO LXI D,PERMSG ;GET PERMISSION TO DELETE IT MVI C,WRITECB CALL BDOS ; RDCHR MVI C,READC ;READ CONSOLE CALL BDOS CPI ABORT JZ EXIT CPI CR JNZ RDCHR ;INVALID RESPONSE, TRY AGAIN MVI E,LF MVI C,WRITEC ;CHARACTER TO CONSOLE CALL BDOS LXI D,FCB MVI C,DELETEF ;KILL FILE CALL BDOS ; CREF LXI D,FCB MVI C,CREATEF ;CREATE FILE CALL BDOS CPI 0FFH ;ERROR? JZ CERROR ;YES ; ;INITIALIXE BUFFER POINTERS ; INIT LXI H,BUFF SHLD BOL LXI H,BUFF+127 SHLD EOB LXI H,BLKBUF+51IP BLOCKS DEPENDING ON JM SKPBL2 ; .TEXT OR .CODE INX H JMP SKPBL1 ; SKPBL2 DAD H ;X2 DAD H ;X4 SHLD LSN ;(FIRST LSN) * 4 ; LR80B CALL R80B ;READ 128 BYTES LDA EOFFLAG ORA A ;LAST PASCAL SECTOR READ? JNZ FILL1A ;YES CALL WB ;WRITE BUFFER JMP LR80B ; FILL1A CALL CT ;FILL BUFFER WITH EOF CALL WB ;WRITE BUFFER LDA TXTFLG CPI 2 ;.TEXT? JNZ FILL2 ;NO LHLD EOB MOV A,M CPI EOF ;CHECK IF LAST SECTOR WRITTEN HAS EOF JZ FILL2 LXI H,BUFF SHLD BOL JMP FILL1ARY IS 4 BLOCKS LONG LXI H,2 ; AND STARTS AT BLOCK 2 CALL SYSRD ;GET IT RET ; ; FIND$FILE: MVI C,77 ;STOP AFTER THE 77'TH ENTRY LHLD DENTP ;GET STARTING ENTRY FI$SCH$LP: LXI D,DTITLE ;ADVANCE TO TILTE STRING DAD D LXI D,SYSTLE ;SET REG-DE TO COMPARISON STRING LDA SYSTLE ;COMPARISON LENGTH INR A ;COMPARE INCLUDES LENGTH BYTE MOV B,A FI$CMP$LP: LDAX D CMP M JNZ FI$CONT ;IT'S NOT THIS ONE INX D INX H DCR B ;CHECK FOR END OF STRING JNZ FI$CMP$LP ;NOT YET JMP FI READ$RX: DAD H ;THERE ARE 4 SECTORS TO A BLOCK DAD H ;MULT LOGICAL BLOCK BY 4 MVI E,4 RR$LP PUSH B ;SET BUFFER ADDRESS PUSH D PUSH H CALL SETDMA POP H ;NOW COMPUTE TRACK/SECTOR PUSH H CALL MAP ;CONVERTS LOGICAL SECTOR IN HL PUSH H LDA RDRIVE MOV E,A MVI C,SELECTD ;SELECT READ DISK CALL BDOS POP H MOV C,H ; INTO TRACK H, SECTOR L PUSH H CALL SETTRK POP H MOV C,L CALL SETSEC CALL READ ORA A JNZ RWERR POP H POP D POP B PUSH H ;ADVANCE THE BUFFEES NOT END IN .TEXT DCX H DCX D DCR C JNZ TEXTLP LXI H,TXTFLG ;GOT .TEXT FILE MVI M,2 LXI D,TEXT MVI C,WRITECB CALL BDOS ; NOTEXT POP H ;POINT TO END OF FILENAME LXI D,CODE+6 MVI C,5 CODELP LDAX D CMP M JNZ NOTCODE ;FILENAME DOES NOT END IN .CODE DCX H DCX D DCR C JNZ CODELP LXI H,TXTFLG MVI M,1 ;GOT .CODE FILE LXI D,CODE MVI C,WRITECB CALL BDOS ; NOTCODE LXI D,FCB MVI C,OPENF ;OPEN FILE CALL BDOS CPI 0FFH ;NON-EXISTANT? JZ CREF ;YES - CREATE IT2 SHLD BUFADD ; LXI B,DIRTOP ;READ DIRECTORY INTO THIS CALL READ$DIR ; LXI H,DIRTOP ;SET DIRECTORY ENTRY POINTER LXI D,DENTSZ ; TO FIRST ENTRY AFTER VOLUME NAME DAD D SHLD DENTP ; CALL FIND$FILE ;FIND THE FILE ; LHLD DENTP ;START OF DIRECTORY ENTRY MOV E,M INX H MOV D,M PUSH D ;SAVE FIRST BLOCK INX H MOV E,M INX H MOV D,M XCHG ;LAST BLOCK+1 IN HL DAD H ;X2 DAD H ;X4 SHLD LSTLSN ;(LAST LSN + 1) * 4 POP H ;GET FIRST BLOCK LDA TXTFLG SKPBL1 DCR A ;SK FILL2 LXI D,FCB MVI C,CLOSEF ;CLOSE FILE CALL BDOS EXIT LXI D,BUFF MVI C,DMAADD CALL BDOS LDA LDRIVE ;GET LOGGED DRIVE MOV E,A MVI C,SELECTD ;RESTORE LOGGED DRIVE CALL BDOS LHLD STACK SPHL ;RESTORE SP RET ;JOB DONE - GO BACK ; ;********************************************************* ; ; SUBROUTINES ; ;********************************************************* ; ;READ DIRECTORY'S 4 BLOCKS TO BUFFER ;BUFFER ADDRESS IS ALREADY IN REG-BC ; READ$DIR: MVI E,4 ;DIRECTO$FOUND ;FOUND IT ; FI$CONT: LHLD DENTP ;ON TO THE NEXT ENTRY LXI D,DENTSZ DAD D SHLD DENTP DCR C ;IS THERE ANY DIRECTORY LEFT? JNZ FI$SCH$LP ;YES FI$HANG: JMP NOFILE ;FILE NOT THERE ; FI$FOUND: RET ;GOT IT ; ; ;READ BLOCKS FROM PASCAL DISKETTE ; SYSRD PUSH D ;SAVE BLOCK COUNT PUSH H ; AND BLOCK NUMBER CALL READ$RX ;BUFFER IS ADVANCED BY 512 BYTES POP H POP D INX H ;ADVANCE TO NEXT BLOCK DCR E ;SEE IF WE'RE DONE JNZ SYSRD RET ; ; ;READ A PASCAL BLOCK ;R ADDRESS LXI H,128 DAD B MOV B,H MOV C,L POP H INX H ;ADVANCE THE BLOCK COUNT DCR E ;SEE IF WE CONTINUE JNZ RR$LP ;YES RET ; ; ;READ SECTOR GIVEN BY LSN ; RDSEC MVI C,DMAADD CALL BDOS LHLD LSN CALL MAP ;CONVERT LOGICAL SECTOR # TO TRACK/SECTOR MOV C,H PUSH H CALL SETTRK POP H MOV C,L CALL SETSEC CALL READ ORA A JNZ RWERR LHLD LSN INX H SHLD LSN RET ; ;CLEAR TO END OF BUFFER ; CT LHLD EOB INX H XCHG LHLD BOL CT1 CALL EQUAL RZ MVI M,EO   F INX H JMP CT1 ; EQUAL MOV A,L CMP E RNZ MOV A,H CMP D RET ;ZERO IF DE=HL ; ;READ A SECTOR TO BUFFER ; R80B MVI B,128 LXI H,BUFF R80B1 PUSH B PUSH H CALL RB POP H POP B PUSH PSW LDA EOFFLAG ORA A JZ R80B2 ;NOT EOF POP PSW SHLD BOL RET ; R80B2 POP PSW MOV M,A INX H DCR B JNZ R80B1 RET ; ;WRITE 128 BYTE BUFFER ; WB LXI D,BUFF MVI C,DMAADD CALL BDOS LXI D,FCB MVI C,WRITER CALL BDOS ORA A JNZ RWERR RET ; ;SCAN FOR BLANKS IN COMMA LDA TXTFLG CPI 2 ;.TEXT? JNZ NOTEXT2 LDA DFLAG ;WAS LAST CHAR DLE? ORA A JNZ RBFBT ;YES MOV A,M ORA A INX H SHLD BUFADD JZ RBFB ;SKIP BYTE OF ZERO CPI CR JNZ CKDLE STA NLF ;PUT LF AFTER CR RET ;PROCESS BYTE FOLLOWING DLE ; RBFBT MOV A,M INX H SHLD BUFADD SUI 32 ;GET INDENTATION STA NTB ;SAVE NUMBER OF COLUMNS TO INDENT XRA A STA DFLAG ;CLEAR TAB FLAG JMP RBCKTB ;DO BLANK EXPANSION ; ;CHECK FOR DLE CODE - USED FOR INDENTATION ; CKDLE CPI DLE RNZ BUF SHLD BUFADD ;RESET POINTER TO START OF BUFFER JMP RBFB ; SETEOF LXI H,EOFFLAG MVI M,1 ;LAST SECTOR ALREADY READ RET ; ;ERROR MESSAGES ; NOFLNM LXI D,NOFLNMSG JMP GENERR ; NOFILE LXI D,NOFMSG JMP GENERR ; RWERR ORI '0' ;MAKE IT ASCII STA WERMSG LXI D,WERMSG GENERR MVI C,WRITECB CALL BDOS JMP EXIT ; CERROR LXI D,ERRMSG ORI '0' STA ERRMSG JMP GENERR ; DRVERR LXI D,DERMSG JMP GENERR ; ;TURN LSN INTO TRACK/SECTOR ; ;NOTE - TRACK 0 IS NOT USED, SO BLOCK 0 IS A JP DIVL LXI B,26 DAD B RET ; ; ; ;BIOS ENTRIES ; SETTRK LHLD 1 MVI L,1EH PCHL ; SETSEC LHLD 1 MVI L,21H PCHL ; SETDMA LHLD 1 MVI L,24H PCHL ; READ LHLD 1 MVI L,27H PCHL ; NOFLNMSG DB CR,LF,'ERROR - Missing file name$' NOFMSG DB CR,LF,'"Pascal" file does not exist$' WERMSG DB ' Read/Write ERROR$' PERMSG DB CR,LF,'"CP/M" file already exists.' DB CR,LF,'C/R to continue, CTRL-C to abort$' ERRMSG DB ' ERROR in file Create or Open$' TEXT DB CR,LF,'.TEXT file bRITEC EQU 2 ;WRITE CONSOLE CHARACTER WRITECB EQU 9 ;WRITE CONSOLE BUFFER SELECTD EQU 14 ;SELECT DRIVE OPENF EQU 15 ;OPEN FILE CLOSEF EQU 16 ;CLOSE FILE DELETEF EQU 19 ;DELETE FILE WRITER EQU 21 ;WRITE RECORD CREATEF EQU 22 ;CREATE FILE LOGGED EQU 25 ;GET LOGGED DRIVE DMAADD EQU 26 ;SET DMA ADDRESS ; CR EQU 0DH LF EQU 0AH ABORT EQU 3 ;CRTL-C EOF EQU 1AH ; END START ND LINE ; SCBLK INX H MOV A,M CPI 0 ;CHECK IF END OF INPUT LINE JZ NOFLNM CPI ' ' RET ; ;PROCESS LF AND TAB FILL, GET BYTE FROM READ BUFFER ; RB LDA TXTFLG CPI 2 JNZ RBFB ;NOT .TEXT RCCKLF LDA NLF ;NEED LF? ORA A JZ RBCKTB XRA A STA NLF MVI A,LF RET ; RBCKTB LDA NTB ;NEED TAB? ORA A JZ RBFB DCR A STA NTB MVI A,' ' RET ; ;GET BYTE FROM READ BUFFER, AND FILL IF NEEDED ; RBFB LHLD BUFADD LXI D,BLKBUF+512 CALL EQUAL ;CHECK FOR END OF BUFFER JZ RBLK STA DFLAG ;SET FLAG FOR DLE FOUND JMP RBFB ;GET NEXT BYTE (COUNT) ; NOTEXT2 MOV A,M INX H SHLD BUFADD RET ; ;READ 4 SECTORS (A PASCAL BLOCK) ; RBLK LHLD LSN ;GET START LOGICAL SECTOR NUMBER XCHG LHLD LSTLSN CALL EQUAL JZ SETEOF ;FOUND LAST SECTOR LDA RDRIVE ;GET READ DRIVE NUMBER MOV E,A MVI C,SELECTD ;SELECT DISK CALL BDOS LXI D,BLKBUF ;READ 4 SECTORS CALL RDSEC LXI D,BLKBUF+128 CALL RDSEC LXI D,BLKBUF+256 CALL RDSEC LXI D,BLKBUF+384 CALL RDSEC LXI H,BLKT TRACK 1 SECTOR 1 ; ;ON ENTRY - REG-HL HAS LOGICAL BLOCK # * 4 = LOGICAL SECTOR # ;ON EXIT - REG-H HAS PHYSICAL TRACK ; REG-L HAS PHYSICAL SECTOR ; MAP PUSH B PUSH D CALL DIV26 MOV A,L ADD A MOV B,A MVI A,12 CMP L JNC MAPC INR B MAPC MOV C,E XRA A MOV D,A MOV H,A MOV L,B MVI A,6 MAP$LOOP: DAD D DCR A JNZ MAP$LOOP PUSH B CALL DIV26 POP B INR L MOV H,C INR H POP D POP B RET ; ; DIV26 LXI B,-26 MVI E,0FFH DIVL INR E DAD B MOV A,H ORA Aeing processed$' CODE DB CR,LF,'.CODE file being processed$' DERMSG DB CR,LF,'ERROR - Both files on same drive$' ; ; TXTFLG DB 0 DENTP DS 2 EOFFLAG DB 0 NLF DB 0 NTB DB 0 DFLAG DB 0 BUFADD DS 2 LSN DS 2 LSTLSN DS 2 BOL DS 2 EOB DS 2 SYSTLE DS 22 RDRIVE DS 1 ;DRIVE FOR READ LDRIVE DS 1 ;LOGGED DRIVE ON ENTRY ; DS 64 ;STACK AREA STACK DS 2 ;ENTRY SP BLKBUF DS 512 DIRTOP DS 2048 ; ; ;CP/M EQUATES ; BDOS EQU 5 FCB EQU 5CH BUFF EQU 80H READC EQU 1 ;READ CONSOLE CHARACTER W   !9":g.!XRGC !R@ />!>!X>Ss#r# ! ʹPP!P+ͪP|1&!P+&! ʹPͪP| '!ʹP!Q|PGMNAME33;;33;;:g.*dog*!~!!! { Aborted, reason = ! {~r0R0!3!d~pE.3"b#! {~p͏|p*b% p*b>w!! {! {|Ø+ {{  {! {|¶ý+ {! {>w(!! {! {~#{t! {! {+   #(w#>w!!>! !t! {Vw!w #Vè}}ô}>q4>4>a(!"I(!"E(!>?WK;*E(*G(,Q|ʚ(!ͧP>+3!î}}ú}S   !"!{"!"k!m!*{"E"C"7";"9"1""'"%"i"!"K")!"!m!"*{!"?"=?!"e!"G!"IjͲ͹j*A*;|p*a!Q͖*a!"A|)96!!ͽF!*a!Q͖*az:!Yg{|m!}2È*az:!Nm{|ʈ9Î9!*a!Q͖*az:!Yg{|!}2*az:!Nm{|ÎÎ!*a!Q͖*az:!Yg{|!}22*az:!Nm{|28!*a!Q͖*az:!Yg{|l!}2Ç*az:!Nm{|ʇ8Í8*A"MOutput file: wopen errorMonitor function headers? Sound alarm on errors? Pause on errors? Optimize for!!gqI{I{!!!wqI{I{!!!qI{I{;J*cz!"g{|f!*c#"c+!9*c!"-I{|ʇ!!}*c!!"?|ª!!"?!! G^=ropen failure on include file!7"!͆I|!!! {@"͊.!!<"!͆I! {!g{R{|3"!! {@"͊.!!charintn6|M"!|#SI|s"!9!I{!9!I{É"!9!I{!9!I{!~!:|ž"͐6!~7|ʳ"!~ͫ6!~#SI|"!9!I{"!#SI|"!9b'I{!9!I{! {!g{|t allowed with gotomust declare first in block*[(),!"! {|V%!9!I{!9! {I{k!L&SI|%!N&SI|%! {|ʸ%! {! {!9T9"9g |9*6 _2w;N9/9 fG9]:9іsa* 9h|&! {!g{! {!m{R{|ʑ&!$' G! {! { {*! {{{I{! {!g{|&o"'!9]f|"!q!͆I|!!j!!|.j!xSI|A5j!}SI|TG!j!SI|g;Cj';Jextern#asm#include#define!9!L{*͇{|6! {ͫo!9! I{!9 {+I{#|3!! {k9D!9! {H{!g{*́{R{|(G3!, FþÛ! {ʷ! {ͫo!9!I{!9 {+I{#|ʴ!D!9 {+I{!z{!g{R{|ʩGô!, F_:*7|! Gno closing bracket!"+"M}2}2}2}2!"a! size? !"=!|![!Q͖|\![!"=|O!!ͽF!!"C^=*C#"C+|r!";x!"=^=Input file: ropen error! {!͙F! {1!!!qI{I{!!!qI{I{!!!qI{I{!!!arI{I{!!!rI{I{! !ttI{! !/sI{! !tI{! !tI{!!KtI{!!rI{!!tI{!!sI{!!!qI{I{!!!qI{I{!!!IqI{I{!!!XqI{I{!#!~2k:#!9! {!{! {! {9%I{!~! {! {!e! {ͻ7! 9!#SI|v#B"*()[,*|ʗ#!$ G*##!% Gn6|ʲ#!0%SI|#!9!I{#!9!I{!~!:|#͐6!9!I{!2%SI|]$!9b'I{|O$!9!I{! {!g{|L$!9! {!{I{Z$!9!I{æ$!4%SI|x$!9!I{æ$! {!g{!g{`{|ʦ$!9!I{*#! {"#!~! {*1*#{!g!ͻ7! 9$ç#!7%SI|$ç#no'! {!g{|&!I' G! {7i! {! { {!{I{must assign to char pointer or arraycannot assign to pointer!'SI|u'!!9]f|Ž'!9!I{寴'!' G!9{I{!'6]negative size illegal]!""!""O;"-!"g:{| (*a!ͽF!~!:|)(!"* G^=*)|?(*/ ;!")!9!~7I{|ʡ(z!m{|q(!~ͫ6Þ(z!g{|ʑ(!~ͫ6Þ(!*{(!~!!!!e!ͻ7! 9!B*SI|(!D* Gk!   "g!"3!R*SI|)!~!:|M)!~L7|)!~ͫ6J)!~!!*3!g!ͻ7! 9*3"3X)!T* G)6;J*c!j*H|‚)!l*SI|‚)!n* Gn6|ʍ)Ð)(!"1*3"5*3|)!w*!͆I|)!͚*͊.)!|*!͆I|)!͚*͊.)!* G)Ü)+!m{|*n*| **-;G!͎illegal function or declaration(no open paren)illegal argument name),no commacharintwrong number of arguments!9*3|­*!9!+SI|*!9!I{*!9!I{!9!~!͆I|,0!"O5.!P.!͆I|-L1! "O5.!T.!͆I|2-*2! "O5.![.!͆I|P-Y3! "O5.!`.!͆I|n-3! "O5.!h.!͆I|ʌ-(4! "O5.͖4|ʗ-5.!m.!͆I|ʸ-R5͊.!"O5.!t.!͆I|-~5͊.!"O5.!z.!͆I|-ͯ5͊.!"O5.!.SI|.!"95.!.SI|).5!"O5.'0͊.!"O*Ocharint{ifwhiledoforswitchcasedefaultgotoreturnbreakcontinue;#asm!.SI|¢.!. Gè.!"9;no semicolon!9*1L{!9*gI{!"#*7#"7!9;!9;I{ ;+!F16!9{ ;!9{!c0o!9{ ;̀<͊.! 9while!9!9;!9;I{!9;I{! 26!"2SI|‹1'0͊. ;!$2SI|¸1!9{!c͊.0o!9{ ;!&2SI|1'0!(260o ;+!9{0o!9{ ;̀.!͆I|M,!ͅ#͊.5.*#,*7!s{|k,*#"*1*#{!o"1!"#!B.SI|ʜ,͸.5.!D.!͆I|ʺ,͞/!"O5.!G.!͆I|,}0!"O5.!M.!/SI|/*;|/!/ G//+.*7+"7!o"1"o*o*gͤ{|ʃ/*o69"q*oz|z/*o*qͤ{|w/!9 {#I{+*o#"o+z*{H/À/*q"o#/"g!"#}no final }!9;I{!c+!"0!͆I|/ ;!9;I{*O!m{*O! m{`{| 00o ;+ ;else!9!9!9͐D!9!9SʹD*!,m{|l0w0!=,0!9!9!9;!9{ ;!9{!c+!9{0o!9{ ;̀*?!m{|>!"?>!"=F>!9*a! -I{|:>!}!=Ò=͏=*;|Y>!?SI|ʑ>*%#"%*'|x>M>;J*c D|Ž>*%"'M>!?SI|>*%#"%*'|ʰ>M>;J*c D|>*%"'M>!?SI|?*%|=*!'m{*c!{z!\g{*c!{z!\m{`{R{|BA*|7A!B GBA=ʹ?@=!'ʹ?B*!/g{*!!*g{`{|A!=*!*g{*!!/g{`{|¼A*|ʫA!=ùAM>*;|ʹAüAxA!=B*ͮ;|ʸB!9!I{*ͮ;|B! {!͇{|B!u!9 {#I{+**{=A!u! {!*{!9!u DI{|zB!9!!9 {#I{+z*{|wB!zʹ?GBõB!9!I{!9!u!9 {#I{+z*{|ʵB!zʹ?ÅBB=ʹ?@*!Ṕ{|B! C G!t;!9!L{!9!'I{! {E!9! {{I{!- F! {!́{|E!9! {! { |0){!z!0m{! {!g{R{! {R{|ʑE!9!I{!z F!9! {! { |I{!9! {! |I{E3EGGEz! ́{| F!9 {#I{+z FE*i|FF*i*kg{|1F!]F G!*i#"i+!z*{VF!z*AuF!zstaging buffer overflow!z! {t!g{|ʘFF! {! {!g{|ʼFF! {! {͙F! ! {|HI! {z! ͇{|II!9 {#I{ÈH! {zͮ;|0I!! {zͮ;|NI!;J!9*c! {HI{|ʀI=!!;J!9*c! {! {|HI{|I=*ͮ;|Iq=öI!!!";J!"! {z! s{| J!9*#"+!9 {#I{+z*{I!9*!*{*c!9H"|ʎJ*c*z!=m{*c*z*c*!{zm{`{|ʎJ!! {z|ʲJ!9 {#I{*#"øJ!I*|J<|J=JþJ*a {|L! {ͬc! {I|OM*=*! {"!*){!*){! {! {!9ͼM! 9ZM!!9L!9!9!9͐D!9! {! {!MI{! {{|ʳM! {!ʹD!9!9͐D! { !I{! {!I{! {{|qN! {! {cM|#N! {ͬc! {{|EN! {*iI{! {{! {! {b{fOOm! {! {cM|ʗN! {ͬc! {{|_O! {{|N! {I{! {!Iqg{|?*'*%g{|>!"'?*'|?*%"' ?CM>!?SI|I?*%|C?*'*%g{|9?!"'*%+"%F?CM>*'|T?M>*M|ʆ?*M*Ag{|y?!;*AuF*a*MͽF*|‘?M>×?M>#ifdef#ifndef#else#endif*!P͇{|?![*#"!z*{;*K|?!"aM>*;|?3 @!["a͏=3!"*|B<|8@! ʹ?<|5@='@B*!"g{|@*ʹ?=*!"m{*c!{z!\g{*c!{z!\m{`{R{|ʶ@*|«@!B Gö@=ʹ?S@=!"ʹ?B*!'g{|PA!'ʹ?ʹ?!["a!=3no quoteno apostropheline too long!(C G!"9no matching #if...!u!:|VC͐6^=!9!I{!u!9 {#I{+zC|ʃCaC<|ʑC=ÃC=C|ʡCÑC*!́{|C!C G!macro string queue full!*!z*{*!͇{|D*#"!z!"**͇{|ʌD!*!|H|YD!*#"+z|UD=D*!*#"+z|qDYD!*#"+z|ʉDqDD!! {*iI{|¨D!"i*iI{*i!*{! {"i|D|DuF!F!!output error ! F! F!: F*9|)G!"9*a!ͽF!͠G:{|bG!!t:{|ʅG!͢! m{|ʅGmG*MGʟG*M͠G!9*aH{!9 {#I{+*cͱ{|G! ! {uFïG!H! {ͽF!H! {͙F! {! {ͽF/\**** !9!L{! {z|wH! {z! {! {zm{|hH!!9 {#I{%H!9!L{! {͇{|I! {z! {! {zm{|HI! {z! ͇{!g{|J?*;|JJþJJ!9!9!L{!9! {! {cMI{! {I|ʋK*=! {|bK!9!I{!9;I{! {! {! {! {OL!9FL! {|8L! {! {! {! {OL!9! {f!9;I{0o ;! {f ;! {! {! {! {!I{I{I{I{!!9! {!9K!9! {|fLͬcÄL{|ʄL{f! {! {!L!9!9! {! {cMI{! {I|L! {!9!"O*1"1!ʹD! {{! {! {b{f\O! {{! {! {b{f! {mmO! {mm! {!Iqg{! {!Xqg{R{|O! {! {b|ʱO:q! {! {b|Om:q! {!Xqg{|Om! {|uQ! {! {{! {{`{I{|wP! {! {{! {! {{xQI{!ʹD! { !I{P! {{!g{! {{!g{`{|P! {!P! { ! {I{P! {!P!    { ! {I{! {!Xqg{|>=<<==!V!or!!!V! {J! 9|I{!!d[SI|3Y! {X| Y! {ͬc͹q! {! {{i|I{!!f[SI|ʁY! {X|[Y! {ͬcq! {! {{{I{!!h[SI|Z! {X|ʩY! {ͬc!9! { {I{|Y! {zI{Y! {!L{! {!I{! {!I{!!j[SI|ʣZ! {X|>Z!l[ G!!9! { {I{! {zI{! {{|~Z!Dh! {zI{!!9! {͂[I{!|[SI|[|Z6!!r!z!g{|]!9{!{f]!9{fIq9]! {z!g{|6]:qIq! {! {!I{I{! {! {zI{!9!I{ ^!^SI|]! {|Ÿ]!a]! {z!m{|]! {ͬc!a]! {a!9! {!" {!I{I{I{ ^! {!9[! {|&^! {!9! {z!g{|R^! {Dh!!9! {!9!9[can't subscript]can't subscript](!`SI|ʼ^!9! {.TI{!`6!! {!9!~!:f|``!()!a G!f)6invalid expression!9!L{;J! {|8aOm*c! bH|™an6|UaÙa!9!9S! {|raͻnOm!9! {H{! bSI|–aÙa8a! b6! {!bH|a! {!{j! {|a! {nao*1! {!o"1),)CCARGC! {{!m{|2b!{|Eb!!! {{!m{! {{!m{`{|ʎb! {!I{b{|b! {! { {I{! {! {{I{! {! { {! {{! {!qg{|S! {! {{! {!Iqg{|2S! {! {! {!Xqg{|WS! {! {{! {!gqg{||S! {! {{! {!wqg{|ʡS! {! { |! {!qg{|S! {! { |!!9!9.T|S!9ͬc!9{|T! {!I{! {!9{I{(T! {!I{!9!9!9!V! {cMI{! {{|mT! {{f!VSI|ʈT!9!qI{äU!VSI|ʣT!9!qI{äU!VSI|ʾT!9!qI{äU!VSI|T!9!IqI{äU!V|!W!r!!!W! {J! 9&&!%W!!'W! {͚L!9|!EW!!GW! {͚L!9^!eW!!gW! {͚L!9&!W!!W! {͚L!9== !=!W!!W! {͚L!9<= >= < >!W! !W! {͚L!9>> <<!W! !W! {͚L!9+ -!X! !X! {͚L!9* / %!\[SI|[X! {X|EX6!!r! {b!!_[SI|ʗX! {X|X6!!3r! {b!!b[SI|X! {X|ʿX! {ͬcq! {! {{{ {b! {{!{3r!![SI|R[|#[6!!3r! {b! {{!{r!++--~!-*&illegal address++--!9!9! {͍^I{!9! { {I{;J*![g{*!(g{R{| ^! { !I{!e^SI||]! {|\!g^ G)6!w^6!!9! {z!g{|9\! {ͬcb\! {z!m{|b\!y^ G!9!I{!9!9͐D!9!I{!!!.T! 9!9ͼM! 9!^6!9{|]!ʹD!9{|]! {|`!9!~L7I{|ʹ_z| _`!l! {! {I{! {! {zI{z!g{|_! {!L{! {! {zI{z!g{|ʳ_! {! {zI{!!!9!~7I{|ʂ`z!m{|ʂ`! {! {I{! {!I{z!m{|K`z!g{|E`! {! {zI{!Dh! {! {! {zI{I{!!9!~!!!!e!ͻ7! 9I{! {! {I{! {!I{!! {{I{{|Qc {|?cOmͬc! {! {{!{!1c͢n͇cl !I{ͬc! {! {{!{!|c͇c{|ʢcͶlëc>l {!m{! {{!g{`{|c͋kcRk!9! {|d!Wf6!9!9͐D!9.T|-d!9ͬc!YfSI|LdʹDOdRdd! {|ed![f6!9{|ʨd!ʹD!9{|ʗd!9! {0o!9!9{|7f!9 {"*!arg{*!ttg{   R{|d!or! {!9́o4f*!rg{*!tg{R{|5e!r! {!9́o4f*!sg{|^e!s! {!9́o4f*!tg{|ʇe!t! {!9́o4f*!tg{|ʮe!9{!ʹD4f*!rg{|e!r! {!9́o4f*!Ktg{|f!Zt! {!9́o4f*!/sg{|)f!=s! {!9́o4f! {JoBf! {JoʹD!9(,)!9!9͐D!9! {S!ʹD! {|¡f!f G! {must be constant expression/mDG?!3! {*I{*!"m{|i*| ii͡i!7ih=!*#"+!*{!33*!́{|\i!i G!! {!*! {9*! {"literal queue overflow*!\m{*!!g{R{|i==*!ng{|i=! *!tg{|i=! *!bg{|j=!*!fg{|0j=! !9!I{!9!I{!9 {+I{#!s{*!0́{`{*!7z{`{|ʤj!9!{=!0{I{Fj!g{|ʻj=j;"/*/0o!jEl!lnMOV A,LSTAX DCCPINT!mE!mEMOV D,HMOV E,L!(mEXCHG;;!8mELXI H,!HmELXI D,!fmE*1!{"1PUSH H! { {|ʄm͢nÍm͎m!9!nL{z|m!9 {#I{+!9 {#I{+z*{Ûm!9*iI{!9 {+I{! {ͪ{|ʅn!nH|ʂn!9 {+I{!9!I{!9 {+I{z͌;|ʂnz! {{*{!0͇{|tnz ){!9!I{n!9!I{nm*1"1 XCHG;; DAD SP!nE*1"1POP D!nEXTHL!nnCCSWITCH!{|pmf!.qE!5qE! {| qm! {INX SPPOP BDCX SPPUSH BDAD SPSPHL!CqEDAD H!RqEDAD D!aqnCCSUB!pqnCCMULT!qnCCDIVwqm!qnCCOR!qnCCXOR!qnCCAND!qnCCLNEG!qnCCASR!qnCCASL!qnCCNEG!qnCCCOM!-rE!9 {+I{!͇{|)r,rrINX H![rE!9 {+I{!͇{|WrZr3rDCX H!jrnCCEQ!rE!rE!rE;GMOV A,HORA LJNZ !rnCCNE!rE!rE!rE;GMO9! {&H{u͔z!9! {H{w!xH|gu!zH|Ku!zz!9! {&H{du!zz!9! {H{w:{|w!+xH|ʡu!@xE!9! {H{w!LxH|u!`xE!9! {H{w!lxH|u!xE!9! {H{w!xH|.v!xE!9! {H{w!xH|]v!xE!9! {;H{w!xH|ʌv!1yE!9! {;H{w!=yH|ʻv!}yE!9! {@H{w!yH|v!yE!9!mDG!9! {H{!I{!9 {##I{ͅg|#g/mrgXh|7g/mrgh|ng!{!I{/m*-;!+ Frg! {DG!!9!9!I{I{!@hSI|ʪgg!BhSI|g!9!I{ggÚg*͌;|g!*͌;|h!9! {! {q=!0{H{g|(h!9! {{I{! {! {I{!+-/mEG!9!L{!hSI|vh!*!'m{|ʱh!9!`{!{͡i!`{H{vh*c#"c! {I{!';!mSI|hEND!k D|k! kEDGNOCCARGCMVI A,!~EGG!+kEENTRY!JkEEEXTRN EXTRN {!g{|sk!|kn{k!knCCGCHARCCGINT!9! { {I{z!m{z!g{`{|k!kEEG!lnk! lEEGLDA CCSXTLHLD !k9*1{f!7lEDAD SP!9! { {I{z!m{z!g{`{|ʋl!lE!lEÓl!lEEGMOV A,LSTA SHLD {!g{|l!lE!lEnEEGCALL !nERET/m!'oEGͻn!+oE*1"1$+5PCHL!EoE;GJMP !ooE!woE!}oE;GMOV A,HORA LJZ {!ʹD! {! {!o!g{|o!oEo!oEDB DW !oEDW $+2!9! {*1{I{|p! {寴tp!͇{|tp!`{|Hp!qE!9 {+I{#|lp!qE!9!{I{Hp! {寴p!s{|p!`{|ʮp! qE!9 {#I{+|p!'qE!9H{îp! {! V A,HORA LJZ !rnCCLT!sE!%sE!+sE;GXRA AORA HJP !8snCCLE!zsE!sE!sE!sE!sE!sE;GMOV A,HORA LJZ $+8XRA AORA HJP !snCCGT!sE!sE!sE;G!sE!tE;GXRA AORA HJM ORA LJZ !tnCCGE!;tE!AtE!GtE;GXRA AORA HJM !TtnCCULT!otE;GJMP !}tnCCULE!tnCCUGT!tnCCUGEz|w!wH|u!zH|tͲz! {@H{w!yH|w!ozE!9! {H{w!yH|Hw!}zE!9! {H{w!+zH|ww!?zE!9! {H{w!KzH|ʦw!czE!9! {H{w!9 {#I{+z*AuFw!9 {#I{+z*AuFát LXI H,0 DAD SP CALL CCGINTXCHG;; LXI H,2 DAD SP CALL CCGINTXCHG;; DAD SP CALL CCGINTCALL CCDSGI DAD D CALL CCGINTCALL CCDDGI DAD SP CALL CCGCHARCALL CCDSGC DAD D CALL CCGCHARCALL CCDDGC DAD SP MOV D,H MOV E,L CALL CCGINT INX H    CALL CCPINTCALL CCINCI DAD SP MOV D,H MOV E,L CALL CCGINT DCX H CALL CCPINTCALL CCDECI DAD SP MOV D,H MOV E,L CALL CCGCHAR INX H MOV A,L STAX DCALL CCINCC DAD SP MOV D,H MOV E,L CALL CCGCHAR DCX H MOV A,L STAX DCALL CCDECC DAD D POP D CALL CCPINTCALL CCDDPDPI DAD D POP D MOV A,L STAX DCALL CCDDPDPC POP D CALL CCPINTCALL CCPDPI POP D MOV A,L STAX DCALL CCPDPCCALL CCPIDDPDCALL CCPCDDPD XCHG;;!zE!zEPOP HPUSH H!zE!zEPOP DPUSH D!zE2}#~:}|G~#:}0| |OxG|x|2}}~:}#~,&}!>} >?+}:}G:}O>X}~.R}#X}1}x}1}̓}x}*j}>?l}#X}̓}#p}> x}~&!ڦ}=_.:;,<>ɾ}6}Ë}ԁ},}x}Õ+րͬc!a]!͹]a!9! ]!"]!w]]] ^!]!9[!^|&^!^!9!^ͦ]!,]|R^!*^Dh!!9!@^!9!9[can't subscript]can't subscript](!`SI|ʼ^!9!V^.T]!`6^#Vbk$w#***!*>*~P>*΂シg>r>**s#r*6*6*~ʥ>*΂ʻ>**s#r*6*6*~>*ހ|'~2#*s#r*5**s#r*6*6#6:>2*~@>*ހ:w#*s#r*5p**s#r*6>:*6MbSb!Zb2>,*~ʰ,à*6*Ƃ>:w  PROGRAM LANGUAGE LIBRARIES FILES INDEX 84719007.VAL * * All the programs and documentation contained on this disk * * are 1;sPUBLIC DOMAIN0;s and are 1;sNOT FOR RESALE0;s. Implementation * * and use of any program is at the users risk. EPSON QX-10 * * USER GROUPS, and other RBBS/RTPM users are suggested as a * * possible source of assista!z!zEPOP BPUSH Bz##9~og {##9~#fo##9T]z+}##9T]z#}}##9T] {+L{##9T] {#L{}|}o|g}o|g}o|g͍{+͍{+͍{+͍{+͍{+͍{+|gzš{{!͸{+͸{+͸{+͸{+z¿{{!||g}o{){{ozg{#|/g}/oDM!y{xGyOȯ{_zW{DMzzL|xT|>)\|8|d|8|}o{_zW=A|!|L|L|z/W{/_x/Gy/O{_zW{z|q|.!N#F#xʎ|~#~#w|w|`i>2}2}$կœ|~#:ʸ|,}!}ä|~&A|A|<2}#~:}?|!!ͥ^!9!~!:|`!9!~L7ͭ^|ʹ_-^| _`!}}}~%~~%')*c6cËcԁc,cxcÕ€ր_!5_!Y!X_!i_;_>_E_!M_|ʳ_!t_!͗_z_}_!!!9!~7ͫ_|ʂ`̈́_!ͮ]|ʂ`!͢_!__!_!__!_|K``!͌_|E`!_!/`ͨ_`!Dh!:`!X`!c`@`C`w`!!9!~!!!!e!ͻrstG!+kEENTRY!JkEEEXTRN EXTRN ͟e!ͮj|sk!|kn{k!knCCGCHARCCGINT!9!͂iLj͟j`!ͬit`!akxj|k!kEEG!lnk! l2 !~#o|g6:ヷ!~&w#!:a{_H:W[HPW[r# x[2 !~#o|g6:LE!tnCCUGT!tnCCUGEz|w!wH|u!zH|tͲz!   *K͞+4}԰'+FÎr7 :2!q: ʊ *M8 ^#V#*~#fo^#*~#fo^#V#*n^#*n^#V# ~#fo^#& ~#fo!+!#!+!#!+!+}|z{|}|z7||7zZZ)|/g}/o#|͉k|/g}/o#ɯ2qZZk:q|/g}/o#|/g}/o#:q<2qqDM!xxGyO҃)v|͔`i|)Öxڷz/W{/_ѯzW{_=yOxGæ2qZZ͉M|}ȯ|g}o)|/g}/o!a{   `OE!y6$ -7rBo&))T])))!y" $)$͋#:+;Gg)xs)m):+;G)xs))" $͖)$͋#* <~G~#)> w" <* <~?*w#> *)G:+;x* <~+P0*~(*~?@)~)~w" <* <~@?%F>@P*>wx>[*>3>3>c*>c*>c*>c*:+;?%:6;?%BD Software C Compiler v1.41 (part II) Can't open file Write error Missing label Missing semicolon Illegal !"!9& à$î$7z$ÆtÀ+ !"!6 H Output filename?  !  |_ !ά! "#|“ !"! Î Open failure#  ê à$î$7z$t!"*|9 ͛ *| 9 ! Input filename? ͞ !͡ ͤ | !"9 !"!¤!ͧ "#|6 !"!$ 1 Open failure͞ ñ ͛ b ^,ò,*-ûUH-*|V !!u z charA |ʓ !D G P !! á intA |ʺ !D G P ! #asmJ | M P ! #includeJ | P P !  #defin n} ͐ ͐`is#r !9> À+e.hc9..*|j !M e missing closing bracket/ *|” !x Ï missing closing #endif/ 2 5 *8 ! errors in compilation.; 2 Puuvw*| !ά! !ά * !"" %,$\%Æ% &7&Ü&!9DM! w#w|=!CE* |ʁ`i6#6! ^#Vr+s *~! ^#Vr+saÈ`i6#6! |™! |ʰ! ͐͐!͐! !, |*! 9x$\%À+#z/W{/_!9~#fo! ! ! ! ! ! !9~#A"s!`*"!"!Y">2>2>22!"!"!@"!" ʞ!F#x±~#±!b2r~# "2r+}|~#G:rx"2r+w# +6#!6#2w2x*s!>r<o&F=-` r'~h6!+`W?_!~7z?` :>ª@w#.¶66*>?w#> w#.7:77 statement Can't create CRL file Illegal operator Lvalue required Lvalue needed with ++ or -- operator Illegal left operand in assignment expressionÔ$e Ø Ä_> X  , ûb "z"p!,?!"rt"n&d ͐| ͐* g !,j ì Ó !"!9$ b.(.c9.e.!9DM!2 ; @globals "**p !~#fo n}ʾ *   !~#fo n&|g}o!~#fon&|g}o`is#r͐ ! *"G !9 6c!9DM`is#r͐*p# `i~#foà$t!9DM|!! 6 <<! 6>"Q! 6"! w#w͐ Ҟ|ʞ! n&ʞ! ^#Vr+s`isY͐ `i6! n! n} |!invaild file name for includeò͐ |4! )missing file name for includeò!"*|l!Hanested include not aloudò!Ȩ`i"#|¯!äOpen failure on include file!"!"9-KÆ%À+à$'7&!9DM;! |!"L`i|%   !invaild identifierL`i|=`i|F!"L!"! 9m-KÆ%À+à$'7&!9DMX! [|!"`i^|¼!ôinvaild identifierad`ig|`ij|!"!"! 9,À+ycLx!9DM! [|ʅ! ^#Vr+s`is#rzu! n}P͐͐`is#rr! 6! n}r͐͐`is#rÂ! 6`i6#6ö! n}š`i6#6ö! n}¯`i6#6ö`i6#6! n}:ʭ*p!,?!! global symnol tabl!"!#endasm|$=*|/=!!"ÇÆ%À+à$,7&Ü&dLx(-*/ %^,àòîyceX Ô$!9DM`iK|!illegal function or declarationNQú!(T|!illegal function or declarationNQú`iW! s#rzu! ~#fo n}@`iZr! ~#fo n}]`iZr! ~#fo 6`i];*p!,?!ڹ!ñgobal symbol table overflowN4*p! s#r*p"p`i͐ `! ~#fo 6! ~#fo ! ~#fo L! must be constant,F;F|F !×͐|![qnegative size illegal͐`is#r!Ë]͐×!9,$\%Æ% &'Ü& %À+!9DM! w#w*|å!*ͣ|"! 6#6! ^#Vr+sͦ*! ^#Vr+sͩ+! 6#6`iͬ|:ͯ`iͲ|M`i͵͐ ͐ !͐`i͸ͻ|vå!|~,ͣ|¢!Ýexpected comma;!9$^,ùoò,fÕÒ"ú" #7ͱ|*|ú!!chÔ$ûLîyc^,o)/e!9DM*r`is#r*! s#r! s#r͐ ͐ "͐"r!!hmelse|„͐ü! s#r͐ ͐ "͐"r͐!9Ô$Ô)o)ûLî/eyc*!9DM*r`is#r*! s#r! s#r! s#r! s#r`i͐͐͐͐͐"r͐"! 9ÍÔ$Ô)^#*7í#o)ae/e#îyc!9DM*r`is#r*! s#ri! s#ri! s#ri! s#ri! s#r`ilo|rÌux|rÌ͐!Too many case statments͹!%!'!:Ϳ|J!!7!E!Missing colon͹Æ"!!W!_!defaultͳ|ʭ!͘! s#r̓ͼ!!Ç!:Ϳ|ª!!!å!Missing colon͹Æ"!!õ!}Ϳ|ʃ"̓ Ͱ! w#w̓ͼ̓͘! s#r̓̓ͼ̓̓["̓)`i~#fo!1"3",! ^#Vr+s)! ~#fo"̓͡ ͼ̓"r̓"É"Æ"q !9á" %7yce͕"|­"͘"!͛"͞"":*yc/e!9DMͽ"`is#rz"#`i~#fo##~#fo"`i~#fo~#foe overflow!é*p! s#r*p"p͐! s#r*͐"*! s#r*r!aڕ!nÊlocal symbol table overflow!é*r! s#r*r"r*! s#r*++"*r!a!local symbol table overflow!é*r! s#r*r"r͐ ͐! ~#fo ! ns! ~#fo ! ns! ~#fo ! ns! ~#fo ͐s! ~#fo͐s! ~#fo ͐s!é!9û,À+!;͵|!missing semicolon͸È',.e.à$ss! ~#fo! ~#fo ! ~#fo sss`i]!"!GI)T|`iK|j*##"Î!pÆillegal argument nameNcf!Ù)*!i|!ö,T|!expected commaNl|A!,?!"r!"*|~!!charo|4!ru{!!>Binto|[!ru{!aswrong number argsN~xʕ!{~!"!,?!"ŕ̈́"! 9,KÀ+$\%4)!9DM!]|!×`i|arʹ|!ͷͺú!!&*intʹ|C!ͷͺú!IK{ͽ|[ú!!ehifʹ|!"ú!!Ïwhileʹ|ʦ!"ú!!ôforʹ|!"ú!!switchʹ|!"ú!!returnʹ|ͺ!"ú!!(.breakʹ|Hͺ!"ú!!R[continueʹ|uͺ!"ú!{};ͽ|ʊú!Õ#asmͽ|ʮͺ!"úͺ! "*,î*#"!}|*|*+"{u! s#r͐ ͐~͐ ́x|5rÌ͐{u͐́̈́|XrÌ͐ {͇͐́͐{͐"r͐͊"r!9Ô$Ô)^#*7e#H$/e^, MÀ+o),erf9..$e.ycî!9DM! w#w*r! s#r*! s#r͘! s#r!  s#r!  s#r! s#r! ͛͞|7 ͡É"ͤͧͪ|K ͡É"ͭ|Y ͡É"͘! s#rͰ*##"!!{ À caseͳ|M!! Ͷ|´ ! ì Bad constant͹q ̓ ̓)`i̓s#r! ^#Vr+s)! ͘s#rͼ!!!"!9#:*yc/e!9DM#`is#rz1#U#`i~#fo##~#fo#`i~#fo~#fo#!9j#,À+(!q#s#(a#|ʂ#!!#Þ#Missing left parnthisd#g#!ù#,À+(!##;Ͱ#|#!!##Missing semicolonͳ#Ͷ#!$,À+(! $ $)#|$!!"$9$Missing right parnthis#$!T$,À+(![$]${K$|l$!!r$Å$Missing left braceN$Q$!*#"!">2ô$dz!9DM! ͱ$͐n}$! ^#Vr+sn&ͱ$$*n&%.9.   !9DM!%%@$͐$,%-*/$#%!6%8%;*!&%|ͣX%)%|͝b%$_%|s%!Ä%*#"+n&Ø%-}*$*\%!9DM͉%͏%͌%|¶%!&`iw#w͏%͒%|%! ~#fo`i^#Vr+s͕%sü%! ~#fo͐6!&!9&À+(!&-&illegal symbol name &&=&Ö/!9DM`is#r͐*pʍ&!͐͐:&||&͐Ó&͐`is#rM&!Ó&!9è&Lx_xt0!9DM!&&already defined symbol or function "`i͟&͐T`i͢&!&&"`i͢&(|)((/)((|/)(|))/)()(=),À+!9DM͐7)|m)!Y)h)missing braket:){)$(.e.!9DM͐r)u)x)Ú)À+!9DM*32!"2G52'4!'222'42|3!33missing apostrophe!242\32222ò32!'2G52/r4$2*r4'2'22*J4$2/i42|X42[4'2*|f4i424'2'2G52*2|?5`iw#w2*2|ʽ4͐ҷ4`i^#Vr+s! 2s2Å4͐! 6! -2`is#rz 5`i^#Vr+sn! s{5! n&! ns*O7*#"! n&.7Ö/!9DM`iw#w͐*Ҽ7!͐!͐+7|ʉ7`i^#Vr+sn}ʂ7j7͐7`i^#Vr+sn}ʡ7É7`i^#Vr+sn}ʹ7á7<7!7!97dM 8!9DM! w#w! `i7`i7͐8!9=86:$æp\%äPdQ*Rkl6lPlil{lÔlílnR!9DM͐ ͐ 8`is#r8=y88=y8͐-:͐ w#w8>=8>8>+œ8>9>-¨8>9>*´8>E9>/8>g9>%8>ʉ9>&8>ʫ9>^8>9>|8>9:8͐͐   8:88͐͐8͐88-89"8;9%8`i6#6:88͐͐8(8`i6#6:88͐͐8+8`i6#6:88͐͐8.8`i6#6:88͐͐818`i6#6:88͐͐848`i6#6:88͐͐878`i6#6:͐-:͐͐:8!-:!9T:;-$æpdMÔ$,Êfo)!9DM͐͐9:`is#r<:?:|Œ:B:|ʓ:͐ ;͐͐E:H:! s#r!:ö:||K:|:͐~#fo͐N:͐6#6͐! 9:! E:;͐Q<==͐g=͐͐ -$æpdM,e{l!9DM͐͐ s=`is#rv=y=&=|=&=|===͐,>͐͐ =!==&͂=|#>ͅ=͐! s=! =͈=͐6#6)>!,>=!9P>R?-*/dM,ell!9DM͐͐ 8>`is#r;>!v>y>==*!>>|³>!>×>!=*!>>|³>͐I?͐͐ A>!>>==D>|?G>͐! 8>! A>J>͐6#6F@j?C! AA>=a?|ʖAd?͐! U?! ^?͐6#6! ~#fo~#fo"|lA!~#fo n}lAm?x@͐"|ʐA!~#fo n}Am?x@p?C!AÞA<*![?|PB!AüA<<*![?|PBs?d?͐! U?! ^?͐6#6! ~#fo~#fo"|&B!~#fo n}&Bv?x@͐"|JB!~#fo n}JBv?x@y?C!VBXB>*![?| C!sBvB>>*![?| Cs?d?͐! U?! ^?͐6#6! ~#fo~#fo"|B!~#fo n}B|?x@͐"|C!~#fo n}C|͐ WDZD͐w#w`EQDTD͐! BD`is#r͐! ND͐ WD]D͐w#w`E!cEúD!9ÍEF-$æpdM,e6lPlil!9DM! w#w͐! ͐oE`is#rrEuE*EuE/EuE%ExE=E͐F͐͐{E!F F*~E|NF́E͐! ! oE`is#r͐! {Ë́E͐w#wF!TFVF/~E|ʛF́E͐! ! oE`is#r͐! {E͇E͐w#wF!FãF%~E|F́E͐! ! oE`is#r͐! {E͊E͐w#wF!FF! 99G,~#fos#r͐w#w͐w#w!KK!-I/I&F|I͐͐͐G`is#r͐w#w͐|vI! ~#fo~#fo|ʚI!|IÌIillegal addressG!KI! ~#fo##~#fo|ʶI!KI!G! ~#fo~#fo! s#r$G'G!KK!II!F|%J͐͐͐G͐G*G͐6#6!KK͐͐-G`is#r!?! ͐0G! ~#fo͐~#fos#r!sJvJ++F|ʼJ͐|’JG!K͐͐G͐3G͐6#6!KK!JJ--F| K͐|JG!K͐͐G͐6G͐6#:! ;í:! 92;;-$æpdMÔ$,aeo)!9DM͐͐;! s#r;;&l; ;&s;͐;͐͐#;&;`is#r!;Ô;&&);|;͐~#fo͐,;͐6#6͐! ;! #;;͐/;!;Ë;! 9 <÷<-$æpdM,eíl!9DM͐͐ ;`is#r;;|Q<;|Q<;=X<͐î<͐͐ |@?G>͐! 8>! A>M>͐6#6F?!I?>!9Â?C-*/dM,elm&m?m+WmpmÈmám!9DM͐͐ U?`is#rX?!?ê?<*![?|@!??>*![?|@!??<=*![?|@!@@>=*![?|@͐C!%@(@>>*![?|D@͐C!J@M@<<*![?|i@͐C͐͐ ^?!~@Á@<=a?|Ad?͐! U?! ^?͐6#6! ~#fo~#fo"|@!~#fo n}@g?x@͐"|A!~#fo n}Aj?x?x@?C!Cx@!97C?D-*/dM,eùmm!9DM͐͐ C`is#r"C!]C`C>>*!%C|šC!{C~C<<*!%C|šC͐6D͐͐ (C!CòC>>+C|C.C! C`is#r͐! (C1C͐w#w3D!CC<<+C|-D.C! C`is#r͐! (C4C͐w#w3D!6DéC!9`DlE-$æpdMe\%*Rlk!9DM͐͐ BD`is#rEDHD+ʘDHD-¤DKD=«D͐cE͐͐ NDHD>+D>D>-D>EZEQDTD͐! BD`is#r͐! NDFpfUmnÏyæpKdMInÀ+f.e.bnxVÁz|nìn!9DM!GGJG++F|ʾG͐͐͐G`is#r|~GG!K! ~#fo##~#fo͐~#fos#r͐͐G͐ G!KK!GG--F|DH͐͐͐G`is#r|GG!K! ~#fo##~#fo͐~#fos#r͐͐G͐ G͐6#6!KK!JHLH-F|ʨHGG|iHGßH͐͐͐G`is#r͐͐GG͐6#6!KK!HðH*F|'I͐^#Vr+s͐͐͐G`is#r͐͐G! ~#fo##~#fo6!KK͐K! 99KàXfKYÂZ$~.9.e.!9DM͐K|UK!KæK͐$K|iK!KæK͐'K|}K!KæK͐*K|ʡK!K*-K!+0KæK!! ~#fo~#fo3K6K!K,Q+$+!9DM! s#r`is#r͐|:L`iw#w!KK+K|L`i6#6!LL-K|7L͐! s#r`i6#6KKK|ML!òLKK|ʄLK! s͐ ?! n&`is#rML͐|L͐`is#r! ~#fo͐s#r!òL!9L4)7ae!9DM!LL(;LL`is#r!LL);L͐͐L   !9M-àXKY!9DM M͐M|7M!͐M|JM!͐M|]M!!sMgHgfUEh!9DM! ~#fo~#fo`is#r͐|™MÛP`i~#fo n}ʷMʷMOÛP`i~#fo n}MDNNO! ~#fo##~#fo`i~#fo n&2N͐+|N`i~#fo n&gM/N`i~#fo n&͐jMAN͐͐mMO! ~#fo##~#fo`i~#fo n&¡N͐+|†N`i~#fo n&gMÞN`i~#fo n&͐jMN͐+|¶N!gMN!͐jMO͐+|N`i~#fo n&gMN`i~#fo n&͐jMQͧP[Q͐>Q>2Q>#Q>8Q>/Q>>QAQͧPAQͪPAQAQ! ! ͰP! ͭP! 9vQpfUedM 8!9DM! ~#fo~#fo`is#r`i~#fo n}Q`i~#fo n! ~#fo##~#foQ͐|Q! ~#fo~#fo|QgQ!R͐͐jQmQ!͐pQmQ! ! sQ! pQ! 93R`[h!9DM͐-R`is#r͐+|WReR͐++|eR0R!9zRi1i2j!9DM! ~#fo~#fo`is#r͐| R]U`i~#fo n}ʾRʾRS]U`i~#fo n}R9SʼSS! ~#fo##~#fo`i~#fo n&6SqRU!!͐wR]U͐+|=U`i~#fo n&qRZU!`i~#fo n&͐wR]U!9xUf.9.e.s!9DM! ~#fo~#fo`is#r|ʣU͐++|ʦUoV`i~#fo n}U V VoViU͐lU! ~#fo~#fo|V!UU+lU! ~#fo~#fooUrUoViU`i~#fo n`i~#fon&?! ~#fo~#fo*oUrU!]VdVdad spuUrUoV!9ñV?\-$\% M`[4)7*RújfUjf9.e.dMqq!9DM͐͐{V`is#r! ~#fo~#fo! s#r~V́V>[V>W>(W>nX s! !Y Y0123456789ABCDEFͯX`is#r|gY!8YMYinvaild hex constantͲX͵X! ~#fow#w!Y! ~#fo͐+s#rͣXͬX! s! !YäY0123456789ABCDEFͯX`is#r|¼Y!Y! ~#fo! ~#fo~#fo?͐+s#rͩXzY!9Z,$Ï^\%!9DM`iw#w!ZZ'Y|(Z!yZY'^ZY|^Z͐|g}o?Y`is#r(ZY! ~#fo͐s#r!yZ!9ÔZ,$À+Ï^\%!9DM!ZäZ"ͅZ|´Z!W[! ~#fo*s#r͈Z"@[͈Z|Z@[**[!Z[string space exhaus#rz]!Æ^! ~#fo! Q\`is#rs#rzI]`i~#fo n}I]!Æ^T\(9^! Q\`is#r|^*p!,?!ڰ]!]è]global symbol table ofverflowW\^*p`is#r*p"p! ͐Z\`i~#fo 6`i~#fo 6`i~#fo `i~#fo`i~#fo `i~#fo ssss! ~#fo͐s#r!Æ^H^! ]\!Æ^! `\|_^!Æ^Æ^!e^x^invalid expressionW\c\!Æ^!9Þ^$\%NtÏy!9DM͒^\ʸ^͕^{_͕^͕^`is͘^>R^>_>N^>_>B^>_>T^>_>F_>OÛP`i~#fo n}"OO\PÛP! ~#fo##~#fo`i~#fo n&‘O͐+|dO`i~#fo n&gMÎO! ~#fo~#fo`i~#fo n&͐pMÿO͐+|°O`i~#fo n&gMÿO͐͐mMÛP! ~#fo##~#fo`i~#fo n&1P͐+|P`i~#fo n&gM.P! ~#fo~#fo`i~#fo n&͐pMYP͐+|FP!gMYP!!͐pMÛP͐+|{P`i~#fo n&gMØP!`i~#fo n&͐pMÛP!9óPpedM 8!9DM! ~#fo~#fo`is#r`i~#fo n}Q`i~#fo n! ~#fo##~#fo+|S`i~#fo n&qR6S`i~#fo n&͐tRS! ~#fo##~#fo`i~#fo n&–S͐+|{S`i~#fo n&qRÓS`i~#fo n&͐tRùS͐+|«S!qRùS!͐tRS͐+|S`i~#fo n&qRS`i~#fo n&͐tRS]U`i~#fo n}TʆTU]U! ~#fo##~#fo`i~#fo n&ƒT͐+|YT`i~#fo n&qRÃT! ~#fo~#fo`i~#fo n&͐wR]U! ~#fo##~#fo`i~#fo n&T͐+|T`i~#fo n&qRT! ~#fo##~#fo`i~#fo n&͐wRU͐+|U!ÐẌ́V! ~#fo n}!WW_X͐w#w! ~#fo##^#Vr+s! ͇V|ʎẂV]ŽW! ~#fo͐͊V͐?s#r!~WÀW]͍V!×XW͐V͓͐V͖V!͙͐V͜V!WöW]͍V!×X͐w#w! ͇V|X́V]X͟V͐͊V͐?͢VͥV͖V!͐ͨV͜V7X͐V͓͐V͖V!͐ͨV͜V!=X?X]͍V! ~#fo##~#fo#s#r!×X͐ͫV!×X͐w#ẅ́V! ~#fo~#foͮV!×X͐×X! 9øX$æp\%NtþyÀ+(!9DMͣX0XͦXXXͦXxX!YͩXͩX! 6ͩXͬX!sted͋Z͈Z"$[͈Z|$[͎Z [!W[*#"+>͎ZsZ͑Z*#"+>6!W[!9!9DM! ~#fo~#fo`is#r|†[!6\`i~#fo n}ʤ[[0\6\`i~#fo n}ʽ[[[!6\!6\! ~#fo##~#fo`i~#fo nѯg \`i~#fo n& \!6\0\`i~#fo n}$\*\0\!6\!6\!6\!9f\, 84)Æ%'7&$À+LxàrK(!9DM! ~#fo! ~#fo##! ~#fos#rs#rs#r!\ä\(B\|\͐͐E\! s#r!\\)H\͐ Æ^͐w#w! K\|H^! ~#fo! N\ _&_! {_! {_!{_! {_! {_`in&͛^|=_`in&{_`in&`is͒^͛^|s_`in&?͕^`isJ_`in&{_!9Ð_.e.&s!_å_@start: csect͇_͊_!_ý_jmp @init͍_!__extrn @and,@asl,@asr,@comp,@com,@div͍_!_`extrn @gchar,@gint,@incdec͍_!`D`extrn @mult,@neg,@nlog,@or,@pint,@sub͍_!O`t`extrn @sxt,@ucomp,@xor,@init,@switch͍_!`ç`extrn @gintss,@gintsl,@gcharss,@gcharsl͍_!``extrn @pintss,@pintsl,@pcharss,@pcharsl͍_!``@eq equ @comp͇_͊_!a   a@ge equ @comp+35h͇_͊_!!a3a@gt equ @comp+1ah͇_͊_!AaSa@le equ @comp+43h͇_͊_!aasa@lt equ @comp+28h͇_͊_!aÓa@ne equ @comp+0dh͇_͊_!aõa@uge equ @ucomp+6ch͇_͊_!aa@ugt equ @ucomp+51h͇_͊_!aa@ule equ @ucomp+79h͇_͊_!bb@ult equ @ucomp+5fh͇_͊_!)b=b@preinc equ @incdec͇_͊_!Kbdb@postinc equ @incdec+10h͇_͊_!rbÊb@predec equ @incdec+08h͇_͊_!bñb@postdec equ @incdec+1ah͇_͊_b&s!bbend;bbs!bbdb bb.(.&s!9DMd! eeCSECTde&s!$e(erete;es$e.!9DM!IeNejmp 2e͐5e8epe&ss$e.!9DM͐|¥e!eÏemov a,hde!eàeora lde!eïejz ge͐jemee&s!eepush he*++"es$e.9.!9DM!f flxi d,e͐ee! f'flxi h,e͐ee!>fEfmvi b,e͐ee!\fhfjmp @switcheexfs!fÃfdw ufÙf&ss$e.!9DM͐|f!føfmov a,h͍f!ffora l͍f!ffjnz ͐f͓͐f͖ffs!fglxi h,idad hhiÄkæk!9DMi! n&i=i kjEk!9DM! ~#fo~#fo! s#r! ~#fo n! ~#fon&?! ~#fo~#fo*`is#r! n}i͐4i|i!ii@pintss7ii!ii@pintsl7i j͐4i| j!ij@pcharss7i j!jj@pcharsl7i͐:i!9Dj&ss.9.e.!9DM͐+||j!\jdjmov a,l5j!ojtjsta 8jÍj!jÈjshld 8j͐;j͐|ʵj!jçj+;j͐>jAjj&s!jjxchgͽjj&s!jjdad djjs.e.!9Dm@ulelms!mm@lem,ms!3m8m@uge)mEms!LmPm@geBm]ms!dmim@ultZmvms!}mÁm@ltsmÎms!mÚm@ugt͋mçms!mòm@gtͤmÿms!mm@asrͼmms!mm@aslmmjn!9DM!n n@preincm͐m#njn!9DM!1n9n@predecn͐ nOnj!Vn[n@negLnhnj!onun@nlogenÅnjn!9DM!nÜn@postincn͐͂nõnjn!9DM!nn@postdecͯn͐Ͳnn`[bEse.!9DM! ~#fo~#fo!qqmust be lvaluep2qLx_xt0 %$\%!9DM!@qMqidentifier "`i q͐T`i#q!iqÅq" is not a vaild array base`i#q`i&q)q|ʠqøq,q]²q/qøq/qÕq!P9q-e*/ %7s,4)j tyc!9DM`iw#wq͐|rq!r r)*!q|`rq|*r`rq͐|9rqq͐##`is#r!NrPr,q|]r`rr!frhr)q͐|ʂr͐qÅrq*͐q"!9ìrLx_xt0!9DM!rrundefine identifier "`iͣr͐T`iͦr!rr"`iͦr`iͩr!bb!ccdsectb$cs!+c/cds !c?c.e.!9DM!McUc extrn 9c͐9cGoy2}$:O*o`7:)~:,"s!"u*|*u{*~#{"*s*u{#"u*+"ú{{}7:,*{:* |}|2q Q|G|:qwB|! {w:wor|2w&!o •| . &7:)~:,"s!"u*||**s|! ~|6*u*+"*3-23-83 Note on SMALL C ver 2 (SMALLC2.OBJ) Small-C V2, STDIO.H, LIB.C are in SMALL-C.LBR This is supposed to be based on the Small C presented in recent Doctor Dobbs Journal articles. It has been altered to work with CP/M 2.2. If you happen to have the articles, and/or know how to use this compiler, and have some sample sources, please make up a short file with some helpful info and leave on this system. I do have some files that are supposed to be the assembly sources for the compiler, wh͐w!w͐+?`is#r! ~#fo##~#fo|ʺw!! ~#fo! ~#fo͐{v! ~#fo##~#fo͐s#r! ~#fo~#fo͐s#r!!! ~#fo~#fo~vw! ~#fo##6#6! ~#fo! ~#fos#r!w!9w~z!9DM! ~#fo~#fow!9DM! n} ͝Hx! n} ͝Hx! n} ͝7**~#Vx7**rxix~#rxÇxc|}{Ø|!9DM͐|žx~xty͐+++|µx!́xty! ~#fo##^#Vr+szx! ~#fo^#Vr+sn&ty!! ~#fo! ~#fo7,2q*&:q):?{=?{=r:qo&  a{  e{_ q{7:O*o`7:)~:,"s!"u*|*u{*~#{"*s*u{#"u*+"ú{{}7:,*{:* |}|2q Q|G|:qwB|! {w:wor|2w&!o •| . &7:)~:,"s!"u*||**s|! ~|6*u*+"*ich require M80, L80,Syslib, the compiler itself to re-compile. It is only useful for minor mods, not major ones, as I have been told it is not the true SOURCE for the compiler. This is a VERY large file, and I will only make it available on an 'AS NEEDED' basis. Leave a message in CBBS to request it, note it will take nearly 2 hours at 300 baud, so it is a one time shot. Check CBBS next day for reply message. . Dick - Pasadena RCPM Sysop    *K͞+11'+FÎr7 :2!q: ʊ *M8 ^#V#*~#fo^#*~#fo^#V#*n^#*n^#V# ~#fo^#& ~#fo!+!#!+!#!+!+}|z{|}|z7||7zZZ)|/g}/o#|͉k|/g}/o#ɯ2qZZk:q|/g}/o#|/g}/o#:q<2qqDM!xxGyO҃)v|͔`i|)Öxڷz/W{/_ѯzW{_=yOxGæ2qZZ͉M|}ȯ|g}o)|/g}/o!a{   `OE!y6$ -7rBo&))T])))!y3͵(>3>@26;q *-;";.,4:+;2+;";|²!}£!9/,4ʹ!¦!90,4>G>)3þ!#'̓&)*͵(1!&,2#%!`/,4^(ͤ&&)*͵(y(~7#^#V#+"1))){S~+2G~`20;25;#~2/;~?>k"=2);#^#V#^#V#"1;^#V"3;:5;ʕ"*;!:0;@ʦ""3;*G;#w"G;*G;~""++21:+"G;*G;+"G;! >"  Missing file name to linkͤ!9 6#6̓9̓A !C ~#fo̓9)~#foͧ(ҡ !h  File name to long at ͡!C ~#fo̓9)~#fo͡ ! é .!C ~#fo̓9)~#foͪ| !C ~#fo̓9)~#fo! .!C ~#fo̓9)~#foͪ+6!C ~#fo̓9)~#fo! ͭ!/ 4 .TXT! Ͱ`i! ͳ#|Š !X g Can not open ͡! ͡!9 s#rzʇ Ͷ !$M j$k**^͐ͼ͹`iͿ̓9+| ͐!8 s̓9 ͐!9 ^#Vr+s- !C ~#fo##~  ͐ . ë# )S%*!9DM!͐  |l !O g Not able to rewind file * j^#Vr+s)*iMjs#r͐ " $ ! Not a valid formated text file ͐ " E 9͐ " ! s! Not a valid formated esd card ! ~5o}6͐ % Ò ͐ ( ++͐  ͐ " `is{!evMissing end card `in}$ʻ!öNot a valid formated text file. Missing '$' ͐ " `is!End of card found when looking for card typeiI͐k*n}=͐k*`i^#Vr+s*"j^#Vr+s*"j^#Vr+szv͐W!9à r%)*ë#%ô'ñ!9DMM"j|µJM$j)*e~#fo! s#r! ~#fo~#foMe"Mj++|"!Load address error for csect͂! ~#fo~#fo|P! ~#fo~#fo! ~#fo#n&$k**^͐ͅ! 6! n}P͈͐$¤͈͐R!Error seeking to RLD card͈͂͐͋͐`is#r`i^#Vr+sz ! ~#fo#n&͐#z/W{/_!9~#fo! ! ! ! ! ! !9~#A"s!`*"!"!Y">2>2>22!"!"!@"!" ʞ!F#x±~#±!b2r~# "2r+}|~#G:rx"2r+w# +6#!6#2w2x*s!>r<o&F=-` r'~h6!+`W?_!~7z?` :>ª@w#.¶66*>?w#> w#.7:77G;6!+>"I;*G;~*/;*I;s#r#*1;s#r#*3;s#r#*+;s#r#*-;s#r#:5;w#"I;w#*:;*I;s#r#*<;s#r#*>;s#r#*6;s#r#*8;s#r#:@;w#"I;w#|?‚#}' 8'J''Ò'î'../ +/(:/x( !9DM*2js#r*0js#r*.js#r*,js#r**js#r*(js#r*&js#r*$js#r*"js#r* js#r*js#r*js#r*es#r*es#r*es#r!Panacea linker version 1.0 copyright (c) March 30, 1981͡! By Mike Bernson̓͡A+|$ !#fo! ͭ!  .COM! Ͱ*`! #|d !B S Can not create ͡! ͡Ͷ!8 n`is#6!!!͐ͼM j)*iMjs#r! ú Pass 1 starting͡*j^#Vr+s`iMe*es#r!9 w#w̓9M.jm ̓9)*h~#foMes#r̓9)*h~#fo ~#fo!; s#r*e~#fo̓;s#r!9 ^#Vr+s *$jw#wM&j#*"js#r*j^#Vr+s! ï Pass 2 starting͡*"j^#Vr+sz `iô *`Ͷ!=9 '.!9DM! `in}Q`in}RB`in}TB!'=Not a valid type card ͐ + ! s#r͐ " ! sÏ!kÊEnd of file in TXT or RLD card ! ~#foM j+)*i~#fos#r`in}T͐k*##~#fo|͐k*##͐ ( s#r`in}R[͐k*~#fo|[͐k*͐ ( s#r`in}Rz! n&?! sÇ! n&##s͐ ( ! nѯg͐  |!End of file seeking to next card O!9+!9DM`iw#w͐M͎͈͐$.͈͐R7! 6P͔͐++͐͑vMj҉*,js#r**js#r*(js#r͗J! ~#fo##~#fo! ~#fo#n&$k**^͐ͅ! w#w! ~#fo##~#fo|-! Csect ͚! ~#fo͚!% does not have any text records͚͔͐##͐͑͐͋! s#r͔͐++++͈͐͑͐$͈͐Tʶ!ñError seeeking to TXT card͂͐͋͐! ͈͐͐͝$͈͐T   ͔͐++͐͑lM(j|G!-BRLD que is not empty͂͗! 9_:/)*!9DM*j^#Vr+sk*`is#r!! `i~#foV! w#w͐ `i~#fo͐͐Ys!|g}o| `i~#fo͐n&|g}os! ^#Vr+sî`i~#fo͐Ys`i~#fo ͐\s#r`i~#fo ͐\s#r`i~#fo#M j+s`i~#fo##`i~#fo`i~#fos#rs#rs#r͐è!9)* V+t!9DM͐ʹ`is#r͐ͷ`i^#Vr+szk͐ʹ! (j^#Vr+s! ~#fo###~#fo͐^! n͐s**j^#Vr+s*(j^#Vr+s! ~#fo###~#fo͐©! n*4js#6! n͐|g}os! ~#fo###~#fo#͐! n&?M4j! s#r͐͐! s**j^#Vr+s*(j^#Vr+s! n&"!91 !9DM*"j^#Vr+s!n!ViLink que over flow.M&j)*e͐s#r! ~#foMes#r! ~#fo ~#fo`is#r*e~#fo͐s#r*&j^#Vr+s!9 )*+ø!9Dn}[͐k*`i~#fo#~#fok*~#fos#r`i~#fo#͐s#r`i~#fo#~#fok*n}`i~#fo#~#fok**,j^#Vr+s!9*$j^#Vr+s!!M$j*$js#r{,'Ò' !9DM`iw#w͐Mjq!j ~#fo͐k*|e͐k*n}e͐ï`i^#Vr+s!j ~#fo! !Û not define.! ! !f9{, !9DM! ~#fo~#fo| `iw#w͐M.j}! ~#foection starts at  Me# !'!8! ending address  Me+# !N!_! Code lenght is  MeMe# !!Ø! Data section lenght is  MeMe# !!ú!  !9!# -'"8'W/!9DM*!!͐ ͐!`iw#w͐͐ "͐)|1"!*"," !! ~#fo͐)~#fo~#fo!!X"Z" !! ~#fo͐)~#fo!! ~#fo͐)~#fo!! s#r͐"! !! ^#Vr+sá"`i^#Vr+s"!9"2#!9DM͐"͐"ͱ#%!%!9%ç/!9DM! ~#fo~#fo%?`is#r`i~#fo! ~#fo##~#fos#r͐i%!9Á%/.)&ë#!9DM! ~#fo~#fou%`is#r! w#w͐ &`i~#fo͐n! ~#fo͐n}&!$͐͐ x%͐ ͐{% &! ^#Vr+sè%͐ ͐~% &!92&/80!9DM!͉͐! ~#fo~#fo,&#|i&!&! ~#fo##!! ~#fo! ~#fo~#fo/&?s#r͐)`is#r! ~#fo! ~#fo͐s#r! ~#fo##~#fo͐s#r!&!s2! -End of file while reading TXT cardͺ*`͐ ^#Vr+s! n&ͽ*e^#Vr+s!9!9DMM(j|! n&"M*jk*fT! s#r! ~#fo#~#fok*! s#r! ~#fon}! ~#fo~#fo! ~#fo ~#fo`is#r! ~#fo ~#fo! s#r͐k*~#fo͐k* ~#fo! ~#fo ~#fo`is#r! ~#fon&|g}o>Ÿ>ʺ>«>>·>a! ~#fo###~#fo͐ ! n͐|g}os**j^#Vr+s*M*(j^#Vr+s!6!1RLD stack overflowM,jk*fT`is#r`i~#fo͐s`i~#fo###͐s#r`i~#fo#͐͐ )*i~#fos#r! s#r`i~#fo#~#fok*n}`i~#fo#`i~#fo#~#fok*s#r`i~#fo#~#fok*n}…`i~#fo#~#fok* ~#fo! s#r͐k*~#fo|…͐k*`i~#fo#~#fok*n}`i~#fo#~#fok*~#fo|`i~#fo#~#fok*͐k*͐)*h~#foͻ|qMj+|5 Mj++|q! ~#fo͐)*h~#fo~#fos#r `i^#Vr+sMj++|®!éDsect not found in pass 1;M.jd!Too many dsect to link;*2j^#Vr+s)*h͐s#r*.j^#Vr+s!9& '!"!9DM!4 P Control section(s) loaded M&j*e !n  Data section used M2j*h ! ý Starting address of code  Me# ! ending address  Me+# ! ! Data s#{,!9DM͐~#fo͐~#fo#8#Z#!9DM͐5#͐5#`#Í/!9DM͐|g}o0! s#r͐9Ҡ#! ~#fos#r͐]#ô#%)&!9DM͐ͮ#`is#r͐͐ #!%͐͐ t$͐ ͐! s#r͐! ~#fo##~#fo_$! ~#fo##~#fo͐s#r! ~#fo~#fo͐s#rq$͐ ͐ͱ#%%͐͐ ! s#r͐! ~#fo~#fo! ~#fo$! ~#fo##~#fo͐s#r! ~#fo~#fo͐s#r%͐ ͐9 'W/!9DM͐n}6'! ^#Vr+sn& ''7*!#B'7**u'X'#~z'e'U'!`i7**~#É'7**ʥ'Ü'~#å'ô'î0!9DM! ~#fo!͐ͱ's#rz'!! ~#fo##w#w! ~#fo~#fo (01!9DM͐(! ~#fo͐(s#rz;(!! ~#fo! ~#fos#r! ~#fo##6#6! ~#fo~#foÄ(81./!9DM͐ҟ(!)! ~#fo##~#fo¼(!)! ~#fo##~#fo`is#r͐! ~#fo! ~#fo~#fo{(   ͐)!)͐+?`is#r! ~#fo##~#fo|ʽ)!! ~#fo! ~#fo͐~(! ~#fo##~#fo͐s#r! ~#fo~#fo͐s#r!!! ~#fo~#fó()! ~#fo##6#6! ~#fo! ~#fos#r!)!9*à1180!9DM͐|*)*͐+++|3*!)*! ~#fo##^#Vr+sze*! ~#fo^#Vr+sn&*!! ~#fo! ~#fo~#fo*`is#r!ڞ*!*! ~#fo##͐?+s#r! ~#fo! ~#fos#r! ~#fo^#Vr+sn&*!9+-!9-q.!9DM͐͐?! s#r͐! s#r͐h.͐͐?`is#r͐͐! s#r͐͐! s#r͐ ! s#r͐͐ P.͐͐ ! s#r͐|8.͐͐͐͐͐!-!9~#fo-8.͐͐͐͐͐ -! ~#fo͐s#rø-! ~#fo͐s#rÒ-! ~#fos#r@-!9!9DM! ^#Vr+szʾ.͐n`is! ^#Vr+s͐ ns! ^#Vr+s`insy.!9 7*|DM**/.><.~# x. >!10î07* 1\!* 17:)~:,"s!"u*|*uʞ1*~#u1"*s*už1#"u*+"b1:woʯ12w&!o 1 . &7:O*o` &00:qw0! {w7:)~:,"s!"u*|ʎ0**s“0! ~Ž06*u*+"*"*u#"uZ07,2q*&:q):0=0=r:qo& !\&STRLESTRCPSTRCA8STRPO_ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D ySTRLESTRCPSTRCA8STRPO_ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D y)!9DM͐*`is#rzG+͐*! s#rzG+͐?͐M+!M+!9b+W/181!9DM͐+|‚+! n&Y+͐++| +! n&!\+͐+++|¿+! n&!\+! ~#fo##^#Vr+sz+! ~#fo^#Vr+s! ns&!! ~#fo! ~#fo~#fo_+*,!! ~#fo##6#6! ~#fo! ~#fos#r! ~#fo^#Vr+s! ns&!9DM`iw#w! ~#fo͐n! ~#fo͐n},! ~#fo`i^#Vr+sn},!-É,! ~#fo͐n! ~#fo͐nѯgW< /~+ x /|} ) , )6!7**:OzR/q#J/  q/  u/_ / _ ¢/   , FNxg>Goy/$/ç/7:,*/:*/}|2q &00:qw0! {w7:)~:,"s!"u*|ʎ0**s“0! ~Ž06*u*+"*"*u#"uZ07,2q*&:q):0=0=r:qo& !\&STRLE7*!# 7**~# 7** ~# 57**+#~0 !`i %)STRLESTRCPSTRCA8STRPO_ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 1 'd ! ^#V#*0}o|g*  ":D x=D y   $EMAI@GCHARS @GCHARS @GCHA@SX@GINTS" @GINTS/@GIN=@PCHARSB @PCHARSN @PINTS[@PINTSi@PINx@INCDE~b@O @XO @AN @NLO@COM@AS@AS @SU $E @NE@CO@MUL#@DI a@SWITClBIOBDO EXI@INI$T o&9~$R $T o g#9~$R $T~$R$Tog$T " o&9~#fo$T/ o g9~#fo$T=~#fo$T B o&9s$T N o g9s$T#,09=GKUZcgpt}$T||g}oº$R$T )$R$T {ozg$T#$R$T|/g}/o$T#DM!yxGyOȯ{_zW$R !$T9 DMzzOxW>)_;g;}o{_zW=D$$T(DOOz/W{/_x/Gy/O{_zW{z$R  !$37<@$Tl{#€z€#^#V###n$R $T /* ** stdio.h -- header for resident STDIO/CALL, and VM interfaces */ #define stdin 0 #define stdout 1 #define stderr 2 #define stdport 3 #define stdlist 4 #define CCEOM 45062 #define ERR -2 #define EOF -1 #define YES 1 #define NO 0 #define NULL 0 #define CR 13 #define LF 10 #asm ; STD I/O ROUTINES EXTRN GETC EXTRN GETCHAR EXTRN FGETC EXTRN FGETS EXTRN PUTC EXTRN PUTCHAR EXTRN FPUTC EXTRN FPUTS EXTRN PUTS EXTRN FOPEN EXTRN FCLOSE EXTRN GETARG XTRN CCGT EXTRN CCLE EXTRN CCGE EXTRN CCLT EXTRN CCCMP EXTRN CCUGE EXTRN CCULT EXTRN CCUGT EXTRN CCULE EXTRN CCUCMP EXTRN CCASR EXTRN CCASL EXTRN CCSUB EXTRN CCNEG EXTRN CCCOM EXTRN CCMULT EXTRN CCDIV EXTRN CCLNEG EXTRN CCSWITCH ; VM ROUTINES ;VM.R: LIBRY EXTRN CCBOJ EXTRN CCEXIT EXTRN CCPOLL EXTRN CCHALT EXTRN CCOPEN EXTRN CCCLOSE EXTRN CCDELIM EXTRN CCREAD EXTRN CCWRITE EXTRN CCSEEK EXTRN CCMODE E [ o&9s#r$T i o g9s#r$T x}|$T 9~͢ͷ͢͢ͷ͢  ^#V^{W$T )_zW/<_zW r+s|s|$R         - B O T $T }o|g$T }o|g$T }o|g$T| !|!|$R$T9͙+͙+͙+͙+$T9J͙+͙+ͩ+ͩ+$T3ͩ+ͩ+{_z!ɳ7z°{!|$R*+++͢o&$R$T $T$T9*+!^#6!#~ }| #~ 6$T9!***********************$T ***noname$R"!.38;@EGIKMOQSUWY[]_acegikmoqsuw$Q9J͙+͙+ͩ+ͩ+$T3ͩ+ͩ+{_z!ɳ7z°{!|$R ; STD I/O ROUTINES MATCHING VM ROUTINES EXTRN FFLUSH EXTRN ABORT EXTRN EXIT EXTRN UNLINK ; ARITHMETIC & LOGICAL ROUTINES EXTRN CCARGC EXTRN CCSXT EXTRN CCDSGI EXTRN CCDDGI EXTRN CCINCI EXTRN CCDECI EXTRN CCGINT EXTRN CCPIDDPD EXTRN CCPDPI EXTRN CCDSGC EXTRN CCDDGC EXTRN CCINCC EXTRN CCDECC EXTRN CCGCHAR EXTRN CCPCDDPD EXTRN CCPDPC EXTRN CCPCHAR EXTRN CCPINT EXTRN CCOR EXTRN CCXOR EXTRN CCAND EXTRN CCEQ EXTRN CCNE EXTRN CCFILE EXTRN CCPURGE EXTRN CCFLUSH EXTRN CCALLOC EXTRN CCFREE EXTRN CCAVAIL #endasm XTRN CCULE EXTRN CCUCMP EXTRN CCASR EXTRN CCASL EXTRN CCSUB EXTRN CCNEG EXTRN CCCOM EXTRN CCMULT EXTRN CCDIV EXTRN CCLNEG EXTRN CCSWITCH ; VM ROUTINES ;VM.R: LIBRY EXTRN CCBOJ EXTRN CCEXIT EXTRN CCPOLL EXTRN CCHALT EXTRN CCOPEN EXTRN CCCLOSE EXTRN CCDELIM EXTRN CCREAD EXTRN CCWRITE EXTRN CCSEEK EXTRN CCMODE E   There is a minor bug in ZCMD, in my haste, I set an equate to 5 when I meant 4. This equate is NUMCOL, and should be set to a "power" of two. In other words, set it to 1, 2, or 4. If it is set at 5, you will get a very weird looking directory display. Paul  CP/M WILL RUN ON EITHER AN 8080A SYSTEM OR A Z80 SYSTEM. Z80ASM WILL RUN IN THE CP/M MINIMUM (16K) SYSTEM BUT WILL UTILI title 'Z80 CMD Processor v1.0 as of 04/13/82' ; ; CP/M Z80 Command Processor Replacement (CCP) Version 1.0 ; ; ZCMD is a replacement for the standard CCP (by Digital Research). ;ZCMD is based upon ZCPR (by the CCP group) and NZCPR (by the ZCPR group). ;This program has been renamed (again) in an effort to avoid confusion with ;ZCPR version 2.0 (which is by Richard Conn). ; ;This program is released to the Public Domain, it may not be sold or re-sold ;for profit. ; ;Grandparent's history: CPR v2.1 has been updated and renamed to ZCMD version 1.0. --pst ; ; The following individuals have contributed to this program: ; ; SBB - Steve Bogolub The person that keeps ZCPR neat and not a chaotic mess ; (fixes my (PST's) bugs and writes great hacks too) ; (v1.1S, v1.5S (?), v1.6) ; PST - Paul Traina The silly person behind SECURE mode. Numerous minor ; re-hacks to make life easier. (a bunch o'bugs too..) ; (v1.1, v1.3, v1.4, v1.5, v1.7, v2.1) ; ; HLB - Howard Bookser CAF - Chuch Fnts or complaints there to PST. ; ; The most obvious differences between ZCMD and ZCPR are the security ; features, controlled by additional conditional assembly flags. Such ; features restrict access to ZCMD intrinsic commands, add additional ; levels of .COM file searching, and prevent access to higher drives ; or user levels, with either internal or external password control of ; these features. Less obvious differences involve code optimization to ; gain space, and some minor bug fixes in the ; ; ZCPR version 1.0 was created from CCPZ version 4.0 by RLC in a coordinated ; effort with the CCP-GROUP. ZCPR was a group effort by CCP-GROUP, whose ; active membership involved in this project consisted of the following: ; RLC - Richard Conn KBP - Keith Peterson ; RGF - Ron Fowler FJW - Frank Wancho ; The following individuals also provided a contribution: ; SBB - Steve Bogolub PST - Paul Traina ; ; Since RLC has now produced ZCPR version 2.0, in an effor to avoid confusion, ; NZorsberg RAF - Bob Fischer ; BB - Ben Bronson PRG - Paul Grupp PJH - Paul Homchick ; HEW - Hal Walchli DR - Dave Roznar HK - Harry Kaemmerer ; SFK - Sigi Kluger PP - Peter Pinchis ; ; In an attempt to maintain a link to the past, changes between the ; current version of ZCMD will be provided as both a difference file ; between ZCMD's (ZCMD10-11.DIF). All updates and bug reports should ; be transmitted to either Technical CBBS (in the East) or preferably ; OxGate-001 (in the West). Make commeTYPE command. ; ;************************************************************************ ; 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: ; ; REL - TRUE if integration is to be done via MOVCPM ; - FALSE if integration is to be done via DDT and SYSGEN ; ; SECURE - TRUE to conditionally disable potentially-harmful ; com   mands (GO, ERA, SAVE, REN, DFU, GET, JUMP). Under ; SECURE, if WHEEL contains RESTRCT, do not accept those ; commands, and search for COM files under current user ; then user "DEFUSR" only. If WHEEL does not contain ; RESTRCT (presumably from passworded change), allow ; all commands, and search current user, then last user ; set by DFU (originally "RESUSR"), then user "DEFUSR" ; for COM files, giving access with password to an ; additional level of COM files.  to PST's PASS.ASM, set this false, otherwise, ZCMD will ; handle the PASSword coding with a built in command. ; ; DRUSER - Set this EQU false if you wish to disable RAF's neat hack ; that allows you the type B: 7 to move to drive B: user area ; seven. This also removes the USER command. Basically, set ; this equate false if you want to use USERPW or some other pgm. ; ; RAS - Remote-Access System; setting this equate to TRUE disables ; certain CPR commands that are consfed into MAXDRIV at cold boot, ; and presumably will be changed later by a passworded ; program if desired. ; ; USRMAX - Maximum legal user # + 1 stored in this location. 0000H ; disables this feature, and uses the value of MAXUSR+1 instead. ; ; BASE - Base Address of user's CP/M system (normally 0 for DR versttp Dt Vr HtsEm rttttttREm tttttttttttttttttttttttttttt,cy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oy oted files at once. ; ; CMDTYP - Set to TRUE to generate code for intrinsic TYPE command. ; ; WSTYPE - Set to TRUE to generate an extra three lines of code ; to correctly interpret the WordStar (tm) internal ; end of line hyphen for display, which is the ASCII ; NEWLINE code (1FH) and normally non-printing or ; troublemaking -- thanks to PJH for this one. CMDTYP ; must be TRUE, or this symbol will be ignored. ; ; CMDLST - Set to TRUE to generate code for intrinsic LIST commae the internal password by setting INPASS to TRUE (external is ; MUCH recommended for easier modification). Those options absolutely ; generate too much code unless either CMDTYP or CMDDIR or both are ; set FALSE. A system with SECURE set to FALSE is right on the edge, ; and requires a give and take on options to fit, i.e. you can have ; MAXDRIV and USRMAX with DIR and TYPE if you leave out LIST and ; querying on ERASE, and so on. ; ******************************************************************* ; ; If you have chosen a SECURE system, all resident commands may be ; activated by entering: PASS Where is a sequence ; of characters placed at PASSID (if INPASS is true, otherwise, see ; documentation in PST's PASS.ASM). If the password is incorrect. the system ; will come back with PASS? as if it was looking for a COM file. ; NORM is the reverse of PASS, it will disable the WHEEL mode. ; ; INPASS - If in the SECURE mode, you wish to use a program similar ; idered harmful in a Remote- ; Access environment; use under Remote-Access Systems (RBBS) for ; security purposes. Note: SECURE is the direct enemy of RAS, ; DON'T define both equates or you will be VERY sorry. ; The advantage SECURE has over RAS is that by saying a magic ; word, all of the normal commands pop into existance. ; ; MAXDRIV - Maximum legal drive number stored in this location. ; (0 means only A:, etc.) 0000H disables this feature. ; The value MAXDR is stufy oy oy oy oy oy oy ok bVtePtem, or by setting the ; MSIZE and BIOSEX equates to the system memory size in ; K-bytes and the "extra" memory required by your BIOS ; in K-bytes. BIOSEX is zero if your BIOS is normal size, ; and can be negative if your BIOS is in PROM or in ; non-contiguous memory. ; ; EPRMPT - Set TRUE to be prompted "Ok?" after seeing what files will ; be erased. No, this is NOT for individual file prompting, ; it is just to confirm deletion of all selecnd. ; Since almost all of the LIST code is common to the ; TYPE code, CMDTYP must be set TRUE as well, or this ; Symbol will be ignored. ; ; CMDDIR - Set to TRUE to generate code for intrinsic DIR command. ; ; Remember, you only get a total of 2048 (0800h) bytes of space for ; ALL of the generated code, or many other areas of your system ; generation will be affected. For example, to be fully SECURE, you ; would set SECURE to TRUE, and define MAXDRIV and USRMAX, and maybe ; us******** ** Be careful when playing with different combinations of these equates. ** ** You might not have enough memory to some combinations. Check this ** ** if you have problems, if they still persist, gripe to me (PST). ** *************************************************************************** ; REL EQU FALSE ;Set to true for MOVCPM integration ; BASE EQU 0 ;Base of CP/M system (set for standard CP/M) ; IF REL CMDLOC EQU 0 ;MOVCPM image ELSE ; ; If REL is FALSE, the value o   f CMDLOC may be set in one ; of two ways. The first way is to set MSIZE and BIOSEX ; as described above using the following three lines: ; ;MSIZE EQU 56 ;size of memory in kilobytes ;BIOSEX EQU 2 ;extra # kilobytes in BIOS ;CMDLOC EQU 3400H+(MSIZE-20-BIOSEX)*1024 ;ZCMD origin ; ; The second way is to obtain the origin of your current ; CMD using BDSLOC or its equivalent, then merely set CMDLOC ; to that value as in the following line: ; CMDLOC EQU 0DA00H ;Fill in with BDLOC supplied value d address in ; the SYSGEN Image ; ;CMDR EQU 0E00H-CMDLOC ;DDT load offset for Apple CP/M 2.20B ;CMDR EQU 0980H-CMDLOC ;DDT load offset for D.R. standard sysgen CMDR EQU 1600H-CMDLOC ;DDT load offset for CompuPro Disk-1 ;CMDR EQU 1100H-CMDLOC ;DDT load offset for Morrow's MicroStuff ENDIF ; ; RAS EQU FALSE ;set to true if cmd is for a remote-access ;system and you don't want to run secure. ; USRMAX EQU 0000H ;location of byte in memory containing ; number of highest allowable user coQU 1 ;max drive # to set into maxdriv on cold boot ; SECURE EQU FALSE ;set true for secure environment... ; DEFUSR EQU 0 ;default user for unrestricted com files ; IF SECURE WHEEL EQU 3EH ;set to "restrct" for limited access RESTRCT EQU 0 ;when (wheel)==restrct, limit commands RESUSR EQU 15 ;check here for restricted access com files ;until changed by dfu or warm boot ENDIF ;SECURE ; INPASS EQU FALSE ;set true if running secure and not pass.com ; INUSER EQU TRUE ;true to allow U to ; get a two-column directory display instead of four-column (narrow 40-col ; screen, remember) was to have their BIOS poke CCP every time it was ; loaded, if there was no terminal interface card in I/O slot 3. ; Naturally, that will turn into a random poke on any non-standard ; CCP, like this one. The best way to get this ZCMD up on the Apple is to ; load it into CPM56.COM, at location 0E00H in the image. The BIOS code ; that pokes the ZCMD can also be modified at that time. The poke is done to a ; the proper value and disable that poke. ; NUMCOL EQU 5 ;number of columns in directory display ; ; The following is presented as an option, but is not generally user-customiz- ; able. A basic design choice had to be made in the design of ZCMD 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 ; logged-; ; Note that you should only use one method or the other. ; Do NOT define CMDLOC twice! ; ; The following gives the required offset to load the CMD into the ; CP/M SYSGEN Image through DDT (the Roffset command); Note that this ; value conforms with the standard value presented in the CP/M reference ; manuals, but it may not necessarily conform with the location of the ; CCP in YOUR CP/M system; several systems (Morrow Designs, P&T, Heath ; Org-0 to name a few) have the CCP located at a non-standarde + 1 ; this value is set by cmd on cold boot, ; and presumably controlled after that ; by a password program. if usrmax=0, then ; maxusr below is used for checking only. ; 03fh is recommended if used *** MAXUSR EQU 15 ;max allowed user number, this + 1 is stuffed ; into usrmax on cold boot, or used directly ; if usrmax=0 ; MAXDRIV EQU 0000H ;location that has max legal drive # ;set it to zero to disable this crock ;03dh is recommended if used *** MAXDR ESER command and drive/user hack ; EPRMPT EQU FALSE ;true to prompt before erasing all files ; INTYPE EQU TRUE ;true to generate internal TYPE command WSTYPE EQU TRUE ;true to generate wordstar hyphen check (INTYPE ;must be true too) INLIST EQU TRUE ;true to generate internal LIST command ;(INTYPE must be true too) INDIR EQU TRUE ;true to generate internal DIR code ; ; ; *** Note to Apple Softcard Users *** ; ; In their infinite (?) wisdom (???), Microsoft decided that the way; by "STA 0C8B2H", found at 24FEH in the CPM56 image. To keep this ; feature, change the 0C8B2H address in that instruction by hand to ; the value generated for the symbol TWOPOK in the DIR routine. If ; you have assembled out the DIR code by setting CMDDIR to FALSE, then ; disable this feature by changing the "STA 0C8B2H" to three NOP instructions. ; ie: change the contents of location 24FEH to 2500H to 00,00,00. If you wish ; to force a two-column display in all cases, set the NUMCOL equate below in drive, so when the user was logged into B: and he issued a SUBMIT ; command, the $$$.SUB was placed on B: and did not execute because the CCP ; looked for it on A: and never found it. ; ; After much debate it was decided to have ZCMD 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 asse   mbly time of creating the $$$.SUB on the logged-in drive ; or on drive A:. ; ; A final definition of the Indirect Command File ($$$.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 files and transforms ; it for processing by the ZCMD (the $$$.SUB File). ; ZCMD will then execute the commands indicated ; EXACbe looking for $$$.SUB on the logged-in drive, and switching ; logged-in drives without moving the $$$.SUB file as well would cause ; processing to abort. ; SUBA EQU TRUE ;Set to TRUE to have $$$.SUB always on A: ;Set to FALSE to have $$$.SUB on the logged-in drive ; ; The following flag enables extended processing for user-program supplied ; command lines. This is for Command Level 3 of ZCMD. Under the current ; ZCMD philosophy, three command levels exist: ; ; (1) that command issued by talize the command line for processing. ; Once the command line is properly stored, the user executes the command line ; by reentering the ZCMD through CMDLOC [NOTE: The C register MUST contain ; a valid User/Disk Flag (see location 4) at this time.] ; CLEVEL3 EQU TRUE ;enable command level 3 processing ; ; Terminal and 'TYPE' customization equates ; NLINES EQU 24 ;number of lines on crt screen WIDE EQU TRUE ;true if wide dir display FENCE EQU '|' ;sep char between dir files ; PGDFLT EQU Tnumber base ; SECTFLG EQU 'S' ;option char for save command to save sectors ; ; end of customization section ; CR EQU 0DH LF EQU 0AH TAB EQU 09H FFEED EQU 0CH BEL EQU 07H ; WBOOT EQU BASE+0000H ;cp/m warm boot address UDFLAG EQU BASE+0004H ;user num in high nybble, disk in low BDOS EQU BASE+0005H ;bdos function call entry pt TFCB EQU BASE+005CH ;default fcb buffer TBUFF EQU BASE+0080H ;default disk i/o buffer TPA EQU BASE+0100H ;base of tpa ; ; ; macros to provide z80 extensions ng range of 8-bit displacements IF (?DD GT 7FH) AND (?DD LT 0FF80H) DB 100H ;displacement range error on jump relative ELSE DB ?DD ENDIF ENDM ; ; Z80 macro extensions ; JR MACRO ?N ;;jump relative DB 18H @GENDD ?N-$-1 ENDM ; JRC MACRO ?N ;;jump relative on carry DB 38H @GENDD ?N-$-1 ENDM ; JRNC MACRO ?N ;;jump relative on no carry DB 30H @GENDD ?N-$-1 ENDM ; JRZ MACRO ?N ;;jump relative on zero DB 28H @GENDD ?N-$-1 ENDM ; JRNZ MACRO ?N ;;jump relative on no zeTLY as if they were typed at the Console." ; ; Hence, to permit this to happen, the $$$.SUB file must always ; be present on a specific drive, and A: is the choice for said drive. ; With this facility engaged as such, Indirect Command Files like: ; ; DIR ; A: ; DIR ; ; can be executed, even though the currently logged-in drive is changed ; during execution. If the $$$.SUB file was present on the currently ; logged-in drive, the above series of commands would not work since the ; ZCMD would the user from his console 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 ; ; Setting CLEVEL3 to TRUE enables extended processing of the third level of ; ZCMD command. All the user program need do is to store the command line and ; set the character count; ZCMD will initialize the pointers properly, store ; the ending zero properly, and capiRUE ;set to false to disable paging by default PGDFLG EQU 'P' ;for type command: page or not (dep on pgdflt) ; this flag reverses the default effect ; SYSFLG EQU 'A' ;for dir command: list $sys and $dir ; SOFLG EQU 'S' ;for dir command: list $sys files only ; SUPRES EQU TRUE ;supresses user # report for user 0 ; SPRMPT EQU '$' ;cmd prompt indicating submit command CMDMPT EQU '>' ;cmd prompt indicating user command ; NUMBASE EQU 'H' ;character used to switch from default ; ; macros include: ; $-MACRO ;first turn off the expansions ; ; JR - jump relative ; JRC - jump relative if carry ; JRNC - jump relative if no carry ; JRZ - jump relative if zero ; JRNZ - jump relative if no zero ; DJNZ - decrement b and jump relative if no zero ; LDIR - mov (hl) to (de) for count in bc ; LxxD - load double reg direct ; SxxD - store double reg direct ; ; @GENDD macro used for checking and generating ; 8-bit jump relative displacements ; @GENDD MACRO ?DD ;;used for checkiro DB 20H @GENDD ?N-$-1 ENDM ; DJNZ MACRO ?N ;;decrement b and jump relative on no zero DB 10H @GENDD ?N-$-1 ENDM ; LDIR MACRO ;;ldir DB 0EDH,0B0H ENDM ; LDED MACRO ?N ;;load de direct DB 0EDH,05BH DW ?N ENDM ; LBCD MACRO ?N ;;load bc direct DB 0EDH,4BH DW ?N ENDM ; SDED MACRO ?N ;;store de direct DB 0EDH,53H DW ?N ENDM ; SBCD MACRO ?N ;;store bc direct DB 0EDH,43H DW ?N ENDM ; ; end of z80 macro extensions ; ; ;**** section 0 **** ; ORG CMDLOC ;    ; Entry points into ZCMD ; ; if ZCMD is entered at location CMDLOC (at the jump to CMD), then the ; default command in CIBUFF will be processed. if ZCMD is entered at ; location CMDLOC+3 (at the jump to CMD1), then the default command in ; CIBUFF will not be processed. ; ; Note: entry into zcmd in this way is permitted under this version, ; 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 4tible with such programs (provided they determine the buffer ; length from the byte at mbuff [CMDLOC+6]), but under ZCMD this is ; no longer necessary, since this buffer pointer is automatically ; initialized in all cases. ; ENTRY: JMP CMD ; process potential default command, and set ; usrmax to maxusr default JMP CMD1 ; do not process potential default command ; ; Buffers et al ; ; Input command line and default command ; ; The command line to be executed is stored here. This command lter count of all characters in the command line ; up to and including the last character is placed into location CBUFF ; (immediately before the command line at CIBUFF). The placed command line ; is then parsed, interpreted, and the indicated command is executed. ; if CLEVEL3 is permitted, a terminating zero is placed after the command ; (otherwise the user program has to place this zero) and the CIBPTR is ; properly initialized (otherwise the user program has to init this ptr). ; If the command is F: DB BUFLEN ;maximum buffer length CBUFF: DB 0 ;number of valid chars in command line CIBUFF: DB ' ' ;default (cold boot) command ; ; The Copyright notice from Digital Research is genned into the ; stock CCP at this location. In order to avoid the slightest chance ; of legal hassles, we'll leave it in. ; DB ' Copyright (C) 1979, Digital Research ' CIBUF: DB 0 ;command string terminator DS BUFLEN-($-CIBUFF)+1 ;total is 'buflen' bytes ; CIBPTR: DW CIBUFF ;pointer to comma;s1 SUBFS2: DS 1 ;s2 SUBFRC: DS 1 ;record count DS 16 ;disk group map SUBFCR: DS 1 ;current record number ; ; command file control block ; FCBDN: DS 1 ;disk name FCBFN: DS 8 ;file name FCBFT: DS 3 ;file type DS 1 ;extent number DS 2 ;s1 and s2 DS 1 ;record count FCBDM: DS 16 ;disk group map FCBCR: DS 1 ;current record number ; ; other buffers ; PAGCNT: DB NLINES-2 ;lines left on page CHRCNT: DB 0 ;char count for type QMCNT: DB 0 ;question mark count for fcb token scann: the ; most significant nybble contains the user number and the least significant ; nybble contains the disk number). ; ; Some user programs (such as SYNONYM3) attempt to use the default ; command facility. Under the original ccp, it was necessary to initialize ; the pointer after the reserved space for the command buffer to point to ; the first byte of the command buffer. under current versions, this is ; no longer the case. The CIBPTR (command input buffer pointer) is located ; to be compaine ; 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 starting at ; CIBUFF. This command line is terminated by the last character (not carriage ; return), and a characplaced by a user program, entering at CMDLOC is enough ; to have the command processed. Again, under the current ZCMD, it is not ; necessary to store the pointer to CIBUFF in CIBPTR; ZCMD will do this for ; the calling program if CLEVEL3 is made true. ; ; Warning: The command 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 MBUFF (CMDLOC+6). ; BUFLEN EQU 80 ;maximum buffer length MBUFnd input buffer CIPTR: DW CIBUF ;pointer to curr command for ; error reporting ; DS 26 ;stack area STACK EQU $ ;top of stack ; ; file type for command ; COMMSG: DB 'COM' ; ; submit file control block ; SUBFCB: IF SUBA ;if $$$.sub on a: DB 1 ;disk name set to default to drive a: ENDIF ; IF NOT SUBA ;if $$$.sub on current drive DB 0 ;disk name set to default to current drive ENDIF ; DB '$$$' ;file name DB ' ' DB 'SUB' ;file type DB 0 ;extent number DB 0 er ; ; ; ZCMD starting points. Note that some CP/M implementations ; require the cold start address to be in the starting page ; of the ccp, for dynamic CCP loading. CMDTBL was moved for ; this reason. ; ; Set USRMAX and/or MAXDRIV to default values on cold boot ; if required. note that some BIOS implementations will end ; up here instead of at the warm boot, defeating passwording ; of these options. I reccomend that such a bios be fixed. ; IF USRMAX OR MAXDRIV CMD: IF USRMAX MVI A,MAXU   SR+1 ;set usrmax on cold boot STA USRMAX ENDIF ;usrmax ; IF MAXDRIV MVI A,MAXDR ;set maxdriv on cold boot STA MAXDRIV ENDIF ;maxdriv ; JR CMD2 ; then proceed ENDIF ;usrmax or maxdriv ; ; start command and don't process default command stored ; CMD1: XRA A ;set no default command STA CBUFF ; ; Start command and possibly process default command ; ; Note on modification by RGF: BDOS returns 0FFh in ; accumulator whenever it logs in a directory, if any ; file name contains a '$'ber (see loc 4) ANI 0FH ;extract default disk drive STA TDRIVE ;set it JRZ NOLOG ;skip if 0...already logged CALL LOGIN ;log in default disk ; IF NOT SUBA ;if $$$.sub is on current drive STA RNGSUB ;bdos '$' clue ENDIF ; NOLOG: LXI D,SUBFCB ;check for $$$.sub on current disk RNGSUB EQU $+1 ;pointer for in-the-code modification MVI A,0 ;2nd byte (immediate arg) is the rngsub flag ORA A ;set flags on clue CMA ;prepare for coming 'cma' CNZ SEAR1 CMA ;0ffh is returned if C RS00 SUI 10 ;subtract 10 from it PUSH PSW ;save it MVI A,'1' ;output 10's digit CALL CONOUT POP PSW RS00: ADI '0' ;output 1's digit (convert to ascii) CALL CONOUT ; ; read input line from user or $$$.sub ; RS000: CALL REDBUF ;input command line from user (or $$$.sub) ; ; process input line ; RS1: ; IF CLEVEL3 ;if third command level is permitted CALL CNVBUF ;capitalize command line, place ending 0, ; and set cibptr value ENDIF ; CALL DEFDMA ;set tbuff to dma add;store low PCHL ;execute cmd routine ; ; entry point for restarting cmd and logging in default drive ; RSTCMD: CALL DLOGIN ;log in default drive ; ; entry point for restarting cmd without logging in default drive ; RCMDNL: CALL SCANER ;extract next token from command line LDA FCBFN ;get first char of token SUI ' ' ;any char? LXI H,TEMPDR ORA M JNZ ERROR JR RESTRT ; ; no file error message ; PRNNF: CALL PRINTC ;no file message DB 'No Fil','e'+80H RET ; ; cmd built-in coNRCMDS EQU ($-CMDTBL)/(NCHARS+2) ;put any commands that are ok to ;run when not under wheel mode ;in front of this label IF INLIST AND INTYPE DB 'LIST' ;list file to printer DW LIST ENDIF ;inlist and intype ; IF INPASS AND SECURE DB 'NORM' ;disable wheel mode DW NORM ENDIF ;inpass and secure ; IF NOT RAS ;for non-ras DB 'GO ' ;jump to 100h DW GO DB 'ERA ' ;erase file DW ERA DB 'SAVE' ;save memory image to disk DW SAVE DB 'REN ' ;rename file DW R in it. this is now used as ; a clue to determine whether or not to do a search ; for submit file, in order to eliminate wasteful searches. ; IF USRMAX OR MAXDRIV CMD2: ELSE CMD: ENDIF ;usrmax or maxdriv ; LXI SP,STACK ;reset stack PUSH B MOV A,C ;c=user/disk number (see loc 4) RAR ;extract user number RAR RAR RAR ANI 0FH MOV E,A ;set user number CALL SETUSR CALL RESET ;reset disk system STA RNGSUB ;save submit clue from drive a: POP B MOV A,C ;c=user/disk numno $$$.sub, so complement STA RNGSUB ;set flag (0=no $$$.sub) LDA CBUFF ;execute default command? ORA A ;0=no JRNZ RS1 ; ; prompt user and input command line from him ; RESTRT: LXI SP,STACK ;reset stack ; ; print prompt (du>) ; CALL CRLF ;print prompt CALL GETDRV ;current drive is part of prompt ADI 'A' ;convert to ascii a-p CALL CONOUT CALL GETUSR ;get user number ; IF SUPRES ;if suppressing usr # report for usr 0 ORA A JRZ RS000 ENDIF ; CPI 10 ;user < 10? JRress CALL GETDRV ;get default drive number STA TDRIVE ;set it CALL SCANER ;parse command name from command line CNZ ERROR ;error if command name contains a '?' LXI D,RSTCMD ;put return address of command PUSH D ;on the stack LDA TEMPDR ;is command of form 'd:command'? ORA A ;nz=yes JNZ COM ; immediately CALL CMDSER ;scan for cmd-resident command JNZ COM ;not cmd-resident MOV A,M ;found it: get low-order part INX H ;get high-order part MOV H,M ;store high MOV L,A mmand table ; NCHARS EQU 4 ;number of chars/command ; ; cmd command name table ; each table entry is composed of the 4-byte command and 2-byte address ; CMDTBL: ; IF INPASS AND SECURE DB 'PASS' ;enable wheel (sysop) mode DW PASS ENDIF ;inpass and secure ; IF INUSER DB 'USER' ;change user areas DW USER ENDIF ;inuser ; IF INTYPE DB 'TYPE' ;type a file to con: DW TYPE ENDIF ;intype ; IF INDIR DB 'DIR ' ;pull a directory of disk files DW DIR ENDIF ;indir EN DB 'DFU ' ;set default user DW DFU DB 'GET ' ;load file into memory DW GET DB 'JUMP' ;jump to location in memory DW JUMP ENDIF ;not ras ; NCMNDS EQU ($-CMDTBL)/(NCHARS+2) ; ;------------------------------------------------------------------------------ ; ; I/O Utilities ; ; Output char in reg A to console and don't change BC ; ; ; Output ; CRLF: MVI A,CR CALL CONOUT MVI A,LF ;fall thru to conout ; CONOUT: PUSH B MVI C,02H OUTPUT: ANI 7FH ;prevent inadverta   nt graphic output to printers MOV E,A PUSH H CALL BDOS POP H POP B RET ; CONIN: MVI C,01H ;get char from con: with echo CALL BDOSB ; ; Convert char in A to upper case ; UCASE: CPI 'a' ;lower-case a RC CPI 7BH ;greater than lower-case z? RNC ANI 5FH ;capitalize RET ; IF INTYPE LCOUT: ENDIF ;INTYPE ; IF INTYPE AND INLIST PUSH PSW ;output char to con: or lst: dep on prflg PRFLG EQU $+1 ;pointer for in-the-code modification MVI A,0 ;2nd byte (immediate arg) is tPGFLG EQU $+1 ;pointer to in-the-code buffer pgflg MVI A,0 ;0 may be changed by pgflg equate CPI PGDFLG ;page default override option wanted? ; IF PGDFLT ;if paging is default JRZ PGBAK ; pgdflg means no paging, please ELSE ;if paging not default JRNZ PGBAK ; pgdflg means please paginate ENDIF ; WTLOOP: CALL BREAK ;get char but don't echo to screen JRZ WTLOOP ;nothing there yet.... so loop CPI 'C'-'@' ;^C JZ RSTCMD ;restart cmd PGBAK: POP H ;restore hl RET ENDIF t string ending with zero byte or character high bit set ; pointed to by hl ; PRIN1: MOV A,M ;get next byte CALL CONOUT ;print char MOV A,M ;get next byte again for test INX H ;pt to next byte ORA A ;set flags RZ ;done if zero RM ;done if msb set JR PRIN1 ; ;------------------------------------------------------------------------------ ; ; BDOS function routines ; ; Return number of current disk in A ; GETDRV: MVI C,19H JR BDOSJP ; ; Set 80h as DMA address ; DEFDMA: LDOS ; SEARF: LXI D,FCBDN ;specify fcb SEAR1: MVI C,11H JR GRBDOS ; SEARN: MVI C,12H JR GRBDOS ; ; Check for submit file in execution and abort it if so ; SUBKIL: LXI H,RNGSUB ;check for submit file in execution MOV A,M ORA A ;0=no RZ MVI M,0 ;abort submit file LXI D,SUBFCB ;delete $$$.sub ; DELETE: MVI C,13H JR BDOSJP ;save more space ; ; Reset user number if changed ; RESETUSR: TMPUSR EQU $+1 ;pointer for in-the-code modification MVI A,0 ;2nd byte (immediate arg) is I H,TDRIVE ;mask in default drive number (low nybble) ORA M ;mask in STA UDFLAG ;set user/disk number RET ; ; Set user/disk flag to user 0 and default disk ; SETU0D: TDRIVE EQU $+1 ;pointer for in-the-code modification MVI A,0 ;2nd byte (immediate arg) is tdrive STA UDFLAG ;set user/disk number RET ; ; Input next command to ZCMD ; (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) ; REDBUF: LDA RNhe print flag ORA A ;0=type JRZ LC1 POP PSW ;get char ; ; Output char in reg A to list device ; LSTOUT: PUSH B MVI C,05H JR OUTPUT LC1: POP PSW ;get char ENDIF ;INTYPE AND INLIST ; IF INTYPE PUSH PSW CALL CONOUT ;output to con: POP PSW CPI LF ;check for paging RNZ ;done if not eol yet ; ; Count down lines and pause for input (direct) if count expires ; PUSH H LXI H,PAGCNT ;count down DCR M JRNZ PGBAK ;jump if not end of page MVI M,NLINES-2 ;refill counter ; ;INTYPE ; READF: LXI D,FCBDN ;fall thru to read READ: MVI C,14H ;fall thru to bdosb ; ; Call BDOS and save BC ; BDOSB: PUSH B CALL BDOS POP B ORA A RET ; ; Print string ending with zero byte or character high bit set ; pointed to by ret address, start with ; PRINTC: PUSH PSW ;save flags CALL CRLF ;new line POP PSW ; PRINT: XTHL ;get ptr to string PUSH PSW ;save flags CALL PRIN1 ;print string POP PSW ;get flags XTHL ;restore hl and ret adr RET ; ; PrinXI D,TBUFF ;80h=tbuff DMASET: MVI C,1AH JR BDOSJP ; RESET: MVI C,0DH BDOSJP: JMP BDOS ; LOGIN: MOV E,A ;move desired # to bdos reg ; IF MAXDRIV LDA MAXDRIV ;check for legal drive # CMP E JC ERROR ;don't do it if too high ENDIF ;maxdriv ; MVI C,0EH JR BDOSJP ;save some code space ; OPENF: XRA A STA FCBCR LXI D,FCBDN ;fall thru to open ; OPEN: MVI C,0FH ;fall thru to grbdos ; GRBDOS: CALL BDOS INR A ;set zero flag for error return RET ; CLOSE: MVI C,10H JR GRBtmpusr MOV E,A ;place in e JR SETUSR ;then go set user GETUSR: MVI E,0FFH ;get current user number SETUSR: MVI C,20H ;set user number to value in e (get if e=ffh) JR BDOSJP ;more space saving ; ; End of BDOS functions ; ;------------------------------------------------------------------------------ ; ; ZCMD Utilities ; ; Set user/disk flag to current user and default disk ; SETUD: CALL GETUSR ;get number of current user ADD A ;place it in high nybble ADD A ADD A ADD A LXGSUB ;submit file currently in execution? ORA A ;0=no JRZ RB1 ;get line from console if not LXI D,SUBFCB ;open $$$.sub PUSH D ;save de CALL OPEN POP D ;restore de JRZ RB1 ;erase $$$.sub if end of file and get cmnd LDA SUBFRC ;get value of last record in file DCR A ;pt to next to last record STA SUBFCR ;save new value of last record in $$$.sub CALL READ ;de=subfcb JRNZ RB1 ;abort $$$.sub if error in reading last rec LXI D,CBUFF ;copy last record (next submit cmnd) to cbu   ff LXI H,TBUFF ; from tbuff LXI B,BUFLEN ;number of bytes LDIR LXI H,SUBFS2 ;pt to s2 of $$$.sub fcb MVI M,0 ;set s2 to zero INX H ;pt to record count DCR M ;decrement record count of $$$.sub LXI D,SUBFCB ;close $$$.sub CALL CLOSE JRZ RB1 ;abort $$$.sub if error MVI A,SPRMPT ;print submit prompt CALL CONOUT LXI H,CIBUFF ;print command line from $$$.sub CALL PRIN1 CALL BREAK ;check for abort (any char) ; IF CLEVEL3 ;if third command level is permitted RZ ;if or less JRC ERR1 PUSH H ;save ptr to error command char CALL CONOUT ;print command char POP H ;get ptr INX H ;pt to next JR ;'>'=delimiter RET ; ; Advance input ptr to first non-blank and fall through to sblank ; ADVAN: LDED CIBPTR ; ; Skip string pointed to by DE (string ends in 0) until end of string ; or non-blank encountered (beginning of token) ; SBLANK: LDAX D ORA A RZ CPI ' ' RNZ INX D JR SBLANK ; ; Add a to hl (hl=hl+a) ; ADDAH: ADD L MOV L,A RNC INR H RET ; ; Extract decimal number from command line ; return with value in reg a (all registers may be affected) ; NUMBER: CALL SCaccumulated value, b=char count ; (c=0, b=11) NUM1: MOV A,M ;get char CPI ' ' ;done if JRZ NUM2 INX H ;pt to next char SUI '0' ;convert to binary (ascii 0-9 to binary) CPI 10 ;error if >= 10 JRNC NUMERR MOV D,A ;digit in d MOV A,C ;new value = old value * 10 RLC RLC RLC ADD C ;check for range error JRC NUMERR ADD C ;check for range error JRC NUMERR ADD D ;new value = old value * 10 + digit JRC NUMERR ;check for range error MOV C,A ;set new value D> (no abort), return to caller and run ENDIF ; IF NOT CLEVEL3 ;if third command level is not permitted JRZ CNVBUF ;if (no abort), capitalize command ENDIF ; CALL SUBKIL ;kill $$$.sub if abort JMP RESTRT ;restart cmd ; ; Input command line from user console ; RB1: CALL SUBKIL ;erase $$$.sub if present CALL SETUD ;set user and disk MVI A,CMDMPT ;print prompt CALL CONOUT MVI C,0AH ;read command line from user LXI D,MBUFF CALL BDOS ; IF CLEVEL3 ;if third command leNZ CB1 ;continue to end of command line CB2: MVI M,0 ;store ending LXI H,CIBUFF ;set command line ptr to 1st char SHLD CIBPTR RET ; ; Check for any char from user console (ret w/zero set if none) ; BREAK: PUSH D ;save de MVI C,6 ;direct console i/o MVI E,0FFH ;input mode CALL BDOSB ;get character (if any) POP D ;restore de JNZ UCASE ;we have something, caseify and return RET ; ; Get the requested user number from the command line and validate it. ; USRNUM: CALL NUMERR2 ;continue ERR1: CALL PRINT ;print '?' DB '?'+80H CALL SUBKIL ;terminate active $$$.sub if any JMP RESTRT ;restart cmd ; ; Check to see if DE points to delimiter; if so, ret w/zero flag set ; SDELM: LDAX D ORA A ;0=delimiter RZ CPI ' ' ;error if < JRC ERROR RZ ;=delimiter CPI '=' ;'='=delimiter RZ CPI '_' ;'_'=delimiter RZ CPI '.' ;'.'=delimiter RZ CPI ':' ;':'=delimiter RZ CPI ';' ;';'=delimiter RZ CPI '<' ;'<'=delimiter RZ CPI '>' ANER ;parse number and place in fcbfn LXI H,FCBFN+10 ;pt to end of token for conversion MVI B,11 ;11 chars max ; ; Check for suffix for hexadecimal number ; NUMS: MOV A,M ;get chars from end, searching for suffix DCX H ;back up CPI ' ' ;space? JRNZ NUMS1 ;check for suffix DJNZ NUMS ;count down JR NUM0 ;by default, process NUMS1: CPI NUMBASE ;check against base switch flag JRZ HNUM0 ; ; Process decimal number ; NUM0: LXI H,FCBFN ;pt to beginning of token LXI B,1100H ;c=JNZ NUM1 ;count down ; ; Return from number ; NUM2: MOV A,C ;get accumulated value RET ; ; Number error routine for space conservation ; NUMERR: JMP ERROR ;use error routine - this is relative pt ; ; Extract hexadecimal number from command line ; return with value in reg a; all registers may be affected ; HEXNUM: CALL SCANER ;parse number and place in fcbfn HNUM0: LXI H,FCBFN ;pt to token for conversion LXI D,0 ;de=accumulated value MVI B,11 ;b=char count HNUM1: MOV A,M ;get c   har CPI ' ' ;done? JRZ HNUM3 ;return if so CPI NUMBASE ;done if numbase suffix JRZ HNUM3 SUI '0' ;convert to binary JRC NUMERR ;return and done if error CPI 10 ;0-9? JRC HNUM2 SUI 7 ;a-f? CPI 10H ;error? JRNC NUMERR HNUM2: INX H ;pt to next char MOV C,A ;digit in c MOV A,D ;get accumulated value RLC ;exchange nybbles RLC RLC RLC ANI 0F0H ;mask out low nybble MOV D,A MOV A,E ;switch low-order nybbles RLC RLC RLC RLC MOV E,A ;high nybble of e=of dir entry CALL ADDAH ;pt to desired byte in dir entry MOV A,M ;get desired byte RET ; ; Check for specified drive and log it in if not default ; SLOGIN: XRA A ;set fcbdn for default drive STA FCBDN CALL COMLOG ;check drive RZ JR DLOG5 ;do login otherwise ; ; Check for specified drive and log in default drive if specified<>default ; DLOGIN: CALL COMLOG ;check drive RZ ;abort if same LDA TDRIVE ;log in default drive ; DLOG5: JMP LOGIN ; ; Routine common to both login  and zero flag is ; reset if '?' is in token ; ; Entry points: ; scaner - load token into first fcb ; scanx - load token into fcb pointed to by hl ; SCANER: LXI H,FCBDN ;point to fcbdn SCANX: XRA A ;set temporary drive number to default STA TEMPDR CALL ADVAN ;skip to non-blank or end of line SDED CIPTR ;set ptr to non-blank or end of line LDAX D ;end of line? ORA A ;0=yes JRZ SCAN2 SBI 'A'-1 ;convert possible drive spec to number MOV B,A ;store number (a:=0, b:=1, etc) i of question marks in fcb MVI B,8 ;max of 8 chars in file name CALL SCANF ;fill fcb file name ; ; Extract file type from possible filename.typ ; MVI B,3 ;prepare to extract type CPI '.' ;if (de) delimiter is a '.', we have a type JRNZ SCAN15 ;fill file type bytes with INX D ;pt to char in command line after '.' CALL SCANF ;fill fcb file type JR SCAN16 ;skip to next processing SCAN15: CALL SCANF4 ;space fill ; ; Fill in ex, s1, s2, and rc with zeroes ; SCAN16: MVI B,4 ;limiter ; SCANF: CALL SDELM ;done if delimiter encountered - fill JRZ SCANF4 INX H ;pt to next byte in fcbdn CPI '*' ;is (de) a wild card? JRNZ SCANF1 ;continue if not MVI M,'?' ;place '?' in fcbdn and don't advance de if so CALL SCQ ;scanner count question marks JR SCANF2 SCANF1: MOV M,A ;store filename char in fcbdn INX D ;pt to next char in command line CPI '?' ;check for question mark (wild) CZ SCQ ;scanner count question marks SCANF2: DJNZ SCANF ;decrement char cnew high of e, ; low nybble of e=new low of d ANI 0FH ;get new low of d ORA D ;mask in high of d MOV D,A ;new high byte in d MOV A,E ANI 0F0H ;mask out low of e ORA C ;mask in new low MOV E,A ;new low byte in e DJNZ HNUM1 ;count down ; ; Return from hexnum ; HNUM3: XCHG ;returned value in hl MOV A,L ;low-order byte in a RET ; ; Point to directory entry in tbuff whose offset is specified by a and c ; DIRPTR: LXI H,TBUFF ;pt to temp buffer ADD C ;pt to 1st byte routines; on exit, z set means abort ; COMLOG: TEMPDR EQU $+1 ;pointer for in-the-code modification MVI A,0 ;2nd byte (immediate arg) is tempdr ORA A ;0=no RZ DCR A ;compare it against default LXI H,TDRIVE CMP M RET ;abort if same ; ; 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 points to char at which to start scan; ; on output, CIBPTR points to char at which to continuen b INX D ;pt to next char LDAX D ;see if it is a colon (:) CPI ':' JRZ SCAN3 ;yes, we have a drive spec DCX D ;no, back up ptr to first non-blank char SCAN2: LDA TDRIVE ;set 1st byte of fcbdn as default drive MOV M,A JR SCAN4 SCAN3: MOV A,B ;we have a drive spec STA TEMPDR ;set temporary drive MOV M,B ;set 1st byte of fcbdn as specified drive INX D ;pt to byte after ':' ; ; Extract filename from possible filename.typ ; SCAN4: XRA A ;a=0 STA QMCNT ;init count of number4 bytes SCAN17: INX H ;pt to next byte in fcbdn MVI M,0 DJNZ SCAN17 ; ; Scan complete -- de pts to delimiter byte after token ; SDED CIBPTR ; ; Set zero flag to indicate presence of '?' in filename.typ ; LDA QMCNT ;get number of question marks ORA A ;set zero flag to indicate any '?' RET ; ; scanf -- scan token pted to by de for a max of b bytes; place it into ; file name field pted to by hl; expand and interpret wild cards of ; '*' and '?'; on exit, de pts to terminating deount until 8 elapsed SCANF3: CALL SDELM ;8 chars or more - skip until delimiter RZ ;zero flag set if delimiter found INX D ;pt to next char in command line JR SCANF3 ; ; Fill memory pointed to by hl with spaces for b bytes ; SCANF4: INX H ;pt to next byte in fcbdn MVI M,' ' ;fill filename part with DJNZ SCANF4 RET ; ; Increment question mark count for scanner ; this routine increments the count of the number of question marks in ; the current fcb entry ; SCQ: LDA QM   CNT ;get count INR A ;increment STA QMCNT ;put count RET ; ; CMDTBL (command table) scanner ; on return, hl pts to address of command if cmd-resident ; on return, zero flag set means cmd-resident command ; CMDSER: LXI H,CMDTBL ;pt to command table ; IF SECURE MVI C,NRCMDS LDA WHEEL ;see if non-restrcted CPI RESTRCT JRZ CMS1 ;pass if restrcted ENDIF ;secure ; MVI C,NCMNDS ;set command counter CMS1: LXI D,FCBFN ;pt to stored command name MVI B,NCHARS ;number of chars/c------------------------------------------------------------------- ; ; ZCMD resident commands ; ;Command: DIR ;Function: To display a directory of the files on disk ;Forms: ; DIR displays the dir files ; DIR S displays the sys files ; DIR A display both dir and sys files ; IF INDIR ; DIR: MVI A,80H ;set system bit examination PUSH PSW CALL SCANER ;extract possible d:filename.typ token CALL SLOGIN ;log in drive if necessary LXI H,FCBFN ;make fcb wild (all '?') if SW DIR2: POP PSW ;get flag DIR2A: ;drop into dirpr to print directory ; then restart cmd ENDIF ;INDIR ; ; directory print routine; on entry, msb of a is 1 (80h) if system files ; excluded. this routine is also used by era. ; DIRPR: MOV D,A ;store system flag in d MVI E,0 ;set column counter to zero PUSH D ;save column counter (e) and system flag (d) MOV A,B ;sys only specifier STA SYSTST CALL SEARF ;search for specified file (first occurrance) CZ PRNNF ;print no file mPOP D ;get entry count (= counter) MOV A,E ;add 1 to it INR E PUSH D ;save it ; TWOPOK EQU $+1 ;for apple patching ANI NUMCOL-1 ;output if 4 entries printed in line ; PUSH PSW JRNZ DIR4 CALL CRLF ;new line JR DIR5 DIR4: CALL PRINT ; IF WIDE DB ' ' ;2 spaces DB FENCE ;then fence char DB ' ',' '+80H ;then 2 more spaces ENDIF ; IF NOT WIDE DB ' ' ;space DB FENCE ;then fence char DB ' '+80H ;then space ENDIF ; DIR5: MVI B,01H ;pt to 1st byte of  filename.typ? JRNC DIR9 ;continue if so CPI 09H ;end if filename only? JRNZ DIR6 ;print typ if so MVI A,'.' ;print dot between file name and type CALL CONOUT JR DIR6 DIR9: POP PSW DIR10: CALL BREAK ;check for abort JRNZ DIR11 CALL SEARN ;search for next file JR DIR3 ;continue DIR11: POP D ;restore stack RET ; ; Fill fcb @hl with '?' ; FILLQ: MVI B,11 ;number of chars in fn & ft FQLP: MVI M,'?' ;store '?' INX H DJNZ FQLP RET ; ;Command: ERA ;Function: Erase filommand (8 max) CMS2: LDAX D ;compare against table entry CMP M JRNZ CMS3 ;no match INX D ;pt to next char INX H DJNZ CMS2 ;count down LDAX D ;next char in input command must be CPI ' ' JRNZ CMS4 RET ;command is cmd-resident (zero flag set) CMS3: INX H ;skip to next command table entry DJNZ CMS3 CMS4: INX H ;skip address INX H DCR C ;decrement table entry number JRNZ CMS1 INR C ;clear zero flag RET ;command is disk-resident (zero flag clear) ; ;-----------no filename.typ MOV A,M ;get first char of filename.typ CPI ' ' ;if , all wild CZ FILLQ CALL ADVAN ;look at next input char MVI B,0 ;sys token default JRZ DIR2 ;jump; there isn't one CPI SYSFLG ;system flag specifier? JRZ GOTSYS ;got system specifier CPI SOFLG ;sys only? JRNZ DIR2 MVI B,80H ;flag sys only GOTSYS: INX D SDED CIBPTR CPI SOFLG ;sys only spec? JRZ DIR2 ;then leave bit spec unchagned POP PSW ;get flag XRA A ;set no system bit examination PUSH Psg;reg a not changed ; ; entry selection loop; on entry, a=offset from searf or searn ; DIR3: JRZ DIR11 ;done if zero flag set DCR A ;adjust to returned value RRC ;convert number to offset into tbuff RRC RRC ANI 60H MOV C,A ;offset into tbuff in c (c=offset to entry) MVI A,10 ;add 10 to pt to system file attribute bit CALL DIRPTR POP D ;get system bit mask from d PUSH D ANA D ;mask for system bit SYSTST EQU $+1 ;pointer to in-the-code buffer systst CPI 0 JRNZ DIR10 file name DIR6: MOV A,B ;a=offset CALL DIRPTR ;hl now pts to 1st byte of file name ANI 7FH ;mask out msb CPI ' ' ;no file name? JRNZ DIR8 ;print file name if present POP PSW PUSH PSW CPI 03H JRNZ DIR7 MVI A,09H ;pt to 1st byte of file type CALL DIRPTR ;hl now pts to 1st byte of file type ANI 7FH ;mask out msb CPI ' ' ;no file type? JRZ DIR9 ;continue if so DIR7: MVI A,' ' ;output DIR8: CALL CONOUT ;print char INR B ;incr char count MOV A,B CPI 12 ;end ofes ;Forms: ; ERA erase specified files and print their names ; IF NOT RAS ;not for remote-access system ; ERA: CALL SCANER ;parse file specification CPI 11 ;all wild (all files = 11 '?')? JRNZ ERA1 ;if not, then do erases CALL PRINTC DB 'All','?'+80H CALL CONIN ;get reply CPI 'Y' ;yes? ERARJ: JNZ RESTRT ;restart cmd if not CALL CRLF ;new line ERA1: CALL SLOGIN ;log in selected disk if any XRA A ;print all files (examine system bit) MOV B,A ;no sys-only opt to dirp   r CALL DIRPR ;print directory of erased files ; IF EPRMPT ; ; query user after files are seen, and give one last chance to back out ; MOV A,E ;how many files displayed? ORA A JZ RESTRT ;if none, don't ask or delete CALL PRINTC ;prompt DB 'Ok','?'+80H CALL CONIN ;get reply folded CPI 'Y' ;yes? JRNZ ERARJ ;get out if not ENDIF ;eprmpt ; LXI D,FCBDN ;delete file(s) specified JMP DELETE ;restart cmd after delete ; ENDIF ;ras ; ;Command: LIST ;Function: Print out lag ENDIF ;intype and inlist ; IF INTYPE CALL SCANER ;extract filename.typ token JNZ ERROR ;error if any question marks CALL ADVAN ;get pgdflg if it's there STA PGFLG ;save it as a flag JRZ NOSLAS ;jump if input ended INX D ;put new buf pointer XCHG SHLD CIBPTR NOSLAS: CALL SLOGIN ;log in selected disk if any CALL OPENF ;open selected file JZ TYPE4 ;abort if error CALL CRLF ;new line MVI A,NLINES-1 ;set line count STA PAGCNT LXI H,CHRCNT ;set char position/count: or lst: device with tabulation ; IF WSTYPE ;wordstar hyphen check CPI 1FH ;is char wordstar eol hyphen? JRNZ NOHYPH ;pass if not MVI A,'-' ;yes, make it a real hyphen NOHYPH: ENDIF ;wstype ; CPI ' ' ;is char control code? JRNC PRT ;go bop char count and print if not CPI CR ;is char a cr? JRZ YESCR ;if so, go zero b then print CPI FFEED ;form feed? JRZ YESCR ;many printers return carriage on this CPI LF ;line feed? JRZ NOBOP ;print, but don't bop b CPI BEL ;bell A ;no error? RZ ;restart cmd TYPE4: JMP ERRLOG ENDIF ;cmdtyp ; ;Command: SAVE ;Function: To save the contents of the TPA onto disk as a file ;Forms: ; SAVE ; save specified number of pages (start at 100h) ; from tpa into specified file; is in dec ; SAVE S ; like save above, but numeric argument specifies ; number of sectors rather than pages ; IF NOT RAS ;not for remote-access system ; SAVE: CALLE0: SDED CIBPTR ;set ptr to bad token or after good token LXI D,TPA ;pt to start of save area (tpa) SAVE1: MOV A,H ;done with save? ORA L ;hl=0 if so JRZ SAVE2 DCX H ;count down on sectors PUSH H ;save ptr to block to save LXI H,128 ;128 bytes per sector DAD D ;pt to next sector PUSH H ;save on stack CALL DMASET ;set dma address for write (address in de) LXI D,FCBDN ;write sector MVI C,15H ;bdos write sector CALL BDOSB ;save bc POP D ;get ptr to next sector in de Pspecified file on the lst: device ;Forms: ; LIST print file (no paging) ; IF INLIST AND INTYPE LIST: MVI A,0FFh ;turn on printer flag JR TYPE0 ENDIF ;inlist and intype ; ;Command: TYPE ;Function: Print out specified file on the con: device ;Forms: ; TYPE print file ; TYPE P print file with paging flag ; IF INTYPE TYPE: ENDIF ;intype ; IF INTYPE AND INLIST XRA A ;turn off printer flag ; ; Entry point for ZCMD list function (list) ; TYPE0: STA PRFLG ;set f MVI M,0FFH ;empty line MVI B,0 ;set tab char counter TYPE1: LXI H,CHRCNT ;pt to char position/count MOV A,M ;end of buffer? CPI 80H JRC TYPE2 PUSH H ;read next block CALL READF POP H JRNZ TYPE3 ;error? XRA A ;reset count MOV M,A TYPE2: INR M ;increment char count LXI H,TBUFF ;pt to buffer CALL ADDAH ;compute address of next char from offset MOV A,M ;get next char ANI 7FH ;mask out msb CPI 1AH ;end of file (^Z)? RZ ;restart cmd if so ; ; Output char to con? JRZ NOBOP ;go ring but don't bop b CPI TAB ;tab? JRNZ TYPE2L ;if not, no other choices, toss control LTAB: MVI A,' ' ; CALL LCOUT INR B ;incr pos count MOV A,B ANI 7 JRNZ LTAB JR TYPE2L ; YESCR: MVI B,0FFH ;combine with inc below to get zero ; PRT: INR B ;increment char count NOBOP: CALL LCOUT ;print it ; ; Continue processing ; TYPE2L: CALL BREAK ;check for abort JRZ TYPE1 ;continue if no char CPI 'C'-'@' ;^c? RZ ;restart if so JR TYPE1 TYPE3: DCR NUMBER ;extract number from command line MOV L,A ;hl=page count MVI H,0 PUSH H ;save page count CALL EXTEST ;test for existence of file and abort if so MVI C,16H ;bdos make file CALL GRBDOS POP H ;get page count JRZ SAVE3 ;error? XRA A ;set record count field of new file's fcb STA FCBCR CALL ADVAN ;look for 's' for sector option INX D ;pt to after 's' token CPI SECTFLG JRZ SAVE0 DCX D ;no 's' token, so back up DAD H ;double it for hl=sector (128 bytes) count SAVOP H ;get sector count JRZ SAVE1 ;continue if no write error JR PRNLE ;go print error and reset dma SAVE2: LXI D,FCBDN ;close saved file CALL CLOSE INR A ;error? JRNZ SAVE3 ;pass if ok ; ENDIF ;not ras ; ; prnle is also used by memload for tpa full error ; PRNLE: CALL PRINTC ;disk or mem full DB 'Ful','l'+80H ; SAVE3: JMP DEFDMA ;set dma to 0080 and restart cmd ; or return to mlerr ; IF NOT RAS ; ; Test file in FCB for existence, ask user to delete if so, and abort    if he ; choses not to. ; EXTEST: CALL SCANER ;extract file name JNZ ERROR ;'?' is not permitted CALL SLOGIN ;log in selected disk CALL SEARF ;look for specified file LXI D,FCBDN ;pt to file fcb RZ ;ok if not found PUSH D ;save ptr to fcb CALL PRINTC DB 'Erase','?'+80H CALL CONIN ;get response POP D ;get ptr to fcb CPI 'Y' ;key on yes JNZ RSTCMD ;restart if no, sp reset eventually PUSH D ;save ptr to fcb CALL DELETE ;delete file POP D ;get ptr to fcb RET ;fter '=' in hl INX H SHLD CIBPTR ;save ptr to old file name CALL SCANER ;extract filename.typ token JRNZ REN4 ;error if any '?' POP PSW ;get old default drive MOV B,A ;save it LXI H,TEMPDR ;compare it against current default drive MOV A,M ;match? ORA A JRZ REN2 CMP B ;check for drive error MOV M,B JRNZ REN4 REN2: MOV M,B XRA A STA FCBDN ;set default drive LXI D,FCBDN ;rename file MVI C,17H ;bdos rename fct CALL GRBDOS RNZ REN3: CALL PRNNF ;print no file msgode, this will select the second ; user area to check for programs (normally user 15). ; ;Forms: ; DFU select default user number -- is in decimal ; IF NOT RAS ;not for remote-access system DFU: CALL USRNUM ;get user number STA DFUSR ;put it away JR RSTJMP ;restart cmd (no default login) ENDIF ;not ras ; ;Command: JUMP ;Function: To call the program (subroutine) at the specified address ; without loading from disk. ;Forms: ; JUMP call at ; is in hex ays to tpa JR CALLPROG ;perform call ; ENDIF ;end of go for ras ; ;Command: COM file processing ;Function: To load the specified com file from disk and execute it ;Forms: ; ; COM: LDA FCBFN ;any command? CPI ' ' ;' ' means command was 'd:' to switch JRNZ COM1 ;not , so must be transient or error LDA TEMPDR ;look for drive spec ORA A ;if zero, just blank JZ RCMDNL DCR A ;adjust for log in STA TDRIVE ;set default drive CALL LOGIN ;log in drive CALL SETUD ecution CALL MEMLOAD ;load memory with file specified in cmd line ; (no return if error or too big) POP H ;get execution address ; ; CALLPROG is the entry point for the execution of the loaded ; program. on entry to this routine, hl must contain the execution ; address of the program (subroutine) to execute ; CALLPROG: SHLD EXECADR ;perform in-line code modification CALL DLOGIN ;log in default drive CALL SCANER ;search command line for next token LXI H,TEMPDR ;save ptr to dri ENDIF ;ras ; ;Command: REN ;Function: To change the name of an existing file ;Forms: ; REN = ; IF NOT RAS ;not for remote-access system ; REN: CALL EXTEST ;test for file existence and return ; if file doesn't exist; abort if it does LDA TEMPDR ;save current default disk PUSH PSW ;save on stack REN0: LXI H,FCBDN ;save new file name LXI D,FCBDM LXI B,16 ;16 bytes LDIR CALL ADVAN ;advance cibptr CPI '=' ;'=' ok JRNZ REN4 REN1: XCHG ;pt to char a REN4: JMP ERRLOG ; ENDIF ;ras ; ;Command: USER ;Function: Change current user number ;Forms: ; USER select specified user number; is in dec ; IF INUSER ;if drive/user code ok... USER: CALL USRNUM ;extract user number from command line MOV E,A ;place user number in e SUSER: CALL SETUSR ;set specified user ENDIF ;inuser RSTJMP: JMP RCMDNL ;restart cmd ; ;Command: DFU ;Function: Set the default user number for the command/file scanner ; Note: When under secure m ; IF NOT RAS ;not for remote-access system ; JUMP: CALL HEXNUM ;get load address in hl JR CALLPROG ;perform call ; ENDIF ;ras ; ;Command: GO ;Function: To call the program in the tpa without loading ; from disk. same as jump 100h, but much ; more convenient, especially when used with ; parameters for programs like stat. also can be ; allowed on remote-access systems with no problems. ; ;Form: ; GO ; IF NOT RAS ;only if ras ; GO: LXI H,TPA ;alw;set drive with current user area ; IF INUSER ;drive/user hackery ok? CALL USRNUM ;get user #, if any MOV E,A ;get it ready for bdos LDA FCBFN ;see if # specified CPI ' ' JRNZ SUSER ;select if wanted ENDIF ;inuser ; JMP RCMDNL ;restart cmd COM1: LDA FCBFT ;file type must be blank CPI ' ' JNZ ERROR LXI H,COMMSG ;place default file type (com) into fcb LXI D,FCBFT ;copy into file type LXI B,3 ;3 bytes LDIR LXI H,TPA ;set execution/load address PUSH H ;save for exve spec PUSH H MOV A,M ;set drive spec STA FCBDN LXI H,FCBDN+10H ;pt to 2nd file name CALL SCANX ;scan for it and load it into fcbdn+16 POP H ;set up drive specs MOV A,M STA FCBDM XRA A STA FCBCR LXI D,TFCB ;copy to default fcb LXI H,FCBDN ;from fcbdn LXI B,33 ;set up default fcb LDIR LXI H,CIBUFF-1 COM4: INX H MOV A,M ;skip to end of 2nd file name ORA A ;end of line? JRZ COM5 CPI ' ' ;end of token? JRNZ COM4 ; ; Load command line into TBUFF ; COM5: MVI    B,-1 ;set char count LXI D,TBUFF ;pt to char pos DCX H COM6: INR B ;incr char count INX H ;pt to next INX D MOV A,M ;copy command line to tbuff STAX D ORA A ;done if zero JRNZ COM6 ; ; Run loaded transient program ; COM7: MOV A,B ;save char count STA TBUFF CALL CRLF ;new line CALL DEFDMA ;set dma to 0080 CALL SETUD ;set user/disk ; ; Execution (call) of program (subroutine) occurs here ; EXECADR EQU $+1 ;change address for in-line code modification CALL TPA ;carestore address JNZ ERROR ;must be unambiguous ; ; fall thru to memload ; ENDIF ;ras ; ; Load memory with the file whose name is specified in the command line ; on input, hl contains starting address to load. ; ; Exit bact to caller if no error. If the COM file is too big, or another ; error, then exit directly to MLERR. ; MEMLOAD: SHLD LOADADR ;set load address CALL GETUSR ;get current user number STA TMPUSR ;save it for later STA TSELUSR ;temp user to select ; ; MLA is a reund, or not in wheel mode, ; then search on current drive under user area "DEFUSR." If file still ; hasn't been found, then do the same thing again except on drive A: ; DFLAG EQU $+1 ;mark in-the-code variable MVI A,0 ;have we checked this drive already? ORA A JRNZ MLA0 ;pass if so to go to drive a: LDA WHEEL ;restricted progs allowed? CPI RESTRCT JRZ MLA00 ;pass if not PUSH B ;push bc LDA DFUSR ;load default user MOV B,A ;put it in b LDA TSELUSR ;check curr user DFUSR EQU r TSELUSR EQU $+1 ;mark in-the-code variable CPI DEFUSR ;check for the user area.. JRZ MLA0 ;..equal default, and jump if so ENDIF ;not secure ; STA TSELUSR ;put down new one MOV E,A CALL SETUSR ;go set new user number JR MLA ;and try again ; ; Error routine to select drive a: if default was originally selected ; MLA0: LXI H,TEMPDR ;get drive from current command XRA A ;a=0 ; IF SECURE STA DFLAG ;allow a: search ENDIF ;secure ; ORA M JNZ MLERR ;error if already dLL READ POP H ;get address of next sector JRNZ ML3 ;read error or eof? LXI D,128 ;move 128 bytes per sector DAD D ;pt to next sector in hl JR ML2 ; ML3: DCR A ;load complete JZ RESETUSR ;if zero, ok, go reset correct user # ; on way out, else fall thru to prnle ; ; TPA full ; ML4: CALL PRNLE ;print msg and reset def dma ; ; Transient load error ; MLERR: ;note that there is an extra return address ;on the stack. it will be tossed when error ;exits to restrt, whll transient CALL DEFDMA ;set dma to 0080, in case ;prog changed it on us CALL SETU0D ;set user 0/disk CALL LOGIN ;login disk JMP RESTRT ;restart cmd ; ;Command: GET ;Function: To load the specified file from disk to the specified address ;Forms: ; GET load the specified file at the specified page; ; is in hex ; IF NOT RAS ;not for remote-access system ; GET: CALL HEXNUM ;get load address in hl PUSH H ;save address CALL SCANER ;get file name POP H ;entry point for a non-standard cp/m modification ; this is the return point for when the .COM (or GET) file is not found the ; first time, drive A: is selected for a second attempt ; MLA: CALL SLOGIN ;log in specified drive if any CALL OPENF ;open command.com file JRNZ MLA1 ;file found - load it ; IF SECURE ; ; If SECURE is enabled, search the current drive, current user, then ; if in wheel mode, search under last user set by dfu (set to "RESUSR" ; on warm boot) on current drive. If not fo$+1 ;default user location CPI RESUSR ;restricted user? MOV A,B ;assume not POP B ;restore bc JRNZ SETTSE ;go try if not MLA00: ;ss if not TSELUSR EQU $+1 ;mark in-the-code variable MVI A,0 ;get curr user SUI DEFUSR ;is it unrestricted com area? JRZ MLA0 ;no more choices if so STA DFLAG ;make dflag non-zero if not MVI A,DEFUSR ; and try unrestricted com area SETTSE: ENDIF ;secure ; IF NOT SECURE DFUSR EQU $+1 ;mark in-the-code variable MVI A,DEFUSR ;get default useisk a: MVI M,1 ;select drive a: ; IF NOT SECURE JR MLA ENDIF ;not secure ; IF SECURE LDA TMPUSR ;go to 'current' user code JR SETTSE ENDIF ;secure ; ; File found -- proceed with load ; MLA1: LOADADR EQU $+1 LXI H,TPA ML2: MVI A,ENTRY/256-1 ;get high-order adr of just below cmd CMP H ;are we going to overwrite the cmd? JRC ML4 ;error if so PUSH H ;save address of next sector XCHG ;... in de CALL DMASET ;set dma address for load LXI D,FCBDN ;read next sector CAich reloads sp. CALL RESETUSR ;reset current user number ; reset must be done before login ERRLOG: CALL DLOGIN ;log in default disk JMP ERROR ;flag error ; ;PASS: Enable wheel mode. ;NORM: Disable wheel mode. ; ; Type PASS to CP/M prompt to enter wheel mode. ; This code can be replaced with PST's PASS.ASM which gives many ; nice little options like no keyboard echo, etc. ; IF INPASS ;we want to use this code, not pass.com PASS: LXI H,PASSWD ;set up pointers LXI    D,CIBUFF+NCHARS+1 MVI B,PASEND-PASSWD ;b= length CKPASS: LDAX D ;trial pw to a CMP M ;check for match JNZ COM ;nope.. look for pass.com INX H ;increment counter INX D DJNZ CKPASS ;continue if more MVI A,NOT RESTRCT ;wheel = not restrct PWOUT: STA WHEEL JMP RESTRT ; NORM: MVI A,RESTRCT JR PWOUT ; PASSWD: DB 'YOURPW' ;your password PASEND: EQU $ ;end of password ; ENDIF ;inpass ; END ; ; Pass - Command to enable priviledged use of a ZCMD system ; running under secure mode. ; By Paul S. Traina -- OxGate Node 001 Sysop ; (author of ZCMD's "secure" section) ; Version 2.2 - 4/13/83 ; ; To run pass do the following: ; A>PASS - To enable wheel mode ; A>PASS - To enable wheel mode without ; Password: any echo of password ; A>PASS - - To disable wheel mode manually ; ; Thanks to Don Brown for MAXUSR/MAXDRV set/reset idea & codeLUSR EQU 15 ;maxusr in wheel mode WHLDRV EQU 2 ;maxdrv in wheel mode ; ORG BASE+100h ; SELECT: LDA FCB+1 ;see what we are supposed to do CPI ' ' ;don't echo pasword (someone looking over JZ GETPASS ;your shoulder?) CPI '-' ;disable wheel mode (become humble again) JZ DISABLE ; ; No, we have a JCL, so let's read it in... ; COMPARE: LXI H,PASSWD ;set up all the pointers LXI D,FCB+1 ;location of password buffer MVI B,PWEND-PASSWD ;number of characters of real password CKPASS: LDA,MAXUSR ;Store UnPriviledged MAXUSR MVI C,MAXDRV ;Store UnPriviledged MAXDRV CALL INSTALL ;..Deinstall Priviledges for Bye ENDIF ; XRA A ;disable wheel flag STA WHEEL RET ;soft-return to CCP ; GETPASS: MVI C,9 LXI D,PMSG CALL BDOS LXI H,FCB+1 ;ok, use the fcb as a buffer GETLOOP: PUSH H ;save HL LOOP1: MVI C,6 ;use direct console i/o MVI E,0FFH ;input a character CALL BDOS ;get character into A ORA A ;set flags JZ LOOP1 ;no character found, try again POP H ; ;Point to maxdrv MOV M,C ;Assign new maxdrv for bye RET ; PMSG: DB 'Password? $' PASSWD: DB 'YOURPW' ;Password shouldn't be more than 8 chars ;or somethings may die exotically. PWEND: ; END nt to cold boot vector DCX H ;Point to high byte MOV D,M ;..Store in D DCX H ;Point to low byte MOV E,M ;..Store in E LXI H,6 ;Maxusr bytes above cold boot DAD D ;Add HL & DE, point to maxusr MOV M,A ;Assign new maxusr for bye INX H ry point for a non-standard cp/m modification ; this is the return point for when the .COM (or GET) file is not found the ;pe.. look for pass.com INX H ;increment counter INX D DJNZ CKPASS ;continue if more MVI A,NOT RESTRCT ;wheel = not restrct PWOUT: STA WHEEL JMP RESTRT ; NORM: MVI A,RESTRCT JR PWOUT ; PASSWD: DB 'YOURPW' ;your password PASEND: EQU $ ;end of password ; ENDIF ;inpass ; END . ; FALSE EQU 0 TRUE EQU NOT FALSE CR EQU 13 ;termination character PSTRING EQU 9 ;BDOS Print a string ENABLE EQU 0FFh ;this is poked into WHEEL BASE EQU 0000h ;set to 4200h for trs80/heath cp/m BDOS EQU BASE+05h ;bdos location WHEEL EQU BASE+3Eh ;location of wheel byte FCB EQU BASE+5Ch ;file control block+1 ; VERBOSE EQU FALSE ;true if let the guy know he blew it or made it BYE EQU TRUE ;true if running ByeII MAXUSR EQU 9 ;maxusr in normal mode MAXDRV EQU 2 ;maxdrv in normal mode WHAX D ;trial password to A CMP M ;check for a match RNZ ;return to CCP (beware of skewed stacks) INX H ;HL=HL+1 INX D ;DE=DE+1 DCR B ;B=B-1 JNZ CKPASS ;if B>0 then CKPASS ; IF BYE MVI A,WHLUSR ;Store priviledged MAXUSR MVI C,WHLDRV ;Store priviledged MAXDRV CALL INSTALL ;Install priviledges for bye ENDIF ; MVI A,ENABLE ;Set enable flag STA WHEEL RET ;return to CCP (watch stack or else...) ; ; Disable wheel mode, and return to normal mode ; DISABLE: IF BYE MVI restore HL ANI 95 ;lowercase to uppercase (indiscriminate but ;effective) CPI CR ;is it a ? JZ COMPARE MOV M,A ;store character in fcb INX H ;increment pointers JMP GETLOOP ;loop until we get a ; INSTALL: LHLD 0001h ;Point to cold boot vector DCX H ;Point to high byte MOV D,M ;..Store in D DCX H ;Point to low byte MOV E,M ;..Store in E LXI H,6 ;Maxusr bytes above cold boot DAD D ;Add HL & DE, point to maxusr MOV M,A ;Assign new maxusr for bye INX H    WHAT IS FAST2 AND HOW DOES IT WORK? ----------------------------------- What is FAST2? It is a new transient program for the CP/M (*) disk operating system. It was originally written by by Roger van Valzpah and released by the CP/M user group as FAST. This version was modified by David Bennett of the Alfred Hospital, Melbourne to be compatible with CP/M version 2.0. FAST2 is used in conjunction with other transients to speed up their execution. Of course, nothing bute directory) are held in a buffer, eliminating the need to seek to read them. Secondly, disk accesses are grouped together in time to reduce the amount of time lost to rotational latency and head load delay. HOW TO USE FAST2 ---------------- The normal CP/M command to assemble a file with the name MUMBLE.ASM is: A>ASM MUMBLE To perform the same function under FAST2, simply type: A>FAST2 ASM MUMBLE Thus, in its simplest form, FAST2 can be used as a prefi on your terminal: A>FAST2 ASM MUMBLE Alfred Hospital FAST 2.01 CP/M ASSEMBLER - VER 1.4 1234 056H USE FACTOR END OF ASSEMBLY FAST terminated A> Where N.NN is the version number of FAST2 that you are using. COMMAND LINE OPTIONS -------------------- The buffering action of FAST2 may be altered with the use of command line options. This is accomplished by following the FAST2 command with an option string enclosed in square brackets (r, more buffering means more memory usage. The type of buffering selected should be tailored to the disk usage patterns of the transient being executed. For instance, write buffering will offer no speed improvement when a transient only reads the disk. One thing that FAST2 must know is which disk drive is to be buffered. This is communicated to FAST2 simply by using the single letter name of the desired drive (e.g. "A" for disk drive A). As a conveniencAST2 by a single letter in the option string. The letter is simply the first letter of the word which describes the type of buffering (capitalized above). The operation and application of each mode will be discussed below. Thus, a typical FAST2 command line might look like this: B>FAST2 [ASWBSR] ASM MUMBLE.BAA In this example, the .ASM source file is on drive B so read and seek buffering have been specified for that drive. The A drive, on the other hand, is to a hardware change can increase the rate at which your CPU executes instructions. But, most transients are "disk bound", that is, they spend a large percentage of their total execution time just waiting for the information they need from the disk. FAST2 uses this fact to increase execution speed by reducing the time spent waiting for the disks. This is accomplished by using two different types of buffering. Firstly, portions of the disk which are frequently accessed (thx to any normal CP/M command. This will load FAST2 which will link itself to your operating system and allocate its disk buffers. Then the transient ASM.COM is loaded and given control. The fact that FAST2 is in the system is totally transparent to the transient, except for the reduced memory size. Messages will be printed just before and after the transient is executed to indicate that FAST2 is in control. After execution, you should see something like this"[" and "]"). A valid option string must consist of a drive specification followed by one or more buffering mode specifications. This group may be repeated for buffering of multiple drives. Examples of typical option strings will be given below. Explicitly specifying the buffering mode is desirable to reach the best trade-off between speed of execution and memory usage. In general, as more buffering is used, execution speed will increase. Howevee, the current default drive may be specified with the commercial at sign ("@"). The second thing which FAST2 must know is which mode of buffering is to be used. FAST2 supports three different buffering modes. Each mode may be used individually or in combination with other modes to offer the fastest execution. The three modes available are: Seek buffering Read buffering Write buffering Yes (all of the above) The type of buffering desired is communicated to F receive the result of the assembly (the .HEX and .PRN files), so it gets write and seek buffering. BUFFERING MODE DESCRIPTIONS --------------------------- Seek buffering causes the disk directory to be read into a buffer the first time a drive is accessed. From then on, all reads from and writes to the directory can be carried out without moving the disk head from its current position. Thus, transients which access the directory frequently will be sped up considera   bly by seek buffering. Transients which fall into this category are those which deal with many different files simultaneously, perform operations with temporary files and rename them, read or write large (more than 16K) files, and those which perform random disk I/O. In particular, ASM.COM, MAC.COM, PIP.COM, and ED.COM are examples of such transients. Read buffering causes an entire track from the disk to be read into a buffer the first time any sector is read froow down transients which read files in a random access mode. Fortunatlly, the vast majority of CP/M transients read the disk sequentially. Examples of such transients are ASM.COM, MAC.COM, PIP.COM, and BASIC-E.COM (if the BASIC program doesn't do random I/O!!). With write buffering, sectors that are to be written to disk are held in a buffer for a time, instead of writing them immediately. Sectors for any given track are held in the buffer until CP/M tries to write to a traOM. DEFAULT PHILOSOPHY ------------------ Two of the qualities generally associated with a good program are versatility and ease of use. FAST2 has been written with these two qualities in mind as the primary design goals. Many times, however, these two goals can be contradictory. A versatile program is one which is capable of a wide variety of tasks or one that fits many different FAST2 Default philosophy applications. This usually means a program with many user selectableability to specify options explicitly, while the default mechanism frees the user from this tedium much of the time. In short, defaults allow versatility and ease of use to peacefully co-exist in the same program. .cp 3 DEFAULT MECHANISMS IN FAST2 --------------------------- There are two levels of defaults built into FAST2. The first default mechanism is used when either the drive or buffering mode is omitted from an option string. If a drive name is not given, the default dr transient with no buffering, FAST2 uses a default option string to specify the buffering used. This string is [@RS], giving the user read and seek buffering on the default drive when no option string is present on the command line. The user may, at his option, alter the default option to one which is more suitable for his typical uses. For instance, if you typically use FAST2 for assembling and don't have to worry about running out of memory, a good default string woulm that track. This increases execution speed because CP/M typically reads most of one track before going on to the next one. Additionally, the time required to read a whole track is a fairly small percentage increase over the time required to read a single sector. The net effect is that less time is spent waiting for the rotational latency of the disk. This mode of buffering is most beneficial to transients which read disk files sequentially. As a matter of fact, it may slck that is not buffered. When it is time to change tracks, only those sectors which were changed are actually written before clearing the buffers to make room for the new data. This improves execution speed for the same reasons that read buffering does, i.e. a whole track can be written in about the time it takes to write a single sector. Transients which benifit from this type of buffering typically write to disk sequentially. Examples include ASM.COM, MAC.COM, and ED.C options. Forcing the user to type the same frequently used options every time a program is invoked or committing him to remember a long list of options is contradictory to the goal of ease of use. This conflict is resolved by the use of default mechanisms within FAST2. A default mechanism is simply a rule that can be used to make assumptions about the user's wishes when he has not stated them explicitly. Thus, versatility has been retained by allowing the user the ive for CP/M is used (this is equivalent to "@"). If no buffering mode is specified, read and seek buffering are used. Thus, the following two commands would be equivalent. B>FAST2 [BRW] LOAD MUMBLE B>FAST2 [RW] LOAD MUMBLE And so would the following two commands. A>FAST2 [BRS] PIP B:THIS=B:THAT A>FAST2 [B] PIP B:THIS=B:THAT The second default mechanism comes into play when no option string is given on the command line. Instead of executing the d be [@RWS]. Conversely, if you are running in a small memory system, a good choice would be to change the default option string. HOW TO CHANGE THE DEFAULT OPTION STRING --------------------------------------- The default string is stored in FAST2 at address 0130H. Thus, to change the option string, use SID or DDT to change the existing string. Assuming you have SID this is very easy: A>SID FAST2.COM SID VERS 1.4 NEXT PC END 0A00 0100 94FF #S130    0130 5B "[@RWS] 0136 20 . #^C A>SAVE 9 FASTX.COM If you do not have SID, you'll have to use DDT and figure out the hex for the ASCII string you wish to patch in. Then use the Substitute command to patch the file as above. In either case, test the patched file before killing the old FAST2.COM and renaming the new file to FAST2.COM. .cp 3 WARNINGS N-E-V-E-R CHANGE DISKS WHILE EXECUTING UNDER FAST2!!! And in case you missed that one I'll say it again.. will NOT get the warning message "Bdos error on A: R/O" if you forget and change disks without booting. Instead you will get wild and unpredictable effects possibly including destroying your disk directory. This also gives rise to a minor incompatibility with any transients which use the BDOS reset function (BDOS call 13). This function is used in transients which allow the user to change disks without rebooting. Some examples are MBASIC, ouble with such programs, FAST2 watches out for any requests for user input. When such a request is detected, FAST2 immediately writes all modified blocks back to disk. While this gives some protection against lost data, it fails with programs such as Wordstar which monitor console status and only request input after a key is struck. Again, DON'T change disks. COMPATIBILITY ------------- FAST2 is fully compatible with the following transients and can be expected ot be able to detect. If the user is able to guard against this occurrence, he may use FAST2 with these transients and expect a significant reduction in execution time. In particular, the improvement in the speed of PIP is little short of unbelievable. CP/M utilities:PIP, DDT, SID, ZSID Editors: ED, WORDMASTER, WORDSTAR, ED-80 Interpreters: MBASIC, RUN, CRUN, CRUN2, PRUN Other: SELECTOR, ADVENTURE FAST2 is fully compatible with the followingessed sequentially, especially if large files are read from beginning to end. The following examples indicate some of the results which can be expected using standard single-sided single- density 8 inch diskettes. A>FAST2 [AYBY] PIP B:=*.* This command can be expected to copy a 241k diskette full of data, file by file, in about 80 seconds. With verification, it takes perhaps 100 seconds. A>FAST2 [ARBY] WS Use this command on your Wordstar utility di. YOU MUST ********** N-E-V-E-R N-O-T E-V-E-R ********** CHANGE DISKS WHILE EXECUTING UNDER FAST2!!! (not even if you think you know what you are doing) Wait until you see the message "FAST2 terminated" before even thinking about switching disks. A rather nasty side effect of seek buffering is that it disables the disk change detection mechanism built into CP/M. This means that youCBASIC, WORDSTAR, and others. Fortunately they only this BDOS function when an explicit command is used to permit changing disks. FAST2 is compatible with transients of this sort as long as no attempt is made to change disks. One way to avoid trouble is to avoid using FAST2 with any transient which requires user input. Any such transient, by waiting for your reply, would leave you with the opportunity to change disks. To minimise the risk of your running into trto provide a significant reduction in execution time. CP/M utilities:LOAD, SUBMIT, DUMP, MAC Compilers: ASM, MAC, RMAC, M80, FORTRAN, F80, COBOL-80, PL/I, etc. FAST2 is fully compatible with the following transients, but due to the fact that they require user input, some caution should be exercised when they are used with FAST2. As mentioned above, stopping for input gives the user the chance to inadvertently change disks which CP/M would n transients, but due to the way in which they access the disk, little or no speed improvement can be expected. Special utilities: SYSGEN, MOVCPM, FAST2, COPY Due to an unfortunate memory dependency, STAT (version 1.4) does not correctly report the number of bytes remaining on the disk when it is executed under FAST2. This is no great loss because FAST2 can do little to speed up the execution of STAT. Best results are obtained in situations where the disk is accsk to edit text on drive B: (but don't change disks!) and you will marvel at the new version of your editor. It will load overlays in the blink of an eye and save files (e.g. ^KS) in nothing flat. A>FAST2 [ARBY] COBOL CMUMBLE The compilation for a small 100 line program drops from about 90 seconds to less than 40. The biggest gains are in loading overlays of the compiler. A>FAST2 [ARBY] CBASIC BMUMBLE $BF One of the mos    t irritating features of this compiler is that if you switch off the listing, you don't know which lines contain any errors which are detected. Solution: save a listing on disk and with FAST2 the compilation will still take no longer than before. FAST2 MESSAGES -------------- During the course of execution, FAST2 may print any of several different messages. Each of these messages is listed below along with conditions under which it is printed. s have been emptied. This too is simply an informatory message printed under normal conditons. NO COM FILE This message is printed when the transient filename given on the command line cannot be found in the directory. No recovery action can be taken, so the execution complete message is printed and FAST2 re-boots. OUT OF MEMORY This message is printed when the size of the TPA is exceeded while allocating bufS. The only recovery action taken is simply the printing of the message, then execution continues normally. This usually indicates a serious error (like a protected disk) and the user should boot and take corrective measures as soon as possible. INVALID OPTION This message is printed whenever an error is detected in the option string being scaned by FAST2. This may be the option string supplied on the command line or the overy action taken is to print the message and ignore the error. It is usually an indicator of hardware problems in your system and should be looked into immediately. If MEMORY HIT errors are persistent and you have a ROM monitor in your system, you can use FAST2 to help find the memory at fault. Create a special FAST2.COM with a jump to your monitor patched into location 521H. This location is called when a memory hit is detected. T LOAD. As mentioned earlier, the only way a transient can tell that it is being executed under FAST2 is that the size of the TPA is decreased. The amount of memory taken out of the TPA by FAST2 is dependant on the number of buffers which are allocated. .cp 4 The formulas used to determine the amount of memory used are: buffers = NTB * (3 + 131 * SPT) + NSB * (3 + 131 * SID) SID = NDE / 4 mem used = 768 + [buffers] Where: NTB is the Number of Track Buf Alfred Hospital FAST 2.01 This message is printed after the transient to be executed under fast has been successfully loaded, but just before control is transfered to it. This is simply an informatory message and does not signal an error condition. In this message, N.NN is the version number of FAST2 which you are using. FAST terminated This message is printed after the transient has finished execution and all disk bufferfers or while loading the transient. In either case, no recovery action can be taken, so the execution complete message is printed and FAST2 re-boots. There are several solutions to the out of memory problem: use less buffering, use smaller transients, or, of course, buy more memory. DISK WRITE ERROR This message is printed when FAST2 attempts to write data to disk and gets the unsuccessful completion flag back from the BIOdefault option string in memory in the unlikely event that it has been incorrectly modified. Some examples of invalid options are the null option ([]), options containing invalid characters ([Q]), or options which specify buffering of the same type for the same drive twice ([ABA]). MEMORY HIT This message is printed whenever FAST2 attempts to write to a memory location and cannot read the data it has just written. The reche HL register contains the address of the bad byte and a bit in the A register is set for each bad bit in memory. MEMORY ALLOCATION ----------------- When FAST2 is loaded, it automatically relocates itself to the top of the TPA (just like DDT and SID). This action overlays the CCP. A side effect of this is that transients which normally return to the CCP without booting will boot when executed under FAST2. An example of such a transient command is fers allocated SPT is the number of Sectors Per Track NSB is the Number of Sector Buffers allocated SID is the number of Sectors in the Directory NDE is the maximum Number of Directory Entries [ ] indicate rounding up to the next multiple of 256 For a normal 8 inch IBM compatible version of CP/M, all these computations can be replaced by a simple estimating rule: Allow 1024 bytes for FAST2 code overhead, 3409 bytes for each track buffer (R or !   W), and 2099 bytes for each seek buffer (S). As an example, FAST2 executed without a command line option string will use 1024 + 3409 + 2099 bytes. If this sum is rounded up to the next multiple of 256, the actual memory usage figure becomes 6656 bytes. The maxmimu on a two drive system is the command option [AYBY] which costs 1024 + 4x3409 + 2x2099 or a total of 18.5K (18944 bytes). PCopyright (C) 1979, Robert A. Van Valzah[RS]   ͣͳկ>   « ;ȷ#ó#~+:~@##~.#y  #* >?  #~.,; :=<>ȷͳ[9!09*."#͊y2͜yuxud INVALID OPTION $͜yuͷD:O~AO#ͷ# Y S W R+~ ]#+y   ! !9>!t>*ͩMEMORY HIkkþÜâôäéî81:g.-͜*"lͩ FAST terminately2y2`i"Yy2O!͞"! ͞"!͞"!!͞|K|!! q#p:O**ͳ*ͳ*ͤ*|:Ewó****|:Ew: ! ^#V#E:ʗͩDISK WRITE ERROR q ~#fo#~¸7##*͚7|:##:O~ȹ7#6#*͚w7: $ @ I$I A $I$$!!$H A $H $$ @ D@@I@A+6~ 6+w:6+:w+"O ~#Yr+s AOUT OF MEMORY$1:Ɓo&6!(͕}O:2O !\͕l͕!6C#6O#6M*DM:gw# x¥T^#{_zw# x}·ó~# &1W:Oʹ|ͩAlfred Hospital FAST 2.01 h:W!-͜;-͜*"!"<>ں!ʑͩOUT OF MEMORkͩNO COM FILkO:O:O*DM|͏##~O#6#DM w#%2|~<"2##~O#~iX6̈́#DM!w!~6*#NNw)# œN~#!   Ïz}`<;`<;  `<`<!*~=#~= oH o g^#VLIX o gDEXECUTPmKBRANCa|`i^#V+MDE0BRANCq}|E(LOOP*(~w_#~w#W{z#~#~|#"(E(+LOOPí(DO*(++++"(s#r#s#rE *(^#VEDIGI!{0@ 5 @@_!ClD(FINDO?{#xY!i_!Cځ{^#VzP!DENCLOSD{W+#ʦW~¾Ez#~¾EEEMIԒnrGKEÆ?TERMINA/g#DDMINUї_>W>o>gDOVE/CDRO&>ESWA5KDDUBXD2DUPfC+]t~w#~wETOGGLm~wE^#VECn&D2^#V^#VEs#rECsE2s#r#s#rE e / *(+p+q"(KBE GD ! GNOO!GCONSTAN3D  ^#VEVARIABL>I EUSE\I ^*&DrSSSSḄS C/̫S@FIRSԴS))җҦ}o|gñ}o|gұ =ŽEANj{ozgDOҽ{ozgDXO{ozgDSP!9DSP *&^#VERP#*(DRP1*&^#V"(E;)I*(N#F#"(ELEAVB`*(^#V#s#rE>Vt*(++"(s#rERm*(^#V#"(E҃ 0}!¯#D0)!#DDD!9^q#Vp}o|gDMINU}/o|GSRTI  WIDT WARNINFENC(D5VOC-LIN@BLHIWOU`SChOFFSEqCONTEXz CURRENԆ"STATœ$BASŠ&DP̫(FLĵ*CSо,R.HL01G2GHEREGALLOErG GCG}o|gɁ+I<DCGGQczm<$%x!D!DU]d <zGG~IaGROԟCSPACūG-DUйVVGTRAVERSI-V-aI<-I z<G-TRAILIN V--GG^zGG(."  Vr G.T V" [ z  GEXPECo --VVU*<V UVGr VzVz(VV U^<zV  <GQUERٞ VP eG ]*]re]G <z<GFIL7 | i`xʎ }  EERASs z GBLANKӒ z GHOLĢ VrGPAij VDGWOR ] ]!zeGDLITERAIG?STACIx VVx GINTERPRE" a , z, k+z z<+zIMMEDIATO V@GVOCABULARٝ V, SS GFORTȵ }DEFINITIONGV) GQUI]! /# [[ OKzABOR$ l +_[ fig-FORTH 1.1 +EWARPX*ECOLĂ%V<V<VVCVV&VVV VXS->ě!z+"   C+GD+GABVGDAB&VGMI4dI<GMACdaI<GMYdr,I,:GMo-rr;,oIIGt<G/MOırGI<GMO<G*/MOrtG*I<GM/MOroIroG(LINErV@!V@G.LIN-6( GMESSAGT2VG\z [ MSG # GPf!so&DP!s}EDRIVŷmSEmTRACmUSm