Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- **`inidisp_forgot_to_force_blank`: the model difference is now identified exactly, and a recorded
claim about it is corrected.** The last per-dot framebuffer gap was documented only as "an
`internal_cgram_address` draw-ordering detail". The concrete difference: MesenCE updates
`InternalCgramAddress` inside `GetRgbColor`, called **only when `color > 0`** and **per layer
during tilemap render** — so a transparent pixel leaves the previous opaque column's value standing,
and several layers may update it within one column. RustySNES assigns it **once per column,
unconditionally, from the composited pixel** at the draw cursor. Structurally different models, not
an off-by-one.

**Gate-on-opaque is not the fix**, measured rather than assumed: wrapping the assignment in
`if ap.opaque` moves the ROM's hash from `0xaeb678a4165b28c5` to `0xa55bd66a1e6dd125` — still not
the MesenCE-agreeing golden — because gating the *composite* is not gating each *layer fetch*.

**Correction:** the AccuracySNES row that breaks under gate-on-opaque is **`C3.12`** ("CGRAM taken
in render"), not `C3.04` ("H counter advances") as previously recorded — `C3.04` passes. `C3.12`
is the row that asserts the redirect target directly, so its failure means the cart row and
MesenCE's model disagree about a backdrop column, and that needs adjudicating before either
changes. The real fix tracks the target in the fetch stage, per layer, on non-zero colour indices.

- **Interlace scenes: the recorded Mesen2 nondeterminism is GONE, but interlace is blocked for a
different reason.** Probed and withdrawn. Three consecutive Mesen2 runs and two snes9x runs of an
interlace scene produced identical results, so the standing note that "Mesen2 alternates between
Expand Down
21 changes: 21 additions & 0 deletions docs/ppu.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,27 @@ Per `ref-docs/2026-06-24-ppu.md` §6:
documented per-dot gap in `undisbeliever_golden.rs`: its artifact is the CGRAM-redirect target on
backdrop columns between opaque regions (an `internal_cgram_address` draw-ordering detail, tied to
the draw-cursor/fetch-ahead alignment of Phase 4c), not a missing access-during-render redirect.

**The exact model difference, identified 2026-08-02.** MesenCE updates `InternalCgramAddress`
inside `GetRgbColor`, which it calls **only when `color > 0`** (`SnesPpu.cpp:1114`) — so a
*transparent* pixel leaves the address holding the previous opaque column's value — and it does so
**per layer during tilemap render**, in render order, so several layers may update it within one
column. RustySNES assigns it **once per column, unconditionally, from the composited pixel** at
the draw cursor (`render.rs`, `pd_draw_columns`). Those are structurally different models, not an
Comment on lines +173 to +174
off-by-one.
Comment on lines +169 to +175

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Remove the conflicting earlier redirect description.

The text at Line 155 through Line 158 still describes MesenCE as the palette of the last-drawn column maintained by the compositor. The text at Line 164 through Line 167 attributes the mismatch to draw-cursor/fetch-ahead alignment. Lines 169-175 now define a different model: per-layer updates, retained state across transparent pixels, and multiple updates within one column. Revise the earlier paragraphs so docs/ppu.md has one authoritative redirect model and keeps RustySNES's composited assignment separate from MesenCE's behavior.

As per path instructions, docs are the spec, not a history log; prose must not drift from the code it describes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/ppu.md` around lines 169 - 175, Revise the earlier redirect discussion
in docs/ppu.md around the descriptions of the last-drawn column and
draw-cursor/fetch-ahead alignment. Remove claims that MesenCE uses
compositor-level composited-column state or that the mismatch is solely cursor
alignment, and make the prose consistent with the authoritative per-layer,
transparent-pixel-retaining model while keeping RustySNES’s once-per-column
composited assignment distinct.

Source: Path instructions


**Gate-on-opaque is NOT the fix, and this was measured rather than assumed.** Wrapping the
assignment in `if ap.opaque` moves the ROM's hash from `0xaeb678a4165b28c5` to
`0xa55bd66a1e6dd125` — still not the MesenCE-agreeing golden — because gating the *composite* is
not the same as gating each *layer fetch*. It also breaks an AccuracySNES row. **Correction to a
previously recorded claim: the row it breaks is `C3.12` ("CGRAM taken in render"), not `C3.04`
("H counter advances"), which passes.** `C3.12` failing is the expected shape — it is the row that
asserts the redirect target directly — and it means the cart row and MesenCE's model disagree
about a backdrop column, which has to be adjudicated before either is changed.

So the real fix is to track the redirect target in the **fetch** stage, per layer, updating only
for a non-zero colour index in MesenCE's layer order. That is a Phase 4c-shaped change, which is
why this is still open.
The per-dot line state is transient (re-fetched at each line start), so it is not save-stated;
`Ppu::load_state` invalidates it (forcing a re-fetch) and a mid-line save re-fetches on load.
- **In-render OAM write redirect** (dossier C7.16). During
Expand Down
Loading