- 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.
This commit is contained in:
Christoph Oelckers 2021-06-01 11:05:26 +02:00
parent a0bf16d8fe
commit 454816299e
17 changed files with 136 additions and 91 deletions

View file

@ -639,7 +639,6 @@ int32_t engineInit(void)
{ {
engineLoadTables(); engineLoadTables();
g_visibility = 512; g_visibility = 512;
if (!mdinited) mdinit();
return 0; return 0;
} }

View file

@ -105,6 +105,7 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FGameTexture
auto pic = charlumps[i]; auto pic = charlumps[i];
Chars[i].OriginalPic = MakeGameTexture(pic->GetTexture(), nullptr, ETextureType::FontChar); Chars[i].OriginalPic = MakeGameTexture(pic->GetTexture(), nullptr, ETextureType::FontChar);
Chars[i].OriginalPic->CopySize(pic, true); Chars[i].OriginalPic->CopySize(pic, true);
Chars[i].OriginalPic->SetName(FStringf("@@%s.%d", name, i));
TexMan.AddGameTexture(Chars[i].OriginalPic); TexMan.AddGameTexture(Chars[i].OriginalPic);
Chars[i].XMove = (int)Chars[i].OriginalPic->GetDisplayWidth(); Chars[i].XMove = (int)Chars[i].OriginalPic->GetDisplayWidth();
if (sysCallbacks.FontCharCreated) sysCallbacks.FontCharCreated(pic, Chars[i].OriginalPic); if (sysCallbacks.FontCharCreated) sysCallbacks.FontCharCreated(pic, Chars[i].OriginalPic);

View file

@ -140,7 +140,7 @@ void LoadScripts();
void MainLoop(); void MainLoop();
void SetConsoleNotifyBuffer(); void SetConsoleNotifyBuffer();
bool PreBindTexture(FRenderState* state, FGameTexture*& tex, EUpscaleFlags& flags, int& scaleflags, int& clampmode, int& translation, int& overrideshader); 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 FontCharCreated(FGameTexture* base, FGameTexture* untranslated);
void LoadVoxelModels(); 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() int RunGame()
{ {
GameStartupInfo.FgColor = 0xffffff; 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 GPalette.Init(MAXPALOOKUPS + 2); // one slot for each translation, plus a separate one for the base palettes and the internal one
gi->loadPalette(); gi->loadPalette();
StartScreen->Progress(); StartScreen->Progress();
TexMan.Init([]() {}, [](BuildInfo &) {}); InitTextures();
StartScreen->Progress();
TileFiles.Init();
TileFiles.LoadArtSet("tiles%03d.art"); // it's the same for all games.
InitFont();
StartScreen->Progress(); StartScreen->Progress();
I_InitSound(); I_InitSound();
StartScreen->Progress(); StartScreen->Progress();
@ -1010,7 +1033,6 @@ int RunGame()
gameinfo.mBackButton = "engine/graphics/m_back.png"; gameinfo.mBackButton = "engine/graphics/m_back.png";
StartScreen->Progress(); StartScreen->Progress();
voxInit();
engineInit(); engineInit();
gi->app_init(); gi->app_init();
StartScreen->Progress(); StartScreen->Progress();
@ -1023,12 +1045,6 @@ int RunGame()
if (!(paletteloaded & PALETTE_MAIN)) if (!(paletteloaded & PALETTE_MAIN))
I_FatalError("No palette found."); 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); FMaterial::SetLayerCallback(setpalettelayer);
if (GameStartupInfo.Name.IsNotEmpty()) I_SetWindowTitle(GameStartupInfo.Name); if (GameStartupInfo.Name.IsNotEmpty()) I_SetWindowTitle(GameStartupInfo.Name);
DeleteStartupScreen(); DeleteStartupScreen();
@ -1526,8 +1542,6 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Raze, GetBuildTime, I_GetBuildTime)
ACTION_RETURN_INT(I_GetBuildTime()); ACTION_RETURN_INT(I_GetBuildTime());
} }
bool PickTexture(FRenderState* state, FGameTexture* tex, int paletteid, TexturePick& pick);
DEFINE_ACTION_FUNCTION(_Raze, PickTexture) DEFINE_ACTION_FUNCTION(_Raze, PickTexture)
{ {
PARAM_PROLOGUE; PARAM_PROLOGUE;

View file

@ -66,6 +66,7 @@ struct GameInterface
virtual ~GameInterface() {} virtual ~GameInterface() {}
virtual bool GenerateSavePic() { return false; } virtual bool GenerateSavePic() { return false; }
virtual void app_init() = 0; virtual void app_init() = 0;
virtual void LoadGameTextures() {}
virtual void loadPalette(); virtual void loadPalette();
virtual void clearlocalinputstate() {} virtual void clearlocalinputstate() {}
virtual void UpdateScreenSize() {} virtual void UpdateScreenSize() {}

View file

@ -38,7 +38,8 @@
#include "i_interface.h" #include "i_interface.h"
#include "vm.h" #include "vm.h"
#include "gstrings.h" #include "gstrings.h"
#include "textures.h" #include "texturemanager.h"
#include "buildtiles.h"
FGameTexture* GetBaseForChar(FGameTexture* t); FGameTexture* GetBaseForChar(FGameTexture* t);
void FontCharCreated(FGameTexture* base, FGameTexture* glyph); 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) #if 0
{
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;
}
static void SetupHires(FFont *font) static void SetupHires(FFont *font)
{ {
if (!font) return; if (!font) return;
@ -105,6 +85,7 @@ static void SetupHires(FFont *font)
FontCharCreated(base, mychar); FontCharCreated(base, mychar);
} }
} }
#endif
void InitFont() void InitFont()
{ {
@ -115,18 +96,50 @@ void InitFont()
IndexFont = V_GetFont("IndexFont"); IndexFont = V_GetFont("IndexFont");
DigiFont = V_GetFont("DigiFont"); DigiFont = V_GetFont("DigiFont");
SetupHires(BigFont); //SetupHires(BigFont);
SetupHires(SmallFont); //SetupHires(SmallFont);
if (g_gameType & GAMEFLAG_DUKE) if (g_gameType & GAMEFLAG_DUKE)
{ {
BigFont13 = V_GetFont("BigFont13"); BigFont13 = V_GetFont("BigFont13");
BigFont15 = V_GetFont("BigFont15"); BigFont15 = V_GetFont("BigFont15");
BigFont = new FFont(0, "BigFont"); BigFont = new FFont(0, "BigFont");
BigFont->CopyFrom(*BigFont15);
} }
OriginalSmallFont = SmallFont; OriginalSmallFont = SmallFont;
OriginalBigFont = BigFont; 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 tilesmallfont = V_GetFont("tilesmallfont");
auto tilebigfont = V_GetFont("tilebigfont"); auto tilebigfont = V_GetFont("tilebigfont");

View file

@ -8,5 +8,6 @@ extern FFont* IndexFont;
extern FFont* DigiFont; extern FFont* DigiFont;
void InitFont(); void InitFont();
void SetupFontSubstitution();
FFont* PickBigFont(const char* txt = nullptr); FFont* PickBigFont(const char* txt = nullptr);
FFont* PickSmallFont(const char* txt = nullptr); FFont* PickSmallFont(const char* txt = nullptr);

View file

@ -489,3 +489,7 @@ struct SetAnim
}; };
void processSetAnim(const char* cmd, FScriptPosition& pos, SetAnim& imp); void processSetAnim(const char* cmd, FScriptPosition& pos, SetAnim& imp);
class FRenderState;
class FGameTexture;
bool PickTexture(FRenderState* state, FGameTexture* tex, int paletteid, TexturePick& pick);

View file

@ -75,6 +75,7 @@ FGameTexture* GetBaseForChar(FGameTexture* t)
void FontCharCreated(FGameTexture* base, FGameTexture* glyph) void FontCharCreated(FGameTexture* base, FGameTexture* glyph)
{ {
if (base->GetName().IsNotEmpty())
deferredChars.Insert(glyph, base); deferredChars.Insert(glyph, base);
} }
@ -155,7 +156,7 @@ FGameTexture* SkyboxReplacement(FTextureID picnum, int palnum)
// //
//========================================================================== //==========================================================================
void PostLoadSetup() void highTileSetup()
{ {
for(int i=0;i<MAXTILES;i++) for(int i=0;i<MAXTILES;i++)
{ {
@ -163,8 +164,33 @@ void PostLoadSetup()
if (!tex->isValid()) continue; if (!tex->isValid()) continue;
auto Hightile = tileReplacements.CheckKey(i); auto Hightile = tileReplacements.CheckKey(i);
if (!Hightile) continue; 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; float scalex = 1.f, scaley = 1.f;
for (auto& rep : *Hightile) 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);
}
} }
} }

View file

@ -422,18 +422,15 @@ void GameInterface::app_init()
HookReplaceFunctions(); HookReplaceFunctions();
Printf(PRINT_NONOTIFY, "Loading tiles\n"); Printf(PRINT_NONOTIFY, "Loading texture tables\n");
if (!tileInit()) tileInit();
I_FatalError("TILES###.ART files not found");
levelLoadDefaults(); levelLoadDefaults();
LoadDefinitions();
//--------- //---------
SetTileNames(); SetTileNames();
C_InitConback(TexMan.CheckForTexture("BACKTILE", ETextureType::Any), true, 0.25); C_InitConback(TexMan.CheckForTexture("BACKTILE", ETextureType::Any), true, 0.25);
TileFiles.SetBackup();
Printf(PRINT_NONOTIFY, "Loading cosine table\n"); Printf(PRINT_NONOTIFY, "Loading cosine table\n");
trigInit(); trigInit();
Printf(PRINT_NONOTIFY, "Initializing view subsystem\n"); Printf(PRINT_NONOTIFY, "Initializing view subsystem\n");

View file

@ -26,6 +26,7 @@ struct GameInterface : public ::GameInterface
{ {
const char* Name() override { return "Duke"; } const char* Name() override { return "Duke"; }
void app_init() override; void app_init() override;
void loadPalette();
void clearlocalinputstate() override; void clearlocalinputstate() override;
bool GenerateSavePic() override; bool GenerateSavePic() override;
void PlayHudSound() override; void PlayHudSound() override;

View file

@ -39,6 +39,7 @@ Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au)
#include "i_interface.h" #include "i_interface.h"
#include "prediction.h" #include "prediction.h"
#include "gamestate.h" #include "gamestate.h"
#include "razefont.h"
BEGIN_DUKE_NS BEGIN_DUKE_NS
@ -265,6 +266,12 @@ static void SetTileNames()
#undef y #undef y
void GameInterface::loadPalette()
{
paletteLoadFromDisk();
genspriteremaps();
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// set up the game module's state // set up the game module's state
@ -309,6 +316,7 @@ void GameInterface::app_init()
loadcons(); loadcons();
fi.initactorflags(); fi.initactorflags();
duke_menufont.Callback(); // depends on the .CON files so it must be after loadcons
OnEvent(EVENT_INIT); OnEvent(EVENT_INIT);
@ -316,7 +324,6 @@ void GameInterface::app_init()
initTiles(); initTiles();
setupbackdrop(); setupbackdrop();
genspriteremaps();
SetupGameButtons(); SetupGameButtons();
InitCheats(); InitCheats();
checkcommandline(); checkcommandline();
@ -324,9 +331,7 @@ void GameInterface::app_init()
screenpeek = myconnectindex; screenpeek = myconnectindex;
LoadDefinitions();
SetTileNames(); SetTileNames();
TileFiles.SetBackup();
C_InitConback(TexMan.CheckForTexture("MENUSCREEN", ETextureType::Any), false, 0.75); C_InitConback(TexMan.CheckForTexture("MENUSCREEN", ETextureType::Any), false, 0.75);
if (ud.multimode > 1) if (ud.multimode > 1)

View file

@ -72,8 +72,9 @@ void ResetEngine()
resettiming(); resettiming();
} }
void InstallEngine() void GameInterface::loadPalette()
{ {
paletteLoadFromDisk();
uploadCinemaPalettes(); uploadCinemaPalettes();
LoadPaletteLookups(); LoadPaletteLookups();
} }
@ -493,13 +494,8 @@ void GameInterface::app_init()
nTotalPlayers += nNetPlayerCount; nTotalPlayers += nNetPlayerCount;
} }
// temp - moving InstallEngine(); before FadeOut as we use nextpage() in FadeOut
InstallEngine();
LoadDefinitions();
SetTileNames(); SetTileNames();
TileFiles.SetBackup();
InitFX(); InitFX();
seq_LoadSequences(); seq_LoadSequences();
InitStatus(); InitStatus();

View file

@ -219,6 +219,7 @@ struct GameInterface : public ::GameInterface
const char* Name() override { return "Exhumed"; } const char* Name() override { return "Exhumed"; }
void app_init() override; void app_init() override;
void clearlocalinputstate() override; void clearlocalinputstate() override;
void loadPalette() override;
bool GenerateSavePic() override; bool GenerateSavePic() override;
void MenuOpened() override; void MenuOpened() override;
void MenuSound(EMenuSounds snd) override; void MenuSound(EMenuSounds snd) override;

View file

@ -110,8 +110,7 @@ static COLOR_MAP PlayerColorMap[PLAYER_COLOR_MAPS][1] =
}; };
void void GameInterface::loadPalette(void)
InitPalette(void)
{ {
static COLOR_MAP AllToRed[] = static COLOR_MAP AllToRed[] =
{ {
@ -216,6 +215,17 @@ InitPalette(void)
short play; short play;
uint8_t tempbuf[256]; 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 // Dive palettes
// //

View file

@ -165,6 +165,11 @@ static void SetTileNames()
} }
#undef x #undef x
void GameInterface::LoadGameTextures()
{
LoadKVXFromScript("swvoxfil.txt"); // Load voxels from script file
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// //
@ -195,17 +200,6 @@ void GameInterface::app_init()
registerosdcommands(); 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; numplayers = 1; myconnectindex = 0;
connecthead = 0; connectpoint2[0] = -1; connecthead = 0; connectpoint2[0] = -1;
@ -225,14 +219,11 @@ void GameInterface::app_init()
for (int i = 0; i < MAX_SW_PLAYERS; i++) for (int i = 0; i < MAX_SW_PLAYERS; i++)
INITLIST(&Player[i].PanelSpriteList); 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. LoadCustomInfoFromScript("engine/swcustom.txt"); // load the internal definitions. These also apply to the shareware version.
if (!SW_SHAREWARE) if (!SW_SHAREWARE)
LoadCustomInfoFromScript("swcustom.txt"); // Load user customisation information LoadCustomInfoFromScript("swcustom.txt"); // Load user customisation information
LoadDefinitions();
SetTileNames(); SetTileNames();
TileFiles.SetBackup();
userConfig.AddDefs.reset(); userConfig.AddDefs.reset();
InitFX(); InitFX();
} }

View file

@ -2233,6 +2233,8 @@ struct GameInterface : public ::GameInterface
{ {
const char* Name() override { return "ShadowWarrior"; } const char* Name() override { return "ShadowWarrior"; }
void app_init() override; void app_init() override;
void LoadGameTextures();
void loadPalette();
void clearlocalinputstate() override; void clearlocalinputstate() override;
void FreeGameData() override; void FreeGameData() override;
void FreeLevelData() override; void FreeLevelData() override;

View file

@ -16,7 +16,6 @@ void DoTheCache(void);
void InitCheats(); void InitCheats();
void MapColors(short num,COLOR_MAP cm,short create); void MapColors(short num,COLOR_MAP cm,short create);
void InitPalette(void);
int32_t CONFIG_ReadSetup(void); int32_t CONFIG_ReadSetup(void);
bool WarpPlaneSectorInfo(short sectnum, SPRITEp* sp_ceiling, SPRITEp* sp_floor); bool WarpPlaneSectorInfo(short sectnum, SPRITEp* sp_ceiling, SPRITEp* sp_floor);