Example #1
0
        public void Parse(Dictionary <ushort, List <ulong> > track, Dictionary <ulong, Record> map, CASCHandler handler, bool quiet, OverToolFlags flags)
        {
            string[]      baseArgs = Environment.GetCommandLineArgs();
            List <string> args     = new List <string>();

            string[] origFlags = baseArgs.Where(x => x[0] == '-').ToArray();
            args.Add(flags.Positionals[0]);
            Dictionary <string, string> tracking = new Dictionary <string, string>();

            tracking[Opt.ToString()] = string.Empty;
            tracking[FullOpt]        = string.Empty;

            foreach (string modeargument in flags.Positionals.Skip(2))
            {
                string modearg = modeargument;
                string subargs = null;
                if (modearg.Contains('['))
                {
                    modearg = modearg.Substring(0, modearg.Length - 1);
                    subargs = modearg.Substring(modearg.IndexOf('[') + 1);
                    modearg = modearg.Substring(0, modearg.IndexOf('['));
                }
                string[] modes = modearg.Split('+');

                foreach (string mode in modes)
                {
                    tracking[mode] = subargs;
                }
            }

            foreach (KeyValuePair <string, string> modes in tracking)
            {
                string mode = modes.Key;
                if ((mode.Length == 1 && mode[0] == Opt) || mode == FullOpt)
                {
                    continue;
                }
                if (!Program.toolsMap.ContainsKey(mode))
                {
                    continue;
                }
                string        subargs = modes.Value;
                string        global  = tracking[Opt.ToString()] + " " + tracking[FullOpt];
                List <string> tmp     = new List <string>();
                tmp.Add(baseArgs[0]);
                tmp.Add(mode.ToString());
                tmp.Add(global);
                tmp.Add(subargs);
                string[] newargs = CommandLineToArgs(string.Join(" ", tmp));
                tmp.Clear();
                tmp.AddRange(origFlags);
                tmp.AddRange(args);
                tmp.AddRange(newargs.Skip(1));
                OverToolFlags newflags = FlagParser.Parse <OverToolFlags>(null, tmp.ToArray());
                IOvertool     tool     = Program.toolsMap[mode];
                tool.Parse(track, map, handler, quiet, newflags);
            }
        }
Example #2
0
        private static void Main()
        {
            Console.OutputEncoding = Encoding.UTF8;

            Flags = FlagParser.Parse <ToolFlags>();
            if (Flags == null)
            {
                return;
            }
            var f = Flags;

            InitStorage();
            InitMisc();
            InitKeys();

            string[] modeArgs = Flags.Positionals.Skip(2).ToArray();

            switch (Flags.Mode.ToLower())
            {
            case "extract":
                Extract(modeArgs);
                break;

            case "extract-type":
                ExtractType(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;
            }
        }
Example #3
0
        private static void Convert(string[] args)
        {
            string output = args.FirstOrDefault();

            ulong[] guids = args.Skip(1).Select(x => ulong.Parse(x, NumberStyles.HexNumber)).ToArray();
            if (string.IsNullOrWhiteSpace(output))
            {
                return;
            }

            Dictionary <ulong, PackageRecord[]> records  = new Dictionary <ulong, PackageRecord[]>();
            Dictionary <ulong, PackageHeader>   packages = new Dictionary <ulong, PackageHeader>();

            var apm = TankHandler.m_packageManifest;

            for (int i = 0; i < apm.m_packageEntries.Length; ++i)
            {
                PackageEntry entry = apm.m_packageEntries[i];
                if (!guids.Contains(teResourceGUID.LongKey(entry.m_packageGUID)) && !guids.Contains(teResourceGUID.Index(entry.m_packageGUID)) && !guids.Contains(entry.m_packageGUID))
                {
                    continue;
                }
                packages[entry.m_packageGUID] = apm.m_packages[i];
                records[entry.m_packageGUID]  = apm.m_packageRecords[i];
            }

            ICLIFlags flags = FlagParser.Parse <ExtractFlags>();

            void Body(ulong key)
            {
                DataTool.FindLogic.Combo.ComboInfo info = new DataTool.FindLogic.Combo.ComboInfo();
                string dest = Path.Combine(output, teResourceGUID.AsString(key));

                foreach (PackageRecord record in records[key])
                {
                    DataTool.FindLogic.Combo.Find(info, record.m_GUID);
                }

                var context = new DataTool.SaveLogic.Combo.SaveContext(info);

                DataTool.SaveLogic.Combo.Save(flags, dest, context);
                context.Wait();
            }

            Parallel.ForEach(records.Keys, Body);
        }
Example #4
0
        static void Main(string[] args)
        {
            FlagParser.Parse(args);
            var file = FlagParser.StringFlag("file", string.Empty, true);
            var hash = FlagParser.StringFlag("hash", string.Empty, true);

            if (string.IsNullOrWhiteSpace(file) || string.IsNullOrWhiteSpace(hash))
            {
                Console.WriteLine("Invalid Parameters");
                return;
            }
            using var hashAlgo = HashAlgorithm.Create(hash ?? "SHA512");
            using var stream   = File.OpenRead(file);
            var checksum = BitConverter.ToString(hashAlgo.ComputeHash(stream)).Replace("-", string.Empty).ToLowerInvariant();

            Console.WriteLine("--- File Checksum ---");
            Console.WriteLine(checksum);
        }
Example #5
0
        private static void Convert(string[] args)
        {
            string output = args.FirstOrDefault();

            ulong[] guids = args.Skip(1).Select(x => ulong.Parse(x, NumberStyles.HexNumber)).ToArray();
            if (string.IsNullOrWhiteSpace(output))
            {
                return;
            }

            Dictionary <ulong, PackageRecord[]> records  = new Dictionary <ulong, PackageRecord[]>();
            Dictionary <ulong, Package>         packages = new Dictionary <ulong, Package>();

            foreach (ApplicationPackageManifest apm in Root.APMFiles)
            {
                for (int i = 0; i < apm.PackageEntries.Length; ++i)
                {
                    PackageEntry entry = apm.PackageEntries[i];
                    if (guids.Contains(teResourceGUID.LongKey(entry.PackageGUID)) || guids.Contains(teResourceGUID.Index(entry.PackageGUID)))
                    {
                        packages[entry.PackageGUID] = apm.Packages[i];
                        records[entry.PackageGUID]  = apm.Records[i];
                    }
                }
            }

            ICLIFlags flags = FlagParser.Parse <ExtractFlags>();

            MapCMF();
            LoadGUIDTable();
            Sound.WwiseBank.GetReady();
            Parallel.ForEach(records.Keys, (key) =>
            {
                DataTool.FindLogic.Combo.ComboInfo info = new DataTool.FindLogic.Combo.ComboInfo();
                string dest = Path.Combine(output, teResourceGUID.AsString(key));
                foreach (PackageRecord record in records[key])
                {
                    DataTool.FindLogic.Combo.Find(info, record.GUID);
                }
                DataTool.SaveLogic.Combo.Save(flags, dest, info);
            });
        }
Example #6
0
        private static void Main()
        {
            Console.OutputEncoding = Encoding.UTF8;

            Files        = new Dictionary <ulong, 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("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;
            }

            #region Initialize CASC
            Log("{0} v{1}", Assembly.GetExecutingAssembly().GetName().Name, Util.GetVersion());
            Log("Initializing CASC...");
            Log("Set language to {0}", Flags.Language);
            CDNIndexHandler.Cache.Enabled   = Flags.UseCache;
            CDNIndexHandler.Cache.CacheData = Flags.CacheData;
            CDNIndexHandler.Cache.Validate  = Flags.ValidateCache;
            // ngdp:us:pro
            // http:us:pro:us.patch.battle.net:1119
            if (Flags.OverwatchDirectory.ToLowerInvariant().Substring(0, 5) == "ngdp:")
            {
                string   cdn     = Flags.OverwatchDirectory.Substring(5, 4);
                string[] parts   = Flags.OverwatchDirectory.Substring(5).Split(':');
                string   region  = "us";
                string   product = "pro";
                if (parts.Length > 1)
                {
                    region = parts[1];
                }
                if (parts.Length > 2)
                {
                    product = parts[2];
                }
                if (cdn == "bnet")
                {
                    Config = CASCConfig.LoadOnlineStorageConfig(product, region);
                }
                else
                {
                    if (cdn == "http")
                    {
                        string host = string.Join(":", parts.Skip(3));
                        Config = CASCConfig.LoadOnlineStorageConfig(host, product, region, true, true, true);
                    }
                }
            }
            else
            {
                Config = CASCConfig.LoadLocalStorageConfig(Flags.OverwatchDirectory, !Flags.SkipKeys, false);
            }
            Config.Languages = new HashSet <string>(new[] { Flags.Language });
            #endregion

            foreach (Dictionary <string, string> build in Config.BuildInfo)
            {
                if (!build.ContainsKey("Tags"))
                {
                    continue;
                }
                if (build["Tags"].Contains("XX?"))
                {
                    IsPTR = true;
                }
                // us ptr region is known as XX, so just look for it in the tags.
                // this should work... untested for Asia
            }

            BuildVersion = uint.Parse(Config.BuildName.Split('.').Last());

            if (Flags.SkipKeys)
            {
                Log("Disabling Key auto-detection...");
            }

            Log("Using Overwatch Version {0}", Config.BuildName);
            CASC = CASCHandler.OpenStorage(Config);
            Root = CASC.Root as OwRootHandler;
            if (Root == null)
            {
                ErrorLog("Not a valid overwatch installation");
                return;
            }

            // Fail when trying to extract data from a specified language with 2 or less files found.
            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;
                }
            }

            Log("Mapping...");
            TrackedFiles[0x90] = new HashSet <ulong>();
            IO.MapCMF();
            IO.LoadGUIDTable();
            Sound.WwiseBank.GetReady();

            #region Key Detection
            if (!Flags.SkipKeys)
            {
                Log("Adding Encryption Keys...");

                foreach (ulong key in TrackedFiles[0x90])
                {
                    if (!ValidKey(key))
                    {
                        continue;
                    }
                    using (Stream stream = IO.OpenFile(Files[key])) {
                        if (stream == null)
                        {
                            continue;
                        }

                        STUEncryptionKey encryptionKey = GetInstance <STUEncryptionKey>(key);
                        if (encryptionKey != null && encryptionKey.LongKey != 0 && !KeyService.keys.ContainsKey(encryptionKey.LongRevKey))
                        {
                            KeyService.keys.Add(encryptionKey.LongRevKey, encryptionKey.KeyValue);
                            Log("Added Encryption Key {0}, Value: {1}", encryptionKey.KeyNameProper, encryptionKey.Key);
                        }
                    }
                }
            }
            #endregion

            Log("Tooling...");
            targetTool.Parse(targetToolFlags);
            if (Debugger.IsAttached)
            {
                Debugger.Break();
            }
        }
Example #7
0
    public IList <IRule> Parse(TextReader input)
    {
        string?line;
        var    rules   = new List <IRule>();
        var    builder = new RuleBuilder();
        var    lineNum = 0;

        // parsers
        var testStringParser = new TestStringParser();
        var conditionParser  = new ConditionPatternParser();
        var regexParser      = new RuleRegexParser();
        var flagsParser      = new FlagParser();
        var tokenizer        = new Tokenizer();

        while ((line = input.ReadLine()) != null)
        {
            lineNum++;
            if (string.IsNullOrEmpty(line))
            {
                continue;
            }
            if (line.StartsWith('#'))
            {
                continue;
            }
            var tokens = tokenizer.Tokenize(line) !;
            if (tokens.Count > 4)
            {
                // This means the line didn't have an appropriate format, throw format exception
                throw new FormatException(Resources.FormatError_ModRewriteParseError("Too many tokens on line", lineNum));
            }

            switch (tokens[0])
            {
            case "RewriteBase":
                // the notion of the path base spans across all rules, not just mod_rewrite
                // So not implemented for now
                throw new NotImplementedException("RewriteBase is not implemented");

            case "RewriteCond":
                try
                {
                    var pattern          = testStringParser.Parse(tokens[1]);
                    var condActionParsed = conditionParser.ParseActionCondition(tokens[2]);

                    var flags = new Flags();
                    if (tokens.Count == 4)
                    {
                        flags = flagsParser.Parse(tokens[3]);
                    }

                    builder.AddConditionFromParts(pattern, condActionParsed, flags);
                }
                catch (FormatException formatException)
                {
                    throw new FormatException(Resources.FormatError_ModRewriteGeneralParseError(lineNum), formatException);
                }
                break;

            case "RewriteRule":
                try
                {
                    var regex   = regexParser.ParseRuleRegex(tokens[1]);
                    var pattern = testStringParser.Parse(tokens[2]);

                    Flags flags;
                    if (tokens.Count == 4)
                    {
                        flags = flagsParser.Parse(tokens[3]);
                    }
                    else
                    {
                        flags = new Flags();
                    }

                    builder.AddMatch(regex, flags);
                    builder.AddAction(pattern, flags);
                    rules.Add(builder.Build());
                    builder = new RuleBuilder();
                }
                catch (FormatException formatException)
                {
                    throw new FormatException(Resources.FormatError_ModRewriteGeneralParseError(lineNum), formatException);
                }
                break;

            case "RewriteMap":
                // Lack of use
                throw new NotImplementedException("RewriteMap are not implemented");

            case "RewriteEngine":
                // Explicitly do nothing here, no notion of turning on regex engine.
                break;

            default:
                throw new FormatException(Resources.FormatError_ModRewriteParseError("Unrecognized keyword: " + tokens[0], lineNum));
            }
        }
        return(rules);
    }
Example #8
0
        private static void Main()
        {
            InitTankSettings();

            HookConsole();

            var tools = GetTools();

        #if DEBUG
            FlagParser.CheckCollisions(typeof(ToolFlags), (flag, duplicate) => { Logger.Error("Flag", $"The flag \"{flag}\" from {duplicate} is a duplicate!"); });
        #endif

            FlagParser.LoadArgs();

            Logger.Info("Core", $"{Assembly.GetExecutingAssembly().GetName().Name} v{Util.GetVersion(typeof(Program).Assembly)}");

            Logger.Info("Core", $"CommandLine: [{string.Join(", ", FlagParser.AppArgs.Select(x => $"\"{x}\""))}]");

            Flags = FlagParser.Parse <ToolFlags>(full => PrintHelp(full, tools));
            if (Flags == null)
            {
                return;
            }

            Logger.Info("Core", $"CommandLineFile: {FlagParser.ArgFilePath}");

            if (Flags.SaveArgs)
            {
                FlagParser.AppArgs = FlagParser.AppArgs.Where(x => !x.StartsWith("--arg"))
                                     .ToArray();
                FlagParser.SaveArgs(Flags.OverwatchDirectory);
            }
            else if (Flags.ResetArgs || Flags.DeleteArgs)
            {
                FlagParser.ResetArgs();
                if (Flags.DeleteArgs)
                {
                    FlagParser.DeleteArgs();
                }

                Logger.Info("Core", $"CommandLineNew: [{string.Join(", ", FlagParser.AppArgs.Select(x => $"\"{x}\""))}]");
                Flags = FlagParser.Parse <ToolFlags>(full => PrintHelp(full, tools));
                if (Flags == null)
                {
                    return;
                }
            }

            if (string.IsNullOrWhiteSpace(Flags.OverwatchDirectory) || string.IsNullOrWhiteSpace(Flags.Mode) || Flags.Help)
            {
                PrintHelp(false, tools);
                return;
            }

            ITool         targetTool           = null;
            ICLIFlags     targetToolFlags      = null;
            ToolAttribute targetToolAttributes = null;

            #region Tool Activation

            foreach (var type in tools)
            {
                var attribute = type.GetCustomAttribute <ToolAttribute>();

                if (!string.Equals(attribute.Keyword, Flags.Mode, StringComparison.InvariantCultureIgnoreCase))
                {
                    continue;
                }
                targetTool           = Activator.CreateInstance(type) as ITool;
                targetToolAttributes = attribute;

                if (attribute.CustomFlags != null)
                {
                    var flags = attribute.CustomFlags;
                    if (typeof(ICLIFlags).IsAssignableFrom(flags))
                    {
                        targetToolFlags = typeof(FlagParser).GetMethod(nameof(FlagParser.Parse), new Type[] { })
                                          ?.MakeGenericMethod(flags)
                                          .Invoke(null, null) as ICLIFlags;
                    }
                }

                break;
            }

            if (targetToolFlags == null)
            {
                return;
            }

            #endregion

            if (targetTool == null)
            {
                FlagParser.Help <ToolFlags>(false, new Dictionary <string, string>());
                PrintHelp(false, tools);
                return;
            }

            if (!targetToolAttributes.UtilNoArchiveNeeded)
            {
                InitStorage();

                //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}");
                //}

                InitKeys();
                InitMisc();
            }

            var stopwatch = new Stopwatch();
            Logger.Info("Core", "Tooling...");
            stopwatch.Start();
            targetTool.Parse(targetToolFlags);
            stopwatch.Stop();

            Logger.Success("Core", $"Execution finished in {stopwatch.Elapsed} seconds");

            ShutdownMisc();
        }
Example #9
0
        public static void Main(string[] args)
        {
            if (args.Length < 2)
            {
                Console.Out.WriteLine("Usage: Mp4Tool {overwatch dir} {file} [--json] [--out=outfile.json]");
                return;
            }

            string gameDir  = args[0];
            string filePath = args[1];

            var files          = new List <string>();
            var fileAttributes = File.GetAttributes(filePath);

            if (fileAttributes.HasFlag(FileAttributes.Directory))
            {
                files.AddRange(Directory.GetFiles(filePath, "*.mp4", SearchOption.TopDirectoryOnly));

                if (files.Count == 0)
                {
                    Console.Out.WriteLine("Found no valid mp4 files.");
                    return;
                }
            }
            else
            {
                if (!filePath.EndsWith(".mp4"))
                {
                    Console.Out.WriteLine("Only MP4s are supported");
                    return;
                }

                files.Add(filePath);
            }

            var flags     = FlagParser.Parse <ListFlags>();
            var toolFlags = FlagParser.Parse <ToolFlags>();

            DataTool.Program.Flags = new ToolFlags {
                OverwatchDirectory = gameDir,
                Language           = toolFlags.Language ?? "enUS",
                SpeechLanguage     = toolFlags.SpeechLanguage ?? "enUS",
                Quiet  = true,
                Online = false
            };

            DataTool.Program.InitStorage(false);
            var replays = ReplayThing.ParseReplays(files);

            if (flags.JSON)
            {
                new JSONTool().OutputJSON(replays, flags);
            }
            else
            {
                foreach (ReplayThing.Replay replay in replays)
                {
                    Console.Out.WriteLine("Replay Info:");
                    Console.Out.WriteLine($" - Title: {replay.Title}");
                    Console.Out.WriteLine($" - Hero: {replay.Hero}");
                    Console.Out.WriteLine($" - Map: {replay.Map}");
                    Console.Out.WriteLine($" - Skin: {replay.Skin}");
                    Console.Out.WriteLine($" - Recorded At: {replay.RecordedAt}");
                    Console.Out.WriteLine($" - Type: {replay.HighlightType}");
                    Console.Out.WriteLine($" - Quality: {replay.Quality})");
                    Console.Out.WriteLine("\n");
                }
            }
        }
Example #10
0
        static void Main(string[] args)
        {
            Console.OutputEncoding = Encoding.UTF8;
            List <IOvertool> tools = new List <IOvertool>();

            {
                Assembly    asm   = typeof(IOvertool).Assembly;
                Type        t     = typeof(IOvertool);
                List <Type> types = asm.GetTypes().Where(tt => tt != t && t.IsAssignableFrom(tt)).ToList();
                foreach (Type tt in types)
                {
                    if (tt.IsInterface)
                    {
                        continue;
                    }
                    IOvertool toolinst = (IOvertool)Activator.CreateInstance(tt);
                    if (toolinst.Display)
                    {
                        tools.Add(toolinst);
                    }
                }
            }

            OverToolFlags flags = FlagParser.Parse <OverToolFlags>(() => PrintHelp(tools));

            if (flags == null)
            {
                return;
            }

            bool quiet = flags.Quiet;

            string root = flags.OverwatchDirectory;
            char   opt  = flags.Mode[0];

            IOvertool tool = null;
            Dictionary <ushort, List <ulong> > track = new Dictionary <ushort, List <ulong> >();

            track[0x90] = new List <ulong>(); // internal requirements
            toolsMap    = new Dictionary <char, IOvertool>();
            foreach (IOvertool t in tools)
            {
                if (t.Opt == opt)
                {
                    tool = t;
                }

                foreach (ushort tr in t.Track)
                {
                    if (!track.ContainsKey(tr))
                    {
                        track[tr] = new List <ulong>();
                    }
                }
                if (toolsMap.ContainsKey(t.Opt))
                {
                    Console.Out.WriteLine("Duplicate opt! {0} conflicts with {1}", t.Title, toolsMap[t.Opt].Title);
                }
                toolsMap[t.Opt] = t;
            }
            if (tool == null || flags.Positionals.Length - 2 < tool.MinimumArgs)
            {
                PrintHelp(tools);
                return;
            }

            Dictionary <ulong, Record> map = new Dictionary <ulong, Record>();

            Console.Out.WriteLine("{0} v{1}", Assembly.GetExecutingAssembly().GetName().Name, OWLib.Util.GetVersion());
            Console.Out.WriteLine("Initializing CASC...");
            Console.Out.WriteLine("Set language to {0}", flags.Language);
            CDNIndexHandler.Cache.Enabled   = flags.UseCache;
            CDNIndexHandler.Cache.CacheData = flags.CacheData;
            CDNIndexHandler.Cache.Validate  = flags.ValidateCache;
            CASCConfig config = null;

            // ngdp:us:pro
            // http:us:pro:us.patch.battle.net:1119
            if (root.ToLowerInvariant().Substring(0, 5) == "ngdp:")
            {
                string   cdn     = root.Substring(5, 4);
                string[] parts   = root.Substring(5).Split(':');
                string   region  = "us";
                string   product = "pro";
                if (parts.Length > 1)
                {
                    region = parts[1];
                }
                if (parts.Length > 2)
                {
                    product = parts[2];
                }
                if (cdn == "bnet")
                {
                    config = CASCConfig.LoadOnlineStorageConfig(product, region);
                }
                else
                {
                    if (cdn == "http")
                    {
                        string host = string.Join(":", parts.Skip(3));
                        config = CASCConfig.LoadOnlineStorageConfig(host, product, region, true, true, true);
                    }
                }
            }
            else
            {
                config = CASCConfig.LoadLocalStorageConfig(root, !flags.SkipKeys, false);
            }
            config.Languages = new HashSet <string>(new string[1] {
                flags.Language
            });

            if (flags.SkipKeys)
            {
                Console.Out.WriteLine("Disabling Key auto-detection...");
            }

            Console.Out.WriteLine("Using Overwatch Version {0}", config.BuildName);
            CASCHandler   handler = CASCHandler.OpenStorage(config);
            OwRootHandler ow      = handler.Root as OwRootHandler;

            if (ow == null)
            {
                Console.Error.WriteLine("Not a valid overwatch installation");
                return;
            }

            // Fail when trying to extract data from a specified language with 2 or less files found.
            if (ow.APMFiles.Count() == 0)
            {
                Console.Error.WriteLine("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);
                return;
            }

            Console.Out.WriteLine("Mapping...");
            Util.MapCMF(ow, handler, map, track, flags);

            if (!flags.SkipKeys)
            {
                Console.Out.WriteLine("Adding Encryption Keys...");

                foreach (ulong key in track[0x90])
                {
                    if (!map.ContainsKey(key))
                    {
                        continue;
                    }
                    using (Stream stream = Util.OpenFile(map[key], handler)) {
                        if (stream == null)
                        {
                            continue;
                        }
                        STUD stud = new STUD(stream);
                        if (stud.Instances[0].Name != stud.Manager.GetName(typeof(EncryptionKey)))
                        {
                            continue;
                        }
                        EncryptionKey ek = (EncryptionKey)stud.Instances[0];
                        if (!KeyService.keys.ContainsKey(ek.KeyNameLong))
                        {
                            KeyService.keys.Add(ek.KeyNameLong, ek.KeyValueText.ToByteArray());
                            Console.Out.WriteLine("Added Encryption Key {0}, Value: {1}", ek.KeyNameText, ek.KeyValueText);
                        }
                    }
                }
            }

            Console.Out.WriteLine("Tooling...");

            tool.Parse(track, map, handler, quiet, flags);
            if (System.Diagnostics.Debugger.IsAttached)
            {
                System.Diagnostics.Debugger.Break();
            }
        }
Example #11
0
        static void Main(string[] args)
        {
            Console.OutputEncoding = Encoding.UTF8;
            List <IOvertool> tools = new List <IOvertool>();

            {
                Assembly    asm   = typeof(IOvertool).Assembly;
                Type        t     = typeof(IOvertool);
                List <Type> types = asm.GetTypes().Where(tt => tt != t && t.IsAssignableFrom(tt)).ToList();
                foreach (Type tt in types)
                {
                    if (tt.IsInterface)
                    {
                        continue;
                    }
                    IOvertool toolinst = (IOvertool)Activator.CreateInstance(tt);
                    if (toolinst.Display)
                    {
                        tools.Add(toolinst);
                    }
                }
            }

            OverToolFlags flags = FlagParser.Parse <OverToolFlags>(() => PrintHelp(tools));

            if (flags == null)
            {
                return;
            }

            Logger.EXIT = !flags.GracefulExit;

            bool quiet = flags.Quiet;

            string root = flags.OverwatchDirectory;
            string opt  = flags.Mode;

            IOvertool tool = null;
            Dictionary <ushort, List <ulong> > track = new Dictionary <ushort, List <ulong> > {
                [0x90] = new List <ulong>() // internal requirements
            };

            toolsMap = new Dictionary <string, IOvertool>();
            foreach (IOvertool t in tools)
            {
                if (t.FullOpt == opt || (opt.Length == 1 && t.Opt != (char)0 && t.Opt == opt[0]))
                {
                    tool = t;
                }

                if (t.Track != null)
                {
                    foreach (ushort tr in t.Track)
                    {
                        if (!track.ContainsKey(tr))
                        {
                            track[tr] = new List <ulong>();
                        }
                    }
                }

                if (toolsMap.ContainsKey(t.FullOpt))
                {
                    Console.Out.WriteLine("Duplicate opt! {0} conflicts with {1}", t.Title, toolsMap[t.FullOpt].Title);
                }
                if (t.FullOpt.Length == 1)
                {
                    Console.Out.WriteLine("FullOpt should not be length 1 for {0}", t.Title);
                }
                toolsMap[t.FullOpt] = t;
            }
            if (tool == null || flags.Positionals.Length - 2 < tool.MinimumArgs)
            {
                PrintHelp(tools);
                return;
            }

            Dictionary <ulong, Record> map = new Dictionary <ulong, Record>();

            Console.Out.WriteLine("{0} v{1}", Assembly.GetExecutingAssembly().GetName().Name, OWLib.Util.GetVersion());
            Console.Out.WriteLine("Initializing CASC...");
            Console.Out.WriteLine("Set language to {0}", flags.Language);
            CDNIndexHandler.Cache.Enabled   = flags.UseCache;
            CDNIndexHandler.Cache.CacheData = flags.CacheData;
            CDNIndexHandler.Cache.Validate  = flags.ValidateCache;
            CASCConfig config = null;

            // ngdp:us:pro
            // http:us:pro:us.patch.battle.net:1119
            if (root.ToLowerInvariant().Substring(0, 5) == "ngdp:")
            {
                string   cdn     = root.Substring(5, 4);
                string[] parts   = root.Substring(5).Split(':');
                string   region  = "us";
                string   product = "pro";
                if (parts.Length > 1)
                {
                    region = parts[1];
                }
                if (parts.Length > 2)
                {
                    product = parts[2];
                }
                if (cdn == "bnet")
                {
                    config = CASCConfig.LoadOnlineStorageConfig(product, region);
                }
                else
                {
                    if (cdn == "http")
                    {
                        string host = string.Join(":", parts.Skip(3));
                        config = CASCConfig.LoadOnlineStorageConfig(host, product, region, true, true, true);
                    }
                }
            }
            else
            {
                config = CASCConfig.LoadLocalStorageConfig(root, !flags.SkipKeys, false);
            }
            config.Languages = new HashSet <string>(new string[1] {
                flags.Language
            });

            if (flags.SkipKeys)
            {
                Console.Out.WriteLine("Disabling Key auto-detection...");
            }

            Regex versionRegex = new Regex(@"\d+\.\d+");
            Match versionMatch = versionRegex.Match(config.BuildName);

            if (versionMatch.Success)
            {
                float version = float.Parse(versionMatch.Value);

                if (version > 1.13)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.Out.WriteLine("==========\nWARNING: Overtool only works with Overwatch version 1.13 and below! You are using {0}!", config.BuildName);
                    Console.Out.WriteLine("You must use DataTool for Overwatch 1.14 and above!\n==========");
                    Console.ResetColor();
                }
            }

            Console.Out.WriteLine("Using Overwatch Version {0}", config.BuildName);
            CASCHandler   handler = CASCHandler.OpenStorage(config);
            OwRootHandler ow      = handler.Root as OwRootHandler;

            if (ow == null)
            {
                Console.Error.WriteLine("Not a valid overwatch installation");
                return;
            }

            // Fail when trying to extract data from a specified language with 2 or less files found.
            if (ow.APMFiles.Count() == 0)
            {
                Console.Error.WriteLine("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;
                }
            }

            Console.Out.WriteLine("Mapping...");
            Util.MapCMF(ow, handler, map, track, flags.Language);

            if (!flags.SkipKeys)
            {
                Console.Out.WriteLine("Adding Encryption Keys...");

                foreach (ulong key in track[0x90])
                {
                    if (!map.ContainsKey(key))
                    {
                        continue;
                    }
                    using (Stream stream = Util.OpenFile(map[key], handler)) {
                        if (stream == null)
                        {
                            continue;
                        }
                        ISTU stu = ISTU.NewInstance(stream, UInt32.Parse(config.BuildName.Split('.').Last()));
                        if (!(stu.Instances.FirstOrDefault() is STUEncryptionKey))
                        {
                            continue;
                        }
                        STUEncryptionKey ek = stu.Instances.FirstOrDefault() as STUEncryptionKey;
                        if (ek != null && !KeyService.keys.ContainsKey(ek.LongRevKey))
                        {
                            KeyService.keys.Add(ek.LongRevKey, ek.KeyValue);
                            Console.Out.WriteLine("Added Encryption Key {0}, Value: {1}", ek.KeyNameProper, ek.Key);
                        }
                    }
                }
            }

            Console.Out.WriteLine("Tooling...");

            tool.Parse(track, map, handler, quiet, flags);
            if (System.Diagnostics.Debugger.IsAttached)
            {
                System.Diagnostics.Debugger.Break();
            }
        }
Example #12
0
 static void Main(string[] args)
 {
     FlagParser.Parse(args);
     Console.WriteLine(FlagParser.StringFlag("stringtest", "none", false));
     Console.WriteLine(FlagParser.DecimalFlag("dectest", 0.45M, false));
 }
Example #13
0
        static void Main(string[] args)
        {
            Dictionary <string, List <string> > admin1codes;
            Dictionary <string, List <string> > admin2codes;
            Dictionary <string, List <string> > countries;
            Dictionary <string, List <string> > features;
            List <string> filters;

            FlagParser.ContinueOnError = true;
            FlagParser.Parse(args);
            bool help = FlagParser.BoolFlag("help", false, false);

            if (help || args.Length == 0)
            {
                DisplayUsage();
                return;
            }
            // process input flags
            string admin1File  = FlagParser.StringFlag("admin1", string.Empty, true);
            string admin2File  = FlagParser.StringFlag("admin2", string.Empty, true);
            string countryFile = FlagParser.StringFlag("countries", string.Empty, true);
            string featureFile = FlagParser.StringFlag("feature", string.Empty, true);
            string input       = FlagParser.StringFlag("input", string.Empty, true);
            string output      = FlagParser.StringFlag("output", string.Empty, true);
            string filter      = FlagParser.StringFlag("filter", string.Empty, false);
            string outputType  = FlagParser.StringFlag("type", "default", false);

            if (FlagParser.Errors.Count > 0)
            {
                foreach (var e in FlagParser.Errors)
                {
                    Console.WriteLine(e);
                }
                return;
            }

            // read admin1 codes
            admin1codes = ReadAdmin1File(admin1File);
            if (admin1codes == null)
            {
                return;
            }

            // read admin2 codes
            admin2codes = ReadAdmin2File(admin2File);
            if (admin2codes == null)
            {
                return;
            }

            // read country codes
            countries = ReadCountryFile(countryFile);
            if (countries == null)
            {
                return;
            }

            // read feature codes
            features = ReadFeatureFile(featureFile);
            if (features == null)
            {
                return;
            }

            // put filters as list
            filters = new List <string>();
            var fltrs = filter.Split(new char[] { ',' });

            foreach (var fltr in fltrs)
            {
                filters.Add(fltr);
            }

            switch (outputType)
            {
            case "full-structured":
                GenerateFullStructuredOutput(input, output, features, filters, countries, admin1codes, admin2codes);
                break;

            case "full-flat":
            default:
                GenerateDefaultOutput(input, output, features, filters, countries, admin1codes, admin2codes);
                break;
            }
        }
Example #14
0
        static void Main(string[] args)
        {
            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...");
            Log("Set language to {0}", Flags.Language);
            CDNIndexHandler.Cache.Enabled   = Flags.UseCache;
            CDNIndexHandler.Cache.CacheData = Flags.CacheData;
            CDNIndexHandler.Cache.Validate  = Flags.ValidateCache;
            // ngdp:us:pro
            // http:us:pro:us.patch.battle.net:1119
            if (Flags.OverwatchDirectory.ToLowerInvariant().Substring(0, 5) == "ngdp:")
            {
                string   cdn     = Flags.OverwatchDirectory.Substring(5, 4);
                string[] parts   = Flags.OverwatchDirectory.Substring(5).Split(':');
                string   region  = "us";
                string   product = "pro";
                if (parts.Length > 1)
                {
                    region = parts[1];
                }
                if (parts.Length > 2)
                {
                    product = parts[2];
                }
                if (cdn == "bnet")
                {
                    Config = CASCConfig.LoadOnlineStorageConfig(product, region);
                }
                else
                {
                    if (cdn == "http")
                    {
                        string host = string.Join(":", parts.Skip(3));
                        Config = CASCConfig.LoadOnlineStorageConfig(host, product, region, true, true, true);
                    }
                }
            }
            else
            {
                Config = CASCConfig.LoadLocalStorageConfig(Flags.OverwatchDirectory, !Flags.SkipKeys, false);
            }
            Config.Languages = new HashSet <string>(new[] { Flags.Language });
            #endregion

            BuildVersion = uint.Parse(Config.BuildName.Split('.').Last());

            if (Flags.SkipKeys)
            {
                Log("Disabling Key auto-detection...");
            }

            Log("Using Overwatch Version {0}", Config.BuildName);
            CASC = CASCHandler.OpenStorage(Config);
            Root = CASC.Root as OwRootHandler;
            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;
            }
        }
Example #15
0
        static void Main(string[] args)
        {
            FlagParser.Parse(args);
            var exeFile = FlagParser.StringFlag("exeFile", string.Empty, true);
            var exePath = FlagParser.StringFlag("exePath", string.Empty, true);
            var zipFile = FlagParser.StringFlag("zipFile", string.Empty, true);

            if (string.IsNullOrWhiteSpace(exeFile) || string.IsNullOrWhiteSpace(exePath) || string.IsNullOrWhiteSpace(zipFile))
            {
                Console.WriteLine("Invalid Parameters");
                return;
            }
            // make sure exe file to update is not running
            foreach (var proc in Process.GetProcesses())
            {
                try
                {
                    if (proc.MainModule.FileName.Equals(exeFile, StringComparison.OrdinalIgnoreCase))
                    {
                        Console.WriteLine("-- Waiting for exit " + exeFile + " --");
                        proc.WaitForExit();
                        Console.WriteLine("-- Application closed " + exeFile + " --");
                    }
                }
                catch (Exception e)
                {
                    Debug.WriteLine(e.Message);
                    Debug.WriteLine(e.StackTrace);
                }
            }
            Console.WriteLine("-- Waiting for process to close --");
            Thread.Sleep(5000);
            Console.WriteLine("-- Extrating Files --");
            // open zip file
            using var zip = ZipStorer.Open(zipFile, FileAccess.Read);
            var dir = zip.Files.Values;

            foreach (var item in dir)
            {
                try
                {
                    if (item.FilenameInZip.ToLower().Contains("zipextractor", StringComparison.OrdinalIgnoreCase))
                    {
                        continue;
                    }
                    var extractFile = Path.Combine(exePath, item.FilenameInZip);
                    if (File.Exists(extractFile))
                    {
                        Console.WriteLine("-- Deleting File " + extractFile);
                        File.Delete(extractFile);
                    }
                    Console.WriteLine("-- Extracting File " + extractFile);
                    zip.ExtractFile(item, extractFile);
                    Console.WriteLine("-- Done Extracting File " + extractFile);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error: " + ex.Message);
                    continue;
                }
            }
            zip.Close();
            // done extract, run exe file again
            var psi = new ProcessStartInfo();

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && RuntimeInformation.OSArchitecture == Architecture.X64)
            {
                psi.FileName = exeFile;
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && RuntimeInformation.OSArchitecture == Architecture.X86)
            {
                psi.FileName = exeFile;
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && RuntimeInformation.OSArchitecture == Architecture.Arm)
            {
                psi.FileName = exeFile;
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && RuntimeInformation.OSArchitecture == Architecture.X64)
            {
                psi.FileName  = "/usr/bin/dotnet";
                psi.Arguments = exeFile.Replace(".exe", ".dll");
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && RuntimeInformation.OSArchitecture == Architecture.Arm)
            {
                psi.FileName  = "/usr/bin/dotnet";
                psi.Arguments = exeFile.Replace(".exe", ".dll");
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && RuntimeInformation.OSArchitecture == Architecture.X64)
            {
                psi.FileName  = "/usr/bin/dotnet";
                psi.Arguments = exeFile.Replace(".exe", ".dll");
            }
            Console.WriteLine("-- Running Application --");
            Console.WriteLine("Filename : " + psi.FileName);
            Console.WriteLine("Args : " + psi.Arguments);
            Process.Start(psi).WaitForExit();
            File.Delete(zipFile);
            Console.WriteLine("-- Update Done --");
            return;
        }
Example #16
0
        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;
            }
        }
Example #17
0
        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();
            }
        }