예제 #1
0
        /// <summary>
        /// Loads a cache file from a stream.
        /// </summary>
        /// <param name="reader">The stream to read from.</param>
        /// <param name="infoLoader">The BuildInfoLoader responsible for loading build information for the cache file.</param>
        /// <param name="buildInfo">The variable to store build information to.</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, BuildInfoLoader infoLoader, out BuildInformation buildInfo)
        {
            // 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
            CacheFileVersionInfo version = new CacheFileVersionInfo(reader);
            if (version.Engine != EngineType.SecondGeneration && version.Engine != EngineType.ThirdGeneration)
                throw new NotSupportedException("Engine not supported");

            // Load build info
            buildInfo = infoLoader.LoadBuild(version.BuildString);
            if (buildInfo == 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, buildInfo, version.BuildString);

                case EngineType.ThirdGeneration:
                    return new ThirdGenCacheFile(reader, buildInfo, version.BuildString);

                default:
                    throw new NotSupportedException("Engine not supported");
            }
        }
        public HaloPluginGenerator()
        {
            InitializeComponent();
            DataContext = GeneratorMaps;

            var supportedBuilds = XDocument.Load(@"Formats\SupportedBuilds.xml");
            _buildLoader = new BuildInfoLoader(supportedBuilds, @"Formats\");
        }
예제 #3
0
        static void Main(string[] args)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "Open Cache File";
            ofd.Filter = "Blam Cache Files|*.map";
            if (ofd.ShowDialog() != DialogResult.OK)
                return;

            SaveFileDialog 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;

            BuildInfoLoader loader = new BuildInfoLoader(@"Formats\SupportedBuilds.xml", "Formats");
            ICacheFile cacheFile;
            LocaleTable locales;
            using (IReader reader = new EndianReader(File.OpenRead(mapPath), Endian.BigEndian))
            {
                Console.WriteLine("Loading cache file...");
                cacheFile = CacheFileLoader.LoadCacheFile(reader, loader);

                Console.WriteLine("Loading locales...");
                locales = cacheFile.Languages[LocaleLanguage.English].LoadStrings(reader);
            }

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

            // Sort locales by stringID
            List<Locale> localesById = new List<Locale>();
            foreach (Locale str in locales.Strings)
            {
                if (str != null)
                    localesById.Add(str);
            }
            localesById.Sort((x, y) => x.ID.Value.CompareTo(y.ID.Value));

            // Dump locales
            Console.WriteLine("Dumping locales...");
            output.WriteLine("---------------");
            output.WriteLine("English Locales");
            output.WriteLine("---------------");
            foreach (Locale str in localesById)
            {
                if (str != null)
                    output.WriteLine("{0} = \"{1}\"", str.ID, 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!");
        }
예제 #4
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
                var cleanMapPath = txtCreatePatchUnModifiedMap.Text;
                var moddedMapPath = txtCreatePatchModifiedMap.Text;
                var outputPath = txtCreatePatchOutputPatch.Text;
                var previewImage = txtCreatePatchPreviewImage.Text;

                // Details
                var author = txtCreatePatchContentAuthor.Text;
                var desc = txtCreatePatchContentDescription.Text;
                var name = txtCreatePatchContentName.Text;

                // Make dat patch
                var patch = new Patch
                {
                    Author = author,
                    Description = desc,
                    Name = name,
                    Screenshot = String.IsNullOrEmpty(previewImage) ?
                        null :
                        File.ReadAllBytes(previewImage)
                };

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

                    var formatsPath = Path.Combine(VariousFunctions.GetApplicationLocation(), "Formats");
                    var loader = new BuildInfoLoader(Path.Combine(formatsPath, "SupportedBuilds.xml"), formatsPath);
                    var originalFile = CacheFileLoader.LoadCacheFile(originalReader, loader);
                    var newFile = CacheFileLoader.LoadCacheFile(originalReader, loader);

                    if (cbCreatePatchHasCustomMeta.IsChecked != null && (bool)cbCreatePatchHasCustomMeta.IsChecked && cboxCreatePatchTargetGame.SelectedIndex < 4)
                    {
                        var targetGame = (TargetGame)cboxCreatePatchTargetGame.SelectedIndex;
                        var 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.Close();
                    if (newReader != null)
                        newReader.Close();
                }

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

                MetroMessageBox.Show("Patch Created!", "Your patch has been created in the designated location. Happy sailing, modder!");
            }
            catch (Exception ex)
            {
                MetroException.Show(ex);
            }
        }
예제 #5
0
        // Patch Applying
        private void btnApplyPatch_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // Check the user isn't completly retarded
                if (!CheckAllApplyMandatoryFields() || currentPatch == null)
                    return;

                // Paths
                var unmoddedMapPath = txtApplyPatchUnmodifiedMap.Text;
                var 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))
                {
                    var formatsPath = Path.Combine(VariousFunctions.GetApplicationLocation(), "Formats");
                    var loader = new BuildInfoLoader(Path.Combine(formatsPath, "SupportedBuilds.xml"), formatsPath);
                    var cacheFile = CacheFileLoader.LoadCacheFile(stream, loader);
                    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;
                    }

                    // 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))
                    {
                        var extractDir = Path.GetDirectoryName(outputPath);
                        var blfDirectory = Path.Combine(extractDir, "images");
                        var infDirectory = Path.Combine(extractDir, "info");
                        if (!Directory.Exists(blfDirectory))
                            Directory.CreateDirectory(blfDirectory);
                        if (!Directory.Exists(infDirectory))
                            Directory.CreateDirectory(infDirectory);

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

                        foreach (var blfContainerEntry in currentPatch.CustomBlfContent.BlfContainerEntries)
                        {
                            var 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);
            }
        }
예제 #6
0
        public void InitalizeMap()
        {
            using (var fileStream = File.OpenRead(_cacheLocation))
            {
                var reader = new EndianReader(fileStream, Endian.BigEndian);
                var formatsPath = Path.Combine(VariousFunctions.GetApplicationLocation(), "Formats");
                var supportedBuildsPath = Path.Combine(formatsPath, "SupportedBuilds.xml");
                _layoutLoader = new BuildInfoLoader(supportedBuildsPath, formatsPath);
                try
                {
                    _cacheFile = CacheFileLoader.LoadCacheFile(reader, _layoutLoader, out _buildInfo);
                }
                catch (NotSupportedException ex)
                {
                    Dispatcher.Invoke(new Action(delegate
                                          {
                                              if (!_0xabad1dea.IWff.Heman(reader))
                                              {
                                                  StatusUpdater.Update("Not a supported target engine");
                                                  MetroMessageBox.Show("Unable to open cache file", ex.Message + ".\r\nWhy not add support in the 'Formats' folder?");
                                              }
                                              else
                                              {
                                                  StatusUpdater.Update("HEYYEYAAEYAAAEYAEYAA");
                                              }

                                              Settings.homeWindow.ExternalTabClose((TabItem)Parent);
                                          }));
                    return;
                }
                _mapManager = new FileStreamManager(_cacheLocation, reader.Endianness);

                // Build SID trie
                _stringIDTrie = new Trie();
                _stringIDTrie.AddRange(_cacheFile.StringIDs);

                Dispatcher.Invoke(new Action(delegate
                                      {
                                          if (Settings.startpageHideOnLaunch)
                                              Settings.homeWindow.ExternalTabClose(Home.TabGenre.StartPage);
                                      }));

                // Set up RTE
                switch (_cacheFile.Engine)
                {
                    case EngineType.SecondGeneration:
                        _rteProvider = new H2VistaRTEProvider("halo2.exe");
                        break;

                    case EngineType.ThirdGeneration:
                        _rteProvider = new XBDMRTEProvider(Settings.xbdm);
                        break;
                }

                Dispatcher.Invoke(new Action(() => StatusUpdater.Update("Loaded Cache File")));

                // Add to Recents
                Dispatcher.Invoke(new Action(delegate
                                      {
                                          RecentFiles.AddNewEntry(Path.GetFileName(_cacheLocation), _cacheLocation, _buildInfo.ShortName, Settings.RecentFileType.Cache);
                                          StatusUpdater.Update("Added To Recents");
                                      }));

                LoadHeader();
                LoadMetaData();
                LoadTags();
                LoadLocales();
                LoadScripts();
            }
        }
예제 #7
0
        static void Main(string[] args)
        {
            if (args.Length != 2)
            {
                Console.WriteLine("Usage: mapexpand <map file> <page count>");
                Console.WriteLine("Pages are multiples of 0x10000 bytes.");
                return;
            }

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

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

            EndianStream stream = new EndianStream(File.Open(args[0], FileMode.Open, FileAccess.ReadWrite), Endian.BigEndian);
            CacheFileVersionInfo version = new CacheFileVersionInfo(stream);
            if (version.Engine != EngineType.ThirdGeneration)
            {
                Console.WriteLine("Only third-generation map files are supported.");
                return;
            }

            BuildInfoLoader infoLoader = new BuildInfoLoader(XDocument.Load("Formats/SupportedBuilds.xml"), "Formats/");
            BuildInformation buildInfo = infoLoader.LoadBuild(version.BuildString);
            ThirdGenCacheFile cacheFile = new ThirdGenCacheFile(stream, buildInfo, version.BuildString);

            Console.WriteLine("- Engine version: {0}", version.BuildString);
            Console.WriteLine("- Internal name: {0}", cacheFile.InternalName);
            Console.WriteLine("- Scenario name: {0}", cacheFile.ScenarioName);
            Console.WriteLine("- File size: 0x{0:X}", cacheFile.FileSize);
            Console.WriteLine("- Virtual size: 0x{0:X}", cacheFile.MetaArea.Size);
            for (int i = 0; i < cacheFile.Partitions.Length; i++)
            {
                var partition = cacheFile.Partitions[i];
                if (partition.BasePointer != null)
                    Console.WriteLine("  - Partition {0} at 0x{1:X}-0x{2:X} (size=0x{3:X})", i, partition.BasePointer.AsPointer(), partition.BasePointer.AsPointer() + partition.Size - 1, partition.Size);
            }
            Console.WriteLine("- Meta pointer mask: 0x{0:X}", cacheFile.MetaArea.PointerMask);
            Console.WriteLine("- Locale pointer mask: 0x{0:X}", (uint)-cacheFile.LocaleArea.PointerMask);
            Console.WriteLine("- String pointer mask: 0x{0:X}", cacheFile.StringArea.PointerMask);
            Console.WriteLine();

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

            int injectSize = pageCount * 0x10000;
            Console.WriteLine("- Start address: 0x{0:X} (offset 0x{1:X})", cacheFile.MetaArea.BasePointer - injectSize, cacheFile.MetaArea.Offset);

            cacheFile.MetaArea.Resize(cacheFile.MetaArea.Size + injectSize, stream);

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

            cacheFile.SaveChanges(stream);

            Console.WriteLine();
            Console.WriteLine("Successfully injected 0x{0:X} bytes at 0x{1:X} (offset 0x{2:X}).", injectSize, cacheFile.MetaArea.BasePointer, cacheFile.MetaArea.Offset);

            stream.Close();
        }
예제 #8
0
 /// <summary>
 /// Loads a cache file from a stream.
 /// </summary>
 /// <param name="reader">The stream to read from.</param>
 /// <param name="infoLoader">The BuildInfoLoader responsible for loading build information for the cache file.</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, BuildInfoLoader infoLoader)
 {
     BuildInformation tempInfo;
     return LoadCacheFile(reader, infoLoader, out tempInfo);
 }