mirror of
https://github.com/kwsch/pk3DS.git
synced 2026-10-02 05:46:47 -05:00
Update garc packing from files
Closes #95, adds padding length option for files that may need it
This commit is contained in:
@@ -13,7 +13,7 @@ public static class GARC
|
||||
public const ushort VER_6 = 0x0600;
|
||||
public const ushort VER_4 = 0x0400;
|
||||
|
||||
public static bool garcPackMS(string folderPath, string garcPath, int version, ProgressBar pBar1 = null, Label label = null, bool supress = false)
|
||||
public static bool garcPackMS(string folderPath, string garcPath, int version, int bytesPadding, ProgressBar pBar1 = null, Label label = null, bool supress = false)
|
||||
{
|
||||
// Check to see if our input folder exists.
|
||||
if (!new DirectoryInfo(folderPath).Exists) { Util.Error("Folder does not exist."); return false; }
|
||||
@@ -194,8 +194,7 @@ public static bool garcPackMS(string folderPath, string garcPath, int version, P
|
||||
catch { }
|
||||
|
||||
// Set up the Header Info
|
||||
using (MemoryStream newGARC = new MemoryStream())
|
||||
using (MemoryStream GARCdata = new MemoryStream())
|
||||
using (var newGARC = new FileStream(garcPath, FileMode.Create))
|
||||
using (BinaryWriter gw = new BinaryWriter(newGARC))
|
||||
{
|
||||
#region Write GARC Headers
|
||||
@@ -233,9 +232,37 @@ public static bool garcPackMS(string folderPath, string garcPath, int version, P
|
||||
foreach (var s in e.SubEntries.Where(s => s.Exists))
|
||||
{ gw.Write((uint)s.Start); gw.Write((uint)s.End); gw.Write((uint)s.Length); }
|
||||
}
|
||||
|
||||
// Write FIMB
|
||||
gw.Write((uint)0x46494D42); // FIMB
|
||||
gw.Write((uint)0x0000000C); // Header Length
|
||||
var dataLen = gw.BaseStream.Position;
|
||||
gw.Write((uint)0); // Data Length - TEMP
|
||||
|
||||
gw.Seek(0x10, SeekOrigin.Begin); // Goto the start of the un-set 0 data we set earlier and set it.
|
||||
var hdrLen = gw.BaseStream.Position;
|
||||
gw.Write((uint)0); // Write Data Offset - TEMP
|
||||
gw.Write((uint)0); // Write total GARC Length - TEMP
|
||||
|
||||
// Write Handling information
|
||||
if (version == VER_4)
|
||||
{
|
||||
gw.Write(garc.ContentLargestUnpadded); // Write Largest File stat
|
||||
}
|
||||
else if (version == VER_6)
|
||||
{
|
||||
gw.Write(garc.ContentLargestPadded); // Write Largest With Padding
|
||||
gw.Write(garc.ContentLargestUnpadded); // Write Largest Without Padding
|
||||
gw.Write(garc.ContentPadToNearest);
|
||||
}
|
||||
|
||||
newGARC.Seek(0, SeekOrigin.End); // Goto the end so we can copy the filedata after the GARC headers.
|
||||
|
||||
#endregion
|
||||
|
||||
#region Write Files
|
||||
var ghLength = gw.BaseStream.Length;
|
||||
|
||||
long largestSize = 0; // Required memory to allocate to handle the largest file
|
||||
long largestPadded = 0; // Required memory to allocate to handle the largest PADDED file (Ver6 only)
|
||||
foreach (string e in packOrder)
|
||||
@@ -245,37 +272,34 @@ public static bool garcPackMS(string folderPath, string garcPath, int version, P
|
||||
{
|
||||
// Update largest file length if necessary
|
||||
long len = new FileInfo(f).Length;
|
||||
int padding = (int)(len % bytesPadding);
|
||||
if (padding != 0) padding = bytesPadding - padding;
|
||||
bool largest = len > largestSize;
|
||||
if (largest)
|
||||
{
|
||||
largestSize = len;
|
||||
largestPadded = len;
|
||||
largestPadded = len + padding;
|
||||
}
|
||||
|
||||
// Write to FIMB
|
||||
using (var input = File.OpenRead(f))
|
||||
input.CopyTo(GARCdata);
|
||||
using (var x = File.OpenRead(f))
|
||||
x.CopyTo(newGARC);
|
||||
|
||||
// While length is not divisible by 4, pad with FF (unused byte)
|
||||
while (GARCdata.Length%garc.ContentPadToNearest != 0)
|
||||
{
|
||||
GARCdata.WriteByte(0xFF);
|
||||
if (largest)
|
||||
largestPadded++;
|
||||
}
|
||||
while (padding-- > 0)
|
||||
gw.Write((byte)0xFF);
|
||||
}
|
||||
}
|
||||
garc.ContentLargestUnpadded = (uint)largestSize;
|
||||
garc.ContentLargestPadded = (uint)largestPadded;
|
||||
var gdLength = gw.BaseStream.Length - ghLength;
|
||||
#endregion
|
||||
|
||||
gw.Write((uint)0x46494D42); // FIMB
|
||||
gw.Write((uint)0x0000000C); // Header Length
|
||||
gw.Write((uint)GARCdata.Length); // Data Length
|
||||
|
||||
gw.Seek(0x10, SeekOrigin.Begin); // Goto the start of the un-set 0 data we set earlier and set it.
|
||||
gw.Write((uint)newGARC.Length); // Write Data Offset
|
||||
gw.Write((uint)(newGARC.Length + GARCdata.Length)); // Write total GARC Length
|
||||
gw.Seek((int)dataLen, SeekOrigin.Begin);
|
||||
gw.Write((uint)gdLength); // Data Length
|
||||
gw.Seek((int)hdrLen, SeekOrigin.Begin);
|
||||
gw.Write((uint)ghLength); // Write Data Offset
|
||||
gw.Write((uint)gw.BaseStream.Length); // Write total GARC Length
|
||||
|
||||
// Write Handling information
|
||||
if (version == VER_4)
|
||||
@@ -289,15 +313,8 @@ public static bool garcPackMS(string folderPath, string garcPath, int version, P
|
||||
gw.Write(garc.ContentPadToNearest);
|
||||
}
|
||||
|
||||
newGARC.Seek(0, SeekOrigin.End); // Goto the end so we can copy the filedata after the GARC headers.
|
||||
|
||||
// Write in the data
|
||||
GARCdata.Position = 0;
|
||||
GARCdata.CopyTo(newGARC); // Copy the data.
|
||||
// New File is ready to be saved (memstream newGARC)
|
||||
try
|
||||
{
|
||||
File.WriteAllBytes(garcPath, newGARC.ToArray());
|
||||
if (label.InvokeRequired)
|
||||
label.Invoke((MethodInvoker)delegate { label.Visible = false; });
|
||||
else { label.Visible = false; }
|
||||
@@ -672,6 +689,17 @@ public static MemGARC packGARC(byte[][] data, int version, int contentpadnearest
|
||||
gw.Seek((int)hdrLen, SeekOrigin.Begin);
|
||||
gw.Write((uint)ghLength); // Write Data Offset
|
||||
gw.Write((uint)gw.BaseStream.Length); // Write total GARC Length
|
||||
|
||||
if (version == VER_4)
|
||||
{
|
||||
gw.Write(garc.ContentLargestUnpadded); // Write Largest File stat
|
||||
}
|
||||
else if (version == VER_6)
|
||||
{
|
||||
gw.Write(garc.ContentLargestPadded); // Write Largest With Padding
|
||||
gw.Write(garc.ContentLargestUnpadded); // Write Largest Without Padding
|
||||
gw.Write(garc.ContentPadToNearest);
|
||||
}
|
||||
}
|
||||
|
||||
byte[] GARCdata = File.ReadAllBytes(tempFile);
|
||||
|
||||
@@ -799,7 +799,7 @@ private void fileSet(IEnumerable<string> files, bool keep = false)
|
||||
{
|
||||
string GARC = Config.getGARCFileName(toEdit);
|
||||
updateStatus($"GARC Set: {toEdit} @ {GARC}... ");
|
||||
threadSet(Path.Combine(RomFSPath, GARC), toEdit);
|
||||
threadSet(Path.Combine(RomFSPath, GARC), toEdit, 4); // 4 bytes for Gen6
|
||||
while (threads > 0) Thread.Sleep(50);
|
||||
if (!keep && Directory.Exists(toEdit)) Directory.Delete(toEdit, true);
|
||||
resetStatus();
|
||||
@@ -1144,14 +1144,14 @@ private bool getGARC(string infile, string outfolder, bool PB, bool bypassExt =
|
||||
}
|
||||
catch (Exception e) { Util.Error("Could not get the GARC:", e.ToString()); threads--; return false; }
|
||||
}
|
||||
private bool setGARC(string outfile, string infolder, bool PB)
|
||||
private bool setGARC(string outfile, string infolder, int padBytes, bool PB)
|
||||
{
|
||||
if (skipBoth || (ModifierKeys == Keys.Control && Util.Prompt(MessageBoxButtons.YesNo, "Cancel writing data back to GARC?") == DialogResult.Yes))
|
||||
{ threads--; updateStatus("Aborted!", false); return false; }
|
||||
|
||||
try
|
||||
{
|
||||
bool success = CTR.GARC.garcPackMS(infolder, outfile, Config.GARCVersion, PB ? pBar1 : null, null, true);
|
||||
bool success = CTR.GARC.garcPackMS(infolder, outfile, Config.GARCVersion, padBytes, PB ? pBar1 : null, null, true);
|
||||
threads--;
|
||||
updateStatus(string.Format(success ? "Success!" : "Failed!"), false);
|
||||
return success;
|
||||
@@ -1165,10 +1165,10 @@ private void threadGet(string infile, string outfolder, bool PB = true, bool byp
|
||||
catch { }
|
||||
new Thread(() => getGARC(infile, outfolder, PB, bypassExt)).Start();
|
||||
}
|
||||
private void threadSet(string outfile, string infolder, bool PB = true)
|
||||
private void threadSet(string outfile, string infolder, int padBytes, bool PB = true)
|
||||
{
|
||||
threads++;
|
||||
new Thread(() => setGARC(outfile, infolder, PB)).Start();
|
||||
new Thread(() => setGARC(outfile, infolder, padBytes, PB)).Start();
|
||||
}
|
||||
|
||||
private static void backupGARCs(bool overwrite, params string[] g)
|
||||
|
||||
35
pk3DS/Tools/ToolsUI.Designer.cs
generated
35
pk3DS/Tools/ToolsUI.Designer.cs
generated
@@ -39,7 +39,10 @@ private void InitializeComponent()
|
||||
this.B_Reset = new System.Windows.Forms.Button();
|
||||
this.CHK_Delete = new System.Windows.Forms.CheckBox();
|
||||
this.pBar1 = new System.Windows.Forms.ProgressBar();
|
||||
this.NUD_Padding = new System.Windows.Forms.NumericUpDown();
|
||||
this.L_Padding = new System.Windows.Forms.Label();
|
||||
((System.ComponentModel.ISupportInitialize)(this.PB_BCLIM)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.NUD_Padding)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// PB_Unpack
|
||||
@@ -147,12 +150,41 @@ private void InitializeComponent()
|
||||
this.pBar1.Size = new System.Drawing.Size(300, 12);
|
||||
this.pBar1.TabIndex = 11;
|
||||
//
|
||||
// NUD_Padding
|
||||
//
|
||||
this.NUD_Padding.Hexadecimal = true;
|
||||
this.NUD_Padding.Location = new System.Drawing.Point(118, 164);
|
||||
this.NUD_Padding.Maximum = new decimal(new int[] {
|
||||
65536,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.NUD_Padding.Name = "NUD_Padding";
|
||||
this.NUD_Padding.Size = new System.Drawing.Size(44, 20);
|
||||
this.NUD_Padding.TabIndex = 12;
|
||||
this.NUD_Padding.Value = new decimal(new int[] {
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
//
|
||||
// L_Padding
|
||||
//
|
||||
this.L_Padding.Location = new System.Drawing.Point(12, 164);
|
||||
this.L_Padding.Name = "L_Padding";
|
||||
this.L_Padding.Size = new System.Drawing.Size(100, 20);
|
||||
this.L_Padding.TabIndex = 13;
|
||||
this.L_Padding.Text = "GARC Padding:";
|
||||
this.L_Padding.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// ToolsUI
|
||||
//
|
||||
this.AllowDrop = true;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(324, 362);
|
||||
this.Controls.Add(this.L_Padding);
|
||||
this.Controls.Add(this.NUD_Padding);
|
||||
this.Controls.Add(this.pBar1);
|
||||
this.Controls.Add(this.CHK_Delete);
|
||||
this.Controls.Add(this.B_Reset);
|
||||
@@ -171,6 +203,7 @@ private void InitializeComponent()
|
||||
this.Text = "Tools";
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.closeForm);
|
||||
((System.ComponentModel.ISupportInitialize)(this.PB_BCLIM)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.NUD_Padding)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
@@ -189,5 +222,7 @@ private void InitializeComponent()
|
||||
private System.Windows.Forms.Button B_Reset;
|
||||
private System.Windows.Forms.CheckBox CHK_Delete;
|
||||
private System.Windows.Forms.ProgressBar pBar1;
|
||||
private System.Windows.Forms.NumericUpDown NUD_Padding;
|
||||
private System.Windows.Forms.Label L_Padding;
|
||||
}
|
||||
}
|
||||
@@ -153,7 +153,6 @@ private void saveARC(string path)
|
||||
{
|
||||
if (!Directory.Exists(path)) { Util.Error("Input path is not a Folder", path); return; }
|
||||
string folderName = Path.GetFileName(path);
|
||||
if (folderName == null) return;
|
||||
string parentName = Directory.GetParent(path).FullName;
|
||||
int type = CB_Repack.SelectedIndex;
|
||||
switch (type)
|
||||
@@ -179,10 +178,14 @@ private void saveARC(string path)
|
||||
return;
|
||||
|
||||
var version = dr == DialogResult.Yes ? CTR.GARC.VER_6 : CTR.GARC.VER_4;
|
||||
int padding = (int)NUD_Padding.Value;
|
||||
if (version == CTR.GARC.VER_4)
|
||||
padding = 4;
|
||||
|
||||
string outfolder = Directory.GetParent(path).FullName;
|
||||
new Thread(() =>
|
||||
{
|
||||
string outfolder = Directory.GetParent(path).FullName;
|
||||
bool r = CTR.GARC.garcPackMS(path, Path.Combine(outfolder, folderName + ".garc"), version, pBar1);
|
||||
bool r = CTR.GARC.garcPackMS(path, Path.Combine(outfolder, folderName + ".garc"), version, padding, pBar1);
|
||||
if (!r) { Util.Alert("Packing failed."); return; }
|
||||
// Delete path after repacking
|
||||
if (CHK_Delete.Checked && Directory.Exists(path))
|
||||
|
||||
Reference in New Issue
Block a user