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
/
BDOS
/
NOVADOSI.LBR
/
NVDS-2.ZZ0
/
NVDS-2.Z80
Wrap
Text File
|
2000-06-30
|
21KB
|
804 lines
;******************************************************************************
;* *
;* DISK FUNCTIONS *
;* *
;******************************************************************************
;
; Return version number
;
cmnd12: ld a,22h ; Set version number
jr cmd25a ; and exit
;
; Reset disk system
;
cmnd13:
if resdsk and not resflag
; detect change between single and double sided disks if this function is
; supported.--b.h.
ld a,(flags) ; Check full system reset flag
bit 5,a
jr z,cmnd13a ; If not set, we can't do setdisk
call setdsk
endif
cmnd13a:ld hl,0 ; Load zero
ld (login),hl ; All drives loged out
if runlog
ld (dskro),hl ; All drives read/write
endif
ld hl,ramlow+80h ; Set up DMA address
ld (dma),hl ; And save it
call stdma ; Do P2bios call
xor a ; Set default drive = 'a'
ld (defdrv),a ; Save it
call seldk ; Select drive 'a'
ld a,(subflg) ; Get submit flag
jr cmd25a ; Exit
;
; Search for file
;
cmnd17:
call seldrv ; Select drive from FCB
ld a,(ix+0) ; Get drive number from FCB
sub '?' ; Test if '?'
jr z,cmd17b ; If so all entries match
ld a,(ix+14) ; Get system byte
cp '?' ; Test if '?'
jr z,cmd17a ; Yes, jump
ld (ix+14),0 ; Load system byte with zero
cmd17a: ld a,15 ; Test first 15 items in FCB
cmd17b: call search ; Do search
cmd17c: ld hl,(dirbuf) ; Copy directory buffer
ld de,(dma) ; To DMA address
ld bc,128 ; Directory=128 bytes
ldir
ret ; Exit
;
; Search for next occurence file
;
cmnd18: ld ix,(dcopy) ; Get last FCB used by search
call seldrv ; Selext drive from FCB
call searcn ; Search next file match
jr cmd17c ; And copy directory to DMA address
;
; Delete file
;
cmnd19:
call seldrv ; Select drive from FCB
call delete ; Delete file
cmd19a: ld a,(searex) ; Get exit byte 00=file found,0ffh not
jr cmd25a ; And exit
;
; Rename file
;
cmnd23:
call seldrv ; Select drive from FCB
call renam ; Rename file
jr cmd19a ; And exit
;
; Return permanent medium vector
;
if hifuncs
permdsk:
ld hl,(pmedia)
jr cmd24a
endif
;
; Return login vector
;
cmnd24: ld hl,(login) ; Get login vector
cmd24a: ld (pexit),hl ; Save it
ret ; And exit
;
; Return current drive
;
cmnd25: ld a,(defdrv) ; Get current drive
cmd25a: jp exit ; And exit
;
; Return alv vector
;
cmnd27: ld hl,(alv) ; Get allocation vector
jr cmd24a ; And exit
;
; Return disk r/o vector
;
cmnd29: ld hl,(dskro) ; Get disk r/o vector
jr cmd24a ; And exit
;
; Change status
;
cmnd30: call seldrv ; Select drive from FCB
call cstat ; Change status
jr cmd19a ; And exit
;
; Return drive table
;
cmnd31: ld hl,(ixp) ; Get drive table
jr cmd24a ; And exit
if hifuncs
;
; Return DMA address
;
getdma: ld hl,(dma)
jr cmd24a
;
; Return a ZRDOS compatible version number
;
zrdos: ld hl,zrvers
jr cmd24a
endif
;
; Set/get user code
;
cmnd32: inc a ; Test if 0ffh
ld a,(user) ; Get old user code
jr z,cmd25a ; If 0ffh then exit
ld a,e ; Get new user code
and 01fh ; Mask it
ld (user),a ; Save it
ret ; And exit
;
; Compute file size command
;
cmnd35: call seldrv ; Select drive from FCB
call filsz ; Compute file size
jr cmd19a ; And exit
;
; Set random record count
;
cmnd36: ld hl,32 ; Set pointer to next record
call calrrc ; Calculate random record count
ldrrc: ld (ix+33),d ; And save random record count
ld (ix+34),c
ld (ix+35),b
ret ; And exit
;
; Reset multiple login drive
;
cmnd37:
cpl ; Complement it
ld e,a
ld a,d ; Get mask MSB
cpl ; Complement it
ld d,a
ld hl,(login) ; Get login vector
ld a,e ; Mask login vector
and l ; LSB
ld l,a
ld a,d ; Mask login vector
and h ; MSB
ld h,a
ld (login),hl ; Save login vector
if runlog ; If resetting unlogged-in disks
ex de,hl ; Use login vector as mask
endif ; Otherwise reset only those in mask
ld hl,(dskro) ; Get drive r/o vector
ld a,e ; Mask drive r/o vector
and l ; LSB
ld l,a
ld a,d ; Mask drive r/o vector
and h ; LSB
ld h,a
ld (dskro),hl ; Save drive r/o vector
;
dbl:
; Code removed by L.H. Resdsk causes problems on a fast boot system and
; clrdsk trashes the login vector which the above routine so carefully sets.
;
; exx
; if resdsk
; call setdsk
; endif
; call initdr
; exx
ret
;
;********************************
;* error routines *
;* *
;********************************
;
;
; Select error
;
selerr: ld de,msel ; Load select error message
ld b,2
jr derror ; And diplay error
;
; File read only error
;
filro: ld de,mfilro ; Load file r/o message
ld a,0ffh ; Set file r/o message flag
ld b,4
jr error ; And display error
;
; Read error message--b.h.
;
rderr: ld de,mrderr
ld b,1
jr derror
;
; Write error message--b.h.
wrterr: ld de,mwrter
ld b,5
jr derror
;
; Drive read only error
;
rdonly: ld de,mro ; Load drive r/o message
derror: xor a ; Set no file r/o message
;
;
; Display error message
;
; P2dos error on d: error message
; function = nn [file = filename.typ]
;
error: ld c,a ; Save file r/o message flag
push bc
push de ; Save error message pointer
ld a,(defdrv) ; Get current drive
ld e,a ; Save drive in E in case of trap
add a,'A' ; Make ascii
ld (mdrive),a ; Save it
if hifuncs
ld a,(trapflag) ; If wb trap, then no messages
or a
ld a,b ; Get ZRDOS error number in A
jp nz,error5
endif
call crout ; Diplay cr/lf
ld de,mberr ; Load message "P2dos error on d:"
call mess ; Display message
pop de ; Get error message pointer
call mess ; Display message
call crout ; Display cr/lf
ld de,mbfunc ; Load message "function ="
call mess ; Display message
ld a,(funct) ; Get function number
push af ; Save it
ld bc,100 ; Display number / 100
call num
ld c,10 ; Display number / 10
call num
ld bc,101h ; Always display number / 1
call num
pop af ; Get function number
pop bc ; Get file r/o flag
cp 15 ; Test if FCB used in command
jr c,error3
cp 24
jr c,error1
cp 30
jr z,error1
cp 33
jr c,error3
cp 37
jr c,error1
cp 40
jr nz,error3
error1: push ix ; Yes then display "file ="
sub 19 ; Test delete file function
jr nz,error2 ; Not then jump
or c ; Test file r/o flag
jr z,error2 ; No file r/o then jump
call caldir ; Get FCB from directory buffer
ex (sp),hl ; Save it
error2: ld de,mfile ; Get message " file ="
call mess ; Display message
pop hl ; Get pointer FCB
ld b,8 ; Display fisrt 8 characters
call filenm
ld a,'.' ; Load '.'
push hl ; Save FCB pointer
call wrcon ; Echo it
pop hl ; Restore FCB pointer
ld b,3 ; Display last 3 characters
call filenm
error3: call gconst ; Test if character present
or a
jr z,error4 ; No then jump
call getch ; Get character
jr error3 ; And test again
error4: call getch ; Get character
; P2dos had a bug which did not allow the user to ignore a read/write error
; by hitting a key other than control-c. This is the fix.--b.h.
;
; Modified by l.h. to escape errors ONLY if the error ignore key is entered.
; This key is defined in the header file.
;
pop hl ; Restore directory entry
if erresc gt 0
push af ; Save it
ld a,(retflg) ; Get retflg
or a
jr z,error5
pop af
cp erresc
ret z
endif
trap equ $+1 ; Warm boot trap address
error5: jp ramlow ; And do warm boot
error5a:xor a
jr error5
;
; Display number
;
num: ld d,0ffh ; Load number -1
num1: inc d ; Increment number
sub c ; Divide by c
jr nc,num1 ; Not finished then loop
add a,c ; Restore last value
push af ; Save it
ld a,d ; Test if "0"
or b ; And if leading zero
jr z,num2 ; Yes, then exit
ld b,d ; Set no leading zero
ld a,d ; Get number
add a,'0' ; Make ascii
push bc ; Save registers
call wrcon ; Echo number
pop bc ; Restore registers
num2: pop af ; Restore number
ret ; And exit
;
; Display filname.typ
;
filenm: inc hl ; Increment pointer FCB
ld a,(hl) ; Get character from FCB
and 07fh ; Mask it
push hl ; Save registers
push bc
call wrcon ; Echo character
pop bc ; Restore registers
pop hl
djnz filenm ; Repeat b times
ret ; And exit
;
; Error messages
; made more meaningful-b.h.
;
; Bad sector message replaced by read/write error messages
;mbadsc: db 'Bad sector$'
;
msel: db 'Drive ?$'
;
mfilro: db 'File '
;
mro: db 'R/O$'
;
mberr: db 'Error, Disk '
mdrive: db 0
db drvsep
db ' $'
;
mbfunc: db 'Fnc: $'
;
mfile: db '; File: $'
;
mrderr: db 'Read Err$'
;
mwrter: db 'Write Err$'
;
; Select disk from FCB
;
seldrv: ld a,0ffh ; Set disk select done flag
ld (fldrv),a
ld a,(defdrv) ; Get current drive
ld (drive),a ; Save it in memory
ld e,a ; Save it in register e
ld a,(ix+0) ; Get drive from FCB
ld (fcb0),a ; Save it
cp '?' ; Test if '?'
jr z,cmnd14 ; Yes, then select drive from register e
and 01fh ; Mask drive
ld a,e ; Test if zero
jr z,seldr0 ; Select drive from register e
ld a,(ix+0) ; Get drive from FCB
dec a ; Decrement drive
seldr0: call seldk ; Select drive
ld a,(ix+0) ; Get drive from FCB
and 0e0h ; Remove drive bits
ld b,a ; Save register
ld a,(user) ; Get user number
or b ; Insert user number in FCB
ld (ix+0),a
ret ; And exit
;
; Select disk
;
cmnd14: ld a,e ; Get drive in A
;
; Select disk
;
seldk: and 0fh ; Mask drive number
ld b,a ; Save counter
ld de,(login) ; Get login vector
or a ; Test drive 'a'
jr z,seldk1 ; Yes then jump
seldk0: rr d ; Shift login vector
rr e ; Until bit 0 register e
djnz seldk0 ; Is current drive
seldk1: ld hl,defdrv ; Get pointer last drive
bit 0,e ; Test if drive logged in
jr z,seldk2 ; No, login drive
cp (hl) ; Test same drive
ret z ; Yes then exit
seldk2: ld (hl),a ; Save new current drive
push de ; Save drive logged in flag
ld c,a ; Copy drive number
call seldsk ; Do P2bios select
ld a,h ; Test if error
or l
jr z,seldk3 ; Yes, illegal drive number
ld e,(hl) ; Get LSB translation vector
inc hl ; Increment pointer
ld d,(hl) ; Get MSB translation vector
inc hl ; Increment pointer
ld (trans),de ; Save translation vector
ld (temp0),hl ; Save address temp0
ld de,06 ; Increment to next address
add hl,de
ld de,dirbuf ; Load dirbuf pointer
ld bc,8 ; Copy 8 bytes
ldir
ld hl,(ixp) ; Get drive parameter address
ld c,15 ; Copy 15 bytes
ldir
pop de ; Get drive logged in flag
bit 0,e ; Test it
ret nz ; Drive logged in so return
ld hl,(login) ; Get login vector
call sdrvb ; Set drive bit in login vector
ld (login),hl ; Save login vector
if hifuncs
ld hl,(ncheck) ; Get number of records to check
ld a,h ; If zero, then permanent medium
or l
jr nz,initflpy ; So don't set permedia table
ld hl,(pmedia) ; Get permanent medium vector
call sdrvb ; Set drive bit
ld (pmedia),hl ; Save perm. medium vector
sbc hl,de ; Check if drive just made perm
jr nz,initdr ; If bit added, then init
ld hl,(temp0)
ld a,(hl) ; Get number of files
inc hl ; If it's zero, then init the dir
or (hl)
jr z,initdr
ld a,(flags) ; Check if auto-init
bit 5,a ; Bit 5, pmedia auto-init
ret z ; If not set, then don't init drive.
endif
jr initdr ; And setup drive tables
seldk3: ld hl,(stsel) ; Load error message address
jp (hl) ; And display error
;
; Init drive
; clear alv bit buffer after drive reset
;
initflpy: ; If using resdsk, arrive here only
if resdsk and resflag ; for logging in floppy drives.
rflgmac ; Code for macro in header file
endif
initdr: ld de,(maxlen) ; Get length alv buffer-1 (bits)
ld a,3 ; Divide by 8
initd0: srl d ; To get bytes
rr e
dec a
jr nz,initd0
inc de ; Increment, so all bits are cleared
ld hl,(alv) ; Get pointer alv buffer
push hl
initd1: ld (hl),0 ; Clear 8 bits
inc hl ; Increment pointer
dec de ; Decrement counter
ld a,d ; Test if counter zero
or e
jr nz,initd1 ; Not then jump
pop hl ; Get alv pointer
ld de,(ndir0) ; Get first two bytes alv buffer
ld (hl),e ; Save LSB
inc hl ; Increment pointer
ld (hl),d ; Save MSB
ld hl,(temp0) ; Clear number of files
xor a ; On this drive
ld (hl),a ; Clear LSB
inc hl ; Increment pointer
ld (hl),a ; Clear MSB
ld (subflg),a ; Clear submit flag (reset disk command)
call setfct ; Set file count
initd2: ld a,0ffh ; Update directory checksum
call rddir ; Read FCB's from directory
call tstfct ; Test last FCB
ret z ; Yes then exit
call caldir ; Calculate entry point FCB
ld a,(hl) ; Get first byte FCB
cp 0e5h ; Test empty directory entry
jr z,initd2 ; Yes then get next FCB
cp 021h ; Test time stamp
jr z,initd2 ; Yes then get next FCB
; The next 3 lines must be removed if reset disk is to flag a $$*.* file on
; any user area rather than just the current user area. (Release E)
;
; ld a,(user) ; Get user number
; cp (hl) ; Test if user is same
; jr nz,initd3 ; No then jump
inc hl ; Point to file name
ld a,(hl) ; Get first char filename
cp '$' ; Test if '$'
jr nz,initd3 ; Not then jump
inc hl ; Check for a second '$'
sub (hl) ; to compensate for public '$' files
jr nz,initd3 ; Not there? then jump
dec a ; Load a with 0ffh
ld (subflg),a ; Save it in subflg
initd3: ld c,1 ; Set bit in alv buffer
call fillbb ; Set bits from FCB in alv buffer
call setlf ; Update last file count
jr initd2 ; And get next FCB
;
; Set drive bit in hl
;
sdrvb: ex de,hl ; Copy hl=>de
ld hl,1 ; Get mask drive "a"
ld a,(defdrv) ; Get current drive
or a ; Test if drive "a"
jr z,sdrvb1 ; Yes then done
sdrvb0: add hl,hl ; Get next mask
dec a ; Decrement drive counter
jr nz,sdrvb0 ; And test if done
sdrvb1: ld a,d ; hl=hl or de
or h
ld h,a
ld a,e
or l
ld l,a
ret ; Exit
;
; Calculate sector/track directory
;
stdir: ld hl,(filcnt) ; Get FCB counter directory
srl h ; Divide by 4
rr l ; (4 FCB's / sector)
srl h
rr l
ld (recdir),hl ; Save value (used by checksum)
ex de,hl ; Copy it to de
ld hl,0 ; Clear hl
;
; Calculate sector/track
; entry: hl,de=sector number (128 byte sector)
; result set track =hl,de / maxsec
; set sector =hl,de mod maxsec
;
calst: ld bc,(maxsec) ; Get sectors/track
ld a,17 ; Set up loop counter
calst0: or a ; Test hl>=bc
sbc hl,bc
ccf
jr c,calst1 ; Yes then jump
add hl,bc ; No then retore hl
or a ; And clear carry
calst1: rl e ; Shift result in de
rl d
dec a ; Test last bit done
jr z,calst2 ; Yes then exit
rl l ; Shift next bit in hl
rl h
jr calst0 ; Continue
calst2: push hl ; Save sector number
ld hl,(nftrk) ; Get first track
add hl,de ; Add track number
ld b,h ; Copy it to bc
ld c,l
call settrk ; P2bios call set track
pop bc ; Restore sector number
ld de,(trans) ; Get translation table address
call sectrn ; P2bios call sector translation
ld b,h ; Copy result to bc
ld c,l
jp setsec ; P2bios call set sector
;
; Get disk map block number from FCB
; exit hl=address FCB
; de=dm
; bc=offset in dm
;
getdm: ld c,(ix+32) ; Get next record
ld a,(nblock) ; Get number of blocks
ld b,a ; Save it
getdm0: srl c ; Shift next record
djnz getdm0 ; Number of blocks times
getdm1: cpl ; Complement number of blocks
add a,9 ; Add 9
ld b,a ; B=8-number of blocks
ld a,(nextnd) ; Get extent mask
and (ix+12) ; Mask with extent
rrca ; Rotate one right
getdm2: rlca ; Rotate one left
djnz getdm2 ; 8-number of blocks times
getdm3: add a,c ; Add the two values to get entry FCB
getdm4: push ix ; Get FCB address
pop hl
ld c,16 ; Add offset 16 to point to dm
add hl,bc
ld c,a ; Add entry FCB
add hl,bc
ld a,(maxlen+1) ; Test 8 bits/16 bits FCB entry
or a
jr nz,getdm5 ; 16 bits => jump
ld e,(hl) ; Get 8 bit value
ld d,0 ; Make MSB zero
ret ; And exit
getdm5: add hl,bc ; Add twice (16 bit values)
ld e,(hl) ; Get LSB
inc hl ; Increment pointer
ld d,(hl) ; Get MSB
dec hl ; Decrement pointer
ret ; And exit
;
; Calculate sector number
; entry: de=block number from FCB
;
calsec: ld hl,0 ; Clear MSB sector number
ld a,(nblock) ; Get loop counter
ld b,a ; Save it in b
calsc0: sla e ; Shift l,d,e
rl d
rl l
djnz calsc0 ; B times
calsc1: ld a,(nmask) ; Get sector mask
and (ix+32) ; And whit next record
or e ; Set up LSB sector number
ld e,a
ret ; And exit
;
; Calculate dirbuf entry point
;
caldir: ld hl,(dirbuf) ; Get start address dirbuf
ld a,(secpnt) ; Get sector pointer
add a,l ; Add l=l+a
ld l,a
ret nc ; No carry exit
inc h ; Increment h
ret ; And exit
;
; Init file count
;
setfct: ld hl,-1 ; Set up file count
ld (filcnt),hl ; Save it
ret ; And exit
;
; Test file count
;
tstfct: ld hl,(filcnt) ; Test file count=0ffffh
ld a,h ; Get MSB
and l ; And LSB
inc a ; Test if result=0ffh
ret ; And exit
;
; Set last file
;
setlf: call tstlf ; Test last file
ret c ; No then exit
inc de ; Increment last file
ld (hl),d ; Save it in temp0
dec hl
ld (hl),e
ret ; And exit
;
; Test last file
;
tstlf: ld hl,(temp0) ; Get pointer to last file
ld de,(filcnt) ; Get file counter
ld a,e ; Subtract de-(hl)
sub (hl)
inc hl
ld a,d
sbc a,(hl)
ret ; Exit
;
; Get next FCB from drive
; entry a=0 check checksum, a=0ffh update checksum
;
rddir: ld c,a ; Save checksum flag
ld hl,(filcnt) ; Get file counter
inc hl ; Increment it
ld (filcnt),hl ; And save it
ld de,(nfiles) ; Get maximum number of files
or a ; Clear carry
sbc hl,de ; Test if last file
add hl,de
jr z,rddir0 ; No jump
jr nc,setfct ; Yes set file count to 0ffffh
rddir0: ld a,l ; Get file count LSB
rrca ; *32
rrca
rrca
and 060h ; Mask it
ld (secpnt),a ; Save it for later use
ret nz ; Return if not fisrt FCB sector
push bc ; Save checksum flag
call stdir ; Calculate sector/track directory
call readdr ; Read sector directory
pop bc ; Restore checksum flag
call chkdir
ret nc
push bc
call initdr ; Relog drive
pop bc
jr rddir
;
; Update/check checksum directory
; entry c=0 check checksum, c=0ffh update checksum
;
chkdir: ld hl,(ncheck) ; Get number of checked records
ld de,(recdir) ; Get current record
or a ; Clear carry
sbc hl,de ; Test current record
ret z ; Exit if zero
ccf
ret nc ; Exit if greater then ncheck
ld hl,(dirbuf) ; Get dirbuf
ld b,128 ; Set up counter
xor a ; Clear checksum
chkdr0: add a,(hl) ; Add checksum
inc hl ; Increment pointer
djnz chkdr0 ; 128 times
ld hl,(csv) ; Get pointer checksum directory
add hl,de ; Add current record
inc c ; Test checksum flag
jr z,chkdr1 ; 0ffh=> update checksum
cp (hl) ; Test checksum
ret z ; Exit if ok
; automatic disk logging--instead of setting read/only flag when disk is
; changed, carry is returned set to calling routine if checksum error
; jp setwpd
scf ; From Mod. 3 Suprbdos
jp setfn ; Set number of files
chkdr1: ld (hl),a ; Update checksum
ret ; And exit
;
; Read sector from drive
;
;
; Readr and writer modified to give separate error messages--b.h.
readr: call read ; P2bios call read sector
ld hl,(srderr)
jr write0
;
; Write sector on drive
;
writer: call write ; P2bios call write sector
ld hl,(swrter)
write0: or a ; Test exit code
ret z ; Exit if ok
ld a,1 ; Allow a return to program if r/o
ld (retflg),a
jp (hl) ; P2dos error on d: bad sector
;
; Read directory from drive
;
readdr: call dmadir ; Set up DMA directory
call readr ; Read record
jr stdma ; Set up DMA user
;
; Write directory on drive
;
writdr: ld c,0ffh ; Update checksum directory
call chkdir
call dmadir ; Set up DMA directory
ld c,1 ; Write directory flag
call writer ; Write record
jr stdma ; Set up DMA user