From b97ee26b3226f3e4dadc8b2c34adf146a4efb304 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Sun, 4 Oct 2026 17:05:13 +0200 Subject: [PATCH] fix: check six doom-era profiles against source --- emulators/gzdoom.yml | 156 +++++++---- emulators/iortcw.yml | 105 ++++---- emulators/jazz2-native.yml | 262 ++++++++++-------- emulators/openjazz.yml | 194 +++++++++----- emulators/raze.yml | 531 ++++++++++++++++++++++++++++++++----- emulators/thextech.yml | 125 +++++---- 6 files changed, 981 insertions(+), 392 deletions(-) diff --git a/emulators/gzdoom.yml b/emulators/gzdoom.yml index 921f68d9..9b5394fd 100644 --- a/emulators/gzdoom.yml +++ b/emulators/gzdoom.yml @@ -17,20 +17,28 @@ notes: | Engine resources (built from wadsrc*/static/ via add_pk3): gzdoom.pk3 BASEWAD, searched by BaseFileSearch - ref: src/version.h:90, src/d_main.cpp + ref: src/version.h:90, src/d_main.cpp:3757-3761 game_support.pk3 OPTIONALWAD, filter/game assets per IWAD - ref: src/version.h:92 + ref: src/version.h:92, src/d_main.cpp:3794 lights.pk3 dynamic light definitions brightmaps.pk3 brightmap textures game_widescreen_gfx.pk3 widescreen HUD/menu replacements + The last three are skipped for shareware IWADs and with -noextras. + ref: src/d_main.cpp:2050-2071 - 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 + Game data is a user-supplied IWAD. iwadinfo.txt declares each known + IWAD with its IWADName, MustContain lumps and support files. The + search directories are scanned for the file names of its Names block + and for any .iwad, .ipk3 or .ipk7 file; each candidate is then + identified by its lumps, not by its name. The Names block also lists + doomu.wad, doom1.wad, bfgdoom.wad, bfgdoom2.wad, freedoomu.wad, + freedoom.wad, hereticsr.wad, heretic1.wad, hexendemo.wad, hexdemo.wad, + strife0.wad and strife.wad. + ref: wadsrc_extra/static/iwadinfo.txt:650-703, src/d_iwad.cpp:502-530 - 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). + Startup refuses to run if BASEWAD (gzdoom.pk3) is absent, and stops + with "Cannot find a game IWAD" when no candidate is identified. + ref: src/d_main.cpp:3757-3761, src/d_iwad.cpp:789-798 files: # ================================================================ @@ -40,29 +48,50 @@ files: - name: "gzdoom.pk3" category: game_data required: true - source_ref: "src/version.h:90 (BASEWAD), wadsrc/CMakeLists.txt:1" + source_ref: "src/version.h:90, src/d_main.cpp:3757-3761, 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" + source_ref: "src/version.h:92, src/d_main.cpp:3794-3796, 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" + source_ref: "src/d_main.cpp:2053-2058, 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" + source_ref: "src/d_main.cpp:2059-2064, 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" + source_ref: "src/d_main.cpp:2065-2070, wadsrc_widepix/CMakeLists.txt:1" + + - name: "gzdoom.sf2" + category: game_data + path: "soundfonts/gzdoom.sf2" + required: false + source_ref: "src/common/audio/music/i_soundfont.cpp:427-430, src/CMakeLists.txt:1429" + note: "Default soundfont, used when the soundfont directories hold none." + + - name: "GENMIDI.GS.wopl" + category: game_data + path: "fm_banks/GENMIDI.GS.wopl" + required: false + source_ref: "src/CMakeLists.txt:1431, src/gameconfigfile.cpp:165-195, src/common/audio/music/i_soundfont.cpp:355-359" + note: "OPL3 bank copied next to the executable; fm_banks is one of the scanned soundfont directories." + + - name: "gs-by-papiezak-and-sneakernets.wopn" + category: game_data + path: "fm_banks/gs-by-papiezak-and-sneakernets.wopn" + required: false + source_ref: "src/CMakeLists.txt:1433, src/gameconfigfile.cpp:165-195, src/common/audio/music/i_soundfont.cpp:360-364" + note: "OPN2 bank copied next to the executable." # ================================================================ # IWADs (user-supplied). At least one is needed to launch a game. @@ -75,136 +104,145 @@ files: 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)." + source_ref: "wadsrc_extra/static/iwadinfo.txt:420, 437, 659" + note: "The Ultimate DOOM and DOOM Registered both use this name; told apart by their lumps." - name: "doom2.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM 2: Hell on Earth)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:640, 653" - name: "doom2f.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM 2: L'Enfer sur Terre)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:625, 657" - name: "doombfg.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM: BFG Edition)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:332, 666" - name: "doom2bfg.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM 2: BFG Edition)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:560, 667" - name: "doomunity.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM: Unity Edition)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:369, 661" - name: "doom2unity.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM 2: Unity Edition)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:592, 655" - name: "doomkex.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM: KEX Edition)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:350, 662" - name: "doom2kex.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM 2: KEX Edition)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:576, 656" - name: "doomxbox.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM: XBox Edition)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:403, 660" - name: "doom2xbox.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM 2: XBox Edition)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:608, 654" - name: "doom_complete.pk3" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (DOOM: Complete: WadSmoosh)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:389, 652" - name: "plutonia.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Final Doom: Plutonia Experiment)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:545, 670" - name: "plutoniaunity.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Plutonia Unity Edition)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:514, 671" - name: "plutoniakex.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Plutonia KEX Edition)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:529, 672" - name: "tnt.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Final Doom: TNT - Evilution)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:499, 673" - name: "tntunity.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (TNT Unity Edition)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:468, 674" - name: "tntkex.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (TNT KEX Edition)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:483, 675" - 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)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:565, 614, src/d_iwad.cpp:877-895" 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)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:598, src/d_iwad.cpp:877-895" + note: "Loaded from the IWAD directory by 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)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:357, 376, 488, 534, 582, 598" + note: "Loaded from the IWAD directory by the KEX and Unity editions." + + - name: "soundtrack" + category: game_data + system: doom + required: false + source_ref: "wadsrc_extra/static/iwadinfo.txt:376, 598, src/d_iwad.cpp:877-895" + note: "Loaded from the IWAD directory by the DOOM and DOOM 2 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." + source_ref: "wadsrc_extra/static/iwadinfo.txt:341, 360, 379, src/d_iwad.cpp:862-875" + note: "id24 resource WAD. SupportWAD of every id IWAD block, loaded when found and i_loadsupportwad is set." # ---- Freedoom (free) ---- @@ -212,19 +250,19 @@ files: category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Freedoom: Phase 1)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:307, 676" - name: "freedoom2.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Freedoom: Phase 2)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:294, 677" - name: "freedm.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (FreeDM)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:281, 680" # ---- Heretic ---- @@ -232,14 +270,15 @@ files: 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." + source_ref: "wadsrc_extra/static/iwadinfo.txt:241, 244, 254, 257, 681" + note: "Both Heretic and Shadow of the Serpent Riders use this name; told apart by the EXTENDED lump." - name: "blasphem.wad" + aliases: ["blasphemer.wad"] category: game_data system: heretic required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Blasphemer)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:228, 692-693" # ---- Hexen ---- @@ -247,13 +286,13 @@ files: category: game_data system: hexen required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Hexen: Beyond Heretic)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:188, 684" - name: "hexdd.wad" category: game_data system: hexen required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Hexen: Deathkings of the Dark Citadel)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:196-207, 685" note: "Deathkings expansion. Requires hexen.wad (Required = Hexen: Beyond Heretic)." # ---- Strife ---- @@ -262,20 +301,20 @@ files: category: game_data system: strife required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Strife: Quest for the Sigil)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:151, 688" - name: "sve.wad" category: game_data system: strife required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Strife: Veteran Edition)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:136, 140, 689" 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)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:142, 155" # ---- Chex Quest ---- @@ -283,13 +322,13 @@ files: category: game_data system: chex required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Chex(R) Quest)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:123, 694" - name: "chex3.wad" category: game_data system: chex required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Chex(R) Quest 3)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:109, 695" # ---- Standalone commercial / community IWADs ---- @@ -297,46 +336,47 @@ files: category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Hacx: Twitch'n Kill)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:83, 698" - name: "hacx2.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Hacx 2.0)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:71, 699" - name: "action2.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Action Doom 2: Urban Brawl)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:97, 696" - name: "harm1.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Harmony)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:57, 697" - name: "square.pk3" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (The Adventures of Square)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:33" + note: "Absent from the Names block: picked up only when named with -iwad." - name: "square1.pk3" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (The Adventures of Square - Squareware)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:45, 700" - name: "delaweare.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Delaweare)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:22, 701" - name: "rotwb.wad" category: game_data system: doom required: false - source_ref: "wadsrc_extra/static/iwadinfo.txt (Rise Of The Wool Ball)" + source_ref: "wadsrc_extra/static/iwadinfo.txt:9, 702" diff --git a/emulators/iortcw.yml b/emulators/iortcw.yml index 8cc1b04e..bd513eec 100644 --- a/emulators/iortcw.yml +++ b/emulators/iortcw.yml @@ -16,21 +16,27 @@ notes: | 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 + ref: SP/code/qcommon/qcommon.h:628, MP/code/qcommon/q_shared.h:62 - 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) + Both builds stop with a fatal error when main/pak0.pk3 is missing, or + present with a checksum other than 1886207346. A demo pak0 under + demomain/ is accepted with a warning and skips the point-release + check. + ref: SP/code/qcommon/files.c:3842-3972, MP/code/qcommon/files.c:3836-3966 - Multiplayer (MP/code/qcommon/files.c): - main/pak0.pk3 shared base, checksum 1886207346 + Single-player (SP/code/qcommon/files.c) then requires the four + point-release paks; a missing one is fatal, a wrong checksum only + prints a warning: + main/sp_pak1.pk3 five localized checksums (en/fr/gm/it/sp) + main/sp_pak2.pk3 3033901371, or 285968110 for the German release + main/sp_pak3.pk3 five localized checksums + main/sp_pak4.pk3 GOTY edition pak, 4131017020 for every language + ref: SP/code/qcommon/files.c:187-225 (checksum arrays), + SP/code/qcommon/qcommon.h:637-638 (NUM_ID_PAKS 6, NUM_SP_PAKS 4), + SP/code/qcommon/files.c:3720-3827 (FS_CheckSPPaks) + + Multiplayer (MP/code/qcommon/files.c) requires the six mp_pak files + the same way: main/mp_pak0.pk3 checksum 764840216 main/mp_pak1.pk3 checksum -1023558518 main/mp_pak2.pk3 checksum 125907563 @@ -38,10 +44,8 @@ notes: | 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". + ref: MP/code/qcommon/files.c:198-218 (mppak_checksums, binpak_checksums), + MP/code/qcommon/files.c:3721-3821 (FS_CheckMPPaks) files: # ================================================================ @@ -53,102 +57,109 @@ files: 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." + source_ref: "SP/code/qcommon/files.c:183-185, 3865-3882, 3950-3967, MP/code/qcommon/files.c:194-196, 3859-3876, 3944-3961" + note: "RTCW retail base. Checksum 1886207346 in both builds; fatal when missing or when the checksum differs." # ================================================================ - # main/ - single-player patches (localized sp_pak1-3, universal sp_pak4) + # main/ - single-player point-release paks # ================================================================ - 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." + required: true + source_ref: "SP/code/qcommon/files.c:188, 196, 204, 212, 220, 3735-3767, 3806-3826" + note: "Single-player build: fatal when missing. One checksum per language (en/fr/gm/it/sp); a mismatch prints a warning." - 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])" + required: true + source_ref: "SP/code/qcommon/files.c:189, 197, 205, 213, 221, 3806-3826" + note: "Single-player build: fatal when missing." - 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])" + required: true + source_ref: "SP/code/qcommon/files.c:190, 198, 206, 214, 222, 3806-3826" + note: "Single-player build: fatal when missing." - 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." + required: true + source_ref: "SP/code/qcommon/files.c:191-192, 199-200, 207-208, 215-216, 223-224, 3806-3826" + note: "Single-player build: fatal when missing. GOTY edition pak, one checksum (4131017020) for every language." # ================================================================ - # main/ - multiplayer patches + # main/ - multiplayer paks # ================================================================ - 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." + required: true + source_ref: "MP/code/qcommon/files.c:199, 3736-3751, 3800-3820" + note: "Multiplayer build: fatal when missing. A checksum mismatch prints a warning." - 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])" + required: true + source_ref: "MP/code/qcommon/files.c:200, 3800-3820" + note: "Multiplayer build: fatal when missing." - 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])" + required: true + source_ref: "MP/code/qcommon/files.c:201, 3800-3820" + note: "Multiplayer build: fatal when missing." - 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])" + required: true + source_ref: "MP/code/qcommon/files.c:202, 3800-3820" + note: "Multiplayer build: fatal when missing." - 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])" + required: true + source_ref: "MP/code/qcommon/files.c:203, 3800-3820" + note: "Multiplayer build: fatal when missing." - 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])" + required: true + source_ref: "MP/code/qcommon/files.c:204, 3800-3820" + note: "Multiplayer build: fatal when missing." - 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." + source_ref: "MP/code/qcommon/files.c:209, 1596-1613" + note: "VM/binary pak, 1.4/1.41 retail. The client extracts game dlls only from paks whose checksum is listed." - 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)\")" + source_ref: "MP/code/qcommon/files.c:210, 1596-1613" note: "VM/binary pak, 1.51c variant." diff --git a/emulators/jazz2-native.yml b/emulators/jazz2-native.yml index 40667556..7b4be7d3 100644 --- a/emulators/jazz2-native.yml +++ b/emulators/jazz2-native.yml @@ -1,5 +1,5 @@ emulator: Jazz² Resurrection -type: standalone +type: standalone + libretro core_classification: game_engine source: "https://github.com/deathkiller/jazz2-native" upstream: "https://github.com/deathkiller/jazz2-native" @@ -7,199 +7,251 @@ profiled_date: "2026-10-04" source_commit: "cc06bdac1b957a069e1d05761c7437cd59886552" core_version: "3.8.0" display_name: "Jazz Jackrabbit 2 (Jazz² Resurrection)" -cores: [] +cores: [jazz2] 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) + ships its own Content/ tree (animations, metadata, translations) that + sits next to the executable in a portable copy, or under + /share// once installed. + ref: Sources/Jazz2/ContentResolver.cpp:187-238 (GetContentPath per + platform), Sources/Jazz2/ContentResolver.cpp:409-485 (Unix layouts) 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) + on first launch into the engine's own formats under Cache/: Anims.j2a + and Data.j2d into a package, then every .j2e, .j2l and the tilesets + the levels name. Music and cinematics are read from Source/ as they + are. + ref: Sources/Jazz2/ContentResolver.cpp:279-309 (GetSourcePath), + Sources/Main.cpp:2224-2288 (RefreshCache), + Sources/Jazz2/Compatibility/AssetConverter.cpp:152-168, + Sources/Jazz2/Compatibility/AssetConverter.cpp:400-516 - 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. + Content/ is the engine runtime, shipped with the release package. + Source/ holds the user's own copy of the 1998 game data. Without + Anims.j2a (or the shareware AnimsSw.j2a) and without an existing + cache the engine starts but is not playable. + + The libretro build looks for Content/ next to the loaded file, in the + core assets directory or in /jazz2/, and for the original + files in Source/ beside it, in the system directory itself or in + /jazz2/Source/. + ref: Sources/Main.cpp:267-355 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" + path: "jazz2/Content/Animations/" + standalone_path: "Content/Animations/" + bundled: true required: true - source_ref: "Sources/Jazz2/ContentResolver.cpp:2651 (CombinePath Content/Animations)" - note: "Native animation sheets, loaded by ContentResolver for every actor." + source_ref: "Sources/Jazz2/ContentResolver.cpp:1093, 1223, 2734-2735" + note: "Native graphics, sounds and the UI fonts, opened through OpenContentFile." - name: "Metadata/" category: game_data - path: "Content/Metadata" + path: "jazz2/Content/Metadata/" + standalone_path: "Content/Metadata/" + bundled: true required: true - source_ref: "Sources/Jazz2/ContentResolver.cpp (metadata loader for actors, UI, bosses)" + source_ref: "Sources/Jazz2/ContentResolver.cpp:839" note: "Actor .res descriptors (Common, Enemy, Player, UI, Boss, ...)." - name: "Translations/" category: game_data - path: "Content/Translations" + path: "jazz2/Content/Translations/" + standalone_path: "Content/Translations/" + bundled: true 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_ref: "Sources/Main.cpp:2019-2025, Sources/Jazz2/UI/Menu/LanguageSelectSection.cpp:82-88" + note: "Language .mo bundles, searched in Cache/Translations/ first. Built-in English is used when none is loaded." # ================================================================ # Source/ (original Jazz Jackrabbit 2 data, user-supplied) - # Converted into Content/Cache on first launch. + # Converted into Cache/ on first launch. # ================================================================ - name: "Anims.j2a" category: game_data system: jazz-jackrabbit-2 - path: "Source/Anims.j2a" + path: "jazz2/Source/Anims.j2a" + standalone_path: "Source/Anims.j2a" + required: true + source_ref: "Sources/Main.cpp:2224-2240, Sources/Jazz2/Compatibility/AssetConverter.cpp:156-159" + note: "Main animation archive. The cache cannot be created without it and the game is not flagged playable." + + - name: "AnimsSw.j2a" + category: game_data + system: jazz-jackrabbit-2 + path: "jazz2/Source/AnimsSw.j2a" + standalone_path: "Source/AnimsSw.j2a" required: false - source_ref: "Sources/Jazz2/Compatibility/JJ2Anims.cpp (JJ2Anims::Open)" - note: "Main animation archive. Required to generate the first-run cache." + source_ref: "Sources/Main.cpp:2227-2229" + note: "Animation archive of the shareware demo, read when Anims.j2a is absent." - name: "Data.j2d" category: game_data system: jazz-jackrabbit-2 - path: "Source/Data.j2d" + path: "jazz2/Source/Data.j2d" + standalone_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." + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:161-164" + note: "Converted into the cache package when present." # 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 + # episode. Every one present in Source/ is converted. + # ref: Sources/Jazz2/Compatibility/AssetConverter.cpp:400-516 - name: "prince.j2e" category: game_data system: jazz-jackrabbit-2 - path: "Source/prince.j2e" + path: "jazz2/Source/prince.j2e" + standalone_path: "Source/prince.j2e" required: false - source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:412 (episodesPath enumeration)" - note: "Episode 1 - Formerly a Prince." + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:184-191, 310-312, 407-436" + note: "First episode of the chain prince, rescue, flash, monk." - name: "rescue.j2e" category: game_data system: jazz-jackrabbit-2 - path: "Source/rescue.j2e" + path: "jazz2/Source/rescue.j2e" + standalone_path: "Source/rescue.j2e" required: false - source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:412" - note: "Episode 2 - Rescue of the Princess (Shareware episode)." + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:193-199, 313-314, 407-436" + note: "Second episode of the chain." - name: "flash.j2e" category: game_data system: jazz-jackrabbit-2 - path: "Source/flash.j2e" + path: "jazz2/Source/flash.j2e" + standalone_path: "Source/flash.j2e" required: false - source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:412" - note: "Episode 3 - Flashback to the Past." + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:201-208, 315-316, 407-436" + note: "Third episode of the chain." - name: "monk.j2e" category: game_data system: jazz-jackrabbit-2 - path: "Source/monk.j2e" + path: "jazz2/Source/monk.j2e" + standalone_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)." + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:210-215, 317-318, 407-436" + note: "Fourth episode of the chain." - name: "share.j2e" category: game_data system: jazz-jackrabbit-2 - path: "Source/share.j2e" + path: "jazz2/Source/share.j2e" + standalone_path: "Source/share.j2e" required: false - source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:412" - note: "Shareware episode descriptor." + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:217-219, 290-291, 407-436" + note: "Shareware Demo episode." + + - name: "xmas98.j2e" + category: game_data + system: jazz-jackrabbit-2 + path: "jazz2/Source/xmas98.j2e" + standalone_path: "Source/xmas98.j2e" + required: false + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:292-293, 412, 420-421, 434" + note: "Holiday Hare '98. Stored under the name xmas99 and skipped when xmas99.j2e is present." - name: "xmas99.j2e" category: game_data system: jazz-jackrabbit-2 - path: "Source/xmas99.j2e" + path: "jazz2/Source/xmas99.j2e" + standalone_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." + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:182, 221-223, 294-295" + note: "The Christmas Chronicles." - name: "secretf.j2e" category: game_data system: jazz-jackrabbit-2 - path: "Source/secretf.j2e" + path: "jazz2/Source/secretf.j2e" + standalone_path: "Source/secretf.j2e" required: false - source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:412" - note: "The Secret Files (TSF) episode." + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:225-233, 296-297, 407-436" + note: "The Secret Files episode." + + - name: "home.j2e" + category: game_data + system: jazz-jackrabbit-2 + path: "jazz2/Source/home.j2e" + standalone_path: "Source/home.j2e" + required: false + source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:423-429" + note: "Entry that lists custom levels." + + # Music, read from Content/Music/ then from Source/ + # ref: Sources/Jazz2/ContentResolver.cpp:2681-2691 - # Audio tracks - name: "menu.j2b" category: game_data system: jazz-jackrabbit-2 - path: "Source/menu.j2b" + path: "jazz2/Source/menu.j2b" + standalone_path: "Source/menu.j2b" required: false - source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:536 (MainMenu::PlayMenuMusic)" + source_ref: "Sources/Jazz2/UI/Menu/MainMenu.cpp:509-511, Sources/Jazz2/Compatibility/AssetConverter.cpp:535-538" 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" + path: "jazz2/Source/bonus2.j2b" + standalone_path: "Source/bonus2.j2b" required: false - source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:536" + source_ref: "Sources/Jazz2/UI/Menu/MainMenu.cpp:503-504, Sources/Jazz2/Compatibility/AssetConverter.cpp:535-538" + note: "Menu music of the reforged main menu, picked at random with bonus3.j2b." - name: "bonus3.j2b" category: game_data system: jazz-jackrabbit-2 - path: "Source/bonus3.j2b" + path: "jazz2/Source/bonus3.j2b" + standalone_path: "Source/bonus3.j2b" required: false - source_ref: "Sources/Jazz2/Compatibility/AssetConverter.cpp:536" + source_ref: "Sources/Jazz2/UI/Menu/MainMenu.cpp:503-504, Sources/Jazz2/Compatibility/AssetConverter.cpp:535-538" + note: "Menu music of the reforged main menu, picked at random with bonus2.j2b." + + - name: "intro.j2b" + category: game_data + system: jazz-jackrabbit-2 + path: "jazz2/Source/intro.j2b" + standalone_path: "Source/intro.j2b" + required: false + source_ref: "Sources/Jazz2/UI/Cinematics.cpp:255, Sources/Main.cpp:558, Sources/Jazz2/Compatibility/AssetConverter.cpp:535-538" + note: "Music of the intro cinematic." + + - name: "ending.j2b" + category: game_data + system: jazz-jackrabbit-2 + path: "jazz2/Source/ending.j2b" + standalone_path: "Source/ending.j2b" + required: false + source_ref: "Sources/Jazz2/UI/Cinematics.cpp:255, Sources/Main.cpp:964, Sources/Jazz2/Compatibility/AssetConverter.cpp:535-538" + note: "Music of the ending cinematic." + + # Cinematics, read from Content/Cinematics/ then from Source/ + + - name: "intro.j2v" + category: game_data + system: jazz-jackrabbit-2 + path: "jazz2/Source/intro.j2v" + standalone_path: "Source/intro.j2v" + required: false + source_ref: "Sources/Jazz2/UI/Cinematics.cpp:267-281, Sources/Main.cpp:558" + note: "Intro cinematic. Skipped when absent." + + - name: "ending.j2v" + category: game_data + system: jazz-jackrabbit-2 + path: "jazz2/Source/ending.j2v" + standalone_path: "Source/ending.j2v" + required: false + source_ref: "Sources/Jazz2/UI/Cinematics.cpp:267-281, Sources/Main.cpp:964" + note: "Ending cinematic. Skipped when absent." diff --git a/emulators/openjazz.yml b/emulators/openjazz.yml index db1a93ed..8a07d710 100644 --- a/emulators/openjazz.yml +++ b/emulators/openjazz.yml @@ -15,21 +15,32 @@ notes: | 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) + File lookup walks a path list (platform paths, command-line paths, + binary directory, working directory, compiled-in DATAPATH) and opens + the first match. + ref: src/io/file.cpp:51-77 (File::File), src/main.cpp:186-220 - 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 + PANEL.000 is the first file opened at startup; the engine aborts with + "Unable to find game data files" if that probe fails. The five .0FN + fonts follow and abort startup the same way. + ref: src/main.cpp:279-295, src/main.cpp:308-333 + + Level, tileset, sprite and planet names are built by createFileName(): + LEVEL., BLOCKS., SPRITES., PLANET., + with a three-digit world extension. The episode menu enables an + episode when LEVEL0. exists for its first world (0, 3, 6, 9, + 12, 15, then 30, 33, 36 and 50). + ref: src/util.cpp:123-193, src/jj1/jj1episodeutils.cpp:19-36, + src/menu/gamemenu.cpp:557-566 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 + time (off by default); it reads JJ2's .j2l/.j2t files directly (no + conversion step). + ref: CMakeLists.txt:241-255, src/jj2/level/jj2level.cpp:54-67 files: # ================================================================ - # Required files (loaded unconditionally at startup) + # Required files (startup aborts without them) # ================================================================ - name: "PANEL.000" @@ -39,41 +50,107 @@ files: 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" + - name: "FONT2.0FN" 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." + source_ref: "src/main.cpp:312, 318-333, src/io/gfx/font.cpp:60-64" + note: "Startup font. File::File throws when absent and startup aborts." + + - name: "FONTBIG.0FN" + category: game_data + system: jazz-jackrabbit + required: true + source_ref: "src/main.cpp:313, 318-333" + + - name: "FONTINY.0FN" + category: game_data + system: jazz-jackrabbit + required: true + source_ref: "src/main.cpp:314, 318-333" + + - name: "FONTMN1.0FN" + category: game_data + system: jazz-jackrabbit + required: true + source_ref: "src/main.cpp:315, 318-333" + + - name: "FONTMN2.0FN" + category: game_data + system: jazz-jackrabbit + required: true + source_ref: "src/main.cpp:316, 318-333" - 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) - # ================================================================ + source_ref: "src/main.cpp:435-443" + note: "Opening cutscene. play() returns the error before the menu when it is absent." - 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." + source_ref: "src/menu/mainmenu.cpp:72-82, src/main.cpp:458-466" + note: "Main menu graphics. The MainMenu constructor throws when it is absent." + + - name: "SOUNDS.000" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/io/sound.cpp:278, 478-485" + note: "Digital sound effects. loadSounds returns false when absent and the engine runs without sfx." + + - name: "MENUSNG.PSM" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/main.cpp:408, src/io/sound.cpp:337-344" + note: "Menu music. playMusic returns silently when the file is absent." + + # ================================================================ + # Menu extras (each reports its absence and returns to the menu) + # ================================================================ + + - name: "INSTRUCT.0SC" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/menu/mainmenu.cpp:177-187" + note: "Instructions screen." + + - name: "ORDER.0SC" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/menu/mainmenu.cpp:209-217" + note: "Order information screen." + + - name: "MACRO.1" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/menu/mainmenu.cpp:277-289" + note: "Demo recording played when the menu idles. MACRO.1 to MACRO.4 are probed." + + - name: "END.0SC" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/main.cpp:479-489" + note: "Cutscene played when the main menu is left." + + # ================================================================ + # Required when entering gameplay (level load fails without them) + # ================================================================ - 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) - # ================================================================ + source_ref: "src/io/gfx/font.cpp:288-292, src/jj1/level/jj1levelload.cpp:412-421" + note: "Level font. JJ1Level::load returns the error when it is absent." - name: "MAINCHAR.000" category: game_data @@ -86,42 +163,49 @@ files: 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)." + source_ref: "src/jj1/bonuslevel/jj1bonuslevel.cpp:53-61, 204-206, src/io/gfx/font.cpp:292" + note: "Bonus level sprites and the bonus-screen font." + + - name: "BONUS.0SC" + category: game_data + system: jazz-jackrabbit + required: false + source_ref: "src/jj1/bonuslevel/jj1bonuslevel.cpp:764-766" + note: "Cutscene played when a bonus level is won." # ================================================================ - # 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. + # Level data. Not every episode is required to run; a user may own + # only one. The episode menu probes LEVEL0. for the first + # world of each episode; the levels that follow are named by the + # level data itself (next level and next world numbers). # ================================================================ - 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)." + source_ref: "src/menu/gamemenu.cpp:324-325, 557-561" + note: "First level of world 0, the opener of episode 1." - 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)." + source_ref: "src/jj1/level/jj1levelload.cpp:437-473" + note: "World intro planet screen (name + preview). The level loads under the name CUSTOM when it is absent." - - name: "BLOCKS1.000" + - name: "BLOCKS.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." + source_ref: "src/jj1/level/jj1levelload.cpp:577-599" + note: "World 0 tileset. The extension is the world number unless the level names another one." - - name: "SPRITES1.000" + - name: "SPRITES.000" category: game_data system: jazz-jackrabbit required: false - source_ref: "src/jj1/level/jj1levelload.cpp:604 (createFileName \"SPRITES\")" + source_ref: "src/jj1/level/jj1levelload.cpp:602-609" note: "World 0 enemy/object sprites. One file per world." - name: "BONUSMAP.000" @@ -131,48 +215,34 @@ files: 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)." + source_ref: "src/jj1/level/jj1level.cpp:794-801" + note: "First level of world 1, reached from the level data of world 0." - name: "LEVEL0.002" category: game_data system: jazz-jackrabbit required: false - source_ref: "src/jj1/level/jj1demolevel.cpp:78" + source_ref: "src/jj1/level/jj1level.cpp:794-801" - 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)." + source_ref: "src/menu/gamemenu.cpp:557-561, src/jj1/jj1episodeutils.cpp:26-28" + note: "First level of world 3, the opener of episode 2." - name: "LEVEL0.004" category: game_data system: jazz-jackrabbit required: false - source_ref: "src/jj1/level/jj1demolevel.cpp:78" + source_ref: "src/jj1/level/jj1level.cpp:794-801" - 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." + source_ref: "src/jj1/level/jj1level.cpp:794-801" diff --git a/emulators/raze.yml b/emulators/raze.yml index 5643a72f..4b1b043f 100644 --- a/emulators/raze.yml +++ b/emulators/raze.yml @@ -20,13 +20,27 @@ notes: | 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 + Game detection reads engine/grpinfo.txt from raze.pk3. Every file of + the search directories is a candidate, whatever its name: a file is + identified when its size and CRC32 equal those of a grpinfo block, or + when it is an archive holding every `mustcontain` entry of a block + that declares no CRC. A block also carries a game id, flags and optional `loadgrp` / `loadart` dependencies. - ref: source/core/gamecontrol.cpp (GrpScan), wadsrc/static/engine/grpinfo.txt + ref: source/core/searchpaths.cpp:286-326, source/core/searchpaths.cpp:696-704, + source/core/searchpaths.cpp:738-870, wadsrc/static/engine/grpinfo.txt:1-45 + + The names below are the ones the releases ship. The engine itself + names DUKE3D.GRP, DUKEDC.GRP, NWINTER.GRP, VACATION.GRP, NAM.GRP, + NAPALM.GRP, WW2GI.GRP, REDNECK.GRP and BLOOD.RFF, as the defaults of + its -addon, -nam, -napalm, -ww2gi, -route66 and -cryptic switches. + ref: source/core/gamecontrol.cpp:328-367 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`. + Raze to run. An addon block names the CRC of its base game in + `dependency`. grpinfo.txt also identifies the Mac demos of Duke Nukem + 3D and Shadow Warrior, the Nuclear Winter demo, Duke!ZONE II, + Penthouse Paradise, Alien World Order, Platoon Leader, the ProAsm + build of Wanton Destruction and the SSI build of Cryptic Passage. files: # ================================================================ @@ -44,207 +58,580 @@ files: # ================================================================ - name: "DUKE3D.GRP" + description: "Duke Nukem 3D" category: game_data system: duke3d + path: "DUKE3D.GRP" required: false size: 26524524 - crc32: "BBC9CE44" - source_ref: "wadsrc/static/engine/grpinfo.txt (Duke Nukem 3D)" + crc32: "bbc9ce44" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:3, 48-59" - name: "DUKE3D.GRP" + description: "Duke Nukem 3D (South Korean Censored)" category: game_data system: duke3d - path: ".variants/DUKE3D.GRP.aa4f6a40" + path: "DUKE3D.GRP" required: false size: 26385383 - crc32: "AA4F6A40" - source_ref: "wadsrc/static/engine/grpinfo.txt (Duke Nukem 3D South Korean Censored)" + crc32: "aa4f6a40" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:4, 61-72" - name: "DUKE3D.GRP" + description: "Duke Nukem 3D: Atomic Edition" category: game_data system: duke3d - path: ".variants/DUKE3D.GRP.fd3dcff1" + path: "DUKE3D.GRP" required: false size: 44356548 - crc32: "FD3DCFF1" - source_ref: "wadsrc/static/engine/grpinfo.txt (Duke Nukem 3D: Atomic Edition)" + crc32: "fd3dcff1" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:5, 74-85" - name: "DUKE3D.GRP" + description: "Duke Nukem 3D: Plutonium Pak" category: game_data system: duke3d - path: ".variants/DUKE3D.GRP.f514a6ac" + path: "DUKE3D.GRP" required: false size: 44348015 - crc32: "F514A6AC" - source_ref: "wadsrc/static/engine/grpinfo.txt (Duke Nukem 3D: Plutonium Pak)" + crc32: "f514a6ac" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:6, 113-124" - name: "DUKE3D.GRP" + description: "Duke Nukem 3D: Atomic Edition (WT)" category: game_data system: duke3d - path: ".variants/DUKE3D.GRP.982afe4a" + path: "DUKE3D.GRP" 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)" + crc32: "982afe4a" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:7, 87-98" + note: "World Tour release." - name: "DUKE3D.GRP" + description: "Duke Nukem 3D: Atomic Edition (WT)" category: game_data system: duke3d - path: ".variants/DUKE3D.GRP.983ad923" + path: "DUKE3D.GRP" + required: false + size: 44486702 + crc32: "89792e05" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:100-111" + note: "World Tour release, second known build." + + - name: "DUKE3D.GRP" + description: "Duke Nukem 3D Shareware 0.99" + category: game_data + system: duke3d + path: "DUKE3D.GRP" + required: false + size: 9690241 + crc32: "02f18900" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:8, 126-136" + + - name: "DUKE3D.GRP" + description: "Duke Nukem 3D Shareware 1.0" + category: game_data + system: duke3d + path: "DUKE3D.GRP" + required: false + size: 10429258 + crc32: "a28aa589" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:9, 138-148" + + - name: "DUKE3D.GRP" + description: "Duke Nukem 3D Shareware 1.1" + category: game_data + system: duke3d + path: "DUKE3D.GRP" + required: false + size: 10442980 + crc32: "912e1e8d" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:10, 150-160" + + - name: "DUKE3D.GRP" + description: "Duke Nukem 3D Shareware 1.3D" + category: game_data + system: duke3d + path: "DUKE3D.GRP" required: false size: 11035779 - crc32: "983AD923" - source_ref: "wadsrc/static/engine/grpinfo.txt (Duke Nukem 3D Shareware 1.3D)" + crc32: "983ad923" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:11, 162-172" + + - name: "DUKEDC.GRP" + description: "Duke it out in D.C. (1.3D)" + category: game_data + system: duke3d + path: "DUKEDC.GRP" + required: false + size: 7926624 + crc32: "a9242158" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:14, 198-208" + note: "Addon of the 1.3D release (dependency DUKE13_CRC)." + + - name: "DUKEDC.GRP" + description: "Duke it out in D.C." + category: game_data + system: duke3d + path: "DUKEDC.GRP" + required: false + size: 8225517 + crc32: "b79d997f" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:15, 210-220" + note: "Addon of the Atomic Edition (dependency DUKE15_CRC)." + + - name: "DUKEDC.GRP" + description: "Duke it out in D.C." + category: game_data + system: duke3d + path: "DUKEDC.GRP" + required: false + size: 8410183 + crc32: "a8cf80da" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:16, 222-232" + + - name: "DUKEDC.GRP" + description: "Duke it out in D.C." + category: game_data + system: duke3d + path: "DUKEDC.GRP" + required: false + size: 8410187 + crc32: "39a692bf" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:234-245" + + - name: "DUKEDC.GRP" + description: "Duke it out in D.C." + category: game_data + system: duke3d + path: "DUKEDC.GRP" + required: false + size: 8410183 + crc32: "777c77b1" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:247-258" + + - name: "DUKEDC.GRP" + description: "Duke it out in D.C." + category: game_data + system: duke3d + path: "DUKEDC.GRP" + required: false + size: 8410149 + crc32: "c63b6a8b" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:260-271" + + - name: "VACATION.GRP" + description: "Duke Caribbean: Life's a Beach (1.3)" + category: game_data + system: duke3d + path: "VACATION.GRP" + required: false + size: 23559381 + crc32: "4a2dbb62" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:17, 273-285" + note: "Addon of the 1.3D release (dependency DUKE13_CRC)." + + - name: "VACATION.GRP" + description: "Duke Caribbean: Life's a Beach" + category: game_data + system: duke3d + path: "VACATION.GRP" + required: false + size: 22551333 + crc32: "2f4fccee" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:18, 287-299" + note: "Addon of the Atomic Edition (dependency DUKE15_CRC)." + + - name: "VACATION.GRP" + description: "Duke Caribbean: Life's a Beach" + category: game_data + system: duke3d + path: "VACATION.GRP" + required: false + size: 22521880 + crc32: "b62b42fd" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:19, 301-313" + + - name: "VACATION.GRP" + description: "Duke Caribbean: Life's a Beach" + category: game_data + system: duke3d + path: "VACATION.GRP" + required: false + size: 22213819 + crc32: "18f01c5b" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:20, 316-328" + + - name: "VACATION.GRP" + description: "Duke Caribbean: Life's a Beach" + category: game_data + system: duke3d + path: "VACATION.GRP" + required: false + size: 22397273 + crc32: "65b5f690" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:330-343" + + - name: "VACATION.GRP" + description: "Duke Caribbean: Life's a Beach" + category: game_data + system: duke3d + path: "VACATION.GRP" + required: false + size: 22201375 + crc32: "b28e883c" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:345-358" + + - name: "VACATION.GRP" + description: "Duke Caribbean: Life's a Beach" + category: game_data + system: duke3d + path: "VACATION.GRP" + required: false + size: 22213795 + crc32: "64cf2351" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:360-373" + + - name: "NWINTER.GRP" + description: "Duke: Nuclear Winter" + category: game_data + system: duke3d + path: "NWINTER.GRP" + required: false + size: 16169365 + crc32: "f1cae8e4" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:21, 375-388" + note: "Addon of the Atomic Edition (dependency DUKE15_CRC)." # ================================================================ # Blood # ================================================================ - name: "BLOOD.RFF" + description: "BLOOD: 1.0" category: game_data system: blood + path: "BLOOD.RFF" 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." + size: 8200353 + crc32: "b291418f" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:32, 485-499" - - name: "BLOOD.GRP" + - name: "BLOOD.RFF" + description: "BLOOD: 1.1" category: game_data system: blood + path: "BLOOD.RFF" required: false - source_ref: "wadsrc/static/engine/grpinfo.txt (BLOOD: One Unit Whole Blood loadgrp)" + size: 8231173 + crc32: "c3a99936" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:33, 501-515" + + - name: "BLOOD.RFF" + description: "BLOOD: One Unit Whole Blood" + category: game_data + system: blood + path: "BLOOD.RFF" + required: false + size: 9570681 + crc32: "a8fdda84" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:34, 517-531" + note: "Any other archive holding help1.qav, normal.plu, inverse.clu, cosine.dat and blood.pal is taken as an unknown Blood version (lines 533-544)." - name: "SOUNDS.RFF" category: game_data system: blood + path: "SOUNDS.RFF" required: false - source_ref: "wadsrc/static/engine/grpinfo.txt (BLOOD loadgrp \"SOUNDS.RFF\")" + source_ref: "wadsrc/static/engine/grpinfo.txt:494, 510, 526, 542" + note: "Named by loadgrp in every Blood block; loaded with the main resource." - name: "GUI.RFF" category: game_data system: blood + path: "GUI.RFF" required: false - source_ref: "wadsrc/static/engine/grpinfo.txt (BLOOD loadgrp \"GUI.RFF\")" + source_ref: "wadsrc/static/engine/grpinfo.txt:494, 510, 526, 542" + note: "Named by loadgrp in every Blood block; loaded with the main resource." + + - name: "BLOOD.GRP" + category: game_data + system: blood + path: "BLOOD.GRP" + required: false + source_ref: "wadsrc/static/engine/grpinfo.txt:494, 510, 526, 542" + note: "Named by loadgrp in every Blood block; loaded with the main resource." - name: "CRYPTIC.INI" category: game_data system: blood + path: "CRYPTIC.INI" required: false - source_ref: "wadsrc/static/engine/grpinfo.txt (BLOOD: Cryptic Passage addon)" + source_ref: "wadsrc/static/engine/grpinfo.txt:574-585, source/core/gamecontrol.cpp:361-367, source/core/searchpaths.cpp:712-730" + note: "Cryptic Passage addon. Detected next to the Blood files when CRYPTIC.INI, CP01.MAP and CP02.MAP are all present; depends on One Unit Whole Blood and loads CPART07.AR_ and CPART15.AR_." # ================================================================ # Shadow Warrior # ================================================================ - name: "SW.GRP" + description: "Shadow Warrior" category: game_data system: shadow-warrior + path: "SW.GRP" required: false size: 47536148 - crc32: "7545319F" - source_ref: "wadsrc/static/engine/grpinfo.txt (Shadow Warrior registered)" + crc32: "7545319f" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:36, 614-625" - - name: "WD.GRP" + - name: "SW.GRP" + description: "Shadow Warrior (Europe)" category: game_data system: shadow-warrior + path: "SW.GRP" + required: false + size: 47536148 + crc32: "d4a1e153" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:627-638" + + - name: "SW.GRP" + description: "Shadow Warrior (UK)" + category: game_data + system: shadow-warrior + path: "SW.GRP" + required: false + size: 47536148 + crc32: "3ee68767" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:640-651" + + - name: "SW.GRP" + description: "Shadow Warrior (Censored)" + category: game_data + system: shadow-warrior + path: "SW.GRP" + required: false + size: 47537951 + crc32: "1a8776d2" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:653-664" + + - name: "SW.GRP" + description: "Shadow Warrior Shareware 1.0" + category: game_data + system: shadow-warrior + path: "SW.GRP" + required: false + size: 25702245 + crc32: "daa6bece" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:666-676" + + - name: "SW.GRP" + description: "Shadow Warrior Shareware 1.1" + category: game_data + system: shadow-warrior + path: "SW.GRP" + required: false + size: 25833456 + crc32: "f21a6b35" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:678-688" + + - name: "SW.GRP" + description: "Shadow Warrior Shareware 1.2" + category: game_data + system: shadow-warrior + path: "SW.GRP" + required: false + size: 26056769 + crc32: "08a7fa1f" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:690-700" + + - name: "WT.GRP" + description: "Shadow Warrior: Wanton Destruction" + category: game_data + system: shadow-warrior + path: "WT.GRP" required: false size: 48698128 - crc32: "A9AAA7B7" - source_ref: "wadsrc/static/engine/grpinfo.txt (Shadow Warrior: Wanton Destruction)" + crc32: "a9aaa7b7" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:37, 714-724" + note: "Addon of the registered game (dependency SWREG12_CRC)." - - name: "TD.GRP" + - name: "WT.GRP" + description: "Shadow Warrior: Wanton Destruction" category: game_data system: shadow-warrior + path: "WT.GRP" + required: false + size: 48698128 + crc32: "8b6e8011" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:726-736" + + - name: "TD.GRP" + description: "Shadow Warrior: Twin Dragon" + category: game_data + system: shadow-warrior + path: "TD.GRP" required: false size: 12499012 - crc32: "A1A65BE8" - source_ref: "wadsrc/static/engine/grpinfo.txt (Shadow Warrior: Twin Dragon)" + crc32: "a1a65be8" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:38, 751-762" + note: "Addon of the registered game (dependency SWREG12_CRC)." + + - name: "TD.GRP" + description: "Shadow Warrior: Twin Dragon" + category: game_data + system: shadow-warrior + path: "TD.GRP" + required: false + size: 6236287 + crc32: "b5b71277" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:764-774" + + - name: "TD.GRP" + description: "Shadow Warrior: Twin Dragon" + category: game_data + system: shadow-warrior + path: "TD.GRP" + required: false + size: 6235578 + crc32: "acc8dcde" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:776-786" # ================================================================ # Powerslave / Exhumed # ================================================================ - name: "STUFF.DAT" + description: "Powerslave" category: game_data system: exhumed + path: "STUFF.DAT" required: false size: 27020745 - crc32: "303CBD89" - source_ref: "wadsrc/static/engine/grpinfo.txt (Powerslave)" + crc32: "303cbd89" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:40, 901-912" - name: "STUFF.DAT" + description: "Exhumed" category: game_data system: exhumed - path: ".variants/STUFF.DAT.e3b172f1" + path: "STUFF.DAT" required: false size: 27108170 - crc32: "E3B172F1" - source_ref: "wadsrc/static/engine/grpinfo.txt (Exhumed)" + crc32: "e3b172f1" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:41, 914-925" + + - name: "STUFF.DAT" + description: "Powerslave Demo" + category: game_data + system: exhumed + path: "STUFF.DAT" + required: false + size: 27020745 + crc32: "1d8c7645" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:42, 927-937" # ================================================================ # Redneck Rampage # ================================================================ - name: "REDNECK.GRP" + description: "Redneck Rampage" category: game_data system: redneck + path: "REDNECK.GRP" required: false size: 141174222 - crc32: "19D9BC79" - source_ref: "wadsrc/static/engine/grpinfo.txt (Redneck Rampage)" + crc32: "19d9bc79" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:28, 788-801" - name: "REDNECK.GRP" + description: "Redneck Rampage Rides Again" category: game_data system: redneck - path: ".variants/REDNECK.GRP.958018c6" + path: "REDNECK.GRP" required: false size: 191798609 - crc32: "958018C6" - source_ref: "wadsrc/static/engine/grpinfo.txt (Redneck Rampage Rides Again)" + crc32: "958018c6" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:29, 803-816" # ================================================================ # Nam / Napalm / WWII GI # ================================================================ - name: "NAM.GRP" + description: "NAM" category: game_data system: nam + path: "NAM.GRP" required: false size: 43448927 - crc32: "75C1F07B" - source_ref: "wadsrc/static/engine/grpinfo.txt (NAM)" + crc32: "75c1f07b" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:24, 846-858" - name: "NAPALM.GRP" + description: "NAPALM" category: game_data system: nam + path: "NAPALM.GRP" required: false size: 44365728 - crc32: "3DE1589A" - source_ref: "wadsrc/static/engine/grpinfo.txt (NAPALM)" + crc32: "3de1589a" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:25, 860-872" - name: "WW2GI.GRP" + description: "WWII GI" category: game_data system: ww2gi + path: "WW2GI.GRP" required: false size: 77939508 - crc32: "907B82BF" - source_ref: "wadsrc/static/engine/grpinfo.txt (WWII GI)" + crc32: "907b82bf" + validation: [size, crc32] + source_ref: "wadsrc/static/engine/grpinfo.txt:26, 874-886" diff --git a/emulators/thextech.yml b/emulators/thextech.yml index db0871ec..1f714c95 100644 --- a/emulators/thextech.yml +++ b/emulators/thextech.yml @@ -4,30 +4,37 @@ core_classification: game_engine source: "https://github.com/TheXTech/TheXTech" upstream: "https://github.com/TheXTech/TheXTech" profiled_date: "2026-10-04" -source_commit: "48f15208ff2857985d3534f191dab494ea3cd3d0" +source_commit: "a72915cd9a2c811f2388423775f20d75bb2107bd" 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 + no game assets; asset packs are searched at startup under every root + of AppPathManager::assetsSearchPath(): the root itself (legacy + layout), then each directory or archive of its assets/ folder. + ref: src/main/asset_pack.cpp:249-378 (s_find_asset_packs), + lib/AppPath/private/app_path.cpp:135-181 - 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 + A directory is scanned when it carries graphics/ui/, an archive when + it carries _meta.ini. Two descriptors are recognized: + _meta.ini archive pack ([content] engine "TheXTech", platform + matching the running target, pack-id) + gameinfo.ini directory pack ([game] id, menu images under + [android]) + A pack under assets/ is ignored when no id could be read; the legacy + root pack needs none. + ref: src/main/asset_pack.cpp:125-207, 334-339 - 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 + The pack-selection menu loads an icon, a logo and a background. Only + the logo is checked: without it the pack is ignored ("Could not load + UI assets from possible asset pack"). + ref: src/main/asset_pack.cpp:115-117, 225-233, 282-283 + + The selected pack is then loaded by GFX_t::load, which fails when one + of the UI images it requires from graphics/ui/ is missing. + ref: src/gfx.cpp:121-229, src/main/asset_pack.cpp:415-438 TheXTech is content-agnostic. The reference packs that TheXTech releases alongside the engine are the SMBX 1.3 asset pack @@ -37,97 +44,119 @@ notes: | files: # ================================================================ - # Asset pack identification files (one of the two is required) + # Asset pack identification files # ================================================================ - 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." + source_ref: "src/main/asset_pack.cpp:125, 131-181, 318-319" + note: "Archive pack descriptor. [content] engine=TheXTech, platform, pack-id. An archive without it is skipped." - 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." + source_ref: "src/main/asset_pack.cpp:126, 182-190, src/main/game_info.cpp:143" + note: "Directory pack descriptor. [game] id names the pack, [android] logo/background override the menu images." # ================================================================ - # UI assets probed to validate an asset pack + # Images of the pack-selection menu # ================================================================ - 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." + required: false + source_ref: "src/main/asset_pack.cpp:115, 225" + note: "Pack icon. Loaded during pack scan, result not checked." - 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." + source_ref: "src/main/asset_pack.cpp:116, 226-230, 334-335, src/gfx.cpp:201" + note: "Main menu logo. Pack ignored if no logo loads; GFX_t::load requires it as well." - 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." + required: false + source_ref: "src/main/asset_pack.cpp:117, 227-233" + note: "Menu background. Loaded during pack scan, result not checked." # ================================================================ - # Core content directories (engine iterates on disk, filenames are - # the pack's own; the directory contract is what the engine checks) + # Core content (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." + source_ref: "src/main/asset_pack.cpp:274, 326-327, src/gfx.cpp:121-229, src/load_gfx.cpp:120-123" + note: "graphics/ui/ must exist for a directory to be scanned as a pack; GFX_t::load rejects the pack when a required UI image is missing." - 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." + source_ref: "src/sound.cpp:1319" + note: "SFX directory, files named by 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." + source_ref: "src/sound.cpp:1318" + note: "Music tracks, files named by music.ini." - name: "sounds.ini" category: game_data required: false - source_ref: "src/sound.cpp (SFX index file)" + source_ref: "src/sound.cpp:1322, 1348-1354, 1363" + note: "SFX index. A message box reports its absence and the game runs without SFX." - name: "music.ini" category: game_data required: false - source_ref: "src/sound.cpp (music index file)" + source_ref: "src/sound.cpp:1321, 1341-1347, 1356" + note: "Music index. A message box reports its absence and the game runs without default music." - - name: "intro/" + - name: "intro.lvlx" + category: game_data + required: true + source_ref: "src/game_main.cpp:172-185, 224-250, 1095-1106" + note: "Level shown behind the main menu. intro.lvl and a level picked from introset/ take its place; with none of the three the game exits on a fatal error." + + - name: "intro.lvl" 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." + source_ref: "src/game_main.cpp:176-177" + note: "Read when intro.lvlx is absent." - - name: "outro/" + - name: "introset/" category: game_data required: false - source_ref: "src/main/game_main.cpp (outro episode)" + source_ref: "src/game_main.cpp:194-222, 247" + note: "Directory of .lvl/.lvlx intro levels; one is picked at random when present." + + - name: "outro.lvlx" + category: game_data + required: false + source_ref: "src/game_main.cpp:857-869" + note: "Level shown behind the credits, unless the episode names its own." + + - name: "outro.lvl" + category: game_data + required: false + source_ref: "src/game_main.cpp:865-866" + note: "Read when outro.lvlx is absent." - name: "worlds/" category: game_data required: false - source_ref: "src/main/game_main.cpp (world loader)" - note: "Default world episodes shipped with the pack." + source_ref: "src/main/menu_main.cpp:361-370" + note: "Episodes shipped with the pack, listed next to the user's worlds directory." - name: "battle/" category: game_data required: false - source_ref: "src/main/game_main.cpp (battle mode levels)" + source_ref: "src/main/menu_main.cpp:701-706" + note: "Battle mode levels shipped with the pack."