The rustynes-libretro crate has been fully implemented, providing a cycle-accurate NES emulation core for the RetroArch ecosystem.
-
Phase 1: Project Initialization
- Scaffolded the
rustynes-libretrocrate undercrates/and added it to the workspace. - Linked dependencies:
rustynes-core(cycle-accurate emulation) andrust-libretrov0.3.2 (API bindings).
- Scaffolded the
-
Phase 2: Lifecycle & Initial State
- Integrated
on_load_gamewith RetroArch's API. - Handled the
RustyNesLibretrostruct initialization and cleanup automatically, backing it by a safe instance ofNes.
- Integrated
-
Phase 3: Core Emulation Hooks
- Implemented
on_runexecutingnes.run_frame(). - Routed input mapping queries using RetroArch's Joypad API.
- Pushed video output safely to the
VideoContextAPI and delivered precise 44100Hz dual-channel audio dynamically viabatch_audio_samples.
- Implemented
-
Phase 4: Save States and Direct Memory Mapping
- Added new backend memory accessors
wram(),vram(), andsram()securely without sacrificing Rust's memory isolation model. - Embedded RetroAchievements compatibility by mapping memory into
get_memory_dataandget_memory_size. - Added deterministic snapshotting support by exposing
snapshot_core_intosize querying withget_serialize_size, and hooking states throughon_serialize/on_unserialize.
- Added new backend memory accessors
-
Phase 5: Bindgen ROM Loading Bug Fix
- Diagnosed a core failure where
rust-libretro-sysbindgenrules generated theretro_game_infoandretro_game_info_extas 1-byte opaque structs. - Fixed ROM extraction and path detection by bypassing
rust_libretro'sretro_game_infomacros natively. - Bound directly to
RETRO_ENVIRONMENT_GET_GAME_INFO_EXT(callback66) via a newly implemented internal#[repr(C)] struct RetroGameInfoExtexplicitly matching the C layout fromlibretro.h.
- Diagnosed a core failure where
-
Phase 6: Audio/Video Format Fixes
- Video (Color Swaps): Fixed the bug where the sky rendered pink.
rustynes-corenaturally outputsRGBA8(R, G, B, A order), but Libretro'sXRGB8888pixel format interprets bytes in native little-endian layout (B, G, R, X). Passing the raw buffer blindly caused Red and Blue to map inversely. Pre-allocated avideo_bufferthat clones the core framebuffer and performs a linear-time, allocation-free byte-swap on theRandBchannels.
- Video (Color Swaps): Fixed the bug where the sky rendered pink.
-
Phase 7: Audio Pitch Synchronization Fix
- Diagnosed an overarching pitch-shifting distortion caused by an explicit sample rate mismatch. The emulator internally synthesizes standard dual-channel audio at
44100Hz, buton_get_av_infoerroneously informed RetroArch that the core produced a48000Hzstream. This forced RetroArch to consume and play the incoming 44.1kHz sample batches at a 48kHz playback rate, inherently accelerating playback speed, pitching the audio up, and severely dampening bass frequencies. - Adjusted the
timing.sample_ratereturned to RetroArch to match RustyNES's native44100.0output perfectly, restoring 1:1 playback fidelity.
- Diagnosed an overarching pitch-shifting distortion caused by an explicit sample rate mismatch. The emulator internally synthesizes standard dual-channel audio at
-
Phase 8: Upstream Libretro Integrations
- Staged the
rustynes_libretro.infometadata file into thelibretro-superbuildbot infrastructure. - Injected
rustynescompilation rules andgitrepository endpoints into standardlinux,windows, andosxcore recipes inlibretro-super. - Authored the user-facing Libretro documentation (
docs/library/rustynes.md) detailing supported features, inputs, and database associations. - Linked the documentation into the core
mkdocs.ymlnavigation structure fordocs.libretro.com. - Wrote a unified Bash submission script (
submit_libretro_prs.sh) to automate forking and pushing these branches directly to GitHub using the local user's authenticatedghenvironment.
- Staged the
- ✅ Workspace validation via
cargo check --workspacepasses entirely. - ✅ Memory isolation boundaries remain safe.
- ✅ Save state and memory access behaviors are compatible with RetroArch environments (e.g. RetroAchievements).
- ✅ Loading archived ROMs directly natively via RetroArch buffers succeeds flawlessly.
- ✅ Automated submission script (
submit_libretro_prs.sh) is prepared and verified to target correct branches.
Based on your request, AGENTS.md was thoroughly updated from CLAUDE.md:
- Updated toolchain rules to Rust 1.96 and edition 2024.
- Emphasized strict testing strategies (e.g., pinning ROM test expectations).
- Highlighted the rule prohibiting commercial ROM commits, prioritizing
tests/roms/external/. - Updated performance boundaries (
<= 2 ms/frame headless) and architectural constraints forrustynes-coreacting as the sole cross-crate boundary facade.