million-perfect-letters/src/glue.mli.a

355 lines
12 KiB
Plaintext

;license:MIT
;(c) 2020 by 4am
;
; ProDOS MLI wrapper (6502 compatible)
;
; Public functions:
; - LoadFile1Shot
; - SaveFile1Shot
; - CreateFile
; - OpenFile
; - ReadFile
; - WriteFile
; - SeekFile
; - FlushFile
; - CloseFile
; - Quit
; ProDOS constants (these are memory addresses)
PRODOSMLI = $BF00 ; [callable] MLI entry point
DEVNUM = $BF30 ; last accessed device
; MLI parameter counts + command codes (these are not memory addresses)
CMD_QUIT = $0465 ; quit to ProDOS
CMD_GETTIME = $0082 ; get current time
CMD_CREATE = $07C0 ; create new file
CMD_DESTROY = $01C1 ; delete a file
CMD_GETFILEINFO = $0AC4 ; get file (or volume) info
CMD_ONLINE = $02C5 ; check online volume(s)
CMD_SETPREFIX = $01C6 ; change current directory
CMD_GETPREFIX = $01C7 ; get current directory
CMD_OPEN = $03C8 ; open a file
CMD_NEWLINE = $03C9 ; set line-by-line read mode
CMD_READ = $04CA ; read an open file
CMD_WRITE = $04CB ; write to an open file
CMD_CLOSE = $01CC ; close an open file
CMD_FLUSH = $01CD ; flush an open, written file to disk
CMD_SETMARK = $02CE ; change position in an open file
CMD_SETEOF = $02D0 ; set file size
;------------------------------------------------------------------------------
; LoadFile1Shot
; load a file into memory all at once, using ProDOS MLI calls
;
; in: stack contains 8 bytes of parameters:
; +1 [word] address of pathname
; +3 [word] address of data buffer (to receive file contents)
; +5 [word] maximum length of data to read
; +7 [word] address of ProDOS file buffer
; out: if C set, load failed and A = error code from open or read
; if C clear, load succeeded
; Y clobbered
; X preserved
; all other flags & registers clobbered
;------------------------------------------------------------------------------
LoadFile1Shot
+PARAMS_ON_STACK 8
+LDPARAM16 1, @filename
+LDPARAM16 3, @databuffer
+LDPARAM16 5, @datalength
+LDPARAM16 7, @filebuffer
jsr OpenFile
@filename
!word $FDFD
@filebuffer
!word $FDFD
bcs @exit
sta @refnum
jsr ReadFile
@refnum
!byte $FD
@databuffer
!word $FDFD
@datalength
!word $FDFD
php
lda @refnum
jsr CloseFile
plp
@exit rts
;------------------------------------------------------------------------------
; SaveFile1Shot
; 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 (if we need to create the file)
; +4 [word] aux file type
; +6 [word] address of data buffer
; +8 [word] length of data buffer
; +A [word] address of ProDOS file buffer
; out: if C set, save failed and A = error code
; from open or write
; if C clear, save succeeded
; Y clobbered
; X preserved
; other flags clobbered
;------------------------------------------------------------------------------
SaveFile1Shot
+PARAMS_ON_STACK 11
+LDPARAM16 $01, @filename
+LDPARAM16 $01, @filename2
+LDPARAM8 $03, @filetype
+LDPARAM16 $04, @auxfiletype
+LDPARAM16 $06, @databuffer
+LDPARAM16 $08, @datalength
+LDPARAM16 $0A, @filebuffer
- jsr OpenFile
@filename
!word $FDFD
@filebuffer
!word $FDFD
bcc +
jsr CreateFile
@filename2
!word $FDFD
@filetype
!byte $FD
@auxfiletype
!word $FDFD
bcs @exit
bcc -
+ sta @refnum
jsr WriteFile
@databuffer
!word $FDFD
@datalength
!word $FDFD
php ; save C flag from WriteFile
pha ; save error code or file refnum
@refnum=*+1
lda #$FD ; SMC
jsr CloseFile
pla ; A = error code or file refnum from WriteFile
plp ; get C flag from Writefile
@exit rts
;------------------------------------------------------------------------------
; CreateFile
; 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: stack contains 5 bytes of parameters:
; +1 address of pathname
; +3 [byte] file type
; +4 [word] aux file type
; out: if error, C set and A = error code
; if success, C clear
; Y clobbered
; X preserved
; other flags clobbered
;------------------------------------------------------------------------------
CreateFile
+PARAMS_ON_STACK 5
+LDPARAM16 1, mliparam+1 ; address of filename
+LDPARAM8 3, mliparam+4 ; filetype
+LDPARAM16 4, mliparam+5 ; aux filetype
lda #$C3 ; = full access
sta mliparam+3 ; set access bits
ldy #1 ; = file
sty mliparam+7 ; storage type
dey ; = 0 (current date/time)
sty mliparam+8 ; creation date
sty mliparam+9
sty mliparam+10 ; creation time
sty mliparam+11
+LDADDR CMD_CREATE
jmp mli
;------------------------------------------------------------------------------
; OpenFile
; open file via ProDOS MLI
;
; in: stack contains 4 bytes of parameters:
; +1 [word] address of filename
; +3 [word] ProDOS file buffer
; out: if C set, open failed and A = error code
; if C clear, open succeeded and A = file reference number
; Y clobbered
; X preserved
; other flags clobbered
;------------------------------------------------------------------------------
OpenFile
+PARAMS_ON_STACK 4
+LDPARAM16 1, mliparam+1 ; address of filename
+LDPARAM16 3, mliparam+3 ; address of ProDOS file buffer
+LDADDR CMD_OPEN
jsr mli
bcs +
lda refnum ; caller should save file reference number
; as this memory location may be
; overwritten by later MLI calls
+ rts
;------------------------------------------------------------------------------
; ReadFile
; read an open file via ProDOS MLI
;
; in: stack contains 5 bytes of parameters:
; +1 [byte] ProDOS file reference number
; +2 [word] address of data buffer (to receive file contents)
; +4 [word] maximum length of data to read
; out: if C set, read failed and A = error code
; if C clear, read succeeded and A = the same
; file reference number that was passed in
; Y clobbered
; X preserved
; other flags clobbered
; stack set to next instruction after parameters
;------------------------------------------------------------------------------
ReadFile
+PARAMS_ON_STACK 5
+LDPARAM8 1, mliparam+1 ; file reference number
+LDPARAM16 2, mliparam+2 ; address of data buffer
+LDPARAM16 4, mliparam+4 ; data length
+LDADDR CMD_READ
jsr mli
bcs +
lda mliparam+1 ; if no error, return file reference number
+ rts
;------------------------------------------------------------------------------
; WriteFile
; write to an open file via ProDOS MLI
;
; in: A = file reference number
; stack contains 4 bytes of parameters:
; +1 [word] address of data buffer
; +3 [word] length of data buffer
; out: if C set, save failed and A = error code
; if C clear, write succeeded and A = the same file reference
; number that was passed in
; Y clobbered
; X preserved
; other flags clobbered
;------------------------------------------------------------------------------
WriteFile
sta mliparam+1 ; file reference number
+PARAMS_ON_STACK 4
+LDPARAM16 1, mliparam+2 ; data buffer address
+LDPARAM16 3, mliparam+4 ; data buffer length
+LDADDR CMD_WRITE
jsr mli
bcs + ; error, A = MLI error code
lda mliparam+1 ; no error, return file reference number
+ rts
;------------------------------------------------------------------------------
; SeekFile
; set file position within an open file
;
; in: A = file reference number
; X = seek offset (lo)
; Y = seek offset (hi)
; note: this routine can not seek beyond 65535 bytes even though
; ProDOS can do that
; out: if C set, seek failed and A = error code
; if C clear, seek succeeded and A = the same file reference
; number that was passed in
; Y clobbered
; X preserved
; other flags clobbered
;------------------------------------------------------------------------------
SeekFile
sta mliparam+1 ; file reference number
stx mliparam+2
sty mliparam+3
lda #0
sta mliparam+4
+LDADDR CMD_SETMARK
bne mli ; always branches
;------------------------------------------------------------------------------
; FlushFile
; flush an open file (actually writes it to disk, but without closing it)
;
; in: A = file reference number
; out: if error, C set and A = error code
; if success, C clear
; Y clobbered
; X preserved
; other flags clobbered
;------------------------------------------------------------------------------
FlushFile
sta mliparam+1 ; file reference number
+LDADDR CMD_FLUSH
bne mli ; always branches
;------------------------------------------------------------------------------
; CloseFile
; close an open file
;
; in: A = file reference number
; out: if error, C set and A = error code
; if success, C clear
; Y clobbered
; X preserved
; other flags clobbered
;------------------------------------------------------------------------------
CloseFile
sta mliparam+1 ; file reference number
+LDADDR CMD_CLOSE
bne mli ; always branches
GetTime
+LDADDR CMD_GETTIME
beq mli ; always branches
;------------------------------------------------------------------------------
; Quit
; quit to ProDOS
; in: none
; out: does not return
;------------------------------------------------------------------------------
Quit
lda #0
jsr CloseFile
+LDADDR CMD_QUIT
; /!\ execution falls through here
;------------------------------------------------------------------------------
; mli
; 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 $FD,$FD,$FD,$FD
filetype !byte $FD ; file type (set by MLI get_file_info)
auxtype ; auxiliary file type (2 bytes, set by MLI get_file_info)
refnum !byte $FD ; file refnum (set by MLI open)
mlilen !byte $FD,$FD ; file length (set by MLI read)
blocks !byte $FD,$FD ; blocks used (set by getvolumeinfo)
; member is also used by createfile
!byte $FD,$FD,$FD,$FD,$FD,$FD,$FD,$FD
; used by get_file_info