# 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 wrappers - `crates/nesemu-adapter-api`: backend-agnostic adapter traits - `crates/nesemu-adapter-headless`: headless/null adapter implementations - `crates/nesemu-desktop`: GTK4 desktop frontend that consumes the root crate ## High-Level Layers The workspace is split into four layers: 1. `native_core` Owns emulation correctness and hardware-facing behavior. 2. `runtime` Wraps the core with host-oriented execution, pacing, lifecycle control, and save-state helpers. 3. adapter crates Define integration edges without coupling the core to a concrete backend. 4. 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 dispatch - `src/native_core/ppu`: rendering pipeline, VRAM/OAM/register behavior - `src/native_core/apu`: timing, channel state, and audio-facing hardware state - `src/native_core/bus`: component wiring and device-visible read/write semantics - `src/native_core/mapper`: cartridge mapper abstraction and concrete implementations - `src/native_core/ines`: iNES parsing and ROM metadata - `src/native_core/state_io`: shared state decoding helpers ## Runtime Module Boundaries - `src/runtime/core.rs`: `NesRuntime` orchestration around CPU + bus - `src/runtime/state.rs`: runtime save/load state format - `src/runtime/audio.rs`: interim PCM synthesis from core state - `src/runtime/timing.rs`: frame pacing types and video timing - `src/runtime/types.rs`: public joypad-related types and helpers - `src/runtime/host/io.rs`: host IO traits and null implementations - `src/runtime/host/executor.rs`: per-frame execution unit - `src/runtime/host/clock.rs`: clock abstraction and pacing implementations - `src/runtime/host/loop_runner.rs`: host loop wrapper for frame-based execution - `src/runtime/host/session.rs`: app lifecycle wrapper for running, pausing, and stepping ## Data Flow At a high level, the runtime stack looks like this: 1. ROM bytes are parsed into cartridge metadata and ROM contents. 2. A mapper is created from the ROM description. 3. `NativeBus` wires CPU, PPU, APU, mapper, and input-visible state together. 4. `Cpu6502` executes against the bus. 5. `NesRuntime` wraps the core to provide frame-level execution, rendering, and save-state helpers. 6. `RuntimeHostLoop` and `ClientRuntime` adapt 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 - `JoypadButtons` are exposed in the public order `[Up, Down, Left, Right, A, B, Start, Select]` - `InputProvider` polls the current button state from the host - `VideoOutput` receives RGBA frames - `AudioOutput` receives mixed mono samples - port 2 is currently treated as disconnected in the exposed core API ## Save-State Design - `NativeBus::save_state` and `NativeBus::load_state` persist low-level emulator state - `NesRuntime` extends 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.rs` exercises 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.rs` is 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