jsgroth_jgenesis/ARCHITECTURE.md
jsgroth db5763845a SDL2 -> SDL3
SDL3 is built from source by default and optionally statically linked; both of these are controlled using Cargo features in the CLI and GUI packages

AppImage builds need to statically link SDL3 when building SDL3 from source because otherwise the AppImage build process won't locate the SDL3 shared library file (possibly a way to fix this but I didn't see anything obvious)

these changes required removing two config settings:
* borderless vs. exclusive fullscreen, since changing this seems to be much more difficult in SDL3
* audio hardware/device queue size, which SDL3 no longer seems to expose directly
2025-08-14 17:43:32 -05:00

6.9 KiB

Architecture

Overview

The crates can be broken up roughly into 6 categories:

  • Common libraries: jgenesis-common, jgenesis-proc-macros, cdrom, dsp
  • CPU emulators: z80-emu, m68000-emu, mos6502-emu, wdc65816-emu, spc700-emu, sh2-emu
  • Config libraries: smsgg-config, genesis-config, nes-config, snes-config, gb-config
  • Emulation backend: smsgg-core, genesis-core, segacd-core, s32x-core, nes-core, snes-core, snes-coprocessors, gb-core, ym-opll
  • Emulation frontend: jgenesis-renderer, jgenesis-native-driver, jgenesis-native-config, jgenesis-cli, jgenesis-gui, jgenesis-web
  • CPU emulator test harnesses: z80-test-runner, m68000-test-runner, mos6502-test-runner, wdc65816-test-runner, spc700-test-runner

Repo structure:

  • common/ contains common library crates
  • cpu/ contains the CPU emulator and test harness crates
  • config/ contains the config library crates
  • backend/ contains the emulation backend crates
  • frontend/ contains the emulation frontend crates

The CPU emulators are designed to be usable with any implementation of their respective bus traits. The test harnesses provide a bus implementation that maps every address to RAM (which is what the tests expect), while the various consoles provide implementations that emulate the console's memory map.

The "config" crates contain common structs and enums that are both used in the corresponding backend crate and serialized into the frontend's config file. These are in separate crates from the backend cores to improve incremental compilation times, specifically by only re-executing serde and clap derive macros when needed.

For the most part, the backends interact with the frontends through trait implementations. The backends implement traits that enable frontend features including save states and rewind. The frontends provide trait implementations to the backends that enable the backends to display video frames, output audio samples, and persist any save files (e.g. for a cartridge with battery-backed SRAM). The frontends are also responsible for passing current emulated controller state to the backends (i.e. which buttons are currently pressed).

Common Crates

jgenesis-common

Contains traits that define the interface between the emulation backends and the emulation frontends, as well as some dependency-light common code that is used across many of the other crates (e.g. helper extension traits).

jgenesis-proc-macros

Custom derive macros and other proc macros used across many of the other crates.

cdrom

Contains code for reading CD-ROM images in CUE/BIN or CHD format.

dsp

DSP (digital signal processing) code, used primarily for audio-related functionality (e.g. resampling).

CPU Crates

z80-emu

Instruction-based emulation core for the Zilog Z80 CPU, which is used in the Master System, the Game Gear, and the Genesis.

m68000-emu

Instruction-based emulation core for the Motorola 68000 CPU, which is used in the Genesis and the Sega CD.

mos6502-emu

Cycle-based emulation core for the MOS 6502 CPU. Supports both the stock 6502 and the NES 6502.

wdc65816-emu

Cycle-based emulation core for the WDC 65C816 CPU (aka 65816), which is used in the SNES.

spc700-emu

Cycle-based emulation core for the Sony SPC700 CPU, which is used in the SNES as a dedicated audio processor embedded inside the APU.

sh2-emu

Instruction-based emulation core for the Hitachi SH-2 CPU, used in the Sega 32X and the Sega Saturn. This implementation includes the SH7604 hardware features.

Config Crates

smsgg-config

Common structs and enums for the Sega Master System and Game Gear.

genesis-config

Common structs and enums for the Sega Genesis, including Sega CD and 32X.

nes-config

Common structs and enums for NES.

snes-config

Common structs and enums for SNES.

gb-config

Common structs and enums for Game Boy and Game Boy Color.

Backend Crates

ym-opll

Emulation core for the Yamaha OPLL sound chip, used in the Sega Master System FM sound unit expansion and the NES VRC7 mapper.

smsgg-core

Emulation core for the Sega Master System and Game Gear. The core is shared because there are very few hardware differences between the two.

genesis-core

Emulation core for the Sega Genesis / Mega Drive. Uses the PSG component from smsgg-core, since the Genesis reused the Master System PSG as a secondary sound chip.

segacd-core

Emulation core for the Sega CD / Mega CD. Uses many components from genesis-core, as the Genesis side of the system is virtually unchanged except for the parts of the memory map that the standalone Genesis maps to the cartridge.

s32x-core

Emulation core for the Sega 32X / Mega 32X. Also uses many components from genesis-core.

nes-core

Emulation core for the Nintendo Entertainment System (NES) / Famicom.

snes-core

Emulation core for the Super Nintendo Entertainment System (SNES) / Super Famicom. Depends on snes-coprocessors to emulate cartridges that contain coprocessors.

snes-coprocessors

Emulation for coprocessors used in SNES cartridges. Coprocessor cartridge implementations expose methods such as reading a memory address, writing a memory address, and ticking the internal processor (for cartridges that contain a CPU or DSP).

gb-core

Emulation core for the Game Boy and Game Boy Color.

Frontend Crates

jgenesis-renderer

GPU-based implementation of the Renderer trait in jgenesis-traits, built on top of wgpu. Can be used with any window that implements the raw-window-handle traits. Exists in its own crate so that it can be used in both the native and web frontends.

jgenesis-native-driver

Native emulation frontend that uses SDL3 for windowing, audio, and input.

jgenesis-native-config

Contains the code representation of the configuration file used by the CLI and GUI.

jgenesis-cli / jgenesis-gui

CLI and GUI that both invoke jgenesis-native-driver to run the emulator. jgenesis-gui is built using egui and eframe.

jgenesis-web

Web emulation frontend that compiles to WASM and runs in a web browser.

CPU Test Harness Crates

z80-test-runner

Test harness to test z80-emu against Z80 test suites that were assembled for old PCs, such as ZEXDOC and ZEXALL.

m68000-test-runner

Test harness to test m68000-emu against TomHarte's 68000 test suite.

mos6502-test-runner

Test harness to test mos6502-emu against TomHarte's NES 6502 test suite.

wdc65816-test-runner

Test harness to test wdc65816-emu against TomHarte's 65816 test suite.

spc700-test-runner

Test harness to test spc700-emu against JSON SPC700 test suites.