diff --git a/.gitignore b/.gitignore index 530fcf51..d03c8cec 100644 --- a/.gitignore +++ b/.gitignore @@ -356,3 +356,4 @@ Toolbox/Lib.zip yuzu-glsl-decompiler AnimSetupPrevious.zip AnimSetupNew.zip +Switch_Toolbox_Library/Forms/Editors/UV/UVEditor.cs diff --git a/File_Format_Library/FileFormats/DKCTF/CModel.cs b/File_Format_Library/FileFormats/DKCTF/CModel.cs index 59c45d0b..7fbd5cbe 100644 --- a/File_Format_Library/FileFormats/DKCTF/CModel.cs +++ b/File_Format_Library/FileFormats/DKCTF/CModel.cs @@ -140,8 +140,10 @@ namespace DKCTF { string guid = texMap.Value.FileID.ToString(); if (texFolder.Nodes.ContainsKey(guid) || !Textures.ContainsKey(guid)) + { + Console.WriteLine($"Texture not present in pak file! {mat.Name} {texMap.Key} {guid}"); continue; - + } if (Textures[guid].FileFormat == null) Textures[guid].OpenFile(); @@ -153,7 +155,7 @@ namespace DKCTF t.Tag = tex; texFolder.Nodes.Add(t); - if (texMap.Key == "DIFT") + if (texMap.Key == "DIFT" || texMap.Key == "BCLR") { tex.Text = guid; @@ -167,6 +169,7 @@ namespace DKCTF TreeNode texFolder = new STTextureFolder("Textures"); TreeNode skeletonFolder = new STTextureFolder("Skeleton"); + TreeNode shaderFolder = new STTextureFolder("Materials"); public void Load(System.IO.Stream stream) { @@ -179,11 +182,14 @@ namespace DKCTF Nodes.Add(meshFolder); Nodes.Add(texFolder); - Nodes.Add(skeletonFolder); + Nodes.Add(shaderFolder); Model = ToGeneric(); + foreach (var mat in ModelData.Materials) + shaderFolder.Nodes.Add(new TreeNode(mat.Name + "_" + mat.ID.ToString())); + foreach (GenericRenderedObject mesh in Model.Objects) { Renderer.Meshes.Add(mesh); @@ -235,6 +241,7 @@ namespace DKCTF if (tex.Key == "DIFT") type = STGenericMatTexture.TextureType.Diffuse; if (tex.Key == "NMAP") type = STGenericMatTexture.TextureType.Normal; if (tex.Key == "SPCT") type = STGenericMatTexture.TextureType.Specular; + if (tex.Key == "BCLR") type = STGenericMatTexture.TextureType.Diffuse; genericMaterial.TextureMaps.Add(new STGenericMatTexture() { diff --git a/File_Format_Library/FileFormats/DKCTF/CTexture.cs b/File_Format_Library/FileFormats/DKCTF/CTexture.cs index 8cda0edd..275509f0 100644 --- a/File_Format_Library/FileFormats/DKCTF/CTexture.cs +++ b/File_Format_Library/FileFormats/DKCTF/CTexture.cs @@ -134,13 +134,16 @@ namespace DKCTF Header = new TXTR(stream); - if (Header.IsSwitch) + if (!Header.IsSwitch) PlatformSwizzle = PlatformSwizzle.Platform_WiiU; Width = Header.TextureHeader.Width; Height = Header.TextureHeader.Height; MipCount = (uint)Header.MipSizes.Length; Format = FormatList[Header.TextureHeader.Format]; + + if (Header.TextureHeader.Type == 3) + this.ArrayCount = 6; } public void Save(System.IO.Stream stream) @@ -225,18 +228,6 @@ namespace DKCTF } } - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public class STextureHeader - { - public uint Type; - public uint Format; - public uint Width; - public uint Height; - public uint Depth; - public uint TileMode; - public uint Swizzle; - } - Dictionary FormatList = new Dictionary() { { 12, TEX_FORMAT.R8G8B8A8_UNORM }, @@ -257,11 +248,40 @@ namespace DKCTF { 32, TEX_FORMAT.R16G16_FLOAT }, { 33, TEX_FORMAT.R8G8_UNORM }, + { 53, TEX_FORMAT.ASTC_4x4_UNORM }, { 54, TEX_FORMAT.ASTC_5x4_UNORM }, { 55, TEX_FORMAT.ASTC_5x5_UNORM }, { 56, TEX_FORMAT.ASTC_6x5_UNORM }, { 57, TEX_FORMAT.ASTC_6x6_UNORM }, { 58, TEX_FORMAT.ASTC_8x5_UNORM }, + { 59, TEX_FORMAT.ASTC_8x6_UNORM }, + { 60, TEX_FORMAT.ASTC_8x8_UNORM }, + { 61, TEX_FORMAT.ASTC_10x5_UNORM }, + { 62, TEX_FORMAT.ASTC_10x6_UNORM}, + { 63, TEX_FORMAT.ASTC_10x8_UNORM}, + { 64, TEX_FORMAT.ASTC_10x10_UNORM}, + { 65, TEX_FORMAT.ASTC_12x10_UNORM}, + { 66, TEX_FORMAT.ASTC_12x12_UNORM}, + + { 67, TEX_FORMAT.ASTC_4x4_SRGB}, + { 68, TEX_FORMAT.ASTC_5x4_SRGB }, + { 69, TEX_FORMAT.ASTC_5x5_SRGB }, + { 70, TEX_FORMAT.ASTC_6x5_SRGB }, + { 71, TEX_FORMAT.ASTC_6x6_SRGB }, + { 72, TEX_FORMAT.ASTC_8x5_SRGB }, + { 73, TEX_FORMAT.ASTC_8x6_SRGB }, + { 74, TEX_FORMAT.ASTC_8x8_SRGB}, + { 75, TEX_FORMAT.ASTC_10x5_SRGB }, + { 76, TEX_FORMAT.ASTC_10x6_SRGB}, + { 77, TEX_FORMAT.ASTC_10x8_SRGB}, + { 78, TEX_FORMAT.ASTC_10x10_SRGB}, + { 79, TEX_FORMAT.ASTC_12x10_SRGB}, + { 80, TEX_FORMAT.ASTC_12x12_SRGB}, + + { 81, TEX_FORMAT.BC6H_UF16 }, + { 82, TEX_FORMAT.BC6H_SF16 }, + { 83, TEX_FORMAT.BC7_UNORM }, + { 84, TEX_FORMAT.BC7_UNORM_SRGB }, }; } } diff --git a/File_Format_Library/FileFormats/DKCTF/FileData/BufferHelper.cs b/File_Format_Library/FileFormats/DKCTF/FileData/BufferHelper.cs index 228ed9b7..402874c3 100644 --- a/File_Format_Library/FileFormats/DKCTF/FileData/BufferHelper.cs +++ b/File_Format_Library/FileFormats/DKCTF/FileData/BufferHelper.cs @@ -42,19 +42,23 @@ namespace DKCTF /// /// Gets a vertex list from the provided buffer and descriptor info. /// - public static List LoadVertexBuffer(byte[] buffer, CMDL.VertexBuffer vertexBuffer, bool isLittleEndian) + public static CMDL.CVertex[] LoadVertexBuffer(List buffers, int startIndex, CMDL.VertexBuffer vertexInfo, bool isLittleEndian) { - List vertices = new List(); + var vertices = new CMDL.CVertex[vertexInfo.VertexCount]; - using (var reader = new FileReader(buffer)) + foreach (var comp in vertexInfo.Components) { - reader.SetByteOrder(!isLittleEndian); //switch is little endianness + var buffer = buffers[startIndex + (int)comp.BufferID]; + using (var reader = new FileReader(buffer)) + { + reader.SetByteOrder(!isLittleEndian); //switch is little endianness - for (int i = 0; i < vertexBuffer.VertexCount; i++) { - CMDL.CVertex vertex = new CMDL.CVertex(); - vertices.Add(vertex); + for (int i = 0; i < vertexInfo.VertexCount; i++) + { + if (vertices[i] == null) vertices[i] = new CMDL.CVertex(); + + CMDL.CVertex vertex = vertices[i]; - foreach (var comp in vertexBuffer.Components) { reader.SeekBegin(comp.Offset + i * comp.Stride); switch (comp.Type) { @@ -68,7 +72,7 @@ namespace DKCTF vertex.TexCoord0 = ReadData(reader, comp.Format).Xy; break; case CMDL.EVertexComponent.in_texCoord1: - vertex.TexCoord1 = ReadData(reader, comp.Format).Xy; + vertex.TexCoord0 = ReadData(reader, comp.Format).Xy; break; case CMDL.EVertexComponent.in_texCoord2: vertex.TexCoord2 = ReadData(reader, comp.Format).Xy; @@ -89,7 +93,6 @@ namespace DKCTF } } } - return vertices; } diff --git a/File_Format_Library/FileFormats/DKCTF/FileData/CHAR.cs b/File_Format_Library/FileFormats/DKCTF/FileData/CHAR.cs index 0cce3597..1dcf5b19 100644 --- a/File_Format_Library/FileFormats/DKCTF/FileData/CHAR.cs +++ b/File_Format_Library/FileFormats/DKCTF/FileData/CHAR.cs @@ -31,7 +31,7 @@ namespace DKCTF public override void Read(FileReader reader) { - reader.ReadStruct(); + var assetHeader = reader.ReadStruct(); reader.ReadStruct(); //Dumb hack atm bool IsSwitch = false; diff --git a/File_Format_Library/FileFormats/DKCTF/FileData/CMDL.cs b/File_Format_Library/FileFormats/DKCTF/FileData/CMDL.cs index 81358267..bff6ce19 100644 --- a/File_Format_Library/FileFormats/DKCTF/FileData/CMDL.cs +++ b/File_Format_Library/FileFormats/DKCTF/FileData/CMDL.cs @@ -52,7 +52,7 @@ namespace DKCTF { } - public override void ReadMetaData(FileReader reader) + public override void ReadMetaData(FileReader reader, CFormDescriptor pakVersion) { Meta = new SMetaData(); Meta.Unknown = reader.ReadUInt32(); @@ -60,13 +60,12 @@ namespace DKCTF Meta.ReadBufferInfo = IOFileExtension.ReadList(reader); Meta.VertexBuffers = IOFileExtension.ReadList(reader); Meta.IndexBuffers = IOFileExtension.ReadList(reader); - Console.WriteLine(); } - public override void WriteMetaData(FileWriter writer) + public override void WriteMetaData(FileWriter writer, CFormDescriptor pakVersion) { - writer.Write(Meta.GPUOffset); writer.Write(Meta.Unknown); + writer.Write(Meta.GPUOffset); IOFileExtension.WriteList(writer, Meta.ReadBufferInfo); IOFileExtension.WriteList(writer, Meta.VertexBuffers); IOFileExtension.WriteList(writer, Meta.IndexBuffers); @@ -130,47 +129,41 @@ namespace DKCTF } } } + + //Prepare buffer list + List vertexData = new List(); for (int i = 0; i < Meta.VertexBuffers.Count; i++) { - var vertexInfo = VertexBuffers[i]; - var buffer = Meta.VertexBuffers[i]; //First buffer or specific buffer var info = Meta.ReadBufferInfo[(int)buffer.ReadBufferIndex]; //Seek into the buffer region reader.SeekBegin(info.Offset + buffer.Offset); - using (reader.TemporarySeek(reader.Position, System.IO.SeekOrigin.Begin)) - { - reader.SetByteOrder(false); - var type = reader.ReadUInt32(); - reader.SetByteOrder(true); - - if (type != 13) - { - byte[] b = reader.ReadBytes((int)buffer.CompressedSize - 4); - System.IO.File.WriteAllBytes($"{Toolbox.Library.Runtime.ExecutableDir}\\VBuffer_{type}_{i}_{buffer.DecompressedSize}.bin", b); - } - } - //Decompress var data = IOFileExtension.DecompressedBuffer(reader, buffer.CompressedSize, buffer.DecompressedSize, IsSwitch); if (buffer.DecompressedSize != data.Length) throw new Exception(); - var vertices = BufferHelper.LoadVertexBuffer(data, vertexInfo,IsSwitch); + vertexData.Add(data); + + startPos += buffer.CompressedSize; + } + + + for (int j = 0; j < VertexBuffers.Count; j++) + { + var vertexInfo = VertexBuffers[j]; + var bufferID = j * 2; + if (!this.IsMPR) + bufferID = j; + + var vertices = BufferHelper.LoadVertexBuffer(vertexData, bufferID, vertexInfo, IsSwitch); //Read foreach (var mesh in Meshes) - { - if (mesh.Header.VertexBufferIndex == i) - { - //Only use the vertices referenced in the indices - //Some meshes use the same big buffer and can add too many unecessary vertices - mesh.SetupVertices(vertices); - } - } - startPos += buffer.CompressedSize; + if (mesh.Header.VertexBufferIndex == j) + mesh.SetupVertices(vertices.ToList()); } break; } @@ -241,6 +234,8 @@ namespace DKCTF private void ReadMaterials(FileReader reader) { + if (this.IsMPR) + reader.ReadUInt32(); uint numMaterials = reader.ReadUInt32(); for (int i = 0; i < numMaterials; i++) { @@ -250,8 +245,26 @@ namespace DKCTF uint size = reader.ReadUInt32(); material.Name = reader.ReadString((int)size, true); material.ID = reader.ReadStruct(); - material.Type = reader.ReadStruct(); - material.Flags = reader.ReadUInt32(); + if (this.IsMPR) + { + reader.ReadBytes(24); //Shader guid and extras? + uint numTypes = reader.ReadByte(); + reader.ReadBytes(3); + reader.ReadUInt32s((int)numTypes); //type list, fourcc + + uint numDataInts = reader.ReadUInt32(); + + //A list of data types with extra flags + for (int j = 0; j < numDataInts; j++) + { + var dtype = reader.ReadStruct(); + var dformat = reader.ReadStruct(); + reader.ReadUInt16(); + } + } + else + reader.ReadBytes(8); //Type, Flags + uint numData = reader.ReadUInt32(); //A list of data types @@ -304,6 +317,9 @@ namespace DKCTF reader.ReadStruct(); } break; + case "MA4": //Matrix4x4 + material.Matrices.Add(dtype, reader.ReadSingles(16)); + break; default: throw new Exception($"Unsupported material type {dformat}!"); } @@ -315,10 +331,31 @@ namespace DKCTF { uint numMeshes = reader.ReadUInt32(); for (int i = 0; i < numMeshes; i++) + { + var mesh = new CRenderMesh(); + + if (this.IsMPR) + mesh = reader.ReadStruct(); + else + { + uint type = reader.ReadUInt32(); //prim type + mesh.MaterialIndex = reader.ReadUInt16(); + mesh.VertexBufferIndex = reader.ReadByte(); + mesh.IndexBufferIndex = reader.ReadByte(); + mesh.IndexStart = reader.ReadUInt32(); + mesh.IndexCount = reader.ReadUInt32(); + reader.ReadUInt16(); //0x10 + reader.ReadByte(); //0x12 + reader.ReadByte(); //0x13 + reader.ReadByte(); //flags + } + Meshes.Add(new CMesh() { - Header = reader.ReadStruct(), + Header = mesh, }); + } + Console.WriteLine(); } private void ReadVertexBuffer(FileReader reader) @@ -334,6 +371,8 @@ namespace DKCTF for (int j = 0; j < numAttributes; j++) vertexBuffer.Components.Add(reader.ReadStruct()); VertexBuffers.Add(vertexBuffer); + if (this.IsMPR) + reader.ReadByte(); } } @@ -381,6 +420,7 @@ namespace DKCTF public Dictionary Scalars = new Dictionary(); public Dictionary Int = new Dictionary(); public Dictionary Int4 = new Dictionary(); + public Dictionary Matrices = new Dictionary(); public Dictionary Colors = new Dictionary(); } @@ -416,16 +456,13 @@ namespace DKCTF [StructLayout(LayoutKind.Sequential, Pack = 1)] public class CRenderMesh { - public PrimtiiveType PrimtiiveMode; public ushort MaterialIndex; public byte VertexBufferIndex; public byte IndexBufferIndex; public uint IndexStart; public uint IndexCount; - public ushort field_10; - public byte field_12; - public byte field_13; - public byte field_14; + public ushort field_C; + public ushort field_E; //0x4000 } [StructLayout(LayoutKind.Sequential, Pack = 1)] @@ -465,7 +502,7 @@ namespace DKCTF [StructLayout(LayoutKind.Sequential, Pack = 1)] public class SVertexDataComponent { - public uint field_0; + public uint BufferID; public uint Offset; public uint Stride; public VertexFormat Format; diff --git a/File_Format_Library/FileFormats/DKCTF/FileData/Common.cs b/File_Format_Library/FileFormats/DKCTF/FileData/Common.cs index 8e220750..fe43275c 100644 --- a/File_Format_Library/FileFormats/DKCTF/FileData/Common.cs +++ b/File_Format_Library/FileFormats/DKCTF/FileData/Common.cs @@ -20,11 +20,22 @@ namespace DKCTF public FileForm() { } + public bool IsLittleEndian = false; + public bool IsMPR = false; + public FileForm(Stream stream, bool leaveOpen = false) { using (var reader = new FileReader(stream, leaveOpen)) { - reader.SetByteOrder(true); + //Small "hack" to detect endianness. + using (reader.TemporarySeek(4, SeekOrigin.Begin)) { + //Size is a uint64. If the first 4 bytes are present, file is little endian + IsLittleEndian = reader.ReadUInt32() != 0; + //MPR is only game currently that is little endian + IsMPR = IsLittleEndian; + } + + reader.SetByteOrder(!IsLittleEndian); FileHeader = reader.ReadStruct(); Read(reader); AfterLoad(); @@ -61,7 +72,7 @@ namespace DKCTF /// /// Reads meta data information within the pak archive. /// - public virtual void ReadMetaData(FileReader reader) + public virtual void ReadMetaData(FileReader reader, CFormDescriptor pakVersion) { } @@ -69,7 +80,7 @@ namespace DKCTF /// /// Writes meta data information within the pak archive. /// - public virtual void WriteMetaData(FileWriter writer) + public virtual void WriteMetaData(FileWriter writer, CFormDescriptor pakVersion) { } @@ -87,22 +98,28 @@ namespace DKCTF /// public long ReadMetaFooter(FileReader reader) { - using (reader.TemporarySeek(reader.BaseStream.Length - 12, SeekOrigin.Begin)) + using (reader.TemporarySeek(reader.BaseStream.Length - 20, SeekOrigin.Begin)) { if (reader.ReadString(4, Encoding.ASCII) != "META") return reader.BaseStream.Length; } - using (reader.TemporarySeek(reader.BaseStream.Length - 12, SeekOrigin.Begin)) + using (reader.TemporarySeek(reader.BaseStream.Length - 20, SeekOrigin.Begin)) { reader.ReadSignature(4, "META"); reader.ReadString(4); //type of file + uint versionA = reader.ReadUInt32(); //pak version A + uint versionB = reader.ReadUInt32(); //pak version B uint size = reader.ReadUInt32(); //size of meta data //Seek back to meta data reader.SeekBegin(reader.Position - size); //Read meta data - ReadMetaData(reader); + CFormDescriptor pakHeader = new CFormDescriptor(); + pakHeader.VersionA = versionA; + pakHeader.VersionB = versionB; + + ReadMetaData(reader, pakHeader); return reader.BaseStream.Length - size; } @@ -111,22 +128,24 @@ namespace DKCTF /// /// Writes a footer to a file for accessing meta data information outside a .pak archive. /// - public static byte[] WriteMetaFooter(FileReader reader, uint metaOffset, string type) + public static byte[] WriteMetaFooter(FileReader reader, uint metaOffset, string type, PACK pack) { //Magic + meta offset first var mem = new MemoryStream(); using (var writer = new FileWriter(mem)) { - writer.SetByteOrder(true); + writer.SetByteOrder(!pack.IsLittleEndian); reader.SeekBegin(metaOffset); var file = GetFileForm(type); - file.ReadMetaData(reader); - file.WriteMetaData(writer); + file.ReadMetaData(reader, pack.FileHeader); + file.WriteMetaData(writer, pack.FileHeader); //Write footer header last writer.WriteSignature("META"); writer.WriteSignature(type); + writer.Write(pack.FileHeader.VersionA); + writer.Write(pack.FileHeader.VersionB); writer.Write((uint)(writer.BaseStream.Length + 4)); //size } return mem.ToArray(); diff --git a/File_Format_Library/FileFormats/DKCTF/FileData/IOFileExtension.cs b/File_Format_Library/FileFormats/DKCTF/FileData/IOFileExtension.cs index 1472eff6..820aeedc 100644 --- a/File_Format_Library/FileFormats/DKCTF/FileData/IOFileExtension.cs +++ b/File_Format_Library/FileFormats/DKCTF/FileData/IOFileExtension.cs @@ -58,14 +58,12 @@ namespace DKCTF reader.SetByteOrder(true); Console.WriteLine($"type {type}"); - // File.WriteAllBytes($"Buffer{type}.bin", reader.ReadBytes((int)(compSize - 4))); - var data = reader.ReadBytes((int)compSize - 4); switch (type) { case CompressionType.None: - return reader.ReadBytes((int)decompSize); + return data; //LZSS with byte, short, and uint types case CompressionType.LZSS_8: return DecompressLZSS(data, 1, decompSize); case CompressionType.LZSS_16: return DecompressLZSS(data, 2, decompSize); diff --git a/File_Format_Library/FileFormats/DKCTF/FileData/PACK.cs b/File_Format_Library/FileFormats/DKCTF/FileData/PACK.cs index 0988cc55..e69cb2ad 100644 --- a/File_Format_Library/FileFormats/DKCTF/FileData/PACK.cs +++ b/File_Format_Library/FileFormats/DKCTF/FileData/PACK.cs @@ -70,7 +70,7 @@ namespace DKCTF for (int i = 0; i < numEntries; i++) { DirectoryAssetEntry entry = new DirectoryAssetEntry(); - entry.Read(reader); + entry.Read(reader, this.FileHeader); Assets.Add(entry); } } @@ -85,7 +85,8 @@ namespace DKCTF var id = IOFileExtension.ReadID(reader); uint offset = reader.ReadUInt32(); - MetaOffsets.Add(id.ToString(), offset); + if (!MetaOffsets.ContainsKey(id.ToString())) + MetaOffsets.Add(id.ToString(), offset); } } @@ -118,14 +119,27 @@ namespace DKCTF public CObjectId FileID; public long Offset; + public long DecompressedSize; public long Size; - public void Read(FileReader reader) + public void Read(FileReader reader, CFormDescriptor header) { Type = reader.ReadString(4, Encoding.ASCII); FileID = IOFileExtension.ReadID(reader); - Offset = reader.ReadInt64(); - Size = reader.ReadInt64(); + if (header.VersionA >= 1 && header.VersionB >= 1) + { + long flag1 = reader.ReadUInt32(); + long flag2 = reader.ReadUInt32(); + Offset = reader.ReadInt64(); + DecompressedSize = reader.ReadInt64(); + Size = reader.ReadInt64(); + } + else + { + Offset = reader.ReadInt64(); + Size = reader.ReadInt64(); + DecompressedSize = Size; + } } } diff --git a/File_Format_Library/FileFormats/DKCTF/FileData/TXTR.cs b/File_Format_Library/FileFormats/DKCTF/FileData/TXTR.cs index 95ceb4be..c516a0d9 100644 --- a/File_Format_Library/FileFormats/DKCTF/FileData/TXTR.cs +++ b/File_Format_Library/FileFormats/DKCTF/FileData/TXTR.cs @@ -26,7 +26,6 @@ namespace DKCTF public uint Unknown { get; set; } - public bool IsSwitch => this.FileHeader.VersionA >= 0x0F; public TXTR() { } @@ -35,34 +34,57 @@ namespace DKCTF { } - public byte[] CreateUncompressedFile(byte[] fileData) + public byte[] CreateUncompressedFile(byte[] fileData, CFormDescriptor pakHeader, bool isLittleEndian) { var mem = new MemoryStream(); using (var writer = new FileWriter(mem)) using (var reader = new FileReader(fileData)) { - writer.SetByteOrder(true); - reader.SetByteOrder(true); + reader.SetByteOrder(!isLittleEndian); + writer.SetByteOrder(!isLittleEndian); FileHeader = reader.ReadStruct(); ReadMetaFooter(reader); + //Rewrite header for saving uncompressed file reader.Position = 0; byte[] textureInfo = reader.ReadBytes((int)Meta.GPUOffset + 24); long pos = reader.BaseStream.Position - 24; - var buffer = Meta.BufferInfo[0]; - reader.Seek(buffer.Offset); + List combinedBuffer = new List(); - byte[] BufferData = IOFileExtension.DecompressedBuffer(reader, buffer.CompressedSize, buffer.DecompressedSize, IsSwitch); + byte[] textureData = new byte[Meta.DecompressedSize]; + + if (pakHeader.VersionA >= 1 && pakHeader.VersionB >= 1) + { + //Decompress all buffers + foreach (var info in Meta.TextureInfo) + { + var buff = Meta.BufferInfo[info.Index]; + + //Go to the buffer + reader.SeekBegin(info.StartOffset + buff.StartOffset); + //Decompress the buffer + byte[] BufferData = IOFileExtension.DecompressedBuffer(reader, buff.CompressedSize, buff.DestSize, IsSwitch || isLittleEndian); + combinedBuffer.Add(BufferData); + + Array.Copy(BufferData, 0, textureData, (int)buff.DestOffset, (int)buff.DestSize); + } + } + else + { + var buffer = Meta.BufferInfoV1[0]; + reader.SeekBegin(Meta.GPUDataStart + buffer.Offset); + + textureData = IOFileExtension.DecompressedBuffer(reader, buffer.CompressedSize, buffer.DecompressedSize, IsSwitch); + } writer.Write(textureInfo); - writer.Write(BufferData); + writer.Write(textureData); - using (writer.TemporarySeek(pos + 4, SeekOrigin.Begin)) - { - writer.Write((long)BufferData.Length); + using (writer.TemporarySeek(pos + 4, SeekOrigin.Begin)) { + writer.Write((long)textureData.Length); } return mem.ToArray(); @@ -84,9 +106,8 @@ namespace DKCTF if (Meta != null) { var buffer = Meta.BufferInfo[0]; - - reader.Seek(buffer.Offset); - BufferData = IOFileExtension.DecompressedBuffer(reader, buffer.CompressedSize, buffer.DecompressedSize, IsSwitch); + reader.SeekBegin(buffer.StartOffset); + BufferData = IOFileExtension.DecompressedBuffer(reader, (uint)buffer.CompressedSize, (uint)buffer.DestSize, IsSwitch); } else { @@ -96,33 +117,63 @@ namespace DKCTF } } - public override void ReadMetaData(FileReader reader) + public override void ReadMetaData(FileReader reader, CFormDescriptor pakVersion) { Meta = new SMetaData(); - Meta.Unknown = reader.ReadUInt32(); - Meta.AllocCategory = reader.ReadUInt32(); - Meta.GPUOffset = reader.ReadUInt32(); - Meta.BaseAlignment = reader.ReadUInt32(); - Meta.GPUDataStart = reader.ReadUInt32(); - Meta.GPUDataSize = reader.ReadUInt32(); - Meta.BufferInfo = IOFileExtension.ReadList(reader); + // MPR + if (pakVersion.VersionA >= 1 && pakVersion.VersionB >= 1) + { + reader.ReadUInt32(); //Extra uint in MPR + Meta.Unknown = reader.ReadUInt32(); + Meta.AllocCategory = reader.ReadUInt32(); + Meta.GPUOffset = reader.ReadUInt32(); + Meta.BaseAlignment = reader.ReadUInt32(); + Meta.DecompressedSize = reader.ReadUInt32(); //total decomp size + Meta.TextureInfo = IOFileExtension.ReadList(reader); + Meta.BufferInfo = IOFileExtension.ReadList(reader); + } + else + { + Meta.Unknown = reader.ReadUInt32(); + Meta.AllocCategory = reader.ReadUInt32(); + Meta.GPUOffset = reader.ReadUInt32(); + Meta.BaseAlignment = reader.ReadUInt32(); + Meta.GPUDataStart = reader.ReadUInt32(); + Meta.GPUDataSize = reader.ReadUInt32(); + Meta.BufferInfoV1 = IOFileExtension.ReadList(reader); + } + Console.WriteLine(); } - public override void WriteMetaData(FileWriter writer) + public override void WriteMetaData(FileWriter writer, CFormDescriptor pakVersion) { - writer.Write(Meta.Unknown); - writer.Write(Meta.AllocCategory); - writer.Write(Meta.GPUOffset); - writer.Write(Meta.BaseAlignment); - writer.Write(Meta.GPUDataStart); - writer.Write(Meta.GPUDataSize); - IOFileExtension.WriteList(writer, Meta.BufferInfo); + if (pakVersion.VersionA >= 1 && pakVersion.VersionB >= 1) + { + writer.Write(Meta.Unknown); + writer.Write(0); + writer.Write(Meta.AllocCategory); + writer.Write(Meta.GPUOffset); + writer.Write(Meta.BaseAlignment); + writer.Write(Meta.DecompressedSize); + IOFileExtension.WriteList(writer, Meta.TextureInfo); + IOFileExtension.WriteList(writer, Meta.BufferInfo); + } + else + { + writer.Write(Meta.Unknown); + writer.Write(Meta.AllocCategory); + writer.Write(Meta.GPUOffset); + writer.Write(Meta.BaseAlignment); + writer.Write(Meta.GPUDataStart); + writer.Write(Meta.GPUDataSize); + IOFileExtension.WriteList(writer, Meta.BufferInfoV1); + } } [StructLayout(LayoutKind.Sequential, Pack = 1)] public class STextureHeader { - public uint Type; + public uint Type; //1 = 2D 3 = Cubemap public uint Format; public uint Width; public uint Height; @@ -135,16 +186,38 @@ namespace DKCTF public class SMetaData { public uint Unknown; //4 + public uint Unknown2; public uint AllocCategory; - public uint GPUOffset; - public uint BaseAlignment; + public uint GPUOffset; public uint GPUDataStart; public uint GPUDataSize; + public uint BaseAlignment; + public uint DecompressedSize; + public List TextureInfo = new List(); public List BufferInfo = new List(); + public List BufferInfoV1 = new List(); + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public class STextureInfo + { + public byte Index; + public uint StartOffset; + public uint EndOffset; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public class SCompressedBufferInfo + { + public uint Index; + public uint StartOffset; + public uint CompressedSize; + public uint DestOffset; + public uint DestSize; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public class SCompressedBufferInfoV1 { public uint DecompressedSize; public uint CompressedSize; diff --git a/File_Format_Library/FileFormats/DKCTF/PAK.cs b/File_Format_Library/FileFormats/DKCTF/PAK.cs index f1eb3e5f..0919f0d0 100644 --- a/File_Format_Library/FileFormats/DKCTF/PAK.cs +++ b/File_Format_Library/FileFormats/DKCTF/PAK.cs @@ -58,9 +58,14 @@ namespace DKCTF public Dictionary CharFiles = new Dictionary(); public Dictionary AnimFiles = new Dictionary(); + public PACK PakData; + + internal bool IsMPR; + public void Load(System.IO.Stream stream) { PACK pack = new PACK(stream); + PakData = pack; for (int i = 0; i < pack.Assets.Count; i++) { @@ -124,12 +129,13 @@ namespace DKCTF if (file.AssetEntry.Type == "ANIM") file.FileName = file.FileName.Replace("exportData", "animations"); } } - files = files.OrderBy(x => x.FileName).ToList(); + // files = files.OrderBy(x => x.FileName).ToList(); } Dictionary DirectoryLabels = new Dictionary() { { "CHAR", "Characters" }, + { "CHPR", "Character Project" }, { "CMDL", "Static Models" }, { "SMDL", "Skinned Models" }, { "TXTR", "Textures" }, @@ -185,14 +191,20 @@ namespace DKCTF using (var reader = new FileReader(SubData, true)) { - Data.Add(reader.ReadBytes((int)reader.BaseStream.Length)); + var data = reader.ReadBytes((int)reader.BaseStream.Length); + + reader.Position = 0; + if (AssetEntry.DecompressedSize != AssetEntry.Size) + data = IOFileExtension.DecompressedBuffer(reader, (uint)AssetEntry.Size, (uint)AssetEntry.DecompressedSize, true); + + Data.Add(data); if (WriteMetaData) { using (var r = new FileReader(ArchiveStream, true)) { - r.SetByteOrder(true); + r.SetByteOrder(!ParentArchive.PakData.IsLittleEndian); - Data.Add(FileForm.WriteMetaFooter(r, (uint)MetaPointer, AssetEntry.Type)); + Data.Add(FileForm.WriteMetaFooter(r, (uint)MetaPointer, AssetEntry.Type, ParentArchive.PakData)); } } } @@ -200,7 +212,7 @@ namespace DKCTF if (AssetEntry.Type == "TXTR") { var txt = new TXTR(); - return txt.CreateUncompressedFile(Utils.CombineByteArray(Data.ToArray())); + return txt.CreateUncompressedFile(Utils.CombineByteArray(Data.ToArray()), ParentArchive.PakData.FileHeader, ParentArchive.PakData.IsMPR); } @@ -255,7 +267,7 @@ namespace DKCTF } if (file is CCharacter) ((CCharacter)file).LoadModels(pak); - + this.FileFormat = file; return file; diff --git a/Switch_Toolbox_Library/Forms/Editors/UV/PickableUVMap.cs b/Switch_Toolbox_Library/Forms/Editors/UV/PickableUVMap.cs index d7a2d122..c25e3f26 100644 --- a/Switch_Toolbox_Library/Forms/Editors/UV/PickableUVMap.cs +++ b/Switch_Toolbox_Library/Forms/Editors/UV/PickableUVMap.cs @@ -48,6 +48,7 @@ namespace Toolbox.Library.Forms { if (genericObjects.Count == 0) return; + foreach (var genericObject in genericObjects) { int divisions = 4; @@ -83,8 +84,6 @@ namespace Toolbox.Library.Forms } } - Console.WriteLine($"displayFaceSize {f.Count} {displayFaceSize} {genericObject.vertices.Count }"); - for (int v = 0; v < displayFaceSize; v += 3) { if (displayFaceSize < 3 || genericObject.vertices.Count < 3) diff --git a/Switch_Toolbox_Library/Forms/Editors/UV/UVEditor.cs b/Switch_Toolbox_Library/Forms/Editors/UV/UVEditor.cs index c0d9a306..5124daa2 100644 --- a/Switch_Toolbox_Library/Forms/Editors/UV/UVEditor.cs +++ b/Switch_Toolbox_Library/Forms/Editors/UV/UVEditor.cs @@ -202,13 +202,22 @@ namespace Toolbox.Library.Forms { if (meshesCB.SelectedIndex >= 0) { - uvViewport1.ActiveObjects.Clear(); - - if (Objects.Count > meshesCB.SelectedIndex) - uvViewport1.ActiveObjects.Add(Objects[meshesCB.SelectedIndex]); ActiveMaterial = Materials[meshesCB.SelectedIndex]; + uvViewport1.ActiveObjects.Clear(); + foreach (var obj in Objects) + { + if (obj.GetMaterial() == ActiveMaterial) + uvViewport1.ActiveObjects.Add(obj); + + foreach (var p in obj.PolygonGroups) + { + if (p.Material == ActiveMaterial && !uvViewport1.ActiveObjects.Contains(obj)) + uvViewport1.ActiveObjects.Add(obj); + } + } + ChannelTextures.Clear(); Textures.Clear(); textureCB.Items.Clear(); @@ -235,6 +244,8 @@ namespace Toolbox.Library.Forms if (textureCB.Items.Count > 0) textureCB.SelectedIndex = 0; + + uvViewport1.UpdateViewport(); } }