From b12ad0cad8eadec62ebe01cdddc88175b8b17861 Mon Sep 17 00:00:00 2001 From: Matthew Stanley <1379tech@gmail.com> Date: Thu, 30 Apr 2026 18:11:19 -0700 Subject: [PATCH] pi: host backtrace on OOB ROM read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a Windows DbgHelp backtrace inside do_rom_read's OOB branch. Cap reduced from 32 to 8 logged events so the backtrace stays readable. Identifies which recompiled C function (and via the funcs_NN.c filename, which MIPS function) issued the bogus DMA. Used to diagnose a downstream crash hypothesis: OOB events come from __amDMA → n_alAdpcmPull pulling ADPCM samples from corrupted wave-table base addresses. Pre-existing audio-buzz issue surfaces once attract gets past 0x8FF0ABFC and starts generating audio. The OOB DMAs zero-fill harmlessly; not the crash producer. Co-Authored-By: Claude Opus 4.7 (1M context) --- librecomp/src/pi.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/librecomp/src/pi.cpp b/librecomp/src/pi.cpp index 08cd806..2b26e5c 100644 --- a/librecomp/src/pi.cpp +++ b/librecomp/src/pi.cpp @@ -4,6 +4,11 @@ #include #include #include +#ifdef _WIN32 +#include +#include +#pragma comment(lib, "dbghelp.lib") +#endif #include "recomp.h" #include "librecomp/addresses.hpp" #include "librecomp/game.hpp" @@ -115,13 +120,34 @@ void recomp::do_rom_read(uint8_t* rdram, gpr ram_address, uint32_t physical_addr const uint32_t rom_off = physical_addr - recomp::rom_base; if (rom_off >= rom.size() || rom_off + num_bytes > rom.size()) { static int s_logged = 0; - if (s_logged < 32) { + if (s_logged < 8) { s_logged++; fprintf(stderr, "[do_rom_read] OUT-OF-BOUNDS phys=0x%08X off=0x%X size=0x%zX " "(rom_size=0x%zX) — zero-filling dst=0x%08X\n", physical_addr, rom_off, num_bytes, rom.size(), (uint32_t)(int32_t)ram_address); +#ifdef _WIN32 + HANDLE proc = GetCurrentProcess(); + SymInitialize(proc, NULL, TRUE); + void* frames[24]; + USHORT n = CaptureStackBackTrace(0, 24, frames, NULL); + char symbuf[sizeof(SYMBOL_INFO) + 256]; + SYMBOL_INFO* sym = (SYMBOL_INFO*)symbuf; + sym->SizeOfStruct = sizeof(SYMBOL_INFO); + sym->MaxNameLen = 255; + IMAGEHLP_LINE64 line; memset(&line, 0, sizeof(line)); + line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + for (USHORT i = 0; i < n && i < 18; i++) { + DWORD64 disp64 = 0; DWORD disp32 = 0; + const char* name = "?"; const char* file = "?"; DWORD lineno = 0; + if (SymFromAddr(proc, (DWORD64)frames[i], &disp64, sym)) name = sym->Name; + if (SymGetLineFromAddr64(proc, (DWORD64)frames[i], &disp32, &line)) { + file = line.FileName; lineno = line.LineNumber; + } + fprintf(stderr, " #%02u %s (%s:%lu)\n", i, name, file, lineno); + } +#endif fflush(stderr); } for (size_t i = 0; i < num_bytes; i++) {