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); }
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); }
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); }
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(); }