EvCB write-trace instrumentation confirmed OpenEvent is never called for
any event class during boot, not only VBlank. Static ROM analysis found
that the only instruction in SCPH1001.BIN that stores to the VSync
counter at 0x80079D9C lives in an unrecompiled 15-instruction function
at 0xBFC425BC (identified as the VBlank chain handler: increments the
counter, optionally calls the user callback at *0x800DFF40). Added as a
seed so the function is now compiled and present in the dispatch table.
Recompile alone does not unblock the boot — no JAL, literal, or
lui 0xBFC4 exists in ROM that would load this address, so the kernel
registrar that enqueues it on the root-counter chain is itself missing
and needs to be found (next session, via DuckStation cross-reference).
Changes:
- recompiler/seeds: +0xBFC425BC (vblank_chain_handler), 825 seeds total
- debug_server: wtrace_range / wtrace_dump / wtrace_clear TCP commands,
1024-entry ring buffer capturing (addr, old, new, ra, width); default
range 0x0000E000..0x0000E1F0 active from process start so early-boot
writes are captured before a TCP client can attach
- memory.c: inline bounds check + hook call in psx_write_{word,half,byte}
- tools: print_wtrace.py, sample_ra.py, sample_ra_long.py,
scan_f2_sites.py — investigation helpers
Runtime behaviour unchanged (still hangs in VSync spin at Sony logo) —
the seed is a prerequisite; the upstream registrar is the next bug.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Integrated the salvaged gpu_sw_renderer.c into gpu.c's command pipeline:
- Textured triangles/quads now do real CLUT/texpage lookup instead of flat color
- Gouraud-shaded triangles/quads interpolate vertex colors via SW renderer
- Shaded+textured primitives extract texcoords and pass to SW renderer
- Textured rectangles (variable, 8x8, 16x16) use sw_draw_textured_rect
- VRAM→VRAM copy (GP0 0x80-0x9F) implemented via sw_copy_rect
- All GPU environment commands sync state to SW renderer (draw area,
draw offset, mask bits, texture window)
- Fixed generated/cpu_state.h to include gte_data/gte_ctrl arrays
(struct layout mismatch caused segfault on first run)
Validated: BIOS boots, GPU processes 16,859+ GP0 commands including
1,149 draw calls and 66 copy transfers. VRAM contains non-zero pixel
data across multiple regions confirming active rendering.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three interrupt delivery bugs fixed that were blocking shell progression:
1. RFE after handler exit: The exception handler's normal exit path
(jmpbuf longjmp at 0xBFC10944) does not execute RFE. In our model
the handler returns to psx_check_interrupts, not to the WaitEvent
caller. Without RFE, IEc stays 0 forever after the first interrupt.
Fix: apply RFE in psx_check_interrupts if IEc is still 0 after the
handler returns.
2. GPR save/restore around handler dispatch: The handler's jmpbuf exit
restores callee-saved registers from the kernel jmpbuf (intended for
a non-local jump to WaitEvent's caller). In our model this corrupts
the interrupted code's registers. Fix: save all GPRs before handler
dispatch and restore them after, matching real hardware where the
interrupted code's registers are preserved via TCB save/restore.
3. VBlank tick gated on !in_exception: The handler runs thousands of
block leaders, each calling psx_check_interrupts. Without gating,
dispatch_count advances inside the handler, firing new VBlanks that
stack up and starve the main code. Fix: only increment dispatch_count
and fire VBlank/timer ticks when not in exception handling.
4. DMA IRQ edge-triggered: update_master_irq() was level-triggered,
re-asserting i_stat bit 3 on every call while master_flag=1. Combined
with no BIOS callback to acknowledge DMA IRQs, this caused an
interrupt storm. Fix: edge-detect master_flag 0->1 transition, and
suppress DMA completion IRQs entirely since transfers are synchronous.
Also adds GPU debug diagnostics: GP0 command counters (nop/fill/draw/
env/copy), draw area/offset in gpu_state, vram_peek debug command.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>