mirror of
https://github.com/a2stuff/prodos-drivers.git
synced 2025-01-08 08:29:57 +00:00
initial snapshot
This commit is contained in:
commit
fbd79badee
29
Makefile
Normal file
29
Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
CC65 = ~/dev/cc65/bin
|
||||
CAFLAGS = --target apple2enh --list-bytes 0
|
||||
CCFLAGS = --config apple2-asm.cfg
|
||||
|
||||
OUTDIR = out
|
||||
|
||||
HEADERS = $(wildcard inc/*.inc)
|
||||
|
||||
TARGETS = $(OUTDIR)/ram.system.SYS
|
||||
|
||||
.PHONY: clean all
|
||||
all: $(OUTDIR) $(TARGETS)
|
||||
|
||||
$(OUTDIR):
|
||||
mkdir -p $(OUTDIR)
|
||||
|
||||
clean:
|
||||
rm -f $(OUTDIR)/*.o
|
||||
rm -f $(OUTDIR)/*.list
|
||||
rm -f $(TARGETS)
|
||||
|
||||
$(OUTDIR)/%.o: %.s $(HEADERS)
|
||||
$(CC65)/ca65 $(CAFLAGS) --listing $(basename $@).list -o $@ $<
|
||||
|
||||
# System Files .SYS
|
||||
$(OUTDIR)/%.SYS: $(OUTDIR)/%.o
|
||||
$(CC65)/ld65 $(CCFLAGS) -o '$@' $<
|
||||
xattr -wx prodos.AuxType '00 20' $@
|
27
inc/apple2.inc
Normal file
27
inc/apple2.inc
Normal file
@ -0,0 +1,27 @@
|
||||
;;; ============================================================
|
||||
;;;
|
||||
;;; More Apple II Symbols
|
||||
;;;
|
||||
;;; ============================================================
|
||||
|
||||
;;; Soft Switches
|
||||
|
||||
ROMIN2 := $C082
|
||||
|
||||
;;; ============================================================
|
||||
;;; Aux Memory / Extended 80 Column Card
|
||||
;;; ============================================================
|
||||
|
||||
;;; Softswitches
|
||||
RAMRDOFF := $C002
|
||||
RAMRDON := $C003
|
||||
RAMWRTOFF := $C004
|
||||
RAMWRTON := $C005
|
||||
ALTZPOFF := $C008
|
||||
ALTZPON := $C009
|
||||
|
||||
CLR80VID := $C00C
|
||||
SET80VID := $C00D
|
||||
RDALTZP := $C016
|
||||
RD80STORE := $C018
|
||||
RDPAGE2 := $C01C
|
101
inc/macros.inc
Normal file
101
inc/macros.inc
Normal file
@ -0,0 +1,101 @@
|
||||
;;; ============================================================
|
||||
;;; Generic Macros
|
||||
;;; ============================================================
|
||||
|
||||
.define _is_immediate(arg) (.match (.mid (0, 1, {arg}), #))
|
||||
.define _is_register(arg) (.match ({arg}, x) .or .match ({arg}, y))
|
||||
.define _is_y_register(arg) (.match ({arg}, y))
|
||||
.define _immediate_value(arg) (.right (.tcount ({arg})-1, {arg}))
|
||||
|
||||
.macro _op_lo op, arg
|
||||
.if _is_immediate {arg}
|
||||
op #<_immediate_value {arg}
|
||||
.else
|
||||
op arg
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
.macro _op_hi op, arg
|
||||
.if _is_immediate {arg}
|
||||
op #>_immediate_value {arg}
|
||||
.else
|
||||
op arg+1
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
;;; ============================================================
|
||||
;;; Length-prefixed string
|
||||
;;;
|
||||
;;; Can include control chars by using:
|
||||
;;;
|
||||
;;; PASCAL_STRING {"abc",$0D,"def"}
|
||||
|
||||
.macro PASCAL_STRING str,res
|
||||
.local data
|
||||
.local end
|
||||
.byte end - data
|
||||
data: .byte str
|
||||
end:
|
||||
.if .paramcount > 1
|
||||
.res res - (end - data), 0
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
|
||||
;;; ============================================================
|
||||
;;; Common patterns
|
||||
|
||||
.macro copy arg1, arg2, arg3, arg4
|
||||
.if _is_register {arg2} && _is_register {arg4}
|
||||
;; indexed load/indexed store
|
||||
lda arg1,arg2
|
||||
sta arg3,arg4
|
||||
.elseif _is_register {arg2}
|
||||
;; indexed load variant (arg2 is x or y)
|
||||
lda arg1,arg2
|
||||
sta arg3
|
||||
.elseif _is_register {arg3}
|
||||
;; indexed store variant (arg3 is x or y)
|
||||
lda arg1
|
||||
sta arg2,arg3
|
||||
.else
|
||||
lda arg1
|
||||
sta arg2
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
|
||||
|
||||
;;; Copy 16-bit value
|
||||
;;; copy16 #$1111, $2222 ; immediate, absolute
|
||||
;;; copy16 $1111, $2222 ; absolute, absolute
|
||||
;;; copy16 $1111,x, $2222 ; indirect load, absolute store
|
||||
;;; copy16 $1111, $2222,x ; absolute load, indirect store
|
||||
;;; copy16 $1111,x $2222,x ; indirect load, indirect store
|
||||
;;; copy16 #$1111, $2222,x ; immediate load, indirect store
|
||||
.macro copy16 arg1, arg2, arg3, arg4
|
||||
.if _is_register {arg2} && _is_register {arg4}
|
||||
;; indexed load/indexed store
|
||||
lda arg1,arg2
|
||||
sta arg3,arg4
|
||||
lda arg1+1,arg2
|
||||
sta arg3+1,arg4
|
||||
.elseif _is_register {arg2}
|
||||
;; indexed load variant (arg2 is x or y)
|
||||
lda arg1,arg2
|
||||
sta arg3
|
||||
lda arg1+1,arg2
|
||||
sta arg3+1
|
||||
.elseif _is_register {arg3}
|
||||
;; indexed store variant (arg3 is x or y)
|
||||
_op_lo lda, {arg1}
|
||||
sta arg2,arg3
|
||||
_op_hi lda, {arg1}
|
||||
sta arg2+1,arg3
|
||||
.else
|
||||
_op_lo lda, {arg1}
|
||||
sta arg2
|
||||
_op_hi lda, {arg1}
|
||||
sta arg2+1
|
||||
.endif
|
||||
.endmacro
|
473
inc/prodos.inc
Normal file
473
inc/prodos.inc
Normal file
@ -0,0 +1,473 @@
|
||||
;;; ============================================================
|
||||
;;;
|
||||
;;; 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
|
||||
|
||||
;;; ============================================================
|
||||
;;; File Types
|
||||
;;; ============================================================
|
||||
|
||||
FT_TYPELESS = $00
|
||||
FT_BAD = $01
|
||||
FT_TEXT = $04 ; ASCII Text File *
|
||||
FT_BINARY = $06 ; Generic Binary 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
|
||||
|
||||
;;; ============================================================
|
||||
;;; 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
|
780
ram.system.s
Normal file
780
ram.system.s
Normal file
@ -0,0 +1,780 @@
|
||||
;;; Disassembly of "RAM.SYSTEM" found on Mouse Desk 2.0 images
|
||||
|
||||
.setcpu "6502"
|
||||
|
||||
.include "apple2.inc"
|
||||
.include "inc/macros.inc"
|
||||
.include "inc/apple2.inc"
|
||||
.include "inc/prodos.inc"
|
||||
.include "opcodes.inc"
|
||||
|
||||
|
||||
|
||||
zpproc_addr := $B0
|
||||
zpproc_relay_addr := $2D0
|
||||
chain_path := $280
|
||||
|
||||
driver_target = $FF00
|
||||
|
||||
kMaxUsableBanks = 24 ; Why is this capped so low???
|
||||
; (driver has room for another ~20?)
|
||||
|
||||
;;; ============================================================
|
||||
;;; RamWorks I/O
|
||||
|
||||
RWBANK := $C073
|
||||
|
||||
;;; ============================================================
|
||||
|
||||
.org $2000
|
||||
|
||||
jmp relocate_chain
|
||||
|
||||
;;; ============================================================
|
||||
|
||||
;; Interpreter signature
|
||||
.byte $EE,$EE
|
||||
|
||||
;; Buffer size
|
||||
.byte 64
|
||||
|
||||
chain_path_orig:
|
||||
PASCAL_STRING "/MOUSE.DESK/MD.SYSTEM", 63
|
||||
|
||||
.byte $FF, $FF
|
||||
|
||||
;;; Configuration Parameters
|
||||
|
||||
banks_to_reserve: .byte 0 ; banks to reserve (e.g. for AppleWorks)
|
||||
|
||||
slot: .byte 3 ; S3D1; could be $B for S3D2
|
||||
|
||||
|
||||
;;; ============================================================
|
||||
;;; Chain to the next system file (path above)
|
||||
;;; ============================================================
|
||||
;;;
|
||||
;;; Relocated to $BD00 to leave room at $2000 for the sys file.
|
||||
|
||||
chain_target = $BD00
|
||||
|
||||
saved_org .set *
|
||||
.proc chain
|
||||
.org ::chain_target
|
||||
|
||||
;; Copy path to $280
|
||||
ldx chain_path_orig
|
||||
beq quit
|
||||
: lda chain_path_orig,x
|
||||
sta chain_path,x
|
||||
dex
|
||||
bpl :-
|
||||
|
||||
MLI_CALL GET_FILE_INFO, get_file_info_params
|
||||
bcs quit
|
||||
|
||||
ldx get_file_info_params_file_type
|
||||
inx
|
||||
bne quit
|
||||
MLI_CALL OPEN, open_params
|
||||
bcs close
|
||||
lda open_params_ref_num
|
||||
sta read_params_ref_num
|
||||
sta get_eof_params_ref_num
|
||||
|
||||
MLI_CALL GET_EOF, get_eof_params
|
||||
bcs close
|
||||
|
||||
;; Ensure there is room for chained file
|
||||
lda get_eof_params_eof+2
|
||||
bne close
|
||||
lda get_eof_params_eof+1
|
||||
cmp #$98 ; $2000+$97FF=$B7FF (have up to $BF00)
|
||||
bcs close
|
||||
sta read_params_request_count+1
|
||||
lda get_eof_params_eof
|
||||
sta read_params_request_count
|
||||
|
||||
;; Read
|
||||
MLI_CALL READ, read_params
|
||||
bcs close
|
||||
|
||||
;; Close
|
||||
MLI_CALL CLOSE, close_params
|
||||
bcs close
|
||||
|
||||
;; Invoke it
|
||||
jmp sys_target
|
||||
|
||||
close: MLI_CALL CLOSE, close_params
|
||||
|
||||
quit: MLI_CALL QUIT, quit_params
|
||||
|
||||
DEFINE_QUIT_PARAMS quit_params
|
||||
|
||||
sys_target := $2000
|
||||
io_buff := $1C00
|
||||
|
||||
DEFINE_GET_FILE_INFO_PARAMS get_file_info_params, chain_path
|
||||
get_file_info_params_file_type := get_file_info_params::file_type
|
||||
|
||||
DEFINE_OPEN_PARAMS open_params, chain_path, io_buff
|
||||
open_params_ref_num := open_params::ref_num
|
||||
|
||||
DEFINE_CLOSE_PARAMS close_params
|
||||
|
||||
DEFINE_READ_PARAMS read_params, sys_target, 0
|
||||
read_params_ref_num := read_params::ref_num
|
||||
read_params_request_count := read_params::request_count
|
||||
|
||||
DEFINE_GET_EOF_PARAMS get_eof_params
|
||||
get_eof_params_ref_num := get_eof_params::ref_num
|
||||
get_eof_params_eof := get_eof_params::eof
|
||||
|
||||
.endproc
|
||||
.assert .sizeof(chain) <= $100, error, "Chain routine must fit in one page"
|
||||
.org (saved_org + .sizeof(chain))
|
||||
|
||||
;;; ============================================================
|
||||
;;; Copy chain code to final location
|
||||
|
||||
.proc relocate_chain
|
||||
ldy #$00
|
||||
: lda chain,y
|
||||
sta chain_target,y
|
||||
iny
|
||||
bne :-
|
||||
;; fall through
|
||||
.endproc
|
||||
|
||||
;;; ============================================================
|
||||
;;; Install the driver
|
||||
|
||||
.proc install_driver
|
||||
|
||||
sta CLR80COL
|
||||
ldy #0
|
||||
sty RWBANK
|
||||
sta ALTZPON ; Use ZP to probe banks
|
||||
|
||||
;; Clear map1 / map2 (256 bytes) to $FF
|
||||
lda #$FF
|
||||
: sta map1,y
|
||||
iny
|
||||
bne :-
|
||||
|
||||
;; Stash first two bytes of each bank (128 possible banks)
|
||||
: sty RWBANK
|
||||
lda $00
|
||||
sta stash_00,y
|
||||
lda $01
|
||||
sta stash_01,y
|
||||
iny
|
||||
bpl :-
|
||||
dey
|
||||
|
||||
;; Write bank num/complement at $0/$1
|
||||
: sty RWBANK
|
||||
sty $00
|
||||
tya
|
||||
eor #$FF
|
||||
sta $01
|
||||
dey
|
||||
bne :-
|
||||
|
||||
;; Y = 0
|
||||
|
||||
;; Reset signature bytes on main/aux banks
|
||||
sty RWBANK
|
||||
sty $00
|
||||
sty $01
|
||||
sta ALTZPOFF
|
||||
sty $00
|
||||
sty $01
|
||||
sta ALTZPON
|
||||
|
||||
lda banks_to_reserve
|
||||
sta reserved_banks
|
||||
|
||||
;;; ============================================================
|
||||
|
||||
;; Copy into every bank
|
||||
ldy #1
|
||||
bank_loop:
|
||||
;; Check bank for signature bytes (bank num/complement at $0/$1)
|
||||
sty RWBANK
|
||||
cpy $00
|
||||
bne next_bank
|
||||
tya
|
||||
eor #$FF
|
||||
eor $01
|
||||
bne next_bank
|
||||
cpy $00 ; Bank 0 (aux) is reserved for 128k apps
|
||||
bne next_bank
|
||||
|
||||
;; Flag as available in map2
|
||||
;; (map2,N = N if available, $FF otherwise)
|
||||
tya
|
||||
sta map2,y
|
||||
|
||||
;; Skip over reserved banks, then start storing them in the map
|
||||
ldx reserved_banks
|
||||
bne :+
|
||||
sta first_used_bank
|
||||
: dec reserved_banks
|
||||
bpl next_bank
|
||||
sta map1,y
|
||||
;; (map1,N = N if available, $FF otherwise - also???)
|
||||
|
||||
;; Copy helper proc into bank's ZP
|
||||
ldx #sizeof_zpproc
|
||||
: lda zpproc-1,x
|
||||
sta zpproc_addr-1,x
|
||||
dex
|
||||
bne :-
|
||||
|
||||
next_bank:
|
||||
iny
|
||||
bpl bank_loop
|
||||
|
||||
;;; ============================================================
|
||||
|
||||
;; Y = $80
|
||||
|
||||
;; Restore stashed $0/$1 bytes of back
|
||||
;; (except first, in first_used_bank ???)
|
||||
loop0: lda map2-1,y
|
||||
bmi :+
|
||||
cmp first_used_bank
|
||||
beq :+
|
||||
sta RWBANK
|
||||
lda stash_00-1,y
|
||||
sta $00
|
||||
lda stash_01-1,y
|
||||
sta $01
|
||||
: dey
|
||||
bne loop0
|
||||
|
||||
;; Y = 0
|
||||
sty RWBANK
|
||||
sty $00
|
||||
|
||||
;; Count number of available banks, and populate
|
||||
;; driver_bank_list with list of banks.
|
||||
ldx #$FF
|
||||
loop1: inx
|
||||
cpx #kMaxUsableBanks
|
||||
bcs break
|
||||
loop2: iny
|
||||
bmi break
|
||||
lda map1,y
|
||||
bmi loop2
|
||||
sta driver_bank_list,x
|
||||
bpl loop1
|
||||
break:
|
||||
;; Patch driver with block-specific data
|
||||
;; X = number of available banks
|
||||
|
||||
;; Compute number of blocks
|
||||
txa
|
||||
lsr a
|
||||
sta vol_dir_header+VolumeDirectoryHeader::total_blocks+1
|
||||
ror vol_dir_header+VolumeDirectoryHeader::total_blocks
|
||||
|
||||
stx driver_block_x ; num banks
|
||||
dex ; -1
|
||||
stx num_banks_minus_one
|
||||
|
||||
bmi fail ; 0 banks? give up.
|
||||
|
||||
lda vol_dir_header+VolumeDirectoryHeader::total_blocks
|
||||
sec
|
||||
sbc driver_block_x
|
||||
and #$F8
|
||||
sta vol_dir_header+VolumeDirectoryHeader::total_blocks
|
||||
sta driver_blocks_lo
|
||||
bcs :+
|
||||
dec vol_dir_header+VolumeDirectoryHeader::total_blocks+1
|
||||
: lda vol_dir_header+VolumeDirectoryHeader::total_blocks+1
|
||||
sta driver_blocks_hi
|
||||
|
||||
lda driver_bank_list
|
||||
sta RWBANK
|
||||
lda $00
|
||||
beq fail
|
||||
|
||||
;; Check for ZP signature - if not found, set it and install.
|
||||
ldx #2
|
||||
: lda L23A0,x
|
||||
cmp $06,x
|
||||
bne set_sig
|
||||
dex
|
||||
bpl :-
|
||||
|
||||
bit BUTN1 ; escape hatch in case of loop ???
|
||||
bmi L21F0
|
||||
jmp do_install
|
||||
|
||||
fail: jmp do_chain
|
||||
|
||||
sloop: lda L23A0,x
|
||||
set_sig:
|
||||
sta $06,x
|
||||
dex
|
||||
bpl sloop
|
||||
|
||||
;;; ============================================================
|
||||
|
||||
;;; Prepare key blocks in
|
||||
|
||||
L21F0: sta ALTZPOFF
|
||||
|
||||
;; Stamp current date/time into vol_dir_header
|
||||
ldy #3
|
||||
: lda DATELO,y
|
||||
sta vol_dir_header+VolumeDirectoryHeader::creation_date,y
|
||||
dey
|
||||
bpl :-
|
||||
|
||||
;; Fill pages $06-$0F with 00-FF
|
||||
sta RAMWRTON
|
||||
iny
|
||||
tya
|
||||
: sta $0600,y
|
||||
sta $0700,y
|
||||
sta $0800,y
|
||||
sta $0900,y
|
||||
sta $0A00,y
|
||||
sta $0B00,y
|
||||
sta $0C00,y
|
||||
sta $0D00,y
|
||||
sta $0E00,y
|
||||
sta $0F00,y
|
||||
iny
|
||||
bne :-
|
||||
|
||||
;; Copy vol_dir_header into page $06
|
||||
ldy #.sizeof(VolumeDirectoryHeader)-1
|
||||
: lda vol_dir_header,y
|
||||
sta $0600,y
|
||||
dey
|
||||
bpl :-
|
||||
|
||||
ldy #$02
|
||||
sty $0800
|
||||
iny
|
||||
sty $0A00
|
||||
iny
|
||||
sty $0C00
|
||||
sty $0802
|
||||
iny
|
||||
sty $0A02
|
||||
|
||||
ptr := $3C
|
||||
lda vol_dir_header+VolumeDirectoryHeader::total_blocks
|
||||
sta ptr
|
||||
lda vol_dir_header+VolumeDirectoryHeader::total_blocks+1
|
||||
lsr a
|
||||
ror ptr
|
||||
lsr a
|
||||
ror ptr
|
||||
lsr a
|
||||
ror ptr
|
||||
clc
|
||||
adc #$0E
|
||||
sta ptr+1
|
||||
|
||||
ldy #0
|
||||
tya
|
||||
: sta (ptr),y
|
||||
lda ptr
|
||||
sec
|
||||
sbc #1
|
||||
sta ptr
|
||||
lda #$FF
|
||||
bcs :-
|
||||
dec ptr+1
|
||||
ldx ptr+1
|
||||
cpx #$0E
|
||||
bcs :-
|
||||
lda #$01
|
||||
sta $0E00
|
||||
|
||||
;;; ============================================================
|
||||
|
||||
do_install:
|
||||
lda #0
|
||||
sta RAMWRTOFF
|
||||
sta ALTZPOFF
|
||||
sta RWBANK
|
||||
bit LCBANK1
|
||||
bit LCBANK1
|
||||
|
||||
lda #OPC_CLD ; signature
|
||||
cmp driver_target
|
||||
beq copy_driver
|
||||
sta ALTZPON ; Maybe in AUX?
|
||||
cmp driver_target
|
||||
beq copy_driver
|
||||
cmp $DE00 ; ???
|
||||
beq copy_driver
|
||||
sta ALTZPOFF
|
||||
|
||||
;; Copy driver into place
|
||||
copy_driver:
|
||||
ldy #0
|
||||
: lda driver_src,y
|
||||
sta driver_target,y
|
||||
iny
|
||||
cpy #sizeof_driver
|
||||
bcc :-
|
||||
|
||||
;; Check if slot already has a device
|
||||
ldy DEVCNT
|
||||
: lda DEVLST,y
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
cmp slot
|
||||
beq install_device
|
||||
dey
|
||||
bpl :-
|
||||
|
||||
;; Shift devices up by one
|
||||
inc DEVCNT
|
||||
ldy DEVCNT
|
||||
: lda DEVLST-1,y
|
||||
sta DEVLST,y
|
||||
dey
|
||||
bne :-
|
||||
|
||||
;; Install device in ProDOS via DEVLST/DEVADR.
|
||||
;; (Y has index in DEVLST)
|
||||
install_device:
|
||||
lda slot
|
||||
asl a
|
||||
tax
|
||||
asl a
|
||||
asl a
|
||||
asl a
|
||||
sta on_line_params+1 ; unit_number
|
||||
ora #$0E ; $3E - signature byte used by DeskTop
|
||||
sta DEVLST,y
|
||||
copy16 #(driver_target+1), DEVADR,x
|
||||
|
||||
;; Did we install into S3D2?
|
||||
lda slot
|
||||
cmp #$0B ; Slot 3 Drive 2
|
||||
beq finish
|
||||
|
||||
;; No, so uninstall S3D2 (regular /RAM)
|
||||
ldy DEVCNT
|
||||
: lda DEVLST,y
|
||||
and #$F0
|
||||
cmp #$B0 ; Slot 3 drive 2 i.e. normal /RAM
|
||||
beq found
|
||||
dey
|
||||
bpl :-
|
||||
bmi finish ; always
|
||||
|
||||
;; Actually remove from DEVLST
|
||||
slot3d2_devadr := DEVADR + $10 + 3*2
|
||||
found: ldx slot3d2_devadr + 1
|
||||
inx
|
||||
bne finish
|
||||
: copy DEVLST+1,y, DEVLST,y
|
||||
iny
|
||||
cpy DEVCNT
|
||||
bcc :-
|
||||
beq :-
|
||||
dec DEVCNT
|
||||
copy16 NODEV, slot3d2_devadr ; clear driver
|
||||
|
||||
finish: bit ROMIN2
|
||||
MLI_CALL ON_LINE, on_line_params
|
||||
ldx #$00
|
||||
lda on_line_params_buffer
|
||||
ora L239F
|
||||
bne do_chain
|
||||
bcc do_chain
|
||||
copy #$FF, L239F
|
||||
sta ALTZPON
|
||||
copy driver_bank_list, RWBANK
|
||||
stx $06
|
||||
stx RWBANK
|
||||
stx vol_dir_header+VolumeDirectoryHeader::total_blocks
|
||||
jmp install_driver ; retry???
|
||||
|
||||
do_chain:
|
||||
sta ALTZPOFF
|
||||
jmp chain_target
|
||||
|
||||
;;; ============================================================
|
||||
;;; Installed on zero page of each bank at $B0
|
||||
|
||||
saved_org .set *
|
||||
.proc zpproc
|
||||
.org ::zpproc_addr
|
||||
|
||||
sta $E0 ; dst1 hi
|
||||
bcs :+
|
||||
sty $E0 ; dst1 hi
|
||||
tay
|
||||
: lda #$00
|
||||
sta RAMWRTON
|
||||
bcc :+
|
||||
txa
|
||||
ldx #$00
|
||||
sta RAMWRTOFF
|
||||
sta RAMRDON
|
||||
|
||||
;; One block = two pages
|
||||
: sty $DD ; src1 hi
|
||||
iny
|
||||
sty $E3 ; src2 hi
|
||||
|
||||
sta $DF ; dst1 lo
|
||||
sta $E5 ; dst2 lo
|
||||
|
||||
stx $DC ; src1 lo
|
||||
stx $E2 ; src2 lo
|
||||
|
||||
ldy $E0 ; dst1 hi
|
||||
iny
|
||||
sty $E6 ; dst2 hi
|
||||
|
||||
ldy #$00
|
||||
: lda $1000,y ; src1
|
||||
sta $1000,y ; dst1
|
||||
lda $1000,y ; src2
|
||||
sta $1000,y ; dst2
|
||||
iny
|
||||
bne :-
|
||||
|
||||
sta RAMWRTOFF
|
||||
sta RAMRDOFF
|
||||
clc
|
||||
bit $02E4
|
||||
rts
|
||||
.endproc
|
||||
sizeof_zpproc := .sizeof(zpproc)
|
||||
.org (saved_org + .sizeof(zpproc))
|
||||
|
||||
;;; ============================================================
|
||||
|
||||
on_line_params_buffer := $220
|
||||
DEFINE_ON_LINE_PARAMS on_line_params, $30, on_line_params_buffer
|
||||
|
||||
num_banks_minus_one:
|
||||
.byte 0
|
||||
|
||||
L239F: .byte 0
|
||||
L23A0: .byte $C7, $C5, $C2 ; signature sequence ???
|
||||
|
||||
;; Volume Directory Header
|
||||
.proc vol_dir_header
|
||||
.word 0 ; preceding block number
|
||||
.word $03 ; succeeding block number
|
||||
.byte ST_VOLUME_DIRECTORY << 4 | 3 ; storage type / name length
|
||||
.byte "RAM" ; name field is 15 bytes
|
||||
.res 15-3
|
||||
.res 8, 0 ; reserved (8 bytes)
|
||||
.word 0, 0 ; creation date/time
|
||||
.byte 1 ; version (1 = ProDOS 2.0)
|
||||
.byte 0 ; min_version
|
||||
.byte ACCESS_DEFAULT ; access
|
||||
.byte $27 ; entry_length
|
||||
.byte $D ; entries_per_block
|
||||
.word 0 ; file_count
|
||||
.word 6 ; bit_map_pointer
|
||||
blocks: .word 0 ; total_blocks
|
||||
.endproc
|
||||
.assert .sizeof(vol_dir_header) = .sizeof(VolumeDirectoryHeader), error, "Size mismatch"
|
||||
|
||||
.endproc
|
||||
|
||||
;;; ============================================================
|
||||
;;; Ram Disk Driver - installed at $FF00
|
||||
;;; ============================================================
|
||||
|
||||
saved_org .set *
|
||||
.proc driver_src
|
||||
.org ::driver_target
|
||||
driver_start := *
|
||||
|
||||
start: cld ; used as a signature
|
||||
|
||||
lda DRIVER_COMMAND
|
||||
bne not_status
|
||||
driver_blocks_lo := *+1
|
||||
ldx #0 ; self-modified - blocks low
|
||||
driver_blocks_hi := *+1
|
||||
ldy #0 ; self-modified - blocks high
|
||||
LFF09: clc
|
||||
bcc LFF83 ; always
|
||||
|
||||
not_status:
|
||||
cmp #DRIVER_COMMAND_FORMAT
|
||||
beq LFF09
|
||||
|
||||
;; COMMAND_READ or COMMAND_WRITE
|
||||
LFF10: lda #$27
|
||||
bcs rts1
|
||||
|
||||
lda RD80STORE
|
||||
pha
|
||||
sta CLR80COL
|
||||
|
||||
;; Save $40/41
|
||||
lda $40
|
||||
pha
|
||||
lda $41
|
||||
pha
|
||||
|
||||
lda DRIVER_BUFFER
|
||||
sta $40
|
||||
ldx DRIVER_BUFFER+1
|
||||
inx
|
||||
stx $41
|
||||
|
||||
jsr install_zpproc_relay
|
||||
|
||||
zpproc_relay_patch1_offset := $04
|
||||
stx zpproc_relay_addr + zpproc_relay_patch1_offset
|
||||
lda RDALTZP
|
||||
|
||||
zpproc_relay_patch2_offset := $14
|
||||
sta zpproc_relay_addr + zpproc_relay_patch2_offset
|
||||
lda DRIVER_BLOCK_NUMBER+1
|
||||
pha
|
||||
tax
|
||||
lda DRIVER_BLOCK_NUMBER
|
||||
LFF3C: sec
|
||||
: iny
|
||||
sbc #$7F
|
||||
bcs :-
|
||||
dex
|
||||
bpl LFF3C
|
||||
|
||||
tya
|
||||
adc DRIVER_BLOCK_NUMBER
|
||||
bcc :+
|
||||
inc DRIVER_BLOCK_NUMBER+1
|
||||
: asl a
|
||||
tay
|
||||
lda DRIVER_BLOCK_NUMBER+1
|
||||
rol a
|
||||
tax
|
||||
pla
|
||||
sta DRIVER_BLOCK_NUMBER+1
|
||||
driver_block_x := *+1
|
||||
cpx #$0 ; self-modified - ???
|
||||
bcs LFF74
|
||||
|
||||
tya
|
||||
sbc #191
|
||||
cmp #16
|
||||
bcs :+
|
||||
adc #208
|
||||
|
||||
tay
|
||||
bit LCBANK2
|
||||
: lda DRIVER_COMMAND
|
||||
lsr a ; carry set = READ, clear = WRITE
|
||||
lda bank_list,x
|
||||
ldx DRIVER_BUFFER
|
||||
jsr zpproc_relay_addr
|
||||
bit LCBANK1
|
||||
|
||||
LFF74: jsr install_zpproc_relay
|
||||
|
||||
;; Restore $40/41
|
||||
pla
|
||||
sta $41
|
||||
pla
|
||||
sta $40
|
||||
|
||||
pla
|
||||
bpl LFF83
|
||||
sta SET80COL
|
||||
LFF83: lda #$00
|
||||
bcs LFF10
|
||||
|
||||
rts1: rts
|
||||
|
||||
install_zpproc_relay:
|
||||
ldy #sizeof_zpproc_relay+1
|
||||
: ldx zpproc_relay-1,y
|
||||
lda zpproc_relay_addr-1,y
|
||||
sta zpproc_relay-1,y
|
||||
txa
|
||||
sta zpproc_relay_addr-1,y
|
||||
dey
|
||||
bne :-
|
||||
|
||||
ldx DRIVER_BUFFER+1
|
||||
bpl done
|
||||
bit DRIVER_BUFFER+1
|
||||
bvc done
|
||||
|
||||
: ldx $8000,y
|
||||
lda (DRIVER_BUFFER),y
|
||||
sta $8000,y
|
||||
txa
|
||||
sta (DRIVER_BUFFER),y
|
||||
ldx $8100,y
|
||||
lda ($40),y
|
||||
sta $8100,y
|
||||
txa
|
||||
sta ($40),y
|
||||
iny
|
||||
bne :-
|
||||
|
||||
ldx #$80
|
||||
done: rts
|
||||
|
||||
bank_list:
|
||||
.res ::kMaxUsableBanks, 0
|
||||
|
||||
.proc zpproc_relay
|
||||
sta RWBANK
|
||||
|
||||
patch_loc1 := *+1
|
||||
lda #$00
|
||||
sta ALTZPON
|
||||
jsr zpproc_addr
|
||||
sty RWBANK
|
||||
bmi :+
|
||||
sta ALTZPOFF
|
||||
: rts
|
||||
|
||||
patch_loc2 := *
|
||||
.endproc
|
||||
sizeof_zpproc_relay := .sizeof(zpproc_relay)
|
||||
patch_loc1_offset := zpproc_relay::patch_loc1 - zpproc_relay
|
||||
patch_loc2_offset := zpproc_relay::patch_loc2 - zpproc_relay
|
||||
;; These offsets can't be used directly due to ca65 addressing mode
|
||||
;; assumptions, so just verify they are correct.
|
||||
.assert zpproc_relay_patch1_offset = patch_loc1_offset, error, "Offset mismatch"
|
||||
.assert zpproc_relay_patch2_offset = patch_loc2_offset, error, "Offset mismatch"
|
||||
|
||||
.byte 0
|
||||
|
||||
.endproc
|
||||
sizeof_driver := .sizeof(driver_src)
|
||||
.org (saved_org + .sizeof(driver_src))
|
||||
|
||||
driver_blocks_lo := driver_src + driver_src::driver_blocks_lo - driver_src::driver_start
|
||||
driver_blocks_hi := driver_src + driver_src::driver_blocks_hi - driver_src::driver_start
|
||||
driver_block_x := driver_src + driver_src::driver_block_x - driver_src::driver_start
|
||||
driver_bank_list := driver_src + driver_src::bank_list - driver_src::driver_start
|
||||
|
||||
;;; Scratch space beyond code used during install
|
||||
|
||||
reserved_banks := *
|
||||
first_used_bank := *+1
|
||||
map1 := *+2
|
||||
map2 := *+2+$80
|
||||
stash_00 := *+2+$100
|
||||
stash_01 := *+2+$180
|
18
res/go.sh
Executable file
18
res/go.sh
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Run this from the ram.system directory
|
||||
|
||||
set -e
|
||||
source "res/util.sh"
|
||||
|
||||
function verify {
|
||||
diff "orig/$1" "out/$2" \
|
||||
&& (cecho green "diff $2 good" ) \
|
||||
|| (tput blink ; cecho red "DIFF $2 BAD" ; return 1)
|
||||
}
|
||||
|
||||
|
||||
#do_make clean
|
||||
do_make all
|
||||
|
||||
verify "RAM.SYSTEM.SYS" "ram.system.SYS"
|
15
res/util.sh
Normal file
15
res/util.sh
Normal file
@ -0,0 +1,15 @@
|
||||
function cecho {
|
||||
case $1 in
|
||||
red) tput setaf 1 ; shift ;;
|
||||
green) tput setaf 2 ; shift ;;
|
||||
yellow) tput setaf 3 ; shift ;;
|
||||
esac
|
||||
echo -e "$@"
|
||||
tput sgr0
|
||||
}
|
||||
|
||||
function do_make {
|
||||
make $MAKE_FLAGS "$1" \
|
||||
&& (cecho green "make $1 good") \
|
||||
|| (tput blink ; cecho red "MAKE $1 BAD" ; return 1)
|
||||
}
|
Loading…
Reference in New Issue
Block a user