static MDBBody ParseMDB(Stream stream) { byte[] temp4 = new byte[0x4]; if (stream.Read(temp4, 0, 0x4) != 0x4) { Console.WriteLine("Head const read fail"); return(null); } if (!BitConverter.IsLittleEndian) { Array.Reverse(temp4, 0, 0x4); } MDBBody body = new MDBBody(); if ((body.head = BitConverter.ToInt32(temp4, 0)) != 0x08) { Console.WriteLine("Head const read mismatch, value {0:X}", body.head); return(null); } if (stream.Read(temp4, 0, 0x4) != 0x4) { Console.WriteLine("unknown_flag read fail"); return(null); } if (!BitConverter.IsLittleEndian) { Array.Reverse(temp4, 0, 0x4); } body.unknown_flag = BitConverter.ToBoolean(temp4, 0); if (stream.Read(temp4, 0, 0x4) != 0x4) { Console.WriteLine("num texture entries read fail"); return(null); } if (!BitConverter.IsLittleEndian) { Array.Reverse(temp4, 0, 0x4); } body.num_texture_entries = BitConverter.ToInt32(temp4, 0); body.texture_entries = new TextureEntry[body.num_texture_entries]; for (int i = 0; i < body.num_texture_entries; i++) { TextureEntry te = new TextureEntry { texture_name = AstebreedUtil.StreamNullTermStr(stream), file_name = AstebreedUtil.StreamNullTermStr(stream) }; body.texture_entries[i] = te; } if (stream.Read(temp4, 0, 0x4) != 0x4) { Console.WriteLine("num texture names read fail"); return(null); } if (!BitConverter.IsLittleEndian) { Array.Reverse(temp4, 0, 0x4); } body.num_texture_names = BitConverter.ToInt32(temp4, 0); body.texture_names = new string[body.num_texture_names]; for (int i = 0; i < body.num_texture_names; i++) { body.texture_names[i] = AstebreedUtil.StreamNullTermStr(stream); } if (stream.Read(temp4, 0, 0x4) != 0x4) { Console.WriteLine("num mat entries read fail"); return(null); } if (!BitConverter.IsLittleEndian) { Array.Reverse(temp4, 0, 0x4); } body.num_mat_entries = BitConverter.ToInt32(temp4, 0); body.mat_entries = new MatEntry[body.num_mat_entries]; for (int i = 0; i < body.num_mat_entries; i++) { MatEntry me = new MatEntry { mat_name = AstebreedUtil.StreamNullTermStr(stream) }; me._populated = me.mat_name.Length != 0; if (stream.Read(temp4, 0, 0x4) != 0x4) { Console.WriteLine("num mat kvps read fail"); return(null); } if (!BitConverter.IsLittleEndian) { Array.Reverse(temp4, 0, 0x4); } me.num_mat_kvps = BitConverter.ToInt32(temp4, 0); me.mat_kvps = new MatKVP[me.num_mat_kvps]; for (int j = 0; j < me.num_mat_kvps; j++) { MatKVP kvp = new MatKVP(); kvp.key = AstebreedUtil.StreamNullTermStr(stream); if (stream.Read(temp4, 0, 0x4) != 0x4) { Console.WriteLine("kvp word count read fail"); return(null); } if (!BitConverter.IsLittleEndian) { Array.Reverse(temp4, 0, 0x4); } kvp.wordcount = BitConverter.ToInt32(temp4, 0); kvp.value = new byte[kvp.wordcount * 4]; if (stream.Read(kvp.value, 0, kvp.value.Length) != kvp.value.Length) { Console.WriteLine("kvp value read fail"); return(null); } me.mat_kvps[j] = kvp; } if (stream.Read(temp4, 0, 0x4) != 0x4) { Console.WriteLine("num shader tex mappings read fail"); return(null); } if (!BitConverter.IsLittleEndian) { Array.Reverse(temp4, 0, 0x4); } me.num_shader_texture_mapping_entries = BitConverter.ToInt32(temp4, 0); me.shader_texture_mapping_entries = new ShaderTextureMappingEntry[me.num_shader_texture_mapping_entries]; for (int j = 0; j < me.num_shader_texture_mapping_entries; j++) { ShaderTextureMappingEntry se = new ShaderTextureMappingEntry { shader_param_name = AstebreedUtil.StreamNullTermStr(stream), texture_name = AstebreedUtil.StreamNullTermStr(stream) }; me.shader_texture_mapping_entries[j] = se; } me.shader_name = AstebreedUtil.StreamNullTermStr(stream); if (stream.Read(temp4, 0, 0x4) != 0x4) { Console.WriteLine("unknown val 1 read fail"); return(null); } if (!BitConverter.IsLittleEndian) { Array.Reverse(temp4, 0, 0x4); } me.unknown_num_1 = BitConverter.ToInt32(temp4, 0); body.mat_entries[i] = me; } if (stream.Read(temp4, 0, 0x4) != 0x4) { Console.WriteLine("num node entries read fail"); return(null); } if (!BitConverter.IsLittleEndian) { Array.Reverse(temp4, 0, 0x4); } body.num_node_entries = BitConverter.ToInt32(temp4, 0); body.node_entries = new NodeEntry[body.num_node_entries]; for (int i = 0; i < body.num_node_entries; i++) { NodeEntry ne = new NodeEntry(); ne.node_name = AstebreedUtil.StreamNullTermStr(stream); ne.parent_node = AstebreedUtil.StreamNullTermStr(stream); ne.node_type = AstebreedUtil.StreamNullTermStr(stream); ne.data = new byte[68]; if (stream.Read(ne.data, 0, 68) != 68) { Console.WriteLine("node data read fail"); return(null); } body.node_entries[i] = ne; } if (stream.Read(temp4, 0, 0x4) != 0x4) { Console.WriteLine("num meshes read fail"); return(null); } if (!BitConverter.IsLittleEndian) { Array.Reverse(temp4, 0, 0x4); } body.num_meshes = BitConverter.ToInt32(temp4); body.meshes = new Mesh[body.num_meshes]; for (int i = 0; i < body.num_meshes; i++) { Mesh mesh = new Mesh { mesh_name = AstebreedUtil.StreamNullTermStr(stream) }; if (stream.Read(temp4, 0, 0x4) != 0x4) { Console.WriteLine("unknown val 2 read fail"); return(null); } if (!BitConverter.IsLittleEndian) { Array.Reverse(temp4, 0, 0x4); } mesh.unknown_num_2 = BitConverter.ToInt32(temp4, 0); mesh.data = new byte[28]; if (stream.Read(mesh.data, 0, 28) != 28) { Console.WriteLine("mesh data read fail"); return(null); } if (stream.Read(temp4, 0, 0x4) != 0x4) { Console.WriteLine("num node ids read fail"); return(null); } if (!BitConverter.IsLittleEndian) { Array.Reverse(temp4, 0, 0x4); } mesh.num_node_ids = BitConverter.ToInt32(temp4, 0); mesh.node_ids = new NodeID[mesh.num_node_ids]; for (int j = 0; j < mesh.num_node_ids; j++) { NodeID ni = new NodeID(); ni._ = (byte)stream.ReadByte(); ni.node_name = AstebreedUtil.StreamNullTermStr(stream); mesh.node_ids[j] = ni; } if (stream.Read(temp4, 0, 0x4) != 0x4) { Console.WriteLine("num vertices read fail"); return(null); } if (!BitConverter.IsLittleEndian) { Array.Reverse(temp4, 0, 0x4); } mesh.num_vertices = BitConverter.ToInt32(temp4, 0); if (stream.Read(temp4, 0, 0x4) != 0x4) { Console.WriteLine("vertex length read fail"); return(null); } if (!BitConverter.IsLittleEndian) { Array.Reverse(temp4, 0, 0x4); } mesh.vertex_length = BitConverter.ToInt32(temp4, 0); mesh.vertices = new Vertex[mesh.num_vertices]; for (int j = 0; j < mesh.num_vertices; j++) { Vertex v = new Vertex(); v.data = new byte[mesh.vertex_length]; if (stream.Read(v.data, 0, v.data.Length) != v.data.Length) { Console.WriteLine("vertex data read fail"); return(null); } mesh.vertices[j] = v; } body.meshes[i] = mesh; } body.foot = new byte[24]; if (stream.Read(body.foot, 0, body.foot.Length) != body.foot.Length) { Console.WriteLine("body foot read fail"); return(null); } Console.WriteLine("End read @ {0}", stream.Position); return(body); }
static void MDBFmtParseAttempt() { Console.WriteLine("Enter file to parse."); string file = Console.ReadLine(); MDBBody body = ParseMDB(new FileStream(file, FileMode.Open, FileAccess.Read)); if (body == null) { return; } Console.WriteLine("Done parsing."); byte[] temp4 = new byte[4]; foreach (Mesh mesh in body.meshes) { Console.WriteLine("Mesh {0}", mesh.mesh_name); byte[] mins = new byte[mesh.vertex_length]; byte[] maxes = new byte[mesh.vertex_length]; float[] minFloats = new float[mesh.vertex_length / 4]; float[] maxFloats = new float[mesh.vertex_length / 4]; //byte[] temp = new byte[0x14]; for (int i = 0; i < mesh.vertex_length; i++) { byte val = mesh.vertices[0].data[i]; mins[i] = val; maxes[i] = val; } for (int i = 0; i < mesh.vertex_length / 4; i++) { Array.Copy(mesh.vertices[0].data, i * 4, temp4, 0, 4); float val = BitConverter.ToSingle(temp4); minFloats[i] = val; maxFloats[i] = val; } foreach (Vertex v in mesh.vertices) { //AstebreedUtil.PrintHexArray(v.data, 0x20, 0x20, false); /* * AstebreedUtil.JustPrintFloat(v.data, 0x0, true); * Console.Write(' '); * AstebreedUtil.JustPrintFloat(v.data, 0x4, true); * Console.Write(' '); * AstebreedUtil.JustPrintFloat(v.data, 0x8, true); * Console.WriteLine(); */ /*Array.Copy(v.data, 0xC, temp, 0, 0x14); * if (!BitConverter.IsLittleEndian) { * Array.Reverse(temp, 0x0, 0x4); * Array.Reverse(temp, 0x4, 0x4); * } * float f1 = BitConverter.ToSingle(temp, 0x0), f2 = BitConverter.ToSingle(temp, 0x4); * if (f1 < 0.99f) { * AstebreedUtil.PrintHexArray(v.data, 0xC, 0x14, false); * Console.Write("\t"); * Console.Write("{0} {1}", f1, f2); * Console.WriteLine(); * }*/ for (int i = 0; i < mesh.vertex_length; i++) { byte val = v.data[i]; mins[i] = Math.Min(val, mins[i]); maxes[i] = Math.Max(val, maxes[i]); } for (int i = 0; i < mesh.vertex_length / 4; i++) { Array.Copy(v.data, i * 4, temp4, 0, 4); float val = BitConverter.ToSingle(temp4); minFloats[i] = Math.Min(val, minFloats[i]); maxFloats[i] = Math.Max(val, maxFloats[i]); } } Console.WriteLine(" Min | Max"); for (int i = 0; i < mesh.vertex_length; i++) { Console.WriteLine("{0,4:X4} {1,2:X2} {2,2:X2}", i, mins[i], maxes[i]); } Console.WriteLine(" FMin | FMax"); for (int i = 0; i < mesh.vertex_length / 4; i++) { Console.WriteLine("{0} {1} {2}", i, minFloats[i], maxFloats[i]); } /*AstebreedUtil.PrintHexArray(mins, 0, mins.Length, true); * Console.WriteLine(); * AstebreedUtil.PrintHexArray(maxes, 0, maxes.Length, true); * Console.WriteLine();*/ } }