Exemplo n.º 1
0
        public ReplayHeader ParseReplayHeader(byte[] totalReplayBytes, out int currIndex)
        {
            currIndex = 0;
            byte[]       replayHeaderBytes  = totalReplayBytes.SubArray(0, HEADER_SIZE);
            ReplayHeader parsedReplayHeader = new ReplayHeader(replayHeaderBytes);

            //Check if the replay file starts with the expected header string of "Warcraft III recorded game"
            byte[] replayStartHeader = replayHeaderBytes.SubArray(0, REPLAY_HEADER_ST_BYTES.Length);
            if (!replayStartHeader.SequenceEqual(REPLAY_HEADER_ST_BYTES))
            {
                throw new InvalidDataException(String.Format(ERROR_INVALID_HEADER_START_STRING, Encoding.UTF8.GetString(replayStartHeader)));
            }
            currIndex += REPLAY_HEADER_ST_BYTES.Length; //Move 26 characters forward

            //Get file offset
            uint replayFileOffset = ByteUtility.ReadDoubleWord(replayHeaderBytes, currIndex);

            if (replayFileOffset != FILE_OFFSET_FIRST_COMPRESSED_DATA_BLOCK)
            {
                throw new InvalidDataException(String.Format(ERROR_INVALID_REPLAY_FILE_OFFSET,
                                                             BitConverter.ToString(BitConverter.GetBytes(replayFileOffset))));
            }
            currIndex += 4;

            //Get overall size of compressed file
            uint compressedFileSize = ByteUtility.ReadDoubleWord(replayHeaderBytes, currIndex);

            parsedReplayHeader.CompressedFileSize = compressedFileSize;
            currIndex += 4;

            //Get replay version
            uint replayHeaderVersion = ByteUtility.ReadDoubleWord(replayHeaderBytes, currIndex);

            if (replayHeaderVersion != SUPPORTED_REPLAY_HEADER_VERSION)
            {
                throw new InvalidDataException(String.Format(ERROR_INVALID_REPLAY_HEADER_VERSION,
                                                             BitConverter.ToString(BitConverter.GetBytes(replayHeaderVersion))));
            }
            currIndex += 4;

            //Get overall size of decompressed file
            uint decompressedFileSize = ByteUtility.ReadDoubleWord(replayHeaderBytes, currIndex);

            parsedReplayHeader.DecompressedFileSize = decompressedFileSize;
            currIndex += 4;

            //Get total number of compressed data blocks in file
            uint compressedDataBlockCount = ByteUtility.ReadDoubleWord(replayHeaderBytes, currIndex);

            parsedReplayHeader.CompressedDataBlockCount = (int)compressedDataBlockCount;
            currIndex += 4;

            //Start SubHeaderParsing (Version 1)
            //Get version identifier (Classic, TFT)
            string clientType = ByteUtility.ReadDoubleWordString(replayHeaderBytes, currIndex);

            if (clientType != SUPPORTED_WC3_CLIENT_TYPE)
            {
                throw new InvalidDataException(String.Format(ERROR_INVALID_REPLAY_CLIENT_TYPE, clientType));
            }
            currIndex += 4;

            //Get Client Version Number
            string replayVersion      = ByteUtility.ReadDoubleWordString(replayHeaderBytes, currIndex);
            double replayVersionValue = 0;

            Double.TryParse(replayVersion, out replayVersionValue);
            //For some reason, replays generated by GHost doesn't follow the standard replay format
            //This part is commented out until I figure out what's going on

            //if (replayVersionValue < 1.0 && replayVersionValue > 2.0)
            //{
            //    throw new InvalidDataException(String.Format(ERROR_INVALID_REPLAY_VERSION, replayVersion));
            //}
            parsedReplayHeader.ReplayVersion = replayVersion;
            currIndex += 4;

            ushort buildNumber = ByteUtility.ReadWord(replayHeaderBytes, currIndex);

            parsedReplayHeader.BuildNumber = buildNumber;
            currIndex += 2;

            ushort flag = ByteUtility.ReadWord(replayHeaderBytes, currIndex);

            if (flag != FLAG_MULTIPLAYER)
            {
                //throw new InvalidDataException(String.Format(ERROR_INVALID_GAME_TYPE, BitConverter.ToString(BitConverter.GetBytes(flag))));
            }
            currIndex += 2;

            uint replayLength = ByteUtility.ReadDoubleWord(replayHeaderBytes, currIndex);

            parsedReplayHeader.ReplayLength = replayLength;
            currIndex += 4;

            uint checksum = ByteUtility.ReadDoubleWord(replayHeaderBytes, currIndex);

            parsedReplayHeader.CRC32 = checksum;
            currIndex += 4;

            return(parsedReplayHeader);
        }