home *** CD-ROM | disk | FTP | other *** search
- ;
- ; SYSLIB Module Name: SFILEI
- ; Author: Richard Conn
- ; SYSLIB Version Number: 2.0
- ; Module Version Number: 1.0
- ; Module Entry Points:
- ; ADRCPY F$GET F$PUT FI$CLOSE
- ; FI$OPEN FO$CLOSE FO$OPEN
- ; Module External References:
- ; F$MOPEN F$OPEN INITFCB
- ;
-
- ;
- ; SFILEIO.MAC -- BYTE-ORIENTED FILE I/O FOR SYSLIB
- ; INCLUDED ROUTINES ARE -- FILE INPUT OPEN, FILE OUTPUT OPEN,
- ; FILE INPUT CLOSE, FILE OUTPUT CLOSE,
- ; GET, PUT
- ; Error Diagnostics are returned to the caller via the Zero Flag
- ; (Zero Flag Set - Z - ALWAYS Means No Error Occurred)
- ; and the A Register
- ; If the Zero Flag is Set (Z), then the A Register either contains
- ; a 0 or the required returned value if A is significant for
- ; the particular routine.
- ; If the Zero Flag is Clear (NZ), then the A Register contains the
- ; error code. No other returned register value in HL, DE, or BC
- ; should be considered to be valid. The Returned Error Codes
- ; in A are:
- ; Code Meaning
- ; 1 GET or PUT attempted on unopened file
- ; 2 Disk Full (Ran out of space)
- ; 3 Input File Not Found
- ; 4 Attempt to Read Past the EOF
- ; 5 Directory Full
- ; 6 Error in Closing a File
- ; 7 Attempt to Open a File which is already open
- ;
-
- ;
- ; EXTERNAL LIBRARY FILE DEFINITIONS
- ;
- EXT F$OPEN ; OPEN FILE
- EXT F$MOPEN ; OPEN/CREATE FILE
- EXT INITFCB ; INIT FCB
-
- ;
- ; CP/M EQUATES AND ASCII CONSTANTS
- ;
- CPM EQU 0 ; WARM BOOT FOR CP/M
- TBUFF EQU 80H ; TEMPORARY FILE I/O BUFFER
- CR EQU 0DH ; <CR>
- LF EQU 0DH ; <LF>
-
- BDOS EQU 5 ; BDOS ENTRY POINT
- B$CL EQU 16 ; CLOSE FILE
- B$RD EQU 20 ; READ NEXT RECORD
- B$WR EQU 21 ; WRITE NEXT RECORD
- B$DMA EQU 26 ; SET DMA ADDRESS
-
- ;
- ; SUPPORTING MACROS
- ;
- PUTRG MACRO ; SAVE BC, DE, HL
- PUSH B
- PUSH D
- PUSH H
- ENDM
- GETRG MACRO ; RESTORE HL, DE, BC
- POP H
- POP D
- POP B
- ENDM
-
- ;**********************************************************************
- ; SUPPORTING ROUTINES
- ;
-
- ;
- ; ADDRESS TABLE COPY ROUTINE
- ;
- ADRCPY::
- LXI H,I$FLG ; PT TO FIRST ENTRY
- MVI B,20 ; 20 BYTES (10 ADDRESSES) TO COPY
- JMP SFCBL ; DO COPY
-
- ;
- ; GET ONE-LEVEL INDIRECT ADDRESS
- ; HL = ADDRESS CONTAINED AT MEMORY LOCATION PTED TO BY HL
- ;
- GETADR:
- PUSH D ; SAVE DE
- MOV E,M ; GET LOW
- INX H
- MOV D,M ; GET HIGH
- MOV H,D ; SET HL
- MOV L,E
- POP D ; GET DE
- RET
-
- ;
- ; SAVEFCB UTILITY -- COPY FCB FROM DE TO HL
- ;
- SAVEFCB:
- MVI B,36 ; 36 BYTES
- SFCBL:
- LDAX D ; GET BYTE
- MOV M,A ; PUT BYTE
- INX H ; PT TO NEXT
- INX D
- DCR B ; COUNT DOWN
- JNZ SFCBL
- RET
- ;
- ; F$ABORT -- FILE ERROR -- ABORT
- ;
- F$ABORT:
- GETRG ; RESTORE REGISTERS
- ORA A ; SET FLAGS
- RET
- ;
- ; F$CLOS -- CLOSE FILE
- ;
- F$CLOS:
- MVI C,B$CL ; CLOSE FILE
- CALL BDOS
- RET
- ;
- ; F$READ -- READ ONE 128-BYTE BLOCK VIA CP/M
- ;
- F$READ:
- MVI C,B$RD ; READ BLOCK
- CALL BDOS
- RET
- ;
- ; F$WRIT -- WRITE ONE 128-BYTE BLOCK VIA CP/M
- ;
- F$WRIT:
- MVI C,B$WR ; WRITE BLOCK
- CALL BDOS
- RET
- ;
- ; READ$BLOCK -- READ BLOCK FROM INPUT FILE INTO INPUT BUFFER
- ; ON RETURN, Z=OK AND NZ=NOT OK (PAST EOF)
- ;
- READ$BLOCK:
- LHLD I$FCB ; GET FCB ADDRESS
- XCHG ; ... IN DE
- CALL F$READ ; READ BLOCK
- PUSH PSW ; SAVE STATUS
- LHLD I$BUF ; PT TO INPUT BUFFER
- LXI D,TBUFF ; PT TO TEMP BUFFER
- MVI B,128 ; 128 BYTES
- CALL SFCBL ; COPY FROM DE TO HL FOR B BYTES
- POP PSW ; GET STATUS
- ORA A ; SET ZERO FLAG IF OK
- RET
- ;
- ; WRIT$BLOCK -- WRITE BLOCK TO OUTPUT FILE
- ;
- WRIT$BLOCK:
- LHLD O$BUF ; ADDRESS OF OUTPUT BUFFER
- XCHG ; ... IN DE
- LXI H,TBUFF ; PT TO TEMP BUFFER
- MVI B,128 ; 128 BYTES
- CALL SFCBL ; COPY FROM DE TO HL FOR B BYTES
- LHLD O$FCB ; PT TO DEFAULT FCB
- XCHG ; ... IN DE
- CALL F$WRIT ; WRITE BLOCK
- ORA A ; OK?
- RZ ; OK IF ZERO
- MVI A,2 ; DISK FULL ERROR CODE
- RET
- ;
- ; **** BASE ROUTINES ****
- ;
- ; FI$OPEN -- OPEN FILE WHOSE FCB IS PTED TO BY DE FOR INPUT
- ;
- FI$OPEN::
- PUTRG ; SAVE REGISTERS
- PUSH D ; SAVE PTR
- LXI D,TBUFF ; SET DMA ADDRESS
- MVI C,B$DMA
- CALL BDOS
- POP D ; GET PTR
- LHLD I$FLG ; ALREADY OPENED?
- MOV A,M ; GET FLAG
- ORA A ; 0=NO
- JZ FI$OP0
- MVI A,7 ; FILE ALREADY OPEN ERROR
- JMP F$ABORT
- FI$OP0:
- LHLD I$FCB ; PT TO DEFAULT OPEN FCB
- PUSH H ; SAVE PTR TO FCB
- CALL SAVEFCB ; CREATE NEW FCB
- POP D ; GET PTR TO FCB
- CALL INITFCB ; CLEAR FCB FIELDS
- CALL F$OPEN ; OPEN FILE
- ORA A ; ZERO MEANS OK
- JZ FI$OP1
- MVI A,3 ; FILE NOT FOUND FOR INPUT
- JMP F$ABORT
- FI$OP1:
- CALL READ$BLOCK ; READ FIRST BLOCK
- JZ FI$OP2
- MVI A,4 ; READ PAST EOF ERROR
- JMP F$ABORT
- FI$OP2:
- LHLD I$BUF ; PT TO BUFFER
- XCHG ; ... ADDRESS IN DE
- LHLD I$PTR ; SAVE PTR
- MOV M,E ; SAVE ADDRESS PTR
- INX H
- MOV M,D
- LHLD I$CNT ; GET PTR TO COUNT
- MVI M,128 ; SET COUNT
- LHLD I$FLG ; GET PTR TO FLAG
- MVI M,0FFH ; SET FILE OPENED FLAG
- GETRG ; RESTORE REGISTERS
- XRA A ; OK RETURN
- RET
- ;
- ; FO$OPEN -- OPEN FILE WHOSE FCB IS PTED TO BY DE FOR OUTPUT
- ;
- FO$OPEN::
- PUTRG ; SAVE REGISTERS
- PUSH D ; SAVE PTR
- LXI D,TBUFF ; SET DMA ADDRESS
- MVI C,B$DMA
- CALL BDOS
- POP D ; GET PTR
- LHLD O$FLG ; CHECK FOR FILE ALREADY OPENED
- MOV A,M ; GET FLAG
- ORA A ; 0 MEANS NOT YET OPENED
- JZ FO$OP0
- MVI A,7 ; FILE ALREADY OPENED ERROR
- JMP F$ABORT
- FO$OP0:
- LHLD O$FCB ; PT TO DEFAULT OPEN FCB
- PUSH H ; SAVE PTR TO FCB
- CALL SAVEFCB ; CREATE NEW FCB
- POP D ; GET PTR TO FCB
- CALL INITFCB ; CLEAR FCB FIELDS
- CALL F$MOPEN ; OPEN AND/OR CREATE FILE
- JZ FO$OP1
- MVI A,5 ; DIRECTORY FULL
- JMP F$ABORT
- FO$OP1:
- LHLD O$BUF ; PT TO BUFFER
- XCHG ; ... IN DE
- LHLD O$PTR ; SAVE PTR
- MOV M,E ; SAVE ADDRESS PTR
- INX H
- MOV M,D
- LHLD O$CNT ; GET PTR TO COUNT
- MVI M,128 ; SET COUNT
- LHLD O$FLG ; GET PTR TO FLAG
- MVI M,0FFH ; SET FILE OPENED FLAG
- GETRG ; RESTORE REGISTERS
- XRA A ; OK RETURN
- RET
- ;
- ; F$GET -- GET BYTE FROM INPUT FILE; BYTE RETURNED IN REG A
- ; ON RETURN, IF CARRY=0 (NC), THEN OK; IF CARRY=1 (C), THEN PAST EOF
- ;
- F$GET::
- PUTRG ; SAVE REGISTERS
- LHLD I$FLG ; PT TO FLAG
- MOV A,M ; GET IT; INPUT OK?
- ORA A ; ZERO MEANS NO
- JNZ F$G1
- MVI A,1 ; FILE NOT YET OPENED
- JMP F$ABORT
- F$G1:
- LHLD I$PTR ; PT TO NEXT BYTE
- CALL GETADR ; GET ADDRESS OF BYTE PTED TO BY PTR
- MOV A,H ; EOF WAS REACHED IF POINTER IS ZERO
- ORA L
- JZ F$GEOF
- MOV A,M ; GET BYTE
- STA BYTE ; SAVE BYTE FOR RETURN
- INX H ; PT TO NEXT BYTE
- XCHG ; ... IN DE
- LHLD I$PTR ; PT TO POINTER
- MOV M,E ; SAVE ADDRESS PTR
- INX H
- MOV M,D
- LHLD I$CNT ; PT TO COUNT
- DCR M ; DECREMENT COUNT
- JNZ F$GET1
- ; READ IN NEXT BLOCK AND RESET POINTERS
- LHLD I$BUF ; PT TO BUFFER
- XCHG ; ... IN DE
- LHLD I$PTR
- MOV M,E ; SAVE ADDRESS PTR
- INX H
- MOV M,D
- LHLD I$CNT ; PT TO COUNT
- MVI M,128 ; SET COUNT
- CALL READ$BLOCK
- JZ F$GET1 ; OK RETURN
- LHLD I$PTR ; SET POINTER TO ZERO TO INDICATE EOF REACHED
- MVI M,0 ; STORE ZEROES
- INX H
- MVI M,0
- ; NORMAL EXIT
- F$GET1:
- GETRG ; RESTORE REGISTERS
- XRA A ; ZERO MEANS OK
- LDA BYTE ; GET BYTE VALUE TO RETURN
- RET
- ; EOF EXIT
- F$GEOF:
- MVI A,4 ; EOF
- JMP F$ABORT
-
- ;
- ; F$PUT -- PUT BYTE IN REG A INTO OUTPUT FILE
- ;
- F$PUT::
- PUTRG ; SAVE REGISTERS
- STA BYTE ; SAVE BYTE TO OUTPUT
- LHLD O$FLG ; GET FILE OPENED FLAG
- MOV A,M ; GET FLAG
- ORA A ; ZERO MEANS NO
- JNZ F$P1
- POP PSW ; CLEAR STACK
- MVI A,1 ; FILE NOT OPENED
- JMP F$ABORT
- F$P1:
- LHLD O$PTR ; GET PTR TO NEXT BYTE
- CALL GETADR ; PT TO BYTE PTED TO BY PTR
- LDA BYTE ; GET BYTE TO OUTPUT
- MOV M,A ; PUT BYTE
- INX H ; PT TO NEXT
- XCHG ; ... IN DE
- LHLD O$PTR ; PT TO PTR
- MOV M,E ; SAVE ADDRESS
- INX H
- MOV M,D
- LHLD O$CNT ; PT TO COUNT
- DCR M ; COUNT DOWN
- JNZ F$PUT1 ; RETURN IF OK
- ; BUFFER FULL -- WRITE IT TO DISK AND RESET POINTER AND COUNT
- LHLD O$BUF ; RESET POINTER
- XCHG ; ADDR OF BUFFER IN DE
- LHLD O$PTR
- MOV M,E ; SAVE ADDRESS PTR
- INX H
- MOV M,D
- LHLD O$CNT ; PT TO COUNT
- MVI M,128 ; RESET COUNT
- CALL WRIT$BLOCK
- MVI A,2 ; ASSUME DISK FULL ERROR
- JNZ F$ABORT ; ERROR IN WRITE
- ; NORMAL EXIT
- F$PUT1:
- GETRG ; RESTORE REGISTERS
- XRA A ; Z FOR NO ERROR
- LDA BYTE ; GET BYTE VALUE
- RET
- ;
- ; FI$CLOS -- CLOSE FILE OPENED FOR INPUT
- ;
- FI$CLOS::
- PUSH H
- LHLD I$FLG ; SET INPUT OPENED FLAG
- MVI M,0 ; INPUT NOT OPENED NOW
- POP H
- RET
- ;
- ; GENERAL-PURPOSE POINTERS FOR ALL GLOBAL ROUTINES
- ;
- I$FLG: DS 2 ; INPUT FILE OPENED FLAG (0=NO)
- O$FLG: DS 2 ; OUTPUT FILE OPENED FLAG (0=NO)
- I$FCB: DS 2 ; INPUT FILE FCB
- O$FCB: DS 2 ; OUTPUT FILE FCB
- I$BUF: DS 2 ; INPUT BUFFER
- O$BUF: DS 2 ; OUTPUT BUFFER
- I$PTR: DS 2 ; INPUT CHAR PTR
- O$PTR: DS 2 ; OUTPUT CHAR PTR
- I$CNT: DS 2 ; INPUT CHAR COUNT
- O$CNT: DS 2 ; OUTPUT CHAR COUNT
-
-
- BYTE: DS 1 ; BYTE STORAGE
-
- ;
- ; FO$CLOS -- CLOSE FILE OPENED FOR OUTPUT
- ;
- FO$CLOS::
- PUTRG ; SAVE REGS
- STA BYTE ; SAVE A
- MVI A,1AH ; PUT CTRL-Z
- CALL F$PUT
- CLOSE1:
- LHLD O$CNT ; PT TO COUNT
- MOV A,M ; GET COUNT
- CPI 128 ; CLOSE IF BLOCK JUST WRITTEN
- JZ CLOSE2
- XRA A ; PUT ZERO
- CALL F$PUT
- JMP CLOSE1
- CLOSE2:
- LHLD O$FLG ; SET OUTPUT OPENED FLAG
- MVI M,0 ; NOT OPENED
- LHLD O$FCB ; PT TO OUTPUT FCB
- XCHG ; ... PT VIA DE
- CALL F$CLOS ; CLOSE FILE
- CPI 0FFH ; ERROR?
- JNZ CLOSE3
- MVI A,6 ; CLOSE ERROR
- JMP F$ABORT
- CLOSE3:
- GETRG ; RESTORE REGS
- XRA A ; OK RETURN
- LDA BYTE ; GET ORIGINAL A
- RET
-
- END
-