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