private CacheHeader(Stream stream)
            {
                using (var binaryReader = new BinaryReader(stream, Encoding.Default, true))
                {
                    //  read the fourcc tag and throw on incorrect value
                    HeadFourCC = binaryReader.ReadTagClass();
                    if (HeadFourCC != (TagClass)"head")
                    {
                        throw new InvalidDataException();
                    }

                    EngineVersion = binaryReader.ReadInt32();
                    FileSize      = binaryReader.ReadInt32();
                    stream.Seek(4, SeekOrigin.Current);

                    //  Check the BuildVersion then return to the last stream position
                    stream.Seek(0x11C, SeekOrigin.Current);
                    var test = Encoding.ASCII.GetString(binaryReader.ReadBytes(32)).Trim(Char.MinValue);
                    Version = test == @"11081.07.04.30.0934.main" ? HaloVersion.PC_RETAIL : HaloVersion.XBOX_RETAIL;
                    stream.Seek(-0x13C, SeekOrigin.Current);

                    IndexInfo = IndexInfoStruct.DeserializeFrom(stream);

                    //  move the stream past some unused/zeroed bytes
                    if (Version == HaloVersion.PC_RETAIL)
                    {
                        SharedInfoStruct.DeserializeFrom(stream);
                    }
                    stream.Seek(32 + 224, SeekOrigin.Current);

                    //  read the build string and remove the trailing null bytes
                    BuildString = Encoding.ASCII.GetString(binaryReader.ReadBytes(32)).Trim(Char.MinValue);

                    //  read the map type (ie: singleplayer, multiplayer, shared, singleplayershared, mainmenu).
                    Type = (MapType)binaryReader.ReadInt32();

                    stream.Seek(28, SeekOrigin.Current);
                    StringsInfo = StringsInfoStruct.DeserializeFrom(stream);
                    stream.Seek(36, SeekOrigin.Current);

                    //  read the name string and remove the trailing null bytes
                    Name = Encoding.ASCII.GetString(binaryReader.ReadBytes(32)).Trim(Char.MinValue);
                    stream.Seek(4, SeekOrigin.Current);

                    //  read the scenario string and remove the trailing null bytes
                    Scenario = Encoding.ASCII.GetString(binaryReader.ReadBytes(128)).Trim(Char.MinValue);
                    stream.Seek(128, SeekOrigin.Current);
                    stream.Seek(4, SeekOrigin.Current);
                    PathsInfo = PathsInfoStruct.DeserializeFrom(stream);
                    if (Version == HaloVersion.PC_RETAIL)
                    {
                        UnknownInfo = UnknownInfoStruct.DeserializeFrom(stream);
                    }
                    Checksum = binaryReader.ReadInt32();

                    //  seek the last 4 bytes before the end of the header
                    stream.Seek(2044 - (int)stream.Position, SeekOrigin.Current);
                    FootFourCC = binaryReader.ReadTagClass();
                }
            }
Beispiel #2
0
        /// <summary>
        ///     Copies the paths from the Index into the given stream at the current address
        ///     note: Creates the table on an align(512) address then creates the table-index on
        ///     an align(512) address following it.
        /// </summary>
        /// <param name="outputStream">The stream to write to</param>
        /// <returns>PathInfoStruct containing addresses/info of the paths table & index</returns>
        private PathsInfoStruct GeneratePathsTable(Stream outputStream)
        {
            var info = new PathsInfoStruct( );
            //  extract the paths from the index and copy them into a local list object.
            var paths = Index.Select(x => x.Path).ToList( );

            info.PathCount        = paths.Count;
            info.PathTableAddress = outputStream.Align(512);
            //  pad the stream to align(512) and assign the new address to PathTableAddress.
            GenerateStringEntries(outputStream, paths);
            //  Write the paths into the stream and subtract the PathTableAddress from the new stream position
            //  to get the PathTableLength.
            info.PathTableLength = ( int )outputStream.Position - info.PathTableAddress;
            //  pad the stream to align(512) and assign the new address to PathIndexAddress.
            info.PathIndexAddress = outputStream.Align(512);
            //  write the index for the path table
            GenerateTableIndex(outputStream, paths);

            //  finish on the next 512 alignment boundary
            outputStream.Align(512);
            Padding.AssertIsAligned(512, outputStream);
            //  return the struct that contains the information about where in the stream this
            //  resource was written
            return(info);
        }