nes-emu
Version:
A NES emulator
70 lines (69 loc) • 2.41 kB
JavaScript
;
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;
}
};