mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-25 18:05:12 -04:00
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:
@@ -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."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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}')
|
||||
Reference in New Issue
Block a user