;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 ;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 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 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