Files
xenia-rs/HANDOFF-intro-video-done.md
MechaCat02 cc9ebbb5e7 [iterate-4A] docs: handoff for intro-video-done milestone + speed frontier
HANDOFF-intro-video-done.md: what to push/copy, the 6 branch commits, build/run,
root-cause summary, and the profiled emulator-speed frontier with ranked levers.

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

110 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Handoff — Intro video SOLVED (`iterate-4A/apu-xma-stage1`, tag `intro-video-done`)
The original frontier — **why `dat/movie/ADV.wmv` never played** vs Xenia Canary — is **solved**.
The intro renders authentically: white SQUARE ENIX logo + cyan glow + red diamonds on a near-black
background, correct color / geometry / luminance, playing reliably. This doc is the handoff for that
state and the newly-opened **emulator-speed** frontier.
> Method (unchanged): first-divergence vs canary · fix causes not symptoms · NO masking · measure the
> oracle, never infer. Full setup for this branch is in `HANDOFF-iterate-4A-milestone2.md` (FFmpeg dev
> libs, DuckDB tooling, etc.) — read that first on a fresh machine.
---
## 0. What to push / copy for handoff
**Git (the only repo):** `xenia-rs/`. Branch `iterate-4A/apu-xma-stage1`, **6 commits ahead of origin**.
```bash
cd xenia-rs
git push origin iterate-4A/apu-xma-stage1 # the 6 commits below
git push origin intro-video-done # the annotated milestone tag (-> 5573ac1)
```
**Not in git (machine-local — copy manually for a full-context handoff):**
- `../CLAUDE.md` — project working instructions (project root is NOT a git repo).
- `~/.claude/projects/-home-fabi-RE---Project-Sylpheed/memory/` — the auto-memory (`MEMORY.md`
index + topic files). This is where the detailed step-by-step history lives.
- Large local artifacts (NOT pushed): the real ISO (`sylpheed.iso` symlink target), `sylpheed.db`
(DuckDB static-analysis DB, ~1h35m to regenerate — see CLAUDE.md), canary build.
---
## 1. Commits on this branch (ahead of origin)
| Commit | What |
|---|---|
| `645feb8` | ROOT #1 decode-timeout clock (IPM 10k→1M), #1b feeder starvation (incumbent-pick), #2 `k_8` texture decoder |
| `4344152` | re-baseline boot golden 50M→200M after the clock fix |
| `3559c8f` | ROOT #3 host render path — multi-texture YUV, tfetch dest-swizzle, PS const-bank +256 |
| `deb9292` | RectangleList quad completion (fix diagonal seam) |
| `5573ac1` | MULSC/ADDSC/SUBSC scalar-const operand addressing (fix squared-luma) — **tag `intro-video-done`** |
| `2c883e9` | diagnostics snapshot: `XENIA_PROFILE` profiler + probe/tooling (this handoff) |
Working tree is **clean** — all diagnostics/tooling are now committed in `2c883e9`.
---
## 2. Build & run (see CLAUDE.md for the authoritative version)
```bash
cd xenia-rs
export CARGO_BUILD_JOBS=4 && cargo build --release # ~8s incremental
# Headless oracle run (threaded GPU, single-thread CPU lockstep):
RUST_LOG=warn ./target/release/xenia-rs exec sylpheed.iso -n 3000000000
# Watch the movie (windowed): add --ui ; the first on-screen frame is at ~81s WALL
# (mostly boot). Give it >=150s. Boot is DETERMINISTIC; only wall speed varies.
```
Movie oracles: `sylph-run.sh [runs] [n] [timeout]` (default 180s). Static analysis: `zq.py` over
`sylpheed.db` (DECIMAL bounds, never `0x`). Both are committed at repo root now.
---
## 3. Root-cause summary (the fixes)
- **#1 clock deadline** — movie handler `sub_821B4968` has a 2000 ms decode-ready timeout;
`INSTRUCTIONS_PER_MS` 10k ran ~320× too fast so a legit 720p decode looked timed-out → abort.
Fixed to 1_000_000 (`state.rs`; `XENIA_INSTR_PER_MS` overrides).
- **#1b feeder starvation** — co-located feeder tid24 lost the equal-priority rotation;
`pick_runnable` now has an incumbent-preference tiebreak (`scheduler.rs`; `XENIA_INCUMBENT_PICK`).
- **#2 `k_8` decoder** — the movie uploads YUV planes as linear `k_8`; added `decode_k8`.
- **#3 host render path** — multi-texture (8 YUV slots), tfetch 12-bit dest-swizzle, PS constant
bank +256 (Xenos splits VS 0..255 / PS 256..511), RectangleList quad synthesis (v3=v0+v2v1),
and MULSC operand addressing (src3, not src_a/src_b). Details: memory topic file STEPs 88→97.
---
## 4. Open frontier — emulator SPEED (profiled, not yet worked)
Playback is slow (~1419 fps). First quantified profile (`XENIA_PROFILE=1`, headless):
- Effective **~35 MIPS** overall (3 B guest instr / 86 s clean).
- **Interpreter body ~40% @ ~95102 MIPS**; kernel HLE ~4%; block-cache lookup ~56%;
**texture decode 0.3% (cache works — not a bottleneck); present ~0%; no default IPS throttle.**
- The rest is **per-block dispatch + scheduler plumbing** — ~13 instr/block over ~229 M blocks,
each paying fixed prologue/epilogue/lookup/borrow costs. **Overhead-bound, not interpreter-body
bound.** (Note: default run is single-thread lockstep `run_superblock`, confirming the
"serialized single-core" architecture; the console's 6 HW threads are time-sliced onto one host
thread. `--parallel` exists but is not validated for the movie.)
**Ranked levers:**
1. **Coarsen the execution unit — longer superblock chains** (raise `superblock_budget`). Cheap,
reversible, targets the dominant overhead. ⚠️ chaining is also the scheduling lever (can starve
the movie subsystem — validate against the oracles). *Start here.*
2. **JIT / block-recompiler** — collapses both the interpreter body and per-block dispatch; the real
ceiling (~510×), but a multi-week subsystem.
3. **True multi-core** (guest threads on separate host threads) — huge for a 6-thread workload but
riskiest: would invalidate the IPM=1M + incumbent-pick timing fixes that made the video work.
**Caveat for the next session:** precise remainder attribution needs a sampling profiler
(`perf_event_paranoid=4` blocks perf without sudo here; gdb `ptrace_scope=1` blocks non-descendant
attach). The `XENIA_PROFILE` coarse timers are the current best tool and are now gated zero-cost
when off.
---
## 5. `XENIA_PROFILE` quick reference
`XENIA_PROFILE=1 <run>` → periodic snapshots (every 500 M guest instr, or every 500 presents) +
a clean-exit report on stderr. Buckets: interp `step_block`, kernel HLE `call_export`, block
decode/cache `lookup_or_build`, texture decode, host draw, present, and the unaccounted remainder.
Zero-cost when unset (cached `is_on()` gate). Source: `crates/xenia-gpu/src/prof.rs`.