mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-28 19:07:47 -04:00
e8094affb4
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>
70 lines
2.7 KiB
Python
70 lines
2.7 KiB
Python
#!/usr/bin/env python3
|
|
import sys
|
|
rom = open('F:/Projects/psxrecomp-v4/bios/SCPH1001.BIN','rb').read()
|
|
|
|
matches = []
|
|
for rt in range(32):
|
|
word = (0x0F << 26) | (rt << 16) | 0xF200
|
|
b = word.to_bytes(4, 'little')
|
|
off = 0
|
|
while True:
|
|
o = rom.find(b, off)
|
|
if o == -1: break
|
|
bios_addr = 0xBFC00000 + o
|
|
next_word = int.from_bytes(rom[o+4:o+8], 'little')
|
|
op = (next_word >> 26) & 0x3F
|
|
rs = (next_word >> 21) & 0x1F
|
|
rt_out = (next_word >> 16) & 0x1F
|
|
imm = next_word & 0xFFFF
|
|
matches.append((bios_addr, rt, op, rs, rt_out, imm, next_word, o))
|
|
off = o + 4
|
|
|
|
print("--- ROM sites forming 0xF200xxxx (class values) ---")
|
|
for addr, rt, op, rs, rt_out, imm, nw, offset in matches:
|
|
if rs == rt and rt_out == rt:
|
|
if op == 0x0D:
|
|
marker = "OPENEVENT-TARGET" if imm in (1,2,3,9) else ""
|
|
print(f" 0x{addr:08X}: lui r{rt}, 0xF200; ori r{rt}, 0x{imm:04X} class=0xF200{imm:04X} {marker}")
|
|
|
|
print("\n--- 0xF2000003 (VBlank) sites, JAL-adjacency check ---")
|
|
for addr, rt, op, rs, rt_out, imm, nw, offset in matches:
|
|
if rs == rt and rt_out == rt and op == 0x0D and imm == 0x0003:
|
|
o = offset
|
|
# JAL preceding? (i.e. at offset-4)
|
|
if o >= 4:
|
|
prev = int.from_bytes(rom[o-4:o], 'little')
|
|
op_prev = (prev >> 26) & 0x3F
|
|
if op_prev == 0x03:
|
|
jal_addr = 0xBFC00000 + o - 4
|
|
target = (jal_addr & 0xF0000000) | ((prev & 0x3FFFFFF) << 2)
|
|
print(f" 0x{addr:08X}: VBlank class; PREV_JAL at 0x{jal_addr:08X} -> 0x{target:08X}")
|
|
else:
|
|
print(f" 0x{addr:08X}: VBlank class; prev op=0x{op_prev:02x} at 0x{0xBFC00000+o-4:08X}")
|
|
|
|
# Now: find which functions contain these addresses
|
|
# A function "contains" addr if it's the closest-entry <= addr
|
|
# Read dispatch.c:
|
|
print("\n--- Functions containing 0xF2000003 sites ---")
|
|
import re
|
|
dispatch = open('F:/Projects/psxrecomp-v4/generated/SCPH1001_dispatch.c').read()
|
|
entries = re.findall(r'\{\s*0x([0-9A-F]+)u,\s*func_([0-9A-F]+)\s*\}', dispatch)
|
|
# Only keep those in code range (phys 0x1FC00000+)
|
|
fn_list = sorted([(int(a,16), name) for a,name in entries])
|
|
def containing_fn(addr):
|
|
phys = addr & 0x1FFFFFFF
|
|
prev = None
|
|
for faddr, name in fn_list:
|
|
if faddr <= phys:
|
|
prev = (faddr, name)
|
|
else:
|
|
break
|
|
return prev
|
|
|
|
for addr, rt, op, rs, rt_out, imm, nw, offset in matches:
|
|
if rs == rt and rt_out == rt and op == 0x0D and imm == 0x0003:
|
|
cf = containing_fn(addr)
|
|
if cf:
|
|
print(f" 0x{addr:08X} (lui+ori F2000003) is inside func_{cf[1]} (entry 0x{cf[0]:08X})")
|
|
else:
|
|
print(f" 0x{addr:08X}: NO CONTAINING FUNCTION (orphan code region!)")
|