Applecorn/mainmem.svc.s
2021-09-23 12:59:36 -04:00

1145 lines
39 KiB
ArmAsm

* MAINMEM.SVC.S
* (c) Bobbi 2021 GPLv3
*
* Main memory entry points called by Applecorn MOS running in
* aux memory. Each entry point performs some ProDOS service,
* then returns to aux memory.
* TO DO: All OSFILE calls combined and dispatch in here
* All start with PREPATH, UPDFB, COPYFB then branch
* to relevent routine.
INFOFILE >>> ENTMAIN
JSR PREPATH ; Preprocess path
JSR UPDFB ; Update FILEBLK
JSR COPYFB ; Copy back to aux mem
>>> XF2AUX,OSFILERET
* ProDOS file handling to delete a file
* Called by AppleMOS OSFILE
* Return A=0 no object, A=1 file deleted, A=2 dir deleted
* A>$1F ProDOS error
DELFILE >>> ENTMAIN
JSR PREPATH ; Preprocess pathname
JSR UPDFB ; Update FILEBLK
JSR COPYFB ; Copy back to aux mem
PHA ; Save object type
JSR DODELETE
BCC :DELETED
PLX ; Drop object
JSR CHKNOTFND
PHA
:DELETED PLA ; Get object back
:EXIT >>> XF2AUX,OSFILERET
DODELETE LDA #<MOSFILE ; Attempt to destroy file
STA DESTPL+1
LDA #>MOSFILE
STA DESTPL+2
JSR MLI
DB DESTCMD
DW DESTPL
RTS
* ProDOS file handling to create a directory
* Invoked by AppleMOS OSFILE
* Return A=02 on success (ie: 'directory')
* A>$1F ProDOS error, translated by OSFILE handler
MAKEDIR >>> ENTMAIN
JSR PREPATH ; Preprocess pathname
JSR UPDFB ; Update FILEBLK
JSR COPYFB ; Copy back to aux mem
CMP #$02
BEQ :EXIT ; Dir already exists
LDA #$0D ; 'Directory'
STA CREATEPL+7 ; ->Storage type
LDA #$0F ; 'Directory'
STA CREATEPL+4 ; ->File type
STZ CREATEPL+5 ; Aux type LSB
STZ CREATEPL+6 ; Aux type MSB
LDA #$C3 ; Default permissions
STA CREATEPL+3
JSR CRTFILE ; Create MOSFILE
BCS :EXIT ; Failed, exit with ProDOS result
JSR UPDFB ; Update FILEBLK
JSR COPYFB ; Copy FILEBLK to aux mem
LDA #$02 ; Success, $02=dir created
:EXIT >>> XF2AUX,OSFILERET
* ProDOS file handling to rename a file
RENFILE >>> ENTMAIN
JSR PREPATH ; Preprocess arg1
JSR MFtoTMP ; Stash arg1
JSR COPYMF21 ; Copy arg2
JSR PREPATH ; Preprocess arg2
JSR COPYMF12 ; Put it back in MOSFILE2
JSR TMPtoMF ; Recover arg1->MOSFILE
LDA #<MOSFILE
STA RENPL+1
LDA #>MOSFILE
STA RENPL+2
LDA #<MOSFILE2
STA RENPL+3
LDA #>MOSFILE2
STA RENPL+4
JSR MLI
DB RENCMD
DW RENPL
>>> XF2AUX,RENRET
* ProDOS file handling for file copying
* Returns with ProDOS error code in A
COPYFILE >>> ENTMAIN
JSR MFtoTMP ; Swap MOSFILE & MOSFILE2
JSR COPYMF21
JSR TMPtoMF2
JSR PREPATH ; Preprocess arg2 (in MOSFILE)
JSR WILDONE ; Handle any wildcards
JSR EXISTS ; See if destination exists
STA :DESTTYPE ; Stash for later
JSR MFtoTMP ; Swap MOSFILE & MOSFILE2 again
JSR COPYMF21
JSR TMPtoMF2
JSR PREPATH ; Preprocess arg1
SEC ; Force wildcard lookup
JSR WILDCARD ; Handle any wildcards in arg1
BCS :NONE
JSR HASWILD
BCC :MAINLOOP ; No wildcards in final segment
LDA :DESTTYPE ; Wildcards, check dest type
CMP #$02 ; Existing directory?
BNE :BADDEST ; If not, error
BRA :MAINLOOP ; Source: wildcard, dest: dir
:NOWILD
:MAINLOOP
LDA MOSFILE2 ; Length
STA :OLDLEN
JSR EXISTS ; See if source is file or dir
CMP #$02 ; Directory
BEQ :SKIP ; Skip directories
LDA :DESTTYPE ; Check dest type
CMP #$02 ; Existing directory?
BNE :NOTDIR
LDY MOSFILE2 ; Dest idx = length
LDA MOSFILE2,Y ; Get last char
CMP #'/' ; Is it slash?
BEQ :HASSLSH
LDA #'/' ; Add a '/' separator
STA MOSFILE2+1,Y
INY
:HASSLSH LDX #$00 ; Source id
:APPLOOP CPX MATCHBUF ; At end?
BEQ :DONEAPP
LDA MATCHBUF+1,X ; Appending MATCHBUF to MOSFILE2
STA MOSFILE2+1,Y
INX
INY
BRA :APPLOOP
:DONEAPP STY MOSFILE2 ; Update length
:NOTDIR LDA :DESTTYPE ; Recover destination type
JSR COPY1FILE ; Copy an individual file
BCS :COPYERR
:SKIP JSR WILDNEXT
BCS :NOMORE
LDA :OLDLEN ; Restore MOSFILE2
STA MOSFILE2
BRA :MAINLOOP
JSR CLSDIR
:EXIT >>> XF2AUX,COPYRET
:NONE JSR CLSDIR
LDA #$46 ; 'File not found'
BRA :EXIT
:BADDEST JSR CLSDIR
LDA #$FD ; 'Wildcards' error
BRA :EXIT
:NOMORE JSR CLSDIR
LDA #$00
BRA :EXIT
:COPYERR PHA
JSR CLSDIR
PLA
BRA :EXIT
:DESTTYPE DB $00
:OLDLEN DB $00
* Copy a single file
* Source is in MOSFILE, DEST in MOSFILE2
* Returns with carry set if error, carry clear otherwise
* Returns with ProDOS error code in A
* Buffer COPYBUF is used for the file copy, to avoid trashing
* directory block in RDBUF (when doing wilcard search)
COPY1FILE LDA #<MOSFILE
STA GINFOPL+1
STA OPENPL2+1
LDA #>MOSFILE
STA GINFOPL+2
STA OPENPL2+2
JSR GETINFO ; GET_FILE_INFO
BCS :ERR
LDA #<MOSFILE2
STA GINFOPL+1
STA DESTPL+1
LDA #>MOSFILE2
STA GINFOPL+2
STA DESTPL+2
JSR MLI ; DESTROY
DB DESTCMD
DW DESTPL
LDA #$07 ; Fix num parms in PL
STA GINFOPL
LDA #$C3 ; Default permissions
STA GINFOPL+3
JSR MLI ; Call CREATE with ..
DB CREATCMD ; .. PL from GET_FILE_INFO
DW GINFOPL
LDX #$0A ; Num parms back as we found it
STX GINFOPL
BCS :ERR ; Error creating dest file
LDA #$00 ; Look for empty slot
JSR FINDBUF
STX :BUFIDX1
JSR BUFADDR
BCS :ERR ; No I/O bufs available
STA OPENPL2+3
STY OPENPL2+4
JSR MLI
DB OPENCMD
DW OPENPL2
BCS :ERR ; Open error
BRA :S1
:ERR SEC ; Report error
RTS
:S1 LDA OPENPL2+5 ; File ref num
STA RDPLCP+1
LDX :BUFIDX1
STA FILEREFS,X ; Record the ref number
LDA #<MOSFILE2
STA OPENPL2+1
LDA #>MOSFILE2
STA OPENPL2+2
LDA #$00 ; Look for empty slot
JSR FINDBUF
STX :BUFIDX2
JSR BUFADDR
BCS :ERRCLS1 ; No I/O bufs available
STA OPENPL2+3
STY OPENPL2+4
JSR MLI
DB OPENCMD
DW OPENPL2
BCS :ERRCLS1
LDA OPENPL2+5 ; File ref num
STA WRTPLCP+1
LDX :BUFIDX2
STA FILEREFS,X ; Record the ref number
:MAINLOOP JSR MLI ; Read a block
DB READCMD
DW RDPLCP
BCC :RDOKAY
CMP #$4C ; Is it EOF?
BEQ :EOFEXIT
BRA :ERRCLS2 ; Any other error
:RDOKAY LDA RDPLCP+6 ; Trans count MSB
STA WRTPLCP+4 ; Request count MSB
LDA RDPLCP+7 ; Trans count MSB
STA WRTPLCP+5 ; Request count MSB
JSR MLI ; Write a block
DB WRITECMD
DW WRTPLCP
BCS :ERRCLS2 ; Write error
BRA :MAINLOOP
:EOFEXIT CLC ; No error
PHP
LDA #$00
PHA
:CLOSE2 LDA WRTPLCP+1 ; Close output file
STA CLSPL+1
JSR CLSFILE
LDX :BUFIDX2
STZ FILEREFS,X
:CLOSE1 LDA RDPLCP+1 ; Close input file
STA CLSPL+1
JSR CLSFILE
LDX :BUFIDX1
STZ FILEREFS,X
PLA
PLP
RTS
:ERRCLS1 SEC
PHP
PHA
BRA :CLOSE1
:ERRCLS2 SEC
PHP
PHA
BRA :CLOSE2
:BUFIDX1 DB $00
:BUFIDX2 DB $00
* ProDOS file handling for MOS OSFIND OPEN call
* Options in A: $40 'r', $80 'w', $C0 'rw'
OFILE >>> ENTMAIN
PHA ; Preserve arg for later
JSR PREPATH ; Preprocess pathname
PLA
PHA
CMP #$80 ; Is it "w"?
BEQ :NOWILD ; If so, no wildcards
JSR WILDONE ; Handle any wildcards
:NOWILD JSR EXISTS ; See if file exists ...
CMP #$02 ; ... and is a directory
BNE :NOTDIR
JMP :NOTFND ; Bail out if directory
:NOTDIR PLA
PHA
CMP #$80 ; Write mode
BNE :S1
JSR DODELETE
LDA #$01 ; Storage type - file
STA CREATEPL+7
LDA #$06 ; Filetype BIN
STA CREATEPL+4
LDA #<MOSFILE
STA OPENPL+1
LDA #>MOSFILE
STA OPENPL+2
LDA #$00 ; Auxtype
STA CREATEPL+5
LDA #$00
STA CREATEPL+6
LDA #$C3 ; Default permissions
STA CREATEPL+3
JSR CRTFILE ; Create MOSFILE
:S1 LDA #$00 ; Look for empty slot
JSR FINDBUF
STX BUFIDX
JSR BUFADDR
BCS :NOTFND
STA OPENPL2+3
STY OPENPL2+4
LDA #<MOSFILE
STA OPENPL2+1
LDA #>MOSFILE
STA OPENPL2+2
JSR MLI
DB OPENCMD
DW OPENPL2
BCS :NOTFND
LDA OPENPL2+5 ; File ref number
LDX BUFIDX
CPX #$FF
BEQ FINDEXIT
STA FILEREFS,X ; Record the ref number
BRA FINDEXIT
:NOTFND LDA #$00
FINDEXIT >>> XF2AUX,OSFINDRET
BUFIDX DB $00
* ProDOS file handling for MOS OSFIND CLOSE call
CFILE >>> ENTMAIN
LDA MOSFILE ; File ref number
STA CLSPL+1
JSR CLSFILE
LDA MOSFILE
JSR FINDBUF
BCS :S1
LDA #$00
STA FILEREFS,X
:S1 JMP FINDEXIT
* ProDOS file handling for MOS OSBGET call
* Returns with char read in A and error num in Y (or 0)
FILEGET >>> ENTMAIN
LDA MOSFILE ; File ref number
STA READPL2+1
JSR MLI
DB READCMD
DW READPL2
BCC :NOERR
TAY ; Error number in Y
BRA :EXIT
:NOERR LDY #$00
LDA BLKBUF
:EXIT >>> XF2AUX,OSBGETRET
* ProDOS file handling for MOS OSBPUT call
* Enters with char to write in A
FILEPUT >>> ENTMAIN
STA BLKBUF ; Char to write
LDA MOSFILE ; File ref number
STA WRITEPL+1
LDA #$01 ; Bytes to write
STA WRITEPL+4
LDA #$00
STA WRITEPL+5
JSR WRTFILE
>>> XF2AUX,OSBPUTRET
* ProDOS file handling for OSBYTE $7F EOF
* Returns EOF status in A ($FF for EOF, $00 otherwise)
FILEEOF >>> ENTMAIN
LDA MOSFILE ; File ref number
STA GEOFPL+1
STA GMARKPL+1
JSR MLI
DB GEOFCMD
DW GEOFPL
BCS :ISEOF ; If error, just say EOF
JSR MLI
DB GMARKCMD
DW GMARKPL
BCS :ISEOF ; If error, just say EOF
LDA GEOFPL+2 ; Subtract Mark from EOF
SEC
SBC GMARKPL+2
STA :REMAIN
LDA GEOFPL+3
SBC GMARKPL+3
STA :REMAIN+1
LDA GEOFPL+4
SBC GMARKPL+4
STA :REMAIN+2
LDA :REMAIN ; Check bytes remaining
BNE :NOTEOF
LDA :REMAIN+1
BNE :NOTEOF
LDA :REMAIN+2
BNE :NOTEOF
:ISEOF LDA #$FF
BRA :EXIT
:NOTEOF LDA #$00
:EXIT >>> XF2AUX,CHKEOFRET
:REMAIN DS 3 ; Remaining bytes
* ProDOS file handling for OSARGS flush commands
FLUSH >>> ENTMAIN
LDA MOSFILE ; File ref number
STA FLSHPL+1
JSR MLI
DB FLSHCMD
DW FLSHPL
>>> XF2AUX,OSARGSRET
* ProDOS file handling for OSARGS set ptr command
SEEK >>> ENTMAIN
LDA MOSFILE ; File ref number
STA GMARKPL+1 ; GET_MARK has same params
LDA MOSFILE+2 ; Desired offset in MOSFILE[2..4]
STA GMARKPL+2
LDA MOSFILE+3
STA GMARKPL+3
LDA MOSFILE+4
STA GMARKPL+4
JSR MLI
DB SMARKCMD
DW GMARKPL
>>> XF2AUX,OSARGSRET
* ProDOS file handling for OSARGS get ptr command
* and for OSARGs get length command
TELL >>> ENTMAIN
LDA MOSFILE ; File ref number
STA GMARKPL+1
LDA MOSFILE+2 ; Mode (0=pos, otherwise len)
CMP #$00
BEQ :POS
JSR MLI
DB GEOFCMD
DW GMARKPL ; MARK parms same as EOF parms
BRA :S1
:POS JSR MLI
DB GMARKCMD
DW GMARKPL
:S1 LDX MOSFILE+1 ; Pointer to ZP control block
BCS :ERR
>>> ALTZP ; Alt ZP & Alt LC on
LDA GMARKPL+2
STA $00,X
LDA GMARKPL+3
STA $01,X
LDA GMARKPL+4
STA $02,X
STZ $03,X
>>> MAINZP ; Alt ZP off, ROM back in
:EXIT >>> XF2AUX,OSARGSRET
:ERR LDX MOSFILE+1 ; Address of ZP control block
>>> ALTZP ; Alt ZP & Alt LC on
STZ $00,X
STZ $01,X
STZ $02,X
STZ $03,X
>>> MAINZP ; Alt ZP off, ROM back in
BRA :EXIT
* ProDOS file handling for MOS OSFILE LOAD call
* Invoked by AppleMOS OSFILE
* Return A=01 if successful (meaning 'file')
* A>$1F ProDOS error, translated by FILERET
LOADFILE >>> ENTMAIN
JSR PREPATH ; Preprocess pathname
JSR WILDONE ; Handle any wildcards
JSR EXISTS ; See if it exists ...
CMP #$01 ; ... and is a file
BEQ :ISFILE
JMP :NOTFND
:ISFILE STZ :BLOCKS
LDA #<MOSFILE
STA OPENPL+1
LDA #>MOSFILE
STA OPENPL+2
JSR OPENFILE
BCS :NOTFND ; File not found
:L1 LDA OPENPL+5 ; File ref number
STA READPL+1
JSR RDFILE
BCC :S1
CMP #$4C ; EOF
BEQ :EOF
BRA :READERR
:S1 LDA #<BLKBUF
STA A1L
LDA #>BLKBUF
STA A1H
CLC
LDA #<BLKBUF
ADC READPL+6 ; LSB of trans count
STA A2L
LDA #>BLKBUF
ADC READPL+7 ; MSB of trans count
STA A2H
LDA FBEXEC ; If FBEXEC is zero, use addr
CMP #$00 ; in the control block
BEQ :CBADDR
LDA #<MOSFILE ; Otherwise use file addr
STA GINFOPL+1
LDA #>MOSFILE
STA GINFOPL+2
JSR GETINFO ; GET_FILE_INFO
BCS :READERR
LDA GINFOPL+5 ; Aux type LSB
STA FBLOAD+0
LDA GINFOPL+6 ; Aux type MSB
STA FBLOAD+1
:CBADDR LDA FBLOAD
STA A4L
STA FBEXEC ; EXEC = LOAD
LDA FBLOAD+1
STA A4H
STA FBEXEC+1
LDX :BLOCKS
:L2 CPX #$00
BEQ :S2
INC
INC
DEX
BRA :L2
:S2 STA A4H
SEC ; Main -> AUX
JSR AUXMOVE
INC :BLOCKS
BRA :L1
:NOTFND LDA #$46 ; Nothing found
PHA
BRA :EXIT
:READERR LDA #$5D ; Read error
PHA
BRA :EOF2
:EOF LDA #$01 ; Success ('File')
PHA
:EOF2 LDA OPENPL+5 ; File ref num
STA CLSPL+1
JSR CLSFILE
:EXIT JSR UPDFB ; Update FILEBLK
JSR COPYFB ; Copy FILEBLK to auxmem
PLA ; Get return code back
>>> XF2AUX,OSFILERET
:BLOCKS DB $00
* ProDOS file handling for MOS OSFILE SAVE call
* Invoked by AppleMOS OSFILE
* Return A=01 if successful (ie: 'file')
* A>$1F ProDOS error translated by FILERET
SAVEFILE >>> ENTMAIN
JSR PREPATH ; Preprocess pathname
JSR EXISTS ; See if file exists ...
CMP #$02 ; ... and is a directory
BNE :NOTDIR
LDA $41 ; Dir exists, return $41
PHA
JMP :EXIT
:NOTDIR LDA #<MOSFILE ; Attempt to destroy file
STA DESTPL+1
LDA #>MOSFILE
STA DESTPL+2
JSR MLI
DB DESTCMD
DW DESTPL
STZ :BLOCKS
LDA #$01 ; Storage type - file
STA CREATEPL+7
LDA #$06 ; Filetype BIN
STA CREATEPL+4
LDA #<MOSFILE
STA OPENPL+1
LDA #>MOSFILE
STA OPENPL+2
LDA FBLOAD ; Auxtype = load address
STA CREATEPL+5
LDA FBLOAD+1
STA CREATEPL+6
LDA #$C3 ; Default permissions
STA CREATEPL+3
JSR CRTFILE
BCS :FWD1 ; :CANTOPEN error
JSR OPENFILE
BCS :FWD1 ; :CANTOPEN error
SEC ; Compute file length
LDA FBEND
SBC FBSTRT
STA :LENREM
LDA FBEND+1
SBC FBSTRT+1
STA :LENREM+1
:L1 LDA FBSTRT ; Set up for first block
STA A1L
STA A2L
LDA FBSTRT+1
STA A1H
STA A2H
INC A2H ; $200 = 512 bytes
INC A2H
LDA OPENPL+5 ; File ref number
STA WRITEPL+1
LDA #$00 ; 512 byte request count
STA WRITEPL+4
LDA #$02
STA WRITEPL+5
LDX :BLOCKS
:L2 CPX #$00 ; Adjust for subsequent blks
BEQ :S1
INC A1H
INC A1H
INC A2H
INC A2H
DEX
BRA :L2
:FWD1 BRA :CANTOPEN ; Forwarding call from above
:S1 LDA :LENREM+1 ; MSB of length remaining
CMP #$02
BCS :S2 ; MSB of len >= 2 (not last)
CMP #$00 ; If no bytes left ...
BNE :S3
LDA :LENREM
BNE :S3
BRA :NORMALEND
:S3 LDA FBEND ; Adjust for last block
STA A2L
LDA FBEND+1
STA A2H
LDA :LENREM
STA WRITEPL+4 ; Remaining bytes to write
LDA :LENREM+1
STA WRITEPL+5
:S2 LDA #<BLKBUF
STA A4L
LDA #>BLKBUF
STA A4H
CLC ; Aux -> Main
JSR AUXMOVE
LDA OPENPL+5 ; File ref number
STA WRITEPL+1
JSR WRTFILE
BCS :WRITEERR
BRA :UPDLEN
:ENDLOOP INC :BLOCKS
BRA :L1
:UPDLEN SEC ; Update length remaining
LDA :LENREM
SBC WRITEPL+4
STA :LENREM
LDA :LENREM+1
SBC WRITEPL+5
STA :LENREM+1
BRA :ENDLOOP
:CANTOPEN LDA #$5E ; Can't open/create
PHA
BRA :EXIT
:WRITEERR LDA OPENPL+5 ; File ref num
STA CLSPL+1
JSR CLSFILE
LDA #$5D ; Write error
PHA
BRA :EXIT
:NORMALEND LDA OPENPL+5 ; File ref num
STA CLSPL+1
JSR CLSFILE
BCC :OK ; If close OK
LDA #$5D ; Write error
PHA
BRA :EXIT
:OK LDA #$01 ; Success ('File')
PHA
:EXIT JSR UPDFB ; Update FILEBLK
JSR COPYFB ; Copy FILEBLK to aux mem
PLA
>>> XF2AUX,OSFILERET
:BLOCKS DB $00
:LENREM DW $0000 ; Remaining length
* Update FILEBLK before returning to aux memory
* Returns A=object type or ProDOS error
UPDFB LDA #<MOSFILE
STA OPENPL+1
STA GINFOPL+1
LDA #>MOSFILE
STA OPENPL+2
STA GINFOPL+2
JSR GETINFO ; Call GET_FILE_INFO
BCC :UPDFB1
JMP CHKNOTFND
:UPDFB1 LDA GINFOPL+5 ; Aux type LSB
STA FBLOAD
STA FBEXEC
LDA GINFOPL+6 ; Aux type MSB
STA FBLOAD+1
STA FBEXEC+1
STZ FBLOAD+2
STZ FBEXEC+2
STZ FBLOAD+3
STZ FBEXEC+3
*
LDA GINFOPL+3 ; Access byte
CMP #$40 ; Locked?
AND #$03 ; ------wr
PHP
STA FBATTR+0
ASL A ; -----wr-
ASL A ; ----wr--
ASL A ; ---wr---
ASL A ; --wr----
PLP
BCS :UPDFB2
ORA #$08 ; --wrl---
:UPDFB2 ORA FBATTR+0 ; --wrl-wr
STA FBATTR+0
*
LDA GINFOPL+11 ; yyyyyyym
PHA
ROR A ; ?yyyyyyy m
LDA GINFOPL+10 ; mmmddddd m
PHA
ROR A ; mmmmdddd
LSR A ; -mmmmddd
LSR A ; --mmmmdd
LSR A ; ---mmmmd
LSR A ; ----mmmm
STA FBATTR+2
PLA ; mmmddddd
AND #31 ; ---ddddd
STA FBATTR+1
PLA ; yyyyyyym
SEC
SBC #81*2 ; Offset from 1981
BCS :UPDFB3 ; 1981-1999 -> 00-18
ADC #100*2 ; 2000-2080 -> 19-99
:UPDFB3 PHA ; yyyyyyym
AND #$E0 ; yyy-----
ORA FBATTR+1 ; yyyddddd
STA FBATTR+1
PLA ; yyyyyyym
AND #$FE ; yyyyyyy0
ASL A ; yyyyyy00
ASL A ; yyyyy000
ASL A ; yyyy0000
ORA FBATTR+2 ; yyyymmmm
STA FBATTR+2
STZ FBATTR+3
JSR OPENFILE ; Open file
BCS :ERR
LDA OPENPL+5 ; File ref number
STA GMARKPL+1
JSR MLI ; Call GET_EOF MLI
DB GEOFCMD
DW GMARKPL ; MARK parms same as EOF
LDA GMARKPL+2
STA FBSIZE+0
LDA GMARKPL+3
STA FBSIZE+1
LDA GMARKPL+4
STA FBSIZE+2
STZ FBSIZE+3
LDA OPENPL+5 ; File ref number
STA CLSPL+1
JSR CLSFILE
LDA #$01 ; Prepare A=file
LDX GINFOPL+7
CPX #$0D ; Is it a directory?
BNE :UPDFB5
LDA #$02 ; Return A=directory
:UPDFB5 RTS
:ERR
CHKNOTFND CMP #$44 ; Convert ProDOS 'not found'
BEQ :NOTFND ; into result=$00
CMP #$45
BEQ :NOTFND
CMP #$46
BNE :CHKNOTFND2
:NOTFND LDA #$00
:CHKNOTFND2 RTS
* Quit to ProDOS
QUIT INC $3F4 ; Invalidate powerup byte
STA $C054 ; PAGE2 off
JSR MLI
DB QUITCMD
DW QUITPL
RTS
* Used for *CAT, *EX and *INFO
* On entry: A=$5x *CAT, A=$9x *EX, A=$Ax *INFO
CATALOG >>> ENTMAIN
AND #$F0
STA CATARG ; Stash argument
CMP #$A0 ; Is it *INFO?
BNE :NOTINFO
JMP INFO ; Handle entry for *INFO
:NOTINFO LDA MOSFILE ; Length of pathname
BEQ :NOPATH ; If zero use prefix
JSR PREPATH ; Preprocess pathname
JSR WILDONE ; Handle any wildcards
JSR EXISTS ; See if path exists ...
CMP #$01 ; ... and is a file
BNE :NOTFILE
LDA #$46 ; Not found (TO DO: err code?)
BRA CATEXIT
:NOTFILE LDA #<MOSFILE
STA OPENPL+1
LDA #>MOSFILE
STA OPENPL+2
BRA :OPEN
:NOPATH JSR GETPREF ; Fetch prefix into PREFIX
LDA #<PREFIX
STA OPENPL+1
LDA #>PREFIX
STA OPENPL+2
:OPEN JSR OPENFILE
BCS CATEXIT ; Can't open dir
CATREENTRY
LDA OPENPL+5 ; File ref num
STA READPL+1
JSR RDFILE
BCC :S1
CMP #$4C ; EOF
BEQ :EOF
BRA :READERR
:S1 JSR COPYAUXBLK
>>> XF2AUX,PRONEBLK
:READERR
:EOF LDA OPENPL+5 ; File ref num
STA CLSPL+1
JSR CLSFILE
CATEXIT >>> XF2AUX,STARCATRET
* PRONEBLK call returns here ...
CATALOGRET
>>> ENTMAIN
LDA CATARG
CMP #$A0 ; Is this an *INFO call?
BEQ INFOREENTRY
BRA CATREENTRY
CATARG DB $00
* Handle *INFO
INFO JSR PREPATH ; Preprocess pathname
SEC
JSR WILDCARD ; Handle any wildcards
JSR EXISTS ; Check matches something
CMP #$00
BNE INFOFIRST
JSR CLSDIR
LDA #$46 ; Not found (TO DO: err code?)
BRA CATEXIT
INFOREENTRY
JSR WILDNEXT2 ; Start of new block
BCS INFOEXIT ; No more matches
INFOFIRST LDA WILDIDX
CMP #$FF ; Is WILDNEXT about to read new blk?
BEQ :DONEBLK ; If so, print this blk first
JSR WILDNEXT2
BCS :DONEBLK ; If no more matches
BRA INFOFIRST
:DONEBLK JSR COPYAUXBLK
>>> XF2AUX,PRONEBLK
INFOEXIT CMP #$4C ; EOF
BNE INFOCLS
LDA #$00 ; EOF is not an error
INFOCLS JSR CLSDIR ; Be sure to close it!
BRA CATEXIT
* Set prefix. Used by *CHDIR to change directory
SETPFX >>> ENTMAIN
JSR PREPATH ; Preprocess pathname
JSR WILDONE ; Handle any wildcards
BCS :ERR
LDA #<MOSFILE
STA SPFXPL+1
LDA #>MOSFILE
STA SPFXPL+2
JSR MLI ; SET_PREFIX
DB SPFXCMD
DW SPFXPL
:EXIT >>> XF2AUX,CHDIRRET
:ERR LDA #$40 ; Invalid pathname syn
BRA :EXIT
* Obtain info on blocks used/total blocks
DRVINFO >>> ENTMAIN
JSR PREPATH
BCS :ERR
LDA #<MOSFILE
STA GINFOPL+1
LDA #>MOSFILE
STA GINFOPL+2
JSR GETINFO ; GET_FILE_INFO
BCS :EXIT
PHA
>>> ALTZP ; Alt ZP & Alt LC on
LDA GINFOPL+8 ; Blcks used LSB
STA AUXBLK
LDA GINFOPL+9 ; Blks used MSB
STA AUXBLK+1
LDA GINFOPL+5 ; Tot blks LSB
STA AUXBLK+2
LDA GINFOPL+6 ; Tot blks MSB
STA AUXBLK+3
>>> MAINZP ; ALt ZP off, ROM back in
PLA
:EXIT >>> XF2AUX,FREERET
:ERR LDA #$40 ; Invalid pathname syn
BRA :EXIT
* Change file permissions, for *ACCESS
* Filename in MOSFILE, flags in MOSFILE2
SETPERM >>> ENTMAIN
JSR PREPATH ; Preprocess pathname
BCS :SYNERR
CLC
JSR WILDCARD ; Handle any wildcards
BCS :NONE
STZ :LFLAG
STZ :WFLAG
STZ :RFLAG
LDX MOSFILE2 ; Length of arg2
INX
:L1 DEX
CPX #$00
BEQ :MAINLOOP
LDA MOSFILE2,X ; Read arg2 char
CMP #'L' ; L=Locked
BNE :S1
STA :LFLAG
BRA :L1
:S1 CMP #'R' ; R=Readable
BNE :S2
STA :RFLAG
BRA :L1
:S2 CMP #'W' ; W=Writable
BNE :ERR2 ; Bad attribute
STA :WFLAG
BRA :L1
:SYNERR LDA #$40 ; Invalid pathname syn
BRA :EXIT
:NONE JSR CLSDIR
LDA #$46 ; 'File not found'
BRA :EXIT
:MAINLOOP LDA #<MOSFILE
STA GINFOPL+1
LDA #>MOSFILE
STA GINFOPL+2
JSR GETINFO ; GET_FILE_INFO
BCS :EXIT
LDA GINFOPL+3 ; Access byte
AND #$03 ; Start with R, W off
ORA #$C0 ; Start with dest/ren on
LDX :RFLAG
BEQ :S3
ORA #$01 ; Turn on read enable
:S3 LDX :WFLAG
BEQ :S4
ORA #$02 ; Turn on write enable
:S4 LDX :LFLAG
BEQ :S5
AND #$3D ; Turn off destroy/ren/write
:S5 STA GINFOPL+3 ; Access byte
JSR SETINFO ; SET_FILE_INFO
JSR WILDNEXT
BCS :NOMORE
BRA :MAINLOOP
:EXIT >>> XF2AUX,ACCRET
:NOMORE JSR CLSDIR
LDA #$00
BRA :EXIT
:ERR2 LDA #$53 ; Invalid parameter
BRA :EXIT
:LFLAG DB $00 ; 'L' attribute
:WFLAG DB $00 ; 'W' attribute
:RFLAG DB $00 ; 'R' attribute
* Multi file delete, for *DESTROY
* Filename in MOSFILE
MULTIDEL >>> ENTMAIN
JSR PREPATH ; Preprocess pathname
BCS :SYNERR
CLC
JSR WILDCARD ; Handle any wildcards
BCS :NONE
BRA :MAINLOOP
:SYNERR LDA #$40 ; Invalid pathname syn
BRA :EXIT
:NONE JSR CLSDIR
LDA #$46 ; 'File not found'
BRA :EXIT
:MAINLOOP JSR DODELETE
BCS :DELERR
JSR WILDNEXT
BCS :NOMORE
BRA :MAINLOOP
:EXIT >>> XF2AUX,DESTRET
:DELERR PHA
JSR CLSDIR
PLA
BRA :EXIT
:NOMORE JSR CLSDIR
LDA #$00
BRA :EXIT
* Read machid from auxmem
MACHRD LDA $C081
LDA $C081
LDA $FBC0
SEC
JSR $FE1F
BRA MAINRDEXIT
* Read mainmem from auxmem
MAINRDMEM STA A1L
STY A1H
LDA $C081
LDA $C081
LDA (A1L)
MAINRDEXIT >>> XF2AUX,NULLRTS ; Back to an RTS
* Call FDraw Clear routine
CLRHGR >>> ENTMAIN
LDA BGCOLOR
STA FDRAWADDR+5
JSR FDRAWADDR+16 ; FDRAW: SetColor
JSR FDRAWADDR+22 ; FDRAW: Clear
LDA FGCOLOR
STA FDRAWADDR+5
JSR FDRAWADDR+16 ; FDRAW: SetColor
>>> XF2AUX,VDU16RET
* Call FDraw SetLineMode routine
SETLINE >>> ENTMAIN
JSR FDRAWADDR+43 ; FDRAW: SetLineMode
>>> XF2AUX,VDU18RET1
* Call FDraw DrawLine routine
DRAWLINE >>> ENTMAIN
LDA PLOTMODE
AND #$03
CMP #$01 ; Draw in foreground colour
BNE :S1
LDA FGCOLOR
BRA :SETCOLOR
:S1 CMP #$02 ; Draw in inverse colour
BNE :S2
SEC
LDA #$07
SBC FGCOLOR
BRA :SETCOLOR
:S2 LDA BGCOLOR ; Draw in background colour
:SETCOLOR STA FDRAWADDR+5
JSR FDRAWADDR+16 ; FDRAW: SetColor
JSR FDRAWADDR+28 ; FDRAW: DrawLine
>>> XF2AUX,VDU25RET
* Call FDraw DrawPoint routine
DRAWPNT >>> ENTMAIN
LDA PLOTMODE
AND #$03
CMP #$01 ; Draw in foreground colour
BNE :S1
LDA FGCOLOR
BRA :SETCOLOR
:S1 CMP #$02 ; Draw in inverse colour
BNE :S2
SEC
LDA #$07
SBC FGCOLOR
BRA :SETCOLOR
:S2 LDA BGCOLOR ; Draw in background colour
:SETCOLOR STA FDRAWADDR+5
JSR FDRAWADDR+16 ; FDRAW: SetColor
JSR FDRAWADDR+25 ; FDRAW: DrawPoint
>>> XF2AUX,VDU25RET
* Reset colours and linetype
GFXINIT JSR FDRAWADDR+0 ; Initialize FDRAW library
LDA #$20
STA FDRAWADDR+5
JSR FDRAWADDR+19 ; FDRAW: Set page $2000
STZ LINETYPE
STZ FDRAWADDR+5
JSR FDRAWADDR+43 ; FDRAW: SetLineMode
LDA #$07
STA FGCOLOR
STA FDRAWADDR+5
JSR FDRAWADDR+16 ; FDRAW: SetColor
STZ BGCOLOR
JSR FDRAWADDR+22 ; FDRAW: clear HGR screen
RTS
FGCOLOR DB $00 ; Foreground colour
BGCOLOR DB $00 ; Background colour
LINETYPE DB $00 ; 0 normal, 1 XOR
PLOTMODE DB $00 ; K value for PLOT K,X,Y