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
/
BEEHIVE
/
ZCAT
/
MOVE12.LBR
/
MOVE12.ZQ0
/
MOVE12.Z80
Wrap
Text File
|
2000-06-30
|
10KB
|
405 lines
;
; program: move
; author: dennis wright
; version: 1.1
; date: 11 oct 85
;
vers equ 12
;
; version 1.2 - Changed to warm boot only if directory written. dlw
;
; version 1.1 - Fixed bug in file name compare routine. dlw
;
; version 1.0 - release
;
MONTH EQU 9
DAY EQU 8
YEAR EQU 85
;
; Based on public domain program mov2usr by R.E.D
;
DOS EQU 0005H ; Dos entry address
BUFFER EQU 80H ; Default cp/m buffer
FCB EQU 5CH ; Default cp/m fcb
FCB2 EQU 6CH
USR1 EQU FCB+13 ; Fcb1 user
USR2 EQU FCB2+13 ; Fcb2 user
GSUSER EQU 32 ; Set/get user code
CR EQU 0DH
LF EQU 0AH
;
Z3ENV SET 0E200H
;
EXT Z3VINIT,TINIT
EXT DUTDIR
EXT COUT,CRLF,BIOS
;
; environment definition
;
IF Z3ENV NE 0
;
; external zcpr3 environment descriptor
;
JP START
DB 'Z3ENV' ; This is a zcpr3 utility
DB 1 ; External environment descriptor
Z3EADR:
DW Z3ENV
START:
LD HL,(Z3EADR) ; Pt to zcpr3 environment
;
ELSE
;
; internal zcpr3 environment descriptor
;
MACLIB Z3BASE.LIB
MACLIB SYSENV.LIB
Z3EADR:
JP START
SYSENV
START:
LD HL,Z3EADR ; Pt to zcpr3 environment
ENDIF
;
; start of program -- initialize zcpr3 environment
;
CALL Z3VINIT ; Initialize the zcpr3 env
CALL TINIT ; Initialize the terminal
ld hl,0
add hl,sp
ld (oldstk),hl
ld hl,stack
ld sp,hl
LD E,0FFH ; Get current user number
LD C,GSUSER
CALL DOS
LD (CURUSR),A ; Save it
LD A,(USR1) ; Get requested source user number
LD E,A ; And log in to it.
LD C,GSUSER
CALL DOS
LD A,(FCB+1)
CP '/'
JP Z,HELP
CP ' '
JP NZ,GOTNAM
HELP: LD DE,USAGE
JP PRNRET
;
CPMRET: LD A,(FOUND1)
OR A
JP NZ,GOT1
LD DE,NOFILE
PRNRET: CALL PRNTLIN
GOT1: LD A,(CURUSR) ; Log back into original user area.
LD E,A
LD C,GSUSER
CALL DOS
ld a,(dirwrt)
or a
JP nz,0
ld hl,(oldstk)
ld sp,hl
ret
;
GOTNAM: LD HL,BUFFER
INC HL
BUFLP: INC HL
LD A,(HL)
CP 0
JP NZ,BUFLP
DEC HL
LD A,(HL)
CP ':'
LD DE,NOUSR
JP NZ,PRNRET
LD A,(USR2)
LD (USERNO),A
LD A,(FCB) ; Get fcb drive number (1st byte)
CP 0 ; Check for default drive (0)
JP Z,DEFAULT ; Jump if default else subtract 1
SBC 01 ; To convert into dos usable
; Drive number a=0,b=1,c=2
LD (DRVNO),A ; Save drive number for later
JP RDONLY
DEFAULT:LD C,19H ; Dos get drive number function
CALL DOS ; Get drive number
LD (DRVNO),A ; Save the actual drive number
;
; check drive for read only status - do this before selecting
; drive because selection will void r/o status
;
RDONLY: LD A,(FCB2)
CP 0
JP Z,DFLT
SBC 01
JP CHKDRV
;
DFLT: LD C,19H
CALL DOS
CHKDRV: LD HL,DRVNO
CP (HL)
LD DE,DIRMSG
JP NZ,PRNRET
LD A,(USR1)
LD C,A
LD A,(USR2)
CP C
LD DE,SAMUSR
JP Z,PRNRET
CP 16
LD DE,USRMSG
JP NC,PRNRET
LD C,1DH ; Dos r/o vector function
CALL DOS ; Do it
LD A,(DRVNO) ; Get the drive number back
ADD 02 ; Increment count to
; Rotate vector bit to carry
LD C,A ; Set up rotate
SHIFT: DEC C ; Check for end
JP Z,CHECK ; Check carry if finished
LD H,A ; Else get first byte
OR A ; Clear carry
RRA ; Shift it
LD H,A ; And put it back
LD A,L ; Get next byte
RRA ; Shift it
LD L,A ; Put it back
JP SHIFT ; Loop for more
;
CHECK: JP C,ROERR ; Jump if carry set
LD A,(DRVNO) ; Get drive number
LD E,A ; Set up for dos call, move Drive number to E
LD C,0EH ; Dos select disk function
CALL DOS
LD DE,AMBFIL ; Point to match any filename.typ
LD C,11H ; Dos search first function
CALL DOS ; Do it
LD (DIRCODE),A ; Save directory code
CP 0FFH ; See if end of entries
JP Z,CPMRET ; Return if end
;
; main program function loop
;
LOOP: LD A,(DIRCODE) ; Get the directory code
ADD A,A ; Offset by 32 bytes per entry
ADD A,A
ADD A,A
ADD A,A
ADD A,A
LD E,A ; Prepare for offset computation
LD D,00 ; Clear high byte
LD HL,BUFFER ; Get buffer address
ADD HL,DE ; Compute offset into buffer
LD (DBOFF),HL ; Save the address into the buffer
EX DE,HL ; Swap
LD A,(DE) ; Get the dr byte for this entry
CP 0E5H ; See if erased
JP Z,INDIRCD ; Jump to do next entry if erased
LD HL,USERNO ; Point to user number
CP (HL) ; See if old and new user number are same
JP Z,INDIRCD ; Jump to do next entry
LD HL,USR1 ; See if directory entry user is same as
CP (HL) ; Specified user.
JP NZ,INDIRCD
;
COMPARE:LD HL,FCB+1 ; Point to first character
LD C,0BH ; Load count for compare
EX DE,HL ; Swap
INC HL ; Incr past directory user number
CP1: LD A,(DE) ; Get fcb file character
CP '?' ; See if anything matches
JP Z,MATCH ; Jump past compare if '?'
SUB (HL) ; Compare thru subtraction
AND 7FH ; Clear high (flag) bit
JP NZ,INDIRCD ; Quit if no match
MATCH: INC DE ; Point to next characters
INC HL
DEC C ; Decrease count of characters
JP NZ,CP1 ; Loop until zero
LD A,(USERNO) ; Get the new user number
LD HL,(DBOFF) ; Get buffer offset
LD (HL),A ; Put new user number in directory
LD A,(WRTOK) ; Get write flag
INC A ; Increase flag
LD (WRTOK),A ; Save updated flag
LD HL,(DBOFF) ; Address of file fcb
LD DE,12 ; Offset to extent byte
ADD HL,DE
LD A,(HL)
OR A ; First extent?
JP NZ,INDIRCD ; Only want to print message once per file
LD A,-1
LD (FOUND1),A
CALL CRLF
CALL FILPRN ; Print the file name
LD DE,MV2MSG
CALL PRNTLIN
LD A,(DRVNO)
ADD 'A'
CALL COUT
LD A,(USERNO) ; Get user number
CALL PRTUSR
LD A,':'
CALL COUT
LD A,(USERNO)
LD C,A
LD A,(DRVNO)
LD B,A
CALL DUTDIR
JP Z,INDIRCD
LD C,8
DIRLP: LD A,(HL)
CP ' '
JP Z,INDIRCD
CALL COUT
INC HL
DEC C
JP NZ,DIRLP
INDIRCD:LD A,(DIRCODE) ; Get the directory code
INC A ; Increase it one
LD (DIRCODE),A ; Save new key into buffer
CP 04 ; Only four entries in buffer
JP Z,WRTBUF ; Update buffer if last entry
JP LOOP ; Else look at remainder of buffer
;
WRTBUF: LD A,(WRTOK) ; Get write flag - anything greater
; Than zero means a change was made
CP 0 ; Check for change made
JP Z,SRNXT ; Jump if no changes made
CALL WRTDE ; Else write the buffer back to directory
XOR A ; Zero accum to clear writr flag
LD (WRTOK),A ; Save cleared flag
dec a ; Set directory written flag
ld (dirwrt),a
SRNXT: LD DE,AMBFIL ; Point to any match fcb
LD C,12H ; Dos search next function
CALL DOS ; Do it
CP 0FFH ; See if end of entries
JP Z,CPMRET ; And return if no more files
CP 0 ; Loop until buffer is updated by dos
JP NZ,SRNXT ; Jump until dircode is zero
LD (DIRCODE),A ; Save the 0 in dircode
JP LOOP ; And loop again
RET ; End of main program
;
; error messages
;
;
ROERR: LD DE,ROMSG ; Print disk r/o
JP PRNRET ; And end
;
SECERR: LD DE,BADSEC ; Print bios sector error
JP PRNRET ; And end
;
;
PRNTLIN:LD C,09H ; Dos print string function
JP DOS
;
;
FILPRN: ; Print filename
LD A,(DRVNO)
ADD 'A'
CALL COUT ; Print drive letter
LD E,0FFH
LD C,32
CALL DOS
CALL PRTUSR ; Print user number
LD A,':' ; Followed by ':'
CALL COUT
LD HL,(DBOFF) ; Address of file fcb
LD C,0CH ; Filename.typ char count
INC HL ; Bypass first byte
FP1: PUSH BC ; Save count
LD A,4 ; Check for period position
CP C
JP Z,PERIOD ; Print period if time
LD A,(HL) ; Ignore blanks
CALL COUT ; Else print character
FP2: POP BC ; Get count
DEC C ; Dcr count
INC HL ; Point to next char
JP NZ,FP1 ; Loop until zero
RET
;
PERIOD: LD A,'.' ; Print the period
CALL COUT
POP BC ; Get count
DEC C ; Dcr count
JP FP1
;
WRTDE: LD DE,BUFFER ; Set dma to buffer
LD C,1AH ; Dos setdma function
CALL DOS
LD C,1H ; Set bios write to directory
; Write vice 0=write to allocated
; 2=write to unallocated
LD A,14 ; Bios write
CALL BIOS
OR A ; Check for error
JP NZ,SECERR
LD DE,BUFFER ; Reset buffer address to buffer
LD C,1AH ; Dos setdma function
JP DOS
;
PRTUSR: CP 09 ; See one or two digit user number
JP NC,DOUBLE ; Jump if two digits
SINGLE: ADD 30H ; Else convert to ascii
CALL COUT ; And print it
RET
;
DOUBLE: ADD 26H ; Subtract 9 to get first digit
; And add 30h to make ascii.
; Or just add 26h to do both...
PUSH AF ; Save this digit and print '1'
LD A,'1' ; Load the character
CALL COUT ; And print it
POP AF ; Get the remainder digit
CALL COUT ; And print it
RET
;
DIRMSG: DB ' Can Only Move between User Areas on Same Drive.$'
SAMUSR: DB ' Specified User number is same as current User number.$'
BADSEC: DB ' Bad Sector Write Error','$'
ROMSG: DB ' Drive is set to R/O','$'
USRMSG: DB ' User number must be 0-15','$'
NOUSR: DB ' No User number or dir: specified','$'
MV2MSG: DB ' - Directory entry moved to $'
USAGE: DB 'MOVE, Version ',VERS/10+'0','.',VERS MOD 10+'0',CR,LF
DB 'MOVE - Move file(s) to new user area.',CR,LF
DB 'Syntax:',CR,LF
DB ' MOVE du:afn user:',CR,LF
DB 'or MOVE du:afn dir:',CR,LF,LF
DB 'NOTE: Filename and type may contain wildcards.',CR,LF
DB ' User area must be on same drive as du:.',CR,LF
DB ' Valid User numbers from 0 to 15 or',CR,LF
DB ' Directory names may be used.',CR,LF,'$'
;
NOFILE: DB ' No File','$'
FOUND1: DB 0
CURUSR: DB 0 ; Save area for current user number
WRTOK: DB 0 ; Flag for change requiring write
; Set if change to directory made
AMBFIL: ; Fcb for match anything file
DB '????????????????',0,0,0
DB 0,0,0,0,0,0,0,0,0,0,0,0,0
USERNO: DB 0 ; Storage for new user number
; Obtained from tfcb
DIRCODE:DB 0 ; Storage for directory code
; Provided by dos in accum
DBOFF: DW 0 ; Address for current fcb
; In the buffer starting at 80h
; Created by (32 * dircode + buffer
; Address) 32 bytes per dir entry
DRVNO: DB 0 ; Storage for selected drive number
; Provided by fcb dr byte(1st byte)
; And confirmed by dos if needed
dirwrt: db 0
oldstk: dw 0
ds 32
stack: ds 2
;
END