Update retro formats to support Metroid Prime Remastered

This commit is contained in:
KillzXGaming 2023-02-16 17:25:43 -05:00
parent 976939bec0
commit afe7ab3890
13 changed files with 322 additions and 128 deletions

1
.gitignore vendored
View file

@ -356,3 +356,4 @@ Toolbox/Lib.zip
yuzu-glsl-decompiler
AnimSetupPrevious.zip
AnimSetupNew.zip
Switch_Toolbox_Library/Forms/Editors/UV/UVEditor.cs

View file

@ -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()
{

View file

@ -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<uint, TEX_FORMAT> FormatList = new Dictionary<uint, TEX_FORMAT>()
{
{ 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 },
};
}
}

View file

@ -42,19 +42,23 @@ namespace DKCTF
/// <summary>
/// Gets a vertex list from the provided buffer and descriptor info.
/// </summary>
public static List<CMDL.CVertex> LoadVertexBuffer(byte[] buffer, CMDL.VertexBuffer vertexBuffer, bool isLittleEndian)
public static CMDL.CVertex[] LoadVertexBuffer(List<byte[]> buffers, int startIndex, CMDL.VertexBuffer vertexInfo, bool isLittleEndian)
{
List<CMDL.CVertex> vertices = new List<CMDL.CVertex>();
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;
}

View file

@ -31,7 +31,7 @@ namespace DKCTF
public override void Read(FileReader reader)
{
reader.ReadStruct<CAssetHeader>();
var assetHeader = reader.ReadStruct<CAssetHeader>();
reader.ReadStruct<SInfo>();
//Dumb hack atm
bool IsSwitch = false;

View file

@ -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<SReadBufferInfo>(reader);
Meta.VertexBuffers = IOFileExtension.ReadList<SBufferInfo>(reader);
Meta.IndexBuffers = IOFileExtension.ReadList<SBufferInfo>(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<byte[]> vertexData = new List<byte[]>();
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<CObjectId>();
material.Type = reader.ReadStruct<Magic>();
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<Magic>();
var dformat = reader.ReadStruct<Magic>();
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<STextureUsageInfo>();
}
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<CRenderMesh>();
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<CRenderMesh>(),
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<SVertexDataComponent>());
VertexBuffers.Add(vertexBuffer);
if (this.IsMPR)
reader.ReadByte();
}
}
@ -381,6 +420,7 @@ namespace DKCTF
public Dictionary<string, float> Scalars = new Dictionary<string, float>();
public Dictionary<string, int> Int = new Dictionary<string, int>();
public Dictionary<string, int[]> Int4 = new Dictionary<string, int[]>();
public Dictionary<string, float[]> Matrices = new Dictionary<string, float[]>();
public Dictionary<string, Color4f> Colors = new Dictionary<string, Color4f>();
}
@ -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;

View file

@ -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<CFormDescriptor>();
Read(reader);
AfterLoad();
@ -61,7 +72,7 @@ namespace DKCTF
/// <summary>
/// Reads meta data information within the pak archive.
/// </summary>
public virtual void ReadMetaData(FileReader reader)
public virtual void ReadMetaData(FileReader reader, CFormDescriptor pakVersion)
{
}
@ -69,7 +80,7 @@ namespace DKCTF
/// <summary>
/// Writes meta data information within the pak archive.
/// </summary>
public virtual void WriteMetaData(FileWriter writer)
public virtual void WriteMetaData(FileWriter writer, CFormDescriptor pakVersion)
{
}
@ -87,22 +98,28 @@ namespace DKCTF
/// </summary>
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
/// <summary>
/// Writes a footer to a file for accessing meta data information outside a .pak archive.
/// </summary>
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();

View file

@ -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);

View file

@ -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;
}
}
}

View file

@ -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<CFormDescriptor>();
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<byte[]> combinedBuffer = new List<byte[]>();
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<SCompressedBufferInfo>(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<STextureInfo>(reader);
Meta.BufferInfo = IOFileExtension.ReadList<SCompressedBufferInfo>(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<SCompressedBufferInfoV1>(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<STextureInfo> TextureInfo = new List<STextureInfo>();
public List<SCompressedBufferInfo> BufferInfo = new List<SCompressedBufferInfo>();
public List<SCompressedBufferInfoV1> BufferInfoV1 = new List<SCompressedBufferInfoV1>();
}
[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;

View file

@ -58,9 +58,14 @@ namespace DKCTF
public Dictionary<string, CHAR> CharFiles = new Dictionary<string, CHAR>();
public Dictionary<string, FileEntry> AnimFiles = new Dictionary<string, FileEntry>();
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<string, string> DirectoryLabels = new Dictionary<string, string>()
{
{ "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;

View file

@ -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)

View file

@ -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();
}
}