public EntryUnpacker(GTVolume baseVolume, string outDir, string parentDir, List <int> fileIndexesToExtract) { _volume = baseVolume; OutDir = outDir; ParentDirectory = parentDir; _fileIndexesToExtract = fileIndexesToExtract; }
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}."); }
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); }
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); }
public GTVolumeTOC(GTVolumeHeader parentHeader, GTVolume parentVolume) { ParentHeader = parentHeader; ParentVolume = parentVolume; }
/// <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); }