1
0
Fork 0
mirror of https://github.com/imjasonh/nescript synced 2026-07-08 08:55:38 +00:00

review: tighten PRNG / void-intrinsic / FCEUX path handling

Follow-up cleanup on the cc65 parity batch. Addresses issues found
during a post-commit code review.

**Correctness fixes:**

- `rand8()` / `rand16()` at statement position (result discarded)
  were being eliminated by DCE because `op_dest` returned
  `Some(dest)` for Rand8/Rand16 even though the ops have a visible
  side effect — advancing the PRNG state. Now `op_dest` returns
  `None` for both, keeping the JSR regardless of liveness. New
  regression test `rand8_statement_survives_dce`.
- Void-only intrinsics (`poke`, `seed_rand`, `set_palette_brightness`)
  used in expression position (e.g. `var x = seed_rand(42)`) were
  panicking the linker with an unresolved `__ir_fn_X` label. The
  analyzer now emits E0203 with a clear message; new
  `void_intrinsic_in_expression_position_errors` test covers all
  three names.
- Statement-position `rand8()` / `rand16()` weren't lowered at all
  (they fell through to the default Call path). Now both lower to
  their IR op with a fresh temp that nothing reads; the JSR still
  runs so the PRNG state advances.
- `--fceux-labels foo.nes` was producing `foo.0.nl` because
  `PathBuf::with_extension` replaces instead of appends. Rewritten
  to literally append `.<bank>.nl` / `.ram.nl` to the OsString, so
  users get the FCEUX-expected `foo.nes.<bank>.nl` naming.
- Linker now asserts CNROM / AxROM don't accept user-declared
  switchable PRG banks — their page sizes don't fit the 16 KB per
  bank model, and silently producing a mis-sized ROM is worse than
  a loud panic.

**PRNG cleanup:**

- Removed the stream-of-consciousness comment block in `gen_prng`
  that described three abandoned algorithms before landing on the
  actual Galois LFSR.
- Simplified `__rand16` to a single JSR + LDX instead of two
  JSRs + TAY/TYA round-trip — a single shift already produces 16
  fresh bits, the doubled call just burned ~40 cycles. The golden
  PNG for `prng_demo` was regenerated to reflect the new sequence.
- Rewrote the `gen_prng` doc comment to accurately describe the
  algorithm as a Galois LFSR (it was mislabelled as xorshift).
- Rewrote the `gen_palette_brightness` doc comment with a proper
  table of level→mask mappings — the prior prose description
  didn't match the actual table values.

**Tests:**

- Three new unit tests in `linker::debug_symbols` covering the
  FCEUX `.nl` renderer: user-facing labels only, empty output when
  no user labels exist, and deterministic sorting in `.ram.nl`.
- Extended `nes2_mapper_high_nibble_in_byte_8_is_zero_for_small_mappers`
  to cover AxROM + CNROM.
- Renumbered priority list in future-work.md after removing the
  shipped sections (J, K, N, parts of V and Y).

All 737 tests + 40/40 emulator goldens still green.
This commit is contained in:
Claude 2026-04-18 18:48:55 +00:00
parent a924dcc59c
commit f4968256f4
No known key found for this signature in database
13 changed files with 337 additions and 166 deletions

View file

@ -1,9 +1,11 @@
// PRNG demo — sprite positions driven by the runtime PRNG.
//
// Each frame draws four sprites at addresses pulled from the
// xorshift-style `rand8()` intrinsic, with an extra `rand16()`
// sample binned into a horizontal velocity. Exercises `rand8`,
// `rand16`, and `seed_rand` end-to-end.
// Each frame draws four sprites at pseudorandom coordinates pulled
// from the Galois-LFSR `rand8()` intrinsic, plus one sprite whose
// (x, y) pair comes from a single `rand16()` draw. Exercises all
// three PRNG intrinsics (`rand8`, `rand16`, `seed_rand`) end-to-end.
// `seed_rand(0x1234)` on the first frame pins the sequence so the
// committed golden is deterministic.
game "PRNG Demo" {
mapper: NROM

Binary file not shown.