From 454816299ebd8654e7be27fbc3673dea22f63d43 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 1 Jun 2021 11:05:26 +0200 Subject: [PATCH] - reorganized loading of textures. Due to dependencies on initializing some data in app_init it was not possible to cleanly set up the fonts. This adds a game-side function for loading the entire palettes before starting with the texture data and another one for loading game-side texture data. This now allows fully setting up the palettes before starting with the textures and to fully set up the textures before reading the .def files. All this is needed because to properly initialize, the fonts need to be able to access the fully initialized texture state, including replacements and hires substitutions from the .def files. --- source/build/src/engine.cpp | 1 - source/common/fonts/specialfont.cpp | 1 + source/core/gamecontrol.cpp | 44 ++++++++++++------- source/core/gamestruct.h | 1 + source/core/razefont.cpp | 63 +++++++++++++++++----------- source/core/razefont.h | 1 + source/core/textures/buildtiles.h | 4 ++ source/core/textures/hightile.cpp | 48 ++++++++++++--------- source/games/blood/src/blood.cpp | 7 +--- source/games/duke/src/duke3d.h | 1 + source/games/duke/src/game.cpp | 11 +++-- source/games/exhumed/src/exhumed.cpp | 8 +--- source/games/exhumed/src/exhumed.h | 1 + source/games/sw/src/colormap.cpp | 14 ++++++- source/games/sw/src/game.cpp | 19 +++------ source/games/sw/src/game.h | 2 + source/games/sw/src/misc.h | 1 - 17 files changed, 136 insertions(+), 91 deletions(-) diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index a6bfa2ef3..8a4ea5697 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -639,7 +639,6 @@ int32_t engineInit(void) { engineLoadTables(); g_visibility = 512; - if (!mdinited) mdinit(); return 0; } diff --git a/source/common/fonts/specialfont.cpp b/source/common/fonts/specialfont.cpp index b00a19ad3..8bde8499e 100644 --- a/source/common/fonts/specialfont.cpp +++ b/source/common/fonts/specialfont.cpp @@ -105,6 +105,7 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FGameTexture auto pic = charlumps[i]; Chars[i].OriginalPic = MakeGameTexture(pic->GetTexture(), nullptr, ETextureType::FontChar); Chars[i].OriginalPic->CopySize(pic, true); + Chars[i].OriginalPic->SetName(FStringf("@@%s.%d", name, i)); TexMan.AddGameTexture(Chars[i].OriginalPic); Chars[i].XMove = (int)Chars[i].OriginalPic->GetDisplayWidth(); if (sysCallbacks.FontCharCreated) sysCallbacks.FontCharCreated(pic, Chars[i].OriginalPic); diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index 44d678f9b..0bc074ba3 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -140,7 +140,7 @@ void LoadScripts(); void MainLoop(); void SetConsoleNotifyBuffer(); bool PreBindTexture(FRenderState* state, FGameTexture*& tex, EUpscaleFlags& flags, int& scaleflags, int& clampmode, int& translation, int& overrideshader); -void PostLoadSetup(); +void highTileSetup(); void FontCharCreated(FGameTexture* base, FGameTexture* untranslated); void LoadVoxelModels(); @@ -880,6 +880,33 @@ void GetGames() // //========================================================================== +static void InitTextures() +{ + TexMan.Init([]() {}, [](BuildInfo&) {}); + StartScreen->Progress(); + mdinit(); + + TileFiles.Init(); + TileFiles.LoadArtSet("tiles%03d.art"); // it's the same for all games. + voxInit(); + gi->LoadGameTextures(); // loads game-side data that must be present before processing the .def files. + LoadDefinitions(); + InitFont(); // InitFonts may only be called once all texture data has been initialized. + + lookups.postLoadTables(); + highTileSetup(); + lookups.postLoadLookups(); + SetupFontSubstitution(); + V_LoadTranslations(); // loading the translations must be delayed until the palettes have been fully set up. + TileFiles.SetBackup(); +} + +//========================================================================== +// +// +// +//========================================================================== + int RunGame() { GameStartupInfo.FgColor = 0xffffff; @@ -985,12 +1012,8 @@ int RunGame() GPalette.Init(MAXPALOOKUPS + 2); // one slot for each translation, plus a separate one for the base palettes and the internal one gi->loadPalette(); StartScreen->Progress(); - TexMan.Init([]() {}, [](BuildInfo &) {}); - StartScreen->Progress(); - TileFiles.Init(); - TileFiles.LoadArtSet("tiles%03d.art"); // it's the same for all games. + InitTextures(); - InitFont(); StartScreen->Progress(); I_InitSound(); StartScreen->Progress(); @@ -1010,7 +1033,6 @@ int RunGame() gameinfo.mBackButton = "engine/graphics/m_back.png"; StartScreen->Progress(); - voxInit(); engineInit(); gi->app_init(); StartScreen->Progress(); @@ -1023,12 +1045,6 @@ int RunGame() if (!(paletteloaded & PALETTE_MAIN)) I_FatalError("No palette found."); - lookups.postLoadTables(); - PostLoadSetup(); - lookups.postLoadLookups(); - duke_menufont.Callback(); - V_LoadTranslations(); // loading the translations must be delayed until the palettes have been fully set up. - FMaterial::SetLayerCallback(setpalettelayer); if (GameStartupInfo.Name.IsNotEmpty()) I_SetWindowTitle(GameStartupInfo.Name); DeleteStartupScreen(); @@ -1526,8 +1542,6 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Raze, GetBuildTime, I_GetBuildTime) ACTION_RETURN_INT(I_GetBuildTime()); } -bool PickTexture(FRenderState* state, FGameTexture* tex, int paletteid, TexturePick& pick); - DEFINE_ACTION_FUNCTION(_Raze, PickTexture) { PARAM_PROLOGUE; diff --git a/source/core/gamestruct.h b/source/core/gamestruct.h index 97b0a857b..17eb72f2b 100644 --- a/source/core/gamestruct.h +++ b/source/core/gamestruct.h @@ -66,6 +66,7 @@ struct GameInterface virtual ~GameInterface() {} virtual bool GenerateSavePic() { return false; } virtual void app_init() = 0; + virtual void LoadGameTextures() {} virtual void loadPalette(); virtual void clearlocalinputstate() {} virtual void UpdateScreenSize() {} diff --git a/source/core/razefont.cpp b/source/core/razefont.cpp index b3c5c199f..489730f21 100644 --- a/source/core/razefont.cpp +++ b/source/core/razefont.cpp @@ -38,7 +38,8 @@ #include "i_interface.h" #include "vm.h" #include "gstrings.h" -#include "textures.h" +#include "texturemanager.h" +#include "buildtiles.h" FGameTexture* GetBaseForChar(FGameTexture* t); void FontCharCreated(FGameTexture* base, FGameTexture* glyph); @@ -60,28 +61,7 @@ CUSTOM_CVAR(Int, duke_menufont, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOIN } } -static int compareChar(int code, FFont* gamefont, FFont* myfont) -{ - auto c1 = gamefont->GetChar(code, CR_UNDEFINED, nullptr); - auto c2 = myfont->GetChar(code, CR_UNDEFINED, nullptr); - if (c1 == nullptr || c2 == nullptr) return 1; // this should never happen unless one of the fonts is broken. - if (c1->GetTexelHeight() != c2->GetTexelHeight()) return 0; - if (c1->GetTexelWidth() != c2->GetTexelWidth()) return 0; - auto t1 = c1->GetTexture(); - auto t2 = c2->GetTexture(); - auto buf1 = t1->CreateTexBuffer(0); - auto buf2 = t2->CreateTexBuffer(0); - // at this point the palette has not yet been fully set up so the alpha channel is not consistent. - // We have to mask it out here to be able to compare the two buffers. - for (int i = 0; i < buf1.mWidth * buf1.mHeight * 4; i++) - { - buf1.mBuffer[i] = buf2.mBuffer[i] = 0; - } - - int res = memcmp(buf1.mBuffer, buf2.mBuffer, buf1.mWidth * buf1.mHeight * 4); - return res == 0; -} - +#if 0 static void SetupHires(FFont *font) { if (!font) return; @@ -105,6 +85,7 @@ static void SetupHires(FFont *font) FontCharCreated(base, mychar); } } +#endif void InitFont() { @@ -115,18 +96,50 @@ void InitFont() IndexFont = V_GetFont("IndexFont"); DigiFont = V_GetFont("DigiFont"); - SetupHires(BigFont); - SetupHires(SmallFont); + //SetupHires(BigFont); + //SetupHires(SmallFont); if (g_gameType & GAMEFLAG_DUKE) { BigFont13 = V_GetFont("BigFont13"); BigFont15 = V_GetFont("BigFont15"); BigFont = new FFont(0, "BigFont"); + BigFont->CopyFrom(*BigFont15); } OriginalSmallFont = SmallFont; OriginalBigFont = BigFont; +} +static int compareChar(int code, FFont* gamefont, FFont* myfont) +{ + auto c1 = gamefont->GetChar(code, CR_UNDEFINED, nullptr); + auto c2 = myfont->GetChar(code, CR_UNDEFINED, nullptr); + if (c1 == nullptr || c2 == nullptr) return 1; // this should never happen unless one of the fonts is broken. + + if (c1->GetTexelHeight() != c2->GetTexelHeight()) return 0; + if (c1->GetTexelWidth() != c2->GetTexelWidth()) return 0; + + // If there's a hires version attached to the base, treat this as the base being different. + TexturePick pick; + if (PickTexture(nullptr, c1, 0, pick) && pick.texture != c1) return 0; + + auto t1 = c1->GetTexture(); + auto t2 = c2->GetTexture(); + auto buf1 = t1->CreateTexBuffer(0); + auto buf2 = t2->CreateTexBuffer(0); + // at this point the palette has not yet been fully set up so the alpha channel is not consistent. + // We have to mask it out here to be able to compare the two buffers. + for (int i = 3; i < buf1.mWidth * buf1.mHeight * 4; i+=4) + { + buf1.mBuffer[i] = buf2.mBuffer[i] = 0; + } + + int res = memcmp(buf1.mBuffer, buf2.mBuffer, buf1.mWidth * buf1.mHeight * 4); + return res == 0; +} + +void SetupFontSubstitution() +{ auto tilesmallfont = V_GetFont("tilesmallfont"); auto tilebigfont = V_GetFont("tilebigfont"); diff --git a/source/core/razefont.h b/source/core/razefont.h index d77ff67e5..8bbeb3fe3 100644 --- a/source/core/razefont.h +++ b/source/core/razefont.h @@ -8,5 +8,6 @@ extern FFont* IndexFont; extern FFont* DigiFont; void InitFont(); +void SetupFontSubstitution(); FFont* PickBigFont(const char* txt = nullptr); FFont* PickSmallFont(const char* txt = nullptr); diff --git a/source/core/textures/buildtiles.h b/source/core/textures/buildtiles.h index 77b928f2e..4f5e50aba 100644 --- a/source/core/textures/buildtiles.h +++ b/source/core/textures/buildtiles.h @@ -489,3 +489,7 @@ struct SetAnim }; void processSetAnim(const char* cmd, FScriptPosition& pos, SetAnim& imp); +class FRenderState; +class FGameTexture; +bool PickTexture(FRenderState* state, FGameTexture* tex, int paletteid, TexturePick& pick); + diff --git a/source/core/textures/hightile.cpp b/source/core/textures/hightile.cpp index 66590f9eb..d5e6259b1 100644 --- a/source/core/textures/hightile.cpp +++ b/source/core/textures/hightile.cpp @@ -75,7 +75,8 @@ FGameTexture* GetBaseForChar(FGameTexture* t) void FontCharCreated(FGameTexture* base, FGameTexture* glyph) { - deferredChars.Insert(glyph, base); + if (base->GetName().IsNotEmpty()) + deferredChars.Insert(glyph, base); } @@ -155,7 +156,7 @@ FGameTexture* SkyboxReplacement(FTextureID picnum, int palnum) // //========================================================================== -void PostLoadSetup() +void highTileSetup() { for(int i=0;iisValid()) continue; auto Hightile = tileReplacements.CheckKey(i); if (!Hightile) continue; + textureReplacements.Insert(tex->GetID().GetIndex(), std::move(*Hightile)); + } + tileReplacements.Clear(); - FGameTexture* detailTex = nullptr, * glowTex = nullptr, * normalTex = nullptr, *specTex = nullptr; + decltype(deferredChars)::Iterator it(deferredChars); + decltype(deferredChars)::Pair* pair; + while (it.NextPair(pair)) + { + auto rep = textureReplacements.CheckKey(pair->Value->GetID().GetIndex()); + if (rep) + { + auto myrep = *rep; // don't create copies directly from the map we're inserting in! + auto chk = textureReplacements.CheckKey(pair->Key->GetID().GetIndex()); + if (!chk) textureReplacements.Insert(pair->Key->GetID().GetIndex(), std::move(myrep)); + } + } + deferredChars.Clear(); + decltype(textureReplacements)::Iterator it2(textureReplacements); + decltype(textureReplacements)::Pair* pair2; + while (it2.NextPair(pair2)) + { + auto tex = TexMan.GameByIndex(pair2->Key); + if (!tex->isValid()) continue; + auto Hightile = &pair2->Value; + if (!Hightile) continue; + + FGameTexture* detailTex = nullptr, * glowTex = nullptr, * normalTex = nullptr, * specTex = nullptr; float scalex = 1.f, scaley = 1.f; for (auto& rep : *Hightile) { @@ -207,22 +233,6 @@ void PostLoadSetup() } } } - textureReplacements.Insert(tex->GetID().GetIndex(), std::move(*Hightile)); - } - tileReplacements.Clear(); - - int i = 0; - decltype(deferredChars)::Iterator it(deferredChars); - decltype(deferredChars)::Pair* pair; - while (it.NextPair(pair)) - { - i++; - auto rep = textureReplacements.CheckKey(pair->Value->GetID().GetIndex()); - if (rep) - { - auto chk = textureReplacements.CheckKey(pair->Key->GetID().GetIndex()); - if (!chk) textureReplacements.Insert(pair->Key->GetID().GetIndex(), *rep); - } } } diff --git a/source/games/blood/src/blood.cpp b/source/games/blood/src/blood.cpp index 2477b81a6..0707ab04a 100644 --- a/source/games/blood/src/blood.cpp +++ b/source/games/blood/src/blood.cpp @@ -422,18 +422,15 @@ void GameInterface::app_init() HookReplaceFunctions(); - Printf(PRINT_NONOTIFY, "Loading tiles\n"); - if (!tileInit()) - I_FatalError("TILES###.ART files not found"); + Printf(PRINT_NONOTIFY, "Loading texture tables\n"); + tileInit(); levelLoadDefaults(); - LoadDefinitions(); //--------- SetTileNames(); C_InitConback(TexMan.CheckForTexture("BACKTILE", ETextureType::Any), true, 0.25); - TileFiles.SetBackup(); Printf(PRINT_NONOTIFY, "Loading cosine table\n"); trigInit(); Printf(PRINT_NONOTIFY, "Initializing view subsystem\n"); diff --git a/source/games/duke/src/duke3d.h b/source/games/duke/src/duke3d.h index 9ffd490f1..426ba3a34 100644 --- a/source/games/duke/src/duke3d.h +++ b/source/games/duke/src/duke3d.h @@ -26,6 +26,7 @@ struct GameInterface : public ::GameInterface { const char* Name() override { return "Duke"; } void app_init() override; + void loadPalette(); void clearlocalinputstate() override; bool GenerateSavePic() override; void PlayHudSound() override; diff --git a/source/games/duke/src/game.cpp b/source/games/duke/src/game.cpp index 102d7db81..3a23f8f2f 100644 --- a/source/games/duke/src/game.cpp +++ b/source/games/duke/src/game.cpp @@ -39,6 +39,7 @@ Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au) #include "i_interface.h" #include "prediction.h" #include "gamestate.h" +#include "razefont.h" BEGIN_DUKE_NS @@ -265,6 +266,12 @@ static void SetTileNames() #undef y +void GameInterface::loadPalette() +{ + paletteLoadFromDisk(); + genspriteremaps(); +} + //--------------------------------------------------------------------------- // // set up the game module's state @@ -309,6 +316,7 @@ void GameInterface::app_init() loadcons(); fi.initactorflags(); + duke_menufont.Callback(); // depends on the .CON files so it must be after loadcons OnEvent(EVENT_INIT); @@ -316,7 +324,6 @@ void GameInterface::app_init() initTiles(); setupbackdrop(); - genspriteremaps(); SetupGameButtons(); InitCheats(); checkcommandline(); @@ -324,9 +331,7 @@ void GameInterface::app_init() screenpeek = myconnectindex; - LoadDefinitions(); SetTileNames(); - TileFiles.SetBackup(); C_InitConback(TexMan.CheckForTexture("MENUSCREEN", ETextureType::Any), false, 0.75); if (ud.multimode > 1) diff --git a/source/games/exhumed/src/exhumed.cpp b/source/games/exhumed/src/exhumed.cpp index 8aef71e58..47a43aead 100644 --- a/source/games/exhumed/src/exhumed.cpp +++ b/source/games/exhumed/src/exhumed.cpp @@ -72,8 +72,9 @@ void ResetEngine() resettiming(); } -void InstallEngine() +void GameInterface::loadPalette() { + paletteLoadFromDisk(); uploadCinemaPalettes(); LoadPaletteLookups(); } @@ -493,13 +494,8 @@ void GameInterface::app_init() nTotalPlayers += nNetPlayerCount; } - // temp - moving InstallEngine(); before FadeOut as we use nextpage() in FadeOut - InstallEngine(); - LoadDefinitions(); SetTileNames(); - TileFiles.SetBackup(); - InitFX(); seq_LoadSequences(); InitStatus(); diff --git a/source/games/exhumed/src/exhumed.h b/source/games/exhumed/src/exhumed.h index 2bd9c120b..1ad629dca 100644 --- a/source/games/exhumed/src/exhumed.h +++ b/source/games/exhumed/src/exhumed.h @@ -219,6 +219,7 @@ struct GameInterface : public ::GameInterface const char* Name() override { return "Exhumed"; } void app_init() override; void clearlocalinputstate() override; + void loadPalette() override; bool GenerateSavePic() override; void MenuOpened() override; void MenuSound(EMenuSounds snd) override; diff --git a/source/games/sw/src/colormap.cpp b/source/games/sw/src/colormap.cpp index 6845fc44f..becad327d 100644 --- a/source/games/sw/src/colormap.cpp +++ b/source/games/sw/src/colormap.cpp @@ -110,8 +110,7 @@ static COLOR_MAP PlayerColorMap[PLAYER_COLOR_MAPS][1] = }; -void -InitPalette(void) +void GameInterface::loadPalette(void) { static COLOR_MAP AllToRed[] = { @@ -216,6 +215,17 @@ InitPalette(void) short play; uint8_t tempbuf[256]; + paletteLoadFromDisk(); + auto pal = fileSystem.LoadFile("3drealms.pal", 0); + if (pal.Size() >= 768) + { + for (auto& c : pal) + c <<= 2; + + paletteSetColorTable(DREALMSPAL, pal.Data(), true, true); + } + + // // Dive palettes // diff --git a/source/games/sw/src/game.cpp b/source/games/sw/src/game.cpp index 9b795cbe9..2bd3598f8 100644 --- a/source/games/sw/src/game.cpp +++ b/source/games/sw/src/game.cpp @@ -165,6 +165,11 @@ static void SetTileNames() } #undef x +void GameInterface::LoadGameTextures() +{ + LoadKVXFromScript("swvoxfil.txt"); // Load voxels from script file +} + //--------------------------------------------------------------------------- // // @@ -195,17 +200,6 @@ void GameInterface::app_init() registerosdcommands(); - auto pal = fileSystem.LoadFile("3drealms.pal", 0); - if (pal.Size() >= 768) - { - for (auto& c : pal) - c <<= 2; - - paletteSetColorTable(DREALMSPAL, pal.Data(), true, true); - } - InitPalette(); - // sets numplayers, connecthead, connectpoint2, myconnectindex - numplayers = 1; myconnectindex = 0; connecthead = 0; connectpoint2[0] = -1; @@ -225,14 +219,11 @@ void GameInterface::app_init() for (int i = 0; i < MAX_SW_PLAYERS; i++) INITLIST(&Player[i].PanelSpriteList); - LoadKVXFromScript("swvoxfil.txt"); // Load voxels from script file LoadCustomInfoFromScript("engine/swcustom.txt"); // load the internal definitions. These also apply to the shareware version. if (!SW_SHAREWARE) LoadCustomInfoFromScript("swcustom.txt"); // Load user customisation information - LoadDefinitions(); SetTileNames(); - TileFiles.SetBackup(); userConfig.AddDefs.reset(); InitFX(); } diff --git a/source/games/sw/src/game.h b/source/games/sw/src/game.h index 47ad1cede..697655440 100644 --- a/source/games/sw/src/game.h +++ b/source/games/sw/src/game.h @@ -2233,6 +2233,8 @@ struct GameInterface : public ::GameInterface { const char* Name() override { return "ShadowWarrior"; } void app_init() override; + void LoadGameTextures(); + void loadPalette(); void clearlocalinputstate() override; void FreeGameData() override; void FreeLevelData() override; diff --git a/source/games/sw/src/misc.h b/source/games/sw/src/misc.h index 00d518286..1c1bf0fce 100644 --- a/source/games/sw/src/misc.h +++ b/source/games/sw/src/misc.h @@ -16,7 +16,6 @@ void DoTheCache(void); void InitCheats(); void MapColors(short num,COLOR_MAP cm,short create); -void InitPalette(void); int32_t CONFIG_ReadSetup(void); bool WarpPlaneSectorInfo(short sectnum, SPRITEp* sp_ceiling, SPRITEp* sp_floor);