1
0
mirror of synced 2025-01-19 01:14:08 +01:00

Update LM2 dictionary and chunk tables.

Searching chunks and the associated section is more accurate for LM2.
Chunk types are also improved
This commit is contained in:
KillzXGaming 2019-11-10 08:53:05 -05:00
parent 71c7776f37
commit ddfdbdc724
5 changed files with 150 additions and 68 deletions

View File

@ -19,6 +19,7 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
public class ChunkSubEntry
{
public SubDataType ChunkType;
public byte BlockIndex;
public uint ChunkSize;
public uint ChunkOffset;
}
@ -47,7 +48,14 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
entry.Unknown1 = tableReader.ReadUInt32(); //8
entry.ChunkOffset = tableReader.ReadUInt32(); //The chunk offset in the file. Relative to the first chunk position in the file
entry.ChunkType = tableReader.ReadEnum<DataType>(false); //The type of chunk. 0x8701B5 for example for texture info
entry.ChunkSubCount = tableReader.ReadUInt32(); //Uncertain about this. 2 for textures (info + block). Some sections however use large numbers.
byte unk = tableReader.ReadByte();
byte chunkFlags = tableReader.ReadByte();
// entry.ChunkSubCount = tableReader.ReadUInt32(); //Uncertain about this. 2 for textures (info + block). Some sections however use large numbers.
var flags = tableReader.ReadByte(); //Uncertain about this. 2 for textures (info + block). Some sections however use large numbers.
entry.ChunkSubCount = flags;
tableReader.ReadByte();
tableReader.ReadByte();
tableReader.ReadByte();
//This increases by 2 each chunk info, however the starting value is not 0
//Note the last entry does not have this
@ -66,6 +74,13 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
{
ChunkSubEntry subEntry = new ChunkSubEntry();
subEntry.ChunkType = tableReader.ReadEnum<SubDataType>(false); //The type of chunk. 0x8701B5 for example for texture info
byte unk = tableReader.ReadByte();
byte chunkFlags = tableReader.ReadByte();
byte blockFlag = (byte)(chunkFlags >> 4);
if (blockFlag < 8)
subEntry.BlockIndex = blockFlag;
subEntry.ChunkSize = tableReader.ReadUInt32();
subEntry.ChunkOffset = tableReader.ReadUInt32();
ChunkSubEntries.Add(subEntry);

View File

@ -70,6 +70,7 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
LM2_ModelFolder modelFolder;
TreeNode materialNamesFolder = new TreeNode("Material Names");
TreeNode chunkFolder = new TreeNode("Chunks");
TreeNode messageFolder = new TreeNode("Message Data");
public byte[] GetFile003Data()
{
@ -86,6 +87,8 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
Text = FileName;
var HashNames = NLG_Common.HashNames;
using (var reader = new FileReader(stream))
{
reader.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
@ -154,23 +157,43 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
byte[] File002Data = fileEntries[2].GetData(); //Get the third file
byte[] File003Data = fileEntries[3].GetData(); //Get the fourth file
LuigisMansion3.LM3_DICT.LoadHashes();
List<uint> ModelHashes = new List<uint>();
for (int i = 0; i < ChunkTable.ChunkEntries.Count; i++)
{
if (ChunkTable.ChunkEntries[i].ChunkType == DataType.Model)
{
}
using (var chunkReader = new FileReader(File002Data))
{
chunkReader.SeekBegin(ChunkTable.ChunkEntries[i].ChunkOffset);
uint magic = chunkReader.ReadUInt32();
uint hash = chunkReader.ReadUInt32();
ModelHashes.Add(hash);
Console.WriteLine($"{ChunkTable.ChunkEntries[i].ChunkType} {hash}");
}
}
int chunkId = 0;
uint ImageHeaderIndex = 0;
uint modelIndex = 0;
uint messageIndex = 0;
foreach (var chunk in ChunkTable.ChunkSubEntries)
{
var chunkEntry = new ChunkDataEntry(this, chunk);
chunkEntry.DataFile = File003Data;
chunkEntry.Text = $"Chunk {chunk.ChunkType.ToString("X")} {chunk.ChunkType} {chunkId++}";
chunkEntries.Add(chunkEntry);
chunkFolder.Nodes.Add(chunkEntry);
if (chunk.BlockIndex == 0)
chunkEntry.DataFile = File002Data;
else if (chunk.BlockIndex == 1)
chunkEntry.DataFile = File003Data;
switch (chunk.ChunkType)
{
case SubDataType.TextureHeader:
chunkEntry.DataFile = File002Data;
//Read the info
using (var textureReader = new FileReader(chunkEntry.FileData))
@ -184,20 +207,52 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
textureFolder.Nodes.Add(currentTexture);
Renderer.TextureList.Add(currentTexture);
Console.WriteLine(currentTexture.ID2);
ImageHeaderIndex++;
}
break;
case SubDataType.TextureData:
currentTexture.ImageData = chunkEntry.FileData;
break;
case SubDataType.ModelStart:
case SubDataType.MaterialData:
currentModel = new LM2_Model(this);
currentModel.ModelInfo = new LM2_ModelInfo();
currentModel.Text = $"Model {modelIndex}";
currentModel.ModelInfo.Data = chunkEntry.FileData;
modelFolder.Nodes.Add(currentModel);
if (ModelHashes.Count > modelIndex)
{
currentModel.Text = $"Model {modelIndex} {ModelHashes[(int)modelIndex].ToString("x")}";
if (HashNames.ContainsKey(ModelHashes[(int)modelIndex]))
currentModel.Text = HashNames[ModelHashes[(int)modelIndex]];
}
modelIndex++;
break;
case SubDataType.ModelData:
uint numModels = chunk.ChunkSize / 16;
using (var dataReader = new FileReader(chunkEntry.FileData))
{
for (int i = 0; i < numModels; i++)
{
uint hashID = dataReader.ReadUInt32();
uint numMeshes = dataReader.ReadUInt32();
dataReader.ReadUInt32();
dataReader.ReadUInt32(); //0
Console.WriteLine(hashID);
string text = hashID.ToString("X");
if (HashNames.ContainsKey(hashID))
text = HashNames[hashID];
if (i == 0)
currentModel.Text = text;
}
}
break;
case SubDataType.MeshBuffers:
currentModel.BufferStart = chunkEntry.Entry.ChunkOffset;
currentModel.BufferSize = chunkEntry.Entry.ChunkSize;
@ -214,25 +269,37 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
for (int i = 0; i < numBones; i++)
{
boneReader.SeekBegin(i * 68);
uint hash = boneReader.ReadUInt32();
uint HashID = boneReader.ReadUInt32();
boneReader.ReadUInt32(); //unk
boneReader.ReadUInt32(); //unk
boneReader.ReadUInt32(); //unk
boneReader.ReadSingle(); //0
var Scale = new OpenTK.Vector3(
boneReader.ReadSingle(),
boneReader.ReadSingle(),
boneReader.ReadSingle());
boneReader.ReadSingle(); //0
var Rotate = new OpenTK.Vector3(
boneReader.ReadSingle(),
boneReader.ReadSingle(),
boneReader.ReadSingle());
boneReader.ReadSingle(); //0
var Position = new OpenTK.Vector3(
boneReader.ReadSingle(),
boneReader.ReadSingle(),
boneReader.ReadSingle());
boneReader.ReadSingle(); //1
STBone bone = new STBone(currentModel.Skeleton);
bone.Text = hash.ToString("X");
if (LuigisMansion3.LM3_DICT.HashNames.ContainsKey(hash))
bone.Text = LuigisMansion3.LM3_DICT.HashNames[hash];
bone.Text = HashID.ToString("X");
if (NLG_Common.HashNames.ContainsKey(HashID))
bone.Text = NLG_Common.HashNames[HashID];
bone.position = new float[3] { 0, 0, 0 };
bone.rotation = new float[4] { 0, 0, 0, 1 };
bone.position = new float[3] { Position.X, Position.Z, -Position.Y };
bone.rotation = new float[4] { Rotate.X, Rotate.Z, -Rotate.Y, 1 };
bone.scale = new float[3] { 0.2f, 0.2f, 0.2f };
boneReader.SeekBegin(52 + (i * 68));
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);
}
@ -282,41 +349,28 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
uint hash = chunkReader.ReadUInt32();
string strHash = hash.ToString("X");
if (LuigisMansion3.LM3_DICT.HashNames.ContainsKey(hash))
strHash = LuigisMansion3.LM3_DICT.HashNames[hash];
Console.WriteLine("Hash! T " + strHash);
if (NLG_Common.HashNames.ContainsKey(hash))
strHash = NLG_Common.HashNames[hash];
}
}
break;
case (SubDataType)0x12017105:
case (SubDataType)0x7105:
using (var chunkReader = new FileReader(chunkEntry.FileData))
{
while (chunkReader.Position <= chunkReader.BaseStream.Length - 8)
{
uint hash = chunkReader.ReadUInt32();
uint unk = chunkReader.ReadUInt32();
string strHash = hash.ToString("X");
if (LuigisMansion3.LM3_DICT.HashNames.ContainsKey(hash))
strHash = LuigisMansion3.LM3_DICT.HashNames[hash];
foreach (var bone in currentModel.Skeleton.bones) {
if (bone.Text == strHash)
{
}
}
}
}
currentModel.Skeleton.reset();
currentModel.Skeleton.update();
break;
case SubDataType.MaterialName:
using (var matReader = new FileReader(chunkEntry.FileData))
{
materialNamesFolder.Nodes.Add(matReader.ReadZeroTerminatedString());
string mat = matReader.ReadZeroTerminatedString();
materialNamesFolder.Nodes.Add(mat);
}
break;
case SubDataType.MessageData:
messageFolder.Nodes.Add(new NLOC_Wrapper($"Message Data {messageIndex++}",
new System.IO.MemoryStream(chunkEntry.FileData)));
break;
default:
break;
}
@ -327,6 +381,9 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
model.ReadVertexBuffers();
}
if (messageFolder.Nodes.Count > 0)
Nodes.Add(messageFolder);
if (modelFolder.Nodes.Count > 0)
Nodes.Add(modelFolder);

View File

@ -6,9 +6,10 @@ using System.Threading.Tasks;
namespace FirstPlugin.LuigisMansion.DarkMoon
{
public enum DataType : uint
public enum DataType : ushort
{
Texture = 0x8701B500,
Texture = 0xB500,
Model = 0xB000,
}
public enum VertexDataFormat
@ -25,24 +26,25 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
Index_8 = 0x8000,
}
public enum SubDataType : uint
public enum SubDataType : ushort
{
ModelStart = 0x1201B006,
SubmeshInfo = 0x1201B003, //Or polygon groups?
VertexStartPointers = 0x1201B004,
ModelTransform = 0x1301B001, //Matrix4x4. 0x40 in size
MeshBuffers = 0x1301B005, //vertex and index buffer
BoneData = 0x1201B102,
BoneHashes = 0x1201B103,
MaterialName = 0x1201B333,
MeshIndexTable = 0x1201B007,
MessageData = 0x12027020,
ShaderData = 0x1401B400,
TextureHeader = 0x0201B501,
TextureData = 0x1701B502,
UILayoutMagic = 0x92027000,
UILayoutHeader = 0x12027001,
UILayoutData = 0x12027002, //Without header
UILayout = 0x02027003, //All parts combined
MaterialData = 0xB006,
ModelData = 0xB002,
SubmeshInfo = 0xB003, //Or polygon groups?
VertexStartPointers = 0xB004,
ModelTransform = 0xB001, //Matrix4x4. 0x40 in size
MeshBuffers = 0xB005, //vertex and index buffer
BoneData = 0xB102,
BoneHashes = 0xB103,
MaterialName = 0xB333,
MeshIndexTable = 0xB007,
MessageData = 0x7020,
ShaderData = 0xB400,
TextureHeader = 0xB501,
TextureData = 0xB502,
UILayoutMagic = 0x7000,
UILayoutHeader = 0x7001,
UILayoutData = 0x7002, //Without header
UILayout = 0x7003, //All parts combined
}
}

View File

@ -54,7 +54,10 @@ namespace FirstPlugin.LuigisMansion3
entry.ChunkSize = tableReader.ReadUInt32(); //Always 8
entry.ChunkOffset = tableReader.ReadUInt32(); //The chunk offset in the file. Relative to the first chunk position in the file
entry.ChunkType = tableReader.ReadEnum<DataType>(false); //The type of chunk. 0x8701B5 for example for texture info
byte unk = tableReader.ReadByte();
byte chunkFlags = tableReader.ReadByte();
entry.ChunkSubCount = tableReader.ReadByte(); //Uncertain about this. 2 for textures (info + block). Some sections however use large numbers.
Console.WriteLine($"ChunkSubCount {entry.ChunkSubCount} {(entry.ChunkSubCount >> 4)}");
tableReader.ReadByte();
tableReader.ReadByte();
tableReader.ReadByte();
@ -77,7 +80,12 @@ namespace FirstPlugin.LuigisMansion3
{
ChunkSubEntry subEntry = new ChunkSubEntry();
subEntry.ChunkType = tableReader.ReadEnum<SubDataType>(false); //The type of chunk. 0x8701B5 for example for texture info
tableReader.ReadUInt16();
var chunkFlags = tableReader.ReadUInt16();
byte blockFlag = (byte)(chunkFlags >> 12);
//Console.WriteLine($"blockFlag {chunkFlags >> 1} {chunkFlags >> 2} {chunkFlags >> 3} {chunkFlags >> 4} {chunkFlags >> 5} {chunkFlags >> 6} {chunkFlags >> 7} {chunkFlags >> 8}");
Console.WriteLine($"blockFlag {blockFlag} { subEntry.ChunkType}");
subEntry.ChunkSize = tableReader.ReadUInt32();
subEntry.ChunkOffset = tableReader.ReadUInt32();
ChunkSubEntries.Add(subEntry);

View File

@ -29,15 +29,15 @@ namespace FirstPlugin
string HashString = hashStr.TrimEnd();
uint hash = (uint)NLG_Common.StringToHash(HashString);
if (!HashNames.ContainsKey(hash))
HashNames.Add(hash, HashString);
if (!hashNames.ContainsKey(hash))
hashNames.Add(hash, HashString);
string[] hashPaths = HashString.Split('/');
for (int i = 0; i < hashPaths?.Length; i++)
{
hash = (uint)NLG_Common.StringToHash(hashPaths[i]);
if (!HashNames.ContainsKey(hash))
HashNames.Add(hash, HashString);
if (!hashNames.ContainsKey(hash))
hashNames.Add(hash, HashString);
}
}
}