summaryrefslogtreecommitdiff
path: root/NW4RTools/BrresWriter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'NW4RTools/BrresWriter.cs')
-rw-r--r--NW4RTools/BrresWriter.cs367
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