pitch-dark/src/prodos.a

336 lines
10 KiB
Plaintext

;license:MIT
;(c) 2017-8 by 4am
;
; ProDOS and file routines
;
; Public functions
; - LoadFile
; - SaveFile
; - QuitToProDOS
;
; MLI command codes
CMD_QUIT = $65 ; quit to ProDOS
CMD_CREATE = $C0 ; create new file
CMD_DESTROY = $C1 ; delete a file
CMD_OPEN = $C8 ; open a file
CMD_READ = $CA ; read an open file
CMD_WRITE = $CB ; write to an open file
CMD_CLOSE = $CC ; close an open file
; MLI parameter counts
PC_QUIT = $04
PC_CREATE = $07
PC_DESTROY = $01
PC_OPEN = $03
PC_READ = $04
PC_WRITE = $04
PC_CLOSE = $01
PRODOSMLI = $BF00 ; [callable] MLI entry point
MACHID = $BF98
;-------------------------------
; LoadFile
; load a file into memory all at once, using ProDOS MLI calls
;
; in: stack contains 8 bytes of parameters:
; +1 address of pathname
; +3 address of data buffer (to receive file contents)
; +5 [word] maximum length of data to read
; +7 address of ProDOS file buffer
; out: if C set, load failed and A contains error code
; from open or read
; if C clear, load succeeded and ($02) contains
; data loaded from file
; all other flags clobbered
; all registers clobbered
; stack set to next instruction after parameters
;-------------------------------
!zone {
LoadFile
pla
sta $00
plx
stx $01
lda #$08
clc
adc $00
bcc +
inx
+ phx
pha
ldy #$01
lda ($00),y ; lo byte of pathname
sta mliparam+1
iny
lda ($00),y ; hi byte of pathname
sta mliparam+2
ldy #$07
lda ($00),y ; lo byte of ProDOS file buffer
sta mliparam+3
iny
lda ($00),y ; hi byte of ProDOS file buffer
sta mliparam+4
jsr _openfile
bcs .exit ; C set on error
pha ; push file reference number
ldy #$03
lda ($00),y ; lo address of data buffer
sta mliparam+2
iny
lda ($00),y ; hi address of data buffer
sta mliparam+3
iny
lda ($00),y ; lo data length
sta mliparam+4
iny
lda ($00),y ; hi data length
sta mliparam+5
pla ; pull file reference number
jsr _readfile
php ; save flags from readfile
pha
jsr _closefile ; always close whether read worked or not
pla
plp ; restore flags from readfile
; (so caller gets codes from read attempt,
; not close)
.exit
rts
}
;-------------------------------
; SaveFile
; save a file to disk all at once, using ProDOS MLI calls
;
; in: stack contains 11 ($0B) bytes of parameters:
; +1 address of pathname
; +3 [byte] file type
; +4 [word] aux file type
; +6 address of data buffer
; +8 [word] length of data buffer
; +A address of ProDOS file buffer
; out: if C set, save failed and A contains error code
; from open or write
; if C clear, save succeeded
; all other flags clobbered
; all registers clobbered
; stack set to next instruction after parameters
;-------------------------------
!zone {
SaveFile
pla
sta $00
plx
stx $01
lda #$0B
clc
adc $00
bcc +
inx
+ phx
pha
ldy #$01
lda ($00),y ; lo byte of pathname
sta mliparam+1
iny
lda ($00),y ; hi byte of pathname
sta mliparam+2
jsr _deletefile ; don't care if this fails
ldy #$03
lda ($00),y ; file type
sta mliparam+4
iny
lda ($00),y ; lo byte of aux file type
sta mliparam+5
iny
lda ($00),y ; hi byte of aux file type
sta mliparam+6
jsr _createfile
bcs .exit
ldy #$0A
lda ($00),y ; lo byte of ProDOS file buffer
sta mliparam+3
iny
lda ($00),y ; hi byte of ProDOS file buffer
sta mliparam+4
jsr _openfile
bcs .exit
pha ; push file reference number
ldy #$06
lda ($00),y ; lo address of data buffer
sta mliparam+2
iny
lda ($00),y ; hi address of data buffer
sta mliparam+3
iny
lda ($00),y ; lo data length
sta mliparam+4
iny
lda ($00),y ; hi data length
sta mliparam+5
pla ; pull file reference number
jsr _writefile
php ; save flags from writefile
pha
jsr _closefile ; always close whether write worked or not
pla
plp ; restore flags from write
; (so caller gets codes from write attempt,
; not close)
.exit
rts
}
;-------------------------------
; open file via ProDOS MLI
;
; in: caller has filled @mliparam with address of
; pathname, address of data buffer, and maximum
; data length
; out: if C set, open failed and A contains error code
; if C clear, open succeeded and A contains
; file reference number
;-------------------------------
_openfile
lda #CMD_OPEN ; MLI command
ldy #PC_OPEN ; number of parameters for 'open' command
jsr mli
bcs +
lda refnum ; caller should save file reference number
; as this memory location may be
; overwritten by later MLI calls
+ rts
;-------------------------------
; read an open file via ProDOS MLI
;
; in: A = file reference number
; caller has filled @mliparam with address of
; data buffer and maximum data length
; out: if C set, read failed and A contains error code
; if C clear, read succeeded and A contains the same
; file reference number that was passed in
;-------------------------------
_readfile
sta mliparam+1 ; store file reference number
lda #CMD_READ ; MLI read command
ldy #PC_READ ; number of parameters for 'read' command
jsr mli
bcs +
lda mliparam+1 ; if no error, return file reference number
+ rts
;-------------------------------
; write to an open file via ProDOS MLI
;
; in: A = file reference number
; caller has filled @mliparam with address of
; data buffer and data length
; out: if C set, write failed and A contains error code
; if C clear, write succeeded and A contains the same
; file reference number that was passed in
;-------------------------------
_writefile
sta mliparam+1 ; store file reference number
lda #CMD_WRITE ; MLI write command
ldy #PC_WRITE ; number of parameters for 'write' command
jsr mli
bcs +
lda mliparam+1 ; if no error, return file reference number
+ rts
;-------------------------------
; close an open file
; in: A = file reference number
; out: if error, C set and A contains error code
; if success, C clear
;-------------------------------
_closefile
sta mliparam+1 ; store file reference number
lda #CMD_CLOSE ; MLI close command
ldy #PC_CLOSE ; number of parameters for 'close' command
jsr mli
rts
;-------------------------------
; create a file via ProDOS MLI
; always sets access bits to $C3 (full access)
; always sets creation to 0 (current date/time)
; always sets storage type to 1 (file)
; in: caller has filled @mliparam
; with address of pathname,
; file type, aux file type
; out: if error, C set and A contains error code
; if success, C clear
;-------------------------------
accessbits = $C3 ; full access
_createfile
lda #accessbits
sta mliparam+3 ; access bits (full access)
ldy #1
sty mliparam+7 ; storage type (file)
dey
sty mliparam+8 ; creation date (current)
sty mliparam+9
sty mliparam+10 ; creation time (current)
sty mliparam+11
lda #CMD_CREATE ; MLI create command
ldy #PC_CREATE ; number of parameters for 'create' command
jsr mli
rts
;-------------------------------
; delete a file using ProDOS MLI
; in: caller has filled @mliparam
; with address of pathname
; out: if error, C set and A contains error code
; if success, C clear
;-------------------------------
_deletefile
lda #CMD_DESTROY ; MLI destroy command
ldy #PC_DESTROY ; number of parameters for 'destroy' command
jsr mli
rts
QuitToProDOS
lda #CMD_QUIT
ldy #PC_QUIT
; execution falls through here
;-------------------------------
; low-level MLI wrapper
; in: A = MLI command code
; Y = number of MLI parameters
; caller has filled @mliparam
; with all relevant parameters
; out: returns immediately after
; calling MLI, so whatever
; state the MLI routine sets,
; the caller will see it
; verbatim
;-------------------------------
mli sta mlicmd ; store command code
sty mliparam ; number of parameters
jsr PRODOSMLI ; call ProDOS
mlicmd !byte 00 ; command number
!word mliparam ; address of parameter table
rts
mliparam !byte $FE,$FE,$FE,$FE
filetype !byte $FE ; file type (set by MLI get_file_info)
auxtype ; auxiliary file type (2 bytes, set by MLI get_file_info)
refnum !byte $FE ; file refnum (set by MLI open)
mlilen !byte $FE,$FE ; file length (set by MLI read)
blocks !byte $FE,$FE ; blocks used (set by getvolumeinfo)
; member is also used by createfile
!byte $FE,$FE,$FE,$FE,$FE,$FE,$FE,$FE
; used by get_file_info