UNPKG

nes-emu

Version:

A NES emulator

98 lines (95 loc) 4.86 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _indirect = require("../cpu/addressings/indirect"); var _helpers = require("../helpers"); var _lodash = _interopRequireDefault(require("lodash")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const hex = (value, length) => _lodash.default.padStart(value.toString(16).toUpperCase(), length, "0"); /** A logger that resembles Nintendulator's logs format, to use with nestest (a test ROM). */ class NESTestLogger { constructor() { this.lastLog = null; } /** Logs a CPU instruction. All the information is in `request`. */ log(request) { const { context, pc, operation, initialArgument, finalArgument } = request; try { context.inDebugMode(() => { const { cpu } = context; const memory = cpu.memory; const cycle = (value, length) => _lodash.default.padStart(value.toString(), length); const section = (string, length) => _lodash.default.padEnd(string.substr(0, length), length); const hexArgument = value => { if (operation.addressing.parameterSize === 0) return ""; return operation.addressing.parameterSize === 2 ? hex(value, 4) : hex(value, 2); }; const formatParameter = () => { const instructionsWithValue = ["STA", "STX", "STY", "LDA", "LDX", "LDY", "BIT", "ORA", "AND", "EOR", "ADC", "SBC", "CMP", "CPX", "CPY", "LSR", "ASL", "ROR", "ROL", "INC", "DEC"]; const $initialArgument = hexArgument(initialArgument); const $finalArgument = hexArgument(finalArgument); let finalAddress = null; try { finalAddress = operation.addressing.getAddress(context, initialArgument); } catch (e) {} switch (operation.addressing.id) { case "IMPLICIT": return ""; case "IMMEDIATE": return "#$".concat($finalArgument); case "ABSOLUTE": let $address = "$".concat($initialArgument); if (_lodash.default.includes(instructionsWithValue, operation.instruction.id)) $address += " = ".concat(hex(memory.readAt(finalAddress), 2)); return $address; case "ZERO_PAGE": return "$".concat($initialArgument, " = ").concat(hex(memory.readAt(finalAddress), 2)); case "INDEXED_ABSOLUTE_X": case "INDEXED_ZERO_PAGE_X": return "$".concat($initialArgument, ",X @ ").concat(hexArgument(finalAddress), " = ").concat(hex(memory.readAt(finalAddress), 2)); case "INDEXED_ABSOLUTE_Y": case "INDEXED_ZERO_PAGE_Y": return "$".concat($initialArgument, ",Y @ ").concat(hexArgument(finalAddress), " = ").concat(hex(memory.readAt(finalAddress), 2)); case "INDIRECT": return "($".concat($initialArgument, ") = ").concat(hex(finalAddress, 4)); case "INDEXED_INDIRECT_X": return "($".concat($initialArgument, ",X) @ ").concat(hex(_helpers.Byte.force8Bit(initialArgument + cpu.registers.x.value), 2), " = ").concat(hex(finalAddress, 4), " = ").concat(hex(memory.readAt(finalAddress), 2)); case "INDEXED_INDIRECT_Y": return "($".concat($initialArgument, "),Y = ").concat(hex((0, _indirect.getIndirectAddress)(context, initialArgument), 4), " @ ").concat(hex(finalAddress, 4), " = ").concat(hex(memory.readAt(finalAddress), 2)); case "ACCUMULATOR": return "A"; default: return "$".concat($finalArgument); } }; const $counter = section(hex(pc, 4), 6); const $operation = hex(operation.id, 2); let $arguments = " "; if (operation.addressing.parameterSize > 0) { $arguments += operation.addressing.parameterSize === 2 ? hex(_helpers.Byte.lowPartOf(initialArgument), 2) + " " + hex(_helpers.Byte.highPartOf(initialArgument), 2) : hex(initialArgument, 2); } const $commandHex = section($operation + $arguments, 10); const $assembly = section(operation.instruction.id + " " + formatParameter(), 32); const $registers = ["a", "x", "y"].map(register => { return register.toUpperCase() + ":" + hex(cpu.registers[register].value, 2); }).join(" ") + " P:" + hex(cpu.flags.toByte(), 2) + " SP:" + hex(cpu.sp.value, 2); const $ppuCycle = "PPU:" + cycle(0, 3) + "," + cycle(1, 3); const $cpuCycle = "CYC:" + cpu.cycle; const $status = "".concat($registers, " ").concat($ppuCycle, " ").concat($cpuCycle); this.lastLog = $counter + $commandHex + $assembly + $status; }); } catch (e) { console.error(e); } } } exports.default = NESTestLogger;