neser 0.1.1

NESER - NES Emulator in Rust - is a NES emulator written in Rust. It aims to be a high-quality, hardware-accurate emulator that is also easy to use and extend. It supports a wide range of NES games and features, including various mappers, audio processing, and input handling. NESER is designed to be modular and extensible, allowing developers to easily add new features or support for additional hardware. It can be run using one of two frontends: a native desktop application using SDL2, or a web application using WebAssembly. The desktop application provides a high-performance, feature-rich experience with support for various input devices and display options, while the web application allows users to play NES games directly in their browsers without needing to install any software in a BYOR manner (Bring Your Own Roms).
Documentation
# =============================================================================
# NESER Configuration File Example
# =============================================================================
#
# This file shows all available configuration options with their default values.
# Copy this file to one of the following locations:
#
#   ~/.neser/neser.conf    (user-wide settings)
#   ./neser.conf           (project/directory-specific settings)
#
# Or specify a custom path with: neser --config /path/to/config.conf
#
# Configuration priority (later overrides earlier):
#   1. Default values (built-in)
#   2. ~/.neser/neser.conf (if it exists)
#   3. ./neser.conf (if it exists)
#   4. --config <file> (if specified, replaces steps 2 and 3)
#   5. Command-line arguments (highest priority)
#
# Format: key=value (one per line)
# Comments start with #
# Boolean values: true/false, yes/no, 1/0 (case-insensitive)
#
# Command-line arguments use the same keys with -- prefix and hyphens:
#   hardware=nes-pal  →  --hardware nes-pal
#   audio=false       →  --audio false  OR  --audio=0  OR  --no-audio  OR  --disable-audio
#   audio=true        →  --audio  OR  --audio true  OR  --audio=1
#   pulse1=true       →  --pulse1  OR  --pulse1 true  OR  --pulse1=1
#   pulse2=false      →  --pulse2 false  OR  --pulse2=0  OR  --no-pulse2  OR  --disable-pulse2
#
# CLI boolean flags:
#   - No value (--flag) defaults to true
#   - With value (--flag true/false) sets explicit value  
#   - Prefix negation (--no-flag, --disable-flag) sets to false
# =============================================================================

# -----------------------------------------------------------------------------
# Hardware
# -----------------------------------------------------------------------------
# Set to "nes-ntsc", "nes-pal", or "famicom".
# NES-NTSC runs at ~60 FPS, NES-PAL at ~50 FPS.
# nes-ntsc is the standard for North American and Japanese NES consoles.
# nes-pal is used for European NES consoles.
# famicom uses Famicom hardware mode and NTSC timing.
hardware=nes-ntsc

# -----------------------------------------------------------------------------
# Audio Settings
# -----------------------------------------------------------------------------
# Enable or disable audio output entirely.
audio=true

# Individual APU channel toggles.
# Useful for isolating specific sounds or debugging audio issues.
pulse1=true
pulse2=true
triangle=true
noise=true
dmc=true

# -----------------------------------------------------------------------------
# Video Settings
# -----------------------------------------------------------------------------
# Enable vertical sync to prevent screen tearing.
# Disabling may reduce input latency but can cause visual artifacts.
vsync=true

# Window scaling factor (1.0 to 5.0).
# The NES outputs 256x240 pixels. This multiplies the window size.
# Example: 4.0 = 1024x960 window
# Note: Only applies in windowed mode, ignored in fullscreen.
window_height=960

# Run in fullscreen mode.
fullscreen=false

# Display index for fullscreen mode (0 = primary display).
# Only used when fullscreen=true.
display=0

# Shader/filter preset.
# Applies visual effects like CRT simulation or pixel scaling.
# Valid values:
#   - crt    : CRT simulation with scanlines, shadow mask, bloom
#   - ntsc   : NTSC composite video simulation
#   - smooth : Smooth pixel upscaling (xBRZ)
#   - none   : No filter, raw pixels
# Leave empty or comment out for no shader.
#filter=crt

# -----------------------------------------------------------------------------
# Input Settings
# -----------------------------------------------------------------------------
# Enable gamepad/joystick support.
# Set to false to use keyboard only.
gamepads=true

# Enable Four Score emulation mode.
# When true, NESER emulates 4-player Four Score reads on $4016/$4017.
# Input fallback policy:
#   - 2 physical gamepads connected: gamepads -> players 1-2, keyboard -> players 3-4
#   - 1 physical gamepad connected: gamepad -> player 1, keyboard -> players 2-3
#   - 0 physical gamepads connected: keyboard -> players 1-2
enable_4_score=false

# Controller Type Configuration (Per-Port)
# Each of the two controller ports can be configured independently.
# Valid values: joypad, arkanoid, none
# Default: joypad for both ports
#
# Port 1 (Player 1):
#controller_port1=joypad
#
# Port 2 (Player 2):
#controller_port2=joypad
#
# Auto-detection behavior:
# If a specific port hasn't been explicitly configured, NESER will
# automatically detect known paddle ROMs and configure that port:
#   - Arkanoid (CRC 0x32FB0583) → paddle on port 2
#   - PaddleTest3 (CRC 0x47F9F410) → paddle on port 1
#
# Auto-detection is per-port: if you explicitly configure port 2, auto-detection
# for port 2 is disabled, but port 1 can still be auto-detected (and vice versa).
# This gives you fine-grained control over each port independently.

# Paddle Controller Input (SDL frontend)
# When a paddle controller is enabled on a port, mouse input controls it:
#   - Mouse X position → paddle position (0-255, non-linear curve)
#   - Left mouse button → paddle trigger
# Mouse input is routed to ALL ports configured as paddles.
# Keyboard/gamepad input for paddle-configured ports is suppressed.
#
# Configuration examples:
#
# Example 1: Mouse-based paddle on port 1 (for PaddleTest3-style games)
#   controller_port1=arkanoid
#   controller_port2=joypad
#
# Example 2: Mouse-based paddle on port 2 (for Arkanoid)
#   controller_port1=joypad
#   controller_port2=arkanoid
#
# Example 3: Paddles on both ports (both controlled by same mouse)
#   controller_port1=arkanoid
#   controller_port2=arkanoid
#
# Example 4: Force joypad mode even for Arkanoid ROM
#   controller_port1=joypad
#   controller_port2=joypad

# Zapper Light Detection Size
# Controls the size of the square area sampled around the Zapper cursor
# when checking for light detection:
#   0 = single pixel (default)
#   1 = 3×3 square (9 pixels)
#   2 = 5×5 square (25 pixels)
#   n = (2·n + 1)² pixels sampled
#
# Larger values make it easier to hit targets but increase CPU usage.
# Values above 10 may cause noticeable performance impact.
# Valid range: 0-255
zapper_detection_size=0

# -----------------------------------------------------------------------------
# Debugging
# -----------------------------------------------------------------------------
# Open debugger windows (CPU/PPU/APU) on startup.
# The emulator will start paused when this is enabled.
debugger=false

# Load save-state on startup (uses ROM .state path).
# This will automatically restore the emulator state from the last save.
load_state=false

# -----------------------------------------------------------------------------
# Emulation Speed (DISABLED - not supported with current eventloop design)
# -----------------------------------------------------------------------------
# Emulation speed multiplier (1.0 = normal speed).
# Values < 1.0 slow down, > 1.0 speed up.
# Example: 0.5 = half speed, 2.0 = double speed

# -----------------------------------------------------------------------------
# RAM Initialization Mode
# -----------------------------------------------------------------------------
# Controls how all emulated RAM (CPU, PRG, CHR, PPU nametable, and palette) is
# initialized on power-on/hard reset. This affects hardware-accuracy and test
# determinism.
#
# Valid values:
#   - zero: Initialize all RAM to 0x00 (predictable, not hardware-accurate)
#   - random: Initialize all RAM to pseudo-random values (hardware-accurate)
#   - seeded-random:SEED: Initialize RAM with pseudo-random values using a fixed seed
#                         (hardware-accurate and deterministic for testing)
#
# Soft resets preserve RAM contents (no re-initialization).
#
# Default: zero (deterministic for testing and debugging)
#
# Note: For hardware-accurate behavior, set to "random"
#
# Examples:
#   ram_init_mode=zero
#   ram_init_mode=random
#   ram_init_mode=seeded-random:12345
#
ram_init_mode=zero

# -----------------------------------------------------------------------------
# OAM DRAM Decay
# -----------------------------------------------------------------------------
# Enable or disable dynamic OAM DRAM decay emulation.
#
# Notes:
# - This is an explicit emulator feature toggle and defaults to disabled.
# - NTSC behavior is affected when enabled.
# - PAL remains non-decaying due PAL OAM refresh behavior.
#
# Valid values: true, false
#
oam_dram_decay=false

# -----------------------------------------------------------------------------
# Overscan Removal
# -----------------------------------------------------------------------------
# Simulate a CRT television by removing overscan pixels before displaying.
# Pixels are removed symmetrically from both edges.
#
# horizontal_overscan: pixels removed from each of left and right edges.
#   Valid range: 0..=8. Default: 8.
#
# vertical_overscan: pixels removed from each of top and bottom edges.
#   Valid range: 0..=16. Default: 8.
#
horizontal_overscan=8
vertical_overscan=8