mirror of
https://github.com/N64Recomp/N64Recomp.git
synced 2026-05-15 07:29:46 -05:00
RSPRecomp: pre-task hook + richer watchdog state dump
Two related changes for diagnosing hung RSP ucodes: 1. Per-ucode pre-task hook. The legacy wrapper now calls recomp::rsp::run_pre_task_hook(rdram, &persistent_ctx, ucode_name, ucode_addr) before invoking impl. Lets games register hook callbacks keyed by ucode name to replicate parts of rspboot's setup that the static recompilation can't infer (initial GPRs, DMA-engine residue, pre-loaded command data in DMEM). No-op when no hook is registered (one branch). Used this session to unstick Stadium's aspMain dispatch by pre-loading audio commands at DMEM[0x2B0] and seeding $29 = 0x2B0, $30 = chunk_size. Confirmed via watchdog trail: the dispatch now lands on real handlers (r26 = first audio cmd word 0x020004E0, r28/r27/r30 advance through one command) instead of looping on dispatch-table residue. 2. Watchdog trip dump now includes r1, r2, r3, r25, r26, r27, r28, r29, r30, r31, jump_target, dma_mem_address, dma_dram_address. Earlier dump (r1/r28/r29/r31 only) was too sparse to localize the next blocker — Stadium's hang now occurs at L_11B4 ↔ L_10EC because r3 is uninit going into the dispatched handler (handler does `r3 -= 1` then DMAs, but no upstream path set r3 for the first command). Richer state lets future hangs in any consumer game be diagnosed without recompiling the recompiler each time. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2e71ff4352
commit
4d594da0b9
|
|
@ -257,7 +257,8 @@ bool process_instruction(size_t instr_index, const std::vector<rabbitizer::Instr
|
|||
" uint32_t pos = (ctx->pc_trail_idx + i) & 31;\n"
|
||||
" fprintf(stderr, \" [%2u] PC=0x%04X\\n\", i, ctx->pc_trail[pos]);\n"
|
||||
" }}\n"
|
||||
" fprintf(stderr, \"[rsp watchdog] regs: r1=%08X r28=%08X r29=%08X r31=%08X data_ptr-related: r28=%08X data_size: r27=%08X\\n\", ctx->r1, ctx->r28, ctx->r29, ctx->r31, ctx->r28, ctx->r27);\n"
|
||||
" fprintf(stderr, \"[rsp watchdog] gprs: r1=%08X r2=%08X r3=%08X r25=%08X r26=%08X r27=%08X r28=%08X r29=%08X r30=%08X r31=%08X jt=%08X dma_mem=%08X dma_dram=%08X\\n\",\n"
|
||||
" ctx->r1, ctx->r2, ctx->r3, ctx->r25, ctx->r26, ctx->r27, ctx->r28, ctx->r29, ctx->r30, ctx->r31, ctx->jump_target, ctx->dma_mem_address, ctx->dma_dram_address);\n"
|
||||
" return RspExitReason::Watchdog;\n"
|
||||
" }}\n",
|
||||
instr_vram);
|
||||
|
|
@ -1173,6 +1174,14 @@ void create_function(const std::string& function_name, std::ofstream& output_fil
|
|||
"\n"
|
||||
"RspExitReason {0}(uint8_t* rdram, [[maybe_unused]] uint32_t ucode_addr) {{\n"
|
||||
" static thread_local RspContext persistent_ctx{{}};\n"
|
||||
" // Pre-task hook: if a runtime registered a hook keyed by\n"
|
||||
" // this ucode's name, call it here. Lets game-specific code\n"
|
||||
" // replicate parts of rspboot's setup that the static\n"
|
||||
" // recompilation can't infer (initial GPRs, DMA-engine\n"
|
||||
" // residue, pre-loaded command data in DMEM). Inline\n"
|
||||
" // null-check by the std::unordered_map lookup — typical\n"
|
||||
" // cost is one branch when no hook is registered.\n"
|
||||
" recomp::rsp::run_pre_task_hook(rdram, &persistent_ctx, \"{0}\", ucode_addr);\n"
|
||||
" return {0}_impl(rdram, &persistent_ctx);\n"
|
||||
"}}\n",
|
||||
function_name);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user