apple2js/js/mmu.ts
Ian Flanigan b80436d99c
More typescript conversion (#46)
* Convert js/ram to a class

* Convert js/mmu to Typescript

* Convert js/apple2io to Typescript

* Convert js/canvas to Typescript

* Use new types in js/mmu

* Rename js/symbols.js to js/symbols.ts

* Remove the difference between readPages and writePages

As @whscullin said in PR #38, there's no need to have both readable
and writable pages since all implementations are currently both. This
change combines them into `Page`. Likewise, `PageHandler` now extends
`Page`.

`Apple2IO` now implements `PageHandler`. This caught a bug where `end`
had been renamed `endend` by mistake.

There are a few other formatting changes as well.

* Convert js/apple2 to Typescript

* Convert js/prefs to Typescript

* Convert all of the ROMs in js/roms to Typescript

Now all of the ROMs are classes that extend the ROM class. There is
some rudamentary checking to make sure that the length of the ROM
matches the declared start and end pages. (This caught what looks to
be an error in roms/apple2e, but it's hard for me to tell.)

The typing also caught an error where the character ROM was being
used for the main ROM for the apple2j version.

* Convert js/roms/cards/* to Typescript

* Convert js/formats/format_utils to Typescript

This change also seems to fix a bug with `.po` image files that
weren't being read correctly.
2020-11-24 08:48:14 -08:00

895 lines
28 KiB
TypeScript

/* Copyright 2010-2019 Will Scullin <scullin@scullinsteel.com>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation. No representations are made about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*/
import CPU6502 from './cpu6502';
import RAM from './ram';
import { debug, toHex } from './util';
import { byte, Memory } from './types';
import Apple2IO from './apple2io';
import { HiresPage, LoresPage, VideoModes } from './canvas';
/*
* I/O Switch locations
*/
const LOC = {
// 80 Column
_80STOREOFF: 0x00,
_80STOREON: 0x01,
// Aux RAM
RAMRDOFF: 0x02,
RAMRDON: 0x03,
RAMWROFF: 0x04,
RAMWRON: 0x05,
// Bank switched ROM
INTCXROMOFF: 0x06,
INTCXROMON: 0x07,
ALTZPOFF: 0x08,
ALTZPON: 0x09,
SLOTC3ROMOFF: 0x0A,
SLOTC3ROMON: 0x0B,
CLR80VID: 0x0C, // clear 80 column mode
SET80VID: 0x0D, // set 80 column mode
CLRALTCH: 0x0E, // clear mousetext
SETALTCH: 0x0F, // set mousetext
// Status
BSRBANK2: 0x11,
BSRREADRAM: 0x12,
RAMRD: 0x13,
RAMWRT: 0x14,
INTCXROM: 0x15,
ALTZP: 0x16,
SLOTC3ROM: 0x17,
_80STORE: 0x18,
VERTBLANK: 0x19,
RDTEXT: 0x1A, // using text mode
RDMIXED: 0x1B, // using mixed mode
RDPAGE2: 0x1C, // using text/graphics page2
RDHIRES: 0x1D, // using Hi-res graphics mode
RDALTCH: 0x1E, // using alternate character set
RD80VID: 0x1F, // using 80-column display mode
PAGE1: 0x54, // select text/graphics page1 main/aux
PAGE2: 0x55, // select text/graphics page2 main/aux
RESET_HIRES: 0x56,
SET_HIRES: 0x57,
DHIRESON: 0x5E, // Enable double hires
DHIRESOFF: 0x5F, // Disable double hires
BANK: 0x73, // Back switched RAM card bank
IOUDISON: 0x7E, // W IOU Disable on / R7 IOU Disable
IOUDISOFF: 0x7F, // W IOU Disable off / R7 Double Hires
// Bank 2
READBSR2: 0x80,
WRITEBSR2: 0x81,
OFFBSR2: 0x82,
READWRBSR2: 0x83,
// Shadow Bank 2
_READBSR2: 0x84,
_WRITEBSR2: 0x85,
_OFFBSR2: 0x86,
_READWRBSR2: 0x87,
// Bank 1
READBSR1: 0x88,
WRITEBSR1: 0x89,
OFFBSR1: 0x8a,
READWRBSR1: 0x8b,
// Shadow Bank 1
_READBSR1: 0x8c,
_WRITEBSR1: 0x8d,
_OFFBSR1: 0x8e,
_READWRBSR1: 0x8f
};
class Switches implements Memory {
// Remapping of LOCS from string -> number to number -> string
private locs: { [loc: number]: string } = {};
constructor(private readonly mmu: MMU, private readonly io: any) {
Object.keys(LOC).forEach((loc: keyof typeof LOC) => {
let v = LOC[loc];
this.locs[v] = loc;
});
}
start() {
return 0xC0;
}
end() {
return 0xC0;
}
read(_page: byte, off: byte) {
var result;
if (off in this.locs) {
result = this.mmu._access(off);
} else {
result = this.io.ioSwitch(off, undefined);
}
return result;
}
write(_page: byte, off: byte, val: byte) {
if (off in this.locs) {
this.mmu._access(off, val);
} else {
this.io.ioSwitch(off, val);
}
}
}
class AuxRom {
constructor(
private readonly mmu: MMU,
private readonly rom: Memory) { }
read(page: byte, off: byte) {
if (page == 0xc3) {
this.mmu._setIntc8rom(true);
this.mmu._updateBanks();
}
if (page == 0xcf && off == 0xff) {
this.mmu._setIntc8rom(false);
this.mmu._updateBanks();
}
return this.rom.read(page, off);
}
write(_page: byte, _off: byte, _val: byte) {
// It's ROM.
}
}
/*
interface State {
bank1: this._bank1,
readbsr: this._readbsr,
writebsr: this._writebsr,
prewrite: this._prewrite,
intcxrom: this._intcxrom,
slot3rom: this._slot3rom,
intc8rom: this._intc8rom,
auxRamRead: this._auxRamRead,
auxRamWrite: this._auxRamWrite,
altzp: this._altzp,
_80store: this._80store,
page2: this._page2,
hires: this._hires,
mem00_01: [this.mem00_01[0].getState(), this.mem00_01[1].getState()],
mem02_03: [this.mem02_03[0].getState(), this.mem02_03[1].getState()],
mem0C_1F: [this.mem0C_1F[0].getState(), this.mem0C_1F[1].getState()],
mem60_BF: [this.mem60_BF[0].getState(), this.mem60_BF[1].getState()],
memD0_DF: [
this.memD0_DF[0].getState(), this.memD0_DF[1].getState(),
this.memD0_DF[2].getState(), this.memD0_DF[3].getState()
],
memE0_FF: [this.memE0_FF[0].getState(), this.memE0_FF[1].getState()]
};
*/
export default class MMU implements Memory {
private _readPages = new Array(0x100);
private _writePages = new Array(0x100);
private _pages = new Array(0x100);
// Language Card RAM Softswitches
private _bank1: boolean;
private _readbsr: boolean;
private _writebsr: boolean;
private _prewrite: boolean;
// Auxillary ROM
private _intcxrom: boolean;
private _slot3rom: boolean;
private _intc8rom: boolean;
// Auxillary RAM
private _auxRamRead: boolean;
private _auxRamWrite: boolean;
private _altzp: boolean;
// Video
private _80store: boolean;
private _page2: boolean;
private _hires: boolean;
private _iouDisable: boolean;
private _vbEnd = 0;
private switches = new Switches(this, this.io);
private auxRom = new AuxRom(this, this.rom);
// These fields represent the bank-switched memory ranges.
private mem00_01 = [new RAM(0x0, 0x1), new RAM(0x0, 0x1)];
private mem02_03 = [new RAM(0x2, 0x3), new RAM(0x2, 0x3)];
private mem04_07 = [this.lores1.bank0(), this.lores1.bank1()];
private mem08_0B = [this.lores2.bank0(), this.lores2.bank1()];
private mem0C_1F = [new RAM(0xC, 0x1F), new RAM(0xC, 0x1F)];
private mem20_3F = [this.hires1.bank0(), this.hires1.bank1()];
private mem40_5F = [this.hires2.bank0(), this.hires2.bank1()];
private mem60_BF = [new RAM(0x60, 0xBF), new RAM(0x60, 0xBF)];
private memC0_C0 = [this.switches];
private memC1_CF = [this.io, this.auxRom];
private memD0_DF = [
this.rom,
new RAM(0xD0, 0xDF), new RAM(0xD0, 0xDF),
new RAM(0xD0, 0xDF), new RAM(0xD0, 0xDF)
];
private memE0_FF = [this.rom, new RAM(0xE0, 0xFF), new RAM(0xE0, 0xFF)];
constructor(
private readonly cpu: CPU6502,
private readonly vm: VideoModes,
private readonly lores1: LoresPage,
private readonly lores2: LoresPage,
private readonly hires1: HiresPage,
private readonly hires2: HiresPage,
private readonly io: Apple2IO,
// TODO(flan): Better typing.
private readonly rom: any) {
/*
* Initialize read/write banks
*/
// Zero Page/Stack
for (let idx = 0x0; idx < 0x2; idx++) {
this._pages[idx] = this.mem00_01;
this._readPages[idx] = this._pages[idx][0];
this._writePages[idx] = this._pages[idx][0];
}
// 0x300-0x400
for (let idx = 0x2; idx < 0x4; idx++) {
this._pages[idx] = this.mem02_03;
this._readPages[idx] = this._pages[idx][0];
this._writePages[idx] = this._pages[idx][0];
}
// Text Page 1
for (let idx = 0x4; idx < 0x8; idx++) {
this._pages[idx] = this.mem04_07;
this._readPages[idx] = this._pages[idx][0];
this._writePages[idx] = this._pages[idx][0];
}
// Text Page 2
for (let idx = 0x8; idx < 0xC; idx++) {
this._pages[idx] = this.mem08_0B;
this._readPages[idx] = this._pages[idx][0];
this._writePages[idx] = this._pages[idx][0];
}
// 0xC00-0x2000
for (let idx = 0xC; idx < 0x20; idx++) {
this._pages[idx] = this.mem0C_1F;
this._readPages[idx] = this._pages[idx][0];
this._writePages[idx] = this._pages[idx][0];
}
// Hires Page 1
for (let idx = 0x20; idx < 0x40; idx++) {
this._pages[idx] = this.mem20_3F;
this._readPages[idx] = this._pages[idx][0];
this._writePages[idx] = this._pages[idx][0];
}
// Hires Page 2
for (let idx = 0x40; idx < 0x60; idx++) {
this._pages[idx] = this.mem40_5F;
this._readPages[idx] = this._pages[idx][0];
this._writePages[idx] = this._pages[idx][0];
}
// 0x6000-0xc000
for (let idx = 0x60; idx < 0xc0; idx++) {
this._pages[idx] = this.mem60_BF;
this._readPages[idx] = this._pages[idx][0];
this._writePages[idx] = this._pages[idx][0];
}
// I/O Switches
{
let idx = 0xc0;
this._pages[idx] = this.memC0_C0;
this._readPages[idx] = this._pages[idx][0];
this._writePages[idx] = this._pages[idx][0];
}
// Slots
for (let idx = 0xc1; idx < 0xd0; idx++) {
this._pages[idx] = this.memC1_CF;
this._readPages[idx] = this._pages[idx][0];
this._writePages[idx] = this._pages[idx][0];
}
// Basic ROM
for (let idx = 0xd0; idx < 0xe0; idx++) {
this._pages[idx] = this.memD0_DF;
this._readPages[idx] = this._pages[idx][0];
this._writePages[idx] = this._pages[idx][0];
}
// Monitor ROM
for (let idx = 0xe0; idx < 0x100; idx++) {
this._pages[idx] = this.memE0_FF;
this._readPages[idx] = this._pages[idx][0];
this._writePages[idx] = this._pages[idx][0];
}
};
_initSwitches() {
this._bank1 = true;
this._readbsr = false;
this._writebsr = false;
this._prewrite = false;
this._auxRamRead = false;
this._auxRamWrite = false;
this._altzp = false;
this._intcxrom = false;
this._slot3rom = false;
this._intc8rom = false;
this._80store = false;
this._page2 = false;
this._hires = false;
this._iouDisable = true;
}
_debug(..._args: any) {
// debug.apply(this, arguments);
}
_setIntc8rom(on: boolean) {
this._intc8rom = on;
}
_updateBanks() {
if (this._auxRamRead) {
for (let idx = 0x02; idx < 0xC0; idx++) {
this._readPages[idx] = this._pages[idx][1];
}
} else {
for (let idx = 0x02; idx < 0xC0; idx++) {
this._readPages[idx] = this._pages[idx][0];
}
}
if (this._auxRamWrite) {
for (let idx = 0x02; idx < 0xC0; idx++) {
this._writePages[idx] = this._pages[idx][1];
}
} else {
for (let idx = 0x02; idx < 0xC0; idx++) {
this._writePages[idx] = this._pages[idx][0];
}
}
if (this._80store) {
if (this._page2) {
for (let idx = 0x4; idx < 0x8; idx++) {
this._readPages[idx] = this._pages[idx][1];
this._writePages[idx] = this._pages[idx][1];
}
if (this._hires) {
for (let idx = 0x20; idx < 0x40; idx++) {
this._readPages[idx] = this._pages[idx][1];
this._writePages[idx] = this._pages[idx][1];
}
}
} else {
for (let idx = 0x4; idx < 0x8; idx++) {
this._readPages[idx] = this._pages[idx][0];
this._writePages[idx] = this._pages[idx][0];
}
if (this._hires) {
for (let idx = 0x20; idx < 0x40; idx++) {
this._readPages[idx] = this._pages[idx][0];
this._writePages[idx] = this._pages[idx][0];
}
}
}
}
if (this._intcxrom) {
for (let idx = 0xc1; idx < 0xd0; idx++) {
this._readPages[idx] = this._pages[idx][1];
}
} else {
for (let idx = 0xc1; idx < 0xd0; idx++) {
this._readPages[idx] = this._pages[idx][0];
}
if (!this._slot3rom) {
this._readPages[0xc3] = this._pages[0xc3][1];
}
if (this._intc8rom) {
for (let idx = 0xc8; idx < 0xd0; idx++) {
this._readPages[idx] = this._pages[idx][1];
}
}
}
if (this._altzp) {
for (let idx = 0x0; idx < 0x2; idx++) {
this._readPages[idx] = this._pages[idx][1];
this._writePages[idx] = this._pages[idx][1];
}
} else {
for (let idx = 0x0; idx < 0x2; idx++) {
this._readPages[idx] = this._pages[idx][0];
this._writePages[idx] = this._pages[idx][0];
}
}
if (this._readbsr) {
if (this._bank1) {
for (let idx = 0xd0; idx < 0xe0; idx++) {
this._readPages[idx] = this._pages[idx][this._altzp ? 2 : 1];
}
} else {
for (let idx = 0xd0; idx < 0xe0; idx++) {
this._readPages[idx] = this._pages[idx][this._altzp ? 4 : 3];
}
}
for (let idx = 0xe0; idx < 0x100; idx++) {
this._readPages[idx] = this._pages[idx][this._altzp ? 2 : 1];
}
} else {
for (let idx = 0xd0; idx < 0x100; idx++) {
this._readPages[idx] = this._pages[idx][0];
}
}
if (this._writebsr) {
if (this._bank1) {
for (let idx = 0xd0; idx < 0xe0; idx++) {
this._writePages[idx] = this._pages[idx][this._altzp ? 2 : 1];
}
} else {
for (let idx = 0xd0; idx < 0xe0; idx++) {
this._writePages[idx] = this._pages[idx][this._altzp ? 4 : 3];
}
}
for (let idx = 0xe0; idx < 0x100; idx++) {
this._writePages[idx] = this._pages[idx][this._altzp ? 2 : 1];
}
} else {
for (let idx = 0xd0; idx < 0x100; idx++) {
this._writePages[idx] = this._pages[idx][0];
}
}
}
/*
* The Big Switch
*/
_access(off: byte, val?: byte) {
let result;
let readMode = val === undefined;
let writeMode = val !== undefined;
switch (off) {
// Apple //e memory management
case LOC._80STOREOFF:
if (writeMode) {
this._80store = false;
this._debug('80 Store Off');
this.vm.page(this._page2 ? 2 : 1);
} else {
// Chain to io for keyboard
result = this.io.ioSwitch(off, val);
}
break;
case LOC._80STOREON:
if (writeMode) {
this._80store = true;
this._debug('80 Store On');
} else
result = 0;
break;
case LOC.RAMRDOFF:
if (writeMode) {
this._auxRamRead = false;
this._debug('Aux RAM Read Off');
} else
result = 0;
break;
case LOC.RAMRDON:
if (writeMode) {
this._auxRamRead = true;
this._debug('Aux RAM Read On');
} else
result = 0;
break;
case LOC.RAMWROFF:
if (writeMode) {
this._auxRamWrite = false;
this._debug('Aux RAM Write Off');
} else
result = 0;
break;
case LOC.RAMWRON:
if (writeMode) {
this._auxRamWrite = true;
this._debug('Aux RAM Write On');
} else
result = 0;
break;
case LOC.INTCXROMOFF:
if (writeMode) {
this._intcxrom = false;
this._intc8rom = false;
this._debug('Int CX ROM Off');
}
break;
case LOC.INTCXROMON:
if (writeMode) {
this._intcxrom = true;
this._debug('Int CX ROM On');
}
break;
case LOC.ALTZPOFF: // 0x08
if (writeMode) {
this._altzp = false;
this._debug('Alt ZP Off');
}
break;
case LOC.ALTZPON: // 0x09
if (writeMode) {
this._altzp = true;
this._debug('Alt ZP On');
}
break;
case LOC.SLOTC3ROMOFF: // 0x0A
if (writeMode) {
this._slot3rom = false;
this._debug('Slot 3 ROM Off');
}
break;
case LOC.SLOTC3ROMON: // 0x0B
if (writeMode) {
this._slot3rom = true;
this._debug('Slot 3 ROM On');
}
break;
// Graphics Switches
case LOC.CLR80VID:
if (writeMode) {
this._debug('80 Column Mode off');
this.vm._80col(false);
}
break;
case LOC.SET80VID:
if (writeMode) {
this._debug('80 Column Mode on');
this.vm._80col(true);
}
break;
case LOC.CLRALTCH:
if (writeMode) {
this._debug('Alt Char off');
this.vm.altchar(false);
}
break;
case LOC.SETALTCH:
if (writeMode) {
this._debug('Alt Char on');
this.vm.altchar(true);
}
break;
case LOC.PAGE1:
this._page2 = false;
if (!this._80store) {
result = this.io.ioSwitch(off, val);
}
this._debug('Page 2 off');
break;
case LOC.PAGE2:
this._page2 = true;
if (!this._80store) {
result = this.io.ioSwitch(off, val);
}
this._debug('Page 2 on');
break;
case LOC.RESET_HIRES:
this._hires = false;
result = this.io.ioSwitch(off, val);
this._debug('Hires off');
break;
case LOC.DHIRESON:
if (this._iouDisable) {
this.vm.doubleHires(true);
} else {
result = this.io.ioSwitch(off, val); // an3
}
break;
case LOC.DHIRESOFF:
if (this._iouDisable) {
this.vm.doubleHires(false);
} else {
result = this.io.ioSwitch(off, val); // an3
}
break;
case LOC.SET_HIRES:
this._hires = true;
result = this.io.ioSwitch(off, val);
this._debug('Hires on');
break;
case LOC.IOUDISON:
if (writeMode) {
this._iouDisable = true;
}
result = this._iouDisable ? 0x00 : 0x80;
break;
case LOC.IOUDISOFF:
if (writeMode) {
this._iouDisable = false;
}
result = this.vm.isDoubleHires() ? 0x80 : 0x00;
break;
// Language Card Switches
case LOC.READBSR2: // 0xC080
case LOC._READBSR2: // 0xC084
this._bank1 = false;
this._readbsr = true;
this._writebsr = false;
this._prewrite = false;
// _debug('Bank 2 Read');
break;
case LOC.WRITEBSR2: // 0xC081
case LOC._WRITEBSR2: // 0xC085
this._bank1 = false;
this._readbsr = false;
if (readMode) { this._writebsr = this._prewrite; }
this._prewrite = readMode;
// _debug('Bank 2 Write');
break;
case LOC.OFFBSR2: // 0xC082
case LOC._OFFBSR2: // 0xC086
this._bank1 = false;
this._readbsr = false;
this._writebsr = false;
this._prewrite = false;
// _debug('Bank 2 Off');
break;
case LOC.READWRBSR2: // 0xC083
case LOC._READWRBSR2: // 0xC087
this._bank1 = false;
this._readbsr = true;
if (readMode) { this._writebsr = this._prewrite; }
this._prewrite = readMode;
// _debug('Bank 2 Read/Write');
break;
case LOC.READBSR1: // 0xC088
case LOC._READBSR1: // 0xC08c
this._bank1 = true;
this._readbsr = true;
this._writebsr = false;
this._prewrite = false;
// _debug('Bank 1 Read');
break;
case LOC.WRITEBSR1: // 0xC089
case LOC._WRITEBSR1: // 0xC08D
this._bank1 = true;
this._readbsr = false;
if (readMode) { this._writebsr = this._prewrite; }
this._prewrite = readMode;
// _debug('Bank 1 Write');
break;
case LOC.OFFBSR1: // 0xC08A
case LOC._OFFBSR1: // 0xC08E
this._bank1 = true;
this._readbsr = false;
this._writebsr = false;
this._prewrite = false;
// _debug('Bank 1 Off');
break;
case LOC.READWRBSR1: // 0xC08B
case LOC._READWRBSR1: // 0xC08F
this._bank1 = true;
this._readbsr = true;
if (readMode) { this._writebsr = this._prewrite; }
this._prewrite = readMode;
//_debug('Bank 1 Read/Write');
break;
// Status registers
case LOC.BSRBANK2:
this._debug('Bank 2 Read ' + !this._bank1);
result = !this._bank1 ? 0x80 : 0x00;
break;
case LOC.BSRREADRAM:
this._debug('Bank SW RAM Read ' + this._readbsr);
result = this._readbsr ? 0x80 : 0x00;
break;
case LOC.RAMRD: // 0xC013
this._debug('Aux RAM Read ' + this._auxRamRead);
result = this._auxRamRead ? 0x80 : 0x0;
break;
case LOC.RAMWRT: // 0xC014
this._debug('Aux RAM Write ' + this._auxRamWrite);
result = this._auxRamWrite ? 0x80 : 0x0;
break;
case LOC.INTCXROM: // 0xC015
// _debug('Int CX ROM ' + _intcxrom);
result = this._intcxrom ? 0x80 : 0x00;
break;
case LOC.ALTZP: // 0xC016
this._debug('Alt ZP ' + this._altzp);
result = this._altzp ? 0x80 : 0x0;
break;
case LOC.SLOTC3ROM: // 0xC017
this._debug('Slot C3 ROM ' + this._slot3rom);
result = this._slot3rom ? 0x80 : 0x00;
break;
case LOC._80STORE: // 0xC018
this._debug('80 Store ' + this._80store);
result = this._80store ? 0x80 : 0x00;
break;
case LOC.VERTBLANK: // 0xC019
// result = cpu.getCycles() % 20 < 5 ? 0x80 : 0x00;
result = (this.cpu.getCycles() < this._vbEnd) ? 0x80 : 0x00;
break;
case LOC.RDTEXT:
result = this.vm.isText() ? 0x80 : 0x0;
break;
case LOC.RDMIXED:
result = this.vm.isMixed() ? 0x80 : 0x0;
break;
case LOC.RDPAGE2:
result = this.vm.isPage2() ? 0x80 : 0x0;
break;
case LOC.RDHIRES:
result = this.vm.isHires() ? 0x80 : 0x0;
break;
case LOC.RD80VID:
result = this.vm.is80Col() ? 0x80 : 0x0;
break;
case LOC.RDALTCH:
result = this.vm.isAltChar() ? 0x80 : 0x0;
break;
default:
debug('MMU missing register ' + toHex(off));
break;
}
if (result !== undefined)
return result;
result = 0;
this._updateBanks();
return result;
}
public start() {
this.lores1.start();
this.lores2.start();
return 0x00;
}
public end() {
return 0xff;
}
public reset() {
debug('reset');
this._initSwitches();
this._updateBanks();
this.vm.reset();
this.io.reset();
}
public read(page: byte, off: byte) {
return this._readPages[page].read(page, off);
}
public write(page: byte, off: byte, val: byte) {
this._writePages[page].write(page, off, val);
}
public resetVB() {
this._vbEnd = this.cpu.getCycles() + 1000;
}
/*
public getState(): State {
return {
bank1: this._bank1,
readbsr: this._readbsr,
writebsr: this._writebsr,
prewrite: this._prewrite,
intcxrom: this._intcxrom,
slot3rom: this._slot3rom,
intc8rom: this._intc8rom,
auxRamRead: this._auxRamRead,
auxRamWrite: this._auxRamWrite,
altzp: this._altzp,
_80store: this._80store,
page2: this._page2,
hires: this._hires,
mem00_01: [this.mem00_01[0].getState(), this.mem00_01[1].getState()],
mem02_03: [this.mem02_03[0].getState(), this.mem02_03[1].getState()],
mem0C_1F: [this.mem0C_1F[0].getState(), this.mem0C_1F[1].getState()],
mem60_BF: [this.mem60_BF[0].getState(), this.mem60_BF[1].getState()],
memD0_DF: [
this.memD0_DF[0].getState(), this.memD0_DF[1].getState(),
this.memD0_DF[2].getState(), this.memD0_DF[3].getState()
],
memE0_FF: [this.memE0_FF[0].getState(), this.memE0_FF[1].getState()]
};
}
public setState(state: State) {
this._readbsr = state.readbsr;
this._writebsr = state.writebsr;
this._bank1 = state.bank1;
this._prewrite = state.prewrite;
this._intcxrom = state.intcxrom;
this._slot3rom = state.slot3rom;
this._intc8rom = state.intc8rom;
this._auxRamRead = state.auxRamRead;
this._auxRamWrite = state.auxRamWrite;
this._altzp = state.altzp;
this._80store = state._80store;
this._page2 = state.page2;
this._hires = state.hires;
this.mem00_01[0].setState(state.mem00_01[0]);
this.mem00_01[1].setState(state.mem00_01[1]);
this.mem02_03[0].setState(state.mem02_03[0]);
this.mem02_03[1].setState(state.mem02_03[1]);
this.mem0C_1F[0].setState(state.mem0C_1F[0]);
this.mem0C_1F[1].setState(state.mem0C_1F[1]);
this.mem60_BF[0].setState(state.mem60_BF[0]);
this.mem60_BF[1].setState(state.mem60_BF[1]);
this.memD0_DF[0].setState(state.memD0_DF[0]);
this.memD0_DF[1].setState(state.memD0_DF[1]);
this.memD0_DF[2].setState(state.memD0_DF[2]);
this.memD0_DF[3].setState(state.memD0_DF[3]);
this.memE0_FF[0].setState(state.memE0_FF[0]);
this.memE0_FF[1].setState(state.memE0_FF[1]);
this._updateBanks();
}
*/
}