Skip to content

Releases: doublegate/RustyNES

RustyNES v0.8.6

29 Dec 06:41

Choose a tag to compare

RustyNES v0.8.6 - Sub-Cycle Accuracy Improvements (M11 S3-S5)

Hardware accuracy milestone - Implements DMC DMA cycle stealing, open bus behavior, and per-cycle mapper clocking. M11 83% complete.

Highlights

  • DMC DMA Cycle Stealing: CPU stalls 4 cycles per DMC sample fetch (matches hardware)
  • Open Bus Behavior: Tracks data bus state for unmapped memory reads
  • Controller Open Bus: Bits 5-7 properly mixed from open bus with controller data
  • Per-Cycle Mapper Clocking: Mapper IRQs now trigger at cycle-precise timing

What's Changed

DMC DMA Cycle Stealing

The DMC audio channel now properly steals CPU cycles when fetching samples:

// When DMC needs a sample, CPU stalls for 4 cycles
// This affects timing-sensitive code that runs during audio playback
bus.dmc_stall_cycles = 4;

Games that rely on precise timing during DMC playback will now behave correctly.

Open Bus Behavior

Implemented last_bus_value tracking for hardware-accurate unmapped memory reads:

// All memory operations now track the bus state
fn read(&mut self, addr: u16) -> u8 {
    let value = self.internal_read(addr);
    self.last_bus_value = value;  // Track for open bus
    value
}

fn write(&mut self, addr: u16, value: u8) {
    self.last_bus_value = value;  // Track for open bus
    self.internal_write(addr, value);
}

Reads from unmapped addresses return the last value on the data bus, matching NES hardware behavior.

Controller Open Bus

Controller reads now properly mix open bus bits with controller data:

// Controller returns: bits 0-4 from controller, bits 5-7 from open bus
let controller_bits = self.controller.read() & 0x1F;
let open_bus_bits = self.last_bus_value & 0xE0;
controller_bits | open_bus_bits

This fixes games that use bits 5-7 of controller port reads for copy protection or other purposes.

Per-Cycle Mapper Clocking

Mappers are now clocked on every CPU cycle via on_cpu_cycle():

fn on_cpu_cycle(&mut self) {
    // Clock mapper for cycle-accurate IRQ timing
    self.bus.mapper.clock(1);

    // Step PPU 3 dots
    self.bus.ppu.step();
    self.bus.ppu.step();
    self.bus.ppu.step();
}

This improves IRQ timing precision for mappers like MMC3 that use scanline counters.

Quality Metrics

  • Tests: 522+ passing (0 failures, 1 ignored doctest)
  • Blargg Pass Rate: 100% (90/90 tests)
  • New Tests: 2 open bus behavior tests added
  • M11 Progress: Sprints 3-5 complete (83%)

M11 Sub-Cycle Accuracy Milestone

Sprint Focus Status
S1 CPU cycle callback infrastructure Complete
S2 PPU synchronization per memory access Complete
S3 APU/DMC cycle stealing Complete
S4 Open bus behavior Complete
S5 Mapper cycle clocking Complete
S6 Final validation Pending

Technical Specifications

Feature Implementation
DMC DMA Stall 4 cycles per sample fetch
Open Bus Decay Instant (no capacitance simulation)
Controller Open Bus Bits 5-7 from last bus value
Mapper Clock 1 tick per CPU cycle

Installation

Pre-built Binaries

Download the appropriate binary for your platform from the Assets section below.

From Source

git clone https://github.com/doublegate/RustyNES.git
cd RustyNES
cargo build --release

Upgrading from v0.8.5

Recommended update - Significant hardware accuracy improvements. Drop-in replacement with no configuration changes required.


Full Changelog: v0.8.5...v0.8.6

RustyNES v0.8.5

29 Dec 05:58

Choose a tag to compare

RustyNES v0.8.5 - Cycle-Accurate CPU/PPU Synchronization

Major accuracy milestone - Implements cycle-accurate CPU execution with PPU synchronization for precise VBlank timing. M11 Sprints 1 & 2 complete.

Highlights

  • Cycle-Accurate Execution: CPU executes sub-instruction cycles with PPU stepped between memory accesses
  • VBlank Timing Tests: Previously-ignored ppu_02 and ppu_03 tests now enabled with cycle-accurate harness
  • M11 Progress: Sub-Cycle Accuracy Sprints 1 & 2 complete
  • Wayland Fix: Suppressed benign calloop warnings on Linux

What's Changed

Cycle-Accurate CPU/PPU Synchronization (M11 S1-S2)

Implemented true sub-cycle CPU execution where the PPU is stepped after each CPU memory access, not just after complete instructions:

Before (instruction-level):

// Execute full instruction atomically
let cycles = cpu.step(bus);
// Then step PPU for all cycles at once
for _ in 0..(cycles * 3) {
    ppu.step();
}

After (cycle-level):

// CPU emits cycle events during instruction execution
// PPU stepped 3 dots after EACH memory access
cpu.step_cycle_accurate(bus, |bus, cycle_type| {
    bus.ppu.step();
    bus.ppu.step();
    bus.ppu.step();
});

This architecture change enables:

  • Precise $2002 (PPUSTATUS) reads during VBlank transitions
  • Correct sprite 0 hit timing at cycle level
  • Accurate mid-instruction register updates

VBlank Timing Tests Enabled

The previously-ignored timing tests now pass with a cycle-accurate test harness:

  • ppu_02-vbl_set_time: Verifies exact cycle when VBlank flag is set
  • ppu_03-vbl_clear_time: Verifies exact cycle when VBlank flag is cleared

These tests require reading $2002 at the precise cycle boundary - only possible with sub-cycle execution.

Desktop Wayland Fix

Suppressed benign calloop Wayland warnings that appeared on Linux systems. These warnings were cosmetic and did not affect functionality, but cluttered the console output.

Quality Metrics

  • Tests: 519+ passing (0 failures)
  • Blargg Pass Rate: 100% (90/90 tests)
  • VBlank Timing: ppu_02 and ppu_03 now passing
  • M11 Progress: Sprints 1-2 complete (40%)

M11 Sub-Cycle Accuracy Milestone

Sprint Focus Status
S1 CPU cycle callback infrastructure Complete
S2 PPU synchronization per memory access Complete
S3 APU synchronization Pending
S4 Test validation & edge cases Pending
S5 Performance optimization Pending

Installation

Pre-built Binaries

Download the appropriate binary for your platform from the Assets section below.

From Source

git clone https://github.com/doublegate/RustyNES.git
cd RustyNES
cargo build --release

Upgrading from v0.8.4

Recommended update - Significant timing accuracy improvement. Drop-in replacement with no configuration changes required.


Full Changelog: v0.8.4...v0.8.5

RustyNES v0.8.4

29 Dec 04:18

Choose a tag to compare

RustyNES v0.8.4 - CPU/PPU Timing & Version Consistency

Timing accuracy improvement - PPU now stepped before CPU cycle for more accurate $2002 reads at VBlank transitions.

Highlights

  • CPU/PPU Timing: PPU pre-stepping before CPU cycle in tick() for better VBlank timing
  • Version Consistency: Fixed About window and Settings dialogs showing outdated versions
  • Documentation: Fixed clone_mapper doctest by implementing full Clone for mapper Box types

What's Changed

CPU/PPU Timing Improvement

The emulation tick order has been adjusted for more accurate timing:

Before: CPU cycle executed, then PPU stepped 3 dots
After: PPU stepped 3 dots, then CPU cycle executed

This change improves timing accuracy when reading $2002 (PPUSTATUS) at VBlank transitions. Games that poll for VBlank start will see the flag set at the correct cycle.

// New tick order in Console::tick()
fn tick(&mut self) {
    // Step PPU first (3 dots per CPU cycle)
    self.bus.ppu.step();
    self.bus.ppu.step();
    self.bus.ppu.step();

    // Then execute CPU cycle
    self.cpu.step(&mut self.bus);
}

Version Consistency Fix

Fixed version display mismatches across the application:

  • About Window: Was showing 0.8.1, now correctly shows 0.8.4
  • Settings Dialog: Was showing 0.8.2, now correctly shows 0.8.4

Version is now pulled from a single source (env!("CARGO_PKG_VERSION")) throughout the codebase.

Documentation Fix

Fixed the clone_mapper doctest in the Mapper trait by implementing full Clone for mapper Box types. The example now compiles and can be verified at build time.

Quality Metrics

  • Tests: 517+ passing (0 failures, 2 ignored)
  • Blargg Pass Rate: 100% (90/90 tests)
  • Ignored Tests: ppu_02_vbl_set_time, ppu_03_vbl_clear_time (architectural limitation, see notes)

Technical Notes

The 2 ignored PPU timing tests require sub-cycle CPU execution to pass:

  • ppu_02-vbl_set_time: Tests exact cycle when VBlank flag is set
  • ppu_03-vbl_clear_time: Tests exact cycle when VBlank flag is cleared

These tests need the CPU to execute one sub-cycle at a time with PPU stepped between each memory access. This is deferred to Phase 2+ as it requires a major CPU architecture refactor.

Installation

Pre-built Binaries

Download the appropriate binary for your platform from the Assets section below.

From Source

git clone https://github.com/doublegate/RustyNES.git
cd RustyNES
cargo build --release

Upgrading from v0.8.3

This is a drop-in replacement. Timing improvements are automatic.


Full Changelog: v0.8.3...v0.8.4

RustyNES v0.8.3

29 Dec 03:25

Choose a tag to compare

RustyNES v0.8.3 - Critical Rendering Bug Fix

Critical fix for display rendering - Resolves framebuffer issue causing games to display as 4 faint postage-stamp copies instead of proper full-window rendering.

Highlights

  • Critical Bug Fix: Framebuffer now correctly converts NES palette indices to RGB
  • Documentation: Changed 3 doctests from ignore to no_run for compile-time verification
  • Zero Regressions: 516+ tests passing

What's Fixed

Framebuffer Rendering (Critical)

Problem: Games displayed as 4 faint, darkened, postage-stamp sized copies horizontally arranged instead of proper full-window NES output.

Root Cause: The framebuffer was passing raw NES palette indices (0-63) directly as RGBA values. Since palette indices are small numbers (0-63), they produced very dark, nearly black pixels when interpreted as color values.

Solution: Added palette index to RGB conversion using the 64-entry NES_PALETTE lookup table.

// Before (broken)
framebuffer[offset] = palette_index; // 0-63 treated as RGB = dark pixels

// After (fixed)
let (r, g, b) = NES_PALETTE[palette_index as usize];
framebuffer[offset] = r;
framebuffer[offset + 1] = g;
framebuffer[offset + 2] = b;
framebuffer[offset + 3] = 255; // Alpha

Result: Proper full-window NES rendering with correct color palette.

Documentation Improvements

Changed 3 doctests from ignore to no_run for compile-time verification:

  • lib.rs (rustynes-mappers): Complete example with error handling
  • rom.rs (rustynes-mappers): Rom::load with proper error handling pattern

This ensures documentation examples are verified at compile time even if they cannot execute in the test environment.

Quality Metrics

  • Tests: 516+ passing (0 failures)
  • Blargg Pass Rate: 100% (90/90 tests)
  • Zero Regressions: All emulation accuracy preserved

Installation

Pre-built Binaries

Download the appropriate binary for your platform from the Assets section below.

From Source

git clone https://github.com/doublegate/RustyNES.git
cd RustyNES
cargo build --release

Upgrading from v0.8.2

Strongly recommended update - This fixes a critical rendering issue that affected all games.


Full Changelog: v0.8.2...v0.8.3

RustyNES v0.8.2

29 Dec 02:47

Choose a tag to compare

RustyNES v0.8.2 - M10 Final Polish Sprint 1 Complete

UI/UX improvements release - Comprehensive desktop GUI polish with themes, status bar, keyboard shortcuts, and modal dialogs.

Highlights

  • Theme Support: Light/Dark/System themes with persistence and real-time switching
  • Status Bar: FPS counter, ROM name display, color-coded status messages
  • Tabbed Settings: Video/Audio/Input/Advanced tabs with tooltips
  • Keyboard Shortcuts: Standard shortcuts for common operations
  • Modal Dialogs: Welcome screen, error dialogs, confirmation prompts

What's Changed

Theme Support

  • Light, Dark, and System theme options
  • Persisted to configuration file
  • Real-time theme switching without restart

Status Bar

  • FPS counter with 500ms update interval
  • Current ROM name display
  • Color-coded status messages with 3-second auto-expiry

Tabbed Settings Dialog

Organized settings into logical categories:

  • Video: Scaling mode, aspect ratio, VSync
  • Audio: Volume, sample rate, buffer size
  • Input: Controller mapping, keyboard bindings
  • Advanced: Debug options, timing settings

All settings include comprehensive tooltips explaining their purpose.

Keyboard Shortcuts

Shortcut Action
Ctrl+O Open ROM
Ctrl+P Pause/Resume
Ctrl+R Reset
Ctrl+Q Quit
F1 CPU Debug Window
F2 PPU Debug Window
F3 Memory Viewer
M Mute Audio

Modal Dialogs

  • Welcome screen for first-time users
  • Error dialogs with descriptive messages
  • Confirmation prompts for destructive actions
  • Help window (F1 context-sensitive)

Visual Polish

  • Contextual tooltips throughout UI
  • Organized menus with separators
  • Consistent styling across all windows

Quality Metrics

  • Tests: 508+ passing (0 failures)
  • Blargg Pass Rate: 100% (90/90 tests)
  • M10 Progress: Sprint 1 complete (50% total)
  • Zero Regressions: All emulation accuracy preserved

Installation

Pre-built Binaries

Download the appropriate binary for your platform from the Assets section below.

From Source

git clone https://github.com/doublegate/RustyNES.git
cd RustyNES
cargo build --release

Upgrading from v0.8.1

This is a drop-in replacement. New UI features are available immediately.


Full Changelog: v0.8.1...v0.8.2

RustyNES v0.8.1

28 Dec 23:09

Choose a tag to compare

RustyNES v0.8.1 - M9 Known Issues Resolution (85% Complete)

Performance optimization release - Adds inline hints to CPU and PPU hot paths for improved emulation speed.

Highlights

  • CPU Performance: #[inline] hints on step(), execute_opcode(), handle_nmi(), handle_irq()
  • PPU Performance: #[inline] hints on step(), step_with_chr()
  • M9 Progress: Sprints 1-3 complete, Sprint 4 (bug fixes & polish) pending

What's Changed

CPU Inline Hints

Added #[inline] attributes to critical CPU execution paths:

  • step() - Main execution loop
  • execute_opcode() - Opcode dispatch
  • handle_nmi() - Non-maskable interrupt
  • handle_irq() - Maskable interrupt

PPU Inline Hints

Added #[inline] attributes to PPU rendering hot paths:

  • step() - Main PPU cycle
  • step_with_chr() - CHR-ROM variant

M9 Sprint Status

Sprint Focus Status
S1 Audio improvements Complete
S2 PPU edge cases Complete
S3 Performance optimization Complete
S4 Bug fixes & polish Pending

Quality Metrics

  • Tests: 508+ passing (0 failures)
  • Blargg Pass Rate: 100% (90/90 tests)
  • Inline Annotations: 68+ across CPU/PPU crates
  • Zero Regressions: All previous functionality preserved

Installation

Pre-built Binaries

Download the appropriate binary for your platform from the Assets section below.

From Source

git clone https://github.com/doublegate/RustyNES.git
cd RustyNES
cargo build --release

Upgrading from v0.8.0

This is a drop-in replacement. No configuration changes required.


Full Changelog: v0.8.0...v0.8.1

RustyNES v0.8.0

28 Dec 22:34

Choose a tag to compare

RustyNES v0.8.0 - Rust 2024 Edition & Dependency Modernization

Technology stack upgrade - Adopts Rust 2024 Edition and modernizes all major dependencies for long-term maintainability.

Highlights

  • Rust 2024 Edition: MSRV set to 1.88 for latest language features
  • Dependency Modernization: Major version upgrades across GUI, audio, and config crates
  • Performance Optimizations: Inline hints and buffer reuse patterns for reduced allocations
  • Audio Resampling: High-quality rubato integration for flexible sample rate support

What's Changed

Rust 2024 Edition

  • Updated all workspace and crate configurations to Rust 2024 Edition
  • MSRV (Minimum Supported Rust Version) set to 1.88
  • Benefits from latest compiler optimizations and language features

Dependency Upgrades

Dependency Previous New Purpose
eframe 0.29 0.33 Window + egui + OpenGL
egui 0.29 0.33 Immediate mode GUI
cpal 0.15 0.16 Audio device I/O
rubato - 0.16 Audio resampling (new)
ron 0.8 0.12 Configuration format
thiserror 1.x 2.0 Error handling

Performance Optimizations

  • Added #[inline] hints on critical audio/rendering paths
  • Buffer reuse patterns for reduced memory allocations
  • PPU edge case handling improvements

Audio Improvements (M9 S1-S2)

  • Two-stage decimation via rubato: 1.79MHz -> 192kHz -> 48kHz
  • A/V sync with adaptive speed adjustment (0.99x-1.01x)
  • Dynamic buffer sizing (2048-16384 samples)
  • Hardware-accurate mixer with NES filter chain

PPU Edge Cases (M9 S2)

  • Sprite overflow bug matching hardware false positives/negatives
  • Palette RAM mirroring at $3F10/$3F14/$3F18/$3F1C
  • Mid-scanline write detection for split-screen effects

Quality Metrics

  • Tests: 508+ passing (0 failures)
  • Blargg Pass Rate: 100% (90/90 tests)
  • Zero Regressions: All previous functionality preserved

Installation

Pre-built Binaries

Download the appropriate binary for your platform from the Assets section below.

From Source

git clone https://github.com/doublegate/RustyNES.git
cd RustyNES
cargo build --release

Upgrading from v0.7.1

This is a drop-in replacement. Configuration files are automatically migrated to the new RON format version.


Full Changelog: v0.7.1...v0.8.0

RustyNES v0.7.1 - Desktop Cycle-Accurate Execution Fix

25 Dec 04:48

Choose a tag to compare

RustyNES v0.7.1 - Desktop Cycle-Accurate Execution Fix

Critical fix for desktop application - Now uses the same cycle-accurate execution mode as the 100%-passing test suite.

What's Fixed

Desktop Integration (Critical)

The desktop application was using step_frame() which batches entire CPU instructions before synchronizing PPU and APU. This caused:

  • Mid-frame register updates to be delayed
  • Timing-sensitive effects (sprite 0 hit, scroll splits) to render incorrectly
  • Audio/video synchronization issues

Solution: Changed to step_frame_accurate() which executes exactly:

  • 1 CPU cycle
  • 3 PPU dots (maintaining 3:1 ratio)
  • 1 APU step

The desktop now matches the execution behavior that achieves 100% Blargg test pass rate.

Sample Rate Configuration

New APIs allow configuring APU sample rate to match audio device:

// Create console with specific sample rate
let console = Console::with_sample_rate(mapper, 44100);

// Or use Bus directly
let bus = Bus::with_sample_rate(mapper, 48000);

Benefits:

  • APU generates samples at exact audio device rate
  • Eliminates pitch shifting from sample rate mismatch
  • Proper audio/video synchronization

Technical Comparison

Execution Mode step_frame() step_frame_accurate()
CPU Full instruction 1 cycle
PPU Batch sync after 3 dots per CPU cycle
APU Batch sync after 1 step per CPU cycle
Mid-frame updates Delayed Immediate
Test suite N/A 100% pass rate

Files Changed

  • crates/rustynes-core/src/bus.rs - Added with_sample_rate() constructor
  • crates/rustynes-core/src/console.rs - Added with_sample_rate() constructor
  • crates/rustynes-desktop/src/app.rs - Changed to step_frame_accurate()

Installation

Pre-built Binaries

Download the appropriate binary for your platform from the Assets section below.

From Source

git clone https://github.com/doublegate/RustyNES.git
cd RustyNES
cargo build --release

Upgrading from v0.7.0

This is a drop-in replacement. No configuration changes required.
The fix is automatic - the desktop will now use cycle-accurate execution.


Full Changelog: v0.7.0...v0.7.1

RustyNES v0.7.0 - Milestone 8 Complete (100% Blargg Pass Rate)

24 Dec 20:48
9775067

Choose a tag to compare

RustyNES v0.7.0 - Milestone 8 Complete

100% Blargg Test Suite Pass Rate - All 90 accuracy tests passing!

Release Highlights

🎮 Cycle-Accurate Emulation - Every CPU cycle, PPU dot, and APU sample timed to hardware specifications.

📊 Test Validation

Suite Pass Rate Tests
Blargg CPU 100% 22/22
Blargg PPU 100% 25/25
Blargg APU 100% 15/15
Mappers 100% 28/28
Total 100% 500+

What's New in v0.7.0

CPU Timing Improvements

  • cpu_dummy_reads.nes: Cycle-accurate dummy read timing for implied addressing modes
  • cpu_interrupts.nes: Proper NMI hijacking during BRK instruction execution
  • RTI instruction I flag restoration (no delay like CLI/SEI)
  • prev_irq_inhibit mechanism for correct IRQ acknowledgment timing

PPU Accuracy Enhancements

  • Open bus emulation with proper decay counter
  • OAM attribute byte masking (bits 2-4 don't exist in 2C02 hardware)
  • Odd frame skip at scanline 261, dot 339 (pre-render line)
  • VBlank/NMI timing precision with flag read race conditions

APU Audio Fidelity

  • Frame counter immediate clocking on mode switch
  • +1 cycle timing correction across all frame events
  • DMC 2-stage sample pipeline (shift register + buffer)
  • Hardware-accurate non-linear mixer using NESdev TND formula
  • $4015 IRQ acknowledgment (frame counter only, not DMC)

Mapper Validation

  • All 5 core mappers verified: NROM (0), MMC1 (1), UxROM (2), CNROM (3), MMC3 (4)
  • 28/28 mapper integration tests passing

Technical Documentation

New comprehensive documentation added:

  • docs/testing/MILESTONE_8_TEST_ROM_FIXES.md - 800+ line technical analysis
    • Sprint-by-sprint breakdown of all fixes
    • Code examples and hardware behavior explanations
    • Architecture insights discovered during development

Metrics Comparison

Metric v0.6.0 v0.7.0 Improvement
Total Tests 429 500+ +71 tests
Blargg CPU 65% 100% +35%
Blargg PPU 100% 100% Maintained
Blargg APU 100% 100% Maintained

Installation

Pre-built Binaries

Download the appropriate binary for your platform from the Assets section below.

From Source

git clone https://github.com/doublegate/RustyNES.git
cd RustyNES
cargo build --release

Usage

# Run with ROM
rustynes-desktop path/to/game.nes

# Run without arguments for file picker
rustynes-desktop

Requirements

  • Rust 1.75+ (for building from source)
  • GPU with Vulkan/Metal/DX12 support (wgpu backend)
  • Audio output device (cpal backend)

What's Next (Phase 1.5 Continuation)

  • M9: Performance & Polish
  • M10: Documentation and v1.0-alpha preparation
  • Phase 2: RetroAchievements, netplay, TAS tools, Lua scripting

Full Changelog: v0.6.0...v0.7.0

v0.6.0 - Accuracy Improvements (Milestone 7 Complete)

20 Dec 09:03

Choose a tag to compare

RustyNES v0.6.0 - Accuracy Improvements

Phase 1.5 Stabilization - First Milestone Complete
Released: December 20, 2025

Highlights

  • APU frame counter precision: Fixed 4-step mode timing (22371→22372 cycles)
  • Hardware-accurate audio mixer: Non-linear TND formula matching NESdev reference
  • OAM DMA cycle precision: 513 cycles (even CPU start) vs 514 cycles (odd CPU start)
  • CPU cycle parity tracking for accurate DMA alignment
  • 429 tests passing with 0 failures, 6 ignored (valid architectural reasons)

M7 Sprint 1: CPU Accuracy

  • All 256 opcodes verified against nestest.nes golden log
  • Page boundary crossing timing accuracy confirmed
  • Unofficial opcode cycle counts validated
  • Interrupt timing precision verified

M7 Sprint 2: PPU Accuracy

  • VBlank/NMI timing functional with flag read/race condition handling
  • Sprite 0 hit detection working (2/2 basic tests passing)
  • Attribute shift register verification complete
  • Palette RAM mirroring edge cases handled

M7 Sprint 3: APU Accuracy

  • Frame counter precision fixed: 4-step mode quarter frame at cycle 22372 (was 22371)
  • Hardware-accurate non-linear mixer: NESdev TND formula implemented
  • Triangle linear counter timing verified
  • Mixer output validated against reference implementation

M7 Sprint 4: Timing & Synchronization

  • OAM DMA cycle precision: 513 cycles (even CPU start) vs 514 cycles (odd CPU start)
  • CPU cycle parity tracking for accurate DMA alignment
  • CPU/PPU synchronization verified
  • Bus timing accuracy confirmed

Technical Specifications

Specification Value
APU Frame Counter (4-step) Cycles 7457, 14913, 22372, 29830
TND Mixer Formula 159.79 / (100 + 1 / (triangle/8227 + noise/12241 + dmc/22638))
OAM DMA Timing 513 + if (cpu_cycles % 2) == 1 { 1 } else { 0 }

Quality Metrics

  • Tests passing: 429
  • Test failures: 0
  • Tests ignored: 6 (valid architectural reasons)
  • Regressions: Zero from v0.5.0

Deferred to M8+

  • Cycle-by-cycle CPU execution (architectural refactor for ±2 cycle PPU precision)
  • DMC DMA cycle stealing conflicts
  • Additional sprite 0 hit edge cases

What's Next

M8: Test ROM Validation - Target 95%+ pass rate on blargg test suites


Full Changelog: https://github.com/doublegate/RustyNES/blob/main/CHANGELOG.md