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) }