nes-emu
Version:
A NES emulator
89 lines (87 loc) • 2.98 kB
JavaScript
;
var _memory = require("../memory");
var _constants = require("./constants");
var _constants2 = _interopRequireDefault(require("../constants"));
var _createTestContext = _interopRequireDefault(require("../helpers/createTestContext"));
var _helpers = require("../helpers");
var _lodash = _interopRequireDefault(require("lodash"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const should = require("chai").Should();
const registersOf = cpu => _lodash.default.mapValues(cpu.registers, reg => reg.value);
describe("CPU", () => {
let cpu, memory;
beforeEach(() => {
({
cpu,
memory
} = (0, _createTestContext.default)(context => {
// mock the whole memory map
const memory = new _memory.MemoryChunk(_constants2.default.CPU_ADDRESSED_MEMORY);
_helpers.WithContext.apply(memory);
context.cpu.memory = memory;
// define sample program: NOP ; LDA #$05 ; STA $0201
memory.write2BytesAt(_constants.interrupts.RESET.vector, 0x1234);
[0xea, 0xa9, 0x05, 0x8d, 0x01, 0x02].forEach((byte, i) => memory.writeAt(0x1234 + i, byte));
}));
});
it("initializes all variables", () => {
cpu.pc.value.should.equal(0x1234);
cpu.sp.value.should.equal(0xfd);
cpu.flags.should.include({
n: false,
v: false,
d: false,
i: true,
z: false,
c: false
});
cpu.cycle.should.equal(7);
registersOf(cpu).should.include({
x: 0,
y: 0,
a: 0
});
});
it("can run 3 simple operations", () => {
let cycles;
cycles = cpu.step();
cycles.should.equal(2);
cpu.pc.value.should.equal(0x1235);
cpu.cycle.should.equal(9);
cycles = cpu.step();
cycles.should.equal(2);
cpu.pc.value.should.equal(0x1237);
cpu.cycle.should.equal(11);
cpu.registers.a.value.should.equal(5);
cycles = cpu.step();
cycles.should.equal(4);
cpu.pc.value.should.equal(0x123a);
cpu.cycle.should.equal(15);
memory.readAt(0x0201).should.equal(5);
});
_lodash.default.values(_constants.interrupts).forEach(interrupt => {
it("can handle ".concat(interrupt.id, " interrupts"), () => {
cpu.step();
cpu.pc.value.should.equal(0x1235);
cpu.flags.i = false;
memory.write2BytesAt(interrupt.vector, 0x3125);
cpu.interrupt(interrupt);
cpu.stack.pop().should.equal(0b00100000);
cpu.stack.pop2Bytes().should.equal(0x1235);
cpu.cycle.should.equal(16);
cpu.flags.i.should.equal(true);
cpu.pc.value.should.equal(0x3125);
});
});
it("ignores IRQ interrupts when the I flag is set", () => {
cpu.step();
cpu.pc.value.should.equal(0x1235);
cpu.flags.i = true;
memory.write2BytesAt(_constants.interrupts.IRQ.vector, 0x3125);
cpu.interrupt(_constants.interrupts.IRQ);
cpu.sp.value.should.equal(0xfd);
cpu.cycle.should.equal(9);
cpu.flags.i.should.equal(true);
cpu.pc.value.should.equal(0x1235);
});
});