emulator: Sonic 3 A.I.R. type: standalone core_classification: game_engine source: "https://github.com/Eukaryot/sonic3air" upstream: "https://github.com/Eukaryot/sonic3air" source_commit: "de0fd6a7c07b399c9a612cb7cb8d61b54cb339d1" profiled_date: "2026-10-04" display_name: "Sonic 3 - Angel Island Revisited" cores: [sonic3air] systems: [sonic3-air] notes: | Sonic 3 - Angel Island Revisited by Eukaryot. The Oxygen Engine runs the decompiled game logic (lemon scripts) against the original Genesis ROM loaded at runtime. The ROM is not shipped with the engine. ROM search order (ResourcesCache::loadRom): 1. GameAppData/ 2. Last known ROM path (settings.json RomPath) 3. Configured RomPath (config.json) 4. SteamRomName in the install directory 5. Steam library .../Sega Classics/uncompressed ROMs/ 6. User-picked file via native file dialog (filter *.bin) ref: Oxygen/oxygenengine/source/oxygen/resources/ResourcesCache.cpp:19-115, Oxygen/oxygenengine/source/oxygen/application/GameLoader.cpp:60-94, Oxygen/oxygenengine/source/oxygen/platform/PlatformFunctions.cpp:379-408 ROM validation (ResourcesCache::loadRomFile + checkRomContent): 1. Read file into memory. 2. applyRomModifications: XOR optional diff file, blank regions, then byte overwrites from the active RomInfo. The default S3K_Steam entry sets offset 0x2001f0 = 0x4a (patches the ROM header checksum field so the Steam dump matches the authoritative hash). 3. Size check: must equal 0x400000 (4 MiB). 4. Content check: Murmur2_64 of the full post-modification ROM must equal 0x344983ffcfeff8cb. ref: Oxygen/oxygenengine/source/oxygen/resources/ResourcesCache.cpp:152-282, Oxygen/sonic3air/source/sonic3air/ConfigurationImpl.cpp:33-47, Oxygen/sonic3air/oxygenproject.json:9-20 The engine ships four data packages (enginedata.bin, gamedata.bin, audiodata.bin, audioremaster.bin). Three are required and part of the release, while audioremaster.bin is optional and downloaded on demand from https://sonic3air.org/download/audioremaster.bin when the user enables the remastered soundtrack. ref: Oxygen/sonic3air/oxygenproject.json:32-38, Oxygen/sonic3air/source/sonic3air/EngineDelegate.cpp:115-118, Oxygen/sonic3air/source/sonic3air/audio/RemasteredMusicDownload.cpp:48-62 The packages are written by the game binary itself when run with -pack from Oxygen/sonic3air/ (PackageBuilder::performPacking), which the mastering scripts call before copying the results to the release image. gamedata.bin data/ without data/audio/ and data/metadata.json audiodata.bin data/audio/original/ audioremaster.bin data/audio/remastered/ enginedata.bin ../oxygenengine/data/ Each package is a flat container: "OPCK", format version 3, content version BUILD_NUMBER, then one entry per file keyed by its path relative to the base directory, in std::map order. Packing reads the data directories only. The ROM is not involved. ref: Oxygen/sonic3air/source/sonic3air/main.cpp:92-97, Oxygen/sonic3air/source/sonic3air/helper/PackageBuilder.cpp:16-63, Oxygen/oxygenengine/source/oxygen/file/FilePackage.cpp:44-151, Oxygen/oxygenengine/source/oxygen/file/FilePackage.h:28-30, Oxygen/sonic3air/source/sonic3air/version.inc:1, Oxygen/sonic3air/___internal/mastering/mastering_linux.sh:48-52 Each package is opened from the game data directory, data/ under the install directory, then from data/ under the app-data directory, where the downloader saves audioremaster.bin. Package paths below are written under sonic3-air/, which stands for either root. ref: Oxygen/oxygenengine/source/oxygen/engine/EngineMain.cpp:643-651, Oxygen/oxygenengine/source/oxygen/application/Configuration.cpp:288-289 Only one RomInfo is declared (S3K_Steam). The engine does not support on-the-fly Sonic 3 + Sonic & Knuckles lock-on concatenation at run time, so the user must supply the 4 MiB combined ROM (as distributed with Sega Mega Drive & Genesis Classics / Sonic Origins). files: - name: "Sonic_Knuckles_wSonic3.bin" category: game_data system: sonic3-air required: true size: 4194304 validation: [size] source_ref: "Oxygen/sonic3air/source/sonic3air/ConfigurationImpl.cpp:39-46 (fillDefaultGameProfile), Oxygen/oxygenengine/source/oxygen/resources/ResourcesCache.cpp:262-277 (checkRomContent)" note: | Sonic 3 & Knuckles combined ROM as shipped on Steam (Sega Mega Drive and Genesis Classics / Sonic Origins). Expected size 0x400000 bytes. After the engine overwrites offset 0x2001f0 with 0x4a, Murmur2_64 of the whole buffer must equal 0x344983ffcfeff8cb (not CRC32: the hash is computed with rmx::getMurmur2_64 over mRom). The engine also accepts a user-picked .bin via the native file-selection dialog that satisfies the same post-modification check. - name: "enginedata.bin" path: "sonic3-air/data/enginedata.bin" category: game_data system: sonic3-air required: true bundled: true size: 508007 sha1: "8b54d9f850288325b5bac6e5a0cd4b496d6310d4" md5: "760334d49c9bd08309e12b8841731576" source_ref: "Oxygen/sonic3air/source/sonic3air/EngineDelegate.cpp:115, Oxygen/oxygenengine/source/oxygen/engine/EngineMain.cpp:603-617, Oxygen/oxygenengine/source/oxygen/engine/EngineMain.cpp:643-651, Oxygen/sonic3air/source/sonic3air/helper/PackageBuilder.cpp:57-62" note: | Oxygen Engine data package, packed from Oxygen/oxygenengine/data/ (fonts, images, shaders, sprites, oxygen_icon.png). A required package that cannot be opened closes the application, unless the data is present unpacked (data/images/icon.png exists). The engine then checks for oxygen_icon.png in the engine data and stops when it is absent (EngineMain.cpp:584-593). Shipped under data/ in the v26.03.28.0 Windows zip, Linux tar.gz and APK. Batocera installs data/ unpacked from the source tree instead (sonic3-air.mk:40). - name: "gamedata.bin" path: "sonic3-air/data/gamedata.bin" category: game_data system: sonic3-air required: true bundled: true size: 3705612 sha1: "7e84e6798d6bf2196b14eeac5f96d4b9e37a27a4" md5: "793157701edac935c1662832b93b92cb" source_ref: "Oxygen/sonic3air/source/sonic3air/EngineDelegate.cpp:116, Oxygen/oxygenengine/source/oxygen/engine/EngineMain.cpp:603-617, Oxygen/oxygenengine/source/oxygen/engine/EngineMain.cpp:643-651, Oxygen/sonic3air/source/sonic3air/helper/PackageBuilder.cpp:36-41" note: | Game data package, packed from Oxygen/sonic3air/data/ without the audio directory and metadata.json (binary tables, fonts, images, rawdata, sprites). A required package that cannot be opened closes the application, unless the data is present unpacked (data/images/icon.png exists). Shipped under data/ in the v26.03.28.0 Windows zip, Linux tar.gz and APK. Batocera installs data/ unpacked from the source tree instead (sonic3-air.mk:40). - name: "audiodata.bin" path: "sonic3-air/data/audiodata.bin" category: game_data system: sonic3-air required: true bundled: true size: 2289447 sha1: "2f8e0e046a60b75229d90e1f1b7b02823ec05d90" md5: "9b6aa7442bbac1053b91ab72a889b0b1" source_ref: "Oxygen/sonic3air/source/sonic3air/EngineDelegate.cpp:117, Oxygen/oxygenengine/source/oxygen/engine/EngineMain.cpp:603-617, Oxygen/oxygenengine/source/oxygen/engine/EngineMain.cpp:643-651, Oxygen/sonic3air/source/sonic3air/helper/PackageBuilder.cpp:43-48" note: | Audio data package, packed from Oxygen/sonic3air/data/audio/original/ (emulated soundtrack definitions and prototype SMPS tracks). A required package that cannot be opened closes the application, unless the data is present unpacked (data/images/icon.png exists). Shipped under data/ in the v26.03.28.0 Windows zip, Linux tar.gz and APK. Batocera installs data/ unpacked from the source tree instead (sonic3-air.mk:40). - name: "audioremaster.bin" path: "sonic3-air/data/audioremaster.bin" category: game_data system: sonic3-air required: false source_ref: "Oxygen/sonic3air/source/sonic3air/EngineDelegate.cpp:118 (mDataPackages, Required=false), Oxygen/sonic3air/source/sonic3air/audio/RemasteredMusicDownload.cpp:45-62" note: | Remastered soundtrack package (131677405 bytes). Downloaded on demand from https://sonic3air.org/download/audioremaster.bin, saved as data/audioremaster.bin under the app-data directory and reloaded via EngineMain::reloadFilePackage. Absent at first launch. The engine falls back to the emulated FM soundtrack.