Example #1
0
        public static void ChangeDemoDir(SourceDemo demo, Stream s, string newDir)
        {
            void Write(byte[] buf) => s.Write(buf, 0, buf.Length);

            string old = demo.Header.GameDirectory;

            if (old == newDir)
            {
                // no difference
                Write(demo.Reader.Data);
                return;
            }
            int             lenDiff = newDir.Length - old.Length;
            BitStreamReader bsr     = demo.Reader;

            byte[] dirBytes = Encoding.ASCII.GetBytes(newDir);

            Write(bsr.ReadBytes(796));
            Write(dirBytes);             // header doesn't matter but I change it anyway
            Write(new byte[260 - newDir.Length]);
            bsr.SkipBytes(260);
            Write(bsr.ReadBytes(12));
            byte[] tmp = BitConverter.GetBytes((uint)(bsr.ReadUInt() + lenDiff));
            if (!BitConverter.IsLittleEndian)
            {
                tmp = tmp.Reverse().ToArray();
            }
            Write(tmp);

            foreach (SignOn signOn in demo.FilterForPacket <SignOn>().Where(signOn => signOn.FilterForMessage <SvcServerInfo>().Any()))
            {
                // catch up to signOn packet
                int byteCount = (signOn.Reader.AbsoluteBitIndex - bsr.AbsoluteBitIndex) / 8;
                Write(bsr.ReadBytes(byteCount));
                bsr.SkipBits(signOn.Reader.BitLength);

                BitStreamWriter bsw          = new BitStreamWriter();
                BitStreamReader signOnReader = signOn.Reader;
                bsw.WriteBits(signOnReader.ReadRemainingBits());
                signOnReader = signOnReader.FromBeginning();
                int bytesToMessageStreamSize = demo.DemoInfo.MaxSplitscreenPlayers * 76 + 8;
                signOnReader.SkipBytes(bytesToMessageStreamSize);
                // edit the message stream length - read uint, and edit at index before the reading of said uint
                bsw.EditIntAtIndex((int)(signOnReader.ReadUInt() + lenDiff), signOnReader.CurrentBitIndex - 32, 32);

                // actually change the game dir
                SvcServerInfo serverInfo = signOn.FilterForMessage <SvcServerInfo>().Single();
                int           editIndex  = serverInfo.GameDirBitIndex - signOn.Reader.AbsoluteBitIndex;
                bsw.RemoveBitsAtIndex(editIndex, old.Length * 8);
                bsw.InsertBitsAtIndex(dirBytes, editIndex, newDir.Length * 8);
                Write(bsw.AsArray);
            }
            Write(bsr.ReadRemainingBits().bytes);
        }
        // writes a edited version of the given demo to the stream
        // this is all manually hacked together and it shall stay this way for now
        public static void RemoveCaptions(SourceDemo demo, Stream s)
        {
            void Write(byte[] buf) => s.Write(buf, 0, buf.Length);

            Packet[] closeCaptionPackets = demo.FilterForPacket <Packet>()
                                           .Where(packet => packet.FilterForMessage <SvcUserMessage>()
                                                  .Any(frame => frame.MessageType == UserMessageType.CloseCaption)).ToArray();

            if (closeCaptionPackets.Length == 0)
            {
                Write(demo.Reader.Data);
                return;
            }

            int changedPackets = 0;

            Write(demo.Header.Reader.ReadRemainingBits().bytes);

            foreach (PacketFrame frame in demo.Frames)
            {
                if (frame.Packet != closeCaptionPackets[changedPackets])
                {
                    Write(frame.Reader.ReadRemainingBits().bytes);                     // write frames that aren't changed
                }
                else
                {
                    Packet          p    = (Packet)frame.Packet;
                    BitStreamWriter bsw  = new BitStreamWriter(frame.Reader.BitLength / 8);
                    var             last = p.MessageStream.Last().message;
                    int             len  = last.Reader.AbsoluteStart - frame.Reader.AbsoluteStart + last.Reader.BitLength;
                    bsw.WriteBits(frame.Reader.ReadBits(len), len);
                    int msgSizeOffset = p.MessageStream.Reader.AbsoluteStart - frame.Reader.AbsoluteStart;
                    int typeInfoLen   = demo.DemoInfo.NetMsgTypeBits + demo.DemoInfo.UserMessageLengthBits + 8;
                    bsw.RemoveBitsAtIndices(p.FilterForUserMessage <CloseCaption>()
                                            .Select(caption => (caption.Reader.AbsoluteStart - frame.Reader.AbsoluteStart - typeInfoLen,
                                                                caption.Reader.BitLength + typeInfoLen)));
                    bsw.WriteUntilByteBoundary();
                    bsw.EditIntAtIndex((bsw.BitLength - msgSizeOffset - 32) >> 3, msgSizeOffset, 32);
                    Write(bsw.AsArray);

                    // if we've edited all the packets, write the rest of the data in the demo
                    if (++changedPackets == closeCaptionPackets.Length)
                    {
                        BitStreamReader tmp = demo.Reader;
                        tmp.SkipBits(frame.Reader.AbsoluteStart + frame.Reader.BitLength);
                        Write(tmp.ReadRemainingBits().bytes);
                        break;
                    }
                }
            }
        }