#include "doctest.h" #include "cpu/cpu.h" #include "memory/ram.h" TEST_CASE("EI followed by DI should not trigger interrupt") { u8 test_ram[] = { 0xFB, // EI 0xF3, // DI 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; RAM r(test_ram, 0x20, true); Cpu cpu(&r); cpu.state.IE = 0x1F; // Enable all types of interrupts cpu.state.IF = 0x1F; // All interrupts pending CHECK(cpu.state.PC == 0x0); CHECK(cpu.state.IME == IME_OFF); cpu.step(); CHECK(cpu.state.PC == 0x1); CHECK(cpu.state.IME == IME_SCHEDULED); cpu.step(); CHECK(cpu.state.PC == 0x2); CHECK(cpu.state.IME == IME_OFF); cpu.step(); CHECK(cpu.state.PC == 0x3); CHECK(cpu.state.IME == IME_OFF); } TEST_CASE("interrupt triggers call to correct ISR") { RAM r(0x100); Cpu cpu(&r); cpu.state.IME = IME_ON; cpu.state.IE = INT_MASK; InterruptType it; u8 expected_pc; SUBCASE("VBlank") { it = INT_VBlank; expected_pc = 0x40; } SUBCASE("LCDSTAT") { it = INT_LCDSTAT; expected_pc = 0x48; } SUBCASE("Timer") { it = INT_Timer; expected_pc = 0x50; } SUBCASE("Serial") { it = INT_Serial; expected_pc = 0x58; } SUBCASE("Joypad") { it = INT_Joypad; expected_pc = 0x60; } cpu.signalInterrupt(it); CHECK(cpu.state.IF == it); cpu.step(); CHECK(cpu.state.IF == 0); CHECK(cpu.state.PC == expected_pc); CHECK(cpu.state.IME == IME_OFF); }