# Project Sylpheed: Arc of Deception — Reborn A clean-room, open-source reimplementation of **Project Sylpheed: Arc of Deception** (Xbox 360, 2006). Built with **Rust** and the **Bevy** game engine. Runs natively on Windows, macOS, and Linux, and in the browser via WebAssembly. > **Legal note:** This project contains no original game code or assets. You must own a legitimate copy of Project Sylpheed to use this engine. Assets remain the intellectual property of SETA Corporation / Square Enix. --- ## Current Status: Milestone 1 — Asset Explorer - [x] XISO disc image reading via `xdvdfs` - [x] Xbox 360 texture de-tiling (Morton / Z-order) - [x] XPR2 texture container parsing - [x] Bevy custom `AssetLoader` for `.xpr` textures - [x] Orbit camera viewer - [x] CLI tools: extract, list, sniff, texture info, texture export - [x] GitHub Actions CI (Windows + macOS + Linux + WASM) - [x] WASM / web build target - [ ] Mesh format (reverse engineering in progress) - [ ] Audio format (XMA → PCM pipeline) - [ ] Mission data format --- ## Repository Structure ``` sylpheed-reborn/ └── sylpheed-viewer/ ← Milestone 1: asset explorer (Rust/Bevy workspace) ├── Cargo.toml ← Workspace root ├── crates/ │ ├── sylpheed-formats/ # Format parsers — no Bevy dependency │ │ ├── xiso.rs # XISO / XDVDFS disc image reader │ │ ├── texture.rs # XPR2 container + DXT de-tiling (Morton) │ │ ├── vfs.rs # Virtual filesystem + magic-byte sniffer │ │ ├── mesh.rs # Mesh parser (stub — RE in progress) │ │ └── audio.rs # Audio parser (stub — XMA TODO) │ │ │ ├── sylpheed-viewer/ # Bevy application │ │ ├── lib.rs # App setup + WASM entry point │ │ ├── main.rs # Native binary entry point │ │ ├── asset_loader.rs # Custom Bevy AssetLoaders │ │ ├── camera.rs # Orbit camera (LMB orbit, RMB pan, scroll zoom) │ │ └── ui.rs # egui file browser + RE notes panel │ │ │ └── sylpheed-cli/ # Command-line tools │ └── main.rs # extract / list / sniff / texture info commands │ ├── assets/ ← Extracted game files (gitignored) ├── .github/workflows/ │ └── ci.yml # CI: Windows + macOS + Linux + WASM ├── Trunk.toml # WASM build configuration └── justfile # All build recipes ``` --- ## Getting Started ### Prerequisites ```bash # Install Rust curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # Install just (task runner) cargo install just # For web builds only cargo install trunk rustup target add wasm32-unknown-unknown ``` #### Linux — Bevy system dependencies ```bash sudo apt-get install -y \ libasound2-dev libudev-dev libwayland-dev \ libxkbcommon-dev libx11-dev libxi-dev pkg-config ``` ### Step 1 — Extract your disc ```bash cd sylpheed-viewer # Extract using the CLI tool just extract /path/to/project_sylpheed.iso # Or manually with xdvdfs cargo install xdvdfs-cli xdvdfs unpack project_sylpheed.iso ./assets/ ``` ### Step 2 — Run the viewer ```bash cd sylpheed-viewer just run # Native viewer just web # WASM dev server → http://localhost:8080 ``` The asset viewer opens an orbit camera scene. Use the left panel to browse extracted game files. Click a `.xpr` file to preview it as a texture. --- ## Build Commands All commands run from the `sylpheed-viewer/` directory. ```bash just run # Run the native viewer (debug) just run-dev # Run with hot-reloading just build-native # Build native release binary just web # WASM dev server at localhost:8080 just build-web # WASM release build → ./dist/ just extract game.iso # Extract an ISO to ./assets/ just sniff # Identify file formats in ./assets/ just sniff-unknown # Show only unrecognised formats (RE focus) just test # Run all tests just ci # Full CI: fmt + lint + test + WASM check ``` --- ## Technology Stack | Layer | Choice | Reason | |-------|--------|--------| | Language | **Rust** | Memory safety, performance, cross-platform | | Game engine | **Bevy 0.15** | ECS-first, WASM-native, data-driven | | XISO reading | **xdvdfs** | Pure Rust, reads Xbox 360 disc images | | Binary parsing | **binrw** | Derive-macro based, ideal for RE work | | Web bundler | **Trunk** | Bevy's standard WASM build tool | | CLI | **clap** | Asset extraction and inspection tools | | Debug UI | **bevy_egui** | In-viewer asset browser and RE notes panel | --- ## Key Architectural Decisions **`sylpheed-formats` has zero Bevy dependency.** All binary format parsers live here and are testable with plain `cargo test`. Bevy integration is a thin layer on top in `sylpheed-viewer`. **WASM is a first-class target.** XISO reading is gated behind `#[cfg(not(target_arch = "wasm32"))]` since the browser can't read local files. On the web, assets must be pre-extracted and served over HTTP. **Modding is designed in from the start.** The virtual filesystem (`vfs.rs`) is the single choke point for all asset reads — a mod loader only needs to intercept that one layer to override any file. --- ## Reverse Engineering Notes ### Known file formats | Path pattern | Format | Status | Notes | |---|---|---|---| | `*.XPR`, `*.XPR2` | XPR2 texture | ✅ Parsing | DXT1/3/5, DXN, Morton de-tiling done | | `DEFAULT.XEX` | Xbox EXE 2 | 🔬 Study | Main executable — load in Ghidra (PPC BE) | | `*.XWB`, `*.XSB` | XACT audio | ⏳ TODO | Wave/sound banks; audio is XMA codec | | `*.pak`, `*.p00` | SETA archive | ⏳ Unknown | Paired header/data format | | mesh files | Unknown | ⏳ TODO | Run `just sniff-unknown` to find candidates | ### RE workflow ```bash # 1. Extract and map the disc just extract game.iso just sniff-unknown # shows hex magic bytes of unknown files # 2. Hex-inspect candidates # Groups of 12 bytes at offsets: likely f32 XYZ vertices # Groups of 6 bytes: likely u16 triangle indices # 3. Cross-reference in Ghidra # Load DEFAULT.XEX with PowerPC Big-Endian processor # Search string refs to file extensions → find load functions # 4. Implement parser # Add binrw #[derive(BinRead)] struct in sylpheed-formats/src/mesh.rs # cargo test -p sylpheed-formats ``` ### Next steps (Milestone 2) 1. **Mesh format** — fingerprint with `sniff-unknown`, implement `mesh.rs` 2. **Audio** — parse XWB headers, batch-convert XMA to WAV via `ffmpeg` 3. **Mission data** — format unknown; starts after mesh/texture loading works 4. **Flight model** — document by playing the original; implement as Bevy system --- ## Constraints 1. **Never copy decompiled or disassembled game code** — reimplement behavior through observation only. 2. **Assets stay gitignored** — `assets/` and `*.iso` are excluded. Never commit game files. 3. **Keep `sylpheed-formats` Bevy-free** — parsers must be testable without a GPU. 4. **WASM must always compile** — CI enforces `cargo check --target wasm32-unknown-unknown`. 5. **`justfile` is the source of truth** for build commands — add new recipes there. --- ## Milestone Roadmap | Milestone | Goal | Status | |---|---|---| | 1 | Asset Explorer | 🚧 In Progress | | 2 | Flying Tech Demo | ⏳ Planned | | 3 | Combat Prototype | ⏳ Planned | | 4 | Mission 1 Playable | ⏳ Planned | | 5 | Full Game (all 16 missions) | ⏳ Planned | | 6 | Mod SDK | ⏳ Planned | --- ## Useful References - [xdvdfs](https://github.com/antangelo/xdvdfs) — XISO disc image reader (used in this project) - [Xenia emulator](https://github.com/xenia-canary/xenia-canary) — GPU/API reference (cloned at `../../xenia-canary/`) - [xboxdevwiki](https://xboxdevwiki.net) — Xbox 360 hardware documentation - [binrw docs](https://binrw.rs) — binary format parsing framework - [Free60 Project](https://free60project.github.io/wiki/) — open Xbox 360 hardware docs