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