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
/
CPM
/
UTILS
/
DIRUTL
/
MOVE22.LBR
/
MOVE22.ZZ0
/
MOVE22.Z80
Wrap
Text File
|
1989-12-03
|
16KB
|
734 lines
; Program: MOVE
; Author: Joe Wright
; Date: 28 February 1986
; Version: 2.0
vers equ 22 ; Fixed bug in handling of large
; files. Needed to set S2, not s1 wild.
; Modified move algorithm for increased
; speed. Now uses "search next" and
; does only one write per directory
; sector per file instead of possibly
; four.
; Cleaned up command line parsing code.
; Removed special handling for stand-
; alone user numbers as DUSCAN seems
; to do it right. Shortened code in
; SCANER: and fixed IFCBG: to work with
; extended environment. Shortened code
; in several other places as well.
; Added a call to FRESET just before
; deleting a file in the destination
; area to avoid problems when running
; under DRI BDOS.
; Added conditional assembly for type 4.
; December 4, 1989 Howard Goldstein
;
;vers equ 21 ; "B" version, one Bridger hint, one bug fix.
; Wildcard to both extent bytes before file
; existence test in "mainloop:", clear carry
; flag before the "sbc hl,de" a little after
; the call to "eval10".
; December 31, 1987 Bruce Morgen
; "A" version, incorporated Bridger's FRESET
; December 30, 1987 Bruce Morgen
; ZCPR33 Type 3 format with safety header, search
; for an empty user area instead of bombing out
; everything in user 31, established DSEG - with
; initialization to assure predictable re-entrance.
; Fixed wildcard FCB (had too many "?"s). Allow
; legitimate DU/DIR destination specs without
; colons, ditto standalone user numbers. Added
; intelligent help message (change name to MAKE or
; MV, help also changes). Scanning code ATTEMPTS
; to following all Z33/BGii stipulations where
; applicable....
; December 28, 1987 Bruce Morgen
;vers equ 20 ; Fixed drive selection bug. Add Query as default
; option. Report directories in DU:DIR form.
; 28 Feb 86 jww
z3env equ 0
.accept 'Program type (3 or 4) ',type
biosv equ 001h
fcb1 equ 05ch
usr1 equ fcb1+13
fcb2 equ 06ch
usr2 equ fcb2+13
tbuf equ 080h
tab equ 9
cr equ 13
lf equ 10
ext z33chk,getccp,freset
ext z3init,cout,dutdir,dnscan,duscan,dirscan,getefcb
ext pafdc,prttype,eprint,pfn1,bdos
ext caps,cin,hfilb,fillb,@fncmp
; TYPE 3 HEADER
; Code modified as suggested by Charles Irvine to function correctly with
; interrupts enabled. Program will abort with an error message when not
; loaded to the correct address (attempt to run it under CP/M or Z30).
entry:
if type eq 3
jr start0 ; Must use relative jump
nop ; Filler
else
rst 0
dw start
endif
db 'Z3ENV'
z3type: db type
z3eadr:
dw z3env ; Filled in by Z33
dw entry ; Intended load address
if type eq 3
start0:
ld hl,0 ; Point to warmboot entry
ld a,(hl) ; Save the byte there
di ; Protect against interrupts
ld (hl),0c9h ; Replace warmboot with a return opcode
rst 0 ; Call address 0, pushing RETADDR
; onto stack
retaddr:
ld (hl),a ; Restore byte at 0
dec sp ; Get stack pointer to point
dec sp ; To the value of RETADDR
pop hl ; Get it into HL and restore stack
ei ; We can allow interrupts again
ld de,retaddr ; This is where we should be
xor a ; Clear carry flag
push hl ; Save address again
sbc hl,de ; Subtract -- we should have 0 now
pop hl ; Restore value of RETADDR
jr z,start ; If addresses matched, begin real code
ld de,notz33msg-retaddr ; Offset to message
add hl,de
ex de,hl ; Switch pointer to message into DE
ld c,9
jp 0005h ; Return via BDOS print string function
notz33msg:
db 'Not Z33+$' ; Abort message if not Z33-compatible
endif
start: ld (stack),sp
ld sp,stack
ld a,'Q'
ld (option),a
ld a,32
ld (empusr),a
ld hl,fcbwild
ld (hl),0
inc hl
ld b,11
ld a,'?'
call hfilb
xor a
ld b,4
call fillb
ld c,12 ; Get dos version
call bdos
cp 30h
jp z,baddos ; Cant run under CP/M+
ld hl,(z3eadr)
LD A,H
OR L
JP Z,BADDOS ; Must have a Z3 environment
call z3init ; initialize the environment
;
; Turn off PUBLIC
;
ld de,126
add hl,de ; point to PUBLIC bytes
ld e,(hl)
inc hl
ld d,(hl)
ld (public),de ; save them
xor a
ld (hl),a
dec hl
ld (hl),a ; Turn public off
ld hl,fcb1+1
ld a,(hl)
cp ' '
jp z,help ; Invoked without command tail
cp '/'
jr nz,gotname
inc hl
ld a,(hl)
cp '/'
jp z,help ; Help is asked for
;
; Search for options
;
gotname:
ld hl,tbuf+2 ; Beginning of command tail
gotloop:
ld a,(hl) ; Get the character
inc hl ; Point to next
or a
jr z,got0 ; Use default options
cp '/'
jr nz,gotloop ; Try again
ld a,(hl) ; Get option character
cp 'O' ; Overwrite option
jr z,setopt
cp 'S' ; Skip option
jr z,setopt
cp 'Q'
jp nz,invopt ; Invalid option selected
setopt:
ld (option),a
;
; Resolve Drive/User with ZCPR3 constructs
;
got0:
ld a,(fcb2+15) ; Check for valid z33 parse
or a
jr nz,jpinvdu ; Complain immediately if we detect it
ld a,(fcb1+15)
or a
jr nz,jpinvdu
ld a,(fcb1) ; Source
dec a ; 0ffh if current drive, otherwise drvno.
call m,getdsk ; Return selected disk
ld (drvno),a ; Save drive number
ld hl,fcb2+1 ; Point second FCB name area
ld a,' '
cp (hl) ; Is it blank?
jr nz,doscan ; If not, go parse possible DU
dec hl ; Point back to drive byte
ld a,(hl)
dec a
call m,getdsk ; Via BDOS if necessary
ld b,a ; Stow in B
ld a,(usr2) ; Get CCP-parsed user code
ld c,a ; Into C
got1: ld a,(usr1)
ld (srcusr),a
cp c
jr z,jpinvdu ; Users must be different
ld a,c
ld (desusr),a
ld a,(drvno)
cp b
jr nz,jpinvdu ; Drives must be the same
ld c,14 ; Select drive
ld e,a
call bdos
jr search0
;
doscan: call scaner ; Parse du or dir
jr nz,got1 ; Use that if successful
jpinvdu:
jp invdu
;
search0:
;
; Find a scratchpad user area
;
ld hl,desusr
ld a,(empusr)
search1:
dec a
jp m,usfail
cp (hl)
jr z,search1
ld (empusr),a
call gsuser
ld de,fcbwild ; All wildcards
call searchf
jr nz,search0
;
; Confirm file existence
;
userok:
ld a,(srcusr)
call gsuser
ld de,fcb1
call searchf
jp z,nofile
ld a,(fcb1+7) ; Get "found via ZDOS public" flag
bit 7,a
jp nz,nofile ; File considered not found if so
;
; Check for CON: abort, then do per-file main loop
;
mainloop:
ld c,6 ; Direct console input
ld e,0ffh
call bdos
cp 3 ; Control C?
jp z,abort
ld de,fcb1
call searchf ; Search First function
jp z,quit ; No more found
call findir ; Point to specific entry in tbuf
ld bc,16 ; Move 16 bytes
ld de,fcbdrv
ldir
ld a,(desusr)
call gsuser
ld a,(fcb1) ; Drive number
ld (fcbdrv),a ; Replace user number from BDOS
ld a,'?' ; Wild card
ld (fcb1+12),a
ld (fcb1+14),a
ld (fcbext),a ; Make extents wild
ld (fcbs2),a
ld de,fcbdrv
call searchf
jp nz,filexists ; Bail out if file exists in destination
call eprint
db cr,lf,' Moving ',0
ld a,(srcusr)
call pdir
ld de,fcbname ; Point to name
call pfn1
call eprint
db ' to ',0
ld a,(desusr)
call pdir
ld a,(srcusr)
call gsuser
call moveit
jr mainloop
moveit:
ld c,17 ; Start with "search first"
ld de,fcbdrv
;
; At this point, de points to fcb and c contains function code
;
mvt0: call search ; Find matching entry
ret z ; Not this one, try again
ld b,0 ; Init counter
call findir ; point hl to dir entry
mvt1: ld a,(desusr)
ld (hl),a ; Replace current with destination
inc b ; Bump count of entries changed in this sector
;
; Check for additional matches in current dir sector
;
mvt2: ld a,20h
add a,l ; Point to next entry
jr z,mvt3 ; No more entries; write sector
ld l,a
ld a,(srcusr) ; Source user
cp (hl) ; Compare with user in dir entry
jr nz,mvt2
push hl ; Save regs
push de
push bc
inc hl ; Point to filename
inc de
ld b,11 ; Compare 11 bytes (file name and type)
call @fncmp
pop bc
pop de ; restore pointers
pop hl
jr z,mvt1 ; Match. Fix user number and check next
jr mvt2 ; No match. Check next entry
mvt3: call write ; Write the buffer back to disk
call sync ; Do "search nexts" to keep in sync
jr mvt0
;
; SYNC does "search next" calls to keep BDOS in sync with
; additional changes we might have made in the directory sector. On
; entry, DE contains pointer to FCB and B contains the count of
; searches necessary plus 1. On exit DE still has the FCB pointer and
; C contains 18, the function code for "search next" to be used by
; the call to SEARCH at MVT0.
;
SYNC: LD C,18 ; Search next code
syncloop:
dec b ; Count down
ret z ; Exit if no more
call bdos ; Do function
jr syncloop ; ..and loop back
;
; PDIR prints the drive, user and directory name
;
pdir: ld c,a ; Store user number in c
ld a,(drvno) ; Get drive
ld b,a ; ..and store in b
add a,'A'
call cout
ld a,c
call pafdc
ld a,':'
call cout
call dutdir ; Attempt to find directory name
jr nz,name ; Found it
call eprint
db 'Noname- ',0
ret
name:
ld b,8 ; Print 8 chars max
name1: ld a,(hl) ; Get dir name char
call cout ; Print it
cp ' ' ; Was it a space?
ret z ; Return if so
inc hl
djnz name1
ld a,' '
jp cout
;
; Return current disk in A
;
getdsk:
ld c,25
jp bdos
;
; Get/Set user function
;
gsuser:
ld c,32
ld e,a
jp bdos
;
; Search For First function
;
searchf:
ld c,17
search: call bdos
cp 0ffh
ret
;
; Point hl to the found directory entry
;
findir:
rrca
rrca
rrca
add a,tbuf
ld l,a
ld h,0
ret
;
; Bios Write function, preserve regs
;
write:
push bc
push de
call wrt1
pop de
pop bc
ret
wrt1: ld hl,(biosv)
ld l,42 ; Bios write entry
ld c,1 ; Directory write
jp (hl) ; Jump to bios, return to syncloop
;
; Convert D, U, DU, or named DIR to drive in B, user in C
scaner:
call ifcbg ; Running BGii? (Returns a=0 if so)
jr z,scanjp ; BG is always DU before DIR
call z33chk ; Running Z33 or later? (a=0 if so)
jr nz,scanjp ; If not Z33, assume dir first
push hl ; Save pointer
call getccp ; Get start of CCP
ld de,7 ; Offset to the option flag
add hl,de
ld a,(hl) ; Option flag to a
pop hl ; Restore pointer
bit 0,a ; Do we take DU prefixes at all?
jr nz,chkdir ; If so, see if DIRs are also OK
and 10b ; If not, DIR is our only hope
jp nz,dirscan ; OK, scan for DIR only
ret ; Otherwise return Z for failure
chkdir: bit 1,a ; Let's see if both DIR and DU
jp z,duscan ; If not, scan for DU only
and 100b ; Isolate du-first bit
xor 100b ; Invert (0 = du first)
scanjp: jp dnscan ; Central JP so we can use JRs
; Adapted from Jay Sage's COMIF:
;
; Condition: BG (BackGrounder)
;
; This option tests for the presence of the 'BGii' ID string that
; shows that BackGrounder ii is running. The code looks for the
; ID at an offset of IDOFF from the beginning of the CPR code. The
; value of IDOFF was determined by examination.
idoff equ 5bh
ifcbg:
push hl
call getccp ; Point to beginning of ccp
ld de,idoff ; Offset to 'BGii' ID string in BG CPR
add hl,de
ld de,idstr ; Point to reference ID string
ld b,idlen ; Length of ID string
bgchk1:
ld a,(de) ; Get reference character
sub (hl) ; Compare to actual character
jr nz,bgfals ; Set false if mismatch
inc hl ; Move to next characters
inc de
djnz bgchk1 ; Loop through all characters
bgfals:
pop hl
ret
idstr: db 'BGii'
idlen equ [$-idstr]
; Error message routines
invopt:
call eprint
db cr,lf,tab,'-- Invalid Option --',0
jp help
invdu:
call eprint
db cr,lf,'-- Invalid Drive/User Selection --',0
jp help
baddos:
call eprint
db '-- CP/M 2.2-compatible Z System required!'
db cr,lf,0
jp exit1
abort:
call eprint
db cr,lf,tab,'-- Aborted --',0
jp quit
nofile:
call eprint
db cr,lf,tab,'-- No Source File --',0
jp exit
usfail:
call eprint
db cr,lf,'-- No Empty User Area On Drive --',0
jp exit
filexists:
call eprint
db cr,lf,' ',0
ld a,(desusr)
call pdir
ld de,fcbname
call pfn1
ld a,(option)
cp 'O' ; Overwrite
jr z,overwr
cp 'S'
jr z,filex1
call eprint
db ' exists. Move anyway? (Y or N)',0
call cin ; Wait for response
call caps
cp 'Y'
jr z,overwr
;
; Move temporarily to scratchpad user area
;
filex1:
ld a,(desusr)
push af ; save it on the stack
ld a,(empusr)
ld (desusr),a ; temporarily
ld a,(srcusr)
call gsuser
call moveit
pop af
ld (desusr),a
call eprint
db ' NOT moved.',0
ld a,255
ld (wrflag),a
jr filexex
overwr:
;
; Reset drive and delete the destination file
;
ld a,(drvno)
call freset
ld de,fcbdrv
ld c,19
call bdos
call eprint
db ' Erased',0
filexex:
ld a,(srcusr)
call gsuser
jp mainloop
;
; Main and ONLY program exit
;
quit:
ld a,(wrflag)
or a
jr z,quit5
;
; Move any files in scratchpad user area back to source
;
ld a,(empusr)
call gsuser
ld c,17 ; Start with "search first"
ld de,fcb1 ; use ambiguous fcb
quit1: call search
jr z,quit5 ; No entries left
ld b,0 ; Init counter
call findir ; point hl to dir entry
quit2: ld a,(srcusr)
ld (hl),a ; Replace current with destination
inc b ; Bump count of entries changed in this sector
quit3: ld a,20h
add a,l ; Point to next entry
jr z,quit4 ; No more entries; write sector
ld l,a
ld a,(empusr) ; Scratch pad user
cp (hl) ; Compare with user in dir entry
jr z,quit2 ; Match. Fix user number and check next
jr quit3 ; No match. Check next entry
quit4: call write ; Write the buffer back to disk
call sync ; Do "search nexts" to keep in sync
jr quit1
quit5:
ld a,(drvno)
call freset
exit:
;
; Turn PUBLIC on again
;
ld hl,(z3eadr)
ld de,126
add hl,de ; Point to PUBLIC area
ld de,(public) ; Get original bytes
ld (hl),e
inc hl
ld (hl),d
exit1:
ld sp,(stack)
ret
help:
call eprint
db cr,lf,'MOVE Version '
db vers/10+'0','.',vers mod 10+'0'
db ' ',0
ld hl,entry
ld a,type
call prttype
call eprint
db cr,lf,'Syntax:',cr,lf,' ',0
call comnam
call eprint
db ' [dir1:]afn [dir2[:]] [/o]',cr,lf,lf,' ',0
call comnam
call eprint
db ' afn dir[:] Moves from current to dir:'
db cr,lf,' ',0
call comnam
call eprint
db ' dir:afn dir1[:] Moves from dir: to dir1:'
db cr,lf,' ',0
call comnam
call eprint
db ' dir:afn Moves from dir: to current.'
db cr,lf,lf,'All directories must reference the same drive.'
db cr,lf,'Options are: "Q"uery, "S"kip or "O"verwrite.'
db cr,lf,'Duplicate entries will be Queried by default.'
db cr,lf,lf,'Example: ',0
call comnam
call eprint
db ' dir:afn dir1: /o to overwrite.'
db cr,lf,0
jp exit
; Print actual COMfile name if we can,
; otherwise print "MOVE"
comnam: call getefcb
jr z,noefcb
ld b,8
comnml: inc hl
ld a,(hl)
and 7fh
cp ' '
call nz,cout
djnz comnml
ret
;
noefcb: call eprint
db 'MOVE',0
ret
;
; The following line is included so that the PRTTYPE routine will use
; EPRINT rather than causing PRINT to be linked in as well.
print:: jp eprint
;___________________________
;
dseg
wrflag:
ds 1
empusr:
ds 1
srcusr:
ds 1
drvno:
ds 1 ; Drive number
desusr:
ds 1
fcbwild:
ds 16
fcbdrv:
ds 16
fcbname equ fcbdrv+1
fcbext equ fcbdrv+12
fcbs2 equ fcbdrv+14
option:
ds 1 ; Default to Query duplicate files
public:
ds 2
ds 48 ; Stack area
stack: ds 2 ; ZCPR3's stack
end