a2d/inc/prodos.inc

490 lines
12 KiB
PHP
Raw Normal View History

2018-02-27 04:13:18 +00:00
;;; ============================================================
;;;
;;; ProDOS MLI
2018-02-27 04:13:18 +00:00
;;;
;;; ============================================================
;;; Entry point / Global Page
2018-01-06 05:03:10 +00:00
MLI := $BF00 ; Entry point
2018-11-12 03:11:44 +00:00
DATETIME := $BF06 ; JMP to clock routine
DEVADR := $BF10 ; Device driver addresses ($BF10-$BF2F)
NODEV := $BF10 ; "No Device Connected" entry (slot 0)
2018-01-06 05:03:10 +00:00
DEVNUM := $BF30 ; Most recent accessed device
DEVCNT := $BF31 ; Number of on-line devices minus 1
2018-11-12 03:11:44 +00:00
DEVLST := $BF32 ; Up to 14 units ($BF32-$BF3F)
2018-01-06 05:03:10 +00:00
BITMAP := $BF58 ; System memory bitmap
BITMAP_SIZE = $18 ; Bits for pages $00 to $BF
2018-01-06 05:03:10 +00:00
DATELO := $BF90 ; Date lo
DATEHI := $BF91 ; Date hi
TIMELO := $BF92 ; Time lo
TIMEHI := $BF93 ; Time hi
2018-03-04 05:33:40 +00:00
LEVEL := $BF94 ; File level
2018-01-06 05:03:10 +00:00
MACHID := $BF98 ; Machine ID
SLTBYT := $BF99 ; '1' bits indicate rom in slot (bit#)
2018-04-04 04:26:13 +00:00
IVERSION := $BFFD ; Interpreter Version
KVERSION := $BFFF ; ProDOS Kernel Version
2017-09-13 15:09:33 +00:00
;;; Patch Locations
SELECTOR := $D100
BLOCK_SIZE = $200
2018-03-07 16:12:30 +00:00
2018-02-27 04:13:18 +00:00
;;; ============================================================
2018-01-06 05:03:10 +00:00
;;; MLI Calls
2018-02-27 04:13:18 +00:00
;;; ============================================================
2018-01-06 05:03:10 +00:00
;;; 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
2018-01-06 05:03:10 +00:00
;;; 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
2018-01-06 05:03:10 +00:00
;;; System Calls
GET_TIME = $82
ALLOC_INTERRUPT = $40
DEALLOC_INTERRUPT = $41
QUIT = $65
2018-01-06 05:03:10 +00:00
;;; Direct Disk Access Commands
READ_BLOCK = $80
WRITE_BLOCK = $81
2018-02-27 04:13:18 +00:00
;;; ============================================================
2018-01-18 17:32:25 +00:00
;;; Device Types (low nibble of unit number in DEVLST)
2018-02-27 04:13:18 +00:00
;;; ============================================================
2018-01-06 05:03:10 +00:00
;;; As used by DeskTop; these are not actually correct...
DT_DISKII = $0
DT_PROFILE = $4
DT_REMOVABLE = $B
DT_RAM = $F
2018-01-06 05:03:10 +00:00
2018-01-18 17:32:25 +00:00
;;; 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..."
2018-02-27 04:13:18 +00:00
;;; ============================================================
2017-09-28 15:45:05 +00:00
;;; File Types
2018-02-27 04:13:18 +00:00
;;; ============================================================
2018-01-06 05:03:10 +00:00
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
2017-09-28 15:45:05 +00:00
2018-03-06 05:27:41 +00:00
;;; ============================================================
;;; Access
;;; ============================================================
ACCESS_DEFAULT = %11000011
ACCESS_LOCKED = %00100001
2018-03-06 05:27:41 +00:00
2018-02-27 04:13:18 +00:00
;;; ============================================================
2018-01-20 03:41:20 +00:00
;;; Storage Types
2018-02-27 04:13:18 +00:00
;;; ============================================================
2018-01-20 03:41:20 +00:00
ST_STANDARD_FILE = $01
ST_LINKED_DIRECTORY = $0D
ST_VOLUME_DIRECTORY = $0F
2018-01-20 03:41:20 +00:00
2018-02-27 04:13:18 +00:00
;;; ============================================================
2018-02-13 05:14:23 +00:00
;;; Errors
2018-02-27 04:13:18 +00:00
;;; ============================================================
2018-02-13 05:14:23 +00:00
ERR_DEVICE_NOT_CONNECTED = $28
ERR_WRITE_PROTECTED = $2B
ERR_INVALID_PATHNAME = $40
ERR_INVALID_REFERENCE = $43
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
ERR_ACCESS_ERROR = $4E
ERR_DUPLICATE_VOLUME = $57
2018-02-13 05:14:23 +00:00
;;; ============================================================
;;; Misc Structures
;;; ============================================================
.struct DateTime
datelo .byte
datehi .byte
timelo .byte
timehi .byte
.endstruct
2018-04-21 04:58:15 +00:00
;;; ============================================================
;;; Directory Structures
;;; ============================================================
STORAGE_TYPE_MASK = $F0
NAME_LENGTH_MASK = $0F
2018-04-21 04:58:15 +00:00
;;; Volume Directory Header structure
.struct VolumeDirectoryHeader
prev_block .word
next_block .word
storage_type_name_length .byte
file_name .byte 15
reserved .byte 8
creation_date .word
creation_time .word
version .byte
min_version .byte
access .byte
entry_length .byte
entries_per_block .byte
file_count .word
;; same through here ---------
bit_map_pointer .word
total_blocks .word
.endstruct
.assert .sizeof(VolumeDirectoryHeader) = $2B, error, "incorrect struct size"
;;; Subdirectory Header structure
.struct SubdirectoryHeader
prev_block .word
next_block .word
storage_type_name_length .byte
file_name .byte 15
reserved .byte 8
creation_date .word
creation_time .word
version .byte
min_version .byte
access .byte
entry_length .byte
entries_per_block .byte
file_count .word
;; same through here ---------
parent_pointer .word
parent_entry_number .byte
parent_entry_length .byte
.endstruct
.assert .sizeof(SubdirectoryHeader) = $2B, error, "incorrect struct size"
;; File Entry structure
.struct FileEntry
storage_type_name_length .byte
file_name .byte 15
file_type .byte
key_pointer .word
blocks_used .word
eof .faraddr
creation_date .word
creation_time .word
version .byte
min_version .byte
access .byte
aux_type .word
mod_date .word
mod_time .word
header_pointer .word
.endstruct
.assert .sizeof(FileEntry) = $27, error, "incorrect struct size"
2018-12-06 03:35:04 +00:00
;;; ============================================================
;;; ProDOS Driver Protocol
;;; ============================================================
;;; Addresses for command parameters
DRIVER_COMMAND := $42
DRIVER_UNIT_NUMBER := $43
DRIVER_BUFFER := $44
DRIVER_BLOCK_NUMBER := $46
;;; Commands
DRIVER_COMMAND_STATUS = 0
DRIVER_COMMAND_READ = 1
DRIVER_COMMAND_WRITE = 2
DRIVER_COMMAND_FORMAT = 3
2018-12-06 03:35:04 +00:00
2018-04-21 04:58:15 +00:00
2018-02-27 04:13:18 +00:00
;;; ============================================================
;;; Macros
2018-02-27 04:13:18 +00:00
;;; ============================================================
2018-01-06 05:03:10 +00:00
.macro MLI_CALL op, addr
jsr MLI
.byte op
.addr addr
.endmacro
2018-01-05 05:57:50 +00:00
2018-02-28 02:38:18 +00:00
.macro DEFINE_OPEN_PARAMS name, pn, io, rn
2018-02-26 04:28:23 +00:00
.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
2018-03-07 18:39:36 +00:00
.if .xmatch(.string(io), "io_buffer")
.error "Can't pass 'io_buffer' label to DEFINE_*_PARAMS"
.endif
2018-02-26 04:28:23 +00:00
.proc name
param_count: .byte 3
pathname: .addr pn
io_buffer: .addr io
2018-02-28 02:38:18 +00:00
.ifnblank rn
ref_num: .byte rn
.else
2018-02-26 04:28:23 +00:00
ref_num: .byte 0
2018-02-28 02:38:18 +00:00
.endif
2018-02-26 04:28:23 +00:00
.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
2018-02-26 05:03:58 +00:00
.macro DEFINE_GET_FILE_INFO_PARAMS name, pn
2018-02-26 04:28:23 +00:00
.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
2018-02-26 05:03:58 +00:00
pathname: .addr pn
2018-02-26 04:28:23 +00:00
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
2018-02-26 05:03:58 +00:00
.macro DEFINE_ON_LINE_PARAMS name, un, db
2018-02-26 04:28:23 +00:00
.proc name
param_count: .byte 2
2018-02-26 05:03:58 +00:00
.ifnblank un
unit_num: .byte un
.else
2018-02-26 04:28:23 +00:00
unit_num: .byte 0
2018-02-26 05:03:58 +00:00
.endif
2018-02-26 04:28:23 +00:00
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
2018-05-14 07:10:39 +00:00
.macro DEFINE_QUIT_PARAMS name, ext, pathname
2018-02-26 04:28:23 +00:00
.proc name
2018-02-28 02:38:18 +00:00
param_count: .byte 4
2018-05-14 07:10:39 +00:00
.ifnblank ext
.byte ext
2018-02-28 02:38:18 +00:00
.else
.byte 0
.endif
2018-05-14 07:10:39 +00:00
.ifnblank pathname
.word pathname
2018-02-28 02:38:18 +00:00
.else
.word 0
.endif
.byte 0
.word 0
2018-02-26 04:28:23 +00:00
.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
2018-02-26 05:03:58 +00:00
.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
2018-02-26 04:28:23 +00:00
param_count: .byte 1
pathname: .addr pn
.endproc
.endmacro
2018-02-26 05:03:58 +00:00
.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
2018-02-27 04:51:23 +00:00
.macro DEFINE_GET_EOF_PARAMS name
.proc name
param_count: .byte 2
ref_num: .byte 0
eof: .faraddr 0
.endproc
.endmacro
2018-02-26 05:03:58 +00:00
.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
2018-02-27 04:13:18 +00:00
.endmacro