mirror of
https://github.com/mi57730/a2d.git
synced 2025-02-21 23:29:00 +00:00
Correct docs for some DeskTop icon APIs, and improve resilience of some of the APIs to having atypical grafports selected when called.
505 lines
13 KiB
PHP
505 lines
13 KiB
PHP
;;; ============================================================
|
|
;;;
|
|
;;; ProDOS MLI
|
|
;;;
|
|
;;; ============================================================
|
|
|
|
;;; Entry point / Global Page
|
|
MLI := $BF00 ; Entry point
|
|
DATETIME := $BF06 ; JMP to clock routine
|
|
DEVADR := $BF10 ; Device driver addresses ($BF10-$BF2F)
|
|
NODEV := $BF10 ; "No Device Connected" entry (slot 0)
|
|
DEVNUM := $BF30 ; Most recent accessed device
|
|
DEVCNT := $BF31 ; Number of on-line devices minus 1
|
|
DEVLST := $BF32 ; Up to 14 units ($BF32-$BF3F)
|
|
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
|
|
SLTBYT := $BF99 ; '1' bits indicate rom in slot (bit#)
|
|
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)
|
|
;;; ============================================================
|
|
|
|
;;; As used by DeskTop; these are not actually correct...
|
|
|
|
DT_DISKII = $0
|
|
DT_PROFILE = $4
|
|
DT_REMOVABLE = $B
|
|
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 ; ASCII Text File *
|
|
FT_BINARY = $06 ; Generic Binary File *
|
|
FT_FONT = $07 ; Font File
|
|
FT_GRAPHICS = $08 ; Graphics File
|
|
FT_DIRECTORY = $0F ; Directory *
|
|
FT_ADB = $19 ; AppleWorks Database *
|
|
FT_AWP = $1A ; AppleWorks Word Processing *
|
|
FT_ASP = $1B ; AppleWorks Spreadsheet *
|
|
FT_SRC = $B0 ; IIgs system type; re-used?
|
|
FT_S16 = $B3 ; IIgs Application Program
|
|
FT_PAS = $EF ; Pascal Area *
|
|
FT_CMD = $F0 ; ProDOS Command File *
|
|
FT_INT = $FA ; Integer BASIC Program *
|
|
FT_IVR = $FB ; Integer BASIC Variable File *
|
|
FT_BASIC = $FC ; Applesoft BASIC Program *
|
|
FT_VAR = $FD ; Applesoft BASIC Variable File *
|
|
FT_REL = $FE ; EDASM/Contiki Relocatable File *
|
|
FT_SYSTEM = $FF ; ProDOS System File *
|
|
|
|
;;; Types marked with * are known to BASIC.SYSTEM and have an
|
|
;;; associated three-letter abbreviation.
|
|
|
|
;;; ============================================================
|
|
;;; Access
|
|
;;; ============================================================
|
|
|
|
ACCESS_DEFAULT = %11000011
|
|
ACCESS_LOCKED = %00100001
|
|
|
|
;;; ============================================================
|
|
;;; Storage Types
|
|
;;; ============================================================
|
|
|
|
ST_STANDARD_FILE = $01
|
|
ST_LINKED_DIRECTORY = $0D
|
|
ST_VOLUME_DIRECTORY = $0F
|
|
|
|
;;; ============================================================
|
|
;;; Errors
|
|
;;; ============================================================
|
|
|
|
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
|
|
ERR_NETWORK_ERROR = $88
|
|
|
|
;;; ============================================================
|
|
;;; Misc Structures
|
|
;;; ============================================================
|
|
|
|
.struct DateTime
|
|
datelo .byte
|
|
datehi .byte
|
|
timelo .byte
|
|
timehi .byte
|
|
.endstruct
|
|
|
|
;;; ============================================================
|
|
;;; Directory Structures
|
|
;;; ============================================================
|
|
|
|
STORAGE_TYPE_MASK = $F0
|
|
NAME_LENGTH_MASK = $0F
|
|
|
|
;;; 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"
|
|
|
|
;;; ============================================================
|
|
;;; 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
|
|
|
|
|
|
;;; ============================================================
|
|
;;; Macros
|
|
;;; ============================================================
|
|
|
|
.macro MLI_CALL op, addr
|
|
jsr MLI
|
|
.byte op
|
|
.addr addr
|
|
.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, ext, pathname
|
|
.proc name
|
|
param_count: .byte 4
|
|
.ifnblank ext
|
|
.byte ext
|
|
.else
|
|
.byte 0
|
|
.endif
|
|
.ifnblank pathname
|
|
.word pathname
|
|
.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
|