UNPKG

nes-emu

Version:

A NES emulator

98 lines (90 loc) 3.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _memory = require("../../memory"); var _constants = _interopRequireDefault(require("../../constants")); var _helpers = require("../../helpers"); var _lodash = _interopRequireDefault(require("lodash")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } /** * An abstract class that represents a generic mapper. * It has two memory segments: * - One mapped at CPU $4020-$FFFF (for PRG ROM, PRG RAM, and mapper registers) * - One mapped at PPU $0000-$1FFF (for CHR ROM / Pattern tables) * It intercepts all CPU write operations. */ class Mapper { static get id() { throw new Error("not_implemented"); } constructor() { let prgRomPageSize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _constants.default.PRG_ROM_PAGE_SIZE; let chrRomPageSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _constants.default.CHR_ROM_PAGE_SIZE; _helpers.WithContext.apply(this); this.prgRomPageSize = prgRomPageSize; this.chrRomPageSize = chrRomPageSize; } /** Creates a memory segment for CPU range $4020-$FFFF. */ createCPUSegment(context) { throw new Error("not_implemented"); } /** Creates a memory segment for PPU range $0000-$1FFF. */ createPPUSegment(context) { throw new Error("not_implemented"); } /** When a context is loaded. */ onLoad(context) { const { cartridge } = context; const prg = cartridge.prgRom; const chr = cartridge.chrRom; const totalPrgPages = Math.floor(prg.length / this.prgRomPageSize); const totalChrPages = Math.floor(chr.length / this.chrRomPageSize); this.prgPages = _lodash.default.range(0, totalPrgPages).map(page => this._getPage(prg, this.prgRomPageSize, page)); this.chrPages = _lodash.default.range(0, totalChrPages).map(page => this._getPage(chr, this.chrRomPageSize, page)); this.segments = { cpu: this.createCPUSegment(context), ppu: this.createPPUSegment(context) }; } /** Maps a CPU write operation. */ cpuWriteAt(address, byte) { this.context.cpu.memory.writeAt(address, byte); } /** Runs at cycle 260 of every scanline (including preline). Returns a CPU interrupt or null. */ tick() { return null; } /** Returns a snapshot of the current state. */ getSaveState() { return { chrPages: this.context.cartridge.header.usesChrRam ? this.chrPages.map(it => Array.from(it)) : null }; } /** Restores state from a snapshot. */ setSaveState(saveState) { if (saveState.chrPages != null) this.chrPages = saveState.chrPages.map(it => new Uint8Array(it)); } _newPrgBank() { let id = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; return new _memory.MemoryChunk(this.prgPages[id]).asReadOnly(); } _newChrBank(cartridge) { let id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; return new _memory.MemoryChunk(this.chrPages[id]).asReadOnly(!cartridge.header.usesChrRam); } _getPrgPage(page) { return this.prgPages[Math.max(0, page % this.prgPages.length)]; } _getChrPage(page) { return this.chrPages[Math.max(0, page % this.chrPages.length)]; } _getPage(memory, pageSize, page) { const offset = page * pageSize; return memory.slice(offset, offset + pageSize); } } exports.default = Mapper;