mirror of
https://github.com/KillzXGaming/Switch-Toolbox
synced 2024-11-10 07:04:36 +00:00
LM3 fixes. and improvements.
Fixed UV issues which would show up broken. Improved the tree loading. Havok files are loaded, and additional string data.
This commit is contained in:
parent
544a30639b
commit
f5605f6878
6 changed files with 197 additions and 47 deletions
|
@ -161,7 +161,7 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
|
|||
{
|
||||
var chunkEntry = new ChunkDataEntry(this, chunk);
|
||||
chunkEntry.DataFile = File003Data;
|
||||
chunkEntry.Text = $"Chunk {chunk.ChunkType} {chunkId++}";
|
||||
chunkEntry.Text = $"Chunk {chunk.ChunkType.ToString("X")} {chunk.ChunkType} {chunkId++}";
|
||||
chunkEntries.Add(chunkEntry);
|
||||
chunkFolder.Nodes.Add(chunkEntry);
|
||||
|
||||
|
|
|
@ -38,6 +38,9 @@ namespace FirstPlugin.LuigisMansion3
|
|||
{
|
||||
tableReader.SetByteOrder(false);
|
||||
|
||||
if (tableReader.BaseStream.Length <= 4)
|
||||
return;
|
||||
|
||||
//Load the first chunk table
|
||||
//These point to sections which usually have magic and a hash
|
||||
//The chunk table afterwards contains the data itself
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace FirstPlugin.LuigisMansion3
|
|||
}
|
||||
}
|
||||
|
||||
public static bool DebugMode = true;
|
||||
public static bool DebugMode = false;
|
||||
|
||||
public List<ChunkDataEntry> chunkEntries = new List<ChunkDataEntry>();
|
||||
|
||||
|
@ -82,6 +82,7 @@ namespace FirstPlugin.LuigisMansion3
|
|||
|
||||
public static Dictionary<uint, string> HashNames = new Dictionary<uint, string>();
|
||||
|
||||
public List<string> StringList = new List<string>();
|
||||
private void LoadHashes()
|
||||
{
|
||||
foreach (string hashStr in Properties.Resources.LM3_Hashes.Split('\n'))
|
||||
|
@ -110,9 +111,15 @@ namespace FirstPlugin.LuigisMansion3
|
|||
return fileEntries[60].GetData(); //Get the fourth file
|
||||
}
|
||||
|
||||
private ushort Unknown0x4;
|
||||
|
||||
public List<ChunkInfo> ChunkInfos = new List<ChunkInfo>();
|
||||
|
||||
public bool DrawablesLoaded = false;
|
||||
public void Load(System.IO.Stream stream)
|
||||
{
|
||||
CanSave = false;
|
||||
|
||||
LoadHashes();
|
||||
modelFolder = new LM3_ModelFolder(this);
|
||||
DrawableContainer.Name = FileName;
|
||||
|
@ -125,37 +132,36 @@ namespace FirstPlugin.LuigisMansion3
|
|||
{
|
||||
reader.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
|
||||
uint Identifier = reader.ReadUInt32();
|
||||
ushort Unknown = reader.ReadUInt16(); //Could also be 2 bytes, not sure. Always 0x0401
|
||||
Unknown0x4 = reader.ReadUInt16(); //Could also be 2 bytes, not sure. Always 0x0401
|
||||
IsCompressed = reader.ReadByte() == 1;
|
||||
reader.ReadByte(); //Padding
|
||||
uint unk = reader.ReadUInt32();
|
||||
uint unk2 = reader.ReadUInt32();
|
||||
uint SizeLargestFile = reader.ReadUInt32();
|
||||
byte numFiles = reader.ReadByte();
|
||||
byte numChunkInfos = reader.ReadByte();
|
||||
byte numStrings = reader.ReadByte();
|
||||
reader.ReadByte(); //padding
|
||||
|
||||
//Start of the chunk info. A fixed list of chunk information
|
||||
|
||||
TreeNode chunkNodes = new TreeNode("Chunks Debug");
|
||||
|
||||
for (int i = 0; i < 52; i++)
|
||||
for (int i = 0; i < numChunkInfos; i++)
|
||||
{
|
||||
ChunkInfo chunk = new ChunkInfo();
|
||||
chunk.Read(reader);
|
||||
chunkNodes.Nodes.Add(chunk);
|
||||
ChunkInfos.Add(chunk);
|
||||
}
|
||||
|
||||
TreeNode tableNodes = new TreeNode("File Section Entries");
|
||||
|
||||
if (DebugMode)
|
||||
Nodes.Add(chunkNodes);
|
||||
TreeNode chunkLookupNodes = new TreeNode("Chunk Lookup Files");
|
||||
tableNodes.Nodes.Add(chunkLookupNodes);
|
||||
|
||||
Nodes.Add(tableNodes);
|
||||
|
||||
var FileCount = 120;
|
||||
|
||||
TreeNode stringFolder = new TreeNode("Strings");
|
||||
TreeNode chunkTexFolder = new TreeNode("Texture");
|
||||
TreeNode chunkModelFolder = new TreeNode("Model");
|
||||
|
||||
long FileTablePos = reader.Position;
|
||||
for (int i = 0; i < FileCount; i++)
|
||||
for (int i = 0; i < numFiles; i++)
|
||||
{
|
||||
var file = new FileEntry(this);
|
||||
file.Read(reader);
|
||||
|
@ -164,7 +170,11 @@ namespace FirstPlugin.LuigisMansion3
|
|||
if (file.DecompressedSize > 0)
|
||||
{
|
||||
file.Text = $"entry {i}";
|
||||
tableNodes.Nodes.Add(file);
|
||||
|
||||
if (i < 52)
|
||||
chunkLookupNodes.Nodes.Add(file);
|
||||
else
|
||||
tableNodes.Nodes.Add(file);
|
||||
}
|
||||
|
||||
//The first file stores a chunk layout
|
||||
|
@ -200,6 +210,13 @@ namespace FirstPlugin.LuigisMansion3
|
|||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < numStrings; i++)
|
||||
{
|
||||
StringList.Add(reader.ReadZeroTerminatedString());
|
||||
stringFolder.Nodes.Add(StringList[i]);
|
||||
}
|
||||
|
||||
TreeNode havokFolder = new TreeNode("Havok Physics");
|
||||
|
||||
//Model data block
|
||||
//Contains texture hash refs and model headers
|
||||
|
@ -229,11 +246,20 @@ namespace FirstPlugin.LuigisMansion3
|
|||
int chunkId = 0;
|
||||
uint modelIndex = 0;
|
||||
uint ImageHeaderIndex = 0;
|
||||
uint havokFileIndex = 0;
|
||||
foreach (var chunk in ChunkTable.ChunkSubEntries)
|
||||
{
|
||||
Console.WriteLine($"chunk.ChunkType {chunk.ChunkType}");
|
||||
var chunkEntry = new ChunkDataEntry(this, chunk);
|
||||
chunkEntry.Text = $"{chunkId} {chunk.ChunkType.ToString("X")} {chunk.ChunkType} {chunk.ChunkOffset} {chunk.ChunkSize}";
|
||||
|
||||
switch (chunk.ChunkType)
|
||||
{
|
||||
case SubDataType.HavokPhysics:
|
||||
chunkEntry.DataFile = File052Data;
|
||||
chunkEntry.Text = $"File_{havokFileIndex++}.hkx";
|
||||
havokFolder.Nodes.Add(chunkEntry);
|
||||
break;
|
||||
case SubDataType.TextureHeader:
|
||||
chunkEntry.DataFile = File063Data;
|
||||
|
||||
|
@ -331,17 +357,63 @@ namespace FirstPlugin.LuigisMansion3
|
|||
case SubDataType.UILayout:
|
||||
chunkEntry.DataFile = File053Data;
|
||||
break;
|
||||
case SubDataType.BoneData:
|
||||
if (chunk.ChunkSize > 0x40 && currentModel.Skeleton == null)
|
||||
{
|
||||
/* chunkEntry.DataFile = File052Data;
|
||||
using (var boneReader = new FileReader(chunkEntry.FileData))
|
||||
{
|
||||
currentModel.Skeleton = new STSkeleton();
|
||||
DrawableContainer.Drawables.Add(currentModel.Skeleton);
|
||||
|
||||
uint numBones = chunk.ChunkSize / 0x40;
|
||||
for (int i = 0; i < numBones; i++)
|
||||
{
|
||||
boneReader.SeekBegin(i * 0x40);
|
||||
STBone bone = new STBone(currentModel.Skeleton);
|
||||
bone.position = new float[3] { 0, 0, 0 };
|
||||
bone.rotation = new float[4] { 0, 0, 0, 1 };
|
||||
bone.scale = new float[3] { 0.2f, 0.2f, 0.2f };
|
||||
|
||||
boneReader.SeekBegin(48 + (i * 0x40));
|
||||
var Position = new OpenTK.Vector3(boneReader.ReadSingle(), boneReader.ReadSingle(), boneReader.ReadSingle());
|
||||
Position = OpenTK.Vector3.TransformPosition(Position, OpenTK.Matrix4.CreateRotationX(OpenTK.MathHelper.DegreesToRadians(90)));
|
||||
bone.position[0] = Position.X;
|
||||
bone.position[2] = Position.Y;
|
||||
bone.position[1] = Position.Z;
|
||||
|
||||
|
||||
bone.RotationType = STBone.BoneRotationType.Euler;
|
||||
currentModel.Skeleton.bones.Add(bone);
|
||||
}
|
||||
|
||||
currentModel.Skeleton.reset();
|
||||
currentModel.Skeleton.update();
|
||||
}*/
|
||||
}
|
||||
break;
|
||||
case (SubDataType)0x5012:
|
||||
case (SubDataType)0x5013:
|
||||
case (SubDataType)0x5014:
|
||||
chunkEntry.DataFile = File063Data;
|
||||
break;
|
||||
case (SubDataType)0x7101:
|
||||
case (SubDataType)0x7102:
|
||||
case (SubDataType)0x7103:
|
||||
case (SubDataType)0x7104:
|
||||
case (SubDataType)0x7105:
|
||||
case (SubDataType)0x7106:
|
||||
case (SubDataType)0x6503:
|
||||
case (SubDataType)0x6501:
|
||||
chunkEntry.DataFile = File053Data;
|
||||
break;
|
||||
default:
|
||||
chunkEntry.DataFile = File052Data;
|
||||
break;
|
||||
}
|
||||
|
||||
chunkEntry.Text = $"{chunkId} {chunk.ChunkType.ToString("X")} {chunk.ChunkType} {chunk.ChunkOffset} {chunk.ChunkSize}";
|
||||
chunkFolder.Nodes.Add(chunkEntry);
|
||||
|
||||
|
||||
// if (currentModel != null && currentModel.Meshes?.Count > 0)
|
||||
// break;
|
||||
if (chunk.ChunkType != SubDataType.HavokPhysics)
|
||||
chunkFolder.Nodes.Add(chunkEntry);
|
||||
|
||||
chunkId++;
|
||||
}
|
||||
|
@ -352,11 +424,17 @@ namespace FirstPlugin.LuigisMansion3
|
|||
currentModel.ModelInfo.Data), currentModel.Meshes, TextureHashes);
|
||||
}
|
||||
|
||||
if (havokFolder.Nodes.Count > 0)
|
||||
Nodes.Add(havokFolder);
|
||||
|
||||
if (textureFolder.Nodes.Count > 0)
|
||||
Nodes.Add(textureFolder);
|
||||
|
||||
if (modelFolder.Nodes.Count > 0)
|
||||
Nodes.Add(modelFolder);
|
||||
|
||||
if (stringFolder.Nodes.Count > 0)
|
||||
Nodes.Add(stringFolder);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,7 +445,43 @@ namespace FirstPlugin.LuigisMansion3
|
|||
|
||||
public void Save(System.IO.Stream stream)
|
||||
{
|
||||
using (var writer = new FileWriter(stream))
|
||||
{
|
||||
writer.SetByteOrder(true);
|
||||
writer.Write(0x78340300);
|
||||
writer.SetByteOrder(false);
|
||||
writer.Write(Unknown0x4);
|
||||
writer.Write(IsCompressed);
|
||||
writer.Write((byte)0); //padding
|
||||
writer.Write(GetLargestFileSize());
|
||||
writer.Write((byte)fileEntries.Count);
|
||||
writer.Write((byte)ChunkInfos.Count);
|
||||
writer.Write((byte)StringList.Count);
|
||||
writer.Write((byte)0); //padding
|
||||
|
||||
for (int i = 0; i < ChunkInfos.Count; i++)
|
||||
{
|
||||
writer.Write(ChunkInfos[i].Unknown1);
|
||||
writer.Write(ChunkInfos[i].Unknown2);
|
||||
writer.Write(ChunkInfos[i].Unknown3);
|
||||
writer.Write(ChunkInfos[i].Unknown4);
|
||||
writer.Write(ChunkInfos[i].Unknown5);
|
||||
writer.Write(ChunkInfos[i].Unknown6);
|
||||
}
|
||||
|
||||
for (int i = 0; i < fileEntries.Count; i++)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
for (int i = 0; i < StringList.Count; i++)
|
||||
writer.WriteString(StringList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private uint GetLargestFileSize()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public bool AddFile(ArchiveFileInfo archiveFileInfo)
|
||||
|
@ -380,22 +494,23 @@ namespace FirstPlugin.LuigisMansion3
|
|||
return false;
|
||||
}
|
||||
|
||||
public class ChunkInfo : TreeNodeCustom
|
||||
public class ChunkInfo
|
||||
{
|
||||
public string Type;
|
||||
public uint Unknown1;
|
||||
public uint Unknown2;
|
||||
public uint Unknown3;
|
||||
public uint Unknown4;
|
||||
public uint Unknown5;
|
||||
public uint Unknown6;
|
||||
|
||||
public void Read(FileReader reader)
|
||||
{
|
||||
uint Unknown1 = reader.ReadUInt32();
|
||||
ushort Unknown2 = reader.ReadUInt16();
|
||||
ushort Unknown3 = reader.ReadUInt16();
|
||||
uint Unknown2 = reader.ReadUInt32();
|
||||
uint Unknown3 = reader.ReadUInt32();
|
||||
uint Unknown4 = reader.ReadUInt32();
|
||||
Type = reader.ReadString(3);
|
||||
byte Unknown5 = reader.ReadByte();
|
||||
uint Unknown5 = reader.ReadUInt32();
|
||||
uint Unknown6 = reader.ReadUInt32();
|
||||
uint Unknown7 = reader.ReadUInt32();
|
||||
|
||||
Text = $" Type: [{Type}] [{Unknown1} {Unknown2} {Unknown3} {Unknown4} {Unknown5} {Unknown6}] ";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -481,6 +596,11 @@ namespace FirstPlugin.LuigisMansion3
|
|||
Unknown3 = reader.ReadByte();
|
||||
}
|
||||
|
||||
public void Write()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private bool IsTextureBinary()
|
||||
{
|
||||
var stream = GetData();
|
||||
|
|
|
@ -66,5 +66,10 @@ namespace FirstPlugin.LuigisMansion3
|
|||
UILayoutHeader = 0x7001,
|
||||
UILayoutData = 0x7002, //Without header
|
||||
UILayout = 0x7003, //All parts combined
|
||||
|
||||
HavokPhysics = 0xC900,
|
||||
|
||||
BoneData = 0xB102,
|
||||
BoneHashList = 0xB103,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,8 @@ namespace FirstPlugin.LuigisMansion3
|
|||
public List<LM3_Mesh> Meshes = new List<LM3_Mesh>();
|
||||
public List<PointerInfo> VertexBufferPointers = new List<PointerInfo>();
|
||||
|
||||
public STSkeleton Skeleton;
|
||||
|
||||
public uint BufferStart;
|
||||
public uint BufferSize;
|
||||
|
||||
|
@ -103,6 +105,15 @@ namespace FirstPlugin.LuigisMansion3
|
|||
|
||||
viewport.SuppressUpdating = true;
|
||||
|
||||
for (int i = 0; i < DataDictionary.DrawableContainer.Drawables.Count; i++)
|
||||
{
|
||||
if (DataDictionary.DrawableContainer.Drawables[i] is STSkeleton)
|
||||
((STSkeleton)DataDictionary.DrawableContainer.Drawables[i]).HideSkeleton = true;
|
||||
}
|
||||
|
||||
if (Skeleton != null)
|
||||
Skeleton.HideSkeleton = false;
|
||||
|
||||
foreach (var mesh in DataDictionary.Renderer.Meshes)
|
||||
mesh.Checked = false;
|
||||
|
||||
|
@ -339,14 +350,13 @@ namespace FirstPlugin.LuigisMansion3
|
|||
|
||||
vert.pos = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
|
||||
vert.pos = Vector3.TransformPosition(vert.pos, mesh.Transform);
|
||||
reader.ReadSingle();
|
||||
vert.nrm = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()).Normalized();
|
||||
|
||||
vert.uv0 = new Vector2(reader.ReadSingle(), reader.ReadSingle());
|
||||
vert.uv1 = new Vector2(reader.ReadSingle(), reader.ReadSingle());
|
||||
var val = reader.ReadSingle();
|
||||
// if (formatInfo.BufferLength >= 0x1C)
|
||||
// vert.col = Read_8_8_8_8_Unorm(reader);
|
||||
//Texture coordinates are stored between normals, WHY NLG
|
||||
var texCoordU = reader.ReadSingle();
|
||||
vert.nrm = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
|
||||
var texCoordV = reader.ReadSingle();
|
||||
vert.tan = new Vector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
|
||||
vert.uv0 = new Vector2(texCoordU, texCoordV);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -375,6 +385,11 @@ namespace FirstPlugin.LuigisMansion3
|
|||
return new Vector3(reader.ReadByte() / 255f, reader.ReadByte() / 255f, reader.ReadByte() / 255f );
|
||||
}
|
||||
|
||||
public static Vector2 NormalizeUvCoordsToFloat(uint U, uint V)
|
||||
{
|
||||
return new Vector2(U / 1024f, V / 1024f);
|
||||
}
|
||||
|
||||
public static Vector2 NormalizeUvCoordsToFloat(ushort U, ushort V)
|
||||
{
|
||||
return new Vector2( U / 1024f, V / 1024f);
|
||||
|
@ -400,8 +415,17 @@ namespace FirstPlugin.LuigisMansion3
|
|||
while (!reader.EndOfStream && reader.Position < reader.BaseStream.Length - 4)
|
||||
{
|
||||
uint HashIDCheck = reader.ReadUInt32();
|
||||
if (Hashes.Contains(HashIDCheck) && !ModelTexHashes.Contains(HashIDCheck))
|
||||
ModelTexHashes.Add(HashIDCheck);
|
||||
if (Hashes.Contains(HashIDCheck))
|
||||
{
|
||||
using (reader.TemporarySeek(8, System.IO.SeekOrigin.Current))
|
||||
{
|
||||
uint unk = reader.ReadUInt32();
|
||||
if (unk == 0xF880BD9F)
|
||||
{
|
||||
ModelTexHashes.Add(HashIDCheck);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < Meshes.Count; i++)
|
||||
|
@ -546,8 +570,6 @@ namespace FirstPlugin.LuigisMansion3
|
|||
IndexStartOffset = reader.ReadUInt32();
|
||||
IndexCount = reader.ReadUInt16();
|
||||
IndexFormat = reader.ReadEnum<IndexFormat>(false);
|
||||
if (IndexFormat != IndexFormat.Index_16)
|
||||
IndexFormat = IndexFormat.Index_8;
|
||||
VertexCount = reader.ReadUInt32();
|
||||
reader.ReadUInt32(); //unknown
|
||||
BufferPtrOffset = reader.ReadUInt16(); //I believe this might be for the buffer pointers. It shifts by 4 for each mesh
|
||||
|
@ -584,7 +606,6 @@ namespace FirstPlugin.LuigisMansion3
|
|||
{ 0xa2fdc74f42ce4fdb, new FormatInfo(VertexDataFormat.Float32_32_32, 0x30)},
|
||||
{ 0xcb092e9f8322ba, new FormatInfo(VertexDataFormat.Float32_32_32, 0x30)},
|
||||
{ 0x2031dd4da78347d9, new FormatInfo(VertexDataFormat.Float32_32_32, 0x30)},
|
||||
|
||||
{ 0x210ed90e5465129a, new FormatInfo(VertexDataFormat.Float32_32_32, 0x30)},
|
||||
{ 0xa86b2280a1500a0c, new FormatInfo(VertexDataFormat.Float32_32_32, 0x30)},
|
||||
{ 0xc5f54a808b32320c, new FormatInfo(VertexDataFormat.Float32_32_32, 0x30)},
|
||||
|
@ -592,12 +613,11 @@ namespace FirstPlugin.LuigisMansion3
|
|||
{ 0xc344835dd398dde9, new FormatInfo(VertexDataFormat.Float32_32_32, 0x30)},
|
||||
{ 0x8d45618da4768c19, new FormatInfo(VertexDataFormat.Float32_32_32, 0x30)},
|
||||
{ 0xd5b9166924e124f5, new FormatInfo(VertexDataFormat.Float32_32_32, 0x30)},
|
||||
|
||||
{ 0x5f5227f782c08883, new FormatInfo(VertexDataFormat.Float32_32_32, 0x0C)},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Dark moon list just for the sake of having them defined
|
||||
{ 0x6350379972D28D0D, new FormatInfo(VertexDataFormat.Float16, 0x46)},
|
||||
{ 0xDC0291B311E26127, new FormatInfo(VertexDataFormat.Float16, 0x16)},
|
||||
{ 0x93359708679BEB7C, new FormatInfo(VertexDataFormat.Float16, 0x16)},
|
||||
|
|
|
@ -183,11 +183,13 @@ namespace Toolbox.Library
|
|||
return;
|
||||
}
|
||||
|
||||
public bool HideSkeleton;
|
||||
|
||||
public override void Draw(GL_ControlModern control, Pass pass, EditorSceneBase editorScene)
|
||||
{
|
||||
CheckBuffers();
|
||||
|
||||
if (!Runtime.OpenTKInitialized || !Runtime.renderBones || !Visible)
|
||||
if (!Runtime.OpenTKInitialized || !Runtime.renderBones || !Visible || HideSkeleton)
|
||||
return;
|
||||
|
||||
SF.Shader shader = OpenTKSharedResources.shaders["BONE"];
|
||||
|
|
Loading…
Reference in a new issue