Files
Stefan ArentzandClaude Opus 4.8 3e7474ac9f Mouse plan M1: a maskable-interrupt path + corrected cpu.irq() (#325)
The first phase of the AppleMouse II card (plans/20260721-01): the reusable
IRQ machinery the mouse (and later Mockingboard) needs. Dormant in
production — no device asserts the line yet — so no existing test moves.

CPU (ewm-core):
- Split BRK from a hardware IRQ, which shared one BRK-shaped code path. A
  real `cpu.irq()` now pushes the *exact* resume PC with B **clear** and
  vectors $FFFE; `nmi()` matches via $FFFA. BRK keeps its own path
  (`brk_interrupt`): PC+1 with B **set**. A shared `enter_interrupt` helper
  carries the three. Dormann (which exercises BRK) is byte-identical.
- Tests: a hardware IRQ pushes the exact PC / B=0 / masks I / RTI resumes;
  BRK pushes PC+1 / B=1 — the two stay distinct.

Machine (ewm/two.rs):
- `Two` caches the maskable IRQ line as one bool; `service_irq()` polls it
  between `cpu.step()`s in both burst loops (SDL `run`, headless `serve`).
  Level-sensitive and gated by I: high + I==0 takes the IRQ (which sets I,
  so the handler runs to RTI); SEI holds it pending until CLI; a low line is
  never taken. Just a `bool && I` check per step — the line is refreshed on
  state change, never scanned per instruction (the hazard the plan flags).
- Test: the line is level-sensitive and I-gated. `set_irq_line` is a
  test-only hook until Phase M4 wires the mouse device's asserted state.

Kickoff decisions recorded in the plan (owner directed one PR per phase;
relative/captured coords; firmware-default clamp; Two-local IRQ line;
scripted M4 gate).

Gates: cargo fmt / clippy -D warnings / cargo test (370 pass, incl. Dormann,
two_timing, and the golden-BMP screenshots — the burst-loop change is inert).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 00:46:31 -04:00
..