chore(ci): Bump actions/upload-artifact from 4 to 6 - #4
Conversation
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 6. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](actions/upload-artifact@v4...v6) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
LabelsThe following labels could not be found: Please fix the above issues or remove invalid values from |
There was a problem hiding this comment.
Pull request overview
This PR updates the actions/upload-artifact action from version 4 to version 6 in the CI workflow, bringing support for Node.js 24 and updated dependencies.
- Updates the upload-artifact action to leverage Node.js 24 runtime
- Maintains compatibility with existing artifact upload configuration
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
doublegate
left a comment
There was a problem hiding this comment.
Reviewed / Approved - GitHub Version Bump(s) -- DG 12/19
…+ harvest (A-H) Frontend-only (zero changes to any core crate; AccuracyCoin 100%/139 and the 60/60 + 52/52 commercial oracles stay byte-identical). The three requested features plus five low-risk quality-of-life items harvested from the reference emulators (tetanes/Mesen2/fceux survey). A. Master volume — [audio] volume + muted; gain applied once per cpal callback at the lock-free ring consume point (QueueInner gain atomic); Audio-tab slider + mute, live-applied. B. Emulation-speed presets (25/50/75/100/150/200/300%) — EmuCore.speed scales effective_frame_duration at every pacer site (1.0 = bit-identical); forces wall-clock pacing at non-100% (display-sync can't do fractional rates); pitch-shifted glitch-free audio via a resampler base_ratio re-centering the DRC band on the speed. Emulation->Speed submenu + status readout; keys =/-/0 (SpeedUp/Down/Reset, verified unbound). C. Save-state thumbnails — native Save-States manager (File->Save States...) surfacing the existing core THM thumbnail via save_state::slot_meta + Nes::extract_thumbnail; per-slot egui texture cache, invalidated on save and dropped on ROM change. D. Controller hot-plug toast (gilrs Connected/Disconnected). E. Deadzone slider in the Input settings tab (exposes the existing config). F. Overscan crop toggle ([graphics] hide_overscan; blit-UV crop of the top/ bottom 8 scanlines, no new pass) — View + Video tab. G. Pause-screen dimming overlay (40% dim + centered PAUSED, over the viewport only). H. Reset-to-Defaults per Settings section (two-click confirm, live re-apply). Gates: fmt, workspace clippy, wasm-winit/wasm-canvas/no-default/RA clippy, rustdoc, frontend tests (149), and the determinism re-verify (AccuracyCoin 139/139 + oracles 60/60 + 52/52) all green. New file save_states_ui.rs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…h (I-K) The remaining three ref-proj survey items, completing the full set. I. Per-APU-channel mute toggles — the one core-touching item, done determinism-safe. rustynes-apu gains a `channel_mask: u8` (default CHANNEL_MASK_ALL = 0x3F) gated at the single mix site: with the default mask every channel passes through unchanged, so the mixer output is byte-identical (the oracle/tests never clear a bit) — NOT serialized into the save-state. Nes::set_apu_channel_mask/apu_channel_mask passthrough. Six checkboxes (Pulse1/Pulse2/Triangle/Noise/DMC/Mapper Audio) in the Settings Audio tab, pushed to the core under the emu lock, re-applied on ROM load + power-cycle, persisted to [audio]. +4 APU unit tests prove default == unmasked. J. Screenshot-to-clipboard (native-only) — `arboard` behind the cfg(not(wasm32)) target table (never enters wasm); File -> "Copy Screenshot to Clipboard" reuses the take_screenshot grab, toasts on success/failure, never panics. K. Live FPS/frame-time graph — a hand-rolled ui.painter() sparkline in the Performance panel (presented over produced, a 16.64 ms NTSC deadline line, auto-scaled) — no egui_plot dependency. MSRV guard: `.cargo/config.toml` gains `[resolver] incompatible-rust-versions = "fallback"` so a future `cargo update` can't pull `image` (arboard's clipboard image dep) past the 1.86 MSRV; the committed Cargo.lock already holds MSRV-safe pins (arboard 3.6.1, image 0.25.5) and is unchanged by the guard. Gates: fmt, workspace clippy, wasm-winit/wasm-canvas/no-default/RA clippy, rustdoc, frontend tests (150), and the determinism re-verify — AccuracyCoin 100% (139/139), oracles 60/60 + 52/52 byte-identical (independently re-run after the core APU change), APU crate 127 tests. ppu/cpu/mappers untouched. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…harvest) README + CHANGELOG [1.0.0] + the user-guide (controls/configuration/menus/ display-and-audio/troubleshooting) now reflect the shipped #4 batch: master volume + mute, per-APU-channel mutes (channel_mask bitmask), emulation-speed presets (25-300%, keys =/-/0), the thumbnail Save-States manager, overscan crop, pause-dim, gamepad deadzone slider, controller hot-plug toasts, screenshot-to-clipboard, per-section Reset-to-Defaults, and the Performance- panel frame-time sparkline. Settings tabs labelled Display/Audio/Input/Advanced. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Records the bug-fix rounds 1-3 and the #4 feature batch (all user-smoke-tested) + the .cargo MSRV resolver guard, replacing the "compile-verified only" caveat the shell originally shipped with. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Adjudicated (post-hoc closeout): Copilot's review is an overview of a routine Dependabot bump — |
…0 pal_apu_tests Implement the PAL (2A07) APU frame-counter sequencer step positions, closing five of the seven PAL timing residuals the salvaged screen-reading oracle pinned. The blargg `pal_apu_tests` corpus now scores 8/10 under forced PAL region (was 3/10), with the two remaining failures documented as a bounded, fail-loud residual. Mechanism --------- The 2A03 (NTSC) and 2A07 (PAL) share the same six-step sequencer but divide the CPU clock differently, so the identical quarter/half/IRQ events land at different CPU-cycle counts. `FrameCounter` now carries a `pal: bool` selector, derived from the console `Region` by `Apu::new` (true only for `Region::Pal`; NTSC and Dendy — a PAL-clocked famiclone with an NTSC-period frame counter — keep the NTSC positions). The sequencer step tables are: - PAL 4-step (mode 0): 8313 / 16627 / 24939 / 33252 / 33253 / 33254 (quarter 8313/16627/24939/33253; half 16627/33253; IRQ 33252/33253/33254). - PAL 5-step (mode 1): 8313 / 16627 / 24939 / 41565 / 41566 (quarter 8313/16627/24939/41565; half 16627/41565; no IRQ). These are the canonical Mesen2 `stepCyclesPal` values. The mode-0 terminal three cycles replicate the NTSC IRQ-flag-visibility / `irq_line_active` split verbatim at the PAL positions, preserving the AccuracyCoin Frame-Counter-IRQ Tests I/J/K/L/M semantics for PAL. NTSC byte-identity (sacred constraint) -------------------------------------- The change is strictly region-gated: the `pal == false` branch runs the original NTSC step tables unchanged, and the power-on / snapshot-restore default is NTSC. The `tick` hot path was split into `clock_sequencer` + `four_step` / `five_step` helpers (to stay within the clippy line budget) with no behavioral change to the NTSC arms. Verified byte-identical: - AccuracyCoin 141/141 (100.00%) — unchanged. - `apu_test` 8/8, NTSC `blargg_apu_2005` 11/11, `nestest` 0-diff — unchanged. - APU snapshot format is untouched: `pal` is derived, not persisted; `Apu::restore` re-derives it from the restored region. Residual (honest) ----------------- `10.len_halt_timing` and `11.len_reload_timing` still fail, but the PAL step positions advanced them from `FAILED: #2` to `FAILED: #3` / `#4`. Their NTSC builds pass (`blargg_apu_2005` 10 & 11), localizing the gap to a PAL-specific length-counter halt/reload write-vs-half-frame-clock ordering detail adjacent to the frame-counter step model. Left as fail-loud residual pins and recorded in docs/accuracy-ledger.md; closing it is a separate deeper investigation. Tests + docs ------------ Adds seven PAL frame-counter unit tests (step positions, IRQ position, no-IRQ-at-NTSC-position, wrap, 5-step, NTSC-default). Promotes pal_apu 04-08 from residual pins to strict passes; keeps 10/11 as documented residuals. Updates docs/apu-2a03.md, docs/accuracy-ledger.md, docs/STATUS.md, docs/testing-strategy.md to the 8/10 state. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…0 pal_apu_tests Implement the PAL (2A07) APU frame-counter sequencer step positions, closing five of the seven PAL timing residuals the salvaged screen-reading oracle pinned. The blargg `pal_apu_tests` corpus now scores 8/10 under forced PAL region (was 3/10), with the two remaining failures documented as a bounded, fail-loud residual. Mechanism --------- The 2A03 (NTSC) and 2A07 (PAL) share the same six-step sequencer but divide the CPU clock differently, so the identical quarter/half/IRQ events land at different CPU-cycle counts. `FrameCounter` now carries a `pal: bool` selector, derived from the console `Region` by `Apu::new` (true only for `Region::Pal`; NTSC and Dendy — a PAL-clocked famiclone with an NTSC-period frame counter — keep the NTSC positions). The sequencer step tables are: - PAL 4-step (mode 0): 8313 / 16627 / 24939 / 33252 / 33253 / 33254 (quarter 8313/16627/24939/33253; half 16627/33253; IRQ 33252/33253/33254). - PAL 5-step (mode 1): 8313 / 16627 / 24939 / 41565 / 41566 (quarter 8313/16627/24939/41565; half 16627/41565; no IRQ). These are the canonical Mesen2 `stepCyclesPal` values. The mode-0 terminal three cycles replicate the NTSC IRQ-flag-visibility / `irq_line_active` split verbatim at the PAL positions, preserving the AccuracyCoin Frame-Counter-IRQ Tests I/J/K/L/M semantics for PAL. NTSC byte-identity (sacred constraint) -------------------------------------- The change is strictly region-gated: the `pal == false` branch runs the original NTSC step tables unchanged, and the power-on / snapshot-restore default is NTSC. The `tick` hot path was split into `clock_sequencer` + `four_step` / `five_step` helpers (to stay within the clippy line budget) with no behavioral change to the NTSC arms. Verified byte-identical: - AccuracyCoin 141/141 (100.00%) — unchanged. - `apu_test` 8/8, NTSC `blargg_apu_2005` 11/11, `nestest` 0-diff — unchanged. - APU snapshot format is untouched: `pal` is derived, not persisted; `Apu::restore` re-derives it from the restored region. Residual (honest) ----------------- `10.len_halt_timing` and `11.len_reload_timing` still fail, but the PAL step positions advanced them from `FAILED: #2` to `FAILED: #3` / `#4`. Their NTSC builds pass (`blargg_apu_2005` 10 & 11), localizing the gap to a PAL-specific length-counter halt/reload write-vs-half-frame-clock ordering detail adjacent to the frame-counter step model. Left as fail-loud residual pins and recorded in docs/accuracy-ledger.md; closing it is a separate deeper investigation. Tests + docs ------------ Adds seven PAL frame-counter unit tests (step positions, IRQ position, no-IRQ-at-NTSC-position, wrap, 5-step, NTSC-default). Promotes pal_apu 04-08 from residual pins to strict passes; keeps 10/11 as documented residuals. Updates docs/apu-2a03.md, docs/accuracy-ledger.md, docs/STATUS.md, docs/testing-strategy.md to the 8/10 state. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…pal_apu_tests) Close the final two PAL APU accuracy residuals — blargg `pal_apu_tests` `10.len_halt_timing` and `11.len_reload_timing` — by modelling the 2A03's one-step deferral of length-counter halt changes and length reloads relative to the frame sequencer's half-frame length clock. Extends PR #275 from 8/10 to 10/10 pal_apu_tests, with NTSC held byte-identical. Root cause ---------- The length counter applied a `$4000`-bit-5 halt change and a `$4003` length reload IMMEDIATELY, during the CPU's bus write. Because the CPU's bus access runs before the APU's per-cycle `tick_with_external` (which fires the half-frame length clock), a halt/reload write that landed on the exact cycle of a half-frame clock was applied BEFORE that clock — the inverse of silicon, which applies both AFTER. This surfaced only on PAL because the NTSC `blargg_apu_2005` 10/11 ROMs report via a `$6000` protocol they have no PRG-RAM for (a vacuous status==0), whereas the PAL suite decodes the on-screen verdict. PAL reported `FAILED #3` (len_halt: "should be clocked when halted at 16629" — the write-on-clock-cycle case) and `FAILED #4` (len_reload: "reload during clock when ctr = 0 should work"). Mechanism (mirrors TetaNES LengthCounter::reload + Mesen2 _newHaltValue) ----------------------------------------------------------------------- `LengthCounter` gains three deferral fields: * new_halt — latched by `set_halt` on a $4000/$4004/$4008/$400C write; promoted to the effective `halt` in `reload`. * reload_val — pending length load latched by `load` (deferred). * previous_count — snapshot of `count` at load time. `reload()` applies a pending reload only if the post-clock `count` still equals `previous_count` (a same-cycle half-frame clock did not decrement it because it was already zero), then refreshes `halt = new_halt`. The APU calls `reload()` on all four length channels once per CPU cycle in `tick_with_external`, AFTER `handle_frame_events` (the half-frame clock) and BEFORE the mixer samples channel outputs. NTSC byte-identity (sacred) --------------------------- On the common non-coincident write cycle the count is untouched between the write and `reload`, so `count == previous_count` holds and the reload settles in-cycle before the sample — identical to an immediate load; halt does not affect `output()` directly, so its deferral is invisible except at a clock. Only the write-lands-on-the-clock-cycle coincidence the ROMs probe differs. Verified byte-identical: AccuracyCoin 141/141, blargg_apu_2005 11/11, f2_accuracy_audit 6/6, apu_reset 4/4, apu_mixer / apu_test / volume_tests / nestest / visual_regression all unchanged against their pre-change goldens. The snapshot byte layout is unchanged: the deferral scratch fields are not serialized (they resolve within the write cycle), and `read_length` seeds `new_halt = halt` so a restore never spuriously clears a halted counter. pal_apu_tests 10 & 11 promoted from the fail-loud `pal_apu_residual!` pins to `pal_apu_pass!`; the now-unused macro is removed. Docs synced: docs/apu-2a03.md (new §Length halt/reload ordering), docs/accuracy-ledger.md (residual closed), docs/STATUS.md, docs/testing-strategy.md, CHANGELOG.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…0 pal_apu_tests Implement the PAL (2A07) APU frame-counter sequencer step positions, closing five of the seven PAL timing residuals the salvaged screen-reading oracle pinned. The blargg `pal_apu_tests` corpus now scores 8/10 under forced PAL region (was 3/10), with the two remaining failures documented as a bounded, fail-loud residual. Mechanism --------- The 2A03 (NTSC) and 2A07 (PAL) share the same six-step sequencer but divide the CPU clock differently, so the identical quarter/half/IRQ events land at different CPU-cycle counts. `FrameCounter` now carries a `pal: bool` selector, derived from the console `Region` by `Apu::new` (true only for `Region::Pal`; NTSC and Dendy — a PAL-clocked famiclone with an NTSC-period frame counter — keep the NTSC positions). The sequencer step tables are: - PAL 4-step (mode 0): 8313 / 16627 / 24939 / 33252 / 33253 / 33254 (quarter 8313/16627/24939/33253; half 16627/33253; IRQ 33252/33253/33254). - PAL 5-step (mode 1): 8313 / 16627 / 24939 / 41565 / 41566 (quarter 8313/16627/24939/41565; half 16627/41565; no IRQ). These are the canonical Mesen2 `stepCyclesPal` values. The mode-0 terminal three cycles replicate the NTSC IRQ-flag-visibility / `irq_line_active` split verbatim at the PAL positions, preserving the AccuracyCoin Frame-Counter-IRQ Tests I/J/K/L/M semantics for PAL. NTSC byte-identity (sacred constraint) -------------------------------------- The change is strictly region-gated: the `pal == false` branch runs the original NTSC step tables unchanged, and the power-on / snapshot-restore default is NTSC. The `tick` hot path was split into `clock_sequencer` + `four_step` / `five_step` helpers (to stay within the clippy line budget) with no behavioral change to the NTSC arms. Verified byte-identical: - AccuracyCoin 141/141 (100.00%) — unchanged. - `apu_test` 8/8, NTSC `blargg_apu_2005` 11/11, `nestest` 0-diff — unchanged. - APU snapshot format is untouched: `pal` is derived, not persisted; `Apu::restore` re-derives it from the restored region. Residual (honest) ----------------- `10.len_halt_timing` and `11.len_reload_timing` still fail, but the PAL step positions advanced them from `FAILED: #2` to `FAILED: #3` / `#4`. Their NTSC builds pass (`blargg_apu_2005` 10 & 11), localizing the gap to a PAL-specific length-counter halt/reload write-vs-half-frame-clock ordering detail adjacent to the frame-counter step model. Left as fail-loud residual pins and recorded in docs/accuracy-ledger.md; closing it is a separate deeper investigation. Tests + docs ------------ Adds seven PAL frame-counter unit tests (step positions, IRQ position, no-IRQ-at-NTSC-position, wrap, 5-step, NTSC-default). Promotes pal_apu 04-08 from residual pins to strict passes; keeps 10/11 as documented residuals. Updates docs/apu-2a03.md, docs/accuracy-ledger.md, docs/STATUS.md, docs/testing-strategy.md to the 8/10 state. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…pal_apu_tests) Close the final two PAL APU accuracy residuals — blargg `pal_apu_tests` `10.len_halt_timing` and `11.len_reload_timing` — by modelling the 2A03's one-step deferral of length-counter halt changes and length reloads relative to the frame sequencer's half-frame length clock. Extends PR #275 from 8/10 to 10/10 pal_apu_tests, with NTSC held byte-identical. Root cause ---------- The length counter applied a `$4000`-bit-5 halt change and a `$4003` length reload IMMEDIATELY, during the CPU's bus write. Because the CPU's bus access runs before the APU's per-cycle `tick_with_external` (which fires the half-frame length clock), a halt/reload write that landed on the exact cycle of a half-frame clock was applied BEFORE that clock — the inverse of silicon, which applies both AFTER. This surfaced only on PAL because the NTSC `blargg_apu_2005` 10/11 ROMs report via a `$6000` protocol they have no PRG-RAM for (a vacuous status==0), whereas the PAL suite decodes the on-screen verdict. PAL reported `FAILED #3` (len_halt: "should be clocked when halted at 16629" — the write-on-clock-cycle case) and `FAILED #4` (len_reload: "reload during clock when ctr = 0 should work"). Mechanism (mirrors TetaNES LengthCounter::reload + Mesen2 _newHaltValue) ----------------------------------------------------------------------- `LengthCounter` gains three deferral fields: * new_halt — latched by `set_halt` on a $4000/$4004/$4008/$400C write; promoted to the effective `halt` in `reload`. * reload_val — pending length load latched by `load` (deferred). * previous_count — snapshot of `count` at load time. `reload()` applies a pending reload only if the post-clock `count` still equals `previous_count` (a same-cycle half-frame clock did not decrement it because it was already zero), then refreshes `halt = new_halt`. The APU calls `reload()` on all four length channels once per CPU cycle in `tick_with_external`, AFTER `handle_frame_events` (the half-frame clock) and BEFORE the mixer samples channel outputs. NTSC byte-identity (sacred) --------------------------- On the common non-coincident write cycle the count is untouched between the write and `reload`, so `count == previous_count` holds and the reload settles in-cycle before the sample — identical to an immediate load; halt does not affect `output()` directly, so its deferral is invisible except at a clock. Only the write-lands-on-the-clock-cycle coincidence the ROMs probe differs. Verified byte-identical: AccuracyCoin 141/141, blargg_apu_2005 11/11, f2_accuracy_audit 6/6, apu_reset 4/4, apu_mixer / apu_test / volume_tests / nestest / visual_regression all unchanged against their pre-change goldens. The snapshot byte layout is unchanged: the deferral scratch fields are not serialized (they resolve within the write cycle), and `read_length` seeds `new_halt = halt` so a restore never spuriously clears a halted counter. pal_apu_tests 10 & 11 promoted from the fail-loud `pal_apu_residual!` pins to `pal_apu_pass!`; the now-unused macro is removed. Docs synced: docs/apu-2a03.md (new §Length halt/reload ordering), docs/accuracy-ledger.md (residual closed), docs/STATUS.md, docs/testing-strategy.md, CHANGELOG.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…oracle (8/10, v2.1.5) (#275) * wip(pal-apu): salvage orphaned-agent PAL APU oracle work WIP snapshot of the v2.1.5 PAL APU oracle workstream, committed to protect the work after the spawning background agent was orphaned on a session exit. Not yet gate-verified; to be assessed and completed before PR. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(apu): model PAL frame-counter step positions (region-gated); 8/10 pal_apu_tests Implement the PAL (2A07) APU frame-counter sequencer step positions, closing five of the seven PAL timing residuals the salvaged screen-reading oracle pinned. The blargg `pal_apu_tests` corpus now scores 8/10 under forced PAL region (was 3/10), with the two remaining failures documented as a bounded, fail-loud residual. Mechanism --------- The 2A03 (NTSC) and 2A07 (PAL) share the same six-step sequencer but divide the CPU clock differently, so the identical quarter/half/IRQ events land at different CPU-cycle counts. `FrameCounter` now carries a `pal: bool` selector, derived from the console `Region` by `Apu::new` (true only for `Region::Pal`; NTSC and Dendy — a PAL-clocked famiclone with an NTSC-period frame counter — keep the NTSC positions). The sequencer step tables are: - PAL 4-step (mode 0): 8313 / 16627 / 24939 / 33252 / 33253 / 33254 (quarter 8313/16627/24939/33253; half 16627/33253; IRQ 33252/33253/33254). - PAL 5-step (mode 1): 8313 / 16627 / 24939 / 41565 / 41566 (quarter 8313/16627/24939/41565; half 16627/41565; no IRQ). These are the canonical Mesen2 `stepCyclesPal` values. The mode-0 terminal three cycles replicate the NTSC IRQ-flag-visibility / `irq_line_active` split verbatim at the PAL positions, preserving the AccuracyCoin Frame-Counter-IRQ Tests I/J/K/L/M semantics for PAL. NTSC byte-identity (sacred constraint) -------------------------------------- The change is strictly region-gated: the `pal == false` branch runs the original NTSC step tables unchanged, and the power-on / snapshot-restore default is NTSC. The `tick` hot path was split into `clock_sequencer` + `four_step` / `five_step` helpers (to stay within the clippy line budget) with no behavioral change to the NTSC arms. Verified byte-identical: - AccuracyCoin 141/141 (100.00%) — unchanged. - `apu_test` 8/8, NTSC `blargg_apu_2005` 11/11, `nestest` 0-diff — unchanged. - APU snapshot format is untouched: `pal` is derived, not persisted; `Apu::restore` re-derives it from the restored region. Residual (honest) ----------------- `10.len_halt_timing` and `11.len_reload_timing` still fail, but the PAL step positions advanced them from `FAILED: #2` to `FAILED: #3` / `#4`. Their NTSC builds pass (`blargg_apu_2005` 10 & 11), localizing the gap to a PAL-specific length-counter halt/reload write-vs-half-frame-clock ordering detail adjacent to the frame-counter step model. Left as fail-loud residual pins and recorded in docs/accuracy-ledger.md; closing it is a separate deeper investigation. Tests + docs ------------ Adds seven PAL frame-counter unit tests (step positions, IRQ position, no-IRQ-at-NTSC-position, wrap, 5-step, NTSC-default). Promotes pal_apu 04-08 from residual pins to strict passes; keeps 10/11 as documented residuals. Updates docs/apu-2a03.md, docs/accuracy-ledger.md, docs/STATUS.md, docs/testing-strategy.md to the 8/10 state. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(changelog): rewrite the v2.1.5 PAL APU entry to the 8/10 implemented state The salvaged WIP entry described the pre-implementation state (screen-reading oracle wired, 3/10 honest pass, PAL frame counter unmodeled). Rewrite it to record the delivered work: the region-gated PAL (2A07) frame-counter step positions, the resulting 8/10 pass count (04-08 flipped to PASS), the preserved NTSC byte-identity (AccuracyCoin 141/141, apu_test 8/8, blargg_apu_2005 11/11, nestest 0-diff), and the two documented length halt/reload timing residuals (10/11) pinned fail-loud. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(apu): defer length halt/reload ordering; close PAL 10/11 (10/10 pal_apu_tests) Close the final two PAL APU accuracy residuals — blargg `pal_apu_tests` `10.len_halt_timing` and `11.len_reload_timing` — by modelling the 2A03's one-step deferral of length-counter halt changes and length reloads relative to the frame sequencer's half-frame length clock. Extends PR #275 from 8/10 to 10/10 pal_apu_tests, with NTSC held byte-identical. Root cause ---------- The length counter applied a `$4000`-bit-5 halt change and a `$4003` length reload IMMEDIATELY, during the CPU's bus write. Because the CPU's bus access runs before the APU's per-cycle `tick_with_external` (which fires the half-frame length clock), a halt/reload write that landed on the exact cycle of a half-frame clock was applied BEFORE that clock — the inverse of silicon, which applies both AFTER. This surfaced only on PAL because the NTSC `blargg_apu_2005` 10/11 ROMs report via a `$6000` protocol they have no PRG-RAM for (a vacuous status==0), whereas the PAL suite decodes the on-screen verdict. PAL reported `FAILED #3` (len_halt: "should be clocked when halted at 16629" — the write-on-clock-cycle case) and `FAILED #4` (len_reload: "reload during clock when ctr = 0 should work"). Mechanism (mirrors TetaNES LengthCounter::reload + Mesen2 _newHaltValue) ----------------------------------------------------------------------- `LengthCounter` gains three deferral fields: * new_halt — latched by `set_halt` on a $4000/$4004/$4008/$400C write; promoted to the effective `halt` in `reload`. * reload_val — pending length load latched by `load` (deferred). * previous_count — snapshot of `count` at load time. `reload()` applies a pending reload only if the post-clock `count` still equals `previous_count` (a same-cycle half-frame clock did not decrement it because it was already zero), then refreshes `halt = new_halt`. The APU calls `reload()` on all four length channels once per CPU cycle in `tick_with_external`, AFTER `handle_frame_events` (the half-frame clock) and BEFORE the mixer samples channel outputs. NTSC byte-identity (sacred) --------------------------- On the common non-coincident write cycle the count is untouched between the write and `reload`, so `count == previous_count` holds and the reload settles in-cycle before the sample — identical to an immediate load; halt does not affect `output()` directly, so its deferral is invisible except at a clock. Only the write-lands-on-the-clock-cycle coincidence the ROMs probe differs. Verified byte-identical: AccuracyCoin 141/141, blargg_apu_2005 11/11, f2_accuracy_audit 6/6, apu_reset 4/4, apu_mixer / apu_test / volume_tests / nestest / visual_regression all unchanged against their pre-change goldens. The snapshot byte layout is unchanged: the deferral scratch fields are not serialized (they resolve within the write cycle), and `read_length` seeds `new_halt = halt` so a restore never spuriously clears a halted counter. pal_apu_tests 10 & 11 promoted from the fail-loud `pal_apu_residual!` pins to `pal_apu_pass!`; the now-unused macro is removed. Docs synced: docs/apu-2a03.md (new §Length halt/reload ordering), docs/accuracy-ledger.md (residual closed), docs/STATUS.md, docs/testing-strategy.md, CHANGELOG.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(test-harness): neutral pal_apu_pass message + reuse screen decode buffer Address two PR #275 bot-review threads (both behavior-preserving): - **Copilot (pal_apu_tests.rs):** the `pal_apu_pass!` macro's failure message called every ROM a "region-independent APU check", but the macro also covers the PAL frame-counter-timing checks (04-08) and the length halt/reload checks (10-11), for which that claim is false. Reworded to a neutral "PAL APU {name}: expected on-screen PASSED but ROM reported {verdict}" and updated the macro doc to enumerate all three categories it now covers. - **Gemini (nes_runner.rs `decode_screen_text`):** the decoder allocated a fresh `String` per frame and a per-row intermediate `String` (~60 allocs per frame, ~100k+ per multi-hundred-frame run). Refactored to `decode_screen_text_into(nes, &mut String)`: `run_nes_screen` now decodes every frame into ONE reused buffer (`clear`ed each frame, moved into the result at the end). Trailing-space trimming and blank-row dropping are done in place by tracking each row's start offset + last non-space byte and `truncate`-ing back to it (every glyph is ASCII `0x20..=0x7e`, so one byte per char and the offsets are always on a char boundary) — no per-row scratch String. Decoded text is byte-for-byte identical; verified pal_apu_tests still 10/10 with unchanged on-screen verdicts and frame counts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Bumps actions/upload-artifact from 4 to 6.
Release notes
Sourced from actions/upload-artifact's releases.
... (truncated)
Commits
b7c566aMerge pull request #745 from actions/upload-artifact-v6-releasee516bc8docs: correct description of Node.js 24 support in READMEddc45eddocs: update README to correct action name for Node.js 24 support615b319chore: release v6.0.0 for Node.js 24 support017748bMerge pull request #744 from actions/fix-storage-blob38d4c79chore: rebuild dist7d27270chore: add missing license cache files for@actions/core,@actions/io, and mi...5f643d3chore: update license files for@actions/artifact@5.0.1 dependencies1df1684chore: update package-lock.json with@actions/artifact@5.0.1b5b1a91fix: update@actions/artifactto ^5.0.0 for Node.js 24 punycode fixDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot mergewill merge this PR after your CI passes on it@dependabot squash and mergewill squash and merge this PR after your CI passes on it@dependabot cancel mergewill cancel a previously requested merge and block automerging@dependabot reopenwill reopen this PR if it is closed@dependabot closewill close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)