mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-25 18:05:12 -04:00
87d99d4f1d
Adds the Beetle-discovered chain writer/init PCs as dispatch_miss seeds
so the recompiler emits standalone functions for them at their RAM
destination addresses (via the existing Phase 1e ROM↔RAM alias rule
RAM = ROM - 0xBFC10000 + 0x500):
0xBFC14A54 → 0x00004F54 (chain BUSY-writer)
0xBFC158D0 → 0x00005DD0 (chain init slot-0 BUSY)
0xBFC158D8 → 0x00005DD8 (chain init slot-1 BUSY)
0xBFC159F4 → 0x00005EF4 (chain step 0x02-OPEN writer — KEY)
0xBFC15AA8 → 0x00005FA8 (chain step 0x04-OPEN writer — KEY)
Post-regen dispatch_table contains all 5 as standalone entries. e.g.
func_00005EF4 is a clean 3-instruction leaf (sb $t3, 0($a3); v0=1; jr ra).
Validation (full output in docs/CASE_A_AOT_GAP.md "Vertical slice result"):
- ✓ dispatch_table contains all 5 entries
- ✗ none of the 5 are reached at runtime — chain still doesn't dispatch
- ✗ [0x80007510..0x7570] all-zero — the chain init function FUN_bfc158a8
(= func_00005DA8) never runs in our recomp during this session, gates
haven't even reached the initial 0x01 BUSY state
- ✓ shell IS on memcard screen ([0x80066948] = 0x32)
The seed addition is correct and necessary work — it removes one of two
layers of "writer is unreachable". The remaining layer is upstream:
nothing in our recomp causes FUN_bfc14b00 / FUN_bfc158a8 to run during
the memcard flow. That's a different category from "chain runs but
fails on byte N" and is not chased here per Case A directive.
Beetle wtrace also revealed the writers at 0x5EF4 / 0x5FA8 are tiny
leaf utilities called from BIOS code in BFC08{B98,C94,D08,F28} — NOT
chain-step jump-table targets as initially assumed. The chain step
tables at RAM 0x6c70/0x6c98/0x6ccc point at 0x52xx / 0x56xx-0x5Axx /
0x5Bxx-0x5Dxx ranges. Memo updated accordingly.
Includes 4 new validation scripts under tools/ used during this audit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
60 lines
2.3 KiB
Python
60 lines
2.3 KiB
Python
"""Check whether chain init at FUN_bfc158a8 has ever run."""
|
|
import socket, json
|
|
|
|
def call(d):
|
|
s = socket.create_connection(('127.0.0.1', 4370)); s.settimeout(15.0)
|
|
s.sendall((json.dumps(d) + '\n').encode())
|
|
buf = b''
|
|
while True:
|
|
try: c = s.recv(65536)
|
|
except socket.timeout: break
|
|
if not c: break
|
|
buf += c
|
|
if buf.count(b'{') == buf.count(b'}') and buf.strip(): break
|
|
s.close()
|
|
return json.loads(buf.decode())
|
|
|
|
|
|
def read(addr, n):
|
|
r = call({'id': 1, 'cmd': 'read_ram', 'addr': f'0x{addr:08X}', 'len': n})
|
|
return r.get('hex', '')
|
|
|
|
|
|
# Init at FUN_bfc158a8 should write:
|
|
# sw t8, 0x7544(at) ; t8 = 0x4d6c
|
|
# sw t9, ?(at) ; t9 = 0x4f90
|
|
# sb t6, 0x7568(at) ; slot 0 = 0x01
|
|
# sb t7, 0x7569(at) ; slot 1 = 0x01
|
|
# sb zero, 0x755A ; abort flag = 0
|
|
# sb zero, 0x7264 ; slot toggle = 0
|
|
print('=== chain init evidence ===')
|
|
print(f' 0x7540..0x7550 (chain handler ptrs): {read(0x80007540, 16)}')
|
|
print(f' 0x7568..0x7570 (gate bytes): {read(0x80007568, 8)}')
|
|
print(f' 0x7264 (slot toggle): {read(0x80007264, 4)}')
|
|
print(f' 0x755A (abort flag byte): {read(0x8000755A, 4)}')
|
|
print(f' 0x7258 (SIO MMIO base ptr): {read(0x80007258, 4)}')
|
|
print()
|
|
|
|
# Function pointer tables that the chain dispatchers (FUN_bfc14cf4 + FUN_bfc15188)
|
|
# index into. If init populated them, they should contain RAM addresses (0x80004F54,
|
|
# 0x80005EF4, etc. — likely as physical addresses 0x000xxxxx).
|
|
print('=== chain step jump tables ===')
|
|
print(f' 0x6c70 (jt1 — 10 entries): {read(0x80006c70, 40)}')
|
|
print(f' 0x6c98 (jt2 — 13 entries): {read(0x80006c98, 52)}')
|
|
print(f' 0x6ccc (jt3 — 4 entries): {read(0x80006ccc, 16)}')
|
|
print()
|
|
|
|
# Has the chain init function ever been dispatched?
|
|
print('=== dispatch_check on init/chain entries ===')
|
|
for pc, name in [(0x5DA8, 'FUN_bfc158a8 (init)'),
|
|
(0x5000, 'FUN_bfc14b00 (chain coord)'),
|
|
(0x51F4, 'FUN_bfc14cf4 (dispatcher 1)'),
|
|
(0x5688, 'FUN_bfc15188 (dispatcher 2)'),
|
|
(0x5EF4, '0x02 writer (NEW)'),
|
|
(0x5FA8, '0x04 writer (NEW)')]:
|
|
r = call({'id': 100, 'cmd': 'dispatch_check', 'addr': f'0x{pc:08X}'})
|
|
print(f" 0x{pc:08X} {name}: in_recent_ring={r.get('found')}")
|
|
print()
|
|
|
|
print(f"frame: {call({'id':0,'cmd':'ping'}).get('frame')}")
|