mirror of
https://github.com/RevCurtisP/C02.git
synced 2024-12-01 14:51:52 +00:00
695 lines
24 KiB
Plaintext
695 lines
24 KiB
Plaintext
|
;C02 Module file.h02 Assembly Language Routines
|
||
|
;for all Commodore 8 bit machines
|
||
|
; Requires error code definitions from error.a02,
|
||
|
; External routines FSFLFA, RESRXY, STRLEN
|
||
|
; and the following RAM locations definitions
|
||
|
; external zero page byte pairs SRCLO,SRCHI and DSTLO,DSTHI
|
||
|
; and external bytes TEMP1, TEMP2
|
||
|
; NOTE: Reading from CASSETTE will not produce an EOF
|
||
|
|
||
|
;Kernal Device Numbers
|
||
|
KEYBRD EQU 0
|
||
|
CASST1 EQU 1
|
||
|
MODEM1 EQU 2
|
||
|
SCREEN EQU 3
|
||
|
PRNTR1 EQU 4
|
||
|
PRNTR2 EQU 5
|
||
|
PRNTR3 EQU 6
|
||
|
PRNTR4 EQU 7
|
||
|
DRIVE1 EQU 8
|
||
|
DRIVE2 EQU 9
|
||
|
DRIVE3 EQU 10
|
||
|
DRIVE4 EQU 11
|
||
|
DRIVE5 EQU 12
|
||
|
DRIVE6 EQU 13
|
||
|
DRIVE7 EQU 14
|
||
|
DRIVE8 EQU 15
|
||
|
|
||
|
;Disk Numbers (Within Drive)
|
||
|
DISK0 EQU $00
|
||
|
DISK1 EQU $40
|
||
|
|
||
|
;File Open Modes
|
||
|
MWRITE EQU $80
|
||
|
MREAD EQU $00
|
||
|
|
||
|
;File Load Modes
|
||
|
MABSLT EQU $80 ;Absolute (Use File Header Address)
|
||
|
MRELCT EQU $00 ;Relocate (Use Specified Address)
|
||
|
|
||
|
;File Types
|
||
|
FTASC EQU $00 ;ASCII Text (SEQ)
|
||
|
FTBAS EQU $10 ;Basic Program (PRG)
|
||
|
FTBIN EQU $20 ;Binary File (PRG)
|
||
|
FTUSR EQU $30 ;User-Defined (USR)
|
||
|
|
||
|
;Zero Page System Variables (Names Subject to Change)
|
||
|
FSIOST EQU $90 ;Kernal I/O Status Word
|
||
|
FSNOFL EQU $98 ;Number of Open I/O Files
|
||
|
FSRCVB EQU $A4 ;Serial Bus Received Byte
|
||
|
FSSVLO EQU $AC ;Save Address (Low Byte)
|
||
|
FSSVHI EQU $AD ;Save Address (High Byte)
|
||
|
FSFNLN EQU $B7 ;Length of Current Filename
|
||
|
FSLFNO EQU $B8 ;Current Logical File Number
|
||
|
FSSADR EQU $B9 ;Current Secondary Address
|
||
|
FSDVNO EQU $BA ;Current Device Number
|
||
|
FSFNLO EQU $BB ;Pointer: Current Filename (LSB)
|
||
|
FSFNHI EQU $BC ;Pointer: Current Filename (MSB)
|
||
|
|
||
|
;IEC STATUS Bit Masks
|
||
|
FSSTTO EQU $03 ;Disk - Read/Write Timeout $21 //Error - Operation Timed Out
|
||
|
FSSTSB EQU $04 ;Tape - Short Block
|
||
|
FSSTLB EQU $08 ;Tape - Long Block
|
||
|
FSSTRE EQU $10 ;Tape - Read Error
|
||
|
FSSTCE EQU $20 ;Both - Checksum Error
|
||
|
FSSTEF EQU $40 ;Both - End of File
|
||
|
FSSTNP EQU $80 ;Disk - Device Not Present
|
||
|
FSSTET EQU $80 ;Tape - End of Tape
|
||
|
|
||
|
;RS-232 Status Bit Masks
|
||
|
;$01 - Parity Error
|
||
|
;$02 - Framing Error
|
||
|
;$04 - Receive Overrun
|
||
|
;$10 - CTS Missing
|
||
|
;$40 - DSR Missing
|
||
|
;$80 - BREAK Detected
|
||
|
|
||
|
;fsioet[15] - I/O Error Table by Channel Number
|
||
|
FSIOET EQU $0140 ;Bottom of BASIC Stack Area
|
||
|
|
||
|
;fscntr - File Counter
|
||
|
FSCNTR EQU $0150 ;Byte Following Error Table
|
||
|
|
||
|
;fsbufr - Buffer for String Concatenation
|
||
|
FSBUFR EQU $0200 ;BASIC Line Editor Input Buffer
|
||
|
|
||
|
;Error Code Conversion Tables
|
||
|
;FSCSST DC FSSSPE,FSSSFE,FSSSRO,FSSSCM,FSSSDM,FSSSBD
|
||
|
FSCSTT DC FSSTTO,FSSTSB,FSSTLB,FSSTRE,FSSTCE ;STATUS to Error Code
|
||
|
|
||
|
;String Constants
|
||
|
FSCMDI DC "I",0 ;Command - Initialize Drive
|
||
|
FSWSFX DC ",S,W",0 ;Filename Suffix for Write
|
||
|
|
||
|
;fsbcmd(command) - Build Disk Command String
|
||
|
;Args: A = Disk Command (Single Letter Abbreviation)
|
||
|
;Uses: FSBUFR = Command String
|
||
|
; TEMP2 = Mode/Option Byte
|
||
|
FSBCMD: STA FSBUFR ;Store Command in FSBUFR[0]
|
||
|
JSR FSDSKN ;Get Disk Number
|
||
|
STA FSBUFR+1 ;and Store in FSBUFR[1]
|
||
|
LDA #58 ;Load ':'
|
||
|
STA FSBUFR+2 ;and Store in FSBUFR[2]
|
||
|
LDA #0 ;Load String Terminator
|
||
|
STA FSBUFR+3 ;and Store in FSBUFR[3]
|
||
|
RTS
|
||
|
|
||
|
;fsdskn() - Get Disk Number
|
||
|
;Uses: TEMP2 = Mode/Option Byte
|
||
|
;Returns: A = Disk Number "0" or "1"
|
||
|
FSDSKN: LDA TEMP2 ;Get Option Byte
|
||
|
AND #$01 ;Isolate Drive Number
|
||
|
ORA #$30 ;Convert to ASCII
|
||
|
RTS
|
||
|
|
||
|
;fschan(chan) - Find Channel Info
|
||
|
;Args: A = Logical File Number
|
||
|
;Uses: $0259 = LAT File number table
|
||
|
; $0263 = FAT Device number table
|
||
|
; $026D = SAT Secondary address table
|
||
|
;Returns: A = Device Number
|
||
|
; Y = Secondary Address
|
||
|
; X = Index into File Tables
|
||
|
; $FF if Channel Not Open
|
||
|
FSCHAN: JSR FSFLFA ;Find File Table Index
|
||
|
BMI FSCHAX ;If Found
|
||
|
LDA $026D,X ;Load Secondary Address into Y
|
||
|
TAY
|
||
|
LDA $0263,X ;Load Device Number into X
|
||
|
FSCHAX: RTS
|
||
|
|
||
|
;fsinit(device) - Initialize Disk Drive
|
||
|
;Args: A = Device Number
|
||
|
; Y,X = Pointer to Command String
|
||
|
;Uses: FSBUFR - String Concatenation Buffer
|
||
|
;Sets: TEMP2 = Number of Bytes Read from Drive
|
||
|
;Returns: A = Drive Status Code
|
||
|
; Y = Kernal or I/O Error
|
||
|
FSINIT: LDX #<FSCMDI ;Load Pointer to Command String
|
||
|
LDY #>FSCMDI ;and Fall Trhough to FSDCMD
|
||
|
|
||
|
;fsdcmd(device) - Send Command to Drive
|
||
|
;Args: A = Device Number
|
||
|
; Y,X = Pointer to Command String
|
||
|
;Uses: FSBUFR - String Concatenation Buffer
|
||
|
;Sets: TEMP2 = Number of Bytes Read from Drive
|
||
|
;Returns: A = Drive Status Code
|
||
|
; Y = Kernal or I/O Error
|
||
|
FSDCMD: JSR SETSRC ;Save Command String Pointer
|
||
|
JSR FSOCMD ;Open Command Channel
|
||
|
BEQ FSCHAX ;If Not Open, Return
|
||
|
ORA #$80 ;Set flag to Emit C/R
|
||
|
JSR FPUTSA ;Call fputs() - Alternate Entry Point
|
||
|
BCC FSDSTR ;If No Error, Get Disk Status
|
||
|
RTS ;Else Return
|
||
|
|
||
|
;fscste(status) - Convert STATUS byte into Error Code
|
||
|
FSCSTE: LDY #5 ;Set Index to Table Size
|
||
|
FSCSTL: AND FSCSTT-1,Y ;Mask Bits Against Table Entry
|
||
|
BNE FSCSTS ;If Bits Not Set
|
||
|
DEY ; Decrement Index
|
||
|
BNE FSCSTL ; and Loop if Not Zero
|
||
|
FSCSTS: TYA ;Copy Index to Accumulator
|
||
|
BEQ FSCSTX ;If Not Zero
|
||
|
ORA #$10 ; Convert from $0x to $1x
|
||
|
FSCSTX: RTS
|
||
|
|
||
|
;fscdst(status) - Convert Drive Status
|
||
|
;Args: A = Drive Status Code
|
||
|
;Returns: Y = Converted Error Code
|
||
|
|
||
|
|
||
|
;fsdsts(device) - Get Drive Status
|
||
|
;Args: A = Device Number
|
||
|
;Uses: FSBUFR - String Concatenation Buffer
|
||
|
;Returns: A = Drive Status Code
|
||
|
; Y = Kernal or I/O Error
|
||
|
FSDSTS: JSR FSOCMD ;Open Command Channel
|
||
|
BCS FSCHAX ;If Error, Return
|
||
|
FSDSTR: JSR FSRCMD ;Read Command Channel
|
||
|
BEQ FSDSTX ;If Bytes Read
|
||
|
JSR FSGBFR ; Get Buffer Address
|
||
|
JSR ATOC ; Convert Error# to Byte
|
||
|
LDY #0 ; Set Error to 0
|
||
|
FSDSTX: RTS ;and Return
|
||
|
|
||
|
;fscbfr() - Copy Source String to String Buffer
|
||
|
;Args: C = Mode
|
||
|
;Uses: SRCLO,SRCHI = Pointer to Source String
|
||
|
FSCBFR: JSR FSGBFR ;Get String Buffer Address
|
||
|
JSR SETDST ;Set Buffer as Destination
|
||
|
LDY #0 ;Initialize Index
|
||
|
BCS FSCBFS ;If Carry Clear
|
||
|
JMP STRCPL ; Copy String
|
||
|
FSCBFS: JMP STRCAL ;Else Concatenate String
|
||
|
|
||
|
;fsgbfr() - Get String Buffer Address
|
||
|
FSGBFR: LDX #<FSBUFR ;Load LSB into X
|
||
|
LDY #>FSBUFR ;Load MSB into Y
|
||
|
RTS
|
||
|
|
||
|
;fsocmd(device) - Open Command Channel
|
||
|
;Args: A = Device Number
|
||
|
;Returns: A = Logical File Number
|
||
|
FSOCMD: ORA #$10 ;Set LFN to Device# + 16
|
||
|
JSR FSFLFA ;Find File Table Index
|
||
|
BPL FSCHAX ;If Already Open, Return
|
||
|
TAX ;Copy Device Number to X
|
||
|
FSOCMX: LDA #0 ;Set Filename to None
|
||
|
JSR $FFBD ;Call Kernal SETNAM Routine
|
||
|
FSET15: LDA #15 ;Set LFN to 15
|
||
|
BNE FSOPEY ;Copy to SA and Open Channel
|
||
|
|
||
|
;fsname(&s) - Set Filename for Load, Save
|
||
|
;Args: Y,X = Pointer to string containing filename
|
||
|
FSNAME: JSR STRLEN ;Get Length of String
|
||
|
JSR GETSRC ;Retrieve String Address
|
||
|
JMP $FFBD ;Execute Kernal SETNAM Routine
|
||
|
|
||
|
;fsonam(&s) - Set Filename for Open
|
||
|
;Args: Y,X = Pointer to string containing filename
|
||
|
FSONAM: LDA TEMP1 ;Get Device Number
|
||
|
AND TEMP2 ;AND with Mode/Option
|
||
|
AND #$08 ;Check Disk + Write Bit
|
||
|
BEQ FSNAME ;Execute FSNAME/FSWNAM
|
||
|
|
||
|
;fswnam(&s) - Set Filename for Write to Disk
|
||
|
;Args: Y,X = Pointer to string containing filename
|
||
|
FSWNAM: JSR SETSRC ;Set Filename as Source
|
||
|
CLC ;Set Flag to Copy
|
||
|
JSR FSCBFR ;and Copy to String Buffer
|
||
|
LDX #<FSWSFX
|
||
|
LDY #>FSWSFX
|
||
|
JSR STRCAT ;Append Write Suffix
|
||
|
JSR FSGBFR ;Get String Buffer Address
|
||
|
JMP $FFBD ;Execute Kernal SETNAM Routine
|
||
|
|
||
|
;fsldsv() - Setup for Load and Save
|
||
|
;Args: A = Logical File Number
|
||
|
; Y = Mode
|
||
|
; X = Device Number
|
||
|
;Returns: Y,X = Destination Address (DSTHI,DSTLO)
|
||
|
FSLDSV: PHA ;Save LFN
|
||
|
TYA ;Copy Mode to Accumulator
|
||
|
LSR ;Rotate Bit 3 to Bit 1
|
||
|
LSR
|
||
|
LSR
|
||
|
TAY ;Use as Secondary Address
|
||
|
PLA ;Restore LFN
|
||
|
JSR $FFBA ;Call Kernal SETLFS Routine
|
||
|
JMP GETDST ;Get Load/End Address into X,Y
|
||
|
|
||
|
;fsopts() - Parse Load/Save/Open Options Byte
|
||
|
;Args: A = Combined Options Byte
|
||
|
; Bits 0-3 = Device Number
|
||
|
; Bits 4-7 = Mode/Option
|
||
|
;Sets: TEMP0 = Combined Option
|
||
|
; TEMP1 = Device
|
||
|
; TEMP2 = Mode/Option
|
||
|
; Bit 1 = Disk Number
|
||
|
; Bits 1-2 = File Type
|
||
|
; Bit 3 = Mode (0=Read/1=Write)
|
||
|
;Returns: A = Mode/Option
|
||
|
FSOPTS: STA TEMP0 ;Save Argument
|
||
|
AND #$0F ;Isolate Device Number
|
||
|
STA TEMP1 ;and Save it
|
||
|
LDA TEMP0 ;Restore Argument
|
||
|
LSR ;Shift to Low Nybble
|
||
|
LSR
|
||
|
LSR
|
||
|
LSR
|
||
|
STA TEMP2 ;and Save it
|
||
|
RTS
|
||
|
|
||
|
;fsopen(chan, mode, device) - Open Channel to Device
|
||
|
;Requires prior call to FSNAME
|
||
|
;Args: A = Logical File Number
|
||
|
; Y = Mode: 0=Read, !0= Write
|
||
|
; X = Device 0=Keyboard, 1=Cassette, 2=RS232, 3=Screen
|
||
|
; 4-7=Printers, 8-15=Disks, 31=All Devices
|
||
|
;Returns: A,X = Channel Number (0=Error)
|
||
|
; Y = Error Number (0=None)
|
||
|
FSOPEN: CPX #1
|
||
|
BNE FSOPEY ;If Device is Cassette
|
||
|
CPY #0
|
||
|
BEQ FSOPEZ ; If Mode is Not Zero
|
||
|
LDY #2 ; Set Secondary Address to 2
|
||
|
BNE FSOPEZ ;Else
|
||
|
FSOPEY: TAY ; Copy LFN to Secondary Address
|
||
|
FSOPEZ: JSR $FFBA ;Call Kernal SETLFS Routine
|
||
|
JSR $FFC0 ;Call Kernal OPEN Routine
|
||
|
BCS FSERRV ;If Error Return A=0, Y=Error#
|
||
|
BCC FSOPED ;** Skip Drive Check for now; **
|
||
|
LDA FSDVNO ;Get Current Device Number
|
||
|
CMP #8 ;Check Device Number
|
||
|
BCC FSOPED ;If Disk Drive
|
||
|
JSR FSDSTS ; Get Drive Status
|
||
|
BCS FSERRV ; If Error Return A=0, Y=Error#
|
||
|
FSOPED: LDA #0 ;Set Error Code to 0
|
||
|
STA FSIOET ;Clear General Error Entry
|
||
|
LDX FSLFNO ;Get LFN
|
||
|
STA FSIOET,X ;Clear Error Table Entry
|
||
|
TAY ;Clear Error Code
|
||
|
TXA ;Return LFN
|
||
|
RTS
|
||
|
|
||
|
;fsload(chan, mode, device) - Load File from Device
|
||
|
;Requires: DSTLO,DSTHI = Load Address
|
||
|
; Prior call to FSNAME
|
||
|
;Args: A = Logical File Number
|
||
|
; Y = Mode: 0=Read, !0= Write
|
||
|
; X = Device 1=Cassette, 8-15=Disks
|
||
|
;Returns: A = Error Number (0=None)
|
||
|
; Y,X = Address at Last Byte Loaded
|
||
|
FSLOAD: JSR FSLDSV ;Set up for Load/Save
|
||
|
LDA TEMP3 ;Get Load/Verify Flag
|
||
|
FSLOAK: JSR $FFD5 ;Call Kernal LOAD Routine
|
||
|
BCC FSZERO ;If No Error, Return 0
|
||
|
RTS
|
||
|
|
||
|
;fssave(chan, mode, device) - Save File to Device
|
||
|
;Requires: DSTLO,DSTHI = Load Address
|
||
|
; Prior call to FSNAME
|
||
|
;Args: A = Logical File Number
|
||
|
; Y = Mode: 0=Read, !0= Write
|
||
|
; X = Device 1=Cassette, 8-15=Disks
|
||
|
;Returns: A = Error Number (0=None)
|
||
|
; Y,X = Address at Last Byte Loaded
|
||
|
FSSAVE: JSR FSLDSV ;Set up for Load/Save
|
||
|
LDA #FSSVLO ;Load Start Address Pointer
|
||
|
JSR $FFD8 ;Call Kernal SAVE Routine
|
||
|
BCC FSZERO ;If No Error, Return 0
|
||
|
RTS
|
||
|
|
||
|
;fsrdst() - Read I/O Status Byte
|
||
|
;Replaces Kernal READST Routine, fixing RS-232 bug,
|
||
|
;bypassing Kernal messages, and preserving Accumulator
|
||
|
;Affects: X
|
||
|
;Returns: Carry Set if Error
|
||
|
; Overflow Set if EOF
|
||
|
; Y = I/O Status
|
||
|
; Bit Cassette Read Serial Bus I/O Tape Load/Verify
|
||
|
; $01 Write Timeout
|
||
|
; $02 Read Timeout
|
||
|
; $04 Short Block Short Block
|
||
|
; $08 Long Block Long Block
|
||
|
; $10 Read Error Any Mismatch
|
||
|
; $20 Checksum Err Checksum Err
|
||
|
; $40 End of File EOI Line
|
||
|
; $80 End of Tape Device Not Present End of Tape
|
||
|
FSRDST: TAX ;Save Accumulator
|
||
|
CLV ;Clear Overflow Flag
|
||
|
LDY $BA ;Get Current Device Number
|
||
|
CPY #$02 ;Check Device Number
|
||
|
BNE FSRDSS ;If Serial Port
|
||
|
LDA $0297 ; Read RS-232 Status Word
|
||
|
LDY #0 ; then
|
||
|
STY $0297 ; Clear It
|
||
|
BEQ FSRDSX ;Else
|
||
|
FSRDSS: LDA FSIOST ; Load I/O Status Byte
|
||
|
BIT FSIOST ; EOF Bit into Overflow Flag
|
||
|
BEQ FSRDSX ; If Error
|
||
|
BVS FSRDSX ; And Not EOF
|
||
|
JSR FSCSTE ; Convert ST into Error
|
||
|
FSRDSX: LDY FSLFNO ;Get Logical File Number
|
||
|
STA FSIOET,Y ;Save Error in Table
|
||
|
BVC FSRDSY ;If EOF
|
||
|
AND #$BF ; Clear EOF Flag
|
||
|
FSRDSY: CMP #1 ;Set Carry if Error
|
||
|
TAY ;Copy Error Code to Y
|
||
|
TXA ;Restore Accumulator
|
||
|
RTS
|
||
|
|
||
|
;fsunch() - Find Unused Channel Number
|
||
|
;Affects: X,Y
|
||
|
;Returns: A = Channel Number
|
||
|
; 0=No Channel Available
|
||
|
FSUNCH: LDY #2 ;Start with Channel 2
|
||
|
FSUNCL: TYA ;Copy Channel to Accumulator`
|
||
|
JSR FSFLFA ;Find File Table Index
|
||
|
BMI FSUNCX ;If Channel Allocated
|
||
|
INY ; Increment Channel
|
||
|
CPY #15 ; If less than 15
|
||
|
BCC FSUNCL ; Loop
|
||
|
LDY #0 ; Else Return 0
|
||
|
FSUNCX: TYA ;Copy Channel to Set Flags
|
||
|
RTS
|
||
|
|
||
|
;fscdrv() - Check if Device is Disk Drive
|
||
|
;Uses: TEMP1 = Device Number
|
||
|
;Returns: A = Device Number
|
||
|
; 0 if Not a Disk Drive
|
||
|
; Y = Error Code
|
||
|
; 0 = None
|
||
|
FSCDRV: LDA TEMP1 ;Get Device Number
|
||
|
FSCDRA: CMP #8 ;If >=8
|
||
|
BCS FSRTS ; Return
|
||
|
;fserr7() - Return General Error 7
|
||
|
FSERR7: LDA #7 ;Set Error to Illegal Device Number
|
||
|
DC $2C ;BIT - Skip Next Instruction
|
||
|
;fserr2() - Return General Error 2
|
||
|
FSERR2: LDA #2 ;Set Error to 2
|
||
|
;fserrv(error) - Write General Error Entry
|
||
|
FSERRV: LDX #0 ;Set No Logical File Number
|
||
|
DC $2C ;BIT - Skip Next Instruction
|
||
|
;fserrw() - Write Error To Table and Return in Y
|
||
|
FSERRW: LDX FSLFNO ;Get Logical File Number
|
||
|
FSERRX: STA FSIOET,X ;Save Error To Table
|
||
|
FSERRY: TAY ;Move Error Code to Y
|
||
|
FSZERO: LDA #0 ;Return 0
|
||
|
FSRTS: RTS
|
||
|
|
||
|
;fload(args, &name) - Load File
|
||
|
;Args: A = Mode + Device #
|
||
|
; Y,X = Pointer to File Name
|
||
|
;Returns: A = Error Number (0=None)
|
||
|
; Y,X = Address at Last Byte Loaded
|
||
|
FLOAD: JSR FSOPTS ;Parse Options Argument
|
||
|
LDA #0 ;Set Flag to LOAD
|
||
|
FLOADA: STA TEMP3 ;and Save It
|
||
|
JSR FSNAME ;Set Filename for Open
|
||
|
JSR FSUNCH ;Find Unused Channel Number
|
||
|
BEQ FSERR2 ;If None Available, Return Error
|
||
|
JSR RESRXY ;Load Device, Mode into X, Y
|
||
|
JMP FSLOAD ;and Load File
|
||
|
|
||
|
;fsave(args, &name) - Save File
|
||
|
;Requires: SRCLO,SRCHI = Start Address
|
||
|
; DSTLO,DSTHI = End Address
|
||
|
;Args: A = Mode + Device #
|
||
|
; Y,X = Pointer to File Name
|
||
|
;Returns: A = Error Number (0=None)
|
||
|
; Y,X = Address at Last Byte Loaded
|
||
|
FSAVE: JSR SAVREG ;Save Arguments
|
||
|
JSR GETSRC ;Get Start Address
|
||
|
STX FSSVLO ;and Store It
|
||
|
STY FSSVHI
|
||
|
JSR RESREG ;Restore Arguments
|
||
|
JSR FSOPTS ;Parse Options Argument
|
||
|
JSR FSNAME ;Set Filename for Open
|
||
|
JSR FSUNCH ;Find Unused Channel Number
|
||
|
BEQ FSERR2 ;If None Available, Return 0
|
||
|
JSR RESRXY ;Load Device, Mode into X, Y
|
||
|
JMP FSSAVE ;and Load File
|
||
|
|
||
|
;fvrfy(args, &name) - Verify File
|
||
|
;Args: A = Mode + Device #
|
||
|
; Y,X = Pointer to File Name
|
||
|
;Returns: A = Error Number (0=None)
|
||
|
; Y,X = Address at Last Byte Loaded
|
||
|
FVRFY: JSR FSOPTS ;Parse Options Argument
|
||
|
LDA #1 ;Set Flag to VERIFY
|
||
|
BNE FLOADA ;Execute FLOAD Alternate Entry Point
|
||
|
|
||
|
;fopen(args, &name) - Open File
|
||
|
;Args: A = Mode + Device #
|
||
|
; Y,X = Pointer to File Name
|
||
|
;Returns: A = File Channel (0=File Not Opened)
|
||
|
; Y = File Error (0=None)
|
||
|
FOPEN: JSR FSOPTS ;Parse Options Argument
|
||
|
FOPENA: JSR FSONAM ;Set Filename for Open
|
||
|
JSR FSUNCH ;Find Unused Channel Number
|
||
|
BEQ FSERR2 ;If None Available, Return Error 2
|
||
|
JSR RESRXY ;Load Device, Mode into X, Y
|
||
|
JMP FSOPEN ;and Open File
|
||
|
|
||
|
;fsccmd() - Close Command Channel
|
||
|
;Args: A = Device Number
|
||
|
;Returns: A = Logical File Number
|
||
|
FSCCMD: ORA #$10 ;Set LFN to Device# + 16
|
||
|
|
||
|
;fclose(chan) - Close File
|
||
|
;Args: A = Channel Number (0=Close All)
|
||
|
FCLOSE: ORA #0 ;Check File Number
|
||
|
BEQ FCLOSS ;If Not 0
|
||
|
JMP $FFC3 ; Execute Kernal Routine CLOSE
|
||
|
FCLOSS: JMP $FFE7 ;Else Execute Kernal Routine CLALL
|
||
|
|
||
|
;feof(lfn) - Check for End of File
|
||
|
;Args: A = Logical file number
|
||
|
;Affects: A,X
|
||
|
;Returns: A = $FF If End of File
|
||
|
; $00 Otherwise
|
||
|
FEOF: JSR FERROR ;Get Error Code
|
||
|
AND #$40 ;Mask off EOF Bit
|
||
|
BEQ FEOFX ;If Not 0
|
||
|
FSTRUE: LDA #$FF ; Return TRUE
|
||
|
FEOFX: RTS ;Return from Subroutine
|
||
|
|
||
|
;ferror(lfn) - Get Error on Channel`
|
||
|
;Args: A = Channel Number (0=None)
|
||
|
;Returns: A = Error Code
|
||
|
; 1 = Terminated by the STOP key
|
||
|
; 2 = Too many open files
|
||
|
; 3 = File Not Open
|
||
|
; 4 = File not found
|
||
|
; 5 = Device not present
|
||
|
; 6 = Not an input file
|
||
|
; 7 = Not an output file
|
||
|
; 8 = File name is missing
|
||
|
; 9 = Illegal device number
|
||
|
FERROR: TAX ;Copy LFN to X
|
||
|
LDA FSIOET,X ;Load I/O Status for LFN
|
||
|
RTS
|
||
|
|
||
|
;fflush() - Flush file buffer
|
||
|
;Args: A = Logical File Number
|
||
|
FFLUSH: RTS ;No Logic Needed
|
||
|
|
||
|
;fgetc(lfn) - Read character from file
|
||
|
;Args: A = Logical file number
|
||
|
;Affects: X
|
||
|
;Returns: A = Character
|
||
|
; Y = Error Code (0=None)
|
||
|
FGETC: TAX ;Move logical file number to X register
|
||
|
JSR $FFC6 ;Call Kernal Routine CHKIN
|
||
|
FGETCW: BCS FSERRW ;If Error, Write to Table and Return in Y
|
||
|
JSR $FFCF ;Call Kernal Routine CHRIN
|
||
|
TAY ;Save Character
|
||
|
FGETCC: JSR $FFCC ;Call Kernal Routine CLRCHN
|
||
|
TYA ;Restore Character
|
||
|
JSR FSRDST ;Read Status Byte
|
||
|
BVS FSORA0 ;If Not EOF
|
||
|
BCS FSZERO ;and Error, Return NUL
|
||
|
FSORA0: ORA #0 ;Else Set Flags Based on Character
|
||
|
RTS
|
||
|
|
||
|
;fsrcmd() - Read Command Channel
|
||
|
FSRCMD: LDA #15 ;Set LFN to 15
|
||
|
JSR FSGBFR ;Get Buffer Address
|
||
|
|
||
|
;fgets(lfn, &s) - Read string from file
|
||
|
;Args: A = Logical file number
|
||
|
; Y,X = Pointer to String
|
||
|
;Affects: X
|
||
|
;Returns: A = Number of bytes read
|
||
|
; Y = Error Code
|
||
|
FGETS: JSR SETDST ;Save string address
|
||
|
TAX ;Move logical file number to X register
|
||
|
JSR $FFC6 ;Call Kernal Routine CHKIN
|
||
|
BCS FGETCW ;If Error, Write to Table and Return in Y
|
||
|
LDY #0 ;Initialize Index
|
||
|
FGETSL: STY TEMP3 ;and Save It
|
||
|
JSR $FFCF ;Call Kernal Routine CHRIN
|
||
|
LDY TEMP3 ;Restore Index
|
||
|
CMP #$0D ;If Not C/R (Real or from Error)
|
||
|
BEQ FGETSX
|
||
|
STA (DSTLO),Y ;Store Character in String
|
||
|
INY ;Increment Pointer
|
||
|
BPL FGETSL ;and Loop if Less Than 128
|
||
|
FGETSX: LDA #0 ;Store NUL Terminator
|
||
|
STA (DSTLO),Y ;at End of String
|
||
|
JSR $FFCC ;Call Kernal Routine CLRCHN
|
||
|
TYA ;Copy Length of String to Acuumulator
|
||
|
JSR FSRDST ;Get I/O Status in Y Register
|
||
|
ORA #0 ;Set Flags based on Accumulator
|
||
|
FGETSR: RTS
|
||
|
|
||
|
;fread(lfn, count) - Read bytes from file
|
||
|
;Requires: DSTLO, DSTHI - Pointer to destination string
|
||
|
;Args: A = Logical file number
|
||
|
; Y = Number of Bytes to Read
|
||
|
;Sets: TEMP1 = Number of Bytes to Read
|
||
|
; TEMP2 = 0 (Read Mode)
|
||
|
; TEMP3 = Number of Bytes Read
|
||
|
;Affects: X
|
||
|
;Returns: A = Number of bytes read
|
||
|
; Y = Error Code (0=None)
|
||
|
; Carry Set if Error, Clear if None
|
||
|
FREAD: LDX #0 ;Mode = READ
|
||
|
FREADA: STX TEMP2 ;Save Mode
|
||
|
STY TEMP1 ;Save Number of Bytes
|
||
|
TAX ;Move logical file number to X register
|
||
|
JSR $FFC6 ;Call Kernal Routine CHKIN
|
||
|
FREADE: BCS FGETCW ;If Error, Write to Table and Return in Y
|
||
|
LDY #0 ;Initialize Index
|
||
|
STY TEMP3 ;and Save It
|
||
|
FREADL: JSR $FFCF ;Call Kernal Routine CHRIN
|
||
|
JSR FSRDST ;Get I/O Status in Y Register
|
||
|
BCS FREADX ;If No Error
|
||
|
LDY TEMP3 ; Retrieve Index
|
||
|
LDX TEMP2 ; Get Mode
|
||
|
BNE FREADN ; If READ
|
||
|
STA (DSTLO),Y ; Store Character in String
|
||
|
FREADN: INY ; Increment Pointer
|
||
|
STY TEMP3 ; and Save It
|
||
|
BVS FREADS ; If Not EOF
|
||
|
CPY TEMP1 ; Compare against Count
|
||
|
BNE FREADL ; and Loop if Less
|
||
|
FREADS: LDY #0 ; Set Error to None
|
||
|
FREADX: JSR $FFCC ;Call Kernal Routine CLRCHN
|
||
|
CLC ;Clear Carry
|
||
|
TYA ;Copy Error Code to Accumulator
|
||
|
ADC #$FF ;Set Carry if Error
|
||
|
LDA TEMP3 ;Return Length of String
|
||
|
RTS
|
||
|
|
||
|
;fputc(lfn, chr) - Write character from file
|
||
|
;Args: A = Logical file number
|
||
|
; Y = Character to Write
|
||
|
;Returns: A = Character (0 if Error)
|
||
|
; Y = Error Code (0=None)
|
||
|
FPUTC: TAX ;Move LFN to X register
|
||
|
JSR $FFC9 ;Call Kernal Routine CHKOUT
|
||
|
BCS FREADE ;If Error, Write to Table and Return in Y
|
||
|
TYA ;Copy Character to Accumulator
|
||
|
FPUTCO: JSR $FFD2 ;Call Kernal Routine CHROUT
|
||
|
JMP FGETCC ;Clear Channel and Check STATUS
|
||
|
|
||
|
;fputln(lfn, &s) - Write Line to File
|
||
|
;Args: A = Logical file number
|
||
|
; Y,X = Pointer to String
|
||
|
;Sets: SRCLO,SRCHI = Pointer to String
|
||
|
;Affects: X,Y
|
||
|
;Returns: A = Number of bytes written
|
||
|
; Y = Error Code (0=None)
|
||
|
FPUTLN: ORA #$80 ;Set High Bit and Fall Through
|
||
|
|
||
|
;fputs(lfn, &s) - Write String to File
|
||
|
;Args: A = Logical file number
|
||
|
; Y,X = Pointer to String
|
||
|
;Sets: SRCLO,SRCHI = Pointer to String
|
||
|
;Affects: X,Y
|
||
|
;Returns: A = Number of bytes written
|
||
|
; Y = Error Code (0=None)
|
||
|
FPUTS: JSR SETSRC ;Save string address & initialize pointer
|
||
|
FPUTSA: STA TEMP2 ;Save LFN Argument
|
||
|
AND #$7F ;Strip High Bit
|
||
|
TAX ;Copy LFN to X Register
|
||
|
JSR $FFC9 ;Call Kernal Routine CHKOUT
|
||
|
BCS FREADE ;If Error, Write to Table and Return in Y
|
||
|
LDY #0 ;Initialize Index
|
||
|
STY TEMP3 ;and Save It
|
||
|
FPUTSL: LDA (SRCLO),Y ;Load next character
|
||
|
BEQ FPUTSX ;If NUL, Finish Up
|
||
|
JSR $FFD2 ;Call Kernal Routine CHROUT
|
||
|
STY TEMP3 ;Save Index
|
||
|
JSR FSRDST ;Read I/O Status
|
||
|
BCS FREADX ;If Error, Return in Y
|
||
|
LDY TEMP3 ;Restore Index
|
||
|
INY ;Increment Index
|
||
|
BPL FPUTSL ;Loop if Less than 128
|
||
|
BMI FREADS ;Else Finish Up
|
||
|
FPUTSX: LDA TEMP2 ;Retrieve LFN Argument
|
||
|
BPL FREADS ;Finish Up if High Bit Not Set
|
||
|
INY ;Else Increment Count
|
||
|
LDA #$0D ;Load Carriage Return
|
||
|
BNE FPUTCO ;and Write It
|
||
|
|
||
|
FSKIP: LDX #$FF ;Set Mode to Skip
|
||
|
BNE FREADA ;and Execute FREAD
|
||
|
|
||
|
;fwrite(lfn, count) - Write bytes from file
|
||
|
;Requires: SRCLO, SRCHI - Pointer to destination string
|
||
|
;Args: A = Logical File Number
|
||
|
; Y = Number of Bytes to Write
|
||
|
;Affects: X
|
||
|
;Returns: A = Number of bytes read
|
||
|
; Y = Error Code (0=None)
|
||
|
FWRITE: STY TEMP1 ;Save Number of Bytes
|
||
|
TAX ;Move logical file number to X register
|
||
|
JSR $FFC9 ;Call Kernal Routine CHKOUT
|
||
|
BCS FREADE ;If Error, Return in Y (FSERRY)
|
||
|
LDY #0 ;Initialize Index
|
||
|
STY TEMP3 ;and Save It
|
||
|
FWRITL: LDA (SRCLO),Y ;Load next character
|
||
|
JSR $FFD2 ;Call Kernal Routine CHROUT
|
||
|
JSR FSRDST ;Read I/O Status
|
||
|
BCS FREADX ;If Error, Return In Y
|
||
|
INC TEMP3 ;Increment Index
|
||
|
LDY TEMP3 ;and Load it Index
|
||
|
CPY TEMP1 ;Compare against Count
|
||
|
BNE FWRITL ;and Loop if Less
|
||
|
BEQ FREADS ;Else Return No Error
|
||
|
|
||
|
;fgetw(lfn) - Read Word from File
|
||
|
;Args: A = Logical file number
|
||
|
;Sets: TEMP0 = Logical File Number
|
||
|
; TEMP1 = LSB
|
||
|
; TEMP2 = MSB
|
||
|
;Returns: A = Error Code (0=None)
|
||
|
; Y,X = Word (MSB, LSB)
|
||
|
FGETW: STA TEMP0 ;Save LFN
|
||
|
FGETWA: LDA TEMP0 ;Load LFN (Alternate Entry Point)
|
||
|
JSR FGETC ;Read LSB
|
||
|
BCS FGETWX ;If No Error
|
||
|
STA TEMP1 ; Save in TEMP1
|
||
|
LDA TEMP1 ; Restore LFN
|
||
|
JSR FGETC ; Read MSB
|
||
|
STA TEMP2 ; Save in TEMP2
|
||
|
FGETWX: TYA ;Copy Error to A
|
||
|
JSR RESRXY ;Load Word into Y,X
|
||
|
ORA #0 ;Set Flags
|
||
|
RTS
|
||
|
|