mirror of
https://github.com/UltiNaruto/PKGTool
synced 2024-11-21 19:23:03 +00:00
Ajoutez des fichiers projet.
This commit is contained in:
parent
6cd06acb9c
commit
b6067401f4
6 changed files with 386 additions and 0 deletions
25
PKGTool.sln
Normal file
25
PKGTool.sln
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31727.386
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PKGTool", "PKGTool\PKGTool.csproj", "{C882EC56-0245-481E-B2F2-3C7336B7963A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C882EC56-0245-481E-B2F2-3C7336B7963A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C882EC56-0245-481E-B2F2-3C7336B7963A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C882EC56-0245-481E-B2F2-3C7336B7963A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C882EC56-0245-481E-B2F2-3C7336B7963A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {FBC66971-6591-422B-AF47-66D00A35825C}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
130
PKGTool/Dread/FileFormats/PKG.cs
Normal file
130
PKGTool/Dread/FileFormats/PKG.cs
Normal file
|
@ -0,0 +1,130 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Dread.FileFormats
|
||||
{
|
||||
public class PKG : Misc.Structs.BinaryStruct
|
||||
{
|
||||
public List<KeyValuePair<UInt64, MemoryStream>> Files = new List<KeyValuePair<UInt64, MemoryStream>>();
|
||||
|
||||
public void Close()
|
||||
{
|
||||
foreach (var file in Files)
|
||||
file.Value.Close();
|
||||
Files.Clear();
|
||||
}
|
||||
|
||||
Int32[,] GenerateFileOffsets()
|
||||
{
|
||||
Int32 i = 0;
|
||||
Int32[,] offsets = new Int32[Files.Count, 2];
|
||||
Int32 cursor = 12 + Files.Count * 16;
|
||||
if ((cursor % 8) != 0) cursor += 8 - (cursor % 8);
|
||||
foreach (var file in Files)
|
||||
{
|
||||
offsets[i, 0] = cursor;
|
||||
cursor += (Int32)file.Value.Length;
|
||||
offsets[i, 1] = cursor;
|
||||
if ((cursor % 8) != 0) cursor += 8 - (cursor % 8);
|
||||
i++;
|
||||
}
|
||||
return offsets;
|
||||
}
|
||||
|
||||
public override int StructSize
|
||||
{
|
||||
get
|
||||
{
|
||||
int len = 12 + Files.Count * 16;
|
||||
if ((len % 8) != 0) len += 8 - (len % 8);
|
||||
foreach (var file in Files)
|
||||
{
|
||||
len += (int)file.Value.Length;
|
||||
if((len % 8) != 0) len += 8 - (len % 8);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
public override void import(Stream stream)
|
||||
{
|
||||
Int32 i, data_section_start;
|
||||
List<UInt64> IDs = new List<UInt64>();
|
||||
List<Int32[]> Offsets = new List<Int32[]>();
|
||||
|
||||
var reader = new BinaryReader(stream);
|
||||
Int32 header_size = reader.ReadInt32();
|
||||
Int32 data_section_size = reader.ReadInt32();
|
||||
Int32 file_count = reader.ReadInt32();
|
||||
|
||||
for(i = 0; i< file_count;i++)
|
||||
{
|
||||
Files.Add(new KeyValuePair<UInt64, MemoryStream>(reader.ReadUInt64(), new MemoryStream()));
|
||||
Offsets.Add(new Int32[] { reader.ReadInt32(), reader.ReadInt32() });
|
||||
}
|
||||
|
||||
if (header_size != (Int32)stream.Position)
|
||||
throw new Exception("Invalid PKG file! (Guessed header size doesn't correspond to the real size)");
|
||||
|
||||
// padding
|
||||
if ((stream.Position % 8) != 0) stream.Position += 8 - (stream.Position % 8);
|
||||
|
||||
data_section_start = (Int32)stream.Position;
|
||||
|
||||
for (i=0;i<file_count;i++)
|
||||
{
|
||||
if (Offsets[i][0] != (int)stream.Position)
|
||||
throw new Exception("Wrong starting offset!");
|
||||
Files[i].Value.Write(reader.ReadBytes(Offsets[i][1] - Offsets[i][0]));
|
||||
Files[i].Value.Position = 0L;
|
||||
|
||||
// padding
|
||||
if ((stream.Position % 8) != 0) stream.Position += 8 - (stream.Position % 8);
|
||||
}
|
||||
|
||||
if (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)");
|
||||
}
|
||||
|
||||
public override void export(Stream stream)
|
||||
{
|
||||
Int32 i, header_size, data_section_start, data_section_size;
|
||||
Int32[,] offsets = GenerateFileOffsets();
|
||||
|
||||
var writer = new BinaryWriter(stream);
|
||||
stream.Position += 8;
|
||||
writer.Write(Files.Count);
|
||||
for(i=0;i<Files.Count;i++)
|
||||
{
|
||||
writer.Write(Files[i].Key);
|
||||
writer.Write(offsets[i, 0]);
|
||||
writer.Write(offsets[i, 1]);
|
||||
}
|
||||
|
||||
header_size = (Int32)stream.Position;
|
||||
|
||||
// padding
|
||||
while (stream.Position % 8 != 0) writer.Write((byte)0);
|
||||
|
||||
data_section_start = (Int32)stream.Position;
|
||||
|
||||
for (i = 0; i < Files.Count; i++)
|
||||
{
|
||||
Files[i].Value.CopyTo(stream);
|
||||
Files[i].Value.Position = 0L;
|
||||
|
||||
// padding
|
||||
while (stream.Position % 8 != 0) writer.Write((byte)0);
|
||||
}
|
||||
|
||||
data_section_size = (Int32)stream.Position - data_section_start;
|
||||
|
||||
stream.Position = 0L;
|
||||
|
||||
writer.Write(header_size);
|
||||
writer.Write(data_section_size);
|
||||
}
|
||||
}
|
||||
}
|
12
PKGTool/Misc/Structs/BinaryStruct.cs
Normal file
12
PKGTool/Misc/Structs/BinaryStruct.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using System.IO;
|
||||
|
||||
namespace Misc.Structs
|
||||
{
|
||||
public abstract class BinaryStruct
|
||||
{
|
||||
public BinaryStruct() { }
|
||||
public abstract void import(Stream stream);
|
||||
public abstract void export(Stream stream);
|
||||
public abstract int StructSize { get; }
|
||||
}
|
||||
}
|
8
PKGTool/PKGTool.csproj
Normal file
8
PKGTool/PKGTool.csproj
Normal file
|
@ -0,0 +1,8 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
203
PKGTool/Program.cs
Normal file
203
PKGTool/Program.cs
Normal file
|
@ -0,0 +1,203 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace PKGTool
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Usage()
|
||||
{
|
||||
Console.WriteLine("PKG Tool");
|
||||
Console.WriteLine("-----------------------");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Extract : PKGTool -x <input path> [-o <output path>");
|
||||
Console.WriteLine("Create : PKGTool -c <input path> [-o <output path>");
|
||||
}
|
||||
|
||||
static String GenerateFileName(UInt64 ID, MemoryStream File)
|
||||
{
|
||||
String fn = String.Empty;
|
||||
BinaryReader reader = new BinaryReader(File);
|
||||
String magic = Encoding.UTF8.GetString(reader.ReadBytes(4), 0, 4);
|
||||
switch(magic)
|
||||
{
|
||||
case "\x1BLua":
|
||||
fn = $"{ID:X16}.lc";
|
||||
break;
|
||||
case "\x6F\x7F\xF3\x73":
|
||||
fn = $"{ID:X16}.bapd";
|
||||
break;
|
||||
case "BTXT":
|
||||
fn = $"{ID:X16}.txt";
|
||||
break;
|
||||
case "CWAV":
|
||||
fn = $"{ID:X16}.bcwav";
|
||||
break;
|
||||
case "FGRP":
|
||||
fn = $"{ID:X16}.bfgrp";
|
||||
break;
|
||||
case "FSAR":
|
||||
fn = $"{ID:X16}.bfsar";
|
||||
break;
|
||||
case "LSND":
|
||||
fn = $"{ID:X16}.blsnd";
|
||||
break;
|
||||
case "LUT\x01":
|
||||
fn = $"{ID:X16}.blut";
|
||||
break;
|
||||
case "MANM":
|
||||
fn = $"{ID:X16}.bcskla";
|
||||
break;
|
||||
case "MFNT":
|
||||
fn = $"{ID:X16}.bfont";
|
||||
break;
|
||||
case "MMDL":
|
||||
fn = $"{ID:X16}.bcmdl";
|
||||
break;
|
||||
case "MNAV":
|
||||
fn = $"{ID:X16}.bmnav";
|
||||
break;
|
||||
case "MPSI":
|
||||
fn = $"{ID:X16}.bpsi";
|
||||
break;
|
||||
case "MSAD":
|
||||
fn = $"{ID:X16}.bmsad";
|
||||
break;
|
||||
case "MSAS":
|
||||
fn = $"{ID:X16}.bmsas";
|
||||
break;
|
||||
case "MSHD":
|
||||
fn = $"{ID:X16}.bshdat";
|
||||
break;
|
||||
case "MSUR":
|
||||
fn = $"{ID:X16}.bsmat";
|
||||
break;
|
||||
case "MTXT":
|
||||
fn = $"{ID:X16}.bctex";
|
||||
break;
|
||||
case "MUCT":
|
||||
fn = $"{ID:X16}.buct";
|
||||
break;
|
||||
default:
|
||||
fn = $"{ID:X16}.bin";
|
||||
break;
|
||||
}
|
||||
File.Position = 0;
|
||||
return fn;
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
FileStream tmp = null;
|
||||
String fn = String.Empty;
|
||||
String outPath = String.Empty;
|
||||
Dread.FileFormats.PKG pkg = new Dread.FileFormats.PKG();
|
||||
try
|
||||
{
|
||||
if (args.Length >= 2)
|
||||
{
|
||||
if (args[0] == "-x")
|
||||
{
|
||||
if (!File.Exists(args[1]))
|
||||
throw new FileNotFoundException($"Couldn't find the file {args[1]}");
|
||||
|
||||
pkg.import(File.OpenRead(args[1]));
|
||||
|
||||
if (args.Length == 4)
|
||||
{
|
||||
if (args[2] == "-o")
|
||||
outPath = args[2];
|
||||
else
|
||||
{
|
||||
Usage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (args.Length == 2)
|
||||
outPath = String.Join(Path.DirectorySeparatorChar, Directory.GetCurrentDirectory(), Path.GetFileNameWithoutExtension(args[1]));
|
||||
else
|
||||
{
|
||||
Usage();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Directory.Exists(outPath))
|
||||
Directory.CreateDirectory(outPath);
|
||||
|
||||
using(var list = new StreamWriter(String.Join(Path.DirectorySeparatorChar, outPath, "files.list")))
|
||||
{
|
||||
foreach (var file in pkg.Files)
|
||||
{
|
||||
fn = GenerateFileName(file.Key, file.Value);
|
||||
Console.WriteLine($"Extracting {fn}...");
|
||||
tmp = File.Open(String.Join(Path.DirectorySeparatorChar, outPath, fn), FileMode.Create, FileAccess.Write);
|
||||
file.Value.CopyTo(tmp);
|
||||
file.Value.Position = 0L;
|
||||
tmp.Close();
|
||||
list.WriteLine(fn);
|
||||
}
|
||||
}
|
||||
|
||||
pkg.Close();
|
||||
}
|
||||
else if (args[0] == "-c")
|
||||
{
|
||||
if (!Directory.Exists(args[1]))
|
||||
throw new FileNotFoundException($"Couldn't find the folder {args[1]}");
|
||||
|
||||
if (!File.Exists(String.Join(Path.DirectorySeparatorChar, args[1], "files.list")))
|
||||
throw new FileNotFoundException($"Couldn't find the file files.list");
|
||||
|
||||
if (args.Length == 4)
|
||||
{
|
||||
if (args[2] == "-o")
|
||||
outPath = args[2];
|
||||
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)
|
||||
outPath += ".pkg";
|
||||
else if (Path.GetExtension(outPath).ToLower() != ".pkg")
|
||||
outPath = Path.ChangeExtension(outPath, ".pkg");
|
||||
|
||||
using (var list = new StreamReader(String.Join(Path.DirectorySeparatorChar, args[1], "files.list")))
|
||||
{
|
||||
while (!list.EndOfStream)
|
||||
{
|
||||
fn = list.ReadLine().TrimEnd('\r', '\n');
|
||||
Console.WriteLine($"Adding {fn}...");
|
||||
pkg.Files.Add(new KeyValuePair<UInt64, MemoryStream>(Convert.ToUInt64("0x" + Path.GetFileNameWithoutExtension(fn), 16), new MemoryStream(File.ReadAllBytes(String.Join(Path.DirectorySeparatorChar, args[1], fn)))));
|
||||
}
|
||||
}
|
||||
|
||||
tmp = File.Open(outPath, FileMode.Create, FileAccess.Write);
|
||||
pkg.export(tmp);
|
||||
tmp.Close();
|
||||
pkg.Close();
|
||||
}
|
||||
}
|
||||
else
|
||||
Usage();
|
||||
} catch (Exception ex) {
|
||||
Console.WriteLine("An error occured!");
|
||||
Console.WriteLine(ex.Message);
|
||||
Console.WriteLine(ex.StackTrace);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
8
PKGTool/Properties/launchSettings.json
Normal file
8
PKGTool/Properties/launchSettings.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"profiles": {
|
||||
"PKGTool": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "-c \"D:\\Projects\\PKGTool\\PKGTool\\bin\\Debug\\net5.0\\s010_cave\""
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue