mirror of
https://github.com/UltiNaruto/PKGTool
synced 2024-11-22 11:43:21 +00:00
Version 1.4.5
Implemented an argument system Added -i command to ignore data section size check on read
This commit is contained in:
parent
2829b64bd4
commit
0a176ee74d
4 changed files with 209 additions and 106 deletions
|
@ -8,6 +8,7 @@ namespace Dread.FileFormats
|
||||||
public class PKG : BinaryStruct
|
public class PKG : BinaryStruct
|
||||||
{
|
{
|
||||||
public List<KeyValuePair<UInt64, MemoryStream>> Files = new List<KeyValuePair<UInt64, MemoryStream>>();
|
public List<KeyValuePair<UInt64, MemoryStream>> Files = new List<KeyValuePair<UInt64, MemoryStream>>();
|
||||||
|
public bool IgnoreDataSectionSizeCheck = false;
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
|
@ -86,7 +87,7 @@ namespace Dread.FileFormats
|
||||||
stream.Position = stream.Position.Aligned(8);
|
stream.Position = stream.Position.Aligned(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data_section_size != (Int32)stream.Position - data_section_start)
|
if (!IgnoreDataSectionSizeCheck && data_section_size != (Int32)stream.Position - data_section_start)
|
||||||
throw new Exception("Invalid PKG file! (Guessed data section size doesn't correspond to the real size)");
|
throw new Exception("Invalid PKG file! (Guessed data section size doesn't correspond to the real size)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
<Version>1.4.4</Version>
|
<Version>1.4.5</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -10,13 +10,131 @@ namespace PKGTool
|
||||||
{
|
{
|
||||||
class Program
|
class Program
|
||||||
{
|
{
|
||||||
|
struct Argument
|
||||||
|
{
|
||||||
|
public String cmd;
|
||||||
|
public String[] args;
|
||||||
|
}
|
||||||
|
|
||||||
static void Usage()
|
static void Usage()
|
||||||
{
|
{
|
||||||
Console.WriteLine("PKG Tool");
|
Console.WriteLine("PKG Tool");
|
||||||
Console.WriteLine("-----------------------");
|
Console.WriteLine("-----------------------");
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
Console.WriteLine("Extract : PKGTool -x <input path> [-o <output path>");
|
Console.WriteLine("Extract : PKGTool -x <input path> [-o <output path>] [-i]");
|
||||||
Console.WriteLine("Create : PKGTool -c <input path> [-o <output path>");
|
Console.WriteLine("Create : PKGTool -c <input path> [-o <output path>]");
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ParseArguments(String[] args, out List<Argument> outArgs)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
outArgs = new List<Argument>();
|
||||||
|
|
||||||
|
for (i = 0; i < args.Length; i++)
|
||||||
|
{
|
||||||
|
if (i < args.Length - 1)
|
||||||
|
{
|
||||||
|
if (args[i] == "-c")
|
||||||
|
{
|
||||||
|
if (outArgs.Any(a => a.cmd == "-x"))
|
||||||
|
{
|
||||||
|
Console.WriteLine("Cannot compress when extracting a file already!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args[i + 1].StartsWith("-"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
outArgs.Add(new Argument()
|
||||||
|
{
|
||||||
|
cmd = args[i],
|
||||||
|
args = new String[] { args[i + 1] }
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args[i] == "-x")
|
||||||
|
{
|
||||||
|
if (outArgs.Any(a => a.cmd == "-c"))
|
||||||
|
{
|
||||||
|
Console.WriteLine("Cannot extract when compressing a file already!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args[i + 1].StartsWith("-"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
outArgs.Add(new Argument()
|
||||||
|
{
|
||||||
|
cmd = args[i],
|
||||||
|
args = new String[] { args[i + 1] }
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args[i] == "-o")
|
||||||
|
{
|
||||||
|
if (!outArgs.Any(a => a.cmd == "-c") && !outArgs.Any(a => a.cmd == "-x"))
|
||||||
|
{
|
||||||
|
Console.WriteLine("Are you compressing or extracting?");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args[i + 1].StartsWith("-"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
outArgs.Add(new Argument()
|
||||||
|
{
|
||||||
|
cmd = args[i],
|
||||||
|
args = new String[] { args[i + 1] }
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args[i] == "-i")
|
||||||
|
{
|
||||||
|
if (outArgs.Any(a => a.cmd == "-x"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!args[i+1].StartsWith("-"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
outArgs.Add(new Argument()
|
||||||
|
{
|
||||||
|
cmd = args[i],
|
||||||
|
args = new String[0]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (args[i] == "-c" ||
|
||||||
|
args[i] == "-x" ||
|
||||||
|
args[i] == "-o")
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args[i] == "-i")
|
||||||
|
{
|
||||||
|
if (!outArgs.Any(a => a.cmd == "-x"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
outArgs.Add(new Argument()
|
||||||
|
{
|
||||||
|
cmd = args[i],
|
||||||
|
args = new String[0]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!outArgs.Any(a => a.cmd == "-c") && !outArgs.Any(a => a.cmd == "-x"))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String GenerateFileName(UInt64 ID, MemoryStream File)
|
static String GenerateFileName(UInt64 ID, MemoryStream File)
|
||||||
|
@ -100,63 +218,67 @@ namespace PKGTool
|
||||||
return fn;
|
return fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Main(string[] args)
|
static void Main(string[] argv)
|
||||||
{
|
{
|
||||||
|
if(!ParseArguments(argv, out List<Argument> arguments))
|
||||||
|
{
|
||||||
|
Usage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isCompressing = arguments.Any(a => a.cmd == "-c");
|
||||||
|
bool isExtracting = arguments.Any(a => a.cmd == "-x");
|
||||||
|
bool specifyOutputFolder = arguments.Any(a => a.cmd == "-o");
|
||||||
|
bool ignoreDataSectionSizeCheck = arguments.Any(a => a.cmd == "-i");
|
||||||
|
Dictionary<String, UInt64> AssetIDByFilePath = JObject.Parse(Encoding.UTF8.GetString(Properties.Resources.resource_infos)).ToObject<Dictionary<String, UInt64>>();
|
||||||
|
Dictionary<UInt64, String> AssetFilePathByID = AssetIDByFilePath.ToDictionary(kvp => kvp.Value, kvp => kvp.Key);
|
||||||
CRC64 crc = new CRC64();
|
CRC64 crc = new CRC64();
|
||||||
FileStream tmp = null;
|
FileStream tmp = null;
|
||||||
String fn = String.Empty;
|
String fn = String.Empty;
|
||||||
String filePath = String.Empty;
|
String filePath = String.Empty;
|
||||||
|
String inPath = String.Empty;
|
||||||
String outPath = String.Empty;
|
String outPath = String.Empty;
|
||||||
Dread.FileFormats.PKG pkg = new Dread.FileFormats.PKG();
|
|
||||||
Dictionary<String, UInt64> AssetIDByFilePath = JObject.Parse(Encoding.UTF8.GetString(Properties.Resources.resource_infos)).ToObject<Dictionary<String, UInt64>>();
|
|
||||||
Dictionary<UInt64, String> AssetFilePathByID = AssetIDByFilePath.ToDictionary(kvp => kvp.Value, kvp => kvp.Key);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (args.Length >= 2)
|
if (isCompressing)
|
||||||
{
|
inPath = arguments.Where(a => a.cmd == "-c").FirstOrDefault().args[0];
|
||||||
if (args[0] == "-x")
|
else if (isExtracting)
|
||||||
{
|
inPath = arguments.Where(a => a.cmd == "-x").FirstOrDefault().args[0];
|
||||||
if (!File.Exists(args[1]))
|
|
||||||
throw new FileNotFoundException($"Couldn't find the file {args[1]}");
|
|
||||||
|
|
||||||
pkg.import(File.OpenRead(args[1]));
|
if(specifyOutputFolder)
|
||||||
|
outPath = arguments.Where(a => a.cmd == "-o").FirstOrDefault().args[0];
|
||||||
|
else
|
||||||
|
outPath = Path.Combine(Directory.GetCurrentDirectory(), Path.GetFileNameWithoutExtension(inPath));
|
||||||
|
|
||||||
if (args.Length == 4)
|
Dread.FileFormats.PKG pkg = new Dread.FileFormats.PKG();
|
||||||
|
if (isExtracting)
|
||||||
{
|
{
|
||||||
if (args[2] == "-o")
|
pkg.IgnoreDataSectionSizeCheck = ignoreDataSectionSizeCheck;
|
||||||
outPath = args[3];
|
|
||||||
else
|
if (!File.Exists(inPath))
|
||||||
{
|
throw new FileNotFoundException($"Couldn't find the file {inPath}");
|
||||||
Usage();
|
|
||||||
return;
|
pkg.import(File.OpenRead(inPath));
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (args.Length == 2)
|
|
||||||
outPath = String.Join(Path.DirectorySeparatorChar, Directory.GetCurrentDirectory(), Path.GetFileNameWithoutExtension(args[1]));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Usage();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Directory.Exists(outPath))
|
if (!Directory.Exists(outPath))
|
||||||
Directory.CreateDirectory(outPath);
|
Directory.CreateDirectory(outPath);
|
||||||
|
|
||||||
using(var list = new StreamWriter(String.Join(Path.DirectorySeparatorChar, outPath, "files.list")))
|
using(var list = new StreamWriter(Path.Combine(outPath, "files.list")))
|
||||||
{
|
{
|
||||||
foreach (var file in pkg.Files)
|
foreach (var file in pkg.Files)
|
||||||
{
|
{
|
||||||
if (AssetFilePathByID.ContainsKey(file.Key))
|
if (AssetFilePathByID.ContainsKey(file.Key))
|
||||||
{
|
{
|
||||||
fn = AssetFilePathByID[file.Key];
|
fn = AssetFilePathByID[file.Key];
|
||||||
filePath = String.Join(Path.DirectorySeparatorChar, outPath, fn.Replace('/', Path.DirectorySeparatorChar));
|
filePath = Path.Combine(outPath, fn.Replace('/', Path.DirectorySeparatorChar));
|
||||||
if (!Directory.Exists(Path.GetDirectoryName(filePath)))
|
if (!Directory.Exists(Path.GetDirectoryName(filePath)))
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
|
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fn = GenerateFileName(file.Key, file.Value);
|
fn = GenerateFileName(file.Key, file.Value);
|
||||||
Console.WriteLine($"Extracting {fn}...");
|
Console.WriteLine($"Extracting {fn}...");
|
||||||
tmp = File.Open(String.Join(Path.DirectorySeparatorChar, outPath, fn), FileMode.Create, FileAccess.Write);
|
tmp = File.Open(Path.Combine(outPath, fn), FileMode.Create, FileAccess.Write);
|
||||||
file.Value.CopyTo(tmp);
|
file.Value.CopyTo(tmp);
|
||||||
file.Value.Position = 0L;
|
file.Value.Position = 0L;
|
||||||
tmp.Close();
|
tmp.Close();
|
||||||
|
@ -166,38 +288,20 @@ namespace PKGTool
|
||||||
|
|
||||||
pkg.Close();
|
pkg.Close();
|
||||||
}
|
}
|
||||||
else if (args[0] == "-c")
|
else if (isCompressing)
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(args[1]))
|
if (!Directory.Exists(inPath))
|
||||||
throw new FileNotFoundException($"Couldn't find the folder {args[1]}");
|
throw new FileNotFoundException($"Couldn't find the folder {inPath}");
|
||||||
|
|
||||||
if (!File.Exists(String.Join(Path.DirectorySeparatorChar, args[1], "files.list")))
|
if (!File.Exists(Path.Combine(inPath, "files.list")))
|
||||||
throw new FileNotFoundException($"Couldn't find the file files.list");
|
throw new FileNotFoundException($"Couldn't find the file files.list");
|
||||||
|
|
||||||
if (args.Length == 4)
|
|
||||||
{
|
|
||||||
if (args[2] == "-o")
|
|
||||||
outPath = args[3];
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Usage();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (args.Length == 2)
|
|
||||||
outPath = String.Join(Path.DirectorySeparatorChar, Directory.GetCurrentDirectory(), Path.GetFileNameWithoutExtension(args[1]));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Usage();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Path.GetExtension(outPath) == String.Empty)
|
if (Path.GetExtension(outPath) == String.Empty)
|
||||||
outPath += ".pkg";
|
outPath += ".pkg";
|
||||||
else if (Path.GetExtension(outPath).ToLower() != ".pkg")
|
else if (Path.GetExtension(outPath).ToLower() != ".pkg")
|
||||||
outPath = Path.ChangeExtension(outPath, ".pkg");
|
outPath = Path.ChangeExtension(outPath, ".pkg");
|
||||||
|
|
||||||
using (var list = new StreamReader(String.Join(Path.DirectorySeparatorChar, args[1], "files.list")))
|
using (var list = new StreamReader(Path.Combine(inPath, "files.list")))
|
||||||
{
|
{
|
||||||
while (!list.EndOfStream)
|
while (!list.EndOfStream)
|
||||||
{
|
{
|
||||||
|
@ -205,14 +309,14 @@ namespace PKGTool
|
||||||
try {
|
try {
|
||||||
if (Path.GetFileNameWithoutExtension(fn).Length == 16)
|
if (Path.GetFileNameWithoutExtension(fn).Length == 16)
|
||||||
{
|
{
|
||||||
pkg.Files.Add(new KeyValuePair<UInt64, MemoryStream>(Convert.ToUInt64(Path.GetFileNameWithoutExtension(fn), 16), new MemoryStream(File.ReadAllBytes(String.Join(Path.DirectorySeparatorChar, args[1], fn)))));
|
pkg.Files.Add(new KeyValuePair<UInt64, MemoryStream>(Convert.ToUInt64(Path.GetFileNameWithoutExtension(fn), 16), new MemoryStream(File.ReadAllBytes(Path.Combine(inPath, fn)))));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pkg.Files.Add(new KeyValuePair<UInt64, MemoryStream>(crc.ComputeAsValue(fn), new MemoryStream(File.ReadAllBytes(String.Join(Path.DirectorySeparatorChar, args[1], fn)))));
|
pkg.Files.Add(new KeyValuePair<UInt64, MemoryStream>(crc.ComputeAsValue(fn), new MemoryStream(File.ReadAllBytes(Path.Combine(inPath, fn)))));
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
pkg.Files.Add(new KeyValuePair<UInt64, MemoryStream>(crc.ComputeAsValue(fn), new MemoryStream(File.ReadAllBytes(String.Join(Path.DirectorySeparatorChar, args[1], fn)))));
|
pkg.Files.Add(new KeyValuePair<UInt64, MemoryStream>(crc.ComputeAsValue(fn), new MemoryStream(File.ReadAllBytes(Path.Combine(inPath, fn)))));
|
||||||
}
|
}
|
||||||
Console.WriteLine($"Adding {fn}...");
|
Console.WriteLine($"Adding {fn}...");
|
||||||
}
|
}
|
||||||
|
@ -223,9 +327,6 @@ namespace PKGTool
|
||||||
tmp.Close();
|
tmp.Close();
|
||||||
pkg.Close();
|
pkg.Close();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
Usage();
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Console.WriteLine("An error occured!");
|
Console.WriteLine("An error occured!");
|
||||||
Console.WriteLine(ex.Message);
|
Console.WriteLine(ex.Message);
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
{
|
{
|
||||||
"profiles": {
|
"profiles": {
|
||||||
"PKGTool": {
|
"PKGTool": {
|
||||||
"commandName": "Project"
|
"commandName": "Project",
|
||||||
|
"commandLineArgs": "-x \"D:\\Emulateur\\Switch\\Modding\\Metroid Dread\\romfs\\packs\\players\\samus.pkg\" -i"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue