# NESER Architecture

> NESER — NES Emulator in Rust

## Overview

NESER is a cycle-accurate NES (Nintendo Entertainment System) emulator written in Rust, built on an architecture that supports multiple emulated hardware targets. It supports three frontend targets: a native desktop window (winit + OpenGL), a terminal-based TUI ROM launcher, and a WebAssembly-powered browser frontend. The emulator implements the core NES hardware — CPU, PPU, APU, and bus — as well as over 200 cartridge mappers, multiple input device types, debugging tools, save states, and an autorun recording/playback system.

The codebase is roughly 183,000 lines of Rust, with additional JavaScript for the web frontend and Python tooling for ROM management.

As of version 0.3.0, NESER has been refactored to introduce a hardware-agnostic `Emulator` trait and a `Console` enum that wraps the NES, Game Boy, and Game Boy Advance implementations. This allows the native frontend and GL backend to dispatch common operations through the trait instead of matching on specific console variants or using NES-specific types directly. The architecture is designed to be extensible for future emulated systems while maintaining a clean separation between hardware-specific logic and shared platform/frontend code.

## High-Level Architecture

```none
┌───────────────────────────────────────────────────────┐
│                     Frontends                         │
│  ┌─────────────-─┐ ┌──────────────┐ ┌──────────────┐  │
│  │Native Frontend│ │ TUI Frontend │ │ WASM Frontend│  │
│  │(Desktop, GL)  │ │ (Terminal)   │ │ (Browser)    │  │
│  └──────┬──────-─┘ └──────┬───────┘ └──────┬───────┘  │
│         │                │                │           │
│         └────────────────┼────────────────┘           │
│                          ▼                            │
│  ┌─────────────────────────────────────────────────┐  │
│  │  Console enum + Emulator trait                  │  │
│  │  (src/platform/emulator.rs)                     │  │
│  │  Hardware-agnostic interface: run_tick, render, │  │
│  │  audio, input, save/load state, reset           │  │
│  │  Variants: Nes, GameBoy, GameBoyAdvance         │  │
│  └──────────────────────┬─────────────────────────-┘  │
│                         │                             │
│                         ▼                             │
│  ┌─────────────────────────────────────────────────┐  │
│  │           NES Emulator (src/nes/)               │  │
│  │  Nes struct orchestrates CPU ↔ PPU ↔ APU ↔ Bus  │  │
│  └──────────┬──────────────────────────┬───────────┘  │
│             │                          │              │
│    ┌────────▼────────┐       ┌─────────▼──────────┐   │
│    │    CPU (6502)   │       │    PPU (2C02)      │   │
│    │  Opcodes, DMA,  │       │  Background,       │   │
│    │  Interrupts     │       │  Sprites, Timing   │   │
│    └────────┬────────┘       └─────────┬──────────┘   │
│             │                          │              │
│    ┌────────▼──────────────────────────▼───────────┐  │
│    │                    Bus                        │  │
│    │  Address routing: CPU RAM, PPU regs, APU regs,│  │
│    │  OAM DMA, Controller I/O, Mapper/Cartridge    │  │
│    └────────┬──────────────────────────┬───────────┘  │
│             │                          │              │
│    ┌────────▼────────┐       ┌─────────▼──────────┐   │
│    │   APU (2A03)    │       │    Cartridge       │   │
│    │ Pulse, Triangle,│       │  iNES/NES2.0 parser│   │
│    │ Noise, DMC      │       │  207 Mappers       │   │
│    └─────────────────┘       └────────────────────┘   │
│                                                       │
│  ┌─────────────────────────────────────────────────┐  │
│  │  Supporting Systems                             │  │
│  │  Input · Debugging · Autorun · Save States      │  │
│  └─────────────────────────────────────────────────┘  │
│                                                       │
│  ┌─────────────────────────────────────────────────┐  │
│  │  Shared Platform (src/)                         │  │
│  │  AppContext · FrontendConfig · Audio · Rendering│  │
│  └─────────────────────────────────────────────────┘  │
└───────────────────────────────────────────────────────┘
```

The emulator is designed around a **multi-layer architecture**:

- **Emulator trait + Console enum** (`src/platform/emulator.rs`): The `Emulator` trait defines the common interface that every emulated system must implement (run, render, audio, input, save/load state, reset — 22 methods total). `Nes`, `GameBoy`, and `Gba` implement the trait in their respective modules. The `Console` enum wraps all three systems and delegates common methods through `as_core()`/`as_core_mut()` (which return `&dyn Emulator`), keeping a single pair of match arms instead of one per method. System-specific features (NES debugging, PPU viewer, Zapper) are still accessed by matching on `Console::Nes`.
- **NES emulator** (`src/nes/`): All NES-specific hardware lives under this namespace. The `Nes` struct in `src/nes/console/nes.rs` orchestrates the per-cycle stepping of CPU, PPU, APU, and Bus.
- **Shared platform** (`src/platform/`): `FrontendConfig` (src/platform/config.rs), `AppContext` (src/platform/app_context.rs), audio infrastructure, and system-agnostic toast formatters are shared across all emulated systems.
- **Bus-centric hardware**: Within the NES, the `Bus` struct routes memory reads and writes between the CPU, PPU registers, APU registers, RAM, OAM DMA, controller ports, and the cartridge mapper.

## Binaries and Scripts

### Rust Binaries

| Binary | Source | Feature | Description |
| --------- | -------- | --------- | ------------- |
| `neser` | `src/main.rs` | `native` (default) | Main emulator with native desktop window (winit + OpenGL), audio, gamepad input, shader filters, debugger, and autorun support. |
| `joysticks` | `src/bin/joysticks.rs` | `native` | Diagnostic utility that lists connected joysticks/gamepads, displays their GUID, and shows real-time axis/button state. |

The `src/bin/roms.rs` file is a library binary (accessed via `cargo run --bin roms`) that provides ROM management commands: `list` (scan a directory for NES ROMs), `info` (parse and display iNES/NES2.0 header details), and `infoall` (batch info for all ROMs).

### Shell Scripts

| Script | Description |
| -------- | ------------- |
| `scripts/build_web.sh` | Builds the WASM target with `cargo build --target wasm32-unknown-unknown --features wasm`, runs `wasm-bindgen` to generate JS glue code into `web/pkg/`, then bundles the web frontend with `npx vite build` into `dist/`. |
| `scripts/run_web.sh` | Symlinks `web/roms/` into `dist/` for ROM directory browsing, then starts a local HTTP server (`python3 -m http.server`) in `dist/` for testing the browser frontend. |
| `scripts/test-dir.sh` | Runs Rust tests for specific source directories. Converts directory paths (e.g., `src/nes/cartridge`) to `cargo test` module filters. Supports `--skip-integration` and `--list` flags. Used by CI to conditionally run tests based on changed files. |

### Python Tools

| Tool | Description |
| ------ | ------------- |
| `scripts/sort_roms.py` | Sorts ROM files into mapper-numbered subdirectories based on their iNES header. |
| `scripts/package_release.py` | Builds per-target release archives with a top-level `neser/` directory. Includes the binary, runtime resources, README, LICENSE, config example, fonts, and only shader files reachable from configured shader presets. Excludes development scripts. |
| `scripts/verify_release_package.py` | Verifies release archive manifests for `.tar.gz` and `.zip`, checks Unix executable permissions when requested, extracts packages to a temporary directory, and can run a smoke command such as `./neser --version` from the package root. |
| `scripts/disassemble_rom.py` | Disassembles a NES ROM file and prints 6502 assembly output. |
| `scripts/display_audio_output.py` | Visualizes APU audio output data for debugging audio issues. |
| `scripts/mappertool/` | A Textual-based TUI application for browsing and managing a ROM database, inspecting mapper assignments, and cross-referencing ROM files with the embedded ROM database. |
| `scripts/scraper/` | Scrapes NES cartridge databases (NesCartDB, NES 2.0 XML) into a local SQLite database for ROM identification and mapper research. |

## Directory Structure

### `src/` — Rust Source Code

#### Platform Layer (Hardware-Agnostic)

| File | Description |
| ------ | ------------- |
| `src/platform/emulator.rs` | `Emulator` trait — defines the common interface (22 methods) for all emulated systems: `run_tick`, `is_ready_to_render`, `screen_snapshot`, `get_sample`, `set_button`, `save_state_bytes`/`load_state_bytes`, `reset`, etc. `Console` enum wraps `Box<Nes>` and `Box<GameBoy>`, delegating common methods through `as_core()`/`as_core_mut()`. System-specific features accessed via variant matching (`Console::Nes`). |
| `src/platform/config.rs` | `FrontendConfig` struct — generic frontend settings (audio, video, autorun, debugger, window, metadata paths) shared across all emulated systems. Includes `resolved_metadata_db_path()`, `resolved_image_cache_path()`, and `resolved_favorites_path()` helpers. |
| `src/platform/app_context.rs` | `AppContext` — shared application state including configuration, ROM database, and toast notification manager. Wrapped in `Rc<RefCell<>>` for interior mutability. |
| `src/platform/catalog/` | Shared ROM catalog module — discovers ROMs, parses headers, enriches entries with metadata and cover art. Used by both TUI and native graphical frontends. |
| `src/platform/catalog/mod.rs` | `load_catalog()` builds sorted `Vec<RomEntry>` from disk scan; `enrich_catalog()` integrates metadata matching and cover art downloading. |
| `src/platform/catalog/rom_entry.rs` | `RomEntry` struct — a discovered ROM enriched with iNES header data, ROM DB lookup results, TheGamesDB metadata (genres, overview, rating, etc.), cover art paths, and favorite status. |
| `src/platform/catalog/favorites.rs` | `Favorites` struct — persistent favorites storage backed by `~/.neser/favorites.json`. Supports load, toggle, save, and contains operations. |
| `src/platform/metadata/` | TheGamesDB metadata access via SQLite (`rusqlite`). |
| `src/platform/metadata/db.rs` | `MetadataDb` — opens `metadata.db` and queries game metadata (title, overview, genres, release date, players, rating, image filenames). |
| `src/platform/metadata/matcher.rs` | Fuzzy title matching using `strsim::jaro_winkler` to link ROM DB names to TheGamesDB entries. |
| `src/platform/image_cache/` | Cover art download and caching system. Downloads front boxart and screenshots from TheGamesDB CDN into `~/.neser/image_cache/` using `reqwest`. |

#### NES Emulation (`src/nes/`)

All NES-specific hardware and supporting code lives under `src/nes/`.

| Directory/File | Description |
| ---------------- | ------------- |
| `src/nes/mod.rs` | Module declarations for all NES sub-modules. |
| `src/nes/console/` | Top-level NES orchestration. |
| `src/nes/console/nes.rs` | The `Nes` struct — creates and owns CPU, PPU, APU, and Bus. Runs the master clock cycle loop. Handles save state capture/restore, cartridge insertion, and reset logic. Implements the `Emulator` trait for system-agnostic dispatch. |
| `src/nes/console/config.rs` | `Config` struct (composition of `FrontendConfig` + `NesConfig`), `NesConfig` struct (NES-specific hardware settings), and CLI argument parser. Defines all command-line flags, config file loading, and hardware/timing/input settings. |
| `src/nes/console/cartridge_catalog.rs` | Scans directories for NES ROMs and builds/caches a CSV catalog of discovered cartridges for the TUI launcher. |
| `src/nes/console/ram_init.rs` | RAM initialization modes: `Zero`, `Random`, and `SeededRandom` for deterministic test setups. |
| `src/nes/cpu/` | MOS 6502 CPU implementation. |
| `src/nes/cpu/cpu.rs` | The `Cpu` struct — register state, instruction fetch/decode/execute loop, interrupt handling (NMI, IRQ, BRK), and DMA integration. |
| `src/nes/cpu/opcode.rs` | Opcode definitions and the instruction lookup table covering all official and unofficial 6502 opcodes. |
| `src/nes/cpu/master_clock.rs` | Master clock divider that coordinates CPU, PPU, and APU cycle ratios for accurate NTSC/PAL timing. |
| `src/nes/cpu/dma.rs` | OAM DMA and DMC DMA transfer logic (test-only module). |
| `src/nes/ppu/` | Picture Processing Unit (2C02/2C07) implementation. |
| `src/nes/ppu/ppu.rs` | The `Ppu` struct — coordinates all PPU subsystems per scanline/cycle. Contains a nested `ppu/` subdirectory with `tick.rs` for single-cycle PPU execution logic. |
| `src/nes/ppu/background.rs` | Background tile fetching, shift registers, and fine-scroll handling. |
| `src/nes/ppu/sprites.rs` | Sprite evaluation, OAM secondary buffer, and sprite-0 hit detection. |
| `src/nes/ppu/rendering.rs` | Pixel compositing — merges background and sprite layers with priority logic. |
| `src/nes/ppu/memory.rs` | PPU memory map — nametable mirroring, palette RAM, pattern table access through the cartridge mapper. |
| `src/nes/ppu/registers.rs` | PPU register interface ($2000–$2007) including the internal v/t scroll latches and read buffer. |
| `src/nes/ppu/timing.rs` | Scanline and dot-accurate timing, VBlank/pre-render logic, even/odd frame handling. |
| `src/nes/ppu/screen_buffer.rs` | Double-buffered 256×240 framebuffer for completed frames. |
| `src/nes/ppu/color_effects.rs` | Emphasis bits and grayscale color effects. |
| `src/nes/ppu/status.rs` | PPU status register ($2002) with VBlank, sprite-0 hit, and overflow flags. |
| `src/nes/apu/` | Audio Processing Unit (2A03) implementation. |
| `src/nes/apu/apu.rs` | The `Apu` struct — mixer output, frame counter sequencing, sample generation. |
| `src/nes/apu/pulse.rs` | Two pulse wave channels with sweep and envelope. |
| `src/nes/apu/triangle.rs` | Triangle wave channel with linear counter. |
| `src/nes/apu/noise.rs` | Noise channel with LFSR and envelope. |
| `src/nes/apu/dmc.rs` | Delta Modulation Channel — sample playback with DMA fetches. |
| `src/nes/apu/envelope.rs` | Shared envelope generator used by pulse and noise channels. |
| `src/nes/apu/frame_counter.rs` | APU frame counter (4-step/5-step modes) driving length counter and envelope clocks. |
| `src/nes/apu/length_counter.rs` | Shared length counter used by pulse, triangle, and noise channels. |
| `src/nes/bus/` | System bus connecting all hardware components. |
| `src/nes/bus/bus.rs` | The `Bus` struct — main address decoding and routing for the CPU address space ($0000–$FFFF). Manages device dispatch for reads/writes. |
| `src/nes/bus/ram_device.rs` | 2KB CPU RAM ($0000–$07FF, mirrored to $1FFF). |
| `src/nes/bus/ppu_device.rs` | Routes PPU register access ($2000–$3FFF). |
| `src/nes/bus/apu_device.rs` | Routes APU register access ($4000–$4017). |
| `src/nes/bus/oam_dma_device.rs` | OAM DMA transfer initiation ($4014). |
| `src/nes/bus/controller_device.rs` | Controller port I/O ($4016–$4017), supporting standard joypads, Four Score, Zapper, Arkanoid paddle, and Famicom expansion devices. |
| `src/nes/bus/mapper_device.rs` | Routes cartridge address space ($4018–$FFFF) to the mapper. |

#### Cartridge and Mapper System

| Directory/File | Description |
| ---------------- | ------------- |
| `src/nes/cartridge/` | Cartridge loading, ROM parsing, and mapper implementations. |
| `src/nes/cartridge/cartridge.rs` | `Cartridge` struct — loads ROM files, parses iNES/NES2.0 headers, creates the appropriate mapper, and manages save files (.sav) and save states (.state). |
| `src/nes/cartridge/ines.rs` | iNES and NES 2.0 header parser — extracts mapper number, PRG/CHR ROM sizes, mirroring, battery backup, timing mode, and console type. |
| `src/nes/cartridge/mapper.rs` | `Mapper` trait definition and `mapper_registry!` macro that maps mapper numbers to concrete implementations. Contains the factory function `create_mapper()`. **207 mappers** are currently registered. |
| `src/nes/cartridge/base_mapper.rs` | `BaseMapper` — shared infrastructure for all mappers: PRG/CHR bank selection (signed index with modulo wrapping), PRG-RAM allocation, mirroring control, and save-state banking snapshots. |
| `src/nes/cartridge/common.rs` | Shared types: `ChrMemory` (CHR-ROM/RAM), `PrgRam`, `BankSwitch`, `BankedRom`, and `StateSnapshot` trait for mapper serialization. |
| `src/nes/cartridge/mapper_templates.rs` | Reusable mapper templates: `SimpleFixedPrgMapper`, `SimpleBankedPrgMapper`, `DualBank32Mapper` for common banking patterns. |
| `src/nes/cartridge/cpu_cycle_irq.rs` | CPU cycle-based IRQ counter shared by multiple mappers. |
| `src/nes/cartridge/hardware_type.rs` | Hardware type detection for NES vs Famicom variants. |
| `src/nes/cartridge/rom_db.rs` | ROM database lookup by CRC32 — identifies known ROMs for auto-detection of controller types, hardware quirks, and region hints. |
| `src/nes/cartridge/rom_db.csv` | CSV database of ~10,400 known ROMs with CRC32, name, country, hardware, mapper, submapper, mirroring, PRG/CHR sizes, battery flag, VS hardware/PPU types, and expansion type. |
| `src/nes/cartridge/test_helpers.rs` | Test utilities for mapper unit tests. |

| `src/nes/cartridge/` (cont.) | |

##### Mapper Implementations by Manufacturer

| Directory | Mapper Count | Notable Mappers |
|-----------|:------------:|-----------------|
| `src/nes/cartridge/nintendo/` | 22 | NROM (0), MMC1 (1), UxROM (2), CNROM (3), MMC3 (4), MMC5 (5), AxROM (7), MMC2/MMC4 (9/10), FDS (20), VS System (99) |
| `src/nes/cartridge/konami/` | 7 | VRC1 (75), Mapper 151 (151), VRC2/VRC4 (21–25), VRC3 (73), VRC6 (24/26), VRC7 (85) |
| `src/nes/cartridge/namco/` | 5 | Namco 118 (206), Namco 163 (19), Namcot 3425/3443/3446 |
| `src/nes/cartridge/sunsoft/` | 5 | Sunsoft-2 (93), Sunsoft-3 (67), Sunsoft-4 (68), FME-7 (69) |
| `src/nes/cartridge/irem/` | 5 | G-101 (32), H-3001 (65), TAM-S1 (97), LROG017 (77), NINA/Tengen (34) |
| `src/nes/cartridge/jaleco/` | 7 | JF-10 through JF-19, SS88006 (18), Mapper 87 |
| `src/nes/cartridge/taito/` | 4 | TC0190 (33/48), TC0350 (206 variant), X1-005 (80), X1-017 (82) |
| `src/nes/cartridge/bandai/` | 3 | Bandai FCG (16/153/159), Mapper 70, Mapper 96 |
| `src/nes/cartridge/sachen/` | 4 | Sachen mappers (36, 132, 133, 243) |
| `src/nes/cartridge/camerica/` | 1 | Camerica/Codemasters (71) |
| `src/nes/cartridge/tengen/` | 1 | RAMBO-1 (64) |
| `src/nes/cartridge/unlicensed/` | 136 | Multicarts, pirate mappers, bootleg boards (Color Dreams, Action 53, JY Company, and many numbered mappers) |

#### Input System

| Directory/File | Description |
| ---------------- | ------------- |
| `src/nes/input/` | NES input device implementations. |
| `src/nes/input/controller.rs` | `ControllerType` enum and input abstraction layer. |
| `src/nes/input/nes_joypad.rs` | Standard NES joypad with 8-button serial protocol. |
| `src/nes/input/arkanoid_controller.rs` | Arkanoid paddle controller with analog position and trigger. |
| `src/nes/input/zapper.rs` | NES Zapper light gun with light detection. |
| `src/nes/input/power_pad.rs` | Power Pad (Family Trainer) mat controller. |
| `src/nes/input/snes_adapter.rs` | SNES-to-NES controller adapter. |

#### Game Boy Emulation (`src/gb/`)

All Game Boy (DMG) hardware lives under `src/gb/`. The module is structured around the `GbBus` trait so the SM83 CPU remains bus-agnostic and unit-testable with stub buses.

| Directory/File | Description |
| ---------------- | ------------- |
| `src/gb/mod.rs` | Module declarations for all GB sub-modules. |
| `src/gb/console/mod.rs` | Module declarations and re-exports for the GB console layer. Re-exports `Gb` and `CpuTraceLine` so call sites can keep using `crate::gb::console::Gb`. |
| `src/gb/console/gb.rs` | `Gb<B: GbBus>` — thin console shell that owns the CPU. `step()` executes one instruction and ticks the bus by the elapsed M-cycles. DMG-specific impls for screen, frame-ready, and reset. |
| `src/gb/console/gameboy.rs` | `GameBoy` — platform-facing wrapper that owns a `Gb<DmgBus>` (created lazily on `load_rom`). Implements the `Emulator` trait for system-agnostic dispatch. |
| `src/gb/console/save_state.rs` | Versioned DMG/CGB save-state serialization. Captures CPU, bus, cartridge RAM, opaque MBC state, and optional minimal SGB command/input state; CGB-specific fields include double-speed accumulator state used by APU/cartridge RTC timing and CGB 0-D extra-OAM RAM state. |
| `src/gb/bus/bus.rs` | `GbBus` trait — `read(&mut self, addr: u16) -> u8`, `write(&mut self, addr: u16, val: u8)`, and a default no-op `tick(&mut self, m_cycles: u8)`. `StubBus` implements the trait for unit tests. |
| `src/gb/bus/dmg_bus.rs` | `DmgBus` — full DMG memory map. Routes all 16-bit addresses to cartridge ROM/RAM, VRAM, WRAM, echo RAM, OAM, HRAM, Timer registers ($FF04–$FF07), APU registers ($FF10–$FF3F), IF ($FF0F), IE ($FFFF), and I/O stubs. Owns the cartridge, Timer, and APU. Overrides `tick()` to advance the Timer, APU, and propagate timer interrupts to IF. Exposes `sample_ready()`/`take_sample()`/`set_audio_sample_rate()` for the platform audio layer. `DmgBus::new_sgb` enables a narrow SGB `$FF00` command/input overlay for SGB-specific test ROMs without implying full SGB emulation. |
| `src/gb/bus/cgb_bus.rs` | `CgbBus` — full CGB memory map with VRAM/WRAM banking, CGB 0-D extra-OAM RAM / CGB-E `$FEA0-$FEFF` behavior, HDMA, KEY0/KEY1 speed switching, CGB boot ROM handling, and double-speed timing. In double speed it half-rates real-time peripherals such as the APU and cartridge RTC while preserving accumulator phase in save states. |
| `src/gb/apu/mod.rs` | Module declarations and re-exports for the GB APU. Re-exports `Apu` from the sibling implementation file. |
| `src/gb/apu/apu.rs` | `Apu` — DMG Audio Processing Unit. 8-step frame sequencer (512 Hz), NR50/NR51/NR52 power/volume/panning control, mixer (NR51 L/R routing, NR50 master volume), sample output pipeline (fractional M-cycle accumulator). |
| `src/gb/apu/channel1.rs` | `Channel1` — Pulse channel with frequency sweep. Duty cycle (4 patterns), length counter, volume envelope, frequency sweep (period, direction, shift). |
| `src/gb/apu/channel2.rs` | `Channel2` — Pulse channel without sweep. Duty cycle, length counter, volume envelope. |
| `src/gb/apu/channel3.rs` | `Channel3` — Wave output channel. 32-nibble wave RAM ($FF30–$FF3F), 4 output levels (mute/100%/50%/25%), length counter, wave position advancing at half the pulse-channel rate. |
| `src/gb/apu/channel4.rs` | `Channel4` — Noise channel. 15-bit or 7-bit LFSR, 8 clock divisor codes × 8 shift values = 64 noise frequencies, length counter, volume envelope. |
| `src/gb/cpu/sm83.rs` | `Sm83<B: GbBus>` — SM83/LR35902 CPU core. Full instruction set (primary + CB-prefixed), HALT bug, STOP state/speed-switch handling, and interrupt dispatch at five vectors. Each M-cycle increments an internal counter used by the console for bus ticking. |
| `src/gb/cpu/opcode.rs` | Opcode metadata tables (BASE[256] and CB[256]) for debugging and tracing. |
| `src/gb/ppu/mod.rs` | Module declarations and re-exports for the GB PPU. Re-exports `Ppu` so the public path remains `crate::gb::ppu::Ppu`. |
| `src/gb/ppu/ppu.rs` | `Ppu` — DMG/CGB LCD controller. Owns VRAM/OAM, LCD/STAT timing state, screen buffer, CGB palette RAM/bank state, STAT/VBlank interrupt generation, OAM corruption helpers, and dispatches per-dot Pixel FIFO rendering for all GB modes. |
| `src/gb/ppu/pixel_fifo.rs` | Dot-stepped DMG/CGB pixel renderer. Samples palette and LCDC writes as pixels are emitted, schedules OBJ fetch stalls in the visible pixel stream, tracks per-OBJ-fetch LCDC samples for DMG/CGB-DMG-compat rendering, caches scanline sprite candidates, and writes completed pixels directly into the screen buffer. |
| `src/gb/ppu/obj_fifo.rs` | DMG/CGB-DMG-compat OBJ fetch policy helpers and low-level tests for LCDC.1 object-fetch start/cancel behavior. |
| `src/gb/ppu/rendering.rs` | Shared DMG and CGB palette conversion helpers used by the Pixel FIFO renderer. |
| `src/gb/ppu/sprites.rs` | GB/CGB sprite scan, pixel fetch, priority ordering, separate low/high-byte OBJ-size sampling for DMG fetches, and Mode 3 OBJ penalty helpers. |
| `src/gb/timer/timer.rs` | `Timer` — DIV/TIMA/TMA/TAC subsystem. `tick(m_cycles)` advances counters and sets `interrupt_pending` on TIMA overflow; caller (DmgBus) propagates this to IF. |
| `src/gb/cartridge/cartridge.rs` | `GbCartridge` trait plus ROM loader surface. `load_cartridge(bytes: &[u8]) -> Result<Box<dyn GbCartridge>, RomError>` validates the header checksum and returns the appropriate MBC implementation. |
| `src/gb/cartridge/mbc0.rs` | ROM-only cartridge (MBC type 0x00) and ROM+RAM cartridges (types 0x08/0x09). ROM+RAM uses a fixed 32 KiB ROM window plus externally enabled/wrapped SRAM for homebrew/test ROM compatibility. |
| `src/gb/cartridge/mbc1.rs` | MBC1 cartridge (types 0x01–0x03). ROM bank switching ($2000–$3FFF), secondary bank register ($4000–$5FFF), banking mode ($6000–$7FFF), RAM enable ($0000–$1FFF). Supports up to 2 MB ROM and 32 KB RAM. |
| `src/gb/cartridge/mod.rs` | Module declarations and re-exports for GB cartridge support. Re-exports `GbCartridge`, `RomError`, and `load_cartridge`. |
| `src/gb/sgb.rs` | Minimal Super Game Boy command/input state used by explicit SGB test helpers. Decodes SGB packets sent through `$FF00` and implements only `MLT_REQ` player selection/current-player behavior; full SGB rendering, borders, palettes, and sound remain out of scope. |
| `src/gb/integration_tests/acid_tests.rs` | Headless automation for GBEmulatorShootout acid rendering and hardware-probe ROMs. Runs `dmg-acid2.gb`, `cgb-acid2.gbc`, `cgb-acid-hell.gbc`, and `which.gb` on the relevant DMG/CGB models and asserts screen CRCs. |
| `src/gb/integration_tests/ax6_tests.rs` | Headless automation for ax6 `rtc3test` MBC3 RTC validation. Runs the GBEmulatorShootout split ROMs (`rtc3test-1.gb` through `rtc3test-3.gb`) on both DMG and CGB hardware modes, captures result-screen PNGs with `NESER_CAPTURE_SCREEN=1`, and asserts reviewed screen CRCs. |
| `src/gb/integration_tests/cpp_tests.rs` | Headless automation for CasualPokePlayer GBEmulatorShootout MBC3/RTC ROMs. Runs `rtc-invalid-banks-test.gb`, `latch-rtc-test.gb`, and `ramg-mbc3-test.gb` on DMG and CGB paths and asserts CRCs against the upstream reference PNGs. |
| `src/gb/integration_tests/samesuite_sgb_tests.rs` | SameSuite SGB command integration tests. Runs `command_mlt_req.gb` and `command_mlt_req_1_incrementing.gb` on DMG-B with the explicit SGB input overlay and asserts the Mooneye-compatible pass marker. |

#### Game Boy Advance Emulation (`src/gba/`)

All Game Boy Advance hardware lives under `src/gba/`. The module currently provides the ARM7TDMI CPU core, the system memory bus / I/O register foundation, the cartridge loader (header parsing + auto-detected SRAM/EEPROM/Flash save backends), the PPU foundation (display register dispatch, scanline timing, V/H-Blank IRQs, and Mode 3 bitmap rendering), the keypad / key-interrupt subsystem (`KEYINPUT` / `KEYCNT`), and a built-in open-source BIOS (`src/gba/bios/`) that eliminates the need for proprietary BIOS dumps; subsequent phases will add the remaining display modes, sprite (OBJ) rendering and the APU.

| Directory/File | Description |
| ---------------- | ------------- |
| `src/gba/mod.rs` | Game Boy Advance module root. Re-exports `Gba` (platform-facing wrapper), the `cpu`, `input`, `ppu` and `bios` sub-modules, `GbaBus`, `Ppu`, `Keypad`, and `GbaCartridge` / `SaveType` / `load_cartridge`. Includes `#[cfg(test)]` GBA integration test modules under `src/gba/integration_tests/`. |
| `src/gba/bios/mod.rs` | Open-source BIOS module. Embeds the pre-built 16KB binary via `include_bytes!` and exports `EMBEDDED_BIOS`. Contains unit tests for BIOS functional correctness (div, sqrt, checksum, boot). |
| `src/gba/bios/bios.s` | ARM assembly source for the open-source GBA BIOS. Implements exception vectors, IRQ dispatcher, SWI dispatch (Div, Sqrt, Halt, IntrWait, SoftReset, etc.), and boot sequence. |
| `src/gba/bios/bios.ld` | Linker script producing exactly 16384 bytes flat binary at base address 0x00000000. |
| `src/gba/bios/Makefile` | Build instructions for the BIOS binary using `arm-none-eabi-as`/`arm-none-eabi-ld`/`arm-none-eabi-objcopy`. |
| `src/gba/bios/bios.bin` | Pre-built 16KB BIOS binary, committed to the repo for CI/users without the ARM toolchain. |
| `src/gba/console/gba.rs` | `Gba` — platform-facing GBA wrapper implementing the `Emulator` trait. Owns ARM7TDMI + bus, executes per-instruction ticks, handles IRQ line dispatch, frame-ready signaling, ROM loading, and GBA save-state capture/restore. Falls back to the built-in BIOS when no external BIOS is available. |
| `src/gba/console/save_state.rs` | Versioned GBA save-state serialization. Captures CPU state, bus memory regions, bus-owned simple peripherals (I/O backing, interrupt controller, timers, DMA, SIO, keypad, WAITCNT-derived wait states, HALTCNT request state), PPU registers/timing/framebuffer state, APU channel/FIFO/mixer/timing state, cartridge save-backend state (SRAM/EEPROM/Flash data and command parser state), and scalar open-bus/BIOS-lock fields while intentionally excluding BIOS and ROM bytes. |
| `src/gba/integration_tests/mod.rs` | GBA integration test module root. Includes gba-suite runner and test definitions. |
| `src/gba/integration_tests/gba_suite_runner.rs` | Headless harness for GBA validation ROMs including jsmolka `gba-tests`, FuzzARM, ArmWrestler, and `mgba-emu/suite`. It loads ROM assets from `roms/gba/automated_tests/`, injects the embedded BIOS where needed, drives interactive menus, captures framebuffer CRCs, and can write PNG checkpoints under `target/gba_suite_checkpoints/` when `NESER_CAPTURE_SCREEN=1`. |
| `src/gba/integration_tests/gba_suite_tests.rs` | ROM-level GBA integration tests for CPU, memory, save, PPU, ArmWrestler, and `mgba-emu/suite` coverage. mGBA Video subtests are represented as per-subtest actual-vs-expected framebuffer assertions, with currently failing subtests individually ignored and linked to tracking issues. |
| `src/gba/integration_tests/save_state_tests.rs` | End-to-end GBA save-state integration tests that save, dirty CPU/bus/PPU state, restore, and verify screen CRC plus state markers return to the saved point. |
| `src/gba/cpu/mod.rs` | Module root for the ARM7TDMI core. Re-exports `Arm7tdmi`, `Bus`, `RamBus`, `Registers`, `CpuMode`, etc. |
| `src/gba/cpu/registers.rs` | `Registers` — ARM7TDMI register file with R0–R15, CPSR, and per-mode banked SPSR/SP/LR (and FIQ-banked R8–R12). Includes `CpuMode` (USR/FIQ/IRQ/SVC/ABT/UND/SYS) and `condition_met` for the 16 ARM condition codes. |
| `src/gba/cpu/bus.rs` | `Bus` trait used by the CPU for byte/halfword/word reads and writes, plus a flat little-endian `RamBus` implementation used by tests and boot stubs. |
| `src/gba/cpu/arm.rs` | ARM 32-bit instruction decoder/executor. Covers data processing, branch (B/BL), branch-and-exchange (BX), single-data transfer (LDR/STR/LDRB/STRB) and SWI; honours conditional execution. |
| `src/gba/cpu/thumb.rs` | Thumb 16-bit instruction decoder/executor. Covers move-shifted register, add/subtract, MOV/CMP/ADD/SUB immediate, hi-register operations, BX, PC-relative load, PUSH/POP and conditional/unconditional branches. |
| `src/gba/cpu/arm7tdmi.rs` | `Arm7tdmi` — fetch/decode/execute pipeline, S/N cycle accounting, exception vectors, and IRQ/FIQ/SWI dispatch (banked register handling, CPSR→SPSR save, vector jump). |
| `src/gba/bus/mod.rs` | GBA bus module root. Keeps declarations/re-exports minimal and delegates implementation to focused sibling files. |
| `src/gba/bus/gba_bus.rs` | `GbaBus` storage and inherent API: memory/peripheral ownership, BIOS/ROM loading, stepping peripherals, DMA trigger hooks, save-state capture/restore, open-bus helpers, and mGBA debug console state. |
| `src/gba/bus/cpu_bus.rs` | CPU `Bus` trait implementation for `GbaBus`, including full GBA address-space routing, read/write side effects, WAITCNT updates, HALTCNT handling, and Game Pak prefetch timing helpers. |
| `src/gba/bus/dma_bus.rs` | `DmaBus` implementation for `GbaBus`, preserving DMA-specific latch/open-bus behavior while routing transfers through the standard bus paths. |
| `src/gba/bus/waitstates.rs` | `Waitstates` and `WidthClass`, including WAITCNT-derived N/S cycle lookup tables for BIOS/RAM/I/O/video/Game Pak regions. |
| `src/gba/bus/addressing.rs` | Shared bus address helpers for VRAM mirroring, timer/DMA control register decoding, Game Pak wait-state predicates, and no-cart open-bus values. |
| `src/gba/bus/memory.rs` | Backing-store sizes (BIOS/EWRAM/IWRAM/PRAM/VRAM/OAM/SRAM) and helpers for little-endian halfword/word access with mirrored offsets. |
| `src/gba/bus/io.rs` | `IoRegisters` — dispatch table for the `0x0400_0000`–`0x0400_03FF` I/O window. Routes interrupt-controller and timer registers to live state and provides a backing store for the remaining ~300 registers so unimplemented PPU/APU/DMA registers don't panic. |
| `src/gba/bus/interrupt.rs` | `InterruptController` — `IE`/`IF`/`IME` registers with write-1-to-clear `IF` semantics and an `irq_line()` predicate consumed by the CPU. |
| `src/gba/bus/timer.rs` | `Timers` / `Timer` — 4-channel 16-bit timer bank with prescalers (1/64/256/1024), cascade mode, reload latching, enable rising-edge load and overflow IRQ generation. |
| `src/gba/bus/sio.rs` | `Sio` — Serial I/O controller implementing the transfer state machine. Normal 8/32-bit transfers complete after baud-rate-dependent cycle counts (512/64/2048/256); Multiplayer mode stays busy indefinitely (no peers). Raises IRQ_SIO on completion when enabled. |
| `src/gba/input/mod.rs` | Input subsystem module root. Re-exports `Keypad` and the keypad register addresses / `KEYCNT` flag constants. |
| `src/gba/input/keypad.rs` | `Keypad` — `KEYINPUT` (P1, `0x04000130`) and `KEYCNT` (`0x04000132`) registers. Tracks the 10 GBA buttons (A, B, Select, Start, Up, Down, Left, Right, L, R) with active-low read semantics, exposes `set_button` / `set_states` / `get_states` for frontend routing, and raises the keypad IRQ (`IF` bit 12 / IRQ3) per `KEYCNT`'s IRQ-enable + AND/OR condition bits. |
| `src/gba/ppu/mod.rs` | `Ppu` — display controller foundation. Owns `DISPCNT` / `DISPSTAT` / `VCOUNT`, drives scanline/dot timing (1232 cycles × 228 lines = 280 896 cycles per frame), maintains V-Blank/H-Blank/V-Counter status flags, raises the matching IRQs and renders Mode 3 (240×160 15-bit direct bitmap from VRAM) plus a backdrop fill from PRAM[0]. Owns the BG2/BG3 affine register file (write-only `0x0400_0020..=0x0400_003E`), routed in via `write_affine`. Stepped from `GbaBus::step`, which forwards V-Blank/H-Blank edges to the DMA hooks. |
| `src/gba/ppu/affine.rs` | `BgAffine` — per-background affine register file (PA/PB/PC/PD as signed 8.8 fixed-point `i16`; X/Y as signed 19.8 fixed-point `i32` sign-extended from bit 27 of the 28-bit hardware field). Provides the halfword write helpers (`write_x_low`/`write_x_high`/`write_y_low`/`write_y_high`) used by the bus dispatcher; the renderer that consumes these values is a follow-up sub-issue. |
| `src/gba/ppu/color.rs` | 15-bit BGR555 → 24-bit RGB888 palette conversion (`expand5_to_8`, `bgr555_to_rgb888`, `write_pixel`) using the canonical `c8 = (c5 << 3) | (c5 >> 2)` channel widening. |
| `src/gba/cartridge/mod.rs` | Cartridge module root. Re-exports `GbaCartridge`, `load_cartridge`, `SaveType`, and the per-backend types. |
| `src/gba/cartridge/header.rs` | `GbaHeader` parser — reads title, game code, maker code, the fixed `0x96` byte and computes/validates the header complement check (offsets `0x0A0..=0x0BC`). |
| `src/gba/cartridge/save_type.rs` | `SaveType` enum (`None` / `Sram32K` / `Eeprom512` / `Eeprom8K` / `Flash64K` / `Flash128K`) and the `detect_save_type` heuristic that scans 4-byte aligned ROM offsets for `EEPROM_V`, `SRAM_V`, `FLASH_V`, `FLASH512_V`, `FLASH1M_V`. |
| `src/gba/cartridge/sram.rs` | `Sram` — 32 KB battery-backed SRAM with mirrored read/write and `snapshot`/`restore` for `.sav` flush. |
| `src/gba/cartridge/eeprom.rs` | `Eeprom` — 512 B / 8 KB EEPROM bit-serial I²C state machine (`write_bit` / `read_bit`) handling read & write transactions over 6/14-bit address busses. |
| `src/gba/cartridge/flash.rs` | `Flash` — 64 KB single-bank / 128 KB dual-bank Flash backend implementing the JEDEC magic-write command sequence: byte program, sector erase, chip erase, ID readback (`0x90`/`0xF0`) and bank switch (`0xB0`). |
| `src/gba/cartridge/cartridge.rs` | `GbaCartridge` aggregate — owns the ROM image, parsed header and selected `SaveBackend`. `load_cartridge` validates size (≤ 32 MB), parses the header and constructs the matching backend. |
| `src/gba/debugging/mod.rs` | GBA debugging support module root (excluded from WASM builds). Re-exports `Breakpoints`, `CpuTrace`, `TraceEntry`, `GbaDebuggerController`, and the `disasm_arm` / `disasm_thumb` formatters. |
| `src/gba/debugging/disasm.rs` | ARM 32-bit and Thumb 16-bit disassembler — formats the subset of instructions implemented by the executor (data-processing, B/BL, BX, LDR/STR/LDRB/STRB, SWI for ARM; formats 1, 2, 3, 4, 5, 6, 14, 16, 18 for Thumb) and renders unimplemented opcodes as `<undefined>`. |
| `src/gba/debugging/breakpoints.rs` | `Breakpoints` — `BTreeSet<u32>` wrapper supporting insert/remove/contains/clear and ordered iteration over breakpoint addresses. |
| `src/gba/debugging/trace.rs` | `CpuTrace` ring buffer of recently retired instructions (`TraceEntry` carrying PC, raw word, Thumb flag, mnemonic, R0–R15 snapshot, CPSR and cumulative cycle count); configurable capacity, default 1024, with enable/disable toggle. |
| `src/gba/debugging/controller.rs` | `GbaDebuggerController` — glues the breakpoint set, trace ring buffer, optional file logger, and disassembler to `Arm7tdmi`. Provides `step`, `run_until_breakpoint` and trace-to-file hooks. |

#### Frontends

| Directory/File | Description |
| ---------------- | ------------- |
| `src/frontends/native/` | Desktop frontend using winit + OpenGL. |
| `src/frontends/native/event_loop.rs` | Main event loop — holds `Console` enum, handles input events, frame timing, VSync, autorun integration, pause/resume, and hot-reload of ROMs. NES-specific features (debugger, Zapper, SNES mouse) accessed by extracting the inner `Nes` via pattern match. |
| `src/frontends/native/audio.rs` | Native audio device setup and sample queuing. |
| `src/frontends/native/keyboard.rs` | Keyboard input handling — maps physical keys to NES buttons, debugger hotkeys, and system commands. |
| `src/frontends/native/gamepad.rs` | Gamepad input using gilrs — maps controller axes/buttons to NES joypads. |
| `src/frontends/native/mouse.rs` | Mouse input — Zapper light gun, SNES mouse, and Arkanoid paddle coordinate mapping. |
| `src/frontends/native/gl_wrapper.rs` | OpenGL context management for native windows. |
| `src/frontends/native/gl_backend.rs` | OpenGL framebuffer, texture management, and debugger UI. |
| `src/frontends/native/egui_renderer.rs` | Shared egui frame input, frame runner, and egui_glow painter seam for the native emulator renderer cutover. |
| `src/frontends/native/egui_theme.rs` | Shared egui font and dark-theme setup used by native egui surfaces. |
| `src/frontends/native/egui_texture.rs` | Shared egui native texture metadata used by ROM browser textures and future emulator egui rendering. |
| `src/frontends/native/ui_geometry.rs` | Shared pure geometry helpers for letterboxed frames, overlays, toasts, and crosshair layout. |
| `src/frontends/native/shader_manager.rs` | Shader pipeline using librashader — loads `.slangp` presets (CRT, NTSC, xBRZ). |
| `src/frontends/native/rom_browser/` | Graphical ROM browser — a console-style launcher with cover art grid, search, genre filter, detail view, and favorites. |
| `src/frontends/native/rom_browser/app.rs` | `RomBrowserApp` — winit `ApplicationHandler` implementing the browser state machine, grid rendering, overlay modes (search, genre filter, detail view), input handling, and favorites. |
| `src/frontends/native/rom_browser/renderer.rs` | `BrowserGl` — egui_glow + egui_winit setup, texture loading from image files, and frame lifecycle management for the browser window. |
| `src/frontends/native/rom_browser/theme.rs` | Visual theme constants — colours, spacing, layout calculations (`grid_layout`, `cell_height`, `sidebar_width`). |
| `src/frontends/tui/` | Terminal UI ROM launcher using `ratatui` + `crossterm`. |
| `src/frontends/tui/app.rs` | TUI application state and event loop. |
| `src/frontends/tui/rom_list.rs` | Scrollable ROM list widget. |
| `src/frontends/tui/catalog.rs` | Integration with the cartridge catalog for ROM discovery. |
| `src/frontends/tui/launcher.rs` | Launches the SDL emulator for a selected ROM. |
| `src/frontends/tui/action_menu.rs` | Context menu for ROM actions. |
| `src/frontends/web/` | WebAssembly frontend. |
| `src/frontends/web/wasm.rs` | `wasm-bindgen` bindings — exposes `WasmNes` to JavaScript with methods for frame stepping, input, audio sample retrieval, save states, autorun, and NES debugger support. |
| `src/frontends/web/wasm_gb.rs` | `wasm-bindgen` bindings for the Game Boy frontend (`WasmGb`) with ROM loading, frame rendering, audio, reset, and joypad input. |
| `src/frontends/web/wasm_gba.rs` | `wasm-bindgen` bindings for the Game Boy Advance frontend (`WasmGba`) with ROM loading, 240×160 RGBA frame rendering, audio, reset, toast draining, and 10-button keypad input. |
| `src/frontends/web/wasm_autorun_state.rs` | Autorun state management for the WASM frontend. |
| `src/frontends/web/wasm_tests.rs` | WASM-specific integration tests (run via `wasm-pack test`). |

#### Debugging

| Directory/File | Description |
| ---------------- | ------------- |
| `src/debugging/` | Generic debugging and diagnostic tools. |
| `src/debugging/breakpoints.rs` | Breakpoint system — supports address breakpoints and conditional breaks. |
| `src/debugging/tracing.rs` | CPU/PPU/APU/Mapper trace output at configurable verbosity levels. |
| `src/debugging/logging.rs` | Debug logging infrastructure. |
| `src/nes/debugging/` | NES-specific debugging tools. |
| `src/nes/debugging/ui.rs` | egui-based debugger UI with CPU state, memory viewer, and disassembly. |
| `src/nes/debugging/disasm.rs` | 6502 disassembler for real-time instruction display. |
| `src/nes/debugging/ppu_viewer.rs` | PPU nametable and pattern table viewer. |
| `src/nes/debugging/snapshot.rs` | Debugging state snapshots. |
| `src/nes/debugging/types.rs` | Shared NES debugging types and constants. |
| `src/nes/debugging/control.rs` | Debugger controller for breakpoints, stepping, and pause/continue. |

#### Autorun System

| Directory/File | Description |
| ---------------- | ------------- |
| `src/autorun/` | Input recording and deterministic playback system. |
| `src/autorun/types.rs` | `AutorunFile` format — stores per-frame joypad input with periodic CRC checkpoints for regression testing. Supports versioned format (currently v3 with run-length encoding). |
| `src/nes/autorun/headless_playback.rs` | NES headless playback engine — replays input without rendering for automated verification. Compares CRC checksums at each checkpoint. |
| `src/autorun/utils.rs` | Utilities for loading, saving, converting, and trimming autorun files. |

#### Other Core Files

| File | Description |
| ------ | ------------- |
| `src/platform/frontend_toasts.rs` | System-agnostic toast message formatters (gamepad connection/disconnection, cartridge load, gamepad initialization). |
| `src/nes/frontend_toasts.rs` | NES-specific toast message formatters (emulator timing mode, hardware mode/model selection). |

#### Tests

| Directory/File | Description |
| ---------------- | ------------- |
| `src/nes/integration_tests/` | Integration test suites. |
| `src/nes/integration_tests/cpu_tests.rs` | CPU instruction and timing tests using Blargg test ROMs. |
| `src/nes/integration_tests/ppu_tests.rs` | PPU rendering, timing, and register tests using Blargg test ROMs. |
| `src/nes/integration_tests/apu_audio_tests.rs` | APU channel audio output verification. |
| `src/nes/integration_tests/apu_visual_tests.rs` | APU tests that produce visual output (Blargg test ROMs). |
| `src/nes/integration_tests/mapper_tests.rs` | Mapper-specific tests using holy-mapperel and other test ROMs. |
| `src/nes/integration_tests/autorun_tests.rs` | Autorun recording/playback round-trip tests. |
| `src/nes/integration_tests/input_tests.rs` | Controller input tests. |
| `src/nes/integration_tests/ram_init_tests.rs` | RAM initialization mode tests. |
| `src/nes/integration_tests/rom_test_runner.rs` | Generic test ROM harness — runs a ROM headlessly and checks for pass/fail output. |
| `src/nes/integration_tests/romtest_harness.rs` | Shared infrastructure for ROM-based test assertions. |
| `src/nes/integration_tests/manual_test_cartridges.rs` | Programmatically generated minimal test ROMs for specific hardware scenarios. |
| `src/nes/integration_tests/miscellaneous_tests.rs` | Miscellaneous integration tests. |
| `build.rs` | Build script that scans `roms/games/mappers/` for `.autorun` files and generates per-ROM regression tests at compile time. |

### `web/` — Browser Frontend

The web frontend is bundled with **Vite** (config at `vite.config.ts`, root: `web/`, build output: `dist/`). Styled with **Tailwind CSS v4** and **DaisyUI v5** (night theme with neon accent colors). Uses a DaisyUI drawer layout with a sidebar for ROM/emulation controls and a top bar for screen controls. TypeScript modules are organized into feature folders under `web/src/`.

| Directory/File | Description |
| -------------- | ------------- |
| `web/index.html` | Entry point — DaisyUI drawer layout with sidebar, top bar, canvas area, footer, and autorun modal dialog. Loads `./src/app.ts` as the main module. |
| `web/main.css` | Tailwind CSS entry point with DaisyUI plugin config, neon theme overrides, and custom component styles. |
| `web/debugger.css` | Debugger panel styling (green-on-black terminal aesthetic). |
| `web/src/app.ts` | Application bootstrapper — initializes the WASM module, selects `WasmNes` / `WasmGb` / `WasmGba` by ROM extension, sets up the render loop, and coordinates all subsystems. |
| `web/src/audio/` | Audio resampling (`audio_resampler.ts`), frame timing (`frame_limiter.ts`, `frame_plan.ts`). |
| `web/src/input/` | Gamepad API (`gamepad.ts`), GBA keyboard mapping (`keyboard_mapping.ts`), keyboard/gamepad routing (`input_routing.ts`), mouse input (`mouse_input.ts`), pointer lock (`pointer_lock.ts`). |
| `web/src/display/` | Canvas sizing (`canvas_size.ts`), zoom controls (`zoom_controls.ts`), cursor visibility, crosshair overlay, and console-specific filter selection (`filters.ts`; GBA is stock-only in the web frontend). |
| `web/src/rom/` | ROM file listing (`rom_list.ts`), extension-to-console detection (`rom_extensions.ts` for `.nes`, `.gb`, `.gbc`, `.cgb`, `.gba`), selection UI (`rom_selection.ts`), autorun context. |
| `web/src/save-state/` | Save state persistence using IndexedDB (`save_state_storage.ts`, `save_state_controller.ts`, `save_state_context.ts`). |
| `web/src/debugger/` | Browser-based debugger panels — disassembly, OAM viewer, watch expressions, PPU viewer layout/scroll. |
| `web/src/shortcuts/` | Keyboard shortcut actions and help overlay. |
| `web/src/ui/` | Toast overlays (`toast_overlay.ts`), gamepad init toast, sine scroller. |
| `web/integration/` | Playwright-based end-to-end integration tests for the web frontend. |

Each TypeScript module has a corresponding `.test.ts` unit test file (run with `vitest`).

### `shaders/` — Visual Filters

Shader presets using the Slang shading language, loaded via librashader:

| File | Description |
| ------ | ------------- |
| `crt-lottes.slangp` | CRT simulation — scanlines, shadow mask, bloom, and curvature. |
| `ntsc-256px-composite.slangp` | NTSC composite video simulation with color bleeding and artifacts. |
| `xbrz-freescale.slangp` | xBRZ smooth pixel upscaling for clean, sharp output. |
| `stock.slang` / `stock.slangp` | Passthrough shader (no effect). |

### `roms/` — Test ROMs

| Directory | Description |
| --------- | ------------- |
| `roms/automated_tests/` | **70+ test ROM suites** used by the integration test harness. Includes Blargg's CPU/PPU/APU tests, DMA timing tests, mapper-specific tests (MMC3, MMC5, FME-7, VRC6), sprite tests, and more. |
| `roms/gb/automated_tests/acid/` | Vendored GBEmulatorShootout acid ROMs (`which.gb`, `dmg-acid2.gb`, `cgb-acid2.gbc`, `cgb-acid-hell.gbc`) used by `src/gb/integration_tests/acid_tests.rs` for DMG/CGB screen CRC coverage. |
| `roms/gb/automated_tests/cpp/` | Vendored CasualPokePlayer GBEmulatorShootout MBC3/RTC ROMs and upstream PNG references used by `src/gb/integration_tests/cpp_tests.rs`. |
| `roms/gb/automated_tests/daid/` | Vendored daid GB/GBC accuracy ROMs and upstream PNG references from GBEmulatorShootout, used by `src/gb/integration_tests/daid_tests.rs` for screen CRC and reference-PNG auditing. |
| `roms/gb/automated_tests/rtc3test/` | Vendored ax6 `rtc3test` split MBC3 RTC test ROMs from GBEmulatorShootout, used by `src/gb/integration_tests/ax6_tests.rs` for DMG/CGB result-screen CRC testing. |
| `roms/gba/automated_tests/gba-tests/` | Git submodule snapshot of jsmolka `gba-tests` (ARM/Thumb GBA CPU validation ROMs) used by `src/gba/integration_tests/gba_suite_tests.rs`. |
| `roms/automated_tests/mapper_verification/` | Custom mapper verification ROMs built from assembly source with per-mapper test definitions. |
| `roms/manual_tests/` | ROMs for manual visual/audio verification (e.g., volume tests). |
| `roms/games/` | Game ROMs (not checked into version control). Subdirectories organized by mapper number for autorun regression tests. |

### `docs/` — Documentation

| File | Description |
| ------ | ------------- |
| `docs/MAPPER_SUPPORT.md` | Mapper support status and compatibility notes. |
| `docs/MAPPER_CAPABILITIES.md` | Per-mapper capability matrix (banking, IRQ, audio expansion, etc.). |
| `docs/MAPPERTOOL_UI_DESIGN.md` | Design document for the mappertool TUI. |
| `docs/architecture-diagrams.md` | Save-state architecture diagrams (current vs proposed). |

### `.github/` — CI/CD and Automation

#### CI Workflows

| Workflow | Description |
| ---------- | ------------- |
| `ci.yml` | Main CI pipeline. Runs on push to `main` and PRs. Jobs: Rust tests (`cargo test --lib --all-features`), Clippy lint, `cargo fmt` check, WASM build + test (`wasm-pack test`), web JS unit tests (`npm test`), web Playwright integration tests, and Python script tests. Uses path-based change detection to skip unchanged jobs, and runs NES/GBA integration suites selectively (GBA integration also triggers on `roms/gba/automated_tests/gba-tests` asset changes). |
| `release.yml` | Release pipeline triggered by version tags (`v*.*.*`). Runs full CI, then builds Linux x86_64, macOS x86_64, macOS aarch64, and Windows x86_64 on target-compatible runners. Each build job creates a structured release archive with `scripts/package_release.py`, verifies it with `scripts/verify_release_package.py`, and smoke-runs the packaged binary with `--version` from inside the extracted `neser/` directory. Publishes only verified `.tar.gz` and `.zip` archives to GitHub Releases with a git-cliff changelog. |

#### Agentic Workflows (Copilot-powered)

| Workflow | Description |
| ---------- | ------------- |
| `bug-of-the-day.md` | Selects the highest-priority open bug issue, fixes it using the bug-hunter workflow, and creates a pull request. |
| `next-mapper.md` | After a PR is closed, selects a random open mapper issue, implements it with TDD, and creates a PR. |
| `code-simplifier.md` | Analyzes recently modified code and creates PRs with readability/maintainability improvements. |
| `daily-repo-status.md` | Generates daily repository activity reports as GitHub issues. |
| `issue-enhancer.md` | Automatically enhances issues with proper labeling and quality improvements. |

### Configuration

| File | Description |
|------|-------------|
| `neser.conf.example` | Annotated example configuration file documenting all settings: hardware mode (NES-NTSC/NES-PAL/Famicom), audio, video (VSync, window size, fullscreen, shaders), input (gamepads, Four Score, controller types, Zapper detection), debugging, RAM initialization, OAM DRAM decay, and overscan. |
| `gamecontrollerdb.txt` | SDL2 game controller mapping database for broad gamepad compatibility. |

### Build Configuration

| File | Description |
| ------ | ------------- |
| `Cargo.toml` | Rust project manifest. Defines three feature flags: `sdl` (default — desktop frontend), `wasm` (WebAssembly frontend), `tui` (terminal ROM launcher). The library crate type is both `rlib` (for tests) and `cdylib` (for WASM). Debug builds use `opt-level = 1` to keep audio smooth; dependencies use `opt-level = 3`. |
| `build.rs` | Compile-time code generation — scans for `.autorun` files and generates Rust test functions for each. |
| `playwright.config.mjs` | Playwright configuration for web integration tests. |
| `vite.config.js` | Vite bundler configuration — root: `web/`, build output: `dist/`, dev/preview server on port 8000, Vitest test pattern. |
| `package.json` | Node.js project for web frontend — Vite bundler, Vitest unit tests, and Playwright integration tests. |

## Key Design Decisions

- **Bus-centric architecture**: All memory access goes through the `Bus`, enabling accurate mapper intercepts and DMA behavior.
- **Cycle-accurate timing**: CPU, PPU, and APU are synchronized via a master clock divider. PPU runs 3 cycles per CPU cycle (NTSC) or 3.2 (PAL).
- **Feature-gated frontends**: SDL, WASM, and TUI frontends are behind Cargo features, so the core emulation library has no platform dependencies.
- **Interior mutability via `Rc<RefCell<>>`**: Components that need shared ownership (Bus, PPU, APU) use reference-counted cells rather than unsafe code.
- **Mapper trait pattern**: All mappers implement the `Mapper` trait with a standard interface for PRG/CHR reads/writes, IRQ management, and state snapshots. Common banking logic is provided by `BaseMapper`.
- **Deterministic testing**: RAM initialization modes and autorun recordings enable fully deterministic regression testing against reference CRC checksums.
- **Save state serialization**: Uses JSON (via serde) with a versioned format. Mapper state is serialized as opaque byte vectors to keep the format flexible.
- **ROM browser architecture**: The native frontend includes a console-style graphical ROM browser as the default landing screen. It uses the shared `platform/catalog` module for ROM discovery, `platform/metadata` for TheGamesDB fuzzy matching via `rusqlite` + `strsim`, and `platform/image_cache` for cover art downloading via `reqwest`. The browser renders a cover art grid with egui (`egui_glow` + `egui_winit`), supports real-time search, genre filtering, a detail view overlay, and persistent favorites. When launched without a ROM path, the browser opens first; selecting a ROM transitions to emulation mode via an application state machine.

## Testing Strategy

1. **Unit tests** — Extensive per-module tests throughout the codebase (run with `cargo test --lib`).
2. **ROM-based integration tests** — Blargg, holy-mapperel, daid GB/GBC, Mealybug, SameSuite, ax6 rtc3test, and other community test ROMs verified via headless execution and screen CRC/reference artifact checks.
3. **Autorun regression tests** — Build-time generated tests that replay recorded input and verify CRC checkspoints.
4. **WASM tests** — Browser-environment tests via `wasm-pack test --headless --chrome`.
5. **JavaScript unit tests** — Web frontend JS modules tested with Vitest (`npm test`).
6. **Playwright integration tests** — End-to-end browser tests for the web frontend.
7. **Python tests** — Unit tests for the ROM scraper and mappertool utilities.
