home *** CD-ROM | disk | FTP | other *** search
-
- ; BE SURE TO CHECK ZCPR3 EQUATE BELOW BEFORE ASSEMBLING
- ;
- ; ********************************************
- ; * *
- ; * MAKE USER NUMBER CHANGE *
- ; * *
- ; * SYNTAX: MAKE D:AFN O /O (ALL) *
- ; * MAKE DU:AFN O /O (ALL) *
- ; * MAKE DIR:AFN O /O (ZCPR3) *
- ; * *
- ; * where the drive, drive/user, and *
- ; * named directory forms (where *
- ; * appropriate) are optional *
- ; * *
- ; * and *
- ; * *
- ; * where O is one of the options: *
- ; * *
- ; * DIR: new DIR for files (ZCPR3) *
- ; * DU: new DU for files *
- ; * U: new DU for files *
- ; * nn new user # for files *
- ; * R set files to R/O *
- ; * W set files to R/W *
- ; * S set files to SYS *
- ; * D set files to DIR *
- ; * A set files to ARCHIVE *
- ; * N set files to Non-ARCHIVE *
- ; * E erase files *
- ; * U unerase files *
- ; * blank show status of files *
- ; * *
- ; * /O auto delete of dest file *
- ; * *
- ; * for built-in help screen enter *
- ; * MAKE // *
- ; * *
- ; ********************************************
-
-
- ; This primary purpose of this program is to allow one to change the user
- ; number of designated files on a designated drive to a different user number.
- ; This is carried out without copying the files and then deleting the original
- ; files; rather, the user number tag in the disk directory is simply changed
- ; to reflect the new user number. The program also has options to set files
- ; attributes of read-only, read-write, system, and directory. Files can also
- ; be erased or unerased.
-
- ; The code assumes that the track and sector are set by the BDOS search
- ; functions and uses a simple BIOS write to update the directory. Before using
- ; this program, test it on a garbage disk to make sure that it works with your
- ; system.
-
- ; VERSION 1.0 - 07/05/81 R.E.D.
- ; 1.1 - 07/15/81 R.E.D.
- ;
- ; 1.2 - 8/1/82
- ; ENHANCED FILE NAME DISPLAY.
- ; KEN LOVETT
- ; 1.3 - 8/6/83
- ; FIXED BUG WHICH CAUSED LAST CHAR IN FILE SPEC TO
- ; BE NON-SIGNIFICANT.
- ; KEN LOVETT
- ; 2.0 - 8/7/83
- ; ADDED OPTIONS TO SET R/O, R/W, SYS, DIR FLAGS. ALSO
- ; ERASE AND UNERASE FILES.
- ; KEN LOVETT
- ;
- ; 2.1 - 6/20/85
- ; Added (actually, just enabled - it was always there)
- ; full 32 (0-31) area capability, extended display routine
- ; to handle the higher user numbers, added a four-byte kludge
- ; of a display fix required by late-model Kaypros and merely
- ; harmless otherwise, other minor display stuff.
- ; Bruce Morgen
- ;
- ; 2.2 - 07/02/85
- ; Major cleanup of the code (which was highly unstructured and
- ; thus hard to read). Added check on user number of files so
- ; that the code will act only on files in the logged in area.
- ; There is still no checking to make sure that there is not
- ; already a file in the destination user area of the same name
- ; as the file that is being moved in.
- ; Jay Sage
- ;
- ; 2.3 - 07/14/85
- ; In ZCPR3 systems the CCP processes the DU: and named directory
- ; forms of directory specification. The drive value is returned
- ; in the usual way in the FCB, and the user number is placed in
- ; the S1 byte. Version 22Z of MAKE allows the syntax:
- ;
- ; MAKE DIR:AFN OPTION
- ;
- ; The files to be operated on can be specified using the full
- ; ZCPR3 format. The option can even take the DIR: form with a
- ; named directory. The ZCPR3 equate determines whether a
- ; ZCPR3 version or a standard version will be assembled.
- ; For some reason, even though there is no change in allocation,
- ; performing any write to the directory sets the disk to R/O
- ; status. I have changed the code I originally put it to
- ; reset the disk system whenever any write has occurred. I had
- ; not noticed this problem because I use the ZRDOS replacement
- ; for the BDOS, and it automatically relogs changed disks.
- ; Jay Sage
- ;
- ; 2.4 - 06/15/86
- ; Added ability to SET or RESET the ARCHIVE bit, and added
- ; the WHEEL conditional, which makes MAKE disappear
- ; (echoes: MAKE?) unless the wheel byte is set.
- ; Michael Conley
- ;
- ; 2.5 - (an obsolete version # observed in the Chicago area dated
- ; 1984 - skipped to avoid confusion.
- ;
- ; 2.6 - 07/22/86
- ; Added "All users" switch for any options not involving a
- ; user number. A number sign after the selected option
- ; makes it operate on ALL user areas, not just the current
- ; one. (e.g., MAKE *.BAK E# -- would erase all .BAK files
- ; in all user areas.)
- ; Michael Conley
- ;
- ; 2.7 - 04/10/88
- ; Added DU: support for both source and destination while
- ; not needing ZCPR3. Added destination existence checking
- ; and auto erasure/manual prompting for erasure of destination
- ; file of same name. (will abort processing if other than
- ; a Y/y answer to delete file on destination. UNERASE now
- ; works on specified user(if supplied before filename)
- ; Eugene Nolan
- ;
- ;=============================================================================
-
- ; P R O G R A M E Q U A T E S
-
- ;=============================================================================
-
-
- VERSION EQU 27
-
- FALSE EQU 0
- TRUE EQU NOT FALSE
-
- ZCPR3 EQU FALSE ;true for ZCPR3 version, false for general CP/M
-
- WHEEL EQU FALSE ;true to test wheel byte before running
- WHLADR EQU 3EH ;wheel byte location
-
- BDOS EQU 0005H ;BDOS entry address
- DMAADDR EQU 0080H ;default CP/M file buffer
- FCB EQU 005CH ;default CP/M FCB
- TFCB EQU 006CH ;temporary FCB
- Z3ENV EQU 00000H ;ZCPR3 environment address filled in by Z3INS
- CR EQU 0DH ;(z3env not presently needed anyway)
- LF EQU 0AH
- TAB EQU 09H
- BELL EQU 07H
-
- ;
- ;
- ;
- ;=============================================================================
-
- ; M A I N P R O G R A M C O D E
-
- ;-----------------------------------------------------------------------------
-
-
- ORG 0100H
-
- MAKE:
-
- IF ZCPR3
-
- ;ZCPR3 initialization (not actually needed here, but if one
- ;runs the install program it will not report a bad utility)
-
- JMP START
- DB 'Z3ENV'
- DB 1 ;external enviroment
- DW Z3ENV ;environment address (value is not used here)
- START:
-
- ENDIF ;ZCPR3
-
- ;set up local stack pointer
-
- LXI H,0 ;get CP/M stack pointer
- DAD SP
- SHLD OLDSTK ;save it for later return
- LXI SP,NEWSTK ;set up new local stack
-
- ;perform setup tasks
-
- IF WHEEL
- LDA WHLADR ;get wheel byte
- ORA A ;is it set?
- JZ EREXIT ;no/don't run
- ENDIF ;wheel
-
- CALL SIGNON ;print signon message
-
-
- CALL CHKHLP ;see if help requested and go there if so
-
- IF NOT ZCPR3 ;if ZCPR2, we assume correct version of CP/M
- CALL CHKVER ;abort if not CP/M version 2.0 or later
- ENDIF ;NOT ZCPR3
-
- CALL INIT ;set up data areas
-
-
- CALL SETDU ;handle current and specified DU areas
- CALL GETOPT ;get option from command line (abort if bad)
- CALL CHKRO ;abort if destination drive is R/O and option
- ;..requests change in files
-
- ;begin main work of program
-
- CALL SRCHF ;locate first directory entry (abort if none)
-
- LOOP: CALL SETPTR ;set DMAPTR to point to disk directory FCB
- CALL CHKFIL ;check for applicable file
- CNC CALLOPT ;if applicable file, process option
-
- NEXTFIL: ;go on to next file
-
- LXI H,DIRCODE ;point to the directory code
- INR M ;increase it one
- MOV A,M ;get new value
- CPI 04 ;check for four FCB entries completed
- JNZ LOOP ;if not, go back and continue
-
- ;process this group of four files and go on to next
-
- LXI H,CHGFLAG ;point to change flag
- MOV A,M ;get it into A
- MVI M,0 ;reset it
- ORA A ;set flags from original value
- CNZ WRTDE ;if changes were made, write the buffer back
-
- ;sequence through files to get new buffer-full of FCB's
-
- SRNXT: LXI D,AMBFIL ;point to any-match FCB
- MVI C,12H ;BDOS search-next function
- CALL BDOS
- CPI 0FFH ;see if end of entries
- JZ QUIT ;quit if no more files
- CPI 0 ;loop until buffer is updated by BDOS
- JNZ SRNXT ;jump until dircode is zero
- STA DIRCODE ;save the 0 in dircode
- JMP LOOP ; and loop again
-
- ;=============================================================================
-
- ; O P T I O N P R O C E S S I N G R O U T I N E S
-
- ;-----------------------------------------------------------------------------
-
- ; Set the file attribute to SYS. If the file was not already SYS, then the
- ; CHGFLAG is set to indicate the need later to write the modified sector out
- ; to disk.
-
- SETSYS:
- LHLD DMAPTR ;point to disk directory FCB entry
- LXI D,10 ;offset 10 to DIR/SYS byte
- DAD D
- MOV A,M ;get the SYS/DIR byte
- ORA A ;test current state of SYS bit
- CP SETCHGFL ;if not already SYS, set the change flag
- ORI 80H ;make sure it is set
- MOV M,A ;write modified byte back out
- CALL REPORT ;report the new file status
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; Set the file attribute to DIR. If the file was not already DIR, then the
- ; CHGFLAG is set to indicate the need later to write the modified sector out
- ; to disk.
-
- SETDIR:
- LHLD DMAPTR ;point to disk directory FCB entry
- LXI D,10 ;offset 10 to SYS/DIR byte
- DAD D
- MOV A,M
- ORA A ;sign flag shows state of SYS bit
- CM SETCHGFL ;if not already DIR, set change flag
- ANI 7FH ;clear the DIR bit
- MOV M,A ;write modified byte back to buffer
- CALL REPORT ;report the new file status
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; Set the file attribute to R/O. If the file was not already R/O, then the
- ; CHGFLAG is set to indicate the need later to write the modified sector out
- ; to disk.
-
- SETRO:
- LHLD DMAPTR ;point to disk directory FCB entry
- LXI D,9 ;offset 9 to R/O-R/W byte
- DAD D
- MOV A,M
- ORA A ;test current state of R/O bit
- CP SETCHGFL ;if not already R/O, set the change flag
- ORI 80H ;make sure it is set
- MOV M,A ;write modified byte back out
- CALL REPORT ;report the new file status
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; Set the file attribute to R/W. If the file was not already R/W, then the
- ; CHGFLAG is set to indicate the need later to write the modified sector out
- ; to disk.
-
- SETRW:
- LHLD DMAPTR ;point to disk directory FCB entry
- LXI D,9 ;offset 9 to R/O-R/W byte
- DAD D
- MOV A,M
- ORA A ;sign flag shows state of R/O-R/W bit
- CM SETCHGFL ;if not already R/W, set change flag
- ANI 7FH ;clear the R/O bit
- MOV M,A ;write modified byte back to buffer
- CALL REPORT ;report the new file status
- RET
- ;-----------------------------------------------------------------------------
- ; Set the file attribute to ARC. If the file was not already ARC, then the
- ; CHGFLAG is set to indicate the need later to write the modified sector out
- ; to disk.
-
- SETARC:
- LHLD DMAPTR ;point to disk directory FCB entry
- LXI D,11 ;offset 10 to ARCHIVE byte
- DAD D
- MOV A,M ;get the ARCHIVE byte
- ORA A ;test current state of ARC bit
- CP SETCHGFL ;if not already ARC, set the change flag
- ORI 80H ;make sure it is set
- MOV M,A ;write modified byte back out
- CALL REPORT ;report the new file status
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; RESET the ARCHIVE file attribute. If the file was already ARC, then the
- ; CHGFLAG is set to indicate the need later to write the modified sector out
- ; to disk.
-
- SETNRC:
- LHLD DMAPTR ;point to disk directory FCB entry
- LXI D,11 ;offset 10 to ARCHIVE byte
- DAD D
- MOV A,M
- ORA A ;sign flag shows state of ARC bit
- CM SETCHGFL ;if it was ARC, set change flag
- ANI 7FH ;clear the ARC bit
- MOV M,A ;write modified byte back to buffer
- CALL REPORT ;report the new file status
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; Erase the file by writing E5 as the user number tag. We know that the file
- ; is not already erased because of the work of subroutine CHKFIL earlier.
- ; Therefore, we must set the change flag to show the need to write the sector
- ; back out to disk.
-
- ERASE:
- LHLD DMAPTR
- MVI M,0E5H
- CALL SETCHGFL ;show need to write sector back to disk
- CALL REPORT ;report the new file status
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; Unerase the file by writing the current user number into the tag byte in
- ; place of the E5. The comments under ERASE apply here, too.
-
- UNERA:
- LDA SRCUSR ;get logged/specified in user number
- LHLD DMAPTR
- MOV M,A ;put it into disk directory user # tag
- CALL SETCHGFL ;show need to write sector back to disk
- CALL REPORT ;report the new file status
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; Change the user number of the file.
-
- CHUSER: LDA OPTION ;get user number
- LHLD DMAPTR ;point to place to put it
- MOV M,A ;put new user number in directory
- CALL SETCHGFL ;show need to write sector back out to disk
- CALL REPORT ;report the new file status
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; This code reports the attributes of the files acted on and, if required,
- ; the erased or unerased status. This code is called directly by the blank
- ; option and indirectly by all the other option processors after they have
- ; finished performing their changes on the files.
-
- REPORT: CALL PRTFN ;print the file name
- CALL ILPRT ;print spacer and equal sign
- DB ' = ',0
- CALL PRTOPT ;print the option letter or number
- MVI C,3 ;put in three more blank spaces
- CALL PRTBLK
- CALL PRTATTR ;print file attributes
- LDA OPTION ;see if files erased
- CPI 'E'
- CZ PRTERA ;if so, print erased message
- LDA OPTION
- CPI 'U' ;see if files unerased
- CZ PRTUNE ;if so, print unerased message
- RET
-
-
- ;=============================================================================
-
- ; P R O G R A M F L O W R O U T I N E S
-
- ;-----------------------------------------------------------------------------
-
- ; CALLOPT
-
- ; This routine uses the value of OPTION to look up the processing routine
- ; to which to branch.
-
- CALLOPT:
- LXI H,JMPTBL ;point to jump table
- LDA OPTION ;get user number or option letter
- MOV B,A ;save it in B
-
- LOOKUP: MOV A,M ;get option letter from table
- INX H ;point to jump address
- ORA A ;end of table?
- JZ JMPOPT2 ;if so, jump
- CMP B ;do we match a table entry
- JZ JMPOPT1 ;if so, go to code to get jump address
- INX H ;else jump over jump address to
- INX H ;..next option character
- JMP LOOKUP ;and try again
-
- JMPOPT1:
- MOV A,M ;get low part of jump address into A
- INX H ;point to high part of address
- MOV H,M ;get it into H
- MOV L,A ;jump address is in HL
- PCHL ;jump to it
-
- JMPOPT2:
- LXI H,CHUSER ;default to change user routine
- PCHL ;jump to it
-
- JMPTBL: DB ' '
- DW REPORT
-
- DB 'S'
- DW SETSYS
-
- DB 'D'
- DW SETDIR
-
- DB 'R'
- DW SETRO
-
- DB 'W'
- DW SETRW
-
- DB 'A'
- DW SETARC
-
- DB 'N'
- DW SETNRC
-
- DB 'E'
- DW ERASE
-
- DB 'U'
- DW UNERA
-
- DB 0 ;end of table mark
-
- ;-----------------------------------------------------------------------------
-
- ; QUIT
-
- ; This code sends a CRLF to the console, restores the original CP/M stack,
- ; and returns to CP/M. If indicated by the reset flag, it resets the disk
- ; system. The logged DU area when the program was invoked is restored. The
- ; entry point QUIT2 is used by code (CHKHLP and CHKVER) that have not changed
- ; the logged in directory.
-
- QUIT: CALL CRLF
-
- ;log in the original drive/user
-
- LDA DEFDRV ;get original default drive
- CALL LOGDRV ;log it in
- LDA DEFUSR ;get original default user
- CALL LOGUSR ;log it in
-
- ;see if we need to reset the disk system
-
- QUIT1: LDA RSTFLAG
- ORA A ;if reset flag is clear
- JZ QUIT2 ;..we can skip disk system reset
-
- ;reset the disk system
-
- MVI C,0DH
- CALL BDOS
-
- ;restore the original stack
-
- QUIT2: LHLD OLDSTK ;get original stack pointer
- SPHL ;set it up
- RET ;back to CP/M
-
- IF WHEEL
- EREXIT: ;if using wheel byte and wheel not set
- CALL ILPRT ;we pretend the program doesn't exist
- DB 'MAKE?',0 ;by printing phony CCP error.
- JMP QUIT2
- ENDIF ;wheel
-
- ;=============================================================================
-
- ; F I L E S E L E C T I O N S U B R O U T I N E S
-
- ;-----------------------------------------------------------------------------
-
- ; CHKFIL
-
- ; This subroutine checks to see whether or not the FCB pointed to in the
- ; DMA buffer is one that should be acted on. If not, the routine returns
- ; with the zero flag set.
-
- CHKFIL: CALL CHKUN ;check user number and erased status of file
- RC ;return with carry set to skip file
- CALL CHKFN ;next check the file name for a match
- RET ;return showing status of name match
-
- ;-----------------------------------------------------------------------------
-
- ; CHKUN
-
- ; This subroutine checks the user number status of a file and sets the carry
- ; flag if the file should be skipped over. If the option is UNERASE and the
- ; file is not an erased file, it should be skipped. If the option is not
- ; unerase and the file is an erased file, then likewise it should be skipped.
- ; Finally, if the file is in a user number other than the logged in user, it
- ; should also be skipped.
-
- CHKUN: ;test file erased status
-
- LHLD DMAPTR ;point to user number tag of file
- MOV A,M ;get the tag
- CPI 0E5H ;carry flag set if not erased
- PUSH PSW ;save flag
-
- ;test program option status
-
- LDA OPTION ;get the option
- CPI 'U' ;is it unerase?
- JNZ CHKUN1 ;if not, skip to CHKUN1
-
- ;case of unerase option
-
- POP PSW ;carry flag set if not erased
- RET ;file not erased will be skipped
-
- ;case of option other than unerase
-
- CHKUN1: POP PSW
- CMC ;carry flag set if file erased
- RC ;erased file will be skipped
-
- ;now check for user number in source area
-
- LDA ALLUSR ;see if "all users" was requested
- CPI '#' ;
- JZ CHKUN2 ;if so, skip over compare...
- LDA SRCUSR ;get source user number
- CMP M ;compare to file tag
- RZ ;if OK, return (carry is clear)
- STC ;else set carry
- CHKUN2:
- RET ;..and return
-
- ;-----------------------------------------------------------------------------
-
- ; CHKFN
-
- ; This subroutine compares the name of the file in the FCB in the DMA buffer
- ; with the specification from the command line.
-
- CHKFN: ;set up pointers and character count
-
- LHLD DMAPTR ;get pointer to FCB in DMA buffer
- INX H ;point to first character in the name
- LXI D,FCB+1 ;set DE to name in FCB from command line
- MVI C,0BH ;load count for compare
-
- CP1: LDAX D ;get fcb command line character
- CPI '?' ;see if anything matches
- JZ MATCH ;if it is '?', consider it a match
- SUB M ;get difference (see next instruction)
- ANI 7FH ;clear attribute bit
- JZ MATCH ;if zero, characters match
- STC ;else set carry
- RET ;..and return
-
- MATCH: INX D ;point to next characters
- INX H
- DCR C ;decrease count of characters
- JNZ CP1 ;loop until zero
- RET ;carry is clear showing names match
-
-
-
- ;=============================================================================
-
- ; D I S K O P E R A T I O N S U B R O U T I N E S
-
- ;-----------------------------------------------------------------------------
-
- ; SRCHF
-
- ; This subroutine uses the fully ambiguous file spec at AMBFIL to locate the
- ; first directory entry on the disk. The directory code (0-3) is saved. If
- ; no directory entry is found, then the program gives a message and branches
- ; to QUIT for a prompt return.
-
- SRCHF: LXI D,AMBFIL ;point to match any filename.typ
- MVI C,11H ;bdos search first function
- CALL BDOS ;do it
- STA DIRCODE ;save directory code
- CPI 0FFH ;see if end of entries
- RNZ ;if something found, return
- CALL ILPRT ;else give a message
- DB BELL,CR,LF
- DB 'No Files On Disk',CR,LF,0
- JMP QUIT
-
- ;-----------------------------------------------------------------------------
-
- ; WRTDE
-
- ; This routine writes the directory buffer back to the disk. I also sets the
- ; reset flag so that the disk system will be reset on program termination.
-
- WRTDE: LXI H,RSTFLAG ;point to the flag
- MVI M,0FFH ;set the flag
- MVI C,1H ;set BIOS write to directory
- ; C = 0 write to allocated
- ; C = 1 write to directory
- ; C = 2 write to unallocated
- CALL WRITE ;do the write
- ORA A ;check for error
- RZ ;if none, return
-
- CALL ILPRT
- DB BELL
- DB CR,LF
- DB 'Bad Sector Write Error',CR,LF,0
-
- JMP QUIT
-
- ;-----------------------------------------------------------------------------
-
- ; WRITE
-
- ; This routine is filled in during the operation of the program and performs
- ; a direct BIOS sector write operation on the currently selected track and
- ; sector.
-
- WRITE: JMP 0000 ;vector to bios write routine
-
-
- ;=============================================================================
-
- ; P R I N T I N G R O U T I N E S
-
- ;-----------------------------------------------------------------------------
-
- ; PRTFN
-
- ; This subroutine displays (at the beginning of the next line of the screen)
- ; the name of the file pointed to in the DMA buffer.
-
- PRTFN: CALL CRLF ;print cr/lf
- LHLD DMAPTR ;address of file fcb
- INX H ;skip to file name
- LXI D,BLNKCNT ;point to blanks counter
- XCHG ;exchange pointers
- MVI M,0 ;preset blank count to zero
-
- MVI C,8 ;length of file name
- CALL PRTSTR ;print the name first
-
- MVI A,'.' ;print the period
- CALL CHAROUT
-
- MVI C,3 ;now print the file type
- CALL PRTSTR
-
- MOV C,M ;get number of blanks needed for fill
- CALL PRTBLK ;print the blanks
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; PRTOPT
-
- ; This subroutine prints out the option as a letter or as a number as
- ; appropriate.
-
- PRTOPT: LDA OPTION ;get the option value
- CPI 20H ;if it's a user number, carry will be set
- JNC CHAROUT ;if not number, just print the character
- MVI B,'0'-1 ;preset for two-digit calculation later
- CPI 10 ;see if single digit
- JNC TWODIG ;if not, print two digits
- ADI '0' ;else convert to ASCII
- JMP CHAROUT ;and print it
- TWODIG: INR B ;count tens digit in B
- SUI 10 ;keep subtracting 10 until carry is set
- JNC TWODIG
- ADI 10 ;get remainder (units digit) back
- MOV C,A ;save it in C
- MOV A,B ;print tens digit
- CALL CHAROUT
- MOV A,C ;print units digit
- ADI '0'
- JMP CHAROUT
-
- ;-----------------------------------------------------------------------------
-
- ; PRTATTR
-
- ; This subroutine prints the attribute status (SYS or DIR and R/O or R/W)
- ; of the file currently being worked on.
-
- PRTATTR:
- LHLD DMAPTR ;point to file FCB
- LXI D,9 ;offset to R/O-R/W byte
- DAD D
- PUSH H ;save pointer for reuse below
- MOV A,M
- RAL ;move R/O bit into carry
- PUSH PSW ;save flags
- CC PRTRO ;if carry, print read-only
- POP PSW ;get flags back to test again
- CNC PRTRW ;if not carry, print read-write
-
- POP H ;get pointer back
- INX H ;point to SYS/DIR byte
- PUSH H ;save pointer for reuse below
- MOV A,M
- RAL ;move SYS/DIR bit into carry
- PUSH PSW ;save flags
- CC PRTSYS ;if carry, print SYS
- POP PSW ;get them back
- CNC PRTDIR ;if not carry, print DIR
- POP H
- INX H
- MOV A,M
- RAL ;move ARCHIVE bit into carry
- PUSH PSW ;save flags
- CC PRTARC ;if carry, print ARC
- POP PSW ;get them back
- CNC PRTNRC ;if not carry, print Non-ARC
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; MESSAGE PRINTING ROUTINES
-
- PRTRO: CALL ILPRT ;file is read-only
- DB ' R/O',0
- RET
-
- PRTRW: CALL ILPRT ;file is read-write
- DB ' R/W',0
- RET
-
- PRTSYS: CALL ILPRT ;file has SYS attribute
- DB ' SYS',0
- RET
-
- PRTDIR: CALL ILPRT ;file has DIR attribute
- DB ' DIR',0
- RET
-
- PRTARC: CALL ILPRT ;file has ARC attribute
- DB ' ARCHIVE',0
- RET
-
- PRTNRC: CALL ILPRT ;file has NO ARC attribute
- DB ' Non-ARC',0
- RET
-
- PRTERA: CALL ILPRT ;file erased
- DB ' *** ERASED ***',0
- RET
-
- PRTUNE: CALL ILPRT ;file unerased
- DB ' *** UNERASED ***',0
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; HELP
-
- ; This code displays the built in help screen and then jumps to QUIT to
- ; return to CP/M.
-
- HELP: CALL ILPRT
- DB CR,LF
- DB TAB,'Syntax: '
-
- IF ZCPR3
- DB 'MAKE [DIR:]AMBIG.FIL X[#]',CR,LF,LF
- DB '* where DIR: is an optional directory specifier',CR,LF
- DB ' using either the DU: or named directory format',CR,LF,LF
- ENDIF ;ZCPR3
-
- IF NOT ZCPR3
- DB 'MAKE [DU:][D:][U:]AMBIG.FIL [X][#][ /O]',CR,LF,LF
- DB '* where DU: is an optional drive-user,drive,user specifier'
- db CR,LF
- DB ' and /O cause auto delete of file on destination',cr,lf
- ENDIF ;NOT ZCPR3
-
- DB '* and where `X'' may be ONE of the options:',CR,LF,LF
-
- IF ZCPR3
- DB TAB,'DIR:',TAB,'Moves files to named directory DIR',CR,LF
- ENDIF ;ZCPR3
-
- DB TAB,'U ,U:, DU: ','Moves files to user # U (0-31)',CR,LF,LF
- DB 'The following operate in the current user area.',CR,LF
- DB 'Add a # to act on ALL user areas at once.',CR,LF,LF
- DB TAB,'S',TAB,'Sets file attribute(s) to SYSTEM',CR,LF
- DB TAB,'D',TAB,'Sets file attribute(s) to DIRECTORY',CR,LF
- DB TAB,'R',TAB,'Sets file attribute(s) to READ/ONLY',CR,LF
- DB TAB,'W',TAB,'Sets file attribute(s) to READ/WRITE',CR,LF
- DB TAB,'A',TAB,'Sets file attribute(s) to ARCHIVE',CR,LF
- DB TAB,'N',TAB,'Sets file attribute(s) to NON-ARCHIVE',CR,LF
- DB TAB,'E',TAB,'Erases the specified files',CR,LF
- DB TAB,'U',TAB,'Unerases the specified files',CR,LF,0
-
- JMP QUIT2
-
-
- ;=============================================================================
-
- ; G E N E R A L - P U R P O S E S U B R O U T I N E S
-
- ;-----------------------------------------------------------------------------
-
- ; CRTOUT
-
- ; This subroutine sends the character in register A to the console. Registers
- ; BC, DE, and HL are preserved.
-
- CHAROUT:
-
- PUSH H ;save registers
- PUSH D
- PUSH B
- MOV E,A ;get character into E
- MVI C,06 ;BDOS direct console I/O
- CALL BDOS
- POP B ;restore registers
- POP D
- POP H
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; CRLF
-
- ; This routine sends a carriage return and linefeed to the console.
-
- CRLF: CALL ILPRT
- DB CR,LF,0
- RET
-
-
- ;-----------------------------------------------------------------------------
-
- ; FILL
-
- ; This subroutine fills memory starting at HL for a length B with the byte
- ; in A.
-
- FILL:
- MOV M,A
- INX H
- DCR B
- JNZ FILL
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; ILPRT
-
- ; This subroutine prints the string that follows its call. The string must
- ; be terminated with a null (0).
-
- ILPRT: POP H ;get address following call into HL
-
- ILPRT1: MOV A,M ;get character from message
- INX H ;point to next character
- ORA A ;test for null indicating end of message
- JZ ILPRT2 ;if end, fix up return address
- MOV E,A ;have BDOS send character it to console
- MVI C,2
- PUSH H ;save pointer to string
- CALL BDOS
- POP H ;restore pointer
- JMP ILPRT1 ;process it
-
- ILPRT2: PUSH H ;set up return address to just past message
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; PRTSTR
-
- ; This subroutine prints a string of characters pointed to by DE. The number
- ; of characters is in the C register. Blanks are not printed; instead, the
- ; blanks counter pointed to by HL is incremented.
-
- PRTSTR: LDAX D ;get character
- CPI ' ' ;see if it is a blank
- CZ UPCOUNT ;if so, up the count
- CNZ CHAROUT ;if not, output the character
- INX D
- DCR C ;check count
- JNZ PRTSTR
- RET
-
- UPCOUNT:
- PUSH PSW ;save flags
- INR M ;increase the blank counter
- POP PSW ;restore flags
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; PRTBLK
-
- ; This subroutine prints blank spaces given by the count in C. The routine
- ; will work even for a count of zero.
-
- PRTBLK: INR C ;turn 0 into 1
- PRTBL1: DCR C ;check count
- RZ ;return if count exhausted
- MVI A,' ' ;set character to print
- CALL CHAROUT
- JMP PRTBL1
-
-
- ;=============================================================================
-
- ; S E T U P S U B R O U T I N E S
-
- ;-----------------------------------------------------------------------------
-
- ; SIGNON
-
- ; This subroutine displays the program signon message.
-
- SIGNON: CALL ILPRT
- DB CR,LF,'MAKE - Version '
- DB VERSION / 10 + '0'
- DB '.'
- DB VERSION MOD 10 + '0'
-
- IF ZCPR3
- DB ' for ZCPR3'
- ENDIF ;ZCPR3
-
- DB CR,LF,0
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; CHKHLP
-
- ; This subroutine checks to see if the user has invoked the program in a
- ; way to request the built-in help screen. The help screen is shown if the
- ; command has no tail or if the tail begins with a slash.
-
- CHKHLP: LDA FCB+1 ;get first character of first parameter
- CPI ' ' ;no name?
- JZ HELP ;if so, go to HELP
- CPI '/' ;parameter starts with slash?
- JZ HELP ;if so, go to HELP
- RET ;return with flag set appropriately
-
- ;-----------------------------------------------------------------------------
-
- ; CHKVER
-
- ; This subroutine checks for a valid version number (one that supports user
- ; numbers). If it is not valid, then this routine displays and error message
- ; and jumps to QUIT2.
-
- IF NOT ZCPR3
-
- CHKVER: MVI C,0CH ;bdos version number function
- CALL BDOS
- CPI 20H ;make sure 2.0 or more
- RNC ;return if OK
- CALL ILPRT ;else print error message
- DB BELL,CR,LF
- DB 'Requires CP/M version 2.0 or higher.',CR,LF,0
- JMP QUIT2 ;terminate program
-
- ENDIF ;NOT ZCPR3
-
- ;-----------------------------------------------------------------------------
-
- ; INIT
-
- ; This subroutine initializes the data areas in the program so that GO
- ; command will re-run the program correctly.
-
- INIT: XRA A ;zero the accumulator
- STA CHGFLAG ;preset control flags
- STA RSTFLAG
- STA DIRCODE
-
- LXI H,AMBFIL2
- MVI B,16
- CALL FILL ;clear the fcb
-
- MVI A,'?'
- MVI B,16
- LXI H,AMBFIL
- CALL FILL
-
- LHLD 0001 ;get warmboot address (base of bios + 3)
- LXI D,27H ;offset for jump to bios write
- DAD D ;compute address for write routine
- SHLD WRITE + 1 ;load our vector with this address
-
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; SETDU
-
- ; This subroutine gets and saves the values of the currently logged in drive
- ; and user area and the drive and user specified (if any) on the command line
- ; for the files to be operated on.
-
- SETDU: ;get currently logged in user number
-
- MVI C,20H ;BDOS get/set user number function
- MVI E,0FFH ;get user flag
- CALL BDOS
- STA DEFUSR
- STA SRCUSR ;save for now as source user also
-
- ;get the currently logged in drive
-
- MVI C,19H ;bdos get drive number function
- CALL BDOS ;get drive number
- STA DEFDRV
- INR A ;change range 1-16 and
- STA SRCDRV ;..save for now as source drive also
-
-
- CALL PARSEM ;parse command tail to FCB's
- ;(only look for /O if ZCPR3)
-
- ;now log in the drive and user in file spec
-
- LDA FCB ;get drive spec from FCB
- ORA A ;see if default specified
- JZ SETDU1
- STA SRCDRV ;save source drive
- SUI 1 ;get in range 0-15
- CALL LOGDRV ;log in the drive
- XRA A ;and change FCB to show default drive
- STA FCB
-
-
- LDA FCB+13 ;get user number from S1 byte
- STA SRCUSR ;save as source user area
- CALL LOGUSR ;log in the user number
- SETDU1:
-
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; These two routines log in the drive or user number given in the A register.
- ; No registers are preserved.
-
-
- LOGDRV: MOV E,A
- MVI C,0EH
- CALL BDOS
- RET
-
- LOGUSR: MOV E,A
- MVI C,20H
- CALL BDOS
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; GETOPT
-
- ; Process option specified on the command line. If there is an error, the
- ; routine jumps to HELP which in turn jumps to QUIT. If a named directory
- ; is specified for the destination on the command line, then its user number
- ; is obtained from address TFCB+13. The drive is checked to make sure that
- ; the destination is on the same drive.
-
- GETOPT:
-
-
- ;check for destination specified using DU/named directory
-
- LDA TFCB ;check for drive number
- ORA A ;if zero, no DIR: or DU: given
- JZ GETOPT1
-
- ;check for correct drive spec
-
- LXI H,SRCDRV ;point to source drive value
- CMP M
- JNZ BADDRV ;if not the same, jump to bad drive message
-
- ;get the user number
-
- LDA TFCB + 13
- STA OPTION ;store user number as option
- JMP CHKNUM ;check for valid user number
-
- BADDRV: CALL ILPRT ;destination and source drives not same
- DB BELL
- DB CR,LF,LF
- DB 'Source and Destination Drives',CR,LF
- DB 'Must be the Same'
- DB CR,LF
- DB 0
- JMP QUIT
-
-
- GETOPT1:
- LXI H,TFCB ;point to parsed second parameter
- MOV A,M ;make sure it wasn't of form 'D:'
- ORA A ;drive byte should be zero
- JNZ BADOPT
- INX H ;now look at data entered
-
- MOV A,M ;get the first character
- CALL GETNUM ;try to read it as a number
- JC LETTER ;if not, must be a letter or bad
- MOV B,A ;save digit in B
- STA OPTION ;..and as interim option
- INX H ;try next character
- MOV A,M
- CPI ' ' ;if it is a blank
- JZ CHKNUM ;..go to test user number value
-
- CALL GETNUM ;see if second character is a number
- JC BADOPT ;if not, we have a bad option spec
-
- MOV C,A ;save second digit
- MOV A,B ;get first digit back
- ADD A ;double it three times to make 8x
- ADD A
- ADD A
- ADD B ;now add original in twice to make 10x
- ADD B
- ADD C ;finally, add in second digit
- STA OPTION ;..and save the final result
-
- ;check for valid user number (in range and not same
- ;as logged in user number)
-
- CHKNUM: LDA OPTION ;make sure we have the user number
- CPI 32 ;test for valid user number range
- JNC BADNUM
- LXI H,SRCUSR ;see if same as source user
- CMP M
- JZ SAMENUM ;if so, give message
- CALL LOGUSR
- LXI D,FCB ;See if file exists on destination
- MVI C,11H
- CALL BDOS
- CPI 0FFH
- JNZ FNDDES ;NZ=yes
- LDA SRCUSR ;no, relog user
- CALL LOGUSR
- RET
- FNDDES:
- CALL ILPRT
- DB BELL,CR,LF,"EXISTS ON DESTINATION",0
- LDA OVRWRT ;Auto overwrite?(/O)
- ORA A
- JZ NFNDOV ;Z=no
- FNDOVR:
- LXI D,FCB ;Delete file on destination user
- MVI C,19
- CALL BDOS
- CALL ILPRT
- DB " - DELETED",CR,LF,0
- RET
- NFNDOV:
- CALL ILPRT
- DB " >>DELETE(Y/N)? ",0
- MVI C,1 ;Query operator as to what to do
- CALL BDOS
- CPI "Y"
- JZ FNDOVR
- CPI "y"
- JZ FNDOVR
- JMP QUIT2 ;abort if not a yes answer
-
- LETTER: ;check for valid letter option
- PUSH PSW ;save option letter
- INX H ;check whether option followed by '#'
- MOV A,M
- CPI '#'
- JNZ LETTER0 ;not "all users" switch, don't save it
- STA ALLUSR
- LETTER0:
- POP PSW ;get option character back
- LXI H,OPTLIST ;point to list of valid options
- MOV C,M ;get number of options in list
- LETTER1: ;loop through them checking
- INX H
- CMP M ;compare to list entry
- JZ GOODOPT ;if it matches, we have a good option
- DCR C ;else, count down
- JNZ LETTER1 ;..and try again
- JMP HELP ;we get here if option is not valid
-
- GOODOPT: ;we have a good option letter
- STA OPTION
- RET
-
- BADOPT: ;we have a bad option specifier
- CALL ILPRT
- DB BELL,CR,LF
- DB TAB,'**** BAD OPTION SPECIFIER ****',CR,LF,0
- JMP HELP
-
- BADNUM: ;we have an illegal user number
- CALL ILPRT
- DB BELL,CR,LF
- DB TAB,'**** ILLEGAL USER NUMBER ****',CR,LF,0
- JMP HELP
-
- SAMENUM: ;give message about already in that user area
- CALL ILPRT
- DB BELL,CR,LF
- DB 'Destination User Number is the',CR,LF
- DB 'Same as the Source User Number'
- DB CR,LF,0
- JMP QUIT
-
- ;subroutine to check for number character
- ;returns with carry set if not a number
-
- GETNUM: CPI '0' ;see if less than '0'
- RC ;if so, set carry flag as signal
- CPI '9'+1 ;see if more than '9'
- CMC ;reverse sense of carry flag
- RC ;if >9, return with carry set
- SUI '0' ;convert to number value
- RET ;carry is clear
-
- ;list of valid options
-
- OPTLIST:
- DB ENDLIST-OPTLIST ;number of options in list
- DB ' SDRWANEU' ;valid options
- ENDLIST:
-
- ;-----------------------------------------------------------------------------
-
- ; CHKRO
-
- ; This routine checks to see if the destination drive is read-only. If it
- ; is, an appropriate error message is displayed and the program aborts with
- ; a jump to QUIT. If the option is display only (option = space char), then
- ; this test is skipped.
-
-
- CHKRO: LDA OPTION ;see if display option is in effect
- CPI ' '
- RZ ;if so, skip rest of test
-
- MVI C,1DH ;get R/O vector from BDOS
- CALL BDOS
-
- ;calculate number of left-shifts needed
-
- LDA SRCDRV ;get the target drive number
- CMA ;complement it (makes 255-SRCDRV)
- ADI 17 ;makes A = 16 - SRCDRV (value 1-16)
-
- ;shift word in HL to put bit of R/O vector for
- ;specified drive into high bit position
-
- CHKRO1: DCR A ;test for done
- JZ CHKRO2 ;if so, jump
- DAD H ;shift HL to left
- JMP CHKRO1 ;and loop
-
- CHKRO2: DAD H ;move high bit into carry flag
- RNC ;if not R/O, return
- CALL ILPRT ;else print R/O error message
- DB BELL,CR,LF
- DB 'Drive is set to R/O',CR,LF,0
-
- JMP QUIT ;abort program
-
-
- ;=============================================================================
-
- ; M I S C E L L A N E O U S R O U T I N E S
-
- ;-----------------------------------------------------------------------------
-
- ; SETPTR
-
- ; This subroutine uses the value of the directory code to calculate a pointer
- ; to the FCB in the DMA buffer. This is done by multiplying the directory code
- ; by 32 and adding it to the DMA address (DMAADDR). The result is saved in
- ; DMAPTR.
-
- SETPTR:
- LDA DIRCODE ;get the directory code
- ADD A ;offset by 32 bytes per entry
- ADD A
- ADD A
- ADD A
- ADD A
- MOV E,A ;move value into DE
- MVI D,0
- LXI H,DMAADDR ;get buffer address
- DAD D ;compute offset into buffer
- SHLD DMAPTR ;save the address into the buffer
- RET
-
- ;-----------------------------------------------------------------------------
-
- ; SETCHGFL
-
- ; This subroutine sets the change-flag to show that the directory sector
- ; has been modified and needs to be written out to disk.
-
- SETCHGFL:
- PUSH PSW
- MVI A,0FFH ;set the sector change flag
- STA CHGFLAG
- POP PSW
- RET
-
- ;
- ;
- ;
- ;This section adds complete parseing of command line tail held at
- ; 80h in to the FCB's into a form compatible with ZCPR3's DU: form.
-
- CHRCNT EQU 80H
-
- PARSEM:
-
- LXI H,CHRCNT ; Point to character count
- MOV A,M ; Get character count
- INX H ; Pt to first character of command line
- CALL ADDAH ; Pt to after last char of command line
- MVI M,0 ; Store ending zero
- LXI H,CHRCNT+1 ; First char of command line
- SHLD NXTCHR
- XCHG
-
- IF ZCPR3
-
- CHKSLSH:
- CALL ADVAN ;move thru Tail until end or '/' found
- LDAX D
- ORA A
- JZ FSLH1 ;z=end, no '/'
- CPI "/"
- JNZ CHKSLSH
- INX D
- LDAX D
- CPI 'O' ;overwrite option?
- JZ FSLSH1 ;z=yes
- CPI 'o'
- JZ FSLSH1
- XRA A
- FSLSH1:
- STA OVRWRT
- RET
- ENDIF ;ZCPR3
-
- IF NOT ZCPR3
- LDA SRCDRV ; Save drive BDSO says is default
- STA TEMPDR
- CALL SCANER ; Search command line for next token
- LXI H,TEMPDR ; Save pointer to drive specification
- PUSH H
- LDA COLON ; ':' found in token?
- ORA A
- JZ NPARUSR ; Z=no
- MOV A,M ; Set drive specification
- STA FCBDN
- LDA TEMPUSR ; Save user in 'S1' byte in FCB
- STA FCBDN+13
- NPARUSR:
- LXI H,FCBDN+10H ; Pt to 2nd file name
- LDA SRCDRV
- STA TEMPDR
- CALL SCANX ; Scan for it and load it into fcb+16
- POP H ; Set up drive specs
- LDA COLON ; DU form?
- ORA A
- JZ NPRUSR1 ; Z=no
- MOV A,M
- STA FCBDM ; Yes ,save D
- LDA TEMPUSR
- STA FCBDM+13 ; And U
- NPRUSR1:
- XRA A ; Zero current record number(not really needed)
- STA FCBCR
- CALL ADVAN ; Skip over blanks in tail
- LDAX D
- CPI "/" ; O overwrite option here?
- JNZ NOOVR0
- INX D
- LDAX D
- CPI 'O'
- JZ NOOVRW ; Z=yes
- CPI 'o'
- JZ NOOVRW
- NOOVR0: XRA A
- NOOVRW:
- STA OVRWRT
- LXI D,FCB ; Copy to default FCB
- LXI H,FCBDN ; From FCBDN
- MVI B,33 ; Set up default FCB
-
- LDDIR: MOV A,M ; Move parsed FCB's to CPM's default ones
- STAX D
- INX H
- INX D
- DCR B
- JNZ LDDIR
-
- RET
-
- SCANER: LXI H,FCBDN ; Point to FCBDN
- ;
- SCANX:
- XRA A ; A=0
- MOV M,A ; Set first byte of FCBDN
- STA COLON ; Set no colon flag
- LDA DEFUSR ; Get current user
- STA TEMPUSR ; Set tempusr
- CALL ADVAN ; Skip to non-blank or end of line
- MVI B,11 ; Prep for possible space fill
- JZ SCAN4 ; Done if eol
- ;
- ;
- ; Scan token for DU: form, which means we have a user/disk specification
- ; DE points to next character in line, HL points to FCBDN.
- ;
- PUSH D ; Save pointer to first character
- CALL SDELM ; Check for delimiter and get first char
- CPI 'A' ; In letter range?
- JC SCAN1
- CPI 'P'+1 ; In letter range?
- JC SCAN1A
- ;
- SCAN1: CPI '0' ; Check for digit range
- JC SCAN2
- CPI '9'+1 ; In digit range?
- JNC SCAN2
- ;
- SCAN1A: INX D ; Pt to next char
- CALL SDELM ; Check for delimiter, else digit
- JMP SCAN1
- ;
- SCAN2: POP D ; Restore ptr to first char
- CPI ':' ; Was delimiter a colon?
- JNZ SCAN3 ; Done if no colon
- STA COLON ; Set colon found
- ;
- ;
- ; Scan for and extract user/disk info - on entry, HL point to FCBDN, DE
- ; points to first character and A-register contains the first character.
- ;
- LDAX D ; Get first character
- CPI 'A' ; Convert possible drive spec to number
- JC SUD1 ; If less than 'a', must be digit
- ;
- ;
- ; Set disk number (A=1)
- ;
- SUI 'A'-1
- ;
- ; IF DRVMAX
- ; PUSH B ; Save 'BC'
- ; PUSH PSW ; Save drive request
- ; LDA DRVMAX ; Get maximum legal drive
- ; ADI 2 ; Bump it two for the compare
- ; MOV B,A ; Save maximum drive in 'B'
- ; POP PSW ; Restore drive request
- ; CMP B ; See if illegal drive
- ; POP B ; Restore bc
- ; ENDIF ; DRVMAX
- ;;
- ; IF NOT DRVMAX
- ; CPI MAXDISK+1 ; Within range?
- ; ENDIF ; NOT DRVMAX
- ;
- JC ERROR ; Invalid disk number
- STA TEMPDR ; Set temporary drive number
- MOV M,A ; Set fcbdn
- INX D ; Pt to next char
- LDAX D ; See if it is a colon (:)
- CPI ':'
- JZ SUD2 ; Done if no user number (it is a colon)
- ;
- ;
- ; Set user number
- ;
- SUD1: PUSH H ; Save pointer to FCBDN
- XCHG ; Hl pts to first digit
- CALL NUM0A ; Get number
- XCHG ; De pts to terminating colon
- ;
- ; IF USRMAX
- ; LXI H,USRMAX
- ; CMP M
- ; ENDIF ; USRMAX
- ;
- ; IF NOT USRMAX
- ; CPI MAXUSR+1 ; Within limit?
- ; ENDIF ; NOT USRMAX
- ;
- POP H ; Get pointer to FCBDN
- JC ERROR
- ;
- STA TEMPUSR ; Save user number
- ;
- SUD2: INX D ; Point to character after colon
- ;
- ;
- ; Extract filename from possible FILENAME.TYP - DE points to next char-
- ; acter to process, HL points tao FCBDN.
- ;
- SCAN3: XRA A ; A=0
- STA QMCNT ; Init question mark count
- MVI B,8 ; Max of 8 chars in file name
- CALL SCANF ; Fill FCB file name
- ;
- ;
- ; Extract file type from possible FILENAME.TYP
- ;
- MVI B,3 ; Prepare to extract type
- LDAX D ; Get last char which stopped scan
- CPI '.' ; Have a type if de) delimiter is a '.'
- JNZ SCAN4 ; Fill file type bytes with <sp>
- INX D ; Pt to char in command line after '.'
- CALL SCANF ; Fill fcb file type
- JMP SCAN5 ; Skip to next processing
- ;
- SCAN4: CALL SCANF4 ; Space fill
- ;
- ;
- ; Fill in EX, S1, S2, and RC with zeroes
- ;
- SCAN5: MVI B,4 ; 4 bytes
- XRA A ; A=0
- CALL SCANF5 ; Fill with zeroes
- ;
- ;
- ; Scan complete -- DE points to delimiter byte after token
- ;
- XCHG
- SHLD NXTCHR
- XCHG
- ;
- ;
- ; Set zero flag to indicate presence of '?' in FILENAME.TYPE
- ;
- QMCNT EQU $+1 ; Pointer for in-the-code modification
- MVI A,0 ; Number of question marks
- ORA A ; Set zero flag to indicate any '?'
- RET
- ;.....
- ;
- ;
- ; Scan token pointed to by DE for a max of B bytes; place it into file
- ; name field pointed to by HL; expand and interpret wild cards of '*'
- ; '?'; on exit, DE points to terminating delimiter.
- ;
- SCANF: CALL SDELM ; Done if delimiter encountered
- JZ SCANF4
- INX H ; Point to next byte in FCBDN
- CPI '*' ; Is (DE) a wild card?
- JNZ SCANF1 ; Continue if not
- MVI M,'?' ; Place '?' in FCB
- CALL SCQ ; Scanner count question marks
- JMP SCANF2
- ;
- SCANF1: MOV M,A ; Store filename char in fcb
- INX D ; Pt to next char in command line
- CPI '?' ; Check for question mark (wild)
- CZ SCQ ; Scanner count question marks
- ;
- SCANF2: DCR B
- JNZ SCANF
- ; DJNZ SCANF ; Decrement char count until 8 elapsed
- ;
- SCANF3: CALL SDELM ; 8 chars or more - skip until delimiter
- RZ ; Zero flag set if delimiter found
- INX D ; Pt to next char in command line
- JMP SCANF3
- ;
- ;
- ; Fill memory pointed to by HL with spaces for B bytes
- ;
- SCANF4: MVI A,' ' ; Fill with spaces
- ;
- SCANF5: INX H ; Point to next byte in FCB
- MOV M,A ; Fill with byte in A-reg.
- DCR B
- JNZ SCANF5
- ; DJNZ SCANF5
- RET
- ;.....
- ;
- ;
- ; 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
- ;.....
- ;
- ;
-
- ;
- ;
- ; Check to see if DE points to delimiter, if so return with zero flag
- ; set.
- ;
- SDELM: LDAX D
- ORA A ; 0=delimiter
- RZ
- CPI ' '+1 ; Delim if <= <SP>
- 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
- CPI '>' ; '>'=delimiter
- RET
- ;
- ZERO: XRA A ; Set zero flag
- RET
- ;.....
- ;
- ;
- ; Advance input pointer to first non-blank and fall through to SBLANK
- ;
- ADVAN: PUSH H
- LHLD NXTCHR
- XCHG
- POP H
- ;LDED NXTCHR ; Point to next character
- ;
- ;
- ; Skip string pointed to by DE (string ends in 0 OR CMDSEP) until end of
- ; string or non-delimited encounterd (beginning of token).
- ;
- SBLANK:
- LDAX D ; Get character
- ORA A ; Zero?
- RZ
- CALL SDELM ; Skip over delimiter
- RNZ
- INX D ; Advance to next char
- JMP SBLANK
- ;.....
- ;
- ;
- ; Add A ro HL (HL=HL+A)
- ;
- ADDAH: ADD L
- MOV L,A
- RNC
- INR H
- RET
-
-
- NUM0A: LXI B,1100H ; C=accumulated value, b=char count
- ; ; (c=0, b=11)
- NUM1: MOV A,M ; Get character
- CPI ' ' ; Done if <SP>
- JZ NUM2
- CPI ':' ; Done if colon
- JZ NUM2
- INX H ; Pt to next char
- SUI '0' ; Convert to binary
- CPI 10 ; Error if >= 10
- JNC NUMERR
- MOV D,A ; Digit in d
- MOV A,C ; New value = old value * 10
- RLC ; *2
- JC NUMERR
- RLC ; *4
- JC NUMERR
- RLC ; *8
- JC NUMERR
- ADD C ; *9
- JC NUMERR
- ADD C ; *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
-
- ; DJNZ NUM1 ; Count down
- ;
- ;
- ; Return from number
- ;
- NUM2: MOV A,C ; Get accumulated value
- RET
- ;.....
- ;
- ;
- ; Number error routine for space conservation
- ;
- NUMERR: JMP BADNUM ; Use error routine
- ERROR: JMP BADNUM
-
-
- FCBDN: DB 0 ; Disk name
- FCBFN: DS 8 ; File name
- FCBFT: DS 3 ; File type
- DS 1 ; Extent number
- DS 2 ; S1 and S2
- DS 1 ; Record count
- FCBDM: DB 0
- DS 15 ; Disk group map
- FCBCR: DS 1 ; Current record number
- TEMPDR DS 2
- NXTCHR DS 2
- TEMPUSR DS 1
- CURUSR DS 1
- COLON DS 2
- ENDIF ;NOT ZCPR3
-
- OVRWRT DS 1
-
- ;=============================================================================
-
- ; D A T A A R E A
-
- ;-----------------------------------------------------------------------------
-
- OLDSTK: ;place to keep old stack pointer
- DS 2
-
- BLNKCNT: ;count of blank characters in file name
- DS 1
-
- CHGFLAG: ;flag for change requiring write
- DS 1
-
- RSTFLAG: ;flag for need to reset disk system
- DS 1
-
- AMBFIL: ;working fcb
- DS 16
-
- AMBFIL2: ;space for rest of FCB
- DS 19
-
- OPTION: ;storage for new user number or option
- DS 1
-
- ALLUSR: ;storage for "all users" switch
- DS 1
-
- DIRCODE: ;storage for directory code (0-3)
- DS 1
-
- DMAPTR: ;address of FCB in DMA buffer
- DS 2
-
- DEFDRV: ;current default drive
- DS 1
-
- SRCDRV: ;source drive
- DS 1
-
- DEFUSR: ;current default user number
- DS 1
-
- SRCUSR: ;source user area from file spec
- DS 1
-
- DS 60 ;room for local stack
- NEWSTK:
-
- END