From 218ca90543758a20ac326e444ca0643174ca7384 Mon Sep 17 00:00:00 2001 From: Rebellion Developments Date: Thu, 16 Mar 2000 11:25:00 +0100 Subject: Import Aliens vs Predator - Gold (Build 116) Source code release, imported from: https://www.gamefront.com/games/aliens-vs-predator-3/file/avp-gold-complete-source-code All text files were converted to Unix format. --- 3dc/win95/awTexLd.cpp | 2974 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2974 insertions(+) create mode 100644 3dc/win95/awTexLd.cpp (limited to '3dc/win95/awTexLd.cpp') diff --git a/3dc/win95/awTexLd.cpp b/3dc/win95/awTexLd.cpp new file mode 100644 index 0000000..65f4b7a --- /dev/null +++ b/3dc/win95/awTexLd.cpp @@ -0,0 +1,2974 @@ +#include "advwin32.h" +#ifndef DB_LEVEL +#define DB_LEVEL 4 +#endif +#include "db.h" + +#ifndef NDEBUG + #define HT_FAIL db_log1 + #include "hash_tem.hpp" // for the backup surfaces memory leak checking +#endif + +#ifdef _MSC_VER + #include "iff.hpp" +#endif + +#include "list_tem.hpp" + +#include +#include +#include + +#include "awTexLd.h" +#pragma warning(disable: 4701) +#include "awTexLd.hpp" +#pragma warning(default: 4701) + +#ifdef _CPPRTTI + #include +#endif + +/* awTexLd.cpp - Author: Jake Hotson */ + +/*****************************************/ +/* Preprocessor switches for experiments */ +/*****************************************/ + +#define MIPMAPTEST 0 // experiment to create mip map surfaces for textures, but doesn't bother putting any data into them + +/*****************************/ +/* DB_LEVEL dependent macros */ +/*****************************/ + +#if DB_LEVEL >= 5 +#define inline // prevent function inlining at level 5 debugging +#endif + +/*****************************************************/ +/* ZEROFILL and SETDWSIZE macros ensure that I won't */ +/* accidentally get the parameters wrong */ +/*****************************************************/ + +#if 1 // which do you prefer? + +// zero mem +template +static inline void ZEROFILL(X & x) +{ + memset(&x,0,sizeof(X)); +} + +// set dwSize +template +static inline void SETDWSIZE(X & x) +{ + x.dwSize = sizeof(X); +} + +template +static inline void INITDXSTRUCT(X & x) +{ + ZEROFILL(x); + SETDWSIZE(x); +} + +#else + +#define ZEROFILL(x) (memset(&x,0,sizeof x)) +#define SETDWSIZE(x) (x.dwSize = sizeof x) +#define INITDXSTRUCT(x) (ZEROFILL(x),SETDWSIZE(x)) + +#endif + +/*****************************************************************/ +/* Put everything I can in a namespace to avoid naming conflicts */ +/*****************************************************************/ + +namespace AwTl +{ + /**************************************************/ + /* Allow breakpoints to be potentially hard coded */ + /* into macros and template functions */ + /**************************************************/ + + db_code5(void BrkPt(){}) + #define BREAKPOINT db_code5(::AwTl::BrkPt();) + + #if DB_LEVEL > 4 + static unsigned GetRefCount(IUnknown * pUnknown) + { + if (!pUnknown) return 0; + pUnknown->AddRef(); + return static_cast(pUnknown->Release()); + } + #endif + + /*********************************/ + /* Pixel format global structure */ + /*********************************/ + + PixelFormat pixelFormat; + + PixelFormat pfTextureFormat; + PixelFormat pfSurfaceFormat; + + static inline void SetBitShifts(unsigned * leftShift,unsigned * rightShift,unsigned mask) + { + if (!mask) + *leftShift = 0; + else + for (*leftShift = 0; !(mask & 1); ++*leftShift, mask>>=1) + ; + for (*rightShift = 8; mask; --*rightShift, mask>>=1) + ; + } + + /************************************/ + /* D3D Driver info global structure */ + /************************************/ + + static + struct DriverDesc + { + DriverDesc() : validB(false), ddP(NULL) {} + + bool validB : 1; + bool needSquareB : 1; + bool needPow2B : 1; + + unsigned minWidth; + unsigned minHeight; + unsigned maxWidth; + unsigned maxHeight; + + DWORD memFlag; + + DDObject * ddP; + } + driverDesc; + + /*************************************************************************/ + /* Class used to hold all the parameters for the CreateTexture functions */ + /*************************************************************************/ + + class CreateTextureParms + { + public: + inline CreateTextureParms() + : fileNameS(NULL) + , fileH(INVALID_HANDLE_VALUE) + , dataP(NULL) + , restoreH(NULL) + , maxReadBytes(UINT_MAX) + , bytesReadP(NULL) + , flags(AW_TLF_DEFAULT) + , originalWidthP(NULL) + , originalHeightP(NULL) + , widthP(NULL) + , heightP(NULL) + , backupHP(NULL) + , prevTexP(static_cast(NULL)) + , prevTexB(false) + , loadTextureB(false) + , callbackF(NULL) + , rectA(NULL) + { + } + + SurfUnion DoCreate() const; + + bool loadTextureB; + + LPCTSTR fileNameS; + HANDLE fileH; + PtrUnionConst dataP; + AW_BACKUPTEXTUREHANDLE restoreH; + + unsigned maxReadBytes; + unsigned * bytesReadP; + + unsigned flags; + + unsigned * widthP; + unsigned * heightP; + + unsigned * originalWidthP; + unsigned * originalHeightP; + + AW_BACKUPTEXTUREHANDLE * backupHP; + + SurfUnion prevTexP; + bool prevTexB; // used when rectA is non-NULL, otherwise prevTexP is used + + AW_TL_PFN_CALLBACK callbackF; + void * callbackParam; + + unsigned numRects; + AwCreateGraphicRegion * rectA; + }; + + + /****************************************/ + /* Reference Count Object Debug Support */ + /****************************************/ + + #ifndef NDEBUG + + static bool g_bAllocListActive = false; + + class AllocList : public ::HashTable + { + public: + AllocList() + { + g_bAllocListActive = true; + } + ~AllocList() + { + if (Size()) + { + db_log1(("AW: Potential Memory Leaks Detected!!!")); + } + #ifdef _CPPRTTI + #pragma message("Run-Time Type Identification (RTTI) is enabled") + for (Iterator itLeak(*this) ; !itLeak.Done() ; itLeak.Next()) + { + db_logf1(("\tAW Object not deallocated: Type: %s RefCnt: %u",typeid(*itLeak.Get()).name(),itLeak.Get()->m_nRefCnt)); + } + if (Size()) + { + db_log1(("AW: Object dump complete")); + } + #else // ! _CPPRTTI + #pragma message("Run-Time Type Identification (RTTI) is not enabled - memory leak checking will not report types") + unsigned nRefs(0); + for (Iterator itLeak(*this) ; !itLeak.Done() ; itLeak.Next()) + { + nRefs += itLeak.Get()->m_nRefCnt; + } + if (Size()) + { + db_logf1(("AW: Objects not deallocated: Number of Objects: %u Number of References: %u",Size(),nRefs)); + } + #endif // ! _CPPRTTI + g_bAllocListActive = false; + } + }; + + static AllocList g_listAllocated; + + void DbRemember(RefCntObj * pObj) + { + g_listAllocated.AddAsserted(pObj); + } + + void DbForget(RefCntObj * pObj) + { + if (g_bAllocListActive) + g_listAllocated.RemoveAsserted(pObj); + } + + #endif // ! NDEBUG + + /********************************************/ + /* structure to contain loading information */ + /********************************************/ + + struct LoadInfo + { + DDSurface * surfaceP; + bool surface_lockedB; + DDSurface * dst_surfaceP; + D3DTexture * textureP; + D3DTexture * dst_textureP; + + unsigned surface_width; + unsigned surface_height; + PtrUnion surface_dataP; + LONG surface_pitch; + DWORD dwCapsCaps; + + unsigned * widthP; + unsigned * heightP; + SurfUnion prevTexP; + SurfUnion resultP; + unsigned top,left,bottom,right; + unsigned width,height; // set to right-left and bottom-top + + AwCreateGraphicRegion * rectP; + + bool skipB; // used to indicate that a surface/texture was not lost and .`. does not need restoring + + LoadInfo() + : surfaceP(NULL) + , surface_lockedB(false) + , dst_surfaceP(NULL) + , textureP(NULL) + , dst_textureP(NULL) + , skipB(false) + { + } + }; + + /*******************************/ + /* additiional texture formats */ + /*******************************/ + + struct AdditionalPixelFormat : PixelFormat + { + bool canDoTranspB; + unsigned maxColours; + + // for List + bool operator == (AdditionalPixelFormat const &) const { return false; } + bool operator != (AdditionalPixelFormat const &) const { return true; } + }; + + static List listTextureFormats; + +} // namespace AwTl + +/*******************/ +/* Generic Loaders */ +/*******************/ + +#define HANDLE_DXERROR(s) \ + if (DD_OK != awTlLastDxErr) { \ + awTlLastErr = AW_TLE_DXERROR; \ + db_logf3(("AwCreateGraphic() failed whilst %s",s)); \ + db_log1("AwCreateGraphic(): ERROR: DirectX SDK call failed"); \ + goto EXIT_WITH_ERROR; \ + } else { \ + db_logf5(("\tsuccessfully completed %s",s)); \ + } + +#define ON_ERROR_RETURN_NULL(s) \ + if (awTlLastErr != AW_TLE_OK) { \ + db_logf3(("AwCreateGraphic() failed whilst %s",s)); \ + db_logf1(("AwCreateGraphic(): ERROR: %s",AwTlErrorToString())); \ + return static_cast(NULL); \ + } else { \ + db_logf5(("\tsuccessfully completed %s",s)); \ + } + +#define CHECK_MEDIA_ERRORS(s) \ + if (pMedium->m_fError) { \ + db_logf3(("AwCreateGraphic(): The following media errors occurred whilst %s",s)); \ + if (pMedium->m_fError & MediaMedium::MME_VEOFMET) { \ + db_log3("\tA virtual end of file was met"); \ + if (awTlLastErr == AW_TLE_OK) awTlLastErr = AW_TLE_EOFMET; \ + } \ + if (pMedium->m_fError & MediaMedium::MME_EOFMET) { \ + db_log3("\tAn actual end of file was met"); \ + if (awTlLastErr == AW_TLE_OK) awTlLastErr = AW_TLE_EOFMET; \ + } \ + if (pMedium->m_fError & MediaMedium::MME_OPENFAIL) { \ + db_log3("\tThe file could not be opened"); \ + if (awTlLastErr == AW_TLE_OK) { awTlLastErr = AW_TLE_CANTOPENFILE; awTlLastWinErr = GetLastError(); } \ + } \ + if (pMedium->m_fError & MediaMedium::MME_CLOSEFAIL) { \ + db_log3("\tThe file could not be closed"); \ + if (awTlLastErr == AW_TLE_OK) { awTlLastErr = AW_TLE_CANTOPENFILE; awTlLastWinErr = GetLastError(); } \ + } \ + if (pMedium->m_fError & MediaMedium::MME_UNAVAIL) { \ + db_log3("\tA requested operation was not available"); \ + if (awTlLastErr == AW_TLE_OK) { awTlLastErr = AW_TLE_CANTREADFILE; awTlLastWinErr = GetLastError(); } \ + } \ + if (pMedium->m_fError & MediaMedium::MME_IOERROR) { \ + db_log3("\tA read error occurred"); \ + if (awTlLastErr == AW_TLE_OK) { awTlLastErr = AW_TLE_CANTREADFILE; awTlLastWinErr = GetLastError(); } \ + } \ + } + +AwTl::SurfUnion AwBackupTexture::Restore(AwTl::CreateTextureParms const & rParams) +{ + using namespace AwTl; + + ChoosePixelFormat(rParams); + + if (!pixelFormat.validB) + db_log3("AwCreateGraphic(): ERROR: pixel format not valid"); + if (!driverDesc.ddP || !driverDesc.validB && rParams.loadTextureB) + db_log3("AwCreateGraphic(): ERROR: driver description not valid"); + + awTlLastErr = pixelFormat.validB && driverDesc.ddP && (driverDesc.validB || !rParams.loadTextureB) ? AW_TLE_OK : AW_TLE_NOINIT; + + ON_ERROR_RETURN_NULL("initializing restore") + + OnBeginRestoring(pixelFormat.palettizedB ? 1< itFormat(&listTextureFormats); !itFormat.done(); itFormat.next()) + { + AdditionalPixelFormat const * pThisFormat = &itFormat(); + // is this format suitable? + // ignoring alpha for now + if + ( + (nMinPalSize <= 1U<bitsPerPixel && nMinPalSize || !pThisFormat->palettizedB) // few enough colours for palettized format + && (nColours <= pThisFormat->maxColours && nColours || !pThisFormat->maxColours) // pass the max colours test + && (pThisFormat->canDoTranspB || !m_bTranspMask) // pass the transparency test + ) + { + pFormat = pThisFormat; + } + } + + pixelFormat = *pFormat; + + #if DB_LEVEL >= 4 + if (pixelFormat.palettizedB) + { + db_logf4(("\tchosen %u-bit palettized texture format",pixelFormat.bitsPerPixel)); + } + else + { + if (pixelFormat.alphaB) + { + unsigned alpha_l_shft,alpha_r_shft; + SetBitShifts(&alpha_l_shft,&alpha_r_shft,pixelFormat.ddpf.dwRGBAlphaBitMask); + + db_logf4(("\tchosen %u-bit %u%u%u%u texture format", + pixelFormat.bitsPerPixel, + 8U-pixelFormat.redRightShift, + 8U-pixelFormat.greenRightShift, + 8U-pixelFormat.blueRightShift, + 8U-alpha_r_shft)); + } + else + { + db_logf4(("\tchosen %u-bit %u%u%u texture format", + pixelFormat.bitsPerPixel, + 8U-pixelFormat.redRightShift, + 8U-pixelFormat.greenRightShift, + 8U-pixelFormat.blueRightShift)); + } + } + #endif + } + else + { + // use display surface format + pixelFormat = pfSurfaceFormat; + } + +} + +AwTl::SurfUnion AwBackupTexture::CreateTexture(AwTl::CreateTextureParms const & _parmsR) +{ + using namespace AwTl; + + // which flags to use? + unsigned fMyFlags = + _parmsR.flags & AW_TLF_PREVSRCALL ? db_assert1(_parmsR.restoreH), + _parmsR.flags & (AW_TLF_CHECKLOST|AW_TLF_SKIPNOTLOST) | m_fFlags & ~(AW_TLF_CHECKLOST|AW_TLF_SKIPNOTLOST) + : _parmsR.flags & AW_TLF_PREVSRC ? db_assert1(_parmsR.restoreH), + _parmsR.flags & ~AW_TLF_TRANSP | m_fFlags & AW_TLF_TRANSP + : _parmsR.flags; + + db_code1(ULONG refcnt;) + + DDPalette * dd_paletteP = NULL; + LoadInfo * arrLoadInfo = NULL; + unsigned nLoadInfos = 0; + { + // quick error check + if (pixelFormat.palettizedB && (!m_nPaletteSize || 1U< _parmsR.rectA[i].left + && _parmsR.rectA[i].bottom > _parmsR.rectA[i].top + ) + { + // rectangle covers at least some of the image and non-null previous texture + arrLoadInfo[nLoadInfos].widthP = &_parmsR.rectA[i].width; + arrLoadInfo[nLoadInfos].heightP = &_parmsR.rectA[i].height; + if (_parmsR.prevTexB) + { + if (_parmsR.loadTextureB) + arrLoadInfo[nLoadInfos].prevTexP = _parmsR.rectA[i].pTexture; + else + arrLoadInfo[nLoadInfos].prevTexP = _parmsR.rectA[i].pSurface; + } + else + { + arrLoadInfo[nLoadInfos].prevTexP = static_cast(NULL); + if (_parmsR.loadTextureB) + _parmsR.rectA[i].pTexture = NULL; + else + _parmsR.rectA[i].pSurface = NULL; + } + + arrLoadInfo[nLoadInfos].rectP = &_parmsR.rectA[i]; + arrLoadInfo[nLoadInfos].top = _parmsR.rectA[i].top; + arrLoadInfo[nLoadInfos].left = _parmsR.rectA[i].left; + arrLoadInfo[nLoadInfos].bottom = _parmsR.rectA[i].bottom; + arrLoadInfo[nLoadInfos].right = _parmsR.rectA[i].right; + + if (arrLoadInfo[nLoadInfos].right > m_nWidth) arrLoadInfo[nLoadInfos].right = m_nWidth; + if (arrLoadInfo[nLoadInfos].bottom > m_nHeight) arrLoadInfo[nLoadInfos].bottom = m_nHeight; + + arrLoadInfo[nLoadInfos].width = arrLoadInfo[nLoadInfos].right - arrLoadInfo[nLoadInfos].left; + arrLoadInfo[nLoadInfos].height = arrLoadInfo[nLoadInfos].bottom - arrLoadInfo[nLoadInfos].top; + + ++nLoadInfos; + } + else + { + if (!_parmsR.prevTexB) + _parmsR.rectA[i].pTexture = NULL; + } + } + } + else + { + nLoadInfos = 1; + arrLoadInfo = new LoadInfo[1]; + arrLoadInfo[0].widthP = _parmsR.widthP; + arrLoadInfo[0].heightP = _parmsR.heightP; + arrLoadInfo[0].prevTexP = _parmsR.prevTexP; + arrLoadInfo[0].rectP = NULL; + arrLoadInfo[0].top = 0; + arrLoadInfo[0].left = 0; + arrLoadInfo[0].bottom = m_nHeight; + arrLoadInfo[0].right = m_nWidth; + arrLoadInfo[0].width = m_nWidth; + arrLoadInfo[0].height = m_nHeight; + } + + bool bSkipAll = true; + + // loop creating surfaces + {for (unsigned i=0; ileft,pLoadInfo->top,pLoadInfo->right,pLoadInfo->bottom)); + db_logf5(("\treference count on input surface %u",_parmsR.loadTextureB ? GetRefCount(pLoadInfo->prevTexP.textureP) : GetRefCount(pLoadInfo->prevTexP.surfaceP))); + + // determine what the width and height of the surface will be + + if (_parmsR.loadTextureB || fMyFlags & AW_TLF_TEXTURE) + { + awTlLastErr = + AwGetTextureSize + ( + &pLoadInfo->surface_width, + &pLoadInfo->surface_height, + fMyFlags & AW_TLF_MINSIZE && pLoadInfo->rectP ? pLoadInfo->rectP->right - pLoadInfo->rectP->left : pLoadInfo->width, + fMyFlags & AW_TLF_MINSIZE && pLoadInfo->rectP ? pLoadInfo->rectP->bottom - pLoadInfo->rectP->top : pLoadInfo->height + ); + if (awTlLastErr != AW_TLE_OK) + goto EXIT_WITH_ERROR; + } + else + { + pLoadInfo->surface_width = fMyFlags & AW_TLF_MINSIZE && pLoadInfo->rectP ? pLoadInfo->rectP->right - pLoadInfo->rectP->left : pLoadInfo->width; + pLoadInfo->surface_height = fMyFlags & AW_TLF_MINSIZE && pLoadInfo->rectP ? pLoadInfo->rectP->bottom - pLoadInfo->rectP->top : pLoadInfo->height; + #if 1 // not sure if this is required... + pLoadInfo->surface_width += 3; + pLoadInfo->surface_width &= ~3; + pLoadInfo->surface_height += 3; + pLoadInfo->surface_height &= ~3; + #endif + } + + if (pLoadInfo->widthP) *pLoadInfo->widthP = pLoadInfo->surface_width; + if (pLoadInfo->heightP) *pLoadInfo->heightP = pLoadInfo->surface_height; + + // Create DD Surface + + DD_SURFACE_DESC ddsd; + INITDXSTRUCT(ddsd); + ddsd.ddpfPixelFormat = pixelFormat.ddpf; + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; + if (_parmsR.loadTextureB || fMyFlags & AW_TLF_TEXTURE) + pLoadInfo->dwCapsCaps = DDSCAPS_TEXTURE | (fMyFlags & (AW_TLF_COMPRESS|AW_TLF_TEXTURE) ? DDSCAPS_SYSTEMMEMORY : driverDesc.memFlag); + else + pLoadInfo->dwCapsCaps = DDSCAPS_OFFSCREENPLAIN | (fMyFlags & AW_TLF_VIDMEM ? DDSCAPS_VIDEOMEMORY : DDSCAPS_SYSTEMMEMORY); + ddsd.ddsCaps.dwCaps = pLoadInfo->dwCapsCaps; + ddsd.dwHeight = pLoadInfo->surface_height; + ddsd.dwWidth = pLoadInfo->surface_width; + + #if MIPMAPTEST + /* + D3DPTEXTURECAPS_POW2 + All nonmipmapped textures must have widths and heights specified as powers of two if this flag is set. + (Note that all mipmapped textures must always have dimensions that are powers of two.) + */ + if (128==pLoadInfo->surface_width && 128==pLoadInfo->surface_height) + { + ddsd.ddsCaps.dwCaps |= DDSCAPS_MIPMAP | DDSCAPS_COMPLEX; + ddsd.dwFlags |= DDSD_MIPMAPCOUNT; + ddsd.dwMipMapCount = 3; + } + #endif + + if (pLoadInfo->prevTexP.voidP && (!_parmsR.loadTextureB || !(fMyFlags & AW_TLF_COMPRESS))) + { + if (_parmsR.loadTextureB) + awTlLastDxErr = pLoadInfo->prevTexP.textureP->QueryInterface(GUID_DD_SURFACE,(LPVOID *)&pLoadInfo->surfaceP); + else + awTlLastDxErr = pLoadInfo->prevTexP.surfaceP->QueryInterface(GUID_DD_SURFACE,(LPVOID *)&pLoadInfo->surfaceP); + HANDLE_DXERROR("getting direct draw surface interface") + #if DB_LEVEL >= 5 + if (_parmsR.loadTextureB) + db_logf5(("\t\tnow prev tex ref %u new surface i/f ref %u",GetRefCount(pLoadInfo->prevTexP.textureP),GetRefCount(pLoadInfo->surfaceP))); + else + db_logf5(("\t\tnow prev surf ref %u new surface i/f ref %u",GetRefCount(pLoadInfo->prevTexP.surfaceP),GetRefCount(pLoadInfo->surfaceP))); + #endif + + // check for lost surfaces + if (fMyFlags & AW_TLF_CHECKLOST) + { + awTlLastDxErr = pLoadInfo->surfaceP->IsLost(); + + if (DDERR_SURFACELOST == awTlLastDxErr) + { + db_log4("\tRestoring Lost Surface"); + + awTlLastDxErr = pLoadInfo->surfaceP->Restore(); + } + else if (DD_OK == awTlLastDxErr && (fMyFlags & AW_TLF_SKIPNOTLOST)) + { + db_log4("\tSkipping Surface which was not Lost"); + + pLoadInfo->skipB = true; + } + + HANDLE_DXERROR("testing for lost surface and restoring if necessary"); + } + + if (!pLoadInfo->skipB) + { + // check that the surface desc is OK + // note that SetSurfaceDesc is *only* supported for changing the surface memory pointer + DD_SURFACE_DESC old_ddsd; + INITDXSTRUCT(old_ddsd); + awTlLastDxErr = pLoadInfo->surfaceP->GetSurfaceDesc(&old_ddsd); + HANDLE_DXERROR("getting previous surface desc") + // check width, height, RGBBitCount and memory type + 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)) + { + 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) + { + unsigned bpp = 0; + if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) + bpp = 8; + else if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4) + bpp = 4; + else if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED2) + bpp = 2; + else if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED1) + bpp = 1; + else if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_RGB) + bpp = old_ddsd.ddpfPixelFormat.dwRGBBitCount; + if (pixelFormat.bitsPerPixel != bpp) + awTlLastErr = AW_TLE_CANTRELOAD; + } + else + awTlLastErr = AW_TLE_CANTRELOAD; + } + else + awTlLastErr = AW_TLE_CANTRELOAD; + if (AW_TLE_OK != awTlLastErr) + { + db_log1("AwCreateGraphic() failed because existing surface is incompatible"); + goto EXIT_WITH_ERROR; + } + } + else + { + pLoadInfo->surfaceP->Release(); + pLoadInfo->surfaceP = NULL; + } + } + else + { + if (pLoadInfo->prevTexP.voidP && (fMyFlags & AW_TLF_CHECKLOST)) + { + db_assert1(_parmsR.loadTextureB); + + awTlLastDxErr = pLoadInfo->prevTexP.textureP->QueryInterface(GUID_DD_SURFACE,(LPVOID *)&pLoadInfo->surfaceP); + HANDLE_DXERROR("getting direct draw surface interface") + + db_logf5(("\t\tnow prev tex ref %u new surface i/f ref %u",GetRefCount(pLoadInfo->prevTexP.textureP),GetRefCount(pLoadInfo->surfaceP))); + + awTlLastDxErr = pLoadInfo->surfaceP->IsLost(); + + if (DDERR_SURFACELOST == awTlLastDxErr) + { + db_log4("\tRestoring Lost Surface"); + + awTlLastDxErr = pLoadInfo->surfaceP->Restore(); + } + else if (DD_OK == awTlLastDxErr && (fMyFlags & AW_TLF_SKIPNOTLOST)) + { + db_log4("\tSkipping Surface which was not Lost"); + + pLoadInfo->skipB = true; + } + + HANDLE_DXERROR("testing for lost surface and restoring if necessary"); + + pLoadInfo->surfaceP->Release(); + pLoadInfo->surfaceP = NULL; + } + + if (!pLoadInfo->skipB) + { + do + { + awTlLastDxErr = driverDesc.ddP->CreateSurface(&ddsd,&pLoadInfo->surfaceP,NULL); + } + while + ( + DDERR_OUTOFVIDEOMEMORY == awTlLastDxErr + && _parmsR.callbackF + && _parmsR.callbackF(_parmsR.callbackParam) + ); + + HANDLE_DXERROR("creating direct draw surface") + } + } + + if (pLoadInfo->skipB) + { + db_assert1(pLoadInfo->prevTexP.voidP); + + // skipping so result is same as input + pLoadInfo->resultP = pLoadInfo->prevTexP; + + if (_parmsR.loadTextureB) + pLoadInfo->prevTexP.textureP->AddRef(); + else + pLoadInfo->prevTexP.surfaceP->AddRef(); + } + + #if MIPMAPTEST + if (128==surface_width && 128==surface_height) + { + // test if we can get attached surfaces... + DDSCAPS ddscaps; + ZEROFILL(ddscaps); + ddscaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP; + DDSurface * mip2P; + awTlLastDxErr = pLoadInfo->surfaceP->GetAttachedSurface(&ddscaps,&mip2P); + HANDLE_DXERROR("getting first mipmap") + DDSurface * mip3P; + awTlLastDxErr = mip2P->GetAttachedSurface(&ddscaps,&mip3P); + HANDLE_DXERROR("getting second mipmap") + db_logf5(("\tabout to release 2nd mip with ref %u",GetRefCount(mip2P))); + db_code1(refcnt =) + mip2P->Release(); + db_onlyassert1(1==refcnt); + db_logf5(("\tabout to release 3nd mip with ref %u",GetRefCount(mip3P))); + db_code1(refcnt =) + mip3P->Release(); + db_onlyassert1(1==refcnt); + } + #endif + + bSkipAll = bSkipAll && pLoadInfo->skipB; + }} + + if (!bSkipAll) + { + Colour * paletteP = m_nPaletteSize ? GetPalette() : NULL; + + unsigned y = 0; + bool reversed_rowsB = AreRowsReversed(); + if (reversed_rowsB) + { + y = m_nHeight-1; + } + + for (unsigned rowcount = m_nHeight; rowcount; --rowcount) + { + PtrUnion src_rowP = GetRowPtr(y); + db_assert1(src_rowP.voidP); + + // allow loading of the next row from the file + LoadNextRow(src_rowP); + + // loop for copying data to surfaces + for (unsigned i=0; iskipB) + { + // are we in the vertical range of this surface? + if (y>=pLoadInfo->top && ybottom) + { + if (!pLoadInfo->surface_lockedB) + { + // lock the surfaces + DD_SURFACE_DESC ddsd; + INITDXSTRUCT(ddsd); + awTlLastDxErr = pLoadInfo->surfaceP->Lock(NULL,&ddsd,DDLOCK_WRITEONLY|DDLOCK_NOSYSLOCK,NULL); + HANDLE_DXERROR("locking direct draw surface") + pLoadInfo->surface_lockedB = true; + pLoadInfo->surface_dataP.voidP = ddsd.lpSurface; + pLoadInfo->surface_dataP.byteP += ddsd.lPitch * (y-pLoadInfo->top); + pLoadInfo->surface_pitch = ddsd.lPitch; + } + + // convert and copy the section of the row to the direct draw surface + ConvertRow(pLoadInfo->surface_dataP,pLoadInfo->surface_width,src_rowP,pLoadInfo->left,pLoadInfo->width,paletteP db_code1(DB_COMMA m_nPaletteSize)); + + // do the bottom row twice if the dd surface is bigger + if (pLoadInfo->bottom-1 == y && pLoadInfo->surface_height > pLoadInfo->height) + { + PtrUnion next_surface_rowP = pLoadInfo->surface_dataP; + next_surface_rowP.byteP += pLoadInfo->surface_pitch; + ConvertRow(next_surface_rowP,pLoadInfo->surface_width,src_rowP,pLoadInfo->left,pLoadInfo->width,paletteP db_code1(DB_COMMA m_nPaletteSize)); + } + + // next ddsurface row + if (reversed_rowsB) + pLoadInfo->surface_dataP.byteP -= pLoadInfo->surface_pitch; + else + pLoadInfo->surface_dataP.byteP += pLoadInfo->surface_pitch; + } + else if (pLoadInfo->surface_lockedB) + { + // unlock the surface + awTlLastDxErr = pLoadInfo->surfaceP->Unlock(NULL); + HANDLE_DXERROR("unlocking direct draw surface") + pLoadInfo->surface_lockedB = false; + } + } + } + + // next row + if (reversed_rowsB) + --y; + else + ++y; + + if (AW_TLE_OK != awTlLastErr) + { + db_log1("AwCreateGraphic() failed whilst copying data to direct draw surface"); + goto EXIT_WITH_ERROR; + } + } + + // create a palette for the surfaces if there is one + DWORD palcreateflags = 0; + PALETTEENTRY colour_tableA[256]; + if (pixelFormat.palettizedB) + { + if (!_parmsR.loadTextureB && !(fMyFlags & AW_TLF_TEXTURE)) + { + db_log3("AwCreateGraphic(): WARNING: setting a palette on a DD surface may have no effect"); + } + + #if 0 + if (m_bTranspMask) + { + colour_tableA[0].peRed = 0; + colour_tableA[0].peGreen = 0; + colour_tableA[0].peBlue = 0; + colour_tableA[0].peFlags = 0; + for (unsigned i=1; iCreatePalette(palcreateflags,colour_tableA,&dd_paletteP,NULL); + HANDLE_DXERROR("creating palette for direct draw surface") + } + + {for (unsigned i=0; iskipB) + { + // unlock the surface + if (pLoadInfo->surface_lockedB) + { + awTlLastDxErr = pLoadInfo->surfaceP->Unlock(NULL); + HANDLE_DXERROR("unlocking direct draw surface") + pLoadInfo->surface_lockedB = false; + } + + if (pixelFormat.palettizedB) + { + // set the palette on the surface + awTlLastDxErr = pLoadInfo->surfaceP->SetPalette(dd_paletteP); + HANDLE_DXERROR("setting palette on direct draw surface") + } + } + + }} + + if (pixelFormat.palettizedB) + { + db_logf5(("\tabout to release palette with ref %u",GetRefCount(dd_paletteP))); + dd_paletteP->Release(); + dd_paletteP = NULL; + } + + DWORD dwColourKey; + DDCOLORKEY invis; + // get colour for chroma keying if required + if (m_bTranspMask && (!pixelFormat.alphaB || fMyFlags & AW_TLF_CHROMAKEY)) + { + dwColourKey = GetTransparentColour(); + invis.dwColorSpaceLowValue = dwColourKey; + invis.dwColorSpaceHighValue = dwColourKey; + } + + {for (unsigned i=0; iskipB) + { + // do the copying crap and Texture::Load() stuff - see CopyD3DTexture in d3_func.cpp + + if (_parmsR.loadTextureB) + { + // get a texture pointer + awTlLastDxErr = pLoadInfo->surfaceP->QueryInterface(GUID_D3D_TEXTURE,(LPVOID *)&pLoadInfo->textureP); + HANDLE_DXERROR("getting texture interface on direct draw surface") + db_logf5(("\t\tnow surface ref %u texture ref %u",GetRefCount(pLoadInfo->surfaceP),GetRefCount(pLoadInfo->textureP))); + + if (fMyFlags & AW_TLF_COMPRESS) // deal with Texture::Load and ALLOCONLOAD flag + { + if (pLoadInfo->prevTexP.voidP) + { + // load into the existing texture + awTlLastDxErr = pLoadInfo->prevTexP.textureP->QueryInterface(GUID_DD_SURFACE,(LPVOID *)&pLoadInfo->dst_surfaceP); + HANDLE_DXERROR("getting direct draw surface interface") + db_logf5(("\t\tnow prev texture ref %u dst surface ref %u",GetRefCount(pLoadInfo->prevTexP.textureP),GetRefCount(pLoadInfo->dst_surfaceP))); + // check that the surface desc is OK + // note that SetSurfaceDesc is *only* supported for changing the surface memory pointer + DD_SURFACE_DESC old_ddsd; + INITDXSTRUCT(old_ddsd); + awTlLastDxErr = pLoadInfo->surfaceP->GetSurfaceDesc(&old_ddsd); + HANDLE_DXERROR("getting previous surface desc") + // check width, height, RGBBitCount and memory type + 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)) + { + 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) + { + unsigned bpp = 0; + if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) + bpp = 8; + else if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4) + bpp = 4; + else if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED2) + bpp = 2; + else if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED1) + bpp = 1; + else if (old_ddsd.ddpfPixelFormat.dwFlags & DDPF_RGB) + bpp = old_ddsd.ddpfPixelFormat.dwRGBBitCount; + if (pixelFormat.bitsPerPixel != bpp) + awTlLastErr = AW_TLE_CANTRELOAD; + } + else + awTlLastErr = AW_TLE_CANTRELOAD; + } + else + awTlLastErr = AW_TLE_CANTRELOAD; + if (AW_TLE_OK != awTlLastErr) + { + db_log1("AwCreateGraphic() failed because existing surface is incompatible"); + goto EXIT_WITH_ERROR; + } + } + else + { + DD_SURFACE_DESC ddsd; + + INITDXSTRUCT(ddsd); + + awTlLastDxErr = pLoadInfo->surfaceP->GetSurfaceDesc(&ddsd); + HANDLE_DXERROR("getting direct draw surface desc") + + ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY; + ddsd.ddsCaps.dwCaps |= DDSCAPS_ALLOCONLOAD | driverDesc.memFlag; + do + { + awTlLastDxErr = driverDesc.ddP->CreateSurface(&ddsd,&pLoadInfo->dst_surfaceP,NULL); + } + while + ( + DDERR_OUTOFVIDEOMEMORY == awTlLastDxErr + && _parmsR.callbackF + && _parmsR.callbackF(_parmsR.callbackParam) + ); + HANDLE_DXERROR("creating destination direct draw surface") + } + + // create a zero palette if required -> Texture::Load() will copy in correct palette + if (pixelFormat.palettizedB) + { + memset(colour_tableA,0,sizeof colour_tableA); + + awTlLastDxErr = driverDesc.ddP->CreatePalette(palcreateflags,colour_tableA,&dd_paletteP,NULL); + HANDLE_DXERROR("creating palette for destination direct draw surface") + awTlLastDxErr = pLoadInfo->dst_surfaceP->SetPalette(dd_paletteP); + HANDLE_DXERROR("setting palette on destination direct draw surface") + db_logf5(("\tabout to release dest palette with ref %u",GetRefCount(dd_paletteP))); + dd_paletteP->Release(); + dd_paletteP = NULL; + } + + // get a texture pointer on the destination + awTlLastDxErr = pLoadInfo->dst_surfaceP->QueryInterface(GUID_D3D_TEXTURE,(LPVOID *)&pLoadInfo->dst_textureP); + HANDLE_DXERROR("getting texture interface on destination direct draw surface") + db_logf5(("\t\tnow dst surface ref %u dst texture ref %u",GetRefCount(pLoadInfo->dst_surfaceP),GetRefCount(pLoadInfo->dst_textureP))); + + do + { + awTlLastDxErr = pLoadInfo->dst_textureP->Load(pLoadInfo->textureP); + } + while + ( + DDERR_OUTOFVIDEOMEMORY == awTlLastDxErr + && _parmsR.callbackF + && _parmsR.callbackF(_parmsR.callbackParam) + ); + HANDLE_DXERROR("loading texture into destination") + + // release src texture and surface, and set pointers to point to dst texture and surface + db_logf5(("\tabout to release internal surface with ref %u",GetRefCount(pLoadInfo->surfaceP))); + db_code1(refcnt =) + pLoadInfo->surfaceP->Release(); + db_onlyassert1(1==refcnt); + pLoadInfo->surfaceP = pLoadInfo->dst_surfaceP; + pLoadInfo->dst_surfaceP = NULL; + + db_logf5(("\tabout to release internal texture i/f with ref %u",GetRefCount(pLoadInfo->textureP))); + db_code1(refcnt =) + pLoadInfo->textureP->Release(); + db_onlyassert1(!refcnt); + pLoadInfo->textureP = pLoadInfo->dst_textureP; + pLoadInfo->dst_textureP = NULL; + } + } + + // set chroma keying if required + if (m_bTranspMask && (!pixelFormat.alphaB || fMyFlags & AW_TLF_CHROMAKEY)) + { + awTlLastDxErr = pLoadInfo->surfaceP->SetColorKey(DDCKEY_SRCBLT,&invis); + HANDLE_DXERROR("setting the colour key") + } + + if (_parmsR.loadTextureB) + { + // release the direct draw interface: + // since the textureP was obtained with a call + // to QueryInterface on the surface (increasing + // its referenc count), this wont actually release + // the surface + + db_logf5(("\tabout to release surface i/f with ref %u",GetRefCount(pLoadInfo->surfaceP))); + db_code1(refcnt =) + pLoadInfo->surfaceP->Release(); + pLoadInfo->surfaceP = NULL; + // if loading into a previous texture, refcnt may be two or more, our ref and the ref passed to us + db_onlyassert1(1==refcnt|| pLoadInfo->prevTexP.voidP); + + pLoadInfo->resultP = pLoadInfo->textureP; + } + else + { + db_assert1(pLoadInfo->surfaceP); + + DDSurface * pSurfaceReturn = NULL; + + awTlLastDxErr = pLoadInfo->surfaceP->QueryInterface(GUID_DD_SURFACE, (LPVOID *)&pSurfaceReturn); + HANDLE_DXERROR("getting the required DDSurface interface") + db_logf5(("\t\tnow surface ref %u return surface ref %u",GetRefCount(pLoadInfo->surfaceP),GetRefCount(pSurfaceReturn))); + + pLoadInfo->resultP = pSurfaceReturn; + } + } + }} + + // release the IDirectDrawSurface interfaces if returning DDSurface interfaces + if (!_parmsR.loadTextureB) + { + for (unsigned i=0; iRelease(); + } + } + } + } + + // OK + db_log4("AwCreateGraphic() OK"); + + SurfUnion pRet = static_cast(NULL); + + if (!_parmsR.rectA) + { + // if loading the entire graphic as one surface/texture, return pointer to that + pRet = arrLoadInfo[0].resultP; + } + else + { + // return NULL, but fill in the pTexture or pSurface members of the AwCreateGraphicRegion + for (unsigned i=0; irectP); + + if (_parmsR.loadTextureB) + { + if (pLoadInfo->prevTexP.voidP) + { + db_assert1(pLoadInfo->prevTexP.textureP == pLoadInfo->rectP->pTexture); + db_assert1(pLoadInfo->resultP.textureP == pLoadInfo->rectP->pTexture); + db_logf5(("\tabout to release duplicate texture i/f with ref %u",GetRefCount(pLoadInfo->resultP.textureP))); + pLoadInfo->resultP.textureP->Release(); + } + else + { + pLoadInfo->rectP->pTexture = pLoadInfo->resultP.textureP; + } + db_logf5(("\tresultant texture for region with ref count %u",GetRefCount(pLoadInfo->rectP->pTexture))); + } + else + { + if (pLoadInfo->prevTexP.voidP) + { + db_assert1(pLoadInfo->prevTexP.surfaceP == pLoadInfo->rectP->pSurface); + db_assert1(pLoadInfo->resultP.surfaceP == pLoadInfo->rectP->pSurface); + db_logf5(("\tabout to release duplicate surface i/f with ref %u",GetRefCount(pLoadInfo->resultP.surfaceP))); + pLoadInfo->resultP.surfaceP->Release(); + } + else + { + pLoadInfo->rectP->pSurface = pLoadInfo->resultP.surfaceP; + } + db_logf5(("\tresultant texture for surface with ref count %u",GetRefCount(pLoadInfo->rectP->pSurface))); + } + } + } + delete[] arrLoadInfo; + + #if DB_LEVEL >= 5 + if (_parmsR.loadTextureB) + db_logf5(("AwCreateGraphic(): returning texture with ref cnt %u",GetRefCount(pRet.textureP))); + else + db_logf5(("AwCreateGraphic(): returning surface with ref cnt %u",GetRefCount(pRet.surfaceP))); + #endif + + return pRet; + } + + EXIT_WITH_ERROR: + { + + db_logf2(("AwCreateGraphic(): ERROR: %s",AwTlErrorToString())); + + if (arrLoadInfo) + { + for (unsigned i=0; idst_textureP), + GetRefCount(pLoadInfo->dst_surfaceP), + GetRefCount(pLoadInfo->textureP), + GetRefCount(pLoadInfo->surfaceP))); + + if (pLoadInfo->dst_textureP) + { + pLoadInfo->dst_textureP->Release(); + } + if (pLoadInfo->textureP) + { + pLoadInfo->textureP->Release(); + } + if (pLoadInfo->dst_surfaceP) + { + pLoadInfo->dst_surfaceP->Release(); + } + if (pLoadInfo->surfaceP) + { + if (pLoadInfo->surface_lockedB) + pLoadInfo->surfaceP->Unlock(NULL); + db_code1(refcnt =) + pLoadInfo->surfaceP->Release(); + db_onlyassert1(!refcnt); + } + + if (pLoadInfo->rectP) + { + pLoadInfo->rectP->width = 0; + pLoadInfo->rectP->height = 0; + } + } + + delete[] arrLoadInfo; + } + + if (dd_paletteP) + { + db_code1(refcnt =) + dd_paletteP->Release(); + db_onlyassert1(!refcnt); + } + + return static_cast(NULL); + } +} + +void AwBackupTexture::OnBeginRestoring(unsigned nMaxPaletteSize) +{ + if (nMaxPaletteSize && (nMaxPaletteSize < m_nPaletteSize || !m_nPaletteSize)) + { + awTlLastErr = AW_TLE_CANTPALETTIZE; + db_logf3(("AwCreateGraphic(): [restoring] ERROR: Palette size is %u, require %u",m_nPaletteSize,nMaxPaletteSize)); + } +} + +bool AwBackupTexture::AreRowsReversed() +{ + return false; +} + +void AwBackupTexture::ConvertRow(AwTl::PtrUnion pDest, unsigned nDestWidth, AwTl::PtrUnionConst pSrc, unsigned nSrcOffset, unsigned nSrcWidth, AwTl::Colour * pPalette db_code1(DB_COMMA unsigned nPaletteSize)) +{ + using namespace AwTl; + + if (pPalette) + { + if (pixelFormat.palettizedB) + { + GenericConvertRow::Do(pDest,nDestWidth,pSrc.byteP+nSrcOffset,nSrcWidth); + } + else + { + if (m_bTranspMask) + GenericConvertRow::Do(pDest,nDestWidth,pSrc.byteP+nSrcOffset,nSrcWidth,pPalette db_code1(DB_COMMA nPaletteSize)); + else + GenericConvertRow::Do(pDest,nDestWidth,pSrc.byteP+nSrcOffset,nSrcWidth,pPalette db_code1(DB_COMMA nPaletteSize)); + } + } + else + { + if (m_bTranspMask) + GenericConvertRow::Do(pDest,nDestWidth,pSrc.colourP+nSrcOffset,nSrcWidth); + else + GenericConvertRow::Do(pDest,nDestWidth,pSrc.colourP+nSrcOffset,nSrcWidth); + } +} + +void AwBackupTexture::OnFinishRestoring(bool) +{ +} + +namespace AwTl { + + Colour * TypicalBackupTexture::GetPalette() + { + return m_pPalette; + } + + PtrUnion TypicalBackupTexture::GetRowPtr(unsigned nRow) + { + return m_ppPixMap[nRow]; + } + + void TypicalBackupTexture::LoadNextRow(PtrUnion) + { + // already loaded + } + + unsigned TypicalBackupTexture::GetNumColours() + { + return m_nPaletteSize; + } + + unsigned TypicalBackupTexture::GetMinPaletteSize() + { + return m_nPaletteSize; + } + + + SurfUnion TexFileLoader::Load(MediaMedium * pMedium, CreateTextureParms const & rParams) + { + m_fFlags = rParams.flags; + + awTlLastErr = AW_TLE_OK; + + LoadHeaderInfo(pMedium); + + CHECK_MEDIA_ERRORS("loading file headers") + ON_ERROR_RETURN_NULL("loading file headers") + + ChoosePixelFormat(rParams); + + if (!pixelFormat.validB) + db_log3("AwCreateGraphic(): ERROR: pixel format not valid"); + if (!driverDesc.ddP || !driverDesc.validB && rParams.loadTextureB) + db_log3("AwCreateGraphic(): ERROR: driver description not valid"); + + awTlLastErr = pixelFormat.validB && driverDesc.ddP && (driverDesc.validB || !rParams.loadTextureB) ? AW_TLE_OK : AW_TLE_NOINIT; + + ON_ERROR_RETURN_NULL("initializing load") + + AllocateBuffers(rParams.backupHP ? true : false, pixelFormat.palettizedB ? 1<Release(); + else + pTex.surfaceP->Release(); + pTex.voidP = NULL; + } + else + { + db_assert1(rParams.rectA); + + for (unsigned i=0; ipTexture->Release(); + else + pRect->pSurface->Release(); + } + pRect->width = 0; + pRect->height = 0; + } + } + db_logf1(("AwCreateGraphic(): ERROR: %s",AwTlErrorToString())); + bOK = false; + } + + OnFinishLoading(bOK); + + if (bOK && rParams.backupHP) + { + *rParams.backupHP = CreateBackupTexture(); + } + + return pTex; + } + + void TexFileLoader::OnFinishLoading(bool) + { + } + + + TypicalTexFileLoader::~TypicalTexFileLoader() + { + if (m_pPalette) + { + delete[] m_pPalette; + + if (m_pRowBuf) delete[] m_pRowBuf.byteP; + if (m_ppPixMap) + { + delete[] m_ppPixMap->byteP; + delete[] m_ppPixMap; + } + } + else + { + if (m_pRowBuf) delete[] m_pRowBuf.colourP; + if (m_ppPixMap) + { + delete[] m_ppPixMap->colourP; + delete[] m_ppPixMap; + } + } + } + + unsigned TypicalTexFileLoader::GetNumColours() + { + return m_nPaletteSize; + } + + unsigned TypicalTexFileLoader::GetMinPaletteSize() + { + return m_nPaletteSize; + } + + void TypicalTexFileLoader::AllocateBuffers(bool bWantBackup, unsigned /*nMaxPaletteSize*/) + { + if (m_nPaletteSize) + { + m_pPalette = new Colour [ m_nPaletteSize ]; + } + + if (bWantBackup) + { + m_ppPixMap = new PtrUnion [m_nHeight]; + if (m_nPaletteSize) + { + m_ppPixMap->byteP = new BYTE [m_nHeight*m_nWidth]; + BYTE * pRow = m_ppPixMap->byteP; + for (unsigned y=1;ycolourP = new Colour [m_nHeight*m_nWidth]; + Colour * pRow = m_ppPixMap->colourP; + for (unsigned y=1;y(&rlcAwBmpLoader_187); + + mfidt.hack += reinterpret_cast(&rlcAwIffLoader_428); + mfidt.hack += reinterpret_cast(&rlcAwIffLoader_429); + mfidt.hack += reinterpret_cast(&rlcAwIffLoader_430); + + mfidt.hack += reinterpret_cast(&rlcAwPpmLoader_229); + mfidt.hack += reinterpret_cast(&rlcAwPgmLoader_230); + mfidt.hack += reinterpret_cast(&rlcAwPbmLoader_231); + + mfidt.hack += reinterpret_cast(&rccIlbmBmhdChunk_4); + mfidt.hack += reinterpret_cast(&rccIlbmCmapChunk_5); + mfidt.hack += reinterpret_cast(&rccIlbmBodyChunk_6); + mfidt.hack += reinterpret_cast(&rccIlbmGrabChunk_7); + } +#endif + g_pMagicFileIdTree = &mfidt; + + MagicFileIdTree * pLayer = g_pMagicFileIdTree; + + while (*pszMagic) + { + BYTE c = static_cast(*pszMagic++); + + if (!pLayer->m_arrNextLayer[c]) + pLayer->m_arrNextLayer[c] = new MagicFileIdTree; + + pLayer = pLayer->m_arrNextLayer[c]; + } + + db_assert1(!pLayer->m_pfnCreate); + + pLayer->m_pfnCreate = pfnCreate; + } + + static + TexFileLoader * CreateLoaderObject(MediaMedium * pMedium) + { + TexFileLoader * (* pfnBest) () = NULL; + + signed nMoveBack = 0; + + BYTE c; + + MagicFileIdTree * pLayer = g_pMagicFileIdTree; + + while (pLayer) + { + if (pLayer->m_pfnCreate) + pfnBest = pLayer->m_pfnCreate; + + MediaRead(pMedium,&c); + + -- nMoveBack; + + pLayer = pLayer->m_arrNextLayer[c]; + } + + pMedium->MovePos(nMoveBack); + + if (pfnBest) + return pfnBest(); + else + return NULL; + } + + /**********************************/ + /* These are the loader functions */ + /**********************************/ + + static inline SurfUnion DoLoadTexture(MediaMedium * pMedium, CreateTextureParms const & rParams) + { + TexFileLoader * pLoader = CreateLoaderObject(pMedium); + + if (!pLoader) + { + awTlLastErr = AW_TLE_BADFILEFORMAT; + db_log1("AwCreateGraphic(): ERROR: file format not recognized"); + return static_cast(NULL); + } + else + { + SurfUnion pTex = pLoader->Load(pMedium,rParams); + pLoader->Release(); + return pTex; + } + } + + static inline SurfUnion LoadTexture(MediaMedium * pMedium, CreateTextureParms const & _parmsR) + { + if (_parmsR.bytesReadP||_parmsR.maxReadBytes!=UINT_MAX) + { + MediaSection * pMedSect = new MediaSection; + pMedSect->Open(pMedium,_parmsR.maxReadBytes); + SurfUnion pTex = DoLoadTexture(pMedSect,_parmsR); + pMedSect->Close(); + if (_parmsR.bytesReadP) *_parmsR.bytesReadP = pMedSect->GetUsedSize(); + delete pMedSect; + return pTex; + } + else + { + return DoLoadTexture(pMedium,_parmsR); + } + } + + SurfUnion CreateTextureParms::DoCreate() const + { + if (INVALID_HANDLE_VALUE!=fileH) + { + MediaWinFileMedium * pMedium = new MediaWinFileMedium; + pMedium->Attach(fileH); + SurfUnion pTex = LoadTexture(pMedium,*this); + pMedium->Detach(); + pMedium->Release(); + return pTex; + } + else if (dataP) + { + MediaMemoryReadMedium * pMedium = new MediaMemoryReadMedium; + pMedium->Open(dataP); + SurfUnion pTex = LoadTexture(pMedium,*this); + pMedium->Close(); + pMedium->Release(); + return pTex; + } + else + { + db_assert1(restoreH); + return restoreH->Restore(*this); + } + } + + #if DB_LEVEL >= 4 + static void LogPrimCaps(LPD3DPRIMCAPS _pcP, bool _triB) + { + #define DEVCAP(mask,can_or_does,explanation) \ + db_logf4(("\t\t" can_or_does "%s " explanation, _pcP->MEMBER & (mask) ? "" : "not")); + + #define MEMBER dwMiscCaps + DEVCAP(D3DPMISCCAPS_CONFORMANT,"Does ","conform to OpenGL standard") + if (_triB) + { + DEVCAP(D3DPMISCCAPS_CULLCCW,"Does ","support counterclockwise culling through the D3DRENDERSTATE_CULLMODE state") + DEVCAP(D3DPMISCCAPS_CULLCW,"Does ","support clockwise triangle culling through the D3DRENDERSTATE_CULLMODE state") + db_logf4(("\t\tDoes %s perform triangle culling", _pcP->dwMiscCaps & (D3DPMISCCAPS_CULLNONE) ? "not" : "")); + } + else + { + DEVCAP(D3DPMISCCAPS_LINEPATTERNREP,"Can","handle values other than 1 in the wRepeatFactor member of the D3DLINEPATTERN structure") + } + DEVCAP(D3DPMISCCAPS_MASKPLANES,"Can","perform a bitmask of color planes") + DEVCAP(D3DPMISCCAPS_MASKZ,"Can","enable and disable modification of the z-buffer on pixel operations") + #undef MEMBER + #define MEMBER dwRasterCaps + DEVCAP(D3DPRASTERCAPS_ANISOTROPY,"Does ","support anisotropic filtering") + DEVCAP(D3DPRASTERCAPS_ANTIALIASEDGES,"Can","antialias lines forming the convex outline of objects") + DEVCAP(D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT,"Does","support antialiasing that is dependent on the sort order of the polygons") + DEVCAP(D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT,"Does","support antialiasing that is not dependent on the sort order of the polygons") + DEVCAP(D3DPRASTERCAPS_DITHER,"Can","dither to improve color resolution") + DEVCAP(D3DPRASTERCAPS_FOGRANGE,"Does ","support range-based fog") + DEVCAP(D3DPRASTERCAPS_FOGTABLE,"Does ","calculate the fog value by referring to a lookup table containing fog values that are indexed to the depth of a given pixel") + DEVCAP(D3DPRASTERCAPS_FOGVERTEX,"Does ","calculate the fog value during the lighting operation") + DEVCAP(D3DPRASTERCAPS_MIPMAPLODBIAS,"Does ","support level-of-detail (LOD) bias adjustments") + DEVCAP(D3DPRASTERCAPS_PAT,"Can","perform patterned drawing for the primitive being queried") + DEVCAP(D3DPRASTERCAPS_ROP2,"Can","support raster operations other than R2_COPYPEN") + DEVCAP(D3DPRASTERCAPS_STIPPLE,"Can","stipple polygons to simulate translucency") + DEVCAP(D3DPRASTERCAPS_SUBPIXEL,"Does ","perform subpixel placement of z, color, and texture data, rather than working with the nearest integer pixel coordinate") + DEVCAP(D3DPRASTERCAPS_SUBPIXELX,"Is ","subpixel accurate along the x-axis only and is clamped to an integer y-axis scan line") + DEVCAP(D3DPRASTERCAPS_XOR,"Can","support XOR operations") + DEVCAP(D3DPRASTERCAPS_ZBIAS,"Does ","support z-bias values") + DEVCAP(D3DPRASTERCAPS_ZBUFFERLESSHSR,"Can","perform hidden-surface removal without requiring the application to sort polygons, and without requiring the allocation of a z-buffer") + DEVCAP(D3DPRASTERCAPS_ZTEST,"Can","perform z-test operations") + #undef MEMBER + #define MEMBER dwZCmpCaps + DEVCAP(D3DPCMPCAPS_ALWAYS,"Can","always pass the z test") + DEVCAP(D3DPCMPCAPS_EQUAL,"Can","pass the z test if the new z equals the current z") + DEVCAP(D3DPCMPCAPS_GREATER,"Can","pass the z test if the new z is greater than the current z") + DEVCAP(D3DPCMPCAPS_GREATEREQUAL,"Can","pass the z test if the new z is greater than or equal to the current z") + DEVCAP(D3DPCMPCAPS_LESS,"Can","pass the z test if the new z is less than the current z") + DEVCAP(D3DPCMPCAPS_LESSEQUAL,"Can","pass the z test if the new z is less than or equal to the current z") + DEVCAP(D3DPCMPCAPS_NEVER,"Can","always fail the z test") + DEVCAP(D3DPCMPCAPS_NOTEQUAL,"Can","pass the z test if the new z does not equal the current z") + #undef MEMBER + #define MEMBER dwSrcBlendCaps + DEVCAP(D3DPBLENDCAPS_BOTHINVSRCALPHA,"Can","source blend with source blend factor of (1-As, 1-As, 1-As, 1-As) and destination blend factor of (As, As, As, As); the destination blend selection is overridden") + DEVCAP(D3DPBLENDCAPS_BOTHSRCALPHA,"Can","source blend with source blend factor of (As, As, As, As) and destination blend factor of (1-As, 1-As, 1-As, 1-As); the destination blend selection is overridden") + DEVCAP(D3DPBLENDCAPS_DESTALPHA,"Can","source blend with blend factor of (Ad, Ad, Ad, Ad)") + DEVCAP(D3DPBLENDCAPS_DESTCOLOR,"Can","source blend with blend factor of (Rd, Gd, Bd, Ad)") + DEVCAP(D3DPBLENDCAPS_INVDESTALPHA,"Can","source blend with blend factor of (1-Ad, 1-Ad, 1-Ad, 1-Ad)") + DEVCAP(D3DPBLENDCAPS_INVDESTCOLOR,"Can","source blend with blend factor of (1-Rd, 1-Gd, 1-Bd, 1-Ad)") + DEVCAP(D3DPBLENDCAPS_INVSRCALPHA,"Can","source blend with blend factor of (1-As, 1-As, 1-As, 1-As)") + DEVCAP(D3DPBLENDCAPS_INVSRCCOLOR,"Can","source blend with blend factor of (1-Rd, 1-Gd, 1-Bd, 1-Ad)") + DEVCAP(D3DPBLENDCAPS_ONE,"Can","source blend with blend factor of (1, 1, 1, 1)") + DEVCAP(D3DPBLENDCAPS_SRCALPHA,"Can","source blend with blend factor of (As, As, As, As)") + DEVCAP(D3DPBLENDCAPS_SRCALPHASAT,"Can","source blend with blend factor of (f, f, f, 1); f = min(As, 1-Ad).") + DEVCAP(D3DPBLENDCAPS_SRCCOLOR,"Can","source blend with blend factor of (Rs, Gs, Bs, As)") + DEVCAP(D3DPBLENDCAPS_ZERO,"Can","source blend with blend factor of (0, 0, 0, 0)") + #undef MEMBER + #define MEMBER dwDestBlendCaps + DEVCAP(D3DPBLENDCAPS_BOTHINVSRCALPHA,"Can","destination blend with source blend factor of (1-As, 1-As, 1-As, 1-As) and destination blend factor of (As, As, As, As); the destination blend selection is overridden") + DEVCAP(D3DPBLENDCAPS_BOTHSRCALPHA,"Can","destination blend with source blend factor of (As, As, As, As) and destination blend factor of (1-As, 1-As, 1-As, 1-As); the destination blend selection is overridden") + DEVCAP(D3DPBLENDCAPS_DESTALPHA,"Can","destination blend with blend factor of (Ad, Ad, Ad, Ad)") + DEVCAP(D3DPBLENDCAPS_DESTCOLOR,"Can","destination blend with blend factor of (Rd, Gd, Bd, Ad)") + DEVCAP(D3DPBLENDCAPS_INVDESTALPHA,"Can","destination blend with blend factor of (1-Ad, 1-Ad, 1-Ad, 1-Ad)") + DEVCAP(D3DPBLENDCAPS_INVDESTCOLOR,"Can","destination blend with blend factor of (1-Rd, 1-Gd, 1-Bd, 1-Ad)") + DEVCAP(D3DPBLENDCAPS_INVSRCALPHA,"Can","destination blend with blend factor of (1-As, 1-As, 1-As, 1-As)") + DEVCAP(D3DPBLENDCAPS_INVSRCCOLOR,"Can","destination blend with blend factor of (1-Rd, 1-Gd, 1-Bd, 1-Ad)") + DEVCAP(D3DPBLENDCAPS_ONE,"Can","destination blend with blend factor of (1, 1, 1, 1)") + DEVCAP(D3DPBLENDCAPS_SRCALPHA,"Can","destination blend with blend factor of (As, As, As, As)") + DEVCAP(D3DPBLENDCAPS_SRCALPHASAT,"Can","destination blend with blend factor of (f, f, f, 1); f = min(As, 1-Ad)") + DEVCAP(D3DPBLENDCAPS_SRCCOLOR,"Can","destination blend with blend factor of (Rs, Gs, Bs, As)") + DEVCAP(D3DPBLENDCAPS_ZERO,"Can","destination blend with blend factor of (0, 0, 0, 0)") + #undef MEMBER + #define MEMBER dwAlphaCmpCaps + DEVCAP(D3DPCMPCAPS_ALWAYS,"Can","always pass the alpha test") + DEVCAP(D3DPCMPCAPS_EQUAL,"Can","pass the alpha test if the new alpha equals the current alpha") + DEVCAP(D3DPCMPCAPS_GREATER,"Can","pass the alpha test if the new alpha is greater than the current alpha") + DEVCAP(D3DPCMPCAPS_GREATEREQUAL,"Can","pass the alpha test if the new alpha is greater than or equal to the current alpha") + DEVCAP(D3DPCMPCAPS_LESS,"Can","pass the alpha test if the new alpha is less than the current alpha") + DEVCAP(D3DPCMPCAPS_LESSEQUAL,"Can","pass the alpha test if the new alpha is less than or equal to the current alpha") + DEVCAP(D3DPCMPCAPS_NEVER,"Can","always fail the alpha test") + DEVCAP(D3DPCMPCAPS_NOTEQUAL,"Can","pass the alpha test if the new alpha does not equal the current alpha") + #undef MEMBER + #define MEMBER dwShadeCaps + DEVCAP(D3DPSHADECAPS_ALPHAFLATBLEND,"Can","support an alpha component for flat blended transparency") + DEVCAP(D3DPSHADECAPS_ALPHAFLATSTIPPLED,"Can","support an alpha component for flat stippled transparency") + DEVCAP(D3DPSHADECAPS_ALPHAGOURAUDBLEND,"Can","support an alpha component for Gouraud blended transparency") + DEVCAP(D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED,"Can","support an alpha component for Gouraud stippled transparency") + DEVCAP(D3DPSHADECAPS_ALPHAPHONGBLEND,"Can","support an alpha component for Phong blended transparency") + DEVCAP(D3DPSHADECAPS_ALPHAPHONGSTIPPLED,"Can","support an alpha component for Phong stippled transparency") + DEVCAP(D3DPSHADECAPS_COLORFLATMONO,"Can","support colored flat shading in the D3DCOLOR_MONO color model") + DEVCAP(D3DPSHADECAPS_COLORFLATRGB,"Can","support colored flat shading in the D3DCOLOR_RGB color model") + DEVCAP(D3DPSHADECAPS_COLORGOURAUDMONO,"Can","support colored flat shading in the D3DCOLOR_MONO color model") + DEVCAP(D3DPSHADECAPS_COLORGOURAUDRGB,"Can","support colored Gouraud shading in the D3DCOLOR_RGB color model") + DEVCAP(D3DPSHADECAPS_COLORPHONGMONO,"Can","support colored Phong shading in the D3DCOLOR_MONO color model") + DEVCAP(D3DPSHADECAPS_COLORPHONGRGB,"Can","support colored Phong shading in the D3DCOLOR_RGB color model") + DEVCAP(D3DPSHADECAPS_FOGFLAT,"Can","support fog in the flat shading model") + DEVCAP(D3DPSHADECAPS_FOGGOURAUD,"Can","support fog in the Gouraud shading model") + DEVCAP(D3DPSHADECAPS_FOGPHONG,"Can","support fog in the Phong shading model") + DEVCAP(D3DPSHADECAPS_SPECULARFLATMONO,"Can","support specular highlights in flat shading in the D3DCOLOR_MONO color model") + DEVCAP(D3DPSHADECAPS_SPECULARFLATRGB,"Can","support specular highlights in flat shading in the D3DCOLOR_RGB color model") + DEVCAP(D3DPSHADECAPS_SPECULARGOURAUDMONO,"Can","support specular highlights in Gouraud shading in the D3DCOLOR_MONO color model") + DEVCAP(D3DPSHADECAPS_SPECULARGOURAUDRGB,"Can","support specular highlights in Gouraud shading in the D3DCOLOR_RGB color model") + DEVCAP(D3DPSHADECAPS_SPECULARPHONGMONO,"Can","support specular highlights in Phong shading in the D3DCOLOR_MONO color model") + DEVCAP(D3DPSHADECAPS_SPECULARPHONGRGB,"Can","support specular highlights in Phong shading in the D3DCOLOR_RGB color model") + #undef MEMBER + #define MEMBER dwTextureCaps + DEVCAP(D3DPTEXTURECAPS_ALPHA,"Does ","support RGBA textures in the D3DTEX_DECAL and D3DTEX_MODULATE texture filtering modes") + DEVCAP(D3DPTEXTURECAPS_BORDER,"Does ","support texture mapping along borders") + DEVCAP(D3DPTEXTURECAPS_PERSPECTIVE,"Does ","support perspective correction") + DEVCAP(D3DPTEXTURECAPS_POW2,"Does ","require all nonmipmapped textures to have widths and heights specified as powers of two") + DEVCAP(D3DPTEXTURECAPS_SQUAREONLY,"Does ","require all textures to be square") + DEVCAP(D3DPTEXTURECAPS_TRANSPARENCY,"Does ","support texture transparency") + #undef MEMBER + #define MEMBER dwTextureFilterCaps + DEVCAP(D3DPTFILTERCAPS_LINEAR,"Can","use a weighted average of a 2x2 area of texels surrounding the desired pixel") + DEVCAP(D3DPTFILTERCAPS_LINEARMIPLINEAR,"Can","use a weighted average of a 2x2 area of texels, and also interpolate between mipmaps") + DEVCAP(D3DPTFILTERCAPS_LINEARMIPNEAREST,"Can","use a weighted average of a 2x2 area of texels, and also use a mipmap") + DEVCAP(D3DPTFILTERCAPS_MIPLINEAR,"Can","choose two mipmaps whose texels most closely match the size of the pixel to be textured, and interpolate between them") + DEVCAP(D3DPTFILTERCAPS_MIPNEAREST,"Can","use an appropriate mipmap for texel selection") + DEVCAP(D3DPTFILTERCAPS_NEAREST,"Can","use the texel with coordinates nearest to the desired pixel value is used") + #undef MEMBER + #define MEMBER dwTextureBlendCaps + DEVCAP(D3DPTBLENDCAPS_ADD,"Can","use the additive texture-blending mode") + DEVCAP(D3DPTBLENDCAPS_COPY,"Can","use copy mode texture-blending") + DEVCAP(D3DPTBLENDCAPS_DECAL,"Can","use decal texture-blending mode") + DEVCAP(D3DPTBLENDCAPS_DECALALPHA,"Can","use decal-alpha texture-blending mode") + DEVCAP(D3DPTBLENDCAPS_DECALMASK,"Can","use decal-mask texture-blending mode") + DEVCAP(D3DPTBLENDCAPS_MODULATE,"Can","use modulate texture-blending mode") + DEVCAP(D3DPTBLENDCAPS_MODULATEALPHA,"Can","use modulate-alpha texture-blending mode") + DEVCAP(D3DPTBLENDCAPS_MODULATEMASK,"Can","use modulate-mask texture-blending mode") + #undef MEMBER + #define MEMBER dwTextureAddressCaps + DEVCAP(D3DPTADDRESSCAPS_BORDER,"Does ","support setting coordinates outside the range [0.0, 1.0] to the border color") + DEVCAP(D3DPTADDRESSCAPS_CLAMP,"Can","clamp textures to addresses") + DEVCAP(D3DPTADDRESSCAPS_INDEPENDENTUV,"Can","separate the texture-addressing modes of the U and V coordinates of the texture") + DEVCAP(D3DPTADDRESSCAPS_MIRROR,"Can","mirror textures to addresses") + DEVCAP(D3DPTADDRESSCAPS_WRAP,"Can","wrap textures to addresses") + #undef MEMBER + #undef DEVCAP + db_logf4(("\t\tMaximum size of the supported stipple is %u x %u",_pcP->dwStippleWidth,_pcP->dwStippleHeight)); + } + static void LogCaps(LPD3DDEVICEDESC _descP) + { + if (_descP->dwFlags & D3DDD_BCLIPPING) + { + db_logf4(("\tCan%s perform 3D clipping",_descP->bClipping ? "" : "not")); + } + else db_log4("\tHas unknown 3D clipping capability"); + + if (_descP->dwFlags & D3DDD_COLORMODEL) + { + db_logf4(("\tCan%s use mono (ramp) colour model",_descP->dcmColorModel & D3DCOLOR_MONO ? "" : "not")); + db_logf4(("\tCan%s use full RGB colour model",_descP->dcmColorModel & D3DCOLOR_RGB ? "" : "not")); + } + else db_log4("\tHas unknown colour model"); + + if (_descP->dwFlags & D3DDD_DEVCAPS) + { + #define DEVCAP(mask,can_or_does,explanation) \ + db_logf4(("\t" can_or_does "%s " explanation,_descP->dwDevCaps & (mask) ? "" : "not")); + + DEVCAP(D3DDEVCAPS_CANRENDERAFTERFLIP,"Can","queue rendering commands after a page flip") + DEVCAP(D3DDEVCAPS_DRAWPRIMTLVERTEX,"Does ","export a DrawPrimitive-aware HAL") + DEVCAP(D3DDEVCAPS_EXECUTESYSTEMMEMORY,"Can","use execute buffers from system memory") + DEVCAP(D3DDEVCAPS_EXECUTEVIDEOMEMORY,"Can","use execute buffer from video memory") + DEVCAP(D3DDEVCAPS_FLOATTLVERTEX,"Does ","accept floating point for post-transform vertex data") + DEVCAP(D3DDEVCAPS_SORTDECREASINGZ,"Does ","need Z data sorted for decreasing depth") + DEVCAP(D3DDEVCAPS_SORTEXACT,"Does ","need data sorted exactly") + DEVCAP(D3DDEVCAPS_SORTINCREASINGZ,"Does ","need data sorted for increasing depth") + DEVCAP(D3DDEVCAPS_TEXTURENONLOCALVIDMEM,"Can","retrieve textures from nonlocal video (AGP) memory") + DEVCAP(D3DDEVCAPS_TEXTURESYSTEMMEMORY,"Can","retrieve textures from system memory") + DEVCAP(D3DDEVCAPS_TEXTUREVIDEOMEMORY,"Can","retrieve textures from device memory") + DEVCAP(D3DDEVCAPS_TLVERTEXSYSTEMMEMORY,"Can","use buffers from system memory for transformed and lit vertices") + DEVCAP(D3DDEVCAPS_TLVERTEXVIDEOMEMORY,"Can","use buffers from video memory for transformed and lit vertices") + + #undef DEVCAP + } + else db_log4("\tHas unknown device capabilities"); + + if (_descP->dwFlags & D3DDD_DEVICERENDERBITDEPTH) + { + #define DEVCAP(mask,explanation) \ + db_logf4(("\tCan%s render to "explanation" surface",_descP->dwDeviceRenderBitDepth & (mask) ? "" : "not")); + + DEVCAP(DDBD_8,"an 8-bit") + DEVCAP(DDBD_16,"a 16-bit") + DEVCAP(DDBD_24,"a 24-bit") + DEVCAP(DDBD_32,"a 32-bit") + + #undef DEVCAP + } + else db_log4("\tHas unknown rendering target bitdepth requirements"); + + if (_descP->dwFlags & D3DDD_DEVICEZBUFFERBITDEPTH) + { + #define DEVCAP(mask,explanation) \ + db_logf4(("\tCan%s use "explanation" Z-buffer",_descP->dwDeviceZBufferBitDepth & (mask) ? "" : "not")); + + DEVCAP(DDBD_8,"an 8-bit") + DEVCAP(DDBD_16,"a 16-bit") + DEVCAP(DDBD_24,"a 24-bit") + DEVCAP(DDBD_32,"a 32-bit") + + #undef DEVCAP + } + else db_log4("\tHas unknown Z-buffer bitdepth requirements"); + + if (_descP->dwFlags & D3DDD_TRANSFORMCAPS) + { + db_log4("\tTransform capabilities are known"); + } + else db_log4("\tHas unknown transform capabilities"); + + if (_descP->dwFlags & D3DDD_LIGHTINGCAPS) + { + db_log4("\tLighting capabilities are known"); + } + else db_log4("\tHas unknown lighting capabilities"); + + if (_descP->dwFlags & D3DDD_LINECAPS) + { + db_log4("\tLine drawing capabilities follow"); + LogPrimCaps(&_descP->dpcLineCaps,false); + } + else db_log4("\tHas unknown line drawing capabilities"); + + if (_descP->dwFlags & D3DDD_TRICAPS) + { + db_log4("\tTriangle rendering capabilities follow"); + LogPrimCaps(&_descP->dpcTriCaps,true); + } + else db_log4("\tHas unknown triangle rendering capabilities"); + + if (_descP->dwFlags & D3DDD_MAXBUFFERSIZE) + { + unsigned max_exb = _descP->dwMaxBufferSize; + if (!max_exb) max_exb = UINT_MAX; + db_logf4(("\tMaximum execute buffer size is %u",max_exb)); + } + else db_log4("\tHas unknown maximum execute buffer size"); + + if (_descP->dwFlags & D3DDD_MAXVERTEXCOUNT) + { + db_logf4(("\tMaximum vertex count is %u",_descP->dwMaxVertexCount)); + } + else db_log4("\tHas unknown maximum vertex count"); + + unsigned max_tw = _descP->dwMaxTextureWidth; + unsigned max_th = _descP->dwMaxTextureHeight; + unsigned max_sw = _descP->dwMaxStippleWidth; + unsigned max_sh = _descP->dwMaxStippleHeight; + if (!max_tw) max_tw = UINT_MAX; + if (!max_th) max_th = UINT_MAX; + if (!max_sw) max_sw = UINT_MAX; + if (!max_sh) max_sh = UINT_MAX; + + db_logf4(("\tMinimum texture size is %u x %u",_descP->dwMinTextureWidth,_descP->dwMinTextureHeight)); + db_logf4(("\tMaximum texture size is %u x %u",max_tw,max_th)); + db_logf4(("\tMinimum stipple size is %u x %u",_descP->dwMinStippleWidth,_descP->dwMinStippleHeight)); + db_logf4(("\tMaximum stipple size is %u x %u",max_sw,max_sh)); + } + #endif + + // Parse the format string and get the parameters + + static bool ParseParams(CreateTextureParms * pParams, char const * _argFormatS, va_list ap) + { + bool bad_parmsB = false; + db_code2(unsigned ch_off = 0;) + db_code2(char ch = 0;) + + while (*_argFormatS && !bad_parmsB) + { + db_code2(++ch_off;) + db_code2(ch = *_argFormatS;) + switch (*_argFormatS++) + { + case 's': + if (pParams->fileNameS || INVALID_HANDLE_VALUE!=pParams->fileH || pParams->dataP || pParams->restoreH) + bad_parmsB = true; + else + { + pParams->fileNameS = va_arg(ap,LPCTSTR); + db_logf4(("\tFilename = \"%s\"",pParams->fileNameS)); + } + break; + case 'h': + if (pParams->fileNameS || INVALID_HANDLE_VALUE!=pParams->fileH || pParams->dataP || pParams->restoreH) + bad_parmsB = true; + else + { + pParams->fileH = va_arg(ap,HANDLE); + db_logf4(("\tFile HANDLE = 0x%08x",pParams->fileH)); + } + break; + case 'p': + if (pParams->fileNameS || INVALID_HANDLE_VALUE!=pParams->fileH || pParams->dataP || pParams->restoreH) + bad_parmsB = true; + else + { + pParams->dataP = va_arg(ap,void const *); + db_logf4(("\tData Pointer = %p",pParams->dataP)); + } + break; + case 'r': + if (pParams->fileNameS || INVALID_HANDLE_VALUE!=pParams->fileH || pParams->dataP || pParams->restoreH || UINT_MAX!=pParams->maxReadBytes || pParams->bytesReadP || pParams->backupHP) + bad_parmsB = true; + else + { + pParams->restoreH = va_arg(ap,AW_BACKUPTEXTUREHANDLE); + db_logf4(("\tRestore Handle = 0x%08x",pParams->restoreH)); + } + break; + case 'x': + if (UINT_MAX!=pParams->maxReadBytes || pParams->restoreH) + bad_parmsB = true; + else + { + pParams->maxReadBytes = va_arg(ap,unsigned); + db_logf4(("\tMax bytes to read = %u",pParams->maxReadBytes)); + } + break; + case 'N': + if (pParams->bytesReadP || pParams->restoreH) + bad_parmsB = true; + else + { + pParams->bytesReadP = va_arg(ap,unsigned *); + db_logf4(("\tPtr to bytes read = %p",pParams->bytesReadP)); + } + break; + case 'f': + if (AW_TLF_DEFAULT!=pParams->flags) + bad_parmsB = true; + else + { + pParams->flags = va_arg(ap,unsigned); + db_logf4(("\tFlags = 0x%08x",pParams->flags)); + } + break; + case 'W': + if (pParams->widthP || pParams->rectA) + bad_parmsB = true; + else + { + pParams->widthP = va_arg(ap,unsigned *); + db_logf4(("\tPtr to width = %p",pParams->widthP)); + } + break; + case 'H': + if (pParams->heightP || pParams->rectA) + bad_parmsB = true; + else + { + pParams->heightP = va_arg(ap,unsigned *); + db_logf4(("\tPtr to height = %p",pParams->heightP)); + } + break; + case 'X': + if (pParams->originalWidthP) + bad_parmsB = true; + else + { + pParams->originalWidthP = va_arg(ap,unsigned *); + db_logf4(("\tPtr to image width = %p",pParams->originalWidthP)); + } + break; + case 'Y': + if (pParams->originalHeightP) + bad_parmsB = true; + else + { + pParams->originalHeightP = va_arg(ap,unsigned *); + db_logf4(("\tPtr to image height = %p",pParams->originalHeightP)); + } + break; + case 'B': + if (pParams->backupHP || pParams->restoreH) + bad_parmsB = true; + else + { + pParams->backupHP = va_arg(ap,AW_BACKUPTEXTUREHANDLE *); + db_logf4(("\tPtr to backup handle = %p",pParams->backupHP)); + } + break; + case 't': + if (pParams->prevTexP.voidP) + bad_parmsB = true; + else if (pParams->rectA) + { + pParams->prevTexB = true; + db_log4("\tPrevious DDSurface * or D3DTexture * in rectangle array"); + } + else if (pParams->loadTextureB) + { + pParams->prevTexP = va_arg(ap,D3DTexture *); + db_logf4(("\tPrevious D3DTexture * = %p",pParams->prevTexP.textureP)); + } + else + { + pParams->prevTexP = va_arg(ap,DDSurface *); + db_logf4(("\tPrevious DDSurface * = %p",pParams->prevTexP.surfaceP)); + } + break; + case 'c': + if (pParams->callbackF) + bad_parmsB = true; + else + { + pParams->callbackF = va_arg(ap,AW_TL_PFN_CALLBACK); + pParams->callbackParam = va_arg(ap,void *); + db_logf4(("\tCallback function = %p, param = %p",pParams->callbackF,pParams->callbackParam)); + } + break; + case 'a': + if (pParams->prevTexP.voidP || pParams->rectA || pParams->widthP || pParams->heightP) + bad_parmsB = true; + else + { + pParams->numRects = va_arg(ap,unsigned); + pParams->rectA = va_arg(ap,AwCreateGraphicRegion *); + db_logf4(("\tRectangle array = %p, size = %u",pParams->rectA,pParams->numRects)); + } + break; + default: + bad_parmsB = true; + } + } + + if (!pParams->fileNameS && INVALID_HANDLE_VALUE==pParams->fileH && !pParams->dataP && !pParams->restoreH) + { + awTlLastErr = AW_TLE_BADPARMS; + db_log2("AwCreateGraphic(): ERROR: No data medium is specified"); + return false; + } + else if (bad_parmsB) + { + awTlLastErr = AW_TLE_BADPARMS; + db_logf2(("AwCreateGraphic(): ERROR: Unexpected '%c' in format string at character %u",ch,ch_off)); + return false; + } + else + { + db_log5("\tParameters are OK"); + return true; + } + } + + // Use the parameters parsed to load the surface or texture + + SurfUnion LoadFromParams(CreateTextureParms * pParams) + { + if (pParams->fileNameS) + { + pParams->fileH = CreateFile(pParams->fileNameS,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); + + if (INVALID_HANDLE_VALUE==pParams->fileH) + { + awTlLastErr = AW_TLE_CANTOPENFILE; + awTlLastWinErr = GetLastError(); + db_logf1(("AwCreateGraphic(): ERROR opening file \"%s\"",pParams->fileNameS)); + db_log2(AwTlErrorToString()); + return static_cast(NULL); + } + + SurfUnion textureP = pParams->DoCreate(); + + CloseHandle(pParams->fileH); + + return textureP; + } + else return pParams->DoCreate(); + } + +} // namespace AwTl + +/******************************/ +/* PUBLIC: AwSetTextureFormat */ +/******************************/ + +#define IS_VALID_MEMBER(sP,mem) (reinterpret_cast(&(sP)->mem) - reinterpret_cast(sP) < static_cast((sP)->dwSize)) + +#if defined(__WATCOMC__) && (__WATCOMC__ <= 1100) // currently Watcom compiler crashes when the macro is expanded with the db_logf code in it +#define GET_VALID_MEMBER(sP,mem,deflt) (IS_VALID_MEMBER(sP,mem) ? (sP)->mem : (deflt)) +#else +#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))) +#endif + +#define HANDLE_INITERROR(test,s) \ + if (!(test)) { \ + db_logf3((FUNCTION_NAME " failed becuse %s",s)); \ + db_log1(FUNCTION_NAME ": ERROR: unexpected parameters"); \ + return AW_TLE_BADPARMS; \ + } else { \ + db_logf5(("\t" FUNCTION_NAME " passed check '%s'",#test )); \ + } + +#define FUNCTION_NAME "AwSetD3DDevice()" + +AW_TL_ERC AwSetD3DDevice(D3DDevice * _d3ddeviceP) +{ + using AwTl::driverDesc; + + driverDesc.validB = false; + + db_logf4(("AwSetD3DDevice(%p) called",_d3ddeviceP)); + + HANDLE_INITERROR(_d3ddeviceP,"D3DDevice * is NULL") + + D3DDEVICEDESC hw_desc; + D3DDEVICEDESC hel_desc; + INITDXSTRUCT(hw_desc); + INITDXSTRUCT(hel_desc); + + awTlLastDxErr = _d3ddeviceP->GetCaps(&hw_desc,&hel_desc); + if (DD_OK != awTlLastDxErr) + { + db_logf2(("AwSetD3DDevice(): ERROR: %s",AwDxErrorToString())); + return AW_TLE_DXERROR; + } + + db_log4("Direct3D Device Hardware Capabilities:"); + db_code4(AwTl::LogCaps(&hw_desc);) + db_log4("Direct3D Device Emulation Capabilities:"); + db_code4(AwTl::LogCaps(&hel_desc);) + + LPD3DDEVICEDESC descP = (GET_VALID_MEMBER(&hw_desc,dwFlags,0) & D3DDD_COLORMODEL && GET_VALID_MEMBER(&hw_desc,dcmColorModel,0) & (D3DCOLOR_RGB|D3DCOLOR_MONO)) ? &hw_desc : &hel_desc; + db_logf4(("Direct3D Device is %s",&hw_desc==descP ? "HAL" : "emulation only")); + + HANDLE_INITERROR(GET_VALID_MEMBER(descP,dwFlags,0) & D3DDD_DEVCAPS && IS_VALID_MEMBER(descP,dwDevCaps),"LPD3DDEVICEDESC::dwDevCaps is not valid") + HANDLE_INITERROR(descP->dwDevCaps & (D3DDEVCAPS_TEXTUREVIDEOMEMORY|D3DDEVCAPS_TEXTURENONLOCALVIDMEM|D3DDEVCAPS_TEXTURESYSTEMMEMORY),"Textures cannot be in ANY type of memory") + + driverDesc.memFlag = descP->dwDevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY ? DDSCAPS_SYSTEMMEMORY : DDSCAPS_VIDEOMEMORY; + driverDesc.minWidth = GET_VALID_MEMBER(descP,dwMinTextureWidth,0); + driverDesc.minHeight = GET_VALID_MEMBER(descP,dwMinTextureHeight,0); + driverDesc.maxWidth = GET_VALID_MEMBER(descP,dwMaxTextureWidth,0); + driverDesc.maxHeight = GET_VALID_MEMBER(descP,dwMaxTextureHeight,0); + driverDesc.needPow2B = GET_VALID_MEMBER(descP,dpcTriCaps.dwTextureCaps,0) & D3DPTEXTURECAPS_POW2 ? true : false; + driverDesc.needSquareB = GET_VALID_MEMBER(descP,dpcTriCaps.dwTextureCaps,0) & D3DPTEXTURECAPS_SQUAREONLY ? true : false; + // if max w and h are 0, make them as large as possible + if (!driverDesc.maxWidth) driverDesc.maxWidth = UINT_MAX; + if (!driverDesc.maxHeight) driverDesc.maxHeight = UINT_MAX; + + db_log4("AwSetD3DDevice() OK"); + + db_log4("Direct 3D Device texture characteristics follow:"); + db_logf4(("\tMinimum texture size: %u x %u",driverDesc.minWidth,driverDesc.minHeight)); + db_logf4(("\tMaximum texture size: %u x %u",driverDesc.maxWidth,driverDesc.maxHeight)); + db_logf4(("\tTextures %s be sqaure",driverDesc.needSquareB ? "must" : "need not")); + db_logf4(("\tTextures %s be a power of two in width and height",driverDesc.needPow2B ? "must" : "need not")); + db_logf4(("\tTextures can%s be in non-local video (AGP) memory",descP->dwDevCaps & D3DDEVCAPS_TEXTURENONLOCALVIDMEM ? "" : "not")); + db_logf4(("\tTextures can%s be in local video (device) memory",descP->dwDevCaps & D3DDEVCAPS_TEXTUREVIDEOMEMORY ? "" : "not")); + db_logf4(("\tTextures can%s be in system memory",descP->dwDevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY ? "" : "not")); + db_logf4(("\tTextures will be in %s memory",driverDesc.memFlag & DDSCAPS_SYSTEMMEMORY ? "system" : "video")); + + driverDesc.validB = true; + + return AW_TLE_OK; +} + +AW_TL_ERC AwSetDDObject(DDObject * _ddP) +{ + using AwTl::driverDesc; + + db_logf4(("AwSetDDObject(%p) called.",_ddP)); + #ifdef DIRECTDRAW_VERSION + db_logf4(("\tCompiled with DirectDraw Version %u.%u",DIRECTDRAW_VERSION/0x100U,DIRECTDRAW_VERSION%0x100U)); + #else + db_log4("\tCompiled with unknown DirectDraw version"); + #endif + + + HANDLE_INITERROR(_ddP,"DDObject * is NULL") + driverDesc.ddP = _ddP; + + return AW_TLE_OK; +} + +AW_TL_ERC AwSetD3DDevice(DDObject * _ddP, D3DDevice * _d3ddeviceP) +{ + db_logf4(("AwSetD3DDevice(%p,%p) called",_ddP,_d3ddeviceP)); + + AW_TL_ERC iResult = AwSetDDObject(_ddP); + + if (AW_TLE_OK != iResult) + return iResult; + else + return AwSetD3DDevice(_d3ddeviceP); +} + +#undef FUNCTION_NAME +#define FUNCTION_NAME "AwSetPixelFormat()" +static AW_TL_ERC AwSetPixelFormat(AwTl::PixelFormat * _pfP, LPDDPIXELFORMAT _ddpfP) +{ + using AwTl::SetBitShifts; + + _pfP->validB = false; + + // parameter check + HANDLE_INITERROR(_ddpfP,"DDPIXELFORMAT is NULL") + HANDLE_INITERROR(IS_VALID_MEMBER(_ddpfP,dwFlags),"DDPIXELFORMAT::dwFlags is an invalid field") + HANDLE_INITERROR(!(_ddpfP->dwFlags & DDPF_ALPHA),"DDPIXELFORMAT describes an alpha only surface") + HANDLE_INITERROR(!(_ddpfP->dwFlags & DDPF_PALETTEINDEXEDTO8),"DDPIXELFORMAT describes a 1- 2- or 4- bit surface indexed to an 8-bit palette. This is not yet supported") + HANDLE_INITERROR(!(_ddpfP->dwFlags & DDPF_ZBUFFER),"DDPIXELFORMAT describes Z buffer") + HANDLE_INITERROR(!(_ddpfP->dwFlags & DDPF_ZPIXELS),"DDPIXELFORMAT describes a RGBZ surface") + HANDLE_INITERROR(!(_ddpfP->dwFlags & DDPF_YUV),"DDPIXELFORMAT describes a YUV surface. This is not yet supported") + HANDLE_INITERROR(!(_ddpfP->dwFlags & DDPF_FOURCC),"DDPIXELFORMAT gives a FourCC code for a non RGB surface. This is not yet supported") + + _pfP->palettizedB = true; + switch (_ddpfP->dwFlags & (DDPF_PALETTEINDEXED8|DDPF_PALETTEINDEXED4|DDPF_PALETTEINDEXED2|DDPF_PALETTEINDEXED1)) + { + case 0: + _pfP->palettizedB = false; + break; + case DDPF_PALETTEINDEXED1: + _pfP->bitsPerPixel = 1; + break; + case DDPF_PALETTEINDEXED2: + _pfP->bitsPerPixel = 2; + break; + case DDPF_PALETTEINDEXED4: + _pfP->bitsPerPixel = 4; + break; + case DDPF_PALETTEINDEXED8: + _pfP->bitsPerPixel = 8; + break; + default: + db_log1("AwSetPixelFormat(): ERROR: more than one DDPF_PALETTEINDEXED flags is set"); + return AW_TLE_BADPARMS; + } + + _pfP->alphaB = _ddpfP->dwFlags & DDPF_ALPHAPIXELS ? true : false; + + if (_pfP->palettizedB) + { + HANDLE_INITERROR(!_pfP->alphaB,"alpha channel info is on a palettized format. This is not yet supported") + #if DB_LEVEL >= 4 + if (_ddpfP->dwFlags & DDPF_RGB) + { + db_log4(FUNCTION_NAME ": WARNING: RGB data supplied for a palettized format is ignored"); + db_logf4(("\tRGB bitcount is %u",GET_VALID_MEMBER(_ddpfP,dwRGBBitCount,0))); + db_logf4(("\tRed Mask is 0x%08x",GET_VALID_MEMBER(_ddpfP,dwRBitMask,0))); + db_logf4(("\tGreen Mask is 0x%08x",GET_VALID_MEMBER(_ddpfP,dwGBitMask,0))); + db_logf4(("\tBlue Mask is 0x%08x",GET_VALID_MEMBER(_ddpfP,dwBBitMask,0))); + } + #endif + } + else + { + HANDLE_INITERROR(IS_VALID_MEMBER(_ddpfP,dwRGBBitCount),"DDPIXELFORMAT::dwRGBBitCount is an invalid field") + switch (_ddpfP->dwRGBBitCount) + { + case 4: + case 8: + case 16: + case 24: + case 32: + break; + default: + db_log1("AwSetPixelFormat(): ERROR: RGB bit count is not 4,8,16,24 or 32"); + return AW_TLE_BADPARMS; + } + + HANDLE_INITERROR(!_pfP->alphaB || GET_VALID_MEMBER(_ddpfP,dwRGBAlphaBitMask,0),"Pixel format specifies alpha channel info but alpha mask is zero") + HANDLE_INITERROR(IS_VALID_MEMBER(_ddpfP,dwRBitMask),"DDPIXELFORMAT::dwRBitMask is an invalid field") + HANDLE_INITERROR(IS_VALID_MEMBER(_ddpfP,dwGBitMask),"DDPIXELFORMAT::dwGBitMask is an invalid field") + HANDLE_INITERROR(IS_VALID_MEMBER(_ddpfP,dwBBitMask),"DDPIXELFORMAT::dwBBitMask is an invalid field") + + _pfP->bitsPerPixel = _ddpfP->dwRGBBitCount; + SetBitShifts(&_pfP->redLeftShift,&_pfP->redRightShift,_ddpfP->dwRBitMask); + SetBitShifts(&_pfP->greenLeftShift,&_pfP->greenRightShift,_ddpfP->dwGBitMask); + SetBitShifts(&_pfP->blueLeftShift,&_pfP->blueRightShift,_ddpfP->dwBBitMask); + } + ZEROFILL(_pfP->ddpf); + memcpy(&_pfP->ddpf,_ddpfP,__min(_ddpfP->dwSize,sizeof(DDPIXELFORMAT))); + if (!_pfP->alphaB) + _pfP->ddpf.dwRGBAlphaBitMask = 0; + + db_log4("AwSetPixelFormat() OK"); + + #if DB_LEVEL >= 4 + db_logf4(("Pixel Format is %u-bit %s",_pfP->bitsPerPixel,_pfP->palettizedB ? "palettized" : _pfP->alphaB ? "RGBA" : "RGB")); + if (!_pfP->palettizedB) + { + if (_pfP->alphaB) + { + unsigned alpha_l_shft,alpha_r_shft; + SetBitShifts(&alpha_l_shft,&alpha_r_shft,_pfP->ddpf.dwRGBAlphaBitMask); + db_logf4(("\t%u-%u-%u-%u",8-_pfP->redRightShift,8-_pfP->greenRightShift,8-_pfP->blueRightShift,8-alpha_r_shft)); + db_logf4(("\tAlpha->[%u..%u]",alpha_l_shft+7-alpha_r_shft,alpha_l_shft)); + } + else + { + db_logf4(("\t%u-%u-%u",8-_pfP->redRightShift,8-_pfP->greenRightShift,8-_pfP->blueRightShift)); + } + db_logf4(("\tRed->[%u..%u]",_pfP->redLeftShift+7-_pfP->redRightShift,_pfP->redLeftShift)); + db_logf4(("\tGreen->[%u..%u]",_pfP->greenLeftShift+7-_pfP->greenRightShift,_pfP->greenLeftShift)); + db_logf4(("\tBlue->[%u..%u]",_pfP->blueLeftShift+7-_pfP->blueRightShift,_pfP->blueLeftShift)); + } + #endif + + _pfP->validB = true; + return AW_TLE_OK; +} + +AW_TL_ERC AwSetTextureFormat2(LPDDPIXELFORMAT _ddpfP) +{ + db_logf4(("AwSetTextureFormat(%p) called",_ddpfP)); + + using namespace AwTl; + + while (listTextureFormats.size()) + listTextureFormats.delete_first_entry(); + + return AwSetPixelFormat(&pfTextureFormat, _ddpfP); +} + +AW_TL_ERC AwSetAdditionalTextureFormat2(LPDDPIXELFORMAT _ddpfP, unsigned _maxAlphaBits, int _canDoTransp, unsigned _maxColours) +{ + db_logf4(("AwSetAdditionalTextureFormat(%p.%u,%d,%u) called",_ddpfP,_maxAlphaBits,_canDoTransp,_maxColours)); + + using namespace AwTl; + + AdditionalPixelFormat pf; + + AW_TL_ERC erc = AwSetPixelFormat(&pf, _ddpfP); + + if (AW_TLE_OK == erc) + { + pf.canDoTranspB = _canDoTransp ? true : false; + pf.maxColours = _maxColours; + + listTextureFormats.add_entry_end(pf); + } + + return erc; +} + +AW_TL_ERC AwSetSurfaceFormat2(LPDDPIXELFORMAT _ddpfP) +{ + db_logf4(("AwSetSurfaceFormat(%p) called",_ddpfP)); + + using namespace AwTl; + + return AwSetPixelFormat(&pfSurfaceFormat, _ddpfP); +} + +/****************************/ +/* PUBLIC: AwGetTextureSize */ +/****************************/ + +AW_TL_ERC AwGetTextureSize(register unsigned * _widthP, register unsigned * _heightP, unsigned _width, unsigned _height) +{ + db_assert1(_widthP); + db_assert1(_heightP); + + using AwTl::driverDesc; + + if (!driverDesc.validB) + { + db_log3("AwGetTextureSize(): ERROR: driver description not valid"); + return AW_TLE_NOINIT; + } + + if (_width < driverDesc.minWidth) _width = driverDesc.minWidth; + if (_height < driverDesc.minHeight) _height = driverDesc.minHeight; + + if (driverDesc.needPow2B) + { + *_widthP = 1; + while (*_widthP < _width) *_widthP <<= 1; + *_heightP = 1; + while (*_heightP < _height) *_heightP <<= 1; + } + else + { + *_widthP = _width; + *_heightP = _height; + } + + if (driverDesc.needSquareB) + { + if (*_widthP < *_heightP) *_widthP = *_heightP; + else *_heightP = *_widthP; + } + + #if 1 // not sure if this is required... + *_widthP += 3; + *_widthP &= ~3; + *_heightP += 3; + *_heightP &= ~3; + #endif + + db_logf4(("\tAwGetTextureSize(): d3d texture will be %ux%u",*_widthP,*_heightP)); + + if (*_widthP > driverDesc.maxWidth || *_heightP > driverDesc.maxHeight) + { + db_log3("AwGetTextureSize(): ERROR: image size too large to be a d3d texture"); + return AW_TLE_IMAGETOOLARGE; + } + else return AW_TLE_OK; +} + + +/******************************/ +/* PUBLIC: AwCreate functions */ +/******************************/ + +D3DTexture * _AWTL_VARARG AwCreateTexture(char const * _argFormatS, ...) +{ + db_logf4(("AwCreateTexture(\"%s\") called",_argFormatS)); + + using namespace AwTl; + + va_list ap; + va_start(ap,_argFormatS); + CreateTextureParms parms; + parms.loadTextureB = true; + bool bParmsOK = ParseParams(&parms, _argFormatS, ap); + va_end(ap); + return bParmsOK ? LoadFromParams(&parms).textureP : NULL; +} + +DDSurface * _AWTL_VARARG AwCreateSurface(char const * _argFormatS, ...) +{ + db_logf4(("AwCreateSurface(\"%s\") called",_argFormatS)); + + using namespace AwTl; + + va_list ap; + va_start(ap,_argFormatS); + CreateTextureParms parms; + parms.loadTextureB = false; + bool bParmsOK = ParseParams(&parms, _argFormatS, ap); + va_end(ap); + return bParmsOK ? LoadFromParams(&parms).surfaceP : NULL; +} + +AW_TL_ERC AwDestroyBackupTexture(AW_BACKUPTEXTUREHANDLE _bH) +{ + db_logf4(("AwDestroyBackupTexture(0x%08x) called",_bH)); + if (_bH) + { + _bH->Release(); + return AW_TLE_OK; + } + else + { + db_log1("AwDestroyBackupTexture(): ERROR: AW_BACKUPTEXTUREHANDLE==NULL"); + return AW_TLE_BADPARMS; + } +} + +/*********************************/ +/* PUBLIC DEBUG: LastErr globals */ +/*********************************/ + +AW_TL_ERC awTlLastErr; +HRESULT awTlLastDxErr; +DWORD awTlLastWinErr; + +/*******************************************/ +/* PUBLIC DEBUG: AwErrorToString functions */ +/*******************************************/ + +#ifndef NDEBUG +char const * AwWinErrorToString(DWORD error) +{ + if (NO_ERROR==error) return "No error"; + static TCHAR buffer[1024]; + if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,NULL,error,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),buffer,sizeof buffer/sizeof(TCHAR)-1,NULL)) + wsprintf(buffer,TEXT("FormatMessage() failed; previous Windows error code: 0x%08X"),error); + for (TCHAR * bufP = buffer; *bufP; ++bufP) + { + switch (*bufP) + { + case '\n': + case '\r': + *bufP=' '; + } + } + return reinterpret_cast(buffer); +} + +char const * AwTlErrorToString(AwTlErc error) +{ + char const * defaultS; + switch (error) + { + case AW_TLE_OK: + return "No error"; + case AW_TLE_DXERROR: + if (DD_OK==awTlLastDxErr) + return "Unknown DirectX error"; + else + return AwDxErrorToString(); + case AW_TLE_BADPARMS: + return "Invalid parameters or functionality not supported"; + case AW_TLE_NOINIT: + return "Initialization failed or not performed"; + case AW_TLE_CANTOPENFILE: + defaultS = "Unknown error opening file"; + goto WIN_ERR; + case AW_TLE_CANTREADFILE: + defaultS = "Unknown error reading file"; + WIN_ERR: + if (NO_ERROR==awTlLastWinErr) + return defaultS; + else + return AwWinErrorToString(); + case AW_TLE_EOFMET: + return "Unexpected end of file during texture load"; + case AW_TLE_BADFILEFORMAT: + return "Texture file format not recognized"; + case AW_TLE_BADFILEDATA: + return "Texture file data not consistent"; + case AW_TLE_CANTPALETTIZE: + return "Texture file data not palettized"; + case AW_TLE_IMAGETOOLARGE: + return "Image is too large for a texture"; + case AW_TLE_CANTRELOAD: + return "New image is wrong size or format to load into existing texture"; + default: + return "Unknown texture loading error"; + } +} + +char const * AwDxErrorToString(HRESULT error) +{ + switch(error) { + case DD_OK: + return "No error.\0"; + case DDERR_ALREADYINITIALIZED: + return "This object is already initialized.\0"; + case DDERR_BLTFASTCANTCLIP: + return "Return if a clipper object is attached to the source surface passed into a BltFast call.\0"; + case DDERR_CANNOTATTACHSURFACE: + return "This surface can not be attached to the requested surface.\0"; + case DDERR_CANNOTDETACHSURFACE: + return "This surface can not be detached from the requested surface.\0"; + case DDERR_CANTCREATEDC: + return "Windows can not create any more DCs.\0"; + case DDERR_CANTDUPLICATE: + return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created.\0"; + case DDERR_CLIPPERISUSINGHWND: + return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd.\0"; + case DDERR_COLORKEYNOTSET: + return "No src color key specified for this operation.\0"; + case DDERR_CURRENTLYNOTAVAIL: + return "Support is currently not available.\0"; + case DDERR_DIRECTDRAWALREADYCREATED: + return "A DirectDraw object representing this driver has already been created for this process.\0"; + case DDERR_EXCEPTION: + return "An exception was encountered while performing the requested operation.\0"; + case DDERR_EXCLUSIVEMODEALREADYSET: + return "An attempt was made to set the cooperative level when it was already set to exclusive.\0"; + case DDERR_GENERIC: + return "Generic failure.\0"; + case DDERR_HEIGHTALIGN: + return "Height of rectangle provided is not a multiple of reqd alignment.\0"; + case DDERR_HWNDALREADYSET: + return "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or palettes created.\0"; + case DDERR_HWNDSUBCLASSED: + return "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring state.\0"; + case DDERR_IMPLICITLYCREATED: + return "This surface can not be restored because it is an implicitly created surface.\0"; + case DDERR_INCOMPATIBLEPRIMARY: + return "Unable to match primary surface creation request with existing primary surface.\0"; + case DDERR_INVALIDCAPS: + return "One or more of the caps bits passed to the callback are incorrect.\0"; + case DDERR_INVALIDCLIPLIST: + return "DirectDraw does not support the provided cliplist.\0"; + case DDERR_INVALIDDIRECTDRAWGUID: + return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier.\0"; + case DDERR_INVALIDMODE: + return "DirectDraw does not support the requested mode.\0"; + case DDERR_INVALIDOBJECT: + return "DirectDraw received a pointer that was an invalid DIRECTDRAW object.\0"; + case DDERR_INVALIDPARAMS: + return "One or more of the parameters passed to the function are incorrect.\0"; + case DDERR_INVALIDPIXELFORMAT: + return "The pixel format was invalid as specified.\0"; + case DDERR_INVALIDPOSITION: + return "Returned when the position of the overlay on the destination is no longer legal for that destination.\0"; + case DDERR_INVALIDRECT: + return "Rectangle provided was invalid.\0"; + case DDERR_LOCKEDSURFACES: + return "Operation could not be carried out because one or more surfaces are locked.\0"; + case DDERR_NO3D: + return "There is no 3D present.\0"; + case DDERR_NOALPHAHW: + return "Operation could not be carried out because there is no alpha accleration hardware present or available.\0"; + case DDERR_NOBLTHW: + return "No blitter hardware present.\0"; + case DDERR_NOCLIPLIST: + return "No cliplist available.\0"; + case DDERR_NOCLIPPERATTACHED: + return "No clipper object attached to surface object.\0"; + case DDERR_NOCOLORCONVHW: + return "Operation could not be carried out because there is no color conversion hardware present or available.\0"; + case DDERR_NOCOLORKEY: + return "Surface doesn't currently have a color key\0"; + case DDERR_NOCOLORKEYHW: + return "Operation could not be carried out because there is no hardware support of the destination color key.\0"; + case DDERR_NOCOOPERATIVELEVELSET: + return "Create function called without DirectDraw object method SetCooperativeLevel being called.\0"; + case DDERR_NODC: + return "No DC was ever created for this surface.\0"; + case DDERR_NODDROPSHW: + return "No DirectDraw ROP hardware.\0"; + case DDERR_NODIRECTDRAWHW: + return "A hardware-only DirectDraw object creation was attempted but the driver did not support any hardware.\0"; + case DDERR_NOEMULATION: + return "Software emulation not available.\0"; + case DDERR_NOEXCLUSIVEMODE: + return "Operation requires the application to have exclusive mode but the application does not have exclusive mode.\0"; + case DDERR_NOFLIPHW: + return "Flipping visible surfaces is not supported.\0"; + case DDERR_NOGDI: + return "There is no GDI present.\0"; + case DDERR_NOHWND: + return "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND.\0"; + case DDERR_NOMIRRORHW: + return "Operation could not be carried out because there is no hardware present or available.\0"; + case DDERR_NOOVERLAYDEST: + return "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on to establish a destination.\0"; + case DDERR_NOOVERLAYHW: + return "Operation could not be carried out because there is no overlay hardware present or available.\0"; + case DDERR_NOPALETTEATTACHED: + return "No palette object attached to this surface.\0"; + case DDERR_NOPALETTEHW: + return "No hardware support for 16 or 256 color palettes.\0"; + case DDERR_NORASTEROPHW: + return "Operation could not be carried out because there is no appropriate raster op hardware present or available.\0"; + case DDERR_NOROTATIONHW: + return "Operation could not be carried out because there is no rotation hardware present or available.\0"; + case DDERR_NOSTRETCHHW: + return "Operation could not be carried out because there is no hardware support for stretching.\0"; + case DDERR_NOT4BITCOLOR: + return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette.\0"; + case DDERR_NOT4BITCOLORINDEX: + return "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette.\0"; + case DDERR_NOT8BITCOLOR: + return "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color.\0"; + case DDERR_NOTAOVERLAYSURFACE: + return "Returned when an overlay member is called for a non-overlay surface.\0"; + case DDERR_NOTEXTUREHW: + return "Operation could not be carried out because there is no texture mapping hardware present or available.\0"; + case DDERR_NOTFLIPPABLE: + return "An attempt has been made to flip a surface that is not flippable.\0"; + case DDERR_NOTFOUND: + return "Requested item was not found.\0"; + case DDERR_NOTLOCKED: + return "Surface was not locked. An attempt to unlock a surface that was not locked at all, or by this process, has been attempted.\0"; + case DDERR_NOTPALETTIZED: + return "The surface being used is not a palette-based surface.\0"; + case DDERR_NOVSYNCHW: + return "Operation could not be carried out because there is no hardware support for vertical blank synchronized operations.\0"; + case DDERR_NOZBUFFERHW: + return "Operation could not be carried out because there is no hardware support for zbuffer blitting.\0"; + case DDERR_NOZOVERLAYHW: + return "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays.\0"; + case DDERR_OUTOFCAPS: + return "The hardware needed for the requested operation has already been allocated.\0"; + case DDERR_OUTOFMEMORY: + return "DirectDraw does not have enough memory to perform the operation.\0"; + case DDERR_OUTOFVIDEOMEMORY: + return "DirectDraw does not have enough video memory to perform the operation.\0"; + case DDERR_OVERLAYCANTCLIP: + return "The hardware does not support clipped overlays.\0"; + case DDERR_OVERLAYCOLORKEYONLYONEACTIVE: + return "Can only have ony color key active at one time for overlays.\0"; + case DDERR_OVERLAYNOTVISIBLE: + return "Returned when GetOverlayPosition is called on a hidden overlay.\0"; + case DDERR_PALETTEBUSY: + return "Access to this palette is being refused because the palette is already locked by another thread.\0"; + case DDERR_PRIMARYSURFACEALREADYEXISTS: + return "This process already has created a primary surface.\0"; + case DDERR_REGIONTOOSMALL: + return "Region passed to Clipper::GetClipList is too small.\0"; + case DDERR_SURFACEALREADYATTACHED: + return "This surface is already attached to the surface it is being attached to.\0"; + case DDERR_SURFACEALREADYDEPENDENT: + return "This surface is already a dependency of the surface it is being made a dependency of.\0"; + case DDERR_SURFACEBUSY: + return "Access to this surface is being refused because the surface is already locked by another thread.\0"; + case DDERR_SURFACEISOBSCURED: + return "Access to surface refused because the surface is obscured.\0"; + case DDERR_SURFACELOST: + return "Access to this surface is being refused because the surface memory is gone. The DirectDrawSurface object representing this surface should have Restore called on it.\0"; + case DDERR_SURFACENOTATTACHED: + return "The requested surface is not attached.\0"; + case DDERR_TOOBIGHEIGHT: + return "Height requested by DirectDraw is too large.\0"; + case DDERR_TOOBIGSIZE: + return "Size requested by DirectDraw is too large, but the individual height and width are OK.\0"; + case DDERR_TOOBIGWIDTH: + return "Width requested by DirectDraw is too large.\0"; + case DDERR_UNSUPPORTED: + return "Action not supported.\0"; + case DDERR_UNSUPPORTEDFORMAT: + return "FOURCC format requested is unsupported by DirectDraw.\0"; + case DDERR_UNSUPPORTEDMASK: + return "Bitmask in the pixel format requested is unsupported by DirectDraw.\0"; + case DDERR_VERTICALBLANKINPROGRESS: + return "Vertical blank is in progress.\0"; + case DDERR_WASSTILLDRAWING: + return "Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is incomplete.\0"; + case DDERR_WRONGMODE: + return "This surface can not be restored because it was created in a different mode.\0"; + case DDERR_XALIGN: + return "Rectangle provided was not horizontally aligned on required boundary.\0"; + case D3DERR_BADMAJORVERSION: + return "D3DERR_BADMAJORVERSION\0"; + case D3DERR_BADMINORVERSION: + return "D3DERR_BADMINORVERSION\0"; + case D3DERR_EXECUTE_LOCKED: + return "D3DERR_EXECUTE_LOCKED\0"; + case D3DERR_EXECUTE_NOT_LOCKED: + return "D3DERR_EXECUTE_NOT_LOCKED\0"; + case D3DERR_EXECUTE_CREATE_FAILED: + return "D3DERR_EXECUTE_CREATE_FAILED\0"; + case D3DERR_EXECUTE_DESTROY_FAILED: + return "D3DERR_EXECUTE_DESTROY_FAILED\0"; + case D3DERR_EXECUTE_LOCK_FAILED: + return "D3DERR_EXECUTE_LOCK_FAILED\0"; + case D3DERR_EXECUTE_UNLOCK_FAILED: + return "D3DERR_EXECUTE_UNLOCK_FAILED\0"; + case D3DERR_EXECUTE_FAILED: + return "D3DERR_EXECUTE_FAILED\0"; + case D3DERR_EXECUTE_CLIPPED_FAILED: + return "D3DERR_EXECUTE_CLIPPED_FAILED\0"; + case D3DERR_TEXTURE_NO_SUPPORT: + return "D3DERR_TEXTURE_NO_SUPPORT\0"; + case D3DERR_TEXTURE_NOT_LOCKED: + return "D3DERR_TEXTURE_NOT_LOCKED\0"; + case D3DERR_TEXTURE_LOCKED: + return "D3DERR_TEXTURE_LOCKED\0"; + case D3DERR_TEXTURE_CREATE_FAILED: + return "D3DERR_TEXTURE_CREATE_FAILED\0"; + case D3DERR_TEXTURE_DESTROY_FAILED: + return "D3DERR_TEXTURE_DESTROY_FAILED\0"; + case D3DERR_TEXTURE_LOCK_FAILED: + return "D3DERR_TEXTURE_LOCK_FAILED\0"; + case D3DERR_TEXTURE_UNLOCK_FAILED: + return "D3DERR_TEXTURE_UNLOCK_FAILED\0"; + case D3DERR_TEXTURE_LOAD_FAILED: + return "D3DERR_TEXTURE_LOAD_FAILED\0"; + case D3DERR_MATRIX_CREATE_FAILED: + return "D3DERR_MATRIX_CREATE_FAILED\0"; + case D3DERR_MATRIX_DESTROY_FAILED: + return "D3DERR_MATRIX_DESTROY_FAILED\0"; + case D3DERR_MATRIX_SETDATA_FAILED: + return "D3DERR_MATRIX_SETDATA_FAILED\0"; + case D3DERR_SETVIEWPORTDATA_FAILED: + return "D3DERR_SETVIEWPORTDATA_FAILED\0"; + case D3DERR_MATERIAL_CREATE_FAILED: + return "D3DERR_MATERIAL_CREATE_FAILED\0"; + case D3DERR_MATERIAL_DESTROY_FAILED: + return "D3DERR_MATERIAL_DESTROY_FAILED\0"; + case D3DERR_MATERIAL_SETDATA_FAILED: + return "D3DERR_MATERIAL_SETDATA_FAILED\0"; + case D3DERR_LIGHT_SET_FAILED: + return "D3DERR_LIGHT_SET_FAILED\0"; + #if 0 // retained mode error codes + case D3DRMERR_BADOBJECT: + return "D3DRMERR_BADOBJECT\0"; + case D3DRMERR_BADTYPE: + return "D3DRMERR_BADTYPE\0"; + case D3DRMERR_BADALLOC: + return "D3DRMERR_BADALLOC\0"; + case D3DRMERR_FACEUSED: + return "D3DRMERR_FACEUSED\0"; + case D3DRMERR_NOTFOUND: + return "D3DRMERR_NOTFOUND\0"; + case D3DRMERR_NOTDONEYET: + return "D3DRMERR_NOTDONEYET\0"; + case D3DRMERR_FILENOTFOUND: + return "The file was not found.\0"; + case D3DRMERR_BADFILE: + return "D3DRMERR_BADFILE\0"; + case D3DRMERR_BADDEVICE: + return "D3DRMERR_BADDEVICE\0"; + case D3DRMERR_BADVALUE: + return "D3DRMERR_BADVALUE\0"; + case D3DRMERR_BADMAJORVERSION: + return "D3DRMERR_BADMAJORVERSION\0"; + case D3DRMERR_BADMINORVERSION: + return "D3DRMERR_BADMINORVERSION\0"; + case D3DRMERR_UNABLETOEXECUTE: + return "D3DRMERR_UNABLETOEXECUTE\0"; + #endif + default: + return "Unrecognized error value.\0"; + } +} +#endif -- cgit v1.3