Example #1
0
        private static void ExceptionHandler(object sender, UnhandledExceptionEventArgs e)
        {
            if (e.ExceptionObject is Exception ex)
            {
                Logger.Error(null, ex.ToString());
                if (Debugger.IsAttached)
                {
                    throw ex;
                }
            }

            unchecked {
                Environment.Exit((int)0xDEADBEEF);
            }
        }
Example #2
0
        public static void ShutdownMisc()
        {
            if (!string.IsNullOrWhiteSpace(Flags.ScratchDBPath))
            {
                var dbPath = Flags.ScratchDBPath;
                if (!File.Exists(dbPath) || new DirectoryInfo(dbPath).Exists)
                {
                    dbPath = Path.Combine(Path.GetFullPath(Flags.ScratchDBPath), "Scratch.db");
                }

                if (Flags.Deduplicate && !string.IsNullOrWhiteSpace(dbPath))
                {
                    Logger.Warn("ScratchDB", "Saving Scratch database...");
                    Combo.ScratchDBInstance.Save(dbPath);
                }
            }
        }
Example #3
0
 public void AddTask(Action action)
 {
     if (Program.Flags?.DisableAsyncSave == true)
     {
         action();
     }
     else
     {
         m_pendingTasks.Add(Task.Run(() => {
             try {
                 action();
             } catch (Exception e) {
                 Logger.Error("Combo", $"Async exception: {e}");
             }
         }));
     }
 }
Example #4
0
 public static void ConvertSoundFile(Stream stream, Stream outputStream)
 {
     try {
         using (Sound.WwiseRIFFVorbis vorbis =
                    new Sound.WwiseRIFFVorbis(stream,
                                              Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Third Party",
                                                                            "packed_codebooks_aoTuV_603.bin")))) {
             Stream vorbisStream = new MemoryStream();
             vorbis.ConvertToOgg(vorbisStream);
             vorbisStream.Position = 0;
             using (Stream revorbStream = RevorbStd.Revorb.Jiggle(vorbisStream)) {
                 revorbStream.Position = 0;
                 revorbStream.CopyTo(outputStream);
             }
         }
     } catch (Exception e) {
         Logger.Error("Combo", $"Error converting sound: {e}");
     }
 }
Example #5
0
        public static void InitMisc()
        {
            var dbPath = Flags.ScratchDBPath;

            if (Flags.Deduplicate)
            {
                Logger.Warn("ScratchDB", "Will attempt to deduplicate files if extracting...");
                if (!string.IsNullOrWhiteSpace(Flags.ScratchDBPath))
                {
                    Logger.Warn("ScratchDB", "Loading Scratch database...");
                    if (!File.Exists(dbPath) || new DirectoryInfo(dbPath).Exists)
                    {
                        dbPath = Path.Combine(Path.GetFullPath(Flags.ScratchDBPath), "Scratch.db");
                    }

                    Combo.ScratchDBInstance.Load(dbPath);
                }
            }

            IO.LoadGUIDTable();
            Sound.WwiseBank.GetReady();
        }
Example #6
0
        private static void ConvertAnimation(Stream animStream, string path, bool convertAnims, FindLogic.Combo.AnimationAsset animationInfo, bool scaleAnims)
        {
            var parsedAnimation = default(teAnimation);
            var priority        = 100;

            try
            {
                parsedAnimation = new teAnimation(animStream, true);
                priority        = parsedAnimation.Header.Priority;
            }
            catch (Exception)
            {
                Logger.Error("Combo", $"Unable to parse animation {animationInfo.GetName()}");
            }
            string animationDirectory =
                Path.Combine(path, "Animations", priority.ToString());

            if (convertAnims && parsedAnimation != null)
            {
                SEAnim seAnim     = new SEAnim(parsedAnimation, scaleAnims);
                string animOutput = Path.Combine(animationDirectory,
                                                 animationInfo.GetNameIndex() + "." + seAnim.Extension);
                CreateDirectoryFromFile(animOutput);
                using (Stream fileStream = new FileStream(animOutput, FileMode.Create)) {
                    seAnim.Write(fileStream);
                }
            }
            else
            {
                animStream.Position = 0;
                string rawAnimOutput = Path.Combine(animationDirectory,
                                                    $"{animationInfo.GetNameIndex()}.{teResourceGUID.Type(animationInfo.m_GUID):X3}");
                CreateDirectoryFromFile(rawAnimOutput);
                using (Stream fileStream = new FileStream(rawAnimOutput, FileMode.Create)) {
                    animStream.CopyTo(fileStream);
                }
            }
        }
Example #7
0
        public static void InitKeys()
        {
            if (!Flags.SkipKeys)
            {
                Logger.Info("Core", "Checking ResourceKeys");

                foreach (var key in TrackedFiles[0x90])
                {
                    if (!ValidKey(key))
                    {
                        continue;
                    }

                    var resourceKey = GetInstance <STUResourceKey>(key);
                    if (resourceKey == null || resourceKey.GetKeyID() == 0 || Client.ConfigHandler.Keyring.Keys.ContainsKey(resourceKey.GetReverseKeyID()))
                    {
                        continue;
                    }
                    Client.ConfigHandler.Keyring.AddKey(resourceKey.GetReverseKeyID(), resourceKey.m_key);
                    Logger.Info("Core", $"Added ResourceKey {resourceKey.GetKeyIDString()}, Value: {resourceKey.GetKeyValueString()}");
                }
            }
        }
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 InitStorage(bool online = true)
        {
            if (Flags.Language != null)
            {
                Logger.Info("CASC", $"Set language to {Flags.Language}");
            }

            if (Flags.SpeechLanguage != null)
            {
                Logger.Info("CASC", $"Set speech language to {Flags.SpeechLanguage}");
            }

            var args = new ClientCreateArgs {
                SpeechLanguage = Flags.SpeechLanguage,
                TextLanguage   = Flags.Language,
                HandlerArgs    = new ClientCreateArgs_Tank {
                    CacheAPM = Flags.UseCache
                },
                Online = online
            };

            LoadHelper.PreLoad();
            Client = new ClientHandler(Flags.OverwatchDirectory, args);
            LoadHelper.PostLoad(Client);

            if (args.TextLanguage != "enUS")
            {
                Logger.Warn("Core", "Reminder! When extracting data in other languages, the names of the heroes/skins/etc must be in the language you have chosen.");
            }

            if (Client.AgentProduct.ProductCode != "pro")
            {
                Logger.Warn("Core", $"The branch \"{Client.AgentProduct.ProductCode}\" is not supported!. This might result in failure to load. Proceed with caution.");
            }

            if (!Client.AgentProduct.Settings.Languages.Select(x => x.Language)
                .Contains(args.TextLanguage))
            {
                Logger.Warn("Core", "Battle.Net Agent reports that language {0} is not installed.", args.TextLanguage);
            }
            else if (!Client.AgentProduct.Settings.Languages.Select(x => x.Language)
                     .Contains(args.SpeechLanguage))
            {
                Logger.Warn("Core", "Battle.Net Agent reports that language {0} is not installed.", args.SpeechLanguage);
            }

            TankHandler = Client.ProductHandler as ProductHandler_Tank;
            if (TankHandler == null)
            {
                Logger.Error("Core", $"Not a valid Overwatch installation (detected product: {Client.Product})");
                return;
            }

            BuildVersion = uint.Parse(Client.InstallationInfo.Values["Version"]
                                      .Split('.')
                                      .Last());
            if (BuildVersion < 39028)
            {
                Logger.Error("Core", "DataTool doesn't support Overwatch versions below 1.14. Please use OverTool.");
            }
            else if (BuildVersion < 56957)
            {
                Logger.Error("Core", "This version of DataTool doesn't support versions of Overwatch below 1.35. Please downgrade DataTool.");
            }

            InitTrackedFiles();
        }
Example #10
0
        private static async Task SaveTextureTask(ICLIFlags flags, string path, SaveContext info, ulong textureGUID, string name = null)
        {
            bool   convertTextures         = true;
            string convertType             = "tif";
            string multiSurfaceConvertType = "tif";
            bool   createMultiSurfaceSheet = false;
            bool   lossless = false;
            int    maxMips  = 1;

            if (flags is ExtractFlags extractFlags)
            {
                if (extractFlags.SkipTextures)
                {
                    return;
                }
                createMultiSurfaceSheet = extractFlags.SheetMultiSurface;
                convertTextures         = !extractFlags.RawTextures && !extractFlags.Raw;
                convertType             = extractFlags.ConvertTexturesType.ToLowerInvariant();
                lossless = extractFlags.ConvertTexturesLossless;

                multiSurfaceConvertType = convertType;
                if (extractFlags.ForceDDSMultiSurface)
                {
                    multiSurfaceConvertType = "dds";
                }

                if (convertType == "dds" && extractFlags.SaveMips)
                {
                    maxMips = 0xF;
                }
            }

            if (!path.EndsWith(Path.DirectorySeparatorChar.ToString()))
            {
                path += Path.DirectorySeparatorChar;
            }


            FindLogic.Combo.TextureAsset textureInfo = info.m_info.m_textures[textureGUID];
            string filePath = Path.Combine(path, name ?? $"{textureInfo.GetNameIndex()}");

            if (teResourceGUID.Type(textureGUID) != 0x4)
            {
                filePath += $".{teResourceGUID.Type(textureGUID):X3}";
            }

            if (Program.Flags != null && Program.Flags.Deduplicate)
            {
                if (ScratchDBInstance.HasRecord(textureGUID))
                {
                    return;
                }

                ScratchDBInstance[textureGUID] = new ScratchDB.ScratchPath($"{filePath}.{convertType}", true);
            }

            CreateDirectoryFromFile(path);

            await s_texurePrepareSemaphore.WaitAsync();

            try {
                if (!convertTextures)
                {
                    teTexture texture;
                    using (Stream textureStream = OpenFile(textureGUID)) {
                        texture = new teTexture(textureStream, true);
                        textureStream.Position = 0;
                        WriteFile(textureStream, $"{filePath}.004");
                    }

                    if (!texture.PayloadRequired)
                    {
                        return;
                    }
                    for (int i = 0; i < texture.Payloads.Length; ++i)
                    {
                        using (Stream texturePayloadStream = OpenFile(texture.GetPayloadGUID(textureGUID, i)))
                            WriteFile(texturePayloadStream, $"{filePath}_{i}.04D");
                    }
                }
                else
                {
                    teTexture texture;
                    using (Stream textureStream = OpenFile(textureGUID)) {
                        if (textureStream == null)
                        {
                            return;
                        }

                        texture = new teTexture(textureStream);
                    }

                    //if (texture.Header.Flags.HasFlag(teTexture.Flags.CUBEMAP)) return;
                    // for diffing when they add/regen loads of cubemaps

                    if (texture.PayloadRequired)
                    {
                        for (int i = 0; i < texture.Payloads.Length; ++i)
                        {
                            using (var payloadStream = OpenFile(texture.GetPayloadGUID(textureGUID, i)))
                                texture.LoadPayload(payloadStream, i);
                            if (maxMips == 1)
                            {
                                break;
                            }
                        }
                    }

                    uint?width    = null;
                    uint?height   = null;
                    uint?surfaces = null;
                    if (texture.Header.IsCubemap || texture.Header.IsArray || texture.HasMultipleSurfaces)
                    {
                        if (createMultiSurfaceSheet)
                        {
                            Logger.Debug("Combo", $"Saving {Path.GetFileName(filePath)} as a sheet because it has more than one surface");
                            height               = (uint)(texture.Header.Height * texture.Header.Surfaces);
                            surfaces             = 1;
                            texture.Header.Flags = 0;
                        }
                        else if (convertType != "tif" && convertType != "dds")
                        {
                            Logger.Debug("Combo", $"Saving {Path.GetFileName(filePath)} as {multiSurfaceConvertType} because it has more than one surface");
                            convertType = multiSurfaceConvertType;
                        }
                    }


                    WICCodecs?imageFormat = null;
                    switch (convertType)
                    {
                    case "tif":
                        imageFormat = WICCodecs.TIFF;
                        break;

                    case "png":
                        imageFormat = WICCodecs.PNG;
                        break;

                    case "jpg":
                        imageFormat = WICCodecs.JPEG;
                        break;
                    }

                    // if (convertType == "tga") imageFormat = Im.... oh
                    // so there is no TGA image format.
                    // sucks to be them

                    if (convertType == "dds")
                    {
                        using (Stream convertedStream = texture.SaveToDDS(maxMips == 1 ? 1 : texture.Header.MipCount, width, height, surfaces)) {
                            WriteFile(convertedStream, $"{filePath}.dds");
                        }

                        return;
                    }

                    Process pProcess;

                    using (Stream convertedStream = texture.SaveToDDS(maxMips == 1 ? 1 : texture.Header.MipCount, width, height, surfaces)) {
                        var data = DDSConverter.ConvertDDS(convertedStream, DXGI_FORMAT.R8G8B8A8_UNORM, imageFormat.Value, 0);
                        if (data != null)
                        {
                            WriteFile(data, $"{filePath}.{convertType}");
                        }
                        else
                        {
                            convertedStream.Position = 0;
                            WriteFile(convertedStream, $"{filePath}.dds");
                            Logger.Error("Combo", $"Unable to save {Path.GetFileName(filePath)} as {convertType} because DirectXTex failed.");
                        }
                    }
                }
            } finally {
                s_texurePrepareSemaphore.Release();
            }
        }