apple2js/js/mmu.ts

895 lines
28 KiB
TypeScript
Raw Normal View History

/* 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) => {
2020-11-24 16:53:43 +00:00
const v = LOC[loc];
this.locs[v] = loc;
});
}
start() {
return 0xC0;
}
end() {
return 0xC0;
}
read(_page: byte, off: byte) {
2020-11-24 16:53:43 +00:00
let 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
{
2020-11-24 16:53:43 +00:00
const 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];
}
2020-11-24 16:53:43 +00:00
}
_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;
2020-11-24 16:53:43 +00:00
const readMode = val === undefined;
const 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 {
2020-11-24 16:53:43 +00:00
// 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;
2020-11-24 16:53:43 +00:00
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
2020-11-24 16:53:43 +00:00
// _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
2020-11-24 16:53:43 +00:00
// 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();
}
*/
}