Files
xenia-rs/RE_SYMBOLS.md
MechaCat02 6b248d71e9 docs: RE symbol map + DB re-stamp for cracked IPFB name-hash
Record the guest functions identified while cracking the IPFB TOC
name-hash: Pak_FindEntryByName (0x824609C8), Pak_HashPathName
(0x82460928), Sylph_NameHash (0x82455C78, the Barrett poly-hash),
Str_ToLowerAscii (0x825F4F90), Pak_IsIPFBHeader (0x824607B0),
Archive_StreamReadCrc32 (0x82458508, content CRC — not the name-hash),
Res3D_LoadMeshChunk (0x82640290), and g_Crc32Table (0x828992F0).

RE_SYMBOLS.md is the source of truth (names/addresses/signatures +
confidence, the name-hash algorithm, and the confirmed TOC key path
schemes unit\<ID>.tbl / weapon\<ID>.tbl). apply_re_symbols.sql re-stamps
functions.name onto sylpheed.db (wiped on regen); already applied.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 21:45:26 +02:00

4.9 KiB
Raw Blame History

Project Sylpheed — reverse-engineered symbol map

Durable record of guest functions/data in the retail title (default.xex, base 0x82000000) that have been positively identified by RE. Addresses are guest virtual addresses. This is the source of truth for names; the DuckDB sylpheed.db (this dir) functions.name column can be re-stamped from here with apply_re_symbols.sql (names are wiped on a full DB regen).

Confidence: H = behaviour proven (reproduced/verified against data), M = strongly inferred from disassembly, L = tentative.

Archive (IPFB .pak) subsystem

Address Name Conf Description
0x824609C8 Pak_FindEntryByName H Look up a TOC entry by path. Args (r3 = pak object, r4 = char* path). Calls Pak_HashPathName(path), then binary-searches the sorted 12-byte TOC (base pak+4, count pak+8, stride 12; compares the 32-bit name_hash). Returns the matching record pointer or 0.
0x82460928 Pak_HashPathName H Duplicate r3 = char* path, lowercase it in place (Str_ToLowerAscii), hash with Sylph_NameHash, free the copy, return the 32-bit hash. This is the path→key bridge.
0x82455C78 Sylph_NameHash H The IPFB TOC / cache-path name-hash. See Name-hash. Input must already be lowercased. r3 = char*r3 = u32 hash.
0x825F4F90 Str_ToLowerAscii H In-place ASCII lowercase (AZ+0x20); other bytes pass through. r3 = char*. (When r3 == 0 it takes an unrelated init branch.)
0x824607B0 Pak_IsIPFBHeader H Validate an IPFB header. Loads the header's first word and checks it equals "IPFB" (0x49504642) via a delta trick: first_word - 0x49504620 == 0x22 ('B' - ' '). r5 = header ptr. Returns bool-ish in r3.
0x82460AD0 (pak header parse, unregistered container) M The pak-open/validate path around 0x82460DC00x82460EC4 builds an expected-header template ("IPFB", 0x10000000 flags) on the stack and calls Pak_IsIPFBHeader. Function-boundary detection missed the enclosing frame (entry ≈ 0x82460E34).
0x82458508 Archive_StreamReadCrc32 M Streaming block reader that validates content with a reflected CRC-32 (init 0xFFFFFFFF, final ~, table at g_Crc32Table). Compares the computed CRC to a stored expected value (state+144). This is a content-integrity CRC, not the name-hash.
0x828992F0 g_Crc32Table (data) H 256-entry reflected CRC-32 lookup table. Referenced only by Archive_StreamReadCrc32 and its sibling loop at 0x82457AF8.

3D resource subsystem

Address Name Conf Description
0x82640290 Res3D_LoadMeshChunk L 3D-resource loader: walks 12-byte records, checks chunk tags (0x1A22AA26, 0x2DA2AA24), and copies float triples (x/y/z vertices) via lfs/stfs. Part of the DefTables/machines\<model>\… mesh path.

Name-hash (Sylph_NameHash)

Per-byte Barrett-reduced polynomial hash over the lowercased name:

A = 0 ; B = 0
for each (sign-extended) byte c of the lowercased name:
    A = (A << 8) + c                                              # 32-bit
    A = A - (((A * 0x8003_1493) >> 32) rol 9 & 0x1FF) * 0x00FF_F9D7   # A mod 0x00FF_F9D7 (no final fixup)
    B = B + c
hash = ((B & 0xFF) << 24) | (A & 0x00FF_FFFF)
  • Modulus 0x00FF_F9D7, reciprocal 0x8003_1493 (the mulhwu/mullw Barrett step).
  • Low 24 bits = modular polynomial hash; top byte = 8-bit additive checksum of the bytes.
  • No trailing conditional subtract — the value is defined by the exact op sequence.
  • Faithful Rust reproduction: sylpheed-formats/src/hash.rs (name_hash).

Verified against retail TOCs: name_hash("files.tbl") == 0x8342_1153, name_hash("eng\\weapon.tbl") == 0x900C_8DCD, name_hash("eng\\strings.tbl") == 0x10C8_0B87, name_hash("jpn\\weapon.tbl") == 0x9E85_FEFF.

TOC key path conventions (preimages)

The 32-bit TOC key is name_hash of a backslash path with the entry's internal identity string. Confirmed schemes:

Scheme Example Where
unit\<ID>.tbl unit\UN_f001_TCAF_DeltaSaber_T_EX5.tbl0x7C96296C craft/ship entries in GP_MAIN_GAME_*.pak
weapon\<ID>.tbl weapon\Weapon_DSaber_P_wep_26_Missile.tbl weapon entries
<lang>\<name>.tbl eng\weapon.tbl, jpn\strings.tbl localized loadout/text tables
<name>.tbl files.tbl root manifest

<ID> = the entry's internal ID field (IDXD string pool). Craft/weapon entries also self-describe by content, so stats are readable without the key.

Open threads

  • Defaulted IDXD fields (*Ratio, the *Count family) carry no value on disc. The large 16-byte-record binary node table inside a craft IDXD is spatial/mesh data, not defaults (ruled out: it is not keyed by name_hash(field_key)). Defaults must live in per-schema_hash schema-definition tables (e.g. craft schema 0x43FAA517) — location TBD.