示例#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");
            }
        }
示例#2
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();
        }