From 51ad64f71e95da5d07b2290acc2865e0c750d524 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Dec 2022 20:04:31 +0100 Subject: [PATCH] - initialize all special tiles to their intended type before starting the game. This ensures that we have an immutable mapping of tile number to texture ID now. --- source/common/2d/v_2ddrawer.h | 2 +- source/core/textures/buildtiles.cpp | 82 +--------------------------- source/core/textures/buildtiles.h | 2 - source/games/blood/src/fire.cpp | 2 +- source/games/blood/src/mirrors.cpp | 16 ------ source/games/blood/src/view.cpp | 2 +- source/games/duke/src/bowling.cpp | 50 ++++++++++++++++- source/games/duke/src/duke3d.h | 6 +- source/games/duke/src/game.cpp | 34 ++++++++---- source/games/duke/src/render.cpp | 3 +- source/games/exhumed/src/2d.cpp | 7 +-- source/games/exhumed/src/exhumed.cpp | 19 ++++++- source/games/exhumed/src/exhumed.h | 3 +- source/games/exhumed/src/menu.cpp | 4 +- source/games/exhumed/src/ramses.cpp | 2 +- source/games/sw/src/game.cpp | 10 ++++ source/games/sw/src/game.h | 5 +- source/games/sw/src/jsector.cpp | 7 --- 18 files changed, 118 insertions(+), 138 deletions(-) diff --git a/source/common/2d/v_2ddrawer.h b/source/common/2d/v_2ddrawer.h index 82c8aeada..7203ca3c1 100644 --- a/source/common/2d/v_2ddrawer.h +++ b/source/common/2d/v_2ddrawer.h @@ -193,7 +193,7 @@ public: TArray mData; int Width, Height; bool isIn2D; - bool locked; // prevents clearing of the data so it can be reused multiple times (useful for screen fades) + bool locked = false; // prevents clearing of the data so it can be reused multiple times (useful for screen fades) float screenFade = 1.f; DVector2 offset; DMatrix3x3 transform; diff --git a/source/core/textures/buildtiles.cpp b/source/core/textures/buildtiles.cpp index eb8178807..5aec9f331 100644 --- a/source/core/textures/buildtiles.cpp +++ b/source/core/textures/buildtiles.cpp @@ -420,40 +420,6 @@ FGameTexture* BuildTiles::ValidateCustomTile(int tilenum, ReplacementType type) return rep; } -//========================================================================== -// -// global interface -// -//========================================================================== - -int32_t BuildTiles::artLoadFiles(const char* filename) -{ - TileFiles.LoadArtSet(filename); - gotpic.Zero(); - return 0; -} - -//========================================================================== -// -// Retrieves the pixel store for a modifiable tile -// Modifiable tiles must be declared on startup. -// -//========================================================================== - -uint8_t* BuildTiles::tileGet(int tilenum) -{ - if (tilenum < 0 || tilenum >= MAXTILES) return nullptr; - auto& td = tiledata[tilenum]; - auto tile = td.texture; - auto reptype = td.replacement; - if (reptype == ReplacementType::Writable || reptype == ReplacementType::Restorable) - { - auto wtex = static_cast(tile->GetTexture()->GetImage()); - if (wtex) return wtex->GetRawData(); - } - return nullptr; -} - //========================================================================== // // Creates a tile for displaying custom content @@ -622,6 +588,8 @@ void tileCopy(int tile, int source, int pal, int xoffset, int yoffset, int flags void tileDelete(int tile) { + if (TileFiles.locked) + I_FatalError("Modifying tiles after startup is not allowed."); TileFiles.tiledata[tile].texture = TexMan.GameByIndex(0); TileFiles.tiledata[tile].replacement = ReplacementType::Art; // whatever this was, now it isn't anymore. (SW tries to nuke camera textures with this, :( ) tiletovox[tile] = -1; // clear the link but don't clear the voxel. It may be in use for another tile. @@ -659,52 +627,6 @@ void BuildTiles::CloseAll() ArtFiles.DeleteAndClear(); } -//========================================================================== -// -// Copy a block of a tile. -// Only used by RR's bowling lane. -// -//========================================================================== - -void tileCopySection(int tilenum1, int sx1, int sy1, int xsiz, int ysiz, int tilenum2, int sx2, int sy2) -{ - int xsiz1 = tileWidth(tilenum1); - int ysiz1 = tileHeight(tilenum1); - int xsiz2 = tileWidth(tilenum2); - int ysiz2 = tileHeight(tilenum2); - if (xsiz1 > 0 && ysiz1 > 0 && xsiz2 > 0 && ysiz2 > 0) - { - auto p1 = tilePtr(tilenum1); - auto p2 = tileData(tilenum2); - if (p2 == nullptr) return; // Error: Destination is not writable. - - int x1 = sx1; - int x2 = sx2; - for (int i=0; i= 0 && y2 >= 0 && x2 < xsiz2 && y2 < ysiz2) - { - auto src = p1[x1 * ysiz1 + y1]; - if (src != TRANSPARENT_INDEX) - p2[x2 * ysiz2 + y2] = src; - } - - y1++; - y2++; - if (y1 >= ysiz1) y1 = 0; - } - x1++; - x2++; - if (x1 >= xsiz1) x1 = 0; - } - } - TileFiles.InvalidateTile(tilenum2); -} - //========================================================================== // // Retrieve animation offset diff --git a/source/core/textures/buildtiles.h b/source/core/textures/buildtiles.h index 2e1b3b70d..681f265df 100644 --- a/source/core/textures/buildtiles.h +++ b/source/core/textures/buildtiles.h @@ -365,10 +365,8 @@ struct BuildTiles } FGameTexture* ValidateCustomTile(int tilenum, ReplacementType type); - int32_t artLoadFiles(const char* filename); uint8_t* tileMakeWritable(int num); uint8_t* tileCreate(int tilenum, int width, int height); - uint8_t* tileGet(int tilenum); void InvalidateTile(int num); void MakeCanvas(int tilenum, int width, int height); }; diff --git a/source/games/blood/src/fire.cpp b/source/games/blood/src/fire.cpp index 4183e095b..6b846a616 100644 --- a/source/games/blood/src/fire.cpp +++ b/source/games/blood/src/fire.cpp @@ -75,7 +75,7 @@ void DoFireFrame(void) memcpy(FrameBuffer + 16896 + i * 128, SeedBuffer[nRand], 128); } CellularFrame(FrameBuffer, 128, 132); - auto pData = TileFiles.tileGet(2342); + auto pData = tileData(2342); uint8_t* pSource = FrameBuffer; int x = fireSize; do diff --git a/source/games/blood/src/mirrors.cpp b/source/games/blood/src/mirrors.cpp index be9ecea73..022e8c7dd 100644 --- a/source/games/blood/src/mirrors.cpp +++ b/source/games/blood/src/mirrors.cpp @@ -44,7 +44,6 @@ MIRROR mirror[16]; // only needed by Polymost. void InitMirrors(void) { mirrorcnt = 0; - tileDelete(504); portalClear(); for (int i = (int)wall.Size() - 1; i >= 0; i--) @@ -52,13 +51,10 @@ void InitMirrors(void) auto pWalli = &wall[i]; if (mirrorcnt == 16) break; - int nTile = 4080 + mirrorcnt; if (pWalli->overpicnum == 504) { if (pWalli->extra > 0 && pWalli->type == kWallStack) { - pWalli->overpicnum = nTile; - mirror[mirrorcnt].mynum = i; mirror[mirrorcnt].type = 0; pWalli->cstat |= CSTAT_WALL_1WAY; @@ -96,7 +92,6 @@ void InitMirrors(void) { mirror[mirrorcnt].link = i; mirror[mirrorcnt].mynum = i; - pWalli->picnum = nTile; mirror[mirrorcnt].type = 0; pWalli->cstat |= CSTAT_WALL_1WAY; pWalli->portalflags = PORTAL_WALL_MIRROR; @@ -176,17 +171,6 @@ void SerializeMirrors(FSerializer& arc) .Array("mirror", mirror, countof(mirror)) .EndObject(); } - - if (arc.isReading()) - { - - tileDelete(504); - - for (int i = 0; i < 16; i++) - { - tileDelete(4080 + i); - } - } } END_BLD_NS diff --git a/source/games/blood/src/view.cpp b/source/games/blood/src/view.cpp index 58c91c5ba..bdab7655b 100644 --- a/source/games/blood/src/view.cpp +++ b/source/games/blood/src/view.cpp @@ -155,7 +155,7 @@ void viewInit(void) lensTable[i] = LittleLong(lensTable[i]); } #endif - uint8_t* data = TileFiles.tileGet(4077); + uint8_t* data = tileData(4077); memset(data, TRANSPARENT_INDEX, kLensSize * kLensSize); for (int i = 0; i < 16; i++) diff --git a/source/games/duke/src/bowling.cpp b/source/games/duke/src/bowling.cpp index f8226cc37..bb6e2c822 100644 --- a/source/games/duke/src/bowling.cpp +++ b/source/games/duke/src/bowling.cpp @@ -34,6 +34,51 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms BEGIN_DUKE_NS +//========================================================================== +// +// +//========================================================================== + +void tileCopySection(int tilenum1, int sx1, int sy1, int xsiz, int ysiz, int tilenum2, int sx2, int sy2) +{ + int xsiz1 = tileWidth(tilenum1); + int ysiz1 = tileHeight(tilenum1); + int xsiz2 = tileWidth(tilenum2); + int ysiz2 = tileHeight(tilenum2); + if (xsiz1 > 0 && ysiz1 > 0 && xsiz2 > 0 && ysiz2 > 0) + { + auto p1 = tilePtr(tilenum1); + auto p2 = tileData(tilenum2); + if (p2 == nullptr) return; // Error: Destination is not writable. + + int x1 = sx1; + int x2 = sx2; + for (int i = 0; i < xsiz; i++) + { + int y1 = sy1; + int y2 = sy2; + for (int j = 0; j < ysiz; j++) + { + if (x2 >= 0 && y2 >= 0 && x2 < xsiz2 && y2 < ysiz2) + { + auto src = p1[x1 * ysiz1 + y1]; + if (src != TRANSPARENT_INDEX) + p2[x2 * ysiz2 + y2] = src; + } + + y1++; + y2++; + if (y1 >= ysiz1) y1 = 0; + } + x1++; + x2++; + if (x1 >= xsiz1) x1 = 0; + } + } + +} + + void updatepindisplay(int tag, int pins) { static const uint8_t pinx[] = { 64, 56, 72, 48, 64, 80, 40, 56, 72, 88 }; @@ -41,11 +86,12 @@ void updatepindisplay(int tag, int pins) if (tag < 1 || tag > 4) return; tag += RTILE_BOWLINGLANE1 - 1; - if (TileFiles.tileMakeWritable(tag)) + if (tileData(tag)) { tileCopySection(RTILE_LANEPICBG, 0, 0, 128, 64, tag, 0, 0); for (int i = 0; i < 10; i++) if (pins & (1 << i)) - tileCopySection(RTILE_LANEPICS, 0, 0, 8, 8, tag, pinx[i] - 4, piny[i] - 10); + tileCopySection(RTILE_LANEPICS, 0, 0, 8, 8, tag, pinx[i] - 4, piny[i] - 10); + TileFiles.InvalidateTile(tag); } } diff --git a/source/games/duke/src/duke3d.h b/source/games/duke/src/duke3d.h index 23c916ab0..828765c8b 100644 --- a/source/games/duke/src/duke3d.h +++ b/source/games/duke/src/duke3d.h @@ -23,9 +23,9 @@ struct GameInterface : public ::GameInterface { const char* Name() override { return "Duke"; } void app_init() override; - void loadPalette(); - void LoadGameTextures(); - + void loadPalette() override; + void LoadGameTextures() override; + void SetupSpecialTextures() override; 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 78c604381..5d2b18345 100644 --- a/source/games/duke/src/game.cpp +++ b/source/games/duke/src/game.cpp @@ -279,16 +279,6 @@ static void setupbackdrop() // //--------------------------------------------------------------------------- -static void initTiles() -{ - tileDelete(TILE_MIRROR); - - if (isRR()) - tileDelete(0); - - tileDelete(FOF); -} - #define x(a, b) registerName(#a, b); #define y(a, b) registerName(#a, b); static void SetTileNames() @@ -314,6 +304,29 @@ void GameInterface::LoadGameTextures() SetTileNames(); } +void GameInterface::SetupSpecialTextures() +{ + // set up all special tiles here, before we fully hook up with the texture manager. + tileDelete(FOF); // portal marker + if (!isRR()) + { + tileDelete(560); // the mirror tile. + TileFiles.MakeCanvas(TILE_VIEWSCR, tileWidth(502), tileHeight(502)); + } + else + { + tileDelete(1089); // the mirror tile. + tileDelete(0); // RR uses this as an empty texture + TileFiles.tileMakeWritable(2025); // bowling lane pin displays + TileFiles.tileMakeWritable(2026); + TileFiles.tileMakeWritable(2027); + TileFiles.tileMakeWritable(2028); + TileFiles.MakeCanvas(TILE_VIEWSCR, tileWidth(1055), tileHeight(1055)); // not used by the game but all the support code is present, meaning maps are free to use it. + } + TileFiles.lock(); // from this point on the tile<->texture associations may not change anymore. +} + + void GameInterface::loadPalette() { @@ -376,7 +389,6 @@ void GameInterface::app_init() //Net_SendClientInfo(); - initTiles(); setupbackdrop(); SetupGameButtons(); InitCheats(); diff --git a/source/games/duke/src/render.cpp b/source/games/duke/src/render.cpp index 990fa37dd..c536a627e 100644 --- a/source/games/duke/src/render.cpp +++ b/source/games/duke/src/render.cpp @@ -67,7 +67,7 @@ BEGIN_DUKE_NS void GameInterface::UpdateCameras(double smoothratio) { - const int VIEWSCREEN_ACTIVE_DISTANCE = 512; + const int VIEWSCREEN_ACTIVE_DISTANCE = 1024; if (camsprite == nullptr) return; @@ -78,7 +78,6 @@ void GameInterface::UpdateCameras(double smoothratio) if (camsprite->GetOwner() && (p->GetActor()->spr.pos - camsprite->spr.pos).Length() < VIEWSCREEN_ACTIVE_DISTANCE) { auto tex = tileGetTexture(camsprite->spr.picnum); - TileFiles.MakeCanvas(TILE_VIEWSCR, (int)tex->GetDisplayWidth(), (int)tex->GetDisplayHeight()); auto canvas = tileGetCanvas(TILE_VIEWSCR); if (!canvas) return; diff --git a/source/games/exhumed/src/2d.cpp b/source/games/exhumed/src/2d.cpp index ba2e11917..b53943277 100644 --- a/source/games/exhumed/src/2d.cpp +++ b/source/games/exhumed/src/2d.cpp @@ -112,10 +112,10 @@ void menu_DoPlasma() if (!PlasmaBuffer) { - auto pixels = TileFiles.tileCreate(kTile4092, kPlasmaWidth, kPlasmaHeight); + auto pixels = tileData(kTile4092); memset(pixels, 96, kPlasmaWidth * kPlasmaHeight); - PlasmaBuffer = TileFiles.tileCreate(kTile4093, kPlasmaWidth, kPlasmaHeight); + PlasmaBuffer = tileData(kTile4093); memset(PlasmaBuffer, 96, kPlasmaWidth * kPlasmaHeight); @@ -437,10 +437,9 @@ void uploadCinemaPalettes() static int DoStatic(int a, int b) { - TileFiles.tileMakeWritable(kTileLoboLaptop); auto tex = dynamic_cast(tileGetTexture(kTileLoboLaptop)->GetTexture()->GetImage()); if (tex) tex->Reload(); - auto pixels = TileFiles.tileMakeWritable(kTileLoboLaptop); + auto pixels = tileData(kTileLoboLaptop); int y = 160 - a / 2; int left = 81 - b / 2; diff --git a/source/games/exhumed/src/exhumed.cpp b/source/games/exhumed/src/exhumed.cpp index 4fed68089..92d341cf9 100644 --- a/source/games/exhumed/src/exhumed.cpp +++ b/source/games/exhumed/src/exhumed.cpp @@ -236,7 +236,7 @@ void DrawClock() { int ebp = 49; - auto pixels = TileFiles.tileMakeWritable(kTile3603); + auto pixels = tileData(kTile3603); memset(pixels, TRANSPARENT_INDEX, 4096); @@ -549,6 +549,21 @@ void GameInterface::LoadGameTextures() SetTileNames(); } +void GameInterface::SetupSpecialTextures() +{ + TileFiles.tileCreate(kTile4092, kPlasmaWidth, kPlasmaHeight); + TileFiles.tileCreate(kTile4093, kPlasmaWidth, kPlasmaHeight); + TileFiles.tileCreate(kTileRamsesWorkTile, kSpiritY * 2, kSpiritX * 2); + TileFiles.tileMakeWritable(kTileLoboLaptop); + for(int i = kTile3603; i < kClockSymbol1 + 145; i++) + TileFiles.tileMakeWritable(kTile3603); + TileFiles.tileMakeWritable(kEnergy1); + TileFiles.tileMakeWritable(kEnergy2); + for (int i = 0; i < 16; i++) + TileFiles.tileMakeWritable(kClockSymbol1); + TileFiles.lock(); +} + //--------------------------------------------------------------------------- // // @@ -615,7 +630,7 @@ void CopyTileToBitmap(int nSrcTile, int nDestTile, int xPos, int yPos) { int nOffs = tileHeight(nDestTile) * xPos; - auto pixels = TileFiles.tileMakeWritable(nDestTile); + auto pixels = tileData(nDestTile); uint8_t *pDest = pixels + nOffs + yPos; uint8_t *pDestB = pDest; diff --git a/source/games/exhumed/src/exhumed.h b/source/games/exhumed/src/exhumed.h index c1a3540b1..b04562ab4 100644 --- a/source/games/exhumed/src/exhumed.h +++ b/source/games/exhumed/src/exhumed.h @@ -209,7 +209,8 @@ struct GameInterface : public ::GameInterface { const char* Name() override { return "Exhumed"; } void app_init() override; - void LoadGameTextures(); + void LoadGameTextures() override; + void SetupSpecialTextures() override; void clearlocalinputstate() override; void loadPalette() override; bool GenerateSavePic() override; diff --git a/source/games/exhumed/src/menu.cpp b/source/games/exhumed/src/menu.cpp index 3d3a627bf..b3b9e05e0 100644 --- a/source/games/exhumed/src/menu.cpp +++ b/source/games/exhumed/src/menu.cpp @@ -93,8 +93,8 @@ void DoEnergyTile() { nButtonColor += nButtonColor < 0 ? 8 : 0; - auto energy1 = TileFiles.tileMakeWritable(kEnergy1); - auto energy2 = TileFiles.tileMakeWritable(kEnergy2); + auto energy1 = tileData(kEnergy1); + auto energy2 = tileData(kEnergy2); uint8_t* ptr1 = energy1 + 1984; uint8_t* ptr2 = energy1 + 2048; diff --git a/source/games/exhumed/src/ramses.cpp b/source/games/exhumed/src/ramses.cpp index 4e1aa35b5..0b1c36967 100644 --- a/source/games/exhumed/src/ramses.cpp +++ b/source/games/exhumed/src/ramses.cpp @@ -121,7 +121,7 @@ void InitSpiritHead() nHeadStage = 0; // work tile is twice as big as the normal head size - Worktile = TileFiles.tileCreate(kTileRamsesWorkTile, kSpiritY * 2, kSpiritX * 2); + Worktile = tileData(kTileRamsesWorkTile); pSpiritSpr->spr.cstat &= ~CSTAT_SPRITE_INVISIBLE; diff --git a/source/games/sw/src/game.cpp b/source/games/sw/src/game.cpp index 9e1ac646f..ae99186e1 100644 --- a/source/games/sw/src/game.cpp +++ b/source/games/sw/src/game.cpp @@ -225,6 +225,16 @@ void GameInterface::LoadGameTextures() SetTileNames(); } +void GameInterface::SetupSpecialTextures() +{ + tileDelete(MIRROR); // mirror + for (int i = 0; i < MAXMIRRORS; i++) + { + tileDelete(i + MIRRORLABEL); + TileFiles.MakeCanvas(CAMSPRITE + i, 128, 114); + } + TileFiles.lock(); +} //--------------------------------------------------------------------------- // // diff --git a/source/games/sw/src/game.h b/source/games/sw/src/game.h index e0341deeb..94ab5519e 100644 --- a/source/games/sw/src/game.h +++ b/source/games/sw/src/game.h @@ -1657,8 +1657,9 @@ struct GameInterface : public ::GameInterface { const char* Name() override { return "ShadowWarrior"; } void app_init() override; - void LoadGameTextures(); - void loadPalette(); + void LoadGameTextures() override; + void SetupSpecialTextures() override; + void loadPalette() override; void clearlocalinputstate() override; void FreeLevelData() override; bool GenerateSavePic() override; diff --git a/source/games/sw/src/jsector.cpp b/source/games/sw/src/jsector.cpp index 7cb5d0ca6..12826dd9a 100644 --- a/source/games/sw/src/jsector.cpp +++ b/source/games/sw/src/jsector.cpp @@ -261,12 +261,10 @@ void JS_InitMirrors(void) // Scan wall tags for mirrors mirrorcnt = 0; - tileDelete(MIRROR); oscilationclock = I_GetBuildTime(); for (i = 0; i < MAXMIRRORS; i++) { - tileDelete(i + MIRRORLABEL); mirror[i].campic = -1; mirror[i].camspriteActor = nullptr; mirror[i].cameraActor = nullptr; @@ -348,10 +346,6 @@ void JS_InitMirrors(void) { mirror[mirrorcnt].campic = itActor->spr.picnum; mirror[mirrorcnt].camspriteActor = itActor; - - // JBF: commenting out this line results in the screen in $BULLET being visible - tileDelete(mirror[mirrorcnt].campic); - Found_Cam = true; } } @@ -603,7 +597,6 @@ void JS_DrawCameras(PLAYER* pp, const DVector3& campos, double smoothratio) // Set up the tile for drawing - TileFiles.MakeCanvas(mirror[cnt].campic, 128, 114); { if (dist < MAXCAMDIST)