Some checks failed
CI / rust (push) Has been cancelled
Fix 9 clippy warnings across mmc5 mapper and desktop frontend. Sync api_contract.md and architecture.md with actual public surface.
4.8 KiB
4.8 KiB
Architecture
This document describes how the workspace is organized internally.
Use ../README.md for project overview, integration.md for host integration, and api_contract.md for supported public surface.
Workspace Layout
nesemu: reusable emulation library and host-facing runtime wrapperscrates/nesemu-adapter-api: backend-agnostic adapter traitscrates/nesemu-adapter-headless: headless/null adapter implementationscrates/nesemu-desktop: GTK4 desktop frontend that consumes the root crate
High-Level Layers
The workspace is split into four layers:
native_coreOwns emulation correctness and hardware-facing behavior.runtimeWraps the core with host-oriented execution, pacing, lifecycle control, and save-state helpers.- adapter crates Define integration edges without coupling the core to a concrete backend.
- desktop frontend Serves as a consumer and manual test harness, not as part of the library contract.
Core Module Boundaries
src/native_core/cpu: 6502 execution, addressing helpers, opcode dispatchsrc/native_core/ppu: rendering pipeline, VRAM/OAM/register behaviorsrc/native_core/apu: timing, channel state, and audio-facing hardware statesrc/native_core/bus: component wiring and device-visible read/write semanticssrc/native_core/mapper: cartridge mapper abstraction and concrete implementationssrc/native_core/ines: iNES parsing and ROM metadatasrc/native_core/state_io: shared state decoding helpers
Runtime Module Boundaries
src/runtime/core.rs:NesRuntimeorchestration around CPU + bussrc/runtime/state.rs: runtime save/load state formatsrc/runtime/audio.rs: interim PCM synthesis from core statesrc/runtime/timing.rs: frame pacing types and video timingsrc/runtime/types.rs: public joypad-related types and helperssrc/runtime/constants.rs: frame dimensions and video constantssrc/runtime/error.rs:RuntimeErrortype definitionssrc/runtime/ring_buffer.rs: lock-free ring buffer for audio sample transportsrc/runtime/adapters.rs: adapter bridge types (behindadapter-apifeature)src/runtime/host/io.rs: host IO traits and null implementationssrc/runtime/host/executor.rs: per-frame execution unitsrc/runtime/host/clock.rs: clock abstraction and pacing implementationssrc/runtime/host/loop_runner.rs: host loop wrapper for frame-based executionsrc/runtime/host/session.rs: app lifecycle wrapper for running, pausing, and stepping
Data Flow
At a high level, the runtime stack looks like this:
- ROM bytes are parsed into cartridge metadata and ROM contents.
- A mapper is created from the ROM description.
NativeBuswires CPU, PPU, APU, mapper, and input-visible state together.Cpu6502executes against the bus.NesRuntimewraps the core to provide frame-level execution, rendering, and save-state helpers.RuntimeHostLoopandClientRuntimeadapt the runtime to host application control flow.
Public Surface Strategy
The root crate re-exports the integration-critical API so external users do not need to depend on the internal module layout.
The design intent is:
- external clients use root re-exports and
runtime - advanced clients may use
native_core - internal module paths are free to evolve faster than the root surface
Host Responsibilities
The library intentionally leaves these concerns to the host application:
- windowing and presentation backend
- audio device/output backend
- platform input mapping
- ROM file I/O
- persistent state storage
Input, Video, and Audio Contracts
JoypadButtonsare exposed in the public order[Up, Down, Left, Right, A, B, Start, Select]InputProviderpolls the current button state from the hostVideoOutputreceives RGBA framesAudioOutputreceives mixed mono samples- port 2 is currently treated as disconnected in the exposed core API
Save-State Design
NativeBus::save_stateandNativeBus::load_statepersist low-level emulator stateNesRuntimeextends that state with runtime metadata such as frame number and active buttons- save-state payloads are versioned for crate-internal use, not for long-term external compatibility
Testing Layout
- CPU tests are grouped by behavior, interrupts, and invariants
- mapper tests are grouped by mapper family and property-style checks
- runtime tests cover frame execution, pacing, state roundtrips, and lifecycle control
tests/public_api.rsexercises the supported public flow as a black-box consumer
Constraints And Tradeoffs
- no platform backend is bundled beyond the GTK desktop example
- audio mixing in
runtime/audio.rsis intentionally interim - optional adapter crates are thin integration layers, not mandatory parts of the core runtime
- compatibility promises are defined in
docs/api_contract.md, not by internal module visibility