Version 1.3

Fixed repacking PKGs
Removed the need to put the amount of bytes that pads the header

/!\ Repacking a PKG that was unpacks with an older version won't be supported
This commit is contained in:
UltiNaruto 2021-10-21 17:14:33 +02:00
parent 46c5278587
commit 666886e3f8
5 changed files with 94 additions and 25 deletions

View file

@ -1,13 +1,12 @@
using System;
using Misc.Structs;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Dread.FileFormats
{
public class PKG : Misc.Structs.BinaryStruct
public class PKG : BinaryStruct
{
public Int32 HeaderPaddingLength = 0;
public List<KeyValuePair<UInt64, MemoryStream>> Files = new List<KeyValuePair<UInt64, MemoryStream>>();
public void Close()
@ -21,14 +20,14 @@ namespace Dread.FileFormats
{
Int32 i = 0;
Int32[,] offsets = new Int32[Files.Count, 2];
Int32 cursor = 12 + Files.Count * 16 + HeaderPaddingLength;
if ((cursor % 8) != 0) cursor += 8 - (cursor % 8);
Int32 cursor = 12 + Files.Count * 16;
cursor = cursor.Aligned(128);
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);
cursor = cursor.Aligned(8);
i++;
}
return offsets;
@ -39,11 +38,11 @@ namespace Dread.FileFormats
get
{
int len = 12 + Files.Count * 16;
if ((len % 8) != 0) len += 8 - (len % 8);
len = len.Aligned(128);
foreach (var file in Files)
{
len += (int)file.Value.Length;
if((len % 8) != 0) len += 8 - (len % 8);
len = len.Aligned(128);
}
return len;
}
@ -66,14 +65,13 @@ namespace Dread.FileFormats
Offsets.Add(new Int32[] { reader.ReadInt32(), reader.ReadInt32() });
}
if (header_size != (Int32)stream.Position)
{
HeaderPaddingLength = header_size - (Int32)stream.Position;
stream.Position += HeaderPaddingLength;
}
// padding
if ((stream.Position % 8) != 0) stream.Position += 8 - (stream.Position % 8);
stream.Position = stream.Position.Aligned(128) - 4;
if (header_size != (Int32)stream.Position)
throw new Exception("Invalid PKG file! (Guessed header size doesn't correspond to the real size)");
stream.Position = stream.Position.Aligned(128);
data_section_start = (Int32)stream.Position;
@ -85,7 +83,7 @@ namespace Dread.FileFormats
Files[i].Value.Position = 0L;
// padding
if ((stream.Position % 8) != 0) stream.Position += 8 - (stream.Position % 8);
stream.Position = stream.Position.Aligned(8);
}
if (data_section_size != (Int32)stream.Position - data_section_start)
@ -107,17 +105,20 @@ namespace Dread.FileFormats
writer.Write(offsets[i, 1]);
}
writer.Write(Enumerable.Repeat<byte>(0, HeaderPaddingLength).ToArray());
// padding
while ((stream.Position + 4) % 128 != 0) writer.Write((byte)0);
header_size = (Int32)stream.Position;
// padding
while (stream.Position % 8 != 0) writer.Write((byte)0);
while (stream.Position % 128 != 0) writer.Write((byte)0);
data_section_start = (Int32)stream.Position;
for (i = 0; i < Files.Count; i++)
{
if (offsets[i, 0] != (int)stream.Position)
throw new Exception("Wrong starting offset!");
Files[i].Value.CopyTo(stream);
Files[i].Value.Position = 0L;

View file

@ -17053,7 +17053,11 @@
"maps/levels/c10_samus/s010_cave/models/imats/part029_n1_planereflection_part029_floor.bsmat": 11004062968986159012,
"maps/levels/c10_samus/s010_cave/models/imats/part030_n1_planereflection_part030_floor.bsmat": 10193656516338241483,
"maps/levels/c10_samus/s010_cave/models/imats/part031_a3_floorreflect_floor01.bsmat": 5664200389330730817,
"maps/levels/c10_samus/s010_cave/s010_cave.bmscd": 17223667496843672118,
"maps/levels/c10_samus/s010_cave/s010_cave.bmsnav": 6372273410937899229,
"maps/levels/c10_samus/s010_cave/s010_cave.bmssd": 14934703314286521848,
"maps/levels/c10_samus/s010_cave/s010_cave.brfld": 2847679399987825563,
"maps/levels/c10_samus/s010_cave/s010_cave.lc": 16697753406496556015,
"maps/levels/c10_samus/s020_magma/models/imats/part001_r12_breakables01sg_casca003_mp_opaquemaps_simple_32.bsmat": 13052231187569305547,
"maps/levels/c10_samus/s020_magma/models/imats/part001_r12_breakables01sg_casca003_mp_opaquemaps_simple_33.bsmat": 10938639062821405479,
"maps/levels/c10_samus/s020_magma/models/imats/part001_r12_breakables01sg_casca003_mp_opaquemaps_simple_34.bsmat": 8881372012702907811,
@ -17293,7 +17297,11 @@
"maps/levels/c10_samus/s020_magma/models/imats/part25_x2_mapmodel07_mp_opaquemaps_simple_31.bsmat": 6719729052105774777,
"maps/levels/c10_samus/s020_magma/models/imats/part25_x2_mapmodel14_mp_opaquemaps_simple_93.bsmat": 299798591696126041,
"maps/levels/c10_samus/s020_magma/models/imats/part25_x2_mapmodel22_mp_opaquemaps_simple_92.bsmat": 11465117789372562982,
"maps/levels/c10_samus/s020_magma/s020_magma.bmscd": 235004496791583241,
"maps/levels/c10_samus/s020_magma/s020_magma.bmsnav": 1582247735210037287,
"maps/levels/c10_samus/s020_magma/s020_magma.bmssd": 2523876732219092423,
"maps/levels/c10_samus/s020_magma/s020_magma.brfld": 14681972687750269860,
"maps/levels/c10_samus/s020_magma/s020_magma.lc": 7356096468494929561,
"maps/levels/c10_samus/s030_baselab/models/imats/centrallight_lightshaft_centrallight.bsmat": 10246052756621257545,
"maps/levels/c10_samus/s030_baselab/models/imats/part001_e5_mapmodel01_mp_opaquemaps_simple_32.bsmat": 17118905794486578253,
"maps/levels/c10_samus/s030_baselab/models/imats/part001_lightshaft_part001lightshaft.bsmat": 17086338870922760847,
@ -17448,7 +17456,11 @@
"maps/levels/c10_samus/s030_baselab/models/imats/part026_jg4_mapmodel006_mp_opaquemaps_simple_32.bsmat": 3963638231384014626,
"maps/levels/c10_samus/s030_baselab/models/imats/part026_jg4_mapmodel006_mp_opaquemaps_simple_37.bsmat": 11408343282427742334,
"maps/levels/c10_samus/s030_baselab/models/imats/part027_jp1_planereflect01_part027_jp1_reflection.bsmat": 18120437154957150014,
"maps/levels/c10_samus/s030_baselab/s030_baselab.bmscd": 735646901249328500,
"maps/levels/c10_samus/s030_baselab/s030_baselab.bmsnav": 14463857975607309464,
"maps/levels/c10_samus/s030_baselab/s030_baselab.bmssd": 3058490783213425338,
"maps/levels/c10_samus/s030_baselab/s030_baselab.brfld": 14030883220546090201,
"maps/levels/c10_samus/s030_baselab/s030_baselab.lc": 3409077286579939826,
"maps/levels/c10_samus/s040_aqua/models/imats/part001_e6_mapmodel03_mp_opaquemaps_simple_36.bsmat": 3543394198386911763,
"maps/levels/c10_samus/s040_aqua/models/imats/part001_e6_mapmodel05_mp_opaquemaps_simple_39.bsmat": 4738054898356893997,
"maps/levels/c10_samus/s040_aqua/models/imats/part0019_jp9_lshaft01_lights.bsmat": 15679096795668261144,
@ -17606,7 +17618,11 @@
"maps/levels/c10_samus/s040_aqua/models/imats/part023_e3_mapmodel00_mp_opaquemaps_simple_20.bsmat": 15576596489315400368,
"maps/levels/c10_samus/s040_aqua/models/imats/part024_n2_planereflection_part024_floor.bsmat": 12529703966036454986,
"maps/levels/c10_samus/s040_aqua/models/imats/part025_n2_planereflection_part025_floor.bsmat": 1866984694413238195,
"maps/levels/c10_samus/s040_aqua/s040_aqua.bmscd": 11501940391051834630,
"maps/levels/c10_samus/s040_aqua/s040_aqua.bmsnav": 16047071442374881353,
"maps/levels/c10_samus/s040_aqua/s040_aqua.bmssd": 13824751253340021448,
"maps/levels/c10_samus/s040_aqua/s040_aqua.brfld": 6277216191705154731,
"maps/levels/c10_samus/s040_aqua/s040_aqua.lc": 5322844506903055246,
"maps/levels/c10_samus/s050_forest/models/imats/part001_s2_mapmodel01_mp_opaque_17.bsmat": 8971941433537019289,
"maps/levels/c10_samus/s050_forest/models/imats/part002_f2_lightshaft01_aquatrench.bsmat": 15113258871674806546,
"maps/levels/c10_samus/s050_forest/models/imats/part003_e4_breakables00sg_casca054_mp_opaquemaps_simple_25.bsmat": 17031664662463971060,
@ -17724,7 +17740,11 @@
"maps/levels/c10_samus/s050_forest/models/imats/part020_f3_mattepaint00_mattepaintingforest019background01.bsmat": 12406991137837235388,
"maps/levels/c10_samus/s050_forest/models/imats/part021_jp1_reflection_part021_forest_jp1_reflection.bsmat": 14029877982906446421,
"maps/levels/c10_samus/s050_forest/models/imats/part025_n2_planereflection_part025_floor.bsmat": 16186503427407780179,
"maps/levels/c10_samus/s050_forest/s050_forest.bmscd": 12233192194656623443,
"maps/levels/c10_samus/s050_forest/s050_forest.bmsnav": 1105626709112314515,
"maps/levels/c10_samus/s050_forest/s050_forest.bmssd": 9908337684793625757,
"maps/levels/c10_samus/s050_forest/s050_forest.brfld": 7009633443258624766,
"maps/levels/c10_samus/s050_forest/s050_forest.lc": 7842868973344647195,
"maps/levels/c10_samus/s060_quarantine/models/imats/part001_n3_planereflection_part001_floor.bsmat": 14235996016280489210,
"maps/levels/c10_samus/s060_quarantine/models/imats/part001_p_lshaft02_lights.bsmat": 14971469910325906134,
"maps/levels/c10_samus/s060_quarantine/models/imats/part003_n3_lshaft01_lights.bsmat": 12687136522861654032,
@ -17770,7 +17790,11 @@
"maps/levels/c10_samus/s060_quarantine/models/imats/part01_n3_mapmodel23_luzroja.bsmat": 7549242519443816420,
"maps/levels/c10_samus/s060_quarantine/models/imats/part01_n3_mapmodel23_mp_opaquemaps_simple.bsmat": 2793405979501244656,
"maps/levels/c10_samus/s060_quarantine/models/imats/part01_p_vignette_indoor.bsmat": 6030977814534187724,
"maps/levels/c10_samus/s060_quarantine/s060_quarantine.bmscd": 6200802223911616494,
"maps/levels/c10_samus/s060_quarantine/s060_quarantine.bmsnav": 9166951593258508500,
"maps/levels/c10_samus/s060_quarantine/s060_quarantine.bmssd": 8523580271505664032,
"maps/levels/c10_samus/s060_quarantine/s060_quarantine.brfld": 11425513242001280579,
"maps/levels/c10_samus/s060_quarantine/s060_quarantine.lc": 1543384941348812604,
"maps/levels/c10_samus/s070_basesanc/models/imats/part001_pb3_breakables00sg_casca021_mp_opaquemaps_simple_20.bsmat": 10651973680477907624,
"maps/levels/c10_samus/s070_basesanc/models/imats/part001_pb3_breakables01sg_casca022_mp_opaquemaps_simple_20.bsmat": 14047680856861990570,
"maps/levels/c10_samus/s070_basesanc/models/imats/part001_pb3_lightshaftinside01_lightshaftindise01.bsmat": 17086023973008880924,
@ -17933,7 +17957,11 @@
"maps/levels/c10_samus/s070_basesanc/models/imats/part012_e11_sg_casca12sg_casca084_mp_opaquemaps_simple_39.bsmat": 15940378687724741366,
"maps/levels/c10_samus/s070_basesanc/models/imats/part013_n2_planereflection_part024_floor.bsmat": 15236876391520991441,
"maps/levels/c10_samus/s070_basesanc/models/imats/part014_n2_planereflection_part014_floor.bsmat": 5453474231564889939,
"maps/levels/c10_samus/s070_basesanc/s070_basesanc.bmscd": 17564293810197241426,
"maps/levels/c10_samus/s070_basesanc/s070_basesanc.bmsnav": 13556873861119440185,
"maps/levels/c10_samus/s070_basesanc/s070_basesanc.bmssd": 15241469719544154524,
"maps/levels/c10_samus/s070_basesanc/s070_basesanc.brfld": 4270211997453266943,
"maps/levels/c10_samus/s070_basesanc/s070_basesanc.lc": 8938686359508448586,
"maps/levels/c10_samus/s080_shipyard/models/imats/part001_o5_mapmodel03_mp_opaquemaps_simple_26.bsmat": 8395866495046307770,
"maps/levels/c10_samus/s080_shipyard/models/imats/part001_o5_mattepaint01_mattepaintingshipyard006sky01.bsmat": 17452613073028320246,
"maps/levels/c10_samus/s080_shipyard/models/imats/part001_o5_mattepaint01_mattepaintingshipyard006sky02.bsmat": 10738047110742714050,
@ -18107,7 +18135,11 @@
"maps/levels/c10_samus/s080_shipyard/models/imats/part007_e11_mattepaint01_mattepaintingshipyard007sky01_scroll05.bsmat": 2515876738157818275,
"maps/levels/c10_samus/s080_shipyard/models/imats/part007_e11_mattepaint02_mattepaintingshipyard006sky01.bsmat": 18356649319415159015,
"maps/levels/c10_samus/s080_shipyard/models/imats/part007_e11_mattepaint02_mattepaintingshipyard006sky02.bsmat": 11065059128738297299,
"maps/levels/c10_samus/s080_shipyard/s080_shipyard.bmscd": 5873333135951496722,
"maps/levels/c10_samus/s080_shipyard/s080_shipyard.bmsnav": 15580160668144664320,
"maps/levels/c10_samus/s080_shipyard/s080_shipyard.bmssd": 8198308900827615708,
"maps/levels/c10_samus/s080_shipyard/s080_shipyard.brfld": 11024946409120839615,
"maps/levels/c10_samus/s080_shipyard/s080_shipyard.lc": 9802522975747510928,
"maps/levels/c10_samus/s090_skybase/models/imats/part001_jp6_lshaft02_lights01.bsmat": 17101856578387373738,
"maps/levels/c10_samus/s090_skybase/models/imats/part001_jp6_lshaft03_lights01.bsmat": 939048235506193486,
"maps/levels/c10_samus/s090_skybase/models/imats/part001_jp6_lshaft04_lights01.bsmat": 2013379507388437373,
@ -18138,7 +18170,11 @@
"maps/levels/c10_samus/s090_skybase/models/imats/part004_jp5_planereflect02_skybaseplanereflect02.bsmat": 12707081530355167622,
"maps/levels/c10_samus/s090_skybase/models/imats/part004_p0_lshaft01_lightsfinal.bsmat": 1083999570592624796,
"maps/levels/c10_samus/s090_skybase/models/imats/part004_p0_lshaft02_lightsfinal2.bsmat": 4812439230286204675,
"maps/levels/c10_samus/s090_skybase/s090_skybase.bmscd": 8513891897343302243,
"maps/levels/c10_samus/s090_skybase/s090_skybase.bmsnav": 9882296738099617737,
"maps/levels/c10_samus/s090_skybase/s090_skybase.bmssd": 6224837038660783533,
"maps/levels/c10_samus/s090_skybase/s090_skybase.brfld": 13737479236041534414,
"maps/levels/c10_samus/s090_skybase/s090_skybase.lc": 10065543726819693949,
"maps/objects/aberration01_a/imats/aberration01_a_mp_opaquemaps_simple_01.bsmat": 5605368667902581907,
"maps/objects/aberration01_b/imats/aberration01_b_mp_opaquemaps_simple_01.bsmat": 9612903300511620112,
"maps/objects/aquadigrock01/imats/aquadigrock01_mp_opaquemaps_simple.bsmat": 8596552807246769816,

View file

@ -2,6 +2,25 @@
namespace Misc.Structs
{
public static class BinaryStructExtensions
{
public static int Aligned(this int position, int alignment)
{
if (position % alignment != 0)
return position + (alignment - (position % alignment));
else
return position;
}
public static long Aligned(this long position, long alignment)
{
if (position % alignment != 0L)
return position + (alignment - (position % alignment));
else
return position;
}
}
public abstract class BinaryStruct
{
public BinaryStruct() { }

View file

@ -23,7 +23,7 @@ namespace PKGTool
{
String fn = String.Empty;
BinaryReader reader = new BinaryReader(File);
String magic = Encoding.UTF8.GetString(reader.ReadBytes(4), 0, 4);
String magic = Encoding.ASCII.GetString(reader.ReadBytes(4), 0, 4);
switch(magic)
{
case "\x1BLua":
@ -32,6 +32,9 @@ namespace PKGTool
case "\x6F\x7F\xF3\x73":
fn = $"{ID:X16}.bapd";
break;
case "\xFB\x42\x9B\x06":
fn = $"{ID:X16}.bmscu";
break;
case "BTXT":
fn = $"{ID:X16}.txt";
break;
@ -65,12 +68,18 @@ namespace PKGTool
case "MPSI":
fn = $"{ID:X16}.bpsi";
break;
case "MPSY":
fn = $"{ID:X16}.bcptl";
break;
case "MSAD":
fn = $"{ID:X16}.bmsad";
break;
case "MSAS":
fn = $"{ID:X16}.bmsas";
break;
case "MSCD":
fn = $"{ID:X16}.bmscd";
break;
case "MSHD":
fn = $"{ID:X16}.bshdat";
break;
@ -135,7 +144,6 @@ namespace PKGTool
using(var list = new StreamWriter(String.Join(Path.DirectorySeparatorChar, outPath, "files.list")))
{
list.WriteLine($"Padding = {pkg.HeaderPaddingLength}");
foreach (var file in pkg.Files)
{
if (AssetFilePathByID.ContainsKey(file.Key))
@ -191,12 +199,18 @@ namespace PKGTool
using (var list = new StreamReader(String.Join(Path.DirectorySeparatorChar, args[1], "files.list")))
{
pkg.HeaderPaddingLength = Convert.ToInt32(list.ReadLine().Substring("Padding = ".Length));
while (!list.EndOfStream)
{
fn = list.ReadLine().TrimEnd('\r', '\n');
try {
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)))));
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)))));
}
else
{
pkg.Files.Add(new KeyValuePair<UInt64, MemoryStream>(crc.ComputeAsValue(fn), new MemoryStream(File.ReadAllBytes(String.Join(Path.DirectorySeparatorChar, args[1], fn)))));
}
} catch {
pkg.Files.Add(new KeyValuePair<UInt64, MemoryStream>(crc.ComputeAsValue(fn), new MemoryStream(File.ReadAllBytes(String.Join(Path.DirectorySeparatorChar, args[1], fn)))));
}

View file

@ -1,8 +1,7 @@
{
"profiles": {
"PKGTool": {
"commandName": "Project",
"commandLineArgs": "-x \"D:\\Emulateur\\Switch\\Modding\\Metroid Dread\\packs\\maps\\s010_cave\\s010_cave.pkg\""
"commandName": "Project"
}
}
}