mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 10:19:47 -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>
64 lines
1.6 KiB
Python
64 lines
1.6 KiB
Python
"""Read shell flow gates + see if memcard subsystem ran at all."""
|
|
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', '')
|
|
|
|
|
|
def hex_words(hexstr, n):
|
|
"""Split hex string into n LE 32-bit words."""
|
|
out = []
|
|
for i in range(n):
|
|
b = hexstr[i*8:(i+1)*8]
|
|
if len(b) < 8: break
|
|
# LE
|
|
word = int(b[6:8] + b[4:6] + b[2:4] + b[0:2], 16)
|
|
out.append(word)
|
|
return out
|
|
|
|
|
|
print('=== shell state machine 0x80066940 ===')
|
|
hx = read(0x80066940, 32)
|
|
print(f' raw = {hx}')
|
|
print(f' words = {[hex(w) for w in hex_words(hx, 8)]}')
|
|
|
|
print()
|
|
print('=== shell flow gate 0x80066bc0 ===')
|
|
hx = read(0x80066bc0, 32)
|
|
print(f' raw = {hx}')
|
|
print(f' words = {[hex(w) for w in hex_words(hx, 8)]}')
|
|
|
|
print()
|
|
print('=== card chain state 0x80007510..0x80007570 ===')
|
|
hx = read(0x80007510, 0x60)
|
|
print(f' raw = {hx}')
|
|
|
|
print()
|
|
print('=== card slots gates 0x80007568..0x80007570 ===')
|
|
hx = read(0x80007568, 8)
|
|
print(f' raw = {hx} (slot0..3 gate bytes + xor accums)')
|
|
|
|
print()
|
|
print('=== xor accumulators 0x80007560..0x80007568 ===')
|
|
hx = read(0x80007560, 8)
|
|
print(f' raw = {hx} (slot0/slot1 xor accums)')
|
|
|
|
print()
|
|
print('=== ping ===')
|
|
print(call({'id': 0, 'cmd': 'ping'}))
|