feat: initialise workspace — Milestone 1 asset explorer
Three-crate Cargo workspace structured per PROJECT.md spec: - crates/sylpheed-formats — Xbox 360 format parsers (no Bevy) - crates/sylpheed-viewer — Bevy 0.15 asset viewer + egui UI - crates/sylpheed-cli — CLI tools (extract/list/sniff/texture) Milestone 1 features: - XISO disc image reading via xdvdfs 0.8 - XPR2 texture container parsing + Morton de-tiling - D3DFORMAT → wgpu TextureFormat mapping (DXT1/3/5, DXN, ARGB) - Custom Bevy AssetLoader for .xpr files - Orbit camera (LMB orbit, RMB pan, scroll zoom) - egui file browser + RE notes panel - CLI: extract / list / sniff / texture info / texture export - GitHub Actions CI (Linux, macOS, Windows, WASM) - Trunk WASM build config Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
225
README.md
Normal file
225
README.md
Normal file
@@ -0,0 +1,225 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user