예제 #1
0
 public EntryUnpacker(GTVolume baseVolume, string outDir, string parentDir, List <int> fileIndexesToExtract)
 {
     _volume               = baseVolume;
     OutDir                = outDir;
     ParentDirectory       = parentDir;
     _fileIndexesToExtract = fileIndexesToExtract;
 }
예제 #2
0
        public static void List(ListVerbs options)
        {
            bool isFile = File.Exists(options.InputPath);
            bool isDir  = false;

            if (!isFile)
            {
                isDir = Directory.Exists(options.InputPath);
                if (!isDir)
                {
                    Console.WriteLine($"[X] Volume file or PDIPFS folder \"{options.InputPath}\" does not exist.");
                    return;
                }
            }


            Keyset[] keyset = CheckKeys();
            if (keyset is null)
            {
                return;
            }

            bool     found = false;
            GTVolume vol   = null;

            foreach (var k in keyset)
            {
                vol = GTVolume.Load(k, options.InputPath, isDir, Syroot.BinaryData.Core.Endian.Big);
                if (vol != null)
                {
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                Console.WriteLine($"[X] Could not unpack volume. Make sure that you have a valid game key/seed in your key.json.");
                return;
            }

            using var sw = new StreamWriter(options.OutputPath);
            var entries = vol.TableOfContents.GetAllRegisteredFileMap();

            foreach (var entry in entries)
            {
                if (vol.IsPatchVolume)
                {
                    sw.WriteLine($"{entry.Key} ({entry.Value.EntryIndex}) - {PDIPFSPathResolver.GetPathFromSeed(entry.Value.EntryIndex)}");
                }
                else
                {
                    sw.WriteLine($"{entry.Key} ({entry.Value.EntryIndex})");
                }
            }

            sw.WriteLine($"[!] Wrote {entries.Count} at {options.OutputPath}.");
        }
예제 #3
0
        public static void Pack(PackVerbs options)
        {
            bool isFile = File.Exists(options.InputPath);
            bool isDir  = false;

            if (!isFile)
            {
                isDir = Directory.Exists(options.InputPath);
                if (!isDir)
                {
                    Console.WriteLine($"[X] Volume file or PDIPFS folder \"{options.InputPath}\" does not exist.");
                    return;
                }
            }

            if (File.Exists(options.FolderToRepack))
            {
                Program.Log("[X] No, don't put a specific file to repack. Use the whole folder containing files in their proper volume folder." +
                            "Example: Your input folder is GT5, inside is a file like textdata/gt5/somefile.xml, just use '-p GT5'. ");
                return;
            }
            else if (!Directory.Exists(options.FolderToRepack))
            {
                Program.Log("[X] Folder to pack directory does not exist, create it first and put the files to pack inside accordingly with their proper game path.");
                return;
            }

            Keyset[] keyset = CheckKeys();
            if (keyset is null)
            {
                return;
            }

            if (!string.IsNullOrEmpty(options.LogPath))
            {
                sw = new StreamWriter(options.LogPath);
            }

            if (!string.IsNullOrEmpty(options.CustomGameID) && options.CustomGameID.Length > 128)
            {
                Console.WriteLine($"[X] Custom Game ID must not be above 128 characters.");
                return;
            }

            bool     found = false;
            GTVolume vol   = null;

            foreach (var k in keyset)
            {
                vol = GTVolume.Load(k, options.InputPath, isDir, Syroot.BinaryData.Core.Endian.Big);
                if (vol != null)
                {
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                Console.WriteLine($"[X] Could not decrypt volume to read information for packing. Make sure that you have a valid game key/seed in your key.json.");
                return;
            }

            PrintToConsole = true;

            if (!vol.IsPatchVolume)
            {
                Program.Log("[X] Cannot repack files in single volume files (GT.VOL).");
                return;
            }

            if (options.Cache)
            {
                Program.Log("[!] Using packing cache.");
            }
            vol.UsePackingCache = options.Cache;

            Program.Log("[-] Started packing process.");

            string[] filesToRemove = Array.Empty <string>();
            if (options.PackRemoveFiles && File.Exists("files_to_remove.txt"))
            {
                filesToRemove = File.ReadAllLines("files_to_remove.txt");
            }

            if (options.PackAllAsNew)
            {
                Program.Log("[!] Note: --pack-all-as-new provided - packing as new is now on by default. To use overwrite mode, use --pack-as-overwrite");
            }

            if (vol.UsePackingCache && File.Exists(".pack_cache"))
            {
                vol.ReadPackingCache(".pack_cache");
            }

            vol.NoCompress = options.NoCompress;
            vol.RegisterEntriesToRepack(options.FolderToRepack);
            vol.PackFiles(options.OutputPath, filesToRemove, !options.PackAsOverwrite, options.CustomGameID);
        }
예제 #4
0
        public static void Unpack(UnpackVerbs options)
        {
            bool isFile = File.Exists(options.InputPath);
            bool isDir  = false;

            if (!isFile)
            {
                isDir = Directory.Exists(options.InputPath);
                if (!isDir)
                {
                    Console.WriteLine($"[X] Volume file or PDIPFS folder \"{options.InputPath}\" does not exist.");
                    return;
                }
            }


            Keyset[] keyset = CheckKeys();
            if (keyset is null)
            {
                return;
            }


            if (!string.IsNullOrEmpty(options.LogPath))
            {
                sw = new StreamWriter(options.LogPath);
            }

            SaveTOC    = options.SaveTOC;
            SaveHeader = options.SaveVolumeHeader;
            if (isDir)
            {
                string indexFile = Path.Combine(options.InputPath, PDIPFSPathResolver.Default);
                if (!File.Exists(indexFile))
                {
                    Console.WriteLine($"[X] Provided input folder (assuming PDIPFS) does not contain an Index file. ({PDIPFSPathResolver.Default}) Make sure this folder is actually a PDIPFS folder.");
                    return;
                }
            }

            bool     found = false;
            GTVolume vol   = null;

            foreach (var k in keyset)
            {
                vol = GTVolume.Load(k, options.InputPath, isDir, Syroot.BinaryData.Core.Endian.Big);
                if (vol != null)
                {
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                Console.WriteLine($"[X] Could not unpack volume. Make sure that you have a valid game key/seed in your key.json.");
                return;
            }

            Program.Log("[-] Started unpacking process.");
            vol.SetOutputDirectory(options.OutputPath);
            if (options.OnlyLog)
            {
                vol.NoUnpack = true;
            }

            vol.UnpackFiles(options.FileIndexesToExtract);
        }
예제 #5
0
 public GTVolumeTOC(GTVolumeHeader parentHeader, GTVolume parentVolume)
 {
     ParentHeader = parentHeader;
     ParentVolume = parentVolume;
 }
예제 #6
0
        /// <summary>
        /// Loads a volume file.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="isPatchVolume"></param>
        /// <param name="endianness"></param>
        /// <returns></returns>
        public static GTVolume Load(Keyset keyset, string path, bool isPatchVolume, Endian endianness)
        {
            var fs = new FileStream(!isPatchVolume ? path : Path.Combine(path, PDIPFSPathResolver.Default), FileMode.Open);

            GTVolume vol;

            if (isPatchVolume)
            {
                vol = new GTVolume(path, Endian.Big);
            }
            else
            {
                vol = new GTVolume(fs, endianness);
            }
            vol.SetKeyset(keyset);

            if (fs.Length < HeaderSize)
            {
                throw new IndexOutOfRangeException($"Volume header file size is smaller than expected header size ({HeaderSize}). Ensure that your volume file is not corrupt.");
            }

            vol.VolumeHeaderData = new byte[HeaderSize];
            fs.Read(vol.VolumeHeaderData);

            if (!vol.DecryptHeader(vol.VolumeHeaderData, BASE_VOLUME_ENTRY_INDEX))
            {
                fs?.Dispose();
                return(null);
            }

            if (!vol.ReadHeader(vol.VolumeHeaderData))
            {
                fs?.Dispose();
                return(null);
            }

            if (Program.SaveHeader)
            {
                File.WriteAllBytes("VolumeHeader.bin", vol.VolumeHeaderData);
            }

            Program.Log("[-] Reading table of contents.", true);

            if (!vol.DecryptTOC())
            {
                fs?.Dispose();
                return(null);
            }

            if (!vol.TableOfContents.LoadTOC())
            {
                fs?.Dispose();
                return(null);
            }

            Program.Log($"[>] File names tree offset: {vol.TableOfContents.NameTreeOffset}", true);
            Program.Log($"[>] File extensions tree offset: {vol.TableOfContents.FileExtensionTreeOffset}", true);
            Program.Log($"[>] Node tree offset: {vol.TableOfContents.NodeTreeOffset}", true);
            Program.Log($"[>] Entry count: {vol.TableOfContents.RootAndFolderOffsets.Count}.", true);

            if (Program.SaveTOC)
            {
                File.WriteAllBytes("VolumeTOC.bin", vol.TableOfContents.Data);
            }

            return(vol);
        }