nes-emu
Version:
A NES emulator
100 lines (94 loc) • 3.59 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _memory = require("../memory");
var _registers = require("../registers");
var _helpers = require("../helpers");
/** The CPU memory map. Addess space size: 64KB. */
class CPUMemoryMap {
constructor() {
_helpers.WithContext.apply(this);
_memory.WithCompositeMemory.apply(this);
}
/** When a context is loaded. */
onLoad(_ref) {
let {
ppu,
apu,
mapper,
controllers
} = _ref;
this.ram = new _memory.MemoryChunk(0x0800);
const ramMirror = new _memory.MemoryMirror(this.ram, 0x1800);
const ppuRegisters = ppu.registers.toMemory();
const ppuRegistersMirror = new _memory.MemoryMirror(ppuRegisters, 0x1ff8);
const apuRegisters = apu.registers.toMemory();
const port2AndFrameCounter = new _registers.MixedInMemoryRegister(controllers[1].port, apu.registers.apuFrameCounter);
const cpuTestModeRegisters = new _memory.MemoryPadding(0x0008);
this.defineChunks([
// Address range Size Device
this.ram,
// $0000-$07FF $0800 2KB internal RAM
ramMirror,
// $0800-$1FFF $1800 Mirrors of $0000-$07FF
ppuRegisters,
// $2000-$2007 $0008 NES PPU registers
ppuRegistersMirror,
// $2008-$3FFF $1FF8 Mirrors of $2000-$2007 (repeats every 8 bytes)
apuRegisters,
// $4000-$4013 $0014 NES APU registers
ppu.registers.oamDma,
// $4014-$4014 $0001 PPU's OAM DMA register
apu.registers.apuMain,
// $4015-$4015 $0001 APU status/control register
controllers[0].port,
// $4016-$4016 $0001 Controller port 1
port2AndFrameCounter,
// $4017-$4017 $0001 Controller port 2 and APU frame counter
cpuTestModeRegisters,
// $4018-$401F $0008 APU and I/O functionality that is normally disabled
mapper.segments.cpu // $4020-$FFFF $BFE0 Cartridge space: PRG ROM, PRG RAM, and mapper registers
]);
}
/** Reads a `byte` from `address`, which can be a register or a memory address. */
readAt(address) {
return address.value != null ? address.value : _memory.WithCompositeMemory.readAt.call(this, address);
}
/** Writes a `byte` to `address`, which can be a register or a memory address. */
writeAt(address, byte) {
if (address.value != null) address.value = byte;else _memory.WithCompositeMemory.writeAt.call(this, address, byte);
}
/** Returns a snapshot of the current state. */
getSaveState() {
const {
ppu,
apu
} = this.context;
return {
ram: Array.from(this.ram.bytes),
ppuRegisters: ppu.registers.toMemory().chunks.map(it => it.value),
apuRegisters: apu.registers.toMemory().chunks.map(it => it.value),
apuControl: apu.registers.apuControl.value,
apuFrameCounter: apu.registers.apuFrameCounter.value
};
}
/** Restores state from a snapshot. */
setSaveState(saveState) {
const {
ppu,
apu
} = this.context;
this.ram.bytes.set(saveState.ram);
ppu.registers.toMemory().chunks.forEach((chunk, i) => {
chunk.setValue && chunk.setValue(saveState.ppuRegisters[i]);
});
apu.registers.toMemory().chunks.forEach((chunk, i) => {
chunk.setValue && chunk.setValue(saveState.apuRegisters[i]);
});
apu.registers.apuControl.setValue(saveState.apuControl);
apu.registers.apuFrameCounter.setValue(saveState.apuFrameCounter);
}
}
exports.default = CPUMemoryMap;
;