From a70b7fa69881bcfe5ccbe4045781eaab100ccfc4 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Sun, 24 May 2020 23:26:47 +0200
Subject: [PATCH] - use the texture manager to handle texture data.

---
 source/build/src/palette.cpp            |  28 +++++-
 source/build/src/polymost.cpp           |   5 +-
 source/common/engine/palettecontainer.h |   3 +-
 source/common/textures/textures.h       |   2 +-
 source/core/gamecontrol.cpp             |   5 +-
 source/core/textures/buildtiles.cpp     | 127 +++++++++---------------
 source/core/textures/buildtiles.h       |  20 +---
 source/sw/src/game.cpp                  |  28 ------
 8 files changed, 88 insertions(+), 130 deletions(-)

diff --git a/source/build/src/palette.cpp b/source/build/src/palette.cpp
index a849cf7ce..f1a25ee83 100644
--- a/source/build/src/palette.cpp
+++ b/source/build/src/palette.cpp
@@ -51,10 +51,11 @@ void paletteSetColorTable(int32_t id, uint8_t const* table, bool notransparency,
     if (id == 0)
     {
         GPalette.SetPalette(table, 255);
+        GPalette.BaseColors[255] = 0;
         BuildTransTable(GPalette.BaseColors);
     }
     FRemapTable remap;
-    remap.AddColors(0, 256, table);
+    remap.AddColors(0, 256, table, 255);
     if (!notransparency)
     {
         remap.Palette[255] = 0;
@@ -267,7 +268,30 @@ void palettePostLoadLookups(void)
             }
         }
     }
-    // todo: at this point we should swap colors 0 and 255 so that paletted images being created here have their transparent color at index 0.
+#ifdef SWAP_255
+    // Swap colors 0 and 255 in all tables so that all paletted images have their transparent color at index 0.
+    // This means: 
+    // - Swap palette and remap entries in all stored remap tables
+    // - change all remap entries of 255 to 0 and vice versa
+
+    auto colorswap = [](FRemapTable* remap)
+    {
+        std::swap(remap->Palette[0], remap->Palette[255]);
+        std::swap(remap->Remap[0], remap->Remap[255]);
+        for (auto& c : remap->Remap)
+        {
+            if (c == 0) c = 255;
+            else if (c == 255) c = 0;
+        }
+    };
+
+    for (auto remap : GPalette.uniqueRemaps)
+    {
+        colorswap(remap);
+    }
+    colorswap(&GPalette.GlobalBrightmap);
+    std::swap(GPalette.BaseColors[0], GPalette.BaseColors[255]);
+#endif
 }
 
 //==========================================================================
diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp
index 71ed938f8..c292db902 100644
--- a/source/build/src/polymost.cpp
+++ b/source/build/src/polymost.cpp
@@ -19,6 +19,7 @@ Ken Silverman's official web site: http://www.advsys.net/ken
 #include "v_video.h"
 #include "flatvertices.h"
 #include "palettecontainer.h"
+#include "texturemanager.h"
 
 CVAR(Bool, hw_detailmapping, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
 CVAR(Bool, hw_glowmapping, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
@@ -210,7 +211,7 @@ void polymost_glreset()
     }
     else
     {
-		TileFiles.ClearTextureCache();
+        TexMan.FlushAll();
     }
 
 	if (polymosttext)
@@ -535,7 +536,7 @@ static void polymost_drawpoly(vec2f_t const * const dpxy, int32_t const n, int32
     {
         float const r = 1.f / dd[i];
 
-        if (TileFiles.tiledata[globalpicnum].replacement == ReplacementType::Canvas)
+        if (tileGetTexture(globalpicnum)->isCanvas())
         {
             //update texcoords, canvas textures are upside down!
             vt->SetTexCoord(
diff --git a/source/common/engine/palettecontainer.h b/source/common/engine/palettecontainer.h
index 90871863f..fa9d010dc 100644
--- a/source/common/engine/palettecontainer.h
+++ b/source/common/engine/palettecontainer.h
@@ -84,9 +84,10 @@ public:
 	FRemapTable IceMap;				// This is used by the texture compositor so it must be globally accessible.
 	uint8_t GrayMap[256];
 
+	TArray<FRemapTable*> uniqueRemaps;
+
 private:
 	FMemArena remapArena;
-	TArray<FRemapTable*> uniqueRemaps;
 	TArray<TAutoGrowArray<FRemapTablePtr, FRemapTable*>> TranslationTables;
 public:
 	void Init(int numslots);	// This cannot be a constructor!!!
diff --git a/source/common/textures/textures.h b/source/common/textures/textures.h
index a4cb09e82..9dc891fdb 100644
--- a/source/common/textures/textures.h
+++ b/source/common/textures/textures.h
@@ -432,7 +432,7 @@ protected:
 	uint16_t Width, Height;
 	int16_t _LeftOffset[2], _TopOffset[2];
 
-	FTexture (const char *name = NULL, int lumpnum = -1);
+	FTexture(const char *name = NULL, int lumpnum = -1);
 
 public:
 	FTextureBuffer CreateTexBuffer(int translation, int flags = 0);
diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp
index bd60be487..bc24e6847 100644
--- a/source/core/gamecontrol.cpp
+++ b/source/core/gamecontrol.cpp
@@ -424,8 +424,8 @@ int GameMain()
 	C_DeinitConsole();
 	V_ClearFonts();
 	vox_deinit();
-	TileFiles.ClearTextureCache();
-	TileFiles.CloseAll();	// do this before shutting down graphics.
+	TexMan.DeleteAll();
+	TileFiles.CloseAll();	// delete the texture data before shutting down graphics.
 	GLInterface.Deinit();
 	I_ShutdownGraphics();
 	M_DeinitMenus();
@@ -714,6 +714,7 @@ int RunGame()
 	}
 	TexMan.Init([]() {}, [](BuildInfo &) {});
 	V_InitFonts();
+	TileFiles.Init();
 	C_CON_SetAliases();
 	sfx_empty = fileSystem.FindFile("engine/dsempty.lmp"); // this must be done outside the sound code because it's initialized late.
 	I_InitSound();
diff --git a/source/core/textures/buildtiles.cpp b/source/core/textures/buildtiles.cpp
index 8d22cef9a..df7682552 100644
--- a/source/core/textures/buildtiles.cpp
+++ b/source/core/textures/buildtiles.cpp
@@ -113,7 +113,7 @@ static FTexture* GetTileTexture(const char* name, const TArray<uint8_t>& backing
 	auto tex = new FArtTile(backingstore, offset, width, height);
 	auto p = &backingstore[offset];
 	auto siz = width * height;
-#if 0
+#ifdef SWAP_255
 	for (int i = 0; i < siz; i++, p++)
 	{
 		// move transparent color to index 0 to get in line with the rest of the texture management.
@@ -129,6 +129,20 @@ static FTexture* GetTileTexture(const char* name, const TArray<uint8_t>& backing
 	return nullptr;
 }
 
+
+void BuildTiles::Init()
+{
+	auto Placeholder = TexMan.ByIndex(0);
+	for (auto& tile : tiledata)
+	{
+		tile.texture = Placeholder;
+		tile.backup = Placeholder;
+		tile.picanm = {};
+		tile.RotTile = { -1,-1 };
+		tile.replacement = ReplacementType::Art;
+	}
+
+}
 //==========================================================================
 //
 // 
@@ -137,11 +151,9 @@ static FTexture* GetTileTexture(const char* name, const TArray<uint8_t>& backing
 
 void BuildTiles::AddTile(int tilenum, FTexture* tex, bool permap)
 {
-	assert(AllTiles.Find(tex) == AllTiles.Size() && AllMapTiles.Find(tex) == AllMapTiles.Size());
-	auto& array = permap ? AllMapTiles : AllTiles;
-	array.Push(tex);
+	assert(!tex->GetID().isValid());	// must not be added yet.
+	TexMan.AddTexture(tex);
 	tiledata[tilenum].texture = tex;
-
 	if (!permap) tiledata[tilenum].backup = tex;
 }
 
@@ -279,49 +291,6 @@ int CountTiles (const char *fn, const uint8_t *RawData)
 	return tileend >= tilestart ? tileend - tilestart + 1 : 0;
 }
 
-//===========================================================================
-//
-// CloseAllMapArt
-//
-// Closes all per-map ART files
-//
-//===========================================================================
-
-void BuildTiles::CloseAllMapArt()
-{
-	AllMapTiles.DeleteAndClear();
-	PerMapArtFiles.DeleteAndClear();
-}
-
-//===========================================================================
-//
-// ClearTextureCache
-//
-// Deletes all hardware textures
-//
-//===========================================================================
-
-void BuildTiles::ClearTextureCache(bool artonly)
-{
-	for (auto tex : AllTiles)
-	{
-		tex->SystemTextures.Clean(true, true);
-	}
-	for (auto tex : AllMapTiles)
-	{
-		tex->SystemTextures.Clean(true, true);
-	}
-	if (!artonly)
-	{
-		decltype(textures)::Iterator it(textures);
-		decltype(textures)::Pair* pair;
-		while (it.NextPair(pair))
-		{
-			pair->Value->SystemTextures.Clean(true, true);
-		}
-	}
-}
-
 //===========================================================================
 //
 // InvalidateTile
@@ -390,9 +359,8 @@ int BuildTiles::LoadArtFile(const char *fn, const char *mapname, int firsttile)
 				// Only load the data if the header is present
 				if (CountTiles(fn, artptr) > 0)
 				{
-					auto& descs = mapname ? PerMapArtFiles : ArtFiles;
 					auto file = new BuildArtFile;
-					descs.Push(file);
+					ArtFiles.Push(file);
 					file->filename = fn;
 					file->RawData = std::move(artdata);
 					AddTiles(firsttile, file->RawData, mapname);
@@ -405,13 +373,6 @@ int BuildTiles::LoadArtFile(const char *fn, const char *mapname, int firsttile)
 			return -1;
 		}
 	}
-	else
-	{
-		// Reuse the old one but move it to the top. (better not.)
-		//auto fd = std::move(ArtFiles[old]);
-		//ArtFiles.Delete(old);
-		//ArtFiles.Push(std::move(fd));
-	}
 	return 0;
 }
 
@@ -448,10 +409,12 @@ void BuildTiles::LoadArtSet(const char* filename)
 FTexture* BuildTiles::ValidateCustomTile(int tilenum, ReplacementType type)
 {
 	if (tilenum < 0 || tilenum >= MAXTILES) return nullptr;
-	if (tiledata[tilenum].texture != tiledata[tilenum].backup) return nullptr;	// no mucking around with map tiles.
-	auto tile = tiledata[tilenum].texture;
-	if (tiledata[tilenum].replacement == type) return tile;		// already created
-	if (tiledata[tilenum].replacement > ReplacementType::Art) return nullptr;		// different custom type - cannot replace again.
+	auto &td = tiledata[tilenum];
+	if (td.texture != td.backup) return nullptr;	// no mucking around with map tiles.
+	auto tile = td.texture;
+	auto reptype = td.replacement;
+	if (reptype == type) return tile;		// already created
+	if (reptype > ReplacementType::Art) return nullptr;		// different custom type - cannot replace again.
 	FTexture* replacement = nullptr;
 	if (type == ReplacementType::Writable)
 	{
@@ -546,7 +509,7 @@ int32_t tileGetCRC32(int tileNum)
 	auto size = tile->GetWidth() * tile->GetHeight();
 	if (size == 0) return 0;
 
-#if 0
+#ifdef SWAP_255
 	// Temporarily revert the data to its original form with 255 being transparent. Otherwise the CRC won't match.
 	auto p = pixels;
 	for (int i = 0; i < size; i++, p++)
@@ -666,7 +629,6 @@ void tileCopy(int tile, int source, int pal, int xoffset, int yoffset, int flags
 
 void artClearMapArt(void)
 {
-	TileFiles.CloseAllMapArt();
 	for (auto& td : TileFiles.tiledata)
 	{
 		td.texture = td.backup;
@@ -688,7 +650,28 @@ void artSetupMapArt(const char* filename)
 	currentMapArt = filename;
 	artClearMapArt();
 
-	FStringf firstname("%s_00.art", filename);
+	FString lcfilename = filename;
+	lcfilename.MakeLower();
+
+	// Re-get from the texture manager if this map's tiles have already been created.
+	if (TileFiles.maptilesadded.Find(lcfilename) < TileFiles.maptilesadded.Size())
+	{
+		for (int i = 0; i < MAXTILES; i++)
+		{
+			FStringf name("maptile_%s_%05d", lcfilename.GetChars(), i);
+			auto texid = TexMan.CheckForTexture(name, ETextureType::Any);
+			if (texid.isValid())
+			{
+				TileFiles.tiledata[i].texture = TexMan.GetTexture(texid);
+			}
+		}
+		return;
+	}
+
+	TileFiles.maptilesadded.Push(lcfilename);
+
+
+	FStringf firstname("%s_00.art", lcfilename.GetChars());
 	auto fr = fileSystem.OpenFileReader(firstname);
 	if (!fr.isOpen()) return;
 	for (auto& td : TileFiles.tiledata)
@@ -696,6 +679,7 @@ void artSetupMapArt(const char* filename)
 		td.picanmbackup = td.picanm;
 	}
 
+
 	for (bssize_t i = 0; i < MAXARTFILES_TOTAL - MAXARTFILES_BASE; i++)
 	{
 		FStringf fullname("%s_%02d.art", filename, i);
@@ -713,7 +697,7 @@ void artSetupMapArt(const char* filename)
 void tileDelete(int tile)
 {
 	TileFiles.TextureToTile.Remove(tileGetTexture(tile));
-	TileFiles.tiledata[tile].texture = TileFiles.tiledata[tile].backup = TileFiles.Placeholder;
+	TileFiles.tiledata[tile].texture = TileFiles.tiledata[tile].backup = TexMan.ByIndex(0);
 	vox_undefine(tile);
 	md_undefinetile(tile);
 	tileRemoveReplacement(tile);
@@ -806,11 +790,6 @@ int BuildTiles::tileCreateRotated(int tileNum)
 	return index;
 }
 
-void tileSetAnim(int tile, const picanm_t& anm)
-{
-
-}
-
 //==========================================================================
 //
 //
@@ -819,15 +798,7 @@ void tileSetAnim(int tile, const picanm_t& anm)
 
 void BuildTiles::CloseAll()
 {
-	decltype(textures)::Iterator it(textures);
-	decltype(textures)::Pair* pair;
-	while (it.NextPair(pair)) delete pair->Value;
-	textures.Clear();
-	CloseAllMapArt();
 	ArtFiles.DeleteAndClear();
-	AllTiles.DeleteAndClear();
-	if (Placeholder) delete Placeholder;
-	Placeholder = nullptr;
 }
 
 //==========================================================================
diff --git a/source/core/textures/buildtiles.h b/source/core/textures/buildtiles.h
index 1251a71d5..62a67b969 100644
--- a/source/core/textures/buildtiles.h
+++ b/source/core/textures/buildtiles.h
@@ -273,23 +273,11 @@ struct BuildTiles
 	TDeletingArray<BuildArtFile*> ArtFiles;
 	TileDesc tiledata[MAXTILES];
 	TDeletingArray<BuildArtFile*> PerMapArtFiles;
-	TDeletingArray<FTexture*> AllTiles;	// This is for deleting tiles when shutting down.
-	TDeletingArray<FTexture*> AllMapTiles;	// Same for map tiles;
-	TMap<FString, FTexture*> textures;
 	TArray<FString> addedArt;
 	TMap<FTexture*, int> TextureToTile;
+	TArray<FString> maptilesadded;
 
-	BuildTiles()
-	{
-		Placeholder = new FImageTexture(new FDummyTile(0, 0));
-		for (auto& tile : tiledata)
-		{
-			tile.backup = tile.texture = Placeholder;
-			tile.RotTile = { -1,-1 };
-			tile.picanm = {};
-			tile.replacement = ReplacementType::Art;
-		}
-	}
+	void Init(); // This cannot be a constructor because it needs the texture manager running.
 	~BuildTiles()
 	{
 		CloseAll();
@@ -300,7 +288,7 @@ struct BuildTiles
 
 	void AddTile(int tilenum, FTexture* tex, bool permap = false);
 
-	void AddTiles(int firsttile, TArray<uint8_t>& store, const char *mapname);
+	void AddTiles(int firsttile, TArray<uint8_t>& store, const char* mapname);
 
 	void AddFile(BuildArtFile* bfd, bool permap)
 	{
@@ -311,7 +299,7 @@ struct BuildTiles
 	{
 		return ArtFiles.FindEx([filename](const BuildArtFile* element) { return filename.CompareNoCase(element->filename) == 0; });
 	}
-	int LoadArtFile(const char* file, const char *mapname = nullptr, int firsttile = -1);
+	int LoadArtFile(const char* file, const char* mapname = nullptr, int firsttile = -1);
 	void CloseAllMapArt();
 	void LoadArtSet(const char* filename);
 	void AddArt(TArray<FString>& art)
diff --git a/source/sw/src/game.cpp b/source/sw/src/game.cpp
index 62e3f6b98..7ceea649b 100644
--- a/source/sw/src/game.cpp
+++ b/source/sw/src/game.cpp
@@ -787,37 +787,9 @@ bool InitGame()
     }
 
     LoadDemoRun();
-    // Save off total heap for later calculations
-    //TotalMemory = Z_AvailHeap();
-    //DSPRINTF(ds,"Available Heap before LoadImages =  %d", TotalMemory);
-    //MONO_PRINT(ds);
-    // Reserve 1.5 megs for normal program use
-    // Generally, SW is consuming about a total of 11 megs including
-    // all the cached in graphics, etc. per level, so even on a 16 meg
-    // system, reserving 1.5 megs is fine.
-    // Note that on a 16 meg machine, Ken was leaving us about
-    // 24k for use outside the cache!  This was causing out of mem problems
-    // when songs, etc., greater than the remaining heap were being loaded.
-    // Even if you pre-cache songs, etc. to help, reserving some heap is
-    // a very smart idea since the game uses malloc throughout execution.
-    //ReserveMem = AllocMem(1L<<20);
-    //if(ReserveMem == 0) MONO_PRINT("Could not allocate 1.5 meg reserve!");
 
-    // LoadImages will now proceed to steal all the remaining heap space
-    //_outtext("\n\n\n\n\n\n\n\n");
-    //AnimateCacheCursor();
 	TileFiles.LoadArtSet("tiles%03d.art");
 
-    // Now free it up for later use
-    /*
-    if(ReserveMem)
-        {
-        // Recalc TotalMemory for later reference
-        ActualHeap = Z_AvailHeap() + 1536000L;
-        FreeMem(ReserveMem);
-        }
-    */
-
     Connect();
     SortBreakInfo();
     parallaxtype = 1;