1
0
mirror of https://github.com/RevCurtisP/C02.git synced 2024-06-01 05:41:34 +00:00
C02/include/run6502/fileio.a02
2020-10-14 10:59:25 -04:00

350 lines
13 KiB
Plaintext

; C02 Module fileio Assembly Language Eoutines for run6502 emulator
; This is the reference implementation of the fileo module
; The run6502 program has been customized with an emulated file command
; routine at the address set with the -F command line option.
; The file routine is JSRed with the command in A, and any parameters
; in Y and/or X. After command execution. Y and/or X will contain any
; return values, with Y is usually the error code.
;
; The Command Routine FSCMD is defines in file include/run6502.a02
SUBROUTINE FILEIO
DRIVES EQU 26 ;Number of Disk Drives
DRIVE BYTE "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;Disk Drive Letters
DISKS EQU 1 ;Number of Disks in Drive
DISK BYTE 0
;File Open Modes
MREAD EQU $00 ;Open for Read
MWRITE EQU $40 ;Open for Write
MAPPND EQU $80 ;Open for Append
MRECRD EQU $C0 ;Record Oriented File
;File Open Types
TTEXT EQU $00 ;Open as Texy File
TBNRY EQU $20 ;Open as Binary File
; File Load Modes
MRELCT EQU $00 ;Relocate (Load at Specified Address)
MABSLT EQU $80 ;Absolute (Load at Address in File Header)
;ferror(chan, &msg) - Check for Error
;Args: A = Channel Number
; Y,X = String Address
;Returns: A = Last Error ($FF - Invalid Channel)
; Y = Error (0=None)
FERROR: JSR FSADDR ;Set Buffer Address
TAY ;Set Channel Number
LDA #'Y' ;Set Command to FERROR
BNE .FEXECX ;Execute and Return Result in A
;fflush(chan) - Flush Write Buffer to File
;Args: A = Channel
;Returns: A = Status (0=Success, $FF = Failure)
; Y = Error (0=None)
FFLUSH: TAY ;Set Channel Number
LDA #'F' ;Set Command to FLUSH
BNE .FEXECX ;Execute and Return Result in A
;fopen(mode, &name) - Open File
;Setup: Call FSRECS with Record Size if Mode is MRECRD
;Args: A = File Mode | Drive ID
; Y,X = Pointer to File Name
;Returns: A = File Channel (0=File Not Opened)
; Y = Error (0=None)
FOPEN: JSR FSNAME ;Set Filename
.FOPEN TAX ;Pass File Mode to X
JSR FSDRVN ;Convert Drive Letter to Drive Number
BCS .FOPERR ;If Error, Return Carry Set
TAY ;Pass Drive Number in Y
CLC ;Set Mode to FOPEN
LDA #'O' ;Set Command to OPEN
.FEXECX JSR FSCMD ;Execute Command
TXA ;Return Channel in A
.FOPERR RTS
;fclose(chan) - Close File
;Args: A = Channel Number
;Returns: A = Error (0=None)
FCLOSE: TAY ;Set Channel
CLC ;Set Mode to FCLOSE
LDA #'C' ;Set Command to CLOSE
.FEXECY JSR FSCMD ;Execute Command
TYA ;Return Errno
RTS
;feof(chan) - Check for End of File
;Args: A = Channel Number
;Returns: A = $00 - Not End of File
; $FF - End of File
; Otherwise, Error Code
FEOF: TAY ;Set Channel
LDA #'E' ;Set Command to EOF
BNE .FEXECY ;Execute and Return Errno
;fgetc(chan) - Read Character from File
;Args: A = Channel Number
;Returns: A = Character
; Y = Error Code ($00 - Success)
FGETC: TAY ;Set Channel
LDA #'G' ;Set Command to GET
BNE .FEXECX ;Execute and Return Result
;fgets(chan, &s) - Read String from File
;Args: A = Channel Number
; Y,X = Address of String
;Returns: A = Number of Bytes Read
; Y = Error Code ($00 - Success)
FGETS: JSR FSADDR ;Set String Address
TAY ;Set Channel Number
LDA #'H' ;Set Command to GETS
BNE .FEXECX ;Execute and Return Result in A
;fgetr(chan, recno) - Read Record from File
;Setup: Call FSADDR with buffer address
;Args: A = Channel Number
; Y,X = Record Number
;Returns: A = Error Code
; Y,X = Next Record Number
FGETR: JSR FSINDX ;Set Record Number
TAY ;Set Channel Number
SEC ;Set Mode to RECORD
LDA #'R' ;Set Command to READ
BNE .FSCMD ;Execute Command and Return
;fgetw(chan) - Read Word from File
;Args: A = Channel Number
;Returns: A = Error Code ($00 - Success)
; Y,X = Word
FGETW: TAY ;Set Channel
CLC ;Set Mode to Get
LDA #'J' ;Set Command to GET
BNE .FSCMD ;Execute Command and Return
;fputc(chan, char) - Write Character to File
;Args: A = Character to Write
; Y = Channel Number
;Returns: A = Error Code ($00 - Success)
FPUTC: TAX ;Set Character to Write
LDA #'P' ;Set Command to PUT
BNE .FEXECX ;Execute and Return Result in A
;fputln(chan, &s) - Write String to File with Newline
;Args: A = Channel Number
; Y,X = Address of String
;Returns: A = Number of Characters Written
; Y = Error Code ($00 - Success)
FPUTLN: SEC ;Append Newline
BCS .FPUTSA ;Write String to File
;fputr(chan, recno) - Write Record from File
;Setup: Call FSADDR with buffer address
;Args: A = Channel Number
; Y,X = Record Number
;Returns: A = Error Code
; Y,X = Next Record Number
FPUTR: JSR FSINDX ;Set Record Number
TAY ;Set Channel Number
SEC ;Set Mode to RECORD
LDA #'W' ;Set Command to READ
BNE .FSCMD ;Execute Command and Return
;fputs(chan, &s) - Write String to File
;Args: A = Channel Number
; Y,X = Address of String
;Returns: A = Number of Characters Written
; Y = Error Code ($00 - Success)
FPUTS: CLC ;Do Not Append Newline
.FPUTSA JSR FSADDR ;Set File Buffer Address
TAY ;Set Channel
LDA #'Q' ;Set Command to PUTS
BNE .FEXECX ;Execute and Return Result in A
;fputw(chan, word) - Write Word to File
;Args: A = Channel Number
; Y,X = Word
;Returns: A = Error Code ($00 - Success)
FPUTW: JSR FSADDR ;Set File Buffer Address
TAY ;Set Channel
SEC ;Set Mode to PUT
LDA #'J' ;Set Command to WORD
BNE .FEXECY ;Execute and Return Result in A
;fread(count, chan) - Read Bytes from File
;Setup: Call FSADDR with array address
;Args: A = Number of Bytes to Read
; Y = Channel Number
;Returns: A = Number of Bytes Read
; Y = Error Code ($00 - Success)
FREAD: TAX ;Set Number of Bytes to Write
CLC ;Set Mode to BYTES
LDA #'R' ;Set Command to READ
BNE .FEXECX ;Execute and Return Result in A
;rewind(chan) - Move to Beginning of File
;Args: A = Channel Number
;Returns: A = Error Code ($00 - Success)
REWIND: LDX #0 ;Set Position to $0000
LDY #0 ;and Fall Through to FSEEK
;fseek(chan, pos) - Move to Position in File
;Args: A = Channel Number
; Y,X = Position
;Returns: A = Error Code ($00 = Success)
FSEEK: JSR FSINDX ;Set File Index to Position`
TAY ;Set Channel to A
CLC ;Set Mode to SEEK
LDA #'Z' ;Set Command to SEEK
BNE .FEXECY ;Execute and Return Errno
;ftell(chan, pos) - Get Position in File
;Args: A = Channel Number
;Returns: A = Error Code ($00 = Success)
; Y,X = Position in File ($FFFF = Failure)
FTELL: JSR FSADDR ;Set File Address to Position`
TAY ;Set Channel to A
SEC ;Set Mode to TELL
LDA #'Z' ;Set Command to SEEK
BNE .FSCMD ;Execute Command and Return
;fwrite(count cban) - Write Bytes to File
;Setup: Call FSADDR with array address
;Args: A = Number of Bytes to Write
; Y = Channel Number
;Returns: A = Number of Bytes Written
; Y = Error Code ($00 - Success)
FWRITE: TAX ;Set Number of Bytes to Write
LDA #'W' ;Set Command to WRITE
BNE .FEXECX ;Execute and Return Result in A
;fload(name) - Load File into Memory
;Setup: Call FSNAME with filename address
; Call FSADDR with start address
;Args: A = Option + DriveID
; Y,X = End Address
;Returns: A = Error Code ($00 - Success)
; X,Y = Load Address
FLOAD: CMP #MABSLT ;Check Load Mode
BNE .ERR22 ;If Invalid, Return Error
LDA #'L' ;Set Command to LOAD
BNE .FSCMD ;Execute Command and Return
.ERR22 LDA #22
RTS
;fsave(name) - Save File from Memory
;Setup: Call FSNAME with filename address
; Call FSADDR with start address
;Args: A = Option + DriveID
; Y,X = End Address
;Returns: A = Error Code ($00 - Success)
FSAVE: ORA $0 ;If Not Drive 0
BNE .ERR22 ;Return Error
LDA #'S' ;Set Command to SAVE
BNE .FSCMD ;Execute Command and Return
;File System Commands
;Convert Drive Letter Into Drive Number
;Drive letters A-Z in DOS map to drive numbers 1-26
;A drice specifier of NULL - SPACE or @ maps to drive 0, which
;means the current drive in the run6502 File Command Processor.
;Args: A = Drive Letter
;Returns: A = Drive Number
; Carry Clear = Valid Drive Number
; Carry Set = Invalid Drive Number
FSDRVN: SEC
SBC #' ' ;If Drive Specifier
BCS .FSDRVL ;is NULL through SPACE
LDA #0 ; Return Drive Number 0
RTS ; and Carry Clear
.FSDRVL AND #$1F ;Convert A-Z, a-z to 1-26
CMP #DRIVES+2 ;If Drive Number is
BCC .RETURN ;greater than 26
LDA #$FF ; Return Operation Failed
LDY #1 ; and Error - Invalid Argument
.RETURN RTS
;fsinit() - Initialize File System
FSINIT: LDA #'I' ;Set Command to INITFS
.FSCMD JMP FSCMD ;Execute Command and Return
;fsrecs(size) - Set File Record Size
;Args: A = Size
FSRECS: TAX ;Set Y.X to 0,A
LDY #0 ;and Fall The to FSINDX
;fsindx(&array) - Set File Record Number
;Args: Y,X = Record Number
FSINDX: PHP ;Save Status Register
PHA ;Save Accumulator
SEC ;Set Mode to FILEINDX
BCS .FSADDR ;Execute ADDRESS and Restore Accumulator
;fsaddr(&array) - Set File Buffer Address
;Args: Y,X = Address of String or Array
FSADDR: PHP ;Save Status Register
PHA ;Save Accumulator
CLC ;Set mode to FILEADDR
.FSADDR LDA #'A' ;Set Command to ADDRESS
JSR FSCMD ;Execute command
PLA ;Restore Accumulator
PLP ;Restore Status Register
RTS
;fsbuff(&name) - Set File Buffer
;Args: Y,X = Address of String
FSBUFF: PHA ;Save Accumulator
PHP ;Save Status Register
SEC ;Set Mode to FILEBUFF
BCS .SETNAM ;Execute Command 'N' and Return
;fsname(&name) - Set File Name
;Args: Y,X = Address of Filename
FSNAME: PHA ;Save Accumulator
PHP ;Save Status Register
CLC ;Set Mode to FILENAME
.SETNAM LDA #'N' ;Set command to name
.FSCMDA JSR FSCMD ;Execute command
PLP ;Restore Status Register
PLA ;Restore Accumulator
RTS
; Command Description Arguments Returns
; FSADDR Set Buffer Address A='A',YX=Addr YX=Addr
; FCLOSE Close File A='C',Y=Chan,CC Y=Err
; CLOSEDIR Close Directory A='C',Y=Chan,CS Y=Err
; READDIR Read Dir Entry A='D',Y=Chan (1) Y=Err
; FEOF Check for EOF A="E',Y=Chan Y=Err ($FF=EOF)
; FFLUSH Flush Output A='F',Y=Chan Y=Err
; FGETC Get Character A='G',Y=Chan Y=Err, X=Char
; FGETS Get String A='H',Y=Chan (1) Y=Err
; FSINIT Init File System A='I',
; REMOVE Remove File A='K',YX=Name Err
; FLOAD Load File A='L' (3) A=Err, YX=End
; RENAME Rename File A='M',YX=New (2) Y=Err
; FSNAME Set Filename A='N',YX=Name,CC
; FOPEN Open File A='O',Y=Mode|Drive,CC (2) Y=Err, X=Chan
; OPENDIR Open Directory A='O',Y=Drive,CS (2) Y=Err, X=Chan
; FPUTC Put Character A='P',Y=Chan,X=Char Y=Err, X=Char
; FPUTS Put String A='Q',Y=Chan (1) Y=Err
; FREAD Read Bytes A='R',Y=Chan,X=Count (1) Y=Err, X=Count
; FSAVE Save File A='S',Y=Chan,YX=End (3) Y=Err
; GETCWD Get Current Dir A='U',Y=Drive (1) Y=Err, X=Len
; CHDIR Change Directory A='U',Y=Drive (2) Y=Err
; GETDRV Get Current Drive A='V',CC Y=Err, X=Result
; CHDRV Set Current Drive A='V',Y=Drive,CS Y=Err, X=Result
; FWRITE Write Bytes A='W',Y=Chan, X=Count (1) Y=Err, X=Count
; MKDIR Create Directory A='X',Y=Drive,CC (2) Y=Err, X=Result
; RMDIR Remove Directory A='X',Y=Drive,CS (2) Y=Err, X=Result
; FERROR Get Last Error A='Y',Y=Chan (1) Y=Err
; (1) Requires call to FSADDR
; (2) Requires call to FSNAME (and FSINDX for FOPEN w/MRECRD)
; (3) Requires calls to FSADDR and FSNAME