mirror of
https://github.com/KarolS/millfork.git
synced 2025-04-07 11:39:08 +00:00
first attempt at a ProDOS library for the Apple II
This commit is contained in:
parent
3a2e29888d
commit
ef34f534f9
37
examples/apple2/diskrom_dump.mfk
Normal file
37
examples/apple2/diskrom_dump.mfk
Normal file
@ -0,0 +1,37 @@
|
||||
// simple demonstration of ProDOS library routines that will write
|
||||
// the Disk II ROM (assuming it is in slot 6) to the file DISKII.ROM
|
||||
|
||||
import stdio
|
||||
import apple2_prodos
|
||||
|
||||
void main() {
|
||||
// ProDOS requires a 1K aligned page for an open file as an IO buffer
|
||||
array iobuf [1024] align(256)
|
||||
|
||||
// you have to explicitly create a file if it doesn't exist yet
|
||||
// this can fail (so you should check prodos_error
|
||||
// 06 is general binary type
|
||||
prodos_create("DISKII.ROM"p, $06)
|
||||
if prodos_error != 0 {
|
||||
// prodos error call will be returned in prodos_error so you know
|
||||
// what went wrong. 0 = no error
|
||||
putstrz("{n}couldn't create file"z)
|
||||
panic()
|
||||
}
|
||||
|
||||
// ProDOS file handle
|
||||
byte fp
|
||||
|
||||
fp = prodos_open("DISKII.ROM"p, iobuf)
|
||||
// should check here again for error, and after all calls
|
||||
|
||||
// write the disk controller ROM to the file
|
||||
prodos_write(fp, $c600, 256)
|
||||
|
||||
// closing frees the handle and io buffer
|
||||
prodos_close(fp)
|
||||
|
||||
putstrz("{n}DONE"z)
|
||||
|
||||
while true { }
|
||||
}
|
273
include/apple2_prodos.mfk
Normal file
273
include/apple2_prodos.mfk
Normal file
@ -0,0 +1,273 @@
|
||||
|
||||
const byte PRODOS_ALLOC_INTERRUPT = $40
|
||||
const byte PRODOS_DEALLOC_INTERRUPT = $41
|
||||
const byte PRODOS_READ_BLOCK = $80
|
||||
const byte PRODOS_WRITE_BLOCK = $81
|
||||
const byte PRODOS_GET_TIME = $82
|
||||
const byte PRODOS_CREATE = $c0
|
||||
const byte PRODOS_DESTROY = $c1
|
||||
const byte PRODOS_RENAME = $c2
|
||||
const byte PRODOS_SET_FILE_INFO = $c3
|
||||
const byte PRODOS_GET_FILE_INFO = $c4
|
||||
const byte PRODOS_ON_LINE = $c5
|
||||
const byte PRODOS_SET_PREFIX = $c6
|
||||
const byte PRODOS_GET_PREFIX = $c7
|
||||
const byte PRODOS_OPEN = $c8
|
||||
const byte PRODOS_NEWLINE = $c9
|
||||
const byte PRODOS_READ = $ca
|
||||
const byte PRODOS_WRITE = $cb
|
||||
const byte PRODOS_CLOSE = $cc
|
||||
const byte PRODOS_FLUSH = $cd
|
||||
const byte PRODOS_SET_MARK = $ce
|
||||
const byte PRODOS_GET_MARK = $cf
|
||||
const byte PRODOS_SET_EOF = $d0
|
||||
const byte PRODOS_GET_EOF = $d1
|
||||
const byte PRODOS_SET_BUF = $d2
|
||||
const byte PRODOS_GET_BUF = $d3
|
||||
|
||||
|
||||
// ProDOS MLI parameter lists
|
||||
|
||||
struct read_block_plist {
|
||||
byte param_count
|
||||
byte unit_num
|
||||
pointer data_buffer
|
||||
word block_num
|
||||
}
|
||||
|
||||
struct write_block_plist {
|
||||
byte param_count
|
||||
byte unit_num
|
||||
pointer data_buffer
|
||||
word block_num
|
||||
}
|
||||
|
||||
struct close_plist {
|
||||
byte param_count
|
||||
byte ref_num
|
||||
}
|
||||
|
||||
struct flush_plist {
|
||||
byte param_count
|
||||
byte ref_num
|
||||
}
|
||||
|
||||
struct create_plist {
|
||||
byte param_count
|
||||
pointer pathname
|
||||
byte access
|
||||
byte file_type
|
||||
word aux_type
|
||||
byte storage_type
|
||||
word create_time
|
||||
word create_date
|
||||
}
|
||||
|
||||
struct destroy_plist {
|
||||
byte param_count
|
||||
pointer pathname
|
||||
}
|
||||
|
||||
struct open_plist {
|
||||
byte param_count
|
||||
pointer pathname
|
||||
pointer io_buffer
|
||||
byte ref_num
|
||||
}
|
||||
|
||||
struct newline_plist {
|
||||
byte param_count
|
||||
byte ref_num
|
||||
byte enable_mask
|
||||
byte newline_char
|
||||
}
|
||||
|
||||
struct read_plist {
|
||||
byte param_count
|
||||
byte ref_num
|
||||
pointer data_buffer
|
||||
word request_count
|
||||
word trans_count
|
||||
}
|
||||
|
||||
struct rename_plist {
|
||||
byte param_count
|
||||
pointer pathname
|
||||
pointer new_pathname
|
||||
}
|
||||
|
||||
struct write_plist {
|
||||
byte param_count
|
||||
byte ref_num
|
||||
pointer data_buffer
|
||||
word request_count
|
||||
word trans_count
|
||||
}
|
||||
|
||||
struct get_prefix_plist {
|
||||
byte param_count
|
||||
pointer data_buffer
|
||||
}
|
||||
|
||||
struct set_prefix_plist {
|
||||
byte param_count
|
||||
pointer data_buffer
|
||||
}
|
||||
|
||||
// we'll just reuse the same area for all plists
|
||||
|
||||
union prodos_plist {
|
||||
read_block_plist read_block
|
||||
write_block_plist write_block
|
||||
create_plist create
|
||||
destroy_plist destroy
|
||||
rename_plist rename
|
||||
open_plist open
|
||||
newline_plist newline
|
||||
read_plist read
|
||||
|
||||
write_plist write
|
||||
close_plist close
|
||||
flush_plist flush
|
||||
|
||||
get_prefix_plist get_prefix
|
||||
set_prefix_plist set_prefix
|
||||
|
||||
}
|
||||
|
||||
prodos_plist plist
|
||||
|
||||
byte prodos_error
|
||||
|
||||
// Millfork doesn't support self-modification in the assembler yet, so this
|
||||
// code is placed in the following array:
|
||||
//
|
||||
// jsr $bf00
|
||||
// $00
|
||||
// plist.addr
|
||||
// rts
|
||||
//
|
||||
// We modify mli_trampoline[3] ($00 on the second line) to set the specific
|
||||
// ProDOS call before we jsr to $bf00
|
||||
//
|
||||
// TODO: can we just jmp to bf00 and save the extra rts ?
|
||||
|
||||
array mli_trampoline = [ $20, 0, $bf, 0, plist.addr.lo, plist.addr.hi, $60 ]
|
||||
|
||||
asm void prodos_mli_call(byte register(a) pdcall) {
|
||||
sta mli_trampoline+3
|
||||
jsr mli_trampoline
|
||||
sta prodos_error
|
||||
rts
|
||||
}
|
||||
|
||||
void prodos_read_block(byte unum, pointer dbuf, word bnum) {
|
||||
plist.read_block.param_count = 3
|
||||
plist.read_block.unit_num = unum
|
||||
plist.read_block.data_buffer = dbuf
|
||||
plist.read_block.block_num = bnum
|
||||
|
||||
prodos_mli_call(PRODOS_READ_BLOCK)
|
||||
}
|
||||
|
||||
void prodos_write_block(byte unum, pointer dbuf, word bnum) {
|
||||
plist.write_block.param_count = 3
|
||||
plist.write_block.unit_num = unum
|
||||
plist.write_block.data_buffer = dbuf
|
||||
plist.write_block.block_num = bnum
|
||||
|
||||
prodos_mli_call(PRODOS_WRITE_BLOCK)
|
||||
}
|
||||
|
||||
void prodos_close(byte rnum) {
|
||||
plist.close.param_count = 1
|
||||
plist.close.ref_num = rnum
|
||||
|
||||
prodos_mli_call(PRODOS_CLOSE)
|
||||
}
|
||||
|
||||
void prodos_flush(byte fp) {
|
||||
plist.flush.param_count = 1
|
||||
plist.flush.ref_num = fp
|
||||
|
||||
prodos_mli_call(PRODOS_FLUSH)
|
||||
}
|
||||
|
||||
void prodos_get_prefix(pointer fnbuf) {
|
||||
plist.get_prefix.param_count = 1
|
||||
plist.get_prefix.data_buffer = fnbuf
|
||||
|
||||
prodos_mli_call(PRODOS_GET_PREFIX)
|
||||
}
|
||||
|
||||
void prodos_set_prefix(pointer fnbuf) {
|
||||
plist.set_prefix.param_count = 1
|
||||
plist.set_prefix.data_buffer = fnbuf
|
||||
|
||||
prodos_mli_call(PRODOS_SET_PREFIX)
|
||||
}
|
||||
|
||||
void prodos_create(pointer fn, byte ftype) {
|
||||
plist.create.param_count = 7
|
||||
plist.create.pathname = fn
|
||||
plist.create.access = $c3
|
||||
plist.create.file_type = ftype
|
||||
plist.create.aux_type = $0
|
||||
plist.create.storage_type = 1
|
||||
plist.create.create_time = 0
|
||||
plist.create.create_date = 0
|
||||
|
||||
prodos_mli_call(PRODOS_CREATE)
|
||||
}
|
||||
|
||||
void prodos_destroy (pointer fn) {
|
||||
plist.destroy.param_count = 0
|
||||
plist.destroy.pathname = fn
|
||||
prodos_mli_call(PRODOS_DESTROY)
|
||||
}
|
||||
|
||||
void prodos_rename(pointer fn, pointer newfn) {
|
||||
plist.rename.param_count = 2
|
||||
plist.rename.pathname = fn
|
||||
plist.rename.new_pathname = newfn
|
||||
|
||||
prodos_mli_call(PRODOS_RENAME)
|
||||
}
|
||||
|
||||
// returns file handle if no error
|
||||
byte prodos_open (pointer fn, pointer b) {
|
||||
plist.open.param_count = 3
|
||||
plist.open.pathname = fn
|
||||
plist.open.io_buffer = b
|
||||
|
||||
prodos_mli_call(PRODOS_OPEN)
|
||||
|
||||
return plist.open.ref_num
|
||||
}
|
||||
|
||||
void prodos_newline(byte fp, byte mask, byte nlchar) {
|
||||
plist.newline.param_count = 3
|
||||
plist.newline.ref_num = fp
|
||||
plist.newline.enable_mask = mask
|
||||
plist.newline.newline_char = nlchar
|
||||
|
||||
prodos_mli_call(PRODOS_NEWLINE)
|
||||
}
|
||||
|
||||
void prodos_read(byte rnum, pointer dbuf, word rcnt) {
|
||||
plist.read.param_count = 4
|
||||
plist.read.ref_num = rnum
|
||||
plist.read.data_buffer = dbuf
|
||||
plist.read.request_count = rcnt
|
||||
|
||||
prodos_mli_call(PRODOS_READ)
|
||||
}
|
||||
|
||||
void prodos_write(byte rnum, pointer dbuf, word rcnt) {
|
||||
plist.write.param_count = 4
|
||||
plist.write.ref_num = rnum
|
||||
plist.write.data_buffer = dbuf
|
||||
plist.write.request_count = rcnt
|
||||
|
||||
prodos_mli_call(PRODOS_WRITE)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user