public static void Main(string[] args)
        {
            bool convertTextures = false;
            bool showHelp        = false;

            var options = new OptionSet()
            {
                { "convert-textures", "convert textures", v => convertTextures = v != null },
                { "h|help", "show this message and exit", v => showHelp = v != null },
            };

            List <string> extras;

            try
            {
                extras = options.Parse(args);
            }
            catch (OptionException e)
            {
                Console.Write("{0}: ", GetExecutableName());
                Console.WriteLine(e.Message);
                Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName());
                return;
            }

            if (extras.Count < 1 || extras.Count > 2 || showHelp == true)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ input_[sb|toc] [output_dir]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            string bundlePath, superbundlePath, layoutPath, outputBasePath;

            if (Path.GetExtension(extras[0]) == ".sb")
            {
                superbundlePath = Path.GetFullPath(extras[0]);
                bundlePath      = Path.ChangeExtension(superbundlePath, ".toc");
                layoutPath      = Helpers.FindLayoutPath(superbundlePath);
                outputBasePath  = extras.Count > 1 ? extras[1] : Path.ChangeExtension(superbundlePath, null) + "_unpack";
            }
            else
            {
                bundlePath      = Path.GetFullPath(extras[0]);
                superbundlePath = Path.ChangeExtension(bundlePath, ".sb");
                layoutPath      = Helpers.FindLayoutPath(bundlePath);
                outputBasePath  = extras.Count > 1 ? extras[1] : Path.ChangeExtension(bundlePath, null) + "_unpack";
            }

            if (string.IsNullOrEmpty(layoutPath) == true)
            {
                Console.WriteLine("Could not find layout file.");
                return;
            }

            var dataPath = Path.GetDirectoryName(layoutPath) ?? "";

            var bundle      = TableOfContentsFile.Read(bundlePath);
            var superbundle = SuperbundleFile.Read(superbundlePath);

            var extensionsById = ResourceTypes.GetExtensions();

            if (bundle.IsCas == false)
            {
                throw new NotImplementedException();
            }
            else
            {
                var commonBundlePaths = Directory.GetFiles(dataPath, "chunks*.toc", SearchOption.AllDirectories);
                var commonBundles     = new List <TableOfContentsFile>();
                foreach (var commonBundlePath in commonBundlePaths)
                {
                    var commonBundle = TableOfContentsFile.Read(commonBundlePath);
                    commonBundles.Add(commonBundle);
                }

                var superbundleName = Path.ChangeExtension(superbundlePath.Substring(dataPath.Length + 1), null);
                superbundleName = Helpers.FilterName(superbundleName).ToLowerInvariant();

                var layout        = LayoutFile.Read(layoutPath);
                var installChunks = GetSuperbundleInstallChunks(layout, superbundleName);
                var catalogLookup = new CatalogLookup(dataPath);

                foreach (var installChunk in installChunks)
                {
                    if (catalogLookup.Add(installChunk.InstallBundle) == false)
                    {
                        Console.WriteLine("Failed to load catalog for '{0}'.", installChunk.Name);
                    }
                }

                foreach (var bundleInfo in superbundle.Bundles)
                {
                    if (bundleInfo.Resources == null)
                    {
                        continue;
                    }

                    foreach (var resourceInfo in bundleInfo.Resources)
                    {
                        var entry = catalogLookup.GetEntry(resourceInfo);
                        if (entry == null)
                        {
                            Console.WriteLine("Could not find catalog entry for '{0}'.", resourceInfo.Name);
                            continue;
                        }

                        if (entry.CompressedSize != resourceInfo.Size)
                        {
                            throw new FormatException();
                        }

                        var outputName       = Helpers.FilterPath(resourceInfo.Name);
                        var outputPath       = Path.Combine(outputBasePath, outputName + ".dummy");
                        var outputParentPath = Path.GetDirectoryName(outputPath);
                        if (string.IsNullOrEmpty(outputParentPath) == false)
                        {
                            Directory.CreateDirectory(outputParentPath);
                        }

                        Console.WriteLine("{0}", resourceInfo.Name);

                        bool wasConverted = false;
                        if (convertTextures == true && resourceInfo.ResourceType == ResourceTypes.Texture)
                        {
                            wasConverted = ConvertTexture(bundleInfo,
                                                          resourceInfo,
                                                          entry,
                                                          outputPath,
                                                          catalogLookup,
                                                          commonBundles);
                        }

                        if (wasConverted == false)
                        {
                            string extension;
                            if (extensionsById.TryGetValue(resourceInfo.ResourceType, out extension) == true)
                            {
                                extension = "." + extension;
                            }
                            else
                            {
                                extension = ".#" + resourceInfo.ResourceType.ToString("X8");
                            }

                            outputPath = Path.Combine(outputBasePath, outputName + extension);
                            using (var output = File.Create(outputPath))
                            {
                                Extraction.Extract(resourceInfo, entry, output);
                            }
                        }
                    }
                }
            }
        }
Beispiel #2
0
        public static void Main(string[] args)
        {
            bool noPatch         = false;
            bool noCatch         = false;
            int  logLevelOrdinal = 3;
            bool showHelp        = false;

            var options = new OptionSet()
            {
                { "no-catch", "don't catch exceptions when loading data", v => noCatch = v != null },
                { "v|verbose", "increase log level (-v/-vv/-vvv)", v => IncreaseLogLevel(v, ref logLevelOrdinal) },
                { "h|help", "show this message and exit", v => showHelp = v != null },
            };

            List <string> extras;

            try
            {
                extras = options.Parse(args);
            }
            catch (OptionException e)
            {
                Console.Write("{0}: ", GetExecutableName());
                Console.WriteLine(e.Message);
                Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName());
                return;
            }

            if (extras.Count < 1 || extras.Count > 2 || showHelp == true)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ game_dir [output_dir]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            LogHelper.SetConfiguration(NLog.LogLevel.FromOrdinal(logLevelOrdinal));

            var outputBasePath = extras.Count > 1 ? extras[1] : "res_unpack";

            List <string> files = Directory.GetFiles(extras[0], "*.*",
                                                     SearchOption.AllDirectories).Where(s => s.EndsWith(".toc", StringComparison.OrdinalIgnoreCase)).ToList();

            for (int i = 0; i < files.Count; i++)
            {
                var    inputPath = files[i];
                string superbundleName;
                var    dataBasePath = Discovery.FindBasePath(inputPath, out superbundleName);
                if (string.IsNullOrEmpty(dataBasePath) == true)
                {
                    Logger.Error("Failed to discover base game path.");
                    continue;
                }
                Console.WriteLine("----- " + (i + 1) + " of " + files.Count + " - " + Path.GetFileName(inputPath) + " ----");
                Thread.Sleep(1000);
                var dataManager = DataManager.Initialize(dataBasePath, noPatch);
                if (dataManager == null)
                {
                    Logger.Fatal("Could not initialize superbundle manager.");
                    continue;
                }

                var extensionsById = ResourceTypes.GetExtensions();

                VfsFormats.SuperbundleFile superbundle = null;
                try
                {
                    superbundle = dataManager.MountSuperbundle(superbundleName);
                }
                catch
                {
                    superbundle = null;
                }
                if (superbundle == null)
                {
                    continue;
                }

                foreach (var resourceInfo in superbundle.Bundles
                         .Where(bi => bi.Resources != null)
                         .SelectMany(bi => bi.Resources)
                         .OrderBy(bi => bi.Name))
                {
                    using (var data = new MemoryStream())
                    {
                        Logger.Info(resourceInfo.Name);

                        if (noCatch == true)
                        {
                            dataManager.LoadData(resourceInfo, data);
                            data.Position = 0;
                        }
                        else
                        {
                            try
                            {
                                dataManager.LoadData(resourceInfo, data);
                                data.Position = 0;
                            }
                            catch (ChunkCryptoKeyMissingException e)
                            {
                                Logger.Warn("Cannot decrypt '{0}' without crypto key '{1}'.",
                                            resourceInfo.Name,
                                            e.KeyId);
                                continue;
                            }
                            catch (Exception e)
                            {
                                Logger.Warn(e, "Exception while loading '{0}':", resourceInfo.Name);
                                continue;
                            }
                        }

                        if (resourceInfo.ResourceType != ResourceTypes.Texture)
                        {
                            continue;
                        }

                        var outputName       = Helpers.FilterPath(resourceInfo.Name);
                        var outputPath       = Path.Combine(outputBasePath, outputName + ".dummy");
                        var outputParentPath = Path.GetDirectoryName(outputPath);
                        if (string.IsNullOrEmpty(outputParentPath) == false)
                        {
                            Directory.CreateDirectory(outputParentPath);
                        }

                        outputPath = Path.Combine(outputBasePath, outputName + ".dds");
                        Console.WriteLine(outputPath);
                        ConvertTexture(data, outputPath, dataManager);
                    }
                }

                dataManager.Dispose();
            }
        }
Beispiel #3
0
        public static void Main(string[] args)
        {
            bool convertTextures = false;
            bool verbose         = false;
            bool showHelp        = false;

            var options = new OptionSet()
            {
                { "convert-textures", "convert textures", v => convertTextures = v != null },
                { "v|verbose", "be verbose", v => verbose = v != null },
                { "h|help", "show this message and exit", v => showHelp = v != null },
            };

            List <string> extras;

            try
            {
                extras = options.Parse(args);
            }
            catch (OptionException e)
            {
                Console.Write("{0}: ", GetExecutableName());
                Console.WriteLine(e.Message);
                Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName());
                return;
            }

            if (extras.Count < 1 || extras.Count > 2 || showHelp == true)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ input_[sb|toc] [output_dir]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            Paths paths;

            if (Paths.Discover(extras[0], extras.Count > 1 ? extras[1] : null, out paths) == false)
            {
                Console.WriteLine("Failed to discover data paths.");
                return;
            }

            var extensionsById = ResourceTypes.GetExtensions();

            var superbundleName = Path.ChangeExtension(paths.Superbundle.Substring(paths.Data.Length + 1), null);

            superbundleName = Helpers.FilterName(superbundleName).ToLowerInvariant();

            var layout = LayoutFile.Read(Path.Combine(paths.Data, "layout.toc"));

            var chunkLookup = new ChunkLookup(layout, paths.Data);
            var chunkLoader = new ChunkLoader(chunkLookup);

            var initFileSystemPath = Path.Combine(paths.Data, "initfs_Win32");

            CasEncryptHelper.TryLoad(initFileSystemPath, chunkLoader);

            var superbundle = chunkLookup.AddBundle(superbundleName);

            // add common chunk bundles (chunks*.toc/sb)
            foreach (var superbundleInfo in layout.Superbundles.Where(
                         sbi => ChunkLookup.IsChunkBundle(sbi.Name) == true))
            {
                if (chunkLookup.AddBundle(superbundleInfo.Name.ToLowerInvariant()) == null)
                {
                    Console.WriteLine("Failed to load catalog for '{0}'.", superbundleInfo.Name);
                }
            }

            foreach (var bundleInfo in superbundle.Bundles)
            {
                if (bundleInfo.Resources == null)
                {
                    continue;
                }

                foreach (var resourceInfo in bundleInfo.Resources)
                {
                    using (var data = new MemoryStream())
                    {
                        try
                        {
                            chunkLoader.Load(resourceInfo, data);
                            data.Position = 0;
                        }
                        catch (ChunkCryptoKeyMissingException e)
                        {
                            Console.WriteLine("Cannot decrypt '{0}' without crypto key '{1}'.",
                                              resourceInfo.Name,
                                              e.KeyId);
                            continue;
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("Exception while loading '{0}':", resourceInfo.Name);
                            Console.WriteLine(e);
                            continue;
                        }

                        var outputName       = Helpers.FilterPath(resourceInfo.Name);
                        var outputPath       = Path.Combine(paths.Output, outputName + ".dummy");
                        var outputParentPath = Path.GetDirectoryName(outputPath);
                        if (string.IsNullOrEmpty(outputParentPath) == false)
                        {
                            Directory.CreateDirectory(outputParentPath);
                        }

                        if (verbose == true)
                        {
                            Console.WriteLine("{0}", resourceInfo.Name);
                        }

                        bool wasConverted = false;
                        if (convertTextures == true && resourceInfo.ResourceType == ResourceTypes.Texture)
                        {
                            outputPath   = Path.Combine(paths.Output, outputName + ".dds");
                            wasConverted = ConvertTexture(data, outputPath, chunkLookup, chunkLoader);
                        }

                        if (wasConverted == false)
                        {
                            string extension;
                            if (extensionsById.TryGetValue(resourceInfo.ResourceType, out extension) == true)
                            {
                                extension = "." + extension;
                            }
                            else
                            {
                                extension = ".#" + resourceInfo.ResourceType.ToString("X8");
                            }

                            outputPath = Path.Combine(paths.Output, outputName + extension);
                            using (var output = File.Create(outputPath))
                            {
                                output.WriteFromStream(data, data.Length);
                            }
                        }
                    }
                }
            }
        }
Beispiel #4
0
        public static void Main(string[] args)
        {
            bool convertTextures = false;
            bool noPatch         = false;
            bool noCatch         = false;
            int  logLevelOrdinal = 3;
            bool showHelp        = false;

            var options = new OptionSet()
            {
                { "t|convert-textures", "convert textures", v => convertTextures = v != null },
                { "no-patch", "don't use patch data", v => noPatch = v != null },
                { "no-catch", "don't catch exceptions when loading data", v => noCatch = v != null },
                { "v|verbose", "increase log level (-v/-vv/-vvv)", v => IncreaseLogLevel(v, ref logLevelOrdinal) },
                { "h|help", "show this message and exit", v => showHelp = v != null },
            };

            List <string> extras;

            try
            {
                extras = options.Parse(args);
            }
            catch (OptionException e)
            {
                Console.Write("{0}: ", GetExecutableName());
                Console.WriteLine(e.Message);
                Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName());
                return;
            }

            if (extras.Count < 1 || extras.Count > 2 || showHelp == true)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ input_[sb|toc] [output_dir]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            LogHelper.SetConfiguration(NLog.LogLevel.FromOrdinal(logLevelOrdinal));

            var inputPath      = extras[0];
            var outputBasePath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, null) + "_res_unpack";

            string superbundleName;
            var    dataBasePath = Discovery.FindBasePath(inputPath, out superbundleName);

            if (string.IsNullOrEmpty(dataBasePath) == true)
            {
                Logger.Error("Failed to discover base game path.");
                return;
            }

            var dataManager = DataManager.Initialize(dataBasePath, noPatch);

            if (dataManager == null)
            {
                Logger.Fatal("Could not initialize superbundle manager.");
                return;
            }

            var extensionsById = ResourceTypes.GetExtensions();

            var superbundle = dataManager.MountSuperbundle(superbundleName);

            foreach (var resourceInfo in superbundle.Bundles
                     .Where(bi => bi.Resources != null)
                     .SelectMany(bi => bi.Resources)
                     .OrderBy(bi => bi.Name))
            {
                using (var data = new MemoryStream())
                {
                    Logger.Info(resourceInfo.Name);

                    if (noCatch == true)
                    {
                        dataManager.LoadData(resourceInfo, data);
                        data.Position = 0;
                    }
                    else
                    {
                        try
                        {
                            dataManager.LoadData(resourceInfo, data);
                            data.Position = 0;
                        }
                        catch (ChunkCryptoKeyMissingException e)
                        {
                            Logger.Warn("Cannot decrypt '{0}' without crypto key '{1}'.",
                                        resourceInfo.Name,
                                        e.KeyId);
                            continue;
                        }
                        catch (Exception e)
                        {
                            Logger.Warn(e, "Exception while loading '{0}':", resourceInfo.Name);
                            continue;
                        }
                    }

                    var outputName       = Helpers.FilterPath(resourceInfo.Name);
                    var outputPath       = Path.Combine(outputBasePath, outputName + ".dummy");
                    var outputParentPath = Path.GetDirectoryName(outputPath);
                    if (string.IsNullOrEmpty(outputParentPath) == false)
                    {
                        Directory.CreateDirectory(outputParentPath);
                    }

                    bool wasConverted = false;
                    if (convertTextures == true && resourceInfo.ResourceType == ResourceTypes.Texture)
                    {
                        outputPath   = Path.Combine(outputBasePath, outputName + ".dds");
                        wasConverted = ConvertTexture(data, outputPath, dataManager);
                    }

                    if (wasConverted == false)
                    {
                        string extension;
                        if (extensionsById.TryGetValue(resourceInfo.ResourceType, out extension) == true)
                        {
                            extension = "." + extension;
                        }
                        else
                        {
                            extension = ".#" + resourceInfo.ResourceType.ToString("X8");
                        }

                        outputPath = Path.Combine(outputBasePath, outputName + extension);
                        using (var output = File.Create(outputPath))
                        {
                            data.Position = 0;
                            output.WriteFromStream(data, data.Length);
                        }
                    }
                }
            }

            dataManager.Dispose();
        }