diff --git a/CodeWalker.Core/CodeWalker.Core.csproj b/CodeWalker.Core/CodeWalker.Core.csproj
index 43dc750..045ff6e 100644
--- a/CodeWalker.Core/CodeWalker.Core.csproj
+++ b/CodeWalker.Core/CodeWalker.Core.csproj
@@ -122,6 +122,7 @@
+
diff --git a/CodeWalker.Core/GameFiles/GameFileCache.cs b/CodeWalker.Core/GameFiles/GameFileCache.cs
index 0a1dbff..32d5e3b 100644
--- a/CodeWalker.Core/GameFiles/GameFileCache.cs
+++ b/CodeWalker.Core/GameFiles/GameFileCache.cs
@@ -186,7 +186,7 @@ namespace CodeWalker.GameFiles
//TestCuts();
//TestYlds();
//TestYcds();
- //TestYtds();
+ TestYtds();
//TestYbns();
//TestYdrs();
//TestYdds();
@@ -3440,6 +3440,7 @@ namespace CodeWalker.GameFiles
}
public void TestYtds()
{
+ bool ddstest = true;
bool savetest = false;
var errorfiles = new List();
foreach (RpfFile file in AllRpfs)
@@ -3461,6 +3462,23 @@ namespace CodeWalker.GameFiles
UpdateStatus("Error! " + ex.ToString());
errorfiles.Add(entry);
}
+ if (ddstest && (ytdfile != null) && (ytdfile.TextureDict != null))
+ {
+ foreach (var tex in ytdfile.TextureDict.Textures.data_items)
+ {
+ var dds = Utils.DDSIO.GetDDSFile(tex);
+ var tex2 = Utils.DDSIO.GetTexture(dds);
+ if (!tex.Name.StartsWith("script_rt"))
+ {
+ if (tex.Data?.FullData?.Length != tex2.Data?.FullData?.Length)
+ { }
+ if (tex.Stride != tex2.Stride)
+ { }
+ }
+ if ((tex.Format != tex2.Format) || (tex.Width != tex2.Width) || (tex.Height != tex2.Height) || (tex.Depth != tex2.Depth) || (tex.Levels != tex2.Levels))
+ { }
+ }
+ }
if (savetest && (ytdfile != null) && (ytdfile.TextureDict != null))
{
var fentry = entry as RpfFileEntry;
@@ -3687,7 +3705,7 @@ namespace CodeWalker.GameFiles
}
public void TestYdrs()
{
- bool savetest = true;
+ bool savetest = false;
bool boundsonly = true;
var errorfiles = new List();
foreach (RpfFile file in AllRpfs)
@@ -3800,7 +3818,7 @@ namespace CodeWalker.GameFiles
}
public void TestYfts()
{
- bool savetest = true;
+ bool savetest = false;
var errorfiles = new List();
foreach (RpfFile file in AllRpfs)
{
@@ -3855,6 +3873,7 @@ namespace CodeWalker.GameFiles
}
public void TestYpts()
{
+ var savetest = false;
var errorfiles = new List();
foreach (RpfFile file in AllRpfs)
{
@@ -3875,7 +3894,7 @@ namespace CodeWalker.GameFiles
UpdateStatus("Error! " + ex.ToString());
errorfiles.Add(entry);
}
- if ((ypt != null) && (ypt.PtfxList != null))
+ if (savetest && (ypt != null) && (ypt.PtfxList != null))
{
var fentry = entry as RpfFileEntry;
if (fentry == null)
diff --git a/CodeWalker.Core/GameFiles/Resources/Texture.cs b/CodeWalker.Core/GameFiles/Resources/Texture.cs
index 8b0c977..44cfe68 100644
--- a/CodeWalker.Core/GameFiles/Resources/Texture.cs
+++ b/CodeWalker.Core/GameFiles/Resources/Texture.cs
@@ -22,7 +22,7 @@ namespace CodeWalker.GameFiles
// structure data
public uint Unknown_10h { get; set; } // 0x00000000
public uint Unknown_14h { get; set; } // 0x00000000
- public uint Unknown_18h { get; set; } // 0x00000001
+ public uint Unknown_18h { get; set; } = 1; // 0x00000001
public uint Unknown_1Ch { get; set; } // 0x00000000
public ResourceSimpleList64_uint TextureNameHashes { get; set; }
public ResourcePointerList64 Textures { get; set; }
@@ -143,7 +143,7 @@ namespace CodeWalker.GameFiles
// structure data
public uint VFT { get; set; }
- public uint Unknown_4h { get; set; } // 0x00000001
+ public uint Unknown_4h { get; set; } = 1; // 0x00000001
public uint Unknown_8h { get; set; } // 0x00000000
public uint Unknown_Ch { get; set; } // 0x00000000
public uint Unknown_10h { get; set; } // 0x00000000
@@ -153,7 +153,8 @@ namespace CodeWalker.GameFiles
public uint Unknown_20h { get; set; } // 0x00000000
public uint Unknown_24h { get; set; } // 0x00000000
public ulong NamePointer { get; set; }
- public uint Unknown_30h { get; set; }
+ public ushort Unknown_30h { get; set; } = 1;
+ public ushort Unknown_32h { get; set; }
public uint Unknown_34h { get; set; } // 0x00000000
public uint Unknown_38h { get; set; } // 0x00000000
public uint Unknown_3Ch { get; set; } // 0x00000000
@@ -181,7 +182,8 @@ namespace CodeWalker.GameFiles
this.Unknown_20h = reader.ReadUInt32();
this.Unknown_24h = reader.ReadUInt32();
this.NamePointer = reader.ReadUInt64();
- this.Unknown_30h = reader.ReadUInt32();
+ this.Unknown_30h = reader.ReadUInt16();
+ this.Unknown_32h = reader.ReadUInt16();
this.Unknown_34h = reader.ReadUInt32();
this.Unknown_38h = reader.ReadUInt32();
this.Unknown_3Ch = reader.ReadUInt32();
@@ -195,6 +197,22 @@ namespace CodeWalker.GameFiles
{
NameHash = JenkHash.GenHash(Name.ToLowerInvariant());
}
+
+ switch (Unknown_32h)
+ {
+ case 0x20:
+ case 0x28:
+ case 0x30:
+ case 0x38:
+ case 0x40:
+ case 0x48:
+ case 0x80:
+ case 0x90:
+ case 0x2://embedded
+ break;
+ default:
+ break;
+ }
}
///
@@ -218,6 +236,7 @@ namespace CodeWalker.GameFiles
writer.Write(this.Unknown_24h);
writer.Write(this.NamePointer);
writer.Write(this.Unknown_30h);
+ writer.Write(this.Unknown_32h);
writer.Write(this.Unknown_34h);
writer.Write(this.Unknown_38h);
writer.Write(this.Unknown_3Ch);
@@ -251,13 +270,16 @@ namespace CodeWalker.GameFiles
}
// structure data
- public uint Unknown_40h { get; set; }
+ public byte Unknown_40h { get; set; }
+ public byte Unknown_41h { get; set; }
+ public byte Unknown_42h { get; set; }
+ public byte Unknown_43h { get; set; }
public uint Unknown_44h { get; set; } // 0x00000000
- public uint Unknown_48h { get; set; }
+ public uint Unknown_48h { get; set; } // 0, 1
public uint Unknown_4Ch { get; set; } // 0x00000000
public ushort Width { get; set; }
public ushort Height { get; set; }
- public ushort Unknown_54h { get; set; } // 0x0001
+ public ushort Depth { get; set; } = 1; //is depth > 1 supported?
public ushort Stride { get; set; }
public TextureFormat Format { get; set; }
public byte Unknown_5Ch { get; set; } // 0x00
@@ -299,13 +321,16 @@ namespace CodeWalker.GameFiles
base.Read(reader, parameters);
// read structure data
- this.Unknown_40h = reader.ReadUInt32();
+ this.Unknown_40h = reader.ReadByte();
+ this.Unknown_41h = reader.ReadByte();
+ this.Unknown_42h = reader.ReadByte();
+ this.Unknown_43h = reader.ReadByte();
this.Unknown_44h = reader.ReadUInt32();
this.Unknown_48h = reader.ReadUInt32();
this.Unknown_4Ch = reader.ReadUInt32();
this.Width = reader.ReadUInt16();
this.Height = reader.ReadUInt16();
- this.Unknown_54h = reader.ReadUInt16();
+ this.Depth = reader.ReadUInt16();
this.Stride = reader.ReadUInt16();
this.Format = (TextureFormat)reader.ReadUInt32();
this.Unknown_5Ch = reader.ReadByte();
@@ -332,6 +357,171 @@ namespace CodeWalker.GameFiles
this.Levels,
this.Stride
);
+
+ switch (Unknown_40h)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 8:
+ case 9:
+ case 0xA:
+ case 0xB:
+ case 0xC:
+ case 0xE:
+ case 0x10:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1A:
+ case 0x26:
+ case 0x34:
+ case 0x36:
+ case 0x37:
+ case 0x42:
+ case 0x54:
+ case 0x56:
+ case 0x57:
+ case 0x74:
+ case 0x76:
+ case 0x77:
+ case 0x20://embedded only
+ break;
+ default:
+ break;
+ }
+ switch (Unknown_41h)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ case 6:
+ case 8:
+ case 0xA:
+ case 0xC:
+ case 0xE:
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x1C:
+ case 0x1E:
+ case 0x20:
+ case 0x22:
+ case 0x28:
+ case 0x2B:
+ case 0x2C:
+ case 0x30:
+ case 0x38:
+ case 0x39:
+ case 0x3C:
+ case 0x40:
+ case 0x4C:
+ case 0x4E:
+ case 0x50:
+ case 0x54:
+ case 0x56:
+ case 0x57:
+ case 0x58:
+ case 0x5A:
+ case 0x5C:
+ case 0x5E:
+ case 0x60:
+ case 0x64:
+ case 0x68:
+ case 0x70:
+ case 0x78:
+ case 0x80:
+ case 0x90:
+ case 0x9C:
+ case 0x9E:
+ case 0xA0:
+ case 0xA8:
+ case 0xAA:
+ case 0xAC:
+ case 0xAE:
+ case 0xB0:
+ case 0xB2:
+ case 0xB4:
+ case 0xB8:
+ case 0xBC:
+ case 0xC0:
+ case 0xD0:
+ case 7://embedded only
+ case 0xA4://embedded only
+ case 0xAB://embedded only
+ break;
+ default:
+ break;
+ }
+ switch (Unknown_42h)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 0xA:
+ case 0xB:
+ case 0xC:
+ case 0xE:
+ case 0x10:
+ case 0x12:
+ case 0x14:
+ case 0x15:
+ case 0x18:
+ case 0x19:
+ case 0x20:
+ case 0x21:
+ case 0x24:
+ case 0x2A:
+ case 0x40:
+ case 0x55:
+ case 0x80://embedded only
+ break;
+ default:
+ break;
+ }
+ switch (Unknown_43h)
+ {
+ case 0x20://32
+ case 0x28://40
+ case 0x30://48
+ case 0:
+ break;
+ default:
+ break;
+ }
+
+ switch (Unknown_48h)
+ {
+ case 0:
+ case 1:
+ break;
+ default:
+ break;
+ }
+
+
}
///
@@ -345,12 +535,15 @@ namespace CodeWalker.GameFiles
// write structure data
writer.Write(this.Unknown_40h);
+ writer.Write(this.Unknown_41h);
+ writer.Write(this.Unknown_42h);
+ writer.Write(this.Unknown_43h);
writer.Write(this.Unknown_44h);
writer.Write(this.Unknown_48h);
writer.Write(this.Unknown_4Ch);
writer.Write(this.Width);
writer.Write(this.Height);
- writer.Write(this.Unknown_54h);
+ writer.Write(this.Depth);
writer.Write(this.Stride);
writer.Write((uint)this.Format);
writer.Write(this.Unknown_5Ch);
diff --git a/Utils/DDSIO.cs b/CodeWalker.Core/GameFiles/Utils/DDSIO.cs
similarity index 82%
rename from Utils/DDSIO.cs
rename to CodeWalker.Core/GameFiles/Utils/DDSIO.cs
index d9b5a53..e99f363 100644
--- a/Utils/DDSIO.cs
+++ b/CodeWalker.Core/GameFiles/Utils/DDSIO.cs
@@ -69,6 +69,32 @@
+//additional dds importing code modified from: https://gist.github.com/spazzarama/2710d020d1d615cde20c607711655167
+// DDSTextureLoader Ported to C# by Justin Stenning, March 2017
+//--------------------------------------------------------------------------------------
+// File: DDSTextureLoader.cpp
+//
+// Functions for loading a DDS texture and creating a Direct3D runtime resource for it
+//
+// Note these functions are useful as a light-weight runtime loader for DDS files. For
+// a full-featured DDS file reader, writer, and texture processing pipeline see
+// the 'Texconv' sample and the 'DirectXTex' library.
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// http://go.microsoft.com/fwlink/?LinkId=248926
+// http://go.microsoft.com/fwlink/?LinkId=248929
+//--------------------------------------------------------------------------------------
+
+
+
+
+
using CodeWalker.GameFiles;
using System;
using System.Collections.Generic;
@@ -332,7 +358,142 @@ namespace CodeWalker.Utils
}
+ public static Texture GetTexture(byte[] ddsfile)
+ {
+ var ms = new MemoryStream(ddsfile);
+ var br = new BinaryReader(ms);
+ var header = new DDS_HEADER();
+ var header10 = new DDS_HEADER_DXT10();
+ var useheader10 = false;
+
+ if (!DXTex._ReadDDSHeader(br, out header, out header10, out useheader10))
+ { return null; }
+
+ var width = header.dwWidth;
+ var height = header.dwHeight;
+ var depth = header.dwDepth;
+ var mipCount = header.dwMipMapCount;
+ if (mipCount == 0)
+ {
+ mipCount = 1;
+ }
+
+ TEX_DIMENSION resDim = 0;
+ uint arraySize = 1;
+ DXGI_FORMAT format = DXGI_FORMAT.DXGI_FORMAT_UNKNOWN;
+ bool isCubeMap = false;
+
+ if (useheader10)
+ {
+ arraySize = header10.arraySize;
+ format = header10.dxgiFormat;
+ resDim = (TEX_DIMENSION)header10.resourceDimension;
+
+ if (arraySize == 0) throw new Exception("ArraySize was 0! This isn't supported...");
+ switch (format)
+ {
+ case DXGI_FORMAT.DXGI_FORMAT_AI44:
+ case DXGI_FORMAT.DXGI_FORMAT_IA44:
+ case DXGI_FORMAT.DXGI_FORMAT_P8:
+ case DXGI_FORMAT.DXGI_FORMAT_A8P8:
+ throw new NotSupportedException(string.Format("{0} DXGI format is not supported", format.ToString()));
+ default:
+ if (DXTex.BitsPerPixel(format) == 0)
+ throw new NotSupportedException(string.Format("{0} DXGI format is not supported", format.ToString()));
+ break;
+ }
+ switch (resDim)
+ {
+ case TEX_DIMENSION.TEX_DIMENSION_TEXTURE1D:
+ if ((header.dwFlags & DXTex.DDS_HEIGHT) > 0 && height != 1) throw new NotSupportedException("1D texture's height wasn't 1!");
+ height = depth = 1; // D3DX writes 1D textures with a fixed Height of 1
+ break;
+ case TEX_DIMENSION.TEX_DIMENSION_TEXTURE2D:
+ if ((header10.miscFlag & (uint)TEX_MISC_FLAG.TEX_MISC_TEXTURECUBE) > 0) { arraySize *= 6; isCubeMap = true; }
+ depth = 1;
+ break;
+ case TEX_DIMENSION.TEX_DIMENSION_TEXTURE3D:
+ if ((header.dwFlags & DXTex.DDS_HEADER_FLAGS_VOLUME) == 0) throw new ArgumentException("3D texture without volume flag!");
+ if (arraySize > 1) throw new ArgumentException("3D texture with ArraySize > 1!");
+ break;
+ default: throw new ArgumentException("Unknown resource dimension!");
+ }
+ }
+ else
+ {
+ format = header.ddspf.GetDXGIFormat();
+
+ if (format == DXGI_FORMAT.DXGI_FORMAT_UNKNOWN) throw new ArgumentException("Unknown DDS format.");
+ if ((header.dwFlags & DXTex.DDS_HEADER_FLAGS_VOLUME) > 0)
+ {
+ resDim = TEX_DIMENSION.TEX_DIMENSION_TEXTURE3D;
+ }
+ else
+ {
+ if ((header.dwCaps2 & DXTex.DDS_CUBEMAP) > 0)
+ {
+ if ((header.dwCaps2 & DXTex.DDS_CUBEMAP_ALLFACES) != DXTex.DDS_CUBEMAP_ALLFACES) throw new ArgumentException("Not all faces in cubemap exist!");//requires all 6 faces
+ arraySize = 6;
+ isCubeMap = true;
+ }
+ depth = 1;
+ resDim = TEX_DIMENSION.TEX_DIMENSION_TEXTURE2D;
+ // Note there's no way for a legacy Direct3D 9 DDS to express a '1D' texture
+ }
+ if (DXTex.BitsPerPixel(format) == 0) throw new Exception(string.Format("{0} DXGI format is not supported", format.ToString()));
+ }
+
+ if (isCubeMap)
+ { }
+
+ DXTex.ComputePitch(format, (int)width, (int)height, out int rowPitch, out int slicePitch, 0);
+ var stride = slicePitch / height;
+ var scanlines = DXTex.ComputeScanlines(format, (int)height);
+
+ var brem = ms.Length - ms.Position;
+ var ddsdata = br.ReadBytes((int)brem);
+
+ var tex = new Texture();
+ tex.Width = (ushort)width;
+ tex.Height = (ushort)height;
+ tex.Depth = (ushort)depth;
+ tex.Levels = (byte)mipCount;
+ tex.Format = GetTextureFormat(format);
+ tex.Stride = (ushort)stride;
+ tex.Data = new TextureData();
+ tex.Data.FullData = ddsdata;
+
+ //tex.Unknown_43h = (byte)header.ddspf.dwSize;
+
+ return tex;
+ }
+
+
+
+
+ private static TextureFormat GetTextureFormat(DXGI_FORMAT f)
+ {
+ var format = (TextureFormat)0;
+ switch (f)
+ {
+ // compressed
+ case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM: format = TextureFormat.D3DFMT_DXT1; break;
+ case DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM: format = TextureFormat.D3DFMT_DXT3; break;
+ case DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM: format = TextureFormat.D3DFMT_DXT5; break;
+ case DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM: format = TextureFormat.D3DFMT_ATI1; break;
+ case DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM: format = TextureFormat.D3DFMT_ATI2; break;
+ case DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM: format = TextureFormat.D3DFMT_BC7; break;
+
+ // uncompressed
+ case DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM: format = TextureFormat.D3DFMT_A1R5G5B5; break;
+ case DXGI_FORMAT.DXGI_FORMAT_A8_UNORM: format = TextureFormat.D3DFMT_A8; break;
+ case DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM: format = TextureFormat.D3DFMT_A8B8G8R8; break;
+ case DXGI_FORMAT.DXGI_FORMAT_R8_UNORM: format = TextureFormat.D3DFMT_L8; break;
+ case DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM: format = TextureFormat.D3DFMT_A8R8G8B8; break;
+ }
+ return format;
+ }
private static DXGI_FORMAT GetDXGIFormat(TextureFormat f)
{
@@ -1015,6 +1176,7 @@ namespace CodeWalker.Utils
public static uint DDS_FLAGS_VOLUME = 0x00200000; // DDSCAPS2_VOLUME
+ public static uint DDS_MAGIC = 0x20534444; // "DDS "
@@ -1104,7 +1266,6 @@ namespace CodeWalker.Utils
int sizeofddsheader = 31 * 4;
int sizeofddsheader10 = 5 * 4;
- const uint DDS_MAGIC = 0x20534444; // "DDS "
required = 4/*sizeof(uint32_t)*/ + sizeofddsheader/*sizeof(DDS_HEADER)*/;
@@ -1313,6 +1474,68 @@ namespace CodeWalker.Utils
}
+ public static bool _ReadDDSHeader(BinaryReader br, out DDS_HEADER header, out DDS_HEADER_DXT10 header10, out bool useheader10)
+ {
+ var magic = br.ReadUInt32();
+ if (magic != DDS_MAGIC) throw new Exception("Invalid DDS magic!");
+
+ //var header = new DDS_HEADER();
+ //var header10 = new DDS_HEADER_DXT10();
+ int sizeofddsheader = 31 * 4;
+ int sizeofddspixelformat = 8 * 4;
+
+ header.dwSize = br.ReadUInt32();
+ header.dwFlags = br.ReadUInt32();
+ header.dwHeight = br.ReadUInt32();
+ header.dwWidth = br.ReadUInt32();
+ header.dwPitchOrLinearSize = br.ReadUInt32();
+ header.dwDepth = br.ReadUInt32(); // only if DDS_HEADER_FLAGS_VOLUME is set in dwFlags
+ header.dwMipMapCount = br.ReadUInt32();
+
+ //public uint dwReserved1[11]; //x11
+ for (int i = 0; i < 11; i++) br.ReadUInt32();
+
+ header.ddspf.dwSize = br.ReadUInt32();
+ header.ddspf.dwFlags = br.ReadUInt32();
+ header.ddspf.dwFourCC = br.ReadUInt32();
+ header.ddspf.dwRGBBitCount = br.ReadUInt32();
+ header.ddspf.dwRBitMask = br.ReadUInt32();
+ header.ddspf.dwGBitMask = br.ReadUInt32();
+ header.ddspf.dwBBitMask = br.ReadUInt32();
+ header.ddspf.dwABitMask = br.ReadUInt32();
+
+ header.dwCaps = br.ReadUInt32();
+ header.dwCaps2 = br.ReadUInt32();
+ header.dwCaps3 = br.ReadUInt32();
+ header.dwCaps4 = br.ReadUInt32();
+ header.dwReserved2 = br.ReadUInt32();
+
+
+
+ if(((DDS_PIXELFORMAT.DDS_FOURCC & header.ddspf.dwFlags) > 0) &&
+ (DDS_PIXELFORMAT.MAKEFOURCC('D', 'X', '1', '0') == header.ddspf.dwFourCC))
+ {
+ header10.dxgiFormat = (DXGI_FORMAT)br.ReadUInt32();
+ header10.resourceDimension = br.ReadUInt32();
+ header10.miscFlag = br.ReadUInt32(); // see DDS_RESOURCE_MISC_FLAG
+ header10.arraySize = br.ReadUInt32();
+ header10.miscFlags2 = br.ReadUInt32(); // see DDS_MISC_FLAGS2
+ useheader10 = true;
+ }
+ else
+ {
+ header10 = new DDS_HEADER_DXT10();
+ useheader10 = false;
+ }
+
+ if (header.dwSize != sizeofddsheader || header.ddspf.dwSize != sizeofddspixelformat)
+ {
+ throw new Exception("Invalid DDS header size");
+ }
+
+
+ return true;
+ }
}
@@ -1596,86 +1819,250 @@ namespace CodeWalker.Utils
public static uint DDS_PAL8 = 0x00000020; // DDPF_PALETTEINDEXED8
- public static DDS_PIXELFORMAT DDSPF_DXT1 = new DDS_PIXELFORMAT(
- 32, DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 );
-
- public static DDS_PIXELFORMAT DDSPF_DXT2 = new DDS_PIXELFORMAT(
- 32, DDS_FOURCC, MAKEFOURCC('D', 'X', 'T', '2'), 0, 0, 0, 0, 0);
-
- public static DDS_PIXELFORMAT DDSPF_DXT3 = new DDS_PIXELFORMAT(
- 32, DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0);
-
- public static DDS_PIXELFORMAT DDSPF_DXT4 = new DDS_PIXELFORMAT(
- 32, DDS_FOURCC, MAKEFOURCC('D','X','T','4'), 0, 0, 0, 0, 0);
-
- public static DDS_PIXELFORMAT DDSPF_DXT5 = new DDS_PIXELFORMAT(
- 32, DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0);
-
- public static DDS_PIXELFORMAT DDSPF_BC4_UNORM = new DDS_PIXELFORMAT(
- 32, DDS_FOURCC, MAKEFOURCC('B','C','4','U'), 0, 0, 0, 0, 0);
-
- public static DDS_PIXELFORMAT DDSPF_BC4_SNORM = new DDS_PIXELFORMAT(
- 32, DDS_FOURCC, MAKEFOURCC('B','C','4','S'), 0, 0, 0, 0, 0);
-
- public static DDS_PIXELFORMAT DDSPF_BC5_UNORM = new DDS_PIXELFORMAT(
- 32, DDS_FOURCC, MAKEFOURCC('B','C','5','U'), 0, 0, 0, 0, 0);
-
- public static DDS_PIXELFORMAT DDSPF_BC5_SNORM = new DDS_PIXELFORMAT(
- 32, DDS_FOURCC, MAKEFOURCC('B','C','5','S'), 0, 0, 0, 0, 0);
-
- public static DDS_PIXELFORMAT DDSPF_R8G8_B8G8 = new DDS_PIXELFORMAT(
- 32, DDS_FOURCC, MAKEFOURCC('R','G','B','G'), 0, 0, 0, 0, 0);
-
- public static DDS_PIXELFORMAT DDSPF_G8R8_G8B8 = new DDS_PIXELFORMAT(
- 32, DDS_FOURCC, MAKEFOURCC('G','R','G','B'), 0, 0, 0, 0, 0);
-
- public static DDS_PIXELFORMAT DDSPF_YUY2 = new DDS_PIXELFORMAT(
- 32, DDS_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0);
-
- public static DDS_PIXELFORMAT DDSPF_A8R8G8B8 = new DDS_PIXELFORMAT(
- 32, DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
-
- public static DDS_PIXELFORMAT DDSPF_X8R8G8B8 = new DDS_PIXELFORMAT(
- 32, DDS_RGB, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000);
-
- public static DDS_PIXELFORMAT DDSPF_A8B8G8R8 = new DDS_PIXELFORMAT(
- 32, DDS_RGBA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
-
- public static DDS_PIXELFORMAT DDSPF_X8B8G8R8 = new DDS_PIXELFORMAT(
- 32, DDS_RGB, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000);
-
- public static DDS_PIXELFORMAT DDSPF_G16R16 = new DDS_PIXELFORMAT(
- 32, DDS_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000);
-
- public static DDS_PIXELFORMAT DDSPF_R5G6B5 = new DDS_PIXELFORMAT(
- 32, DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000);
-
- public static DDS_PIXELFORMAT DDSPF_A1R5G5B5 = new DDS_PIXELFORMAT(
- 32, DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000);
-
- public static DDS_PIXELFORMAT DDSPF_A4R4G4B4 = new DDS_PIXELFORMAT(
- 32, DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000);
-
- public static DDS_PIXELFORMAT DDSPF_R8G8B8 = new DDS_PIXELFORMAT(
- 32, DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000);
-
- public static DDS_PIXELFORMAT DDSPF_L8 = new DDS_PIXELFORMAT(
- 32, DDS_LUMINANCE, 0, 8, 0xff, 0x00, 0x00, 0x00);
-
- public static DDS_PIXELFORMAT DDSPF_L16 = new DDS_PIXELFORMAT(
- 32, DDS_LUMINANCE, 0, 16, 0xffff, 0x0000, 0x0000, 0x0000);
-
- public static DDS_PIXELFORMAT DDSPF_A8L8 = new DDS_PIXELFORMAT(
- 32, DDS_LUMINANCEA, 0, 16, 0x00ff, 0x0000, 0x0000, 0xff00);
-
- public static DDS_PIXELFORMAT DDSPF_A8 = new DDS_PIXELFORMAT(
- 32, DDS_ALPHA, 0, 8, 0x00, 0x00, 0x00, 0xff);
+ public static DDS_PIXELFORMAT DDSPF_DXT1 = new DDS_PIXELFORMAT(32, DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 );
+ public static DDS_PIXELFORMAT DDSPF_DXT2 = new DDS_PIXELFORMAT(32, DDS_FOURCC, MAKEFOURCC('D', 'X', 'T', '2'), 0, 0, 0, 0, 0);
+ public static DDS_PIXELFORMAT DDSPF_DXT3 = new DDS_PIXELFORMAT(32, DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0);
+ public static DDS_PIXELFORMAT DDSPF_DXT4 = new DDS_PIXELFORMAT(32, DDS_FOURCC, MAKEFOURCC('D','X','T','4'), 0, 0, 0, 0, 0);
+ public static DDS_PIXELFORMAT DDSPF_DXT5 = new DDS_PIXELFORMAT(32, DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0);
+ public static DDS_PIXELFORMAT DDSPF_BC4_UNORM = new DDS_PIXELFORMAT(32, DDS_FOURCC, MAKEFOURCC('B','C','4','U'), 0, 0, 0, 0, 0);
+ public static DDS_PIXELFORMAT DDSPF_BC4_SNORM = new DDS_PIXELFORMAT(32, DDS_FOURCC, MAKEFOURCC('B','C','4','S'), 0, 0, 0, 0, 0);
+ public static DDS_PIXELFORMAT DDSPF_BC5_UNORM = new DDS_PIXELFORMAT(32, DDS_FOURCC, MAKEFOURCC('B','C','5','U'), 0, 0, 0, 0, 0);
+ public static DDS_PIXELFORMAT DDSPF_BC5_SNORM = new DDS_PIXELFORMAT(32, DDS_FOURCC, MAKEFOURCC('B','C','5','S'), 0, 0, 0, 0, 0);
+ public static DDS_PIXELFORMAT DDSPF_R8G8_B8G8 = new DDS_PIXELFORMAT(32, DDS_FOURCC, MAKEFOURCC('R','G','B','G'), 0, 0, 0, 0, 0);
+ public static DDS_PIXELFORMAT DDSPF_G8R8_G8B8 = new DDS_PIXELFORMAT(32, DDS_FOURCC, MAKEFOURCC('G','R','G','B'), 0, 0, 0, 0, 0);
+ public static DDS_PIXELFORMAT DDSPF_YUY2 = new DDS_PIXELFORMAT(32, DDS_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0);
+ public static DDS_PIXELFORMAT DDSPF_A8R8G8B8 = new DDS_PIXELFORMAT(32, DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
+ public static DDS_PIXELFORMAT DDSPF_X8R8G8B8 = new DDS_PIXELFORMAT(32, DDS_RGB, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000);
+ public static DDS_PIXELFORMAT DDSPF_A8B8G8R8 = new DDS_PIXELFORMAT(32, DDS_RGBA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
+ public static DDS_PIXELFORMAT DDSPF_X8B8G8R8 = new DDS_PIXELFORMAT(32, DDS_RGB, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000);
+ public static DDS_PIXELFORMAT DDSPF_G16R16 = new DDS_PIXELFORMAT(32, DDS_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000);
+ public static DDS_PIXELFORMAT DDSPF_R5G6B5 = new DDS_PIXELFORMAT(32, DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000);
+ public static DDS_PIXELFORMAT DDSPF_A1R5G5B5 = new DDS_PIXELFORMAT(32, DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000);
+ public static DDS_PIXELFORMAT DDSPF_A4R4G4B4 = new DDS_PIXELFORMAT(32, DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000);
+ public static DDS_PIXELFORMAT DDSPF_R8G8B8 = new DDS_PIXELFORMAT(32, DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000);
+ public static DDS_PIXELFORMAT DDSPF_L8 = new DDS_PIXELFORMAT(32, DDS_LUMINANCE, 0, 8, 0xff, 0x00, 0x00, 0x00);
+ public static DDS_PIXELFORMAT DDSPF_L16 = new DDS_PIXELFORMAT(32, DDS_LUMINANCE, 0, 16, 0xffff, 0x0000, 0x0000, 0x0000);
+ public static DDS_PIXELFORMAT DDSPF_A8L8 = new DDS_PIXELFORMAT(32, DDS_LUMINANCEA, 0, 16, 0x00ff, 0x0000, 0x0000, 0xff00);
+ public static DDS_PIXELFORMAT DDSPF_A8 = new DDS_PIXELFORMAT(32, DDS_ALPHA, 0, 8, 0x00, 0x00, 0x00, 0xff);
// D3DFMT_A2R10G10B10/D3DFMT_A2B10G10R10 should be written using DX10 extension to avoid D3DX 10:10:10:2 reversal issue
// This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat)
- public static DDS_PIXELFORMAT DDSPF_DX10 = new DDS_PIXELFORMAT(
- 32, DDS_FOURCC, MAKEFOURCC('D','X','1','0'), 0, 0, 0, 0, 0);
+ public static DDS_PIXELFORMAT DDSPF_DX10 = new DDS_PIXELFORMAT(32, DDS_FOURCC, MAKEFOURCC('D','X','1','0'), 0, 0, 0, 0, 0);
+
+
+
+
+
+ private bool ISBITMASK(uint r, uint g, uint b, uint a)
+ {
+ return ((dwRBitMask == r) && (dwGBitMask == g) && (dwBBitMask == b) && (dwABitMask == a));
+ }
+
+ public DXGI_FORMAT GetDXGIFormat()
+ {
+
+ if ((dwFlags & DDS_RGB) > 0)
+ {
+ // Note that sRGB formats are written using the "DX10" extended header
+
+ switch (dwRGBBitCount)
+ {
+ case 32:
+ if (ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000))
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM;
+ }
+
+ if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000))
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM;
+ }
+
+ if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000))
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_B8G8R8X8_UNORM;
+ }
+
+ // No DXGI format maps to ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000) aka D3DFMT_X8B8G8R8
+
+ // Note that many common DDS reader/writers (including D3DX) swap the
+ // the RED/BLUE masks for 10:10:10:2 formats. We assumme
+ // below that the 'backwards' header mask is being used since it is most
+ // likely written by D3DX. The more robust solution is to use the 'DX10'
+ // header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly
+
+ // For 'correct' writers, this should be 0x000003ff, 0x000ffc00, 0x3ff00000 for RGB data
+ if (ISBITMASK(0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000))
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_R10G10B10A2_UNORM;
+ }
+
+ // No DXGI format maps to ISBITMASK(0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000) aka D3DFMT_A2R10G10B10
+
+ if (ISBITMASK(0x0000ffff, 0xffff0000, 0x00000000, 0x00000000))
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_R16G16_UNORM;
+ }
+
+ if (ISBITMASK(0xffffffff, 0x00000000, 0x00000000, 0x00000000))
+ {
+ // Only 32-bit color channel format in D3D9 was R32F
+ return DXGI_FORMAT.DXGI_FORMAT_R32_FLOAT; // D3DX writes this out as a FourCC of 114
+ }
+ break;
+
+ case 24:
+ // No 24bpp DXGI formats aka D3DFMT_R8G8B8
+ break;
+
+ case 16:
+ if (ISBITMASK(0x7c00, 0x03e0, 0x001f, 0x8000))
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM;
+ }
+ if (ISBITMASK(0xf800, 0x07e0, 0x001f, 0x0000))
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_B5G6R5_UNORM;
+ }
+
+ // No DXGI format maps to ISBITMASK(0x7c00, 0x03e0, 0x001f, 0x0000) aka D3DFMT_X1R5G5B5
+ if (ISBITMASK(0x0f00, 0x00f0, 0x000f, 0xf000))
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM;
+ }
+
+ // No DXGI format maps to ISBITMASK(0x0f00, 0x00f0, 0x000f, 0x0000) aka D3DFMT_X4R4G4B4
+
+ // No 3:3:2, 3:3:2:8, or paletted DXGI formats aka D3DFMT_A8R3G3B2, D3DFMT_R3G3B2, D3DFMT_P8, D3DFMT_A8P8, etc.
+ break;
+ }
+ }
+ else if ((dwFlags & DDS_LUMINANCE) > 0)
+ {
+ if (8 == dwRGBBitCount)
+ {
+ if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x00000000))
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_R8_UNORM; // D3DX10/11 writes this out as DX10 extension
+ }
+
+ // No DXGI format maps to ISBITMASK(0x0f, 0x00, 0x00, 0xf0) aka D3DFMT_A4L4
+ }
+
+ if (16 == dwRGBBitCount)
+ {
+ if (ISBITMASK(0x0000ffff, 0x00000000, 0x00000000, 0x00000000))
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_R16_UNORM; // D3DX10/11 writes this out as DX10 extension
+ }
+ if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x0000ff00))
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_R8G8_UNORM; // D3DX10/11 writes this out as DX10 extension
+ }
+ }
+ }
+ else if ((dwFlags & DDS_ALPHA) > 0)
+ {
+ if (8 == dwRGBBitCount)
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_A8_UNORM;
+ }
+ }
+ else if ((dwFlags & DDS_FOURCC) > 0)
+ {
+ if (MAKEFOURCC('D', 'X', 'T', '1') == dwFourCC)
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM;
+ }
+ if (MAKEFOURCC('D', 'X', 'T', '3') == dwFourCC)
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM;
+ }
+ if (MAKEFOURCC('D', 'X', 'T', '5') == dwFourCC)
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM;
+ }
+
+ // While pre-mulitplied alpha isn't directly supported by the DXGI formats,
+ // they are basically the same as these BC formats so they can be mapped
+ if (MAKEFOURCC('D', 'X', 'T', '2') == dwFourCC)
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM;
+ }
+ if (MAKEFOURCC('D', 'X', 'T', '4') == dwFourCC)
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM;
+ }
+
+ if (MAKEFOURCC('A', 'T', 'I', '1') == dwFourCC)
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM;
+ }
+ if (MAKEFOURCC('B', 'C', '4', 'U') == dwFourCC)
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM;
+ }
+ if (MAKEFOURCC('B', 'C', '4', 'S') == dwFourCC)
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM;
+ }
+
+ if (MAKEFOURCC('A', 'T', 'I', '2') == dwFourCC)
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM;
+ }
+ if (MAKEFOURCC('B', 'C', '5', 'U') == dwFourCC)
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM;
+ }
+ if (MAKEFOURCC('B', 'C', '5', 'S') == dwFourCC)
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_BC5_SNORM;
+ }
+
+ // BC6H and BC7 are written using the "DX10" extended header
+
+ if (MAKEFOURCC('R', 'G', 'B', 'G') == dwFourCC)
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_R8G8_B8G8_UNORM;
+ }
+ if (MAKEFOURCC('G', 'R', 'G', 'B') == dwFourCC)
+ {
+ return DXGI_FORMAT.DXGI_FORMAT_G8R8_G8B8_UNORM;
+ }
+
+ // Check for D3DFORMAT enums being set here
+ switch (dwFourCC)
+ {
+ case 36: // D3DFMT_A16B16G16R16
+ return DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_UNORM;
+
+ case 110: // D3DFMT_Q16W16V16U16
+ return DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_SNORM;
+
+ case 111: // D3DFMT_R16F
+ return DXGI_FORMAT.DXGI_FORMAT_R16_FLOAT;
+
+ case 112: // D3DFMT_G16R16F
+ return DXGI_FORMAT.DXGI_FORMAT_R16G16_FLOAT;
+
+ case 113: // D3DFMT_A16B16G16R16F
+ return DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_FLOAT;
+
+ case 114: // D3DFMT_R32F
+ return DXGI_FORMAT.DXGI_FORMAT_R32_FLOAT;
+
+ case 115: // D3DFMT_G32R32F
+ return DXGI_FORMAT.DXGI_FORMAT_R32G32_FLOAT;
+
+ case 116: // D3DFMT_A32B32G32R32F
+ return DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_FLOAT;
+ }
+ }
+
+ return DXGI_FORMAT.DXGI_FORMAT_UNKNOWN;
+ }
};
diff --git a/CodeWalker.Core/Utils/FbxConverter.cs b/CodeWalker.Core/Utils/FbxConverter.cs
index 2e1f0c6..a49de4e 100644
--- a/CodeWalker.Core/Utils/FbxConverter.cs
+++ b/CodeWalker.Core/Utils/FbxConverter.cs
@@ -788,7 +788,8 @@ namespace CodeWalker
}
var texParam = new TextureBase();
texParam.Unknown_4h = 1;
- texParam.Unknown_30h = 131073;//wtf is this? 2x shorts, 0x00020001
+ texParam.Unknown_30h = 1;// 131073;//wtf is this? 2x shorts, 0x00020001
+ texParam.Unknown_32h = 2;
texParam.Name = name;
texParam.NameHash = JenkHash.GenHash(name.ToLowerInvariant());
return texParam;
diff --git a/CodeWalker.csproj b/CodeWalker.csproj
index c8c6bb4..f4f0b20 100644
--- a/CodeWalker.csproj
+++ b/CodeWalker.csproj
@@ -612,7 +612,6 @@
TextInputForm.cs
-