?!Z3DIRTDUMAC"^Z3DUTDIRMAC' Z3GCL1 MAC0Z3GCL2 MAC8 Z3GCRT MACB(Z3GDUOK MACIZ3GEFCB MACN'Z3GENV MACSvZ3GFCP MACV*Z3GFN1 MAC\0Z3GFN2 MAC`/Z3GIOP MACdWZ3GMDISKMACj'Z3GMSG MACoEZ3GMUSERMACtVZ3GNDR MACyDLZ3GPATH MACZ3GPRT MACZ3GQUIETMACMIZ3GRCP MACz Z3GSH MAC )zZ3GSPEEDMACc6Z3GVID MAC?Z3GWHL MAC)eZ3GZFC MACZ3GZNC MACfZ3GZR MACZ3HDR MACZ3IF MACIZ3IFELSEMAClhZ3IFEND MACFZ3IFTESTMAC|Z3INI MACJZ3LOG MAC VZ3LVER MAC:Z3MSG1 MAC<Z3MSG2 MAC\Z3MSG3 MACwZ3MSG4 MAC Z3MSG5 MAC Z3MSG6 MACZ3MSG7 MAC<Z3MSG8 MAC!rZ3MSG9 MAC&sZ3MSGA MAC-Z3MSGB MAC2ĖZ3MSGC MAC:@Z3MSGD MAC@Z3MSGE MACFZ3MSGF MACKFfZ3MSGG MACQqZ3MSGH MACWeXZ3PCL MAC]pZ3PFIND MACp!Z3PRGLD MAC!Z3PRS1 MACn!Z3PRS2 MACQHUZ3PRS3 MACd3`Z3PWHL MACZ3PZNC MACZ3PZR MACVZ3QCOUT MAC#Z3QCRLF MACZ3QOUT MAC[_Z3QPRINTMACZ3QPSTR MACZ3ROOT MACZ3SHEMPTMACTZ3SHFULLMAC /QZ3SHPOP MAC Z3SHPUSHMACF,Z3W1 MAC8Z3W2 MACjMZ3W3 MAC VID1 MAC; ; Z3LIB Module Name: Z3DIRTDU ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; DIRTDU ; Module External References: ; GETNDR CAPS ; ext getndr,caps ; ; DIRTDU searches for the DIR named pted to by HL. If found, ; BC = DU (disk A = 0) and NZ. If not found, A=0 and Zero Flag Set. ; HL pts to delimiter at end of name. ; dirtdu:: push d ;save DE ; ; Save DIR Name in Buffer ; lxi d,dirbuf ;pt to buffer mvi b,8 ;8 chars max dd1: mov a,m ;get char call delchk ;check for delimiter jz dd3 stax d ;store char inx h ;pt to next inx d dcr b ;count down jnz dd1 ; ; Name longer than 8 chars - skip to delimiter ; dd2: mov a,m ;skip to delimiter inx h ;pt to next call delchk ;check for delimiter jnz dd2 dcx h ;pt to delimiter jmp dd4 ; ; Name shorter than 8 chars - space fill ; dd3: mvi a,' ' ;space fill stax d ;store space inx d ;pt to next dcr b ;count down jnz dd3 ; ; HL pts to delimiter, buffer contains name ; dd4: push h ;save ptr to delimiter lxi d,dirbuf ;pt to directory name buffer call getndr ;pt to named dir jnz dd5 ; ; Directory Not Found ; dirnf: pop h ;restore ptr to delimiter pop d ;restore DE xra a ;return with flag set ret ; ; Scan for Directory Name ; dd5: mov a,m ;end of dir? ora a jz dirnf ;not found if so push h ;save ptr to current entry push d ;save ptr to target name inx h ;pt to name inx h mvi b,8 ;8 chars dd6: ldax d ;get target name cmp m ;compare jnz dd7 inx h ;pt to next inx d dcr b ;count down jnz dd6 ; ; DIR Names Match ; pop d ;restore ptrs pop h mov b,m ;get disk number dcr b ;disk A = 0 inx h ;get user number mov c,m ;... in C pop h ;restore ptr to delimiter pop d ;restore DE xra a ;return NZ for OK dcr a ret ; ; Advance to Next DIR Entry ; dd7: pop d ;restore ptrs pop h lxi b,18 ;pt to next entry dad b jmp dd5 ;resume search ; ; Check for Delimiter in A ; delchk: call caps ;capitalize char cpi '0' ;numeric? jc del1 cpi '9'+1 jc del2 cpi 'A' ;alphabetic? jc del1 cpi 'Z'+1 jc del2 ; ; Is a delimiter ; del1: push b mov b,a ;save char xra a ;set Zero mov a,b pop b ret ; ; Is not a delimiter ; del2: push b mov b,a ;save char xra a ;set NZ dcr a mov a,b pop b ret ; ; Buffers ; dirbuf: ds 8 ;8 chars for name end ; ; Z3LIB Module Name: Z3DUTDIR ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; DUTDIR ; Module External References: ; GETNDR ; ext getndr ; ; DUTDIR searches the memory-based named directory for the DU ; given in BC (B=disk, disk A = 0, C=user). DUTDIR returns a pointer ; in HL to the 8-char disk name. If not found, A=0 and Zero Flag Set. ; dutdir:: inr b ;disk A = 1 call getndr ;set HL to point to named directory jnz dd1 ; ; Directory Not Found ; dirnf: dcr b ;restore registers xra a ;error - no named dir ret ; ; Search Loop ; dd1: mov a,m ;check for end ora a ;0 if end jz dirnf cmp b ;check disk jnz dd2 ;skip to next if no match inx h ;pt to user mov a,m ;get user dcx h ;pt back cmp c ;check user jnz dd2 ;skip to next if no match ; ; Directory Name Found ; inx h ;pt to name inx h dcr b ;restore registers xra a ;return NZ for OK dcr a ret ; ; Skip to Next Entry ; dd2: push b ;save BC lxi b,18 ;pt to next entry dad b pop b ;restore BC jmp dd1 end ; ; Z3LIB Module Name: Z3GCL1 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETCL1 ; Module External References: ; ENVPTR ; ext envptr ; ; GETCL1 returns the address of the command line buffer in HL and ; the size of the buffer in bytes in A. No other registers are affected. ; Note: The command line buffer is structured as follows: ; ; cmdline: ; dw
; db ; db ; db ; db 0 ; ; GETCL1 returns the address of CMDLINE in HL and the size (at CMDLINE+2) ; in A. ; getcl1:: push d ;save DE lhld envptr ;pt to environment lxi d,18h ;pt to entry dad d mov e,m ;get address in DE inx h mov d,m push d ;save address in DE inx d ;pt to size as in buffer inx d ldax d ;get size in A ora a ;return with Zero Set if None pop h ;get ptr to command line buffer pop d ;restore DE ret end ; ; Z3LIB Module Name: Z3GCL2 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETCL2 ; Module External References: ; ENVPTR ; ext envptr ; ; GETCL2 returns the address of the next command in the command line ; buffer in HL and the character at this address in A with the Zero Flag Set ; (Z) if there is no further characters in the line. Only HL and PSW are ; affected. Note: The command line buffer is structured as follows: ; ; cmdline: ; dw
; db ; db ; db ; db 0 ; ; GETCL2 returns the address in the first DW at the label CMDLINE in HL ; and the character at that address in A. ; getcl2:: push d ;save DE lhld envptr ;pt to environment lxi d,18h ;pt to entry dad d mov a,m ;get address in DE inx h mov h,m mov l,a ;address in HL mov a,m ;get address of first char in DE inx h mov hh,m mov l,a ;HL pts to first char mov a,m ;get first char in A ora a ;set Zero Flag if no more chars pop d ;restore DE ret end ; ; Z3LIB Module Name: Z3GCRT ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETCRT ; Module External References: ; ENVPTR ; ext envptr ; ; GETCRT returns the address of the CRT data record in HL. This ; record is structured as follows: ; ; db ; db ; db ; ; HL only is affected. ; getcrt:: push psw push d lhld envptr ;pt to environment lxi d,2FH ;pt to selection byte dad d mov b,m ;get selection byte inx h ;pt to first CRT byte inx h mov a,b ;multiply by 3 for record size add a ;*2 add b ;*3 mov e,a ;DE=offset mvi d,0 dad d ;HL pts to byte popd ;restore regs pop psw ret end ; ; Z3LIB Module Name: Z3GDUOK ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETDUOK ; Module External References: ; ENVPTR ; ext envptr ; ; GETDUOK returns the DU OK byte in A. Zero Flag is set ; accordingly. A=0 and Z if DU not OK. Only PSW is affected. ; getduok:: push h push d lhld envptr ;pt to environment lxi d,2EH ;pt to byte address dad d mov a,m ;get byte in A pop d ;restore regs pop h ora a ;set flag ret end ; ; Z3LIB Module Name: Z3GEFCB ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETEFCB ; Module External References: ; ENVPTR ; ext envptr ; ; GETEFCB returns the address of the ZCPR3 external FCB in HL. ; Return with Zero Flag Set (Z) if no external FCB. PSW and HL are affected. ; getefcb:: push d lhld envptr ;get it lxi d,24h ;offset dad d mov a,m ;get address in HL inx h mov h,m mov l,a pop d mov a,h ;check for existence ora l ret end ; ; Z3LIB Module Name: Z3GENV ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETENV ; Module External References: ; ENVPTR ; ext envptr ; ; GETENV returns the address of the ZCPR3 environment buffer in HL. ; No other registers are affected. ; getenv:: lhld envptr ;get it ret end ; ; Z3LIB Module Name: Z3GFCP ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETFCP ; Module External References: ; ENVPTR ; ext envptr ; ; GETFCP returns the address of the flow command package in HL and ; the size of the package in terms of 128-byte blocks in A. If there is ; no FCP buffer, A=0 and Zero Flag Set (Z). No other registers are affected. ; getfcp:: push d ;save DE lhld envptr ;pt to environment lxi d,12h ;pt to entry dad d mov e,m ;get address in DE inx h mov d,m inx h mov a,m ;get size in A xchg ;HL contains address pop d ;restore DE ora a ;set flag ret end ; ; Z3LIB Module Name: Z3GFN1 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETFN1 ; Module External References: ; ENVPTR ; ext envptr ; ; GETFN1 returns the address of the first filename.typ entry in HL. ; HL only is affected. ; getfn1:: push psw push d lhld envptr ;pt to environment lxi d,47H ;pt to file name entry dad d pop d ;restore regs pop psw ret end ; ; Z3LIB Module Name: Z3GFN2 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETFN2 ; Module External References: ; ENVPTR ; ext envptr ; ; GETFN2 returns the address of the second filename.typ entry in HL. ; HL only is affected. ; getfn2:: push psw push d lhld envptr ;pt to environment lxi d,52H ;pt to file name entry dad d pop d ;restore regs pop psw ret end ; ; Z3LIB Module Name: Z3GIOP ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETIOP ; Module External References: ; ENVPTR ; ext envptr ; ; GETIOP returns the address of the input/output package in HL and ; the size of the package in terms of 128-byte blocks in A. If there is ; no IOP buffer, A=0 and Zero Flag Set (Z). No other registers are affected. ; getiop:: push d ;save DE lhld envptr ;pt to environment lxi d,0Fh ;pt to entry dad d mov e,m ;get address in DE inx h mov d,m inx h mov a,m ;get size in A xchg ;HL contains address pop d ;restore DE ora a ;set flag ret end ; ; Z3LIB Module Name: Z3GMDISK ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETMDISK ; Module External References: ; ENVPTR ; ext envptr ; ; GETMDISK returns the maximum disk in A (disk A = 1). Zero Flag is set ; accordingly. Only PSW is affected. ; getmdisk:: push h push d lhld envptr ;pt to environment lxi d,2CH ;pt to byte address dad d mov a,m ;get byte in A pop d ;restore regs pop h ora a ;set flag ret end ; ; Z3LIB Module Name: Z3GMSG ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETMSG ; Module External References: ; ENVPTR ; ext envptr ; ; GETMSG returns the address of the ZCPR3 message buffer in HL. ; A=0 and Zero Flag Set (Z) if there is no ZCPR3 message buffer. ; getmsg:: push d ;save DE lhld envptr ;pt to environment lxi d,22h ;pt to entry dad d mov a,m ;get address in HL inx h mov h,m mov l,a ora h ;set Z flag if HL=0 pop d ;restore DE ret end ; ; Z3LIB Module Name: Z3GMUSER ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETMUSER ; Module External References: ; ENVPTR ; ext envptr ; ; GETMUSER returns the maximum user in A. Zero Flag is set ; accordingly. Only PSW is affected. ; getmuser:: push h push d lhld envptr ;pt to environment lxi d,2DH ;pt to byte address dad d mov a,m ;get byte in A pop d ;restore regs pop h ora a ;set flag ret end ; ; Z3LIB Module Name: Z3GNDR ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETNDR ; Module External References: ; ENVPTR ; ext envptr ; ; GETNDR returns the address of the named directory buffer in HL and ; the maximum number of entries in A. If there is no NDR buffer, A=0 ; and Zero Flag Set (Z). No other registers are affected. ; getndr:: push d ;save DE lhld envptr ;pt to environment lxi d,15h ;pt to entry dad d mov e,m ;get address in DE inx h mov d,m inx h mov a,m ;get size in A xchg ;HL contains address pop d ;restore DE ora a ;set flag ret end ; ; Z3LIB Module Name: Z3GPATH ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETPATH ; Module External References: ; ENVPTR ; ext envptr ; ; GETPATH returns the address of the external path in HL and the ; maximum number of elements in said path in A. If there is no external path, ; A=0 and Zero Flag Set. No other registers are affected. ; getpath:: push d ;save DE lhld envptr ;pt to environment lxi d,9 ;pt to path entry dad d mov e,m ;get path address in DE inx h mov d,m inx h mov a,m ;get path size in A xchg ;HL pts to path pop d ;restore DE ora a ;set flag ret end ; ; Z3LIB Module Name: Z3GPRT ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETPRT ; Module External References: ; ENVPTR ; ext envptr ; ; GETPRT returns the address of the Printer data record in HL. This ; record is structured as follows: ; ; db ; db ; db ; db
; ; HL only is affected. ; getprt:: push psw push d lhld envptr ;pt to environment lxi d,30H ;pt to selection byte dad d mov a,m ;get selection byte inx h ;pt to first CRT lxi d,6 ;pt to first printer dad d add a ;*2 (multiply by 4 to pt to selected printer) add a ;*4 mov e,a ;DE=offset mvi d,0 dad d ;HL pts to byte pop d ;restore regs pop psw ret end ; ; Z3LIB Module Name: Z3GQUIET ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETQUIET ; Module External References: ; ENVPTR ; ext envptr ; ; GETQUIET returns the quiet byte in A. Zero Flag is set accordingly. ; Only PSW is affected. ; getquiet:: push h push d lhld envptr ;pt to environment lxi d,28H ;pt to byte address dad d mov a,m ;get byte in A pop d ;restore regs pop h ora a ;set flag ret end ; ; Z3LIB Module Name: Z3GRCP ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETRCP ; Module External References: ; ENVPTR ; ext envptr ; ; GETRCP returns the address of the resident command package in HL and ; the size of the package in terms of 128-byte blocks in A. If there is ; no RCP buffer, A=0 and Zero Flag Set. No other registers are affected. ; getrcp:: push d ;save DE lhld envptr ;pt to environment lxi d,0Ch ;pt to entry dad d mov e,m ;get address in DE inx h mov d,m inx h mov a,m ;get size in A xchg ;HL contains address pop d ;restore DE ora a ;set flag ret end ; ; Z3LIB Module Name: Z3GSH ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETSH GETSH1 GETSH2 ; Module External References: ; ENVPTR ; ext envptr ; ; GETSH2 returns the address of the shell stack in HL, the size of each ; shell stack entry in DE, and the number of entries possible in the shell ; stack in A and B (same value in each register). A=0 and Zero Flag Set (Z) ; if there is no shell stack. ; getsh2:: call getsh1 ;get data in a different form mov e,b ;DE=size of entry mvi d,0 mov b,a ;B=A=number of entries ret ;Zero Flag has already been set ; ; GETSH1 returns the address of the shell stack in HL, the size of each ; shell stack entry in B, and the number of entries possible in the shell ; stack in A. A=0 and Zero Flag Set (Z) if there is no shell stack. ; No other registers are affected. ; getsh:: getsh1:: push d ;save DE lhld envptr ;pt to environment lxi d,1Eh ;pt to entry dad d mov e,m ;get address in DE inx h mov d,m inx h mov a,m ;get number of entries in A inx h mov b,m ;get size of entry in B xchg ;HL contains address pop d ;restore DE ora a ;set flag ret end ; ; Z3LIB Module Name: Z3GSPEED ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETSPEED ; Module External References: ; ENVPTR ; ext envptr ; ; GETSPEED returns the processor speed in A. Zero Flag is set ; accordingly. Only PSW is affected. ; getspeed:: push h push d lhld envptr ;pt to environment lxi d,2BH ;pt to byte address dad d mov a,m ;get byte in A pop d ;restore regs pop h ora a ;set flag ret end ; ; Z3LIB Module Name: Z3GVID ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETVID ; Module External References: ; ENVPTR ; ext envptr ; ; GETVID returns the address of the ZCPR3 TCAP buffer in HL. ; A=0 and Zero Flag Set (Z) if no Z3TCAP entry present. ; getvid:: push d ;save DE lhld envptr ;get it lxi d,80H ;pt to Z3TCAP dad d pop d ;restore DE mov a,m ;get first char cpi ' '+1 ;test for entry present jc noentry xra a ;return NZ dcr a ret noentry: xra a ;return Z ret end ; ; Z3LIB Module Name: Z3GWHL ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETWHL ; Module External References: ; ENVPTR ; ext envptr ; ; GETWHL returns the wheel byte in A. Zero Flag is set accordingly. ; Only PSW is affected. ; getwhl:: push h push d lhld envptr ;pt to environment lxi d,29H ;pt to wheel byte address dad d mov a,m ;get address in HL inx h mov h,m mov l,a mov a,m ;get wheel byte in A pop d ;restore regs pop h ora a ;set flag ret end ; ; Z3LIB Module Name: Z3GZFC ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETZFC ; Module External References: ; GETENV ; ext getenv ; ; GETZFC returns the address in HL of the first character in the ZEX ; buffer. Carry Flag is Set if data not available. A contains ; the character. ; getzfc:: push h call getenv ;pt to environment mov a,h ;any environment? ora l jz error push d ;pt to message byte lxi d,34 ;offset to message ptr dad d mov e,m ;get address of messages inx h mov d,m xchg ;HL pts to message pop d mov a,h ;any messages? ora l jz error push d ;pt to Zex First Char lxi d,11 dad d mov e,m ;get address inx h mov d,m xchg pop d pop psw ;clear stack mov a,m ;get next char ora a ;set Z and Clear Carry ret error: pop h ;restore HL stc ;set carry ret end ; ; Z3LIB Module Name: Z3GZNC ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETZNC ; Module External References: ; GETENV ; ext getenv ; ; GETZNC returns the address in HL of the next character which ; ZEX will return. Carry Flag is Set if data not available. A contains ; the character. ; getznc:: push h call getenv ;pt to environment mov a,h ;any environment? ora l jz error push d ;pt to message byte lxi d,34 ;offset to message ptr dad d mov e,m ;get address of messages inx h mov d,m xchg ;HL pts to message pop d mov a,h ;any messages? ora l jz error push d ;pt to Zex Next Char Address lxi d,9 dad d mov e,m ;get address inx h mov d,m xchg pop d pop psw ;clear stack mov a,m ;get next char ora a ;set Z and Clear Carry ret error: pop h ;restore HL stc ;set carry ret end ; ; Z3LIB Module Name: Z3GZR ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETZRUN ; Module External References: ; GETENV ; ext getenv ; ; GETZRUN returns the ZEX run message byte in A. Zero Flag ; is Set accordingly. Carry Flag is Set if no such message available. ; getzrun:: push h call getenv ;pt to environment mov a,h ;any environment? ora l jz error push d ;pt to message byte lxi d,34 ;offset to message ptr dad d mov e,m ;get address of messages inx h mov d,m xchg ;HL pts to message pop d mov a,h ;any messages? ora l jz error push d ;pt to Zex Running Flag lxi d,8 dad d pop d mov a,m ;get byte ora a ;set Z and Clear Carry pop h ;restore HL ret error: pop h ;restore HL stc ;set carry ret end ; ; Environment Definition ; if z3env ne 0 ; ; External ZCPR3 Environment Descriptor ; jmp start db 'Z3ENV' ;This is a ZCPR3 Utility db 1 ;External Environment Descriptor z3eadr: dw z3env start: lhld z3eadr ;pt to ZCPR3 environment ; else ; ; Internal ZCPR3 Environment Descriptor ; MACLIB Z3BASE.LIB MACLIB SYSENV.LIB z3eadr: jmp start SYSENV start: lxi h,z3eadr ;pt to ZCPR3 environment endif ; ; Start of Program -- Initialize ZCPR3 Environment ; call z3init ;initialize the ZCPR3 Env and the VLIB Env ; ; Z3LIB Module Name: Z3IF ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; IFT IFF ; Module External References: ; GETMSG ; ext getmsg ; ; IFT turns on the next level of IF and sets it TRUE. Return ; with A=0 and Zero Flag Set (Z) if IF level overflow. ; ift:: push b ;save BC mvi b,0ffh ;turn on call ifset pop b ret ; ; IFF turns on the next level of IF and sets it FALSE. Return ; with A=0 and Zero Flag Set (Z) if IF level overflow. ; iff:: push b ;save BC mvi b,0 ;turn off call ifset pop b ret ; ; Turn on next IF level ; B register is 0 if level is inactive, 0FFH is level is active ; Return with Z flag set if IF overflow ; ifset: push h ;save regs push d push b call getmsg ;pt to messages inx h ;pt to IF byte mov a,m ;get IF byte ora a ;if no IF at all, start 1st one jz ifset1 cpi 80h ;check for overflow (8 IFs max) jz iferr inx h ;pt to active IF ana m ;check to see if current IF is TRUE jnz ifset0 ;continue if so mov b,a ;B=0 to set next IF to FALSE ifset0: dcx h ;pt to IF level mov a,m ;get it rlc ;advance to next level ani 0feh ;only 1 bit on mov m,a ;set IF byte jmp ifset2 ifset1: inr a ;A=1 mov m,a ;set 1st IF inx h ;clear active IF byte mvi m,0 dcx h ifset2: mov d,a ;get IF byte ana b ;set interested bit mov b,a inx h ;pt to active flag mov a,d ;complement IF byte cma mov d,a mov a,m ;get active byte ana d ;mask in only uninterested bits ora b ;mask in complement of interested bit mov m,a ;save result pop b ;restore regs pop d pop h xra a ;return with NZ dcr a ret iferr: pop b ;restore regs pop d pop h xra a ;set Z ret end ; ; Z3LIB Module Name: Z3IFELSE ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; IFELSE ; Module External References: ; GETMSG ; ext getmsg ; ; IFELSE complements the Active Bit for the Current IF. Return with ; A=0 and Zero Flag Set (Z) if there is no current IF. ; ifelse:: push h ;save regs push b call getmsg ;pt to messages inx h ;pt to IF byte mov a,m ;get IF byte ora a ;any active IFs? jz iferr mov b,a ;get IF byte in B inx h ;pt to IF active byte mov a,m ;get it cma ;flip bits ana b ;look at only interested bit mov c,a ;result in C mov a,b ;complement IF byte cma mov b,a mov a,m ;get active byte ana b ;mask in only uninterested bits ora c ;mask in complement of interested bit mov m,a ;save result pop b ;restore registers pop h xra a ;return NZ dcr a ret iferr: pop b ;restore registers pop h xra a ;return Z ret end ; ; Z3LIB Module Name: Z3IFEND ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; IFEND ; Module External References: ; GETMSG ; ext getmsg ; ; IFEND decrements to the previous IF. If there is no active IF, ; return with A=0 and Zero Flag Set (Z). Affect only PSW. ; ifend:: push h ;save regs call getmsg inx h ;pt to IF byte mov a,m ;get it ora a ;no IF active? jz iferr rrc ;move right 1 bit ani 7fh ;mask msb 0 mov m,a ;store active bit pop h ;restore regs xra a ;return NZ dcr a ret iferr: pop h ;restore regs xra a ;return Z ret end ; ; Z3LIB Module Name: Z3IFTEST ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; IFTEST ; Module External References: ; GETMSG ; ext getmsg ; ; IFTEST returns the number of the Current IF. Return with ; A=0 and Zero Flag Set (Z) if there is no current IF. ; iftest:: push h ;save regs push b call getmsg ;pt to messages inx h ;pt to IF byte mov a,m ;get IF byte ora a ;any active IFs? jz ifdone mvi b,0 ;set no IF iftl: inr b ;next IF level rrc ;rotate right 1 bit jnc iftl ;loop until none mov a,b ;count in A ifdone: pop b ;restore registers pop h ora a ;set Z flag if A=0 ret end ; ; Z3LIB Module Name: Z3INI ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; Z3INIT ; Module External References: ; ; ; Z3INIT accepts as input a pointer to the Z3 Environment Descriptor and ; saves it away in a global buffer for future reference. ; z3init:: shld envptr ret envptr:: ds 2 ; global buffer for use by other Z3 routines end ; ; Z3LIB Module Name: Z3LOG ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; Z3LOG ; Module External References: ; ; ; Equates ; bdos equ 5 ; ; Macros ; putrg macro push h push d push b push psw endm getrg macro pop psw pop b pop d pop h endm ; ; Z3LOG logs into the DU contained in a ZCPR3 FCB. On input, ; DE pts to FCB. No codes are returned. ; z3log:: putrg ;save regs ; ; Get Current Disk in B (disk A = 1) ; push d ;save ptr to FCB mvi c,25 ;get disk call bdos inr a mov b,a ;current disk in B pop d ;pt to FCB ; ; Determine Disk in B (disk A = 0) ; ldax d ;get disk ora a ;0=default jz log1 mov b,a ;selected disk in B log1: dcr b ;B=disk (disk A=0) ; ; Get Selected User in C ; lxi h,13 ;pt to S1 for user dad d mov c,m ;user in C ; ; Log Into Disk in B ; push b ;save DU mov e,b ;disk in E mvi c,14 ;select disk call bdos pop b ; ; Log Into User in C ; mov e,c ;user in E mvi c,32 ;select user call bdos getrg ;restore registers ret end ; ; Z3LIB Module Name: Z3LVER ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; Z3LVER ; Module External References: ; None ; vers equ 101H ;Major Version = 1, Minor Version = 1 ; ; Return Version Number of Z3LIB in HL; H=Major Version, L=Minor ; Version ; z3lver:: lxi h,vers ;version number in HL ret end ; ; Z3LIB Module Name: Z3MSG1 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETER1 ; Module External References: ; GETMSG ; ext getmsg ; ; GETER1 returns the error flag message in A. Zero Flag is set ; accordingly. ; geter1:: push h ;save HL call getmsg ;get ptr to messages mov a,m ;get error flag pop h ora a ;set Z flag according to error flag ret end ; ; Z3LIB Module Name: Z3MSG2 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; PUTER1 ; Module External References: ; GETMSG ; ext getmsg ; ; PUTER1 sets the error flag message in A. No registers are affected. ; puter1:: push h ;save HL push psw ;save PSW call getmsg ;get ptr to messages pop psw ;get PSW mov m,a ;store message pop h ret end ; ; Z3LIB Module Name: Z3MSG3 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETER2 ; Module External References: ; GETMSG ; ext getmsg ; ; GETER2 returns the error code message in A. A=0 and Zero Flag Set ; if No Error. ; geter2:: push h ;save HL push d ;save DE call getmsg ;get ptr to messages lxi d,6 ;offset to code dad d mov a,m ;get error flag pop d ;get DE pop h ;get HL ora a ;set flag accordingly ret end ; ; Z3LIB Module Name: Z3MSG4 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; PUTER2 ; Module External References: ; GETMSG ; ext getmsg ; ; PUTER2 sets the error code message in A. No registers are affected. ; puter2:: push h ;save HL push d ;save DE push psw ;save PSW call getmsg ;get ptr to messages lxi d,6 ;offset to code dad d pop psw ;get PSW mov m,a ;store message pop d pop h ret end ; ; Z3LIB Module Name: Z3MSG5 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETCST ; Module External References: ; GETMSG ; ext getmsg ; ; GETCST returns the ZCPR3 command status message in A. A=0 and Zero ; Flag Set if command status is normal. ; getcst:: push h ;save HL call getmsg ;get ptr to messages inx h ;offset of 3 inx h inx h mov a,m ;get command status message pop h ora a ;set zero flag accordingly ret end ; ; Z3LIB Module Name: Z3MSG6 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; QSHELL ; Module External References: ; GETMSG ; ext getmsg ; ; QSHELL returns the ZCPR3 command status message in A and the ; Zero Flag Set (Z) if this message indicates that a Shell has been ; invoked. Only the PSW is affected. ; qshell:: push h ;save HL call getmsg ;get ptr to messages inx h ;offset of 3 inx h inx h mov a,m ;get command status message pop h cpi 1 ;set Z flag if shell ret end ; ; Z3LIB Module Name: Z3MSG7 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; QERROR ; Module External References: ; GETMSG ; ext getmsg ; ; QERROR returns the ZCPR3 command status message in A and the ; Zero Flag Set (Z) if this message indicates that an Error has been ; encountered. If such is the case, HL contains the address of the ; first character of the error line. The PSW and HL are affected. ; qerror:: call getmsg ;get ptr to messages inx h ;offset of 3 inx h inx h mov a,m ;get command status message push psw inx h ;pt to error address mov a,m inx h mov h,m mov l,a ;HL contains error address pop psw cpi 2 ;set Z flag if error ret end ; ; Z3LIB Module Name: Z3MSG8 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETZEX ; Module External References: ; GETMSG ; ext getmsg ; ; GETZEX returns the ZEX message byte in A. A=0 and Zero Flag Set ; if ZEX is running normally (intercepting chars). ; getzex:: push h ;save HL push d ;save DE call getmsg ;get ptr to messages lxi d,7 ;offset to message byte dad d mov a,m ;get message byte pop d ;get DE pop h ;get HL ora a ;set flag accordingly ret end ; ; Z3LIB Module Name: Z3MSG9 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; STOPZEX STRTZEX PUTZEX ; Module External References: ; GETMSG ; ext getmsg ; ; STOPZEX suspends ZEX processing. No registers are affected. ; stopzex:: push psw mvi a,2 ;suspend ZEX call putzex pop psw ret ; ; STRTZEX resumes ZEX processing. No registers are affected. ; strtzex:: push psw xra a ;A=0 means to resume ZEX processing call putzex pop psw ret ; ; PUTZEX sets the ZEX message byte in A. No registers are affected. ; putzex:: push h ;save HL push d ;save DE push psw ;save PSW call getmsg ;get ptr to messages lxi d,7 ;offset to message byte dad d pop psw ;get PSW mov m,a ;store message pop d pop h ret end ; ; Z3LIB Module Name: Z3MSGA ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETERC ; Module External References: ; GETMSG ; ext getmsg ; ; GETERC returns the address of the error command line in HL and ; A=0 and Zero Flag Set if no entry in command line. HL and PSW affected. ; geterc:: push d ;save DE call getmsg ;get ptr to messages lxi d,10H ;offset to buffer dad d mov a,m ;get first char pop d ;get DE ora a ;set flag ret end ; ; Z3LIB Module Name: Z3MSGB ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; PUTERC ; Module External References: ; GETMSG ; ext getmsg ; ; PUTERC stores the string pted to by HL into the error command line ; buffer. Return with A=0 and Zero Flag Set (Z) if string (incl ending 0) ; longer than 32 bytes. Affect only PSW. ; puterc:: push h ;save HL push d ;save DE push h ;save ptr to string mvi b,32 ;check size put1: mov a,m ;get char ora a ;zero = done jz put2 inx h ;pt to next dcr b ;count down jnz put1 pop h ;clear stack and return error code pop d pop h xra a ;return Z ret put2: call getmsg ;get ptr to messages lxi d,10H ;offset to code dad d pop d ;get ptr to string put3: ldax d ;copy string into buffer mov m,a inx h ;pt to next inx d ora a ;done? jnz put3 pop d ;restore regs pop h xra a ;OK return dcr a ;return NZ ret end ; ; Z3LIB Module Name: Z3MSGC ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETREG ; Module External References: ; GETMSG ; ext getmsg ; ; GETREG returns the value of the register specified in B. This ; value is returned in the A register. Zero Flag is set accordingly. ; Only PSW is affected. ; getreg:: push h ;save HL push d ;save DE call getmsg ;get ptr to messages lxi d,30H ;offset to registers dad d mov a,b ;get register number add l ;make HL pt to register mov l,a mov a,h aci 0 mov h,a mov a,m ;get register value pop d ;get DE pop h ;get HL ora a ;set flags ret end ; ; Z3LIB Module Name: Z3MSGD ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; PUTREG ; Module External References: ; GETMSG ; ext getmsg ; ; PUTREG sets the value of the register specified in B. This ; value is input in the A register. No registers are affected. ; putreg:: push h ;save HL push d ;save DE push psw ;save value call getmsg ;get ptr to messages lxi d,30H ;offset to registers dad d mov a,b ;get register number add l ;make HL pt to register mov l,a mov a,h aci 0 mov h,a pop psw ;get value mov m,a ;put register value pop d ;get DE pop h ;get HL ret end ; ; Z3LIB Module Name: Z3MSGE ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; ERRADR ; Module External References: ; GETMSG ; ext getmsg ; ; ERRADR returns the address of the first char of the command line ; in error which ZCPR3 attempted to process. HL affected. ; erradr:: push psw ;save PSW push d ;save DE call getmsg ;get ptr to messages lxi d,4 ;offset to buffer dad d mov a,m ;get address inx h mov h,m mov l,a ;HL = address pop d ;get DE pop psw ret end ; ; Z3LIB Module Name: Z3MSGF ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; PUTCST ; Module External References: ; GETMSG ; ext getmsg ; ; PUTCST sets the ZCPR3 command status message to the value in A. ; No registers are affected. ; ; PUTCST is intended to be used by Shells to indicate that the command ; they are passing is a "normal" command or whatever type of command ; (normal, shell, or error) is desired. ; putcst:: push h ;save HL push psw ;save A call getmsg ;get ptr to messages inx h ;offset of 3 inx h inx h pop psw ;get code mov m,a ;set command status message pop h ret end ; ; Z3LIB Module Name: Z3MSGG ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; GETSHM ; Module External References: ; GETMSG ; ext getmsg ; ; GETSHM returns the value of the shell message specified in B. This ; value is returned in the A register. Zero Flag is set accordingly. ; Only PSW is affected. There are only three shell messages, so 0 <= B <= 2. ; getshm:: push h ;save HL push d ;save DE call getmsg ;get ptr to messages lxi d,13 ;offset to registers dad d mov a,b ;get register number add l ;make HL pt to register mov l,a mov a,h aci 0 mov h,a mov a,m ;get register value pop d ;get DE pop h ;get HL ora a ;set flags ret end ; ; Z3LIB Module Name: Z3MSGH ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; PUTSHM ; Module External References: ; GETMSG ; ext getmsg ; ; PUTSHM sets the value of the shell message specified in B. This ; value is input in the A register. No registers are affected. There are ; only three shell messages, so 0 <= B <= 2. ; putshm:: push h ;save HL push d ;save DE push psw ;save value call getmsg ;get ptr to messages lxi d,13 ;offset to registers dad d mov a,b ;get register number add l ;make HL pt to register mov l,a mov a,h aci 0 mov h,a pop psw ;get value mov m,a ;put register value pop d ;get DE pop h ;get HL ret end ; ; Z3LIB Module Name: Z3PCL ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; Z3PCL ; Module External References: ; GETCL1 GETCL2 ; ext getcl1,getcl2 ; ; Macros ; putrg macro push b push d push h endm getrg macro pop h pop d pop b endm ; ; Z3PCL stores a command line in the ZCPR3 command line buffer. ; This command line is pted to by HL. On return, A=0 and Zero Flag Set ; if command line overflow is possible (no change to command line). ; putcl:: putrg ;save registers xchg ;DE pts to new line call getcl1 ;is command line available? jnz pcl1 ; ; Error Return ; nocl: getrg ;restore registers xra a ;ret Z ret ; ; Process Command Line ; pcl1: mov b,a ;char count in B xchg ;HL pts to new line push h ;save ptr to new line pcl2: mov a,m ;go to end of line ora a ;at end? jz pcl3 inx h ;pt to next dcr b ;count down jnz pcl2 pop h ;clear stack jmp nocl ;command line too long ; ; At End of New Command Line (ptr on stack) ; Ptr to first char of new command line on stack ; HL pts to ending 0 of new command line ; B = number of chars remaining before overflow of Z3 command line ; pcl3: xchg ;DE pts to last byte push d ;save ptr to last byte in case of error call getcl2 ;pt to tail of command line buffer mov a,m ;get first char of tail cpi ';' ;continuation? jz pcl4 ora a ;done? jz pcl4 mvi a,';' ;set continuation char stax d inx d dcr b ;count down jz pcl5 ;overflow ; ; Copy tail onto end of new command line ; pcl4: mov a,m ;get next char stax d ;store it inx h ;pt to next inx d ora a ;done? jz pcl6 dcr b ;count down jnz pcl4 ; ; Command Line too Long ; pcl5: pop h ;get ptr to end of old line mvi m,0 ;store ending 0 pop psw ;clear stack jmp nocl ; ; New Command Line OK ; pcl6: pop psw ;clear stack call getcl1 ;get ptr to buffer lxi d,4 ;pt to first char in buffer xchg dad d xchg mov m,e ;store address inx h mov m,d ;DE pts to first char of buffer pop h ;HL pts to first char of new line ; ; Copy New Command Line into Buffer ; pcl7: mov a,m ;copy stax d inx h inx d ora a ;EOL? jnz pcl7 ; ; Exit with OK Code ; getrg ;restore regs xra a ;set NZ dcr a ret end ; ; Z3LIB Module Name: Z3PFIND ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; PFIND ; Module External References: ; GETPATH ; EXT GETPATH ; ; EQUATES ; BDOS EQU 5 ; ; INTERNAL BUFFERS ; CURELT: DS 1 ; LOW-ORDER PTR TO CURRENT PATH ELEMENT SEARCUR: DS 1 ; 0=DON'T SEARCH CURRENT DIR CDISK: DS 1 ; CURRENT DISK NUMBER CUSER: DS 1 ; CURRENT USER NUMBER TDISK: DS 1 ; TEMP DISK NUMBER TUSER: DS 1 ; TEMP USER NUMBER ; ; PFIND -- LOOK FOR FILE WHOSE FCB IS PTED TO BY DE ALONG PATH ; IF FILE FOUND, RETURN DISK NUMBER IN B, USER NUMBER IN C, AND ; ZERO FLAG CLEAR (NZ) WITH A=0FFH; IF NOT FOUND, RETURN WITH ZERO FLAG ; SET (Z) AND A=0; IF ERROR, RETURN WITH ERROR CODE (1,2,3) AND NZ ; ; INPUTS: DE PTS TO FCB, A IS FLAG: A=0 IF NO CURRENT SEARCH ALSO, ; <>0 IF CURRENT SEARCH ; OUTPUTS: B=DISK, C=USER IF FOUND ; ZERO FLAG SET (Z) IF NOT FOUND ; ZERO FLAG CLEAR (NZ) IF FOUND ; PFIND:: PUSH H ; SAVE REGS PUSH D STA SEARCUR ; SET FLAG TO SEARCH CURRENT XRA A ; SET DISK NUMBER TO CURRENT STAX D ; CHANGE FCB PUSH D ; SAVE FCB PTR MVI C,25 ; GET CURRENT DISK CALL BDOSH STA CDISK ; SAVE CURRENT DISK STA TDISK ; SET TEMP DISK MVI C,32 ; GET CURRENT USER MVI E,0FFH CALL BDOSH STA CUSER ; SAVE CURRENT USER STA TUSER ; SAVE TEMP USER POP D ; GET FCB PTR CALL GETPATH ; GET ADDRESS OF EXTERNAL PATH IN HL LDA SEARCUR ; SEARCH CURRENT? ORA A ; 0=NO JZ PF1 ; ; LOOK FOR FILE WHOSE FCB IS PTED TO BY DE ; PF0: MVI C,17 ; SEARCH FOR FIRST CALL BDOSH INR A ; FILE FOUND? JNZ PFFND ; ; ADVANCE TO NEXT ELEMENT IN PATH ; PF1: MOV A,M ; GET DRIVE NUMBER FROM PATH ORA A ; 0=DONE=FILE NOT FOUND JZ PFNFND CALL GETDU ; GET DU IN BC CALL CKDUP ; CHECK FOR DUPLICATION OF PATH ENTRY INX H ; PT TO NEXT PATH ENTRY INX H JZ PF1 ; CONTINUE IF DUPLICATION OF PATH ENTRY PUSH D ; SAVE FCB PTR PUSH B ; SAVE BC MOV A,B ; SET DISK STA TDISK MOV E,A MVI C,14 ; SELECT DISK CALL BDOSH POP B ; GET BC MOV A,C ; SET USER STA TUSER MOV E,A MVI C,32 ; SELECT USER CALL BDOSH POP D ; GET FCB PTR JMP PF0 ; CONTINUE SEARCH ; ; FILE FOUND FLAG SETTING ; PFFND: XRA A ; FOUND RETURN CODE DCR A ; SET NZ JMP FNDEXIT ; ; FILE NOT FOUND ERROR ; PFNFND: XRA A ; FILE NOT FOUND FNDEXIT: PUSH PSW ; SAVE RETURN CODE LDA CDISK ; RESTORE CURRENT DISK MOV E,A ; SAVE IN E MVI C,14 ; SELECT DISK IN E CALL BDOS LDA CUSER ; RESTORE CURRENT USER MOV E,A ; SAVE IN E MVI C,32 ; SELECT USER IN E CALL BDOS LDA TDISK ; SET FOUND DISK MOV B,A LDA TUSER ; SET FOUND USER MOV C,A POP PSW ; GET RETURN CODE POP D ; RESTORE REGS POP H RET ; ; CHECK ALONG PATH FOR DUPLICATION OF ENTRY ; RETURN WITH Z IF SO ; CKDUP: PUSH H ; SAVE PTRS PUSH D ; SAVE FCB PUSH B ; SAVE DU MOV A,L ; SAVE LOW-ORDER ADDRESS STA CURELT CALL GETPATH ; PT TO FIRST ELEMENT OF PATH CKDUP1: LDA CURELT ; GET CURRENT ELEMENT CMP L ; ARE WE THERE? JZ NODUP CALL GETDU ; GET ELEMENT IN BC INX H ; PT TO NEXT PATH ELEMENT INX H POP D ; GET CURRENT DU IN DE PUSH D ; SAVE IT AGAIN MOV A,B ; COMPARE AGAINST PATH ELEMENT CMP D JNZ CKDUP1 MOV A,C CMP E JNZ CKDUP1 ; NO MATCH, SO CONTINUE ; ; WE HAVE A DUPLICATE - RETURN Z ; POP B ; RESTORE REGS POP D POP H XRA A ; SET Z RET ; ; NO DUPLICATES - RETURN NZ ; NODUP: POP B ; RESTORE REGS POP D POP H XRA A ; SET NZ DCR A RET ; ; RETURN DU IN BC FOR CURRENT PATH ELEMENT PTED TO BY HL ; GETDU: MOV A,M ; GET DISK CPI '$' ; CURRENT? JNZ GETDU1 LDA CDISK ; SELECT CURRENT DISK INR A ; ADJUST GETDU1: DCR A ; SET DISK FOR A=0 MOV B,A ; DISK IN B INX H ; PT TO USER MOV A,M ; GET USER DCX H ; PT BACK TO DISK CPI '$' ; CURRENT? JNZ GETDU2 LDA CUSER ; GET CURRENT USER GETDU2: MOV C,A ; USER IN C RET ; ; CALL BDOS AND NOT CHANGE HL ; BDOSH: PUSH H ; CALL BDOS, BUT SAVE HL PUSH D CALL BDOS POP D POP H RET END ; ; Z3LIB Module Name: Z3PRGLD ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; PRGLOAD ; Module External References: ; ; ; OS Equates ; bdos equ 5 tpa equ 100h ; ; PRGLOAD loads the program indicated by the first 12 bytes pted to ; by DE into memory at 100H and transfers control to it. ; If file does not exist, PRGLOAD returns; if file does exist, PRGLOAD ; clears the stack of its return address and transfers control to the program ; after loading it with the cleared stack as the program's stack. ; prgload:: push d ;save ptr to FCB (DE) lhld bdos+1 ;get base address of BDOS mov a,h ;9 pages below BDOS (1st page below CCP) sui 9 mov h,a mvi l,80H ;HL pts to load address shld ldadr ;set load address lxi d,40H ;set FCB address dad d shld ldfcb ;address of FCB pop d ;pt to original FCB mvi m,0 ;set first byte to 0 (current disk) inx h ;pt to name inx d ;pt to name mvi b,11 ;11 bytes call moveb ;do copy mvi b,24 ;fill next 24 bytes (to R2) with zeroes call zero ;initialize LDFCB lhld ldfcb ;pt to FCB xchg ;... in DE mvi c,15 ;try to open file call bdos cpi 0ffh ;error? rz ;abort if error ; ; Copy Loader Program into TBUFF Area ; pop psw ;clear stack lxi d,loader ;pt to loader program lhld ldadr ;pt to loader address mvi b,64 ;copy 64 bytes call moveb ;do the copy lxi d,100h ;initial DMA address lhld ldadr ;transfer control to the loader program pchl ;transfer control to the loader program ; ; Copy HL to DE for B bytes ; moveb: ldax d ;get byte mov m,a ;put byte inx h ;pt to next inx d dcr b ;count down jnz moveb ret ; ; Zero FCB fields pted to by HL ; zero: mvi m,0 ;store zero inx h ;pt to next dcr b ;count down jnz zero ret ; ; Loader Program ; Upon execution, the address of LOADER is LDADR ; The FCB used by LOADER is at LDFCB ; loader: mvi c,26 ;set DMA push d ;save address call bdos ;perform BDOS function ldfcb equ $+1 lxi d,0 ;pt to FCB mvi c,20 ;read next record call bdos pop h ;get DMA address ora a ;0=OK jnz tpa ;done with load, so run program lxi d,80H ;advance to next record dad d xchg ;DMA address in DE ldadr equ $+1 jmp 0 ;continue load ; ; Memory Marker - For Easy Location of Module End ; db '**** ZCPR3 PRGLOAD ****' end ; ; Z3LIB Module Name: Z3PRS1 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; ZPRSFN PARSER ; Module External References: ; GETDUOK GETMDISK GETMUSER GETNDR ; RETUD CAPSTR ; ; ; External References ; EXT RETUD,CAPSTR,GETDUOK,GETMDISK,GETMUSER,GETNDR ; ; Basic Equates ; CMDSEP equ ';' ;command separator TFCB equ 5CH ;FCB Buffer TFCB2 equ 6CH ;2nd FCB Buffer TBUFF equ 80H ;Temporary Buffer ; ; PARSE TOKEN PTED TO BY HL INTO FCB PTED TO BY DE ; ON INPUT, ; HL pts to token, ending in any valid delimiter ; DE pts to 36-byte FCB ; A = Flag: ; A = 0 if scan for DIR form before DU ; A = 1 if scan for DU form before DIR ; ON OUTPUT, ; HL pts to char following token ; A = Number of Question Marks in File Name and Zero Flag Set ; Accordingly ; ZPRSFN:: PUSH B ;SAVE BC STA DUFIRST ;SET FLAG CALL CAPSTR ;CAPITALIZE INPUT PUSH D ;SAVE PTR TO FCB CALL INITFCB ;INIT IT POP D ;GET PTR BACK XRA A ;DON'T FLUSH ON SCANNER STA SCFLUSH PUSH D ;SAVE PTR AGAIN CALL SCANNER ;SCAN LINE POP D ;RESTORE PTR POP B ;RESTORE BC LDA QMCNT ;CHECK FOR QUESTION MARKS ORA A RET ; ; PARSE COMMAND LINE PTED TO BY HL (may be an element of an MCL) ; ON INPUT, ; HL pts to command line ending in 0 ; A = Flag: ; A = 0 if scan for DIR form before DU ; A = 1 if scan for DU form before DIR ; ON OUTPUT, ; HL pts to next command in MCL ; DE pts to FCB containing command name (header.COM) ; A = Flag: ; A = 0 and Zero Flag Set if OK ; A = number of question marks and NZ if header ; contains one or more question marks ; PARSER:: PUSH B ;SAVE BC CALL PARSE ;DO THE WORK LHLD TAILSV ;GET PTR TO COMMAND TAIL LXI D,TBUFF ;COPY TAIL INTO TBUFF MVI B,0 ;SET CHAR COUNT PUSH D ;SAVE PTR TO TBUFF INX D ;PT TO FIRST CHAR POSITION SVTAIL: MOV A,M ;GET NEXT CHAR CALL TSTEOL ;END OF LINE? JZ SVT1 STAX D ;SAVE CHAR INX H ;PT TO NEXT INX D INR B ;INCREMENT CHAR COUNT JMP SVTAIL SVT1: XRA A ;STORE ENDING 0 STAX D POP H ;GET PTR TO TBUFF MOV M,B ;SET CHAR COUNT POP B ;RESTORE BC LHLD NXTCHR ;PT TO NEXT CHAR IN HL LXI D,FCBDN ;PT TO FCB IN DE LDA ERRFLG ;GET ERROR FLAG IN A ORA A ;SET ZERO FLAG RET ; ; MAIN ROUTINE ; PARSE: ; ; SAVE DU/DIR ORDER FLAG AND CAPITALIZE INPUT LINE ; STA DUFIRST ;0=DIR FIRST, 0FFH=DU FIRST CALL CAPSTR ;CAPITALIZE LINE ; ; SET SCANNER FLUSH FLAG ; MVI A,0FFH STA SCFLUSH ;SET FLAG TO NZ (PERFORM FLUSH) ; ; INITIALIZE THE COMMAND AND TOKEN FCBS ; LXI D,FCBDN ;PT TO COMMAND FCB CALL INITFCB ;INIT IT LXI D,TFCB ;PT TO TOKEN FCB CALL INITFCB ;INIT TFCB and TFCB2 ; ; EXTRACT COMMAND NAME ; LXI D,FCBDN ;PLACE COMMAND NAME INTO COMMAND FCB CALL SCANNER ;EXTRACT COMMAND NAME LDA QMCNT ;SET QUESTION MARK COUNT STA ERRFLG ;INTO ERROR FLAG ; ; SET TYPE OF COMMAND ; PUSH H ;SAVE PTR TO NEXT BYTE LXI H,COMMSG ;PLACE DEFAULT FILE TYPE (COM) INTO FCB LXI D,FCBFT ;PT TO FILE TYPE MVI B,3 ;3 BYTES CALL LDIR POP H ;GET PTR TO NEXT BYTE ; ; SET DIR: PREFIX FLAG ; LDA MYCOLON ;PREVIOUS TOKEN CONTAINED A COLON? STA COLON ;SET FLAG FOR DU: OR DIR: PREFIX ; ; SAVE POINTER TO COMMAND TAIL FOR LATER COPY INTO TBUFF AND FIND END OF ; COMMAND LINE ; SHLD TAILSV ;SAVE PTR TO COMMAND TAIL PUSH H ;SAVE PTR CTAIL: MOV A,M ;GET CHAR CALL TSTEOL ;AT EOL? JZ CTAIL1 INX H ;PT TO NEXT JMP CTAIL CTAIL1: SHLD NXTCHR ;SAVE PTR TO NEXT LINE POP H ;GET PTR TO COMMAND TAIL ; ; EXTRACT FIRST TOKEN ; CALL SKSP ;SKIP OVER SPACES RZ ;DONE IF EOL OR END OF COMMAND LXI D,TFCB ;STORE FIRST TOKEN IN TFCB CALL SCANNER ;EXTRACT TOKEN ; ; EXTRACT SECOND TOKEN ; CALL SKSP ;SKIP OVER SPACES RZ ;DONE IF EOL OR END OF COMMAND LXI D,TFCB2 ;PT TO 2ND FCB AND FALL THRU TO SCANNER ; ; EXTRACT TOKEN FROM COMMAND LINE AND PLACE IT INTO FCB PTED TO BY DE ; FORMAT FCBDN FCB IF TOKEN RESEMBLES FILE NAME AND TYPE (FILENAME.TYP) ; ON INPUT, HL PTS TO NEXT CHAR AND DE PTS TO FCB ; ON OUTPUT, HL PTS TO DELIMITER AFTER TOKEN AND ZERO FLAG IS RESET ; IF '?' IS IN TOKEN ; ; ENTRY POINTS: ; SCANNER - LOAD TOKEN INTO FCB PTED TO BY DE ; ON EXIT, HL PTS TO ENDING DELIMITER ; SCANNER: XRA A ;A=0 STAX D ;SET DEFAULT DRIVE STA MYCOLON ;SET NO COLON STA TEMPDR ;SET TEMPORARY DRIVE NUMBER TO DEFAULT STA QMCNT ;ZERO QUESTION MARK COUNTER CALL RETUD ;GET USER/DISK MOV A,C ;GET USER STA TEMPUSR ;SET TEMPUSR PUSH D ;SAVE PTR TO FIRST BYTE OF FCB MVI B,8 ;8 CHARS MAX CALL SCANF ;PLACE FIRST TOKEN INTO FILE NAME FIELD POP D ;GET PTR TO FIRST BYTE OF FCB MOV A,M ;GET TERMINATING CHAR STA ENDCHAR ;SET ENDING CHAR CPI ':' ;COLON? JNZ SCAN1 ;NO, WE HAVE A FILE NAME STA MYCOLON ;SET COLON INX H ;PT TO CHAR AFTER COLON ; ; CHECK FOR DU: FORM FIRST ; LDA DUFIRST ;CHECK DUFIRST FLAG ORA A JZ SCN1 CALL DUSCAN ;CHECK FOR DU: FORM JZ SUD1 ;GOT IT ; ; CHECK FOR DIR: FORM SECOND OR FIRST ; SCN1: CALL DIRSCAN ;CHECK FOR DIR: FORM JZ SUD1 ;GOT IT ; ; CHECK FOR DU SCAN FOR DUSECOND ; LDA DUFIRST ;CHECK DU FLAG ORA A JNZ SUD1 ; ; CHECK FOR DU: FORM SECOND ; CALL DUSCAN ;CHECK FOR DU: FORM ; ; WE HAVE A VALID DU OR DIR - TEMPDR/TEMPUSR CONTAIN DATA ; SUD1: LDA TEMPDR ;SET DRIVE STAX D ;... IN FCB ; ; REINIT FCB PTED TO BY DE ; PUSH D ;SAVE PTR INX D ;PT TO FN FIELD CALL IFCB ;ONLY PARTIAL INIT (17 BYTES TOTAL) POP D ; ; EXTRACT FILENAME FIELD ; XRA A STA QMCNT ;ZERO QUESTION MARK COUNTER PUSH D ;SAVE PTR TO FIRST BYTE OF FCB MVI B,8 ;8 CHARS MAX CALL SCANF ;STORE FILE NAME POP D ;GET PTR TO FIRST BYTE OF FCB MOV A,M ;GET OFFENDING CHAR STA ENDCHAR ;SET ENDING CHAR ; ; SKIP TO FILE TYPE FIELD ; HL PTS TO NEXT CHAR, DE PTS TO DN FIELD OF FCB ; SCAN1: LDA ENDCHAR ;GET ENDING CHAR XCHG LXI B,8 ;PT TO BEFORE FILE TYPE FIELD OF FCB DAD B XCHG ; ; EXTRACT FILETYPE FIELD ; MVI B,3 ;PREPARE TO EXTRACT FILE TYPE CPI '.' ;IF '.', WE HAVE A TYPE JNZ SCAN2 INX H ;PT TO CHAR AFTER '.' PUSH D CALL SCANF ;GET FCB FILE TYPE POP D SCAN2: ; ; SET USER NUMBER REFERENCED ; HL PTS TO NEXT CHAR, DE PTS TO BEFORE FCB FT ; XCHG LXI B,5 ;PT TO S1 FIELD DAD B XCHG LDA TEMPUSR ;STORE USER NUMBER HERE STAX D LDA SCFLUSH ;FLUSH TO SPACE, ETC? ORA A ;0=NO JZ SCAN4 ; ; SKIP TO SPACE, CHAR AFTER =, OR EOL ; HL PTS TO NEXT CHAR IN LINE ; SCAN3: MOV A,M ;GET NEXT CHAR CPI ' '+1 ;DONE IF LESS THAN SPACE JC SCAN4 CALL TSTEOL ;EOL? JZ SCAN4 INX H ;PT TO NEXT CPI '=' ;EQUATE? JNZ SCAN3 ; ; SET ZERO FLAG TO INDICATE PRESENCE OF '?' IN DIR:FILENAME.TYP ; SCAN4: LDA QMCNT ;NUMBER OF QUESTION MARKS ORA A ;SET ZERO FLAG RET ; ; SCANF -- SCAN TOKEN PTED TO BY HL FOR A MAX OF B BYTES; PLACE IT INTO ; FILE NAME FIELD PTED TO BY DE; EXPAND AND INTERPRET WILD CARDS OF ; '*' AND '?'; ON EXIT, DE PTS TO TERMINATING DELIMITER ; SCANF: CALL SDELM ;DONE IF DELIMITER ENCOUNTERED RZ INX D ;PT TO NEXT BYTE IN FCB CPI '*' ;IS (DE) A WILD CARD? JNZ SCANF1 ;CONTINUE IF NOT ; ; HANDLE WILD FIELD ; MVI A,'?' ;PLACE '?' IN FCB AND DON'T ADVANCE HL IF SO STAX D CALL SCQ ;SCANNER COUNT QUESTION MARKS JMP SCANF2 ; ; HANDLE NORMAL CHARS, INCL '?' ; SCANF1: STAX D ;STORE FILENAME CHAR IN FCB INX H ;PT TO NEXT CHAR IN COMMAND LINE CPI '?' ;CHECK FOR QUESTION MARK (WILD) CZ SCQ ;SCANNER COUNT QUESTION MARKS ; ; COUNT DOWN CHARS ; SCANF2: DCR B ;COUNT DOWN JNZ SCANF ;DECREMENT CHAR COUNT UNTIL 8 ELAPSED ; ; FLUSH TO NEXT DELIMITER ; SCANF3: CALL SDELM ;8 CHARS OR MORE - SKIP UNTIL DELIMITER RZ ;ZERO FLAG SET IF DELIMITER FOUND INX H ;PT TO NEXT CHAR IN COMMAND LINE JMP SCANF3 ; ; INCREMENT QUESTION MARK COUNT FOR SCANNER ; THIS ROUTINE INCREMENTS THE COUNT OF THE NUMBER OF QUESTION MARKS IN ; THE CURRENT FCB ENTRY ; SCQ: PUSH H ;SAVE HL LXI H,QMCNT ;GET COUNT INR M ;INCREMENT POP H ;GET HL RET ; ; SCAN FOR AND EXTRACT DISK/USER INFO ASSUMING DU: FORM ; ON ENTRY, DE PTS TO FIRST BYTE OF FCB CONTAINING POSSIBLE DU FORM ; ON EXIT, ZERO FLAG SET MEAN OK AND TEMPDR AND TEMPUSR SET ; DUSCAN: PUSH H ;SAVE REGS PUSH D CALL DUS ;DO SCAN POP D ;RESTORE REGS POP H RET DUS: CALL GETDUOK ;OK FOR DU FORM? JZ DIRSERR ;ABORT IF NOT XCHG ;PTR IN HL INX H ;PT TO FIRST BYTE OF FN CALL GETMDISK ;GET MAX DISK MOV B,A ;... IN B INR B ;B=MAX DISK + 1 MOV A,M ;GET FIRST CHAR CPI 'A' ;CONVERT POSSIBLE DRIVE SPEC TO NUMBER JC DUS1 ;IF LESS THAN 'A', MUST BE DIGIT ; ; SET DISK NUMBER (A=1) ; SUI 'A'-1 ;CONVERT DRIVE NUMBER TO 1-16 CMP B ;COMPARE AGAINST MAX DISK + 1 JNC DUSE1 ;INVALID DISK NUMBER STA TEMPDR ;SET TEMPORARY DRIVE NUMBER INX H ;PT TO NEXT CHAR MOV A,M ;SEE IF IT IS A SPACE CPI ' ' RZ CALL DIGCK ;CHECK FOR DIGIT RC ; ; SET USER NUMBER ; DUS1: PUSH H ;SAVE PTR TO DIGITS MVI B,2 ;UP TO 2 DIGITS DUS1A: MOV A,M ;CHECK FOR DIGIT OR SPACE CPI ' ' ;IF SPACE, THEN NO DIGIT JZ DUS2 CALL DIGCK ;CHECK FOR DIGIT JC DUSE INX H DCR B JNZ DUS1A ;COUNT DOWN MOV A,M ;3RD CHAR CPI ' ' ;MUST BE SPACE JNZ DUSE DUS2: POP H CALL GETMUSER ;GET MAX USER NUMBER MOV C,A ;... IN C INR C ;MAXUSR+1 CALL NUM ;GET NUMBER CMP C ;COMPARE AGAINST MAXUSR+1 JNC DUSE1 STA TEMPUSR ;SAVE USER NUMBER XRA A ;SET OK RET DUSE: POP H ;CLEAR STACK DUSE1: XRA A DCR A RET ; ; SCAN FOR DIR FORM ; ON ENTRY, DE PTS TO FCB CONTAINING NAME TO CHECK FOR ; ON EXIT, IF FOUND, Z AND TEMPUSR AND TEMPDR SET ; DIRSCAN: PUSH H ;SAVE REGS PUSH D CALL DIRS ;DO SCAN POP D ;RESTORE REGS POP H RET DIRS: CALL GETNDR ;PT TO NAMED DIR JZ DIRSERR ;ABORT IF NONE XCHG ;PTR IN HL INX H ;PT TO FN DIRS1: LDAX D ;GET NEXT CHAR ORA A ;ZERO IF END OF DIR JZ DIRSERR INX D ;PT TO DIR NAME INX D PUSH H ;SAVE PTR TO FILE NAME PUSH D ;SAVE PTR TO DIR ENTRY MVI B,8 ;MATCH? DIRS2: LDAX D ;GET BYTE CMP M ;COMPARE JNZ DIRS3 INX H ;PT TO NEXT INX D DCR B JNZ DIRS2 ;COUNT DOWN DIRS3: POP D ;RESTORE REGS POP H JZ DIRS4 XCHG ;ADVANCE TO NEXT ENTRY LXI B,16 ;8 BYTES FOR NAME + 8 BYTES FOR PASSWORD DAD B XCHG JMP DIRS1 ; ; NO DIR match ; DIRSERR: XRA A ;RETURN NZ DCR A RET ; ; DIR match ; DIRS4: DCX D ;PT TO USER LDAX D ;GET USER STA TEMPUSR DCX D ;PT TO DISK LDAX D ;GET IT STA TEMPDR ;A=1 XRA A ;SET Z RET ; ; SKIP OVER SPACES PTED TO BY HL ; ON RETURN, ZERO FLAG SET MEANS WE HIT EOL OR CMDSEP ; SKSP: MOV A,M ;GET NEXT CHAR INX H ;PT TO NEXT CPI ' ' ;SPACE? JZ SKSP DCX H ;PT TO NON-SPACE RET ; ; CHECK TO SEE IF HL PTS TO DELIMITER; IF SO, RET W/ZERO FLAG SET ; SDELM: MOV A,M ;GET NEXT CHAR FROM LINE CPI ' '+1 ;DELIM IF <= JC ZERO CPI '=' ;'='=DELIMITER RZ CPI 5FH ;UNDERSCORE=DELIMITER RZ CPI '.' ;'.'=DELIMITER RZ CPI ':' ;':'=DELIMITER RZ CPI ',' ;','=DELIMITER RZ CPI '<' ;'<'=DELIMITER RZ CPI '>' ;'>'=DELIMITER RZ ;FALL THRU TO TSTEOL ; ; CHECK TO SEE IF CHAR IN A IS EOL OR CMDSEP ; TSTEOL: ORA A ;EOL? RZ ;RETURN WITH FLAG CPI CMDSEP ;COMMAND SEPARATOR? RET ; ; RETURN WITH A=0 AND Z ; ZERO: XRA A RET ; ; CONVERT NUMBER STRING PTED TO BY HL INTO A NUMBER IN A ; NUM: PUSH B LXI B,1100H ;C=ACCUMULATED VALUE, B=CHAR COUNT ; (C=0, B=11) NUM1: MOV A,M ;GET CHAR CALL SDELM ;DONE IF DELIMITER JZ NUM2 INX H ;PT TO NEXT CHAR CALL DIGCK ;CHECK FOR DIGIT IN A JC NUMERR MOV D,A ;DIGIT IN D MOV A,C ;NEW VALUE = OLD VALUE * 10 RLC ;*2 JC NUMERR RLC ;*4 JC NUMERR ADD C ;*5 JC NUMERR RLC ;*10 JC NUMERR ADD D ;NEW VALUE = OLD VALUE * 10 + DIGIT JC NUMERR ;CHECK FOR RANGE ERROR MOV C,A ;SET NEW VALUE DCR B JNZ NUM1 ;COUNT DOWN ; ; RETURN FROM NUMBER ; NUM2: MOV A,C ;GET ACCUMULATED VALUE POP B ORA A ;CLEAR CARRY RET ; ; RESTORE STACK AND RETURN WITH CARRY SET ; NUMERR: POP B STC RET ; ; CHECK TO SEE IF A IS A DIGIT ; IF SO, RETURN ITS VALUE ; IF NOT, RETURN WITH CARRY SET ; DIGCK: SUI '0' ;DIGIT? RC ;ERROR CPI 10 ;RANGE? JNC DIGCK1 CMC ;FLIP CARRY RET DIGCK1: STC ;SET CARRY RET ; ; INIT FCB PTED TO BY DE ; INITFCB: XRA A STAX D ;SET DEFAULT DISK (DN BYTE IS 0) INX D ;PT TO FILE NAME FIELD CALL IFCB ;FILL 1ST PART OF FCB; FALL THRU TO IFCB TO RUN AGAIN ; ; FILL FN, FT, EX, S1, S2, RC, AND FOLLOWING CR (OR DN) FIELDS ; IFCB: MVI B,11 ;STORE 11 SPACES MVI A,' ' CALL FILL XRA A STAX D ;SET EX TO ZERO INX D CALL RETUD ;GET CURRENT USER MOV A,C STAX D ;SET S1 TO CURRENT USER INX D MVI B,3 ;STORE 3 ZEROES XRA A ;FALL THRU TO FILL ; ; FILL MEMORY POINTED TO BY DE WITH CHAR IN A FOR B BYTES ; FILL: STAX D ;FILL WITH BYTE IN A INX D ;PT TO NEXT DCR B ;COUNT DOWN JNZ FILL RET ; ; COPY HL TO DE FOR B BYTES ; LDIR: MOV A,M ;GET STAX D ;PUT INX H ;PT TO NEXT INX D DCR B ;COUNT DOWN JNZ LDIR RET ; ; BUFFERS ; COMMSG: DB 'COM' ;FILE TYPE OF COM FILE COLON: DS 1 ;INDICATES THAT CURRENT TOKEN CONTAINS DIR/DU DUFIRST: DS 1 ;DU FIRST = 0FFH, DIR FIRST = 0 ENDCHAR: DS 1 ;TERMINATING CHAR IN SCAN ERRFLG: DS 1 ;ERROR FLAG (NUMBER OF QUESTION MARKS IN HDR) FCBDN: DS 1 DS 8 FCBFT: DS 3 DS 4 DS 16 DS 4 MYCOLON: DS 1 ;INDICATES COMMAND BEGINS WITH DIR REFERENCE NXTCHR: DS 2 ;PTR TO NEXT CHAR IN COMMAND SEQUENCE QMCNT: DS 1 ;QUESTION MARK COUNT SCFLUSH: DS 1 ;FLUSH TO SPACE, ETC, ON SCANNER (0=NO) TAILSV: DS 2 ;PTR TO COMMAND TAIL TEMPDR: DS 1 ;TEMPORARY DRIVE REF TEMPUSR: DS 1 ;TEMPORARY USER NUMBER REF END ; ; Z3LIB Module Name: Z3PRS2 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; ZFNAME ; Module External References: ; GETDUOK GETMDISK GETMUSER GETNDR ; RETUD CAPSTR ; ; ; External References ; EXT RETUD,CAPSTR,GETDUOK,GETMDISK,GETMUSER,GETNDR ; ; Basic Equates ; CMDSEP equ ';' ;command separator TFCB equ 5CH ;FCB Buffer TFCB2 equ 6CH ;2nd FCB Buffer TBUFF equ 80H ;Temporary Buffer ; ; PARSE TOKEN PTED TO BY HL INTO FCB PTED TO BY DE ; ON INPUT, ; HL pts to token, ending in any valid delimiter ; DE pts to 36-byte FCB ; A = Flag: ; A = 0 if scan for DIR form before DU ; A = 1 if scan for DU form before DIR ; ON OUTPUT, ; HL pts to char following token ; A = Number of Question Marks in File Name and Zero Flag Set ; Accordingly ; ZFNAME:: PUSH B ;SAVE BC STA DUFIRST ;SET FLAG CALL CAPSTR ;CAPITALIZE INPUT PUSH D ;SAVE PTR TO FCB CALL INITFCB ;INIT IT POP D ;GET PTR BACK PUSH D ;SAVE PTR AGAIN CALL SCANNER ;SCAN LINE POP D ;RESTORE PTR POP B ;RESTORE BC LDA QMCNT ;CHECK FOR QUESTION MARKS ORA A RET ; ; EXTRACT TOKEN FROM COMMAND LINE AND PLACE IT INTO FCB PTED TO BY DE ; FORMAT FCBDN FCB IF TOKEN RESEMBLES FILE NAME AND TYPE (FILENAME.TYP) ; ON INPUT, HL PTS TO NEXT CHAR AND DE PTS TO FCB ; ON OUTPUT, HL PTS TO DELIMITER AFTER TOKEN AND ZERO FLAG IS RESET ; IF '?' IS IN TOKEN ; ; ENTRY POINTS: ; SCANNER - LOAD TOKEN INTO FCB PTED TO BY DE ; ON EXIT, HL PTS TO ENDING DELIMITER ; SCANNER: XRA A ;A=0 STAX D ;SET DEFAULT DRIVE STA TEMPDR ;SET TEMPORARY DRIVE NUMBER TO DEFAULT STA QMCNT ;ZERO QUESTION MARK COUNTER CALL RETUD ;GET USER/DISK MOV A,C ;GET USER STA TEMPUSR ;SET TEMPUSR PUSH D ;SAVE PTR TO FIRST BYTE OF FCB MVI B,8 ;8 CHARS MAX CALL SCANF ;PLACE FIRST TOKEN INTO FILE NAME FIELD POP D ;GET PTR TO FIRST BYTE OF FCB MOV A,M ;GET TERMINATING CHAR STA ENDCHAR ;SET ENDING CHAR CPI ':' ;COLON? JNZ SCAN1 ;NO, WE HAVE A FILE NAME INX H ;PT TO CHAR AFTER COLON ; ; CHECK FOR DU: FORM FIRST ; LDA DUFIRST ;CHECK DUFIRST FLAG ORA A JZ SCN1 CALL DUSCAN ;CHECK FOR DU: FORM JZ SUD1 ;GOT IT ; ; CHECK FOR DIR: FORM SECOND OR FIRST ; SCN1: CALL DIRSCAN ;CHECK FOR DIR: FORM JZ SUD1 ;GOT IT ; ; CHECK FOR DU SCAN FOR DUSECOND ; LDA DUFIRST ;CHECK DU FLAG ORA A JNZ SUD1 ; ; CHECK FOR DU: FORM SECOND ; CALL DUSCAN ;CHECK FOR DU: FORM ; ; WE HAVE A VALID DU OR DIR - TEMPDR/TEMPUSR CONTAIN DATA ; SUD1: LDA TEMPDR ;SET DRIVE STAX D ;... IN FCB ; ; REINIT FCB PTED TO BY DE ; PUSH D ;SAVE PTR INX D ;PT TO FN FIELD CALL IFCB ;ONLY PARTIAL INIT (17 BYTES TOTAL) POP D ; ; EXTRACT FILENAME FIELD ; XRA A STA QMCNT ;ZERO QUESTION MARK COUNTER PUSH D ;SAVE PTR TO FIRST BYTE OF FCB MVI B,8 ;8 CHARS MAX CALL SCANF ;STORE FILE NAME POP D ;GET PTR TO FIRST BYTE OF FCB MOV A,M ;GET OFFENDING CHAR STA ENDCHAR ;SET ENDING CHAR ; ; SKIP TO FILE TYPE FIELD ; HL PTS TO NEXT CHAR, DE PTS TO DN FIELD OF FCB ; SCAN1: LDA ENDCHAR ;GET ENDING CHAR XCHG LXI B,8 ;PT TO BEFORE FILE TYPE FIELD OF FCB DAD B XCHG ; ; EXTRACT FILETYPE FIELD ; MVI B,3 ;PREPARE TO EXTRACT FILE TYPE CPI '.' ;IF '.', WE HAVE A TYPE JNZ SCAN2 INX H ;PT TO CHAR AFTER '.' PUSH D CALL SCANF ;GET FCB FILE TYPE POP D SCAN2: ; ; SET USER NUMBER REFERENCED ; HL PTS TO NEXT CHAR, DE PTS TO BEFORE FCB FT ; XCHG LXI B,5 ;PT TO S1 FIELD DAD B XCHG LDA TEMPUSR ;STORE USER NUMBER HERE STAX D ; ; SET ZERO FLAG TO INDICATE PRESENCE OF '?' IN DIR:FILENAME.TYP ; LDA QMCNT ;NUMBER OF QUESTION MARKS ORA A ;SET ZERO FLAG RET ; ; SCANF -- SCAN TOKEN PTED TO BY HL FOR A MAX OF B BYTES; PLACE IT INTO ; FILE NAME FIELD PTED TO BY DE; EXPAND AND INTERPRET WILD CARDS OF ; '*' AND '?'; ON EXIT, DE PTS TO TERMINATING DELIMITER ; SCANF: CALL SDELM ;DONE IF DELIMITER ENCOUNTERED RZ INX D ;PT TO NEXT BYTE IN FCB CPI '*' ;IS (DE) A WILD CARD? JNZ SCANF1 ;CONTINUE IF NOT ; ; HANDLE WILD FIELD ; MVI A,'?' ;PLACE '?' IN FCB AND DON'T ADVANCE HL IF SO STAX D CALL SCQ ;SCANNER COUNT QUESTION MARKS JMP SCANF2 ; ; HANDLE NORMAL CHARS, INCL '?' ; SCANF1: STAX D ;STORE FILENAME CHAR IN FCB INX H ;PT TO NEXT CHAR IN COMMAND LINE CPI '?' ;CHECK FOR QUESTION MARK (WILD) CZ SCQ ;SCANNER COUNT QUESTION MARKS ; ; COUNT DOWN CHARS ; SCANF2: DCR B ;COUNT DOWN JNZ SCANF ;DECREMENT CHAR COUNT UNTIL 8 ELAPSED ; ; FLUSH TO NEXT DELIMITER ; SCANF3: CALL SDELM ;8 CHARS OR MORE - SKIP UNTIL DELIMITER RZ ;ZERO FLAG SET IF DELIMITER FOUND INX H ;PT TO NEXT CHAR IN COMMAND LINE JMP SCANF3 ; ; INCREMENT QUESTION MARK COUNT FOR SCANNER ; THIS ROUTINE INCREMENTS THE COUNT OF THE NUMBER OF QUESTION MARKS IN ; THE CURRENT FCB ENTRY ; SCQ: PUSH H ;SAVE HL LXI H,QMCNT ;GET COUNT INR M ;INCREMENT POP H ;GET HL RET ; ; SCAN FOR AND EXTRACT DISK/USER INFO ASSUMING DU: FORM ; ON ENTRY, DE PTS TO FIRST BYTE OF FCB CONTAINING POSSIBLE DU FORM ; ON EXIT, ZERO FLAG SET MEAN OK AND TEMPDR AND TEMPUSR SET ; DUSCAN: PUSH H ;SAVE REGS PUSH D CALL DUS ;DO SCAN POP D ;RESTORE REGS POP H RET DUS: CALL GETDUOK ;OK FOR DU FORM? JZ DIRSERR ;ABORT IF NOT XCHG ;PTR IN HL INX H ;PT TO FIRST BYTE OF FN CALL GETMDISK ;GET MAX DISK MOV B,A ;... IN B INR B ;B=MAX DISK + 1 MOV A,M ;GET FIRST CHAR CPI 'A' ;CONVERT POSSIBLE DRIVE SPEC TO NUMBER JC DUS1 ;IF LESS THAN 'A', MUST BE DIGIT ; ; SET DISK NUMBER (A=1) ; SUI 'A'-1 ;CONVERT DRIVE NUMBER TO 1-16 CMP B ;COMPARE AGAINST MAX DISK + 1 JNC DUSE1 ;INVALID DISK NUMBER STA TEMPDR ;SET TEMPORARY DRIVE NUMBER INX H ;PT TO NEXT CHAR MOV A,M ;SEE IF IT IS A SPACE CPI ' ' RZ CALL DIGCK ;CHECK FOR DIGIT RC ; ; SET USER NUMBER ; DUS1: PUSH H ;SAVE PTR TO DIGITS MVI B,2 ;UP TO 2 DIGITS DUS1A: MOV A,M ;CHECK FOR DIGIT OR SPACE CPI ' ' ;IF SPACE, THEN NO DIGIT JZ DUS2 CALL DIGCK ;CHECK FOR DIGIT JC DUSE INX H DCR B JNZ DUS1A ;COUNT DOWN MOV A,M ;3RD CHAR CPI ' ' ;MUST BE SPACE JNZ DUSE DUS2: POP H CALL GETMUSER ;GET MAX USER NUMBER MOV C,A ;... IN C INR C ;MAXUSR+1 CALL NUM ;GET NUMBER CMP C ;COMPARE AGAINST MAXUSR+1 JNC DUSE1 STA TEMPUSR ;SAVE USER NUMBER XRA A ;SET OK RET DUSE: POP H ;CLEAR STACK DUSE1: XRA A DCR A RET ; ; SCAN FOR DIR FORM ; ON ENTRY, DE PTS TO FCB CONTAINING NAME TO CHECK FOR ; ON EXIT, IF FOUND, Z AND TEMPUSR AND TEMPDR SET ; DIRSCAN: PUSH H ;SAVE REGS PUSH D CALL DIRS ;DO SCAN POP D ;RESTORE REGS POP H RET DIRS: CALL GETNDR ;PT TO NAMED DIR JZ DIRSERR ;ABORT IF NONE XCHG ;PTR IN HL INX H ;PT TO FN DIRS1: LDAX D ;GET NEXT CHAR ORA A ;ZERO IF END OF DIR JZ DIRSERR INX D ;PT TO DIR NAME INX D PUSH H ;SAVE PTR TO FILE NAME PUSH D ;SAVE PTR TO DIR ENTRY MVI B,8 ;MATCH? DIRS2: LDAX D ;GET BYTE CMP M ;COMPARE JNZ DIRS3 INX H ;PT TO NEXT INX D DCR B JNZ DIRS2 ;COUNT DOWN DIRS3: POP D ;RESTORE REGS POP H JZ DIRS4 XCHG ;ADVANCE TO NEXT ENTRY LXI B,16 ;8 BYTES FOR NAME + 8 BYTES FOR PASSWORD DAD B XCHG JMP DIRS1 ; ; NO DIR match ; DIRSERR: XRA A ;RETURN NZ DCR A RET ; ; DIR match ; DIRS4: DCX D ;PT TO USER LDAX D ;GET USER STA TEMPUSR DCX D ;PT TO DISK LDAX D ;GET IT STA TEMPDR ;A=1 XRA A ;SET Z RET ; ; CHECK TO SEE IF HL PTS TO DELIMITER; IF SO, RET W/ZERO FLAG SET ; SDELM: MOV A,M ;GET NEXT CHAR FROM LINE CPI ' '+1 ;DELIM IF <= JC ZERO CPI '=' ;'='=DELIMITER RZ CPI 5FH ;UNDERSCORE=DELIMITER RZ CPI '.' ;'.'=DELIMITER RZ CPI ':' ;':'=DELIMITER RZ CPI ',' ;','=DELIMITER RZ CPI '<' ;'<'=DELIMITER RZ CPI '>' ;'>'=DELIMITER RZ ;FALL THRU TO TSTEOL ; ; CHECK TO SEE IF CHAR IN A IS EOL OR CMDSEP ; TSTEOL: ORA A ;EOL? RZ ;RETURN WITH FLAG CPI CMDSEP ;COMMAND SEPARATOR? RET ; ; RETURN WITH A=0 AND Z ; ZERO: XRA A RET ; ; CONVERT NUMBER STRING PTED TO BY HL INTO A NUMBER IN A ; NUM: PUSH B LXI B,1100H ;C=ACCUMULATED VALUE, B=CHAR COUNT ; (C=0, B=11) NUM1: MOV A,M ;GET CHAR CALL SDELM ;DONE IF DELIMITER JZ NUM2 INX H ;PT TO NEXT CHAR CALL DIGCK ;CHECK FOR DIGIT IN A JC NUMERR MOV D,A ;DIGIT IN D MOV A,C ;NEW VALUE = OLD VALUE * 10 RLC ;*2 JC NUMERR RLC ;*4 JC NUMERR ADD C ;*5 JC NUMERR RLC ;*10 JC NUMERR ADD D ;NEW VALUE = OLD VALUE * 10 + DIGIT JC NUMERR ;CHECK FOR RANGE ERROR MOV C,A ;SET NEW VALUE DCR B JNZ NUM1 ;COUNT DOWN ; ; RETURN FROM NUMBER ; NUM2: MOV A,C ;GET ACCUMULATED VALUE POP B ORA A ;CLEAR CARRY RET ; ; RESTORE STACK AND RETURN WITH CARRY SET ; NUMERR: POP B STC RET ; ; CHECK TO SEE IF A IS A DIGIT ; IF SO, RETURN ITS VALUE ; IF NOT, RETURN WITH CARRY SET ; DIGCK: SUI '0' ;DIGIT? RC ;ERROR CPI 10 ;RANGE? JNC DIGCK1 CMC ;FLIP CARRY RET DIGCK1: STC ;SET CARRY RET ; ; INIT FCB PTED TO BY DE ; INITFCB: XRA A STAX D ;SET DEFAULT DISK (DN BYTE IS 0) INX D ;PT TO FILE NAME FIELD CALL IFCB ;FILL 1ST PART OF FCB CALL IFCB ;FILL 2ND PART OF FCB STAX D ;PLACE 0 IN CR FIELD RET ; ; FILL FN, FT, EX, S1, S2, RC, AND FOLLOWING CR (OR DN) FIELDS ; IFCB: MVI B,11 ;STORE 11 SPACES MVI A,' ' CALL FILL XRA A STAX D ;SET EX TO ZERO INX D CALL RETUD ;GET CURRENT USER MOV A,C STAX D ;SET S1 TO CURRENT USER INX D MVI B,3 ;STORE 3 ZEROES XRA A ;FALL THRU TO FILL ; ; FILL MEMORY POINTED TO BY DE WITH CHAR IN A FOR B BYTES ; FILL: STAX D ;FILL WITH BYTE IN A INX D ;PT TO NEXT DCR B ;COUNT DOWN JNZ FILL RET ; ; COPY HL TO DE FOR B BYTES ; LDIR: MOV A,M ;GET STAX D ;PUT INX H ;PT TO NEXT INX D DCR B ;COUNT DOWN JNZ LDIR RET ; ; BUFFERS ; DUFIRST: DS 1 ;DU FIRST = 0FFH, DIR FIRST = 0 ENDCHAR: DS 1 ;TERMINATING CHAR IN SCAN QMCNT: DS 1 ;QUESTION MARK COUNT TEMPDR: DS 1 ;TEMPORARY DRIVE REF TEMPUSR: DS 1 ;TEMPORARY USER NUMBER REF END ; ; Z3LIB Module Name: Z3PRS3 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; DNSCAN DUSCAN DIRSCAN ; Module External References: ; GETDUOK GETMDISK GETMUSER GETNDR ; RETUD CAPS ; ; ; External References ; EXT RETUD,CAPS,GETDUOK,GETMDISK,GETMUSER,GETNDR ; ; Basic Equates ; CMDSEP equ ';' ;Command Separator ; ; DNSCAN - SCAN FOR DISK NAME PTED TO BY HL ; ON INPUT, HL PTS TO DISK NAME (8 CHARS MAX) ; A=FLAG (0=SCAN DU FIRST, 0FFH=SCAN DIR FIRST) ; ON EXIT, A=0 AND ZERO FLAG SET IF NOT VALID DIR NAME ; A=0FFH AND NZ IF VALID, AND BC=DU (A=0) ; ; DNSCAN:: PUSH H ;SAVE KEY REGS PUSH D STA DUFIRST ;SET DUFIRST FLAG LXI D,DIRN ;PT TO DIR NAME BUFFER MVI B,8 ;8 CHARS MAX PUSH D CALL SCANF ;PLACE DIR NAME INTO DIR NAME BUFFER POP H ;HL PTS TO DIR NAME BUFFER ; ; CHECK FOR DU: FORM FIRST ; LDA DUFIRST ;CHECK DUFIRST FLAG ORA A JZ SCN1 CALL DUSCAN ;CHECK FOR DU: FORM JNZ SUD1 ;GOT IT CALL DIRSCAN ;CHECK FOR DIR: FORM JNZ SUD1 ; ; DIR NAME NOT FOUND ; ERROR: XRA A ;SET ERROR FLAG JMP EXIT ; ; CHECK FOR DIR: FORM SECOND OR FIRST ; SCN1: CALL DIRSCAN ;CHECK FOR DIR: FORM JNZ SUD1 ;GOT IT CALL DUSCAN ;CHECK FOR DU: FORM JZ ERROR ;ERROR IF NOT FOUND ; ; WE HAVE A VALID DU OR DIR - TEMPDR/TEMPUSR CONTAIN DATA ; SUD1: MVI A,0FFH ;SET OK FLAG ; ; EXIT - SET PSW AND RESTORE REGS ; EXIT: POP D ;RESTORE REGS POP H ORA A ;RETURN WITH NZ IF FOUND RET ; ; SCANF -- SCAN TOKEN PTED TO BY HL FOR A MAX OF B BYTES; PLACE IT INTO ; BUFFER PTED TO BY DE ; SCANF: CALL SDELM ;DONE IF DELIMITER ENCOUNTERED JZ SCANF1 ;SPACE FILL STAX D ;STORE BYTE INX H ;PT TO NEXT INX D DCR B ;COUNT DOWN JNZ SCANF RET SCANF1: MVI A,' ' ;FILL BUFFER WITH SPACES STAX D INX D ;PT TO NEXT DCR B ;COUNT DOWN JNZ SCANF1 RET ; ; SCAN FOR AND EXTRACT DISK/USER INFO ASSUMING DU: FORM ; ON ENTRY, HL PTS TO FIRST BYTE OF 8-BYTE BUFFER ; CONTAINING POSSIBLE DU FORM ; ON EXIT, NZ MEANS OK AND BC=DU OR Z=ERROR ; DUSCAN:: PUSH H ;SAVE REGS PUSH D CALL GETDUOK ;OK FOR DU FORM? JZ DUSE1 ;ABORT IF NOT CALL RETUD ;GET CURRENT DISK AND USER MOV A,B ;SET TEMP VALUES STA TEMPDR MOV A,C STA TEMPUSR CALL GETMDISK ;GET MAX DISK MOV B,A ;... IN B MOV A,M ;GET FIRST CHAR SUI 'A' ;CONVERT POSSIBLE DRIVE SPEC TO NUMBER JC DUS1 ;IF LESS THAN 'A', MUST BE DIGIT ; ; SET DISK NUMBER (A=1) ; CMP B ;COMPARE AGAINST MAX DISK + 1 JNC DUSE1 ;INVALID DISK NUMBER STA TEMPDR ;SET TEMPORARY DRIVE NUMBER INX H ;PT TO NEXT CHAR CALL SDELM ;CHECK FOR DELIMITER JZ DUSOK CALL DIGCK ;CHECK FOR DIGIT JC DUSE1 ;ERROR IF NOT ; ; SET USER NUMBER ; DUS1: PUSH H ;SAVE PTR TO DIGITS MVI B,2 ;UP TO 2 DIGITS DUS1A: CALL SDELM ;DELIMITER? JZ DUS2 CALL DIGCK ;CHECK FOR DIGIT JC DUSE INX H DCR B JNZ DUS1A ;COUNT DOWN CALL SDELM ;MUST BE DELIMITER JNZ DUSE DUS2: POP H CALL GETMUSER ;GET MAX USER NUMBER MOV C,A ;... IN C INR C ;MAXUSR+1 CALL NUM ;GET NUMBER JC DUSE1 ;NUMBER ERROR CMP C ;COMPARE AGAINST MAXUSR+1 JNC DUSE1 STA TEMPUSR ;SAVE USER NUMBER DUSOK: LDA TEMPDR ;GET DISK MOV B,A ;... IN B LDA TEMPUSR ;GET USER MOV C,A ;... IN C POP D ;RESTORE REGS POP H XRA A ;SET OK DCR A ;NZ RET DUSE: POP H ;CLEAR STACK DUSE1: POP D ;RESTORE REGS POP H XRA A ;Z=ERROR RET ; ; SCAN FOR DIR FORM ; ON ENTRY, HL PTS TO 8-BYTE BUFFER CONTAINING NAME TO CHECK FOR ; ON EXIT, IF FOUND, NZ AND BC=DU, ELSE Z IF NOT FOUND ; DIRSCAN:: PUSH H ;SAVE REGS PUSH D XCHG ;DE PTS TO NAME CALL GETNDR ;PT TO NAMED DIR JZ DIRSERR ;ABORT IF NONE XCHG ;PTR IN HL TO NAME, DE TO DIR BUFFERS DIRS1: LDAX D ;GET NEXT CHAR ORA A ;ZERO IF END OF DIR JZ DIRSERR INX D ;PT TO DIR NAME INX D PUSH H ;SAVE PTR TO FILE NAME PUSH D ;SAVE PTR TO DIR ENTRY MVI B,8 ;MATCH? DIRS2: LDAX D ;GET BYTE CMP M ;COMPARE JNZ DIRS3 INX H ;PT TO NEXT INX D DCR B JNZ DIRS2 ;COUNT DOWN DIRS3: POP D ;RESTORE REGS POP H JZ DIRS4 XCHG ;ADVANCE TO NEXT ENTRY LXI B,16 ;8 BYTES FOR NAME + 8 BYTES FOR PASSWORD DAD B XCHG JMP DIRS1 ; ; NO DIR match ; DIRSERR: POP D ;RESTORE REGS POP H XRA A ;RETURN Z RET ; ; DIR match ; DIRS4: DCX D ;PT TO USER LDAX D ;GET USER MOV C,A ;... IN C DCX D ;PT TO DISK LDAX D ;GET DISK MOV B,A ;... IN B DCR B ;A=0 POP D ;RESTORE REGS POP H XRA A ;SET NZ DCR A RET ; ; CHECK TO SEE IF HL PTS TO DELIMITER; IF SO, RET W/ZERO FLAG SET ; SDELM: MOV A,M ;GET NEXT CHAR FROM LINE CALL CAPS ;CAPITALIZE CPI ' '+1 ;DELIM IF <= JC ZERO CPI '=' ;'='=DELIMITER RZ CPI 5FH ;UNDERSCORE=DELIMITER RZ CPI '.' ;'.'=DELIMITER RZ CPI ':' ;':'=DELIMITER RZ CPI ',' ;','=DELIMITER RZ CPI '<' ;'<'=DELIMITER RZ CPI '>' ;'>'=DELIMITER RZ ;FALL THRU TO TSTEOL ; ; CHECK TO SEE IF CHAR IN A IS EOL OR CMDSEP ; ORA A ;EOL? RZ ;RETURN WITH FLAG CPI CMDSEP ;COMMAND SEPARATOR? RET ; ; RETURN WITH A=0 AND Z ; ZERO: XRA A RET ; ; CONVERT NUMBER STRING PTED TO BY HL INTO A NUMBER IN A ; NUM: PUSH B LXI B,1100H ;C=ACCUMULATED VALUE, B=CHAR COUNT ; (C=0, B=11) NUM1: MOV A,M ;GET CHAR CALL SDELM ;DONE IF DELIMITER JZ NUM2 INX H ;PT TO NEXT CHAR CALL DIGCK ;CHECK FOR DIGIT IN A JC NUMERR MOV D,A ;DIGIT IN D MOV A,C ;NEW VALUE = OLD VALUE * 10 RLC ;*2 JC NUMERR RLC ;*4 JC NUMERR ADD C ;*5 JC NUMERR RLC ;*10 JC NUMERR ADD D ;NEW VALUE = OLD VALUE * 10 + DIGIT JC NUMERR ;CHECK FOR RANGE ERROR MOV C,A ;SET NEW VALUE DCR B JNZ NUM1 ;COUNT DOWN ; ; RETURN FROM NUMBER ; NUM2: MOV A,C ;GET ACCUMULATED VALUE POP B ORA A ;CLEAR CARRY RET ; ; RESTORE STACK AND RETURN WITH CARRY SET ; NUMERR: POP B STC RET ; ; CHECK TO SEE IF A IS A DIGIT ; IF SO, RETURN ITS VALUE ; IF NOT, RETURN WITH CARRY SET ; DIGCK: SUI '0' ;DIGIT? RC ;ERROR CPI 10 ;RANGE? JNC DIGCK1 CMC ;FLIP CARRY RET DIGCK1: STC ;SET CARRY RET ; ; BUFFERS ; DUFIRST: DS 1 ;DU FIRST = 0FFH, DIR FIRST = 0 DIRN: DS 8 ;DIRECTORY NAME BUFFER TEMPDR: DS 1 ;TEMPORARY DRIVE REF TEMPUSR: DS 1 ;TEMPORARY USER NUMBER REF END ; ; Z3LIB Module Name: Z3PWHL ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; PUTWHL ; Module External References: ; ENVPTR ; ext envptr ; ; PUTWHL sets the wheel byte to the value in A. ; No registes are affected. ; putwhl:: push h push d push psw lhld envptr ;pt to environment lxi d,29H ;pt to wheel byte address dad d mov a,m ;get address in HL inx h mov h,m mov l,a pop psw ;get wheel byte mov m,a ;put wheel byte in A pop d ;restore regs pop h ret end ; ; Z3LIB Module Name: Z3PZNC ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; PUTZNC ; Module External References: ; GETENV ; ext getenv ; ; PUTZNC sets from the address in HL the ptr to the next character which ; ZEX will return. Carry Flag is Set if data not available. ; putznc:: push h call getenv ;pt to environment mov a,h ;any environment? ora l jz error push d ;pt to message byte lxi d,34 ;offset to message ptr dad d mov e,m ;get address of messages inx h mov d,m xchg ;HL pts to message pop d mov a,h ;any messages? ora l jz error push d ;pt to Zex Next Char Address lxi d,9 dad d pop d ;restore DE xchg shld temp ;save DE xchg pop d ;get ptr to next char mov m,e ;get address inx h mov m,d push d ;save ptr lhld temp xchg ;restore DE pop h xra a ;set Z and Clear Carry ret error: pop h ;restore HL stc ;set carry ret temp: ds 2 ;2 bytes end ; ; Z3LIB Module Name: Z3PZR ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; PUTZRUN ; Module External References: ; GETENV ; ext getenv ; ; PUTZRUN sets the ZEX run message byte with the value in A. ; Carry Flag is Set if no such message available. ; putzrun:: push h push psw ;save value call getenv ;pt to environment mov a,h ;any environment? ora l jz error push d ;pt to message byte lxi d,34 ;offset to message ptr dad d mov e,m ;get address of messages inx h mov d,m xchg ;HL pts to message pop d mov a,h ;any messages? ora l jz error push d ;pt to Zex Running Flag lxi d,8 dad d pop d pop psw ;get byte mov m,a ;put byte pop h ;restore HL ret error: pop psw ;restore A pop h ;restore HL stc ;set carry ret end ; ; Z3LIB Module Name: Z3QCOUT ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; QCOUT ; Module External References: ; GETQUIET CCOUT ; ext getquiet,ccout ; ; QCOUT outputs the character in A with control character processing ; if the quiet flag says it is OK to do so. ; qcout:: push psw ;affect no regs call getquiet ;get flag jz notquiet ;not quiet, so print pop psw ;restore PSW ret notquiet: pop psw ;restore PSW jmp ccout ;perform normal output end ; ; Z3LIB Module Name: Z3QCRLF ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; QCRLF ; Module External References: ; GETQUIET CRLF ; ext getquiet,crlf ; ; QCRLF outputs the CR-LF sequence if the quiet flag ; says it is OK to do so. ; qcrlf:: push psw ;affect no regs call getquiet ;get flag jz notquiet ;not quiet, so print pop psw ;restore PSW ret notquiet: pop psw ;restore PSW jmp crlf ;perform normal output end ; ; Z3LIB Module Name: Z3QOUT ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; QOUT ; Module External References: ; GETQUIET COUT ; ext getquiet,cout ; ; QOUT outputs the character in A if the quiet flag ; says it is OK to do so. ; qout:: push psw ;affect no regs call getquiet ;get flag jz notquiet ;not quiet, so print pop psw ;restore PSW ret notquiet: pop psw ;restore PSW jmp cout ;perform normal output end ; ; Z3LIB Module Name: Z3QPRINT ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; QPRINT ; Module External References: ; GETQUIET PRINT ; ext getquiet,print ; ; QPRINT prints the string at the return address if the quiet flag ; says it is OK to do so. QPRINT returns to the byte following this ; string on exit. ; qprint:: push psw ;affect no regs call getquiet ;get flag jz notquiet ;not quiet, so print pop psw ;restore PSW xthl ;get ptr to string push psw ;save PSW qpr1: mov a,m ;get next char inx h ;pt to following char ora a ;end of string? jnz qpr1 pop psw ;restore PSW xthl ;done ret notquiet: pop psw ;restore PSW jmp print ;perform normal print end ; ; Z3LIB Module Name: Z3QPSTR ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; QPSTR ; Module External References: ; GETQUIET PSTR ; ext getquiet,pstr ; ; QPSTR prints the string pted to by HL if the quiet flag ; says it is OK to do so. ; qpstr:: push psw ;affect no regs call getquiet ;get flag jz notquiet ;not quiet, so print pop psw ;restore PSW ret notquiet: pop psw ;restore PSW jmp pstr ;perform normal print end ; ; Z3LIB Module Name: Z3ROOT ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; ROOT ; Module External References: ; ENVPTR RETUD ; ext envptr,retud ; ; ROOT returns the DU of the root directory in BC. No other registers ; are affected. ; root:: push d ;save DE push h ;save HL lhld envptr ;pt to environment lxi d,9 ;pt to path entry dad d mov e,m ;get path address in DE inx h mov d,m xchg ;HL pts to path call retud ;get current DU mov a,h ;no path? ora l jz rootx rootl: mov a,m ;get next path element ora a ;end of path? jz rootx ;done if so call retud ;get current DU cpi '$' ;current disk? jz root1 mov b,a ;get disk in B dcr b ;adjust for A=0 root1: inx h ;pt to user mov a,m ;get user inx h ;pt to next path element cpi '$' ;current user? jz rootl ;advance mov c,a ;set user jmp rootl ;continue rootx: pop h ;restore HL pop d ;restore DE ret end ; ; Z3LIB Module Name: Z3SHEMPTY ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; SHEMPTY ; Module External References: ; GETSH ; ext getsh ; ; SHEMPTY tests the shell stack to see if it is empty. If so, ; A=0 and Zero Flag Set (Z), else A<>0 and NZ. ; shempty:: push h ;save HL call getsh ;get ptr to shell stack jz noshell ;error if no shell stack mov a,m ;check first element noshell: ora a ;set flags pop h ;get HL ret end ; ; Z3LIB Module Name: Z3SHFULL ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; SHFULL ; Module External References: ; GETSH ; ext getsh ; ; Macros ; putrg macro push h push d push b endm getrg macro pop b pop d pop h endm ; ; SHFULL tests to see if the Shell Stack is full. A=0 and Zero ; Flag Set (Z) if so, else A<>0 and NZ. ; shfull:: putrg ;save registers ; ; Get Shell Data ; call getsh ;get ptr to shell stack jz noshell ;error if no shell stack mov e,b ;size of element in DE mvi d,0 mov b,a ;number of elements in B mvi c,0ffh ;set not full code ; ; Check to see if shell stack is full ; fchk: mov a,m ;get next element ora a ;last element on stack? jz fchk1 ;stack ok dad d ;pt to next element dcr b ;count down jnz fchk ; ; No Shell Error - Say that Shell is Full ; noshell: mvi c,0 ;set full code fchk1: mov a,c ;get full code getrg ;restore registers ora a ;set flag ret end ; ; Z3LIB Module Name: Z3SHPOP ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; SHPOP ; Module External References: ; GETSH ; ext getsh ; ; Macros ; putrg macro push h push d push b endm getrg macro pop b pop d pop h endm ; ; SHPOP pops the top element off of the Shell Stack if possible. ; SHPOP returns with A=0 and Zero Flag Set (Z) if pop is successful, ; else SHPOP returns with A<>0 and Zero Flag Clear (NZ) if an error occurred. ; The following error codes are returned: ; 1 - no Shell Stack available ; 2 - Shell Stack is empty ; shpop:: putrg ;save registers ; ; Get Shell Data for Later Use ; call getsh ;get ptr to shell stack jz noshell ;error if no shell stack mov c,a ;save number of elements in C mov a,m ;get first element ora a ;empty stack? jz empty mov e,b ;DE=size of shell stack entry mvi d,0 xchg ;HL=dest dad d ;DE=source xchg copy: mvi m,0 ;set zero if no elements to copy mov a,c ;see if any elements to copy cpi 1 jz done dcr c ;count down elements push b ;save values copy1: ldax d ;copy stack entry mov m,a inx h ;pt to next inx d dcr b ;count down jnz copy1 pop b ;get values jmp copy done: getrg ;restore registers xra a ;all is well ret ; ; No Shell Stack Available ; noshell: getrg ;restore registers mvi a,1 ;error code ora a ret ; ; Shell Stack is Empty ; empty: getrg ;restore registers mvi a,2 ;error code ora a ret end ; ; Z3LIB Module Name: Z3SHPUSH ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; SHPUSH ; Module External References: ; GETSH2 ; ext getsh2 ; ; Macros ; putrg macro push h push d push b endm getrg macro pop b pop d pop h endm ; ; SHPUSH pushes the string (incl ending 0) pted to by HL onto ; the Shell Stack if possible. SHPUSH returns with A=0 and Zero Flag ; Set (Z) if push is successful, else SHPUSH returns with A<>0 and ; Zero Flag Clear (NZ) if an error occurred. The following error ; codes are returned: ; 1 - no Shell Stack available ; 2 - Shell Stack is full ; 3 - string is too long for Shell Stack entry ; shpush:: putrg ;save registers ; ; Get Shell Data for Later Use ; push h ;save ptr to string call getsh2 ;get ptr to shell stack pop h ;get ptr to string jz noshell ;error if no shell stack ; ; See if string is too long ; push h ;save ptr to string cksize: mov a,m ;get elt inx h ;pt to next ora a ;end of string? jz cks1 dcr e ;count down jnz cksize jmp toobig ;string is too long cks1: ; ; Check to see if shell stack is full ; call getsh2 ;get values for copy fchk: mov a,m ;get next element ora a ;last element on stack? jz fchk1 ;stack ok dad d ;pt to next element dcr b ;count down jnz fchk jmp noroom ;shell is full fchk1: ; ; Copy current shell stack up ; call getsh2 ;get shell stack values ; ; Point to end of new top element ; push b move0: mov a,b ;check for done cpi 1 jz move1 dad d ;pt to next dcr b ;count down jmp move0 move1: pop b mov c,e ;get count of elements in C dcx h ;pt to first byte to copy xchg ;DE pts to source dad d ;HL pts to destination ; ; Copy stack up one entry size ; move2: mov a,b ;check for copy done cpi 1 ;one less element jz move4 dcr b ;count down push b ;B=number of elements left to copy, C=size of each move3: ldax d ;get mov m,a ;put dcx h ;back up dcx d dcr c ;count down jnz move3 pop b ;get values jmp move2 move4: call getsh2 ;get ptr to shell stack pop d ;get ptr to string ; ; Copy new shell entry from DE to HL ; copy: ldax d ;get byte mov m,a ;put byte inx h ;pt to next inx d ora a ;done? jnz copy getrg ;restore registers xra a ;OK return ret ; ; No Shell Stack Available ; noshell: pop h ;restore HL getrg ;restore registers mvi a,1 ;error code ora a ret ; ; No Room on Shell Stack ; noroom: pop h ;restore HL getrg ;restore registers mvi a,2 ;error code ora a ret ; ; String is too large ; toobig: pop h ;restore HL getrg ;restore registers mvi a,3 ;error code ora a ret end ; ; Z3LIB Module Name: Z3WAIT1 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; WAIT1S ; Module External References: ; GETSPEED ; ext getspeed ; ; WAIT1S delays for approximately 1 second. The ZCPR3 environment ; (particularly processor speed data) is assumed. ; wait1s:: push psw ;affect no regs push d push b call getspeed ;get processor speed jnz w1 mvi a,4 ;assume 4MHz if none given w1: mov b,a ;speed in B loop0: mvi d,50 ;50 outer loops = 50*20,010 = 1,000,500 cycles loop1: mvi e,230 ;230 inner loops = 230*87 = 20,010 cycles loop2: xthl ;18 cycles xthl ;+18 = 36 cycles xthl ;+18 = 54 cycles xthl ;+18 = 72 cycles dcr e ;+ 5 = 77 cycles jnz loop2 ;+10 = 87 cycles dcr d ;outer loop jnz loop1 dcr b ;speed loop jnz loop0 pop b ;restore regs pop d pop psw ret end ; ; Z3LIB Module Name: Z3WAIT2 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; WAIT1MS ; Module External References: ; GETSPEED ; ext getspeed ; ; WAIT1MS delays for approximately 1 millisecond. The ZCPR3 environment ; (particularly processor speed data) is assumed. ; wait1ms:: push psw ;affect no regs push d push b call getspeed ;get processor speed jnz w1 mvi a,4 ;assume 4MHz if none given w1: mov b,a ;speed in B loop0: mvi e,20 ;20 inner loops = 20*51 = 1020 cycles loop1: xthl ;18 cycles xthl ;+18 = 36 cycles dcr e ;+ 5 = 41 cycles jnz loop1 ;+10 = 51 cycles dcr b ;speed loop jnz loop0 pop b ;restore regs pop d pop psw ret end ; ; Z3LIB Module Name: Z3WAIT3 ; Author: Richard Conn ; Z3LIB Version Number: 1.0 ; Module Version Number: 1.0 ; Module Entry Points: ; WAITP1S ; Module External References: ; GETSPEED ; ext getspeed ; ; WAITP1S delays for approximately 0.1 second. The ZCPR3 environment ; (particularly processor speed data) is assumed. ; waitp1s:: push psw ;affect no regs push d push b call getspeed ;get processor speed jnz w1 mvi a,4 ;assume 4MHz if none given w1: mov b,a ;speed in B loop0: mvi d,5 ;5 outer loops = 5*20,010 = 100,050 cycles loop1: mvi e,230 ;230 inner loops = 230*87 = 20,010 cycles loop2: xthl ;18 cycles xthl ;+18 = 36 cycles xthl ;+18 = 54 cycles xthl ;+18 = 72 cycles dcr e ;+ 5 = 77 cycles jnz loop2 ;+10 = 87 cycles dcr d ;outer loop jnz loop1 dcr b ;speed loop jnz loop0 pop b ;restore regs pop d pop psw ret end