-BZ3MSG1 Z80 Z3MSG2 Z80OZ3MSG3 Z80{Z3MSG4 Z80TZ3MSG5 Z80xZ3MSG6 Z80!xZ3MSG7 Z80&\Z3MSG8 Z80,Z3MSG9 Z801 Z3MSGA Z808yZ3MSGB Z80<+Z3MSGC Z80DZ3MSGD Z80JiZ3MSGE Z80P&Z3MSGF Z80UZ3MSGG Z80[Z3MSGH Z80aZ3PCL Z80gOZ3PCRT Z80z4Z3PDUOK Z80(#Z3PFIND Z80!`%Z3PFNX Z80 Z3PMDISKZ80HZ3PMUSERZ80LZ3PPRT Z80hZ3PQUIETZ80Z3PRGLD Z80Z3PRS1 Z80pZZ3PRS2 Z80DRZ3PRS3 Z803ՠZ3PSPEEDZ80ŘZ3PWHL Z80Z3PZNC Z80Z3PZR Z80M&Z3QCOUT Z80PZ3QCRLF Z80eZ3QNDR Z80Z3QOUT Z80Z3QPRINTZ803Z3QPSTR Z80cZ3ROOT Z80 Z3SHEMPTZ80Z3SHFULLZ80IZ3SHPOP Z80 Z3SHPUSHZ80* Z3SNDR Z80@Z3W1 Z80TZ3W2 Z80[/Z3W3 Z80a ; ; Z3LIB Module Name: Z3MSG1 ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public geter1 ext getmsg ; ; GETER1 returns the error flag message in A. Zero Flag is set ; accordingly. ; geter1: push hl ;save HL call getmsg ;get ptr to messages ld a,(hl) ;get error flag pop hl or a ;set Z flag according to error flag ret end ; ; Z3LIB Module Name: Z3MSG2 ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public puter1 ext getmsg ; ; PUTER1 sets the error flag message in A. No registers are affected. ; puter1: push hl ;save HL push af ;save PSW call getmsg ;get ptr to messages pop af ;get PSW ld (hl),a ;store message pop hl ret end ; ; Z3LIB Module Name: Z3MSG3 ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public geter2 ext getmsg ; ; GETER2 returns the error code message in A. A=0 and Zero Flag Set ; if No Error. ; geter2: push hl ;save HL push de ;save DE call getmsg ;get ptr to messages ld de,6 ;offset to code add hl,de ld a,(hl) ;get error flag pop de ;get DE pop hl ;get HL or a ;set flag accordingly ret end ; ; Z3LIB Module Name: Z3MSG4 ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public puter2 ext getmsg ; ; PUTER2 sets the error code message in A. No registers are affected. ; puter2: push hl ;save HL push de ;save DE push af ;save PSW call getmsg ;get ptr to messages ld de,6 ;offset to code add hl,de pop af ;get PSW ld (hl),a ;store message pop de pop hl ret end ; ; Z3LIB Module Name: Z3MSG5 ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public getcst ext getmsg ; ; GETCST returns the ZCPR3 command status message in A. A=0 and Zero ; Flag Set if command status is normal. ; getcst: push hl ;save HL call getmsg ;get ptr to messages inc hl ;offset of 3 inc hl inc hl ld a,(hl) ;get command status message pop hl or a ;set zero flag accordingly ret end ; ; Z3LIB Module Name: Z3MSG6 ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public qshell 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 hl ;save HL call getmsg ;get ptr to messages inc hl ;offset of 3 inc hl inc hl ld a,(hl) ;get command status message pop hl cp 1 ;set Z flag if shell ret end ; ; Z3LIB Module Name: Z3MSG7 ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public qerror 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 inc hl ;offset of 3 inc hl inc hl ld a,(hl) ;get command status message push af inc hl ;pt to error address ld a,(hl) inc hl ld h,(hl) ld l,a ;HL contains error address pop af cp 2 ;set Z flag if error ret end ; ; Z3LIB Module Name: Z3MSG8 ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public getzex 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 hl ;save HL push de ;save DE call getmsg ;get ptr to messages ld de,7 ;offset to message byte add hl,de ld a,(hl) ;get message byte pop de ;get DE pop hl ;get HL or a ;set flag accordingly ret end ; ; Z3LIB Module Name: Z3MSG9 ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public stopzex,strtzex,putzex ext getmsg ; ; STOPZEX suspends ZEX processing. No registers are affected. ; stopzex: push af ld a,2 ;suspend ZEX call putzex pop af ret ; ; STRTZEX resumes ZEX processing. No registers are affected. ; strtzex: push af xor a ;A=0 means to resume ZEX processing call putzex pop af ret ; ; PUTZEX sets the ZEX message byte in A. No registers are affected. ; putzex: push hl ;save HL push de ;save DE push af ;save PSW call getmsg ;get ptr to messages ld de,7 ;offset to message byte add hl,de pop af ;get PSW ld (hl),a ;store message pop de pop hl ret end ; ; Z3LIB Module Name: Z3MSGA ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public geterc 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 de ;save DE call getmsg ;get ptr to messages ld de,10h ;offset to buffer add hl,de ld a,(hl) ;get first char pop de ;get DE or a ;set flag ret end ; ; Z3LIB Module Name: Z3MSGB ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public puterc 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 hl ;save HL push de ;save DE push hl ;save ptr to string ld b,32 ;check size put1: ld a,(hl) ;get char or a ;zero = done jp z,put2 inc hl ;pt to next dec b ;count down jp nz,put1 pop hl ;clear stack and return error code pop de pop hl xor a ;return Z ret put2: call getmsg ;get ptr to messages ld de,10h ;offset to code add hl,de pop de ;get ptr to string put3: ld a,(de) ;copy string into buffer ld (hl),a inc hl ;pt to next inc de or a ;done? jp nz,put3 pop de ;restore regs pop hl xor a ;OK return dec a ;return NZ ret end ; ; Z3LIB Module Name: Z3MSGC ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public getreg 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 hl ;save HL push de ;save DE call getmsg ;get ptr to messages ld de,30h ;offset to registers add hl,de ld a,b ;get register number add a,l ;make HL pt to register ld l,a ld a,h adc a,0 ld h,a ld a,(hl) ;get register value pop de ;get DE pop hl ;get HL or a ;set flags ret end ; ; Z3LIB Module Name: Z3MSGD ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public putreg 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 hl ;save HL push de ;save DE push af ;save value call getmsg ;get ptr to messages ld de,30h ;offset to registers add hl,de ld a,b ;get register number add a,l ;make HL pt to register ld l,a ld a,h adc a,0 ld h,a pop af ;get value ld (hl),a ;put register value pop de ;get DE pop hl ;get HL ret end ; ; Z3LIB Module Name: Z3MSGE ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public erradr 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 af ;save PSW push de ;save DE call getmsg ;get ptr to messages ld de,4 ;offset to buffer add hl,de ld a,(hl) ;get address inc hl ld h,(hl) ld l,a ;HL = address pop de ;get DE pop af ret end ; ; Z3LIB Module Name: Z3MSGF ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public putcst 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 hl ;save HL push af ;save A call getmsg ;get ptr to messages inc hl ;offset of 3 inc hl inc hl pop af ;get code ld (hl),a ;set command status message pop hl ret end ; ; Z3LIB Module Name: Z3MSGG ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public getshm 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 hl ;save HL push de ;save DE call getmsg ;get ptr to messages ld de,13 ;offset to registers add hl,de ld a,b ;get register number add a,l ;make HL pt to register ld l,a ld a,h adc a,0 ld h,a ld a,(hl) ;get register value pop de ;get DE pop hl ;get HL or a ;set flags ret end ; ; Z3LIB Module Name: Z3MSGH ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public putshm 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 hl ;save HL push de ;save DE push af ;save value call getmsg ;get ptr to messages ld de,13 ;offset to registers add hl,de ld a,b ;get register number add a,l ;make HL pt to register ld l,a ld a,h adc a,0 ld h,a pop af ;get value ld (hl),a ;put register value pop de ;get DE pop hl ;get HL ret end ; ; Z3LIB Module Name: Z3PCL ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public putcl ext getcl1,getcl2 ; ; Macros ; putrg macro push bc push de push hl endm getrg macro pop hl pop de pop bc 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 ex de,hl ;DE pts to new line call getcl1 ;is command line available? jp nz,pcl1 ; ; Error Return ; nocl: getrg ;restore registers xor a ;ret Z ret ; ; Process Command Line ; pcl1: ld b,a ;char count in B ex de,hl ;HL pts to new line push hl ;save ptr to new line pcl2: ld a,(hl) ;go to end of line or a ;at end? jp z,pcl3 inc hl ;pt to next dec b ;count down jp nz,pcl2 pop hl ;clear stack jp 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: ex de,hl ;DE pts to last byte push de ;save ptr to last byte in case of error call getcl2 ;pt to tail of command line buffer ld a,(hl) ;get first char of tail cp ';' ;continuation? jp z,pcl4 or a ;done? jp z,pcl4 ld a,';' ;set continuation char ld (de),a inc de dec b ;count down jp z,pcl5 ;overflow ; ; Copy tail onto end of new command line ; pcl4: ld a,(hl) ;get next char ld (de),a ;store it inc hl ;pt to next inc de or a ;done? jp z,pcl6 dec b ;count down jp nz,pcl4 ; ; Command Line too Long ; pcl5: pop hl ;get ptr to end of old line ld (hl),0 ;store ending 0 pop af ;clear stack jp nocl ; ; New Command Line OK ; pcl6: pop af ;clear stack call getcl1 ;get ptr to buffer ld de,4 ;pt to first char in buffer ex de,hl add hl,de ex de,hl ld (hl),e ;store address inc hl ld (hl),d ;DE pts to first char of buffer pop hl ;HL pts to first char of new line ; ; Copy New Command Line into Buffer ; pcl7: ld a,(hl) ;copy ld (de),a inc hl inc de or a ;EOL? jp nz,pcl7 ; ; Exit with OK Code ; getrg ;restore regs xor a ;set NZ dec a ret end ; ; Z3LIB Module Name: Z3PCRT ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public putcrt ext envptr ; ; PUTCRT stores the selection of 0 or 1 in the CRT Selection buffer ; in the Environment Descriptor. ; On exit, A=0 and Zero Flag Set if invalid selection value (not 0 or 1) ; putcrt: push hl ;save regs push de cp 2 ;range check jp nc,pcerror push af ;save selection ld hl,(envptr) ;pt to environment ld de,2fh ;pt to entry add hl,de pop af ;get selection ld (hl),a ;store selection pop de ;get regs pop hl or 0ffh ;set NZ for OK ret pcerror: pop de ;restore registers pop hl xor a ;error return ret end ; ; Z3LIB Module Name: Z3PDUOK ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public putduok ext envptr ; ; PUTDUOK sets the DU OK byte from A. ; No registers are affected. ; putduok: push hl ;save regs push de push af ld hl,(envptr) ;pt to environment ld de,2eh ;pt to byte address add hl,de pop af ;get value ld (hl),a ;put byte in A pop de ;restore regs pop hl ret end ; ; Z3LIB Module Name: Z3PFIND ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public pfind 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 HL ; SAVE REGS PUSH DE LD (SEARCUR),A ; SET FLAG TO SEARCH CURRENT XOR A ; SET DISK NUMBER TO CURRENT LD (DE),A ; CHANGE FCB PUSH DE ; SAVE FCB PTR LD C,25 ; GET CURRENT DISK CALL BDOSH LD (CDISK),A ; SAVE CURRENT DISK LD (TDISK),A ; SET TEMP DISK LD C,32 ; GET CURRENT USER LD E,0FFH CALL BDOSH LD (CUSER),A ; SAVE CURRENT USER LD (TUSER),A ; SAVE TEMP USER POP DE ; GET FCB PTR CALL GETPATH ; GET ADDRESS OF EXTERNAL PATH IN HL LD A,(SEARCUR) ; SEARCH CURRENT? OR A ; 0=NO JP Z,PF1 ; ; LOOK FOR FILE WHOSE FCB IS PTED TO BY DE ; PF0: LD C,17 ; SEARCH FOR FIRST CALL BDOSH INC A ; FILE FOUND? JP NZ,PFFND ; ; ADVANCE TO NEXT ELEMENT IN PATH ; PF1: LD A,(HL) ; GET DRIVE NUMBER FROM PATH OR A ; 0=DONE=FILE NOT FOUND JP Z,PFNFND CALL GETDU ; GET DU IN BC CALL CKDUP ; CHECK FOR DUPLICATION OF PATH ENTRY INC HL ; PT TO NEXT PATH ENTRY INC HL JP Z,PF1 ; CONTINUE IF DUPLICATION OF PATH ENTRY PUSH DE ; SAVE FCB PTR PUSH BC ; SAVE BC LD A,B ; SET DISK LD (TDISK),A LD E,A LD C,14 ; SELECT DISK CALL BDOSH POP BC ; GET BC LD A,C ; SET USER LD (TUSER),A LD E,A LD C,32 ; SELECT USER CALL BDOSH POP DE ; GET FCB PTR JP PF0 ; CONTINUE SEARCH ; ; FILE FOUND FLAG SETTING ; PFFND: XOR A ; FOUND RETURN CODE DEC A ; SET NZ JP FNDEXIT ; ; FILE NOT FOUND ERROR ; PFNFND: XOR A ; FILE NOT FOUND FNDEXIT: PUSH AF ; SAVE RETURN CODE LD A,(CDISK) ; RESTORE CURRENT DISK LD E,A ; SAVE IN E LD C,14 ; SELECT DISK IN E CALL BDOS LD A,(CUSER) ; RESTORE CURRENT USER LD E,A ; SAVE IN E LD C,32 ; SELECT USER IN E CALL BDOS LD A,(TDISK) ; SET FOUND DISK LD B,A LD A,(TUSER) ; SET FOUND USER LD C,A POP AF ; GET RETURN CODE POP DE ; RESTORE REGS POP HL RET ; ; CHECK ALONG PATH FOR DUPLICATION OF ENTRY ; RETURN WITH Z IF SO ; CKDUP: PUSH HL ; SAVE PTRS PUSH DE ; SAVE FCB PUSH BC ; SAVE DU LD A,L ; SAVE LOW-ORDER ADDRESS LD (CURELT),A CALL GETPATH ; PT TO FIRST ELEMENT OF PATH CKDUP1: LD A,(CURELT) ; GET CURRENT ELEMENT CP L ; ARE WE THERE? JP Z,NODUP CALL GETDU ; GET ELEMENT IN BC INC HL ; PT TO NEXT PATH ELEMENT INC HL POP DE ; GET CURRENT DU IN DE PUSH DE ; SAVE IT AGAIN LD A,B ; COMPARE AGAINST PATH ELEMENT CP D JP NZ,CKDUP1 LD A,C CP E JP NZ,CKDUP1 ; NO MATCH, SO CONTINUE ; ; WE HAVE A DUPLICATE - RETURN Z ; POP BC ; RESTORE REGS POP DE POP HL XOR A ; SET Z RET ; ; NO DUPLICATES - RETURN NZ ; NODUP: POP BC ; RESTORE REGS POP DE POP HL XOR A ; SET NZ DEC A RET ; ; RETURN DU IN BC FOR CURRENT PATH ELEMENT PTED TO BY HL ; GETDU: LD A,(HL) ; GET DISK CP '$' ; CURRENT? JP NZ,GETDU1 LD A,(CDISK) ; SELECT CURRENT DISK INC A ; ADJUST GETDU1: DEC A ; SET DISK FOR A=0 LD B,A ; DISK IN B INC HL ; PT TO USER LD A,(HL) ; GET USER DEC HL ; PT BACK TO DISK CP '$' ; CURRENT? JP NZ,GETDU2 LD A,(CUSER) ; GET CURRENT USER GETDU2: LD C,A ; USER IN C RET ; ; CALL BDOS AND NOT CHANGE HL ; BDOSH: PUSH HL ; CALL BDOS, BUT SAVE HL PUSH DE CALL BDOS POP DE POP HL RET END ; ; Z3LIB Module Name: Z3PFNX ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public putfnx ext envptr ; ; PUTFNX sets the nth filename.typ to the FCB-entry pted to by HL ; (FCB+1 is pointed to by HL). On input, A=1 to 4 and HL pts to FCB+1. ; On output, A=0 and Zero Flag set if input A was out of range. ; putfnx: dec a ;check range cp 4 ;0 to 3 is valid jp nc,pfnxerr inc a ;set offset to 1-4 again push de push hl push af ;save A ld hl,(envptr) ;pt to environment ld de,52h ;pt to file name entry add hl,de ld de,11 ;offset to next name pop af ;get A pfnx1: dec a ;count down jp z,pfnx2 add hl,de ;pt to next jp pfnx1 pfnx2: pop de ;get ptr to FCB+1 push de push bc ;save BC ld b,11 ;11 bytes from DE to HL pfnx3: ld a,(de) ;copy ld (hl),a inc hl ;pt to next inc de dec b ;count down jp nz,pfnx3 pop bc ;restore regs pop hl pop de or 0ffh ;set NZ for OK ret pfnxerr: xor a ;error ret end ; ; Z3LIB Module Name: Z3PMDISK ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public putmdisk ext envptr ; ; PUTMDISK sets the maximum disk in A (disk A = 1). ; No registers are affected. ; putmdisk: push hl ;save regs push de push af ld hl,(envptr) ;pt to environment ld de,2ch ;pt to byte address add hl,de pop af ;get value ld (hl),a ;put value pop de ;restore regs pop hl ret end ; ; Z3LIB Module Name: Z3PMUSER ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public putmuser ext envptr ; ; PUTMUSER sets the maximum user in A. ; No registers are affected. ; putmuser: push hl ;save regs push de push af ld hl,(envptr) ;pt to environment ld de,2dh ;pt to byte address add hl,de pop af ;get value ld (hl),a ;put value pop de ;restore regs pop hl ret end ; ; Z3LIB Module Name: Z3PPRT ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public putprt ext envptr ; ; PUTPRT stores the selection of 0 to 3 in the PRT Selection buffer ; in the Environment Descriptor. ; On exit, A=0 and Zero Flag Set if invalid selection value (not 0 to 3) ; putprt: push hl ;save regs push de cp 4 ;range check jp nc,pperror push af ;save selection ld hl,(envptr) ;pt to environment ld de,30h ;pt to entry add hl,de pop af ;get selection ld (hl),a ;store selection pop de ;get regs pop hl or 0ffh ;set NZ for OK ret pperror: pop de ;restore registers pop hl xor a ;error return ret end ; ; Z3LIB Module Name: Z3PQUIET ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public putquiet ext envptr ; ; PUTQUIET sets the quiet byte in A. ; No registers are affected. ; putquiet: push hl ;save regs push de push af ld hl,(envptr) ;pt to environment ld de,28h ;pt to byte address add hl,de pop af ;get value ld (hl),a ;put value pop de ;restore regs pop hl ret end ; ; Z3LIB Module Name: Z3PRGLD ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public prgload ; ; 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 de ;save ptr to FCB (DE) ld hl,(bdos+1) ;get base address of BDOS ld a,h ;9 pages below BDOS (1st page below CCP) sub 9 ld h,a ld l,80h ;HL pts to load address ld (ldadr),hl ;set load address ld de,40h ;set FCB address add hl,de ld (ldfcb),hl ;address of FCB pop de ;pt to original FCB ld (hl),0 ;set first byte to 0 (current disk) inc hl ;pt to name inc de ;pt to name ld b,11 ;11 bytes call moveb ;do copy ld b,24 ;fill next 24 bytes (to R2) with zeroes call zero ;initialize LDFCB ld hl,(ldfcb) ;pt to FCB ex de,hl ;... in DE ld c,15 ;try to open file call bdos cp 0ffh ;error? ret z ;abort if error ; ; Copy Loader Program into TBUFF Area ; pop af ;clear stack ld de,loader ;pt to loader program ld hl,(ldadr) ;pt to loader address ld b,64 ;copy 64 bytes call moveb ;do the copy ld de,100h ;initial DMA address ld hl,(ldadr) ;transfer control to the loader program jp (hl) ;transfer control to the loader program ; ; Copy HL to DE for B bytes ; moveb: ld a,(de) ;get byte ld (hl),a ;put byte inc hl ;pt to next inc de dec b ;count down jp nz,moveb ret ; ; Zero FCB fields pted to by HL ; zero: ld (hl),0 ;store zero inc hl ;pt to next dec b ;count down jp nz,zero ret ; ; Loader Program ; Upon execution, the address of LOADER is LDADR ; The FCB used by LOADER is at LDFCB ; loader: ld c,26 ;set DMA push de ;save address call bdos ;perform BDOS function ldfcb equ $+1 ld de,0 ;pt to FCB ld c,20 ;read next record call bdos pop hl ;get DMA address or a ;0=OK jp nz,tpa ;done with load, so run program ld de,80h ;advance to next record add hl,de ex de,hl ;DMA address in DE ldadr equ $+1 jp 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.3 ; Module Version Number: 1.1 ; PUBLIC ZPRSFN,PARSER 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 BC ;SAVE BC LD (DUFIRST),A ;SET FLAG CALL CAPSTR ;CAPITALIZE INPUT PUSH DE ;SAVE PTR TO FCB CALL INITFCB ;INIT IT POP DE ;GET PTR BACK XOR A ;DON'T FLUSH ON SCANNER LD (SCFLUSH),A PUSH DE ;SAVE PTR AGAIN CALL SCANNER ;SCAN LINE POP DE ;RESTORE PTR POP BC ;RESTORE BC LD A,(QMCNT) ;CHECK FOR QUESTION MARKS OR 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 BC ;SAVE BC CALL PARSE ;DO THE WORK LD HL,(TAILSV) ;GET PTR TO COMMAND TAIL LD DE,TBUFF ;COPY TAIL INTO TBUFF LD B,0 ;SET CHAR COUNT PUSH DE ;SAVE PTR TO TBUFF INC DE ;PT TO FIRST CHAR POSITION SVTAIL: LD A,(HL) ;GET NEXT CHAR CALL TSTEOL ;END OF LINE? JP Z,SVT1 LD (DE),A ;SAVE CHAR INC HL ;PT TO NEXT INC DE INC B ;INCREMENT CHAR COUNT JP SVTAIL SVT1: XOR A ;STORE ENDING 0 LD (DE),A POP HL ;GET PTR TO TBUFF LD (HL),B ;SET CHAR COUNT POP BC ;RESTORE BC LD HL,(NXTCHR) ;PT TO NEXT CHAR IN HL LD DE,FCBDN ;PT TO FCB IN DE LD A,(ERRFLG) ;GET ERROR FLAG IN A OR A ;SET ZERO FLAG RET ; ; MAIN ROUTINE ; PARSE: ; ; SAVE DU/DIR ORDER FLAG AND CAPITALIZE INPUT LINE ; LD (DUFIRST),A ;0=DIR FIRST, 0FFH=DU FIRST CALL CAPSTR ;CAPITALIZE LINE ; ; SET SCANNER FLUSH FLAG ; LD A,0FFH LD (SCFLUSH),A ;SET FLAG TO NZ (PERFORM FLUSH) ; ; INITIALIZE THE COMMAND AND TOKEN FCBS ; LD DE,FCBDN ;PT TO COMMAND FCB CALL INITFCB ;INIT IT LD DE,TFCB ;PT TO TOKEN FCB CALL INITFCB ;INIT TFCB and TFCB2 ; ; EXTRACT COMMAND NAME ; LD DE,FCBDN ;PLACE COMMAND NAME INTO COMMAND FCB CALL SCANNER ;EXTRACT COMMAND NAME LD A,(QMCNT) ;SET QUESTION MARK COUNT LD (ERRFLG),A ;INTO ERROR FLAG ; ; SET TYPE OF COMMAND ; PUSH HL ;SAVE PTR TO NEXT BYTE LD HL,COMMSG ;PLACE DEFAULT FILE TYPE (COM) INTO FCB LD DE,FCBFT ;PT TO FILE TYPE LD B,3 ;3 BYTES CALL LDIR POP HL ;GET PTR TO NEXT BYTE ; ; SET DIR: PREFIX FLAG ; LD A,(MYCOLON) ;PREVIOUS TOKEN CONTAINED A COLON? LD (COLON),A ;SET FLAG FOR DU: OR DIR: PREFIX ; ; SAVE POINTER TO COMMAND TAIL FOR LATER COPY INTO TBUFF AND FIND END OF ; COMMAND LINE ; LD (TAILSV),HL ;SAVE PTR TO COMMAND TAIL PUSH HL ;SAVE PTR CTAIL: LD A,(HL) ;GET CHAR CALL TSTEOL ;AT EOL? JP Z,CTAIL1 INC HL ;PT TO NEXT JP CTAIL CTAIL1: LD (NXTCHR),HL ;SAVE PTR TO NEXT LINE POP HL ;GET PTR TO COMMAND TAIL ; ; EXTRACT FIRST TOKEN ; CALL SKSP ;SKIP OVER SPACES RET Z ;DONE IF EOL OR END OF COMMAND LD DE,TFCB ;STORE FIRST TOKEN IN TFCB CALL SCANNER ;EXTRACT TOKEN ; ; EXTRACT SECOND TOKEN ; CALL SKSP ;SKIP OVER SPACES RET Z ;DONE IF EOL OR END OF COMMAND LD DE,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: XOR A ;A=0 LD (DE),A ;SET DEFAULT DRIVE LD (MYCOLON),A ;SET NO COLON LD (TEMPDR),A ;SET TEMPORARY DRIVE NUMBER TO DEFAULT LD (QMCNT),A ;ZERO QUESTION MARK COUNTER CALL RETUD ;GET USER/DISK LD A,C ;GET USER LD (TEMPUSR),A ;SET TEMPUSR PUSH DE ;SAVE PTR TO FIRST BYTE OF FCB LD B,8 ;8 CHARS MAX CALL SCANF ;PLACE FIRST TOKEN INTO FILE NAME FIELD POP DE ;GET PTR TO FIRST BYTE OF FCB LD A,(HL) ;GET TERMINATING CHAR LD (ENDCHAR),A ;SET ENDING CHAR CP ':' ;COLON? JP NZ,SCAN1 ;NO, WE HAVE A FILE NAME LD (MYCOLON),A ;SET COLON INC HL ;PT TO CHAR AFTER COLON ; ; CHECK FOR DU: FORM FIRST ; LD A,(DUFIRST) ;CHECK DUFIRST FLAG OR A JP Z,SCN1 CALL DUSCAN ;CHECK FOR DU: FORM JP Z,SUD1 ;GOT IT ; ; CHECK FOR DIR: FORM SECOND OR FIRST ; SCN1: CALL DIRSCAN ;CHECK FOR DIR: FORM JP Z,SUD1 ;GOT IT ; ; CHECK FOR DU SCAN FOR DUSECOND ; LD A,(DUFIRST) ;CHECK DU FLAG OR A JP NZ,SUD1 ; ; CHECK FOR DU: FORM SECOND ; CALL DUSCAN ;CHECK FOR DU: FORM ; ; WE HAVE A VALID DU OR DIR - TEMPDR/TEMPUSR CONTAIN DATA ; SUD1: LD A,(TEMPDR) ;SET DRIVE LD (DE),A ;... IN FCB ; ; REINIT FCB PTED TO BY DE ; PUSH DE ;SAVE PTR INC DE ;PT TO FN FIELD CALL IFCB ;ONLY PARTIAL INIT (17 BYTES TOTAL) POP DE ; ; EXTRACT FILENAME FIELD ; XOR A LD (QMCNT),A ;ZERO QUESTION MARK COUNTER PUSH DE ;SAVE PTR TO FIRST BYTE OF FCB LD B,8 ;8 CHARS MAX CALL SCANF ;STORE FILE NAME POP DE ;GET PTR TO FIRST BYTE OF FCB LD A,(HL) ;GET OFFENDING CHAR LD (ENDCHAR),A ;SET ENDING CHAR ; ; SKIP TO FILE TYPE FIELD ; HL PTS TO NEXT CHAR, DE PTS TO DN FIELD OF FCB ; SCAN1: LD A,(ENDCHAR) ;GET ENDING CHAR EX DE,HL LD BC,8 ;PT TO BEFORE FILE TYPE FIELD OF FCB ADD HL,BC EX DE,HL ; ; EXTRACT FILETYPE FIELD ; LD B,3 ;PREPARE TO EXTRACT FILE TYPE CP '.' ;IF '.', WE HAVE A TYPE JP NZ,SCAN2 INC HL ;PT TO CHAR AFTER '.' PUSH DE CALL SCANF ;GET FCB FILE TYPE POP DE SCAN2: ; ; SET USER NUMBER REFERENCED ; HL PTS TO NEXT CHAR, DE PTS TO BEFORE FCB FT ; EX DE,HL LD BC,5 ;PT TO S1 FIELD ADD HL,BC EX DE,HL LD A,(TEMPUSR) ;STORE USER NUMBER HERE LD (DE),A LD A,(SCFLUSH) ;FLUSH TO SPACE, ETC? OR A ;0=NO JP Z,SCAN4 ; ; SKIP TO SPACE, CHAR AFTER =, OR EOL ; HL PTS TO NEXT CHAR IN LINE ; SCAN3: LD A,(HL) ;GET NEXT CHAR CP ' '+1 ;DONE IF LESS THAN SPACE JP C,SCAN4 CALL TSTEOL ;EOL? JP Z,SCAN4 INC HL ;PT TO NEXT CP '=' ;EQUATE? JP NZ,SCAN3 ; ; SET ZERO FLAG TO INDICATE PRESENCE OF '?' IN DIR:FILENAME.TYP ; SCAN4: LD A,(QMCNT) ;NUMBER OF QUESTION MARKS OR 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 RET Z INC DE ;PT TO NEXT BYTE IN FCB CP '*' ;IS (DE) A WILD CARD? JP NZ,SCANF1 ;CONTINUE IF NOT ; ; HANDLE WILD FIELD ; LD A,'?' ;PLACE '?' IN FCB AND DON'T ADVANCE HL IF SO LD (DE),A CALL SCQ ;SCANNER COUNT QUESTION MARKS JP SCANF2 ; ; HANDLE NORMAL CHARS, INCL '?' ; SCANF1: LD (DE),A ;STORE FILENAME CHAR IN FCB INC HL ;PT TO NEXT CHAR IN COMMAND LINE CP '?' ;CHECK FOR QUESTION MARK (WILD) CALL Z,SCQ ;SCANNER COUNT QUESTION MARKS ; ; COUNT DOWN CHARS ; SCANF2: DEC B ;COUNT DOWN JP NZ,SCANF ;DECREMENT CHAR COUNT UNTIL 8 ELAPSED ; ; FLUSH TO NEXT DELIMITER ; SCANF3: CALL SDELM ;8 CHARS OR MORE - SKIP UNTIL DELIMITER RET Z ;ZERO FLAG SET IF DELIMITER FOUND INC HL ;PT TO NEXT CHAR IN COMMAND LINE JP 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 HL ;SAVE HL LD HL,QMCNT ;GET COUNT INC (HL) ;INCREMENT POP HL ;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 HL ;SAVE REGS PUSH DE CALL DUS ;DO SCAN POP DE ;RESTORE REGS POP HL RET DUS: CALL GETDUOK ;OK FOR DU FORM? JP Z,DIRSERR ;ABORT IF NOT EX DE,HL ;PTR IN HL INC HL ;PT TO FIRST BYTE OF FN CALL GETMDISK ;GET MAX DISK LD B,A ;... IN B INC B ;B=MAX DISK + 1 LD A,(HL) ;GET FIRST CHAR CP 'A' ;CONVERT POSSIBLE DRIVE SPEC TO NUMBER JP C,DUS1 ;IF LESS THAN 'A', MUST BE DIGIT ; ; SET DISK NUMBER (A=1) ; SUB 'A'-1 ;CONVERT DRIVE NUMBER TO 1-16 CP B ;COMPARE AGAINST MAX DISK + 1 JP NC,DUSE1 ;INVALID DISK NUMBER LD (TEMPDR),A ;SET TEMPORARY DRIVE NUMBER INC HL ;PT TO NEXT CHAR LD A,(HL) ;SEE IF IT IS A SPACE CP ' ' RET Z CALL DIGCK ;CHECK FOR DIGIT RET C ; ; SET USER NUMBER ; DUS1: PUSH HL ;SAVE PTR TO DIGITS LD B,2 ;UP TO 2 DIGITS DUS1A: LD A,(HL) ;CHECK FOR DIGIT OR SPACE CP ' ' ;IF SPACE, THEN NO DIGIT JP Z,DUS2 CALL DIGCK ;CHECK FOR DIGIT JP C,DUSE INC HL DEC B JP NZ,DUS1A ;COUNT DOWN LD A,(HL) ;3RD CHAR CP ' ' ;MUST BE SPACE JP NZ,DUSE DUS2: POP HL CALL GETMUSER ;GET MAX USER NUMBER LD C,A ;... IN C INC C ;MAXUSR+1 CALL NUM ;GET NUMBER CP C ;COMPARE AGAINST MAXUSR+1 JP NC,DUSE1 LD (TEMPUSR),A ;SAVE USER NUMBER XOR A ;SET OK RET DUSE: POP HL ;CLEAR STACK DUSE1: XOR A DEC 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 HL ;SAVE REGS PUSH DE CALL DIRS ;DO SCAN POP DE ;RESTORE REGS POP HL RET DIRS: CALL GETNDR ;PT TO NAMED DIR JP Z,DIRSERR ;ABORT IF NONE EX DE,HL ;PTR IN HL INC HL ;PT TO FN DIRS1: LD A,(DE) ;GET NEXT CHAR OR A ;ZERO IF END OF DIR JP Z,DIRSERR INC DE ;PT TO DIR NAME INC DE PUSH HL ;SAVE PTR TO FILE NAME PUSH DE ;SAVE PTR TO DIR ENTRY LD B,8 ;MATCH? DIRS2: LD A,(DE) ;GET BYTE CP (HL) ;COMPARE JP NZ,DIRS3 INC HL ;PT TO NEXT INC DE DEC B JP NZ,DIRS2 ;COUNT DOWN DIRS3: POP DE ;RESTORE REGS POP HL JP Z,DIRS4 EX DE,HL ;ADVANCE TO NEXT ENTRY LD BC,16 ;8 BYTES FOR NAME + 8 BYTES FOR PASSWORD ADD HL,BC EX DE,HL JP DIRS1 ; ; NO DIR match ; DIRSERR: XOR A ;RETURN NZ DEC A RET ; ; DIR match ; DIRS4: DEC DE ;PT TO USER LD A,(DE) ;GET USER LD (TEMPUSR),A DEC DE ;PT TO DISK LD A,(DE) ;GET IT LD (TEMPDR),A ;A=1 XOR A ;SET Z RET ; ; SKIP OVER SPACES PTED TO BY HL ; ON RETURN, ZERO FLAG SET MEANS WE HIT EOL OR CMDSEP ; SKSP: LD A,(HL) ;GET NEXT CHAR INC HL ;PT TO NEXT CP ' ' ;SPACE? JP Z,SKSP DEC HL ;PT TO NON-SPACE RET ; ; CHECK TO SEE IF HL PTS TO DELIMITER; IF SO, RET W/ZERO FLAG SET ; SDELM: LD A,(HL) ;GET NEXT CHAR FROM LINE CP ' '+1 ;DELIM IF <= JP C,ZERO CP '=' ;'='=DELIMITER RET Z CP 5FH ;UNDERSCORE=DELIMITER RET Z CP '.' ;'.'=DELIMITER RET Z CP ':' ;':'=DELIMITER RET Z CP ',' ;','=DELIMITER RET Z CP '<' ;'<'=DELIMITER RET Z CP '>' ;'>'=DELIMITER RET Z ;FALL THRU TO TSTEOL ; ; CHECK TO SEE IF CHAR IN A IS EOL OR CMDSEP ; TSTEOL: OR A ;EOL? RET Z ;RETURN WITH FLAG CP CMDSEP ;COMMAND SEPARATOR? RET ; ; RETURN WITH A=0 AND Z ; ZERO: XOR A RET ; ; CONVERT NUMBER STRING PTED TO BY HL INTO A NUMBER IN A ; NUM: PUSH BC LD BC,1100H ;C=ACCUMULATED VALUE, B=CHAR COUNT ; (C=0, B=11) NUM1: LD A,(HL) ;GET CHAR CALL SDELM ;DONE IF DELIMITER JP Z,NUM2 INC HL ;PT TO NEXT CHAR CALL DIGCK ;CHECK FOR DIGIT IN A JP C,NUMERR LD D,A ;DIGIT IN D LD A,C ;NEW VALUE = OLD VALUE * 10 RLCA ;*2 JP C,NUMERR RLCA ;*4 JP C,NUMERR ADD A,C ;*5 JP C,NUMERR RLCA ;*10 JP C,NUMERR ADD A,D ;NEW VALUE = OLD VALUE * 10 + DIGIT JP C,NUMERR ;CHECK FOR RANGE ERROR LD C,A ;SET NEW VALUE DEC B JP NZ,NUM1 ;COUNT DOWN ; ; RETURN FROM NUMBER ; NUM2: LD A,C ;GET ACCUMULATED VALUE POP BC OR A ;CLEAR CARRY RET ; ; RESTORE STACK AND RETURN WITH CARRY SET ; NUMERR: POP BC SCF RET ; ; CHECK TO SEE IF A IS A DIGIT ; IF SO, RETURN ITS VALUE ; IF NOT, RETURN WITH CARRY SET ; DIGCK: SUB '0' ;DIGIT? RET C ;ERROR CP 10 ;RANGE? JP NC,DIGCK1 CCF ;FLIP CARRY RET DIGCK1: SCF ;SET CARRY RET ; ; INIT FCB PTED TO BY DE ; INITFCB: XOR A LD (DE),A ;SET DEFAULT DISK (DN BYTE IS 0) INC DE ;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: LD B,11 ;STORE 11 SPACES LD A,' ' CALL FILL XOR A LD (DE),A ;SET EX TO ZERO INC DE CALL RETUD ;GET CURRENT USER LD A,C LD (DE),A ;SET S1 TO CURRENT USER INC DE LD B,3 ;STORE 3 ZEROES XOR A ;FALL THRU TO FILL ; ; FILL MEMORY POINTED TO BY DE WITH CHAR IN A FOR B BYTES ; FILL: LD (DE),A ;FILL WITH BYTE IN A INC DE ;PT TO NEXT DEC B ;COUNT DOWN JP NZ,FILL RET ; ; COPY HL TO DE FOR B BYTES ; LDIR: LD A,(HL) ;GET LD (DE),A ;PUT INC HL ;PT TO NEXT INC DE DEC B ;COUNT DOWN JP NZ,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.3 ; Module Version Number: 1.1 ; PUBLIC ZFNAME 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 BC ;SAVE BC LD (DUFIRST),A ;SET FLAG CALL CAPSTR ;CAPITALIZE INPUT PUSH DE ;SAVE PTR TO FCB CALL INITFCB ;INIT IT POP DE ;GET PTR BACK PUSH DE ;SAVE PTR AGAIN CALL SCANNER ;SCAN LINE POP DE ;RESTORE PTR POP BC ;RESTORE BC LD A,(QMCNT) ;CHECK FOR QUESTION MARKS OR 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: XOR A ;A=0 LD (DE),A ;SET DEFAULT DRIVE LD (TEMPDR),A ;SET TEMPORARY DRIVE NUMBER TO DEFAULT LD (QMCNT),A ;ZERO QUESTION MARK COUNTER CALL RETUD ;GET USER/DISK LD A,C ;GET USER LD (TEMPUSR),A ;SET TEMPUSR PUSH DE ;SAVE PTR TO FIRST BYTE OF FCB LD B,8 ;8 CHARS MAX CALL SCANF ;PLACE FIRST TOKEN INTO FILE NAME FIELD POP DE ;GET PTR TO FIRST BYTE OF FCB LD A,(HL) ;GET TERMINATING CHAR LD (ENDCHAR),A ;SET ENDING CHAR CP ':' ;COLON? JP NZ,SCAN1 ;NO, WE HAVE A FILE NAME INC HL ;PT TO CHAR AFTER COLON ; ; CHECK FOR DU: FORM FIRST ; LD A,(DUFIRST) ;CHECK DUFIRST FLAG OR A JP Z,SCN1 CALL DUSCAN ;CHECK FOR DU: FORM JP Z,SUD1 ;GOT IT ; ; CHECK FOR DIR: FORM SECOND OR FIRST ; SCN1: CALL DIRSCAN ;CHECK FOR DIR: FORM JP Z,SUD1 ;GOT IT ; ; CHECK FOR DU SCAN FOR DUSECOND ; LD A,(DUFIRST) ;CHECK DU FLAG OR A JP NZ,SUD1 ; ; CHECK FOR DU: FORM SECOND ; CALL DUSCAN ;CHECK FOR DU: FORM ; ; WE HAVE A VALID DU OR DIR - TEMPDR/TEMPUSR CONTAIN DATA ; SUD1: LD A,(TEMPDR) ;SET DRIVE LD (DE),A ;... IN FCB ; ; REINIT FCB PTED TO BY DE ; PUSH DE ;SAVE PTR INC DE ;PT TO FN FIELD CALL IFCB ;ONLY PARTIAL INIT (17 BYTES TOTAL) POP DE ; ; EXTRACT FILENAME FIELD ; XOR A LD (QMCNT),A ;ZERO QUESTION MARK COUNTER PUSH DE ;SAVE PTR TO FIRST BYTE OF FCB LD B,8 ;8 CHARS MAX CALL SCANF ;STORE FILE NAME POP DE ;GET PTR TO FIRST BYTE OF FCB LD A,(HL) ;GET OFFENDING CHAR LD (ENDCHAR),A ;SET ENDING CHAR ; ; SKIP TO FILE TYPE FIELD ; HL PTS TO NEXT CHAR, DE PTS TO DN FIELD OF FCB ; SCAN1: LD A,(ENDCHAR) ;GET ENDING CHAR EX DE,HL LD BC,8 ;PT TO BEFORE FILE TYPE FIELD OF FCB ADD HL,BC EX DE,HL ; ; EXTRACT FILETYPE FIELD ; LD B,3 ;PREPARE TO EXTRACT FILE TYPE CP '.' ;IF '.', WE HAVE A TYPE JP NZ,SCAN2 INC HL ;PT TO CHAR AFTER '.' PUSH DE CALL SCANF ;GET FCB FILE TYPE POP DE SCAN2: ; ; SET USER NUMBER REFERENCED ; HL PTS TO NEXT CHAR, DE PTS TO BEFORE FCB FT ; EX DE,HL LD BC,5 ;PT TO S1 FIELD ADD HL,BC EX DE,HL LD A,(TEMPUSR) ;STORE USER NUMBER HERE LD (DE),A ; ; SET ZERO FLAG TO INDICATE PRESENCE OF '?' IN DIR:FILENAME.TYP ; LD A,(QMCNT) ;NUMBER OF QUESTION MARKS OR 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 RET Z INC DE ;PT TO NEXT BYTE IN FCB CP '*' ;IS (DE) A WILD CARD? JP NZ,SCANF1 ;CONTINUE IF NOT ; ; HANDLE WILD FIELD ; LD A,'?' ;PLACE '?' IN FCB AND DON'T ADVANCE HL IF SO LD (DE),A CALL SCQ ;SCANNER COUNT QUESTION MARKS JP SCANF2 ; ; HANDLE NORMAL CHARS, INCL '?' ; SCANF1: LD (DE),A ;STORE FILENAME CHAR IN FCB INC HL ;PT TO NEXT CHAR IN COMMAND LINE CP '?' ;CHECK FOR QUESTION MARK (WILD) CALL Z,SCQ ;SCANNER COUNT QUESTION MARKS ; ; COUNT DOWN CHARS ; SCANF2: DEC B ;COUNT DOWN JP NZ,SCANF ;DECREMENT CHAR COUNT UNTIL 8 ELAPSED ; ; FLUSH TO NEXT DELIMITER ; SCANF3: CALL SDELM ;8 CHARS OR MORE - SKIP UNTIL DELIMITER RET Z ;ZERO FLAG SET IF DELIMITER FOUND INC HL ;PT TO NEXT CHAR IN COMMAND LINE JP 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 HL ;SAVE HL LD HL,QMCNT ;GET COUNT INC (HL) ;INCREMENT POP HL ;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 HL ;SAVE REGS PUSH DE CALL DUS ;DO SCAN POP DE ;RESTORE REGS POP HL RET DUS: CALL GETDUOK ;OK FOR DU FORM? JP Z,DIRSERR ;ABORT IF NOT EX DE,HL ;PTR IN HL INC HL ;PT TO FIRST BYTE OF FN CALL GETMDISK ;GET MAX DISK LD B,A ;... IN B INC B ;B=MAX DISK + 1 LD A,(HL) ;GET FIRST CHAR CP 'A' ;CONVERT POSSIBLE DRIVE SPEC TO NUMBER JP C,DUS1 ;IF LESS THAN 'A', MUST BE DIGIT ; ; SET DISK NUMBER (A=1) ; SUB 'A'-1 ;CONVERT DRIVE NUMBER TO 1-16 CP B ;COMPARE AGAINST MAX DISK + 1 JP NC,DUSE1 ;INVALID DISK NUMBER LD (TEMPDR),A ;SET TEMPORARY DRIVE NUMBER INC HL ;PT TO NEXT CHAR LD A,(HL) ;SEE IF IT IS A SPACE CP ' ' RET Z CALL DIGCK ;CHECK FOR DIGIT RET C ; ; SET USER NUMBER ; DUS1: PUSH HL ;SAVE PTR TO DIGITS LD B,2 ;UP TO 2 DIGITS DUS1A: LD A,(HL) ;CHECK FOR DIGIT OR SPACE CP ' ' ;IF SPACE, THEN NO DIGIT JP Z,DUS2 CALL DIGCK ;CHECK FOR DIGIT JP C,DUSE INC HL DEC B JP NZ,DUS1A ;COUNT DOWN LD A,(HL) ;3RD CHAR CP ' ' ;MUST BE SPACE JP NZ,DUSE DUS2: POP HL CALL GETMUSER ;GET MAX USER NUMBER LD C,A ;... IN C INC C ;MAXUSR+1 CALL NUM ;GET NUMBER CP C ;COMPARE AGAINST MAXUSR+1 JP NC,DUSE1 LD (TEMPUSR),A ;SAVE USER NUMBER XOR A ;SET OK RET DUSE: POP HL ;CLEAR STACK DUSE1: XOR A DEC 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 HL ;SAVE REGS PUSH DE CALL DIRS ;DO SCAN POP DE ;RESTORE REGS POP HL RET DIRS: CALL GETNDR ;PT TO NAMED DIR JP Z,DIRSERR ;ABORT IF NONE EX DE,HL ;PTR IN HL INC HL ;PT TO FN DIRS1: LD A,(DE) ;GET NEXT CHAR OR A ;ZERO IF END OF DIR JP Z,DIRSERR INC DE ;PT TO DIR NAME INC DE PUSH HL ;SAVE PTR TO FILE NAME PUSH DE ;SAVE PTR TO DIR ENTRY LD B,8 ;MATCH? DIRS2: LD A,(DE) ;GET BYTE CP (HL) ;COMPARE JP NZ,DIRS3 INC HL ;PT TO NEXT INC DE DEC B JP NZ,DIRS2 ;COUNT DOWN DIRS3: POP DE ;RESTORE REGS POP HL JP Z,DIRS4 EX DE,HL ;ADVANCE TO NEXT ENTRY LD BC,16 ;8 BYTES FOR NAME + 8 BYTES FOR PASSWORD ADD HL,BC EX DE,HL JP DIRS1 ; ; NO DIR match ; DIRSERR: XOR A ;RETURN NZ DEC A RET ; ; DIR match ; DIRS4: DEC DE ;PT TO USER LD A,(DE) ;GET USER LD (TEMPUSR),A DEC DE ;PT TO DISK LD A,(DE) ;GET IT LD (TEMPDR),A ;A=1 XOR A ;SET Z RET ; ; CHECK TO SEE IF HL PTS TO DELIMITER; IF SO, RET W/ZERO FLAG SET ; SDELM: LD A,(HL) ;GET NEXT CHAR FROM LINE CP ' '+1 ;DELIM IF <= JP C,ZERO CP '=' ;'='=DELIMITER RET Z CP 5FH ;UNDERSCORE=DELIMITER RET Z CP '.' ;'.'=DELIMITER RET Z CP ':' ;':'=DELIMITER RET Z CP ',' ;','=DELIMITER RET Z CP '<' ;'<'=DELIMITER RET Z CP '>' ;'>'=DELIMITER RET Z ;FALL THRU TO TSTEOL ; ; CHECK TO SEE IF CHAR IN A IS EOL OR CMDSEP ; TSTEOL: OR A ;EOL? RET Z ;RETURN WITH FLAG CP CMDSEP ;COMMAND SEPARATOR? RET ; ; RETURN WITH A=0 AND Z ; ZERO: XOR A RET ; ; CONVERT NUMBER STRING PTED TO BY HL INTO A NUMBER IN A ; NUM: PUSH BC LD BC,1100H ;C=ACCUMULATED VALUE, B=CHAR COUNT ; (C=0, B=11) NUM1: LD A,(HL) ;GET CHAR CALL SDELM ;DONE IF DELIMITER JP Z,NUM2 INC HL ;PT TO NEXT CHAR CALL DIGCK ;CHECK FOR DIGIT IN A JP C,NUMERR LD D,A ;DIGIT IN D LD A,C ;NEW VALUE = OLD VALUE * 10 RLCA ;*2 JP C,NUMERR RLCA ;*4 JP C,NUMERR ADD A,C ;*5 JP C,NUMERR RLCA ;*10 JP C,NUMERR ADD A,D ;NEW VALUE = OLD VALUE * 10 + DIGIT JP C,NUMERR ;CHECK FOR RANGE ERROR LD C,A ;SET NEW VALUE DEC B JP NZ,NUM1 ;COUNT DOWN ; ; RETURN FROM NUMBER ; NUM2: LD A,C ;GET ACCUMULATED VALUE POP BC OR A ;CLEAR CARRY RET ; ; RESTORE STACK AND RETURN WITH CARRY SET ; NUMERR: POP BC SCF RET ; ; CHECK TO SEE IF A IS A DIGIT ; IF SO, RETURN ITS VALUE ; IF NOT, RETURN WITH CARRY SET ; DIGCK: SUB '0' ;DIGIT? RET C ;ERROR CP 10 ;RANGE? JP NC,DIGCK1 CCF ;FLIP CARRY RET DIGCK1: SCF ;SET CARRY RET ; ; INIT FCB PTED TO BY DE ; INITFCB: XOR A LD (DE),A ;SET DEFAULT DISK (DN BYTE IS 0) INC DE ;PT TO FILE NAME FIELD CALL IFCB ;FILL 1ST PART OF FCB CALL IFCB ;FILL 2ND PART OF FCB LD (DE),A ;PLACE 0 IN CR FIELD RET ; ; FILL FN, FT, EX, S1, S2, RC, AND FOLLOWING CR (OR DN) FIELDS ; IFCB: LD B,11 ;STORE 11 SPACES LD A,' ' CALL FILL XOR A LD (DE),A ;SET EX TO ZERO INC DE CALL RETUD ;GET CURRENT USER LD A,C LD (DE),A ;SET S1 TO CURRENT USER INC DE LD B,3 ;STORE 3 ZEROES XOR A ;FALL THRU TO FILL ; ; FILL MEMORY POINTED TO BY DE WITH CHAR IN A FOR B BYTES ; FILL: LD (DE),A ;FILL WITH BYTE IN A INC DE ;PT TO NEXT DEC B ;COUNT DOWN JP NZ,FILL RET ; ; COPY HL TO DE FOR B BYTES ; LDIR: LD A,(HL) ;GET LD (DE),A ;PUT INC HL ;PT TO NEXT INC DE DEC B ;COUNT DOWN JP NZ,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.3 ; Module Version Number: 1.1 ; PUBLIC DNSCAN,DUSCAN,DIRSCAN 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 HL ;SAVE KEY REGS PUSH DE LD (DUFIRST),A ;SET DUFIRST FLAG LD DE,DIRN ;PT TO DIR NAME BUFFER LD B,8 ;8 CHARS MAX PUSH DE CALL SCANF ;PLACE DIR NAME INTO DIR NAME BUFFER POP HL ;HL PTS TO DIR NAME BUFFER ; ; CHECK FOR DU: FORM FIRST ; LD A,(DUFIRST) ;CHECK DUFIRST FLAG OR A JP Z,SCN1 CALL DUSCAN ;CHECK FOR DU: FORM JP NZ,SUD1 ;GOT IT CALL DIRSCAN ;CHECK FOR DIR: FORM JP NZ,SUD1 ; ; DIR NAME NOT FOUND ; ERROR: XOR A ;SET ERROR FLAG JP EXIT ; ; CHECK FOR DIR: FORM SECOND OR FIRST ; SCN1: CALL DIRSCAN ;CHECK FOR DIR: FORM JP NZ,SUD1 ;GOT IT CALL DUSCAN ;CHECK FOR DU: FORM JP Z,ERROR ;ERROR IF NOT FOUND ; ; WE HAVE A VALID DU OR DIR - TEMPDR/TEMPUSR CONTAIN DATA ; SUD1: LD A,0FFH ;SET OK FLAG ; ; EXIT - SET PSW AND RESTORE REGS ; EXIT: POP DE ;RESTORE REGS POP HL OR 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 JP Z,SCANF1 ;SPACE FILL LD (DE),A ;STORE BYTE INC HL ;PT TO NEXT INC DE DEC B ;COUNT DOWN JP NZ,SCANF RET SCANF1: LD A,' ' ;FILL BUFFER WITH SPACES LD (DE),A INC DE ;PT TO NEXT DEC B ;COUNT DOWN JP NZ,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 HL ;SAVE REGS PUSH DE CALL GETDUOK ;OK FOR DU FORM? JP Z,DUSE1 ;ABORT IF NOT CALL RETUD ;GET CURRENT DISK AND USER LD A,B ;SET TEMP VALUES LD (TEMPDR),A LD A,C LD (TEMPUSR),A CALL GETMDISK ;GET MAX DISK LD B,A ;... IN B LD A,(HL) ;GET FIRST CHAR SUB 'A' ;CONVERT POSSIBLE DRIVE SPEC TO NUMBER JP C,DUS1 ;IF LESS THAN 'A', MUST BE DIGIT ; ; SET DISK NUMBER (A=1) ; CP B ;COMPARE AGAINST MAX DISK + 1 JP NC,DUSE1 ;INVALID DISK NUMBER LD (TEMPDR),A ;SET TEMPORARY DRIVE NUMBER INC HL ;PT TO NEXT CHAR CALL SDELM ;CHECK FOR DELIMITER JP Z,DUSOK CALL DIGCK ;CHECK FOR DIGIT JP C,DUSE1 ;ERROR IF NOT ; ; SET USER NUMBER ; DUS1: PUSH HL ;SAVE PTR TO DIGITS LD B,2 ;UP TO 2 DIGITS DUS1A: CALL SDELM ;DELIMITER? JP Z,DUS2 CALL DIGCK ;CHECK FOR DIGIT JP C,DUSE INC HL DEC B JP NZ,DUS1A ;COUNT DOWN CALL SDELM ;MUST BE DELIMITER JP NZ,DUSE DUS2: POP HL CALL GETMUSER ;GET MAX USER NUMBER LD C,A ;... IN C INC C ;MAXUSR+1 CALL NUM ;GET NUMBER JP C,DUSE1 ;NUMBER ERROR CP C ;COMPARE AGAINST MAXUSR+1 JP NC,DUSE1 LD (TEMPUSR),A ;SAVE USER NUMBER DUSOK: LD A,(TEMPDR) ;GET DISK LD B,A ;... IN B LD A,(TEMPUSR) ;GET USER LD C,A ;... IN C POP DE ;RESTORE REGS POP HL XOR A ;SET OK DEC A ;NZ RET DUSE: POP HL ;CLEAR STACK DUSE1: POP DE ;RESTORE REGS POP HL XOR 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 HL ;SAVE REGS PUSH DE EX DE,HL ;DE PTS TO NAME CALL GETNDR ;PT TO NAMED DIR JP Z,DIRSERR ;ABORT IF NONE EX DE,HL ;PTR IN HL TO NAME, DE TO DIR BUFFERS DIRS1: LD A,(DE) ;GET NEXT CHAR OR A ;ZERO IF END OF DIR JP Z,DIRSERR INC DE ;PT TO DIR NAME INC DE PUSH HL ;SAVE PTR TO FILE NAME PUSH DE ;SAVE PTR TO DIR ENTRY LD B,8 ;MATCH? DIRS2: LD A,(DE) ;GET BYTE CP (HL) ;COMPARE JP NZ,DIRS3 INC HL ;PT TO NEXT INC DE DEC B JP NZ,DIRS2 ;COUNT DOWN DIRS3: POP DE ;RESTORE REGS POP HL JP Z,DIRS4 EX DE,HL ;ADVANCE TO NEXT ENTRY LD BC,16 ;8 BYTES FOR NAME + 8 BYTES FOR PASSWORD ADD HL,BC EX DE,HL JP DIRS1 ; ; NO DIR match ; DIRSERR: POP DE ;RESTORE REGS POP HL XOR A ;RETURN Z RET ; ; DIR match ; DIRS4: DEC DE ;PT TO USER LD A,(DE) ;GET USER LD C,A ;... IN C DEC DE ;PT TO DISK LD A,(DE) ;GET DISK LD B,A ;... IN B DEC B ;A=0 POP DE ;RESTORE REGS POP HL XOR A ;SET NZ DEC A RET ; ; CHECK TO SEE IF HL PTS TO DELIMITER; IF SO, RET W/ZERO FLAG SET ; SDELM: LD A,(HL) ;GET NEXT CHAR FROM LINE CALL CAPS ;CAPITALIZE CP ' '+1 ;DELIM IF <= JP C,ZERO CP '=' ;'='=DELIMITER RET Z CP 5FH ;UNDERSCORE=DELIMITER RET Z CP '.' ;'.'=DELIMITER RET Z CP ':' ;':'=DELIMITER RET Z CP ',' ;','=DELIMITER RET Z CP '<' ;'<'=DELIMITER RET Z CP '>' ;'>'=DELIMITER RET Z ;FALL THRU TO TSTEOL ; ; CHECK TO SEE IF CHAR IN A IS EOL OR CMDSEP ; OR A ;EOL? RET Z ;RETURN WITH FLAG CP CMDSEP ;COMMAND SEPARATOR? RET ; ; RETURN WITH A=0 AND Z ; ZERO: XOR A RET ; ; CONVERT NUMBER STRING PTED TO BY HL INTO A NUMBER IN A ; NUM: PUSH BC LD BC,1100H ;C=ACCUMULATED VALUE, B=CHAR COUNT ; (C=0, B=11) NUM1: LD A,(HL) ;GET CHAR CALL SDELM ;DONE IF DELIMITER JP Z,NUM2 INC HL ;PT TO NEXT CHAR CALL DIGCK ;CHECK FOR DIGIT IN A JP C,NUMERR LD D,A ;DIGIT IN D LD A,C ;NEW VALUE = OLD VALUE * 10 RLCA ;*2 JP C,NUMERR RLCA ;*4 JP C,NUMERR ADD A,C ;*5 JP C,NUMERR RLCA ;*10 JP C,NUMERR ADD A,D ;NEW VALUE = OLD VALUE * 10 + DIGIT JP C,NUMERR ;CHECK FOR RANGE ERROR LD C,A ;SET NEW VALUE DEC B JP NZ,NUM1 ;COUNT DOWN ; ; RETURN FROM NUMBER ; NUM2: LD A,C ;GET ACCUMULATED VALUE POP BC OR A ;CLEAR CARRY RET ; ; RESTORE STACK AND RETURN WITH CARRY SET ; NUMERR: POP BC SCF RET ; ; CHECK TO SEE IF A IS A DIGIT ; IF SO, RETURN ITS VALUE ; IF NOT, RETURN WITH CARRY SET ; DIGCK: SUB '0' ;DIGIT? RET C ;ERROR CP 10 ;RANGE? JP NC,DIGCK1 CCF ;FLIP CARRY RET DIGCK1: SCF ;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: Z3PSPEED ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public putspeed ext envptr ; ; PUTSPEED sets the processor speed in A. ; No registers are affected. ; putspeed: push hl ;save regs push de push af ld hl,(envptr) ;pt to environment ld de,2bh ;pt to byte address add hl,de pop af ;get value ld (hl),a ;put value pop de ;restore regs pop hl ret end ; ; Z3LIB Module Name: Z3PWHL ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public putwhl ext envptr ; ; PUTWHL sets the wheel byte to the value in A. ; No registes are affected. ; putwhl: push hl push de push af ld hl,(envptr) ;pt to environment ld de,29h ;pt to wheel byte address add hl,de ld a,(hl) ;get address in HL inc hl ld h,(hl) ld l,a pop af ;get wheel byte ld (hl),a ;put wheel byte in A pop de ;restore regs pop hl ret end ; ; Z3LIB Module Name: Z3PZNC ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public putznc 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 hl call getenv ;pt to environment ld a,h ;any environment? or l jp z,error push de ;pt to message byte ld de,34 ;offset to message ptr add hl,de ld e,(hl) ;get address of messages inc hl ld d,(hl) ex de,hl ;HL pts to message pop de ld a,h ;any messages? or l jp z,error push de ;pt to Zex Next Char Address ld de,9 add hl,de pop de ;restore DE ex de,hl ld (temp),hl ;save DE ex de,hl pop de ;get ptr to next char ld (hl),e ;get address inc hl ld (hl),d push de ;save ptr ld hl,(temp) ex de,hl ;restore DE pop hl xor a ;set Z and Clear Carry ret error: pop hl ;restore HL scf ;set carry ret temp: ds 2 end ; ; Z3LIB Module Name: Z3PZR ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public putzrun 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 hl push af ;save value call getenv ;pt to environment ld a,h ;any environment? or l jp z,error push de ;pt to message byte ld de,34 ;offset to message ptr add hl,de ld e,(hl) ;get address of messages inc hl ld d,(hl) ex de,hl ;HL pts to message pop de ld a,h ;any messages? or l jp z,error push de ;pt to Zex Running Flag ld de,8 add hl,de pop de pop af ;get byte ld (hl),a ;put byte pop hl ;restore HL ret error: pop af ;restore A pop hl ;restore HL scf ;set carry ret end ; ; Z3LIB Module Name: Z3QCOUT ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public qcout 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 af ;affect no regs call getquiet ;get flag jp z,notquiet ;not quiet, so print pop af ;restore PSW ret notquiet: pop af ;restore PSW jp ccout ;perform normal output end ; ; Z3LIB Module Name: Z3QCRLF ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public qcrlf ext getquiet,crlf ; ; QCRLF outputs the CR-LF sequence if the quiet flag ; says it is OK to do so. ; qcrlf: push af ;affect no regs call getquiet ;get flag jp z,notquiet ;not quiet, so print pop af ;restore PSW ret notquiet: pop af ;restore PSW jp crlf ;perform normal output end ; ; Z3LIB Module Name: Z3QNDR ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public dirndr,dundr ext envptr,getndr,caps ; ; Macros ; putrg macro push hl push de push bc endm getrg macro pop bc pop de pop hl endm ; ; DIRNDR searches through the current named directory for the name ; whose buffer is pointed to by HL. This name is automatically capitalized. ; HL pts to an 8-character buffer containing the name to search for. ; On exit, A=0 and Zero Flag Set if name not in buffer or no NDR buffer. ; If found, BC = DU (disk A = 1) associated with name and HL = address of ; NDR entry. ; dirndr: push de ld (dname),hl ;save ptr to name call getndr ;get ptr to NDR jp z,direx dir1: ld a,(hl) ;check for done or a ;0=done jp z,direx call compdir ;compare dir names jp z,dir2 ;found ld de,18 ;pt to next entry add hl,de jp dir1 dir2: ld b,(hl) ;B=disk inc hl ld c,(hl) ;C=user dec hl ;HL = address of entry or 0ffh ;NZ for OK direx: pop de ret ; ; Compare entry pted to by HL with that in buffer ; Return with Z if match ; compdir: push hl push de inc hl ;pt to name inc hl ex de,hl ;DE pts to dir entry, HL pts to target ld hl,(dname) ld b,8 ;8 chars cdir1: ld a,(hl) ;get target call caps ;capitalize ld c,a ld a,(de) ;get source cp c jp nz,cdir2 inc hl ;pt to next inc de dec b ;count down jp nz,cdir1 cdir2: pop de ;restore regs pop hl ret ; ; DUNDR searches through the current named directory for the DU ; contained in BC (disk A = 1). ; ; On exit, A=0 and Zero Flag Set if name not in buffer or no NDR buffer. ; If found, HL = address of NDR entry. ; dundr: push de call getndr ;get ptr to NDR jp z,direx du1: ld a,(hl) ;check for done or a ;0=done jp z,direx cp b ;check disk jp nz,du2 ;no match yet inc hl ld a,(hl) ;get user dec hl cp c ;check user jp nz,du2 ;not found or 0ffh ;NZ for OK pop de ;HL pts to entry ret du2: ld de,18 ;pt to next entry add hl,de jp du1 ; ; Data ; dname: ds 2 ;pointer to target name buffer end ; ; Z3LIB Module Name: Z3QOUT ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public qout ext getquiet,cout ; ; QOUT outputs the character in A if the quiet flag ; says it is OK to do so. ; qout: push af ;affect no regs call getquiet ;get flag jp z,notquiet ;not quiet, so print pop af ;restore PSW ret notquiet: pop af ;restore PSW jp cout ;perform normal output end ; ; Z3LIB Module Name: Z3QPRINT ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public qprint 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 af ;affect no regs call getquiet ;get flag jp z,notquiet ;not quiet, so print pop af ;restore PSW ex (sp),hl ;get ptr to string push af ;save PSW qpr1: ld a,(hl) ;get next char inc hl ;pt to following char or a ;end of string? jp nz,qpr1 pop af ;restore PSW ex (sp),hl ;done ret notquiet: pop af ;restore PSW jp print ;perform normal print end ; ; Z3LIB Module Name: Z3QPSTR ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public qpstr ext getquiet,pstr ; ; QPSTR prints the string pted to by HL if the quiet flag ; says it is OK to do so. ; qpstr: push af ;affect no regs call getquiet ;get flag jp z,notquiet ;not quiet, so print pop af ;restore PSW ret notquiet: pop af ;restore PSW jp pstr ;perform normal print end ; ; Z3LIB Module Name: Z3ROOT ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public root ext envptr,retud ; ; ROOT returns the DU of the root directory in BC. No other registers ; are affected. ; root: push de ;save DE push hl ;save HL ld hl,(envptr) ;pt to environment ld de,9 ;pt to path entry add hl,de ld e,(hl) ;get path address in DE inc hl ld d,(hl) ex de,hl ;HL pts to path call retud ;get current DU ld a,h ;no path? or l jp z,rootx rootl: ld a,(hl) ;get next path element or a ;end of path? jp z,rootx ;done if so call retud ;get current DU cp '$' ;current disk? jp z,root1 ld b,a ;get disk in B dec b ;adjust for A=0 root1: inc hl ;pt to user ld a,(hl) ;get user inc hl ;pt to next path element cp '$' ;current user? jp z,rootl ;advance ld c,a ;set user jp rootl ;continue rootx: pop hl ;restore HL pop de ;restore DE ret end ; ; Z3LIB Module Name: Z3SHEMPTY ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public shempty 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 hl ;save HL call getsh ;get ptr to shell stack jp z,noshell ;error if no shell stack ld a,(hl) ;check first element noshell: or a ;set flags pop hl ;get HL ret end ; ; Z3LIB Module Name: Z3SHFULL ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public shfull ext getsh ; ; Macros ; putrg macro push hl push de push bc endm getrg macro pop bc pop de pop hl 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 jp z,noshell ;error if no shell stack ld e,b ;size of element in DE ld d,0 ld b,a ;number of elements in B ld c,0ffh ;set not full code ; ; Check to see if shell stack is full ; fchk: ld a,(hl) ;get next element or a ;last element on stack? jp z,fchk1 ;stack ok add hl,de ;pt to next element dec b ;count down jp nz,fchk ; ; No Shell Error - Say that Shell is Full ; noshell: ld c,0 ;set full code fchk1: ld a,c ;get full code getrg ;restore registers or a ;set flag ret end ; ; Z3LIB Module Name: Z3SHPOP ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public shpop ext getsh ; ; Macros ; putrg macro push hl push de push bc endm getrg macro pop bc pop de pop hl 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 jp z,noshell ;error if no shell stack ld c,a ;save number of elements in C ld a,(hl) ;get first element or a ;empty stack? jp z,empty ld e,b ;DE=size of shell stack entry ld d,0 ex de,hl ;HL=dest add hl,de ;DE=source ex de,hl copy: ld (hl),0 ;set zero if no elements to copy ld a,c ;see if any elements to copy cp 1 jp z,done dec c ;count down elements push bc ;save values copy1: ld a,(de) ;copy stack entry ld (hl),a inc hl ;pt to next inc de dec b ;count down jp nz,copy1 pop bc ;get values jp copy done: getrg ;restore registers xor a ;all is well ret ; ; No Shell Stack Available ; noshell: getrg ;restore registers ld a,1 ;error code or a ret ; ; Shell Stack is Empty ; empty: getrg ;restore registers ld a,2 ;error code or a ret end ; ; Z3LIB Module Name: Z3SHPUSH ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public shpush ext getsh2 ; ; Macros ; putrg macro push hl push de push bc endm getrg macro pop bc pop de pop hl 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 hl ;save ptr to string call getsh2 ;get ptr to shell stack pop hl ;get ptr to string jp z,noshell ;error if no shell stack ; ; See if string is too long ; push hl ;save ptr to string cksize: ld a,(hl) ;get elt inc hl ;pt to next or a ;end of string? jp z,cks1 dec e ;count down jp nz,cksize jp toobig ;string is too long cks1: ; ; Check to see if shell stack is full ; call getsh2 ;get values for copy fchk: ld a,(hl) ;get next element or a ;last element on stack? jp z,fchk1 ;stack ok add hl,de ;pt to next element dec b ;count down jp nz,fchk jp noroom ;shell is full fchk1: ; ; Copy current shell stack up ; call getsh2 ;get shell stack values ; ; Point to end of new top element ; push bc move0: ld a,b ;check for done cp 1 jp z,move1 add hl,de ;pt to next dec b ;count down jp move0 move1: pop bc ld c,e ;get count of elements in C dec hl ;pt to first byte to copy ex de,hl ;DE pts to source add hl,de ;HL pts to destination ; ; Copy stack up one entry size ; move2: ld a,b ;check for copy done cp 1 ;one less element jp z,move4 dec b ;count down push bc ;B=number of elements left , C=size of each move3: ld a,(de) ;get ld (hl),a ;put dec hl ;back up dec de dec c ;count down jp nz,move3 pop bc ;get values jp move2 move4: call getsh2 ;get ptr to shell stack pop de ;get ptr to string ; ; Copy new shell entry from DE to HL ; copy: ld a,(de) ;get byte ld (hl),a ;put byte inc hl ;pt to next inc de or a ;done? jp nz,copy getrg ;restore registers xor a ;OK return ret ; ; No Shell Stack Available ; noshell: pop hl ;restore HL getrg ;restore registers ld a,1 ;error code or a ret ; ; No Room on Shell Stack ; noroom: pop hl ;restore HL getrg ;restore registers ld a,2 ;error code or a ret ; ; String is too large ; toobig: pop hl ;restore HL getrg ;restore registers ld a,3 ;error code or a ret end ; ; Z3LIB Module Name: Z3SNDR ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public subndr ext envptr,getndr,caps ; ; Macros ; putrg macro push hl push de push bc endm getrg macro pop bc pop de pop hl endm ; ; SUBNDR subtracts a directory name to the named directory buffer, if ; possible. HL pts to an 8-character buffer containing the name to delete. ; On exit, A=0 and Zero Flag Set if name not in buffer or no NDR buffer. ; ; On input, ; HL = address of 8-char name ; On output, A = 0 and Z if error (no NDR or name not in NDR) ; subndr: putrg ld (dname),hl ;save ptr to dir name call getndr ;get ptr to named directory buffer jp z,suberr ; ; Compute possible number of entries in directory ; 7 * (number of 128-byte records) ; ld b,7 ;count number of dir entries ld c,a ;number of records in A xor a ;zero accumulated value subn1: add a,b ;add increment dec c ;count down jp nz,subn1 ld c,a ;max number of entries in C ; ; Look for entry (every 18 bytes) ; ld de,18 ;size of each entry subn2: ld a,(hl) ;end of dir? or a ;0=end jp z,suberr call compnam ;compare names jp z,found add hl,de ;pt to next name dec c ;count down jp nz,subn2 ; ; Error Exit ; suberr: getrg xor a ;error ret ; ; Compare name whose entry is pted to by HL against that pted to by DNAME ; Return with Zero Set if match ; compnam: putrg ex de,hl ;DE pts to name in buffer inc de ;pt to name itself inc de ld hl,(dname) ;HL pts to DNAME ex de,hl comp1: ld a,(de) ;get dname call caps ;capitalize cp (hl) ;match? jp nz,compex inc hl ;pt to next inc de dec b ;count down jp nz,comp1 compex: getrg ret ; ; Name found: ; HL = address of match ; DE = 18 (size of entry) ; found: ex de,hl add hl,de ;HL pts to next entry, DE pts to entry to del ; ; Check for completion ; found1: ld b,18 ;copy/fill 18-byte entry ld a,(hl) ;check for end of dir or a ;0=end jp z,found3 ; ; Move entry up ; found2: ld a,(hl) ;copy ld (de),a inc hl ;pt to next inc de dec b ;count down jp nz,found2 jp found1 ;check next ; ; Zero-Fill deleted last entry ; found3: ld (de),a ;zero-fill entry to delete inc de dec b ;count down jp nz,found3 ; ; OK exit ; getrg or 0ffh ;NZ return ret ; ; Data ; dname: ds 2 ;ptr to name to delete end ; ; Z3LIB Module Name: Z3WAIT1 ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public wait1s ext getspeed ; ; WAIT1S delays for approximately 1 second. The ZCPR3 environment ; (particularly processor speed data) is assumed. ; wait1s: push af ;affect no regs push de push bc call getspeed ;get processor speed jp nz,w1 ld a,4 ;assume 4MHz if none given w1: ld b,a ;speed in B loop0: ld d,50 ;50 outer loops = 50*20,010 = 1,000,500 cycles loop1: ld e,230 ;230 inner loops = 230*87 = 20,010 cycles loop2: ex (sp),hl ;18 cycles ex (sp),hl ;+18 = 36 cycles ex (sp),hl ;+18 = 54 cycles ex (sp),hl ;+18 = 72 cycles dec e ;+ 5 = 77 cycles jp nz,loop2 ;+10 = 87 cycles dec d ;outer loop jp nz,loop1 dec b ;speed loop jp nz,loop0 pop bc ;restore regs pop de pop af ret end ; ; Z3LIB Module Name: Z3WAIT2 ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public wait1ms ext getspeed ; ; WAIT1MS delays for approximately 1 millisecond. The ZCPR3 environment ; (particularly processor speed data) is assumed. ; wait1ms: push af ;affect no regs push de push bc call getspeed ;get processor speed jp nz,w1 ld a,4 ;assume 4MHz if none given w1: ld b,a ;speed in B loop0: ld e,20 ;20 inner loops = 20*51 = 1020 cycles loop1: ex (sp),hl ;18 cycles ex (sp),hl ;+18 = 36 cycles dec e ;+ 5 = 41 cycles jp nz,loop1 ;+10 = 51 cycles dec b ;speed loop jp nz,loop0 pop bc ;restore regs pop de pop af ret end ; ; Z3LIB Module Name: Z3WAIT3 ; Author: Richard Conn ; Z3LIB Version Number: 1.3 ; Module Version Number: 1.1 ; public waitp1s ext getspeed ; ; WAITP1S delays for approximately 0.1 second. The ZCPR3 environment ; (particularly processor speed data) is assumed. ; waitp1s: push af ;affect no regs push de push bc call getspeed ;get processor speed jp nz,w1 ld a,4 ;assume 4MHz if none given w1: ld b,a ;speed in B loop0: ld d,5 ;5 outer loops = 5*20,010 = 100,050 cycles loop1: ld e,230 ;230 inner loops = 230*87 = 20,010 cycles loop2: ex (sp),hl ;18 cycles ex (sp),hl ;+18 = 36 cycles ex (sp),hl ;+18 = 54 cycles ex (sp),hl ;+18 = 72 cycles dec e ;+ 5 = 77 cycles jp nz,loop2 ;+10 = 87 cycles dec d ;outer loop jp nz,loop1 dec b ;speed loop jp nz,loop0 pop bc ;restore regs pop de pop af ret end