From 6821e0035459e43b20b65ae423384775da7470cd Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Sun, 4 Oct 2026 14:54:28 +0200 Subject: [PATCH] feat: profile doom-family engines --- emulators/dhewm3.yml | 122 +++++++++++++ emulators/gzdoom.yml | 342 +++++++++++++++++++++++++++++++++++++ emulators/iortcw.yml | 154 +++++++++++++++++ emulators/jazz2-native.yml | 205 ++++++++++++++++++++++ emulators/openjazz.yml | 178 +++++++++++++++++++ emulators/raze.yml | 250 +++++++++++++++++++++++++++ emulators/thextech.yml | 133 +++++++++++++++ 7 files changed, 1384 insertions(+) create mode 100644 emulators/dhewm3.yml create mode 100644 emulators/gzdoom.yml create mode 100644 emulators/iortcw.yml create mode 100644 emulators/jazz2-native.yml create mode 100644 emulators/openjazz.yml create mode 100644 emulators/raze.yml create mode 100644 emulators/thextech.yml diff --git a/emulators/dhewm3.yml b/emulators/dhewm3.yml new file mode 100644 index 00000000..2f58c121 --- /dev/null +++ b/emulators/dhewm3.yml @@ -0,0 +1,122 @@ +emulator: dhewm3 +type: standalone +core_classification: community_fork +source: "https://github.com/dhewm/dhewm3" +upstream: "https://github.com/dhewm/dhewm3" +profiled_date: "2026-10-04" +source_commit: "455b88e8dff2be822f08eb498f51b383e851fa38" +core_version: "1.5.5" +display_name: "dhewm3" +cores: [] +systems: [doom3] + +notes: | + Doom 3 source port based on the id Software GPL release of the + Doom 3 engine (idTech 4). Carries the original Doom 3 1.3.1 game + code plus bug fixes, SDL abstraction and 64-bit cleanup. + + The engine refuses to run without a `base/` directory containing + the retail pak files. Resurrection of Evil goes in `d3xp/`. + ref: neo/framework/FileSystem.cpp:88-112 ("either base or demo"), + neo/framework/FileSystem.cpp:2089 AddGameDirectory, + neo/framework/FileSystem.cpp:2235 SetupGameDirectories(BASE_GAMEDIR) + BASE_GAMEDIR is defined as "base" (neo/framework/Common.cpp:2724). + + Pak loading scans the gamedir for *.pk4 and loads them in descending + order so a later pak overrides earlier ones. + ref: neo/framework/FileSystem.cpp:2125-2143 (ListOSFiles ".pk4"). + +files: + # ================================================================ + # base/ - Doom 3 retail paks + # README.md:136 names "pak000.pk4 to pak008.pk4"; the engine itself + # loads every .pk4 found in the gamedir, so the exact set depends on + # which patch level the user owns (1.3.1 ships 008). + # ================================================================ + + - name: "pak000.pk4" + category: game_data + system: doom3 + path: "base/pak000.pk4" + required: true + source_ref: "neo/framework/FileSystem.cpp:2125 (ListOSFiles pakfile .pk4)" + + - name: "pak001.pk4" + category: game_data + system: doom3 + path: "base/pak001.pk4" + required: true + source_ref: "neo/framework/FileSystem.cpp:2125" + + - name: "pak002.pk4" + category: game_data + system: doom3 + path: "base/pak002.pk4" + required: true + source_ref: "neo/framework/FileSystem.cpp:2125" + + - name: "pak003.pk4" + category: game_data + system: doom3 + path: "base/pak003.pk4" + required: true + source_ref: "neo/framework/FileSystem.cpp:2125" + + - name: "pak004.pk4" + category: game_data + system: doom3 + path: "base/pak004.pk4" + required: true + source_ref: "neo/framework/FileSystem.cpp:2125" + + - name: "pak005.pk4" + category: game_data + system: doom3 + path: "base/pak005.pk4" + required: false + source_ref: "neo/framework/FileSystem.cpp:2125" + note: "Shipped with 1.1 patch; absent on 1.0 install." + + - name: "pak006.pk4" + category: game_data + system: doom3 + path: "base/pak006.pk4" + required: false + source_ref: "neo/framework/FileSystem.cpp:2125" + note: "Shipped with 1.2 patch." + + - name: "pak007.pk4" + category: game_data + system: doom3 + path: "base/pak007.pk4" + required: false + source_ref: "neo/framework/FileSystem.cpp:2125" + note: "Shipped with 1.3 patch." + + - name: "pak008.pk4" + category: game_data + system: doom3 + path: "base/pak008.pk4" + required: false + source_ref: "neo/framework/FileSystem.cpp:2125, neo/framework/FileSystem.cpp:893-897" + note: "Shipped with 1.3.1 patch; path handling explicitly names it." + + - name: "zpak001.pk4" + category: game_data + system: doom3 + path: "base/zpak001.pk4" + required: false + source_ref: "neo/framework/FileSystem.cpp:232 (\"russian zpak001.pk4\")" + note: "Russian localization pak." + + # ================================================================ + # d3xp/ - Resurrection of Evil expansion (optional) + # ================================================================ + + - name: "pak000.pk4" + category: game_data + system: doom3 + path: "d3xp/pak000.pk4" + required: false + source_ref: "neo/framework/FileSystem.cpp:3744-3754 (explicit d3xp/pak000.pk4 probe)" + note: "Resurrection of Evil main pak." diff --git a/emulators/gzdoom.yml b/emulators/gzdoom.yml new file mode 100644 index 00000000..921f68d9 --- /dev/null +++ b/emulators/gzdoom.yml @@ -0,0 +1,342 @@ +emulator: GZDoom +type: standalone +core_classification: game_engine +source: "https://github.com/ZDoom/gzdoom" +upstream: "https://github.com/ZDoom/gzdoom" +profiled_date: "2026-10-04" +source_commit: "c26ce2e6ca2a0c770f140cb25dde0d30073ca8f7" +core_version: "4.15pre" +display_name: "GZDoom" +cores: [] +systems: [doom, heretic, hexen, strife, chex] + +notes: | + Doom-engine source port by Christoph Oelckers. Supports Doom, Heretic, + Hexen, Strife, Chex Quest and derived games through a unified IWAD + identification pass. + + Engine resources (built from wadsrc*/static/ via add_pk3): + gzdoom.pk3 BASEWAD, searched by BaseFileSearch + ref: src/version.h:90, src/d_main.cpp + game_support.pk3 OPTIONALWAD, filter/game assets per IWAD + ref: src/version.h:92 + lights.pk3 dynamic light definitions + brightmaps.pk3 brightmap textures + game_widescreen_gfx.pk3 widescreen HUD/menu replacements + + Game data is a user-supplied IWAD. iwadinfo.txt declares each known IWAD + with its IWADName, MustContain lumps and support files. + ref: wadsrc_extra/static/iwadinfo.txt + + Startup refuses to run if BASEWAD (gzdoom.pk3) is absent. The other + engine pk3s and the IWAD selection are read from the same base search + (fs_basepath, home dir, system paths). + +files: + # ================================================================ + # Engine resources (shipped with the port, add_pk3 in CMakeLists) + # ================================================================ + + - name: "gzdoom.pk3" + category: game_data + required: true + source_ref: "src/version.h:90 (BASEWAD), wadsrc/CMakeLists.txt:1" + note: "Fonts, menus, zscript, textures. Fatal if absent." + + - name: "game_support.pk3" + category: game_data + required: false + source_ref: "src/version.h:92 (OPTIONALWAD), wadsrc_extra/CMakeLists.txt:1" + note: "Per-game filters under static/filter/ (doom.id, strife, hexen, heretic, chex...)." + + - name: "lights.pk3" + category: game_data + required: false + source_ref: "src/d_main.cpp:2055, wadsrc_lights/CMakeLists.txt:1" + + - name: "brightmaps.pk3" + category: game_data + required: false + source_ref: "src/d_main.cpp:2061, wadsrc_bm/CMakeLists.txt:1" + + - name: "game_widescreen_gfx.pk3" + category: game_data + required: false + source_ref: "src/d_main.cpp:2067, wadsrc_widepix/CMakeLists.txt:1" + + # ================================================================ + # IWADs (user-supplied). At least one is needed to launch a game. + # All source refs point to wadsrc_extra/static/iwadinfo.txt entries. + # ================================================================ + + # ---- Doom ---- + + - name: "doom.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (The Ultimate DOOM / DOOM Registered)" + note: "Ultimate Doom (version 2) or Doom Registered (version 1)." + + - name: "doom2.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM 2: Hell on Earth)" + + - name: "doom2f.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM 2: L'Enfer sur Terre)" + + - name: "doombfg.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM: BFG Edition)" + + - name: "doom2bfg.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM 2: BFG Edition)" + + - name: "doomunity.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM: Unity Edition)" + + - name: "doom2unity.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM 2: Unity Edition)" + + - name: "doomkex.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM: KEX Edition)" + + - name: "doom2kex.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM 2: KEX Edition)" + + - name: "doomxbox.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM: XBox Edition)" + + - name: "doom2xbox.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM 2: XBox Edition)" + + - name: "doom_complete.pk3" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM: Complete: WadSmoosh)" + + - name: "plutonia.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Final Doom: Plutonia Experiment)" + + - name: "plutoniaunity.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Plutonia Unity Edition)" + + - name: "plutoniakex.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Plutonia KEX Edition)" + + - name: "tnt.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Final Doom: TNT - Evilution)" + + - name: "tntunity.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (TNT Unity Edition)" + + - name: "tntkex.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (TNT KEX Edition)" + + - name: "nerve.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Load = \"nerve.wad\" under DOOM 2: BFG/XBox)" + note: "No Rest for the Living. Autoloaded by Doom 2 BFG and Xbox editions." + + - name: "nerveunity.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Load under DOOM 2: Unity Edition)" + + - name: "extras.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Load under KEX/Unity editions)" + + - name: "id24res.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (SupportWAD on every id iwad)" + note: "id24 resource WAD. Loaded with any id IWAD when present." + + # ---- Freedoom (free) ---- + + - name: "freedoom1.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Freedoom: Phase 1)" + + - name: "freedoom2.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Freedoom: Phase 2)" + + - name: "freedm.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (FreeDM)" + + # ---- Heretic ---- + + - name: "heretic.wad" + category: game_data + system: heretic + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Heretic / Heretic: Shadow of the Serpent Riders)" + note: "Both Heretic 1.0 and Shadow of the Serpent Riders use this name; distinguished by EXTENDED lump." + + - name: "blasphem.wad" + category: game_data + system: heretic + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Blasphemer)" + + # ---- Hexen ---- + + - name: "hexen.wad" + category: game_data + system: hexen + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Hexen: Beyond Heretic)" + + - name: "hexdd.wad" + category: game_data + system: hexen + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Hexen: Deathkings of the Dark Citadel)" + note: "Deathkings expansion. Requires hexen.wad (Required = Hexen: Beyond Heretic)." + + # ---- Strife ---- + + - name: "strife1.wad" + category: game_data + system: strife + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Strife: Quest for the Sigil)" + + - name: "sve.wad" + category: game_data + system: strife + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Strife: Veteran Edition)" + note: "Veteran Edition. Required = Strife: Quest for the Sigil (loads voices.wad)." + + - name: "voices.wad" + category: game_data + system: strife + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Load = \"voices.wad\" on Strife entries)" + + # ---- Chex Quest ---- + + - name: "chex.wad" + category: game_data + system: chex + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Chex(R) Quest)" + + - name: "chex3.wad" + category: game_data + system: chex + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Chex(R) Quest 3)" + + # ---- Standalone commercial / community IWADs ---- + + - name: "hacx.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Hacx: Twitch'n Kill)" + + - name: "hacx2.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Hacx 2.0)" + + - name: "action2.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Action Doom 2: Urban Brawl)" + + - name: "harm1.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Harmony)" + + - name: "square.pk3" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (The Adventures of Square)" + + - name: "square1.pk3" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (The Adventures of Square - Squareware)" + + - name: "delaweare.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Delaweare)" + + - name: "rotwb.wad" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt (Rise Of The Wool Ball)" diff --git a/emulators/iortcw.yml b/emulators/iortcw.yml new file mode 100644 index 00000000..8cc1b04e --- /dev/null +++ b/emulators/iortcw.yml @@ -0,0 +1,154 @@ +emulator: ioRTCW +type: standalone +core_classification: community_fork +source: "https://github.com/iortcw/iortcw" +upstream: "https://github.com/iortcw/iortcw" +profiled_date: "2026-10-04" +source_commit: "438e7d413b5f7277187c35b032eb0ef9093ae778" +display_name: "ioRTCW" +cores: [] +systems: [return-to-castle-wolfenstein] + +notes: | + Return to Castle Wolfenstein source port derived from the ioquake3 + codebase and the id Software GPL release of RTCW. Ships as two + separate executables: Single-player and Multiplayer, each with its + own filesystem layer under SP/code/ and MP/code/. + + BASEGAME is "main" for both builds. + ref: SP/code/qcommon/qcommon.h:628, MP/code/qcommon/qcommon.h:656 + + Single-player (SP/code/qcommon/files.c): + main/pak0.pk3 retail base, checksum 1886207346 + fatal if present with wrong checksum + main/sp_pak1.pk3 patch pak, five localized checksums (en/fr/gm/it/sp) + main/sp_pak2.pk3 patch pak, same localization split + main/sp_pak3.pk3 patch pak, same localization split + main/sp_pak4.pk3 GOTY edition pak, single checksum across languages + ref: SP/code/qcommon/files.c:183-230 (checksum arrays), + SP/code/qcommon/qcommon.h:637 (NUM_ID_PAKS 6), + SP/code/qcommon/files.c:3859-3883 (pak0 fatal check) + + Multiplayer (MP/code/qcommon/files.c): + main/pak0.pk3 shared base, checksum 1886207346 + main/mp_pak0.pk3 checksum 764840216 + main/mp_pak1.pk3 checksum -1023558518 + main/mp_pak2.pk3 checksum 125907563 + main/mp_pak3.pk3 checksum 131270674 + main/mp_pak4.pk3 checksum -137448799 + main/mp_pak5.pk3 checksum 2149774797 + main/mp_bin.pk3 or mp_bin0.pk3 (1.51c) - VM/binary pak, optional + ref: MP/code/qcommon/files.c:188-225 (mppak_checksums, binpak_checksums) + + The SP build's pak0 fatal-error check only fires when a mismatched + pak0 is present; a missing pak0 ends up as "no game data found". + +files: + # ================================================================ + # main/ - shared base + # ================================================================ + + - name: "pak0.pk3" + category: game_data + system: return-to-castle-wolfenstein + path: "main/pak0.pk3" + required: true + source_ref: "SP/code/qcommon/files.c:183-184 (pak_checksums), SP/code/qcommon/files.c:3859 (fatal check)" + note: "RTCW retail base. Checksum 1886207346; same checksum used by SP and MP." + + # ================================================================ + # main/ - single-player patches (localized sp_pak1-3, universal sp_pak4) + # ================================================================ + + - name: "sp_pak1.pk3" + category: game_data + system: return-to-castle-wolfenstein + path: "main/sp_pak1.pk3" + required: false + source_ref: "SP/code/qcommon/files.c:187-224 (en/fr/gm/it/sp_sppak_checksums[0])" + note: "Localization-specific patch pak. One of five checksums expected." + + - name: "sp_pak2.pk3" + category: game_data + system: return-to-castle-wolfenstein + path: "main/sp_pak2.pk3" + required: false + source_ref: "SP/code/qcommon/files.c:188-225 (sppak_checksums[1])" + + - name: "sp_pak3.pk3" + category: game_data + system: return-to-castle-wolfenstein + path: "main/sp_pak3.pk3" + required: false + source_ref: "SP/code/qcommon/files.c:189-226 (sppak_checksums[2])" + + - name: "sp_pak4.pk3" + category: game_data + system: return-to-castle-wolfenstein + path: "main/sp_pak4.pk3" + required: false + source_ref: "SP/code/qcommon/files.c:190 (\"sp_pak4.pk3 from GOTY edition\"), checksum 4131017020" + note: "GOTY-edition patch; single checksum shared across languages." + + # ================================================================ + # main/ - multiplayer patches + # ================================================================ + + - name: "mp_pak0.pk3" + category: game_data + system: return-to-castle-wolfenstein + path: "main/mp_pak0.pk3" + required: false + source_ref: "MP/code/qcommon/files.c:188 (mppak_checksums[0]=764840216)" + note: "Multiplayer base. MP build warns if absent but continues." + + - name: "mp_pak1.pk3" + category: game_data + system: return-to-castle-wolfenstein + path: "main/mp_pak1.pk3" + required: false + source_ref: "MP/code/qcommon/files.c:189 (mppak_checksums[1])" + + - name: "mp_pak2.pk3" + category: game_data + system: return-to-castle-wolfenstein + path: "main/mp_pak2.pk3" + required: false + source_ref: "MP/code/qcommon/files.c:190 (mppak_checksums[2])" + + - name: "mp_pak3.pk3" + category: game_data + system: return-to-castle-wolfenstein + path: "main/mp_pak3.pk3" + required: false + source_ref: "MP/code/qcommon/files.c:191 (mppak_checksums[3])" + + - name: "mp_pak4.pk3" + category: game_data + system: return-to-castle-wolfenstein + path: "main/mp_pak4.pk3" + required: false + source_ref: "MP/code/qcommon/files.c:192 (mppak_checksums[4])" + + - name: "mp_pak5.pk3" + category: game_data + system: return-to-castle-wolfenstein + path: "main/mp_pak5.pk3" + required: false + source_ref: "MP/code/qcommon/files.c:193 (mppak_checksums[5])" + + - name: "mp_bin.pk3" + category: game_data + system: return-to-castle-wolfenstein + path: "main/mp_bin.pk3" + required: false + source_ref: "MP/code/qcommon/files.c:199 (binpak_checksums, \"mp_bin.pk3 (1.4/1.41)\")" + note: "VM/binary pak, 1.4/1.41 retail." + + - name: "mp_bin0.pk3" + category: game_data + system: return-to-castle-wolfenstein + path: "main/mp_bin0.pk3" + required: false + source_ref: "MP/code/qcommon/files.c:200 (binpak_checksums, \"mp_bin0.pk3 (1.51c)\")" + note: "VM/binary pak, 1.51c variant." diff --git a/emulators/jazz2-native.yml b/emulators/jazz2-native.yml new file mode 100644 index 00000000..40667556 --- /dev/null +++ b/emulators/jazz2-native.yml @@ -0,0 +1,205 @@ +emulator: Jazz² Resurrection +type: standalone +core_classification: game_engine +source: "https://github.com/deathkiller/jazz2-native" +upstream: "https://github.com/deathkiller/jazz2-native" +profiled_date: "2026-10-04" +source_commit: "cc06bdac1b957a069e1d05761c7437cd59886552" +core_version: "3.8.0" +display_name: "Jazz Jackrabbit 2 (Jazz² Resurrection)" +cores: [] +systems: [jazz-jackrabbit-2] + +notes: | + Open-source reimplementation of Jazz Jackrabbit 2 by Dan R. The engine + ships its own Content/ tree (animations, metadata, translations, + shaders) that must sit next to the executable. + ref: Sources/Jazz2/ContentResolver.cpp:187-240 (GetContentPath per + platform), ContentResolver.cpp:415-452 (desktop fallbacks) + + Original Jazz Jackrabbit 2 data is read from Source/ and converted + on first launch into the engine's own pak format under Cache/. + ref: Sources/Jazz2/ContentResolver.cpp:279-310 (GetSourcePath), + Sources/Jazz2/Compatibility/AssetConverter.cpp:139-170 + (ConvertSourceAssets, iterates .j2e / .j2l / .j2t / .j2b) + + Content/ is the engine runtime — it is shipped with the release + package. Source/ holds the user's own copy of the 1998 game data. + The engine runs its UI with Content/ alone; levels and episodes + require Source/ to carry JJ2 files. + +files: + # ================================================================ + # Content/ (bundled runtime data, shipped with each release) + # These are generated at build time from the Content/ tree in the + # repo; the engine refuses to render its UI without them. + # ================================================================ + + - name: "Animations/" + category: game_data + path: "Content/Animations" + required: true + source_ref: "Sources/Jazz2/ContentResolver.cpp:2651 (CombinePath Content/Animations)" + note: "Native animation sheets, loaded by ContentResolver for every actor." + + - name: "Metadata/" + category: game_data + path: "Content/Metadata" + required: true + source_ref: "Sources/Jazz2/ContentResolver.cpp (metadata loader for actors, UI, bosses)" + note: "Actor .res descriptors (Common, Enemy, Player, UI, Boss, ...)." + + - name: "Translations/" + category: game_data + path: "Content/Translations" + required: false + source_ref: "Sources/Jazz2/ContentResolver.cpp (translation loader)" + note: "Language bundles. Engine falls back to English if absent." + + - name: "Shaders/" + category: game_data + path: "Content/Shaders" + required: false + source_ref: "Sources/nCine (shader loader)" + note: "GLSL shaders used by the Jazz² renderer. Shipped with the engine." + + # ================================================================ + # Source/ (original Jazz Jackrabbit 2 data, user-supplied) + # Converted into Content/Cache on first launch. + # ================================================================ + + - name: "Anims.j2a" + category: game_data + system: jazz-jackrabbit-2 + path: "Source/Anims.j2a" + required: false + source_ref: "Sources/Jazz2/Compatibility/JJ2Anims.cpp (JJ2Anims::Open)" + note: "Main animation archive. Required to generate the first-run cache." + + - name: "Data.j2d" + category: game_data + system: jazz-jackrabbit-2 + path: "Source/Data.j2d" + required: false + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:162 (data.Open \"Data.j2d\")" + + - name: "Plus.j2d" + category: game_data + system: jazz-jackrabbit-2 + path: "Source/Plus.j2d" + required: false + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp (JJ2+ data block)" + note: "JJ2+ extended data (optional)." + + - name: "Jazz2.exe" + category: game_data + system: jazz-jackrabbit-2 + path: "Source/Jazz2.exe" + required: false + source_ref: "Sources/Jazz2/Compatibility/JJ2Strings.cpp (localization extracted from executable)" + note: "Original executable used only to extract localized strings. The engine does not run it." + + # Episode descriptors (.j2e) and level files (.j2l) are optional per + # episode. Any present in Source/ get discovered at scan time. + # ref: Sources/Jazz2/Compatibility/AssetConverter.cpp:338-437 + + - name: "prince.j2e" + category: game_data + system: jazz-jackrabbit-2 + path: "Source/prince.j2e" + required: false + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:412 (episodesPath enumeration)" + note: "Episode 1 - Formerly a Prince." + + - name: "rescue.j2e" + category: game_data + system: jazz-jackrabbit-2 + path: "Source/rescue.j2e" + required: false + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:412" + note: "Episode 2 - Rescue of the Princess (Shareware episode)." + + - name: "flash.j2e" + category: game_data + system: jazz-jackrabbit-2 + path: "Source/flash.j2e" + required: false + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:412" + note: "Episode 3 - Flashback to the Past." + + - name: "monk.j2e" + category: game_data + system: jazz-jackrabbit-2 + path: "Source/monk.j2e" + required: false + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:412" + note: "Episode 4 - Clash of the Jazz & Monk." + + - name: "funky.j2e" + category: game_data + system: jazz-jackrabbit-2 + path: "Source/funky.j2e" + required: false + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:412" + note: "Episode 5 - Jazz in Time (The Secret Files)." + + - name: "share.j2e" + category: game_data + system: jazz-jackrabbit-2 + path: "Source/share.j2e" + required: false + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:412" + note: "Shareware episode descriptor." + + - name: "xmas99.j2e" + category: game_data + system: jazz-jackrabbit-2 + path: "Source/xmas99.j2e" + required: false + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:182 (hasChristmasChronicles probe)" + note: "Holiday Hare 99. Also auto-renamed from xmas98.j2e by the converter." + + - name: "secretf.j2e" + category: game_data + system: jazz-jackrabbit-2 + path: "Source/secretf.j2e" + required: false + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:412" + note: "The Secret Files (TSF) episode." + + # Audio tracks + - name: "menu.j2b" + category: game_data + system: jazz-jackrabbit-2 + path: "Source/menu.j2b" + required: false + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:536 (MainMenu::PlayMenuMusic)" + note: "Main menu music." + + - name: "intro.j2b" + category: game_data + system: jazz-jackrabbit-2 + path: "Source/intro.j2b" + required: false + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:537 (Cinematics::Initialize)" + + - name: "ending.j2b" + category: game_data + system: jazz-jackrabbit-2 + path: "Source/ending.j2b" + required: false + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:537" + + - name: "bonus2.j2b" + category: game_data + system: jazz-jackrabbit-2 + path: "Source/bonus2.j2b" + required: false + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:536" + + - name: "bonus3.j2b" + category: game_data + system: jazz-jackrabbit-2 + path: "Source/bonus3.j2b" + required: false + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:536" diff --git a/emulators/openjazz.yml b/emulators/openjazz.yml new file mode 100644 index 00000000..db1a93ed --- /dev/null +++ b/emulators/openjazz.yml @@ -0,0 +1,178 @@ +emulator: OpenJazz +type: standalone +core_classification: game_engine +source: "https://github.com/AlisterT/openjazz" +upstream: "https://github.com/AlisterT/openjazz" +profiled_date: "2026-10-04" +source_commit: "a1626f4edd4a7af72c54103021790c56d8ecfced" +core_version: "20260301" +display_name: "Jazz Jackrabbit (OpenJazz)" +cores: [] +systems: [jazz-jackrabbit] + +notes: | + Open-source reimplementation of Jazz Jackrabbit 1 (Epic MegaGames, + 1994). Reads the original DOS game data; no asset bundling in the + engine binary. + + File lookup walks a path list (shareware share, home dir, binary dir, + command-line) and opens the first match. + ref: src/io/file.cpp:46-80 (File::File) + + PANEL.000 is loaded during startup; the engine aborts with + "Unable to find game data files" if that first probe fails. + ref: src/main.cpp:281, src/main.cpp:287-294 + + JJ2 engine support is experimental and gated by `ENABLE_JJ2` at build + time; it reads JJ2's .j2l/.j2t files directly (no conversion step). + ref: src/jj2/level/jj2level.cpp:52-70 + +files: + # ================================================================ + # Required files (loaded unconditionally at startup) + # ================================================================ + + - name: "PANEL.000" + category: game_data + system: jazz-jackrabbit + required: true + source_ref: "src/main.cpp:281 (fatal: \"Unable to find game data files\")" + note: "Status bar sprites plus two embedded fonts. Fatal if absent." + + - name: "SOUNDS.000" + category: game_data + system: jazz-jackrabbit + required: true + source_ref: "src/io/sound.cpp:278 (loadSounds(\"SOUNDS.000\"))" + note: "Digital sound effects. Absence disables sfx but engine continues; audio init logs failure." + + - name: "STARTUP.0SC" + category: game_data + system: jazz-jackrabbit + required: true + source_ref: "src/main.cpp:437 (new JJ1Scene(\"STARTUP.0SC\"))" + note: "Opening Epic logo cutscene. Throws E_FILE on absence (startup aborts before menu)." + + # ================================================================ + # Required for menu entry (loaded when main menu opens) + # ================================================================ + + - name: "MENU.000" + category: game_data + system: jazz-jackrabbit + required: true + source_ref: "src/menu/mainmenu.cpp:74 (new File(\"MENU.000\", PATH_TYPE_GAME))" + note: "Main menu graphics and layout. Required to show the menu." + + - name: "FONTS.000" + category: game_data + system: jazz-jackrabbit + required: true + source_ref: "src/io/gfx/font.cpp:291-292 (JJ1Font constructor)" + note: "Main game font (dialog, HUD numbers)." + + # ================================================================ + # Required when entering gameplay (fatal when first level loads) + # ================================================================ + + - name: "MAINCHAR.000" + category: game_data + system: jazz-jackrabbit + required: true + source_ref: "src/jj1/level/jj1levelload.cpp:223 (JJ1Level::load player sprites)" + note: "Jazz sprite sheet. Required to start any level." + + - name: "BONUS.000" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/jj1/bonuslevel/jj1bonuslevel.cpp:55 (new File(\"BONUS.000\"))" + note: "Bonus level sprites + the bonus-screen font (loaded via FONTS.000 code path with the 'bonus' flag)." + + # ================================================================ + # Level data (per world: 1-9 shareware/registered, 50/51 secret). + # Not every episode is required to run; a user may own only one. + # LEVEL*.* path pattern uses a two-digit level and a three-digit + # world extension, built by createFileName() in src/util.cpp. + # ================================================================ + + - name: "LEVEL0.000" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/jj1/level/jj1demolevel.cpp:78, src/menu/gamemenu.cpp:559 (createFileName \"LEVEL\")" + note: "World 0 first level (shareware episode 1 opener)." + + - name: "PLANET.000" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/jj1/level/jj1levelload.cpp:437-450 (planet.### file open)" + note: "World intro planet screen (name + preview)." + + - name: "BLOCKS1.000" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/jj1/level/jj1levelload.cpp:583-584 (createFileName \"BLOCKS\")" + note: "World 0 tileset. BLOCKS. per level, n = 1..9." + + - name: "SPRITES1.000" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/jj1/level/jj1levelload.cpp:604 (createFileName \"SPRITES\")" + note: "World 0 enemy/object sprites. One file per world." + + - name: "BONUSMAP.000" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/jj1/level/jj1level.cpp:690, src/menu/gamemenu.cpp:324,570" + note: "Bonus level map for episode 1." + + # Shareware episode has worlds 0-2, registered adds 3-5 (6 full worlds + # across 3 episodes). The engine opens LEVEL., PLANET., + # BLOCKS. and SPRITES. for each world the player + # visits; absent episodes just stop progression at the end of the + # last available world. + + - name: "LEVEL0.001" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/jj1/level/jj1demolevel.cpp:78 (createFileName \"LEVEL\", worldNum=1)" + note: "World 1 level 0 (shareware episode 1 world 2 opener)." + + - name: "LEVEL0.002" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/jj1/level/jj1demolevel.cpp:78" + + - name: "LEVEL0.003" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/jj1/level/jj1demolevel.cpp:78" + note: "World 3 (registered episode 2 opener)." + + - name: "LEVEL0.004" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/jj1/level/jj1demolevel.cpp:78" + + - name: "LEVEL0.005" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/jj1/level/jj1demolevel.cpp:78" + + # Cutscene scripts (one per episode intro/outro) + - name: "END.0SC" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/jj1/scene/jj1scene.cpp (JJ1Scene loader; path assembled per cutscene)" + note: "Ending cutscene script. Loaded on episode completion." diff --git a/emulators/raze.yml b/emulators/raze.yml new file mode 100644 index 00000000..5643a72f --- /dev/null +++ b/emulators/raze.yml @@ -0,0 +1,250 @@ +emulator: Raze +type: standalone +core_classification: game_engine +source: "https://github.com/ZDoom/Raze" +upstream: "https://github.com/ZDoom/Raze" +profiled_date: "2026-10-04" +source_commit: "76fe82f5eb318fdeb30ba9fb27093a9a10bc3821" +display_name: "Raze" +cores: [] +systems: [duke3d, blood, shadow-warrior, powerslave, exhumed, redneck, nam, ww2gi] + +notes: | + Build-engine source port derived from EDuke32 and NBlood, maintained + by the ZDoom team. Runs Duke Nukem 3D, Blood, Shadow Warrior, + Powerslave/Exhumed, Redneck Rampage, Nam, Napalm, WWII GI through a + shared Build renderer. + + Engine resource (built via add_pk3): + raze.pk3 ENGINERES_FILE, fatal if absent + ref: source/core/version.h:66, source/core/gamecontrol.cpp:1020-1023, + source/core/initfs.cpp:335-336, wadsrc/CMakeLists.txt:2 + + Game detection reads wadsrc/static/engine/grpinfo.txt. Each entry maps + a size+CRC32 (or mustcontain lump set) to a game id, flags and + optional `loadgrp` / `loadart` dependencies. + ref: source/core/gamecontrol.cpp (GrpScan), wadsrc/static/engine/grpinfo.txt + + At least one game's GRP (or equivalent archive) must be present for + Raze to run. Addons depend on the base game CRC via `dependency`. + +files: + # ================================================================ + # Engine resource + # ================================================================ + + - name: "raze.pk3" + category: game_data + required: true + source_ref: "source/core/version.h:66, source/core/gamecontrol.cpp:1020-1023" + note: "I_FatalError(\"Cannot find raze.pk3\") if absent." + + # ================================================================ + # Duke Nukem 3D family + # ================================================================ + + - name: "DUKE3D.GRP" + category: game_data + system: duke3d + required: false + size: 26524524 + crc32: "BBC9CE44" + source_ref: "wadsrc/static/engine/grpinfo.txt (Duke Nukem 3D)" + + - name: "DUKE3D.GRP" + category: game_data + system: duke3d + path: ".variants/DUKE3D.GRP.aa4f6a40" + required: false + size: 26385383 + crc32: "AA4F6A40" + source_ref: "wadsrc/static/engine/grpinfo.txt (Duke Nukem 3D South Korean Censored)" + + - name: "DUKE3D.GRP" + category: game_data + system: duke3d + path: ".variants/DUKE3D.GRP.fd3dcff1" + required: false + size: 44356548 + crc32: "FD3DCFF1" + source_ref: "wadsrc/static/engine/grpinfo.txt (Duke Nukem 3D: Atomic Edition)" + + - name: "DUKE3D.GRP" + category: game_data + system: duke3d + path: ".variants/DUKE3D.GRP.f514a6ac" + required: false + size: 44348015 + crc32: "F514A6AC" + source_ref: "wadsrc/static/engine/grpinfo.txt (Duke Nukem 3D: Plutonium Pak)" + + - name: "DUKE3D.GRP" + category: game_data + system: duke3d + path: ".variants/DUKE3D.GRP.982afe4a" + required: false + size: 44356548 + crc32: "982AFE4A" + source_ref: "wadsrc/static/engine/grpinfo.txt (Atomic Edition World Tour)" + + - name: "DUKEDC.GRP" + category: game_data + system: duke3d + required: false + source_ref: "wadsrc/static/engine/grpinfo.txt (Duke it out in D.C.)" + note: "Expansion; dependency DUKE15_CRC (Atomic Edition)." + + - name: "VACATION.GRP" + category: game_data + system: duke3d + required: false + source_ref: "wadsrc/static/engine/grpinfo.txt (Duke Caribbean: Life's a Beach)" + note: "Expansion; dependency DUKE15_CRC." + + - name: "NWINTER.GRP" + category: game_data + system: duke3d + required: false + source_ref: "wadsrc/static/engine/grpinfo.txt (Duke: Nuclear Winter)" + + - name: "DUKE3D.GRP" + category: game_data + system: duke3d + path: ".variants/DUKE3D.GRP.983ad923" + required: false + size: 11035779 + crc32: "983AD923" + source_ref: "wadsrc/static/engine/grpinfo.txt (Duke Nukem 3D Shareware 1.3D)" + + # ================================================================ + # Blood + # ================================================================ + + - name: "BLOOD.RFF" + category: game_data + system: blood + required: false + source_ref: "wadsrc/static/engine/grpinfo.txt (BLOOD: One Unit Whole Blood - mustcontain blood.pal; loadgrp BLOOD.GRP)" + note: "Blood main resource. Shipped as part of One Unit Whole Blood / Fresh Supply." + + - name: "BLOOD.GRP" + category: game_data + system: blood + required: false + source_ref: "wadsrc/static/engine/grpinfo.txt (BLOOD: One Unit Whole Blood loadgrp)" + + - name: "SOUNDS.RFF" + category: game_data + system: blood + required: false + source_ref: "wadsrc/static/engine/grpinfo.txt (BLOOD loadgrp \"SOUNDS.RFF\")" + + - name: "GUI.RFF" + category: game_data + system: blood + required: false + source_ref: "wadsrc/static/engine/grpinfo.txt (BLOOD loadgrp \"GUI.RFF\")" + + - name: "CRYPTIC.INI" + category: game_data + system: blood + required: false + source_ref: "wadsrc/static/engine/grpinfo.txt (BLOOD: Cryptic Passage addon)" + + # ================================================================ + # Shadow Warrior + # ================================================================ + + - name: "SW.GRP" + category: game_data + system: shadow-warrior + required: false + size: 47536148 + crc32: "7545319F" + source_ref: "wadsrc/static/engine/grpinfo.txt (Shadow Warrior registered)" + + - name: "WD.GRP" + category: game_data + system: shadow-warrior + required: false + size: 48698128 + crc32: "A9AAA7B7" + source_ref: "wadsrc/static/engine/grpinfo.txt (Shadow Warrior: Wanton Destruction)" + + - name: "TD.GRP" + category: game_data + system: shadow-warrior + required: false + size: 12499012 + crc32: "A1A65BE8" + source_ref: "wadsrc/static/engine/grpinfo.txt (Shadow Warrior: Twin Dragon)" + + # ================================================================ + # Powerslave / Exhumed + # ================================================================ + + - name: "STUFF.DAT" + category: game_data + system: exhumed + required: false + size: 27020745 + crc32: "303CBD89" + source_ref: "wadsrc/static/engine/grpinfo.txt (Powerslave)" + + - name: "STUFF.DAT" + category: game_data + system: exhumed + path: ".variants/STUFF.DAT.e3b172f1" + required: false + size: 27108170 + crc32: "E3B172F1" + source_ref: "wadsrc/static/engine/grpinfo.txt (Exhumed)" + + # ================================================================ + # Redneck Rampage + # ================================================================ + + - name: "REDNECK.GRP" + category: game_data + system: redneck + required: false + size: 141174222 + crc32: "19D9BC79" + source_ref: "wadsrc/static/engine/grpinfo.txt (Redneck Rampage)" + + - name: "REDNECK.GRP" + category: game_data + system: redneck + path: ".variants/REDNECK.GRP.958018c6" + required: false + size: 191798609 + crc32: "958018C6" + source_ref: "wadsrc/static/engine/grpinfo.txt (Redneck Rampage Rides Again)" + + # ================================================================ + # Nam / Napalm / WWII GI + # ================================================================ + + - name: "NAM.GRP" + category: game_data + system: nam + required: false + size: 43448927 + crc32: "75C1F07B" + source_ref: "wadsrc/static/engine/grpinfo.txt (NAM)" + + - name: "NAPALM.GRP" + category: game_data + system: nam + required: false + size: 44365728 + crc32: "3DE1589A" + source_ref: "wadsrc/static/engine/grpinfo.txt (NAPALM)" + + - name: "WW2GI.GRP" + category: game_data + system: ww2gi + required: false + size: 77939508 + crc32: "907B82BF" + source_ref: "wadsrc/static/engine/grpinfo.txt (WWII GI)" diff --git a/emulators/thextech.yml b/emulators/thextech.yml new file mode 100644 index 00000000..db0871ec --- /dev/null +++ b/emulators/thextech.yml @@ -0,0 +1,133 @@ +emulator: TheXTech +type: standalone +core_classification: game_engine +source: "https://github.com/TheXTech/TheXTech" +upstream: "https://github.com/TheXTech/TheXTech" +profiled_date: "2026-10-04" +source_commit: "48f15208ff2857985d3534f191dab494ea3cd3d0" +display_name: "TheXTech" +cores: [] +systems: [smbx] + +notes: | + C++ reimplementation of the SMBX 1.3 engine. The engine itself ships + no game assets; an asset pack is probed at startup from + AppPathManager::assetsSearchPath() and the first pack with a valid + graphics/ui/ directory is used. + ref: src/main/asset_pack.cpp:249-340 (s_find_asset_packs, + s_scan_asset_pack), lib/AppPath/private/app_path.cpp:135-170 + + A pack is accepted when it carries graphics/ui/ plus an identification + file. Two schemas are recognized: + _meta.ini modern asset pack (engine field "TheXTech", platform + field matching the running target, pack-id) + gameinfo.ini legacy SMBX-style descriptor read under [android] + ref: src/main/asset_pack.cpp:138-212 + + Three images are loaded unconditionally to render the pack-selection + menu; without them the pack is rejected ("Could not load UI assets + from possible asset pack"). + ref: src/main/asset_pack.cpp:115-117, 285-291 + + TheXTech is content-agnostic. The reference packs that TheXTech + releases alongside the engine are the SMBX 1.3 asset pack + (`thextech-assets-smbx13`) and the free Adventures of Demo pack + (`thextech-assets-adventures-of-demo`); any pack that satisfies the + structure above runs. + +files: + # ================================================================ + # Asset pack identification files (one of the two is required) + # ================================================================ + + - name: "_meta.ini" + category: game_data + required: false + source_ref: "src/main/asset_pack.cpp:138-168 (modern asset pack schema)" + note: "Modern asset pack descriptor. [content] engine=TheXTech + pack-id." + + - name: "gameinfo.ini" + category: game_data + required: false + source_ref: "src/main/asset_pack.cpp:169-180 (legacy schema)" + note: "Legacy SMBX descriptor. [game] id + [android] logo/background." + + # ================================================================ + # UI assets probed to validate an asset pack + # ================================================================ + + - name: "thextech_128.png" + category: game_data + path: "graphics/ui/icon/thextech_128.png" + required: true + source_ref: "src/main/asset_pack.cpp:115 (assets_icon)" + note: "Pack icon. Loaded during pack scan." + + - name: "MenuGFX2.png" + category: game_data + path: "graphics/ui/MenuGFX2.png" + required: true + source_ref: "src/main/asset_pack.cpp:116 (logo_image_path_default), 285-291" + note: "Main menu logo. Pack rejected if this image fails to load." + + - name: "background2-2.png" + category: game_data + path: "graphics/background2/background2-2.png" + required: true + source_ref: "src/main/asset_pack.cpp:117 (bg_image_path_default)" + note: "Menu background. Covered by the UI-assets gate." + + # ================================================================ + # Core content directories (engine iterates on disk, filenames are + # the pack's own; the directory contract is what the engine checks) + # ================================================================ + + - name: "graphics/" + category: game_data + required: true + source_ref: "src/main/asset_pack.cpp:275-291 (DirMan::exists(root + \"graphics/ui/\"))" + note: "Pack validation requires graphics/ui/ to exist." + + - name: "sound/" + category: game_data + required: false + source_ref: "src/load_gfx.cpp:443 (LoadGFXFromList), src/sound.h" + note: "SFX directory read from sounds.ini. Game runs without sounds." + + - name: "music/" + category: game_data + required: false + source_ref: "src/sound.cpp (music loader)" + note: "Music tracks read from music.ini." + + - name: "sounds.ini" + category: game_data + required: false + source_ref: "src/sound.cpp (SFX index file)" + + - name: "music.ini" + category: game_data + required: false + source_ref: "src/sound.cpp (music index file)" + + - name: "intro/" + category: game_data + required: false + source_ref: "src/main/game_main.cpp (intro level loader)" + note: "Intro level episode; played before the main menu when present." + + - name: "outro/" + category: game_data + required: false + source_ref: "src/main/game_main.cpp (outro episode)" + + - name: "worlds/" + category: game_data + required: false + source_ref: "src/main/game_main.cpp (world loader)" + note: "Default world episodes shipped with the pack." + + - name: "battle/" + category: game_data + required: false + source_ref: "src/main/game_main.cpp (battle mode levels)"