/*---------------------------------------------------------------------------* Copyright (C) 2010-2011 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. *---------------------------------------------------------------------------*/ // ------------------------------------------------------------------ // DDS_Helpers.cpp // ------------------------------------------------------------------ #include "stdafx.h" #include #include #include #include #include "ddraw.h" #include "d3d9types.h" #include "DDS.h" #include "DDS_Helpers.h" #include "resource.h" namespace DDSReader { bool IsD3D10Format(const GX2Surface* pSurface) { assert(pSurface); if(!pSurface) return false; switch (pSurface->format) { case GX2_SURFACE_FORMAT_T_BC1_UNORM: case GX2_SURFACE_FORMAT_T_BC2_UNORM: case GX2_SURFACE_FORMAT_T_BC3_UNORM: case GX2_SURFACE_FORMAT_T_BC4_UNORM: case GX2_SURFACE_FORMAT_T_BC4_SNORM: case GX2_SURFACE_FORMAT_T_BC5_UNORM: case GX2_SURFACE_FORMAT_T_BC5_SNORM: return true; } return false; } bool GetGX2TextureInfo(const DDSD2* pDDSD, GX2Surface* pSurface, ChannelFormat channelFormat, TextureDataType textureDataType,MS_CubeFace* pCubeFaceMask) { u32 cubeFaceMask = 0; HMODULE hTexUtilDLL = LoadLibrary(LIB_DLL_TEXUTILS); if ( !hTexUtilDLL ) { printf("Failed to load DLL %s. Exiting.", LIB_DLL_TEXUTILS); FreeLibrary(hTexUtilDLL); exit(1); } PTC2GetSourceSurfaceSize fpTC2GetSourceSurfaceSize = reinterpret_cast(GetProcAddress(hTexUtilDLL, "TC2GetSourceSurfaceSize")); if(pDDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) { pSurface->depth = 0; pSurface->dim = GX2_SURFACE_DIM_CUBE; cubeFaceMask = MS_CF_None; if(pDDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEX) { pSurface->depth++; cubeFaceMask |= MS_CF_PositiveX; } if(pDDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEY) { pSurface->depth++; cubeFaceMask |= MS_CF_PositiveY; } if(pDDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) { pSurface->depth++; cubeFaceMask |= MS_CF_PositiveZ; } if(pDDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) { pSurface->depth++; cubeFaceMask |= MS_CF_NegativeX; } if(pDDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) { pSurface->depth++; cubeFaceMask |= MS_CF_NegativeY; } if(pDDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) { pSurface->depth++; cubeFaceMask |= MS_CF_NegativeZ; } } else if(pDDSD->ddsCaps.dwCaps2 & DDSCAPS2_VOLUME && pDDSD->dwFlags & DDSD_DEPTH) { pSurface->depth = pDDSD->dwDepth; pSurface->dim = GX2_SURFACE_DIM_3D; } else if(pDDSD->dwFlags & DDSD_DEPTH) { pSurface->depth = pDDSD->dwDepth; pSurface->dim = GX2_SURFACE_DIM_2D_ARRAY; } else { pSurface->depth = 1; pSurface->dim = GX2_SURFACE_DIM_2D; } if(pDDSD->dwFlags & DDSD_MIPMAPCOUNT) { pSurface->numMips = pDDSD->dwMipMapCount; } else { pSurface->numMips = pDDSD->dwMipMapCount; } if(pSurface->numMips < 1) { pSurface->numMips = 1; } pSurface->width = pDDSD->dwWidth; pSurface->height = pDDSD->dwHeight; pSurface->tileMode = GX2_TILE_MODE_LINEAR_SPECIAL; pSurface->use = GX2_SURFACE_USE_TEXTURE; pSurface->alignment = 1; switch (channelFormat) { case CF_Compressed: if (pDDSD->ddpfPixelFormat.dwFourCC == MAKEFOURCC('D', 'X', 'T', '1') && (textureDataType == TDT_XRGB || textureDataType == TDT_ARGB)) { pSurface->format = GX2_SURFACE_FORMAT_T_BC1_UNORM; break; } else if (pDDSD->ddpfPixelFormat.dwFourCC == MAKEFOURCC('D', 'X', 'T', '3') && (textureDataType == TDT_XRGB || textureDataType == TDT_ARGB)) { pSurface->format = GX2_SURFACE_FORMAT_T_BC2_UNORM; break; } else if (pDDSD->ddpfPixelFormat.dwFourCC == MAKEFOURCC('D', 'X', 'T', '5') && (textureDataType == TDT_XRGB || textureDataType == TDT_ARGB)) { pSurface->format = GX2_SURFACE_FORMAT_T_BC3_UNORM; break; } else if ( (pDDSD->ddpfPixelFormat.dwFourCC == MAKEFOURCC('A', 'T', 'I', '1') || pDDSD->ddpfPixelFormat.dwFourCC == MAKEFOURCC('B', 'C', '4', 'U' ) ) && textureDataType == TDT_R) { pSurface->format = GX2_SURFACE_FORMAT_T_BC4_UNORM; break; } else if ( (pDDSD->ddpfPixelFormat.dwFourCC == MAKEFOURCC('A', 'T', 'I', '2') || pDDSD->ddpfPixelFormat.dwFourCC == MAKEFOURCC('B', 'C', '5', 'U' ) ) && textureDataType == TDT_RG) { pSurface->format = GX2_SURFACE_FORMAT_T_BC5_UNORM; break; } else if((pDDSD->ddpfPixelFormat.dwLuminanceBitCount == 8) && (pDDSD->ddpfPixelFormat.dwFlags & DDPF_LUMINANCE) && (pDDSD->ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS)) { pSurface->format = GX2_SURFACE_FORMAT_T_R4_G4_UNORM; break; } else if((pDDSD->ddpfPixelFormat.dwLuminanceBitCount == 16) && (pDDSD->ddpfPixelFormat.dwFlags & DDPF_LUMINANCE) && (pDDSD->ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS)) { pSurface->format = GX2_SURFACE_FORMAT_TC_R8_G8_UNORM; break; } else if((pDDSD->ddpfPixelFormat.dwLuminanceBitCount == 16) && (pDDSD->ddpfPixelFormat.dwFlags & DDPF_LUMINANCE) && ((pDDSD->ddpfPixelFormat.dwFlags | DDPF_LUMINANCE) == DDPF_LUMINANCE)) { pSurface->format = GX2_SURFACE_FORMAT_TCD_R16_UNORM; break; } else if((pDDSD->ddpfPixelFormat.dwLuminanceBitCount == 8) && (pDDSD->ddpfPixelFormat.dwFlags & DDPF_LUMINANCE) && ((pDDSD->ddpfPixelFormat.dwFlags | DDPF_LUMINANCE) == DDPF_LUMINANCE)) { pSurface->format = GX2_SURFACE_FORMAT_TC_R8_UNORM; break; } else { printf("Unsupported texture data type"); FreeLibrary(hTexUtilDLL); return false; } break; case CF_8bit: switch (textureDataType) { case TDT_XRGB: case TDT_ARGB: pSurface->format = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM; break; case TDT_R: pSurface->format = GX2_SURFACE_FORMAT_TC_R8_UNORM; case TDT_RG: pSurface->format = GX2_SURFACE_FORMAT_TC_R8_G8_UNORM; break; case TDT_RGB: if (pDDSD->ddpfPixelFormat.dwRBitMask == 0x0000f800 && pDDSD->ddpfPixelFormat.dwGBitMask == 0x000007e0 && pDDSD->ddpfPixelFormat.dwBBitMask == 0x0000001f) { // Loader will flip RGB/BGR order pSurface->format = GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM; } else { assert(!"Unsupported texture data type"); FreeLibrary(hTexUtilDLL); return false; } break; default: assert(!"Unsupported texture data type"); FreeLibrary(hTexUtilDLL); return false; } break; case CF_Float16: switch (textureDataType) { case TDT_XRGB: case TDT_ARGB: pSurface->format = GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT; break; case TDT_R: pSurface->format = GX2_SURFACE_FORMAT_TC_R16_FLOAT; break; case TDT_RG: pSurface->format = GX2_SURFACE_FORMAT_TC_R16_G16_FLOAT; break; default: assert(!"Unsupported texture data type"); FreeLibrary(hTexUtilDLL); return false; } break; case CF_Float32: switch (textureDataType) { case TDT_R: pSurface->format = GX2_SURFACE_FORMAT_TCD_R32_FLOAT; break; case TDT_RG: pSurface->format = GX2_SURFACE_FORMAT_TC_R32_G32_FLOAT; break; case TDT_XRGB: case TDT_ARGB: pSurface->format = GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT; break; default: assert(!"Unsupported texture data type"); FreeLibrary(hTexUtilDLL); return false; } break; case CF_16bit: switch (textureDataType) { case TDT_XRGB: case TDT_ARGB: pSurface->format = GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UNORM; break; case TDT_RG: pSurface->format = GX2_SURFACE_FORMAT_TC_R16_G16_UNORM; break; default: assert(!"Unsupported texture data type"); FreeLibrary(hTexUtilDLL); return false; } break; case CF_32bit: switch (textureDataType) { case TDT_XRGB: case TDT_ARGB: pSurface->format = GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_UINT; break; default: assert(!"Unsupported texture data type"); FreeLibrary(hTexUtilDLL); return false; } break; case CF_1555: if (pDDSD->ddpfPixelFormat.dwRBitMask==0x00007c00) { // Loader will flip RGB/BGR order pSurface->format = GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM; } else { assert(!"Unsupported texture data type"); FreeLibrary(hTexUtilDLL); return false; } break; case CF_4444: pSurface->format = GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM; break; case CF_2101010: switch (textureDataType) { case TDT_XRGB: case TDT_ARGB: if (pDDSD->ddpfPixelFormat.dwRBitMask==0x000003ff) { pSurface->format = GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM; } else if (pDDSD->ddpfPixelFormat.dwRBitMask==0x3ff00000) { // Loader will flip RGB/BGR order pSurface->format = GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM; } else { pSurface->format = GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM; } break; default: assert(!"Unsupported texture data type"); FreeLibrary(hTexUtilDLL); return false; } break; default: assert(!"Unsupported channel format"); FreeLibrary(hTexUtilDLL); return false; } if (!fpTC2GetSourceSurfaceSize(pSurface)) { FreeLibrary(hTexUtilDLL); return false; } FreeLibrary(hTexUtilDLL); return true; } TU_Error GenericLoadFunction(FILE*& pFile, DDSD2*& pDDSD, GX2Surface*& pSurface, void*& extra, ChannelFormat channelFormat, TextureDataType textureDataType, PreLoopFunction fnPreLoop, LoopFunction fnLoop, PostLoopFunction fnPostLoop) { u32 dwWidth, dwHeight; TU_Error err; MS_CubeFace cubeFaceMask = MS_CF_None; memset(pSurface, 0, sizeof(*pSurface)); if (!GetGX2TextureInfo(pDDSD, pSurface, channelFormat, textureDataType, &cubeFaceMask)) { return PE_Unknown; } pSurface->imagePtr = malloc(pSurface->imageSize + pSurface->mipSize); if (pSurface->mipSize) { pSurface->mipPtr = (void*)((u8*)pSurface->imagePtr + pSurface->imageSize); } err = fnPreLoop(pFile, pDDSD, pSurface, extra); if(err != PE_OK) { return err; } if(pSurface->dim == GX2_SURFACE_DIM_2D || pSurface->dim == GX2_SURFACE_DIM_CUBE) { for(u32 nFace = 0; nFace < pSurface->depth; nFace++) { dwWidth = pDDSD->dwWidth; dwHeight = pDDSD->dwHeight; for(u32 nMipLevel = 0; nMipLevel < pSurface->numMips; nMipLevel++) { err = fnLoop(pFile, pDDSD, pSurface, extra, nMipLevel, nFace, dwWidth, dwHeight); if(err != PE_OK) return err; dwWidth = (dwWidth>1) ? (dwWidth>>1) : 1; dwHeight = (dwHeight>1) ? (dwHeight>>1) : 1; } } } else if(pSurface->dim == GX2_SURFACE_DIM_3D) { dwWidth = pDDSD->dwWidth; dwHeight = pDDSD->dwHeight; for(u32 nMipLevel = 0; nMipLevel < pSurface->numMips; nMipLevel++) { int nMaxSlices = MaxFacesOrSlices(pSurface, nMipLevel); for(int nSlice=0; nSlice1 ? dwWidth>>1 : 1; dwHeight = dwHeight>1 ? dwHeight>>1 : 1; } } else if(pSurface->dim == GX2_SURFACE_DIM_2D_ARRAY) { dwWidth = pDDSD->dwWidth; dwHeight = pDDSD->dwHeight; int nMaxSlices = pDDSD->dwDepth; for(u32 nMipLevel = 0; nMipLevel < pSurface->numMips; nMipLevel++) { for(int nSlice=0; nSlice1 ? dwWidth>>1 : 1; dwHeight = dwHeight>1 ? dwHeight>>1 : 1; } } else { ASSERT(0); return PE_Unknown; } return fnPostLoop(pFile, pDDSD, pSurface, extra); } TU_Error GenericFreeFunction(GX2Surface*& pSurface) { if(pSurface == NULL) { assert(pSurface); return PE_Unknown; } if(pSurface->imagePtr != NULL) { free(pSurface->imagePtr); pSurface->imagePtr = NULL; pSurface->mipPtr = NULL; } return PE_OK; } TU_Error PreLoopDefault(FILE*&, DDSD2*&, GX2Surface*&, void*&) { return PE_OK; } TU_Error LoopDefault(FILE*& pFile, DDSD2*&, GX2Surface*& pSurface, void*& extra, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel; ChannelFormat channelFormat = *reinterpret_cast(extra); if (!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { return PE_Unknown; } if(fread(mipLevel.pData, GetMipSize(pSurface, nMipLevel, nFaceOrSlice), 1, pFile) != 1) return PE_Unknown; return PE_OK; } TU_Error PostLoopDefault(FILE*&, DDSD2*&, GX2Surface*&, void*&) { return PE_OK; } TU_Error PreLoopFourCC(FILE*& pFile, DDSD2*& pDDSD, GX2Surface*& pSurface, void*& extra) { u32 dwWidth; u32 dwHeight; u32 dwDepth; u32 dwPixels = 0; switch(pSurface->dim) { case GX2_SURFACE_DIM_2D: case GX2_SURFACE_DIM_CUBE: dwWidth = pSurface->width; dwHeight = pSurface->height; for(u32 i = 0; i < pSurface->numMips; i++) { dwPixels += dwWidth * dwHeight * pSurface->depth; dwWidth = dwWidth>1 ? dwWidth>>1 : 1; dwHeight = dwHeight>1 ? dwHeight>>1 : 1; } break; case GX2_SURFACE_DIM_2D_ARRAY: case GX2_SURFACE_DIM_3D: dwWidth = pSurface->width; dwHeight = pSurface->height; dwDepth = pSurface->depth; for(u32 i = 0; i < pSurface->numMips; i++) { dwPixels += dwWidth * dwHeight * dwDepth; dwWidth = dwWidth>1 ? dwWidth>>1 : 1; dwHeight = dwHeight>1 ? dwHeight>>1 : 1; dwDepth = dwDepth>1 ? dwDepth>>1 : 1; } break; default: assert(0); fclose(pFile); return PE_Unknown; } extra = NULL; return PE_OK; } TU_Error LoopFourCC(FILE*& pFile, DDSD2*&, GX2Surface*& pSurface, void*& /*extra*/, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel; if(!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { return PE_Unknown; } //read in the data.... if(fread(mipLevel.pData, mipLevel.byteSize, 1, pFile) != 1) { return PE_Unknown; } return PE_OK; } TU_Error PostLoopFourCC(FILE*&, DDSD2*&, GX2Surface*&, void*&) { return PE_OK; } TU_Error PreLoopRGB565(FILE*&, DDSD2*& pDDSD, GX2Surface*& pSurface, void*& extra) { return PE_OK; } TU_Error LoopRGB565(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*& extra, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { // Allocate the permanent buffer and unpack the bitmap data into it MipLevel mipLevel; u32 size = (dwWidth * dwHeight) * 2; u16* pData = NULL; u32 count = 0; u16 value; if (!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { return PE_Unknown; } if(fread(mipLevel.pData, size, 1, pFile) != 1) { return PE_Unknown; } pData = (u16*)mipLevel.pData; for (count = 0; count < (size / 2); count++) { value = *(pData + count); *(pData + count) = ((value & 0xf800) >> 11) | (value & 0x07e0) | ((value & 0x1f) << 11); } return PE_OK; } TU_Error PostLoopRGB565(FILE*&, DDSD2*&, GX2Surface*&, void*& extra) { return PE_OK; } TU_Error PreLoopRGB888(FILE*&, DDSD2*& pDDSD, GX2Surface*& pSurface, void*& extra) { // Allocate a temporary buffer and read the bitmap data into it u32 dwTempSize = pDDSD->dwWidth * pDDSD->dwHeight * 3; extra = malloc(dwTempSize); return extra ? PE_OK : PE_Unknown; } TU_Error LoopRGB888(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*& extra, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel; if(fread(extra, dwWidth * dwHeight * 3, 1, pFile) != 1) { free(extra); return PE_Unknown; } if (!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { free(extra); return PE_Unknown; } // Allocate the permanent buffer and unpack the bitmap data into it if(!mipLevel.pData) { free(extra); return PE_Unknown; } u32* pData = (u32*)mipLevel.pData; u8* pTempPtr = (u8*)extra; u8* pEnd = (u8*)pTempPtr + (dwWidth * dwHeight * 3); u8 red, green, blue; while(pTempPtr < pEnd) { blue = *pTempPtr++; green = *pTempPtr++; red = *pTempPtr++; *pData++ = (0xff << 24) | (blue << 16) | (green << 8) | red; } return PE_OK; } TU_Error PostLoopRGB888(FILE*&, DDSD2*&, GX2Surface*&, void*& extra) { free(extra); return PE_OK; } TU_Error PreLoopRGB8888(FILE*&, DDSD2*&, GX2Surface*& pSurface, void*&) { return PE_OK; } TU_Error LoopRGB8888(FILE*& pFile, DDSD2*&, GX2Surface*& pSurface, void*& extra, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { u32 size = (dwWidth * dwHeight * 4); MipLevel mipLevel; if (!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { return PE_Unknown; } ARGB8888Struct* pARGB8888Struct = reinterpret_cast(extra); if(!(pARGB8888Struct->nFlags & EF_UseBitMasks)) { //not using bitmasks if(fread(mipLevel.pData, size, 1, pFile) != 1) { return PE_Unknown; } } else { //using bitmasks if(fread(pARGB8888Struct->pMemory, size, 1, pFile) != 1) { return PE_Unknown; } u8* pData = mipLevel.pData; u32* pTempPtr = (u32*)pARGB8888Struct->pMemory; u32* pEnd = (u32*)pARGB8888Struct->pMemory + (size / 4); while(pTempPtr < pEnd) { *(pData + 0) = static_cast ((*pTempPtr & pARGB8888Struct->nRMask) >> pARGB8888Struct->nRShift); *(pData + 1) = static_cast ((*pTempPtr & pARGB8888Struct->nGMask) >> pARGB8888Struct->nGShift); *(pData + 2) = static_cast ((*pTempPtr & pARGB8888Struct->nBMask) >> pARGB8888Struct->nBShift); *(pData + 3) = static_cast ((*pTempPtr & 0xFF000000) >> 24); //take alpha whether or not its used pData += 4; pTempPtr++; } } return PE_OK; } TU_Error PostLoopRGB8888(FILE*&, DDSD2*&, GX2Surface*&, void*&) { return PE_OK; } TU_Error PreLoopABGR32F(FILE*&, DDSD2*&, GX2Surface*& pSurface, void*&) { return PE_OK; } TU_Error LoopABGR32F(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { u32 size = dwWidth * dwHeight * 16; MipLevel mipLevel; if (!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { return PE_Unknown; } if(fread(mipLevel.pData, size, 1, pFile) != 1) { return PE_Unknown; } return PE_OK; } TU_Error LoopR32F(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { u32 size = dwWidth * dwHeight * 4; MipLevel mipLevel; if (!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { return PE_Unknown; } if(fread(mipLevel.pData, size, 1, pFile) != 1) { return PE_Unknown; } return PE_OK; } TU_Error LoopGR32F(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { u32 size = dwWidth * dwHeight * 8; MipLevel mipLevel; //u64 value; //u32 count; //u64 *pData = NULL; if (!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { return PE_Unknown; } if(fread(mipLevel.pData, size, 1, pFile) != 1) { return PE_Unknown; } /*pData = (u64*)mipLevel.pData; for (count = 0; count < size / 8; count++) { value = *(pData + count); *(pData + count) = ((value & 0x00000000ffffffff) << 32) | ((value & 0xffffffff00000000) >> 32); }*/ return PE_OK; } TU_Error PostLoopABGR32F(FILE*&, DDSD2*&, GX2Surface*&, void*&) { return PE_OK; } TU_Error PreLoopABGR16F(FILE*&, DDSD2*&, GX2Surface*& pSurface, void*&) { return PE_OK; } TU_Error LoopABGR16F(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel; if (!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { return PE_Unknown; } u32 size = dwWidth * dwHeight * 8; if(fread(mipLevel.pData, size, 1, pFile) != 1) return PE_Unknown; return PE_OK; } TU_Error LoopGR16F(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel; if (!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { return PE_Unknown; } u32 size = dwWidth * dwHeight * 4; if(fread(mipLevel.pData, size, 1, pFile) != 1) return PE_Unknown; return PE_OK; } TU_Error LoopR16F(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel; if (!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { return PE_Unknown; } u32 size = dwWidth * dwHeight * 2; if(fread(mipLevel.pData, size, 1, pFile) != 1) return PE_Unknown; return PE_OK; } TU_Error PostLoopABGR16F(FILE*&, DDSD2*&, GX2Surface*&, void*&) { return PE_OK; } TU_Error PreLoopG8(FILE*&, DDSD2*&, GX2Surface*& pSurface, void*&) { return PE_OK; } TU_Error LoopG8(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel; if (!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { return PE_Unknown; } u32 size = dwWidth * dwHeight;// + 0x3) & ~0x3; // Allocate the permanent buffer and unpack the bitmap data into it if(fread(mipLevel.pData, size, 1, pFile) != 1) { return PE_Unknown; } return PE_OK; } TU_Error PostLoopG8(FILE*&, DDSD2*&, GX2Surface*&, void*&) { return PE_OK; } TU_Error PreLoopA4L4(FILE*&, DDSD2*&, GX2Surface*& pSurface, void*&) { return PE_OK; } TU_Error PreLoopA8L8(FILE*&, DDSD2*&, GX2Surface*& pSurface, void*&) { return PE_OK; } TU_Error LoopA4L4(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel; if (!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { return PE_Unknown; } u32 size = ((dwWidth * dwHeight) + 0x3) & ~0x3; // Allocate the permanent buffer and unpack the bitmap data into it if(fread(mipLevel.pData, size, 1, pFile) != 1) { return PE_Unknown; } return PE_OK; } TU_Error LoopA8L8(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel; if (!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { return PE_Unknown; } u32 size = (dwWidth * dwHeight) * 2; // Allocate the permanent buffer and unpack the bitmap data into it if(fread(mipLevel.pData, size, 1, pFile) != 1) { return PE_Unknown; } return PE_OK; } TU_Error PostLoopA4L4(FILE*&, DDSD2*&, GX2Surface*&, void*&) { return PE_OK; } TU_Error PostLoopA8L8(FILE*&, DDSD2*&, GX2Surface*&, void*&) { return PE_OK; } TU_Error PreLoopAG8(FILE*&, DDSD2*&, GX2Surface*& pSurface, void*&) { return PE_OK; } TU_Error LoopAG8(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel; if (!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { return PE_Unknown; } u32 size = (((dwWidth * dwHeight) + 0x3) & ~0x3) * 2; if(fread(mipLevel.pData, size, 1, pFile) != 1) { return PE_Unknown; } return PE_OK; } TU_Error PostLoopAG8(FILE*&, DDSD2*&, GX2Surface*&, void*&) { return PE_OK; } TU_Error PreLoopG16(FILE*&, DDSD2*&, GX2Surface*& pSurface, void*&) { return PE_OK; } TU_Error LoopG16(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel; if (!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { return PE_Unknown; } u32 size = (((dwWidth * dwHeight) + 0x3) & ~0x3) * 2; if(fread(mipLevel.pData, size, 1, pFile) != 1) return PE_Unknown; return PE_OK; } TU_Error PostLoopG16(FILE*&, DDSD2*&, GX2Surface*&, void*&) { return PE_OK; } TU_Error PreLoopA8(FILE*&, DDSD2*&, GX2Surface*& pSurface, void*&) { return PE_OK; } TU_Error LoopA8(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel; if (!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { return PE_Unknown; } u32 size = ((dwWidth * dwHeight) + 0x3) & ~0x3; if (fread(mipLevel.pData, size, 1, pFile) != 1) { return PE_Unknown; } return PE_OK; } TU_Error PostLoopA8(FILE*&, DDSD2*&, GX2Surface*&, void*&) { return PE_OK; } TU_Error PreLoopABGR16(FILE*&, DDSD2*&, GX2Surface*& pSurface, void*&) { return PE_OK; } TU_Error LoopABGR16(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel; if (!GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel)) { return PE_Unknown; } u32 size = dwWidth * dwHeight * 8; if(fread((void*)mipLevel.pData, size, 1, pFile) != 1) { return PE_Unknown; } return PE_OK; } TU_Error PostLoopABGR16(FILE*&, DDSD2*&, GX2Surface*&, void*&) { return PE_OK; } TU_Error PreLoopG16R16(FILE*&, DDSD2*&, GX2Surface*& pSurface, void*&) { return PE_OK; } TU_Error PreLoopARGB1555(FILE*&, DDSD2*&, GX2Surface*& pSurface, void*&) { return PE_OK; } TU_Error PreLoopARGB4444(FILE*&, DDSD2*&, GX2Surface*& pSurface, void*&) { return PE_OK; } TU_Error LoopG16R16(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel; u32 size = dwWidth * dwHeight * 4; //u32 value, count; //u32* pData; GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel); if(fread(mipLevel.pData, size, 1, pFile) != 1) { return PE_Unknown; } /*pData = (u32*)mipLevel.pData; for (count = 0; count < size / 4; count++) { value = *(pData + count); *(pData + count) = ((value & 0x0000ffff) << 16) | ((value & 0xffff0000) >> 16); }*/ return PE_OK; } TU_Error LoopARGB1555(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel; u32 size = dwWidth * dwHeight * 2; u16* pData = NULL; u32 count = 0; u16 value; GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel); if(fread(mipLevel.pData, size, 1, pFile) != 1) { return PE_Unknown; } pData = (u16*)mipLevel.pData; for (count = 0; count < size/2; count++) { value = *(pData + count); // [MSB] ARGB [LSB] to ABGR *(pData + count) = ((value & 0x8000)) | ((value & 0x7c00) >> 10) | ((value & 0x001f) << 10) | (value & 0x03e0); } return PE_OK; } TU_Error LoopARGB4444(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel; u32 count; u32 size = dwWidth * dwHeight * 2; u16* pData = NULL; u16 value; GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel); if(fread(mipLevel.pData, size, 1, pFile) != 1) { return PE_Unknown; } pData = (u16*)mipLevel.pData; for (count = 0; count < (size / 2); count++) { value = *(pData + count); //ARGB ABGR *(pData + count) = (value & 0xf000) | ((value & 0x0f00) >> 8) | (value & 0x00f0) | ((value & 0x000f) << 8); } return PE_OK; } TU_Error PostLoopG16R16(FILE*&, DDSD2*&, GX2Surface*&, void*&) { return PE_OK; } TU_Error PostLoopARGB1555(FILE*&, DDSD2*&, GX2Surface*&, void*&) { return PE_OK; } TU_Error PostLoopARGB4444(FILE*&, DDSD2*&, GX2Surface*&, void*&) { return PE_OK; } bool SetupDDSD(DDSD2& ddsd2, const GX2Surface* pSurface, bool bCompressed) { memset(&ddsd2, 0, sizeof(DDSD2)); ddsd2.dwSize = sizeof(DDSD2); ASSERT(pSurface); if(pSurface == NULL) { return false; } ddsd2.dwWidth = pSurface->width; ddsd2.dwHeight = pSurface->height; ddsd2.dwMipMapCount = pSurface->numMips; ddsd2.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT|DDSD_MIPMAPCOUNT; if(bCompressed) { ddsd2.dwFlags |= DDSD_LINEARSIZE; ddsd2.dwLinearSize = pSurface->imageSize + pSurface->mipSize; } else ddsd2.dwFlags |= DDSD_PITCH; ddsd2.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); ddsd2.ddsCaps.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_COMPLEX|DDSCAPS_MIPMAP; if(pSurface->dim == GX2_SURFACE_DIM_CUBE) { ddsd2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES; } else if(pSurface->dim == GX2_SURFACE_DIM_3D) { ddsd2.dwFlags |= DDSD_DEPTH; ddsd2.dwDepth = pSurface->depth; ddsd2.ddsCaps.dwCaps2 |= DDSCAPS2_VOLUME; } else if(pSurface->dim == GX2_SURFACE_DIM_2D_ARRAY) { ddsd2.dwFlags |= DDSD_DEPTH; ddsd2.dwDepth = pSurface->depth; } return true; } bool SetupDDSD_DDS10(DDSD2& ddsd2, const GX2Surface* pSurface, bool bCompressed) { memset(&ddsd2, 0, sizeof(DDSD2)); ddsd2.dwSize = sizeof(DDSD2); ASSERT(pSurface); if(pSurface == NULL) return false; ddsd2.dwWidth = pSurface->width; ddsd2.dwHeight = pSurface->height; ddsd2.dwMipMapCount = pSurface->numMips; ddsd2.dwFlags = DDSD_WIDTH|DDSD_HEIGHT; ddsd2.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); ddsd2.ddsCaps.dwCaps = DDSCAPS_TEXTURE; if(pSurface->dim == GX2_SURFACE_DIM_CUBE) { ddsd2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES; } else if(pSurface->dim == GX2_SURFACE_DIM_3D) { ddsd2.dwFlags |= DDSD_DEPTH; ddsd2.dwDepth = pSurface->depth; ddsd2.ddsCaps.dwCaps2 |= DDSCAPS2_VOLUME; } else if(pSurface->dim == GX2_SURFACE_DIM_2D_ARRAY) { ddsd2.dwFlags |= DDSD_DEPTH; ddsd2.dwDepth = pSurface->depth; } if(pSurface->numMips > 1) { ddsd2.dwFlags |= DDSD_MIPMAPCOUNT; ddsd2.ddsCaps.dwCaps |= DDSCAPS_MIPMAP; } return true; } TU_Error PreLoopABGR32(FILE*&, DDSD2*&, GX2Surface*& pSurface, void*&) { return PE_OK; } TU_Error LoopABGR32(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel;GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel); if(fread(mipLevel.pData, GetMipSize(pSurface, nMipLevel, nFaceOrSlice), 1, pFile) != 1) return PE_Unknown; return PE_OK; } TU_Error PostLoopABGR32(FILE*&, DDSD2*&, GX2Surface*&, void*&) { return PE_OK; } TU_Error LoopR32(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel;GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel); u32 dwSize = GetMipSize(pSurface, nMipLevel, nFaceOrSlice) / 4; s8* pTempData = (s8*) malloc(dwSize); assert(pTempData); if(!pTempData) return PE_Unknown; u32 dws8sRead = (u32)fread(pTempData, 1, dwSize, pFile); if(dws8sRead != dwSize) { free(pTempData); return PE_Unknown; } u32* pSrc = (u32*) pTempData; u32* pEnd = (u32*) (pTempData + dwSize); u32* pDest = (u32*) mipLevel.pData; while(pSrc < pEnd) { *pDest++ = *pSrc++; *pDest++ = 0; *pDest++ = 0; *pDest++ = _UI32_MAX; } free(pTempData); return PE_OK; } TU_Error LoopR8G8(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel;GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel); u32 dwSize = GetMipSize(pSurface, nMipLevel, nFaceOrSlice) / 2; s8* pTempData = (s8*) malloc(dwSize); assert(pTempData); if(!pTempData) return PE_Unknown; if(fread(pTempData, dwSize, 1, pFile) != 1) { free(pTempData); return PE_Unknown; } u8* pSrc = (u8*)pTempData; u8* pEnd = (u8*)(pTempData + dwSize); u8* pDest = mipLevel.pData; while(pSrc < pEnd) { *pDest++ = 0; u8 bRed = *pSrc++; *pDest++ = *pSrc++; *pDest++ = bRed; *pDest++ = (u8)0xff; } free(pTempData); return PE_OK; } TU_Error LoopR32G32(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel;GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel); u32 dwSize = GetMipSize(pSurface, nMipLevel, nFaceOrSlice) / 2; u32* pTempData = (u32*) malloc(dwSize); assert(pTempData); if(!pTempData) return PE_Unknown; if(fread(pTempData, dwSize, 1, pFile) != 1) { free(pTempData); return PE_Unknown; } u32* pSrc = pTempData; u32* pEnd = (pTempData + (dwSize / sizeof(u32))); u32* pDest = (u32*)mipLevel.pData; while(pSrc < pEnd) { *pDest++ = *pSrc++; *pDest++ = *pSrc++; *pDest++ = 0; *pDest++ = 0; } free(pTempData); return PE_OK; } TU_Error LoopA2R10G10B10(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel;GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel); u32 dwSize = mipLevel.byteSize; u32* pTempData = (u32*) malloc(dwSize); assert(pTempData); if(!pTempData) return PE_Unknown; if(fread(pTempData, dwSize, 1, pFile) != 1) { free(pTempData); return PE_Unknown; } u32* pSrc = pTempData; u32* pEnd = (pTempData + (dwSize / sizeof(u32))); u32* pDest = (u32*)mipLevel.pData; while(pSrc < pEnd) { u32 dwSrc = *pSrc++; // ARGB to ABGR u32 dwDest = (dwSrc & 0xc0000000) | ((dwSrc & 0x3ff00000) >> 20) | (dwSrc & 0x000ffc00) | ((dwSrc & 0x000003ff) << 20); *pDest++ = dwDest; } free(pTempData); return PE_OK; } TU_Error LoopR16G16(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel;GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel); u32 dwSize = GetMipSize(pSurface, nMipLevel, nFaceOrSlice) / 2; WORD* pTempData = (WORD*) malloc(dwSize); assert(pTempData); if(!pTempData) return PE_Unknown; if(fread(pTempData, dwSize, 1, pFile) != 1) { free(pTempData); return PE_Unknown; } WORD* pSrc = pTempData; WORD* pEnd = (pTempData + (dwSize / sizeof(WORD))); WORD* pDest = (WORD*)mipLevel.pData; while(pSrc < pEnd) { *pDest++ = *pSrc++; *pDest++ = *pSrc++; *pDest++ = 0; *pDest++ = 0; } free(pTempData); return PE_OK; } TU_Error LoopR16(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel;GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel); u32 dwSize = GetMipSize(pSurface, nMipLevel, nFaceOrSlice) / 4; s8* pTempData = (s8*) malloc(dwSize); assert(pTempData); if(!pTempData) return PE_Unknown; u32 dws8sRead = (u32)fread(pTempData, 1, dwSize, pFile); if(dws8sRead != dwSize) { free(pTempData); return PE_Unknown; } WORD* pSrc = (WORD*) pTempData; WORD* pEnd = (WORD*) (pTempData + dwSize); WORD* pDest = (WORD*)mipLevel.pData; while(pSrc < pEnd) { *pDest++ = *pSrc++; *pDest++ = 0; *pDest++ = 0; *pDest++ = _UI16_MAX; } free(pTempData); return PE_OK; } TU_Error LoopR8(FILE*& pFile, DDSD2*& , GX2Surface*& pSurface, void*&, u32 nMipLevel, u32 nFaceOrSlice, u32 dwWidth, u32 dwHeight) { MipLevel mipLevel;GetMipLevel(pSurface, nMipLevel, nFaceOrSlice, &mipLevel); u32 dwSize = GetMipSize(pSurface, nMipLevel, nFaceOrSlice) / 4; s8* pTempData = (s8*) malloc(dwSize); assert(pTempData); if(!pTempData) return PE_Unknown; if(fread(pTempData, dwSize, 1, pFile) != 1) { free(pTempData); return PE_Unknown; } u8* pSrc = (u8*)pTempData; u8* pEnd = (u8*)(pTempData + dwSize); u8* pDest = mipLevel.pData; while(pSrc < pEnd) { *pDest++ = 0; *pDest++ = 0; *pDest++ = *pSrc++; *pDest++ = (u8)0xff; } free(pTempData); return PE_OK; } } //namespace DDSReader