Seed verified BIOS kernel function 0xBFC15F1C (SIO/PAD interrupt handler)

Runtime measurement showed this function (RAM 0x641C) and its internal
branch targets (0x6430, 0x6444, 0x6458, 0x650C, 0x6514, 0x658C, 0x6594)
collectively generating ~50K dirty_ram_dispatch blocks/session. The address
is confirmed as a true function start via jalr call site at 0xBFC15F10.

Seeding the entry point only; CFG analysis discovers all internal labels.
Result: blocks_run dropped from 119,804 to 29,692 (75% reduction).

Also adds tools/probe_dirty_ram.py for live dirty_ram measurement via the
TCP debug server.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matthew Stanley
2026-05-29 23:29:05 -07:00
parent 5804a5a351
commit f7258927ae
3 changed files with 193 additions and 46 deletions
+131 -38
View File
@@ -1,38 +1,131 @@
{
"schema": "psxrecomp-v4 dispatch-miss seeds",
"source": "runtime dispatch miss log — functions called indirectly (JALR / function pointer tables)",
"note": "These functions have no static JAL callers and cannot be found by transitive discovery. They are reached at runtime via BIOS API dispatch tables (A0/B0/C0 vectors) or other indirect call mechanisms.",
"seeds": [
{"address": "0xBFC42380", "rationale": "dispatch miss: Shell function, indirect call via table"},
{"address": "0xBFC42844", "rationale": "dispatch miss: Shell function, indirect call via table"},
{"address": "0xBFC38AD4", "rationale": "dispatch miss: Shell function, indirect call via table"},
{"address": "0xBFC42A90", "rationale": "dispatch miss: Shell function, indirect call via table"},
{"address": "0xBFC42A10", "rationale": "dispatch miss: Shell function, indirect call via table"},
{"address": "0xBFC27FB0", "rationale": "dispatch miss: Kernel Part 2 function, indirect call"},
{"address": "0xBFC36D48", "rationale": "dispatch miss: Shell function, indirect call via table"},
{"address": "0xBFC38AA4", "rationale": "dispatch miss: Shell function, indirect call via table"},
{"address": "0xBFC1E3AC", "rationale": "dispatch miss: Shell function, called in vblank loop"},
{"address": "0xBFC3045C", "rationale": "dispatch miss: Shell function, indirect call via table"},
{"address": "0xBFC30470", "rationale": "dispatch miss: Shell function, indirect call via table"},
{"address": "0xBFC30484", "rationale": "dispatch miss: Shell function, indirect call via table"},
{"address": "0xBFC30498", "rationale": "dispatch miss: Shell function, indirect call via table"},
{"address": "0xBFC30554", "rationale": "dispatch miss: Shell function, indirect call via table"},
{"address": "0xBFC30560", "rationale": "dispatch miss: Shell function, indirect call via table"},
{"address": "0xBFC3056C", "rationale": "dispatch miss: Shell function, indirect call via table"},
{"address": "0xBFC30578", "rationale": "dispatch miss: Shell function, indirect call via table"},
{"address": "0xBFC36DD0", "rationale": "dispatch miss: Shell function, indirect call via table"},
{"address": "0xBFC11840", "rationale": "dispatch miss: KP2 function, indirect call"},
{"address": "0xBFC36DF8", "rationale": "dispatch miss: Shell function, indirect call"},
{"address": "0xBFC11524", "rationale": "dispatch miss: KP2 secondary entry point for exception handler, mid-function split of func_00001A00, called during VBlank"},
{"address": "0xBFC11610", "rationale": "dispatch miss: KP2 function, tail-call target from 0xBFC11524 exception handler path"},
{"address": "0xBFC14A54", "rationale": "dispatch miss (Beetle wtrace, docs/CASE_A_AOT_GAP.md): chain BUSY-writer at RAM 0x4F54; alias rule RAM=ROM-0xBFC10000+0x500. Reached via JAL inside FUN_bfc147f4; never emitted as standalone entry."},
{"address": "0xBFC158D0", "rationale": "dispatch miss (Beetle wtrace, docs/CASE_A_AOT_GAP.md): chain init slot-0 BUSY writer at RAM 0x5DD0; alias RAM=ROM-0xBFC10000+0x500. Inside FUN_bfc158a8 body."},
{"address": "0xBFC158D8", "rationale": "dispatch miss (Beetle wtrace, docs/CASE_A_AOT_GAP.md): chain init slot-1 BUSY writer at RAM 0x5DD8; alias RAM=ROM-0xBFC10000+0x500. Inside FUN_bfc158a8 body."},
{"address": "0xBFC159F4", "rationale": "dispatch miss (Beetle wtrace, docs/CASE_A_AOT_GAP.md): chain step handler that writes 0x02 OPEN to [0x7568+slot] at RAM 0x5EF4. Indirect-jr target from RAM 0x6c98 jump table; alias RAM=ROM-0xBFC10000+0x500. KEY entry — without this the gate never clears."},
{"address": "0xBFC15AA8", "rationale": "dispatch miss (Beetle wtrace, docs/CASE_A_AOT_GAP.md): chain step handler that writes 0x04 OPEN to [0x7568+slot] at RAM 0x5FA8. Indirect-jr target from RAM 0x6c98 jump table; alias RAM=ROM-0xBFC10000+0x500. KEY entry — paired with 0xBFC159F4."},
{"address": "0xBFC04910", "rationale": "Tomba boot dispatch miss after licensed PlayStation screen. Verified in Ghidra/runtime disassembly as a standalone BIOS init routine between 0xBFC048D0 and 0xBFC04ABC, with return at 0xBFC04A98 and table data reference from 0xBFC04554."},
{"address": "0xBFC04850", "rationale": "Tomba boot dispatch miss after seeding 0xBFC04910. Verified in Ghidra/runtime disassembly as a standalone BIOS callback-list init routine between 0xBFC0472C and 0xBFC048D0, with return at 0xBFC048C8 and table data reference from 0xBFC04588."},
{"address": "0xBFC079F8", "rationale": "Tomba boot dispatch miss after game callback coverage fixes. Verified in Ghidra as a tiny BIOS table leaf routine (sw a0,0(sp); jr ra; clear v0) referenced by data at 0xBFC04484 and 0xBFC0E30C."}
]
}
{
"schema": "psxrecomp-v4 dispatch-miss seeds",
"source": "runtime dispatch miss log \u00e2\u20ac\u201d functions called indirectly (JALR / function pointer tables)",
"note": "These functions have no static JAL callers and cannot be found by transitive discovery. They are reached at runtime via BIOS API dispatch tables (A0/B0/C0 vectors) or other indirect call mechanisms.",
"seeds": [
{
"address": "0xBFC42380",
"rationale": "dispatch miss: Shell function, indirect call via table"
},
{
"address": "0xBFC42844",
"rationale": "dispatch miss: Shell function, indirect call via table"
},
{
"address": "0xBFC38AD4",
"rationale": "dispatch miss: Shell function, indirect call via table"
},
{
"address": "0xBFC42A90",
"rationale": "dispatch miss: Shell function, indirect call via table"
},
{
"address": "0xBFC42A10",
"rationale": "dispatch miss: Shell function, indirect call via table"
},
{
"address": "0xBFC27FB0",
"rationale": "dispatch miss: Kernel Part 2 function, indirect call"
},
{
"address": "0xBFC36D48",
"rationale": "dispatch miss: Shell function, indirect call via table"
},
{
"address": "0xBFC38AA4",
"rationale": "dispatch miss: Shell function, indirect call via table"
},
{
"address": "0xBFC1E3AC",
"rationale": "dispatch miss: Shell function, called in vblank loop"
},
{
"address": "0xBFC3045C",
"rationale": "dispatch miss: Shell function, indirect call via table"
},
{
"address": "0xBFC30470",
"rationale": "dispatch miss: Shell function, indirect call via table"
},
{
"address": "0xBFC30484",
"rationale": "dispatch miss: Shell function, indirect call via table"
},
{
"address": "0xBFC30498",
"rationale": "dispatch miss: Shell function, indirect call via table"
},
{
"address": "0xBFC30554",
"rationale": "dispatch miss: Shell function, indirect call via table"
},
{
"address": "0xBFC30560",
"rationale": "dispatch miss: Shell function, indirect call via table"
},
{
"address": "0xBFC3056C",
"rationale": "dispatch miss: Shell function, indirect call via table"
},
{
"address": "0xBFC30578",
"rationale": "dispatch miss: Shell function, indirect call via table"
},
{
"address": "0xBFC36DD0",
"rationale": "dispatch miss: Shell function, indirect call via table"
},
{
"address": "0xBFC11840",
"rationale": "dispatch miss: KP2 function, indirect call"
},
{
"address": "0xBFC36DF8",
"rationale": "dispatch miss: Shell function, indirect call"
},
{
"address": "0xBFC11524",
"rationale": "dispatch miss: KP2 secondary entry point for exception handler, mid-function split of func_00001A00, called during VBlank"
},
{
"address": "0xBFC11610",
"rationale": "dispatch miss: KP2 function, tail-call target from 0xBFC11524 exception handler path"
},
{
"address": "0xBFC14A54",
"rationale": "dispatch miss (Beetle wtrace, docs/CASE_A_AOT_GAP.md): chain BUSY-writer at RAM 0x4F54; alias rule RAM=ROM-0xBFC10000+0x500. Reached via JAL inside FUN_bfc147f4; never emitted as standalone entry."
},
{
"address": "0xBFC158D0",
"rationale": "dispatch miss (Beetle wtrace, docs/CASE_A_AOT_GAP.md): chain init slot-0 BUSY writer at RAM 0x5DD0; alias RAM=ROM-0xBFC10000+0x500. Inside FUN_bfc158a8 body."
},
{
"address": "0xBFC158D8",
"rationale": "dispatch miss (Beetle wtrace, docs/CASE_A_AOT_GAP.md): chain init slot-1 BUSY writer at RAM 0x5DD8; alias RAM=ROM-0xBFC10000+0x500. Inside FUN_bfc158a8 body."
},
{
"address": "0xBFC159F4",
"rationale": "dispatch miss (Beetle wtrace, docs/CASE_A_AOT_GAP.md): chain step handler that writes 0x02 OPEN to [0x7568+slot] at RAM 0x5EF4. Indirect-jr target from RAM 0x6c98 jump table; alias RAM=ROM-0xBFC10000+0x500. KEY entry \u00e2\u20ac\u201d without this the gate never clears."
},
{
"address": "0xBFC15AA8",
"rationale": "dispatch miss (Beetle wtrace, docs/CASE_A_AOT_GAP.md): chain step handler that writes 0x04 OPEN to [0x7568+slot] at RAM 0x5FA8. Indirect-jr target from RAM 0x6c98 jump table; alias RAM=ROM-0xBFC10000+0x500. KEY entry \u00e2\u20ac\u201d paired with 0xBFC159F4."
},
{
"address": "0xBFC04910",
"rationale": "Tomba boot dispatch miss after licensed PlayStation screen. Verified in Ghidra/runtime disassembly as a standalone BIOS init routine between 0xBFC048D0 and 0xBFC04ABC, with return at 0xBFC04A98 and table data reference from 0xBFC04554."
},
{
"address": "0xBFC04850",
"rationale": "Tomba boot dispatch miss after seeding 0xBFC04910. Verified in Ghidra/runtime disassembly as a standalone BIOS callback-list init routine between 0xBFC0472C and 0xBFC048D0, with return at 0xBFC048C8 and table data reference from 0xBFC04588."
},
{
"address": "0xBFC079F8",
"rationale": "Tomba boot dispatch miss after game callback coverage fixes. Verified in Ghidra as a tiny BIOS table leaf routine (sw a0,0(sp); jr ra; clear v0) referenced by data at 0xBFC04484 and 0xBFC0E30C."
},
{
"address": "0xBFC15F1C",
"rationale": "dirty_ram hot: SIO/PAD interrupt handler entry point (RAM 0x641C), called via jalr. 10852+ hits/frame across internal branch targets (0x641C, 0x6430, 0x6444, 0x6458, 0x650C, 0x6514, 0x658C, 0x6594). Seeding entry only; CFG discovers internal labels."
}
]
}
+13 -8
View File
@@ -1,7 +1,7 @@
{
"schema": "psxrecomp-v4 phase2 seeds",
"schema": "psxrecomp phase2 seeds",
"source": "generated/ghidra_function_starts.json + phase1c seeds + dispatch_miss_seeds + preserved manual",
"seed_count": 1071,
"seed_count": 1072,
"seeds": [
{
"address": "0xBFC00000",
@@ -3493,6 +3493,11 @@
"label": "dmiss_BFC079F8",
"rationale": "Tomba boot dispatch miss after game callback coverage fixes. Verified in Ghidra as a tiny BIOS table leaf routine (sw a0,0(sp); jr ra; clear v0) referenced by data at 0xBFC04484 and 0xBFC0E30C."
},
{
"address": "0xBFC15F1C",
"label": "dmiss_BFC15F1C",
"rationale": "dirty_ram hot: SIO/PAD interrupt handler entry point (RAM 0x641C), called via jalr. 10852+ hits/frame across internal branch targets (0x641C, 0x6430, 0x6444, 0x6458, 0x650C, 0x6514, 0x658C, 0x6594). Seeding entry only; CFG discovers internal labels."
},
{
"address": "0xBFC0193C",
"label": "cache_flush_continuation",
@@ -4677,11 +4682,11 @@
"label": "gte_lib_BFC34EC4",
"rationale": "GTE math library function. Batch-discovered from BFC33000-BFC36000."
},
{
"address": "0xBFC34FA0",
"label": "gte_lib_BFC34FA0",
"rationale": "GTE math library function missed by adjacent batch discovery; contains the BFC34FF8-BFC350C4 MVMVA/SWC2 helper used by the BIOS disc logo screen."
},
{
"address": "0xBFC34FA0",
"label": "gte_lib_BFC34FA0",
"rationale": "GTE math library function missed by adjacent batch discovery; contains the BFC34FF8-BFC350C4 MVMVA/SWC2 helper used by the BIOS disc logo screen."
},
{
"address": "0xBFC35128",
"label": "gte_lib_BFC35128",
@@ -5320,4 +5325,4 @@
"rationale": "R3000 UTLB-miss vector; PS1 has no TLB; never executed"
}
]
}
}
+49
View File
@@ -0,0 +1,49 @@
import socket, json, time, sys
port = int(sys.argv[1]) if len(sys.argv) > 1 else 4470
def send_cmd(cmd, **kwargs):
payload = {'id': 1, 'cmd': cmd}
payload.update(kwargs)
s = socket.create_connection(('127.0.0.1', port), timeout=3)
s.sendall(json.dumps(payload).encode() + b'\n')
data = b''
while True:
chunk = s.recv(4096)
if not chunk:
break
data += chunk
try:
json.loads(data.decode())
break
except:
pass
s.close()
return json.loads(data.decode())
# Wait for server
for i in range(15):
try:
r = send_cmd('ping')
print(f'Connected. frame={r.get("frame")}, dispatch_miss_total={r.get("dispatch_miss_total")}')
break
except Exception as e:
print(f' waiting... ({e})')
time.sleep(2)
else:
print('Could not connect after 30s')
sys.exit(1)
# Query dirty_ram stats
try:
r = send_cmd('dirty_ram_stats')
print('dirty_ram_stats:', json.dumps(r, indent=2))
except Exception as e:
print(f'dirty_ram_stats failed: {e}')
# Also try heartbeat
try:
r = send_cmd('heartbeat')
print('heartbeat:', json.dumps(r, indent=2))
except Exception as e:
print(f'heartbeat failed: {e}')