/*---------------------------------------------------------------------------* 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_10.cpp // ------------------------------------------------------------------ #include "stdafx.h" #include #include #include #include "ddraw.h" #include "D3D10.h" #include "DDS_10.h" #include "DDS_Helpers.h" #include "resource.h" namespace DDSReader { TU_Error LoadDDS10_RGBA_32F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS10_RGBA32(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS10_RGBA_16F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS10_RGBA16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS10_RG32(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS10_R10G10B10A2(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS10_R11G11B10F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS10_R8G8B8A8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS10_R16G16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS10_R32(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS10_R8G8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS10_R16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS10_R8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface); TU_Error LoadDDS10_FourCC(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface, u32 dwFourCC); #define FOURCC_ATI1N MAKEFOURCC('A', 'T', 'I', '1') #define FOURCC_ATI2N MAKEFOURCC('A', 'T', 'I', '2') typedef struct { DXGI_FORMAT dxgiFormat; D3D10_RESOURCE_DIMENSION resourceDimension; UINT miscFlag; // Used for D3D10_RESOURCE_MISC_FLAG UINT arraySize; UINT reserved; // Currently unused } DDS_HEADER_DDS10; TU_Error LoadDDS10(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { DDS_HEADER_DDS10 HeaderDDS10;; fread(&HeaderDDS10, sizeof(HeaderDDS10), 1, pFile); TU_Error err = PE_Unknown; switch(HeaderDDS10.dxgiFormat) { case DXGI_FORMAT_R32G32B32A32_FLOAT: err = LoadDDS10_RGBA_32F(pFile, pDDSD, pSurface); break; case DXGI_FORMAT_R32G32B32A32_UINT: case DXGI_FORMAT_R32G32B32A32_TYPELESS: case DXGI_FORMAT_R32G32B32A32_SINT: err = LoadDDS10_RGBA32(pFile, pDDSD, pSurface); break; case DXGI_FORMAT_R16G16B16A16_FLOAT: case DXGI_FORMAT_R16G16B16A16_UINT: case DXGI_FORMAT_R16G16B16A16_TYPELESS: case DXGI_FORMAT_R16G16B16A16_SNORM: case DXGI_FORMAT_R16G16B16A16_SINT: err = LoadDDS10_RGBA16(pFile, pDDSD, pSurface); break; case DXGI_FORMAT_R32G32_TYPELESS: case DXGI_FORMAT_R32G32_FLOAT: case DXGI_FORMAT_R32G32_UINT: case DXGI_FORMAT_R32G32_SINT: err = LoadDDS10_RG32(pFile, pDDSD, pSurface); break; case DXGI_FORMAT_R10G10B10A2_TYPELESS: case DXGI_FORMAT_R10G10B10A2_UNORM: case DXGI_FORMAT_R10G10B10A2_UINT: err = LoadDDS10_R10G10B10A2(pFile, pDDSD, pSurface); break; case DXGI_FORMAT_R11G11B10_FLOAT: err = LoadDDS10_R11G11B10F(pFile, pDDSD, pSurface); break; case DXGI_FORMAT_R8G8B8A8_TYPELESS: case DXGI_FORMAT_R8G8B8A8_UNORM: case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: case DXGI_FORMAT_R8G8B8A8_UINT: case DXGI_FORMAT_R8G8B8A8_SNORM: case DXGI_FORMAT_R8G8B8A8_SINT: err = LoadDDS10_R8G8B8A8(pFile, pDDSD, pSurface); break; case DXGI_FORMAT_R16G16_TYPELESS: case DXGI_FORMAT_R16G16_UNORM: case DXGI_FORMAT_R16G16_UINT: case DXGI_FORMAT_R16G16_SNORM: case DXGI_FORMAT_R16G16_SINT: err = LoadDDS10_R16G16(pFile, pDDSD, pSurface); break; case DXGI_FORMAT_R32_TYPELESS: case DXGI_FORMAT_R32_UINT: case DXGI_FORMAT_R32_SINT: err = LoadDDS10_R32(pFile, pDDSD, pSurface); break; case DXGI_FORMAT_R8G8_TYPELESS: case DXGI_FORMAT_R8G8_UNORM: case DXGI_FORMAT_R8G8_UINT: case DXGI_FORMAT_R8G8_SNORM: case DXGI_FORMAT_R8G8_SINT: err = LoadDDS10_R8G8(pFile, pDDSD, pSurface); break; case DXGI_FORMAT_R16_TYPELESS: case DXGI_FORMAT_R16_FLOAT: case DXGI_FORMAT_D16_UNORM: case DXGI_FORMAT_R16_UNORM: case DXGI_FORMAT_R16_UINT: case DXGI_FORMAT_R16_SNORM: case DXGI_FORMAT_R16_SINT: err = LoadDDS10_R16(pFile, pDDSD, pSurface); break; case DXGI_FORMAT_R8_TYPELESS: case DXGI_FORMAT_R8_UNORM: case DXGI_FORMAT_R8_UINT: case DXGI_FORMAT_R8_SNORM: case DXGI_FORMAT_R8_SINT: err = LoadDDS10_R8(pFile, pDDSD, pSurface); break; case DXGI_FORMAT_BC1_TYPELESS: case DXGI_FORMAT_BC1_UNORM: case DXGI_FORMAT_BC1_UNORM_SRGB: err = LoadDDS10_FourCC(pFile, pDDSD, pSurface, FOURCC_BC1); break; case DXGI_FORMAT_BC2_TYPELESS: case DXGI_FORMAT_BC2_UNORM: case DXGI_FORMAT_BC2_UNORM_SRGB: err = LoadDDS10_FourCC(pFile, pDDSD, pSurface, FOURCC_BC2); break; case DXGI_FORMAT_BC3_TYPELESS: case DXGI_FORMAT_BC3_UNORM: case DXGI_FORMAT_BC3_UNORM_SRGB: err = LoadDDS10_FourCC(pFile, pDDSD, pSurface, FOURCC_BC3); break; case DXGI_FORMAT_BC4_TYPELESS: case DXGI_FORMAT_BC4_UNORM: case DXGI_FORMAT_BC4_SNORM: err = LoadDDS10_FourCC(pFile, pDDSD, pSurface, FOURCC_BC4); break; case DXGI_FORMAT_BC5_TYPELESS: case DXGI_FORMAT_BC5_UNORM: case DXGI_FORMAT_BC5_SNORM: err = LoadDDS10_FourCC(pFile, pDDSD, pSurface, FOURCC_BC5); break; default: ASSERT(0); } fclose(pFile); return err; } TU_Error LoadDDS10_RGBA_32F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Float32, TDT_ARGB, PreLoopABGR32F, LoopABGR32F, PostLoopABGR32F); } TU_Error LoadDDS10_RGBA32(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_32bit, TDT_ARGB, PreLoopABGR32F, LoopABGR32F, PostLoopABGR32F); } TU_Error LoadDDS10_RGBA_16F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Float16, TDT_ARGB, PreLoopABGR16F, LoopABGR16F, PostLoopABGR16F); } TU_Error LoadDDS10_RGBA16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Float16, TDT_ARGB, PreLoopABGR16F, LoopABGR16F, PostLoopABGR16F); } TU_Error LoadDDS10_RG32(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_32bit, TDT_XRGB, PreLoopABGR32, LoopR32G32, PreLoopABGR32); } TU_Error LoadDDS10_R10G10B10A2(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { ChannelFormat channelFormat = CF_2101010; void* pChannelFormat = &channelFormat; return GenericLoadFunction(pFile, pDDSD, pSurface, pChannelFormat, channelFormat, TDT_ARGB, PreLoopDefault, LoopDefault /*LoopR10G10B10A2*/, PostLoopDefault); } TU_Error LoadDDS10_R11G11B10F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { return PE_Unknown; } TU_Error LoadDDS10_R8G8B8A8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { ARGB8888Struct* pARGB8888Struct = (ARGB8888Struct*)calloc(sizeof(ARGB8888Struct), 1); void* extra = pARGB8888Struct; pARGB8888Struct->nFlags |= EF_UseBitMasks; pARGB8888Struct->pMemory = malloc(4 * pDDSD->dwWidth * pDDSD->dwHeight); pARGB8888Struct->nRMask = 0x000000ff; pARGB8888Struct->nGMask = 0x0000ff00; pARGB8888Struct->nBMask = 0x00ff0000; pARGB8888Struct->nRShift = 0; pARGB8888Struct->nGShift = 8; pARGB8888Struct->nBShift = 16; return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_8bit, TDT_ARGB, PreLoopRGB8888, LoopRGB8888, PostLoopRGB8888); } TU_Error LoadDDS10_R16G16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_16bit, TDT_XRGB, PreLoopABGR16, LoopR16G16, PreLoopABGR16); } TU_Error LoadDDS10_R8G8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_8bit, TDT_XRGB, PreLoopRGB8888, LoopR8G8, PreLoopRGB8888); } TU_Error LoadDDS10_R32(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_32bit, TDT_XRGB, PreLoopABGR32, LoopR32, PostLoopABGR32); } TU_Error LoadDDS10_R16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_16bit, TDT_XRGB, PreLoopABGR16, LoopR16, PostLoopABGR16); } TU_Error LoadDDS10_R8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface) { void* extra; return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_8bit, TDT_XRGB, PreLoopRGB8888, LoopR8, PreLoopRGB8888); } TU_Error LoadDDS10_FourCC(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface, u32 dwFourCC) { void* extra; return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Compressed, TDT_XRGB, PreLoopFourCC, LoopFourCC, PostLoopFourCC); } DXGI_FORMAT GetDXGIFormat(const GX2Surface* pSurface) { switch (pSurface->format) { case GX2_SURFACE_FORMAT_T_BC1_UNORM: return DXGI_FORMAT_BC1_UNORM; case GX2_SURFACE_FORMAT_T_BC1_SRGB: return DXGI_FORMAT_BC1_UNORM_SRGB; case GX2_SURFACE_FORMAT_T_BC2_UNORM: return DXGI_FORMAT_BC2_UNORM; case GX2_SURFACE_FORMAT_T_BC2_SRGB: return DXGI_FORMAT_BC2_UNORM_SRGB; case GX2_SURFACE_FORMAT_T_BC3_UNORM: return DXGI_FORMAT_BC3_UNORM; case GX2_SURFACE_FORMAT_T_BC3_SRGB: return DXGI_FORMAT_BC3_UNORM_SRGB; case GX2_SURFACE_FORMAT_T_BC4_UNORM: return DXGI_FORMAT_BC4_UNORM; case GX2_SURFACE_FORMAT_T_BC4_SNORM: return DXGI_FORMAT_BC4_SNORM; case GX2_SURFACE_FORMAT_T_BC5_UNORM: return DXGI_FORMAT_BC5_UNORM; case GX2_SURFACE_FORMAT_T_BC5_SNORM: return DXGI_FORMAT_BC5_SNORM; case GX2_SURFACE_FORMAT_TC_R11_G11_B10_FLOAT: return DXGI_FORMAT_R11G11B10_FLOAT; } return DXGI_FORMAT_UNKNOWN; } bool SetupDDSD10(DDS_HEADER_DDS10& HeaderDDS10, const GX2Surface* pSurface) { memset(&HeaderDDS10, 0, sizeof(HeaderDDS10)); ASSERT(pSurface); if(pSurface == NULL) return false; HeaderDDS10.dxgiFormat = GetDXGIFormat(pSurface); if(pSurface->dim == GX2_SURFACE_DIM_2D) { HeaderDDS10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D; HeaderDDS10.miscFlag = 0; HeaderDDS10.arraySize = 1; } else if(pSurface->dim == GX2_SURFACE_DIM_CUBE) { HeaderDDS10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D; HeaderDDS10.miscFlag = D3D10_RESOURCE_MISC_TEXTURECUBE; HeaderDDS10.arraySize = 6; } else { HeaderDDS10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D; HeaderDDS10.miscFlag = 0; HeaderDDS10.arraySize = pSurface->depth; } HeaderDDS10.reserved = 0; return true; } TU_Error SaveDDS10(FILE* pFile, const GX2Surface* pSurface) { assert(pFile); assert(pSurface); DDSD2 ddsd2; SetupDDSD_DDS10(ddsd2, pSurface, true); ddsd2.ddpfPixelFormat.dwFlags = DDPF_FOURCC; ddsd2.ddpfPixelFormat.dwFourCC = MAKEFOURCC('D', 'X', '1', '0'); switch (pSurface->format) { case GX2_SURFACE_FORMAT_T_BC1_UNORM: case GX2_SURFACE_FORMAT_T_BC1_SRGB: case GX2_SURFACE_FORMAT_T_BC4_UNORM: case GX2_SURFACE_FORMAT_T_BC4_SNORM: ddsd2.lPitch = ddsd2.dwWidth * 2; break; case GX2_SURFACE_FORMAT_T_BC2_UNORM: case GX2_SURFACE_FORMAT_T_BC2_SRGB: case GX2_SURFACE_FORMAT_T_BC3_UNORM: case GX2_SURFACE_FORMAT_T_BC3_SRGB: case GX2_SURFACE_FORMAT_T_BC5_UNORM: case GX2_SURFACE_FORMAT_T_BC5_SNORM: ddsd2.lPitch = ddsd2.dwWidth * 4; break; case GX2_SURFACE_FORMAT_TC_R11_G11_B10_FLOAT: ddsd2.lPitch = ddsd2.dwWidth * 4; break; } // Write the data fwrite(&ddsd2, sizeof(DDSD2), 1, pFile); DDS_HEADER_DDS10 HeaderDDS10; SetupDDSD10(HeaderDDS10, pSurface); fwrite(&HeaderDDS10, sizeof(HeaderDDS10), 1, pFile); if(pSurface->imageSize > 0) fwrite(pSurface->imagePtr, GFD_ELEMENT_SIZE_32, (pSurface->imageSize + 3) / GFD_ELEMENT_SIZE_32, pFile); if(pSurface->mipSize > 0) fwrite(pSurface->mipPtr, GFD_ELEMENT_SIZE_32, (pSurface->mipSize + 3) / GFD_ELEMENT_SIZE_32, pFile); fclose(pFile); return PE_OK; } } //namespace DDSReader