UNPKG

broken-neees

Version:

A really broken NEEES emulator that introduces glitches and random bugs on purpose!

89 lines (87 loc) 3.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _Register = require("./Register"); var _FlagsRegister = _interopRequireDefault(require("./FlagsRegister")); var _Stack = _interopRequireDefault(require("./Stack")); var _instructions = _interopRequireDefault(require("./instructions")); var _addressingModes = _interopRequireDefault(require("./addressingModes")); var _defineOperations = _interopRequireDefault(require("../lib/cpu/defineOperations")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } class CPU { constructor(cpuMemory) { this.memory = cpuMemory; this.cycle = 0; this.extraCycles = 0; this.a = new _Register.Register8Bit(); this.x = new _Register.Register8Bit(); this.y = new _Register.Register8Bit(); this.sp = new _Register.Register8Bit(); this.pc = new _Register.Register16Bit(); this.flags = new _FlagsRegister.default(); this.stack = new _Stack.default(this.memory, this.sp); this.operations = (0, _defineOperations.default)(_instructions.default, _addressingModes.default); } step() { const originalPC = this.pc.getValue(); const operation = this._fetchOperation(); const input = this._fetchInput(operation); const argument = this._fetchArgument(operation, input); if (this.logger != null) { this.logger(this, originalPC, operation, input, argument); } operation.instruction.run(this, argument); return this._addCycles(operation); } interrupt(interrupt, withBFlag) { if (interrupt.id === "IRQ" && this.flags.i) return 0; this.stack.push16(this.pc.getValue()); this.stack.push(this.flags.getValue() | (withBFlag && 0b00010000)); this.cycle += 7; this.flags.i = true; this.pc.setValue(this.memory.read16(interrupt.vector)); return 7; } _fetchOperation() { const opcode = this.memory.read(this.pc.getValue()); const operation = this.operations[opcode]; if (operation == null) throw new Error("Invalid opcode: 0x" + opcode.toString(16)); this.pc.increment(); return operation; } _fetchInput(operation) { let input = null; if (operation.addressingMode.inputSize === 1) { input = this.memory.read(this.pc.getValue()); this.pc.increment(); } else if (operation.addressingMode.inputSize === 2) { input = this.memory.read16(this.pc.getValue()); this.pc.increment(); this.pc.increment(); } return input; } _fetchArgument(operation, input) { const arg = operation.instruction.argument === "value" ? operation.addressingMode.getValue(this, input, operation.hasPageCrossPenalty) : operation.addressingMode.getAddress(this, input, operation.hasPageCrossPenalty); // [!!!] if (!this.unbroken) { if (Math.random() < 0.0005 && operation.id === 0x69 /* adc immediate */) return arg + 1; } return arg; } _addCycles(operation) { let cycles; if (this.unbroken) { cycles = operation.cycles + this.extraCycles; } else { // [!!!] cycles = Math.floor(Math.random() * 10); } this.cycle += cycles; this.extraCycles = 0; return cycles; } } exports.default = CPU;