forked from MirrorRepos/RomWBW
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
4.1 KiB
200 lines
4.1 KiB
# vim: ts=4 sw=4 et
|
|
|
|
record CpmFCB is
|
|
dr: uint8;
|
|
f: uint8[11];
|
|
ex: uint8;
|
|
s1: uint8;
|
|
s2: uint8;
|
|
rc: uint8;
|
|
d: uint8[16];
|
|
cr: uint8;
|
|
r: uint16;
|
|
r2: uint8;
|
|
end record;
|
|
|
|
record FCB is
|
|
bufferptr: uint8; # byte just read
|
|
dirty: uint8;
|
|
cpm: CpmFCB;
|
|
buffer: uint8[128];
|
|
end record;
|
|
|
|
sub file_i_init(fcb: [FCB], filename: [uint8]) is
|
|
sub fill(dest: [uint8], src: [uint8], len: uint8): (srcout: [uint8]) is
|
|
loop
|
|
var c := [src];
|
|
if (c < 32) or (c == '.') then
|
|
c := ' ';
|
|
elseif (c == '*') then
|
|
c := '?';
|
|
else
|
|
src := src + 1;
|
|
end if;
|
|
if (c >= 'a') and (c <= 'z') then
|
|
c := c - ('a' - 'A');
|
|
end if;
|
|
[dest] := c;
|
|
dest := dest + 1;
|
|
|
|
len := len - 1;
|
|
if len == 0 then
|
|
break;
|
|
end if;
|
|
end loop;
|
|
srcout := src;
|
|
end sub;
|
|
|
|
MemSet(fcb as [uint8], 0, @bytesof FCB);
|
|
MemSet(&fcb.cpm.f[0] as [uint8], ' ', 11);
|
|
filename := fill(&fcb.cpm.f[0], filename, 8);
|
|
|
|
var c: uint8;
|
|
loop
|
|
c := [filename];
|
|
if (c < 32) or (c == '.') then
|
|
break;
|
|
end if;
|
|
filename := filename + 1;
|
|
end loop;
|
|
|
|
if c == '.' then
|
|
filename := fill(&fcb.cpm.f[8], filename+1, 3);
|
|
end if;
|
|
|
|
fcb.cpm.r := 0xffff;
|
|
fcb.bufferptr := 127;
|
|
end sub;
|
|
|
|
sub fcb_i_gbpb(fcb: [FCB], c: uint8) is
|
|
var cpmfcb := &fcb.cpm;
|
|
var dma := &fcb.buffer[0];
|
|
|
|
@asm "ld c, 26"; # SET DMA
|
|
@asm "ld de, (", dma, ")";
|
|
@asm "call 5";
|
|
|
|
@asm "ld a, (", c, ")";
|
|
@asm "ld c, a";
|
|
@asm "ld de, (", cpmfcb, ")";
|
|
@asm "call 5";
|
|
end sub;
|
|
|
|
sub fcb_i_blockin(fcb: [FCB]) is
|
|
MemSet(&fcb.buffer[0], 0, 128);
|
|
fcb_i_gbpb(fcb, 33); # READ RANDOM
|
|
fcb.dirty := 0;
|
|
end sub;
|
|
|
|
sub fcb_i_blockout(fcb: [FCB]) is
|
|
if fcb.dirty != 0 then
|
|
fcb_i_gbpb(fcb, 34); # WRITE RANDOM
|
|
fcb.dirty := 0;
|
|
end if;
|
|
end sub;
|
|
|
|
sub fcb_i_changeblock(fcb: [FCB], newblock: uint16) is
|
|
if newblock != fcb.cpm.r then
|
|
fcb_i_blockout(fcb);
|
|
fcb.cpm.r := newblock;
|
|
fcb_i_blockin(fcb);
|
|
end if;
|
|
end sub;
|
|
|
|
sub fcb_i_convert_a_to_error() is
|
|
@asm "cp 0xff";
|
|
@asm "ld a, 0";
|
|
@asm "ret nz";
|
|
@asm "inc a";
|
|
end sub;
|
|
|
|
sub FCBOpenIn(fcb: [FCB], filename: [uint8]): (errno: uint8) is
|
|
file_i_init(fcb, filename);
|
|
|
|
var cpmfcb := &fcb.cpm;
|
|
@asm "ld c, 15"; # OPEN_FILE
|
|
@asm "ld de, (", cpmfcb, ")";
|
|
@asm "call 5";
|
|
@asm "call", fcb_i_convert_a_to_error;
|
|
@asm "ld (", errno, "), a";
|
|
end sub;
|
|
|
|
sub FCBOpenUp(fcb: [FCB], filename: [uint8]): (errno: uint8) is
|
|
(errno) := FCBOpenIn(fcb, filename);
|
|
end sub;
|
|
|
|
sub FCBOpenOut(fcb: [FCB], filename: [uint8]): (errno: uint8) is
|
|
file_i_init(fcb, filename);
|
|
|
|
var cpmfcb := &fcb.cpm;
|
|
@asm "ld c, 19"; # DELETE_FILE
|
|
@asm "ld de, (", cpmfcb, ")";
|
|
@asm "call 5";
|
|
|
|
@asm "ld c, 22"; # CREATE_FILE
|
|
@asm "ld de, (", cpmfcb, ")";
|
|
@asm "call 5";
|
|
@asm "call", fcb_i_convert_a_to_error;
|
|
@asm "ld (", errno, "), a";
|
|
end sub;
|
|
|
|
sub FCBClose(fcb: [FCB]): (errno: uint8) is
|
|
fcb_i_blockout(fcb);
|
|
|
|
var cpmfcb := &fcb.cpm;
|
|
@asm "ld c, 16"; # CLOSE_FILE
|
|
@asm "ld de, (", cpmfcb, ")";
|
|
@asm "call 5";
|
|
@asm "call", fcb_i_convert_a_to_error;
|
|
@asm "ld (", errno, "), a";
|
|
end sub;
|
|
|
|
sub FCBSeek(fcb: [FCB], pos: uint32) is
|
|
pos := pos - 1; # seek to *previous* character
|
|
var newblock := (pos >> 7) as uint16;
|
|
var newptr := (pos as uint8) & 127;
|
|
fcb_i_changeblock(fcb, newblock);
|
|
fcb.bufferptr := newptr;
|
|
end sub;
|
|
|
|
sub FCBPos(fcb: [FCB]): (pos: uint32) is
|
|
pos := (((fcb.cpm.r as uint32) << 7) | (fcb.bufferptr as uint32)) + 1;
|
|
end sub;
|
|
|
|
sub FCBExt(fcb: [FCB]): (len: uint32) is
|
|
var oldblock := fcb.cpm.r;
|
|
var cpmfcb := &fcb.cpm;
|
|
|
|
@asm "ld c, 16"; # CLOSE_FILE (actually flushing it to disk)
|
|
@asm "ld de, (", cpmfcb, ")";
|
|
@asm "call 5";
|
|
|
|
@asm "ld c, 35"; # COMPUTE FILE SIZE
|
|
@asm "ld de, (", cpmfcb, ")";
|
|
@asm "call 5";
|
|
|
|
len := ([&fcb.cpm.r as [uint32]] & 0x00ffffff) << 7;
|
|
fcb.cpm.r := oldblock;
|
|
end sub;
|
|
|
|
sub fcb_i_nextchar(fcb: [FCB]) is
|
|
fcb.bufferptr := fcb.bufferptr + 1;
|
|
if fcb.bufferptr == 128 then
|
|
fcb_i_changeblock(fcb, fcb.cpm.r + 1);
|
|
fcb.bufferptr := 0;
|
|
end if;
|
|
end sub;
|
|
|
|
sub FCBGetChar(fcb: [FCB]): (c: uint8) is
|
|
fcb_i_nextchar(fcb);
|
|
c := fcb.buffer[fcb.bufferptr];
|
|
end sub;
|
|
|
|
sub FCBPutChar(fcb: [FCB], c: uint8) is
|
|
fcb_i_nextchar(fcb);
|
|
fcb.buffer[fcb.bufferptr] := c;
|
|
fcb.dirty := 1;
|
|
end sub;
|
|
|
|
include "commfile.coh";
|
|
|
|
|