Initial commit: xenia-rs workspace for Xbox 360 RE
Rust reimplementation of the xenia Xbox 360 emulator targeting reverse- engineering and preservation, initially scoped to Project Sylpheed. Includes: - XEX2 loader (LZX decompression, AES decryption, PE parsing) - XISO / XGD2 disc image VFS - PPC interpreter with 200+ opcodes and VMX128 decoding - Static analyzer: functions, cross-references, labels, asm + SQLite output - HLE kernel covering the xboxkrnl/xam subset used by Sylpheed init - Debugger with in-memory and SQLite-backed execution tracing - `xenia-rs` CLI with extract/dis/exec commands that produce cumulative, superset SQLite databases and opt-in instruction/import/branch traces Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
132
README.md
Normal file
132
README.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# xenia-rs
|
||||
|
||||
Rust reimplementation of the Xbox 360 emulator [xenia](https://github.com/xenia-project/xenia),
|
||||
focused on **reverse-engineering and preservation** rather than full-speed play.
|
||||
The initial target is *Project Sylpheed — Arc of Deception*; getting the title
|
||||
disassembled, traced, and far enough into its init path to understand its engine.
|
||||
|
||||
Heavy cross-reference to [xenia-canary](https://github.com/xenia-canary/xenia-canary)
|
||||
for CPU context setup, kernel export behavior, and XEX loading semantics.
|
||||
|
||||
## Status
|
||||
|
||||
- **XEX loader** — XEX2 header parsing, LZX decompression, AES decryption, PE section parsing.
|
||||
- **VFS / XISO** — XGD2 dual-layer disc images (with the 0x0FD90000 partition offset).
|
||||
- **PPC interpreter** — 200+ opcodes, PowerPC 32/64-bit GPR/FPR, VMX128 decoding.
|
||||
- **Static analyzer** — function discovery (prolog/epilog heuristics), cross-references, labels,
|
||||
save/restore helper detection, assembly text + SQLite database output.
|
||||
- **Kernel HLE** — minimal subset driving Project Sylpheed: ~170 xboxkrnl + xam exports
|
||||
(critical sections, events, TLS, virtual memory, Vd stubs, XAM input/user/content).
|
||||
- **Debugger** — in-memory step/break, SQLite execution + import-call + branch tracing.
|
||||
|
||||
Not yet: GPU (xenos/xe-shader), APU audio, HID, kernel scheduler, full threading,
|
||||
exception delivery.
|
||||
|
||||
## Workspace
|
||||
|
||||
```
|
||||
crates/
|
||||
xenia-types # shared primitive types, bitflags
|
||||
xenia-memory # guest memory, paged allocator, page table
|
||||
xenia-cpu # PPC decoder, interpreter, context
|
||||
xenia-xex # XEX2 loader, PE parser, LZX, AES
|
||||
xenia-vfs # XISO / disc-image reader
|
||||
xenia-kernel # HLE kernel state, exports, XAM
|
||||
xenia-gpu # (stub) Xenos command processor
|
||||
xenia-apu # (stub) XAudio
|
||||
xenia-hid # (stub) XInput
|
||||
xenia-debugger # in-memory trace, breakpoints, step modes
|
||||
xenia-analysis # function/xref analysis, assembly formatter, SQLite DbWriter
|
||||
xenia-app # `xenia-rs` CLI binary
|
||||
```
|
||||
|
||||
## CLI
|
||||
|
||||
Build:
|
||||
```sh
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
The binary `xenia-rs` accepts XEX2 files or ISO / XISO disc images as input
|
||||
(the loader auto-detects discs and extracts `default.xex`).
|
||||
|
||||
### `info` / `browse` / `disasm`
|
||||
|
||||
Quick header / disc / first-N-instructions inspection. See `--help`.
|
||||
|
||||
### `extract` — unpack PE + metadata
|
||||
|
||||
```sh
|
||||
xenia-rs extract <xex-or-iso> [-o <out-dir>] [--db <sqlite-path>]
|
||||
```
|
||||
|
||||
Writes `<name>.pe` (decompressed/decrypted PE image) and `<name>.xex.json`
|
||||
(header metadata). With `--db`, also emits a SQLite database containing the
|
||||
**base tables**: `metadata`, `sections`, `imports`.
|
||||
|
||||
### `dis` — full disassembly
|
||||
|
||||
```sh
|
||||
xenia-rs dis <xex-or-iso> [-o <asm-file>] [--db <sqlite-path>] [--quiet]
|
||||
```
|
||||
|
||||
Runs function + cross-reference analysis and produces:
|
||||
- assembly text to stdout or `-o <file>` (unless `--quiet`)
|
||||
- optional SQLite DB with the **base tables + disasm tables**:
|
||||
`functions`, `labels`, `instructions`, `xrefs`
|
||||
|
||||
### `exec` — interpret with tracing
|
||||
|
||||
```sh
|
||||
xenia-rs exec <xex-or-iso> [-n <max-instrs>] [--db <sqlite-path>]
|
||||
[--trace-instructions] [--trace-imports] [--trace-branches]
|
||||
```
|
||||
|
||||
Loads the title, initializes CPU state per xenia-canary, intercepts import
|
||||
thunks with HLE kernel calls, and interprets from the entry point. Without
|
||||
`-n`, runs until halt/fault. With `--db`, produces a DB that is a **superset
|
||||
of `dis --db`** plus opt-in trace tables:
|
||||
|
||||
| flag | table | rows |
|
||||
|-------------------------|----------------|---------------------------------------------------------|
|
||||
| `--trace-instructions` | `exec_trace` | one row per interpreted instruction (PC, r3/r4, LR, SP) |
|
||||
| `--trace-imports` | `import_calls` | one row per kernel/XAM call (module, ordinal, args) |
|
||||
| `--trace-branches` | `branch_trace` | taken branches classified as `call`/`return`/`jump`/`branch` |
|
||||
|
||||
### Cumulative DB layering
|
||||
|
||||
Each command's DB is a superset of the previous. A single
|
||||
`xenia-rs exec <iso> --db full.db --trace-instructions --trace-imports --trace-branches`
|
||||
produces the full picture in one pass — base tables, complete static
|
||||
disassembly, and runtime traces correlatable by address/cycle.
|
||||
|
||||
## Performance knobs
|
||||
|
||||
- **`XENIA_DB_BATCH_SIZE`** — rows per streaming commit / trace-buffer flush
|
||||
(default `100_000`). Lower values reduce memory use; higher values reduce
|
||||
fsync overhead on slow disks.
|
||||
|
||||
The DB writer uses `journal_mode=OFF`, `synchronous=OFF`, `locking_mode=EXCLUSIVE`
|
||||
and commits in batches; no `ANALYZE` is run at finalize. Indices are created
|
||||
after bulk insertion with progress messages.
|
||||
|
||||
## Example queries
|
||||
|
||||
```sql
|
||||
-- Top 20 kernel functions called during early init
|
||||
SELECT name, COUNT(*) FROM import_calls GROUP BY name ORDER BY 2 DESC LIMIT 20;
|
||||
|
||||
-- All basic-block leaders (targets of taken branches) not already labelled
|
||||
SELECT DISTINCT bt.target
|
||||
FROM branch_trace bt LEFT JOIN labels l ON l.address = bt.target
|
||||
WHERE l.address IS NULL;
|
||||
|
||||
-- Correlate a traced call site with its static disassembly
|
||||
SELECT et.cycle, i.disasm, i.ext_disasm
|
||||
FROM exec_trace et JOIN instructions i ON i.address = et.address
|
||||
WHERE et.address = 0x824AB748 ORDER BY et.cycle;
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
BSD-3-Clause, matching upstream xenia.
|
||||
Reference in New Issue
Block a user