diff options
Diffstat (limited to '')
-rw-r--r-- | NW4RTools/BrresWriter.cs | 367 |
1 files changed, 362 insertions, 5 deletions
diff --git a/NW4RTools/BrresWriter.cs b/NW4RTools/BrresWriter.cs index 5590ab5..1b103fc 100644 --- a/NW4RTools/BrresWriter.cs +++ b/NW4RTools/BrresWriter.cs @@ -31,6 +31,12 @@ namespace NW4RTools { Output.WriteBytes(StringTableData.GetBuffer()); + using (var c = Debug.Push("Offset Map")) { + foreach (var e in OffsetMap) { + Debug.Send("0x{0:X} : {1}", e.Key, e.Value); + } + } + return Output.GetBuffer(); } @@ -38,6 +44,24 @@ namespace NW4RTools { // each written element, and use that to build up a list of offsets. Then, I'll actually write out the data. // This code will also handle building the string table. + #region Offset Data Storage + private Dictionary<Model, int> ModelOffsets; + private Dictionary<ByteCode, int> BytecodeOffsets; + private Dictionary<Node, int> NodeOffsets; + private Dictionary<VertexPosData, int> VtxPosOffsets; + private Dictionary<VertexNrmData, int> VtxNrmOffsets; + private Dictionary<VertexClrData, int> VtxClrOffsets; + private Dictionary<VertexTexCoordData, int> VtxTexCoordOffsets; + private Dictionary<Material, int> MaterialOffsets; + private Dictionary<Shader, int> ShaderOffsets; + private Dictionary<Shape, int> ShapeOffsets; + private Dictionary<List<TexMatPairing>, int> PairingOffsets; + + private Dictionary<Texture, int> TextureOffsets; + private Dictionary<Texture, int> TextureDataOffsets; + + #endregion + #region Offset/String Table Calculation private int CurrentPos; @@ -50,11 +74,13 @@ namespace NW4RTools { // First block, and ResDict CurrentPos += 8; - CurrentPos += GetSizeForResDict(File); + CurrentPos += GetSizeForResDict(File.Count); // Now do each ResDict in the File foreach (object dict in File.Values) { - CurrentPos += GetSizeForResDict(dict as ResDict<object>); + // yay stupid hack + OffsetMap.Add(CurrentPos, "ResDict: " + dict.GetType().GetGenericArguments()[0].ToString()); + CurrentPos += GetSizeForResDict((dict as ICollection).Count); } // OK, so that's done. Process each type @@ -62,7 +88,10 @@ namespace NW4RTools { AddString(name); switch (name) { case "3DModels(NW4R)": - // do that stuff + CalculateModels(); + break; + case "Textures(NW4R)": + CalculateTextures(); break; default: Debug.Send("[[ UNIMPLEMENTED {0} ]]", name); @@ -74,9 +103,337 @@ namespace NW4RTools { CalculateStringTable(); } + #region Model Calculation + private void CalculateModels() { + ModelOffsets = new Dictionary<Model, int>(); + BytecodeOffsets = new Dictionary<ByteCode, int>(); + NodeOffsets = new Dictionary<Node, int>(); + VtxPosOffsets = new Dictionary<VertexPosData, int>(); + VtxNrmOffsets = new Dictionary<VertexNrmData, int>(); + VtxClrOffsets = new Dictionary<VertexClrData, int>(); + VtxTexCoordOffsets = new Dictionary<VertexTexCoordData, int>(); + MaterialOffsets = new Dictionary<Material, int>(); + ShaderOffsets = new Dictionary<Shader, int>(); + ShapeOffsets = new Dictionary<Shape, int>(); + PairingOffsets = new Dictionary<List<TexMatPairing>, int>(); + + + var modelDict = File.GetGroup<Model>("3DModels(NW4R)"); + + foreach (var kv in modelDict) { + AddString(kv.Key); + AlignCalcPos(0x20); + // 0x40? dunno + Model model = kv.Value; + + OffsetMap.Add(CurrentPos, "Model: " + kv.Key); + CurrentPos += 0x4C; + OffsetMap.Add(CurrentPos, "Model Info Struct for: " + kv.Key); + CurrentPos += 0x40; + + OffsetMap.Add(CurrentPos, "Matrix ID to Node ID Data for: " + kv.Key); + CurrentPos += 4 + (model.MatrixIDtoNodeID.Length * 4); + + + OffsetMap.Add(CurrentPos, "ResDict: ByteCode"); + CurrentPos += GetSizeForResDict(model.Bytecode.Count); + OffsetMap.Add(CurrentPos, "ResDict: Nodes"); + CurrentPos += GetSizeForResDict(model.Nodes.Count); + OffsetMap.Add(CurrentPos, "ResDict: VertexPosData"); + CurrentPos += GetSizeForResDict(model.VtxPosData.Count); + + if (model.VtxNrmData.Count > 0) { + OffsetMap.Add(CurrentPos, "ResDict: VertexNrmData"); + CurrentPos += GetSizeForResDict(model.VtxNrmData.Count); + } + + if (model.VtxClrData.Count > 0) { + OffsetMap.Add(CurrentPos, "ResDict: VertexClrData"); + CurrentPos += GetSizeForResDict(model.VtxClrData.Count); + } + + if (model.VtxTexCoordData.Count > 0) { + OffsetMap.Add(CurrentPos, "ResDict: VertexTexCoordData"); + CurrentPos += GetSizeForResDict(model.VtxTexCoordData.Count); + } + + OffsetMap.Add(CurrentPos, "ResDict: Materials"); + CurrentPos += GetSizeForResDict(model.Materials.Count); + OffsetMap.Add(CurrentPos, "ResDict: Shaders"); + CurrentPos += GetSizeForResDict(model.Shaders.Count); + OffsetMap.Add(CurrentPos, "ResDict: Shapes"); + CurrentPos += GetSizeForResDict(model.Shapes.Count); + + if (model.PairingLookupByTexture.Count > 0) { + OffsetMap.Add(CurrentPos, "ResDict: Texture Lookup"); + CurrentPos += GetSizeForResDict(model.PairingLookupByTexture.Count); + } + + // todo: palette lookup, checking if dicts are empty or do not exist + // todo: can dicts even NOT exist? must find this out + + CalculatePairings(model, model.PairingLookupByTexture); + CalculateBytecode(model); + CalculateNodes(model); + CalculateMaterials(model); + CalculateShaders(model); + CalculateShapes(model); + CalculateVtxPosData(model); + CalculateVtxNrmData(model); + CalculateVtxClrData(model); + CalculateVtxTexCoordData(model); + } + } + + private void CalculatePairings(Model m, ResDict<List<TexMatPairing>> dict) { + foreach (var kv in dict) { + OffsetMap.Add(CurrentPos, "Texture/Material Pairing List for: " + kv.Key); + PairingOffsets.Add(kv.Value, CurrentPos); + + CurrentPos += 4 + (kv.Value.Count * 8); + } + } + + private void CalculateBytecode(Model m) { + foreach (var kv in m.Bytecode) { + AddString(kv.Key); + ByteCode bc = kv.Value; + + OffsetMap.Add(CurrentPos, "ByteCode: " + kv.Key); + BytecodeOffsets.Add(kv.Value, CurrentPos); + + foreach (var insn in bc.Instructions) { + switch (insn.GetOp()) { + case ByteCode.OpType.None: + CurrentPos += 1; + break; + case ByteCode.OpType.Done: + CurrentPos += 1; + break; + case ByteCode.OpType.AssignNodeToParentMtx: + CurrentPos += 5; + break; + case ByteCode.OpType.BlendMatrices: + CurrentPos += 4 + (6 * (insn as ByteCode.BlendMatricesInstruction).BlendedMatrices.Length); + break; + case ByteCode.OpType.DrawShape: + CurrentPos += 8; + break; + case ByteCode.OpType.AssignMtxToNode: + CurrentPos += 5; + break; + } + } + } + + AlignCalcPos(4); // should be per-bytecode maybe? + } + + private void CalculateNodes(Model m) { + foreach (var kv in m.Nodes) { + AddString(kv.Key); + + OffsetMap.Add(CurrentPos, "Node: " + kv.Key); + NodeOffsets.Add(kv.Value, CurrentPos); + + CurrentPos += 0xD0; + } + } + + private void CalculateMaterials(Model m) { + foreach (var kv in m.Materials) { + AddString(kv.Key); + + OffsetMap.Add(CurrentPos, "Material: " + kv.Key); + MaterialOffsets.Add(kv.Value, CurrentPos); + + // Base material struct + CurrentPos += 0x14; + + // ResGenMode + CurrentPos += 8; + + // ResMatMode + CurrentPos += 0xC; + + // other stuff + CurrentPos += 0x18; + + // ResTexObj + CurrentPos += 0x104; + + // ResTlutObj + CurrentPos += 0x64; + + // ResTexSrt + CurrentPos += 8 + (0x14 * 8) + (0x34 * 8); + + // ResMatChan + CurrentPos += 0x28; + + // Texture Infos + if (kv.Value.TextureInfos.Count > 0) + OffsetMap.Add(CurrentPos, "Material Texture Infos: " + kv.Key); + + CurrentPos += (kv.Value.TextureInfos.Count * 0x34); + + // Display Lists + AlignCalcPos(0x20); + OffsetMap.Add(CurrentPos, "Material Display Lists: " + kv.Key); + CurrentPos += 0x20 + 0x80 + 0x40 + 0xA0; + } + } + + private void CalculateShaders(Model m) { + foreach (var kv in m.Shaders) { + AddString(kv.Key); + + OffsetMap.Add(CurrentPos, "Shader: " + kv.Key); + ShaderOffsets.Add(kv.Value, CurrentPos); + + CurrentPos += 0x200; + } + } + + private void CalculateShapes(Model m) { + foreach (var kv in m.Shapes) { + AddString(kv.Key); + + OffsetMap.Add(CurrentPos, "Shape: " + kv.Key); + ShapeOffsets.Add(kv.Value, CurrentPos); + + CurrentPos += 0x68; + + AlignCalcPos(0x20); + + OffsetMap.Add(CurrentPos, "Shape DL 1: " + kv.Key); + CurrentPos += (int)kv.Value.DLBufferSize1; + AlignCalcPos(0x20); + + OffsetMap.Add(CurrentPos, "Shape DL 2: " + kv.Key); + CurrentPos += (int)kv.Value.DLBufferSize2; + AlignCalcPos(0x20); + } + } + + private void CalculateVtxPosData(Model m) { + foreach (var kv in m.VtxPosData) { + AddString(kv.Key); + + OffsetMap.Add(CurrentPos, "VertexPosData: " + kv.Key); + VtxPosOffsets.Add(kv.Value, CurrentPos); + + // Main data + CurrentPos += 0x20; + + // Minimum/maximum VEC3 (specific to VtxPosData) + CurrentPos += 0x18; + + AlignCalcPos(0x20); + OffsetMap.Add(CurrentPos, "Data: " + kv.Key); + CurrentPos += kv.Value.EntryCount * kv.Value.EntrySize; + AlignCalcPos(0x20); + } + } + + private void CalculateVtxNrmData(Model m) { + foreach (var kv in m.VtxNrmData) { + AddString(kv.Key); + + OffsetMap.Add(CurrentPos, "VertexNrmData: " + kv.Key); + VtxNrmOffsets.Add(kv.Value, CurrentPos); + + // Main data + CurrentPos += 0x20; + + AlignCalcPos(0x20); + OffsetMap.Add(CurrentPos, "Data: " + kv.Key); + CurrentPos += kv.Value.EntryCount * kv.Value.EntrySize; + AlignCalcPos(0x20); + } + } + + private void CalculateVtxClrData(Model m) { + foreach (var kv in m.VtxClrData) { + AddString(kv.Key); + + OffsetMap.Add(CurrentPos, "VertexClrData: " + kv.Key); + VtxClrOffsets.Add(kv.Value, CurrentPos); + + // Main data + CurrentPos += 0x20; + + AlignCalcPos(0x20); + OffsetMap.Add(CurrentPos, "Data: " + kv.Key); + CurrentPos += kv.Value.EntryCount * kv.Value.EntrySize; + AlignCalcPos(0x20); + } + } + + private void CalculateVtxTexCoordData(Model m) { + foreach (var kv in m.VtxTexCoordData) { + AddString(kv.Key); + + OffsetMap.Add(CurrentPos, "VertexTexCoordData: " + kv.Key); + VtxTexCoordOffsets.Add(kv.Value, CurrentPos); + + // Main data + CurrentPos += 0x20; + + // Minimum/maximum VEC2 (specific to VtxTexCoordData) + CurrentPos += 0x10; + + AlignCalcPos(0x20); + OffsetMap.Add(CurrentPos, "Data: " + kv.Key); + CurrentPos += kv.Value.EntryCount * kv.Value.EntrySize; + AlignCalcPos(0x20); + } + } + #endregion + + #region Texture Calculation + private void CalculateTextures() { + TextureOffsets = new Dictionary<Texture, int>(); + TextureDataOffsets = new Dictionary<Texture, int>(); + + + var textureDict = File.GetGroup<Texture>("Textures(NW4R)"); + + foreach (var kv in textureDict) { + AddString(kv.Key); + AlignCalcPos(0x20); + Texture texture = kv.Value; + + Debug.Send("Current: {0}", kv.Key); + + + OffsetMap.Add(CurrentPos, "Texture: " + kv.Key); + TextureOffsets.Add(kv.Value, CurrentPos); + + CurrentPos += 0x30; + AlignCalcPos(0x20); + + + OffsetMap.Add(CurrentPos, "Texture Data for: " + kv.Key); + TextureDataOffsets.Add(kv.Value, CurrentPos); + + CurrentPos += texture.GetDataSize(); + AlignCalcPos(0x20); + } + } + #endregion + + + + private void AlignCalcPos(int alignTo) { + if ((CurrentPos & (alignTo - 1)) == 0) + return; + + CurrentPos += (alignTo - (CurrentPos & (alignTo - 1))); + } - private int GetSizeForResDict(ResDict<object> dict) { - return 8 + ((dict.Count + 1) * 0x10); + private int GetSizeForResDict(int entryCount) { + return 8 + ((entryCount + 1) * 0x10); } #endregion |