apple2js/js/cards/ramfactor.ts
Ian Flanigan 04ae0327c2
Add the recommended eslint plugins for TypeScript (#121)
This adds both the recommended TypeScript checks, plus the recommended
TypeScript checks that require type checking.  This latter addition
means that eslint essentially has to compile all of the TypeScript in
the project, causing it to be slower. This isn't much of a problem in
VS Code because there's a lot of caching being done, but it's clearly
slower when run on the commandline.

All of the errors are either fixed or suppressed.  Some errors are
suppressed because fixing them would be too laborious for the little
value gained.

The eslint config is also slightly refactored to separate the strictly
TypeScript checks from the JavaScript checks.
2022-05-31 08:38:40 -07:00

155 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() {
// not writable
}
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;
}
}