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:
parent
71c7776f37
commit
ddfdbdc724
@ -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);
|
||||
|
@ -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()
|
||||
{
|
||||
@ -83,9 +84,11 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
|
||||
DrawableContainer.Name = FileName;
|
||||
Renderer = new LM2_Renderer();
|
||||
DrawableContainer.Drawables.Add(Renderer);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user