1 #include <string.h>
2 
3 #include "fixer.h"
4 
5 #include "string.hpp"
6 #ifndef DB_LEVEL
7 	#define DB_LEVEL 4
8 #endif
9 #include "db.h"
10 
11 #include "awtexld.h"
12 
13 #include "chnkload.hpp"
14 #include "chunkpal.hpp"
15 
16 #ifndef CL_SUPPORT_FASTFILE
17 	#error "Please #define CL_SUPPORT_FASTFILE to 0 or 1 in projload.hpp"
18 #endif
19 #if CL_SUPPORT_FASTFILE
20 	#include "ffstdio.h"
21 #endif
22 
23 //#ifndef CL_SUPPORT_ALTTAB
24 //	#error "Please #define CL_SUPPORT_ALTTAB to 0 or 1 in projload.hpp"
25 //#endif
26 //#if CL_SUPPORT_ALTTAB
27 //	#include "alt_tab.h"
28 //#endif
29 
30 #include "chnktexi.h"
31 
32 #if !defined(NDEBUG) && defined(_CPPRTTI)
33 	#include <typeinfo.h>
34 #else
35 	#define dynamic_cast static_cast
36 #endif
37 
38 char const * cl_pszGameMode = NULL;
39 
40 // used to determine if the display is palettized
41 // currently assuming that if this is <= 8 then all
42 // surfaces et. except d3d textures have a global palette
43 extern "C" {
44 	extern int VideoModeColourDepth;
45 };
46 
47 // useful filename handling functions
48 
49 // returns pointer into string pointing to filename without dirname
50 template <class C> // C can be char or char const
StripPath(C * n)51 static C * StripPath(C * n)
52 {
53 	C * rm = strrchr(n,':');
54 	if (rm) n = rm+1;
55 	rm = strrchr(n,'/');
56 	if (rm) n = rm+1;
57 	rm = strrchr(n,'\\');
58 	if (rm) n = rm+1;
59 
60 	return n;
61 }
62 
63 // removes any .extension from filename by inserting null character
StripFileExtension(char * n)64 static void StripFileExtension(char * n)
65 {
66 	char * dotpos = strrchr(n,'.');
67 	if (dotpos) *dotpos = 0;
68 }
69 
StripFileExtension(char const * n)70 static char * StripFileExtension(char const * n)
71 {
72 	char * nn = new char[strlen(n)+1];
73 	strcpy(nn,n);
74 	StripFileExtension(nn);
75 	return nn;
76 }
77 
78 // get the directory associated with the riff - free with delete[]
RiffBasename(Chunk_With_Children * pEnvDataChunk)79 static char * RiffBasename(Chunk_With_Children * pEnvDataChunk)
80 {
81 	Chunk * pChunk = pEnvDataChunk->lookup_single_child("RIFFNAME");
82 
83 	if (pChunk)
84 	{
85 		RIF_Name_Chunk * pRifNameChunk = dynamic_cast<RIF_Name_Chunk *>(pChunk);
86 
87 		const char * pszRifName = StripPath(pRifNameChunk->rif_name);
88 
89 		char * pszBaseName = new char[strlen(pszRifName)+1];
90 		strcpy(pszBaseName,pszRifName);
91 		StripFileExtension(pszBaseName);
92 
93 		return pszBaseName;
94 	}
95 	const char * pszDefault = "empty";
96 	char * pszBaseName = new char [strlen(pszDefault)+1];
97 	strcpy(pszBaseName,pszDefault);
98 
99 	return pszBaseName;
100 }
101 
102 #if CL_SUPPORT_FASTFILE
IsFileInFastFile(char const * pszFileName)103 static inline bool IsFileInFastFile(char const * pszFileName)
104 {
105 	size_t nLen;
106 	return ffreadbuf(pszFileName,&nLen) ? true : false;
107 }
108 #endif
109 
DoesFileExist(char const * pszFileName)110 static bool DoesFileExist(char const * pszFileName)
111 {
112 	unsigned int attr = GetGameFileAttributes(pszFileName, FILETYPE_PERM);
113 
114 	if ((attr & FILEATTR_DIRECTORY) != 0)
115 		return false;
116 	if ((attr & FILEATTR_READABLE) == 0)
117 		return false;
118 	return true;
119 }
120 
GetPath(char * pszFileNameBuf,unsigned nBufSize,ImageDescriptor const & idsc,Chunk_With_Children * pEnvDataChunk,bool bGloballyPalettized)121 static char * GetPath(char * pszFileNameBuf, unsigned nBufSize, ImageDescriptor const & idsc, Chunk_With_Children * pEnvDataChunk, bool bGloballyPalettized)
122 {
123 	// set the name
124 	char const * pszRawName = StripPath(idsc.filename);
125 	char * pszName = new char[strlen(pszRawName)+1];
126 	strcpy(pszName,pszRawName);
127 	StripFileExtension(pszName);
128 
129 	// load this image
130 	char const * pg0ext = ".PG0";
131 
132 	if (!bGloballyPalettized)
133 	{
134 		char const * dir2 = idsc.flags & IDSCF_SPRITE ? "Sprites\\" : idsc.flags & IDSCF_SUBSHAPE ? SubShps_Directory : "";
135 		char * riffname = RiffBasename(pEnvDataChunk);
136 		char const * dir3 = idsc.flags & IDSCF_INCLUDED ? idsc.rifname : riffname;
137 		if (nBufSize < strlen(GenTex_Directory)+strlen(dir2)+strlen(dir3)+1+strlen(pszName)+5)
138 		{
139 			db_log1("CL_LoadImageOnce(): ERROR: buffer not big enough for filename");
140 			pszFileNameBuf = NULL;
141 		}
142 		else
143 		{
144 			strcpy(pszFileNameBuf,GenTex_Directory);
145 			strcat(pszFileNameBuf,dir2);
146 			strcat(pszFileNameBuf,dir3);
147 			strcat(pszFileNameBuf,"\\");
148 			strcat(pszFileNameBuf,pszName);
149 			strcat(pszFileNameBuf,".BM0");
150 		}
151 		delete[] riffname;
152 	}
153 	else
154 	{
155 		if (idsc.flags & IDSCF_FIXEDPALETTE)
156 		{
157 			char const * dir2 = idsc.fixrifname ? *idsc.fixrifname ? idsc.fixrifname : 0 : 0;
158 			char const * dir3 = idsc.flags & IDSCF_SPRITE ? "Sprites\\" : "";
159 			char * riffname = RiffBasename(pEnvDataChunk);
160 			char const * dir4 = idsc.flags & IDSCF_INCLUDED ? idsc.rifname : riffname;
161 			if (nBufSize < strlen(FixTex_Directory)+(dir2 ? strlen(dir2)+1 : 0)+strlen(dir3)+strlen(dir4)+1+strlen(pszName)+5)
162 			{
163 				db_log1("CL_LoadImageOnce(): ERROR: buffer not big enough for filename");
164 				pszFileNameBuf = NULL;
165 			}
166 			else
167 			{
168 				strcpy(pszFileNameBuf,FixTex_Directory);
169 				if (dir2)
170 				{
171 					strcat(pszFileNameBuf,dir2);
172 					strcat(pszFileNameBuf,"\\");
173 				}
174 				strcat(pszFileNameBuf,dir3);
175 				strcat(pszFileNameBuf,dir4);
176 				strcat(pszFileNameBuf,"\\");
177 				strcat(pszFileNameBuf,pszName);
178 				strcat(pszFileNameBuf,pg0ext);
179 			}
180 			delete[] riffname;
181 		}
182 		else
183 		{
184 			char const * dir1 = cl_pszGameMode ? GameTex_Directory : ToolsTex_Directory;
185 			char * dir2 = RiffBasename(pEnvDataChunk);
186 			char const * dir4 = idsc.flags & IDSCF_SPRITE ? "Sprites\\" : "";
187 			char const * dir5 = idsc.flags & IDSCF_INCLUDED ? idsc.rifname : 0;
188 			if (nBufSize < strlen(dir1)+strlen(dir2)+1+(cl_pszGameMode ? strlen(cl_pszGameMode)+1 : 0)+strlen(dir4)+(dir5 ? strlen(dir5)+1 : 0)+strlen(pszName)+5)
189 			{
190 				db_log1("CL_LoadImageOnce(): ERROR: buffer not big enough for filename");
191 				pszFileNameBuf = NULL;
192 			}
193 			else
194 			{
195 				strcpy(pszFileNameBuf,dir1);
196 				strcat(pszFileNameBuf,dir2);
197 				strcat(pszFileNameBuf,"\\");
198 				if (cl_pszGameMode)
199 				{
200 					strcat(pszFileNameBuf,cl_pszGameMode);
201 					strcat(pszFileNameBuf,"\\");
202 				}
203 				strcat(pszFileNameBuf,dir4);
204 				if (dir5)
205 				{
206 					strcat(pszFileNameBuf,dir5);
207 					strcat(pszFileNameBuf,"\\");
208 				}
209 				strcat(pszFileNameBuf,pszName);
210 				strcat(pszFileNameBuf,pg0ext);
211 			}
212 			delete[] dir2;
213 		}
214 	}
215 
216 	if (pszFileNameBuf)
217 		db_logf4(("\tfile expected to be '%s'",pszFileNameBuf));
218 
219 	delete[] pszName;
220 
221 	return pszFileNameBuf;
222 }
223 
CL_GetImageFileName(char * pszDestBuf,unsigned nBufSize,char const * pszFileName,unsigned fFlagsEtc)224 char * CL_GetImageFileName(char * pszDestBuf, unsigned nBufSize, char const * pszFileName, unsigned fFlagsEtc)
225 {
226 	db_assert1(pszFileName);
227 	db_assert1(pszDestBuf);
228 	db_assert1(nBufSize>0);
229 	db_logf4(("CL_LoadImageOnce(): Getting the full pathname for %s",pszFileName));
230 	switch (fFlagsEtc & _LIO_PATHTYPEMASK)
231 	{
232 		case LIO_ABSOLUTEPATH:
233 			db_log4("\t(which is an absolute path)");
234 			if (strlen(pszFileName)<nBufSize)
235 			{
236 				strcpy(pszDestBuf,pszFileName);
237 				return pszDestBuf;
238 			}
239 			else
240 			{
241 				db_log1("CL_LoadImageOnce(): ERROR: buffer not large enough to hold filename");
242 				return NULL;
243 			}
244 		case LIO_RELATIVEPATH:
245 			db_logf4(("\t(which is a path relative to %s or %s)",
246 				FirstTex_Directory ? FirstTex_Directory : "<not-specified>",
247 				SecondTex_Directory ? SecondTex_Directory : "<not-specified>"));
248 			#define _GET_RELATIVE_PATH(pszDirectory,fnDoesExist) \
249 				if (pszDirectory) { \
250 					String str = pszDirectory; \
251 					if (str.length()) { \
252 						int chLast = str.get_at(str.length()-1); \
253 						if (chLast != '\\' && chLast != '/') \
254 							str += '\\'; \
255 						str += pszFileName; \
256 						if (fnDoesExist(str)) { \
257 							if (str.length() < nBufSize) { \
258 								strcpy(pszDestBuf,str); \
259 								return pszDestBuf; \
260 							} else { \
261 								db_log1("CL_LoadImageOnce(): ERROR: buffer not large enough to hold filename"); \
262 								return NULL; /* fail because the buffer isnt big enough */ \
263 				}	}	}	}
264 
265 			#if CL_SUPPORT_FASTFILE
266 			_GET_RELATIVE_PATH(FirstTex_Directory,IsFileInFastFile)
267 			_GET_RELATIVE_PATH(SecondTex_Directory,IsFileInFastFile)
268 			#endif
269 			#if !defined(CL_SUPPORTONLY_FASTFILE) || !CL_SUPPORTONLY_FASTFILE
270 			_GET_RELATIVE_PATH(FirstTex_Directory,DoesFileExist)
271 			_GET_RELATIVE_PATH(SecondTex_Directory,DoesFileExist)
272 			#endif
273 			db_log1("CL_LoadImageOnce(): ERROR: file not found in relative path");
274 			return NULL;
275 		case LIO_RIFFPATH:
276 		{
277 			int enum_id = -1; // may be supported at a later date, valid when pszFileName is NULL
278 
279 			bool bGloballyPalettized = VideoModeColourDepth <= 8 && (fFlagsEtc & _LIO_SURFTYPEMASK) != LIO_D3DTEXTURE;
280 
281 			db_log4("\t(whose path is determined by the current .RIF file)");
282 			if (!Env_Chunk)
283 			{
284 				db_log1("CL_LoadImageOnce(): ERROR: no RIF file");
285 				return NULL;
286 			}
287 			Chunk * pChunk = Env_Chunk->lookup_single_child("REBENVDT");
288 			if (!pChunk)
289 			{
290 				db_log1("CL_LoadImageOnce(): ERROR: no environment data chunk");
291 				return NULL;
292 			}
293 			Chunk_With_Children * pEnvDataChunk = dynamic_cast<Chunk_With_Children *>(pChunk);
294 			db_assert1(pEnvDataChunk);
295 
296 			Environment_Game_Mode_Chunk * pGameModeChunk = NULL;
297 			if (cl_pszGameMode)
298 			{
299 				if (*cl_pszGameMode)
300 				{
301 					List<Chunk *> listGmChunks;
302 					pEnvDataChunk->lookup_child("GAMEMODE",listGmChunks);
303 
304 					for (LIF<Chunk *> itGmChunks(&listGmChunks); !itGmChunks.done(); itGmChunks.next())
305 					{
306 						Environment_Game_Mode_Chunk * pGmChunk = dynamic_cast<Environment_Game_Mode_Chunk *>(itGmChunks());
307 						db_assert1(pGmChunk);
308 						if (pGmChunk->id_equals(cl_pszGameMode))
309 						{
310 							pGameModeChunk = pGmChunk;
311 							break;
312 						}
313 					}
314 
315 					if (!pGameModeChunk)
316 						db_logf3(("CL_LoadImageOnce(): WARNING: Game Mode '%s' not found",cl_pszGameMode));
317 				}
318 			}
319 
320 			char * pszName = StripFileExtension(StripPath(pszFileName));
321 
322 			char * pszSubName = 0;
323 			if (pszFileName)
324 			{
325 				if (strchr(pszFileName,'\\'))
326 				{
327 					pszSubName = new char[strlen(pszFileName)+1];
328 					strcpy(pszSubName,pszFileName);
329 					*strchr(pszSubName,'\\')=0;
330 				}
331 				else if (strchr(pszFileName,'/'))
332 				{
333 					pszSubName = new char[strlen(pszFileName)+1];
334 					strcpy(pszSubName,pszFileName);
335 					*strchr(pszSubName,'/')=0;
336 				}
337 			}
338 
339 			if (pGameModeChunk)
340 			{
341 				bool bShapeInGm = pszSubName ? false : true;
342 				// Get the matching image 'Processor' chunk
343 				Chunk * pMiChunk = pGameModeChunk->lookup_single_child("MATCHIMG");
344 				Matching_Images_Chunk * pMatchImageChunk = NULL;
345 
346 				if (pMiChunk)
347 				{
348 					pMatchImageChunk = dynamic_cast<Matching_Images_Chunk *>(pMiChunk);
349 					db_assert1(pMatchImageChunk);
350 				}
351 
352 				List<Chunk *> listRifChildChunks;
353 				pGameModeChunk->lookup_child("RIFCHILD",listRifChildChunks);
354 
355 				for (LIF<Chunk *> itRifChildChunks(&listRifChildChunks); !itRifChildChunks.done(); itRifChildChunks.next())
356 				{
357 					RIF_Child_Chunk * pRifChildChunk = dynamic_cast<RIF_Child_Chunk *>(itRifChildChunks());
358 					db_assert1(pRifChildChunk);
359 
360 					if (pszSubName)
361 					{
362 						if (_stricmp(pszSubName,pRifChildChunk->rifname) && (*pszSubName || *pRifChildChunk->filename))
363 							continue;
364 						bShapeInGm = true;
365 					}
366 
367 					for (LIF<BMP_Flags> itBmpFlags(&pRifChildChunk->bmps); !itBmpFlags.done(); itBmpFlags.next())
368 					{
369 						BMP_Flags bmpfTemp(itBmpFlags());
370 						StripFileExtension(bmpfTemp.filename);
371 
372 						if (pszFileName ? !_stricmp(pszName,StripPath(bmpfTemp.filename)) : enum_id == bmpfTemp.enum_id)
373 						{
374 							// select image descriptor
375 							ImageDescriptor const idsc
376 								(
377 									*pRifChildChunk->filename ?
378 										(IDscFlags)((bmpfTemp.flags & ChunkBMPFlag_FixedPalette ?
379 											IDSCF_FIXEDPALETTE
380 										:
381 											IDSCF_0)
382 										|IDSCF_INCLUDED)
383 									:
384 										IDSCF_0,
385 									itBmpFlags().filename,
386 									*pRifChildChunk->filename ? pRifChildChunk->rifname : 0
387 								);
388 							ImageDescriptor const * pIdsc = &idsc;
389 
390 							if (pMatchImageChunk) pIdsc = &pMatchImageChunk->GetLoadImage(idsc);
391 							else db_logf3(("CL_LoadImageOnce(): WARNING! no rule to find matching images in game mode '%s'\n",pGameModeChunk->header->mode_identifier));
392 
393 							// load this image
394 							if (GetPath(pszDestBuf,nBufSize,*pIdsc,pEnvDataChunk,bGloballyPalettized))
395 							{
396 								if (pszSubName)
397 								{
398 									delete[] pszSubName;
399 								}
400 								delete[] pszName;
401 								return pszDestBuf;
402 							}
403 						}
404 					}
405 				}
406 
407 				List<Chunk *> listExtShapes;
408 				pGameModeChunk->lookup_child("SHBMPNAM",listExtShapes);
409 
410 				for (LIF<Chunk *> itExtShapes(&listExtShapes); !itExtShapes.done(); itExtShapes.next())
411 				{
412 					External_Shape_BMPs_Store_Chunk * pShapeBmpsChunk = dynamic_cast<External_Shape_BMPs_Store_Chunk *>(itExtShapes());
413 					db_assert1(pShapeBmpsChunk);
414 
415 					if (pszSubName)
416 						if (_stricmp(pszSubName,pShapeBmpsChunk->shapename) && *pszSubName)
417 							continue;
418 
419 					for (LIF<BMP_Name> itBmpNames(&pShapeBmpsChunk->bmps); !itBmpNames.done(); itBmpNames.next())
420 					{
421 						BMP_Name bmpnTemp(itBmpNames());
422 						StripFileExtension(bmpnTemp.filename);
423 
424 						if (pszFileName ? !_stricmp(pszName,StripPath(bmpnTemp.filename)) : enum_id == bmpnTemp.enum_id)
425 						{
426 
427 							// select image descriptor
428 							ImageDescriptor const idsc
429 								(
430 									(IDscFlags)((bmpnTemp.flags & ChunkBMPFlag_FixedPalette ?
431 										IDSCF_FIXEDPALETTE
432 									:
433 										IDSCF_0)
434 									|(pShapeBmpsChunk->GetExtendedData()->flags & GBF_SPRITE ?
435 										IDSCF_SPRITE
436 									:
437 										IDSCF_SUBSHAPE)
438 									|IDSCF_INCLUDED),
439 									itBmpNames().filename,
440 									pShapeBmpsChunk->shapename,
441 									bmpnTemp.flags & ChunkBMPFlag_FixedPalette ? pShapeBmpsChunk->rifname : 0
442 								);
443 							ImageDescriptor const * pIdsc = &idsc;
444 
445 							if (pMatchImageChunk) pIdsc = &pMatchImageChunk->GetLoadImage(idsc);
446 							else db_logf3(("WARNING! no rule to find matching images in game mode %s\n",pGameModeChunk->header->mode_identifier));
447 
448 							// load this image
449 							if (GetPath(pszDestBuf,nBufSize,*pIdsc,pEnvDataChunk,bGloballyPalettized))
450 							{
451 								if (pszSubName)
452 								{
453 									delete[] pszSubName;
454 								}
455 								delete[] pszName;
456 								return pszDestBuf;
457 							}
458 						}
459 					}
460 				}
461 
462 				if (pszSubName)
463 				{
464 					if (!bShapeInGm)
465 						db_logf3(("CL_LoadImageOnce(): WARNING! shape/sprite %s not found in this RIF file\n",pszSubName));
466 					else
467 						db_logf3(("CL_LoadImageOnce(): WARNING! shape/sprite %s does not appear to list %s\n",pszSubName,pszName));
468 				}
469 
470 			}
471 
472 			List<Chunk *> listMatchImageChunk;
473 			pEnvDataChunk->lookup_child("MATCHIMG",listMatchImageChunk);
474 
475 			Matching_Images_Chunk * pMicFix = NULL;
476 			Matching_Images_Chunk * pMicNorm = NULL;
477 
478 			for (LIF<Chunk *> itMatchImageChunk(&listMatchImageChunk); !itMatchImageChunk.done(); itMatchImageChunk.next())
479 			{
480 				Matching_Images_Chunk * pMatchImageChunk = dynamic_cast<Matching_Images_Chunk *>(itMatchImageChunk());
481 				db_assert1(pMatchImageChunk);
482 				if (pMatchImageChunk->flags & MICF_FIXEDPALETTE)
483 					pMicFix = pMatchImageChunk;
484 				else
485 					pMicNorm = pMatchImageChunk;
486 			}
487 
488 			List<Chunk_With_Children *> listShapesSprites;
489 
490 			List<Chunk *> listShapes;
491 			Env_Chunk->lookup_child("REBSHAPE",listShapes);
492 			for (LIF<Chunk *> itShapes(&listShapes); !itShapes.done(); itShapes.next())
493 			{
494 				Shape_Chunk * pShapeChunk = dynamic_cast<Shape_Chunk *>(itShapes());
495 				db_assert1(pShapeChunk);
496 				Chunk * pSxfnChunk = pShapeChunk->lookup_single_child("SHPEXTFL");
497 				if (pSxfnChunk)
498 				{
499 					Shape_External_File_Chunk * pShpExtFnameChunk = dynamic_cast<Shape_External_File_Chunk *>(pSxfnChunk);
500 					db_assert1(pShpExtFnameChunk);
501 					listShapesSprites.add_entry(pShpExtFnameChunk);
502 				}
503 			}
504 			Chunk * pSprChunk = Env_Chunk->lookup_single_child("RSPRITES");
505 			if (pSprChunk)
506 			{
507 				Chunk_With_Children * pSpritesChunk = dynamic_cast<Chunk_With_Children *>(pSprChunk);
508 				db_assert1(pSpritesChunk);
509 
510 				List<Chunk *> listSprHeadChunks;
511 				pSpritesChunk->lookup_child("SPRIHEAD",listSprHeadChunks);
512 
513 				for (LIF<Chunk *> itSprites(&listSprHeadChunks); !itSprites.done(); itSprites.next())
514 				{
515 					Chunk_With_Children * pSpriteHead = dynamic_cast<Chunk_With_Children *>(itSprites());
516 					db_assert1(pSpriteHead);
517 					listShapesSprites.add_entry(pSpriteHead);
518 				}
519 			}
520 
521 			int bShapeFound = pszSubName ? false : true;
522 
523 			for (LIF<Chunk_With_Children *> itShapesSprites(&listShapesSprites); !itShapesSprites.done(); itShapesSprites.next())
524 			{
525 				char * pszSubRifName = RiffBasename(itShapesSprites());
526 
527 				if (pszSubName)
528 				{
529 					if (_stricmp(pszSubRifName,pszSubName)) // must match shapes name exactly
530 					{
531 						delete[] pszSubRifName;
532 						continue;
533 					}
534 					bShapeFound = true;
535 				}
536 
537 				Chunk * pBmpLstStChunk = itShapesSprites()->lookup_single_child("BMPLSTST");
538 				if (pBmpLstStChunk)
539 				{
540 					Bitmap_List_Store_Chunk * pBmpListStoreChunk = dynamic_cast<Bitmap_List_Store_Chunk *>(pBmpLstStChunk);
541 					db_assert1(pBmpListStoreChunk);
542 
543 					for (LIF<BMP_Name> itBmpName(&pBmpListStoreChunk->bmps); !itBmpName.done(); itBmpName.next())
544 					{
545 						BMP_Name bmpnTemp(itBmpName());
546 						StripFileExtension(bmpnTemp.filename);
547 
548 						if (pszFileName ? !_stricmp(pszName,StripPath(bmpnTemp.filename)) : enum_id == bmpnTemp.enum_id)
549 						{
550 
551 							// select image descriptor
552 							char * pszRifName = RiffBasename(pEnvDataChunk);
553 							ImageDescriptor const idsc
554 								(
555 									(IDscFlags)((bmpnTemp.flags & ChunkBMPFlag_FixedPalette ?
556 										IDSCF_FIXEDPALETTE
557 									:
558 										IDSCF_0)
559 									|(pBmpListStoreChunk->GetExtendedData()->flags & GBF_SPRITE ?
560 										IDSCF_SPRITE
561 									:
562 										IDSCF_SUBSHAPE)
563 									|IDSCF_INCLUDED),
564 									itBmpName().filename,
565 									pszSubRifName,
566 									bmpnTemp.flags & ChunkBMPFlag_FixedPalette ? pszRifName : 0
567 								);
568 							ImageDescriptor const * pIdsc = &idsc;
569 							delete[] pszRifName;
570 
571 							if (bmpnTemp.flags & ChunkBMPFlag_FixedPalette)
572 							{
573 								if (pMicFix) pIdsc = &pMicFix->GetLoadImage(idsc);
574 								else db_log3("CL_LoadImageOnce(): WARNING! no rule to find fixed palette matching images in environment data\n");
575 							}
576 							else
577 							{
578 								if (pMicNorm) pIdsc = &pMicNorm->GetLoadImage(idsc);
579 								else db_log3("CL_LoadImageOnce(): WARNING! no rule to find matching images in environment data (interface engine?)\n");
580 							}
581 
582 							// load this image
583 							if (GetPath(pszDestBuf,nBufSize,*pIdsc,pEnvDataChunk,bGloballyPalettized))
584 							{
585 								delete[] pszSubRifName;
586 								if (pszSubName)
587 								{
588 									delete[] pszSubName;
589 								}
590 								delete[] pszName;
591 								return pszDestBuf;
592 							}
593 						}
594 					}
595 				}
596 				delete[] pszSubRifName;
597 			}
598 
599 			if (pszSubName)
600 			{
601 				if (!bShapeFound)
602 					db_logf3(("CL_LoadImageOnce(): WARNING! shape/sprite %s not found in this RIF file\n",pszSubName));
603 				else
604 					db_logf3(("CL_LoadImageOnce(): WARNING! shape/sprite %s does not appear to list %s\n",pszSubName,pszName));
605 				delete[] pszSubName;
606 			}
607 
608 			// not found in game textures, so look in default
609 
610 			else // but only if there is no virtual shape directory
611 			{
612 				Chunk * pBmpNames = pEnvDataChunk->lookup_single_child("BMPNAMES");
613 				if (pBmpNames)
614 				{
615 					Global_BMP_Name_Chunk * pGbnc = dynamic_cast<Global_BMP_Name_Chunk *>(pBmpNames);
616 					db_assert1(pGbnc);
617 
618 					for (LIF<BMP_Name> itBmpName(&pGbnc->bmps); !itBmpName.done(); itBmpName.next())
619 					{
620 						BMP_Name bmpnTemp(itBmpName());
621 						StripFileExtension(bmpnTemp.filename);
622 
623 						if (pszFileName ? !_stricmp(pszName,StripPath(bmpnTemp.filename)) : enum_id == bmpnTemp.enum_id)
624 						{
625 							// select image descriptor
626 							ImageDescriptor const idsc (bmpnTemp.flags & ChunkBMPFlag_FixedPalette ? IDSCF_FIXEDPALETTE : IDSCF_0, itBmpName().filename);
627 							ImageDescriptor const * pIdsc = &idsc;
628 
629 							if (bmpnTemp.flags & ChunkBMPFlag_FixedPalette)
630 							{
631 								if (pMicFix) pIdsc = &pMicFix->GetLoadImage(idsc);
632 								else db_log3("CL_LoadImageOnce(): WARNING! no rule to find fixed palette matching images in environment data\n");
633 							}
634 							else
635 							{
636 								if (pMicNorm) pIdsc = &pMicNorm->GetLoadImage(idsc);
637 								else db_log3("CL_LoadImageOnce(): WARNING! no rule to find matching images in environment data (interface engine?)\n");
638 							}
639 
640 							// load this image
641 							if (GetPath(pszDestBuf,nBufSize,*pIdsc,pEnvDataChunk,bGloballyPalettized))
642 							{
643 								delete[] pszName;
644 								return pszDestBuf;
645 							}
646 						}
647 					}
648 				}
649 			}
650 			delete[] pszName;
651 			return NULL;
652 		}
653 		default: // invalid arguments
654 			db_log1("CL_LoadImageOnce(): ERROR: invalid parameter passed to CL_GetImageFileName()");
655 			return NULL;
656 	}
657 }
658 
659 extern "C" {
660 	extern void CheckForWindowsMessages(void);
661 };
662 
CL_LoadImageOnce(char const * pszFileName,unsigned fFlagsEtc)663 int CL_LoadImageOnce(char const * pszFileName, unsigned fFlagsEtc)
664 {
665 	// safe to handle windows messages at this point (I think - JCWH)
666 	CheckForWindowsMessages();
667 
668 	// get the filename
669 	char szBuf[MAX_PATH];
670 	if (!CL_GetImageFileName(szBuf,sizeof szBuf/sizeof szBuf[0],pszFileName,fFlagsEtc))
671 	{
672 		db_log1("CL_LoadImageOnce(): ERROR: unable to determine path of file");
673 		return GEI_NOTLOADED;
674 	}
675 
676 	db_logf4(("\tLoading '%s'",szBuf));
677 
678 	// already loaded ?
679 	int iExistingImage = GetExistingImageNum(szBuf);
680 	if (GEI_NOTLOADED != iExistingImage)
681 	{
682 		db_logf4(("\tImage already loaded to image number %d",iExistingImage));
683 		return iExistingImage;
684 	}
685 
686 	// what flags do we want?
687 	unsigned fAwLoad = AW_TLF_DEFAULT;
688 	if (fFlagsEtc & LIO_VIDMEM)
689 		fAwLoad |= AW_TLF_VIDMEM;
690 	if (fFlagsEtc & LIO_TRANSPARENT)
691 		fAwLoad |= AW_TLF_TRANSP;
692 	if (fFlagsEtc & LIO_CHROMAKEY)
693 		fAwLoad |= AW_TLF_CHROMAKEY;
694 	if (fFlagsEtc & LIO_LOADMIPMAPS)
695 		db_log1("CL_LoadImageOnce(): WARNING: mip maps not supported yet - will not be created/loaded");
696 
697 	// what are we loading into ?
698 	switch (fFlagsEtc & _LIO_SURFTYPEMASK)
699 	{
700 		case LIO_CHIMAGE:
701 		{
702 			db_log1("CL_LoadImageOnce(): WARNING: having to call LoadImageCH()");
703 			IMAGEHEADER * pImageHdr = GetImageHeader();
704 			db_assert1(pImageHdr);
705 			memset(pImageHdr,0,sizeof(IMAGEHEADER));
706 			if (LoadImageCH(szBuf,pImageHdr))
707 				return NumImages-1;
708 			else
709 			{
710 				db_log1("CL_LoadImageOnce(): ERROR: LoadImageCH() failed");
711 				return GEI_NOTLOADED;
712 			}
713 		}
714 		case LIO_DDSURFACE:
715 		{
716 			#if CL_SUPPORT_FASTFILE
717 			size_t nFastFileLen;
718 			void const * pFastFileData = ffreadbuf(szBuf,&nFastFileLen);
719 			if (pFastFileData)
720 			{
721 				db_log4("\tfile is in a fast file");
722 				unsigned nWidth, nHeight;
723 				AW_BACKUPTEXTUREHANDLE hBackup = NULL;
724 				DDSurface * pSurface =
725 					AwCreateSurface
726 					(
727 						fFlagsEtc & LIO_RESTORABLE ? "pxfXYB" : "pxfXY",
728 						pFastFileData,
729 						nFastFileLen,
730 						fAwLoad,
731 						&nWidth,
732 						&nHeight,
733 						&hBackup
734 					);
735 				if (pSurface)
736 				{
737 					IMAGEHEADER * pImageHdr = GetImageHeader();
738 					db_assert1(pImageHdr);
739 					memset(pImageHdr,0,sizeof(IMAGEHEADER));
740 					pImageHdr->ImageWidth = nWidth;
741 					pImageHdr->ImageHeight = nHeight;
742 					db_assert1(sizeof pImageHdr->ImageName / sizeof pImageHdr->ImageName[0] > strlen(szBuf));
743 					strcpy(pImageHdr->ImageName,szBuf);
744 					pImageHdr->DDSurface = pSurface;
745 					pImageHdr->hBackup = hBackup;
746 					db_logf4(("\tloaded to image number %d",NumImages-1));
747 					#if CL_SUPPORT_ALTTAB
748 						if (fFlagsEtc & LIO_RESTORABLE)
749 						#ifdef NDEBUG
750 							ATIncludeSurface(pSurface,hBackup);
751 						#else
752 						{
753 							char szDbInf[512];
754 							sprintf(szDbInf,"Name \"%s\" Number %d",szBuf,NumImages-1);
755 							ATIncludeSurfaceDb(pSurface,hBackup,szDbInf);
756 						}
757 						#endif
758 					#endif // CL_SUPPORT_ALTTAB
759 					return NumImages-1;
760 				}
761 				else
762 				{
763 					db_log1("CL_LoadImageOnce(): ERROR copying data to surface");
764 					return GEI_NOTLOADED;
765 				}
766 			}
767 			else
768 			#endif // CL_SUPPORT_FASTFILE
769 			{
770 				#if !defined(CL_SUPPORTONLY_FASTFILE) || !CL_SUPPORTONLY_FASTFILE
771 				db_log4("\tloading the actual file");
772 				unsigned nWidth, nHeight;
773 				AW_BACKUPTEXTUREHANDLE hBackup = NULL;
774 				DDSurface * pSurface =
775 					AwCreateSurface
776 					(
777 						fFlagsEtc & LIO_RESTORABLE ? "sfXYB" : "sfXY",
778 						&szBuf[0],
779 						fAwLoad,
780 						&nWidth,
781 						&nHeight,
782 						&hBackup
783 					);
784 				if (pSurface)
785 				{
786 					IMAGEHEADER * pImageHdr = GetImageHeader();
787 					db_assert1(pImageHdr);
788 					memset(pImageHdr,0,sizeof(IMAGEHEADER));
789 					pImageHdr->ImageWidth = nWidth;
790 					pImageHdr->ImageHeight = nHeight;
791 					db_assert1(sizeof pImageHdr->ImageName / sizeof pImageHdr->ImageName[0] > strlen(szBuf));
792 					strcpy(pImageHdr->ImageName,szBuf);
793 					pImageHdr->DDSurface = pSurface;
794 					pImageHdr->hBackup = hBackup;
795 					db_logf4(("\tloaded to image number %d",NumImages-1));
796 					db_logf4(("\t\tsurface:%p",pSurface));
797 					#if CL_SUPPORT_ALTTAB
798 						if (fFlagsEtc & LIO_RESTORABLE)
799 						#ifdef NDEBUG
800 							ATIncludeSurface(pSurface,hBackup);
801 						#else
802 						{
803 							char szDbInf[512];
804 							sprintf(szDbInf,"Name \"%s\" Number %d",szBuf,NumImages-1);
805 							ATIncludeSurfaceDb(pSurface,hBackup,szDbInf);
806 						}
807 						#endif
808 					#endif // CL_SUPPORT_ALTTAB
809 					return NumImages-1;
810 				}
811 				else
812 				{
813 					db_log1("CL_LoadImageOnce(): ERROR copying data to surface");
814 					return GEI_NOTLOADED;
815 				}
816 				#elif !CL_SUPPORT_FASTFILE
817 					#error "CL_SUPPORTONLY_FASTFILE set but CL_SUPPORT_FASTFILE not set"
818 				#endif // !CL_SUPPORTONLY_FASTFILE
819 			}
820 			//db_msg1("THIS CODE SHOULD BE UNREACHABLE");
821 		}
822 		case LIO_D3DTEXTURE:
823 		{
824 			fAwLoad |= AW_TLF_COMPRESS; // required on some cards!!
825 			#if CL_SUPPORT_FASTFILE
826 			size_t nFastFileLen;
827 			void const * pFastFileData = ffreadbuf(szBuf,&nFastFileLen);
828 			if (pFastFileData)
829 			{
830 				db_log4("\tfile is in a fast file");
831 				unsigned nWidth, nHeight;
832 				AW_BACKUPTEXTUREHANDLE hBackup = NULL;
833 				D3DTexture * pTexture =
834 					AwCreateTexture
835 					(
836 						fFlagsEtc & LIO_RESTORABLE ? "pxfWHB" : "pxfWH",
837 						pFastFileData,
838 						nFastFileLen,
839 						fAwLoad,
840 						&nWidth,
841 						&nHeight,
842 						&hBackup
843 					);
844 				if (pTexture)
845 				{
846 					IMAGEHEADER * pImageHdr = GetImageHeader();
847 					db_assert1(pImageHdr);
848 					memset(pImageHdr,0,sizeof(IMAGEHEADER));
849 					pImageHdr->ImageWidth = nWidth;
850 					pImageHdr->ImageHeight = nHeight;
851 					db_assert1(sizeof pImageHdr->ImageName / sizeof pImageHdr->ImageName[0] > strlen(szBuf));
852 					strcpy(pImageHdr->ImageName,szBuf);
853 					pImageHdr->D3DTexture = pTexture;
854 					pImageHdr->hBackup = hBackup;
855 					db_logf4(("\tloaded to image number %d",NumImages-1));
856 
857 					/* KJL 16:05:50 26/02/98 - attempt to get a texture handle */
858 					{
859 						int gotTextureHandle = GetTextureHandle(pImageHdr);
860 						db_assert1(gotTextureHandle==TRUE);
861 					}
862 
863 					#if CL_SUPPORT_ALTTAB
864 						if (fFlagsEtc & LIO_RESTORABLE)
865 						#ifdef NDEBUG
866 							ATIncludeTexture(pTexture,hBackup);
867 						#else
868 						{
869 							char szDbInf[512];
870 							sprintf(szDbInf,"Name \"%s\" Number %d",szBuf,NumImages-1);
871 							ATIncludeTextureDb(pTexture,hBackup,szDbInf);
872 						}
873 						#endif
874 					#endif // CL_SUPPORT_ALTTAB
875 					return NumImages-1;
876 				}
877 				else
878 				{
879 					db_log1("CL_LoadImageOnce(): ERROR copying data to texture");
880 					return GEI_NOTLOADED;
881 				}
882 			}
883 			else
884 			#endif // CL_SUPPORT_FASTFILE
885 			{
886 				#if !defined(CL_SUPPORTONLY_FASTFILE) || !CL_SUPPORTONLY_FASTFILE
887 				db_log4("\tloading the actual file");
888 				unsigned nWidth, nHeight;
889 				AW_BACKUPTEXTUREHANDLE hBackup = NULL;
890 				D3DTexture * pTexture =
891 					AwCreateTexture
892 					(
893 						fFlagsEtc & LIO_RESTORABLE ? "sfWHB" : "sfWH",
894 						&szBuf[0],
895 						fAwLoad,
896 						&nWidth,
897 						&nHeight,
898 						&hBackup
899 					);
900 				if (pTexture)
901 				{
902 					IMAGEHEADER * pImageHdr = GetImageHeader();
903 					db_assert1(pImageHdr);
904 					memset(pImageHdr,0,sizeof(IMAGEHEADER));
905 					pImageHdr->ImageWidth = nWidth;
906 					pImageHdr->ImageHeight = nHeight;
907 					db_assert1(sizeof pImageHdr->ImageName / sizeof pImageHdr->ImageName[0] > strlen(szBuf));
908 					strcpy(pImageHdr->ImageName,szBuf);
909 					pImageHdr->D3DTexture = pTexture;
910 					pImageHdr->hBackup = hBackup;
911 					db_logf4(("\tloaded to image number %d",NumImages-1));
912 
913 					/* KJL 16:05:50 26/02/98 - attempt to get a texture handle */
914 					{
915 						int gotTextureHandle = GetTextureHandle(pImageHdr);
916 						db_assert1(gotTextureHandle==TRUE);
917 					}
918 
919 					#if CL_SUPPORT_ALTTAB
920 						if (fFlagsEtc & LIO_RESTORABLE)
921 						#ifdef NDEBUG
922 							ATIncludeTexture(pTexture,hBackup);
923 						#else
924 						{
925 							char szDbInf[512];
926 							sprintf(szDbInf,"Name \"%s\" Number %d",szBuf,NumImages-1);
927 							ATIncludeTextureDb(pTexture,hBackup,szDbInf);
928 						}
929 						#endif
930 					#endif // CL_SUPPORT_ALTTAB
931 					return NumImages-1;
932 				}
933 				else
934 				{
935 					db_log1("CL_LoadImageOnce(): ERROR copying data to texture");
936 					return GEI_NOTLOADED;
937 				}
938 				#elif !CL_SUPPORT_FASTFILE
939 					#error "CL_SUPPORTONLY_FASTFILE set but CL_SUPPORT_FASTFILE not set"
940 				#endif // !CL_SUPPORTONLY_FASTFILE
941 			}
942 			//db_msg1("THIS CODE SHOULD BE UNREACHABLE");
943 		}
944 		default:
945 			db_log1("CL_LoadImageOnce(): ERROR: Invalid destination surface specification");
946 			return GEI_NOTLOADED;
947 	}
948 }
949 
950