1 #include "fixer.h"
2
3 #ifndef DB_LEVEL
4 #define DB_LEVEL 4
5 #endif
6 #include "db.h"
7
8 #ifndef NDEBUG
9 #define HT_FAIL db_log1
10 #include "hash_tem.hpp" // for the backup surfaces memory leak checking
11 #endif
12
13 #include "iff.hpp"
14
15 #include "list_tem.hpp"
16
17 #include <stdlib.h>
18 #include <stdarg.h>
19 #include <limits.h>
20
21 #include "media.hpp"
22 #include "awtexld.h"
23 #include "awtexld.hpp"
24
25 #ifdef _CPPRTTI
26 #include <typeinfo.h>
27 #endif
28
29 /* awTexLd.cpp - Author: Jake Hotson */
30
31 /*****************************************/
32 /* Preprocessor switches for experiments */
33 /*****************************************/
34
35 #define MIPMAPTEST 0 // experiment to create mip map surfaces for textures, but doesn't bother putting any data into them
36
37 /*****************************/
38 /* DB_LEVEL dependent macros */
39 /*****************************/
40
41 #if DB_LEVEL >= 5
42 #define inline // prevent function inlining at level 5 debugging
43 #endif
44
45 /*****************************************************/
46 /* ZEROFILL and SETDWSIZE macros ensure that I won't */
47 /* accidentally get the parameters wrong */
48 /*****************************************************/
49
50 #if 1 // which do you prefer?
51
52 // zero mem
53 template <class X>
ZEROFILL(X & x)54 static inline void ZEROFILL(X & x)
55 {
56 memset(&x,0,sizeof(X));
57 }
58
59 // set dwSize
60 template <class X>
SETDWSIZE(X & x)61 static inline void SETDWSIZE(X & x)
62 {
63 x.dwSize = sizeof(X);
64 }
65
66 template <class X>
INITDXSTRUCT(X & x)67 static inline void INITDXSTRUCT(X & x)
68 {
69 ZEROFILL(x);
70 SETDWSIZE(x);
71 }
72
73 #else
74
75 #define ZEROFILL(x) (memset(&x,0,sizeof x))
76 #define SETDWSIZE(x) (x.dwSize = sizeof x)
77 #define INITDXSTRUCT(x) (ZEROFILL(x),SETDWSIZE(x))
78
79 #endif
80
81 /*****************************************************************/
82 /* Put everything I can in a namespace to avoid naming conflicts */
83 /*****************************************************************/
84
85 namespace AwTl
86 {
87 /**************************************************/
88 /* Allow breakpoints to be potentially hard coded */
89 /* into macros and template functions */
90 /**************************************************/
91
db_code5(void BrkPt (){})92 db_code5(void BrkPt(){})
93 #define BREAKPOINT db_code5(::AwTl::BrkPt();)
94
95 #if DB_LEVEL > 4
96 static unsigned GetRefCount(IUnknown * pUnknown)
97 {
98 #if 0
99 if (!pUnknown) return 0;
100 pUnknown->AddRef();
101 return static_cast<unsigned>(pUnknown->Release());
102 #endif
103 return 0;
104 }
105 #endif
106
107 /*********************************/
108 /* Pixel format global structure */
109 /*********************************/
110
111 PixelFormat pixelFormat;
112
113 PixelFormat pfTextureFormat;
114 PixelFormat pfSurfaceFormat;
115
SetBitShifts(unsigned * leftShift,unsigned * rightShift,unsigned mask)116 static inline void SetBitShifts(unsigned * leftShift,unsigned * rightShift,unsigned mask)
117 {
118 if (!mask)
119 *leftShift = 0;
120 else
121 for (*leftShift = 0; !(mask & 1); ++*leftShift, mask>>=1)
122 ;
123 for (*rightShift = 8; mask; --*rightShift, mask>>=1)
124 ;
125 }
126
127 /************************************/
128 /* D3D Driver info global structure */
129 /************************************/
130
131 static
132 struct DriverDesc
133 {
DriverDescAwTl::DriverDesc134 DriverDesc() : validB(false), ddP(NULL) {}
135
136 bool validB : 1;
137 bool needSquareB : 1;
138 bool needPow2B : 1;
139
140 unsigned minWidth;
141 unsigned minHeight;
142 unsigned maxWidth;
143 unsigned maxHeight;
144
145 DWORD memFlag;
146
147 void * ddP;
148 } driverDesc;
149
150 /*************************************************************************/
151 /* Class used to hold all the parameters for the CreateTexture functions */
152 /*************************************************************************/
153
154 class CreateTextureParms
155 {
156 public:
CreateTextureParms()157 inline CreateTextureParms()
158 : loadTextureB(false)
159 , fileNameS(NULL)
160 , fileH(NULL)
161 , dataP(NULL)
162 , restoreH(NULL)
163 , maxReadBytes(UINT_MAX)
164 , bytesReadP(NULL)
165 , flags(AW_TLF_DEFAULT)
166 , widthP(NULL)
167 , heightP(NULL)
168 , originalWidthP(NULL)
169 , originalHeightP(NULL)
170 , prevTexP(static_cast<D3DTexture *>(NULL))
171 , prevTexB(false)
172 , callbackF(NULL)
173 , rectA(NULL)
174 {
175 }
176
177 SurfUnion DoCreate() const;
178
179 bool loadTextureB;
180
181 char *fileNameS;
182 FILE *fileH;
183 PtrUnionConst dataP;
184 AW_BACKUPTEXTUREHANDLE restoreH;
185
186 unsigned maxReadBytes;
187 unsigned * bytesReadP;
188
189 unsigned flags;
190
191 unsigned * widthP;
192 unsigned * heightP;
193
194 unsigned * originalWidthP;
195 unsigned * originalHeightP;
196
197 SurfUnion prevTexP;
198 bool prevTexB; // used when rectA is non-NULL, otherwise prevTexP is used
199
200 AW_TL_PFN_CALLBACK callbackF;
201 void * callbackParam;
202
203 unsigned numRects;
204 AwCreateGraphicRegion * rectA;
205 };
206
207
208 /****************************************/
209 /* Reference Count Object Debug Support */
210 /****************************************/
211
212 #ifndef NDEBUG
213
214 static bool g_bAllocListActive = false;
215
216 class AllocList : public ::HashTable<RefCntObj *>
217 {
218 public:
AllocList()219 AllocList()
220 {
221 g_bAllocListActive = true;
222 }
~AllocList()223 ~AllocList()
224 {
225 if (Size())
226 {
227 db_log1(("AW: Potential Memory Leaks Detected!!!"));
228 }
229 #ifdef _CPPRTTI
230 //#warning "Run-Time Type Identification (RTTI) is enabled"
231 for (Iterator itLeak(*this) ; !itLeak.Done() ; itLeak.Next())
232 {
233 db_logf1(("\tAW Object not deallocated: Type: %s RefCnt: %u",typeid(*itLeak.Get()).name(),itLeak.Get()->m_nRefCnt));
234 }
235 if (Size())
236 {
237 db_log1(("AW: Object dump complete"));
238 }
239 #else // ! _CPPRTTI
240 //#warning "Run-Time Type Identification (RTTI) is not enabled - memory leak checking will not report types"
241 unsigned nRefs(0);
242 for (Iterator itLeak(*this) ; !itLeak.Done() ; itLeak.Next())
243 {
244 nRefs += itLeak.Get()->m_nRefCnt;
245 }
246 if (Size())
247 {
248 db_logf1(("AW: Objects not deallocated: Number of Objects: %u Number of References: %u",Size(),nRefs));
249 }
250 #endif // ! _CPPRTTI
251 g_bAllocListActive = false;
252 }
253 };
254
255 static AllocList g_listAllocated;
256
DbRemember(RefCntObj * pObj)257 void DbRemember(RefCntObj * pObj)
258 {
259 g_listAllocated.AddAsserted(pObj);
260 }
261
DbForget(RefCntObj * pObj)262 void DbForget(RefCntObj * pObj)
263 {
264 if (g_bAllocListActive)
265 g_listAllocated.RemoveAsserted(pObj);
266 }
267
268 #endif // ! NDEBUG
269
270 /********************************************/
271 /* structure to contain loading information */
272 /********************************************/
273
274 struct LoadInfo
275 {
276 DDSurface * surfaceP;
277 bool surface_lockedB;
278 DDSurface * dst_surfaceP;
279 D3DTexture * textureP;
280 D3DTexture * dst_textureP;
281
282 unsigned surface_width;
283 unsigned surface_height;
284 PtrUnion surface_dataP;
285 LONG surface_pitch;
286 DWORD dwCapsCaps;
287
288 unsigned * widthP;
289 unsigned * heightP;
290 SurfUnion prevTexP;
291 SurfUnion resultP;
292 unsigned top,left,bottom,right;
293 unsigned width,height; // set to right-left and bottom-top
294
295 AwCreateGraphicRegion * rectP;
296
297 bool skipB; // used to indicate that a surface/texture was not lost and .`. does not need restoring
298
LoadInfoAwTl::LoadInfo299 LoadInfo()
300 : surfaceP(NULL)
301 , surface_lockedB(false)
302 , dst_surfaceP(NULL)
303 , textureP(NULL)
304 , dst_textureP(NULL)
305 , skipB(false)
306 {
307 }
308 };
309
310 /*******************************/
311 /* additiional texture formats */
312 /*******************************/
313
314 struct AdditionalPixelFormat : PixelFormat
315 {
316 bool canDoTranspB;
317 unsigned maxColours;
318
319 // for List
operator ==AwTl::AdditionalPixelFormat320 bool operator == (AdditionalPixelFormat const &) const { return false; }
operator !=AwTl::AdditionalPixelFormat321 bool operator != (AdditionalPixelFormat const &) const { return true; }
322 };
323
324 static List<AdditionalPixelFormat> listTextureFormats;
325
326 } // namespace AwTl
327
328 /*******************/
329 /* Generic Loaders */
330 /*******************/
331
332 #define HANDLE_DXERROR(s) \
333 if (DD_OK != awTlLastDxErr) { \
334 awTlLastErr = AW_TLE_DXERROR; \
335 db_logf3(("AwCreateGraphic() failed whilst %s",s)); \
336 db_log1("AwCreateGraphic(): ERROR: DirectX SDK call failed"); \
337 goto EXIT_WITH_ERROR; \
338 } else { \
339 db_logf5(("\tsuccessfully completed %s",s)); \
340 }
341
342 #define ON_ERROR_RETURN_NULL(s) \
343 if (awTlLastErr != AW_TLE_OK) { \
344 db_logf3(("AwCreateGraphic() failed whilst %s",s)); \
345 db_logf1(("AwCreateGraphic(): ERROR: %s",AwTlErrorToString())); \
346 return static_cast<D3DTexture *>(NULL); \
347 } else { \
348 db_logf5(("\tsuccessfully completed %s",s)); \
349 }
350
351 #define CHECK_MEDIA_ERRORS(s) \
352 if (pMedium->m_fError) { \
353 db_logf3(("AwCreateGraphic(): The following media errors occurred whilst %s",s)); \
354 if (pMedium->m_fError & MediaMedium::MME_VEOFMET) { \
355 db_log3("\tA virtual end of file was met"); \
356 if (awTlLastErr == AW_TLE_OK) awTlLastErr = AW_TLE_EOFMET; \
357 } \
358 if (pMedium->m_fError & MediaMedium::MME_EOFMET) { \
359 db_log3("\tAn actual end of file was met"); \
360 if (awTlLastErr == AW_TLE_OK) awTlLastErr = AW_TLE_EOFMET; \
361 } \
362 if (pMedium->m_fError & MediaMedium::MME_OPENFAIL) { \
363 db_log3("\tThe file could not be opened"); \
364 if (awTlLastErr == AW_TLE_OK) { awTlLastErr = AW_TLE_CANTOPENFILE; awTlLastWinErr = GetLastError(); } \
365 } \
366 if (pMedium->m_fError & MediaMedium::MME_CLOSEFAIL) { \
367 db_log3("\tThe file could not be closed"); \
368 if (awTlLastErr == AW_TLE_OK) { awTlLastErr = AW_TLE_CANTOPENFILE; awTlLastWinErr = GetLastError(); } \
369 } \
370 if (pMedium->m_fError & MediaMedium::MME_UNAVAIL) { \
371 db_log3("\tA requested operation was not available"); \
372 if (awTlLastErr == AW_TLE_OK) { awTlLastErr = AW_TLE_CANTREADFILE; awTlLastWinErr = GetLastError(); } \
373 } \
374 if (pMedium->m_fError & MediaMedium::MME_IOERROR) { \
375 db_log3("\tA read error occurred"); \
376 if (awTlLastErr == AW_TLE_OK) { awTlLastErr = AW_TLE_CANTREADFILE; awTlLastWinErr = GetLastError(); } \
377 } \
378 }
379
Restore(AwTl::CreateTextureParms const & rParams)380 AwTl::SurfUnion AwBackupTexture::Restore(AwTl::CreateTextureParms const & rParams)
381 {
382 using namespace AwTl;
383
384 ChoosePixelFormat(rParams);
385
386 if (!pixelFormat.validB)
387 db_log3("AwCreateGraphic(): ERROR: pixel format not valid");
388 if (!driverDesc.ddP || (!driverDesc.validB && rParams.loadTextureB))
389 db_log3("AwCreateGraphic(): ERROR: driver description not valid");
390
391 awTlLastErr = pixelFormat.validB && driverDesc.ddP && (driverDesc.validB || !rParams.loadTextureB) ? AW_TLE_OK : AW_TLE_NOINIT;
392
393 ON_ERROR_RETURN_NULL("initializing restore")
394
395 OnBeginRestoring(pixelFormat.palettizedB ? 1<<pixelFormat.bitsPerPixel : 0);
396
397 ON_ERROR_RETURN_NULL("initializing restore")
398
399 SurfUnion pTex = CreateTexture(rParams);
400
401 OnFinishRestoring(AW_TLE_OK == awTlLastErr ? true : false);
402
403 return pTex;
404 }
405
HasTransparentMask(bool bDefault)406 bool AwBackupTexture::HasTransparentMask(bool bDefault)
407 {
408 return bDefault;
409 }
410
GetTransparentColour()411 DWORD AwBackupTexture::GetTransparentColour()
412 {
413 return 0;
414 }
415
ChoosePixelFormat(AwTl::CreateTextureParms const & _parmsR)416 void AwBackupTexture::ChoosePixelFormat(AwTl::CreateTextureParms const & _parmsR)
417 {
418 // fprintf(stderr, "AwBackupTexture::ChoosePixelFormat(...)\n");
419
420 using namespace AwTl;
421
422 pixelFormat.validB = false; // set invalid first
423
424 // which flags to use?
425 unsigned fMyFlags =
426 _parmsR.flags & AW_TLF_PREVSRCALL ? db_assert1(_parmsR.restoreH), m_fFlags
427 : _parmsR.flags & AW_TLF_PREVSRC ? db_assert1(_parmsR.restoreH),
428 ((_parmsR.flags & ~AW_TLF_TRANSP) | (m_fFlags & AW_TLF_TRANSP))
429 : _parmsR.flags;
430
431 // transparency?
432 m_bTranspMask = HasTransparentMask(fMyFlags & AW_TLF_TRANSP ? true : false);
433
434 if (_parmsR.loadTextureB || (fMyFlags & AW_TLF_TEXTURE))
435 {
436 #if 0
437 // use a texture format
438 unsigned nColours = GetNumColours();
439 unsigned nMinPalSize = GetMinPaletteSize();
440
441 PixelFormat * pFormat = &pfTextureFormat;
442
443 for (LIF<AdditionalPixelFormat> itFormat(&listTextureFormats); !itFormat.done(); itFormat.next())
444 {
445 AdditionalPixelFormat * pThisFormat = &itFormat();
446 // is this format suitable?
447 // ignoring alpha for now
448 if
449 (
450 (nMinPalSize <= 1U<<pThisFormat->bitsPerPixel && nMinPalSize || !pThisFormat->palettizedB) // few enough colours for palettized format
451 && (nColours <= pThisFormat->maxColours && nColours || !pThisFormat->maxColours) // pass the max colours test
452 && (pThisFormat->canDoTranspB || !m_bTranspMask) // pass the transparency test
453 )
454 {
455 pFormat = pThisFormat;
456 }
457 }
458
459 pixelFormat = *pFormat;
460
461 #if DB_LEVEL >= 4
462 if (pixelFormat.palettizedB)
463 {
464 db_logf4(("\tchosen %u-bit palettized texture format",pixelFormat.bitsPerPixel));
465 }
466 else
467 {
468 if (pixelFormat.alphaB)
469 {
470 unsigned alpha_l_shft,alpha_r_shft;
471 SetBitShifts(&alpha_l_shft,&alpha_r_shft,pixelFormat.dwRGBAlphaBitMask);
472
473 db_logf4(("\tchosen %u-bit %u%u%u%u texture format",
474 pixelFormat.bitsPerPixel,
475 8U-pixelFormat.redRightShift,
476 8U-pixelFormat.greenRightShift,
477 8U-pixelFormat.blueRightShift,
478 8U-alpha_r_shft));
479 }
480 else
481 {
482 db_logf4(("\tchosen %u-bit %u%u%u texture format",
483 pixelFormat.bitsPerPixel,
484 8U-pixelFormat.redRightShift,
485 8U-pixelFormat.greenRightShift,
486 8U-pixelFormat.blueRightShift));
487 }
488 }
489 #endif
490 }
491 else
492 {
493 // use display surface format
494 pixelFormat = pfSurfaceFormat;
495
496 #endif
497 /* Just convert the texture to 32bpp */
498 // may want to support paletted textures
499 // at some point; at which point, should
500 // push texture conversion into the opengl layer
501 pixelFormat.palettizedB = 0;
502
503 pixelFormat.alphaB = 1;
504 pixelFormat.validB = 1;
505 pixelFormat.texB = 1;
506 pixelFormat.bitsPerPixel = 32;
507 pixelFormat.redLeftShift = 0;
508 pixelFormat.greenLeftShift = 8;
509 pixelFormat.blueLeftShift = 16;
510 pixelFormat.redRightShift = 0;
511 pixelFormat.greenRightShift = 0;
512 pixelFormat.blueRightShift = 0;
513 pixelFormat.dwRGBAlphaBitMask = 0xFF000000;
514 }
515 }
516
517 extern "C" {
518 extern int CreateOGLTexture(D3DTexture *, unsigned char *);
519 extern int CreateIMGSurface(D3DTexture *, unsigned char *);
520 };
521
CreateTexture(AwTl::CreateTextureParms const & _parmsR)522 AwTl::SurfUnion AwBackupTexture::CreateTexture(AwTl::CreateTextureParms const & _parmsR)
523 {
524 using namespace AwTl;
525
526 // which flags to use?
527 unsigned fMyFlags =
528 (_parmsR.flags & AW_TLF_PREVSRCALL) ? db_assert1(_parmsR.restoreH),
529 (_parmsR.flags & (AW_TLF_CHECKLOST|AW_TLF_SKIPNOTLOST)) | (m_fFlags & ~(AW_TLF_CHECKLOST|AW_TLF_SKIPNOTLOST))
530 : (_parmsR.flags & AW_TLF_PREVSRC) ? db_assert1(_parmsR.restoreH),
531 ((_parmsR.flags & ~AW_TLF_TRANSP) | (m_fFlags & AW_TLF_TRANSP))
532 : _parmsR.flags;
533
534 if (_parmsR.originalWidthP) *_parmsR.originalWidthP = m_nWidth;
535 if (_parmsR.originalHeightP) *_parmsR.originalHeightP = m_nHeight;
536
537 if (_parmsR.rectA != NULL) {
538 fprintf(stderr, "AwBackupTexture::CreateTexture - rectangle cutouts?\n");
539 }
540
541 if (pixelFormat.texB && (m_bTranspMask && (!pixelFormat.alphaB || fMyFlags & AW_TLF_CHROMAKEY))) {
542 fprintf(stderr, "AwBackupTexture::CreateTexture - chroma\n");
543 }
544
545 if (pixelFormat.texB && m_bTranspMask) {
546 //fprintf(stderr, "AwBackupTexture::CreateTexture - transparency\n");
547 }
548
549 // convert asset to 32-bit rgba
550 // may want to support paletted textures
551 // at some point; at which point, should
552 // push texture conversion into the opengl layer
553
554 unsigned char *buf = (unsigned char *)malloc(m_nWidth * m_nHeight * 4);
555
556 Colour * paletteP = m_nPaletteSize ? GetPalette() : NULL;
557
558 unsigned y = 0;
559 bool reversed_rowsB = AreRowsReversed();
560 if (reversed_rowsB)
561 {
562 y = m_nHeight-1;
563 }
564
565 for (int i = 0, rowcount = m_nHeight; rowcount; --rowcount, i++)
566 {
567 PtrUnion src_rowP = GetRowPtr(y);
568 db_assert1(src_rowP.voidP);
569
570 // allow loading of the next row from the file
571 LoadNextRow(src_rowP);
572
573 // loop for copying data to surfaces
574 {
575
576 {
577 // are we in the vertical range of this surface?
578 {
579
580 // convert and copy the section of the row to the direct draw surface
581 // ConvertRow(pLoadInfo->surface_dataP,pLoadInfo->surface_width,src_rowP,pLoadInfo->left,pLoadInfo->width,paletteP db_code1(DB_COMMA m_nPaletteSize));
582
583 PtrUnion my_data = &buf[y*m_nWidth*4];
584
585 ConvertRow(my_data,m_nWidth,src_rowP,0,m_nWidth,paletteP db_code1(DB_COMMA m_nPaletteSize));
586
587 }
588 }
589 }
590
591 // next row
592 if (reversed_rowsB)
593 --y;
594 else
595 ++y;
596
597 }
598
599 // convert to texture
600 D3DTexture *Tex = (D3DTexture *)calloc(1, sizeof(D3DTexture));
601
602 Tex->w = m_nWidth;
603 Tex->h = m_nHeight;
604 Tex->hasAlpha = m_bTranspMask;
605 Tex->hasChroma = m_fFlags & AW_TLF_CHROMAKEY;
606
607 if (pixelFormat.texB) {
608 CreateOGLTexture(Tex, buf);
609 } else {
610 CreateIMGSurface(Tex, buf);
611 }
612
613 return static_cast<SurfUnion>(Tex);
614
615 #if 0
616
617 // which flags to use?
618 unsigned fMyFlags =
619 _parmsR.flags & AW_TLF_PREVSRCALL ? db_assert1(_parmsR.restoreH),
620 _parmsR.flags & (AW_TLF_CHECKLOST|AW_TLF_SKIPNOTLOST) | m_fFlags & ~(AW_TLF_CHECKLOST|AW_TLF_SKIPNOTLOST)
621 : _parmsR.flags & AW_TLF_PREVSRC ? db_assert1(_parmsR.restoreH),
622 _parmsR.flags & ~AW_TLF_TRANSP | m_fFlags & AW_TLF_TRANSP
623 : _parmsR.flags;
624
625 db_code1(ULONG refcnt;)
626
627 DDPalette * dd_paletteP = NULL;
628 LoadInfo * arrLoadInfo = NULL;
629 unsigned nLoadInfos = 0;
630 {
631 // quick error check
632 if (pixelFormat.palettizedB && (!m_nPaletteSize || 1U<<pixelFormat.bitsPerPixel < m_nPaletteSize))
633 awTlLastErr = AW_TLE_CANTPALETTIZE;
634 if (!m_nHeight || !m_nWidth)
635 awTlLastErr = AW_TLE_BADFILEDATA;
636 if (AW_TLE_OK != awTlLastErr)
637 {
638 db_log1("AwCreateGraphic() failed whilst interpreting the header data or palette");
639 goto EXIT_WITH_ERROR;
640 }
641
642 if (_parmsR.originalWidthP) *_parmsR.originalWidthP = m_nWidth;
643 if (_parmsR.originalHeightP) *_parmsR.originalHeightP = m_nHeight;
644
645 if (_parmsR.rectA)
646 {
647 nLoadInfos = 0;
648 arrLoadInfo = _parmsR.numRects ? new LoadInfo[_parmsR.numRects] : NULL;
649 for (unsigned i=0; i<_parmsR.numRects; ++i)
650 {
651 _parmsR.rectA[i].width = 0;
652 _parmsR.rectA[i].height = 0;
653 if
654 (
655 _parmsR.rectA[i].top < m_nHeight
656 && _parmsR.rectA[i].left < m_nWidth
657 && (!_parmsR.prevTexB || (_parmsR.loadTextureB ? (_parmsR.rectA[i].pTexture != NULL) : (_parmsR.rectA[i].pSurface != NULL)))
658 && _parmsR.rectA[i].right > _parmsR.rectA[i].left
659 && _parmsR.rectA[i].bottom > _parmsR.rectA[i].top
660 )
661 {
662 // rectangle covers at least some of the image and non-null previous texture
663 arrLoadInfo[nLoadInfos].widthP = &_parmsR.rectA[i].width;
664 arrLoadInfo[nLoadInfos].heightP = &_parmsR.rectA[i].height;
665 if (_parmsR.prevTexB)
666 {
667 if (_parmsR.loadTextureB)
668 arrLoadInfo[nLoadInfos].prevTexP = _parmsR.rectA[i].pTexture;
669 else
670 arrLoadInfo[nLoadInfos].prevTexP = _parmsR.rectA[i].pSurface;
671 }
672 else
673 {
674 arrLoadInfo[nLoadInfos].prevTexP = static_cast<D3DTexture *>(NULL);
675 if (_parmsR.loadTextureB)
676 _parmsR.rectA[i].pTexture = NULL;
677 else
678 _parmsR.rectA[i].pSurface = NULL;
679 }
680
681 arrLoadInfo[nLoadInfos].rectP = &_parmsR.rectA[i];
682 arrLoadInfo[nLoadInfos].top = _parmsR.rectA[i].top;
683 arrLoadInfo[nLoadInfos].left = _parmsR.rectA[i].left;
684 arrLoadInfo[nLoadInfos].bottom = _parmsR.rectA[i].bottom;
685 arrLoadInfo[nLoadInfos].right = _parmsR.rectA[i].right;
686
687 if (arrLoadInfo[nLoadInfos].right > m_nWidth) arrLoadInfo[nLoadInfos].right = m_nWidth;
688 if (arrLoadInfo[nLoadInfos].bottom > m_nHeight) arrLoadInfo[nLoadInfos].bottom = m_nHeight;
689
690 arrLoadInfo[nLoadInfos].width = arrLoadInfo[nLoadInfos].right - arrLoadInfo[nLoadInfos].left;
691 arrLoadInfo[nLoadInfos].height = arrLoadInfo[nLoadInfos].bottom - arrLoadInfo[nLoadInfos].top;
692
693 ++nLoadInfos;
694 }
695 else
696 {
697 if (!_parmsR.prevTexB)
698 _parmsR.rectA[i].pTexture = NULL;
699 }
700 }
701 }
702 else
703 {
704 nLoadInfos = 1;
705 arrLoadInfo = new LoadInfo[1];
706 arrLoadInfo[0].widthP = _parmsR.widthP;
707 arrLoadInfo[0].heightP = _parmsR.heightP;
708 arrLoadInfo[0].prevTexP = _parmsR.prevTexP;
709 arrLoadInfo[0].rectP = NULL;
710 arrLoadInfo[0].top = 0;
711 arrLoadInfo[0].left = 0;
712 arrLoadInfo[0].bottom = m_nHeight;
713 arrLoadInfo[0].right = m_nWidth;
714 arrLoadInfo[0].width = m_nWidth;
715 arrLoadInfo[0].height = m_nHeight;
716 }
717
718 bool bSkipAll = true;
719
720 // loop creating surfaces
721 {for (unsigned i=0; i<nLoadInfos; ++i)
722 {
723 LoadInfo * pLoadInfo = &arrLoadInfo[i];
724
725 db_logf4(("\trectangle from image (%u,%u)-(%u,%u)",pLoadInfo->left,pLoadInfo->top,pLoadInfo->right,pLoadInfo->bottom));
726 db_logf5(("\treference count on input surface %u",_parmsR.loadTextureB ? GetRefCount(pLoadInfo->prevTexP.textureP) : GetRefCount(pLoadInfo->prevTexP.surfaceP)));
727
728 // determine what the width and height of the surface will be
729
730 if (_parmsR.loadTextureB || fMyFlags & AW_TLF_TEXTURE)
731 {
732 awTlLastErr =
733 AwGetTextureSize
734 (
735 &pLoadInfo->surface_width,
736 &pLoadInfo->surface_height,
737 fMyFlags & AW_TLF_MINSIZE && pLoadInfo->rectP ? pLoadInfo->rectP->right - pLoadInfo->rectP->left : pLoadInfo->width,
738 fMyFlags & AW_TLF_MINSIZE && pLoadInfo->rectP ? pLoadInfo->rectP->bottom - pLoadInfo->rectP->top : pLoadInfo->height
739 );
740 if (awTlLastErr != AW_TLE_OK)
741 goto EXIT_WITH_ERROR;
742 }
743 else
744 {
745 pLoadInfo->surface_width = fMyFlags & AW_TLF_MINSIZE && pLoadInfo->rectP ? pLoadInfo->rectP->right - pLoadInfo->rectP->left : pLoadInfo->width;
746 pLoadInfo->surface_height = fMyFlags & AW_TLF_MINSIZE && pLoadInfo->rectP ? pLoadInfo->rectP->bottom - pLoadInfo->rectP->top : pLoadInfo->height;
747 #if 1 // not sure if this is required...
748 pLoadInfo->surface_width += 3;
749 pLoadInfo->surface_width &= ~3;
750 pLoadInfo->surface_height += 3;
751 pLoadInfo->surface_height &= ~3;
752 #endif
753 }
754
755 if (pLoadInfo->widthP) *pLoadInfo->widthP = pLoadInfo->surface_width;
756 if (pLoadInfo->heightP) *pLoadInfo->heightP = pLoadInfo->surface_height;
757
758 // Create DD Surface
759
760 DD_SURFACE_DESC ddsd;
761 INITDXSTRUCT(ddsd);
762 ddsd.ddpfPixelFormat = pixelFormat.ddpf;
763 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
764 if (_parmsR.loadTextureB || fMyFlags & AW_TLF_TEXTURE)
765 pLoadInfo->dwCapsCaps = DDSCAPS_TEXTURE | (fMyFlags & (AW_TLF_COMPRESS|AW_TLF_TEXTURE) ? DDSCAPS_SYSTEMMEMORY : driverDesc.memFlag);
766 else
767 pLoadInfo->dwCapsCaps = DDSCAPS_OFFSCREENPLAIN | (fMyFlags & AW_TLF_VIDMEM ? DDSCAPS_VIDEOMEMORY : DDSCAPS_SYSTEMMEMORY);
768 ddsd.ddsCaps.dwCaps = pLoadInfo->dwCapsCaps;
769 ddsd.dwHeight = pLoadInfo->surface_height;
770 ddsd.dwWidth = pLoadInfo->surface_width;
771
772 if (pLoadInfo->prevTexP.voidP && (!_parmsR.loadTextureB || !(fMyFlags & AW_TLF_COMPRESS)))
773 {
774 if (_parmsR.loadTextureB)
775 awTlLastDxErr = pLoadInfo->prevTexP.textureP->QueryInterface(GUID_DD_SURFACE,(LPVOID *)&pLoadInfo->surfaceP);
776 else
777 awTlLastDxErr = pLoadInfo->prevTexP.surfaceP->QueryInterface(GUID_DD_SURFACE,(LPVOID *)&pLoadInfo->surfaceP);
778 HANDLE_DXERROR("getting direct draw surface interface")
779 #if DB_LEVEL >= 5
780 if (_parmsR.loadTextureB)
781 db_logf5(("\t\tnow prev tex ref %u new surface i/f ref %u",GetRefCount(pLoadInfo->prevTexP.textureP),GetRefCount(pLoadInfo->surfaceP)));
782 else
783 db_logf5(("\t\tnow prev surf ref %u new surface i/f ref %u",GetRefCount(pLoadInfo->prevTexP.surfaceP),GetRefCount(pLoadInfo->surfaceP)));
784 #endif
785
786 // check for lost surfaces
787 if (fMyFlags & AW_TLF_CHECKLOST)
788 {
789 awTlLastDxErr = pLoadInfo->surfaceP->IsLost();
790
791 if (DDERR_SURFACELOST == awTlLastDxErr)
792 {
793 db_log4("\tRestoring Lost Surface");
794
795 awTlLastDxErr = pLoadInfo->surfaceP->Restore();
796 }
797 else if (DD_OK == awTlLastDxErr && (fMyFlags & AW_TLF_SKIPNOTLOST))
798 {
799 db_log4("\tSkipping Surface which was not Lost");
800
801 pLoadInfo->skipB = true;
802 }
803
804 HANDLE_DXERROR("testing for lost surface and restoring if necessary");
805 }
806
807 if (!pLoadInfo->skipB)
808 {
809 // check that the surface desc is OK
810 // note that SetSurfaceDesc is *only* supported for changing the surface memory pointer
811 DD_SURFACE_DESC old_ddsd;
812 INITDXSTRUCT(old_ddsd);
813 awTlLastDxErr = pLoadInfo->surfaceP->GetSurfaceDesc(&old_ddsd);
814 HANDLE_DXERROR("getting previous surface desc")
815 // check width, height, RGBBitCount and memory type
816 if (old_ddsd.dwFlags & DDSD_ALL || (old_ddsd.dwFlags & (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT)) == (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT))
817 {
818 if (old_ddsd.dwHeight == pLoadInfo->surface_height && old_ddsd.dwWidth == pLoadInfo->surface_width && (old_ddsd.ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY|DDSCAPS_VIDEOMEMORY|DDSCAPS_TEXTURE)) == pLoadInfo->dwCapsCaps)
819 {
820 unsigned bpp = 0;
821 if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
822 bpp = 8;
823 else if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4)
824 bpp = 4;
825 else if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED2)
826 bpp = 2;
827 else if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED1)
828 bpp = 1;
829 else if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_RGB)
830 bpp = old_ddsd.ddpfPixelFormat.dwRGBBitCount;
831 if (pixelFormat.bitsPerPixel != bpp)
832 awTlLastErr = AW_TLE_CANTRELOAD;
833 }
834 else
835 awTlLastErr = AW_TLE_CANTRELOAD;
836 }
837 else
838 awTlLastErr = AW_TLE_CANTRELOAD;
839 if (AW_TLE_OK != awTlLastErr)
840 {
841 db_log1("AwCreateGraphic() failed because existing surface is incompatible");
842 goto EXIT_WITH_ERROR;
843 }
844 }
845 else
846 {
847 pLoadInfo->surfaceP->Release();
848 pLoadInfo->surfaceP = NULL;
849 }
850 }
851 else
852 {
853 if (pLoadInfo->prevTexP.voidP && (fMyFlags & AW_TLF_CHECKLOST))
854 {
855 db_assert1(_parmsR.loadTextureB);
856
857 awTlLastDxErr = pLoadInfo->prevTexP.textureP->QueryInterface(GUID_DD_SURFACE,(LPVOID *)&pLoadInfo->surfaceP);
858 HANDLE_DXERROR("getting direct draw surface interface")
859
860 db_logf5(("\t\tnow prev tex ref %u new surface i/f ref %u",GetRefCount(pLoadInfo->prevTexP.textureP),GetRefCount(pLoadInfo->surfaceP)));
861
862 awTlLastDxErr = pLoadInfo->surfaceP->IsLost();
863
864 if (DDERR_SURFACELOST == awTlLastDxErr)
865 {
866 db_log4("\tRestoring Lost Surface");
867
868 awTlLastDxErr = pLoadInfo->surfaceP->Restore();
869 }
870 else if (DD_OK == awTlLastDxErr && (fMyFlags & AW_TLF_SKIPNOTLOST))
871 {
872 db_log4("\tSkipping Surface which was not Lost");
873
874 pLoadInfo->skipB = true;
875 }
876
877 HANDLE_DXERROR("testing for lost surface and restoring if necessary");
878
879 pLoadInfo->surfaceP->Release();
880 pLoadInfo->surfaceP = NULL;
881 }
882
883 if (!pLoadInfo->skipB)
884 {
885 do
886 {
887 awTlLastDxErr = driverDesc.ddP->CreateSurface(&ddsd,&pLoadInfo->surfaceP,NULL);
888 }
889 while
890 (
891 DDERR_OUTOFVIDEOMEMORY == awTlLastDxErr
892 && _parmsR.callbackF
893 && _parmsR.callbackF(_parmsR.callbackParam)
894 );
895
896 HANDLE_DXERROR("creating direct draw surface")
897 }
898 }
899
900 if (pLoadInfo->skipB)
901 {
902 db_assert1(pLoadInfo->prevTexP.voidP);
903
904 // skipping so result is same as input
905 pLoadInfo->resultP = pLoadInfo->prevTexP;
906
907 if (_parmsR.loadTextureB)
908 pLoadInfo->prevTexP.textureP->AddRef();
909 else
910 pLoadInfo->prevTexP.surfaceP->AddRef();
911 }
912
913 bSkipAll = bSkipAll && pLoadInfo->skipB;
914 }}
915
916 if (!bSkipAll)
917 {
918 Colour * paletteP = m_nPaletteSize ? GetPalette() : NULL;
919
920 unsigned y = 0;
921 bool reversed_rowsB = AreRowsReversed();
922 if (reversed_rowsB)
923 {
924 y = m_nHeight-1;
925 }
926
927 for (unsigned rowcount = m_nHeight; rowcount; --rowcount)
928 {
929 PtrUnion src_rowP = GetRowPtr(y);
930 db_assert1(src_rowP.voidP);
931
932 // allow loading of the next row from the file
933 LoadNextRow(src_rowP);
934
935 // loop for copying data to surfaces
936 for (unsigned i=0; i<nLoadInfos; ++i)
937 {
938 LoadInfo * pLoadInfo = &arrLoadInfo[i];
939
940 if (!pLoadInfo->skipB)
941 {
942 // are we in the vertical range of this surface?
943 if (y>=pLoadInfo->top && y<pLoadInfo->bottom)
944 {
945 if (!pLoadInfo->surface_lockedB)
946 {
947 // lock the surfaces
948 DD_SURFACE_DESC ddsd;
949 INITDXSTRUCT(ddsd);
950 awTlLastDxErr = pLoadInfo->surfaceP->Lock(NULL,&ddsd,DDLOCK_WRITEONLY|DDLOCK_NOSYSLOCK,NULL);
951 HANDLE_DXERROR("locking direct draw surface")
952 pLoadInfo->surface_lockedB = true;
953 pLoadInfo->surface_dataP.voidP = ddsd.lpSurface;
954 pLoadInfo->surface_dataP.byteP += ddsd.lPitch * (y-pLoadInfo->top);
955 pLoadInfo->surface_pitch = ddsd.lPitch;
956 }
957
958 // convert and copy the section of the row to the direct draw surface
959 ConvertRow(pLoadInfo->surface_dataP,pLoadInfo->surface_width,src_rowP,pLoadInfo->left,pLoadInfo->width,paletteP db_code1(DB_COMMA m_nPaletteSize));
960
961 // do the bottom row twice if the dd surface is bigger
962 if (pLoadInfo->bottom-1 == y && pLoadInfo->surface_height > pLoadInfo->height)
963 {
964 PtrUnion next_surface_rowP = pLoadInfo->surface_dataP;
965 next_surface_rowP.byteP += pLoadInfo->surface_pitch;
966 ConvertRow(next_surface_rowP,pLoadInfo->surface_width,src_rowP,pLoadInfo->left,pLoadInfo->width,paletteP db_code1(DB_COMMA m_nPaletteSize));
967 }
968
969 // next ddsurface row
970 if (reversed_rowsB)
971 pLoadInfo->surface_dataP.byteP -= pLoadInfo->surface_pitch;
972 else
973 pLoadInfo->surface_dataP.byteP += pLoadInfo->surface_pitch;
974 }
975 else if (pLoadInfo->surface_lockedB)
976 {
977 // unlock the surface
978 awTlLastDxErr = pLoadInfo->surfaceP->Unlock(NULL);
979 HANDLE_DXERROR("unlocking direct draw surface")
980 pLoadInfo->surface_lockedB = false;
981 }
982 }
983 }
984
985 // next row
986 if (reversed_rowsB)
987 --y;
988 else
989 ++y;
990
991 if (AW_TLE_OK != awTlLastErr)
992 {
993 db_log1("AwCreateGraphic() failed whilst copying data to direct draw surface");
994 goto EXIT_WITH_ERROR;
995 }
996 }
997
998 // create a palette for the surfaces if there is one
999 DWORD palcreateflags = 0;
1000 PALETTEENTRY colour_tableA[256];
1001 if (pixelFormat.palettizedB)
1002 {
1003 if (!_parmsR.loadTextureB && !(fMyFlags & AW_TLF_TEXTURE))
1004 {
1005 db_log3("AwCreateGraphic(): WARNING: setting a palette on a DD surface may have no effect");
1006 }
1007
1008 #if 0
1009 if (m_bTranspMask)
1010 {
1011 colour_tableA[0].peRed = 0;
1012 colour_tableA[0].peGreen = 0;
1013 colour_tableA[0].peBlue = 0;
1014 colour_tableA[0].peFlags = 0;
1015 for (unsigned i=1; i<m_nPaletteSize; ++i)
1016 {
1017 colour_tableA[i].peRed = paletteP[i].r;
1018 colour_tableA[i].peGreen = paletteP[i].g;
1019 colour_tableA[i].peBlue = paletteP[i].b;
1020 if (!(paletteP[i].r + paletteP[i].g + paletteP[i].b))
1021 colour_tableA[i].peRed = 1;
1022 colour_tableA[i].peFlags = 0;
1023 }
1024 }
1025 else
1026 #endif
1027 {
1028 for (unsigned i=0; i<m_nPaletteSize; ++i)
1029 {
1030 colour_tableA[i].peRed = paletteP[i].r;
1031 colour_tableA[i].peGreen = paletteP[i].g;
1032 colour_tableA[i].peBlue = paletteP[i].b;
1033 colour_tableA[i].peFlags = 0;
1034 }
1035 }
1036 for (unsigned i=m_nPaletteSize; i<256; ++i)
1037 colour_tableA[i].peFlags = 0;
1038 switch (pixelFormat.bitsPerPixel)
1039 {
1040 default:
1041 CANT_HAPPEN
1042 case 8:
1043 palcreateflags = DDPCAPS_8BIT | DDPCAPS_ALLOW256;
1044 break;
1045 case 4:
1046 palcreateflags = DDPCAPS_4BIT;
1047 break;
1048 case 2:
1049 palcreateflags = DDPCAPS_2BIT;
1050 break;
1051 case 1:
1052 palcreateflags = DDPCAPS_1BIT;
1053 break;
1054 }
1055 awTlLastDxErr = driverDesc.ddP->CreatePalette(palcreateflags,colour_tableA,&dd_paletteP,NULL);
1056 HANDLE_DXERROR("creating palette for direct draw surface")
1057 }
1058
1059 {for (unsigned i=0; i<nLoadInfos; ++i)
1060 {
1061 LoadInfo * pLoadInfo = &arrLoadInfo[i];
1062
1063 if (!pLoadInfo->skipB)
1064 {
1065 // unlock the surface
1066 if (pLoadInfo->surface_lockedB)
1067 {
1068 awTlLastDxErr = pLoadInfo->surfaceP->Unlock(NULL);
1069 HANDLE_DXERROR("unlocking direct draw surface")
1070 pLoadInfo->surface_lockedB = false;
1071 }
1072
1073 if (pixelFormat.palettizedB)
1074 {
1075 // set the palette on the surface
1076 awTlLastDxErr = pLoadInfo->surfaceP->SetPalette(dd_paletteP);
1077 HANDLE_DXERROR("setting palette on direct draw surface")
1078 }
1079 }
1080
1081 }}
1082
1083 if (pixelFormat.palettizedB)
1084 {
1085 db_logf5(("\tabout to release palette with ref %u",GetRefCount(dd_paletteP)));
1086 dd_paletteP->Release();
1087 dd_paletteP = NULL;
1088 }
1089
1090 DWORD dwColourKey;
1091 DDCOLORKEY invis;
1092 // get colour for chroma keying if required
1093 if (m_bTranspMask && (!pixelFormat.alphaB || fMyFlags & AW_TLF_CHROMAKEY))
1094 {
1095 dwColourKey = GetTransparentColour();
1096 invis.dwColorSpaceLowValue = dwColourKey;
1097 invis.dwColorSpaceHighValue = dwColourKey;
1098 }
1099
1100 {for (unsigned i=0; i<nLoadInfos; ++i)
1101 {
1102 LoadInfo * pLoadInfo = &arrLoadInfo[i];
1103
1104 if (!pLoadInfo->skipB)
1105 {
1106 // do the copying crap and Texture::Load() stuff - see CopyD3DTexture in d3_func.cpp
1107
1108 if (_parmsR.loadTextureB)
1109 {
1110 // get a texture pointer
1111 awTlLastDxErr = pLoadInfo->surfaceP->QueryInterface(GUID_D3D_TEXTURE,(LPVOID *)&pLoadInfo->textureP);
1112 HANDLE_DXERROR("getting texture interface on direct draw surface")
1113 db_logf5(("\t\tnow surface ref %u texture ref %u",GetRefCount(pLoadInfo->surfaceP),GetRefCount(pLoadInfo->textureP)));
1114
1115 if (fMyFlags & AW_TLF_COMPRESS) // deal with Texture::Load and ALLOCONLOAD flag
1116 {
1117 if (pLoadInfo->prevTexP.voidP)
1118 {
1119 // load into the existing texture
1120 awTlLastDxErr = pLoadInfo->prevTexP.textureP->QueryInterface(GUID_DD_SURFACE,(LPVOID *)&pLoadInfo->dst_surfaceP);
1121 HANDLE_DXERROR("getting direct draw surface interface")
1122 db_logf5(("\t\tnow prev texture ref %u dst surface ref %u",GetRefCount(pLoadInfo->prevTexP.textureP),GetRefCount(pLoadInfo->dst_surfaceP)));
1123 // check that the surface desc is OK
1124 // note that SetSurfaceDesc is *only* supported for changing the surface memory pointer
1125 DD_SURFACE_DESC old_ddsd;
1126 INITDXSTRUCT(old_ddsd);
1127 awTlLastDxErr = pLoadInfo->surfaceP->GetSurfaceDesc(&old_ddsd);
1128 HANDLE_DXERROR("getting previous surface desc")
1129 // check width, height, RGBBitCount and memory type
1130 if (old_ddsd.dwFlags & DDSD_ALL || (old_ddsd.dwFlags & (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT)) == (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT))
1131 {
1132 if (old_ddsd.dwHeight == pLoadInfo->surface_height && old_ddsd.dwWidth == pLoadInfo->surface_width && (old_ddsd.ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY|DDSCAPS_VIDEOMEMORY|DDSCAPS_TEXTURE)) == pLoadInfo->dwCapsCaps)
1133 {
1134 unsigned bpp = 0;
1135 if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
1136 bpp = 8;
1137 else if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4)
1138 bpp = 4;
1139 else if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED2)
1140 bpp = 2;
1141 else if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED1)
1142 bpp = 1;
1143 else if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_RGB)
1144 bpp = old_ddsd.ddpfPixelFormat.dwRGBBitCount;
1145 if (pixelFormat.bitsPerPixel != bpp)
1146 awTlLastErr = AW_TLE_CANTRELOAD;
1147 }
1148 else
1149 awTlLastErr = AW_TLE_CANTRELOAD;
1150 }
1151 else
1152 awTlLastErr = AW_TLE_CANTRELOAD;
1153 if (AW_TLE_OK != awTlLastErr)
1154 {
1155 db_log1("AwCreateGraphic() failed because existing surface is incompatible");
1156 goto EXIT_WITH_ERROR;
1157 }
1158 }
1159 else
1160 {
1161 DD_SURFACE_DESC ddsd;
1162
1163 INITDXSTRUCT(ddsd);
1164
1165 awTlLastDxErr = pLoadInfo->surfaceP->GetSurfaceDesc(&ddsd);
1166 HANDLE_DXERROR("getting direct draw surface desc")
1167
1168 ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
1169 ddsd.ddsCaps.dwCaps |= DDSCAPS_ALLOCONLOAD | driverDesc.memFlag;
1170 do
1171 {
1172 awTlLastDxErr = driverDesc.ddP->CreateSurface(&ddsd,&pLoadInfo->dst_surfaceP,NULL);
1173 }
1174 while
1175 (
1176 DDERR_OUTOFVIDEOMEMORY == awTlLastDxErr
1177 && _parmsR.callbackF
1178 && _parmsR.callbackF(_parmsR.callbackParam)
1179 );
1180 HANDLE_DXERROR("creating destination direct draw surface")
1181 }
1182
1183 // create a zero palette if required -> Texture::Load() will copy in correct palette
1184 if (pixelFormat.palettizedB)
1185 {
1186 memset(colour_tableA,0,sizeof colour_tableA);
1187
1188 awTlLastDxErr = driverDesc.ddP->CreatePalette(palcreateflags,colour_tableA,&dd_paletteP,NULL);
1189 HANDLE_DXERROR("creating palette for destination direct draw surface")
1190 awTlLastDxErr = pLoadInfo->dst_surfaceP->SetPalette(dd_paletteP);
1191 HANDLE_DXERROR("setting palette on destination direct draw surface")
1192 db_logf5(("\tabout to release dest palette with ref %u",GetRefCount(dd_paletteP)));
1193 dd_paletteP->Release();
1194 dd_paletteP = NULL;
1195 }
1196
1197 // get a texture pointer on the destination
1198 awTlLastDxErr = pLoadInfo->dst_surfaceP->QueryInterface(GUID_D3D_TEXTURE,(LPVOID *)&pLoadInfo->dst_textureP);
1199 HANDLE_DXERROR("getting texture interface on destination direct draw surface")
1200 db_logf5(("\t\tnow dst surface ref %u dst texture ref %u",GetRefCount(pLoadInfo->dst_surfaceP),GetRefCount(pLoadInfo->dst_textureP)));
1201
1202 do
1203 {
1204 awTlLastDxErr = pLoadInfo->dst_textureP->Load(pLoadInfo->textureP);
1205 }
1206 while
1207 (
1208 DDERR_OUTOFVIDEOMEMORY == awTlLastDxErr
1209 && _parmsR.callbackF
1210 && _parmsR.callbackF(_parmsR.callbackParam)
1211 );
1212 HANDLE_DXERROR("loading texture into destination")
1213
1214 // release src texture and surface, and set pointers to point to dst texture and surface
1215 db_logf5(("\tabout to release internal surface with ref %u",GetRefCount(pLoadInfo->surfaceP)));
1216 db_code1(refcnt =)
1217 pLoadInfo->surfaceP->Release();
1218 db_onlyassert1(1==refcnt);
1219 pLoadInfo->surfaceP = pLoadInfo->dst_surfaceP;
1220 pLoadInfo->dst_surfaceP = NULL;
1221
1222 db_logf5(("\tabout to release internal texture i/f with ref %u",GetRefCount(pLoadInfo->textureP)));
1223 db_code1(refcnt =)
1224 pLoadInfo->textureP->Release();
1225 db_onlyassert1(!refcnt);
1226 pLoadInfo->textureP = pLoadInfo->dst_textureP;
1227 pLoadInfo->dst_textureP = NULL;
1228 }
1229 }
1230
1231 // set chroma keying if required
1232 if (m_bTranspMask && (!pixelFormat.alphaB || fMyFlags & AW_TLF_CHROMAKEY))
1233 {
1234 awTlLastDxErr = pLoadInfo->surfaceP->SetColorKey(DDCKEY_SRCBLT,&invis);
1235 HANDLE_DXERROR("setting the colour key")
1236 }
1237
1238 if (_parmsR.loadTextureB)
1239 {
1240 // release the direct draw interface:
1241 // since the textureP was obtained with a call
1242 // to QueryInterface on the surface (increasing
1243 // its referenc count), this wont actually release
1244 // the surface
1245
1246 db_logf5(("\tabout to release surface i/f with ref %u",GetRefCount(pLoadInfo->surfaceP)));
1247 db_code1(refcnt =)
1248 pLoadInfo->surfaceP->Release();
1249 pLoadInfo->surfaceP = NULL;
1250 // if loading into a previous texture, refcnt may be two or more, our ref and the ref passed to us
1251 db_onlyassert1(1==refcnt|| pLoadInfo->prevTexP.voidP);
1252
1253 pLoadInfo->resultP = pLoadInfo->textureP;
1254 }
1255 else
1256 {
1257 db_assert1(pLoadInfo->surfaceP);
1258
1259 DDSurface * pSurfaceReturn = NULL;
1260
1261 awTlLastDxErr = pLoadInfo->surfaceP->QueryInterface(GUID_DD_SURFACE, (LPVOID *)&pSurfaceReturn);
1262 HANDLE_DXERROR("getting the required DDSurface interface")
1263 db_logf5(("\t\tnow surface ref %u return surface ref %u",GetRefCount(pLoadInfo->surfaceP),GetRefCount(pSurfaceReturn)));
1264
1265 pLoadInfo->resultP = pSurfaceReturn;
1266 }
1267 }
1268 }}
1269
1270 // release the IDirectDrawSurface interfaces if returning DDSurface interfaces
1271 if (!_parmsR.loadTextureB)
1272 {
1273 for (unsigned i=0; i<nLoadInfos; ++i)
1274 {
1275 if (!arrLoadInfo[i].skipB)
1276 {
1277 db_assert1(arrLoadInfo[i].surfaceP);
1278 db_logf5(("\tabout to release internal surface i/f with ref %u",GetRefCount(arrLoadInfo[i].surfaceP)));
1279 arrLoadInfo[i].surfaceP->Release();
1280 }
1281 }
1282 }
1283 }
1284
1285 // OK
1286 db_log4("AwCreateGraphic() OK");
1287
1288 SurfUnion pRet = static_cast<D3DTexture *>(NULL);
1289
1290 if (!_parmsR.rectA)
1291 {
1292 // if loading the entire graphic as one surface/texture, return pointer to that
1293 pRet = arrLoadInfo[0].resultP;
1294 }
1295 else
1296 {
1297 // return NULL, but fill in the pTexture or pSurface members of the AwCreateGraphicRegion
1298 for (unsigned i=0; i<nLoadInfos; ++i)
1299 {
1300 LoadInfo * pLoadInfo = &arrLoadInfo[i];
1301
1302 db_assert1(pLoadInfo->rectP);
1303
1304 if (_parmsR.loadTextureB)
1305 {
1306 if (pLoadInfo->prevTexP.voidP)
1307 {
1308 db_assert1(pLoadInfo->prevTexP.textureP == pLoadInfo->rectP->pTexture);
1309 db_assert1(pLoadInfo->resultP.textureP == pLoadInfo->rectP->pTexture);
1310 db_logf5(("\tabout to release duplicate texture i/f with ref %u",GetRefCount(pLoadInfo->resultP.textureP)));
1311 pLoadInfo->resultP.textureP->Release();
1312 }
1313 else
1314 {
1315 pLoadInfo->rectP->pTexture = pLoadInfo->resultP.textureP;
1316 }
1317 db_logf5(("\tresultant texture for region with ref count %u",GetRefCount(pLoadInfo->rectP->pTexture)));
1318 }
1319 else
1320 {
1321 if (pLoadInfo->prevTexP.voidP)
1322 {
1323 db_assert1(pLoadInfo->prevTexP.surfaceP == pLoadInfo->rectP->pSurface);
1324 db_assert1(pLoadInfo->resultP.surfaceP == pLoadInfo->rectP->pSurface);
1325 db_logf5(("\tabout to release duplicate surface i/f with ref %u",GetRefCount(pLoadInfo->resultP.surfaceP)));
1326 pLoadInfo->resultP.surfaceP->Release();
1327 }
1328 else
1329 {
1330 pLoadInfo->rectP->pSurface = pLoadInfo->resultP.surfaceP;
1331 }
1332 db_logf5(("\tresultant texture for surface with ref count %u",GetRefCount(pLoadInfo->rectP->pSurface)));
1333 }
1334 }
1335 }
1336 delete[] arrLoadInfo;
1337
1338 #if DB_LEVEL >= 5
1339 if (_parmsR.loadTextureB)
1340 db_logf5(("AwCreateGraphic(): returning texture with ref cnt %u",GetRefCount(pRet.textureP)));
1341 else
1342 db_logf5(("AwCreateGraphic(): returning surface with ref cnt %u",GetRefCount(pRet.surfaceP)));
1343 #endif
1344
1345 return pRet;
1346 }
1347
1348 EXIT_WITH_ERROR:
1349 {
1350
1351 db_logf2(("AwCreateGraphic(): ERROR: %s",AwTlErrorToString()));
1352
1353 if (arrLoadInfo)
1354 {
1355 for (unsigned i=0; i<nLoadInfos; ++i)
1356 {
1357 LoadInfo * pLoadInfo = &arrLoadInfo[i];
1358
1359 db_logf5(("\tref counts: dst tex %u dst surf %u int tex %u int surf %u",
1360 GetRefCount(pLoadInfo->dst_textureP),
1361 GetRefCount(pLoadInfo->dst_surfaceP),
1362 GetRefCount(pLoadInfo->textureP),
1363 GetRefCount(pLoadInfo->surfaceP)));
1364
1365 if (pLoadInfo->dst_textureP)
1366 {
1367 pLoadInfo->dst_textureP->Release();
1368 }
1369 if (pLoadInfo->textureP)
1370 {
1371 pLoadInfo->textureP->Release();
1372 }
1373 if (pLoadInfo->dst_surfaceP)
1374 {
1375 pLoadInfo->dst_surfaceP->Release();
1376 }
1377 if (pLoadInfo->surfaceP)
1378 {
1379 if (pLoadInfo->surface_lockedB)
1380 pLoadInfo->surfaceP->Unlock(NULL);
1381 db_code1(refcnt =)
1382 pLoadInfo->surfaceP->Release();
1383 db_onlyassert1(!refcnt);
1384 }
1385
1386 if (pLoadInfo->rectP)
1387 {
1388 pLoadInfo->rectP->width = 0;
1389 pLoadInfo->rectP->height = 0;
1390 }
1391 }
1392
1393 delete[] arrLoadInfo;
1394 }
1395
1396 if (dd_paletteP)
1397 {
1398 db_code1(refcnt =)
1399 dd_paletteP->Release();
1400 db_onlyassert1(!refcnt);
1401 }
1402
1403 return static_cast<D3DTexture *>(NULL);
1404 }
1405 #endif
1406 }
1407
OnBeginRestoring(unsigned nMaxPaletteSize)1408 void AwBackupTexture::OnBeginRestoring(unsigned nMaxPaletteSize)
1409 {
1410 if (nMaxPaletteSize && (nMaxPaletteSize < m_nPaletteSize || !m_nPaletteSize))
1411 {
1412 awTlLastErr = AW_TLE_CANTPALETTIZE;
1413 db_logf3(("AwCreateGraphic(): [restoring] ERROR: Palette size is %u, require %u",m_nPaletteSize,nMaxPaletteSize));
1414 }
1415 }
1416
AreRowsReversed()1417 bool AwBackupTexture::AreRowsReversed()
1418 {
1419 return false;
1420 }
1421
ConvertRow(AwTl::PtrUnion pDest,unsigned nDestWidth,AwTl::PtrUnionConst pSrc,unsigned nSrcOffset,unsigned nSrcWidth,AwTl::Colour * pPalette db_code1 (DB_COMMA unsigned nPaletteSize))1422 void AwBackupTexture::ConvertRow(AwTl::PtrUnion pDest, unsigned nDestWidth, AwTl::PtrUnionConst pSrc, unsigned nSrcOffset, unsigned nSrcWidth, AwTl::Colour * pPalette db_code1(DB_COMMA unsigned nPaletteSize))
1423 {
1424 using namespace AwTl;
1425
1426 if (pPalette)
1427 {
1428 if (pixelFormat.palettizedB)
1429 {
1430 GenericConvertRow<Colour::ConvNull,BYTE>::Do(pDest,nDestWidth,pSrc.byteP+nSrcOffset,nSrcWidth);
1431 }
1432 else
1433 {
1434 if (m_bTranspMask)
1435 GenericConvertRow<Colour::ConvTransp,BYTE>::Do(pDest,nDestWidth,pSrc.byteP+nSrcOffset,nSrcWidth,pPalette db_code1(DB_COMMA nPaletteSize));
1436 else
1437 GenericConvertRow<Colour::ConvNonTransp,BYTE>::Do(pDest,nDestWidth,pSrc.byteP+nSrcOffset,nSrcWidth,pPalette db_code1(DB_COMMA nPaletteSize));
1438 }
1439 }
1440 else
1441 {
1442 if (m_bTranspMask)
1443 GenericConvertRow<Colour::ConvTransp,Colour>::Do(pDest,nDestWidth,pSrc.colourP+nSrcOffset,nSrcWidth);
1444 else
1445 GenericConvertRow<Colour::ConvNonTransp,Colour>::Do(pDest,nDestWidth,pSrc.colourP+nSrcOffset,nSrcWidth);
1446 }
1447 }
1448
OnFinishRestoring(bool)1449 void AwBackupTexture::OnFinishRestoring(bool)
1450 {
1451 }
1452
1453 namespace AwTl {
1454
GetPalette()1455 Colour * TypicalBackupTexture::GetPalette()
1456 {
1457 return m_pPalette;
1458 }
1459
GetRowPtr(unsigned nRow)1460 PtrUnion TypicalBackupTexture::GetRowPtr(unsigned nRow)
1461 {
1462 return m_ppPixMap[nRow];
1463 }
1464
LoadNextRow(PtrUnion)1465 void TypicalBackupTexture::LoadNextRow(PtrUnion)
1466 {
1467 // already loaded
1468 }
1469
GetNumColours()1470 unsigned TypicalBackupTexture::GetNumColours()
1471 {
1472 return m_nPaletteSize;
1473 }
1474
GetMinPaletteSize()1475 unsigned TypicalBackupTexture::GetMinPaletteSize()
1476 {
1477 return m_nPaletteSize;
1478 }
1479
1480
Load(MediaMedium * pMedium,CreateTextureParms const & rParams)1481 SurfUnion TexFileLoader::Load(MediaMedium * pMedium, CreateTextureParms const & rParams)
1482 {
1483 m_fFlags = rParams.flags;
1484
1485 awTlLastErr = AW_TLE_OK;
1486
1487 LoadHeaderInfo(pMedium);
1488
1489 // CHECK_MEDIA_ERRORS("loading file headers")
1490 ON_ERROR_RETURN_NULL("loading file headers")
1491
1492 ChoosePixelFormat(rParams);
1493 #if 0
1494 if (!pixelFormat.validB)
1495 db_log3("AwCreateGraphic(): ERROR: pixel format not valid");
1496 if (!driverDesc.ddP || !driverDesc.validB && rParams.loadTextureB)
1497 db_log3("AwCreateGraphic(): ERROR: driver description not valid");
1498
1499 awTlLastErr = pixelFormat.validB && driverDesc.ddP && (driverDesc.validB || !rParams.loadTextureB) ? AW_TLE_OK : AW_TLE_NOINIT;
1500
1501 ON_ERROR_RETURN_NULL("initializing load")
1502 #endif
1503 // fprintf(stderr, "TexFileLoader::Load Pixel Format?! It's not implemented!\n");
1504
1505 /* TODO */
1506 AllocateBuffers(/* rParams.backupHP ? true : */ false, /* pixelFormat.palettizedB ? ? 1<<pixelFormat.bitsPerPixel : */ 0);
1507
1508 // CHECK_MEDIA_ERRORS("allocating buffers")
1509 ON_ERROR_RETURN_NULL("allocating buffers")
1510
1511 db_logf4(("\tThe image in the file is %ux%u with %u %spalette",m_nWidth,m_nHeight,m_nPaletteSize ? m_nPaletteSize : 0,m_nPaletteSize ? "colour " : ""));
1512
1513 SurfUnion pTex = CreateTexture(rParams);
1514
1515 bool bOK = AW_TLE_OK == awTlLastErr;
1516
1517 // CHECK_MEDIA_ERRORS("loading image data")
1518
1519 if (bOK && awTlLastErr != AW_TLE_OK)
1520 {
1521 fprintf(stderr, "TexFileLoader::Load()\n");
1522 #if 0
1523 // an error occurred which was not detected in CreateTexture()
1524 if (pTex.voidP)
1525 {
1526 if (rParams.loadTextureB)
1527 pTex.textureP->Release();
1528 else
1529 pTex.surfaceP->Release();
1530 pTex.voidP = NULL;
1531 }
1532 else
1533 {
1534 db_assert1(rParams.rectA);
1535
1536 for (unsigned i=0; i<rParams.numRects; ++i)
1537 {
1538 AwCreateGraphicRegion * pRect = &rParams.rectA[i];
1539
1540 if (!rParams.prevTexB)
1541 {
1542 // release what was created
1543 if (rParams.loadTextureB)
1544 pRect->pTexture->Release();
1545 else
1546 pRect->pSurface->Release();
1547 }
1548 pRect->width = 0;
1549 pRect->height = 0;
1550 }
1551 }
1552 db_logf1(("AwCreateGraphic(): ERROR: %s",AwTlErrorToString()));
1553 #endif
1554 bOK = false;
1555 }
1556
1557 OnFinishLoading(bOK);
1558
1559 return pTex;
1560 }
1561
OnFinishLoading(bool)1562 void TexFileLoader::OnFinishLoading(bool)
1563 {
1564 }
1565
1566
~TypicalTexFileLoader()1567 TypicalTexFileLoader::~TypicalTexFileLoader()
1568 {
1569 if (m_pPalette)
1570 {
1571 delete[] m_pPalette;
1572
1573 if (m_pRowBuf) delete[] m_pRowBuf.byteP;
1574 if (m_ppPixMap)
1575 {
1576 delete[] m_ppPixMap->byteP;
1577 delete[] m_ppPixMap;
1578 }
1579 }
1580 else
1581 {
1582 if (m_pRowBuf) delete[] m_pRowBuf.colourP;
1583 if (m_ppPixMap)
1584 {
1585 delete[] m_ppPixMap->colourP;
1586 delete[] m_ppPixMap;
1587 }
1588 }
1589 }
1590
GetNumColours()1591 unsigned TypicalTexFileLoader::GetNumColours()
1592 {
1593 return m_nPaletteSize;
1594 }
1595
GetMinPaletteSize()1596 unsigned TypicalTexFileLoader::GetMinPaletteSize()
1597 {
1598 return m_nPaletteSize;
1599 }
1600
AllocateBuffers(bool bWantBackup,unsigned)1601 void TypicalTexFileLoader::AllocateBuffers(bool bWantBackup, unsigned /*nMaxPaletteSize*/)
1602 {
1603 if (m_nPaletteSize)
1604 {
1605 m_pPalette = new Colour [ m_nPaletteSize ];
1606 }
1607
1608 if (bWantBackup)
1609 {
1610 m_ppPixMap = new PtrUnion [m_nHeight];
1611 if (m_nPaletteSize)
1612 {
1613 m_ppPixMap->byteP = new BYTE [m_nHeight*m_nWidth];
1614 BYTE * pRow = m_ppPixMap->byteP;
1615 for (unsigned y=1;y<m_nHeight;++y)
1616 {
1617 pRow += m_nWidth;
1618 m_ppPixMap[y].byteP = pRow;
1619 }
1620 }
1621 else
1622 {
1623 m_ppPixMap->colourP = new Colour [m_nHeight*m_nWidth];
1624 Colour * pRow = m_ppPixMap->colourP;
1625 for (unsigned y=1;y<m_nHeight;++y)
1626 {
1627 pRow += m_nWidth;
1628 m_ppPixMap[y].colourP = pRow;
1629 }
1630 }
1631 }
1632 else
1633 {
1634 if (m_nPaletteSize)
1635 m_pRowBuf.byteP = new BYTE [m_nWidth];
1636 else
1637 m_pRowBuf.colourP = new Colour [m_nWidth];
1638 }
1639 }
1640
GetRowPtr(unsigned nRow)1641 PtrUnion TypicalTexFileLoader::GetRowPtr(unsigned nRow)
1642 {
1643 if (m_ppPixMap)
1644 {
1645 return m_ppPixMap[nRow];
1646 }
1647 else
1648 {
1649 return m_pRowBuf;
1650 }
1651 }
1652
CreateBackupTexture()1653 AwBackupTexture * TypicalTexFileLoader::CreateBackupTexture()
1654 {
1655 AwBackupTexture * pBackup = new TypicalBackupTexture(*this,m_ppPixMap,m_pPalette);
1656 m_ppPixMap = NULL;
1657 m_pPalette = NULL;
1658 return pBackup;
1659 }
1660
1661 /****************************************************************************/
1662 /* For determining which loader should be used for the file format detected */
1663 /****************************************************************************/
1664
1665 static
1666 class MagicFileIdTree
1667 {
1668 public:
MagicFileIdTree()1669 MagicFileIdTree()
1670 : m_pfnCreate(NULL)
1671 #ifdef _MSC_VER
1672 , hack(0)
1673 #endif
1674 {
1675 for (unsigned i=0; i<256; ++i)
1676 m_arrNextLayer[i]=NULL;
1677 }
1678
~MagicFileIdTree()1679 ~MagicFileIdTree()
1680 {
1681 for (unsigned i=0; i<256; ++i)
1682 if (m_arrNextLayer[i]) delete m_arrNextLayer[i];
1683 }
1684
1685 MagicFileIdTree * m_arrNextLayer [256];
1686
1687 TexFileLoader * (* m_pfnCreate) ();
1688
1689 #ifdef _MSC_VER
1690 unsigned hack;
1691 #endif
1692 }
1693 * g_pMagicFileIdTree = NULL;
1694
RegisterLoader(char const * pszMagic,TexFileLoader * (* pfnCreate)())1695 void RegisterLoader(char const * pszMagic, TexFileLoader * (* pfnCreate) () )
1696 {
1697 static MagicFileIdTree mfidt;
1698
1699 g_pMagicFileIdTree = &mfidt;
1700
1701 MagicFileIdTree * pLayer = g_pMagicFileIdTree;
1702
1703 while (*pszMagic)
1704 {
1705 BYTE c = static_cast<BYTE>(*pszMagic++);
1706
1707 if (!pLayer->m_arrNextLayer[c])
1708 pLayer->m_arrNextLayer[c] = new MagicFileIdTree;
1709
1710 pLayer = pLayer->m_arrNextLayer[c];
1711 }
1712
1713 db_assert1(!pLayer->m_pfnCreate);
1714
1715 pLayer->m_pfnCreate = pfnCreate;
1716 }
1717
1718 static
CreateLoaderObject(MediaMedium * pMedium)1719 TexFileLoader * CreateLoaderObject(MediaMedium * pMedium)
1720 {
1721 TexFileLoader * (* pfnBest) () = NULL;
1722
1723 signed nMoveBack = 0;
1724
1725 BYTE c;
1726
1727 MagicFileIdTree * pLayer = g_pMagicFileIdTree;
1728
1729 while (pLayer)
1730 {
1731 if (pLayer->m_pfnCreate)
1732 pfnBest = pLayer->m_pfnCreate;
1733
1734 MediaRead(pMedium,&c);
1735
1736 -- nMoveBack;
1737
1738 pLayer = pLayer->m_arrNextLayer[c];
1739 }
1740
1741 pMedium->MovePos(nMoveBack);
1742
1743 if (pfnBest)
1744 return pfnBest();
1745 else
1746 return NULL;
1747 }
1748
1749 /**********************************/
1750 /* These are the loader functions */
1751 /**********************************/
1752
DoLoadTexture(MediaMedium * pMedium,CreateTextureParms const & rParams)1753 static inline SurfUnion DoLoadTexture(MediaMedium * pMedium, CreateTextureParms const & rParams)
1754 {
1755 TexFileLoader * pLoader = CreateLoaderObject(pMedium);
1756
1757 if (!pLoader)
1758 {
1759 awTlLastErr = AW_TLE_BADFILEFORMAT;
1760 db_log1("AwCreateGraphic(): ERROR: file format not recognized");
1761 return static_cast<D3DTexture *>(NULL);
1762 }
1763 else
1764 {
1765 SurfUnion pTex = pLoader->Load(pMedium,rParams);
1766 pLoader->Release();
1767 return pTex;
1768 }
1769 }
1770
LoadTexture(MediaMedium * pMedium,CreateTextureParms const & _parmsR)1771 static inline SurfUnion LoadTexture(MediaMedium * pMedium, CreateTextureParms const & _parmsR)
1772 {
1773 if (_parmsR.bytesReadP||_parmsR.maxReadBytes!=UINT_MAX)
1774 {
1775 MediaSection * pMedSect = new MediaSection;
1776 pMedSect->Open(pMedium,_parmsR.maxReadBytes);
1777 SurfUnion pTex = DoLoadTexture(pMedSect,_parmsR);
1778 pMedSect->Close();
1779 if (_parmsR.bytesReadP) *_parmsR.bytesReadP = pMedSect->GetUsedSize();
1780 delete pMedSect;
1781 return pTex;
1782 }
1783 else
1784 {
1785 return DoLoadTexture(pMedium,_parmsR);
1786 }
1787 }
1788
DoCreate() const1789 SurfUnion CreateTextureParms::DoCreate() const
1790 {
1791 if (NULL != fileH)
1792 {
1793 MediaStdFileMedium * pMedium = new MediaStdFileMedium;
1794 pMedium->Attach(fileH);
1795 SurfUnion pTex = LoadTexture(pMedium,*this);
1796 pMedium->Detach();
1797 pMedium->Release();
1798 return pTex;
1799 }
1800 else if (dataP)
1801 {
1802 MediaMemoryReadMedium * pMedium = new MediaMemoryReadMedium;
1803 pMedium->Open(dataP);
1804 SurfUnion pTex = LoadTexture(pMedium,*this);
1805 pMedium->Close();
1806 pMedium->Release();
1807 return pTex;
1808 }
1809 else
1810 {
1811 db_assert1(restoreH);
1812 return restoreH->Restore(*this);
1813 }
1814 }
1815
1816 // Parse the format string and get the parameters
1817
ParseParams(CreateTextureParms * pParams,char const * _argFormatS,va_list ap)1818 static bool ParseParams(CreateTextureParms * pParams, char const * _argFormatS, va_list ap)
1819 {
1820 bool bad_parmsB = false;
1821 db_code2(unsigned ch_off = 0;)
1822 db_code2(char ch = 0;)
1823
1824 while (*_argFormatS && !bad_parmsB)
1825 {
1826 db_code2(++ch_off;)
1827 db_code2(ch = *_argFormatS;)
1828 switch (*_argFormatS++)
1829 {
1830 case 's':
1831 if (pParams->fileNameS || NULL!=pParams->fileH || pParams->dataP || pParams->restoreH)
1832 bad_parmsB = true;
1833 else
1834 {
1835 pParams->fileNameS = va_arg(ap,char *);
1836 db_logf4(("\tFilename = \"%s\"",pParams->fileNameS));
1837 }
1838 break;
1839 case 'h':
1840 if (pParams->fileNameS || NULL!=pParams->fileH || pParams->dataP || pParams->restoreH)
1841 bad_parmsB = true;
1842 else
1843 {
1844 pParams->fileH = va_arg(ap,FILE *);
1845 db_logf4(("\tFile HANDLE = %p",pParams->fileH));
1846 }
1847 break;
1848 case 'p':
1849 if (pParams->fileNameS || NULL!=pParams->fileH || pParams->dataP || pParams->restoreH)
1850 bad_parmsB = true;
1851 else
1852 {
1853 pParams->dataP = va_arg(ap,void const *);
1854 db_logf4(("\tData Pointer = %p",pParams->dataP.voidP));
1855 }
1856 break;
1857 case 'r':
1858 if (pParams->fileNameS || NULL!=pParams->fileH || pParams->dataP || pParams->restoreH || UINT_MAX!=pParams->maxReadBytes || pParams->bytesReadP)
1859 bad_parmsB = true;
1860 else
1861 {
1862 pParams->restoreH = va_arg(ap,AW_BACKUPTEXTUREHANDLE);
1863 db_logf4(("\tRestore Handle = 0x%08x",pParams->restoreH));
1864 }
1865 break;
1866 case 'x':
1867 if (UINT_MAX!=pParams->maxReadBytes || pParams->restoreH)
1868 bad_parmsB = true;
1869 else
1870 {
1871 pParams->maxReadBytes = va_arg(ap,unsigned);
1872 db_logf4(("\tMax bytes to read = %u",pParams->maxReadBytes));
1873 }
1874 break;
1875 case 'N':
1876 if (pParams->bytesReadP || pParams->restoreH)
1877 bad_parmsB = true;
1878 else
1879 {
1880 pParams->bytesReadP = va_arg(ap,unsigned *);
1881 db_logf4(("\tPtr to bytes read = %p",pParams->bytesReadP));
1882 }
1883 break;
1884 case 'f':
1885 if (AW_TLF_DEFAULT!=pParams->flags)
1886 bad_parmsB = true;
1887 else
1888 {
1889 pParams->flags = va_arg(ap,unsigned);
1890 db_logf4(("\tFlags = 0x%08x",pParams->flags));
1891 }
1892 break;
1893 case 'W':
1894 if (pParams->widthP || pParams->rectA)
1895 bad_parmsB = true;
1896 else
1897 {
1898 pParams->widthP = va_arg(ap,unsigned *);
1899 db_logf4(("\tPtr to width = %p",pParams->widthP));
1900 }
1901 break;
1902 case 'H':
1903 if (pParams->heightP || pParams->rectA)
1904 bad_parmsB = true;
1905 else
1906 {
1907 pParams->heightP = va_arg(ap,unsigned *);
1908 db_logf4(("\tPtr to height = %p",pParams->heightP));
1909 }
1910 break;
1911 case 'X':
1912 if (pParams->originalWidthP)
1913 bad_parmsB = true;
1914 else
1915 {
1916 pParams->originalWidthP = va_arg(ap,unsigned *);
1917 db_logf4(("\tPtr to image width = %p",pParams->originalWidthP));
1918 }
1919 break;
1920 case 'Y':
1921 if (pParams->originalHeightP)
1922 bad_parmsB = true;
1923 else
1924 {
1925 pParams->originalHeightP = va_arg(ap,unsigned *);
1926 db_logf4(("\tPtr to image height = %p",pParams->originalHeightP));
1927 }
1928 break;
1929 case 'B':
1930 if (pParams->restoreH)
1931 bad_parmsB = true;
1932 break;
1933 case 't':
1934 if (pParams->prevTexP.voidP)
1935 bad_parmsB = true;
1936 else if (pParams->rectA)
1937 {
1938 pParams->prevTexB = true;
1939 db_log4("\tPrevious DDSurface * or D3DTexture * in rectangle array");
1940 }
1941 else if (pParams->loadTextureB)
1942 {
1943 pParams->prevTexP = va_arg(ap,D3DTexture *);
1944 db_logf4(("\tPrevious D3DTexture * = %p",pParams->prevTexP.textureP));
1945 }
1946 else
1947 {
1948 pParams->prevTexP = va_arg(ap,DDSurface *);
1949 db_logf4(("\tPrevious DDSurface * = %p",pParams->prevTexP.surfaceP));
1950 }
1951 break;
1952 case 'c':
1953 if (pParams->callbackF)
1954 bad_parmsB = true;
1955 else
1956 {
1957 pParams->callbackF = va_arg(ap,AW_TL_PFN_CALLBACK);
1958 pParams->callbackParam = va_arg(ap,void *);
1959 db_logf4(("\tCallback function = %p, param = %p",pParams->callbackF,pParams->callbackParam));
1960 }
1961 break;
1962 case 'a':
1963 if (pParams->prevTexP.voidP || pParams->rectA || pParams->widthP || pParams->heightP)
1964 bad_parmsB = true;
1965 else
1966 {
1967 pParams->numRects = va_arg(ap,unsigned);
1968 pParams->rectA = va_arg(ap,AwCreateGraphicRegion *);
1969 db_logf4(("\tRectangle array = %p, size = %u",pParams->rectA,pParams->numRects));
1970 }
1971 break;
1972 default:
1973 bad_parmsB = true;
1974 }
1975 }
1976
1977 if (!pParams->fileNameS && NULL==pParams->fileH && !pParams->dataP && !pParams->restoreH)
1978 {
1979 awTlLastErr = AW_TLE_BADPARMS;
1980 db_log2("AwCreateGraphic(): ERROR: No data medium is specified");
1981 return false;
1982 }
1983 else if (bad_parmsB)
1984 {
1985 awTlLastErr = AW_TLE_BADPARMS;
1986 db_logf2(("AwCreateGraphic(): ERROR: Unexpected '%c' in format string at character %u",ch,ch_off));
1987 return false;
1988 }
1989 else
1990 {
1991 db_log5("\tParameters are OK");
1992 return true;
1993 }
1994 }
1995
1996 // Use the parameters parsed to load the surface or texture
1997
LoadFromParams(CreateTextureParms * pParams)1998 SurfUnion LoadFromParams(CreateTextureParms * pParams)
1999 {
2000 if (pParams->fileNameS)
2001 {
2002 pParams->fileH = OpenGameFile(pParams->fileNameS, FILEMODE_READONLY, FILETYPE_PERM);
2003
2004 if (NULL==pParams->fileH)
2005 {
2006 awTlLastErr = AW_TLE_CANTOPENFILE;
2007 // awTlLastWinErr = GetLastError();
2008 db_logf1(("AwCreateGraphic(): ERROR opening file \"%s\"",pParams->fileNameS));
2009 db_log2(AwTlErrorToString());
2010 return static_cast<D3DTexture *>(NULL);
2011 }
2012
2013 SurfUnion textureP = pParams->DoCreate();
2014
2015 fclose(pParams->fileH);
2016
2017 return textureP;
2018 }
2019 else return pParams->DoCreate();
2020 }
2021
2022 } // namespace AwTl
2023
2024 /******************************/
2025 /* PUBLIC: AwSetTextureFormat */
2026 /******************************/
2027
2028 #define IS_VALID_MEMBER(sP,mem) (reinterpret_cast<unsigned>(&(sP)->mem) - reinterpret_cast<unsigned>(sP) < static_cast<unsigned>((sP)->dwSize))
2029
2030 #define GET_VALID_MEMBER(sP,mem,deflt) (IS_VALID_MEMBER(sP,mem) ? (sP)->mem : (db_logf4((FUNCTION_NAME ": WARNING: %s->%s is not valid",#sP ,#mem )),(deflt)))
2031
2032 #define HANDLE_INITERROR(test,s) \
2033 if (!(test)) { \
2034 db_logf3((FUNCTION_NAME " failed becuse %s",s)); \
2035 db_log1(FUNCTION_NAME ": ERROR: unexpected parameters"); \
2036 return AW_TLE_BADPARMS; \
2037 } else { \
2038 db_logf5(("\t" FUNCTION_NAME " passed check '%s'",#test )); \
2039 }
2040
2041
AwSetD3DDevice(void * _d3ddeviceP)2042 AW_TL_ERC AwSetD3DDevice(void * _d3ddeviceP)
2043 {
2044 using AwTl::driverDesc;
2045
2046 driverDesc.validB = false;
2047
2048 db_logf4(("AwSetD3DDevice(%p) called",_d3ddeviceP));
2049
2050 // HANDLE_INITERROR(_d3ddeviceP,"D3DDevice * is NULL")
2051
2052 driverDesc.validB = true;
2053
2054 return AW_TLE_OK;
2055 }
2056
AwSetDDObject(void * _ddP)2057 AW_TL_ERC AwSetDDObject(void * _ddP)
2058 {
2059 using AwTl::driverDesc;
2060
2061 fprintf(stderr, "AwSetDDObject(%p) called.",_ddP);
2062
2063 // HANDLE_INITERROR(_ddP,"DDObject * is NULL")
2064 driverDesc.ddP = _ddP;
2065
2066 return AW_TLE_OK;
2067 }
2068
AwSetD3DDevice(void * _ddP,void * _d3ddeviceP)2069 AW_TL_ERC AwSetD3DDevice(void * _ddP, void * _d3ddeviceP)
2070 {
2071 fprintf(stderr, "AwSetD3DDevice(%p,%p) called",_ddP,_d3ddeviceP);
2072
2073 AW_TL_ERC iResult = AwSetDDObject(_ddP);
2074
2075 if (AW_TLE_OK != iResult)
2076 return iResult;
2077 else
2078 return AwSetD3DDevice(_d3ddeviceP);
2079 }
2080
AwSetPixelFormat(AwTl::PixelFormat * _pfP,void * _ddpfP)2081 static AW_TL_ERC AwSetPixelFormat(AwTl::PixelFormat * _pfP, void * _ddpfP)
2082 {
2083 using AwTl::SetBitShifts;
2084
2085 fprintf(stderr, "AwSetPixelFormat(%p, %p)\n", _pfP, _ddpfP);
2086
2087 _pfP->validB = false;
2088
2089 _pfP->palettizedB = true;
2090
2091 _pfP->validB = true;
2092
2093 _pfP->palettizedB = 0;
2094 _pfP->alphaB = 0;
2095 _pfP->validB = 1;
2096 _pfP->bitsPerPixel = 32;
2097 _pfP->redLeftShift = 0;
2098 _pfP->greenLeftShift = 8;
2099 _pfP->blueLeftShift = 16;
2100 _pfP->redRightShift = 0;
2101 _pfP->greenRightShift = 0;
2102 _pfP->blueRightShift = 0;
2103 _pfP->dwRGBAlphaBitMask = 0xFF000000;
2104
2105 return AW_TLE_OK;
2106 }
2107
AwSetTextureFormat2(void * _ddpfP)2108 AW_TL_ERC AwSetTextureFormat2(void* _ddpfP)
2109 {
2110 db_logf4(("AwSetTextureFormat(%p) called",_ddpfP));
2111
2112 using namespace AwTl;
2113
2114 while (listTextureFormats.size())
2115 listTextureFormats.delete_first_entry();
2116
2117 return AwSetPixelFormat(&pfTextureFormat, _ddpfP);
2118 }
2119
AwSetAdditionalTextureFormat2(void * _ddpfP,unsigned _maxAlphaBits,int _canDoTransp,unsigned _maxColours)2120 AW_TL_ERC AwSetAdditionalTextureFormat2(void * _ddpfP, unsigned _maxAlphaBits, int _canDoTransp, unsigned _maxColours)
2121 {
2122 db_logf4(("AwSetAdditionalTextureFormat(%p.%u,%d,%u) called",_ddpfP,_maxAlphaBits,_canDoTransp,_maxColours));
2123
2124 using namespace AwTl;
2125
2126 AdditionalPixelFormat pf;
2127
2128 AW_TL_ERC erc = AwSetPixelFormat(&pf, _ddpfP);
2129
2130 if (AW_TLE_OK == erc)
2131 {
2132 pf.canDoTranspB = _canDoTransp ? true : false;
2133 pf.maxColours = _maxColours;
2134
2135 listTextureFormats.add_entry_end(pf);
2136 }
2137
2138 return erc;
2139 }
2140
AwSetSurfaceFormat2(void * _ddpfP)2141 AW_TL_ERC AwSetSurfaceFormat2(void* _ddpfP)
2142 {
2143 db_logf4(("AwSetSurfaceFormat(%p) called",_ddpfP));
2144
2145 using namespace AwTl;
2146
2147 return AwSetPixelFormat(&pfSurfaceFormat, _ddpfP);
2148 }
2149
2150 /****************************/
2151 /* PUBLIC: AwGetTextureSize */
2152 /****************************/
2153
AwGetTextureSize(unsigned * _widthP,unsigned * _heightP,unsigned _width,unsigned _height)2154 AW_TL_ERC AwGetTextureSize(unsigned * _widthP, unsigned * _heightP, unsigned _width, unsigned _height)
2155 {
2156 * _widthP = _width;
2157 * _heightP = _height;
2158
2159 return AW_TLE_OK;
2160 }
2161
2162
2163 /******************************/
2164 /* PUBLIC: AwCreate functions */
2165 /******************************/
2166
AwCreateTexture(char const * _argFormatS,...)2167 D3DTexture * _AWTL_VARARG AwCreateTexture(char const * _argFormatS, ...)
2168 {
2169 db_logf4(("AwCreateTexture(\"%s\") called",_argFormatS));
2170
2171 using namespace AwTl;
2172
2173 va_list ap;
2174 va_start(ap,_argFormatS);
2175 CreateTextureParms parms;
2176 parms.loadTextureB = true;
2177 bool bParmsOK = ParseParams(&parms, _argFormatS, ap);
2178 va_end(ap);
2179
2180 return bParmsOK ? LoadFromParams(&parms).textureP : NULL;
2181 }
2182
AwCreateSurface(char const * _argFormatS,...)2183 DDSurface * AwCreateSurface(char const * _argFormatS, ...)
2184 {
2185 db_logf4(("AwCreateSurface(\"%s\") called",_argFormatS));
2186
2187 using namespace AwTl;
2188
2189 /* Just convert the texture to 32bpp */
2190 pixelFormat.palettizedB = 0;
2191
2192 pixelFormat.alphaB = 1;
2193 pixelFormat.validB = 1;
2194 pixelFormat.texB = 0;
2195 pixelFormat.bitsPerPixel = 32;
2196 pixelFormat.redLeftShift = 0;
2197 pixelFormat.greenLeftShift = 8;
2198 pixelFormat.blueLeftShift = 16;
2199 pixelFormat.redRightShift = 0;
2200 pixelFormat.greenRightShift = 0;
2201 pixelFormat.blueRightShift = 0;
2202 pixelFormat.dwRGBAlphaBitMask = 0xFF000000;
2203
2204 va_list ap;
2205 va_start(ap,_argFormatS);
2206 CreateTextureParms parms;
2207 parms.loadTextureB = false;
2208 bool bParmsOK = ParseParams(&parms, _argFormatS, ap);
2209 va_end(ap);
2210 return bParmsOK ? LoadFromParams(&parms).surfaceP : NULL;
2211 }
2212
AwDestroyBackupTexture(AW_BACKUPTEXTUREHANDLE _bH)2213 AW_TL_ERC AwDestroyBackupTexture(AW_BACKUPTEXTUREHANDLE _bH)
2214 {
2215 return AW_TLE_OK;
2216 }
2217
2218 /*********************************/
2219 /* PUBLIC DEBUG: LastErr globals */
2220 /*********************************/
2221
2222 AW_TL_ERC awTlLastErr;
2223
2224 /*******************************************/
2225 /* PUBLIC DEBUG: AwErrorToString functions */
2226 /*******************************************/
2227
2228 #ifndef NDEBUG
AwWinErrorToString(DWORD error)2229 char const * AwWinErrorToString(DWORD error)
2230 {
2231 if (NO_ERROR==error)
2232 return "No error";
2233
2234 return "AwWinErrorToString: No clue!";
2235 }
2236
AwTlErrorToString(AwTlErc error)2237 char const * AwTlErrorToString(AwTlErc error)
2238 {
2239 char const * defaultS;
2240 switch (error)
2241 {
2242 case AW_TLE_OK:
2243 return "No error";
2244 case AW_TLE_DXERROR:
2245 // if (!awTlLastDxErr)
2246 return "Unknown DirectX error";
2247 // else
2248 // return AwDxErrorToString();
2249 case AW_TLE_BADPARMS:
2250 return "Invalid parameters or functionality not supported";
2251 case AW_TLE_NOINIT:
2252 return "Initialization failed or not performed";
2253 case AW_TLE_CANTOPENFILE:
2254 defaultS = "Unknown error opening file";
2255 goto WIN_ERR;
2256 case AW_TLE_CANTREADFILE:
2257 defaultS = "Unknown error reading file";
2258 WIN_ERR:
2259 return defaultS;
2260 case AW_TLE_EOFMET:
2261 return "Unexpected end of file during texture load";
2262 case AW_TLE_BADFILEFORMAT:
2263 return "Texture file format not recognized";
2264 case AW_TLE_BADFILEDATA:
2265 return "Texture file data not consistent";
2266 case AW_TLE_CANTPALETTIZE:
2267 return "Texture file data not palettized";
2268 case AW_TLE_IMAGETOOLARGE:
2269 return "Image is too large for a texture";
2270 case AW_TLE_CANTRELOAD:
2271 return "New image is wrong size or format to load into existing texture";
2272 default:
2273 return "Unknown texture loading error";
2274 }
2275 }
2276
AwDxErrorToString(int error)2277 char const * AwDxErrorToString(int error)
2278 {
2279 return "Unrecognized error value.\0";
2280 }
2281
2282 #endif
2283