/// <summary> /// Finds the EngineDatabase that matches a cache file from a stream, if available. /// </summary> /// <param name="reader">The stream to read from.</param> /// <param name="engineDb">The engine database to use to process the cache file.</param> /// <returns>The EngineDescription used to describe the cache file, otherwise null.</returns> public static EngineDescription FindEngineDescription(IReader reader, EngineDatabase engineDb) { // Set the reader's endianness based upon the file's header magic reader.SeekTo(0); byte[] headerMagic = reader.ReadBlock(4); reader.Endianness = DetermineCacheFileEndianness(headerMagic); reader.SeekTo(0x4); int fileVersion = reader.ReadInt32(); var matches = engineDb.FindEnginesByVersion(fileVersion, reader.Endianness); Dictionary <int, string> offsetCache = new Dictionary <int, string>(); foreach (EngineDescription engine in matches) { if (offsetCache.ContainsKey(engine.BuildStringOffset)) { if (offsetCache[engine.BuildStringOffset] == engine.BuildVersion) { return(engine); } else { continue; } } reader.SeekTo(engine.BuildStringOffset); string buildString = reader.ReadAscii(); if (buildString == engine.BuildVersion) { return(engine); } offsetCache[engine.BuildStringOffset] = buildString; } return(null); }
/// <summary> /// Finds any EngineDatabase that matches a cache file from a stream, if available. /// List return is intended to be passed to the user to make the final choice in case of > 1 matches. /// </summary> /// <param name="reader">The stream to read from.</param> /// <param name="engineDb">The engine database to use to process the cache file.</param> /// <returns>List containing matching EngineDescriptions that could possibly describe the cache file, if any.</returns> public static List <EngineDescription> FindEngineDescriptions(IReader reader, EngineDatabase engineDb) { // Set the reader's endianness based upon the file's header magic reader.SeekTo(0); byte[] headerMagic = reader.ReadBlock(4); var endian = DetermineCacheFileEndianness(headerMagic); int fileVersion; if (endian != null) { reader.Endianness = endian.Value; reader.SeekTo(0x4); fileVersion = reader.ReadInt32(); } else { //halo trial lol reader.SeekTo(0x2C0); headerMagic = reader.ReadBlock(4); var trialendian = DetermineTrialCacheFileEndianness(headerMagic); reader.Endianness = trialendian; reader.SeekTo(0x588); fileVersion = reader.ReadInt32(); } var possibleEngines = engineDb.FindEnginesByVersion(fileVersion, reader.Endianness); //reduce extra reads by caching the value at each offset Dictionary <int, string> offsetCache = new Dictionary <int, string>(); List <EngineDescription> matches = new List <EngineDescription>(); foreach (EngineDescription engine in possibleEngines) { if (offsetCache.ContainsKey(engine.BuildStringOffset)) { if (offsetCache[engine.BuildStringOffset] == engine.BuildVersion) { matches.Add(engine); if (!string.IsNullOrEmpty(engine.BuildVersion)) { break; } } continue; } reader.SeekTo(engine.BuildStringOffset); string buildString = reader.ReadAscii(0x20); if (buildString == engine.BuildVersion) { matches.Add(engine); if (!string.IsNullOrEmpty(engine.BuildVersion)) { break; } } offsetCache[engine.BuildStringOffset] = buildString; } return(matches); }