apple2js/js/cards/ramfactor.ts

153 lines
3.8 KiB
TypeScript

import { allocMem, debug } from '../util';
import { Card, Restorable, byte, memory } from '../types';
import { rom } from '../roms/cards/ramfactor';
const LOC = {
// Disk II Stuff
RAMLO: 0x80,
RAMMID: 0x81,
RAMHI: 0x82,
RAMDATA: 0x83,
_RAMLO: 0x84,
_RAMMID: 0x85,
_RAMHI: 0x86,
_RAMDATA: 0x87,
BANK: 0x8F
} as const;
export class RAMFactorState {
loc: number;
firmware: byte;
mem: memory;
}
export default class RAMFactor implements Card, Restorable<RAMFactorState> {
private mem: memory;
private firmware = 0;
private ramlo = 0;
private rammid = 0;
private ramhi = 0;
private loc = 0;
constructor(size: number) {
debug('RAMFactor card');
this.mem = allocMem(size);
for (let off = 0; off < size; off++) {
this.mem[off] = 0;
}
}
private sethi(val: byte) {
this.ramhi = (val & 0xff);
}
private setmid(val: byte) {
if (((this.rammid & 0x80) !== 0) && ((val & 0x80) === 0)) {
this.sethi(this.ramhi + 1);
}
this.rammid = (val & 0xff);
}
private setlo(val: byte) {
if (((this.ramlo & 0x80) !== 0) && ((val & 0x80) === 0)) {
this.setmid(this.rammid + 1);
}
this.ramlo = (val & 0xff);
}
private access(off: byte, val: byte) {
let result = 0;
switch (off & 0x8f) {
case LOC.RAMLO:
case LOC._RAMLO:
if (val !== undefined) {
this.setlo(val);
} else {
result = this.ramlo;
}
break;
case LOC.RAMMID:
case LOC._RAMMID:
if (val !== undefined) {
this.setmid(val);
} else {
result = this.rammid;
}
break;
case LOC.RAMHI:
case LOC._RAMHI:
if (val !== undefined) {
this.sethi(val);
} else {
result = this.ramhi;
result |= 0xf0;
}
break;
case LOC.RAMDATA:
case LOC._RAMDATA:
if (val !== undefined) {
this.mem[this.loc % this.mem.length] = val;
} else {
result = this.mem[this.loc % this.mem.length];
}
this.setlo(this.ramlo + 1);
break;
case LOC.BANK:
if (val !== undefined) {
this.firmware = val & 0x01;
} else {
result = this.firmware;
}
break;
default:
break;
}
this.loc = (this.ramhi << 16) | (this.rammid << 8) | (this.ramlo);
/*
if (val === undefined) {
debug("Read: " + toHex(result) + " from " + toHex(off) + " (loc = " + _loc + ")");
} else {
debug("Wrote: " + toHex(val) + " to " + toHex(off) + " (loc = " + _loc + ")");
}
*/
return result;
}
ioSwitch(off: byte, val: byte) {
return this.access(off, val);
}
read(page: byte, off: byte) {
return rom[this.firmware << 12 | (page - 0xC0) << 8 | off];
}
write() {}
reset() {
this.firmware = 0;
}
getState() {
return {
loc: this.loc,
firmware: this.firmware,
mem: new Uint8Array(this.mem)
};
}
setState(state: RAMFactorState) {
this.loc = state.loc;
this.firmware = state.firmware;
this.mem = new Uint8Array(state.mem);
this.ramhi = (this.loc >> 16) & 0xff;
this.rammid = (this.loc >> 8) & 0xff;
this.ramlo = (this.loc) & 0xff;
}
}