/*---------------------------------------------------------------------------* 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.cpp // ------------------------------------------------------------------ #include "stdafx.h" #include #include #include #include "ddraw.h" #include "d3d9types.h" #include "DDS.h" #include "DDS_10.h" #include "DDS_Helpers.h" #include "resource.h" #include "cafe/gx2/gx2Enum.h" #include "texUtils.h" namespace DDSReader { #define MAX_FORMAT_LENGTH 160 #define MAX_ERROR_LENGTH 240 static const u32 DDS_HEADER = MAKEFOURCC('D', 'D', 'S', ' '); TU_Error LoadDDS_ABGR32F(FILE* pFile, DDSD2* pDDSD,GX2Surface* pSurface); TU_Error LoadDDS_ABGR16F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_GR32F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_R32F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_R16F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_G16R16F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_FourCC(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_RGB565(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_RGB888(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_RGB8888(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface, bool bAlpha); TU_Error LoadDDS_ABGR2101010(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_ABGR16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_G16R16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_R16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_ARGB1555(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_ARGB4444(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_G8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_A4L4(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_A8L8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_G16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_AG8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS_A8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error SaveDDS_ABGR32F(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_RG32F(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_R32F(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_ABGR16F(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_RG16F(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_R16F(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_ARGB8888(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_ABGR2101010(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_ABGR16(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_R16(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_RG16(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_RGB888(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_FourCC(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_G8(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_A8(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_A8L8(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_RGB565(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_ARGB4444(FILE* pFile, const GX2Surface* pSurface); TU_Error SaveDDS_ARGB1555(FILE* pFile, const GX2Surface* pSurface); bool DDSLoadFile(const TCHAR* pszFilename, GX2Surface* pSurface) { FILE* pFile = NULL; if(_tfopen_s(&pFile, pszFilename, _T("rb"))) { return false; } u32 dwFileHeader; fread(&dwFileHeader ,sizeof(u32), 1, pFile); if(dwFileHeader != DDS_HEADER) { fclose(pFile); return false; } DDSD2 ddsd; if(fread(&ddsd, sizeof(DDSD2), 1, pFile) != 1) { fclose(pFile); return false; } if(!(ddsd.dwFlags & DDSD_MIPMAPCOUNT)) ddsd.dwMipMapCount = 1; else if(ddsd.dwMipMapCount == 0) { ddsd.dwMipMapCount = 1; } if(ddsd.ddpfPixelFormat.dwFourCC == MAKEFOURCC('D', 'X', '1', '0')) return LoadDDS10(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwFourCC == D3DFMT_A32B32G32R32F) return LoadDDS_ABGR32F(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwFourCC == D3DFMT_A16B16G16R16F) return LoadDDS_ABGR16F(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwFourCC == D3DFMT_G32R32F) return LoadDDS_GR32F(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwFourCC == D3DFMT_R32F) return LoadDDS_R32F(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwFourCC == D3DFMT_R16F) return LoadDDS_R16F(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwFourCC == D3DFMT_G16R16F) return LoadDDS_G16R16F(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwFourCC == D3DFMT_A16B16G16R16) return LoadDDS_ABGR16(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwFourCC == D3DFMT_Q16W16V16U16) return LoadDDS_ABGR16(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwFourCC == D3DFMT_G16R16) return LoadDDS_G16R16(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwFourCC == D3DFMT_L16) return LoadDDS_R16(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwFourCC) return LoadDDS_FourCC(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwLuminanceBitCount==8 && (ddsd.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE) && (ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS)) return LoadDDS_A4L4(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwLuminanceBitCount==8 && (ddsd.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE)) return LoadDDS_G8(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwLuminanceBitCount==16 && (ddsd.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE) && (ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS)) return LoadDDS_A8L8(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwLuminanceBitCount==16 && (ddsd.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE) && (ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS)) return LoadDDS_AG8(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwLuminanceBitCount==16 && (ddsd.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE)) return LoadDDS_G16(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwAlphaBitDepth==8 && (ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHA)) return LoadDDS_A8(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwRGBBitCount==16 && ddsd.ddpfPixelFormat.dwRBitMask==0x7c00 && ddsd.ddpfPixelFormat.dwGBitMask==0x3e0&&ddsd.ddpfPixelFormat.dwBBitMask==0x1f) return LoadDDS_ARGB1555(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwRGBBitCount==16 && ddsd.ddpfPixelFormat.dwRBitMask==0xf00 && ddsd.ddpfPixelFormat.dwGBitMask==0xf0&&ddsd.ddpfPixelFormat.dwBBitMask==0xf) return LoadDDS_ARGB4444(pFile, &ddsd, pSurface) == PE_OK; else if((ddsd.ddpfPixelFormat.dwFlags & DDPF_RGB) && !(ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) && (ddsd.ddpfPixelFormat.dwRGBBitCount==16)) return LoadDDS_RGB565(pFile, &ddsd, pSurface) == PE_OK; else if((ddsd.ddpfPixelFormat.dwFlags & DDPF_RGB) && !(ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) && (ddsd.ddpfPixelFormat.dwRGBBitCount==24)) return LoadDDS_RGB888(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwRGBBitCount==32 && (ddsd.ddpfPixelFormat.dwRBitMask==0x3ff || ddsd.ddpfPixelFormat.dwRBitMask==0x3ff00000)) return LoadDDS_ABGR2101010(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwRGBBitCount==32 && ddsd.ddpfPixelFormat.dwRBitMask==0xffff && ddsd.ddpfPixelFormat.dwGBitMask==0xffff0000) return LoadDDS_G16R16(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwRGBBitCount==16 && ddsd.ddpfPixelFormat.dwRBitMask==0xffff) return LoadDDS_R16(pFile, &ddsd, pSurface) == PE_OK; else if(ddsd.ddpfPixelFormat.dwRGBBitCount==32) return LoadDDS_RGB8888(pFile, &ddsd, pSurface, (ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) ? true : false) == PE_OK; else if(ddsd.ddpfPixelFormat.dwRGBBitCount==16 && ddsd.ddpfPixelFormat.dwRBitMask==0x7c00 && ddsd.ddpfPixelFormat.dwGBitMask==0x3e0&&ddsd.ddpfPixelFormat.dwBBitMask==0x1f && ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0x8000) return LoadDDS_ARGB1555(pFile, &ddsd, pSurface) == PE_OK; // This case is never executed (the above one supercedes it) *** return false; } bool DDSFree(GX2Surface* pSurface) { return GenericFreeFunction(pSurface) == PE_OK; } void DDSConvertMipsToCubeFormat( const GX2Surface* pSurface, u8* pWrite ) { int minMipSize; if( pSurface->format == GX2_SURFACE_FORMAT_T_BC1_UNORM || pSurface->format == GX2_SURFACE_FORMAT_T_BC1_SRGB ) { minMipSize = 8; } else if( pSurface->format >= GX2_SURFACE_FORMAT_T_BC2_UNORM && pSurface->format <= GX2_SURFACE_FORMAT_T_BC5_SNORM ) { minMipSize = 16; } else { minMipSize = 1; } const u8* pReadImg = (u8*)pSurface->imagePtr; const u8* pReadMip = (u8*)pSurface->mipPtr; for( u32 i = 0; i < 6; ++i ) { int faceSize = pSurface->imageSize/6; memcpy( pWrite, pReadImg + (faceSize*i), faceSize ); pWrite += faceSize; int mipOffset = 0; for( u32 j = 0; j < pSurface->numMips-1; ++j ) { int mipSize = faceSize >> ((j+1)*2); mipSize = max( mipSize, minMipSize ); memcpy( pWrite, pReadMip + mipOffset + (mipSize*i), mipSize ); pWrite += mipSize; mipOffset += mipSize * 6; } assert( mipOffset == pSurface->mipSize ); } } bool DDSSaveFile(const TCHAR* pszFilename, const GX2Surface* pSurface) { assert(pszFilename); assert(pSurface); FILE* pFile = NULL; if(_tfopen_s(&pFile, pszFilename, _T("wb"))) { return false; } fwrite(&DDS_HEADER ,sizeof(u32), 1, pFile); // Cube-maps are stored differently than normal textures. // Rather than have mip levels offset from the main image data, // mips for a particular face directly follow that face in memory. void* pTempImg = NULL, *pTempMip = NULL; u8* pTempData = NULL; if( pSurface->dim == GX2_SURFACE_DIM_CUBE && pSurface->numMips > 1 ) { // Store image data. pTempImg = malloc( pSurface->imageSize ); pTempMip = malloc( pSurface->mipSize ); memcpy( pTempImg, pSurface->imagePtr, pSurface->imageSize ); memcpy( pTempMip, pSurface->mipPtr , pSurface->mipSize ); assert((pSurface->imageSize%6) == 0); pTempData = (u8*)malloc( pSurface->imageSize + pSurface->mipSize ); DDSConvertMipsToCubeFormat( pSurface, pTempData ); memcpy( pSurface->imagePtr, pTempData, pSurface->imageSize ); memcpy( pSurface->mipPtr, pTempData + pSurface->imageSize, pSurface->mipSize ); } bool ret = false; if(pSurface->format == GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UNORM) ret = SaveDDS_ABGR16(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT) ret = SaveDDS_ABGR16F(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT) ret = SaveDDS_ABGR32F(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM) ret = SaveDDS_ABGR2101010(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM) ret = SaveDDS_RGB565(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM) ret = SaveDDS_ARGB1555(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM) ret = SaveDDS_ARGB4444(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_TC_R8_UNORM) ret = SaveDDS_G8(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_TC_R8_G8_UNORM) ret = SaveDDS_A8L8(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM) ret = SaveDDS_ARGB8888(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB) ret = SaveDDS_ARGB8888(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_T_BC1_UNORM) ret = SaveDDS_FourCC(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_T_BC2_UNORM) ret = SaveDDS_FourCC(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_T_BC3_UNORM) ret = SaveDDS_FourCC(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_T_BC4_UNORM) ret = SaveDDS_FourCC(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_T_BC4_SNORM) ret = SaveDDS_FourCC(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_T_BC5_UNORM) ret = SaveDDS_FourCC(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_T_BC5_SNORM) ret = SaveDDS_FourCC(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_T_BC1_SRGB) ret = SaveDDS10(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_T_BC2_SRGB) ret = SaveDDS10(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_T_BC3_SRGB) ret = SaveDDS10(pFile, pSurface) == PE_OK; else if(pSurface->format == GX2_SURFACE_FORMAT_TC_R11_G11_B10_FLOAT) ret = SaveDDS10(pFile, pSurface) == PE_OK; // Restore image data. if( pTempData ) { memcpy( pSurface->imagePtr, pTempImg, pSurface->imageSize ); memcpy( pSurface->mipPtr, pTempMip, pSurface->mipSize ); free( pTempImg ); free( pTempMip ); free( pTempData ); pTempImg = NULL; pTempMip = NULL; pTempData = NULL; } return ret; } TU_Error LoadDDS_FourCC(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TextureDataType tdt = TDT_XRGB; if (pDDSD->ddpfPixelFormat.dwFourCC == MAKEFOURCC('A', 'T', 'I', '1') || pDDSD->ddpfPixelFormat.dwFourCC == MAKEFOURCC('B', 'C', '4', 'U')) { tdt = TDT_R; } else if (pDDSD->ddpfPixelFormat.dwFourCC == MAKEFOURCC('A', 'T', 'I', '2') || pDDSD->ddpfPixelFormat.dwFourCC == MAKEFOURCC('B', 'C', '5', 'U')) { tdt = TDT_RG; } TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Compressed, tdt, PreLoopFourCC, LoopFourCC, PostLoopFourCC); fclose(pFile); return err; } TU_Error LoadDDS_RGB565(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_8bit, TDT_RGB, PreLoopRGB565, LoopRGB565, PostLoopRGB565); fclose(pFile); return err; } TU_Error LoadDDS_RGB888(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_8bit, TDT_XRGB, PreLoopRGB888, LoopRGB888, PostLoopRGB888); fclose(pFile); return err; } TU_Error LoadDDS_RGB8888(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface, bool bAlpha) { ARGB8888Struct* pARGB8888Struct = (ARGB8888Struct*)calloc(sizeof(ARGB8888Struct), 1); void* extra = pARGB8888Struct; pARGB8888Struct->nFlags |= EF_UseBitMasks; if(pARGB8888Struct->nFlags & EF_UseBitMasks) { //using bitmasks pARGB8888Struct->pMemory = malloc(4 * pDDSD->dwWidth * pDDSD->dwHeight); pARGB8888Struct->nRMask = pDDSD->ddpfPixelFormat.dwRBitMask; pARGB8888Struct->nGMask = pDDSD->ddpfPixelFormat.dwGBitMask; pARGB8888Struct->nBMask = pDDSD->ddpfPixelFormat.dwBBitMask; int shift = 0; int tempMask = pARGB8888Struct->nRMask; while(!(tempMask & 0xFF) && tempMask) { shift += 8; tempMask >>= 8; } pARGB8888Struct->nRShift = shift; shift = 0; tempMask = pARGB8888Struct->nGMask; while(!(tempMask & 0xFF) && tempMask) { shift += 8; tempMask >>= 8; } pARGB8888Struct->nGShift = shift; shift = 0; tempMask = pARGB8888Struct->nBMask; while(!(tempMask & 0xFF) && tempMask) { shift += 8; tempMask >>= 8; } pARGB8888Struct->nBShift = shift; } TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_8bit, bAlpha ? TDT_ARGB : TDT_XRGB, PreLoopRGB8888, LoopRGB8888, PostLoopRGB8888); fclose(pFile); return err; } TU_Error LoadDDS_ABGR2101010(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { TU_Error err = PE_Unknown; ChannelFormat channelFormat = CF_2101010; void* pChannelFormat = &channelFormat; if (pDDSD->ddpfPixelFormat.dwRBitMask==0x000003ff) { err = GenericLoadFunction(pFile, pDDSD, pSurface, pChannelFormat, channelFormat, TDT_ARGB, PreLoopDefault, LoopA2R10G10B10, PostLoopDefault); } else if (pDDSD->ddpfPixelFormat.dwRBitMask==0x3ff00000) { err = GenericLoadFunction(pFile, pDDSD, pSurface, pChannelFormat, channelFormat, TDT_ARGB, PreLoopDefault, LoopDefault, PostLoopDefault); } else { // read R10G10B10A2 err = GenericLoadFunction(pFile, pDDSD, pSurface, pChannelFormat, channelFormat, TDT_ARGB, PreLoopDefault, LoopDefault /*LoopR10G10B10A2*/, PostLoopDefault); } fclose(pFile); return err; } TU_Error LoadDDS_ABGR32F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Float32, TDT_ARGB, PreLoopABGR32F, LoopABGR32F, PostLoopABGR32F); fclose(pFile); return err; } TU_Error LoadDDS_GR32F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Float32, TDT_RG, PreLoopABGR32F, LoopGR32F, PostLoopABGR32F); fclose(pFile); return err; } TU_Error LoadDDS_R32F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Float32, TDT_R, PreLoopABGR32F, LoopR32F, PostLoopABGR32F); fclose(pFile); return err; } TU_Error LoadDDS_R16F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Float16, TDT_R, PreLoopABGR16F, LoopR16F, PostLoopABGR16F); fclose(pFile); return err; } TU_Error LoadDDS_G16R16F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Float16, TDT_RG, PreLoopABGR16F, LoopG16R16, PostLoopABGR16F); fclose(pFile); return err; } TU_Error LoadDDS_ABGR16F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Float16, TDT_ARGB, PreLoopABGR16, LoopABGR16, PostLoopABGR16); fclose(pFile); return err; } TU_Error LoadDDS_A4L4(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Compressed, TDT_RG, PreLoopA4L4, LoopA4L4, PostLoopA4L4); fclose(pFile); return err; } TU_Error LoadDDS_A8L8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Compressed, TDT_RG, PreLoopA8L8, LoopA8L8, PostLoopA8L8); fclose(pFile); return err; } TU_Error LoadDDS_G8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Compressed, TDT_XRGB, PreLoopG8, LoopG8, PostLoopG8); fclose(pFile); return err; } TU_Error LoadDDS_AG8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Compressed, TDT_ARGB, PreLoopAG8, LoopAG8, PostLoopAG8); fclose(pFile); return err; } TU_Error LoadDDS_G16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Compressed, TDT_XRGB, PreLoopG16, LoopG16, PostLoopG16); fclose(pFile); return err; } TU_Error LoadDDS_A8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Compressed, TDT_ARGB, PreLoopA8, LoopA8, PostLoopA8); fclose(pFile); return err; } TU_Error LoadDDS_ABGR16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_16bit, TDT_ARGB, PreLoopABGR16, LoopABGR16, PostLoopABGR16); fclose(pFile); return err; } TU_Error LoadDDS_G16R16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_16bit, TDT_RG, PreLoopG16R16, LoopG16R16, PostLoopG16R16); fclose(pFile); return err; } TU_Error LoadDDS_ARGB1555(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_1555, TDT_ARGB, PreLoopARGB1555, LoopARGB1555, PostLoopARGB1555); fclose(pFile); return err; } TU_Error LoadDDS_ARGB4444(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_4444, TDT_ARGB, PreLoopARGB4444, LoopARGB4444, PostLoopARGB4444); fclose(pFile); return err; } TU_Error LoadDDS_R16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; TU_Error err = GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_16bit, TDT_R, PreLoopG16R16, LoopABGR16, PostLoopG16R16); fclose(pFile); return err; } /////////////////////////////////////////////////// /// SAVE FUNCTIONS ////////////////////////////////////////////////// TU_Error SaveDDS_RGB565(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); // Initialise surface descriptor DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, false); ddsd2.lPitch = pSurface->width * 2; ddsd2.ddpfPixelFormat.dwRGBBitCount = 16; ddsd2.ddpfPixelFormat.dwFlags = DDPF_RGB; // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) { u16 value; for (u32 count = 0; count < (pSurface->imageSize / 2); count++) { value = *((u16*)pSurface->imagePtr + count); *((u16*)pSurface->imagePtr + count) = ((value & 0xf800) >> 11) | (value & 0x07e0) | ((value & 0x1f) << 11); } fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); } if(pSurface->mipSize > 0) { u16 value; for (u32 count = 0; count < (pSurface->mipSize / 2); count++) { value = *((u16*)pSurface->mipPtr + count); *((u16*)pSurface->mipPtr + count) = ((value & 0xf800) >> 11) | (value & 0x07e0) | ((value & 0x1f) << 11); } fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); } fclose(pFile); return PE_OK; } TU_Error SaveDDS_ARGB4444(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); // Initialise surface descriptor DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, false); ddsd2.ddpfPixelFormat.dwRBitMask = 0xf00; ddsd2.ddpfPixelFormat.dwGBitMask = 0xf0; ddsd2.ddpfPixelFormat.dwBBitMask = 0xf; ddsd2.lPitch = pSurface->width * 2; ddsd2.ddpfPixelFormat.dwRGBBitCount = 16; ddsd2.ddpfPixelFormat.dwFlags = DDPF_RGB|DDPF_ALPHAPIXELS; // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) { u16 value; for (u32 count = 0; count < (pSurface->imageSize / 2); count++) { value = *((u16*)pSurface->imagePtr + count); //ARGB ABGR *((u16*)pSurface->imagePtr + count) = (value & 0xf000) | ((value & 0x0f00) >> 8) | (value & 0x00f0) | ((value & 0x000f) << 8); } fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); } if(pSurface->mipSize > 0) { u16 value; for (u32 count = 0; count < (pSurface->mipSize / 2); count++) { value = *((u16*)pSurface->mipPtr + count); //ARGB ABGR *((u16*)pSurface->mipPtr + count) = (value & 0xf000) | ((value & 0x0f00) >> 8) | (value & 0x00f0) | ((value & 0x000f) << 8); } fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); } fclose(pFile); return PE_OK; } TU_Error SaveDDS_ARGB1555(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); // Initialise surface descriptor DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, false); ddsd2.ddpfPixelFormat.dwRBitMask = 0x7c00; ddsd2.ddpfPixelFormat.dwGBitMask = 0x3e0; ddsd2.ddpfPixelFormat.dwBBitMask = 0x1f; ddsd2.ddpfPixelFormat.dwRGBAlphaBitMask = 0x8000; ddsd2.lPitch = pSurface->width * 2; ddsd2.ddpfPixelFormat.dwRGBBitCount = 16; ddsd2.ddpfPixelFormat.dwFlags = DDPF_RGB|DDPF_ALPHAPIXELS; // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) { u16 value; for (u32 count = 0; count < pSurface->imageSize/2; count++) { value = *((u16*)pSurface->imagePtr + count); // [MSB] ARGB [LSB] to ABGR *((u16*)pSurface->imagePtr + count) = ((value & 0x8000)) | ((value & 0x7c00) >> 10) | ((value & 0x001f) << 10) | (value & 0x03e0); } fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); } if(pSurface->mipSize > 0) { u16 value; for (u32 count = 0; count < pSurface->mipSize/2; count++) { value = *((u16*)pSurface->mipPtr + count); // [MSB] ARGB [LSB] to ABGR *((u16*)pSurface->mipPtr + count) = ((value & 0x8000)) | ((value & 0x7c00) >> 10) | ((value & 0x001f) << 10) | (value & 0x03e0); } fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); } fclose(pFile); return PE_OK; } TU_Error SaveDDS_ARGB8888(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); // Initialise surface descriptor DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, false); ddsd2.ddpfPixelFormat.dwRBitMask = 0x000000ff; ddsd2.ddpfPixelFormat.dwGBitMask = 0x0000ff00; ddsd2.ddpfPixelFormat.dwBBitMask = 0x00ff0000; ddsd2.lPitch = pSurface->width * 4; ddsd2.ddpfPixelFormat.dwRGBBitCount = 32; ddsd2.ddpfPixelFormat.dwFlags=DDPF_RGB|DDPF_ALPHAPIXELS; ddsd2.ddpfPixelFormat.dwRGBAlphaBitMask = 0x00000000; // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); if(pSurface->mipSize > 0) fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); fclose(pFile); return PE_OK; } TU_Error SaveDDS_ABGR2101010(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); // Initialise surface descriptor DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, false); ddsd2.ddpfPixelFormat.dwRBitMask = 0x3ff00000; ddsd2.ddpfPixelFormat.dwGBitMask = 0x000ffc00; ddsd2.ddpfPixelFormat.dwBBitMask = 0x000003ff; ddsd2.ddpfPixelFormat.dwRGBAlphaBitMask = 0xc0000000; ddsd2.lPitch = pSurface->width * 4; ddsd2.ddpfPixelFormat.dwRGBBitCount = 32; ddsd2.ddpfPixelFormat.dwFlags=DDPF_ALPHAPIXELS|DDPF_RGB; // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); if(pSurface->mipSize > 0) fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); fclose(pFile); return PE_OK; } TU_Error SaveDDS_ABGR16(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); // Initialise surface descriptor DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, false); ddsd2.lPitch = pSurface->width * 8; ddsd2.ddpfPixelFormat.dwFlags = DDPF_FOURCC|DDPF_ALPHAPIXELS; ddsd2.ddpfPixelFormat.dwFourCC = D3DFMT_A16B16G16R16; // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); if(pSurface->mipSize > 0) fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); fclose(pFile); return PE_OK; } TU_Error SaveDDS_R16(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); // Initialise surface descriptor DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, false); ddsd2.lPitch = pSurface->width * 2; ddsd2.ddpfPixelFormat.dwFlags = DDPF_FOURCC|DDPF_ALPHAPIXELS; ddsd2.ddpfPixelFormat.dwFourCC = D3DFMT_L16; // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); if(pSurface->mipSize > 0) fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); fclose(pFile); return PE_OK; } TU_Error SaveDDS_RG16(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); // Initialise surface descriptor DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, false); ddsd2.lPitch = pSurface->width * 4; ddsd2.ddpfPixelFormat.dwFlags = DDPF_FOURCC|DDPF_ALPHAPIXELS; ddsd2.ddpfPixelFormat.dwFourCC = D3DFMT_G16R16; // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); if(pSurface->mipSize > 0) fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); fclose(pFile); return PE_OK; } TU_Error SaveDDS_ABGR16F(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); // Initialise surface descriptor DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, false); ddsd2.lPitch = pSurface->width * 8; ddsd2.ddpfPixelFormat.dwFlags = DDPF_FOURCC|DDPF_ALPHAPIXELS; ddsd2.ddpfPixelFormat.dwFourCC = D3DFMT_A16B16G16R16F; // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); if(pSurface->mipSize > 0) fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); fclose(pFile); return PE_OK; } TU_Error SaveDDS_R16F(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); // Initialise surface descriptor DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, false); ddsd2.lPitch = pSurface->width * 2; ddsd2.ddpfPixelFormat.dwFlags = DDPF_FOURCC|DDPF_ALPHAPIXELS; ddsd2.ddpfPixelFormat.dwFourCC = D3DFMT_R16F; // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); if(pSurface->mipSize > 0) fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); fclose(pFile); return PE_OK; } TU_Error SaveDDS_RG16F(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); // Initialise surface descriptor DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, false); ddsd2.lPitch = pSurface->width * 4; ddsd2.ddpfPixelFormat.dwFlags = DDPF_FOURCC|DDPF_ALPHAPIXELS; ddsd2.ddpfPixelFormat.dwFourCC = D3DFMT_G16R16F; // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); if(pSurface->mipSize > 0) fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); fclose(pFile); return PE_OK; } TU_Error SaveDDS_ABGR32F(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); // Initialise surface descriptor DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, false); ddsd2.lPitch = pSurface->width * 16; ddsd2.ddpfPixelFormat.dwFlags=DDPF_FOURCC|DDPF_ALPHAPIXELS; ddsd2.ddpfPixelFormat.dwFourCC = D3DFMT_A32B32G32R32F; // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); if(pSurface->mipSize > 0) fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); fclose(pFile); return PE_OK; } TU_Error SaveDDS_R32F(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); // Initialise surface descriptor DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, false); ddsd2.lPitch = pSurface->width * 4; ddsd2.ddpfPixelFormat.dwFlags=DDPF_FOURCC|DDPF_ALPHAPIXELS; ddsd2.ddpfPixelFormat.dwFourCC = D3DFMT_R32F; // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); if(pSurface->mipSize > 0) fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); fclose(pFile); return PE_OK; } TU_Error SaveDDS_RG32F(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); // Initialise surface descriptor DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, false); ddsd2.lPitch = pSurface->width * 8; ddsd2.ddpfPixelFormat.dwFlags=DDPF_FOURCC|DDPF_ALPHAPIXELS; ddsd2.ddpfPixelFormat.dwFourCC = D3DFMT_G32R32F; // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); if(pSurface->mipSize > 0) fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); fclose(pFile); return PE_OK; } TU_Error SaveDDS_FourCC(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, true); if (pSurface->format == GX2_SURFACE_FORMAT_T_BC1_UNORM) { ddsd2.ddpfPixelFormat.dwFourCC = MAKEFOURCC('D', 'X', 'T', '1'); } else if (pSurface->format == GX2_SURFACE_FORMAT_T_BC2_UNORM) { ddsd2.ddpfPixelFormat.dwFourCC = MAKEFOURCC('D', 'X', 'T', '3'); } else if (pSurface->format == GX2_SURFACE_FORMAT_T_BC3_UNORM) { ddsd2.ddpfPixelFormat.dwFourCC = MAKEFOURCC('D', 'X', 'T', '5'); } else if (pSurface->format == GX2_SURFACE_FORMAT_T_BC4_UNORM) { ddsd2.ddpfPixelFormat.dwFourCC = MAKEFOURCC('A', 'T', 'I', '1'); } else if (pSurface->format == GX2_SURFACE_FORMAT_T_BC4_SNORM) { ddsd2.ddpfPixelFormat.dwFourCC = MAKEFOURCC('A', 'T', 'I', '1'); } else if (pSurface->format == GX2_SURFACE_FORMAT_T_BC5_UNORM) { ddsd2.ddpfPixelFormat.dwFourCC = MAKEFOURCC('A', 'T', 'I', '2'); } else if (pSurface->format == GX2_SURFACE_FORMAT_T_BC5_SNORM) { ddsd2.ddpfPixelFormat.dwFourCC = MAKEFOURCC('A', 'T', 'I', '2'); } else { return PE_Unknown; } ddsd2.ddpfPixelFormat.dwFlags=DDPF_FOURCC; /* if(pMipSet->m_TextureDataType == TDT_ARGB) ddsd2.ddpfPixelFormat.dwFlags |= DDPF_ALPHAPIXELS; if(pMipSet->m_Flags & MS_AlphaPremult) ddsd2.ddpfPixelFormat.dwFlags |= DDPF_ALPHAPREMULT; ddsd2.ddpfPixelFormat.dwPrivateFormatBitCount = pMipSet->m_dwFourCC2; */ // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); if(pSurface->mipSize > 0) fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); fclose(pFile); return PE_OK; } TU_Error SaveDDS_G8(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, false); ddsd2.lPitch = pSurface->width * 8; ddsd2.ddpfPixelFormat.dwFlags=DDPF_LUMINANCE; ddsd2.ddpfPixelFormat.dwLuminanceBitCount = 8; ddsd2.ddpfPixelFormat.dwLuminanceBitMask = 0xff; // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); if(pSurface->mipSize > 0) fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); fclose(pFile); return PE_OK; } TU_Error SaveDDS_A8(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, false); ddsd2.lPitch = pSurface->width * 8; ddsd2.ddpfPixelFormat.dwFlags=DDPF_ALPHA; ddsd2.ddpfPixelFormat.dwAlphaBitDepth = 8; ddsd2.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff; // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); if(pSurface->mipSize > 0) fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); fclose(pFile); return PE_OK; } TU_Error SaveDDS_A8L8(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); DDSD2 ddsd2; SetupDDSD(ddsd2, pSurface, false); ddsd2.ddpfPixelFormat.dwLuminanceBitCount=16; ddsd2.ddpfPixelFormat.dwFlags = DDPF_LUMINANCE|DDPF_ALPHAPIXELS; ddsd2.lPitch = pSurface->width * 8; ddsd2.ddpfPixelFormat.dwRBitMask = 0x000000ff; ddsd2.ddpfPixelFormat.dwRGBAlphaBitMask = 0x0000ff00; // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); if(pSurface->imageSize > 0) fwrite(pSurface->imagePtr, 1, pSurface->imageSize, pFile); if(pSurface->mipSize > 0) fwrite(pSurface->mipPtr, 1, pSurface->mipSize, pFile); fclose(pFile); return PE_OK; } } //namespace DDSReader