private void OpenCASC(string path) { RecentLocations.Add(path); CollectionViewSource.GetDefaultView(RecentLocations).Refresh(); IsReady = false; Config = null; CASC = null; GUIDTree?.Dispose(); GUIDTree = new GUIDCollection(); NotifyPropertyChanged(nameof(GUIDTree)); GCSettings.LatencyMode = GCLatencyMode.Batch; Task.Run(delegate { try { Config = CASCConfig.LoadLocalStorageConfig(path, true, CASCSettings.LoadAllLanguages); if (Config.InstallData?.Uid != null && Config.InstallData.Uid != "prometheus") { MessageBox.Show($"The branch \"{Config.InstallData.Uid}\" is not supported!\nThis might result in failure to load.\nProceed with caution.", "Unsupported Branch", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK); } CASC = CASCHandler.Open(Config, ProgressSlave); BuildTree(); } catch (Exception e) { MessageBox.Show(e.Message, "Error while loading CASC", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK); if (Debugger.IsAttached) { throw; } } finally { GCSettings.LatencyMode = GCLatencyMode.Interactive; GC.Collect(); } ViewContext.Send(new SendOrPostCallback(delegate { IsReady = true; }), null); }); }
public ModeResult Run(string[] args) { string gameDir = args[1]; ushort type = ushort.Parse(args[2], NumberStyles.HexNumber); CASCConfig config = CASCConfig.LoadLocalStorageConfig(gameDir, true, false); CASC = CASCHandler.Open(config); MapCMF("enUS"); // heck foreach (ulong file in Types[type]) { string filename = teResourceGUID.AsString(file); using (Stream stream = OpenFile(file)) { if (stream == null) { continue; } teStructuredData structuredData = new teStructuredData(stream); } } return(ModeResult.Success); }
public static void LoadCASC() { CASC = CASCHandler.Open(Config); MapCMF(Language); }
static void Main() { Console.OutputEncoding = Encoding.UTF8; Files = new Dictionary <ulong, PackageRecord>(); TrackedFiles = new Dictionary <ushort, HashSet <ulong> >(); Flags = FlagParser.Parse <ToolFlags>(); if (Flags == null) { return; } #region Initialize CASC Log("{0} v{1}", Assembly.GetExecutingAssembly().GetName().Name, Util.GetVersion()); Log("Initializing CASC..."); if (Flags.Language != null) { Log("Set language to {0}", Flags.Language); } if (Flags.SpeechLanguage != null) { Log("Set speech language to {0}", Flags.SpeechLanguage); } CASCHandler.Cache.CacheAPM = Flags.UseCache; CASCHandler.Cache.CacheCDN = Flags.UseCache; CASCHandler.Cache.CacheCDNData = Flags.CacheData; Config = CASCConfig.LoadFromString(Flags.OverwatchDirectory, Flags.SkipKeys); Config.SpeechLanguage = Flags.SpeechLanguage ?? Flags.Language ?? Config.SpeechLanguage; Config.TextLanguage = Flags.Language ?? Config.TextLanguage; #endregion BuildVersion = uint.Parse(Config.BuildVersion.Split('.').Last()); if (Flags.SkipKeys) { Log("Disabling Key auto-detection..."); } Log("Using Overwatch Version {0}", Config.BuildVersion); CASC = CASCHandler.Open(Config); Root = CASC.RootHandler; if (Root == null) { ErrorLog("Not a valid overwatch installation"); return; } if (!Root.APMFiles.Any()) { ErrorLog("Could not find the files for language {0}. Please confirm that you have that language installed, and are using the names from the target language.", Flags.Language); if (!Flags.GracefulExit) { return; } } string[] modeArgs = Flags.Positionals.Skip(2).ToArray(); switch (Flags.Mode.ToLower()) { case "extract": Extract(modeArgs); break; case "search": Search(modeArgs); break; case "search-type": SearchType(modeArgs); break; case "info": Info(modeArgs); break; case "convert": Convert(modeArgs); break; case "types": Types(modeArgs); break; default: Console.Out.WriteLine("Available modes: extract, search, search-type, info"); break; } }
public static void Main(string[] args) { string overwatchDir = args[0]; string mode = args[1]; const string language = "enUS"; // Usage: // {overwatch dir} dump -- Dump hashes // {overwatch dir} compare-enc {other ver num} -- Extract added files from encoding (requires dump from other version) // {overwatch dir} compare-idx {other ver num} -- Extract added files from indices (requires dump from other version) // {overwatch dir} nonblte -- Extract non-blte files // {overwatch dir} extract-encoding -- Extract encoding file // {overwatch dir} addcmf -- Extract all files from the cmf // casc setup Config = CASCConfig.LoadLocalStorageConfig(overwatchDir, false, false); Config.SpeechLanguage = Config.TextLanguage = language; if (mode != "allcmf" && mode != "dump-guids" && mode != "compare-guids" && mode != "dump-cmf") { Config.LoadContentManifest = false; Config.LoadPackageManifest = false; } CASC = CASCHandler.Open(Config); MapCMF(language); //var temp = Config.Builds[Config.ActiveBuild].KeyValue; BuildVersion = uint.Parse(Config.BuildVersion.Split('.').Last()); // c:\\ow\\game\\Overwatch dump // "D:\Games\Overwatch Test" compare 44022 if (mode == "dump") { Dump(args); } else if (mode == "compare-enc") { CompareEnc(args); } else if (mode == "compare-idx") { CompareIdx(args); } else if (mode == "nonblte") { DumpNonBLTE(args); } else if (mode == "extract-encoding") { ExtractEncodingFile(args); } else if (mode == "allcmf") { AllCMF(args); } else if (mode == "dump-guids") { DumpGUIDs(args); } else if (mode == "compare-guids") { CompareGUIDs(args); } else if (mode == "dump-cmf") { DumpCMF(args); } else { throw new Exception($"unknown mode: {mode}"); } }
private static void Main() { AppDomain.CurrentDomain.UnhandledException += ExceptionHandler; Process.GetCurrentProcess().EnableRaisingEvents = true; AppDomain.CurrentDomain.ProcessExit += (sender, @event) => Console.ForegroundColor = ConsoleColor.Gray; Console.CancelKeyPress += (sender, @event) => Console.ForegroundColor = ConsoleColor.Gray; Console.OutputEncoding = Encoding.UTF8; Files = new Dictionary <ulong, ApplicationPackageManifest.Types.PackageRecord>(); TrackedFiles = new Dictionary <ushort, HashSet <ulong> >(); #region Tool Detection HashSet <Type> tools = new HashSet <Type>(); { Assembly asm = typeof(ITool).Assembly; Type t = typeof(ITool); List <Type> types = asm.GetTypes().Where(tt => tt != t && t.IsAssignableFrom(tt)).ToList(); foreach (Type tt in types) { ToolAttribute attrib = tt.GetCustomAttribute <ToolAttribute>(); if (tt.IsInterface || attrib == null) { continue; } tools.Add(tt); if (attrib.TrackTypes == null) { continue; } foreach (ushort type in attrib.TrackTypes) { if (!TrackedFiles.ContainsKey(type)) { TrackedFiles[type] = new HashSet <ulong>(); } } } } #endregion Flags = FlagParser.Parse <ToolFlags>(() => PrintHelp(tools)); if (Flags == null) { return; } //Logger.EXIT = !Flags.GracefulExit; ITool targetTool = null; ICLIFlags targetToolFlags = null; #region Tool Activation foreach (Type type in tools) { ToolAttribute attrib = type.GetCustomAttribute <ToolAttribute>(); if (!string.Equals(attrib.Keyword, Flags.Mode, StringComparison.InvariantCultureIgnoreCase)) { continue; } targetTool = Activator.CreateInstance(type) as ITool; if (attrib.CustomFlags != null) { Type flags = attrib.CustomFlags; if (typeof(ICLIFlags).IsAssignableFrom(flags)) { targetToolFlags = typeof(FlagParser).GetMethod(nameof(FlagParser.Parse), new Type[] { }).MakeGenericMethod(flags).Invoke(null, null) as ICLIFlags; } } break; } #endregion if (targetTool == null) { FlagParser.Help <ToolFlags>(false); PrintHelp(tools); if (Debugger.IsAttached) { Debugger.Break(); } return; } TankLib.Helpers.Logger.Info("Core", $"{Assembly.GetExecutingAssembly().GetName().Name} v{TankLib.Util.GetVersion(typeof(Program).Assembly)}"); TankLib.Helpers.Logger.Info("Core", $"CommandLine: [{string.Join(", ", Environment.GetCommandLineArgs().Skip(1).Select(x => $"\"{x}\""))}]"); #region Initialize CASC if (Flags.Language != null) { TankLib.Helpers.Logger.Info("CASC", $"Set language to {Flags.Language}"); } if (Flags.SpeechLanguage != null) { TankLib.Helpers.Logger.Info("CASC", $"Set speech language to {Flags.SpeechLanguage}"); } CASCHandler.Cache.CacheAPM = Flags.UseCache; CASCHandler.Cache.CacheCDN = Flags.UseCache; CASCHandler.Cache.CacheCDNData = Flags.CacheData; Config = CASCConfig.LoadFromString(Flags.OverwatchDirectory, Flags.SkipKeys); Config.SpeechLanguage = Flags.SpeechLanguage ?? Flags.Language ?? Config.SpeechLanguage; Config.TextLanguage = Flags.Language ?? Config.TextLanguage; if (Config != null) { if (Flags.Language != null && !Config.InstallData.Settings.Languages.Select(x => x.Language).Contains(Flags.Language)) { TankLib.Helpers.Logger.Warn("Core", "Battle.Net Agent reports that language {0} is not installed.", Flags.Language); } if (Config.InstallData.Uid != "prometheus") { TankLib.Helpers.Logger.Warn("Core", $"The branch \"{Config.InstallData.Uid}\" is not supported!. This might result in failure to load. Proceed with caution."); } } #endregion BuildVersion = uint.Parse(Config.BuildVersion.Split('.').Last()); if (BuildVersion < 39028) { TankLib.Helpers.Logger.Error("Core", "DataTool doesn't support Overwatch versions below 1.14. Please use OverTool"); } else if (BuildVersion < 39241) { TankLib.Helpers.Logger.Error("Core", "DataTool doesn't support this 1.14 release as it uses unmangeled hashes"); } else if (BuildVersion < 49154) { TankLib.Helpers.Logger.Error("Core", "This version of DataTool doesn't properly support versions below 1.26. Please downgrade DataTool."); } TankLib.Helpers.Logger.Info("Core", $"Using Overwatch Version {Config.BuildVersion}"); TankLib.Helpers.Logger.Info("CASC", "Initializing..."); CASC = CASCHandler.Open(Config); Root = CASC.RootHandler; //if (Root== null) { // ErrorLog("Not a valid overwatch installation"); // return; //} if (Config.InstallData != null) { } // Fail when trying to extract data from a specified language with 2 or less files found. if (!Root.APMFiles.Any()) { TankLib.Helpers.Logger.Error("Core", "Unable to load APM files for language {0}. Please confirm that you have that language installed.", Flags.Language); return; } TankLib.Helpers.Logger.Info("Core", "Mapping storage"); TrackedFiles[0x90] = new HashSet <ulong>(); IO.MapCMF(); IO.LoadGUIDTable(); Sound.WwiseBank.GetReady(); //foreach (KeyValuePair<ushort, HashSet<ulong>> type in TrackedFiles.OrderBy(x => x.Key)) { // //Console.Out.WriteLine($"Found type: {type.Key:X4} ({type.Value.Count} files)"); // Console.Out.WriteLine($"Found type: {type.Key:X4}"); //} #region Key Detection if (!Flags.SkipKeys) { TankLib.Helpers.Logger.Info("Core", "Checking ResourceKeys"); foreach (ulong key in TrackedFiles[0x90]) { if (!ValidKey(key)) { continue; } using (Stream stream = IO.OpenFile(Files[key])) { if (stream == null) { continue; } STUResourceKey resourceKey = GetInstance <STUResourceKey>(key); if (resourceKey == null || resourceKey.GetKeyID() == 0 || TACTKeyService.Keys.ContainsKey(resourceKey.GetReverseKeyID())) { continue; } TACTKeyService.Keys.Add(resourceKey.GetReverseKeyID(), resourceKey.m_key); TankLib.Helpers.Logger.Info("Core", $"Added ResourceKey {resourceKey.GetKeyIDString()}, Value: {resourceKey.GetKeyValueString()}"); } } } #endregion Stopwatch stopwatch = new Stopwatch(); TankLib.Helpers.Logger.Info("Core", "Tooling..."); var dbPath = Flags.ScratchDBPath; if (Flags.Deduplicate) { TankLib.Helpers.Logger.Warn("ScratchDB", "Will attempt to deduplicate files if extracting..."); if (!string.IsNullOrWhiteSpace(Flags.ScratchDBPath)) { TankLib.Helpers.Logger.Warn("ScratchDB", "Loading deduplication database..."); if (!File.Exists(dbPath)) { dbPath = Path.Combine(Path.GetFullPath(Flags.ScratchDBPath), "Scratch.db"); } SaveLogic.Combo.ScratchDBInstance.Load(dbPath); } } stopwatch.Start(); targetTool.Parse(targetToolFlags); stopwatch.Stop(); TankLib.Helpers.Logger.Success("Core", $"Execution finished in {stopwatch.Elapsed} seconds"); if (Flags.Deduplicate && !string.IsNullOrWhiteSpace(dbPath)) { TankLib.Helpers.Logger.Warn("ScratchDB", "Saving deduplication database..."); SaveLogic.Combo.ScratchDBInstance.Save(dbPath); } if (Debugger.IsAttached) { Debugger.Break(); } }