Esempio n. 1
0
        /// <summary>
        ///     Loads a cache file from a stream.
        /// </summary>
        /// <param name="reader">The stream to read from.</param>
        /// <param name="engineDb">The engine database to use to process the cache file.</param>
        /// <param name="engineInfo">On output, this will contain the cache file's engine description.</param>
        /// <returns>The cache file that was loaded.</returns>
        /// <exception cref="ArgumentException">Thrown if the cache file is invalid.</exception>
        /// <exception cref="NotSupportedException">Thrown if the cache file's target engine is not supported.</exception>
        public static ICacheFile LoadCacheFile(IReader reader, EngineDatabase engineDb, out EngineDescription engineInfo)
        {
            // Set the reader's endianness based upon the file's header magic
            reader.SeekTo(0);
            byte[] headerMagic = reader.ReadBlock(4);
            reader.Endianness = DetermineCacheFileEndianness(headerMagic);

            // Load engine version info
            var version = new CacheFileVersionInfo(reader);
            if (version.Engine != EngineType.SecondGeneration && version.Engine != EngineType.ThirdGeneration)
                throw new NotSupportedException("Engine not supported");

            // Load build info
            engineInfo = engineDb.FindEngineByVersion(version.BuildString);
            if (engineInfo == null)
                throw new NotSupportedException("Engine version \"" + version.BuildString + "\" not supported");

            // Load the cache file depending upon the engine version
            switch (version.Engine)
            {
                case EngineType.SecondGeneration:
                    return new SecondGenCacheFile(reader, engineInfo, version.BuildString);

                case EngineType.ThirdGeneration:
                    return new ThirdGenCacheFile(reader, engineInfo, version.BuildString);

                default:
                    throw new NotSupportedException("Engine not supported");
            }
        }
Esempio n. 2
0
        /// <summary>
        ///     Loads a cache file from a stream.
        /// </summary>
        /// <param name="reader">The stream to read from.</param>
        /// <param name="engineDb">The engine database to use to process the cache file.</param>
        /// <param name="engineInfo">On output, this will contain the cache file's engine description.</param>
        /// <returns>The cache file that was loaded.</returns>
        /// <exception cref="ArgumentException">Thrown if the cache file is invalid.</exception>
        /// <exception cref="NotSupportedException">Thrown if the cache file's target engine is not supported.</exception>
        public static ICacheFile LoadCacheFile(IReader reader, EngineDatabase engineDb, out EngineDescription engineInfo)
        {
            // Set the reader's endianness based upon the file's header magic
            reader.SeekTo(0);
            byte[] headerMagic = reader.ReadBlock(4);
            reader.Endianness = DetermineCacheFileEndianness(headerMagic);

            // Load engine version info
            var version = new CacheFileVersionInfo(reader);

            if (version.Engine != EngineType.SecondGeneration && version.Engine != EngineType.ThirdGeneration)
            {
                throw new NotSupportedException("Engine not supported");
            }

            // Load build info
            engineInfo = engineDb.FindEngineByVersion(version.BuildString);
            if (engineInfo == null)
            {
                throw new NotSupportedException("Engine version \"" + version.BuildString + "\" not supported");
            }

            // Load the cache file depending upon the engine version
            switch (version.Engine)
            {
            case EngineType.SecondGeneration:
                return(new SecondGenCacheFile(reader, engineInfo, version.BuildString));

            case EngineType.ThirdGeneration:
                return(new ThirdGenCacheFile(reader, engineInfo, version.BuildString));

            default:
                throw new NotSupportedException("Engine not supported");
            }
        }
Esempio n. 3
0
        private static CompressionState DetermineState(IReader reader, EngineDatabase engineDb, out EngineType type)
        {
            // Set the reader's endianness based upon the file's header magic
            reader.SeekTo(0);
            byte[] headerMagic = reader.ReadBlock(4);
            reader.Endianness = CacheFileLoader.DetermineCacheFileEndianness(headerMagic);

            // Load engine version info
            var version = new CacheFileVersionInfo(reader);

            type = version.Engine;

            if (version.Engine == EngineType.SecondGeneration)
            {
                // Load build info
                var engineInfo = engineDb.FindEngineByVersion(version.BuildString);
                if (engineInfo == null)
                {
                    return(CompressionState.Null);
                }

                if (!engineInfo.UsesCompression)
                {
                    return(CompressionState.Null);
                }

                return(AnalyzeSecondGen(reader, engineInfo));
            }
            else
            {
                return(CompressionState.Null);
            }
        }
Esempio n. 4
0
        /// <summary>
        ///     Loads a cache file from a stream.
        /// </summary>
        /// <param name="reader">The stream to read from.</param>
        /// <param name="engineDb">The engine database to use to process the cache file.</param>
        /// <param name="engineInfo">On output, this will contain the cache file's engine description.</param>
        /// <returns>The cache file that was loaded.</returns>
        /// <exception cref="ArgumentException">Thrown if the cache file is invalid.</exception>
        /// <exception cref="NotSupportedException">Thrown if the cache file's target engine is not supported.</exception>
        public static ICacheFile LoadCacheFile(IReader map_reader, IReader tag_reader, IReader string_reader, out string tagnamesLocation, string filesLocation, EngineDatabase engineDb, out EngineDescription engineInfo)
        {
            // Set the reader's endianness based upon the file's header magic
            map_reader.SeekTo(0);
            byte[] headerMagic = map_reader.ReadBlock(4);
            Endian engianess = DetermineCacheFileEndianness(headerMagic);
            map_reader.Endianness = engianess;
            if(tag_reader != null) tag_reader.Endianness = engianess;
            if (tag_reader != null) string_reader.Endianness = engianess;

            // Load engine version info
            var version = new CacheFileVersionInfo(map_reader);
            if (version.Engine != EngineType.SecondGeneration && version.Engine != EngineType.ThirdGeneration && version.Engine != EngineType.FourthGeneration)
                throw new NotSupportedException("Engine not supported");

            // Load build info
            engineInfo = engineDb.FindEngineByVersion(version.BuildString);
            if (engineInfo == null)
                throw new NotSupportedException("Engine version \"" + version.BuildString + "\" not supported");

            // Load the cache file depending upon the engine version
            switch (version.Engine)
            {
                case EngineType.SecondGeneration:
                    tagnamesLocation = null;
                    return new SecondGenCacheFile(map_reader, engineInfo, version.BuildString);

                case EngineType.ThirdGeneration:
                    tagnamesLocation = null;
                    return new ThirdGenCacheFile(map_reader, engineInfo, version.BuildString);

                case EngineType.FourthGeneration:
                    if (tag_reader == null || tag_reader.BaseStream.Length == 0) throw new Exception("Can't load version 4 cache file without tags file. Please make sure that tags.dat is in the same folder at the map file.");
                    if (string_reader == null || tag_reader.BaseStream.Length == 0) throw new Exception("Can't load version 4 cache file without strings file. Please make sure that tags.dat is in the same folder at the map file.");

                    // Load the tag names csv file
                    string tagnames_filename = "tagnames_" + version.BuildString + ".csv";
                    string tagnames_location = filesLocation != null ? filesLocation + tagnames_filename : "";
                    if (!File.Exists(tagnames_location)) tagnames_location = "tagnames\\" + tagnames_filename;
                    if (!File.Exists(tagnames_location)) tagnames_location = null;

                    FileStream tagnamesFileStream = tagnames_location != null ? TryInitFilestream(tagnames_location) : null;
                    EndianReader tagnames_reader = null;
                    if (tagnamesFileStream != null)
                    {
                        tagnames_reader = new EndianReader(tagnamesFileStream, Endian.BigEndian);
                        tagnames_reader.Endianness = engianess;
                    }

                    tagnamesLocation = tagnames_location;

                    FourthGenCacheFile cache_file = new FourthGenCacheFile(map_reader, tag_reader, string_reader, tagnames_reader, engineInfo, version.BuildString);
                    tagnamesFileStream.Close();
                    return cache_file;

                default:
                    throw new NotSupportedException("Engine not supported");
            }
        }
Esempio n. 5
0
        public BlamCacheFile(string filePath)
        {
            if (!File.Exists(filePath))
            {
                throw new FileNotFoundException("Invalid cache file path");
            }

            fileStream       = new EndianStream(File.Open(filePath, FileMode.Open, FileAccess.ReadWrite), Endian.LittleEndian);
            cacheFileVersion = new CacheFileVersionInfo(fileStream);
            EngineDatabase database = XMLEngineDatabaseLoader.LoadDatabase("Formats/Engines.xml");

            buildInfo = database.FindEngineByVersion(cacheFileVersion.BuildString);

            switch (cacheFileVersion.Engine)
            {
            case EngineType.ThirdGeneration:
                internalCacheFile = CreateThirdGenCacheFile(fileStream, buildInfo, cacheFileVersion);
                break;

            default:
                throw new InvalidOperationException("Only third generation engine map files are supported at the moment!");
            }
        }
Esempio n. 6
0
        // TODO (Dragon): support CEA 360 with LZX
        private static CompressionState DetermineState(IReader reader, EngineDatabase engineDb, out EngineType type, out EngineDescription engineInfo)
        {
            CacheFileVersionInfo version = null;

            // not all compressed maps have a decompressed header
            // so we handle that here
            try
            {
                // Attempt to set the reader's endianness based upon the file's header magic
                reader.SeekTo(0);
                byte[] headerMagic = reader.ReadBlock(4);
                reader.Endianness = CacheFileLoader.DetermineCacheFileEndianness(headerMagic);

                // Load engine version info
                version = new CacheFileVersionInfo(reader);
            }
            catch (ArgumentException e) // map had no header, assume its CEA
            {
                using (MemoryStream ms_header_out = new MemoryStream())
                {
                    // first chunk offset is at 0x4
                    reader.SeekTo(0x4);
                    int first_chunk_offset  = reader.ReadInt32();
                    int second_chunk_offset = reader.ReadInt32();
                    int first_chunk_size    = second_chunk_offset - first_chunk_offset - 6;

                    reader.SeekTo(first_chunk_offset);

                    // CEA 360 stores an 0xFF, use it for ID
                    byte cea_360_ff_byte = reader.ReadByte();
                    if (cea_360_ff_byte == 0xFF)    // CEA 360
                    {
                        // TODO (Dragon): decompress first chunk to get the header with lzx
                        throw new InvalidOperationException("assembly does not support CEA 360 decompression (missing LZX)");
                    }
                    else // assume CEA MCC
                    {
                        reader.SeekTo(first_chunk_offset + 6);
                        byte[] first_chunk_bytes = reader.ReadBlock(first_chunk_size);
                        using (MemoryStream ms_header_comp = new MemoryStream(first_chunk_bytes))
                        {
                            //ms_header_comp.Write(first_chunk_bytes, 0, first_chunk_size);
                            using (DeflateStream ds = new DeflateStream(ms_header_comp, CompressionMode.Decompress))
                            {
                                ds.CopyTo(ms_header_out);
                            }
                        }
                    }

                    EndianReader header_reader = new EndianReader(ms_header_out, Endian.LittleEndian);
                    version = new CacheFileVersionInfo(header_reader);
                }
            }

            // if version wasnt set its because we couldnt read a proper header, throw an exception
            if (version == null)
            {
                throw new NullReferenceException("Failed to create CacheFileVersionInfo from map header");
            }

            type       = version.Engine;
            engineInfo = engineDb.FindEngineByVersion(version.BuildString);

            if (version.Engine == EngineType.FirstGeneration)
            {
                if (engineInfo == null)
                {
                    return(CompressionState.Null);
                }

                if (!engineInfo.UsesCompression)
                {
                    return(CompressionState.Null);
                }

                return(AnalyzeFirstGen(reader, engineInfo));
            }
            else if (version.Engine == EngineType.SecondGeneration)
            {
                if (engineInfo == null)
                {
                    return(CompressionState.Null);
                }

                if (!engineInfo.UsesCompression)
                {
                    return(CompressionState.Null);
                }

                return(AnalyzeSecondGen(reader, engineInfo));
            }
            else
            {
                return(CompressionState.Null);
            }
        }
        /// <summary>
        ///     Loads a cache file from a stream.
        /// </summary>
        /// <param name="reader">The stream to read from.</param>
        /// <param name="engineDb">The engine database to use to process the cache file.</param>
        /// <param name="engineInfo">On output, this will contain the cache file's engine description.</param>
        /// <returns>The cache file that was loaded.</returns>
        /// <exception cref="ArgumentException">Thrown if the cache file is invalid.</exception>
        /// <exception cref="NotSupportedException">Thrown if the cache file's target engine is not supported.</exception>
        public static ICacheFile LoadCacheFile(IReader map_reader, IReader tag_reader, IReader string_reader, out string tagnamesLocation, string filesLocation, EngineDatabase engineDb, out EngineDescription engineInfo, string tagsLocation, string stringsLocation)
        {
            // Set the reader's endianness based upon the file's header magic
            map_reader.SeekTo(0);
            byte[] headerMagic = map_reader.ReadBlock(4);
            Endian engianess   = DetermineCacheFileEndianness(headerMagic);

            map_reader.Endianness = engianess;
            if (tag_reader != null)
            {
                tag_reader.Endianness = engianess;
            }
            if (tag_reader != null)
            {
                string_reader.Endianness = engianess;
            }

            // Load engine version info
            var version = new CacheFileVersionInfo(map_reader);

            if (version.Engine == EngineType.FirstGeneration)
            {
                throw new NotSupportedException("Engine not supported");
            }

            // Load build info
            engineInfo = engineDb.FindEngineByVersion(version.BuildString);
            if (engineInfo == null)
            {
                throw new NotSupportedException("Engine version \"" + version.BuildString + "\" not supported");
            }

            // Load the cache file depending upon the engine version
            switch (version.Engine)
            {
            case EngineType.SecondGeneration:
                tagnamesLocation = null;
                return(new SecondGenCacheFile(map_reader, engineInfo, version.BuildString));

            case EngineType.ThirdGeneration:
                tagnamesLocation = null;
                return(new ThirdGenCacheFile(map_reader, engineInfo, version.BuildString));

            case EngineType.ThirdGenMCC:
                tagnamesLocation = null;
                return(new NewThirdGenCacheFile(map_reader, engineInfo, version.BuildString));


            case EngineType.FourthGeneration:
                if (tag_reader == null || tag_reader.BaseStream.Length == 0)
                {
                    throw new Exception("Can't load version 4 cache file without tags file. Please make sure that tags.dat is in the same folder at the map file.");
                }
                if (string_reader == null || tag_reader.BaseStream.Length == 0)
                {
                    throw new Exception("Can't load version 4 cache file without strings file. Please make sure that tags.dat is in the same folder at the map file.");
                }

                string tagnames_location = Path.Combine(Path.GetDirectoryName(tagsLocation), "tag_list.csv");


                if (!File.Exists(tagnames_location))
                {
                    tagnames_location = null;
                }

                if (tagnames_location == null)
                {
                    // Load the tag names csv file
                    string tagnames_filename = "tagnames_";
                    if (engineInfo.AltTagNames != null)
                    {
                        tagnames_filename += engineInfo.AltTagNames + ".csv";
                    }
                    else
                    {
                        tagnames_filename += version.BuildString + ".csv";
                    }
                    tagnames_location = filesLocation != null ? filesLocation + tagnames_filename : "";
                    if (File.Exists(tagnames_location))
                    {
                        tagnames_location = "tagnames\\" + tagnames_filename;
                    }
                    else
                    {
                        tagnames_location = null;
                    }
                }

                FileStream tagnamesFileStream = tagnames_location != null?TryInitFilestream(tagnames_location) : null;

                EndianReader tagnames_reader = null;
                if (tagnamesFileStream != null)
                {
                    tagnames_reader            = new EndianReader(tagnamesFileStream, Endian.BigEndian);
                    tagnames_reader.Endianness = engianess;
                }

                tagnamesLocation = tagnames_location;

                FourthGenCacheFile cache_file = new FourthGenCacheFile(map_reader, tag_reader, string_reader, tagnames_reader, engineInfo, version.BuildString);
                tagnamesFileStream.Close();
                return(cache_file);

            default:
                throw new NotSupportedException("Engine not supported");
            }
        }