Example #1
0
        /// <summary>
        ///     Loads a cache file from a stream.
        /// </summary>
        /// <param name="reader">The stream to read from.</param>
        /// <param name="engineDb">The engine database to use to process the cache file.</param>
        /// <param name="engineInfo">On output, this will contain the cache file's engine description.</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, EngineDatabase engineDb, out EngineDescription engineInfo)
        {
            // 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
            var version = new CacheFileVersionInfo(reader);

            if (version.Engine != EngineType.SecondGeneration && version.Engine != EngineType.ThirdGeneration)
            {
                throw new NotSupportedException("Engine not supported");
            }

            // Load build info
            engineInfo = engineDb.FindEngineByVersion(version.BuildString);
            if (engineInfo == 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, engineInfo, version.BuildString));

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

            default:
                throw new NotSupportedException("Engine not supported");
            }
        }
Example #2
0
        /// <summary>
        ///     Loads a cache file from a stream.
        /// </summary>
        /// <param name="reader">The stream to read from.</param>
        /// <param name="engineDb">The engine database to use to process the cache file.</param>
        /// <param name="engineInfo">On output, this will contain the cache file's engine description.</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, EngineDatabase engineDb, out EngineDescription engineInfo)
        {
            // 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
            var version = new CacheFileVersionInfo(reader);
            if (version.Engine != EngineType.SecondGeneration && version.Engine != EngineType.ThirdGeneration)
                throw new NotSupportedException("Engine not supported");

            // Load build info
            engineInfo = engineDb.FindEngineByVersion(version.BuildString);
            if (engineInfo == 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, engineInfo, version.BuildString);

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

                default:
                    throw new NotSupportedException("Engine not supported");
            }
        }
Example #3
0
        /// <summary>
        ///     Loads a cache file from a stream.
        /// </summary>
        /// <param name="reader">The stream to read from.</param>
        /// <param name="engineDb">The engine database to use to process the cache file.</param>
        /// <param name="engineInfo">On output, this will contain the cache file's engine description.</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 map_reader, IReader tag_reader, IReader string_reader, out string tagnamesLocation, string filesLocation, EngineDatabase engineDb, out EngineDescription engineInfo)
        {
            // Set the reader's endianness based upon the file's header magic
            map_reader.SeekTo(0);
            byte[] headerMagic = map_reader.ReadBlock(4);
            Endian engianess = DetermineCacheFileEndianness(headerMagic);
            map_reader.Endianness = engianess;
            if(tag_reader != null) tag_reader.Endianness = engianess;
            if (tag_reader != null) string_reader.Endianness = engianess;

            // Load engine version info
            var version = new CacheFileVersionInfo(map_reader);
            if (version.Engine != EngineType.SecondGeneration && version.Engine != EngineType.ThirdGeneration && version.Engine != EngineType.FourthGeneration)
                throw new NotSupportedException("Engine not supported");

            // Load build info
            engineInfo = engineDb.FindEngineByVersion(version.BuildString);
            if (engineInfo == 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:
                    tagnamesLocation = null;
                    return new SecondGenCacheFile(map_reader, engineInfo, version.BuildString);

                case EngineType.ThirdGeneration:
                    tagnamesLocation = null;
                    return new ThirdGenCacheFile(map_reader, engineInfo, version.BuildString);

                case EngineType.FourthGeneration:
                    if (tag_reader == null || tag_reader.BaseStream.Length == 0) throw new Exception("Can't load version 4 cache file without tags file. Please make sure that tags.dat is in the same folder at the map file.");
                    if (string_reader == null || tag_reader.BaseStream.Length == 0) throw new Exception("Can't load version 4 cache file without strings file. Please make sure that tags.dat is in the same folder at the map file.");

                    // Load the tag names csv file
                    string tagnames_filename = "tagnames_" + version.BuildString + ".csv";
                    string tagnames_location = filesLocation != null ? filesLocation + tagnames_filename : "";
                    if (!File.Exists(tagnames_location)) tagnames_location = "tagnames\\" + tagnames_filename;
                    if (!File.Exists(tagnames_location)) tagnames_location = null;

                    FileStream tagnamesFileStream = tagnames_location != null ? TryInitFilestream(tagnames_location) : null;
                    EndianReader tagnames_reader = null;
                    if (tagnamesFileStream != null)
                    {
                        tagnames_reader = new EndianReader(tagnamesFileStream, Endian.BigEndian);
                        tagnames_reader.Endianness = engianess;
                    }

                    tagnamesLocation = tagnames_location;

                    FourthGenCacheFile cache_file = new FourthGenCacheFile(map_reader, tag_reader, string_reader, tagnames_reader, engineInfo, version.BuildString);
                    tagnamesFileStream.Close();
                    return cache_file;

                default:
                    throw new NotSupportedException("Engine not supported");
            }
        }
Example #4
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);
			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();
		}
        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 #6
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.Close();

            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 #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();
        }
        /// <summary>
        ///     Loads a cache file from a stream.
        /// </summary>
        /// <param name="reader">The stream to read from.</param>
        /// <param name="engineDb">The engine database to use to process the cache file.</param>
        /// <param name="engineInfo">On output, this will contain the cache file's engine description.</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 map_reader, IReader tag_reader, IReader string_reader, out string tagnamesLocation, string filesLocation, EngineDatabase engineDb, out EngineDescription engineInfo, string tagsLocation, string stringsLocation)
        {
            // Set the reader's endianness based upon the file's header magic
            map_reader.SeekTo(0);
            byte[] headerMagic = map_reader.ReadBlock(4);
            Endian engianess   = DetermineCacheFileEndianness(headerMagic);

            map_reader.Endianness = engianess;
            if (tag_reader != null)
            {
                tag_reader.Endianness = engianess;
            }
            if (tag_reader != null)
            {
                string_reader.Endianness = engianess;
            }

            // Load engine version info
            var version = new CacheFileVersionInfo(map_reader);

            if (version.Engine == EngineType.FirstGeneration)
            {
                throw new NotSupportedException("Engine not supported");
            }

            // Load build info
            engineInfo = engineDb.FindEngineByVersion(version.BuildString);
            if (engineInfo == 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:
                tagnamesLocation = null;
                return(new SecondGenCacheFile(map_reader, engineInfo, version.BuildString));

            case EngineType.ThirdGeneration:
                tagnamesLocation = null;
                return(new ThirdGenCacheFile(map_reader, engineInfo, version.BuildString));

            case EngineType.ThirdGenMCC:
                tagnamesLocation = null;
                return(new NewThirdGenCacheFile(map_reader, engineInfo, version.BuildString));


            case EngineType.FourthGeneration:
                if (tag_reader == null || tag_reader.BaseStream.Length == 0)
                {
                    throw new Exception("Can't load version 4 cache file without tags file. Please make sure that tags.dat is in the same folder at the map file.");
                }
                if (string_reader == null || tag_reader.BaseStream.Length == 0)
                {
                    throw new Exception("Can't load version 4 cache file without strings file. Please make sure that tags.dat is in the same folder at the map file.");
                }

                string tagnames_location = Path.Combine(Path.GetDirectoryName(tagsLocation), "tag_list.csv");


                if (!File.Exists(tagnames_location))
                {
                    tagnames_location = null;
                }

                if (tagnames_location == null)
                {
                    // Load the tag names csv file
                    string tagnames_filename = "tagnames_";
                    if (engineInfo.AltTagNames != null)
                    {
                        tagnames_filename += engineInfo.AltTagNames + ".csv";
                    }
                    else
                    {
                        tagnames_filename += version.BuildString + ".csv";
                    }
                    tagnames_location = filesLocation != null ? filesLocation + tagnames_filename : "";
                    if (File.Exists(tagnames_location))
                    {
                        tagnames_location = "tagnames\\" + tagnames_filename;
                    }
                    else
                    {
                        tagnames_location = null;
                    }
                }

                FileStream tagnamesFileStream = tagnames_location != null?TryInitFilestream(tagnames_location) : null;

                EndianReader tagnames_reader = null;
                if (tagnamesFileStream != null)
                {
                    tagnames_reader            = new EndianReader(tagnamesFileStream, Endian.BigEndian);
                    tagnames_reader.Endianness = engianess;
                }

                tagnamesLocation = tagnames_location;

                FourthGenCacheFile cache_file = new FourthGenCacheFile(map_reader, tag_reader, string_reader, tagnames_reader, engineInfo, version.BuildString);
                tagnamesFileStream.Close();
                return(cache_file);

            default:
                throw new NotSupportedException("Engine not supported");
            }
        }
        private KeyValuePair<ICacheFile, BuildInformation> LoadMap(string path, out IReader reader)
        {
            reader = new EndianReader(File.OpenRead(path), Endian.BigEndian);
            var versionInfo = new CacheFileVersionInfo(reader);
            var buildInfo = _buildLoader.LoadBuild(versionInfo.BuildString);

            return
                new KeyValuePair<ICacheFile, BuildInformation>(new ThirdGenCacheFile(reader, buildInfo, versionInfo.BuildString),
                                                               buildInfo);
        }