From 6991b68685d8c1b5fdb119ae8a72e867140ac985 Mon Sep 17 00:00:00 2001 From: Cyd Date: Wed, 15 Jul 2026 16:21:01 -0500 Subject: [PATCH] emu_main: IGC drain-wait hook (0xf0421510): firmware polls [r16] until the rasterizer consumes the region queue; we consume instantly Co-Authored-By: Claude Opus 4.8 --- emulator/firmware-decomp/emu_main.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/emulator/firmware-decomp/emu_main.py b/emulator/firmware-decomp/emu_main.py index 3169055..e8cf56a 100644 --- a/emulator/firmware-decomp/emu_main.py +++ b/emulator/firmware-decomp/emu_main.py @@ -60,6 +60,7 @@ MAPS = { # (PFAM/PFMAM families, FLAGM->MPIPE, sp/rp bit swap, fdest bypass) makes # the firmware's own Newton-Raphson divide compute correctly. intdiv=None, + igcwait=0xf0421510, # post-flush IGC drain poll (ld.l 0(r16)) seeds=[ (0x1000, 0), # _processorId ], @@ -106,8 +107,16 @@ class MainRunner: if m['putchar']: self.hooks[m['putchar']] = self.h_console if m['chain']: self.hooks[m['chain']] = self.h_chainfix if m.get('intdiv'): self.hooks[m['intdiv']] = self.h_intdiv + if m.get('igcwait'): self.hooks[m['igcwait']] = self.h_igcwait self.heap = [0x08010000, 0x0c010000] # bump allocator over the DRAM banks + def h_igcwait(self, cpu): + # Post-flush drain wait: the firmware polls [r16] until the IGC clears + # it after consuming the region queue. We are the IGC: consume instantly. + cpu.mem.w32(cpu.rd(16), 0) + cpu.step() + return True + def h_intdiv(self, cpu): # Runtime integer divide (r22 = r22/r23, result via ftrunc+fxfr): the # compiled Newton-Raphson relies on exact dual-op pipeline timing our