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
/
PACKET
/
RLI120.ARK
/
FILEIO.MAC
< prev
next >
Wrap
Text File
|
1986-08-12
|
14KB
|
752 lines
; FILEIO.MAC - 1/4/86 - Buffered file I/O.
; Two files may be open at once: one for read, one for write.
.z80
maclib TNC.LIB
entry @openn,@openr,@openw,@opena,@closew,rcv
entry inibak,getbuf,copfil,kilfil,renfil,hidfil
entry bkm1,bkm2,bkm3,bkm4,bkm5,bkm6,bkm7,bkm8
entry tobuf,fmbuf,@ntobuf,@ctobuf,rdcmd,rdstr,rdmstr
entry setb7,rfcb,wfcb,ioini,ckdrv,ckro,defdrv,maxdrv
external @mcmd,@cmpcmd,$memry,@outch,numb,bindec
external eofs,leofs,addcr0,opt2,cmd,cmdlen
external getdat,erexst,ercant,erdone,ername,erwhat,erfind
external div8,memtop,ckname,fcb2,fcb3,@prtx,@fill
asciictl
bdosdef
tncdefs
dseg
ro: ds 1 ; Read only drives.
online: ds 1 ; Drives on line (logged in).
maxdrv: ds 1 ; Highest drive online.
defdrv: ds 1 ; Default drive.
rb: ds 2 ; Address of read buffer.
rbptr: ds 2 ; Read buffer pointer.
rbcnt: ds 2 ; # bytes remaining in read buffer.
rbeof: ds 1 ; True if eof read.
rbsec: ds 1 ; # sectors read.
rfcb: ds fcbsize ; Read file control block.
wb: ds 2 ; Address of write buffer.
wbptr: ds 2 ; Write buffer pointer.
wbcnt: ds 2 ; # Bytes left in write buffer.
wbsec: ds 1 ; # sectors in write buffer.
wfcb: ds fcbsize ; Write file control block.
wfcbrc equ wfcb+15 ; FCB: record count.
wfcbcr equ wfcb+32 ; FCB: current record.
wfcbrn equ wfcb+33 ; FCB: random record number.
copst: ds 1
copbs: ds 2
copbp: ds 2
copbc: ds 2
copin: ds 2
tfcb: ds 2
curdrv: ds 1
cseg
dosrc: ld (tfcb),hl
dodosa setdma,defdma
ld hl,(tfcb)
ld a,(hl)
ld (curdrv),a
ld (hl),0
ld bc,12
add hl,bc
ld (hl),0
or a ; Drive specified?
jr z,dosrca ; No
dec a
ld e,a
dodosa seldsk ; Make this drive the default
dosrca: ld de,(tfcb)
dodosa search
push psw
ld hl,(tfcb)
ld a,(curdrv)
ld (hl),a
ld a,(defdrv)
ld e,a
dodosa seldsk ; Put back original default
pop psw
inc a
ret
; Return in hl the number of sectors of free memory.
getbuf: ld de,($memry) ; Start of free mem
ld hl,(memtop) ; End of free mem
or a ; Clear carry
sbc hl,de ; Bytes available
ld e,128
call div8
ld h,0
ret
; Read a bunch of sectors into buffer
copr: movw copbp,$memry ; Point to start of buffer space
movw copbc,copbs ; Init avail buffer count
lxim copin,0 ; Init count of records read
copra: ld de,(copbp)
dodosa setdma ; Point IO to buffer
dodosa read,fcb2 ; Read record
ld (copst),a ; Save read status
or a ; Done?
ret nz ; Yes
inxm copin ; Count records in buffer
ld hl,(copbp)
ld de,128
add hl,de
ld (copbp),hl ; Point to next buffer
dcxm copbc ; One less available
ld a,l
or h ; Any left
jr nz,copra ; Yes, read next
ret
; Write the bunch of sectors from buffer.
copw: movw copbp,$memry
ld hl,(copin)
copwa: ld a,l
or h ; Done?
ret z ; Yes
ld de,(copbp)
dodosa setdma
dodosa write,fcb3 ; Write record
ld hl,(copbp)
ld de,128
add hl,de
ld (copbp),hl
dcxm copin
jr copwa
; The "copy file" command.
copfil: ckname fcb2 ; Input name legal?
jp z,ername ; No
ld a,(fcb2)
call ckdrv ; Input drive on line?
jp nc,erfind ; No
ckname fcb3 ; Output name legal?
jp z,ername ; No
ld a,(fcb3)
call ckdrv ; Output drive on line?
jp nc,erfind ; No
ld a,(fcb3)
call ckro ; Can we write on it?
jp c,ercant ; No
ld hl,fcb3
call dosrc ; Output file already exist?
jp nz,erexst ; Yes
dodosa open,fcb2 ; Open the input file
inc a
jp z,erfind ; No input file
dodosa make,fcb3 ; Create the output file
call copyf ; Do the copy
jp erdone
; Copy file from fcb2 to fcb3.
copyf: call getbuf
ld (copbs),hl ; Sectors of buffer available
copfa: call copr ; Read a bunch
call copw ; Write em
ld a,(copst)
or a ; Done?
jr z,copfa ; No
dodosa close,fcb3
ret
; Delete a file.
kilfil: ckname fcb2 ; Legal file name?
jp z,ername ; No
ld a,(fcb2)
call ckdrv ; Drive on line?
jp nc,erfind ; No
ld a,(fcb2)
call ckro ; Can we write on it?
jp c,ercant ; No
dodosa delete,fcb2 ; Delete the file
inc a
jp z,erfind ; Delete failed
jp erdone
; Toggle $sys attribute on file.
hidfil: ckname fcb2 ; File name legal?
jp z,ername ; No
ld a,(fcb2)
call ckdrv ; Drive on line?
jp nc,erfind ; No
ld a,(fcb2)
call ckro ; Can we write on it?
jp c,ercant ; No
ld hl,fcb2
call dosrc ; Get dir entry into buffer
jp z,erfind ; No such file
dec a
add a,a
add a,a
add a,a
add a,a
add a,a
ld hl,defdma
ld e,a
ld d,0
add hl,de ; (HL) point to dir entry
ld a,(fcb2)
ld (hl),a ; Set drive in dir entry
push hl
ld bc,10
ld a,(opt2)
cp 'N' ; Toggle new attribute?
jr nz,hidfa ; No, do $sys
ld bc,4
hidfa: add hl,bc
ld a,(hl)
xor 80h ; Toggle the bit
ld (hl),a
pop hl
ex de,hl ; (DE) point to dir entry
dodosa setatr
jp erdone
; Rename a file.
renfil: ckname fcb2 ; Old name legal?
jp z,ername ; No
ckname fcb3 ; New name legal?
jp z,ername ; No
ld a,(fcb2)
call ckdrv ; This drive on line?
jp nc,erfind ; No
ld a,(fcb2)
call ckro ; Can we write on it?
jp c,ercant ; No
zmov fcb2+16,fcb3,12
ld hl,fcb3
call dosrc ; New already exist?
jp nz,erexst ; Yes
dodosa rename,fcb2 ; Rename the sucker
inc a
jp z,ercant ; Could not rename
jp erdone
; Set attribute at (HL)
setb7: ld a,(hl)
or 80h
ld (hl),a
ret
; Initialize for backup.
; fcb2 contains file to be backed up (.DAT)
; fcb3 contains file to backup to (.BAK)
; Return zero cleared if success, set if failure.
dseg
renfcb: ds fcbsize
cseg
bkm1: ds 2
bkm2: ds 2
bkm3: ds 2
bkm4: ds 2
bkm5: ds 2
bkm6: ds 2
bkm7: ds 2
bkm8: ds 2
; Check if .DAT exists.
inibak: ld hl,fcb2
call dosrc ; Is a .DAT file?
ld hl,(bkm1)
jp z,inibe ; Tell no file
dodosa close,fcb2 ; Close file.
; Delete .BAK
prtx bkm5
dodosa delete,fcb3
ld hl,fcb3+10
call setb7 ; Set $sys attribute
; Rename or copy .DAT to .BAK
ld a,(fcb3)
ld hl,fcb2
cp m ; DAT and BAK on same device?
jr z,inibb ; Yes
; Different devices, must copy
fill fcb2+12,fcbsize-12,0
dodosa open,fcb2
fill fcb3+12,fcbsize-12,0
dodosa make,fcb3
prtx bkm7
call copyf
dodosa delete,fcb2 ; Delete .DAT
jr inibc
; Same device, can rename.
inibb: prtx bkm6
zmov renfcb,fcb2,16
zmov renfcb+16,fcb3,16
dodosa rename,renfcb
dec a
ld hl,(bkm2) ; Point to msg
jr z,inibd ; Tell error
; Make the new .DAT
inibc: prtx bkm8
fill fcb2+12,fcbsize-12,0
ld hl,fcb2+10
call setb7 ; Set $sys attribute
dodosa make,fcb2
; Open .BAK
fill fcb3+12,fcbsize-12,0
dodosa open,fcb3
inc a
ld hl,(bkm3) ; Point to msg
jr z,inibd ; Tell error
retnz ; Return zero cleared, success
inibd: call @prtx ; Tell what happened...
ld hl,(bkm4) ; and is serious
inibe: call @prtx
retz ; Return zero set, failure
; Initialize buffered file I/O.
; Allocate fixed memory space.
ioini: movw rb,$memry
ld de,secsize*bufsize
add hl,de
ld (wb),hl
add hl,de
ld ($memry),hl
; Find out what drives available.
dodosv ckdsks
ld a,l
ld (online),a ; Drives online
ld c,9
fndmax: dec c
rlca
jr nc,fndmax
ld a,c
ld (maxdrv),a
dodosv getro
ld a,l
ld (ro),a ; Read only drives
dodosv ckcur
ld (defdrv),a ; Current default drive
ret
; Check if drive in (A) is online.
; Carry set if ok, cleared if not online.
ckdrv: or a
scf ; Good status
ret z ; Default
ld hl,maxdrv
ld b,(hl)
inc b
cp b
ret nc ; No more than maxdrv drives
ld c,a
ld a,(online)
ckdrva: dec c
rrca
jr nz,ckdrva
ret
; Check if drive in (A) is R/O.
; Carry set if R/O, cleared if R/W.
ckro: or a
ret z ; Default, carry cleared=R/W
ld c,a
ld a,(ro)
ckroa: dec c
rrca
jr nz,ckroa
ret
; Check if drive exists and is R/W
; Return zero set if not.
ckwrt: ld a,(wfcb)
call ckdrv
jr nc,ckwrta
ld a,(wfcb)
call ckro
jr c,ckwrta
retnz
ckwrta: retz
; Write the buffers to file.
; Return zero set if error.
wtbuf: push bc
push de
call wtbufa
pop de
pop bc
ret
wtbufa: ld de,(wbcnt) ; Bytes unused in buffer
ld hl,secsize*bufsize
or a ; Clear carry
sbc hl,de
ld de,secsize-1
add hl,de
; Divide (hl)=(hl)/128
ld a,l
rla
ld a,h
rla
ld (wbsec),a ; Sectors used in buffer
lxim wbcnt,secsize*bufsize
movw wbptr,wb
ex de,hl
wtbufb: push de
dodosa setdma
dodosa write,wfcb
pop de
or a
jr z,wtbufc
retz ; Error
wtbufc: ld hl,secsize
add hl,de
ex de,hl
ld hl,wbsec
dec (hl)
jr nz,wtbufb
retnz
; Buffered read - fill the buffer.
; Return zero set if error.
rdbuf: push bc
push de
call rdbufa
pop de
pop bc
ret
rdbufa: cmpm rbeof,true
ret z
mvim rbsec,bufsize
movw rbptr,rb
ex de,hl
rdbufb: push de
dodosa setdma
dodosa read,rfcb
pop de
or a
jr z,rdbufc
mvim rbeof,true
dtz rbcnt
ret
rdbufc: ld bc,secsize
ld hl,(rbcnt)
add hl,bc
ld (rbcnt),hl
ld hl,secsize
add hl,de
ex de,hl
ld hl,rbsec
dec (hl)
jr nz,rdbufb
retnz
; Put character in C into buffer.
; Return zero set if error.
tobuf: push hl
dtz wbcnt
call z,wtbuf
pop hl
ret z
push hl
ld hl,(wbptr)
ld (hl),c
inc hl
ld (wbptr),hl
dcxm wbcnt
pop hl
retnz
; Get char from file buffer, return in C.
; Return zero set if error/eof.
fmbuf: push hl
dtz rbcnt
call z,rdbuf
pop hl
ret z
push hl
ld hl,(rbptr)
ld c,(hl)
inc hl
ld (rbptr),hl
dcxm rbcnt
pop hl
retnz
; (B) characters from (HL) to file buffer.
@ntobuf: ld c,(hl)
call tobuf
inc hl
dec b
jr nz,@ntobuf
ret
; Copy characters starting at (HL) to buffer until CR.
; Add LF after CR.
@ctobuf: ld c,(hl)
call tobuf
inc hl
ld a,c
cp cr
jr nz,@ctobuf
ld c,lf
call tobuf
ret
crlf: ld c,cr
call tobuf
ret z
ld c,lf
call tobuf
ret
; Collect a text file from the current console device.
rcv: call getdat
ckcmd rcv,rcve,rcve
cmpm cmd,eof ; Just a ^Z?
jr z,rcvd ; Yes
ld a,(cmdlen)
or a ; Just a CR?
jr z,rcvb ; Yes
ld b,a
ld hl,cmd
rcva: ld a,(hl)
cp eof
jr z,rcvc
ld c,a
call tobuf
jr z,rcve ; Error
inc hl
dec b
jr nz,rcva
rcvb: call crlf
jr z,rcve
jr rcv
rcvc: call crlf
jr z,rcve
rcvd: ld c,eof
call tobuf
jr z,rcve ; Error
closew
ret
rcve: dodosa close,wfcb
dodosa delete,wfcb
retz
; Open file for buffered read.
; Return zero set if error.
@openr: call openny
ret z
mvim rbeof,false
lxim rbcnt,0
retnz
; Open file. If drive not specified, look on all drives.
openny: ld a,(rfcb)
or a
jr nz,opn3
opn1: inc a
ld (rfcb),a
call opn3
ret nz
opn2: ld a,(rfcb)
ld hl,maxdrv
cp (hl)
jr nz,opn1
ret
opn3: ld a,(rfcb)
call ckdrv
jr c,opn4
retz
opn4: dodosa open,rfcb
inc a
ret
; Open file for write, if it does not exist.
; Return zero set if not ok, cleared if ok.
@openn: call ckwrt
jr z,opnwnb
ld hl,wfcb
call dosrc ; File exist?
jr nz,opnwna ; Yes
call opnwa
jr z,opnwnb
retnz
opnwna: call erexst
retz
opnwnb: call ercant
retz
; Open file for buffered write. Delete existing.
; Return zero set if error.
@openw: call ckwrt
ret z
dodosa delete,wfcb
opnwa: dodosa make,wfcb
inc a
ret z
lxim wbcnt,secsize*bufsize
movw wbptr,wb
retnz
; Open file for append. Make file if not exist.
; Return zero set if error.
@opena: call ckwrt
ret z
dodosa open,wfcb
inc a
jr nz,opna
dodosa make,wfcb
inc a
ret z
movw wbptr,wb
lxim wbcnt,secsize*bufsize
retnz
opna: dodosa getend,wfcb
dcxm wfcbrn
ld de,(wb)
dodosa setdma
dodosa rrec,wfcb
ld hl,(wb)
ld c,secsize
ld a,eof
opnb: cp (hl)
jr z,opnc
inc hl
dec c
jr nz,opnb
ld hl,(wb)
ld c,secsize
jr opnd
; Found eof, want to rewrite this record.
opnc: ld a,(wfcbrc)
dec a
ld (wfcbrc),a
opnd: ld (wbptr),hl
ld hl,secsize*(bufsize-1)
ld b,0
add hl,bc
ld (wbcnt),hl
retnz
; Close file opened for buffered write.
; Return zero set if error.
@closew: call wtbuf ; Drain the final buffer
dodosa close,wfcb ; Close the file
inc a ; Set flags
ret
; Read a line from a file into the command line buffer.
; Return zero set if error/eof.
rdcmd: ld hl,cmdlen ; Point to byte count
ld (hl),0 ; Clear it
ld b,cmdmax ; Max length of string
ld de,cmd ; Point to buffer
rdcmda: call fmbuf ; Get byte from I/O buffer
ret z ; I/O error
ld a,c
cp lf ; Was LF?
jr z,rdcmda ; Yes, ignore it
cp cr ; Was CR?
jr z,rdcmdc ; Yes, end of string
rdcmdb: cp eof ; Was end of file?
ret z ; Yes, error (no CR)
ld (de),a ; Store the byte
inc de ; Point where next byte goes
inc (hl) ; Incremement byte count
dec b ; Decrement # bytes left
jr nz,rdcmda ; Some left
rdcmdc: retnz ; Overflowed buffer, truncate string
; Read a line from a file into allocated memory.
; Add CR,0 at end. Return (HL)=start of line.
; Return zero set if I/O error.
rdstr: call rdcmd ; Read the line
ret z ; I/O error or eof
ld hl,($memry) ; Address to put string
push hl ; Save it
movcmd ,0,cmdmax ; Move string there
call addcr0 ; Put CR,0 at end of string
inc hl
ld ($memry),hl ; Next available byte
pop hl ; Return start of string
retnz ; and zero cleared
; Read multiple lines from a file into allocated memory.
; Return (HL)=start of first line.
; Return zero set if I/O error.
;
rdmstr: ld hl,($memry) ; Where to put the string
push hl ; Save it
ld (hl),0 ; Mark end of string
inc hl ; Allocate it
ld ($memry),hl ; Next available byte
rdma: dcxm $memry ; Back up over the 0
call rdstr ; Read a line into memory
jr z,rdmb ; Error
push hl ; Save string start
cmpcmd eofs,leofs
pop hl ; Restore string start
jr nz,rdma ; Not *** EOF
ld (hl),0 ; Mark end of string
inc hl ; Next byte in memory
ld ($memry),hl ; Is next available
xor a ; Set zero flag
inc a ; and clear it
rdmb: pop hl ; Return start of string
ret
end