public void Load(string continent) { var wdlPath = string.Format(@"World\Maps\{0}\{0}.wdl", continent); using (var strm = FileManager.Instance.Provider.OpenFile(wdlPath)) { if (strm == null) return; var reader = new BinaryReader(strm); var signature = 0u; while (signature != 0x4D414F46) { signature = reader.ReadUInt32(); var size = reader.ReadInt32(); if (signature == 0x4D414F46) break; reader.ReadBytes(size); } var tileOffsets = reader.ReadArray<int>(4096); for(var i = 0; i < 4096; ++i) { if (tileOffsets[i] <= 0) continue; strm.Position = tileOffsets[i] + 8; mEntries.Add(i, reader.Read<MareEntry>()); } } }
private static ParameterMetadata ReadParameterList(BinaryReader reader) { return new ParameterMetadata(null, DataType.Object, reader.ReadArray(r => { var type = (DataType) r.ReadByte(); var name = r.ReadUtfString(); return new ParameterMetadata(name, type); })); }
/// <summary> /// Reads a <see cref="Portal"/> /// </summary> /// <param name="br">The <see cref="BinaryReader"/> used to read the <see cref="Portal"/></param> /// <returns>A <see cref="Portal"/></returns> public static Portal Read(BinaryReader br) { return new Portal(br.ReadUInt16(), Vertex.Read16(br), br.ReadArray(4, () => Vertex.Read16(br))); }
/// <summary> /// Reads a <see cref="ObjectTexture"/> /// </summary> /// <param name="br">The <see cref="BinaryReader"/> used to read the <see cref="ObjectTexture"/></param> /// <param name="ver">The game version</param> /// <returns>A <see cref="ObjectTexture"/></returns> public static ObjectTexture Read(BinaryReader br, Engine ver = Engine.Unknown) { var ret = new ObjectTexture(); ret.TransparencyFlags = (BlendingMode) br.ReadUInt16(); ret.TileAndFlag = br.ReadUInt16(); if (ver >= Engine.TR4) { if ((ret.TileAndFlag & 0x7FFF) > 128) Cerr.Write("ObjectTexture.Read[" + ver + "]: TileAndFlag > 128"); ret.NewFlags = br.ReadUInt16(); } else { if (ret.TileAndFlag > 64) Cerr.Write("ObjectTexture.Read[" + ver + "]: TileAndFlag > 64"); if ((ret.TileAndFlag & (1 << 15)) != 0) Cerr.Write("ObjectTexture.Read[" + ver + "]: TileAndFlag has top bit set"); } ret.Vertices = br.ReadArray(4, () => ObjectTextureVertex.Read(br, ver)); if (ver >= Engine.TR4) { ret.OriginalU = br.ReadUInt32(); ret.OriginalV = br.ReadUInt32(); ret.Width = br.ReadUInt32(); ret.Height = br.ReadUInt32(); } if (ver == Engine.TR5) { var filler = br.ReadUInt16(); if (filler != 0) Cerr.Write("ObjectTexture.Read[TR5]: filler: Expected 0, Found 0x" + filler.ToString("X4")); } return ret; }
public static Room Read(BinaryReader br, Engine ver = Engine.Unknown) { var r = new Room(); if (ver == Engine.TR5) { var xela = br.ReadUInt32(); if (xela != 0x414C4558) Cerr.Write("Room.Read[TR5]: 'XELA' header: Expected 0x414C4558, Found 0x" + xela.ToString("X8")); var roomDataSize = br.ReadUInt32(); var pos = br.BaseStream.Position; var endPos = pos + roomDataSize; r.Intensity1 = 32767; r.Intensity2 = 32767; r.LightMode = 0; var separator1 = br.ReadUInt32(); if (separator1 != 0xCDCDCDCD) Cerr.Write("Room.Read[TR5]: separator1: Expected 0xCDCDCDCD, Found 0x" + separator1.ToString("X8")); var portalOffset = br.ReadInt32(); var sectorDataOffset = br.ReadUInt32(); var separator2 = br.ReadUInt32(); if (separator2 != 0 && separator2 != 0xCDCDCDCD) Cerr.Write("Room.Read[TR5]: separator2: Expected 0 or 0xCDCDCDCD, Found 0x" + separator2.ToString("X8")); var staticMeshesOffset = br.ReadUInt32(); r.Offset = new Vertex(br.ReadInt32(), br.ReadUInt32(), -br.ReadInt32()); r.Y_Bottom = -br.ReadInt32(); r.Y_Top = -br.ReadInt32(); r.Num_Z_Sectors = br.ReadUInt16(); r.Num_X_Sectors = br.ReadUInt16(); var lc = FloatColor.Read(br); r.LightColor = new FloatColor(lc.B, lc.G, lc.R, 1.0f); // OpenTomb ignores the alpha channel (but not vt todo?), also B & R are inverted var numLights = br.ReadUInt16(); if (numLights > 512) Cerr.Write("Room.Read[TR5]: numLights > 512"); var numStaticMeshes = br.ReadUInt16(); if (numStaticMeshes > 512) Cerr.Write("Room.Read[TR5]: numStaticMeshes > 512"); r.ReverbInfo = (ReverbInfo) br.ReadByte(); r.AlternateGroup = (sbyte) br.ReadByte(); r.WaterScheme = (byte) br.ReadUInt16(); var filler1 = br.ReadUInt32(); if (filler1 != 0x00007FFF) Cerr.Write("Room.Read[TR5]: filler1: Expected 0x00007FFF, Found 0x" + filler1.ToString("X8")); var filler2 = br.ReadUInt32(); if (filler2 != 0x00007FFF) Cerr.Write("Room.Read[TR5]: filler2: Expected 0x00007FFF, Found 0x" + filler2.ToString("X8")); var separator4 = br.ReadUInt32(); if (separator4 != 0xCDCDCDCD) Cerr.Write("Room.Read[TR5]: separator4: Expected 0xCDCDCDCD, Found 0x" + separator4.ToString("X8")); var separator5 = br.ReadUInt32(); if (separator5 != 0xCDCDCDCD) Cerr.Write("Room.Read[TR5]: separator5: Expected 0xCDCDCDCD, Found 0x" + separator5.ToString("X8")); var filler3 = br.ReadUInt32(); if (filler3 != 0xFFFFFFFF) Cerr.Write("Room.Read[TR5]: filler3: Expected 0xFFFFFFFF, Found 0x" + filler3.ToString("X8")); r.AlternateRoom = br.ReadInt16(); // todo weird TRosettaStone says it's an ushort r.Flags = br.ReadUInt16(); r.Unknown_R1 = br.ReadUInt32(); r.Unknown_R2 = br.ReadUInt32(); r.Unknown_R3 = br.ReadUInt32(); var separator7 = br.ReadUInt32(); if (separator7 != 0 && separator7 != 0xCDCDCDCD) Cerr.Write("Room.Read[TR5]: separator7: Expected 0 or 0xCDCDCDCD, Found 0x" + separator7.ToString("X8")); r.Unknown_R4a = br.ReadUInt16(); r.Unknown_R4b = br.ReadUInt16(); r.Room_X = br.ReadSingle(); r.Unknown_R5 = br.ReadUInt32(); r.Room_Z = -br.ReadSingle(); var separator8 = br.ReadUInt32(); if (separator8 != 0xCDCDCDCD) Cerr.Write("Room.Read[TR5]: separator8: Expected 0xCDCDCDCD, Found 0x" + separator8.ToString("X8")); var separator9 = br.ReadUInt32(); if (separator9 != 0xCDCDCDCD) Cerr.Write("Room.Read[TR5]: separator9: Expected 0xCDCDCDCD, Found 0x" + separator9.ToString("X8")); var separator10 = br.ReadUInt32(); if (separator10 != 0xCDCDCDCD) Cerr.Write("Room.Read[TR5]: separator10: Expected 0xCDCDCDCD, Found 0x" + separator10.ToString("X8")); var separator11 = br.ReadUInt32(); if (separator11 != 0xCDCDCDCD) Cerr.Write("Room.Read[TR5]: separator11: Expected 0xCDCDCDCD, Found 0x" + separator11.ToString("X8")); var separator12 = br.ReadUInt32(); if (separator12 != 0 && separator12 != 0xCDCDCDCD) Cerr.Write("Room.Read[TR5]: separator12: Expected 0 or 0xCDCDCDCD, Found 0x" + separator12.ToString("X8")); var separator13 = br.ReadUInt32(); if (separator13 != 0xCDCDCDCD) Cerr.Write("Room.Read[TR5]: separator13: Expected 0xCDCDCDCD, Found 0x" + separator13.ToString("X8")); var numTriangles = br.ReadUInt32(); if (numTriangles == 0xCDCDCDCD) numTriangles = 0; if (numTriangles > 512) Cerr.Write("Room.Read[TR5]: numTriangles > 512"); r.Triangles = new Triangle[numTriangles]; var numRectangles = br.ReadUInt32(); if (numRectangles == 0xCDCDCDCD) numRectangles = 0; if (numRectangles > 1024) Cerr.Write("Room.Read[TR5]: numRectangles > 1024"); r.Rectangles = new QuadFace[numRectangles]; var separator14 = br.ReadUInt32(); if (separator14 != 0) Cerr.Write("Room.Read[TR5]: separator14: Expected 0, Found 0x" + separator14.ToString("X8")); var lightSize = br.ReadUInt32(); var numLights2 = br.ReadUInt32(); if (numLights2 != numLights) throw new ArgumentException("Room.Read[TR5]: Room.numLights2 != Room.numLights", nameof(numLights2)); r.Unknown_R6 = br.ReadUInt32(); r.Room_Y_Top = -br.ReadSingle(); r.Room_Y_Bottom = -br.ReadSingle(); var numLayers = br.ReadUInt32(); var layerOffset = br.ReadUInt32(); var verticesOffset = br.ReadUInt32(); var polyOffset = br.ReadUInt32(); var polyOffset2 = br.ReadUInt32(); if (polyOffset != polyOffset2) throw new ArgumentException("Room.Read[TR5]: Room.polyOffset2 != Room.polyOffset", nameof(polyOffset2)); var verticesSize = br.ReadUInt32(); if (verticesSize % 28 != 0) throw new ArgumentException( "Room.Read[TR5]: verticesSize has wrong value: " + verticesSize, nameof(verticesSize)); var separator15 = br.ReadUInt32(); if (separator15 != 0xCDCDCDCD) Cerr.Write("Room.Read[TR5]: separator15: Expected 0xCDCDCDCD, Found 0x" + separator15.ToString("X8")); var separator16 = br.ReadUInt32(); if (separator16 != 0xCDCDCDCD) Cerr.Write("Room.Read[TR5]: separator16: Expected 0xCDCDCDCD, Found 0x" + separator16.ToString("X8")); var separator17 = br.ReadUInt32(); if (separator17 != 0xCDCDCDCD) Cerr.Write("Room.Read[TR5]: separator17: Expected 0xCDCDCDCD, Found 0x" + separator17.ToString("X8")); var separator18 = br.ReadUInt32(); if (separator18 != 0xCDCDCDCD) Cerr.Write("Room.Read[TR5]: separator18: Expected 0xCDCDCDCD, Found 0x" + separator18.ToString("X8")); r.Lights = br.ReadArray(numLights, () => Light.Read(br, Engine.TR5)); br.BaseStream.Position = pos + 208 + sectorDataOffset; r.Sectors = br.ReadArray(r.Num_Z_Sectors * r.Num_X_Sectors, () => Sector.Read(br)); var numPortals = br.ReadInt16(); r.Portals = br.ReadArray(numPortals, () => Portal.Read(br)); br.BaseStream.Position = pos + 208 + staticMeshesOffset; r.StaticMeshes = br.ReadArray(numStaticMeshes, () => RoomStaticMesh.Read(br, Engine.TR4)); br.BaseStream.Position = pos + 208 + layerOffset; r.Layers = br.ReadArray(numLayers, () => Layer.Read(br)); br.BaseStream.Position = pos + 208 + polyOffset; { ushort vertexIndex = 0; uint rectangleIndex = 0; uint triangleIndex = 0; foreach (var layer in r.Layers) { for (var j = 0; j < layer.NumRectangles; j++) { r.Rectangles[rectangleIndex] = QuadFace.Read(br, Engine.TR4); r.Rectangles[rectangleIndex].Vertices[0] += vertexIndex; r.Rectangles[rectangleIndex].Vertices[1] += vertexIndex; r.Rectangles[rectangleIndex].Vertices[2] += vertexIndex; r.Rectangles[rectangleIndex].Vertices[3] += vertexIndex; rectangleIndex++; } for (var j = 0; j < layer.NumTriangles; j++) { r.Triangles[triangleIndex] = Triangle.Read(br, Engine.TR4); r.Triangles[triangleIndex].Vertices[0] += vertexIndex; r.Triangles[triangleIndex].Vertices[1] += vertexIndex; r.Triangles[triangleIndex].Vertices[2] += vertexIndex; triangleIndex++; } vertexIndex += layer.NumVertices; } } br.BaseStream.Position = pos + 208 + verticesOffset; { uint vertexIndex = 0; r.Vertices = new RoomVertex[verticesSize / 28]; foreach (var layer in r.Layers) { for (var j = 0; j < layer.NumVertices; j++) { r.Vertices[vertexIndex++] = RoomVertex.Read(br, Engine.TR5); } } } br.BaseStream.Position = endPos; } else { r.Offset = new Vertex(br.ReadInt32(), 0, -br.ReadInt32()); r.Y_Bottom = -br.ReadInt32(); r.Y_Top = -br.ReadInt32(); var numDataWords = br.ReadUInt32(); var pos = br.BaseStream.Position; var numVertices = br.ReadUInt16(); r.Vertices = br.ReadArray(numVertices, () => RoomVertex.Read(br, ver)); var numRectangles = br.ReadUInt16(); r.Rectangles = br.ReadArray(numRectangles, () => QuadFace.Read(br, Engine.TR1)); var numTriangles = br.ReadUInt16(); r.Triangles = br.ReadArray(numTriangles, () => Triangle.Read(br, Engine.TR1)); var numSprites = br.ReadUInt16(); r.Sprites = br.ReadArray(numSprites, () => Sprite.Read(br)); br.BaseStream.Position = pos + numDataWords * 2; r.Portals = br.ReadArray(br.ReadUInt16(), () => Portal.Read(br)); r.Num_Z_Sectors = br.ReadUInt16(); r.Num_X_Sectors = br.ReadUInt16(); r.Sectors = br.ReadArray(r.Num_Z_Sectors * r.Num_X_Sectors, () => Sector.Read(br)); if (ver == Engine.TR4) { //r.RoomColor = ByteColor.ReadARGB(br); todo } if (ver < Engine.TR3) { r.Intensity1 = (short) ((8191 - br.ReadInt16()) << 2); r.Intensity2 = ver < Engine.TR2 ? r.Intensity1 : (short) ((8191 - br.ReadInt16()) << 2); } else { r.Intensity1 = br.ReadInt16(); r.Intensity2 = br.ReadInt16(); } if (ver == Engine.TR2) { r.LightMode = br.ReadInt16(); } r.Lights = br.ReadArray(br.ReadUInt16(), () => Light.Read(br, ver)); r.StaticMeshes = br.ReadArray(br.ReadUInt16(), () => RoomStaticMesh.Read(br, ver)); r.AlternateRoom = br.ReadInt16(); r.Flags = br.ReadUInt16(); // todo trosettastone says it's an int16 (signed) if (ver == Engine.TR1) { r.ReverbInfo = ReverbInfo.MediumRoom; var c = r.Intensity1 / 32767.0f; r.LightColor = new FloatColor(c, c, c); } else if (ver == Engine.TR2) { r.ReverbInfo = r.Flags.HasFlagEx(RoomFlags.WindBlowPonytail) ? ReverbInfo.Outside : ReverbInfo.MediumRoom; var c = r.Intensity1 / 16384.0f; r.LightColor = new FloatColor(c, c, c); } else if (ver == Engine.TR3) { if (r.Flags.HasFlagEx(RoomFlags.Quicksand)) { // Move quicksand flag to another bit to avoid confusion with NL flag. r.Flags = (ushort) ((r.Flags | 0x0002) ^ 0x0080); } r.WaterScheme = br.ReadByte(); r.ReverbInfo = (ReverbInfo) br.ReadByte(); r.Filler = br.ReadByte(); var c = r.Intensity1 / 65534.0f; r.LightColor = new FloatColor(c, c, c); } else if (ver == Engine.TR4) { r.WaterScheme = br.ReadByte(); r.ReverbInfo = (ReverbInfo) br.ReadByte(); r.AlternateGroup = br.ReadSByte(); // todo Trosettastone says it's an unsigned byte r.LightColor = new FloatColor( (r.Intensity2 & 0x00FF) / 255.0f, ((r.Intensity1 & 0xFF00) >> 8) / 255.0f, (r.Intensity1 & 0x00FF) / 255.0f, ((r.Intensity2 & 0xFF00) >> 8) / 255.0f); } } return r; }
private void LoadVertices(BinaryReader reader, int size) { var numVertices = size / SizeCache<Vector3>.Size; mPositions = reader.ReadArray<Vector3>(numVertices); for(var i = 0; i < mPositions.Length; ++i) { mPositions[i] = new Vector3(mPositions[i].X, -mPositions[i].Y, mPositions[i].Z); } }
private void LoadTexCoords(BinaryReader reader, int size) { if (mTexCoordsLoaded && mTexCoords.Length > 0) return; mTexCoordsLoaded = true; var numTexCoords = size / SizeCache<Vector2>.Size; mTexCoords = reader.ReadArray<Vector2>(numTexCoords); }
private void LoadIndices(BinaryReader reader, int size) { var numIndices = size / 2; mIndices = reader.ReadArray<ushort>(numIndices).ToList(); Indices = mIndices.AsReadOnly(); }
private void LoadMcvt(BinaryReader reader) { var heights = reader.ReadArray<float>(145); var posx = Metrics.MapMidPoint - mHeader.Position.Y; var posy = Metrics.MapMidPoint - mHeader.Position.X; var posz = mHeader.Position.Z; var counter = 0; var minPos = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); var maxPos = new Vector3(float.MinValue, float.MinValue, float.MinValue); for (var i = 0; i < 17; ++i) { for (var j = 0; j < (((i % 2) != 0) ? 8 : 9); ++j) { var height = posz + heights[counter]; var x = posx + j * Metrics.UnitSize; if ((i % 2) != 0) x += 0.5f * Metrics.UnitSize; var y = posy + i * Metrics.UnitSize * 0.5f; Vertices[counter].Position = new Vector3(x, y, height); if (height < minPos.Z) minPos.Z = height; if (height > maxPos.Z) maxPos.Z = height; if (x < minPos.X) minPos.X = x; if (x > maxPos.X) maxPos.X = x; if (y < minPos.Y) minPos.Y = y; if (y > maxPos.Y) maxPos.Y = y; Vertices[counter].TexCoordAlpha = new Vector2(j / 8.0f + ((i % 2) != 0 ? (0.5f / 8.0f) : 0), i / 16.0f); Vertices[counter].TexCoord = new Vector2(j + ((i % 2) != 0 ? 0.5f : 0.0f), i * 0.5f); ++counter; } } mMinHeight = minPos.Z; mMaxHeight = maxPos.Z; BoundingBox = new BoundingBox(minPos, maxPos); mMidPoint = minPos + (maxPos - minPos) / 2.0f; }
private void LoadRootFile() { var encKeyStr = mBuildConfig["root"].FirstOrDefault(); if (encKeyStr == null) throw new InvalidOperationException("Build config is missing root key"); var encodingKey = encKeyStr.HexToBytes().ToArray(); EncodingEntry encEntry; if (mEncodingData.TryGetValue(new Binary(encodingKey), out encEntry) == false || encEntry.Keys.Length == 0) throw new InvalidOperationException("Unable to find encoding value for root file"); IndexEntry entry; if (mIndexData.TryGetValue(new Binary(encEntry.Keys[0].ToArray().Take(9).ToArray()), out entry) == false) throw new InvalidOperationException("Unable to locate root file in index table"); var strm = GetDataStream(entry.Index); using (var fileReader = new BinaryReader(strm.Stream, Encoding.UTF8, true)) { fileReader.BaseStream.Position = entry.Offset + 30; using (var reader = new BinaryReader(BlteGetData(fileReader, entry.Size - 30))) { try { while(true) { var count = reader.ReadInt32(); reader.ReadBytes(8 + count * 4); var entries = reader.ReadArray<RootEntryFile>(count); foreach (var e in entries) { var b = e.md5; var rootEntry = new RootEntry { Hash = e.hash, Md5 = new Binary(new[] { b.v1, b.v2, b.v3, b.v4, b.v5, b.v6, b.v7, b.v8, b.v9, b.v10, b.v11, b.v12, b.v13, b.v14, b.v15, b.v16 }) }; if (mRootData.ContainsKey(e.hash)) mRootData[e.hash].Add(rootEntry); else mRootData.Add(e.hash, new List<RootEntry>(20) {rootEntry}); } } } catch(EndOfStreamException) { } } } }
private void LoadIndexFile(string file) { using (var strm = File.OpenRead(file)) { using (var reader = new BinaryReader(strm)) { var h2Len = reader.ReadInt32(); reader.ReadInt32(); var padded = (8 + h2Len + 0x0F) & 0xFFFFFFF0; strm.Position = padded; var dataLen = reader.ReadInt32(); reader.ReadInt32(); var numBlocks = dataLen / 18; var blocks = reader.ReadArray<IndexFileEntry>(numBlocks); foreach(var block in blocks) { var key = new Binary(new[] { block.key.v1, block.key.v2, block.key.v3, block.key.v4, block.key.v5, block.key.v6, block.key.v7, block.key.v8, block.key.v9 }); if (mIndexData.ContainsKey(key)) continue; var idxLowBe = block.indexLowBE; var idxHigh = block.indexHigh; var idxLow = idxLowBe >> 24; idxLow |= ((idxLowBe >> 16) & 0xFF) << 8; idxLow |= ((idxLowBe >> 8) & 0xFF) << 16; idxLow |= ((idxLowBe >> 0) & 0xFF) << 24; mIndexData.Add(key, new IndexEntry() { Index = (((byte)(idxHigh << 2)) | ((idxLow & 0xC0000000) >> 30)), Offset = (idxLow & 0x3FFFFFFF), Size = block.size }); } } } }
private void InitWmoModels(BinaryReader reader) { if (SeekChunk(reader, 0x4D574D4F) == false) return; var size = reader.ReadInt32(); var bytes = reader.ReadBytes(size); var modelNameLookup = new Dictionary<int, string>(); var curOffset = 0; var curBytes = new List<byte>(); for (var i = 0; i < bytes.Length; ++i) { if (bytes[i] == 0) { if (curBytes.Count > 0) modelNameLookup.Add(curOffset, Encoding.ASCII.GetString(curBytes.ToArray())); curOffset = i + 1; curBytes.Clear(); } else curBytes.Add(bytes[i]); } if (SeekChunk(reader, 0x4D574944) == false) return; size = reader.ReadInt32(); var modelNameIds = reader.ReadArray<int>(size / 4); if (SeekChunk(reader, 0x4D4F4446) == false) return; size = reader.ReadInt32(); var modf = reader.ReadArray<Modf>(size / SizeCache<Modf>.Size); foreach (var entry in modf) { if (entry.Mwid >= modelNameIds.Length) continue; var nameId = modelNameIds[entry.Mwid]; string modelName; if (modelNameLookup.TryGetValue(nameId, out modelName) == false) continue; var position = new Vector3(entry.Position.X, entry.Position.Z, entry.Position.Y); var rotation = new Vector3(entry.Rotation.Z, -entry.Rotation.X, 90 - entry.Rotation.Y); WorldFrame.Instance.WmoManager.AddInstance(modelName, entry.UniqueId, position, rotation); mWmoInstances.Add(new LoadedModel(modelName, entry.UniqueId)); } }
private void InitM2Models(BinaryReader reader) { if (SeekChunk(reader, 0x4D4D4458) == false) return; var size = reader.ReadInt32(); var bytes = reader.ReadBytes(size); var fullString = Encoding.ASCII.GetString(bytes); var modelNames = fullString.Split('\0'); var modelNameLookup = new Dictionary<int, string>(); var curOffset = 0; foreach (var name in modelNames) { modelNameLookup.Add(curOffset, name); curOffset += name.Length + 1; } if (SeekChunk(reader, 0x4D4D4944) == false) return; size = reader.ReadInt32(); var modelNameIds = reader.ReadArray<int>(size / 4); if (SeekChunk(reader, 0x4D444446) == false) return; size = reader.ReadInt32(); mDoodadDefs = reader.ReadArray<Mddf>(size / SizeCache<Mddf>.Size); var index = -1; foreach (var entry in mDoodadDefs) { ++index; if (entry.Mmid >= modelNameIds.Length) continue; var nameId = modelNameIds[entry.Mmid]; string modelName; if (modelNameLookup.TryGetValue(nameId, out modelName) == false) continue; var position = new Vector3(entry.Position.X, entry.Position.Z, entry.Position.Y); var rotation = new Vector3(-entry.Rotation.X, -entry.Rotation.Z, 90 - entry.Rotation.Y); var scale = entry.Scale / 1024.0f; var instance = WorldFrame.Instance.M2Manager.AddInstance(modelName, entry.UniqueId, position, rotation, new Vector3(scale)); DoodadInstances.Add(new M2Instance { Hash = modelName.ToUpperInvariant().GetHashCode(), Uuid = entry.UniqueId, BoundingBox = (instance != null ? instance.BoundingBox : new BoundingBox(new Vector3(float.MaxValue), new Vector3(float.MinValue))), RenderInstance = instance, MddfIndex = index }); } }
private void InitChunkInfos(BinaryReader reader) { if(SeekChunk(reader, 0x4D43494E)) mChunkOffsets = reader.ReadArray<Mcin>(256); reader.BaseStream.Position = 0; for (var i = 0; i < 256; ++i) { if (SeekNextMcnk(reader) == false) throw new InvalidOperationException("Area is missing chunks"); mChunkInfos.Add(new ChunkInfo { Offset = (int)(reader.BaseStream.Position), Size = reader.ReadInt32() }); reader.ReadBytes(mChunkInfos.Last().Size); } }
private static void ParseUncompressedLayer(int layer, ref uint[] palette, BinaryReader baseReader, ref BlpHeader header, TextureLoadInfo loadInfo) { if (header.Compression == 3) return; if (palette.Length == 0) { baseReader.BaseStream.Position = SizeCache<BlpHeader>.Size; palette = baseReader.ReadArray<uint>(256); } var w = Math.Max(header.Width >> layer, 1); var h = Math.Max(header.Height >> layer, 1); var indices = loadInfo.Layers[layer]; var colors = new byte[w * h * 4]; if (header.AlphaDepth == 8) DecompPaletteFastPath(ref palette, ref indices, ref colors); else DecompPaletteA8R8G8B8(header.AlphaDepth, ref palette, ref indices, ref colors); loadInfo.Layers[layer] = colors; }
public static TOMBPCFile Parse(BinaryReader br, bool psx = false) { try { var lvl = new TOMBPCFile(); lvl.IsPSX = psx; lvl.GameVersion = (TOMBPCGameVersion) br.ReadUInt32(); lvl.CopyrightInfo = br.ParseString(256); var gameflowSize = br.ReadUInt16(); if (gameflowSize != 128) { throw new ArgumentOutOfRangeException("gameflowSize [UInt16]", gameflowSize, "Should be 128"); } #region First options lvl.FirstOption = br.ReadInt32(); lvl.TitleReplace = br.ReadInt32(); lvl.OnDeathDemoMode = br.ReadInt32(); lvl.OnDeathInGame = br.ReadInt32(); lvl.DemoTime = br.ReadInt32(); lvl.OnDemoInterrupt = br.ReadInt32(); lvl.OnDemoEnd = br.ReadInt32(); br.ReadBytes(36); // Unknown2 lvl.NumLevels = br.ReadInt16(); lvl.NumChapterScreens = br.ReadInt16(); lvl.NumTitles = br.ReadInt16(); lvl.NumFMVs = br.ReadInt16(); lvl.NumCutscenes = br.ReadInt16(); lvl.NumDemoLevels = br.ReadInt16(); lvl.TitleSoundID = br.ReadInt16(); lvl.SingleLevel = br.ReadInt16(); br.ReadBytes(32); // Unknown3 lvl.Flags = (TOMBPCFlags) br.ReadUInt16(); br.ReadBytes(6); // Unknown4 lvl.XORbyte = br.ReadByte(); lvl.Language = (TOMBPCLanguage) br.ReadByte(); lvl.SecretSoundID = br.ReadInt16(); br.ReadBytes(4); // Unknown5 #endregion #region Strings var xor = lvl.Flags.HasFlag(TOMBPCFlags.UseEncryption) ? lvl.XORbyte : (byte)0; lvl.LevelDisplayNames = br.ReadStringArray(lvl.NumLevels, xor); lvl.ChapterScreens = br.ReadStringArray(lvl.NumChapterScreens, xor); lvl.TitleFileNames = br.ReadStringArray(lvl.NumTitles, xor); lvl.FMVFileNames = br.ReadStringArray(lvl.NumFMVs, xor); lvl.LevelFileNames = br.ReadStringArray(lvl.NumLevels, xor); lvl.CutSceneFileNames = br.ReadStringArray(lvl.NumCutscenes, xor); #endregion #region Script // This code is partially from Script.cpp of OpenRaider project var v = new List<List<ushort>>(); var n = lvl.NumLevels + 1; var offset = br.ReadUInt16Array(n); var numBytes = br.ReadUInt16(); var list = new ushort[(numBytes + 6) / 2]; for (ushort i = 0; i < numBytes / 2; i++) { list[i] = br.ReadUInt16(); } lvl.DemoLevelIDs = br.ReadUInt16Array(lvl.NumDemoLevels); br.BaseStream.Position -= lvl.NumDemoLevels * 2; var hack = br.ReadUInt16Array(3); if (hack[0] == 19 && hack[1] == 20 && hack[2] == 21 || hack[0] == 21 && hack[1] == 22 && hack[2] == 23) { list[numBytes / 2] = hack[0]; list[numBytes / 2 + 1] = hack[1]; list[numBytes / 2 + 2] = hack[2]; } else { br.BaseStream.Position -= 6; } var numPCStrings = 0; hack = br.ReadUInt16Array(3); if ((hack[0] == 1) && (hack[1] == 0) && (hack[2] == 864)) { br.BaseStream.Position += 58; numPCStrings = 80; // TR2 has 80 PSX Strings } else if ((hack[0] == 1) && (hack[1] == 0) && (hack[2] == 817)) { br.BaseStream.Position += 34; numPCStrings = 80; // TR3 also has 80 PSX Strings } else { br.BaseStream.Position -= 6; numPCStrings = 41; } for (uint i = 0; i < n; i++) { uint end = (uint) (offset[i] / 2); var readingOp = false; while (readingOp || (list[end] != (ushort) ScriptOpCode.OP_ENDSEQUENCE)) { if (readingOp) { readingOp = false; end++; } else { if (OpcodeHasOperand[list[end]]) readingOp = true; end++; } } end++; var tmp = new List<ushort>(); for (uint a = (uint) (offset[i] / 2); a < end; a++) { tmp.Add(list[a]); } v.Add(tmp); } lvl.Script = v.Select(x => x.ToArray()).ToArray(); #endregion if (psx) { lvl.PSXFMVInfo = br.ReadArray(lvl.NumFMVs, () => Loader.PSXFMVInfo.Read(br)); } var numGameStrings = br.ReadUInt16(); lvl.GameStrings1 = br.ReadStringArray(numGameStrings, lvl.XORbyte); lvl.GameStrings2 = br.ReadStringArray(numPCStrings, lvl.XORbyte); lvl.Puzzles = new[] { br.ReadStringArray(lvl.NumLevels, lvl.XORbyte), br.ReadStringArray(lvl.NumLevels, lvl.XORbyte), br.ReadStringArray(lvl.NumLevels, lvl.XORbyte), br.ReadStringArray(lvl.NumLevels, lvl.XORbyte) }; lvl.Pickups = new[] { br.ReadStringArray(lvl.NumLevels, lvl.XORbyte), br.ReadStringArray(lvl.NumLevels, lvl.XORbyte) }; lvl.Keys = new[] { br.ReadStringArray(lvl.NumLevels, lvl.XORbyte), br.ReadStringArray(lvl.NumLevels, lvl.XORbyte), br.ReadStringArray(lvl.NumLevels, lvl.XORbyte), br.ReadStringArray(lvl.NumLevels, lvl.XORbyte) }; return lvl; } catch (Exception e) { throw new ScriptParseException(e, br.BaseStream.Position); } }
private void LoadMcnr(BinaryReader reader) { var normals = reader.ReadArray<sbyte>(145 * 3); mNormalExtra = reader.ReadBytes(13); for (var i = 0; i < 145; ++i) { var nx = -(normals[i * 3] / 127.0f); var ny = -(normals[i * 3 + 1] / 127.0f); var nz = normals[i * 3 + 2] / 127.0f; Vertices[i].Normal = new Vector3(nx, ny, nz); } }
private void LoadColors(BinaryReader reader, int size) { var numColors = size / 4; mColors = reader.ReadArray<uint>(numColors); }
private void LoadMccv(BinaryReader reader) { var colors = reader.ReadArray<uint>(145); for (var i = 0; i < 145; ++i) { Vertices[i].Color = colors[i]; var r = (colors[i] >> 16) & 0xFF; var g = (colors[i] >> 8) & 0xFF; var b = (colors[i]) & 0xFF; var a = (colors[i] >> 24) & 0xFF; mShadingFloats[i] = new Vector4(b * 2.0f / 255.0f, g * 2.0f / 255.0f, r * 2.0f / 255.0f, a * 2.0f / 255.0f); } }
private void LoadNormals(BinaryReader reader, int size) { var numNormals = size / SizeCache<Vector3>.Size; mNormals = reader.ReadArray<Vector3>(numNormals); for (var i = 0; i < mNormals.Length; ++i) mNormals[i] = new Vector3(mNormals[i].X, -mNormals[i].Y, mNormals[i].Z); }
private void LoadReferences(BinaryReader reader, int size) { var refs = reader.ReadArray<int>(size / 4); if (refs.Length < mHeader.NumDoodadRefs || mHeader.NumDoodadRefs == 0) return; DoodadReferences = refs.Take(mHeader.NumDoodadRefs).ToArray(); var minPos = BoundingBox.Minimum; var maxPos = BoundingBox.Maximum; MapArea parent; if (mParent.TryGetTarget(out parent) == false) return; foreach (var reference in DoodadReferences) { var inst = parent.DoodadInstances[reference]; var min = inst.BoundingBox.Minimum; var max = inst.BoundingBox.Maximum; if (min.X < minPos.X) minPos.X = min.X; if (min.Y < minPos.Y) minPos.Y = min.Y; if (min.Z < minPos.Z) minPos.Z = min.Z; if (max.X > maxPos.X) maxPos.X = max.X; if (max.Y > maxPos.Y) maxPos.Y = max.Y; if (max.Z > maxPos.Z) maxPos.Z = max.Z; } ModelBox = new BoundingBox(minPos, maxPos); }
private bool LoadBatches(BinaryReader reader, int size) { var numBatches = size / SizeCache<Moba>.Size; if (numBatches != (mHeader.numBatchesA + mHeader.numBatchesB + mHeader.numBatchesC)) { Log.Error("Group has inconsistent amount of batches."); return false; } WmoRoot parent; if (!mParent.TryGetTarget(out parent)) { Log.Fatal("FATAL ERROR! Parent of WMO group is null!!"); return false; } var batches = reader.ReadArray<Moba>(numBatches); for (var i = 0; i < numBatches; ++i) { var b = batches[i]; var batch = new WmoBatch { NumIndices = b.numFaces, StartIndex = b.firstFace, MaterialId = b.material, BlendMode = parent.GetMaterial(b.material).BlendMode, }; mBatches.Add(batch); } Batches = mBatches.OrderBy(b => b.BlendMode).ToList().AsReadOnly(); return true; }
private void LoadLayers(BinaryReader reader, int size) { mLayers = reader.ReadArray<Mcly>(size / SizeCache<Mcly>.Size); MapArea parent; if (mParent.TryGetTarget(out parent) == false) { Textures = new List<Graphics.Texture>(); return; } Textures = mLayers.Select(l => parent.GetTexture(l.TextureId)).ToList().AsReadOnly(); }
/// <summary> /// Reads a <see cref="Mesh"/> /// </summary> /// <param name="br">The <see cref="BinaryReader"/> used to read the <see cref="Mesh"/></param> /// <param name="ver">The game version</param> /// <returns>A <see cref="Mesh"/></returns> public static Mesh Read(BinaryReader br, Engine ver = Engine.Unknown) { var ret = new Mesh(); ret.Centre = Vertex.Read16(br); ret.CollisionSize = br.ReadInt32(); ret.Vertices = br.ReadArray(br.ReadInt16(), () => Vertex.Read16(br)); ret.Normals = new Vertex[0]; ret.Lights = new short[0]; ret.NumNormals = br.ReadInt16(); if (ret.NumNormals >= 0) ret.Normals = br.ReadArray(ret.NumNormals, () => Vertex.Read16(br)); else ret.Lights = br.ReadInt16Array(-ret.NumNormals); ret.TexturedRectangles = br.ReadArray(br.ReadInt16(), () => QuadFace.Read(br, ver)); ret.TexturedTriangles = br.ReadArray(br.ReadInt16(), () => Triangle.Read(br, ver)); if (ver < Engine.TR4) { ret.ColouredRectangles = br.ReadArray(br.ReadInt16(), () => QuadFace.Read(br, ver)); ret.ColouredTriangles = br.ReadArray(br.ReadInt16(), () => Triangle.Read(br, ver)); } return ret; }
public bool AsyncLoad(BinaryReader reader, ChunkInfo chunkInfo) { // chunkInfo.Offset points to right after the MCNK signature, the offsets in the header are relative to the signature tho var basePosition = chunkInfo.Offset - 4; reader.BaseStream.Position = chunkInfo.Offset; reader.ReadInt32(); mHeader = reader.Read<Mcnk>(); reader.BaseStream.Position = basePosition + mHeader.Mcvt; var signature = reader.ReadUInt32(); reader.ReadInt32(); if (signature != 0x4D435654) { Log.Error("Chunk is missing valid MCVT sub chunk"); return false; } LoadMcvt(reader); reader.BaseStream.Position = basePosition + mHeader.Mcnr; signature = reader.ReadUInt32(); reader.ReadInt32(); if (signature != 0x4D434E52) { Log.Error("Chunk is missing valid MCNR sub chunk"); return false; } LoadMcnr(reader); if(mHeader.Mcrf > 0) { reader.BaseStream.Position = basePosition + mHeader.Mcrf; signature = reader.ReadUInt32(); var chunkSize = reader.ReadInt32(); if (signature == 0x4D435246) LoadReferences(reader, chunkSize); } var hasMccv = false; if (mHeader.Mccv != 0) { reader.BaseStream.Position = basePosition + mHeader.Mccv; signature = reader.ReadUInt32(); reader.ReadInt32(); if (signature == 0x4D434356) { LoadMccv(reader); hasMccv = true; HasMccv = true; } } reader.BaseStream.Position = basePosition + mHeader.Mcly; signature = reader.ReadUInt32(); var size = reader.ReadInt32(); if (signature != 0x4D434C59) return false; LoadLayers(reader, size); if (mHeader.SizeAlpha > 8) { reader.BaseStream.Position = basePosition + mHeader.Mcal; signature = reader.ReadUInt32(); if (signature == 0x4D43414C) { reader.ReadInt32(); mAlphaCompressed = reader.ReadBytes(mHeader.SizeAlpha - 8); } } InitLayerData(); if(mHeader.SizeShadow > 8 && mHeader.Mcsh > 0) { reader.BaseStream.Position = basePosition + mHeader.Mcsh + 8; var curPtr = 0; for (var i = 0; i < 64; ++i) { for (var j = 0; j < 8; ++j) { byte mask = reader.ReadByte(); for (var k = 0; k < 8; ++k) { AlphaValues[curPtr] &= 0xFFFFFF00; AlphaValues[curPtr++] |= ((mask & (1 << k)) == 0) ? (byte)0xFF : (byte)0xCC; } } } } if(mHeader.Mclv > 0) { reader.BaseStream.Position = basePosition + mHeader.Mclv + 8; var colors = reader.ReadArray<uint>(145); for (var i = 0; i < 145; ++i) Vertices[i].AdditiveColor = colors[i]; } LoadHoles(); if (hasMccv == false) { for (var i = 0; i < 145; ++i) Vertices[i].Color = 0x7F7F7F7F; } if (mHeader.Mcrf > 0) LoadUnusedChunk(0x4D435246, basePosition + mHeader.Mcrf, (mHeader.NumDoodadRefs + mHeader.NumMapObjRefs) * 4, reader); if (mHeader.SizeShadow > 0) LoadUnusedChunk(0x4D435348, basePosition + mHeader.Mcsh, mHeader.SizeShadow, reader); if (mHeader.NumSoundEmitters > 0) LoadUnusedChunk(0x4D435345, basePosition + mHeader.Mcse, mHeader.NumSoundEmitters * 0x1C, reader); if (mHeader.SizeLiquid > 8) LoadUnusedChunk(0x4D434C51, basePosition + mHeader.Mclq, mHeader.SizeLiquid - 8, reader); if (mHeader.Mclv > 0) LoadUnusedChunk(0x4D434C56, basePosition + mHeader.Mclv, 0, reader); WorldFrame.Instance.MapManager.OnLoadProgress(); return true; }
/// <summary> /// Reads a <see cref="Palette"/> /// </summary> /// <param name="br">The <see cref="BinaryReader"/> used to read the <see cref="Palette"/></param> /// <param name="ver">The game version</param> /// <returns>A <see cref="Palette"/></returns> public static Palette Read(BinaryReader br, Engine ver = Engine.Unknown) { return new Palette { Colour = br.ReadArray(256, () => ByteColor.Read(br, ver)) }; }
private void UpdateMapNoWdl(string continent) { var wdtPath = string.Format(@"World\Map\{0}\{0}.wdt", continent); var hasWdt = FileManager.Instance.Provider.Exists(wdtPath); if(hasWdt == false) { UpdateMapFallback(continent); return; } using(var strm = FileManager.Instance.Provider.OpenFile(wdtPath)) { var reader = new BinaryReader(strm); var hasWdtData = false; while (true) { try { var id = reader.ReadUInt32(); var size = reader.ReadInt32(); if (id == 0x4D41494E) { var adtFlags = reader.ReadArray<ulong>(size / 8); var textureData = new uint[Width * Height]; for(var i = 0; i < 64; ++i) { for(var j = 0; j < 64; ++j) { var idx = i * 64 + j; var exists = (adtFlags[idx] & 1) != 0; if(exists) { hasWdtData = true; for(var k = 0; k < 17; ++k) { for(var l = 0; l < 17; ++l) textureData[(i * 17 + k) * (64 * 17) + j * 17 + l] = 0xFFFFFFFF; } } } } var bmpProps = new BitmapProperties(new PixelFormat(SharpDX.DXGI.Format.B8G8R8A8_UNorm, AlphaMode.Ignore)); using (var dataStream = new DataStream(Width * Height * 4, true, true)) { dataStream.WriteRange(textureData); dataStream.Position = 0; mImage = new Bitmap(InterfaceManager.Instance.Surface.RenderTarget, new Size2(Width, Height), new DataPointer(dataStream.DataPointer, Width * Height * 4), Width * 4, bmpProps); } break; } reader.ReadBytes(size); } catch (Exception) { UpdateMapFallback(continent); return; } } if (hasWdtData == false) UpdateMapFallback(continent); } }
private void RegisterDevice(byte[] data) { var registrationInfo = new DeviceRegistrationInfo(); using (var stream = new MemoryStream(data)) using (var reader = new BinaryReader(stream)) { registrationInfo.Id = reader.ReadGuid(); registrationInfo.Key = reader.ReadUtfString(); registrationInfo.Name = reader.ReadUtfString(); registrationInfo.ClassName = reader.ReadUtfString(); registrationInfo.ClassVersion = reader.ReadUtfString(); registrationInfo.Equipment = reader.ReadArray(ReadEquipmentInfo); registrationInfo.Notifications = reader.ReadArray(ReadNotificationInfo); registrationInfo.Commands = reader.ReadArray(ReadCommandInfo); } RegisterDeviceCore(registrationInfo); }
public void ReadBinaryData(System.IO.BinaryReader reader) { coeff = reader.ReadArray <float>(); }
private static JToken ReadParameterValue(BinaryReader reader, ParameterMetadata parameterMetadata) { switch (parameterMetadata.DataType) { case DataType.Null: return null; case DataType.Byte: return (int) reader.ReadByte(); case DataType.Word: return reader.ReadUInt16(); case DataType.Dword: return reader.ReadUInt32(); case DataType.Qword: return reader.ReadUInt64(); case DataType.SignedByte: return reader.ReadSByte(); case DataType.SignedWord: return reader.ReadInt16(); case DataType.SignedDword: return reader.ReadInt32(); case DataType.SignedQword: return reader.ReadInt64(); case DataType.Single: return reader.ReadSingle(); case DataType.Double: return reader.ReadDouble(); case DataType.Boolean: return reader.ReadByte() != 0; case DataType.Guid: return reader.ReadGuid(); case DataType.UtfString: return reader.ReadUtfString(); case DataType.Binary: return reader.ReadBinary(); case DataType.Array: return new JArray(reader .ReadArray(r => ReadParameterValue(r, parameterMetadata.Children[0])) .Cast<object>() .ToArray()); case DataType.Object: return new JObject(parameterMetadata.Children .Select(p => new JProperty(p.Name, ReadParameterValue(reader, p))) .Cast<object>() .ToArray()); default: throw new NotSupportedException(parameterMetadata.DataType + " is not supported for parameters"); } }
private void LoadVertices(BinaryReader reader, int size) { var numVertices = size / SizeCache<Vector3>.Size; mPositions = reader.ReadArray<Vector3>(numVertices); }