mirror of
https://github.com/imjasonh/nescript
synced 2026-07-08 17:06:04 +00:00
Skip the OAM DMA (LDA#0/STA \$2003 + LDA#2/STA \$4014) inside the NMI handler and the `\$FE` hide-sentinel fill of the \$0200 OAM shadow inside `gen_init` for programs that never `draw`. Both are gated on the `__oam_used` marker the IR codegen now drops at the first `IrOp::DrawSprite`. Savings per NMI for a non-drawing program: - ~520 cycles (the DMA is 513 cycles plus the 4 register writes), - ~9 bytes of NMI code, - ~4 bytes of init code (the \$FE swap is replaced by a plain zero-fill of \$0200-\$02FF alongside the rest of the 2 KB RAM clear). Plumbed by: - New `NmiOptions::has_oam: bool`, threaded through `gen_nmi`. - `gen_init(has_oam: bool)` parameter controlling the inner-loop OAM fill. Existing runtime tests all migrate to `gen_init(true)` to preserve their legacy assertions. - Linker computes `has_oam = has_label(user_code, "__oam_used")` once and feeds it to both call sites, and the existing `has_visual_output` predicate reuses the same lookup rather than re-scanning user_code. sfx_pitch_envelope is the one audio-only example; its audio golden flips by the usual cycle-accurate-APU-register-write-timing drift caused by the NMI layout shifting ~14 bytes earlier. https://claude.ai/code/session_016kM6P7PukktBDqTZexrrAN |
||
|---|---|---|
| .. | ||
| goldens | ||
| .gitignore | ||
| harness.html | ||
| package-lock.json | ||
| package.json | ||
| record_gif.mjs | ||
| run_examples.mjs | ||