Example #1
0
        public static Dictionary <string, IEnumerable <UnitSeatMapping> > LoadAllSeatMappings(string path, EngineDatabase db, out EngineDescription engineInfo)
        {
            Dictionary <string, IEnumerable <UnitSeatMapping> > result = new Dictionary <string, IEnumerable <UnitSeatMapping> >();

            string fileName = Path.GetFileNameWithoutExtension(path);

            using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                var reader = new EndianReader(stream, Endian.BigEndian);
                var cache  = CacheFileLoader.LoadCacheFile(reader, fileName, db, out engineInfo);
                if (cache.Type != CacheFileType.Shared && cache.Type != CacheFileType.SinglePlayerShared && cache.ScriptFiles.Length > 0)
                {
                    foreach (var file in cache.ScriptFiles)
                    {
                        if (file is ScnrScriptFile scnr)
                        {
                            var mappings = SeatMappingNameExtractor.ExtractScnrSeatMappings(scnr, reader, engineInfo.ScriptInfo);

                            if (mappings.Any())
                            {
                                result[file.Name] = mappings;
                            }
                        }
                    }
                }
            }

            return(result);
        }
Example #2
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);
            }
        }
Example #3
0
        private static void DumpSharedResources(string mapPath, EngineDatabase db)
        {
            ICacheFile    cacheFile;
            ResourceTable resources;

            using (var reader = new EndianReader(File.OpenRead(mapPath), Endian.BigEndian))
            {
                cacheFile = CacheFileLoader.LoadCacheFile(reader, db);
                resources = cacheFile.Resources.LoadResourceTable(reader);
            }

            using (var output = new StreamWriter(Path.ChangeExtension(mapPath, ".txt")))
            {
                output.WriteLine("Shared resources referenced by {0}:", Path.GetFileName(mapPath));
                output.WriteLine();
                output.WriteLine("Rsrc Datum  Map File      Class  Tag");
                output.WriteLine("----------  --------      -----  ---");

                foreach (Resource resource in resources.Resources.Where(r => r.Location != null && r.ParentTag != null))
                {
                    // If either page has a null file path, then it's shared
                    ResourcePointer loc           = resource.Location;
                    string          primaryFile   = (loc.PrimaryPage != null) ? loc.PrimaryPage.FilePath : null;
                    string          secondaryFile = (loc.SecondaryPage != null) ? loc.SecondaryPage.FilePath : null;
                    if (primaryFile != null || secondaryFile != null)
                    {
                        string className = CharConstant.ToString(resource.ParentTag.Class.Magic);
                        string name      = cacheFile.FileNames.GetTagName(resource.ParentTag) ?? resource.ParentTag.Index.ToString();
                        string fileName  = primaryFile ?? secondaryFile;
                        fileName = fileName.Substring(fileName.IndexOf('\\') + 1);
                        output.WriteLine("{0}  {1, -12}  {2}   {3}", resource.Index, fileName, className, name);
                    }
                }
            }
        }
        private KeyValuePair <ICacheFile, EngineDescription> LoadMap(string path, out IReader reader)
        {
            reader = new EndianReader(File.OpenRead(path), Endian.BigEndian);

            var cacheFile = CacheFileLoader.LoadCacheFile(reader, path, App.AssemblyStorage.AssemblySettings.DefaultDatabase, out EngineDescription buildInfo);

            return
                (new KeyValuePair <ICacheFile, EngineDescription>(cacheFile, buildInfo));
        }
Example #5
0
    public IEnumerator Load(string source, Func <T, IEnumerator> finish = null, Action <string> error = null, Action <float, string> progress = null)
    {
        finishLoad   = finish;
        errorLoad    = error;
        progressLoad = progress;
        cacheSource  = CacheFileLoader.CacheStreamKey(source);
        isInProgress = true;

        yield return(childLoader.Load(source));
    }
        public static async Task Create(Dictionary <string, string> arguments, Dictionary <string, string> options)
        {
            await Task.Delay(1);

            var cacheFilePath    = arguments["cache"];
            var projectDirectory = arguments["project"];

            // Check file exists
            if (cacheFilePath == null || !File.Exists(cacheFilePath))
            {
                throw new ComposerException("Cache doesn't exist");
            }

            // Create project directory
            // TODO: think about logic if directory already exists
            if (!Directory.Exists(projectDirectory))
            {
                Directory.CreateDirectory(projectDirectory);
            }

            // Create Project
            var project = new Models.Project
            {
                Title       = "Example Halo Project",
                Version     = "1.0.0",
                Description = "Simple project for testing the tool",
                Properties  = new ProjectProperties
                {
                    TagsFolder = "tags",
                    GitEnabled = true
                }
            };

            using (var stream = File.OpenRead(cacheFilePath))
                using (var reader = new EndianReader(stream, Endian.BigEndian))
                {
                    EngineDescription engineDescription = null;
                    EngineDatabase    engineDatabase    = XMLEngineDatabaseLoader.LoadDatabase("data/formats/engines.xml");
                    var cacheFile    = CacheFileLoader.LoadCacheFile(reader, engineDatabase, out engineDescription);
                    var stringIdTrie = new Trie();
                    if (cacheFile.StringIDs != null)
                    {
                        stringIdTrie.AddRange(cacheFile.StringIDs);
                    }

                    if (cacheFile.TagClasses.Any())
                    {
                        LoadTags(project, cacheFile, projectDirectory, stringIdTrie);
                    }
                }

            File.WriteAllText(Path.Combine(projectDirectory, "project.json"), JsonConvert.SerializeObject(project, Formatting.Indented));
        }
Example #7
0
        public static IEnumerable <ICacheFile> LoadAllMaps(string[] paths, EngineDatabase db)
        {
            List <ICacheFile> result = new List <ICacheFile>();

            foreach (string path in paths)
            {
                using var stream = new FileStream(path, FileMode.Open, FileAccess.Read);
                var reader = new EndianReader(stream, Endian.BigEndian);
                var cache  = CacheFileLoader.LoadCacheFile(reader, Path.GetFileNameWithoutExtension(path), db);
                result.Add(cache);
            }
            return(result);
        }
Example #8
0
        private static ScriptTable LoadScripts(string path, EngineDatabase db, out EngineDescription desc)
        {
            using (var stream = File.OpenRead(path))
            {
                EngineDescription engine;

                var reader = new EndianReader(stream, Endian.BigEndian);
                var cache  = CacheFileLoader.LoadCacheFile(reader, Path.GetFileName(path), db, out engine);
                desc = engine;
                var scripts = cache.ScriptFiles[0].LoadScripts(reader);

                return(scripts);
            }
        }
        public static bool applyPatch(ZipArchiveEntry zippedPatchFile, string patchFileName, string unmoddedMapPath, string outputPath)
        {
            createTmpDir();
            try {
                zippedPatchFile.ExtractToFile(Config.modpack_dir + @"\tmp\" + patchFileName);
            } catch (IOException) {
                rmTmpDir();
                createTmpDir();
                zippedPatchFile.ExtractToFile(Config.modpack_dir + @"\tmp\" + patchFileName);
            }
            Patch currentPatch = LoadPatch(Config.modpack_dir + @"\tmp\" + patchFileName);

            // Copy the original map to the destination path
            IO.CopyFile(unmoddedMapPath, outputPath, true);             //if modpack has written to unmoddedmap, take from backups

            // Open the destination map
            using (var stream = new EndianStream(File.Open(outputPath, FileMode.Open, FileAccess.ReadWrite), Endian.BigEndian)) {
                EngineDatabase engineDb = XMLEngineDatabaseLoader.LoadDatabase("Formats/Engines.xml");
                ICacheFile     cacheFile;
                try {
                    cacheFile = CacheFileLoader.LoadCacheFile(stream, engineDb);
                } catch (NotSupportedException nse) {
                    form1.showMsg("Error patching '" + patchFileName + "':" + nse.Message, "Error");
                    return(false);
                }
                if (!string.IsNullOrEmpty(currentPatch.BuildString) && cacheFile.BuildString != currentPatch.BuildString)
                {
                    form1.showMsg("Unable to patch. That patch is for a map with a build version of " + currentPatch.BuildString +
                                  ", and the unmodified map file doesn't match that.", "Error");
                    return(false);
                }

                if (currentPatch.MapInternalName == null)
                {
                    // Because Ascension doesn't include this, and ApplyPatch() will complain otherwise
                    currentPatch.MapInternalName = cacheFile.InternalName;
                }

                // Apply the patch!
                try {
                    PatchApplier.ApplyPatch(currentPatch, cacheFile, stream);
                } catch (ArgumentException ae) {
                    form1.showMsg("There was an issue applying the patch file '" + patchFileName + "': " + ae.Message, "Info");
                    return(false);
                }
            }

            rmTmpDir();
            return(true);
        }
Example #10
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 #11
0
    public override IEnumerator BeforeLoad(string source)
    {
        //create query string from url
        memoryKey = CacheFileLoader.CacheStreamKey(source);


        //query from image dictionary
        //if we have a texture with this key
        //we can take it and break;
        if (memoryData.ContainsKey(memoryKey))
        {
            InnerFinishLoad(memoryData[memoryKey]);
            yield break;
        }
    }
Example #12
0
        public static Dictionary <string, ScriptTable> LoadAllScriptFiles(string path, EngineDatabase db, out EngineDescription engineInfo)
        {
            Dictionary <string, ScriptTable> result = new Dictionary <string, ScriptTable>();

            using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                var reader = new EndianReader(stream, Endian.BigEndian);
                var cache  = CacheFileLoader.LoadCacheFile(reader, path, db, out engineInfo);
                if (cache.Type != CacheFileType.Shared && cache.Type != CacheFileType.SinglePlayerShared && cache.ScriptFiles.Length > 0)
                {
                    foreach (var file in cache.ScriptFiles)
                    {
                        result.Add(file.Name, file.LoadScripts(reader));
                    }
                }
            }
            return(result);
        }
Example #13
0
        private void StartGeneration()
        {
            _isWorking = true;

            btnInputFolder.IsEnabled             =
                btnOutputFolder.IsEnabled        =
                    btnGeneratePlugins.IsEnabled = false;

            MaskingPage.Visibility = Visibility.Visible;

            List <MapEntry> generatorMaps = GeneratorMaps.Where(m => m.IsSelected).ToList();
            string          outputPath    = txtOutputFolder.Text;

            EngineDescription picked   = null;
            string            firstMap = generatorMaps.First().LocalMapPath;

            using (FileStream fs = File.OpenRead(firstMap))
            {
                using (EndianReader reader = new EndianReader(fs, Endian.BigEndian))
                {
                    var matches = CacheFileLoader.FindEngineDescriptions(reader, App.AssemblyStorage.AssemblySettings.DefaultDatabase);

                    if (matches.Count > 1)
                    {
                        picked = MetroEnginePicker.Show(firstMap, matches);
                    }
                }
            }

            var worker = new BackgroundWorker();

            worker.DoWork += (o, args) => worker_DoWork(o, args, generatorMaps, outputPath, worker, picked);
            worker.WorkerReportsProgress = true;
            worker.ProgressChanged      += worker_ProgressChanged;
            worker.RunWorkerCompleted   += worker_RunWorkerCompleted;
            worker.RunWorkerAsync();
        }
Example #14
0
        // Patch Applying
        private void btnApplyPatch_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // Check the user isn't completly retarded
                if (!CheckAllApplyMandatoryFields() || currentPatch == null)
                {
                    return;
                }

                // Check the output name
                if (cacheOutputName != "")
                {
                    if (Path.GetFileNameWithoutExtension(txtApplyPatchOutputMap.Text) != cacheOutputName)
                    {
                        if (MetroMessageBox.Show("Warning",
                                                 "This patch suggests to use the filename \"" + cacheOutputName +
                                                 ".map\" to save this map. This filename may be required in order for the map to work correctly.\r\n\r\nAre you sure you want to save this map as \"" +
                                                 Path.GetFileName(txtApplyPatchOutputMap.Text) + "\"?",
                                                 MetroMessageBox.MessageBoxButtons.OkCancel) != MetroMessageBox.MessageBoxResult.OK)
                        {
                            Close();
                            return;
                        }
                    }
                }

                // Paths
                string unmoddedMapPath = txtApplyPatchUnmodifiedMap.Text;
                string outputPath      = txtApplyPatchOutputMap.Text;

                // Copy the original map to the destination path
                File.Copy(unmoddedMapPath, outputPath, true);

                // Open the destination map
                using (var stream = new EndianStream(File.Open(outputPath, FileMode.Open, FileAccess.ReadWrite), Endian.BigEndian))
                {
                    EngineDatabase engineDb  = XMLEngineDatabaseLoader.LoadDatabase("Formats/Engines.xml");
                    ICacheFile     cacheFile = CacheFileLoader.LoadCacheFile(stream, outputPath, engineDb);
                    if (currentPatch.MapInternalName != null && cacheFile.InternalName != currentPatch.MapInternalName)
                    {
                        MetroMessageBox.Show("Unable to apply patch",
                                             "Hold on there! That patch is for " + currentPatch.MapInternalName +
                                             ".map, and the unmodified map file you selected doesn't seem to match that. Find the correct file and try again.");
                        return;
                    }
                    if (!string.IsNullOrEmpty(currentPatch.BuildString) && cacheFile.BuildString != currentPatch.BuildString)
                    {
                        MetroMessageBox.Show("Unable to apply patch",
                                             "Hold on there! That patch is for a map with a build version of" + currentPatch.BuildString +
                                             ", and the unmodified map file you selected doesn't seem to match that. Find the correct file and try again.");
                        return;
                    }

                    // Apply the patch!
                    if (currentPatch.MapInternalName == null)
                    {
                        currentPatch.MapInternalName = cacheFile.InternalName;
                    }
                    // Because Ascension doesn't include this, and ApplyPatch() will complain otherwise

                    PatchApplier.ApplyPatch(currentPatch, cacheFile, stream);

                    // Check for blf snaps
                    if (cbApplyPatchBlfExtraction.IsChecked != null &&
                        (PatchApplicationPatchExtra.Visibility == Visibility.Visible && (bool)cbApplyPatchBlfExtraction.IsChecked))
                    {
                        string extractDir   = Path.GetDirectoryName(outputPath);
                        string blfDirectory = Path.Combine(extractDir, "images");
                        string infDirectory = Path.Combine(extractDir, "info");
                        if (!Directory.Exists(blfDirectory))
                        {
                            Directory.CreateDirectory(blfDirectory);
                        }
                        if (!Directory.Exists(infDirectory))
                        {
                            Directory.CreateDirectory(infDirectory);
                        }

                        string infPath = Path.Combine(infDirectory, Path.GetFileName(currentPatch.CustomBlfContent.MapInfoFileName));
                        File.WriteAllBytes(infPath, currentPatch.CustomBlfContent.MapInfo);

                        foreach (BlfContainerEntry blfContainerEntry in currentPatch.CustomBlfContent.BlfContainerEntries)
                        {
                            string blfPath = Path.Combine(blfDirectory, Path.GetFileName(blfContainerEntry.FileName));
                            File.WriteAllBytes(blfPath, blfContainerEntry.BlfContainer);
                        }
                    }
                }

                MetroMessageBox.Show("Patch Applied!", "Your patch has been applied successfully. Have fun!");
            }
            catch (Exception ex)
            {
                MetroException.Show(ex);
            }
        }
Example #15
0
        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();
        }
Example #16
0
        // Patch Creation
        private void btnCreatePatch_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // Check the user isn't completly retarded
                if (!CheckAllCreateMandatoryFields())
                {
                    return;
                }

                // Check the user isn't a skid
                if (!CheckAllCreateMetaFilesExists())
                {
                    return;
                }

                // Paths
                string cleanMapPath  = txtCreatePatchUnModifiedMap.Text;
                string moddedMapPath = txtCreatePatchModifiedMap.Text;
                string outputPath    = txtCreatePatchOutputPatch.Text;
                string previewImage  = txtCreatePatchPreviewImage.Text;

                // Details
                string author     = txtCreatePatchContentAuthor.Text;
                string desc       = txtCreatePatchContentDescription.Text;
                string name       = txtCreatePatchContentName.Text;
                string outputName = txtCreatePatchOutputName.Text;

                // Make dat patch
                var patch = new Patch
                {
                    Author      = author,
                    Description = desc,
                    Name        = name,
                    OutputName  = outputName,
                    Screenshot  = String.IsNullOrEmpty(previewImage)
                                                ? null
                                                : File.ReadAllBytes(previewImage),
                    BuildString = _buildInfo.Version,
                    PC          = String.IsNullOrEmpty(_buildInfo.GameExecutable)
                                                ? false
                                                : true
                };

                EndianReader originalReader = null;
                EndianReader newReader      = null;
                try
                {
                    originalReader = new EndianReader(File.OpenRead(cleanMapPath), Endian.BigEndian);
                    newReader      = new EndianReader(File.OpenRead(moddedMapPath), Endian.BigEndian);

                    ICacheFile originalFile = CacheFileLoader.LoadCacheFile(originalReader, cleanMapPath,
                                                                            App.AssemblyStorage.AssemblySettings.DefaultDatabase);
                    ICacheFile newFile = CacheFileLoader.LoadCacheFile(newReader, moddedMapPath, App.AssemblyStorage.AssemblySettings.DefaultDatabase);

                    if (cbCreatePatchHasCustomMeta.IsChecked != null && (bool)cbCreatePatchHasCustomMeta.IsChecked &&
                        cboxCreatePatchTargetGame.SelectedIndex < 4)
                    {
                        var      targetGame      = (TargetGame)cboxCreatePatchTargetGame.SelectedIndex;
                        byte[]   mapInfo         = File.ReadAllBytes(txtCreatePatchMapInfo.Text);
                        var      mapInfoFileInfo = new FileInfo(txtCreatePatchMapInfo.Text);
                        FileInfo blfFileInfo;

                        patch.CustomBlfContent = new BlfContent(mapInfoFileInfo.FullName, mapInfo, targetGame);

                        #region Blf Data

                        if (PatchCreationBlfOption0.Visibility == Visibility.Visible)
                        {
                            blfFileInfo = new FileInfo(txtCreatePatchblf0.Text);
                            patch.CustomBlfContent.BlfContainerEntries.Add(new BlfContainerEntry(blfFileInfo.Name,
                                                                                                 File.ReadAllBytes(blfFileInfo.FullName)));
                        }
                        if (PatchCreationBlfOption1.Visibility == Visibility.Visible)
                        {
                            blfFileInfo = new FileInfo(txtCreatePatchblf1.Text);
                            patch.CustomBlfContent.BlfContainerEntries.Add(new BlfContainerEntry(blfFileInfo.Name,
                                                                                                 File.ReadAllBytes(blfFileInfo.FullName)));
                        }
                        if (PatchCreationBlfOption2.Visibility == Visibility.Visible)
                        {
                            blfFileInfo = new FileInfo(txtCreatePatchblf2.Text);
                            patch.CustomBlfContent.BlfContainerEntries.Add(new BlfContainerEntry(blfFileInfo.Name,
                                                                                                 File.ReadAllBytes(blfFileInfo.FullName)));
                        }
                        if (PatchCreationBlfOption3.Visibility == Visibility.Visible)
                        {
                            blfFileInfo = new FileInfo(txtCreatePatchblf3.Text);
                            patch.CustomBlfContent.BlfContainerEntries.Add(new BlfContainerEntry(blfFileInfo.Name,
                                                                                                 File.ReadAllBytes(blfFileInfo.FullName)));
                        }

                        #endregion
                    }

                    PatchBuilder.BuildPatch(originalFile, originalReader, newFile, newReader, patch);
                }
                finally
                {
                    if (originalReader != null)
                    {
                        originalReader.Dispose();
                    }
                    if (newReader != null)
                    {
                        newReader.Dispose();
                    }
                }

                IWriter output = new EndianWriter(File.Open(outputPath, FileMode.Create, FileAccess.Write), Endian.BigEndian);
                AssemblyPatchWriter.WritePatch(patch, output);
                output.Dispose();

                MetroMessageBox.Show("Patch Created!",
                                     "Your patch has been created in the designated location. Happy sailing, modder!");
            }
            catch (Exception ex)
            {
                MetroException.Show(ex);
            }
        }
Example #17
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 database  = XMLEngineDatabaseLoader.LoadDatabase("Formats/Engines.xml");
            var buildInfo = CacheFileLoader.FindEngineDescription(stream, database);

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

            var cacheFile = new ThirdGenCacheFile(stream, buildInfo, args[0]);

            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}", buildInfo.BuildVersion);
            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);
            }
        }
Example #18
0
        // TODO (Dragon): support CEA 360 with LZX
        private static CompressionState DetermineState(IReader reader, EngineDatabase engineDb, out EngineDescription engineInfo, out StructureValueCollection headerValues)
        {
            headerValues = null;
            // not all compressed maps have a decompressed header
            // so we handle that here
            try
            {
                // Load engine version info
                engineInfo = CacheFileLoader.FindEngineDescription(reader, engineDb);
            }
            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);
                    engineInfo = CacheFileLoader.FindEngineDescription(header_reader, engineDb);
                }
            }

            // if engine wasnt set its because we couldnt read a proper header, throw an exception
            if (engineInfo == null || !engineInfo.UsesCompression)
            {
                return(CompressionState.Null);
            }

            if (engineInfo.Engine == EngineType.FirstGeneration)
            {
                return(AnalyzeFirstGen(reader, engineInfo, out headerValues));
            }
            else if (engineInfo.Engine == EngineType.SecondGeneration)
            {
                return(AnalyzeSecondGen(reader, engineInfo, out headerValues));
            }
            else
            {
                return(CompressionState.Null);
            }
        }
Example #19
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 #20
0
        static void Main(string[] args)
        {
            if (args.Length != 3)
            {
                Console.WriteLine("Usage: BlockAlignmentScanner <map dir> <in plugin dir> <out plugin dir>");
                return;
            }

            var mapDir = args[0];
            var inDir  = args[1];
            var outDir = args[2];

            Console.WriteLine("Loading plugins...");
            var pluginsByClass = new Dictionary <string, XDocument>();

            foreach (var pluginPath in Directory.EnumerateFiles(inDir, "*.xml"))
            {
                Console.WriteLine("- {0}", pluginPath);
                var document  = XDocument.Load(pluginPath);
                var className = Path.GetFileNameWithoutExtension(pluginPath);
                pluginsByClass[className] = document;
            }

            Console.WriteLine("Loading engine database...");
            var exeDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            var dbPath = Path.Combine(exeDir, "Formats", "Engines.xml");
            var db     = XMLEngineDatabaseLoader.LoadDatabase(dbPath);

            Console.WriteLine("Processing maps...");
            var alignsByElem = new Dictionary <XElement, int>();

            foreach (var mapPath in Directory.EnumerateFiles(mapDir, "*.map"))
            {
                Console.WriteLine("- {0}", Path.GetFileName(mapPath));
                using (var reader = new EndianReader(File.OpenRead(mapPath), Endian.BigEndian))
                {
                    var map = CacheFileLoader.LoadCacheFile(reader, db);
                    var visitedTagBlocks = new HashSet <uint>();
                    foreach (var tag in map.Tags)
                    {
                        if (tag == null || tag.Class == null || tag.MetaLocation == null)
                        {
                            continue;
                        }

                        // Get the plugin for the tag
                        var       className = CharConstant.ToString(tag.Class.Magic);
                        XDocument plugin;
                        if (!pluginsByClass.TryGetValue(className, out plugin))
                        {
                            continue;
                        }

                        // Process it
                        var baseOffset  = tag.MetaLocation.AsOffset();
                        var baseElement = plugin.Element("plugin");
                        DetectAlignment(map, reader, baseOffset, baseElement, alignsByElem, visitedTagBlocks);
                    }
                }
            }

            Console.WriteLine("Adjusting plugins...");
            foreach (var align in alignsByElem)
            {
                if (align.Value != 4)
                {
                    Console.WriteLine("- \"{0}\" -> align 0x{1:X}", align.Key.Attribute("name").Value, align.Value);
                    align.Key.SetAttributeValue(XName.Get("align"), "0x" + align.Value.ToString("X"));
                }
            }

            if (!Directory.Exists(outDir))
            {
                Directory.CreateDirectory(outDir);
            }

            Console.WriteLine("Saving plugins...");
            foreach (var plugin in pluginsByClass)
            {
                var outPath = Path.Combine(outDir, plugin.Key + ".xml");
                Console.WriteLine("- {0}", outPath);

                var settings = new XmlWriterSettings();
                settings.Indent      = true;
                settings.IndentChars = "\t";
                using (var writer = XmlWriter.Create(outPath, settings))
                    plugin.Value.Save(writer);
            }
        }
Example #21
0
        private static void Main(string[] args)
        {
            var ofd = new OpenFileDialog();

            ofd.Title  = "Open Cache File";
            ofd.Filter = "Blam Cache Files|*.map";
            if (ofd.ShowDialog() != DialogResult.OK)
            {
                return;
            }

            var sfd = new SaveFileDialog();

            sfd.Title  = "Save String Dump";
            sfd.Filter = "Text Files|*.txt";
            if (sfd.ShowDialog() != DialogResult.OK)
            {
                return;
            }

            string mapPath  = ofd.FileName;
            string dumpPath = sfd.FileName;

            EngineDatabase engineDb = XMLEngineDatabaseLoader.LoadDatabase("Formats/Engines.xml");
            ICacheFile     cacheFile;
            LanguagePack   locales;

            using (IReader reader = new EndianReader(File.OpenRead(mapPath), Endian.BigEndian))
            {
                Console.WriteLine("Loading cache file...");
                cacheFile = CacheFileLoader.LoadCacheFile(reader, mapPath, engineDb);

                Console.WriteLine("Loading locales...");
                locales = cacheFile.Languages.LoadLanguage(GameLanguage.English, reader);
            }

            var output = new StreamWriter(dumpPath);

            output.WriteLine("Input file: {0}.map", cacheFile.InternalName);
            output.WriteLine();

            // Sort locales by stringID
            var localesById = new List <LocalizedString>();

            localesById.AddRange(locales.StringLists.SelectMany(l => l.Strings).Where(s => s != null && s.Value != null));
            localesById.Sort((x, y) => x.Key.Value.CompareTo(y.Key.Value));

            // Dump locales
            Console.WriteLine("Dumping locales...");
            output.WriteLine("---------------");
            output.WriteLine("English Locales");
            output.WriteLine("---------------");
            foreach (LocalizedString str in localesById)
            {
                if (str != null)
                {
                    output.WriteLine("{0} = \"{1}\"", str.Key, str.Value);
                }
            }
            output.WriteLine();

            // Dump stringIDs
            Console.WriteLine("Dumping stringIDs...");
            output.WriteLine("---------");
            output.WriteLine("StringIDs");
            output.WriteLine("---------");
            int index = 0;

            foreach (string str in cacheFile.StringIDs)
            {
                if (str != null)
                {
                    output.WriteLine("0x{0:X} = \"{1}\"", index, str);
                }
                else
                {
                    output.WriteLine("0x{0:X} = (null)", index);
                }

                index++;
            }
            output.Close();

            Console.WriteLine("Done!");
        }