PSX Research

This commit is contained in:
Marco 2026-04-07 17:16:44 +02:00
commit 94c49ac5bd
16 changed files with 2052 additions and 16 deletions

View file

@ -1332,6 +1332,64 @@ def parse_field_tags(body: bytes, start: int) -> FieldTagParseResult | None:
return FieldTagParseResult(field_tags=field_tags, end_offset=end_offset, trailing_bytes=body[end_offset:])
def classify_post_ret_metadata(body: bytes, ops: list[dict[str, Any]]) -> dict[str, Any] | None:
last_ret_index = next((index for index in range(len(ops) - 1, -1, -1) if ops[index]["mnemonic"] == "ret"), None)
if last_ret_index is None:
return None
ret_end = ops[last_ret_index]["offset"] + (len(ops[last_ret_index]["raw_bytes"]) // 2)
if len(body) - ret_end <= 1:
return None
debug_result = parse_debug_symbols(body, ret_end)
if debug_result is not None and debug_result.end_offset == len(body):
return {
"ops": ops[:last_ret_index + 1],
"end_reason": "debug_symbols_then_end",
"unknown_tail": debug_result.trailing_bytes,
"debug_symbol_offset": ret_end,
"debug_symbols": [
{
"index": symbol.index,
"unknown1": symbol.unknown1,
"type_id": symbol.type_id,
"type_char": symbol.type_char,
"bp_offset": symbol.bp_offset,
"bp_repr": symbol.bp_repr,
"unknown3": symbol.unknown3,
"name": symbol.name,
}
for symbol in debug_result.debug_symbols
],
"field_tags": [],
"end_offset": debug_result.end_offset,
}
field_tag_result = parse_field_tags(body, ret_end)
if field_tag_result is not None and field_tag_result.end_offset == len(body):
return {
"ops": ops[:last_ret_index + 1],
"end_reason": "field_tags_then_end",
"unknown_tail": field_tag_result.trailing_bytes,
"debug_symbol_offset": None,
"debug_symbols": [],
"field_tags": [
{
"tag_id": tag.tag_id,
"bp_offset": tag.bp_offset,
"bp_repr": bp_repr(tag.bp_offset),
"value_kind": tag.value_kind,
"name": tag.name,
"tag_label": f"{tag.tag_id:02X}:{tag.bp_offset:02X}{tag.value_kind:02X}->{tag.name}",
}
for tag in field_tag_result.field_tags
],
"end_offset": field_tag_result.end_offset,
}
return None
def parse_body_ir(
event_row: dict[str, str],
layout_row: dict[str, str],
@ -1390,6 +1448,16 @@ def parse_body_ir(
and 0 <= operands["symbol_offset"] < len(body)
}
)
post_ret_metadata = classify_post_ret_metadata(body, ops)
if post_ret_metadata is not None:
ops = post_ret_metadata["ops"]
debug_symbol_offset = post_ret_metadata["debug_symbol_offset"]
debug_symbols = post_ret_metadata["debug_symbols"]
field_tags = post_ret_metadata["field_tags"]
end_reason = post_ret_metadata["end_reason"]
unknown_tail = post_ret_metadata["unknown_tail"]
offset = post_ret_metadata["end_offset"]
last_ret_index = next((index for index in range(len(ops) - 1, -1, -1) if ops[index]["mnemonic"] == "ret"), None)
if end_reason == "unknown_opcode" and last_ret_index is not None:
ret_end = ops[last_ret_index]["offset"] + (len(ops[last_ret_index]["raw_bytes"]) // 2)
@ -2973,6 +3041,17 @@ def render_pseudocode(ir: dict[str, Any], shape_catalog: ShapeCatalog | None = N
else:
lines.extend(render_partially_structured_blocks(rendered_blocks))
if ir["debug_symbols"] or ir["field_tags"]:
lines.append("")
lines.append(" /* post-return metadata (not executable):")
for symbol in ir["debug_symbols"]:
lines.append(
f" debug_symbol {sanitize_identifier(symbol['name'])} {symbol['bp_repr']} type=0x{symbol['type_id']:02X} unk1=0x{symbol['unknown1']:02X} unk3=0x{symbol['unknown3']:02X}"
)
for tag in ir["field_tags"]:
lines.append(f" field_tag {tag['tag_label']} ({tag['bp_repr']})")
lines.append(" */")
lines.append("}")
return apply_shape_catalog_to_pseudocode("\n".join(lines) + "\n", shape_catalog)