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);
        }