home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ENTERPRS
/
CPM
/
UTILS
/
F
/
MAKE27.ARK
/
MAKE27.ASM
next >
Wrap
Assembly Source File
|
1990-04-13
|
49KB
|
1,850 lines
; 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