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