Add support for decompressing gz.bin files on it's own

This commit is contained in:
KillzXGaming 2019-09-11 16:25:20 -04:00
parent 82761a6120
commit c7d2a5d8eb
6 changed files with 261 additions and 1 deletions

View file

@ -25,6 +25,7 @@ namespace Toolbox.Library.IO
items.Add(new ToolStripMenuItem("lZ4F")); items.Add(new ToolStripMenuItem("lZ4F"));
items.Add(new ToolStripMenuItem("ZSTD")); items.Add(new ToolStripMenuItem("ZSTD"));
items.Add(new ToolStripMenuItem("ZLIB")); items.Add(new ToolStripMenuItem("ZLIB"));
items.Add(new ToolStripMenuItem("ZLIB_GZ (Hyrule Warriors)"));
SetFunctions(items); SetFunctions(items);
return items; return items;
@ -74,6 +75,8 @@ namespace Toolbox.Library.IO
OpenFileForCompression(CompressionType.Zstb, Compress); OpenFileForCompression(CompressionType.Zstb, Compress);
else if (Name == "ZLIB") else if (Name == "ZLIB")
OpenFileForCompression(CompressionType.Zlib, Compress); OpenFileForCompression(CompressionType.Zlib, Compress);
else if (Name.Contains("ZLIB_GZ"))
OpenFileForCompression(CompressionType.ZlibGz, Compress);
else throw new Exception("Unimplimented Type! " + Name); else throw new Exception("Unimplimented Type! " + Name);
} }
@ -99,6 +102,7 @@ namespace Toolbox.Library.IO
case CompressionType.Lz4: case CompressionType.Lz4:
SaveFileForCompression(STLibraryCompression.Type_LZ4.Compress(data)); SaveFileForCompression(STLibraryCompression.Type_LZ4.Compress(data));
break; break;
} }
} }
public void DecompressData(CompressionType CompressionType, byte[] data) public void DecompressData(CompressionType CompressionType, byte[] data)
@ -131,6 +135,9 @@ namespace Toolbox.Library.IO
case CompressionType.Lz4: case CompressionType.Lz4:
SaveFileForCompression(STLibraryCompression.Type_LZ4.Decompress(data)); SaveFileForCompression(STLibraryCompression.Type_LZ4.Decompress(data));
break; break;
case CompressionType.ZlibGz:
SaveFileForCompression(STLibraryCompression.ZLIB_GZ.Decompress(new MemoryStream(data)));
break;
} }
} }
catch catch
@ -158,6 +165,19 @@ namespace Toolbox.Library.IO
} }
} }
private void SaveFileForCompression(Stream data)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "All files(*.*)|*.*";
Cursor.Current = Cursors.Default;
if (sfd.ShowDialog() == DialogResult.OK)
{
data.ExportToFile(sfd.FileName);
MessageBox.Show($"File has been saved to {sfd.FileName}", "Save Notification");
}
}
private void SaveFileForCompression(byte[] data) private void SaveFileForCompression(byte[] data)
{ {
SaveFileDialog sfd = new SaveFileDialog(); SaveFileDialog sfd = new SaveFileDialog();

View file

@ -61,6 +61,88 @@ namespace Toolbox.Library.IO
} }
public class ZLIB_GZ
{
public static bool IsCompressed(Stream stream)
{
using (var reader = new FileReader(stream, true))
{
reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
uint chunkCount = reader.ReadUInt32();
uint unk = reader.ReadUInt32();
if (reader.BaseStream.Length > 4 + (chunkCount * 4))
{
uint[] chunkSizes = reader.ReadUInt32s((int)chunkCount); //Not very sure about this
reader.Align(128);
while (!reader.EndOfStream)
{
uint size = reader.ReadUInt32();
long pos = reader.Position;
ushort magic = reader.ReadUInt16();
reader.Position = 0;
if (magic == 0x78da)
return true;
}
}
reader.Position = 0;
}
return false;
}
public static Stream Decompress(Stream stream)
{
using (var reader = new FileReader(stream, true))
{
reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
uint unk = reader.ReadUInt32();
try
{
uint chunkCount = reader.ReadUInt32();
uint unk2 = reader.ReadUInt32();
uint[] chunkSizes = reader.ReadUInt32s((int)chunkCount); //Not very sure about this
reader.Align(128);
List<byte[]> DecompressedChunks = new List<byte[]>();
//Now search for zlibbed chunks
while (!reader.EndOfStream)
{
uint size = reader.ReadUInt32();
long pos = reader.Position;
ushort magic = reader.ReadUInt16();
///Check zlib magic
if (magic == 0x78da)
{
var data = STLibraryCompression.ZLIB.Decompress(reader.getSection((uint)pos, size));
DecompressedChunks.Add(data);
reader.SeekBegin(pos + size); //Seek the compressed size and align it to goto the next chunk
reader.Align(128);
}
else //If the magic check fails, seek back 2. This shouldn't happen, but just incase
reader.Seek(-2);
}
//Return the decompressed stream with all chunks combined
return new MemoryStream(Utils.CombineByteArray(DecompressedChunks.ToArray()));
}
catch
{
}
}
return null;
}
}
public class ZLIB public class ZLIB
{ {
public static byte[] Decompress(byte[] b) public static byte[] Decompress(byte[] b)

View file

@ -15,6 +15,7 @@ namespace Toolbox.Library
Lz4, Lz4,
Lz4f, Lz4f,
Zstb, Zstb,
ZlibGz,
MarioTennisCustom, MarioTennisCustom,
} }
} }

View file

@ -0,0 +1,154 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
//Thanks EFE!
//https://github.com/Gericom/EveryFileExplorer/blob/f9f00d193c9608d71c9a23d9f3ab7e752f4ada2a/LibEveryFileExplorer/GFX/BitmapFont.cs
namespace LibEveryFileExplorer.GFX
{
public class BitmapFont : IDisposable
{
public BitmapFont()
{
Characters = new Dictionary<char, Character>();
}
public Dictionary<char, Character> Characters { get; private set; }
public int LineHeight { get; set; }
public int GetLineWidth(String Text, FontRenderSettings Settings, out int LineEnd)
{
LineEnd = -1;
int result = 0;
int i = 0;
foreach (char c in Text)
{
if (c == '\n')
{
if (Text.Length > i + 1) LineEnd = i + 1;
break;
}
else if (c == '\r') { i++; continue; }
if (!Characters.ContainsKey(c)) result += Settings.CharSpacing * 4;
else
{
Character info = Characters[c];
result += (int)(info.CharWidth * Settings.XScale) + Settings.CharSpacing;
}
i++;
}
if (result > 0) result -= Settings.CharSpacing;
return result;
}
public Bitmap PrintToBitmap(String Text, FontRenderSettings Settings)
{
int Width = 0;
int Height = 0;
int linestart = 0;
do
{
int lns;
int linewidth = GetLineWidth(Text.Substring(linestart), Settings, out lns);
if (lns != -1) linestart += lns;
else linestart = -1;
if (linewidth > Width) Width = linewidth;
Height += (int)(LineHeight * Settings.YScale) + Settings.LineSpacing;
}
while (linestart != -1);
if (Width == 0 || Height == 0) return null;
Height -= Settings.LineSpacing;
Width += 2;
Bitmap b = new Bitmap(Width, Height);
using (Graphics g = Graphics.FromImage(b))
{
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default;
int X = 0;
int Y = 0;
foreach (char c in Text)
{
if (c == '\n')
{
X = 0;
Y += (int)(LineHeight * Settings.YScale) + Settings.LineSpacing;
continue;
}
else if (c == '\r') continue;
if (!Characters.ContainsKey(c)) X += Settings.CharSpacing * 4;
else
{
Character info = Characters[c];
g.DrawImage(info.CharBitmap,
new RectangleF(X + info.LeftOffset, Y, info.GlyphWidth * Settings.XScale, LineHeight * Settings.YScale),
new Rectangle(0, 0, info.GlyphWidth, LineHeight),
GraphicsUnit.Pixel);
X += (int)(info.CharWidth * Settings.XScale) + Settings.CharSpacing;
}
}
}
return b;
}
public void Dispose()
{
if (Characters == null) return;
foreach (var character in Characters.Values)
character.CharBitmap?.Dispose();
Characters.Clear();
GC.SuppressFinalize(this);
}
public class Character
{
public Character(Bitmap CharBitmap, int LeftOffset, int GlyphWidth, int CharWidth)
{
this.CharBitmap = CharBitmap;
this.LeftOffset = LeftOffset;
this.GlyphWidth = GlyphWidth;
this.CharWidth = CharWidth;
}
public Bitmap CharBitmap { get; set; }
public int LeftOffset { get; set; }
public int GlyphWidth { get; set; }
public int CharWidth { get; set; }
}
public class FontRenderSettings
{
public FontRenderSettings()
{
CharSpacing = 3;
XScale = YScale = 1;
HAlignment = XAlignment.Left;
VAlignment = YAlignment.Top;
}
public int CharSpacing { get; set; }
public int LineSpacing { get; set; }
public float XScale { get; set; }
public float YScale { get; set; }
public XAlignment HAlignment { get; set; }
public YAlignment VAlignment { get; set; }
public enum XAlignment
{
Left, Center, Right
}
public enum YAlignment
{
Top, Center, Bottom
}
}
}
}

View file

@ -233,6 +233,7 @@
<Compile Include="Compression\Yaz0.cs" /> <Compile Include="Compression\Yaz0.cs" />
<Compile Include="Compression\ZCMP.cs" /> <Compile Include="Compression\ZCMP.cs" />
<Compile Include="Config.cs" /> <Compile Include="Config.cs" />
<Compile Include="Enums\CompressionType.cs" />
<Compile Include="FileFormats\DDS\RGBAPixelDecoder.cs" /> <Compile Include="FileFormats\DDS\RGBAPixelDecoder.cs" />
<Compile Include="Forms\ColorAlphaBox.cs"> <Compile Include="Forms\ColorAlphaBox.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
@ -301,6 +302,7 @@
<Compile Include="Helpers\ArchiveNodeMenuHelper.cs" /> <Compile Include="Helpers\ArchiveNodeMenuHelper.cs" />
<Compile Include="Helpers\DirectoryHelper.cs" /> <Compile Include="Helpers\DirectoryHelper.cs" />
<Compile Include="Helpers\DragHelper.cs" /> <Compile Include="Helpers\DragHelper.cs" />
<Compile Include="Imaging\BitmapFont.cs" />
<Compile Include="Interfaces\FileFormatting\IFormEditorParameters.cs" /> <Compile Include="Interfaces\FileFormatting\IFormEditorParameters.cs" />
<Compile Include="Interfaces\FileFormatting\ILeaveOpenOnLoad.cs" /> <Compile Include="Interfaces\FileFormatting\ILeaveOpenOnLoad.cs" />
<Compile Include="Interfaces\FileFormatting\IPropertyContainer.cs" /> <Compile Include="Interfaces\FileFormatting\IPropertyContainer.cs" />
@ -812,7 +814,6 @@
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon> <DependentUpon>Resources.resx</DependentUpon>
</Compile> </Compile>
<Compile Include="PublicEnums.cs" />
<Compile Include="Rendering\DrawableBackground.cs" /> <Compile Include="Rendering\DrawableBackground.cs" />
<Compile Include="Rendering\DrawableDividedCube.cs" /> <Compile Include="Rendering\DrawableDividedCube.cs" />
<Compile Include="Rendering\DrawableBoundingBox.cs" /> <Compile Include="Rendering\DrawableBoundingBox.cs" />

View file

@ -293,7 +293,9 @@ namespace Toolbox
if (inter.IsGenericType && inter.GetGenericTypeDefinition() == typeof(IEditor<>)) if (inter.IsGenericType && inter.GetGenericTypeDefinition() == typeof(IEditor<>))
{ {
MethodInfo method = objectType.GetMethod("OpenForm"); MethodInfo method = objectType.GetMethod("OpenForm");
MethodInfo methodFill = objectType.GetMethod("FillEditor");
var control = (UserControl)method.Invoke(file, new object[0]); var control = (UserControl)method.Invoke(file, new object[0]);
methodFill.Invoke(file, new object[1] { control });
var form = new GenericEditorForm(false, control); var form = new GenericEditorForm(false, control);
TabDupeIndex = 0; TabDupeIndex = 0;
form.Text = CheckTabDupes(((IFileFormat)file).FileName); form.Text = CheckTabDupes(((IFileFormat)file).FileName);