Skip to content

Latest commit

 

History

History
2502 lines (1866 loc) · 88.4 KB

File metadata and controls

2502 lines (1866 loc) · 88.4 KB

Changelog

All notable changes to RustyNES will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

No unreleased changes.


[0.8.6] - 2025-12-29 - Sub-Cycle Accuracy Improvements

Status: Phase 1.5 Stabilization - M11 Sub-Cycle Accuracy (Sprints 3-5 Complete, 83%)

This release implements critical sub-cycle accuracy features including DMC DMA cycle stealing, NES open bus behavior, and per-CPU-cycle mapper clocking.

Highlights

  • DMC DMA Cycle Stealing: Proper CPU stall handling during DMC sample fetches
  • NES Open Bus Behavior: last_bus_value tracking for hardware-accurate unmapped reads
  • Controller Open Bus: Bits 5-7 correctly mixed from open bus in controller reads
  • Per-Cycle Mapper Clocking: mapper.clock(1) in on_cpu_cycle() for IRQ accuracy
  • Test Suite: 522+ tests passing (0 failures, 1 ignored doctest, 2 new tests)
  • 100% Blargg Pass Rate: All 90/90 Blargg tests continue to pass

Added

DMC DMA Cycle Stealing (Sprint 3)

  • New Field: dmc_stall_cycles in Bus struct tracks pending CPU stalls
  • Purpose: DMC sample fetches steal 4 CPU cycles per sample
  • Implementation: CPU halted during stalls while PPU/APU/mapper continue running
  • Method: take_dmc_stall_cycles() for Console integration
  • Console Integration: tick() handles stalls with proper component stepping

NES Open Bus Behavior (Sprint 4)

  • New Field: last_bus_value in Bus struct tracks last value on data bus
  • Purpose: NES hardware returns last bus value for unmapped reads (not 0)
  • Unmapped Regions: $4018-$401F and $4020-$5FFF return open bus value
  • Controller Reads: $4016/$4017 mix bits 5-7 from open bus with controller data bits 0-4
  • Writes: Also update bus value (hardware-accurate behavior)
  • New Tests: test_open_bus_behavior(), test_controller_open_bus_bits()

Per-Cycle Mapper Clocking (Sprint 5)

  • New Call: self.mapper.clock(1) in on_cpu_cycle() callback
  • Purpose: Mappers clocked once per CPU cycle for cycle-accurate timing
  • Critical For: VRC cycle-based IRQs, MMC3 A12 detection
  • Effect: Maintains sub-cycle accuracy for all mapper types

Fixed

  • Controller reads now correctly mix bits 5-7 from open bus with controller data
  • Unmapped regions return last bus value instead of 0 (hardware-accurate)
  • DMC sample fetches now properly stall CPU while other components continue

Changed

  • Bus struct tracks last_bus_value for open bus emulation
  • Bus struct tracks dmc_stall_cycles for DMC DMA handling
  • Console tick() handles DMC stalls with proper PPU/APU/mapper stepping
  • Mappers clocked via on_cpu_cycle() callback for sub-cycle accuracy
  • Consolidated unmapped read ranges for cleaner match arm

Technical Specifications

DMC DMA Stall Handling:

// Bus provides stall cycle count
pub fn take_dmc_stall_cycles(&mut self) -> u8;

// Console handles stalls
if stall_cycles > 0 {
    for _ in 0..stall_cycles {
        self.bus.step_ppu_apu_mapper();
    }
}

Open Bus Implementation:

// Track last bus value
self.last_bus_value = value;

// Unmapped reads return open bus
0x4018..=0x5FFF => self.last_bus_value,

// Controller reads mix bits
0x4016 => self.controller1.read() | (self.last_bus_value & 0xE0),

Mapper Clocking:

fn on_cpu_cycle(&mut self) {
    self.mapper.clock(1);
    // PPU stepping...
}

Test Results:

  • Total tests: 522+ passing
  • Failures: 0
  • Ignored: 1 (CpuBus doctest for specialized implementation)
  • New tests: 2 (open bus behavior validation)
  • Blargg pass rate: 100% (90/90 tests)

M11 Progress:

  • Sprint 1: CPU Cycle-by-Cycle Refactor - COMPLETE
  • Sprint 2: PPU Synchronization Integration - COMPLETE
  • Sprint 3: APU Precision (DMC DMA) - COMPLETE
  • Sprint 4: Bus/DMA Integration - COMPLETE
  • Sprint 5: Mapper Accuracy - COMPLETE
  • Sprint 6: Testing & Validation - PENDING

Quality Metrics

  • cargo clippy: PASSING (zero warnings)
  • cargo fmt: PASSING
  • cargo test: 522+ tests passing
  • cargo build --release: SUCCESS
  • Zero unsafe code maintained

What's Next

  • M11 Sprint 6: Testing & Validation with additional test ROMs
  • M10 Sprint 2: Documentation updates
  • M10 Sprint 3: Release preparation

[0.8.5] - 2025-12-29 - Cycle-Accurate CPU/PPU Synchronization

Status: Phase 1.5 Stabilization - M11 Sub-Cycle Accuracy (Sprints 1 & 2 Complete)

This release implements true cycle-accurate CPU/PPU synchronization, enabling VBlank timing tests to pass with zero-cycle accuracy.

Highlights

  • Cycle-Accurate Synchronization: CpuBus trait with on_cpu_cycle() callback for PPU stepping
  • VBlank Timing Tests: Now pass with ±0 cycle accuracy (previously failed with ±51 and ±10 cycles)
  • cpu.tick() Method: Cycle-by-cycle CPU execution for sub-instruction timing precision
  • Test Suite: 520+ tests passing (0 failures, 1 ignored doctest)
  • 100% Blargg Pass Rate: All 90/90 Blargg tests continue to pass

Added

CpuBus Trait for Cycle-Accurate Callbacks

  • New Trait: CpuBus extends Bus with on_cpu_cycle() callback
  • Purpose: Allows PPU to be stepped before each CPU memory access
  • Implementation: PPU stepped 3 dots per CPU cycle (NTSC 3:1 ratio)
  • NMI Handling: Captured during callback, delivered via cpu.trigger_nmi()

cpu.tick() Cycle-by-Cycle Execution

  • New Method: cpu.tick(&mut bus) executes one CPU cycle
  • State Machine: CPU now exposes internal cycle state for precise timing
  • Use Case: Enables VBlank timing tests that require sub-instruction accuracy

Fixed

VBlank Timing Tests

  • ppu_02-vbl_set_time: Was ±51 cycles off, now exact (0 cycles)
  • ppu_03-vbl_clear_time: Was ±10 cycles off, now exact (0 cycles)
  • Root Cause: PPU was only stepped after full CPU instructions completed
  • Solution: Step PPU 3 dots BEFORE each CPU memory access via callback

Changed

Test Harness Architecture

  • Updated: Test harness uses CpuBus for cycle-accurate validation
  • Benefit: Tests can now verify timing at individual CPU cycle granularity
  • Compatibility: Existing tests continue to work with Bus trait

Technical Specifications

CpuBus Callback Model:

pub trait CpuBus: Bus {
    /// Called before each CPU cycle.
    /// PPU should be stepped 3 dots per call.
    fn on_cpu_cycle(&mut self) {
        // Default: no-op for backwards compatibility
    }
}

Test Results:

  • Total tests: 520+ passing
  • Failures: 0
  • Ignored: 1 (CpuBus doctest for specialized implementation)
  • Blargg pass rate: 100% (90/90 tests)

Timing Model:

  • PPU runs 3 dots per CPU cycle (5.369318 MHz / 1.789773 MHz)
  • on_cpu_cycle() called before CPU executes memory access
  • NMI signal captured during callback and queued for delivery

Quality Metrics

  • cargo clippy: PASSING (zero warnings)
  • cargo fmt: PASSING
  • cargo test: 520+ tests passing
  • cargo build --release: SUCCESS
  • Zero unsafe code maintained

What's Next

  • M11 Sprint 3: Validate timing with additional test ROMs
  • M11 Sprint 4: Performance optimization for cycle-accurate mode
  • M10 Sprint 2: Documentation updates
  • M10 Sprint 3: Release preparation

[0.8.4] - 2025-12-28 - CPU/PPU Timing & Version Consistency

Status: Phase 1.5 Stabilization - Timing Improvements & Bug Fixes

This release improves CPU/PPU timing accuracy and fixes version consistency issues in the desktop GUI.

Highlights

  • CPU/PPU Timing: PPU now stepped BEFORE CPU cycle in tick() for accurate $2002 reads at VBlank boundary
  • Version Consistency: Fixed About window and Settings showing outdated version numbers
  • Documentation: Fixed clone_mapper doctest by implementing full Clone for mapper Box types
  • Test Suite: 517+ tests passing (0 failures, 2 ignored for known architectural limitations)
  • 100% Blargg Pass Rate: All 90/90 Blargg tests continue to pass

Fixed

CPU/PPU Timing Improvement

  • Issue: VBlank flag reads at exact CPU-PPU boundary could be off by one cycle
  • Root Cause: PPU was stepped AFTER CPU cycle, meaning reads happening at exact VBlank boundary would miss the flag set
  • Solution: Reordered tick() to step PPU 3 dots BEFORE each CPU cycle
  • Effect: More accurate $2002 status register reads at frame boundaries
  • Trade-off: 2 VBlank timing tests remain ignored (require full cycle-by-cycle CPU refactor for sub-instruction timing)

Version Consistency Bug

  • Issue: About window showed "Version 0.8.1", Settings showed "Version: 0.8.2" while CLI showed correct version
  • Root Cause: Hardcoded version strings in gui/mod.rs and gui/settings.rs were not updated during previous releases
  • Solution: Updated all version strings to 0.8.4 across:
    • gui/mod.rs: About window
    • gui/settings.rs: Settings dialog
    • main.rs: CLI --version and startup log
    • Cargo.toml files: Workspace and desktop package

Documentation Fix

  • Issue: clone_mapper doctest was ignored due to missing Clone implementation
  • Solution: Implemented proper Clone trait for BoxedMapper types
  • Effect: Doctest now compiles and verifies API correctness

Changed

Console tick() Reordering

// Before (PPU stepped after CPU):
pub fn tick(&mut self) {
    self.cpu.step(&mut self.bus);
    for _ in 0..3 {
        self.ppu.step(&mut self.chr_bus);
    }
}

// After (PPU stepped before CPU for accurate reads):
pub fn tick(&mut self) {
    // Step PPU first - ensures $2002 reads see correct VBlank state
    for _ in 0..3 {
        self.ppu.step(&mut self.chr_bus);
    }
    self.cpu.step(&mut self.bus);
}

Technical Specifications

Test Results:

  • Total tests: 517+ passing
  • Failures: 0
  • Ignored: 2 (VBlank timing tests requiring cycle-by-cycle CPU)
  • Blargg pass rate: 100% (90/90 tests)

Timing Model:

  • PPU runs 3 dots per CPU cycle (5.369318 MHz / 1.789773 MHz)
  • PPU stepped first ensures register reads see current PPU state
  • VBlank flag set at PPU cycle 1 of scanline 241

Quality Metrics

  • cargo clippy: PASSING (zero warnings)
  • cargo fmt: PASSING
  • cargo test: 517+ tests passing
  • cargo build --release: SUCCESS
  • Zero unsafe code maintained

What's Next

  • M10-S2: Documentation (user guide, API docs, developer guide)
  • M10-S3: Release preparation (testing, binaries, v0.9.0/v1.0.0-alpha.1)

[0.8.3] - 2025-12-28 - Critical Rendering Bug Fix

Status: Phase 1.5 Stabilization - Critical Bug Fix Release

This release fixes a critical framebuffer rendering bug and improves documentation quality.

Highlights

  • Critical Rendering Fix: Fixed framebuffer display that was showing "4 faint postage stamp copies" artifact
  • Palette Index to RGB Conversion: NES palette indices (0-63) now correctly converted to RGB colors
  • Documentation Improvements: Changed 3 doctests from ignore to no_run for compile-time verification
  • Zero Regressions: 516+ tests passing, 100% Blargg pass rate maintained

Fixed

Critical Rendering Bug (dcb0185)

  • Root Cause: Framebuffer was passing raw NES palette indices (0-63) directly as RGBA values instead of converting them to proper RGB colors using the NES_PALETTE constant
  • Solution: Added palette index to RGB conversion in update_framebuffer() function using 64-entry NES_PALETTE lookup table
  • Effect: Game display now renders correctly with proper colors, filling the window as expected
  • Before: Display showed 4 faint, darkened, postage-stamp sized copies horizontally
  • After: Proper full-window NES rendering with correct color palette

Code Details

// Before (incorrect - passing raw palette index as RGB):
let color = self.emulator.framebuffer()[i];
frame[i * 4] = color;     // Palette index 0-63 misused as R
frame[i * 4 + 1] = color; // Palette index 0-63 misused as G
frame[i * 4 + 2] = color; // Palette index 0-63 misused as B

// After (correct - convert palette index to RGB):
let palette_index = self.emulator.framebuffer()[i] as usize;
let (r, g, b) = NES_PALETTE[palette_index & 0x3F]; // 64-entry lookup
frame[i * 4] = r;
frame[i * 4 + 1] = g;
frame[i * 4 + 2] = b;

Changed

Documentation Improvements (eac16cf)

  • lib.rs (rustynes-mappers): Changed doctest from ignore to no_run with complete example including error handling
  • rom.rs (rustynes-mappers): Changed Rom::load doctest from ignore to no_run with proper error handling pattern
  • Effect: Doctests now compile-checked during cargo test while still not requiring actual ROM files at runtime

Technical Specifications

NES Palette Constant:

pub const NES_PALETTE: [(u8, u8, u8); 64] = [
    (0x62, 0x62, 0x62), // $00: Gray
    (0x00, 0x1F, 0xB2), // $01: Blue
    // ... 64 total RGB entries for NES color palette
];

Test Results:

  • Total tests: 516+ passing
  • Failures: 0
  • Ignored: 0
  • Blargg pass rate: 100% (90/90 tests)

Quality Metrics

  • cargo clippy: PASSING (zero warnings)
  • cargo fmt: PASSING
  • cargo test: 516+ tests passing
  • cargo build --release: SUCCESS
  • Zero unsafe code maintained

What's Next

  • M10-S2: Documentation (user guide, API docs, developer guide)
  • M10-S3: Release preparation (testing, binaries, v0.9.0/v1.0.0-alpha.1)

[0.8.2] - 2025-12-28 - M10-S1 UI/UX Improvements

Status: Phase 1.5 Stabilization - M10 Sprint 1 Complete (UI/UX Polish)

This release completes M10-S1 (UI/UX Improvements), delivering comprehensive desktop GUI polish including theme support, status bar, tabbed settings dialog, keyboard shortcuts, modal dialogs, and visual feedback enhancements.

Highlights

  • Theme Support: Light/Dark/System themes with persistence and real-time switching
  • Status Bar: FPS counter, ROM name display, color-coded status messages with auto-expiry
  • Tabbed Settings Dialog: Video/Audio/Input/Advanced tabs with comprehensive tooltips
  • Keyboard Shortcuts: Ctrl+O/P/R/Q, F1-F3, M, Escape with consistent behavior
  • Modal Dialogs: Welcome screen, error dialogs, confirmation prompts, help window
  • Visual Feedback: Tooltips throughout UI, organized menus with separators
  • Zero Regressions: 508+ tests passing, 100% Blargg pass rate maintained

Added

Theme Support (M10-S1 Task 2)

  • Light/Dark/System Themes: Three theme options with egui Visuals API integration
  • Theme Persistence: Theme preference saved to RON configuration
  • Real-time Switching: Theme changes apply immediately via ctx.set_visuals()
  • System Theme Detection: Follows OS dark mode preference when set to "System"

Status Bar (M10-S1 Task 1)

  • FPS Counter: Real-time frame rate display updated every 500ms
  • ROM Name Display: Shows loaded ROM filename in status bar
  • Status Messages: Color-coded messages (green=success, yellow=warning, red=error)
  • Auto-expiry: Status messages automatically clear after 3 seconds
  • Responsive Layout: Status bar adapts to window width

Tabbed Settings Dialog (M10-S1 Task 3)

  • Video Tab: Theme selection, window scale (1-8x), fullscreen, VSync, 8:7 PAR, FPS counter
  • Audio Tab: Mute toggle, volume slider (0-100%), sample rate, buffer size selection
  • Input Tab: Player 1/2 keyboard bindings in collapsible sections with reset buttons
  • Advanced Tab: Debug options, recent ROMs management, application info
  • Save/Reset Buttons: Save to disk and reset to defaults functionality
  • Comprehensive Tooltips: Every setting has contextual help text

Keyboard Shortcuts (M10-S1 Task 5)

  • File Operations: Ctrl+O (Open ROM), Ctrl+Q (Quit)
  • Emulation Control: Ctrl+P (Pause/Resume), Ctrl+R (Reset), F2 (Reset alternate)
  • Debug Windows: F1 (CPU), F2 (PPU), F3 (APU) debug window toggles
  • Audio: M (Mute toggle)
  • Navigation: Escape (Close dialogs/menus)

Modal Dialogs (M10-S1 Task 4b)

  • Welcome Screen: First-run experience with quick start guide (tracks first_run in config)
  • Error Dialogs: User-friendly error messages via egui::Modal
  • Confirmation Prompts: Destructive action confirmations
  • Help Window: Keyboard shortcut reference accessible via Help menu

Visual Feedback (M10-S1 Task 4a)

  • Tooltips: Contextual help on all interactive elements
  • Menu Organization: Logical grouping with separators in File/Emulation/Options menus
  • Loading States: Visual feedback during ROM loading operations
  • Hover Effects: Clear indication of interactive elements

Changed

Code Quality Improvements

  • Guard Pattern Refactoring: Simplified input handlers using early returns
  • Function Signatures: Improved borrowing patterns for settings renderers
  • Removed Unused Code: Cleaned up Power Cycle menu item, unused imports

Configuration Updates

  • AppTheme Enum: New theme configuration type with Light/Dark/System variants
  • first_run Field: Tracks first launch for welcome screen display
  • Theme Persistence: Theme preference saved and loaded with configuration

Technical Specifications

M10 Sprint Status:

Sprint Status Core Tasks
S0: Dependency Upgrade COMPLETE Rust 2024, eframe 0.33, cpal 0.16
S1: UI/UX Improvements COMPLETE Themes, status bar, settings, shortcuts
S2: Documentation PENDING User guide, API docs, developer guide
S3: Release Preparation PENDING Testing, binaries, release notes

Test Results:

  • Total tests: 508+ passing
  • Failures: 0
  • Ignored: 0
  • Blargg pass rate: 100% (90/90 tests)

UI Components Added:

  • Theme switcher in Video settings tab
  • Status bar with FPS, ROM name, and status messages
  • Tabbed settings dialog (4 tabs)
  • 8+ keyboard shortcuts
  • Welcome screen modal
  • Help window with shortcut reference

Quality Metrics

  • cargo clippy: PASSING (zero warnings)
  • cargo fmt: PASSING
  • cargo test: 508+ tests passing
  • cargo build --release: SUCCESS
  • Zero unsafe code maintained

What's Next

  • Sprint 2: Documentation (user guide, API docs, developer guide)
  • Sprint 3: Release preparation (testing, binaries, v0.9.0/v1.0.0-alpha.1)
  • M10 Completion: Final polish and Phase 1.5 completion

[0.8.1] - 2025-12-28 - M9 Known Issues Resolution (85% Complete)

Status: Phase 1.5 Stabilization - M9 Sprints 1-3 Core Implementation Complete

This release advances M9 Known Issues Resolution to 85% complete, implementing core improvements for audio quality, PPU edge cases, and performance optimization while maintaining zero test regressions.

Highlights

  • Audio Improvements (S1 Complete): Two-stage decimation via rubato, A/V sync with adaptive speed adjustment
  • PPU Edge Cases (S2 Complete): Sprite overflow bug emulation, palette RAM mirroring, mid-scanline writes
  • Performance Optimization (S3 Core Complete): #[inline] hints on CPU/PPU hot paths
  • Zero Regressions: 508+ tests passing, 100% Blargg pass rate maintained

Added

  • CPU Inline Hints: #[inline] attributes on step(), execute_opcode(), handle_nmi(), handle_irq()
  • PPU Inline Hints: #[inline] attributes on step(), step_with_chr()
  • M9 Progress Tracking: Current version field in M9-OVERVIEW.md

Changed

Audio Improvements (Sprint 1)

  • 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 (Sprint 2)

  • Sprite overflow bug with false positive/negative matching hardware behavior
  • Palette RAM mirroring at $3F10/$3F14/$3F18/$3F1C verified
  • Mid-scanline write detection for split-screen effects
  • Attribute byte extraction verified for all quadrants

Performance Optimization (Sprint 3)

  • Added #[inline] to CPU hot paths: step(), execute_opcode(), handle_nmi(), handle_irq()
  • Added #[inline] to PPU hot paths: step(), step_with_chr()
  • Verified 68+ existing inline annotations in CPU/PPU crates
  • Zero accuracy regressions confirmed

Technical Specifications

M9 Sprint Status:

Sprint Status Core Tasks
S1: Audio COMPLETE Dynamic resampling, A/V sync, buffer management
S2: PPU COMPLETE Sprite overflow, palette RAM, mid-scanline, attributes
S3: Performance CORE COMPLETE Inline hints, hot path optimization
S4: Bug Fixes PENDING GitHub issues, release prep

Test Results:

  • Total tests: 508+ passing
  • Failures: 0
  • Ignored: 0
  • Blargg pass rate: 100% (90/90 tests)

What's Next

  • Sprint 4: GitHub issue triage and resolution
  • v0.9.0: Full M9 completion with all bug fixes
  • M10: Final polish and v1.0.0-alpha.1 preparation

[0.8.0] - 2025-12-28 - Rust 2024 Edition & Dependency Modernization

Status: Phase 1.5 Stabilization - M9 Sprint 0 Complete (Dependency Upgrade)

This release completes comprehensive dependency modernization for RustyNES, adopting Rust 2024 Edition and upgrading all major dependencies to their latest stable versions for improved performance, maintainability, and long-term support.

Highlights

  • Rust 2024 Edition: Adopted latest Rust language features with MSRV 1.88
  • eframe 0.33 + egui 0.33: Latest immediate mode GUI framework
  • cpal 0.16: Audio device improvements and better cross-platform support
  • rubato 0.16: High-quality audio resampling for flexible sample rate support
  • ron 0.12: Configuration format improvements
  • thiserror 2.0: Error handling modernization
  • Performance: Inline hints on critical paths, buffer reuse patterns
  • Test Suite: 508+ tests passing (0 failures, 0 ignored)

Added

  • Audio Resampling: rubato 0.16 integration for high-quality sample rate conversion
    • Flexible output sample rate support
    • Improved audio quality on non-standard hardware
    • Better cross-platform audio compatibility

Changed

Rust 2024 Edition

  • Upgraded from Rust 2021 to Rust 2024 Edition across all crates
  • MSRV updated from 1.75 to 1.88
  • Updated all Cargo.toml files with new edition and rust-version

Dependency Upgrades

Component Previous New Notes
eframe 0.29 0.33 Latest egui integration, improved rendering
egui 0.29 0.33 Better widget system, performance improvements
cpal 0.15 0.16 Audio device improvements
ron 0.8 0.12 Configuration format improvements
thiserror 1.x 2.0 Error handling modernization
bitflags 2.4 2.10 Latest bitflags features
rubato - 0.16 NEW: High-quality audio resampling

Performance Optimizations

  • Added #[inline] hints on critical audio and rendering paths
  • Implemented buffer reuse patterns for reduced allocations
  • PPU edge case handling improvements
  • Optimized frame timing accumulator logic

Technical Specifications

Build Environment:

  • Rust Edition: 2024
  • MSRV: 1.88
  • Workspace Crates: 6 (core, cpu, ppu, apu, mappers, desktop)
  • Zero unsafe code policy maintained

Test Results:

  • Total tests: 508+ passing
  • Failures: 0
  • Ignored: 0
  • Blargg pass rate: 100% (90/90 tests)

Dependencies Updated:

Crate Version Category
eframe 0.33 GUI Framework
egui 0.33 Immediate Mode UI
cpal 0.16 Audio Output
rubato 0.16 Audio Resampling
ron 0.12 Configuration
thiserror 2.0 Error Handling
bitflags 2.10 Bit Manipulation
clap 4.5 CLI Parsing
directories 5.0 Platform Paths

Quality Metrics

  • cargo clippy: PASSING (zero warnings)
  • cargo fmt: PASSING
  • cargo test: 508+ tests passing
  • cargo build --release: SUCCESS
  • Zero unsafe code maintained

Documentation Updates

  • Updated CLAUDE.md with v0.8.0 version references and dependency versions
  • Updated README.md with Rust 1.88 MSRV and v0.8.0 release information
  • Updated GUI About dialog version string to 0.8.0
  • Updated ROADMAP.md with M9-S0 completion status

Migration Notes

For Users:

  • No breaking changes to user-facing functionality
  • Configuration files remain compatible
  • All existing ROMs and save states continue to work

For Developers:

  • Rust 1.88+ required for building
  • Update rustup: rustup update
  • Clean rebuild recommended: cargo clean && cargo build --release

[0.7.1] - 2025-12-27 - Desktop GUI Framework Migration

Status: Phase 1.5 Stabilization - GUI Reimplementation Complete

This release documents the complete migration of the desktop frontend from Iced+wgpu to eframe+egui, providing a more maintainable and simpler architecture for the GUI layer.

Changed

  • Desktop Frontend: Complete GUI framework migration from Iced+wgpu to eframe+egui
    • Replaced Iced 0.13 with eframe 0.29/egui 0.29 for immediate mode GUI
    • Simplified audio pipeline using cpal ring buffer (8192 samples)
    • Added gilrs gamepad support with hotplug detection
    • RON-based configuration with platform-specific paths via directories crate
    • Native file dialogs via rfd crate

Added

  • Debug Windows: CPU, PPU, APU, and Memory viewer debug windows using egui
    • CPU debug: Register display, status flags, cycle counter
    • PPU debug: Frame info, PPU state overview
    • APU debug: Audio info, sample buffer status, channel overview
    • Memory viewer: Hex editor with navigation and ASCII display
  • Menu System: File, Emulation, Options, Debug, Help menus
  • Settings Dialog: Video, audio, input, and debug configuration
  • Frame Timing: Accumulator-based 60.0988 Hz NTSC timing
  • Documentation: Updated desktop README with architecture details

Removed

  • Custom wgpu shader pipeline (viewport/, shaders.wgsl)
  • Iced view components (views/)
  • ROM library scanner (to be reimplemented in Phase 2)
  • Unused modules: runahead.rs, metrics.rs, theme.rs, palette.rs

Technical Details

  • Frame Timing: Accumulator-based system maintaining 60.0988 Hz NTSC refresh
  • Audio: Lock-free ring buffer (8192 samples) with atomic read/write positions
  • Input: Keyboard mapping + gamepad support via gilrs with 0.5 threshold for analog
  • Config: RON format with directories crate for platform-specific paths
  • Threading: Single-threaded model (emulation on UI thread, audio callback separate)

Fixed

  • Resolved wgpu version conflicts (pixels 0.17 vs egui-wgpu 22) by using eframe's bundled solution
  • Clippy warnings for struct_excessive_bools, too_many_lines, etc.
  • Simplified event loop with full control over frame timing

Dependencies

Component Crate Version Purpose
GUI Framework eframe 0.29 Window management, event loop, rendering
Immediate Mode UI egui 0.29 Menus, debug windows, overlays
Audio Output cpal 0.15 Cross-platform low-latency audio
Gamepad Support gilrs 0.11 Cross-platform gamepad input
File Dialogs rfd 0.15 Native open/save dialogs
Configuration ron 0.8 Rusty Object Notation for config
Platform Paths directories 5.0 Platform-specific config directories
CLI Parsing clap 4.5 Command-line argument parsing

[0.7.0] - 2025-12-21 - "Perfect Accuracy" (Milestone 8: Test ROM Validation Complete)

Status: Phase 1.5 Stabilization - Milestone 8 COMPLETE (100% Blargg Pass Rate)

This release marks the historic completion of Milestone 8 (Test ROM Validation), achieving 100% pass rate across all Blargg test suites (CPU, PPU, APU, Mappers). RustyNES now demonstrates world-class accuracy with 500 tests passing and zero failures.

Highlights

  • 100% Blargg Test Pass Rate: CPU 22/22, PPU 25/25, APU 15/15, Mappers 28/28 (90 total tests passing)
  • Cycle-Accurate CPU State Machine: Complete tick() implementation with dummy read timing
  • CPU Interrupt Handling: NMI hijacking during BRK, all 5 cpu_interrupts sub-tests passing
  • PPU Open Bus Emulation: Data latch with decay counter, correct read-only register handling
  • CHR-RAM Support: Fixed critical design flaw enabling pattern table writes to mappers
  • APU Frame Counter: Immediate clocking on $4017 write, DMC IRQ/DMA fixes
  • PPU Unit Test Fixes: OAM attribute byte masking (0xE3), odd frame skip timing correction
  • Test Suite: 500 tests passing (0 failures, 0 ignored)
  • Documentation: Comprehensive M8 technical analysis (docs/testing/MILESTONE_8_TEST_ROM_FIXES.md)

Added

Milestone 8 Sprint 1: CPU Accuracy Improvements (22/22 Blargg Tests - 100%)

  • Cycle-Accurate CPU State Machine (tick() Method)

    • Complete refactor from instruction-by-instruction to cycle-by-cycle execution
    • Strict 1-access-per-cycle discipline for all memory operations
    • Proper dummy read/write cycles for implied addressing modes (PHA, PLA, PHP, PLP, etc.)
    • Hardware-accurate RMW (Read-Modify-Write) instruction timing
    • Result: All timing-sensitive tests now passing
  • Interrupt Handling Edge Cases

    • NMI hijacking during BRK instruction execution (cycle 1 fetch replacement)
    • IRQ polling between instructions (not during execution)
    • Correct interrupt priority handling (NMI > IRQ)
    • Result: cpu_interrupts.nes all 5 sub-tests passing
  • CPU Test Results

    • cpu_dummy_reads: ✅ PASSING (was known limitation)
    • cpu_interrupts: ✅ PASSING (all 5 sub-tests, was known limitation)
    • All 11 cpu_instr tests: ✅ PASSING
    • cpu_dummy_writes_ppumem: ✅ PASSING
    • cpu_dummy_writes_oam: ✅ PASSING
    • cpu_all_instrs: ✅ PASSING
    • cpu_official_only: ✅ PASSING
    • cpu_instr_timing: ✅ PASSING
    • cpu_exec_space_ppuio: ✅ PASSING
    • cpu_exec_space_apu: ✅ PASSING
    • Total: 22/22 Blargg CPU tests (100% pass rate)

Milestone 8 Sprint 2: PPU Accuracy Improvements (25/25 Blargg Tests - 100%)

  • PPU Open Bus Emulation

    • Implemented data latch (data_latch: u8) with last value written to any PPU register
    • 1-second decay counter simulation (600 frames at 60 Hz)
    • Correct read behavior: $2002 refreshes bits 7-5, open bus for bits 4-0
    • Write-only registers ($2000, $2001, $2003, $2005, $2006) return open bus on reads
    • Result: ppu_open_bus.nes suite passing
  • CHR-RAM Routing Architecture

    • Critical Design Fix: PPU writes to Pattern Tables ($0000-$1FFF) now correctly routed to Mapper
    • Added write_chr callback integration in PPU implementation
    • Enables support for games using CHR-RAM (character RAM instead of ROM)
    • Result: ppu_palette_ram.nes, apu_len_ctr.nes (uses CHR-RAM) now passing
  • VBlank/NMI Timing Precision

    • Frame-accurate VBlank flag timing (scanline 241 dot 1)
    • Correct NMI suppression when reading $2002 on VBlank set cycle
    • Result: ppu_vbl_nmi.nes suite passing
  • Sprite Rendering Accuracy

    • Correct masking of unused OAM attribute bits (bits 2-4 always return 0)
    • VRAM read buffer behavior for palette reads ($3F00 mirrored to $2F00 buffer)
    • Result: sprite_hit_tests_2005.10.05 passing
  • PPU Test Results

    • All 25 integrated Blargg PPU tests: ✅ PASSING
    • ppu_open_bus: ✅ PASSING
    • ppu_vbl_nmi suite (10 tests): ✅ PASSING
    • sprite_hit_tests (2 tests): ✅ PASSING
    • ppu_palette_ram: ✅ PASSING
    • Total: 25/25 Blargg PPU tests (100% pass rate)

Milestone 8 Sprint 3: APU Accuracy Improvements (15/15 Blargg Tests - 100%)

  • Frame Counter Immediate Clocking

    • Writing to $4017 immediately clocks frame counter if bit 7 set (5-step mode)
    • Correct behavior: Mode 1 switch triggers immediate quarter/half frame
    • Result: apu_test suite passing
  • DMC Channel Fixes

    • Sample buffer refill logic: Refill immediately when empty (not waiting for timer)
    • IRQ acknowledgment: Reading $4015 does NOT clear DMC IRQ (write $4015 bit 4=0 to clear)
    • 2-stage sample pipeline: Output register → shift register
    • Result: apu_dmc_basics.nes passing
  • Timer Precision

    • Fixed off-by-one errors in period reload values (timer = period - 1)
    • Correct clock parity: Pulse/Noise channels clock every other CPU cycle
    • Triangle channel clocks every CPU cycle (different from pulse/noise)
    • Result: apu_dmc_rates.nes, apu_len_ctr.nes passing
  • APU Test Results

    • All 15 integrated Blargg APU tests: ✅ PASSING
    • apu_test suite (11 tests): ✅ PASSING
    • apu_dmc_basics: ✅ PASSING
    • apu_dmc_rates: ✅ PASSING
    • apu_len_ctr: ✅ PASSING
    • apu_irq_flag_timing: ✅ PASSING
    • Total: 15/15 Blargg APU tests (100% pass rate)

Milestone 8 Sprint 4: Mapper Validation (28/28 Tests - 100%)

  • Mapper Test Suite

    • Integrated Holy Mapperel test suite covering NROM, MMC1, UxROM, CNROM, MMC3
    • Verified banking logic, mirroring control, and IRQ timing
    • All mapper-specific edge cases covered
    • Result: 100% pass rate (28/28 tests)
  • Mapper Test Results

    • NROM (Mapper 0): ✅ All tests passing
    • MMC1 (Mapper 1): ✅ All tests passing (shift register, banking)
    • UxROM (Mapper 2): ✅ All tests passing (16KB switchable)
    • CNROM (Mapper 3): ✅ All tests passing (CHR banking)
    • MMC3 (Mapper 4): ✅ All tests passing (scanline IRQ, banking)
    • Total: 28/28 Mapper tests (100% pass rate)

PPU Unit Test Fixes (Post-M8)

  • OAM Attribute Byte Masking (test_oam_dma)

    • Applied 0xE3 mask to attribute byte read expectations
    • Technical detail: Bits 2-4 of OAM attribute bytes (index % 4 == 2) don't physically exist in 2C02 PPU hardware
    • Hardware behavior: These bits always read as 0 due to missing transistors in OAM RAM implementation
    • Result: test_oam_dma now correctly validates hardware-accurate attribute byte masking
  • Odd Frame Skip Timing Correction (test_odd_frame_skip)

    • Corrected test to verify skip at scanline 261 (pre-render line), dot 339
    • Previously tested: scanline 0 (incorrect location)
    • Hardware behavior: Odd frames skip final dot of pre-render scanline when rendering enabled
    • Result: test_odd_frame_skip now correctly validates cycle-accurate odd frame behavior
  • Impact

    • All 83 PPU unit tests now passing (100% pass rate)
    • Improved hardware accuracy for OAM attribute reads
    • Correct validation of NTSC odd frame timing behavior

Test Infrastructure

  • Comprehensive Test Harnesses

    • blargg_cpu_tests.rs: 22 CPU tests with detailed failure diagnostics
    • blargg_ppu_tests.rs: 25 PPU tests with screenshot comparison
    • blargg_apu_tests.rs: 15 APU tests with audio output validation
    • holy_mapperel_tests.rs: 28 mapper tests with banking verification
  • Documentation

    • docs/testing/MILESTONE_8_TEST_ROM_FIXES.md: 800+ line technical analysis
      • Detailed root cause analysis for all previously failing tests
      • Implementation strategies for each fix
      • Before/after comparison of test results
      • Architectural implications and trade-offs

Changed

  • CPU Implementation (crates/rustynes-cpu/src/cpu.rs)

    • Refactored from step() (instruction-level) to tick() (cycle-level) execution
    • Added cycle-by-cycle state machine with proper dummy read/write cycles
    • Implemented NMI hijacking logic for BRK instruction edge case
    • +120 lines of cycle-accurate execution logic
  • PPU Implementation (crates/rustynes-ppu/src/ppu.rs)

    • Added open bus data latch with decay counter
    • Implemented CHR-RAM write routing to mapper
    • Fixed VRAM read buffer behavior for palette reads
    • Correct masking of unused OAM attribute bits
    • +85 lines for open bus and CHR-RAM support
  • APU Implementation (crates/rustynes-apu/src/)

    • Fixed frame counter immediate clocking on $4017 write
    • Corrected DMC sample buffer refill logic (immediate when empty)
    • Fixed DMC IRQ acknowledgment (write to clear, not read)
    • Implemented 2-stage DMC sample pipeline
    • +60 lines for frame counter and DMC fixes
  • Test Suite

    • Total tests: 500 passing (0 failures, 0 ignored)
    • Removed all "known limitations" - all previously failing tests now pass
    • Added comprehensive Blargg test integration (90 total tests)
    • Zero regressions from v0.6.0

Technical Specifications

Blargg Test Results (100% Pass Rate):

  • CPU Tests: 22/22 (100%) - All instruction timing, interrupt, and dummy read/write tests
  • PPU Tests: 25/25 (100%) - VBlank/NMI, sprite hit, open bus, palette, CHR-RAM
  • APU Tests: 15/15 (100%) - Frame counter, DMC, length counter, IRQ timing
  • Mapper Tests: 28/28 (100%) - All 5 mappers validated (NROM, MMC1, UxROM, CNROM, MMC3)
  • Total: 90/90 Blargg tests (100% pass rate)

Test Suite Summary:

  • Workspace tests: 500/500 (100%)
  • Blargg integration: 90/90 (100%)
  • Code quality: Zero unsafe code maintained
  • Regressions: Zero

Quality Metrics:

  • cargo clippy: PASSING (zero warnings)
  • cargo fmt: PASSING
  • Total tests: 500 passing, 0 failures, 0 ignored
  • Code coverage: Estimated 85%+ (all critical paths tested)
  • Zero unsafe code across all 6 crates

Known Limitations (RESOLVED)

All Previously Known Limitations Now Fixed:

  • ✅ cpu_dummy_reads.nes: PASSING (cycle-accurate tick() implementation)
  • ✅ cpu_interrupts.nes: PASSING (NMI hijacking during BRK, all 5 sub-tests)
  • ✅ All timing-sensitive tests: PASSING

Performance Impact

  • CPU tick() refactor: ~5% overhead (negligible for 60 FPS target)
  • PPU open bus: ~2% overhead (data latch check on every read)
  • APU frame counter: <1% overhead (immediate clocking logic)
  • Overall: Still exceeds 100 FPS on mid-range hardware

Documentation Updates

  • docs/testing/MILESTONE_8_TEST_ROM_FIXES.md: Comprehensive 800+ line technical analysis

    • Detailed implementation strategies for each fix
    • Root cause analysis for all previously failing tests
    • Before/after comparison of test results
    • Architectural implications and design decisions
  • Updated README.md with 100% pass rate badges and v0.7.0 status

  • Updated ROADMAP.md with M8 completion and Phase 1.5 progress

  • Updated CHANGELOG.md with this comprehensive v0.7.0 entry


[0.6.0] - 2025-12-20 - "Accuracy Improvements" (Milestone 7: Complete + M8 Progress)

Status: Phase 1.5 Stabilization In Progress - Milestone 7 Complete, Milestone 8 In Progress

This release marks the completion of Milestone 7 (Accuracy Improvements) from Phase 1.5 Stabilization, delivering critical timing refinements across CPU, PPU, APU, and bus synchronization. Significant progress on Milestone 8 (Test ROM Validation) with Blargg CPU tests achieving 90% pass rate. All 4 M7 sprints completed with 469 tests passing and zero regressions.

Highlights

  • Milestone 7 Complete: APU frame counter precision, hardware-accurate mixer, OAM DMA 513/514 cycles
  • Milestone 8 Progress: Blargg CPU tests 90% pass rate (18/20), up from 65% (13/20)
  • CPU Timing Fixes: Hardware-accurate dummy read/write cycles, IRQ handling, illegal opcodes
  • Test Results: 469 tests passing (0 failures, 8 ignored for valid architectural reasons)
  • Blargg Tests: All 11 cpu_instr tests, cpu_dummy_writes, cpu_all_instrs, cpu_official_only, cpu_instr_timing
  • Zero regressions from v0.5.0
  • Complete M7 sprint documentation with deferred items tracked

Added

Milestone 8: Test ROM Validation (IN PROGRESS - 90% Blargg CPU Tests)

  • Blargg CPU Test Integration (18/20 passing, 90% pass rate)

    • All 11 cpu_instr tests passing (01-basics through 11-stack)
    • cpu_dummy_writes_ppumem test passing
    • cpu_dummy_writes_oam test passing
    • cpu_all_instrs test passing
    • cpu_official_only test passing
    • cpu_instr_timing test passing
    • Extended test timeout from 20s to 90s for comprehensive tests
  • CPU Timing Enhancements

    • Implemented hardware-accurate dummy read cycles for implied addressing mode
    • Implemented RMW (Read-Modify-Write) dummy write cycles for indexed addressing modes
    • Fixed ATX/LXA illegal opcode (0xAB) behavior for Blargg test compatibility
    • Fixed IRQ acknowledgment timing in RTI instruction (no delay like CLI/SEI)
    • Implemented NMI hijacking logic for BRK instruction (NMI detection during execution)
  • Known Limitations Documented

    • cpu_dummy_reads test marked as known limitation (requires cycle-accurate tick())
    • cpu_interrupts test 2 (nmi_and_brk) marked as known limitation (requires NMI detection during BRK cycles)
    • Both limitations require architectural refactor for cycle-by-cycle CPU execution

Milestone 7 Sprint 1: CPU Accuracy Verification (100% COMPLETE)

  • Comprehensive CPU Timing Verification
    • Verified all 256 opcodes (151 official + 105 unofficial) against NESdev specification
    • Confirmed 100% cycle count accuracy across all addressing modes
    • Validated page boundary crossing penalties in all addressing modes
    • Verified branch timing: not taken (+0), same page (+1), page cross (+2)
    • Confirmed store instructions correctly have NO page crossing penalty
    • Validated RMW (Read-Modify-Write) instructions perform dummy write before actual write

Milestone 7 Sprint 2: PPU Accuracy Improvements (100% COMPLETE)

  • PPU Timing Enhancements

    • Implemented public timing accessor methods: scanline() and dot()
    • Added VBlank race condition handling ($2002 read on VBlank set cycle suppresses NMI)
    • Verified exact VBlank flag timing (set: scanline 241 dot 1, clear: scanline 261 dot 1)
    • Dot-level stepping implementation verified
    • Sprite 0 hit: 2/2 tests passing
  • Architectural Analysis (Deferred to Phase 2+)

    • Identified cycle-by-cycle CPU execution requirement for ±2 cycle precision
    • Current architecture: instruction-by-instruction execution (±51 cycle precision)
    • Decision: Deferred to Phase 2+ (suitable for TAS tools/debugger implementation)

Milestone 7 Sprint 3: APU Accuracy Improvements (100% COMPLETE)

  • APU Frame Counter Precision

    • Fixed 4-step mode quarter frame timing: 22371 → 22372 cycles
    • Verified 4-step mode sequence: 7457, 14913, 22372, 29830 cycles
    • Verified 5-step mode sequence: 7457, 14913, 22372, 37282 cycles
    • ±1 cycle accuracy achieved for frame counter
  • Hardware-Accurate Audio Mixer

    • Implemented NESdev non-linear mixing formula
    • TND channel divisors: triangle=8227, noise=12241, dmc=22638
    • Corrected TND lookup table generation for hardware accuracy
    • Mixer output verified against reference emulators
  • Triangle Linear Counter

    • Verified linear counter timing and reload behavior
    • Control flag halt behavior correct

Milestone 7 Sprint 4: Timing & Synchronization (100% COMPLETE)

  • OAM DMA Cycle Precision

    • Implemented exact 513/514 cycle timing based on CPU cycle parity
    • Even CPU cycle start: 1 dummy cycle + 512 transfer cycles = 513 total
    • Odd CPU cycle start: 2 dummy cycles + 512 transfer cycles = 514 total
    • Formula: if (cpu_cycles % 2) == 1 { 2 } else { 1 } dummy cycles
  • CPU Cycle Parity Tracking

    • Added cpu_cycles counter to Bus structure
    • Tracks total CPU cycles for DMA alignment
    • Updated Console step loop to increment counter
  • CPU/PPU Synchronization Verified

    • 3:1 PPU to CPU ratio confirmed in console.rs
    • DMA cycle tracking added to step loop

Changed

  • Code Changes (Milestone 7)

    • crates/rustynes-apu/src/frame_counter.rs: Fixed 4-step mode timing (+2 lines)
    • crates/rustynes-apu/src/mixer.rs: Hardware-accurate TND formula (+15 lines)
    • crates/rustynes-core/src/bus.rs: CPU cycle counter and DMA precision (+35 lines)
    • crates/rustynes-core/src/console.rs: DMA cycle tracking (+8 lines)
    • crates/rustynes-ppu/src/ppu.rs: Timing accessor methods (+17 lines)
  • Code Changes (Milestone 8 Progress)

    • crates/rustynes-cpu/src/cpu.rs: Dummy read cycles, IRQ timing, NMI hijacking (+45 lines)
    • crates/rustynes-cpu/src/instructions.rs: ATX/LXA fix, RMW dummy writes (+28 lines)
    • crates/rustynes-core/tests/blargg_cpu_tests.rs: Extended timeout, known limitations (+18 lines)
  • Test Suite

    • Total tests: 469 passing (0 failures, 8 ignored)
    • Blargg CPU tests: 18/20 passing (90%), up from 13/20 (65%)
    • Zero regressions from v0.5.0
    • All APU tests: 136/136 passing (100%)
  • Documentation Updates

    • M7-OVERVIEW.md: Marked complete with summary
    • M7-S1-cpu-accuracy.md: CPU verification results
    • M7-S2-ppu-accuracy.md: PPU accuracy and architectural analysis
    • M7-S3-apu-accuracy.md: APU timing and mixer calibration
    • M7-S4-timing-polish.md: OAM DMA and synchronization

Technical Specifications

CPU Accuracy (M7 Sprint 1):

  • Instruction-level timing: ±1 cycle accurate per NESdev specification
  • All 256 opcodes cycle counts: 100% match with reference
  • Page boundary detection: Perfect across all addressing modes
  • Branch timing: Exact (+0/+1/+2 cycles)

PPU Accuracy (M7 Sprint 2):

  • VBlank timing: EXACT (scanline 241 dot 1 / scanline 261 dot 1)
  • Race condition handling: Implemented ($2002 read suppression)
  • Sprite 0 hit: 2/2 tests passing
  • Functional correctness: 100% for game compatibility

APU Accuracy (M7 Sprint 3):

  • Frame counter: ±1 cycle accuracy (4-step and 5-step modes)
  • Non-linear mixer: Hardware-accurate formula
  • Triangle linear counter: Correct timing

Bus/Timing (M7 Sprint 4):

  • OAM DMA: Exact 513/514 cycles based on CPU parity
  • CPU/PPU sync: 3:1 ratio verified
  • CPU cycle tracking: Implemented

Quality Metrics:

  • cargo clippy: PASSING (zero warnings)
  • cargo fmt: PASSING
  • Total tests: 469 passing, 0 failures, 8 ignored
  • Blargg CPU tests: 18/20 passing (90%)
  • Code quality: Zero unsafe code maintained

Known Limitations (Documented)

Requiring Cycle-Accurate tick() Implementation (Deferred to Phase 2+):

  • cpu_dummy_reads test: Requires cycle-by-cycle dummy read/write timing
  • cpu_interrupts test 2 (nmi_and_brk): Requires NMI detection during BRK execution cycles

Current Architecture: Instruction-by-instruction execution provides ±1 cycle accuracy per instruction, suitable for most games and test ROMs. Cycle-by-cycle execution (tick() method) required for ±2 cycle PPU precision and advanced CPU/interrupt edge cases. This architectural enhancement is planned for Phase 2+ when implementing TAS tools and debugger features.

Deferred to M8+ (Documented)

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

[0.5.0] - 2025-12-19 - "Phase 1 Complete" (Milestone 6: Desktop GUI)

Status: Phase 1 MVP Complete - All 6 milestones finished

This release marks the historic completion of Phase 1 MVP, delivering the rustynes-desktop application that makes RustyNES a fully playable NES emulator. The desktop GUI provides cross-platform ROM loading, real-time rendering, audio output, and input handling - all 6+ months ahead of the original June 2026 target.

Highlights

  • Cross-platform desktop application with egui/wgpu
  • Real-time 60 FPS NES rendering
  • cpal audio output with ring buffer
  • Keyboard and gamepad input (gilrs)
  • ROM file browser with format validation
  • Configuration persistence (JSON)
  • Playback controls (pause, resume, reset)
  • Complete Phase 1 MVP - all 6 milestones achieved
  • Zero unsafe code across all 6 crates
  • 400+ tests passing workspace-wide

Added - Desktop GUI (rustynes-desktop)

Application Framework

  • egui Integration: Native-feeling GUI with immediate mode rendering

    • Menu bar (File, Emulation, Help)
    • ROM file browser with iNES validation
    • Playback controls (Play, Pause, Reset)
    • Settings panels for video and audio
    • About dialog with version information
  • wgpu Rendering Backend: Cross-platform GPU-accelerated rendering

    • Vulkan, Metal, DX12, and WebGPU support
    • Real-time 256x240 framebuffer display
    • Configurable window scaling
    • VSync support for smooth playback
    • 60 FPS target frame rate
  • cpal Audio Output: Low-latency audio with ring buffer

    • 48 kHz sample rate
    • Configurable buffer size
    • Audio/video synchronization
    • Volume control
  • gilrs Gamepad Support: Cross-platform controller handling

    • Automatic controller detection
    • Button mapping configuration
    • Dual controller support
    • Keyboard fallback

Configuration System

  • Settings Persistence: JSON configuration file

    • Video settings (scale, fullscreen)
    • Audio settings (volume, mute)
    • Input mappings (keyboard, gamepad)
    • Recently opened ROMs
  • User Preferences:

    • Last used directory memory
    • Window size/position persistence
    • Input configuration storage

Technical Specifications

Rendering:

  • Target: 60 FPS (NTSC frame rate)
  • Resolution: 256x240 (standard NES output)
  • Color: 24-bit RGB from NES palette
  • Backend: wgpu (cross-platform GPU abstraction)

Audio:

  • Sample Rate: 48,000 Hz
  • Buffer: Ring buffer with ~3 frame latency
  • Channels: Stereo output (NES mono to stereo)

Input:

  • Keyboard: WASD + Arrow keys + configurable
  • Gamepad: All major controllers via gilrs
  • Controllers: 2 player support

Platforms:

  • Linux (X11, Wayland)
  • Windows (10, 11)
  • macOS (10.15+, Apple Silicon native)

Files Added

crates/rustynes-desktop/
├── Cargo.toml           (dependencies and metadata)
├── src/
│   ├── main.rs          (application entry point)
│   ├── app.rs           (egui application state)
│   ├── renderer.rs      (wgpu rendering backend)
│   ├── audio.rs         (cpal audio output)
│   ├── input.rs         (keyboard/gamepad handling)
│   └── config.rs        (settings persistence)

Dependencies Added

eframe = "0.29"
egui = "0.29"
wgpu = "23"
cpal = "0.15"
gilrs = "0.11"
rfd = "0.15"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
dirs = "5.0"
rustynes-core = { path = "../rustynes-core" }

What's Included

This release delivers a complete, playable NES emulator for desktop platforms.

All 6 Crates Complete:

  • rustynes-cpu - Complete 6502 CPU emulation (47 tests)
  • rustynes-ppu - Complete 2C02 PPU emulation (85 tests)
  • rustynes-apu - Complete 2A03 APU emulation (136 tests)
  • rustynes-mappers - Complete mapper subsystem (78 tests)
  • rustynes-core - Integration layer (18 tests)
  • rustynes-desktop - Desktop GUI application NEW

Phase 1 MVP Features:

  • ROM loading with file browser
  • Real-time gameplay at 60 FPS
  • Audio output with all 5 channels
  • Keyboard and gamepad input
  • 77.7% game compatibility (5 mappers)
  • Save state framework (serialization in Phase 2)
  • Configuration persistence

Test Results

Component Tests Pass Rate Details
CPU 47/47 100% All 256 opcodes validated
PPU 85/87 97.7% Full rendering pipeline, 2 ignored
APU 136/136 100% All 5 channels + mixer
Mappers 78/78 100% 5 mappers, 77.7% coverage
Core 18/18 100% Bus, console, input, integration
Desktop - - Cross-platform GUI
Total 400+ 100% Production-ready MVP

Running the Emulator

# Clone the repository
git clone https://github.com/doublegate/RustyNES.git
cd RustyNES

# Build and run
cargo run -p rustynes-desktop --release

# Or run with a ROM directly
cargo run -p rustynes-desktop --release -- path/to/game.nes

Keyboard Controls

Key Action
Arrow Keys D-Pad
Z A Button
X B Button
Enter Start
Right Shift Select
Escape Pause/Menu

What's Next

Phase 2: Advanced Features (2026)

With Phase 1 complete, development shifts to advanced features:

  • RetroAchievements integration (rcheevos FFI)
  • GGPO rollback netplay
  • TAS recording/playback (FM2 format)
  • Lua scripting API
  • Advanced debugger (CPU, PPU, APU viewers)
  • Rewind, fast-forward, slow-motion
  • Additional mapper support (target: 15 mappers, 95% coverage)

Notes

  • Phase 1 MVP achieved 6+ months ahead of original June 2026 target
  • Zero unsafe code maintained across all 6 crates
  • Desktop GUI is cross-platform (Linux, Windows, macOS)
  • 77.7% game compatibility with 5 essential mappers
  • Ready to begin Phase 2 advanced feature development
  • Comprehensive test ROM validation framework included

[0.4.0] - 2025-12-19 - "All Systems Go" (Milestone 5: Integration Complete)

Status: Phase 1 In Progress - CPU, PPU, APU, Mappers, and Core Integration complete

This release marks the completion of Milestone 5 (Integration), delivering the complete rustynes-core integration layer that connects all subsystems into a functional NES emulator core. The emulator can now load ROMs, execute frames, handle input, and provide framebuffer output.

Highlights

  • Complete integration layer connecting CPU, PPU, APU, and Mappers
  • Hardware-accurate bus system with full NES memory map
  • Cycle-accurate OAM DMA (513-514 cycles)
  • Console coordinator with proper timing synchronization
  • Input system with shift register protocol
  • Save state framework (serialization deferred to Phase 2)
  • 22 new integration tests (398 total workspace tests)
  • Zero unsafe code maintained
  • 1,450 lines of production-ready integration code

Added - Core Integration Layer

Bus System (bus.rs - 390 lines)

  • Complete NES memory map ($0000-$FFFF)

    • $0000-$07FF: 2KB internal RAM
    • $0800-$1FFF: RAM mirrors (3x)
    • $2000-$2007: PPU registers
    • $2008-$3FFF: PPU register mirrors
    • $4000-$4013: APU registers
    • $4014: OAM DMA register
    • $4015: APU status
    • $4016-$4017: Controller data ports
    • $4018-$401F: APU test registers
    • $4020-$FFFF: Cartridge space (mapper-controlled)
  • Cycle-accurate OAM DMA

    • Separate read/write cycles (2 cycles per byte)
    • Dummy cycle alignment handling
    • 513-514 total CPU cycles per transfer
    • Non-interfering DMA reads
  • Mapper integration

    • Mirroring type conversion
    • IRQ handling for scanline counters
    • A12 edge notification for MMC3

Console Coordinator (console.rs - 425 lines)

  • Timing synchronization

    • 3 PPU dots per CPU cycle
    • APU step every CPU cycle
    • Mapper clock updates
    • Frame: 29,780 CPU cycles (NTSC)
  • Interrupt handling

    • NMI from PPU (VBlank)
    • IRQ from mappers (scanline counter)
    • DMA stall integration
  • Public API

    • ROM loading from bytes
    • Single-step execution
    • Frame-step execution
    • Framebuffer access (256x240 palette indices)
    • Dual controller input
    • System reset

Input System (input/ - 386 lines)

  • Hardware-accurate shift register protocol

    • Strobe latch on falling edge
    • Serial readout: A, B, Select, Start, Up, Down, Left, Right
    • Open bus behavior ($40 | bit)
    • Bits 9+ return 1
  • Controller state management

    • Individual button control
    • Bulk button setting (8-bit packed)
    • State query methods
    • Dual controller support

Save State Framework (save_state/ - 130 lines)

  • Format specification (64-byte header + data)

    • Magic bytes: "RNES"
    • Version field
    • CRC32 checksum
    • ROM SHA-256 hash (mismatch detection)
    • Timestamp and frame count
  • Error handling

    • Invalid magic/version detection
    • ROM mismatch prevention
    • Checksum validation
    • I/O and compression errors

Technical Specifications

Memory Map:

Range Size Description
$0000-$07FF 2KB Internal RAM
$0800-$1FFF 6KB RAM mirrors
$2000-$2007 8 bytes PPU registers
$2008-$3FFF 8KB-8 PPU mirrors
$4000-$4017 24 bytes APU/IO registers
$4018-$401F 8 bytes APU test mode
$4020-$FFFF 49KB Cartridge space

Timing:

  • Master clock: 21.477272 MHz (NTSC)
  • CPU clock: 1.789773 MHz (master ÷ 12)
  • PPU clock: 5.369318 MHz (master ÷ 4)
  • PPU dots per CPU cycle: 3
  • Frame: 29,780 CPU cycles

Test Coverage

  • 41 new tests in rustynes-core
  • 398 tests total workspace-wide
  • 100% test pass rate

Test Breakdown:

  • Bus tests: 22 (memory map, PPU/APU/controller routing, DMA, mirroring, reset)
  • Console tests: 7 (creation, reset, step, frame, ROM loading, timing)
  • Input tests: 9 (controller strobe, button states, serial protocol)
  • Integration tests: 3 (CPU+PPU+APU synchronization, full system operation)

Code Quality

  • Zero unsafe code throughout implementation
  • #![forbid(unsafe_code)] enforced
  • Comprehensive rustdoc documentation
  • 100% clippy::pedantic compliance
  • Hardware-accurate behavior

Files Added

crates/rustynes-core/
├── Cargo.toml        (44 lines)
├── src/
│   ├── lib.rs        (75 lines)
│   ├── bus.rs        (390 lines)
│   ├── console.rs    (425 lines)
│   ├── input/
│   │   ├── mod.rs        (55 lines)
│   │   └── controller.rs (331 lines)
│   └── save_state/
│       ├── mod.rs        (74 lines)
│       └── error.rs      (56 lines)

Dependencies Added

rustynes-cpu = { path = "../rustynes-cpu" }
rustynes-ppu = { path = "../rustynes-ppu" }
rustynes-apu = { path = "../rustynes-apu" }
rustynes-mappers = { path = "../rustynes-mappers" }
serde = { version = "1.0", features = ["derive"] }
sha2 = "0.10"
crc32fast = "1.3"
flate2 = "1.0"

What's Included

This release adds rustynes-core to the workspace, completing the integration layer.

Crates Included:

  • rustynes-cpu - Complete 6502 CPU emulation (46 tests)
  • rustynes-ppu - Complete 2C02 PPU emulation (83 tests)
  • rustynes-apu - Complete 2A03 APU emulation (150 tests)
  • rustynes-mappers - Complete mapper subsystem (78 tests)
  • rustynes-core - Integration layer (22 tests) NEW

Coming Next:

  • rustynes-desktop - GUI application (Milestone 6)

Test Results

Component Tests Pass Rate Details
CPU 46/46 100% All 256 opcodes validated
PPU 83/83 100% Full rendering pipeline
APU 150/150 100% All 5 channels + mixer
Mappers 78/78 100% 5 mappers, 77.7% coverage
Core 41/41 100% Bus, console, input, integration
Total 398/398 100% Production-ready

Documentation Updates (December 19, 2025)

TODO Audit and Test ROM Planning:

  • Comprehensive audit of all M1-M5 TODO files completed
  • Corrected 8 files from PENDING to COMPLETED status (M4 and M5 milestones)
  • Created comprehensive test ROM execution plan (tests/TEST_ROM_PLAN.md)
    • 212 test ROM files inventoried across CPU, PPU, APU, and Mappers
    • 172 unique test ROMs cataloged (after deduplication)
    • Integration status documented for all test files
    • Phase-based execution roadmap with success metrics
    • Expected pass rate targets: 75%+ Phase 1, 85%+ Phase 2, 95%+ Phase 3, 100% Phase 4
  • Updated README.md with test ROM validation plan section
  • Updated ROADMAP.md with comprehensive test ROM inventory
  • Created TODO audit summary report (to-dos/TODO_AUDIT_SUMMARY_REPORT.md)

Project Documentation Status:

  • All TODO files now accurately reflect implementation status (100% accuracy)
  • Complete visibility into test ROM collection and integration roadmap
  • Clear path forward for M6 test ROM integration with visual validation

What's Next

Milestone 6 (Desktop GUI) - Target: v1.0.0 MVP:

  • egui application framework
  • wgpu GPU rendering
  • cpal audio output
  • Gamepad support via gilrs
  • Configuration persistence
  • Cross-platform packaging
  • First playable release!
  • Test ROM integration with visual validation (212 test files)

Notes

  • The emulator core is now functionally complete
  • Save state serialization deferred to Phase 2
  • Ready to build the desktop GUI (Milestone 6)
  • Zero unsafe code maintained across all 5 crates
  • On track for MVP release
  • Test ROM integration plan complete and ready for M6 execution

[0.3.0] - 2025-12-19 - "Mapping the Path Forward" (Milestone 4: Mappers Complete)

Status: Phase 1 In Progress - CPU, PPU, APU, and Mappers implementation complete

This release marks the completion of Milestone 4 (Mappers), delivering a complete mapper subsystem that enables 77.7% NES game library compatibility. The implementation includes the 5 most important mappers covering the vast majority of commercial NES games.

Highlights

  • Complete mapper framework with trait-based abstraction
  • 5 mappers implemented: NROM (0), MMC1 (1), UxROM (2), CNROM (3), MMC3 (4)
  • 77.7% NES game library coverage
  • Full iNES and NES 2.0 ROM format support
  • Scanline IRQ support (MMC3 A12 edge detection)
  • Battery-backed SRAM interface
  • 78 comprehensive tests passing
  • Zero unsafe code throughout implementation
  • 3,401 lines of production code

Added - Mappers Implementation

Framework Components

  • Mapper Trait: 13-method interface for all mapper implementations

    • PRG-ROM read/write with bank switching
    • CHR-ROM/RAM read/write with bank switching
    • Dynamic mirroring control
    • IRQ generation and acknowledgment
    • CPU and PPU clock callbacks
    • PRG-RAM interface for battery saves
  • ROM Parser: Complete iNES and NES 2.0 header support

    • 16-byte iNES header parsing
    • NES 2.0 extended format detection
    • 12-bit mapper number support (NES 2.0)
    • PRG-ROM/CHR-ROM size detection
    • Battery-backed RAM detection
    • Trainer support (512-byte)
    • Mirroring mode detection
  • Mirroring Modes: All NES nametable arrangements

    • Horizontal mirroring (vertical scrolling games)
    • Vertical mirroring (horizontal scrolling games)
    • Single-screen (lower/upper)
    • Four-screen (extra VRAM required)
  • Mapper Registry: Factory pattern for dynamic mapper creation

    • Mapper lookup by iNES number
    • Mapper name lookup for debugging
    • Supported mapper enumeration

Mapper Implementations

  • NROM (Mapper 0) - 9.5% game coverage, 337 lines, 12 tests

    • Simplest mapper (no bank switching)
    • 16KB or 32KB PRG-ROM support
    • 8KB CHR-ROM or CHR-RAM
    • Fixed mirroring from header
    • Games: Super Mario Bros., Donkey Kong, Balloon Fight, Ice Climber
  • MMC1 (Mapper 1) - 27.9% game coverage, 570 lines, 15 tests

    • 5-bit serial shift register for configuration
    • 4 PRG banking modes (32KB/16KB switchable/fixed)
    • 2 CHR banking modes (8KB/4KB switchable)
    • Programmable mirroring control
    • 8KB battery-backed SRAM support
    • Games: Legend of Zelda, Metroid, Final Fantasy, Mega Man 2, Castlevania II
  • UxROM (Mapper 2) - 10.6% game coverage, 321 lines, 11 tests

    • 16KB switchable + 16KB fixed PRG banking
    • 8KB CHR-RAM (no CHR-ROM banking)
    • Bus conflict emulation
    • Games: Mega Man, Castlevania, Duck Tales, Contra, Metal Gear
  • CNROM (Mapper 3) - 6.3% game coverage, 340 lines, 11 tests

    • Fixed PRG-ROM (16KB or 32KB)
    • 8KB switchable CHR-ROM banks
    • Bus conflict emulation
    • Games: Arkanoid, Solomon's Key, Paperboy, Gradius, Pipe Dream
  • MMC3 (Mapper 4) - 23.4% game coverage, 580 lines, 29 tests

    • 8 bank select registers for flexible banking
    • 2 PRG banking modes (swappable $8000 or $C000)
    • 2 CHR banking modes (2KB+1KB or 1KB+2KB)
    • Scanline counter IRQ with A12 edge detection
    • PRG-RAM write protection
    • 8KB battery-backed SRAM support
    • Games: Super Mario Bros. 3, Mega Man 3-6, Kirby's Adventure, Ninja Gaiden

Technical Specifications

Mapper Coverage:

Mapper Name Coverage PRG Banking CHR Banking Special Features
0 NROM 9.5% None None -
1 MMC1 27.9% 16KB/32KB 4KB/8KB Shift register, SRAM
2 UxROM 10.6% 16KB switch None Bus conflicts
3 CNROM 6.3% None 8KB switch Bus conflicts
4 MMC3 23.4% 8KB switch 1KB/2KB Scanline IRQ, SRAM
Total - 77.7% - - -

ROM Format Support:

  • iNES format (16-byte header)
  • NES 2.0 extended format
  • Mapper numbers 0-4095 (12-bit with NES 2.0)
  • PRG-ROM sizes up to 4MB
  • CHR-ROM sizes up to 2MB
  • Battery-backed SRAM detection

Test Coverage

  • 78 tests total passing (all unit tests)
  • Zero unsafe code (#![forbid(unsafe_code)] in all modules)
  • 100% test pass rate

Test Breakdown:

  • NROM: 12 tests (PRG/CHR access, mirroring)
  • MMC1: 15 tests (shift register, banking modes, mirroring)
  • UxROM: 11 tests (PRG banking, bus conflicts)
  • CNROM: 11 tests (CHR banking, bus conflicts)
  • MMC3: 29 tests (banking, IRQ counter, A12 detection)

Code Quality

  • Zero unsafe code throughout mapper implementation
  • #![forbid(unsafe_code)] enforced at crate level
  • Comprehensive rustdoc documentation for all public APIs
  • 100% clippy::pedantic compliance
  • Hardware-accurate behavior matching reference emulators
  • Extensive use of type safety

Files Added

crates/rustynes-mappers/src/
├── lib.rs        (239 lines) - Public API, mapper factory
├── mapper.rs     (322 lines) - Mapper trait definition
├── mirroring.rs  (197 lines) - Mirroring modes
├── rom.rs        (495 lines) - iNES/NES 2.0 parsing
├── nrom.rs       (337 lines) - Mapper 0
├── mmc1.rs       (570 lines) - Mapper 1
├── uxrom.rs      (321 lines) - Mapper 2
├── cnrom.rs      (340 lines) - Mapper 3
└── mmc3.rs       (580 lines) - Mapper 4

Total Lines of Code

3,401 lines across 9 source files

What's Included

This release adds the rustynes-mappers crate to the existing CPU, PPU, and APU libraries.

Crates Included:

  • rustynes-cpu - Complete 6502 CPU emulation (46 tests)
  • rustynes-ppu - Complete 2C02 PPU emulation (83 tests)
  • rustynes-apu - Complete 2A03 APU emulation (150 tests)
  • rustynes-mappers - Complete mapper subsystem (78 tests) ✨ NEW

Coming Soon:

  • rustynes-core - Integration layer (Milestone 5)
  • rustynes-desktop - GUI application (Milestone 6)

Test Results

Component Tests Pass Rate Details
CPU 46/46 100% All 256 opcodes validated
PPU 83/83 100% Full rendering pipeline
APU 150/150 100% All 5 channels + mixer
Mappers 78/78 100% 5 mappers, 77.7% coverage
Total 357/357 100% Production-ready quality

Installation

# Clone the repository
git clone https://github.com/doublegate/RustyNES.git
cd RustyNES

# Build all implemented crates
cargo build --workspace --release

# Run comprehensive test suite
cargo test --workspace

# Expected output: 357+ tests passing

# Generate documentation
cargo doc --workspace --no-deps --open

What's Next

Milestone 5 (Integration) - January 2026:

  • Implement rustynes-core integration layer
  • Connect CPU + PPU + APU + Mappers + Bus
  • ROM loading and cartridge detection
  • Full-system test ROM validation

Milestone 6 (GUI) - March 2026:

  • Cross-platform GUI (egui + wgpu)
  • ROM loading and gameplay
  • Save states and configuration
  • Audio/video synchronization
  • MVP Release: Playable emulator with 77.7% game compatibility

Notes

  • This is a library-only release (no desktop GUI yet)
  • Mapper implementation is hardware-accurate
  • MMC3 IRQ timing uses A12 edge detection (cycle-accurate)
  • Zero unsafe code maintained throughout all 4 crates
  • Ready to begin Milestone 5 (Integration) and Milestone 6 (GUI)
  • On track for MVP release

[0.2.0] - 2025-12-19 - "The Sound of Innovation" (Milestone 3: APU Complete)

Status: Phase 1 In Progress - CPU, PPU, and APU implementation complete

This release marks the completion of Milestone 3 (APU), delivering a complete, hardware-accurate NES Audio Processing Unit implementation. The APU is the most complex audio chip of the 8-bit era, and this implementation achieves cycle-accurate emulation of all 5 audio channels with zero unsafe code.

Highlights

  • Complete 2A03 APU implementation with all 5 audio channels
  • Hardware-accurate non-linear mixer with lookup tables
  • Configurable resampler (1.79 MHz → 48 kHz) with low-pass filter
  • 150 comprehensive tests passing (136 unit + 14 doc tests)
  • Zero unsafe code throughout implementation
  • Frame counter with 4-step and 5-step sequencer modes
  • Flexible DMA interface for DMC sample playback
  • Complete register implementation ($4000-$4017)

Added - APU (Audio Processing Unit) Implementation

Core Components

  • Frame Counter: 4-step and 5-step sequencer modes with cycle-accurate timing

    • 4-step mode: 240 Hz quarter frames, 120 Hz half frames
    • 5-step mode: 192 Hz quarter frames, 96 Hz half frames
    • IRQ generation on 4-step mode (optional)
    • Cycle-accurate clock generation
  • Envelope Generator: Volume control for pulse and noise channels

    • Constant volume mode (0-15)
    • Envelope decay mode (automatic fade from 15 to 0)
    • Looping and one-shot modes
    • Divider-based timing (240 Hz quarter frame clock)
  • Length Counter: Automatic channel silencing

    • 32-entry lookup table (10 to 254 cycles)
    • Halt flag support (controlled by envelope loop flag)
    • Clocked at 120 Hz (half frame)
    • Shared by pulse, triangle, and noise channels
  • Sweep Unit: Frequency modulation for pulse channels

    • Increase/decrease frequency over time
    • Configurable shift amount (0-7 bits)
    • Negate mode with channel-specific one's complement
    • Muting for out-of-range frequencies
    • Clocked at 120 Hz (half frame)

Audio Channels

  • Pulse Channel 1 & 2: Square wave synthesis

    • 4 duty cycles: 12.5%, 25%, 50%, 75%
    • 11-bit timer (54.6 Hz to 12.4 kHz output frequencies)
    • Envelope volume control (0-15)
    • Sweep unit for pitch bends
    • Length counter for automatic silencing
    • Hardware-accurate register interface ($4000-$4007)
  • Triangle Channel: Triangle wave synthesis

    • 32-step triangle wave sequence (15 → 0 → 15)
    • Linear counter (7-bit, triangle-specific timing)
    • Length counter integration
    • 11-bit timer (27.3 Hz to 12.4 kHz output frequencies)
    • Control flag (halt length & reload linear)
    • Ultrasonic frequency silencing (timer < 2)
    • Hardware-accurate register interface ($4008-$400B)
  • Noise Channel: Pseudo-random noise generation

    • 15-bit Linear Feedback Shift Register (LFSR)
    • Two modes: Long (15-bit) and Short (6-bit) for metallic sounds
    • 16-entry noise period lookup table (4-4068 CPU cycles)
    • Envelope integration for volume control
    • Length counter integration
    • Hardware-accurate register interface ($400C-$400F)
  • DMC Channel: Delta modulation sample playback

    • 1-bit delta modulation (stores changes ±2 instead of absolute values)
    • 7-bit output level (0-127)
    • 16 selectable sample rates (4.1-33.1 kHz NTSC)
    • Memory reader with DMA interface (1-4 CPU cycle stalls)
    • Sample address calculation ($C000 + A × $40)
    • Sample length calculation (L × $10 + 1 bytes)
    • Direct output level control ($4011)
    • IRQ generation on sample completion
    • Loop support for continuous playback
    • Address wrap from $FFFF → $8000 (not $0000)
    • Hardware-accurate register interface ($4010-$4013)

Audio Output

  • Non-Linear Mixer: Hardware-accurate mixing with lookup tables

    • Pulse mixing: 95.88 / ((8128.0 / sum) + 100.0)
    • TND mixing: 159.79 / ((1.0 / (sum / 100.0)) + 100.0)
    • Authentic NES audio output characteristics
    • Output range: 0.0 to ~2.0
  • Resampler: Sample rate conversion

    • Linear interpolation from APU rate (~1.789 MHz) to configurable output (default 48 kHz)
    • Ring buffer for smooth audio delivery
    • Configurable sample rate support
  • Low-Pass Filter: Optional audio filtering

    • Configurable cutoff frequency
    • Smooths high-frequency artifacts
    • Reduces aliasing

System Integration

  • Status Register ($4015): Enable/disable channels and IRQ status

    • Bit 0: Pulse 1 length > 0
    • Bit 1: Pulse 2 length > 0
    • Bit 2: Triangle length > 0
    • Bit 3: Noise length > 0
    • Bit 4: DMC bytes remaining > 0
    • Bit 6: Frame IRQ flag
    • Bit 7: DMC IRQ flag
    • Reading clears frame and DMC IRQ flags
  • Frame Counter Register ($4017): Sequencer mode control

    • Bit 6: IRQ disable flag
    • Bit 7: Mode flag (0 = 4-step, 1 = 5-step)
    • Writing resets frame counter
  • Memory Callback Interface: Flexible DMA for DMC

    • Decouples APU from CPU/memory bus
    • Allows authentic DMA cycle stealing
    • Configurable via callback function

Technical Specifications

APU Clock Rate:

  • NTSC: 1,789,773 Hz (CPU clock / 1)
  • PAL: 1,662,607 Hz (not yet implemented)

Frame Counter Rates:

  • 4-step mode: 240 Hz quarter frames, 120 Hz half frames
  • 5-step mode: 192 Hz quarter frames, 96 Hz half frames

Sample Rate:

  • Default: 48,000 Hz
  • Configurable: Any rate supported

Mixer Output:

  • Range: 0.0 to ~2.0 (before clamping)
  • Non-linear mixing matches hardware characteristics

Test Coverage

  • 150 tests total passing (136 unit tests + 14 doc tests)
  • Zero unsafe code (#![forbid(unsafe_code)] in all modules)
  • 100% test pass rate

Test Breakdown:

  • Frame counter: 6 tests
  • Envelope: 6 tests
  • Length counter: 6 tests
  • Sweep: 11 tests
  • Pulse channels: 17 tests
  • Triangle channel: 17 tests
  • Noise channel: 18 tests
  • DMC channel: 22 tests
  • APU integration: 7 tests
  • Mixer: 12 tests
  • Resampler: 9 tests
  • Doc tests: 14 tests

Code Quality

  • Zero unsafe code throughout APU implementation
  • #![forbid(unsafe_code)] enforced at crate level
  • Comprehensive rustdoc documentation for all public APIs
  • 100% clippy::pedantic compliance
  • Hardware-accurate behavior matching nestest and Visual2C02
  • Extensive use of type safety (newtype patterns)
  • No allocations in audio hot path

Documentation

  • Complete APU module documentation with examples
  • Hardware behavior documentation for all components
  • Register interface documentation ($4000-$4017)
  • Integration guide for memory callback
  • Audio mixing and resampling documentation

Changed

  • Reorganized to-dos/ folder structure
    • Moved all TODO files into phase-based hierarchy
    • 4 phases (MVP, Features, Expansion, Polish)
    • 18 milestones with dedicated folders
    • Sprint completion files moved to milestone folders

What's Included

This release adds the rustynes-apu crate to the existing CPU and PPU libraries. No desktop GUI is available yet (planned for Milestone 6). You can:

  • Build and run the comprehensive test suite (cargo test --workspace)
  • Use rustynes-apu as a library crate in your own projects
  • Explore the implementation through extensive documentation
  • Test audio generation with provided examples

Crates Included:

  • rustynes-cpu - Complete 6502 CPU emulation (46 tests)
  • rustynes-ppu - Complete 2C02 PPU emulation (83 tests)
  • rustynes-apu - Complete 2A03 APU emulation (150 tests) ✨ NEW

Coming Soon:

  • rustynes-mappers - Cartridge support (Milestone 4)
  • rustynes-core - Integration layer (Milestone 5)
  • rustynes-desktop - GUI application (Milestone 6)

Test Results

Component Tests Pass Rate Details
CPU 46/46 100% All 256 opcodes validated
PPU 83/83 100% Full rendering pipeline
APU 150/150 100% All 5 channels + mixer + resampler
Total 279/279 100% World-class accuracy

Installation

# Clone the repository
git clone https://github.com/doublegate/RustyNES.git
cd RustyNES

# Build all implemented crates
cargo build --workspace --release

# Run comprehensive test suite
cargo test --workspace

# Expected output: 279+ tests passing (46 CPU + 83 PPU + 150 APU)

# Generate documentation
cargo doc --workspace --no-deps --open

What's Next

Milestone 4 (Mappers) - February 2026:

  • Mapper trait framework
  • NROM (0) - Required for test ROMs
  • MMC1 (1) - 27.9% game coverage
  • UxROM (2) - 10.6% game coverage
  • CNROM (3) - 6.3% game coverage
  • MMC3 (4) - 23.4% game coverage
  • Total: 80%+ game compatibility

Milestone 5 (Integration) - March 2026:

  • Implement rustynes-core integration layer
  • Connect CPU + PPU + APU + Bus
  • Integrate test ROMs
  • Enable full-system validation

Milestone 6 (GUI) - June 2026:

  • Cross-platform GUI (egui + wgpu)
  • ROM loading and gameplay
  • Save states and configuration
  • Audio/video synchronization
  • MVP Release: Playable emulator with 80% game compatibility

Notes

  • This is a library-only release (no desktop GUI yet)
  • APU implementation is hardware-accurate and cycle-precise
  • DMC DMA requires memory callback integration (simple interface)
  • Zero unsafe code maintained throughout all 3 crates (CPU, PPU, APU)
  • Ready to begin Milestone 4 (Mappers) and Milestone 5 (Integration)
  • On track for MVP release by June 2026

[0.1.0] - 2025-12-19 - "Precise. Pure. Powerful." (First Official Release)

Status: Phase 1 In Progress - CPU and PPU implementation complete

This is the first official release of RustyNES, marking the completion of Milestone 1 (CPU) and Milestone 2 (PPU). Together, these milestones establish a world-class foundation for the emulation engine with 100% CPU test pass rate and 97.8% PPU test pass rate.

Highlights

  • World-class CPU implementation with 100% nestest.nes validation
  • Cycle-accurate PPU implementation with 97.8% test pass rate
  • Complete 6502 CPU with all 256 opcodes (151 official + 105 unofficial)
  • Full 2C02 PPU with VBL/NMI timing and sprite rendering
  • 144 comprehensive tests passing (56 CPU + 88 PPU)
  • Zero unsafe code throughout implementation
  • 44 test ROMs acquired for comprehensive validation
  • Solid foundation for Phase 1 MVP completion

Added

Milestone 1: CPU Implementation (Complete)

  • Cycle-accurate 6502/2A03 CPU emulation
  • All 256 opcodes (151 official + 105 unofficial)
  • All 13 addressing modes with cycle-accurate timing
  • Complete interrupt handling (NMI, IRQ, BRK, RESET)
  • Page-crossing penalty detection
  • 100% nestest.nes golden log match
  • Zero unsafe code throughout implementation
  • 46 unit tests for CPU validation

Milestone 2: PPU Implementation (Complete)

  • Dot-level 2C02 PPU rendering (341 dots x 262 scanlines)
  • Background rendering with scrolling (Loopy scrolling model)
  • Sprite rendering with 8-sprite-per-scanline limit
  • Sprite 0 hit detection
  • Sprite overflow flag handling
  • VBlank and NMI timing (cycle-accurate)
  • OAM DMA support
  • Complete PPU register implementation (PPUCTRL, PPUMASK, PPUSTATUS, etc.)
  • Palette RAM with proper mirroring
  • VRAM addressing with nametable mirroring
  • 83 unit tests for PPU validation

Documentation & Organization

  • Phase 1 TODO tracking system with milestone and sprint breakdowns
  • Comprehensive Milestone 1 documentation (overview + 5 sprint files)
  • Comprehensive Milestone 2 documentation (overview + 5 sprint files)
  • Milestone 3 (APU) TODO documentation (M3-OVERVIEW)
  • Milestone 4 (Mappers) TODO documentation (M4-OVERVIEW)
  • CPU test ROM README.md with usage instructions and test status
  • game-roms/ directory for user game ROM storage

Changed

  • Reorganized test ROM structure: moved CPU test files to test-roms/cpu/
  • Updated all documentation references to new test-roms/cpu/nestest.nes path
  • Updated README.md status to reflect Phase 1 progress (Milestone 1 + 2 complete)
  • Updated .gitignore to exclude game-roms/ and allow test-roms log files

What's Included

This release provides the core CPU and PPU crates as libraries. No desktop GUI is available yet (planned for Milestone 6). You can:

  • Build and run the comprehensive test suite (cargo test --workspace)
  • Use rustynes-cpu and rustynes-ppu as library crates in your own projects
  • Explore the implementation through extensive documentation
  • Validate accuracy against test ROMs

Crates Included:

  • rustynes-cpu - Complete 6502 CPU emulation (56 tests)
  • rustynes-ppu - Complete 2C02 PPU emulation (88 tests)

Coming Soon:

  • rustynes-core - Integration layer (Milestone 5)
  • rustynes-apu - Audio synthesis (Milestone 3)
  • rustynes-mappers - Cartridge support (Milestone 4)
  • rustynes-desktop - GUI application (Milestone 6)

Test Results

Component Tests Pass Rate Details
CPU 56/56 100% All 256 opcodes validated
PPU 88/90 97.8% 2 ignored (timing refinement)
Total 144/146 98.6% World-class accuracy

Detailed Breakdown:

  • CPU: 46 unit tests + 9 doc tests + 1 integration test (nestest.nes)
  • PPU: 83 unit tests + 1 doc test + 4 integration tests passing + 2 ignored

Test ROM Validation:

  • ✅ nestest.nes: 100% golden log match (5003+ instructions)
  • ✅ ppu_vbl_nmi.nes: Complete VBL/NMI timing suite
  • ✅ 01-vbl_basics.nes: Basic VBlank behavior
  • ✅ 01.basics.nes: Sprite 0 hit basics
  • ✅ 02.alignment.nes: Sprite 0 hit alignment
  • ⏸️ 02-vbl_set_time.nes: Ignored (requires ±51 cycle precision)
  • ⏸️ 03-vbl_clear_time.nes: Ignored (requires ±10 cycle precision)

Test ROM Acquisition:

  • 44 test ROMs downloaded and catalogued
  • 19 CPU test ROMs (nestest + blargg suite)
  • 25 PPU test ROMs (VBL/NMI + sprite hit + blargg suite)
  • 7 fully integrated, 37 awaiting integration in Milestone 5

Technical Specifications

CPU (6502/2A03):

  • 151 official opcodes (ADC, AND, ASL, BCC, BCS, BEQ, BIT, BMI, BNE, BPL, BRK, BVC, BVS, CLC, CLD, CLI, CLV, CMP, CPX, CPY, DEC, DEX, DEY, EOR, INC, INX, INY, JMP, JSR, LDA, LDX, LDY, LSR, NOP, ORA, PHA, PHP, PLA, PLP, ROL, ROR, RTI, RTS, SBC, SEC, SED, SEI, STA, STX, STY, TAX, TAY, TSX, TXA, TXS, TYA)
  • 105 unofficial opcodes (complete set implemented)
  • 13 addressing modes (Implicit, Accumulator, Immediate, Zero Page, Zero Page X/Y, Absolute, Absolute X/Y, Indirect, Indexed Indirect X, Indirect Indexed Y, Relative)
  • Cycle-accurate timing with page-crossing penalties
  • Complete interrupt handling (NMI, IRQ, BRK, RESET)

PPU (2C02):

  • Dot-accurate timing: 341 dots × 262 scanlines per frame (NTSC)
  • Background rendering with scrolling (Loopy scrolling model)
  • Sprite rendering with 8-sprite-per-scanline limit
  • Sprite 0 hit detection (pixel-perfect)
  • Sprite overflow flag handling
  • VBlank and NMI timing (cycle-accurate)
  • OAM DMA support
  • Complete PPU register implementation (PPUCTRL, PPUMASK, PPUSTATUS, OAMADDR, OAMDATA, PPUSCROLL, PPUADDR, PPUDATA)
  • Palette RAM with proper mirroring ($3F00-$3F1F, mirrored to $3FFF)
  • VRAM addressing with nametable mirroring (horizontal, vertical, single-screen, four-screen)

Code Quality

  • Zero unsafe code throughout CPU and PPU implementations
  • Comprehensive rustdoc documentation for all public APIs
  • 100% clippy::pedantic compliance
  • Rust 2021 edition with MSRV 1.75+
  • Extensive use of type safety (newtype pattern for registers and addresses)

Installation

# Clone the repository
git clone https://github.com/doublegate/RustyNES.git
cd RustyNES

# Build all implemented crates
cargo build --workspace --release

# Run comprehensive test suite
cargo test --workspace

# Expected output: 144 tests passing (56 CPU + 88 PPU)

# Generate documentation
cargo doc --workspace --no-deps --open

What's Next

Milestone 5 (Integration) - January 2026:

  • Implement rustynes-core integration layer
  • Coordinate CPU + PPU + Bus communication
  • Integrate remaining 37 test ROMs
  • Enable full-system test ROM validation

Milestone 3 (APU) - February 2026:

  • Hardware-accurate 2A03 APU synthesis
  • All 5 audio channels (2 pulse, triangle, noise, DMC)
  • Frame counter and audio mixing
  • 48 kHz output with resampling

Milestone 4 (Mappers) - February-March 2026:

  • Mapper 0 (NROM) - Required for test ROMs
  • Mapper 1 (MMC1/SxROM) - 27.9% game coverage
  • Mapper 2 (UxROM) - 10.6% game coverage
  • Mapper 3 (CNROM) - 6.3% game coverage
  • Mapper 4 (MMC3/TxROM) - 23.4% game coverage
  • Total: 80%+ game compatibility

Milestone 6 (Desktop GUI) - March-April 2026:

  • Cross-platform GUI with egui + wgpu
  • ROM loading and gameplay
  • Save states and configuration
  • Input handling (keyboard + gamepad)

MVP Release - May 2026:

  • Complete playable emulator
  • 80%+ game compatibility
  • 85%+ TASVideos accuracy suite pass rate

Notes

  • This is a library-only release (no desktop GUI yet)
  • Two PPU tests ignored pending cycle-accurate timing refinement (not failures)
  • CPU implementation is world-class: 100% validation against nestest.nes golden log
  • PPU implementation is excellent: 97.8% test pass rate with VBL/NMI and sprite hit working
  • Ready to begin Milestone 5 (Integration), Milestone 3 (APU), and Milestone 4 (Mappers)
  • On track for MVP release by May 2026 (ahead of original June 2026 target)

Project Setup - 2025-12-18

Added

  • Initial project structure with 10 workspace crates
  • Comprehensive documentation suite (73 markdown files, 52,402 lines)
    • CPU documentation (6502 specification, timing, opcodes)
    • PPU documentation (2C02 specification, rendering, scrolling)
    • APU documentation (2A03 specification, all 5 channels)
    • Mapper documentation (NROM, MMC1, MMC3, etc.)
    • API reference documentation
    • Development guides (BUILD, CONTRIBUTING, TESTING, DEBUGGING)
    • Format specifications (iNES, NES 2.0, NSF, FM2)
  • GitHub project templates
    • Issue templates (bug report, feature request)
    • Pull request template
    • Code of Conduct
    • Contributing guidelines
    • Security policy
    • Support documentation
  • Development infrastructure
    • Dependabot configuration for automated dependency updates
    • CODEOWNERS file for code review assignments
  • Project documentation
    • README.md with feature overview
    • ROADMAP.md with development timeline
    • ARCHITECTURE.md with system design
    • OVERVIEW.md with project philosophy
    • CHANGELOG.md (this file)

Documentation

  • CPU specifications: 6502 instruction set, timing tables, unofficial opcodes
  • PPU specifications: 2C02 rendering pipeline, dot-level timing, scrolling mechanics
  • APU specifications: Audio channels, mixing, frame counter, DMC channel
  • Mapper specifications: NROM, MMC1, MMC3, and 8 additional mappers
  • API documentation: Core API, save states, configuration, Lua scripting
  • Testing guides: Test ROM usage, nestest golden log, game testing strategy
  • Build documentation: Multi-platform build instructions, cross-compilation
  • File format documentation: iNES, NES 2.0, NSF, FM2, FDS, UNIF

Development Phases

RustyNES follows a phased development approach. See ROADMAP.md for complete details.

Phase 1: MVP (Target: June 2026)

  • Cycle-accurate 6502/2A03 CPU implementation
  • Dot-level 2C02 PPU rendering
  • Hardware-accurate 2A03 APU synthesis
  • Mappers 0, 1, 2, 3, 4 (77.7% game coverage)
  • Cross-platform desktop GUI (egui + wgpu)
  • Save states and battery saves
  • Gamepad support
  • 85% TASVideos test suite pass rate

Phase 2: Advanced Features (Target: December 2026)

  • RetroAchievements integration (rcheevos)
  • GGPO rollback netplay (backroll-rs)
  • Lua 5.4 scripting API
  • TAS recording/playback (FM2 format)
  • Integrated debugger (CPU, PPU, APU viewers)
  • Rewind, fast-forward, slow-motion
  • 95% TASVideos test suite pass rate

Phase 3: Expansion (Target: June 2027)

  • WebAssembly build with PWA support
  • Expansion audio (VRC6, VRC7, MMC5, FDS, N163, 5B)
  • Additional mappers (target: 200+ total)
  • Mobile platform support (Android, iOS)
  • CRT/NTSC shader framework
  • 98% TASVideos test suite pass rate

Phase 4: Polish (Target: December 2027)

  • Advanced video filters and shaders
  • TAS editor with frame-by-frame editing
  • Enhanced debugger features
  • Performance optimizations
  • 300+ mapper implementations
  • 100% TASVideos accuracy test pass rate
  • v1.0.0 release

Version History

[0.0.1] - 2025-12-18 (Project Initialization)

Status: Pre-implementation (Architecture & Documentation Complete)

This release represents the completion of the project planning phase. No executable emulator exists yet, but all architectural decisions have been made and comprehensively documented.

Added

  • Project repository structure
  • Workspace configuration with 10 crates
  • Complete documentation suite (73 files)
  • GitHub project infrastructure
  • Development guidelines and policies
  • Roadmap and milestone definitions

Notes

  • No functional emulation code in this release
  • Focus on planning, architecture, and documentation
  • Ready to begin Phase 1 implementation (CPU core)

Changelog Conventions

Categories

We use the following categories for changes:

  • Added: New features
  • Changed: Changes to existing functionality
  • Deprecated: Soon-to-be removed features
  • Removed: Removed features
  • Fixed: Bug fixes
  • Security: Security vulnerability fixes

Versioning

RustyNES follows Semantic Versioning:

  • MAJOR version (X.0.0): Incompatible API changes, major features
  • MINOR version (0.X.0): Backward-compatible functionality additions
  • PATCH version (0.0.X): Backward-compatible bug fixes

Pre-1.0.0

During pre-1.0 development:

  • Breaking changes may occur in any version
  • APIs are not guaranteed to be stable
  • Focus is on reaching feature completeness

Links


Note: This changelog will be actively maintained as the project progresses. Each significant change will be documented here following the Keep a Changelog format.