Skip to content
Merged
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
57 changes: 57 additions & 0 deletions docs/accuracysnes-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,63 @@ wrapped part is page zero and precisely page zero. Nothing else is in reach howe
which is what lets the program wait a whole buffer cycle instead of timing anything — and the echo
offset free-runs regardless of `FLG` bit 5, so there is no starting phase to know.

### Survey of what is left in Group E, and why none of it is a quick row

Six rows landed in this batch (`E8.01`, `E9.02`, `E5.06`, `E9.09`, `E3.09`, `E3.13`) at roughly one
per sitting. The next person will want to know which of the remaining 26 is cheapest, and the
answer is **none of them** — this is the survey that establishes that, so it is not re-derived.
Comment on lines +771 to +773

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

file="docs/accuracysnes-plan.md"

sed -n '569,590p;769,823p' "$file"

echo
echo "All E-row references in the affected sections:"
sed -n '769,823p' "$file" |
  grep -oE '\bE[0-9]+\.[0-9]+\b' |
  sort |
  uniq -c

Repository: doublegate/RustySNES

Length of output: 6066


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' 'Relevant documentation files:'
git ls-files 'docs/*' | grep -E 'accuracysnes-(plan|coverage)\.md$|architecture\.md|STATUS\.md|(^|/)ADR' || true

printf '\n%s\n' 'Group E headings and row references in the plan:'
rg -n -C 2 'Group E|E[0-9]+\.[0-9]+' docs/accuracysnes-plan.md | sed -n '1,260p'

printf '\n%s\n' 'Coverage references for Group E:'
rg -n -C 2 'Group E|E[0-9]+\.[0-9]+' docs/accuracysnes-coverage.md || true

Repository: doublegate/RustySNES

Length of output: 21497


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' 'Plan and coverage status context:'
sed -n '560,590p;724,755p;769,835p' docs/accuracysnes-plan.md
sed -n '1,75p' docs/accuracysnes-coverage.md

printf '\n%s\n' 'Tracked accuracy-related files:'
git ls-files | grep -Ei 'accuracysnes|dossier|accuracy' | sed -n '1,160p'

printf '\n%s\n' 'Working-tree change summary:'
git status --short
git diff --stat -- docs/accuracysnes-plan.md docs/accuracysnes-coverage.md

Repository: doublegate/RustySNES

Length of output: 18991


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' 'Canonical Group E dossier entries:'
rg -n -C 3 '^\|? *E(1|2|3|4|5|6|7|8|9|10)\.' docs/accuracysnes-research-dossier.md | sed -n '1,260p'

printf '\n%s\n' 'Group E entries in the coverability audit:'
rg -n -C 3 'Group E|E[0-9]+\.[0-9]+' docs/accuracysnes-coverability-audit-2026-07-23.md | sed -n '1,260p'

printf '\n%s\n' 'Coverage and plan status references for the six batch IDs:'
for id in E8.01 E9.02 E5.06 E9.09 E3.09 E3.13; do
  printf '\n--- %s ---\n' "$id"
  rg -n -C 2 --fixed-strings "$id" docs/accuracysnes-coverage.md docs/accuracysnes-plan.md
done

Repository: doublegate/RustySNES

Length of output: 27598


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
import re
from pathlib import Path

coverage = Path("docs/accuracysnes-coverage.md").read_text()
plan = Path("docs/accuracysnes-plan.md").read_text()

# Read only Group E rows from the generated coverage table.
start = coverage.index("| `E1` |")
end = coverage.index("| `F1` |")
coverage_rows = coverage[start:end]

uncovered = []
for line in coverage_rows.splitlines():
    if not line.startswith("| `E"):
        continue
    cells = [cell.strip() for cell in line.strip("|").split("|")]
    if len(cells) < 5 or cells[4] in ("—", ""):
        continue
    uncovered.extend(re.findall(r"E\d+\.\d+", cells[4]))

# Read only the survey body, excluding the heading and the following E8.01 section.
survey_start = plan.index("### Survey of what is left in Group E")
survey_end = plan.index("### `E8.01`", survey_start)
survey = plan[survey_start:survey_end]
survey_ids = sorted(set(re.findall(r"E\d+\.\d+", survey)))

print("Generated coverage uncovered IDs:", len(uncovered))
print(" ".join(uncovered))
print("Unique survey IDs:", len(survey_ids))
print(" ".join(survey_ids))
print("Uncovered IDs omitted from survey:", len(set(uncovered) - set(survey_ids)))
print(" ".join(sorted(set(uncovered) - set(survey_ids))))
print("Survey IDs that coverage marks covered:", len(set(survey_ids) - set(uncovered)))
print(" ".join(sorted(set(survey_ids) - set(uncovered))))
PY

Repository: doublegate/RustySNES

Length of output: 749


Reconcile the Group E inventory with generated coverage. The coverage table lists 31 uncovered IDs, but the survey names 25 IDs, including six covered rows (E3.09, E3.13, E5.06, E8.01, E9.02, E9.09). It therefore lists only 19 current uncovered rows and omits 12. Align the 34 and 26 counts and remove E8.01 from the current remaining set, or label those passages as historical snapshots.

🤖 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/accuracysnes-plan.md` around lines 771 - 773, Reconcile the Group E
inventory in the survey with the generated coverage table: update the 34 and 26
counts to match the current inventory, remove E8.01 and the other covered IDs
from the current remaining set, and include the 12 omitted uncovered IDs. If
these figures are intentionally historical, label the affected passages as
historical snapshots instead.

Sources: Path instructions, Learnings

Recorded per row, because "it is hard" is not usable and "here is the specific obstacle" is.

**Blocked on an observable the SPC700 cannot reach in time.** The instruction set's floor for three
consecutive DSP register reads is 21 cycles of a 32-cycle sample (`E8.06`, withdrawn). Everything
that needs to catch two registers in different phases of one sample is behind that same wall:
`E10.02` (the T0-T31 access schedule), `E10.03` (the DSP registers `ENDX` (`$7C`), `VxOUTX`
(`$x9`) and `VxENVX` (`$x8`) written on three separate cycles — DSP registers throughout this
section, never the `$2140-$2143` ports).

**Blocked on nothing being observable at all.** `E9.16` (the output is XORed with `$FFFF` by the
post-amp) is downstream of every register the cart can read — it changes what reaches the DAC and
nothing else. `E10.04` (SPC and DSP share `/RESET` and the clock) is structural.

**Reachable only through another row's mechanism, which makes the attribution weak.** `E1.11`
(`TSET1`/`TCLR1` read the target twice) can only be distinguished by the value written *back*, and
the only read-sensitive targets — `$FD`-`$FF` — are read-only, so that value lands in the RAM
shadow and needs `E3.13`'s DSP-as-second-reader trick to see. A row whose verdict depends on
another row's mechanism reports that mechanism's failures as its own.

**Needs a rate or ramp measurement, which is where the sawtooth trap lives.** `E6.01` (counter bits
15-12 select the sample), `E6.06` (the counter clamps at `$7FFF`, reachable only through `PMON`),
`E6.10` (gaussian bypassed for noise), `E9.07` (`EDL` latency), `E9.08` (`ESA` delayed 1-2 samples),
`E7.02` (the counter offset table). Each of these is a "how fast" or "how long until", and the
phase that decides it is the one the cart does not control. `E8.01` cost two drafts learning that;
any of these needs a *counting* observable found first, not an instrument built first.

**Genuinely racy.** `E3.12` (the CPUIO bus conflict reads the OR of old and new) and `E4.10`
(simultaneous CPU/SPC access) are contention rows; `E4.09`'s "*can* corrupt `$2143`" is probabilistic
by its own wording.

**Large but mechanical, and the one worth planning for.** `E2.10` is the full 256-opcode SPC700
cycle sweep. It needs every opcode encodable in `gen/src/spc.rs`, which deliberately carries only
opcodes a committed test exercises — an unverified encoding surfaces as an emulator disagreement
rather than as an assembler bug. That is the single biggest coverage item left in the group and the
only one whose difficulty is volume rather than design.

**Thin on oracle.** `E8.11` (DSP `KOF` init) and `E9.20` (the Nintendo FIR preset is bugged) are
named as game-compatibility cases rather than as values, and `E9.20`'s margin is ~3% and entangled
with `E9.11`'s wrapping taps.

**Two method notes that did pay off, and should be tried first on any new row:**

- **Check the emulator side for dead config before designing anything.** `E3.09`'s feature was fully
parsed into `Io::external_wait`/`Io::internal_wait`, serialized, restored — and never read. A
sweep for fields written but not read found it, and a second sweep found `Voice.keyon` in the same
state. Grep a setting's *readers*, not its definition.
- **Prefer an equality against a control to a threshold against nothing.** `E3.13` compares a voice
reading the RAM shadow against a voice reading an identical copy in ordinary RAM; `E9.09` compares
a wrapped echo entry against an unwrapped one. Both would have been "is it non-zero" rows
otherwise, and both would have passed on a broken setup. `E3.13` did fail on one, twice, and the
control voice is what said so.

### `E8.01` — two rejected drafts, and what they were really measuring

The row asks how often the DSP looks at `KON`. Both first attempts measured a **delay**: write
Expand Down
Loading