tests: GPUSTAT.24 survives a save state

Raises IRQ1 from code poked into RAM, saves, acks with GP1(02h), loads, and checks the flag is back. Fails with the restore in GPU::deserialize removed.
This commit is contained in:
Rix
2026-10-10 08:59:18 -07:00
parent 92ded553bd
commit 363869f8a3
+50
View File
@@ -28,3 +28,53 @@ TEST(GPUIRQ, RequestAcknowledge) {
int ret = invoker.invoke();
EXPECT_EQ(ret, 0);
}
// IRQ1 survives a save state. Code poked into RAM raises it with GP0(1Fh) and keeps copying
// GPUSTAT to 0x80100100; a state is saved, GP1(02h) acks the flag, the state is loaded, and
// GPUSTAT.24 must be set again. Loading replays GP1 writes that clear the flag before
// GPU::deserialize puts it back.
static const char c_irq1SaveState[] = R"(
local ram = ffi.cast('uint32_t*', PCSX.getMemPtr())
local base = 0x100000 / 4
local out = 0x100100 / 4
local stubs = {
-- 0x80100000: GP0(1Fh) raises IRQ1, then GPUSTAT -> 0x80100100 forever
0x3c081f80, 0x3c091f00, 0xad091810, 0x3c0b8010,
0x8d0a1814, 0x00000000, 0xad6a0100, 0x08040004, 0x00000000,
0, 0, 0, 0, 0, 0, 0,
-- 0x80100040: GP1(02h) acks IRQ1, then the same loop
0x3c081f80, 0x3c090200, 0xad091814, 0x3c0b8010,
0x8d0a1814, 0x00000000, 0xad6a0100, 0x08040014, 0x00000000,
}
local sentinel = 0xdeadbeef
local frames = 0
local state
local function irq1() return bit.band(ram[out], 0x01000000) ~= 0 and ram[out] ~= sentinel end
IRQ1SaveStateListener = PCSX.Events.createEventListener('GPU::Vsync', function()
frames = frames + 1
if frames == 120 then
for i, w in ipairs(stubs) do ram[base + i - 1] = w end
ram[out] = sentinel
PCSX.getRegisters().pc = 0x80100000
elseif frames == 122 then
if not irq1() then print('IRQ1 never raised') PCSX.quit(2) return end
state = PCSX.createSaveState()
ram[out] = sentinel
PCSX.getRegisters().pc = 0x80100040
elseif frames == 124 then
if ram[out] == sentinel or irq1() then print('GP1(02h) did not ack IRQ1') PCSX.quit(3) return end
PCSX.loadSaveState(state)
elseif frames == 125 then
ram[out] = sentinel
elseif frames == 127 then
if irq1() then PCSX.quit(0) else print('IRQ1 lost across the save state') PCSX.quit(1) end
end
end)
)";
TEST(GPUIRQ, SaveStateKeepsFlag) {
MainInvoker invoker("-no-ui", "-run", "-bios", "src/mips/openbios/openbios.bin", "-testmode", "-interpreter",
"-exec", c_irq1SaveState);
int ret = invoker.invoke();
EXPECT_EQ(ret, 0);
}