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>
41 lines
1.3 KiB
Python
41 lines
1.3 KiB
Python
"""Dump dispatch_tail and summarize."""
|
|
import socket, json
|
|
from collections import Counter
|
|
|
|
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: chunk = s.recv(65536)
|
|
except socket.timeout: break
|
|
if not chunk: break
|
|
buf += chunk
|
|
depth = 0; instr = False; esc = False
|
|
for b in buf:
|
|
if esc: esc = False; continue
|
|
if b == 0x5C: esc = True; continue
|
|
if b == 0x22: instr = not instr; continue
|
|
if instr: continue
|
|
if b == 0x7B: depth += 1
|
|
elif b == 0x7D: depth -= 1
|
|
if depth == 0 and buf.strip(): break
|
|
s.close()
|
|
return json.loads(buf.decode())
|
|
|
|
r = call({'id': 1, 'cmd': 'dispatch_tail', 'count': '4096'})
|
|
addrs = r.get('addrs', [])
|
|
c = Counter(addrs)
|
|
print(f"total ring={r.get('total')} returned={len(addrs)} unique={len(c)}")
|
|
print()
|
|
print('top 30:')
|
|
for a, n in c.most_common(30):
|
|
print(f' {a} x{n}')
|
|
print()
|
|
print('Beetle writer PCs / chain coordinator presence in ring:')
|
|
for pc in ['0x00005EF4','0x00005FA8','0x00004F54','0x00005DD0','0x00005DD8',
|
|
'0x00005000','0x000051F4','0x00005688','0x00005DA8',
|
|
'0x00004D6C','0x0000445C','0x00006524']:
|
|
print(f' {pc}: x{c.get(pc, 0)}')
|