/// <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"); } }
/// <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"); } }
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); } }
/// <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"); } }
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!"); } }
// 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"); } }