1 #include "Tile_Cache.h"
2 #include "ContentManager.h"
3 #include "Directories.h"
4 #include "FileMan.h"
5 #include "GameInstance.h"
6 #include "HImage.h"
7 #include "Structure.h"
8 #include "Structure_Internals.h"
9 #include "Tile_Surface.h"
10 #include "TileDef.h"
11 #include "WorldDef.h"
12 #include <stdexcept>
13 #include <vector>
14 struct AuxObjectData;
15 
16 
17 struct TILE_CACHE_STRUCT
18 {
19 	ST::string rootName;
20 	STRUCTURE_FILE_REF* pStructureFileRef;
21 };
22 
23 
24 static const UINT32 guiMaxTileCacheSize = 50;
25 static UINT32 guiCurTileCacheSize       = 0;
26 static INT32  giDefaultStructIndex      = -1;
27 
28 
29 TILE_CACHE_ELEMENT*                   gpTileCache;
30 static std::vector<TILE_CACHE_STRUCT> gpTileCacheStructInfo;
31 
32 
InitTileCache(void)33 void InitTileCache(void)
34 {
35 	gpTileCache         = new TILE_CACHE_ELEMENT[guiMaxTileCacheSize]{};
36 	guiCurTileCacheSize = 0;
37 
38 	// Zero entries
39 	for (UINT32 i = 0; i < guiMaxTileCacheSize; ++i)
40 	{
41 		gpTileCache[i].pImagery        = 0;
42 		gpTileCache[i].struct_file_ref = 0;
43 	}
44 
45 	// Look for JSD files in the tile cache directory and load any we find
46 	std::vector<ST::string> jsdFiles = GCM->getAllTilecache();
47 
48 	for (const ST::string &file : jsdFiles)
49 	{
50 		TILE_CACHE_STRUCT tc;
51 		tc.rootName = FileMan::getFileNameWithoutExt(file);
52 		tc.pStructureFileRef = LoadStructureFile(file.c_str());
53 
54 		if (strcasecmp(tc.rootName.c_str(), "l_dead1") == 0)
55 		{
56 			giDefaultStructIndex = (INT32)gpTileCacheStructInfo.size();
57 		}
58 
59 		gpTileCacheStructInfo.push_back(tc);
60 	}
61 }
62 
63 
DeleteTileCache()64 void DeleteTileCache( )
65 {
66 	UINT32 cnt;
67 
68 	// Allocate entries
69 	if ( gpTileCache != NULL )
70 	{
71 		// Loop through and delete any entries
72 		for ( cnt = 0; cnt < guiMaxTileCacheSize; cnt++ )
73 		{
74 			if ( gpTileCache[ cnt ].pImagery != NULL )
75 			{
76 				DeleteTileSurface( gpTileCache[ cnt ].pImagery );
77 			}
78 		}
79 		delete[] gpTileCache;
80 	}
81 
82 	gpTileCacheStructInfo.clear();
83 
84 	guiCurTileCacheSize = 0;
85 }
86 
87 
GetCachedTile(const char * const filename)88 INT32 GetCachedTile(const char* const filename)
89 {
90 	INT32 idx = -1;
91 
92 	// Check to see if surface exists already
93 	for (UINT32 cnt = 0; cnt < guiCurTileCacheSize; ++cnt)
94 	{
95 		TILE_CACHE_ELEMENT* const i = &gpTileCache[cnt];
96 		if (i->pImagery == NULL)
97 		{
98 			if (idx == -1) idx = cnt;
99 			continue;
100 		}
101 
102 		if (i->zName.compare_i(filename) != 0) continue;
103 
104 		// Found surface, return
105 		++i->sHits;
106 		return (INT32)cnt;
107 	}
108 
109 	if (idx == -1)
110 	{
111 		if (guiCurTileCacheSize < guiMaxTileCacheSize)
112 		{
113 			idx = guiCurTileCacheSize++;
114 		}
115 		else
116 		{
117 			// cache out least used file
118 			idx = 0;
119 			INT16 sMostHits = gpTileCache[idx].sHits;
120 			for (UINT32 cnt = 1; cnt < guiCurTileCacheSize; ++cnt)
121 			{
122 				const TILE_CACHE_ELEMENT* const i = &gpTileCache[cnt];
123 				if (i->sHits < sMostHits)
124 				{
125 					sMostHits = i->sHits;
126 					idx       = cnt;
127 				}
128 			}
129 
130 			// Bump off lowest index
131 			TILE_CACHE_ELEMENT* const del = &gpTileCache[idx];
132 			DeleteTileSurface(del->pImagery);
133 			del->sHits           = 0;
134 			del->pImagery        = 0;
135 			del->struct_file_ref = 0;
136 		}
137 	}
138 
139 	TILE_CACHE_ELEMENT* const tce = &gpTileCache[idx];
140 
141 	tce->pImagery = LoadTileSurface(filename);
142 
143 	tce->zName = filename;
144 	tce->sHits = 1;
145 
146 	ST::string root_name(FileMan::getFileNameWithoutExt(filename));
147 	STRUCTURE_FILE_REF* const sfr = GetCachedTileStructureRefFromFilename(root_name.c_str());
148 	tce->struct_file_ref = sfr;
149 	if (sfr) AddZStripInfoToVObject(tce->pImagery->vo, sfr, TRUE, 0);
150 
151 	const AuxObjectData* const aux = tce->pImagery->pAuxData;
152 	tce->ubNumFrames = (aux != NULL ? aux->ubNumberOfFrames : 1);
153 
154 	return idx;
155 }
156 
157 
RemoveCachedTile(INT32 const cached_tile)158 void RemoveCachedTile(INT32 const cached_tile)
159 {
160 	if ((UINT32)cached_tile < guiCurTileCacheSize)
161 	{
162 		TILE_CACHE_ELEMENT& e = gpTileCache[cached_tile];
163 		if (e.pImagery)
164 		{
165 			if (--e.sHits != 0) return;
166 
167 			DeleteTileSurface(e.pImagery);
168 			e.pImagery        = 0;
169 			e.struct_file_ref = 0;
170 			return;
171 		}
172 	}
173 	throw std::logic_error("Trying to remove invalid cached tile");
174 }
175 
176 
GetCachedTileStructureRef(INT32 const idx)177 static STRUCTURE_FILE_REF* GetCachedTileStructureRef(INT32 const idx)
178 {
179 	return idx != -1 ? gpTileCache[idx].struct_file_ref : 0;
180 }
181 
182 
GetCachedTileStructureRefFromFilename(char const * const filename)183 STRUCTURE_FILE_REF* GetCachedTileStructureRefFromFilename(char const* const filename)
184 {
185 	size_t const n = gpTileCacheStructInfo.size();
186 	for (size_t i = 0; i != n; ++i)
187 	{
188 		TILE_CACHE_STRUCT& t = gpTileCacheStructInfo[i];
189 		if (strcasecmp(t.rootName.c_str(), filename) == 0) return t.pStructureFileRef;
190 	}
191 	return 0;
192 }
193 
194 
CheckForAndAddTileCacheStructInfo(LEVELNODE * const pNode,INT16 const sGridNo,UINT16 const usIndex,UINT16 const usSubIndex)195 void CheckForAndAddTileCacheStructInfo(LEVELNODE* const pNode, INT16 const sGridNo, UINT16 const usIndex, UINT16 const usSubIndex)
196 {
197 	STRUCTURE_FILE_REF* const sfr = GetCachedTileStructureRef(usIndex);
198 	if (!sfr)  return;
199 
200 	if (AddStructureToWorld(sGridNo, 0, &sfr->pDBStructureRef[usSubIndex], pNode)) return;
201 
202 	if (giDefaultStructIndex == -1) return;
203 
204 	STRUCTURE_FILE_REF* const def_sfr = gpTileCacheStructInfo[giDefaultStructIndex].pStructureFileRef;
205 	if (!def_sfr) return;
206 
207 	AddStructureToWorld(sGridNo, 0, &def_sfr->pDBStructureRef[usSubIndex], pNode);
208 }
209 
210 
CheckForAndDeleteTileCacheStructInfo(LEVELNODE * pNode,UINT16 usIndex)211 void CheckForAndDeleteTileCacheStructInfo( LEVELNODE *pNode, UINT16 usIndex )
212 {
213 	STRUCTURE_FILE_REF *pStructureFileRef;
214 
215 	if ( usIndex >= TILE_CACHE_START_INDEX )
216 	{
217 		pStructureFileRef = GetCachedTileStructureRef( ( usIndex - TILE_CACHE_START_INDEX ) );
218 
219 		if ( pStructureFileRef != NULL)
220 		{
221 			DeleteStructureFromWorld( pNode->pStructureData );
222 		}
223 	}
224 }
225