UNPKG

nes-emu

Version:

A NES emulator

70 lines (69 loc) 2.41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _WithLittleEndian = _interopRequireDefault(require("./WithLittleEndian")); var _lodash = _interopRequireDefault(require("lodash")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } /** A mixin for composite memory handling, with multiple `chunks`. */ var _default = exports.default = { /** Applies the mixin. */ apply(obj) { _lodash.default.defaults(obj, _lodash.default.omit(this, "apply", "createSegment")); _WithLittleEndian.default.apply(obj); obj.chunks = null; obj.lut = null; }, /** Creates a composite memory segment with different `chunks`. */ createSegment(chunks) { const memory = {}; this.apply(memory); memory.defineChunks(chunks); return memory; }, /** Defines the `chunks` of the memory map. */ defineChunks(chunks) { this.chunks = chunks; this.lut = []; let startAddress = 0; for (let chunk of this.chunks) { chunk.$memoryStartAddress = startAddress; startAddress += chunk.memorySize; } this.memorySize = startAddress; this._generateLookUpTable(startAddress); }, /** Reads a byte from `address`, using the correct `chunk`. */ readAt(address) { const chunk = this.lut[address * 2] || this._throwUnreachable(address); const offset = this.lut[address * 2 + 1]; return chunk.readAt(offset); }, /** Writes a `byte` to `address`, using the correct `chunk`. */ writeAt(address, byte) { const chunk = this.lut[address * 2] || this._throwUnreachable(address); const offset = this.lut[address * 2 + 1]; chunk.writeAt(offset, byte); }, _throwUnreachable(address) { throw new Error("Unreachable address: 0x".concat(address.toString(16), ".")); }, _generateLookUpTable(finalAddress) { for (let i = 0; i < finalAddress; i++) { const chunk = this._getChunkFor(i); const offset = this._toRelativeAddress(i, chunk); this.lut[i * 2] = chunk; this.lut[i * 2 + 1] = offset; } }, _getChunkFor(address) { for (let chunk of this.chunks) { const startAddress = chunk.$memoryStartAddress; if (address >= startAddress && address < startAddress + chunk.memorySize) return chunk; } }, _toRelativeAddress(address, chunk) { return address - chunk.$memoryStartAddress; } };