mirror of
https://github.com/imjasonh/nescript
synced 2026-07-09 01:16:12 +00:00
linker+runtime: code review cleanup of the seven gates
* Tighten the OAM-DMA gate: the `has_oam` flag now ORs `__sprite_cycle_used` in addition to `__oam_used`. A hypothetical program that calls `cycle_sprites` without ever drawing would otherwise compile to an NMI that advances \$07EF each frame but never actually runs the DMA the cycling is meant to perturb. The stronger gate keeps the two markers semantically coupled (cycling presupposes DMA) and adds a test that verifies the DMA trigger is emitted for a cycle-only program. * Drop the unused `NmiOptions::any_input()` helper. The only consumer (`gen_nmi`) reads the two flags inline and I never wired up a second caller. * Fix the cycle-count claim in `NmiOptions::has_p2_input` / `has_p1_input` docstrings: LDA abs + LSR A + ROL zp is 11 cycles per port, ×8 loop iterations = ~88 cycles, not the "~30" I wrote in the original commit. Also notes the ~12-cycle strobe + scaffold overhead that disappears when both ports are unused. No behavioural change — all 622 Rust tests and 33 emulator goldens still pass unchanged. https://claude.ai/code/session_016kM6P7PukktBDqTZexrrAN
This commit is contained in:
parent
53c454669d
commit
e5bc325a71
3 changed files with 39 additions and 21 deletions
|
|
@ -388,29 +388,19 @@ pub struct NmiOptions {
|
|||
pub has_oam: bool,
|
||||
/// When false, drop the three instructions that shift `$4017`
|
||||
/// (JOY2) into `ZP_INPUT_P2` from the NMI's 8-iteration input
|
||||
/// loop. Single-player programs save ~6 bytes of code and ~30
|
||||
/// cycles per frame (a `LDA abs`, an `LSR A`, and a `ROL zp`
|
||||
/// running 8 times).
|
||||
/// loop. Single-player programs save ~6 bytes of code and ~88
|
||||
/// cycles per frame (LDA abs + LSR A + ROL zp = 11 cycles × 8
|
||||
/// iterations).
|
||||
pub has_p2_input: bool,
|
||||
/// When false, drop the three instructions that shift `$4016`
|
||||
/// (JOY1) into `ZP_INPUT_P1`. If both `has_p1_input` and
|
||||
/// `has_p2_input` are false the whole strobe-and-loop block
|
||||
/// disappears — programs that never touch `button.*` pay
|
||||
/// zero cycles for input sampling.
|
||||
/// zero cycles for input sampling (~100 cycles: the 88-cycle
|
||||
/// body plus the ~12-cycle strobe and loop scaffold).
|
||||
pub has_p1_input: bool,
|
||||
}
|
||||
|
||||
impl NmiOptions {
|
||||
/// Whether the program reads any controller input — the
|
||||
/// necessary condition for emitting the strobe write to
|
||||
/// `$4016` and the 8-iteration shift loop. Skipped entirely
|
||||
/// when both ports are unused.
|
||||
#[must_use]
|
||||
pub fn any_input(&self) -> bool {
|
||||
self.has_p1_input || self.has_p2_input
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn gen_nmi(opts: NmiOptions) -> Vec<Instruction> {
|
||||
let NmiOptions {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue