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); } }
private KeyValuePair <ICacheFile, EngineDescription> LoadMap(string path, out IReader reader) { reader = new EndianReader(File.OpenRead(path), Endian.BigEndian); reader.SeekTo(0); byte[] headerMagic = reader.ReadBlock(4); reader.Endianness = CacheFileLoader.DetermineCacheFileEndianness(headerMagic); var versionInfo = new CacheFileVersionInfo(reader); EngineDescription buildInfo = App.AssemblyStorage.AssemblySettings.DefaultDatabase.FindEngineByVersion(versionInfo.BuildString); return (new KeyValuePair <ICacheFile, EngineDescription>(new ThirdGenCacheFile(reader, buildInfo, path, versionInfo.BuildString), buildInfo)); }
private void btnCreatePatchModifiedMap_Click(object sender, RoutedEventArgs e) { var ofd = new OpenFileDialog { Title = "Assembly - Select a Modified Map file", Filter = "Blam Cache Files|*.map" }; if (ofd.ShowDialog() != DialogResult.OK) { return; } txtCreatePatchModifiedMap.Text = ofd.FileName; txtCreatePatchOutputName.Text = Path.GetFileNameWithoutExtension(ofd.FileName); var fileStream = new FileStream(ofd.FileName, FileMode.Open); byte[] headerMagic = new byte[4]; fileStream.Read(headerMagic, 0, 4); var endian = CacheFileLoader.DetermineCacheFileEndianness(headerMagic); var cacheStream = new EndianStream(fileStream, endian); var versionInfo = new CacheFileVersionInfo(cacheStream); _buildInfo = App.AssemblyStorage.AssemblySettings.DefaultDatabase.FindEngineByVersion(versionInfo.BuildString); if (_buildInfo != null && _buildInfo.Name != null) { switch (_buildInfo.Name) { case "Halo 2 Vista": cboxCreatePatchTargetGame.SelectedIndex = (int)TargetGame.Halo2Vista; break; case "Halo 3: ODST": cboxCreatePatchTargetGame.SelectedIndex = (int)TargetGame.Halo3ODST; break; default: if (_buildInfo.Name.Contains("MCC")) { cboxCreatePatchTargetGame.SelectedIndex = (int)TargetGame.MCC; } else if (_buildInfo.Name.Contains("Halo 3")) { cboxCreatePatchTargetGame.SelectedIndex = (int)TargetGame.Halo3; } else if (_buildInfo.Name.Contains("Halo: Reach")) { cboxCreatePatchTargetGame.SelectedIndex = (int)TargetGame.HaloReach; } else if (_buildInfo.Name.Contains("Halo 4")) { cboxCreatePatchTargetGame.SelectedIndex = (int)TargetGame.Halo4; } else { cboxCreatePatchTargetGame.SelectedIndex = 6; // Other } break; } } cacheStream.Dispose(); }
// 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); } }