private void ReadHeader(BinaryReader br) { br.BaseStream.Seek(8, SeekOrigin.Begin); // skip magic, DemoFactory checks it demoProtocol = br.ReadUInt32(); if (demoProtocol > 3) { throw new ApplicationException(String.Format("Unsupported demo protocol \"{0}\", should be 3.", demoProtocol)); } networkProtocol = br.ReadUInt32(); if (networkProtocol > 18) { UnsupportedNetworkProtocol = true; } serverName = Common.ReadNullTerminatedString(br, 260); recorderName = Common.ReadNullTerminatedString(br, 260); mapName = Common.ReadNullTerminatedString(br, 260).ToLower(); gameFolderName = Common.ReadNullTerminatedString(br, 260).ToLower(); durationInSeconds = Math.Abs(br.ReadSingle()); if (recorderName == "SourceTV Demo") { perspective = Perspectives.SourceTv; } else { perspective = Perspectives.Pov; } Game = GameManager.Find(this); }
public static Demo CreateDemo(String fileName) { const Int32 magicStringLength = 8; using (FileStream inputStream = File.OpenRead(fileName)) { using (BinaryReader binaryReader = new BinaryReader(inputStream)) { String magic = Common.ReadNullTerminatedString(binaryReader, magicStringLength); binaryReader.Close(); // create demo object Demo demo = null; if (magic == "HLDEMO") { demo = new HalfLifeDemo(fileName); } else if (magic == "HL2DEMO") { demo = new SourceDemo(fileName); } else { throw new ApplicationException("Not a valid Half-Life or Source engine demo file."); } return(demo); } } }
private void ReadHeader(BinaryReader br) { br.BaseStream.Seek(8, SeekOrigin.Begin); // skip magic, DemoFactory checks it demoProtocol = br.ReadUInt32(); if (demoProtocol > 3) { // the format of the rest of the header may have changed, but continue anyway since it's not critical information UnsupportedDemoProtocol = true; } networkProtocol = br.ReadUInt32(); if (networkProtocol > 18) { UnsupportedNetworkProtocol = true; } serverName = Common.ReadNullTerminatedString(br, 260); recorderName = Common.ReadNullTerminatedString(br, 260); mapName = Common.ReadNullTerminatedString(br, 260).ToLower(); gameFolderName = Common.ReadNullTerminatedString(br, 260).ToLower(); durationInSeconds = Math.Abs(br.ReadSingle()); if (recorderName == "SourceTV Demo") { perspective = Perspectives.SourceTv; } else { perspective = Perspectives.Pov; } Game = GameManager.Find(this); }
private void ReadHeader(BinaryReader br) { br.BaseStream.Seek(8, SeekOrigin.Current); // skip magic, DemoFactory checks it demoProtocol = br.ReadUInt32(); if (demoProtocol != 5) { throw new ApplicationException(String.Format("Unknown demo protocol \"{0}\", should be 5.", demoProtocol)); } networkProtocol = br.ReadUInt32(); if (networkProtocol < 43) // don't support demos older than HL 1.1.0.4/CS 1.0 { throw new ApplicationException(String.Format("Unsupported network protcol \"{0}\", only 43 and higher are supported.")); } mapName = Common.ReadNullTerminatedString(br, 260).ToLower(); gameFolderName = Common.ReadNullTerminatedString(br, 260).ToLower(); mapChecksum = br.ReadUInt32(); Int64 directoryEntriesOffset = br.ReadUInt32(); // check directory entries // check offset, should be exactly file length - no. of dir entries (int) + dir entry size * 2 // otherwise, assume they are corrupt if (directoryEntriesOffset != fileLengthInBytes - 4 - (DirectoryEntrySizeInBytes * 2)) { status = StatusEnum.CorruptDirEntries; return; } // seek to directory entries offset Int64 newPosition = br.BaseStream.Seek(directoryEntriesOffset, SeekOrigin.Begin); // CHECK ME: is this correct or is an exception thrown if we seek to far? if (newPosition != directoryEntriesOffset) { status = StatusEnum.CorruptDirEntries; return; } // read no. of directory entries Int32 nDirectoryEntries = br.ReadInt32(); if (nDirectoryEntries != 2) { status = StatusEnum.CorruptDirEntries; return; } // read directory entries for (Int32 i = 0; i < nDirectoryEntries; i++) { br.BaseStream.Seek(4, SeekOrigin.Current); // skip number String dirEntryTitle = Common.ReadNullTerminatedString(br, 64); br.BaseStream.Seek(8, SeekOrigin.Current); // skip flags, cdtrack Single dirEntryTime = br.ReadSingle(); br.BaseStream.Seek(12, SeekOrigin.Current); // skip frames, offset and length (we calculate these ourselves, so corrupt directory entries or not, the demo is treated the same) if (dirEntryTitle.ToLower() == "playback") { // store demo duration durationInSeconds = Math.Abs(dirEntryTime); } } }
private Byte[] ReadFrameData(HalfLifeDemoParser.FrameHeader frameHeader, out Boolean writeFrame) { Byte[] result = null; writeFrame = true; if (frameHeader.Type == 0 || frameHeader.Type == 1) { // frame header Byte[] frameHeaderDemoInfo = parser.Reader.ReadBytes(parser.GameDataDemoInfoLength); Byte[] frameHeaderSequenceInfo = parser.Reader.ReadBytes(parser.GameDataSequenceInfoLength); UInt32 gameDataLength = parser.Reader.ReadUInt32(); // frame data Byte[] frameData = null; if (gameDataLength != 0) { // read frame data frameData = parser.Reader.ReadBytes((Int32)gameDataLength); if (frameData.Length != gameDataLength) { throw new ApplicationException("Gamedata frame length doesn't match header."); } // Give the writer interface a chance to insert any new messages into the first gamedata frame. if (frameHeader.Type == 1 && !foundPlaybackOffset) { demoWriterInterface.ProcessFirstGameDataFrame(ref frameData); } // parse frame messages try { if (demoWriterInterface.ShouldParseGameDataMessages(frameHeader.Type)) { parser.ParseGameDataMessages(frameData, demoWriterInterface.GetNewUserMessageId); // set frame data to version modified by parsing frameData = parser.BitBuffer.Data; } } catch (ThreadAbortException) { throw; } catch (Exception ex) { Error("Error parsing gamedata frame.\n\n" + parser.ComputeMessageLog(), ex, true); if (lastErrorResult != MessageWindow.Result.Continue) { throw new AbortWritingException(); } else { writeFrame = false; return(null); } } } // check for end of loading segment if (frameHeader.Type == 1) { if (!foundPlaybackOffset) { // last 5 frame (end of segment) will have stored the correct offset foundPlaybackOffset = true; } // count playback segment gamedata frames nPlaybackFrames++; } // copy contents of frame into memorystream, return result MemoryStream ms = new MemoryStream(); demoWriterInterface.WriteDemoInfo(frameHeaderDemoInfo, ms); ms.Write(frameHeaderSequenceInfo, 0, frameHeaderSequenceInfo.Length); if (gameDataLength == 0) { ms.Write(BitConverter.GetBytes(gameDataLength), 0, 4); } else { ms.Write(BitConverter.GetBytes(frameData.Length), 0, 4); ms.Write(frameData, 0, frameData.Length); } return(ms.ToArray()); } else if (frameHeader.Type == 3) // client command { String command = Common.ReadNullTerminatedString(parser.Reader, 64); if (!demoWriterInterface.ShouldWriteClientCommand(command)) { // don't write frame writeFrame = false; return(null); } parser.Seek(-64); result = parser.Reader.ReadBytes(64); if (result.Length != 64) { throw new ApplicationException("Unexpected client command frame data length."); } } else if (Config.Settings.PlaybackRemoveWeaponAnimations && frameHeader.Type == 7) { parser.Seek(8); writeFrame = false; return(null); } else if (frameHeader.Type != 5) { Int32 frameLength = parser.GetFrameLength(frameHeader.Type); if (frameLength != 0) { result = parser.Reader.ReadBytes(frameLength); if (result.Length != frameLength) { throw new ApplicationException("Unexpected frame data length."); } } } return(result); }