a2d/inc/prodos.inc
2018-04-03 21:26:13 -07:00

390 lines
9.3 KiB
PHP

;;; ============================================================
;;;
;;; ProDOS MLI
;;;
;;; ============================================================
;;; Entry point / Global Page
MLI := $BF00 ; Entry point
DEVNUM := $BF30 ; Most recent accessed device
DEVCNT := $BF31 ; Number of on-line devices minus 1
DEVLST := $BF32 ; Up to 14 units
BITMAP := $BF58 ; System memory bitmap
BITMAP_SIZE := $18 ; Bits for pages $00 to $BF
DATELO := $BF90 ; Date lo
DATEHI := $BF91 ; Date hi
TIMELO := $BF92 ; Time lo
TIMEHI := $BF93 ; Time hi
LEVEL := $BF94 ; File level
MACHID := $BF98 ; Machine ID
IVERSION := $BFFD ; Interpreter Version
KVERSION := $BFFF ; ProDOS Kernel Version
;;; Patch Locations
SELECTOR := $D100
BLOCK_SIZE := $200
;;; ============================================================
;;; MLI Calls
;;; ============================================================
;;; Housekeeping Calls
CREATE := $C0
DESTROY := $C1
RENAME := $C2
SET_FILE_INFO := $C3
GET_FILE_INFO := $C4
ON_LINE := $C5
SET_PREFIX := $C6
GET_PREFIX := $C7
;;; Filing Calls
OPEN := $C8
NEWLINE := $C9
READ := $CA
WRITE := $CB
CLOSE := $CC
FLUSH := $CD
SET_MARK := $CE
GET_MARK := $CF
SET_EOF := $D0
GET_EOF := $D1
SET_BUF := $D2
GET_BUF := $D3
;;; System Calls
GET_TIME := $82
ALLOC_INTERRUPT := $40
DEALLOC_INTERRUPT := $41
QUIT := $65
;;; Direct Disk Access Commands
READ_BLOCK := $80
WRITE_BLOCK := $81
;;; ============================================================
;;; Device Types (low nibble of unit number in DEVLST)
;;; ============================================================
DT_DISKII := $0
DT_PROFILE := $4
DT_RAM := $F
;;; See ProDOS Tech Note #21 - other than the above types, there
;;; is not an "ID nibble". The nibble is a copy of $CnFE's high
;;; nibble, with this meaning:
;;; bit 3 = removable
;;; bit 2 = interruptable
;;; bit 1-0 = number of volumes (0-1)
;;; "You should ignore the low nibble in the unit number..."
;;; ============================================================
;;; File Types
;;; ============================================================
FT_TYPELESS := $00
FT_BAD := $01
FT_TEXT := $04
FT_BINARY := $06
FT_DIRECTORY := $0F
FT_SRC := $B0 ; IIgs system type; re-used?
FT_S16 := $B3 ; IIgs Application Program
FT_BASIC := $FC
FT_SYSTEM := $FF
;;; ============================================================
;;; Access
;;; ============================================================
ACCESS_DEFAULT := %11000011
;;; ============================================================
;;; Storage Types
;;; ============================================================
ST_STANDARD_FILE := $01
ST_LINKED_DIRECTORY := $0D
ST_VOLUME_DIRECTORY := $0F
;;; ============================================================
;;; Errors
;;; ============================================================
ERR_PATH_NOT_FOUND := $44
ERR_VOL_NOT_FOUND := $45
ERR_FILE_NOT_FOUND := $46
ERR_DUPLICATE_FILENAME:= $47
ERR_OVERRUN_ERROR := $48
ERR_VOLUME_DIR_FULL := $49
ERR_END_OF_FILE := $4C
;;; ============================================================
;;; Macros
;;; ============================================================
.macro MLI_CALL op, addr
jsr MLI
.byte op
.addr addr
.endmacro
.macro PASCAL_STRING str,res ; Length-prefixed string
.local data ; Can include control chars by using:
.local end ; PASCAL_STRING {"abc",$0D,"def"}
.byte end - data
data: .byte str
end:
.if .paramcount > 1
.res res - (end - data), 0
.endif
.endmacro
.macro DEFINE_OPEN_PARAMS name, pn, io, rn
.if .xmatch(.string(pn), "pathname")
;; If 'pathname' is passed then expansion yields a circular reference.
.error "Can't pass 'pathname' label to DEFINE_*_PARAMS"
.endif
.if .xmatch(.string(io), "io_buffer")
.error "Can't pass 'io_buffer' label to DEFINE_*_PARAMS"
.endif
.proc name
param_count: .byte 3
pathname: .addr pn
io_buffer: .addr io
.ifnblank rn
ref_num: .byte rn
.else
ref_num: .byte 0
.endif
.endproc
.endmacro
.macro DEFINE_READ_PARAMS name, db, rc
.proc name
param_count: .byte 4
ref_num: .byte 0
data_buffer: .addr db
request_count: .word rc
trans_count: .word 0
.endproc
.endmacro
.macro DEFINE_WRITE_PARAMS name, db, rc
.proc name
param_count: .byte 4
ref_num: .byte 0
data_buffer: .addr db
request_count: .word rc
trans_count: .word 0
.endproc
.endmacro
.macro DEFINE_CLOSE_PARAMS name
.proc name
param_count: .byte 1
ref_num: .byte 0
.endproc
.endmacro
.macro DEFINE_FLUSH_PARAMS name
.proc name
param_count: .byte 1
ref_num: .byte 0
.endproc
.endmacro
.macro DEFINE_GET_FILE_INFO_PARAMS name, pn
.if .xmatch(.string(pn), "pathname")
;; If 'pathname' is passed then expansion yields a circular reference.
.error "Can't pass 'pathname' label to DEFINE_*_PARAMS"
.endif
.proc name
param_count: .byte $A
pathname: .addr pn
access: .byte 0
file_type: .byte 0
aux_type: .word 0
storage_type: .byte 0
blocks_used: .word 0
mod_date: .word 0
mod_time: .word 0
create_date: .word 0
create_time: .word 0
.endproc
.endmacro
.macro DEFINE_SET_MARK_PARAMS name, pos
.proc name
param_count: .byte 2
ref_num: .byte 0
position: .faraddr pos
.endproc
.endmacro
.macro DEFINE_ON_LINE_PARAMS name, un, db
.proc name
param_count: .byte 2
.ifnblank un
unit_num: .byte un
.else
unit_num: .byte 0
.endif
data_buffer: .addr db
.endproc
.endmacro
.macro DEFINE_READ_BLOCK_PARAMS name, db, bn
.proc name
param_count: .byte 3
unit_num: .byte 0
data_buffer: .addr db
block_num: .word bn
.endproc
.endmacro
.macro DEFINE_WRITE_BLOCK_PARAMS name, db, bn
.proc name
param_count: .byte 3
unit_num: .byte 0
data_buffer: .addr db
block_num: .word bn
.endproc
.endmacro
.macro DEFINE_ALLOC_INTERRUPT_PARAMS name, ic
.proc alloc_interrupt_params
param_count: .byte 2
int_num: .byte 0
int_code: .addr ic
.endproc
.endmacro
.macro DEFINE_DEALLOC_INTERRUPT_PARAMS name
.proc dealloc_interrupt_params
param_count: .byte 1
int_num: .byte 0
.endproc
.endmacro
.macro DEFINE_QUIT_PARAMS name, arg1, arg2
.proc name
param_count: .byte 4
.ifnblank arg1
.byte arg1
.else
.byte 0
.endif
.ifnblank arg2
.word arg2
.else
.word 0
.endif
.byte 0
.word 0
.endproc
.endmacro
.macro DEFINE_SET_PREFIX_PARAMS name, pn
.if .xmatch(.string(pn), "pathname")
;; If 'pathname' is passed then expansion yields a circular reference.
.error "Can't pass 'pathname' label to DEFINE_*_PARAMS"
.endif
.proc name
param_count: .byte 1
pathname: .addr pn
.endproc
.endmacro
.macro DEFINE_GET_PREFIX_PARAMS name, pn
.if .xmatch(.string(pn), "pathname")
;; If 'pathname' is passed then expansion yields a circular reference.
.error "Can't pass 'pathname' label to DEFINE_*_PARAMS"
.endif
.proc name
param_count: .byte 1
pathname: .addr pn
.endproc
.endmacro
.macro DEFINE_DESTROY_PARAMS name, pn
.if .xmatch(.string(pn), "pathname")
;; If 'pathname' is passed then expansion yields a circular reference.
.error "Can't pass 'pathname' label to DEFINE_*_PARAMS"
.endif
.proc name
param_count: .byte 1
pathname: .addr pn
.endproc
.endmacro
.macro DEFINE_CREATE_PARAMS name, pn, ac, ft, at, st
.if .xmatch(.string(pn), "pathname")
;; If 'pathname' is passed then expansion yields a circular reference.
.error "Can't pass 'pathname' label to DEFINE_*_PARAMS"
.endif
.proc name
param_count: .byte 7
pathname: .addr pn
.ifnblank ac
access: .byte ac
.else
access: .byte 0
.endif
.ifnblank ft
file_type: .byte ft
.else
file_type: .byte 0
.endif
.ifnblank at
aux_type: .word at
.else
aux_type: .word 0
.endif
.ifnblank st
storage_type: .byte st
.else
storage_type: .byte 0
.endif
create_date: .word 0
create_time: .word 0
.endproc
.endmacro
.macro DEFINE_SET_EOF_PARAMS name, eo
.proc name
param_count: .byte 2
ref_num: .byte 0
eof: .faraddr eo
.endproc
.endmacro
.macro DEFINE_GET_EOF_PARAMS name
.proc name
param_count: .byte 2
ref_num: .byte 0
eof: .faraddr 0
.endproc
.endmacro
.macro DEFINE_RENAME_PARAMS name, pn, np
.if .xmatch(.string(pn), "pathname")
;; If 'pathname' is passed then expansion yields a circular reference.
.error "Can't pass 'pathname' label to DEFINE_*_PARAMS"
.endif
.proc name
param_count: .byte 2
pathname: .addr pn
new_pathname: .addr np
.endproc
.endmacro