chore: add migration/ bundle for cross-machine setup

Bundles state that lives OUTSIDE the xenia-rs repo so a fresh clone on
another machine can be brought up to identical configuration via
migration/setup.sh:

  - claude-memory/             ~/.claude/projects/-home-fabi-RE-Project-Sylpheed/memory/
                               (103 files, 1.1 MB - MEMORY.md + every
                                project_xenia_rs_*.md from audits
                                addis_signext through audit-058)
  - project-root/dot-claude/   <project-root>/.claude/settings.json
                               (Stop hook + permissions)
  - project-root/ppc-manual/   <project-root>/ppc-manual/
                               (PowerPC reference docs, 397 files, 3.7 MB)
  - project-root/run-canary.sh <project-root>/run-canary.sh
  - README.md                  Human-readable setup checklist
  - setup.sh                   Idempotent installer (also reclones
                               xenia-canary at pinned HEAD 6de80dffe)
  - MANIFEST.md                Per-file mapping + per-file-not-bundled
                               restoration recipe

Excluded from bundle (not shippable via git):
  - Sylpheed ISO (7.8 GB; copyright; manual copy required)
  - sylpheed.db (395 MB; regenerable from XEX via analysis tooling)
  - target/ build artifacts (rebuild on target)
  - audit-runs probe firehoses (.log/.stdout/.stderr ~11 GB; rerun if needed)
  - audit-runs memory dumps (.bin ~4.5 GB; rerun audit-026/027/029 if needed)
  - xenia-canary checkout (setup.sh reclones from
    git.mc02.dev/fabi/Xenia-Canary.git at HEAD 6de80dffe)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-05-10 21:38:38 +02:00
parent 8e709b0a24
commit e6d43a23ac
505 changed files with 86028 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
---
name: EDRAM→memory resolve byte copy — status and remaining gaps
description: What now ships on TILE_FLUSH, which paths still fall through to skip/warn, and the Canary anchors for future expansion
type: project
originSessionId: c0486ac0-d44e-49fc-8a8d-6c28cb11ab9d
---
## Status (post 2026-04-22 landing)
`handle_event_initiator` at [gpu_system.rs:376+](../../../../xenia-rs/crates/xenia-gpu/src/gpu_system.rs)
now **writes bytes into guest memory** on TILE_FLUSH. End-to-end flow:
1. `ResolveInfo::from_register_file` ([draw_state.rs](../../../../xenia-rs/crates/xenia-gpu/src/draw_state.rs)) decodes `RB_COPY_CONTROL / RB_COPY_DEST_*` + `RB_SURFACE_INFO / RB_COLOR_INFO_* / RB_DEPTH_INFO / RB_COLOR_CLEAR / RB_COLOR_CLEAR_LO / RB_DEPTH_CLEAR` into a full Canary-parity struct: rectangle (scissor ∩ dest_pitch, 8-pixel aligned), source base tiles, surface_pitch_tiles (via `GetSurfacePitchTiles`), MSAA, 64bpp flag, clear values, dest_base **masked to `0x1FFF_FFFF`**, Endian128, format, array flag.
2. `ShadowEdram` ([edram.rs](../../../../xenia-rs/crates/xenia-gpu/src/edram.rs)) — 10 MiB (2048 × 80 × 16 samples × 4 B) CPU-side EDRAM that holds per-tile bytes. Clear-resolves paint `RB_COLOR_CLEAR` into the source tiles via `fill_rect_32bpp`; the copy loop reads out via `read_sample_32bpp`.
3. `resolve::copy_to_memory` ([resolve.rs](../../../../xenia-rs/crates/xenia-gpu/src/resolve.rs)) — per-pixel loop. For `k_8_8_8_8` source + dest (bitwise-equivalent fast path) it applies `apply_endian_128` and calls `mem.write_u32(tiled_2d_offset(x, y, pitch_aligned_to_32, bpp_log2=2))` — page versions bump so `texture_cache_host.rs` re-uploads on next bind.
4. `stats.resolves_copied_total` + `resolves_skipped_total` + `resolve_samples_written` flow to the HUD row 2.
## What's supported (expanded coverage)
- **Color sources** (any of these → any compatible color dest):
- `k_8_8_8_8` (0), `k_8_8_8_8_GAMMA` (1) → `k_8_8_8_8` (6), `k_8_8_8_8_A` (14), `k_8_8_8_8_AS_16_16_16_16` (50).
- `k_2_10_10_10` (2), `k_2_10_10_10_AS_10_10_10_10` (10) → `k_2_10_10_10` (7), `k_2_10_10_10_AS_16_16_16_16` (54).
- `k_16_16_FLOAT` (6) → `k_16_16_FLOAT` (31).
- `k_32_FLOAT` (14) → `k_32_FLOAT` (36).
- Gated by `is_32bpp_bitwise_equivalent` ([resolve.rs](../../../../xenia-rs/crates/xenia-gpu/src/resolve.rs)) mirroring Canary `IsColorResolveFormatBitwiseEquivalent` (xenos.h:614).
- **Depth sources**: `kD24S8` (0) → `k_24_8` (22); `kD24FS8` (1) → `k_24_8_FLOAT` (23). Reads depth tiles at `RB_DEPTH_INFO.depth_base`.
- **Rectangle derivation**: vertex-fetch-constant-0 when present (6-dword vertex buffer with endian-decoded floats, Fixed16p8 rounding, 3-vertex bounding box per Canary `draw_util.cc:950-1028`). Falls back to scissor ∩ `(0, 0, dest_pitch, dest_height)` when VF0 isn't a valid resolve vertex buffer. All outputs 8-pixel-aligned via `RESOLVE_ALIGNMENT_PIXELS = 8`.
- **`CopySampleSelect` sanitation** (`xenos.h:1039-1052`): MSAA + depth remap invalid selectors. Single-sample picks (`k0/k1/k2/k3`) honored; averaging modes (`k01/k23/k0123`) pick sample 0 + log `warn` (full averaging TODO).
- Endian: `kNone`, `k8in16`, `k8in32`, `k16in32` all correct. `k8in64`/`k8in128` approximated as `k8in32` + `tracing::warn`.
- Clear-resolve + copy-resolve paths both work.
- Destination address masked to Xenon 29-bit physical space.
## What logs + skips (graceful)
All of the below return `resolves_skipped_total += 1` with a `tracing::warn` identifying the reason — boot continues:
- 64bpp source (`k_16_16_16_16`, `k_16_16_16_16_FLOAT`, `k_32_32_FLOAT`).
- 3D/stacked destination (`copy_dest_array = 1`) — Canary `Tiled3D` not ported.
- Non-zero `dest_exp_bias` on linear formats.
- Non-bitwise-equivalent source/dest pair (e.g. `k_16_16``k_16_16`, which would need conversion tables).
## Deferred (next-session backlog, ordered by ROI)
**Small, bounded — take these first:**
1. **MSAA sample averaging** (`CopySampleSelect::k01/k23/k0123`). Today falls back to sample 0 + `warn`. Fix: read N samples, average by format-aware rule (unorm8 averaged as int, float averaged as float). Needs per-format decoder.
2. **64bpp source** (`k_16_16_16_16`, `k_16_16_16_16_FLOAT`, `k_32_32_FLOAT`). Skipped + logged. Needs double-tile EDRAM stride (`pitch_tiles << is_64bpp`) and two `write_u32` per pixel. Straightforward refactor of `resolve::copy_to_memory`.
3. **`RB_COLOR_CLEAR_LO` for 64bpp clear paint**. Already captured in `ResolveInfo` but `fill_rect_32bpp` only writes one lane. Companion to #2.
4. **Endian `k8in64` / `k8in128`** (properly). Approximated as `k8in32` today. Buffer pixels in pairs/quads before tile-write. Rare in practice.
5. **`copy_dest_exp_bias != 0`**. Skipped + logged. Needs float-format awareness; bake the scale factor into the sample converter.
**Large lifts — their own sessions:**
6. **wgpu render-target readback into `ShadowEdram`**. The clear-then-resolve path works, but once Sylpheed *draws* (currently `first Xenos draw: 0`), drawn pixels never reach EDRAM because the draw pipeline writes to wgpu attachments, not the shadow. Needs async `copy_texture_to_buffer` + CPU retile. Probably what unblocks frame-2 and beyond.
7. **3D / array destinations** (`copy_dest_array = 1`). Needs Canary's `Tiled3D` + `GetTiledOffset3D` ported. Rare on first-pixels path.
8. **Non-bitwise-equivalent conversion** — e.g. `k_16_16` RT (signed, range [-32, 32]) → `k_16_16` texture (unsigned). Requires Canary's conversion shader tables (`draw_util.cc:1320-1391` shader selection).
## Canary anchors (for future expansion)
- [draw_util.cc:926-1318](../../../../xenia-canary/src/xenia/gpu/draw_util.cc) — full `GetResolveInfo` including vertex-fetch rect.
- [draw_util.cc:1320-1391](../../../../xenia-canary/src/xenia/gpu/draw_util.cc) — shader selection (fast vs full paths).
- [render_target_cache.cc:1045](../../../../xenia-canary/src/xenia/gpu/render_target_cache.cc) — `GetResolveCopyRectanglesToDump` for host-RT dump.
- [texture_address.h:190-260](../../../../xenia-canary/src/xenia/gpu/texture_address.h) — `Tiled3D` (for copy_dest_array).
- [xenos.h:1039-1047](../../../../xenia-canary/src/xenia/gpu/xenos.h) — `SanitizeCopySampleSelect` for the MSAA sample-select rules.