예제 #1
0
        private MapFile GenerateMapFile(CachedTagInstance scenarioTag, Blf mapInfo = null)
        {
            MapFile  map    = new MapFile();
            var      header = new MapFileHeader();
            Scenario scnr;

            using (var stream = CacheContext.OpenTagCacheRead())
            {
                var deserializer = new TagDeserializer(CacheContext.Version);
                scnr = (Scenario)CacheContext.Deserialize(stream, scenarioTag);
            }

            map.Version      = CacheContext.Version;
            map.EndianFormat = EndianFormat.LittleEndian;
            map.MapVersion   = MapFileVersion.HaloOnline;

            header.HeadTag = new Tag("head");
            header.FootTag = new Tag("foot");
            header.Version = (int)map.MapVersion;
            header.Build   = CacheVersionDetection.GetBuildName(CacheContext.Version);

            switch (scnr.MapType)
            {
            case ScenarioMapType.MainMenu:
                header.CacheType = CacheFileType.MainMenu;
                break;

            case ScenarioMapType.SinglePlayer:
                header.CacheType = CacheFileType.Campaign;
                break;

            case ScenarioMapType.Multiplayer:
                header.CacheType = CacheFileType.Multiplayer;
                break;
            }
            header.SharedType = CacheFileSharedType.None;

            header.MapId            = scnr.MapId;
            header.ScenarioTagIndex = scenarioTag.Index;
            header.Name             = scenarioTag.Name.Split('\\').Last();
            header.ScenarioPath     = scenarioTag.Name;

            map.Header = header;

            header.FileLength = 0x3390;

            if (mapInfo != null)
            {
                if (mapInfo.ContentFlags.HasFlag(BlfFileContentFlags.StartOfFile) && mapInfo.ContentFlags.HasFlag(BlfFileContentFlags.EndOfFile) && mapInfo.ContentFlags.HasFlag(BlfFileContentFlags.Scenario))
                {
                    map.MapFileBlf = mapInfo;
                }
            }
            return(map);
        }
예제 #2
0
        public override object Execute(List <string> args)
        {
            if (args.Count != 4)
            {
                return(false);
            }

            if (!CacheContext.TryGetTag(args[0], out var srcTag))
            {
                return(false);
            }

            var csvPath    = args[1];
            var csvOutPath = args[2];
            var targetDir  = args[3];

            // Load the CSV
            Console.WriteLine("Reading {0}...", csvPath);
            TagVersionMap tagMap;

            using (var reader = new StreamReader(File.Exists(csvPath) ? File.OpenRead(csvPath) : File.Create(csvPath)))
                tagMap = TagVersionMap.ParseTagVersionMap(reader);

            // Load destination cache files
            var destCacheContext = new GameCacheContextHaloOnline(new DirectoryInfo(targetDir));

            using (var stream = destCacheContext.OpenTagCacheRead())
                destCacheContext.TagCache = new TagCache(stream, destCacheContext.LoadTagNames());

            Console.WriteLine();
            Console.WriteLine("CONVERTING FROM VERSION {0} TO {1}", CacheVersionDetection.GetBuildName(CacheContext.Version), CacheVersionDetection.GetBuildName(destCacheContext.Version));
            Console.WriteLine();

            CachedTagHaloOnline resultTag;

            using (Stream srcStream = CacheContext.TagCache.OpenTagCacheRead(), destStream = destCacheContext.OpenTagCacheReadWrite())
                resultTag = ConvertTag(srcTag, CacheContext, srcStream, destCacheContext, destStream, tagMap);

            Console.WriteLine();
            Console.WriteLine("Repairing decal systems...");

            if (CacheContext.Version != destCacheContext.Version)
            {
                FixDecalSystems(destCacheContext, resultTag.Index);
            }

            Console.WriteLine();
            Console.WriteLine("Saving stringIDs...");
            using (var stream = destCacheContext.OpenStringIdCacheReadWrite())
                destCacheContext.StringIdCache.Save(stream);

            Console.WriteLine("Writing {0}...", csvOutPath);
            using (var stream = new StreamWriter(File.Open(csvOutPath, FileMode.Create, FileAccess.ReadWrite)))
                tagMap.WriteCsv(stream);

            // Uncomment this to add the new tag as a dependency to cfgt to make testing easier

            /*using (var stream = destCacheContext.OpenCacheReadWrite())
             * {
             *  destCacheContext.Cache.Tags[0].Dependencies.Add(resultTag.Index);
             *  destCacheContext.Cache.UpdateTag(stream, destCacheContext.Cache.Tags[0]);
             * }*/

            Console.WriteLine();
            Console.WriteLine("All done! The converted tag is:");
            TagPrinter.PrintTagShort(resultTag);

            destCacheContext.SaveTagNames();

            return(true);
        }
예제 #3
0
        public override object Execute(List <string> args)
        {
            if (args.Count < 1)
            {
                return(false);
            }

            var memory = false;

            while (args.Count > 1)
            {
                switch (args[0].ToLower())
                {
                case "memory":
                    memory = true;
                    break;

                default:
                    throw new FormatException(args[0]);
                }

                args.RemoveAt(0);
            }

            var blamCacheFile = new FileInfo(args[0]);

            if (!blamCacheFile.Exists)
            {
                Console.WriteLine($"CacheFile {blamCacheFile.FullName} does not exist");
                return(true);
            }

            Console.Write("Loading blam cache file...");

            CacheFile blamCache = null;

            using (var cacheStream = new FileStream(blamCacheFile.FullName, FileMode.Open, FileAccess.Read))
            {
                var reader = new EndianReader(cacheStream, EndianFormat.BigEndian);

                var head = reader.ReadInt32();

                if (head == 1684104552)
                {
                    reader.Format = EndianFormat.LittleEndian;
                }

                var v = reader.ReadInt32();

                switch (v)
                {
                case 8:     // Gen2
                    reader.SeekTo(36);
                    switch (reader.ReadInt32())
                    {
                    case 0:         // Halo 2 Xbox
                        reader.SeekTo(288);
                        break;

                    case -1:         // Halo 2 Vista
                        reader.SeekTo(300);
                        break;
                    }
                    break;

                default:     // Gen3+
                    reader.SeekTo(284);
                    break;
                }

                var version = CacheVersionDetection.GetFromBuildName(reader.ReadString(32));

                switch (version)
                {
                case CacheVersion.Halo2Xbox:
                case CacheVersion.Halo2Vista:
                    if (blamCacheFile.Name != "mainmenu.map")
                    {
                        new CacheFileGen2(CacheContext, new FileInfo(Path.Combine(blamCacheFile.Directory.FullName, "mainmenu.map")), version, memory);
                    }
                    if (blamCacheFile.Name != "shared.map")
                    {
                        new CacheFileGen2(CacheContext, new FileInfo(Path.Combine(blamCacheFile.Directory.FullName, "shared.map")), version, memory);
                    }
                    if (blamCacheFile.Name != "single_player_shared.map")
                    {
                        new CacheFileGen2(CacheContext, new FileInfo(Path.Combine(blamCacheFile.Directory.FullName, "single_player_shared.map")), version, memory);
                    }
                    blamCache = new CacheFileGen2(CacheContext, blamCacheFile, version, memory);
                    break;

                case CacheVersion.Halo3Retail:
                case CacheVersion.Halo3ODST:
                case CacheVersion.HaloReach:
                    blamCache = new CacheFileGen3(CacheContext, blamCacheFile, version, memory);
                    break;

                default:     // Same question here as above.
                    throw new NotSupportedException(CacheVersionDetection.GetBuildName(version));
                }
            }

            ContextStack.Push(PortingContextFactory.Create(ContextStack, CacheContext, blamCache));

            Console.WriteLine("done.");

            return(true);
        }
예제 #4
0
        public StringTableGen3(EndianReader reader, MapFile baseMapFile) : base()
        {
            Version = baseMapFile.Version;

            switch (Version)
            {
            case CacheVersion.Halo3Retail:
            case CacheVersion.Halo3Beta:        // double check
                Resolver = new StringIdResolverHalo3();
                break;

            case CacheVersion.Halo3ODST:
                Resolver = new StringIdResolverHalo3ODST();
                break;

            case CacheVersion.HaloReach:
                Resolver  = new StringIdResolverHaloReach();
                StringKey = "ILikeSafeStrings";
                break;

            case CacheVersion.HaloReachMCC0824:
            case CacheVersion.HaloReachMCC0887:
            case CacheVersion.HaloReachMCC1035:
            case CacheVersion.HaloReachMCC1211:
                Resolver = new StringIdResolverHaloReachMCC();
                break;

            default:
                throw new NotSupportedException(CacheVersionDetection.GetBuildName(Version));
            }

            var sectionTable = baseMapFile.Header.SectionTable;

            // means no strings
            if (sectionTable.Sections[(int)CacheFileSectionType.StringSection].Size == 0)
            {
                return;
            }

            var stringIdIndexTableOffset = sectionTable.GetOffset(CacheFileSectionType.StringSection, baseMapFile.Header.StringIDsIndicesOffset);
            var stringIdBufferOffset     = sectionTable.GetOffset(CacheFileSectionType.StringSection, baseMapFile.Header.StringIDsBufferOffset);

            //
            // Read offsets
            //

            reader.SeekTo(stringIdIndexTableOffset);

            int[] stringOffset = new int[baseMapFile.Header.StringIDsCount];
            for (var i = 0; i < baseMapFile.Header.StringIDsCount; i++)
            {
                stringOffset[i] = reader.ReadInt32();
                Add("");
            }

            reader.SeekTo(stringIdBufferOffset);

            EndianReader newReader;

            if (StringKey == "")
            {
                newReader = new EndianReader(new MemoryStream(reader.ReadBytes(baseMapFile.Header.StringIDsBufferSize)), reader.Format);
            }
            else
            {
                newReader = new EndianReader(reader.DecryptAesSegment(baseMapFile.Header.StringIDsBufferSize, StringKey), reader.Format);
            }

            //
            // Read strings
            //

            for (var i = 0; i < stringOffset.Length; i++)
            {
                if (stringOffset[i] == -1)
                {
                    this[i] = "<null>";
                    continue;
                }

                newReader.SeekTo(stringOffset[i]);
                this[i] = newReader.ReadNullTerminatedString();
            }
            newReader.Close();
            newReader.Dispose();
        }