home *** CD-ROM | disk | FTP | other *** search
- ; Library: ZSLIB
- ; Version: 3.5
- ; Module: ZFILEIO
- ; Version: 1.0
- ; Author: Gene Pizzetta
- ; Date: December 15, 1991
- ; Changes: Based on SYSLIB 3.6 SFILEIO module by Richard Conn and Al
- ; Dunsmuir. Added drive and user support. Code is heavily
- ; modified and tightened for a considerable size savings.
- ;
- ; This module is for internal use by the byte-oriented file I/O routines
- ; in the Z0FILE to Z3FILE modules. Entry points here are not appropriate
- ; for calling from user programs.
- ;
- ; FR@OPEN, FW@OPEN -- Open files for byte-oriented input and output.
- ; FR@CLOSE, FW@CLOSE -- Close files after byte-oriented input and output.
- ; F@GET -- Returns next byte from the input file.
- ; F@PUT -- Inserts a byte into the output file.
- ;
- ; The open routines obtain the current drive and user area from the DOS
- ; store them in the control table. The other routines log into the drive
- ; and user in the control table whenever disk access is needed; no further
- ; attention need be paid to the drive/user by the calling routines or by
- ; the programmer.
- ;
- ; Only the first 12 bytes of the user's file control block are significant
- ; when opening a file. The open routines use only the filename and filetype;
- ; the drive byte is ignored. Once a file is open, its original file control
- ; block is no longer referenced. Thus a single abbreviated FCB may be used
- ; and re-used to open multiple files. Both an input and output file can be
- ; opened from the default file control blocks at 5Ch and 6Ch without moving
- ; the filenames.
- ;
- ; Do not use the same buffer for both input and output.
- ;
- ; Error Diagnostics are returned to the caller via the zero flag and the A
- ; register. If the zero flag is set (Z), it always means no error occurred
- ; and the A register contains either 0 or the required returned value. If
- ; the zero flag is reset (NZ), the A register contains an error code and no
- ; other register value should be considered to be valid. The returned error
- ; codes in A are as follows:
- ;
- ; Code Meaning
- ; 1 Get or put attempted on unopened file (F@GET and F@PUT)
- ; 2 Disk full (F@PUT and FW@OPEN)
- ; 3 Input file not found (FR@OPEN)
- ; 4 End of file (F@GET) or input file empty (FR@OPEN)
- ; 5 Directory full (FW@OPEN)
- ; 6 Error in closing a file (FR@CLOSE and FW@CLOSE)
- ; 7 Attempt to open file that is already open (FR@OPEN and FW@OPEN)
- ;
- ; Error code 1 is actually returned to the program by the calling routines
- ; in the ZnFILE modules and not by the routines in this module. Error code
- ; 4 for F@GET is not really an error, but indicates that the end of the file
- ; has been reached and there is no more data. F@GET, F@PUT, and the close
- ; routines are not called by the ZnFILE routines if the file is not open
- ; (an attempt to close an unopened file does nothing, but returns no error).
- ;
- ; FR@OPEN -- Opens file for input.
- ; Entry: DE = address of FCB, HL = address of input control table,
- ; Zero flag reset (NZ) if file already opened
- ; Exit: A = 0, zero flag set (Z) if okay
- ; A = code, zero flag reset (NZ) if error
- ; 3 = file not found
- ; 4 = file empty
- ; 7 = file already open
- ; Uses: AF, HL
- ;
- ; FW@OPEN -- Open file for output.
- ; Entry: DE = address of FCB, HL = address of output control table
- ; Zero flag reset (NZ) if file already opened
- ; Exit: A = 0, zero flag set (Z) if okay
- ; A = code, zero flag reset (NZ) if error
- ; 5 = directory full
- ; 7 = file already open
- ; Uses: AF, HL
- ;
- ; FR@CLOSE -- Close file opened for input.
- ; Entry: HL = address of input control table
- ; Exit: A = 0, zero flag set (Z) if okay
- ; A = code, zero flag reset (NZ) if error
- ; 6 = close error
- ; Uses: AF, HL
- ;
- ; FW@CLOSE -- Close file opened for output.
- ; Entry: HL = address of output control table
- ; Exit: A = 0, zero flag set (Z) if okay
- ; A = code, zero flag reset (NZ) if error
- ; 2 = disk full
- ; 6 = close error
- ; Uses: AF, HL
- ;
- ; F@GET -- Get byte from input file.
- ; Entry: HL = address of input control table
- ; HL should have been pushed onto the stack
- ; Exit: A = byte, zero flag set (Z) if okay
- ; A = code, zero flag reset (NZ) if error
- ; 4 = end of file (not really an error)
- ; HL is popped from the stack
- ; Uses: AF
- ;
- ; F@PUT -- Put byte in A into output file.
- ; Entry: A = byte
- ; HL = address of output control table
- ; HL should have been pushed onto stack
- ; Exit: A = byte, zero flag set (Z) if okay
- ; A = code, zero flag reset (NZ) if error
- ; 2 = disk full
- ; HL is popped from the stack
- ; Uses: AF
- ;
- PUBLIC FR@OPEN,FR@CLOSE,F@GET
- PUBLIC FW@OPEN,FW@CLOSE,F@PUT
- ;
- EXTRN SETDMA,INITFCB,RETUD,LOGUD ; SYSLIB
- EXTRN F$OPEN,F$MOPEN,F$CLOSE,F$READ,F$WRITE
- ;
- Bdos equ 5 ; BDOS entry
- CpmDma equ 80h ; default DMA buffer
- CpmEof equ 1Ah ; CP/M end of file (^Z)
- ;
- ; FR@OPEN -- Opens file for input.
- ;
- FR@OPEN:
- ld a,7 ; error code (already open error)
- ret nz ; (if so, exit)
- push bc ; save BC, DE
- push de
- call iniopn ; prepare for open
- call F$OPEN ; open file
- ld a,3 ; error code (input file not found)
- jr nz,fexit ; (if so, exit)
- call rdblk ; read first block
- jr z,fopen1 ; (OK, so set up file table)
- ld a,4 ; error code (file empty)
- jr fexit
- ;
- ; FW@OPEN -- Open file for output.
- ;
- FW@OPEN:
- ld a,7 ; error code (file already open)
- ret nz ; (if so, exit)
- push bc ; save BC, DE
- push de
- call iniopn ; prepare for open
- call F$MOPEN ; open or create file
- ld a,5 ; error code (directory full)
- jr nz,fexit ; (if so, exit)
- ;
- fopen1: ld hl,(iotbl) ; get address of control table
- inc hl ; set character count
- inc hl
- ld (hl),128
- inc hl ; point to character pointer
- ex de,hl ; ..and move it to DE
- ld hl,36+2 ; get buffer address
- add hl,de
- ex de,hl ; ..into DE
- ld (hl),e ; save buffer start address
- inc hl
- ld (hl),d
- xor a ; file opened OK, so fall through
- ;
- fexit: pop de ; restore registers
- pop bc
- or a ; set flags
- ret
- ;
- ; FR@CLOSE -- Close file opened for input.
- ;
- FR@CLOSE:
- push bc ; save BC, DE
- push de
- call setdu
- ;
- close1: inc hl ; get FCB address
- inc hl
- inc hl
- ex de,hl ; ..in DE
- call F$CLOSE ; close file
- ld a,6 ; error code (close error)
- jr nz,fexit ; (if so, exit)
- xor a ; input/output file closed OK
- jr fexit ; restore registers and exit
- ;
- ; FW@CLOSE -- Close file opened for output.
- ;
- FW@CLOSE:
- push bc ; save BC, DE
- push de
- ld (iotbl),hl ; save output control table address
- call setdu
- ld a,(hl) ; get bytes remaining (buffer free space count)
- cp 128
- jr z,close1 ; (if buffer is empty, close)
- ld a,CpmEof ; put ^Z
- call FPutI
- closlp: ld a,(hl) ; get number of bytes remaining
- cp 128
- jr z,close1 ; (if block just written, close)
- xor a ; put zeroes to fill buffer
- call FPutI
- jr closlp ; loop while space remains
- ;
- ; FPutI - Internal call to F@PUT with stack management
- ;
- FPutI: push hl ; save HL
- ld hl,(iotbl) ; get address of output control table
- ;
- ; F@PUT -- Put byte in A into output file.
- ;
- F@PUT: push bc ; save BC, DE
- push de
- ld (byte),a ; save byte to output
- ld (iotbl),hl ; save address of output control table
- inc hl ; ->user
- inc hl ; pt to char pointer
- inc hl
- ld e,(hl) ; get char pointer
- inc hl
- ld d,(hl)
- ld a,(byte) ; get byte to output
- ld (de),a ; PUT data byte
- inc de ; pt to next output byte
- ld (hl),d ; update current Output buffer address
- dec hl
- ld (hl),e
- dec hl ; pt to buffer data count
- dec (hl) ; decrement count
- jr nz,gpexit ; (exit if space remains in buffer)
- ;
- ; Output buffer is full, so write it and reset pointers and count
- ;
- ld (hl),128 ; set char count
- inc hl ; pt to char pointer
- ex de,hl ; ..in DE
- ld hl,36+2 ; get buffer address
- add hl,de
- ex de,hl ; ..in DE
- ld (hl),e ; save buffer start address
- inc hl
- ld (hl),d
- call wrtblk ; write next block
- jr z,gpexit ; (PUT completed OK, exit)
- ld a,2 ; error code (disk full)
- gperr: or a ; reset zero flag
- jr gpxit2
- ;
- ; F@GET -- Get byte from input file.
- ;
- F@GET: push bc ; save BC, DE
- push de
- ld (iotbl),hl ; save address of input control table
- inc hl
- inc hl ; point to character pointer
- inc hl
- ld e,(hl) ; get character pointer
- inc hl
- ld d,(hl)
- ld a,d ; EOF was reached if pointer is zero
- or e
- ld a,4 ; error code (end of file)
- jr z,gperr ; (end of file, exit)
- ld a,(de) ; GET data byte
- ld (byte),a ; save byte for return
- inc de ; point to next input byte
- ld (hl),d ; update current input buffer address
- dec hl
- ld (hl),e
- dec hl ; point to buffer data count
- dec (hl) ; decrement count
- jr nz,gpexit ; exit if data remains in buffer
- ;
- ; Input buffer empty, so read next block and reset pointers and count
- ;
- ld (hl),128 ; set char count
- inc hl ; point to char pointer
- ex de,hl ; ..in DE
- ld hl,36+2 ; get buffer address
- add hl,de
- ex de,hl ; ..in DE
- ld (hl),e ; save buffer start address
- inc hl
- ld (hl),d
- call rdblk ; read next block
- jr z,gpexit ; (all okay)
- ld hl,(iotbl) ; get address of input/output control table
- inc hl
- inc hl ; point to character pointer
- inc hl
- ld (hl),0 ; zero indicates EOF reached
- inc hl
- ld (hl),0
- ;
- ; Exits for GET or PUT
- ;
- gpexit: xor a ; all is okay
- ld a,(byte) ; get data byte to return
- gpxit2: pop de ; restore registers
- pop bc
- pop hl ; HL was saved before entry
- ret
- ;
- ; Subroutines . . .
- ;
- ; rdblk -- Read block from input file into input buffer.
- ; Entry: None
- ; Exit: Zero flag set (Z) if okay, zero flag reset (NZ) if end of file
- ; Uses: AF, BC, DE, HL
- ;
- rdblk: ld de,(iotbl) ; get input control table address into DE
- ld hl,36+2+1+2 ; get buffer address into HL
- add hl,de
- call SETDMA
- ex de,hl ; control table address to HL
- call setdu ; log into file directory
- ex de,hl
- inc de ; point to input FCB
- inc de
- inc de
- call F$READ ; read in a block from file
- ld hl,CpmDma ; reset DMA address (for compatability)
- jp SETDMA ; return Z to caller if read okay
- ;
- ; wrtblk -- Write block from output buffer into output file.
- ; Entry: None
- ; Exit: Zero flag set (Z) if okay, zero flag reset (NZ) if disk full
- ; Uses: AF, BC, DE, HL
- ;
- wrtblk: ld de,(iotbl) ; get output control table address into DE
- ld hl,36+2+1+2 ; get buffer address into HL
- add hl,de
- call SETDMA
- ex de,hl ; control table address to HL
- call setdu ; log into file directory
- ex de,hl
- inc de ; get address of output FCB
- inc de
- inc de
- call F$WRITE ; write block to file
- ld hl,CpmDma ; reset DMA address (for compatability)
- jp SETDMA ; return Z to caller if write okay
- ;
- ; iniopn -- Gets file directory, moves filename, and initializes FCB for
- ; open routines.
- ; Entry: HL = address of input control table, DE = address of user's FCB
- ; Exit: DE = address of our FCB
- ; Uses: BC, DE, HL
- ;
- iniopn: ld (iotbl),hl ; save address of input control table
- call RETUD ; get drive and user
- ld (hl),b
- inc hl
- ld (hl),c
- inc hl ; point to open FCB
- inc hl
- inc hl
- inc hl
- push hl ; save our FCB pointer
- ld bc,12 ; we only need the first 12 bytes
- ex de,hl ; HL = user's FCB, DE = our FCB
- ldir
- pop de ; get our FCB pointer into DE
- jp INITFCB ; initialize FCB and return
- ;
- ; setdu -- Sets drive and user for current file.
- ; Entry: HL = address of drive byte, followed by user byte.
- ; Return: HL = address of byte following user. Also uses BC.
- ;
- setdu: ld b,(hl) ; get drive
- inc hl
- ld c,(hl) ; get user
- inc hl
- jp LOGUD ; jump and return to caller
- ;
- ; Storage for all global routines
- ;
- DSEG
- ;
- iotbl: ds 2 ; address of input/output control table
- byte: ds 1 ; data byte storage
- ;
- end