Example #1
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);
            }
        }
        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);
            var cacheStream = new EndianStream(fileStream, Endian.BigEndian);
            var versionInfo = new CacheFileVersionInfo(cacheStream);
            var engine      = App.AssemblyStorage.AssemblySettings.DefaultDatabase.FindEngineByVersion(versionInfo.BuildString);

            if (engine != null && engine.Name != null)
            {
                switch (engine.Name)
                {
                case "Halo 2 Vista":
                    cboxCreatePatchTargetGame.SelectedIndex = (int)TargetGame.Halo2Vista;
                    break;

                case "Halo 3: ODST":
                    cboxCreatePatchTargetGame.SelectedIndex = (int)TargetGame.Halo3ODST;
                    break;

                default:
                    if (engine.Name.Contains("Halo 3"))
                    {
                        cboxCreatePatchTargetGame.SelectedIndex = (int)TargetGame.Halo3;
                    }
                    else if (engine.Name.Contains("Halo: Reach"))
                    {
                        cboxCreatePatchTargetGame.SelectedIndex = (int)TargetGame.HaloReach;
                    }
                    else if (engine.Name.Contains("Halo 4"))
                    {
                        cboxCreatePatchTargetGame.SelectedIndex = (int)TargetGame.Halo4;
                    }
                    else
                    {
                        cboxCreatePatchTargetGame.SelectedIndex = 5;                                 // Other
                    }
                    break;
                }
            }

            cacheStream.Close();
        }
Example #3
0
        private KeyValuePair <ICacheFile, EngineDescription> LoadMap(string path, out IReader reader)
        {
            reader = new EndianReader(File.OpenRead(path), Endian.BigEndian);
            var versionInfo             = new CacheFileVersionInfo(reader);
            EngineDescription buildInfo =
                App.AssemblyStorage.AssemblySettings.DefaultDatabase.FindEngineByVersion(versionInfo.BuildString);

            return
                (new KeyValuePair <ICacheFile, EngineDescription>(new ThirdGenCacheFile(reader, buildInfo, versionInfo.BuildString),
                                                                  buildInfo));
        }
Example #4
0
        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));
        }
Example #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!");
            }
        }
Example #6
0
        private static ICacheFile CreateThirdGenCacheFile(IReader inputReader, EngineDescription buildInfo, CacheFileVersionInfo cacheFileVersion)
        {
            string buildString = cacheFileVersion.BuildString;

            return(new ThirdGenCacheFile(inputReader, buildInfo, buildString));
        }
Example #7
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);
            }
        }
Example #8
0
        private static void Main(string[] args)
        {
            if (args.Length != 3)
            {
                Console.WriteLine("Usage: mapexpand <map file> <section> <page count>");
                Console.WriteLine();
                Console.WriteLine("Available sections:");
                Console.WriteLine("  stringidindex");
                Console.WriteLine("  stringiddata");
                Console.WriteLine("  tagnameindex");
                Console.WriteLine("  tagnamedata");
                Console.WriteLine("  resource");
                Console.WriteLine("  tag");
                return;
            }

            int pageCount;

            if (!int.TryParse(args[2], out pageCount) || pageCount <= 0)
            {
                Console.WriteLine("The page count must be a positive integer.");
                return;
            }

            Console.WriteLine("Reading...");

            var stream  = new EndianStream(File.Open(args[0], FileMode.Open, FileAccess.ReadWrite), Endian.BigEndian);
            var version = new CacheFileVersionInfo(stream);

            if (version.Engine != EngineType.ThirdGeneration)
            {
                Console.WriteLine("Only third-generation map files are supported.");
                return;
            }

            var database  = XMLEngineDatabaseLoader.LoadDatabase("Formats/Engines.xml");
            var buildInfo = database.FindEngineByVersion(version.BuildString);
            var cacheFile = new ThirdGenCacheFile(stream, buildInfo, version.BuildString);

            FileSegmentGroup area;
            FileSegment      section;
            int pageSize;

            switch (args[1])
            {
            case "stringidindex":
                area     = cacheFile.StringArea;
                section  = cacheFile.StringIDIndexTable;
                pageSize = 0x1000;
                break;

            case "stringiddata":
                area     = cacheFile.StringArea;
                section  = cacheFile.StringIDDataTable;
                pageSize = 0x1000;
                break;

            case "tagnameindex":
                area     = cacheFile.StringArea;
                section  = cacheFile.FileNameIndexTable;
                pageSize = 0x1000;
                break;

            case "tagnamedata":
                area     = cacheFile.StringArea;
                section  = cacheFile.FileNameDataTable;
                pageSize = 0x1000;
                break;

            case "resource":
                area     = null;
                section  = cacheFile.RawTable;
                pageSize = 0x1000;
                break;

            case "tag":
                area     = cacheFile.MetaArea;
                section  = cacheFile.MetaArea.Segments[0];
                pageSize = 0x10000;
                break;

            default:
                Console.WriteLine("Invalid section name: \"{0}\"", args[1]);
                return;
            }

            Console.WriteLine("- Engine version: {0}", version.BuildString);
            Console.WriteLine("- Internal name: {0}", cacheFile.InternalName);
            Console.WriteLine("- Scenario name: {0}", cacheFile.ScenarioName);
            Console.WriteLine();

            Console.WriteLine("Injecting empty pages...");

            var injectSize = pageCount * pageSize;

            section.Resize(section.Size + injectSize, stream);

            Console.WriteLine("Adjusting the header...");

            cacheFile.SaveChanges(stream);
            stream.Dispose();

            Console.WriteLine();

            var offset = section.Offset;

            if (section.ResizeOrigin == SegmentResizeOrigin.End)
            {
                offset += section.ActualSize - injectSize;
            }

            if (area != null)
            {
                Console.WriteLine("Successfully injected 0x{0:X} bytes at 0x{1:X} (offset 0x{2:X}).", injectSize, area.BasePointer, offset);
            }
            else
            {
                Console.WriteLine("Successfully injected 0x{0:X} bytes at offset 0x{1:X}.", injectSize, offset);
            }
        }