Nothing here changes what a tool computes; it changes where tools look. - tools/re-capture: 33 censuses globbed /work/sylph_extract, a path that has existed nowhere since /work became a clone, so they matched nothing and printed empty results. They now resolve the disc through a new disc.py from $SYLPHEED_DISC and exit loudly without it (the #44 fix, generalised). Nine scripts that imported siblings from the retired Reborn checkout or an old session scratchpad now import from their own directory. unitgroup.py only needs the variable when --pak is not given. - sylpheed-xex: the loader only ever uses the XEX2 retail key. The dead devkit key and a doc comment claiming a devkit fallback that does not exist are gone; Project Sylpheed is a retail XEX2, so no XEX1 key either. - sylpheed-viewer: real_font_rasterizes looked for /tmp/sylph_extract and so always skipped. It reads $SYLPHEED_DISC now, and passes against the disc. - Comments and docs that named xenia-rs, the Reborn repository or /work/*.pe as places to look now name sylpheed.db, Canary's ppc_context.h and the flat .pe; docs/re/README.md no longer says the native Canary build does not run. Historical records keep their original paths: findings that were measured against /work/xenia-rs/sylpheed.db still say so. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
sylph-xexdb — the title's XEX, as a queryable database
sylph-xexdb dis <disc.iso|default.xex> --db sylpheed.db --analyze sql
tools/zq.py dis 0x82341a20 0x82341b00 # then query it
Extract the PE image, disassemble it, detect functions, resolve cross-references and RTTI, and write the lot to DuckDB.
Where it came from, and what did not come with it
This was xenia-rs — a from-scratch Rust Xbox 360 emulator, started because
Canary would not run on Linux. Canary later did, with fixes from us, and the
emulator was retired. The static analysis is the part that stayed useful, so
it came here and the emulator did not: no interpreter, no JIT, no scheduler, no
GPU, no kernel. About 17,000 lines of ~71,000.
That was possible because the coupling was three symbols — decoder::decode,
disasm::DisasmItem, disasm::format — now sylpheed-ppc.
| crate | what it is |
|---|---|
sylpheed-xex |
the XEX2 container: decrypt, LZX, PE image, resources, and the disc image it may live in |
sylpheed-ppc |
PowerPC decode and disassembly |
sylpheed-xexdb |
the analysis passes, the schema, and this binary |
⚠️ Two things that will mislead you
The database is DuckDB. xenia-rs's own --db help said "SQLite" in two
places and was wrong. Query it with python3 -c "import duckdb", or zq.py.
indirect_dispatch_candidates is deliberately not a cross product. A
bcctrl through this->vptr at offset 0 matches nearly every class, so one
site can claim 700+ callees. Sites past --max-indirect-candidates record a
truthful candidate_count with truncated set and emit no candidate rows.
On this title that is 6,556 of 6,983 sites, standing for 1,801,075 candidates
that are counted rather than materialised. An older database built without the
ceiling has ~1.8M more rows in that table and in xrefs, and they say nothing
extra.
The export table
Import names come from docs/reference/xbox360-exports.json — 2,913 ordinals,
compiled in by build.rs.
🔴 It used to come from Canary's xboxkrnl_table.inc through a relative path
to a sibling checkout, which printed a warning and produced an empty table
whenever that checkout was not there. Every import in the database then resolved
to nothing, and the build still succeeded. Now the source is in this repository
and a missing file fails the build.