From 6a21540a4a618409e4b718acbb486f43f5952d99 Mon Sep 17 00:00:00 2001 From: Gericom Date: Mon, 29 Dec 2014 12:33:18 +0100 Subject: [PATCH] Yaz0 compression, (de)comp files from tool menu --- CommonCompressors/YAZ0.cs | 56 ++++++++++++++++++++-------- EveryFileExplorer/Form1.cs | 75 +++++++++++++++++++++++++++++++++++--- 2 files changed, 109 insertions(+), 22 deletions(-) diff --git a/CommonCompressors/YAZ0.cs b/CommonCompressors/YAZ0.cs index eace2d2..5b15b62 100644 --- a/CommonCompressors/YAZ0.cs +++ b/CommonCompressors/YAZ0.cs @@ -3,23 +3,30 @@ using System.Collections.Generic; using System.Linq; using System.Text; using LibEveryFileExplorer.Compression; +using System.Runtime.InteropServices; namespace CommonCompressors { - public unsafe class YAZ0 : CompressionFormat + public unsafe class YAZ0 : CompressionFormat, ICompressable { - /*public unsafe byte[] Compress(byte[] Data) + //Compression could be optimized by using look-ahead. + public unsafe byte[] Compress(byte[] Data) { byte* dataptr = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(Data, 0); - byte[] result = new byte[Data.Length + Data.Length / 8 + 4]; + byte[] result = new byte[Data.Length + Data.Length / 8 + 0x10]; byte* resultptr = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(result, 0); - *resultptr++ = 0x10; - *resultptr++ = (byte)(Data.Length & 0xFF); - *resultptr++ = (byte)((Data.Length >> 8) & 0xFF); + *resultptr++ = (byte)'Y'; + *resultptr++ = (byte)'a'; + *resultptr++ = (byte)'z'; + *resultptr++ = (byte)'0'; + *resultptr++ = (byte)((Data.Length >> 24) & 0xFF); *resultptr++ = (byte)((Data.Length >> 16) & 0xFF); + *resultptr++ = (byte)((Data.Length >> 8) & 0xFF); + *resultptr++ = (byte)((Data.Length >> 0) & 0xFF); + for (int i = 0; i < 8; i++) *resultptr++ = 0; int length = Data.Length; - int dstoffs = 4; + int dstoffs = 16; int Offs = 0; while (true) { @@ -33,9 +40,10 @@ namespace CommonCompressors int nr = 2; { byte* ptr = dataptr - 1; - int maxnum = 18; + int maxnum = 0x111; if (length - Offs < maxnum) maxnum = length - Offs; - int maxback = 0x1000; + //Use a smaller amount of bytes back to decrease time + int maxback = 0x400;//0x1000; if (Offs < maxback) maxback = Offs; maxback = (int)dataptr - maxback; int tmpnr; @@ -47,6 +55,12 @@ namespace CommonCompressors while (tmpnr < maxnum && ptr[tmpnr] == dataptr[tmpnr]) tmpnr++; if (tmpnr > nr) { + if (Offs + tmpnr > length) + { + nr = length - Offs; + back = (int)(dataptr - ptr); + break; + } nr = tmpnr; back = (int)(dataptr - ptr); if (nr == maxnum) break; @@ -59,9 +73,19 @@ namespace CommonCompressors { Offs += nr; dataptr += nr; - *resultptr++ = (byte)((((back - 1) >> 8) & 0xF) | (((nr - 3) & 0xF) << 4)); - *resultptr++ = (byte)((back - 1) & 0xFF); - dstoffs += 2; + if (nr >= 0x12) + { + *resultptr++ = (byte)(((back - 1) >> 8) & 0xF); + *resultptr++ = (byte)((back - 1) & 0xFF); + *resultptr++ = (byte)((nr - 0x12) & 0xFF); + dstoffs += 3; + } + else + { + *resultptr++ = (byte)((((back - 1) >> 8) & 0xF) | (((nr - 2) & 0xF) << 4)); + *resultptr++ = (byte)((back - 1) & 0xFF); + dstoffs += 2; + } comp = 1; } else @@ -70,21 +94,21 @@ namespace CommonCompressors dstoffs++; Offs++; } - header = (byte)((header << 1) | (comp & 1)); - if (Offs == length) + header = (byte)((header << 1) | ((comp == 1) ? 0 : 1)); + if (Offs >= length) { header = (byte)(header << (7 - i)); break; } } result[headeroffs] = header; - if (Offs == length) break; + if (Offs >= length) break; } while ((dstoffs % 4) != 0) dstoffs++; byte[] realresult = new byte[dstoffs]; Array.Copy(result, realresult, dstoffs); return realresult; - }*/ + } public override byte[] Decompress(byte[] Data) { diff --git a/EveryFileExplorer/Form1.cs b/EveryFileExplorer/Form1.cs index ba37fd5..c023577 100644 --- a/EveryFileExplorer/Form1.cs +++ b/EveryFileExplorer/Form1.cs @@ -116,10 +116,15 @@ namespace EveryFileExplorer foreach (Type t in p.CompressionTypes) { MenuItem ii = m.MenuItems.Add(((dynamic)new StaticDynamic(t)).Identifier.GetCompressionDescription()); - ii.MenuItems.Add("Decompress..."); - if (t.GetInterfaces().Contains(typeof(ICompressable))) ii.MenuItems.Add("Compress..."); - //ii.Click += new EventHandler(CreateFileNew_Click); - //ii.Tag = t; + var dec = ii.MenuItems.Add("Decompress..."); + dec.Click += new EventHandler(Decompress_Click); + dec.Tag = t; + if (t.GetInterfaces().Contains(typeof(ICompressable))) + { + var comp = ii.MenuItems.Add("Compress..."); + comp.Click += new EventHandler(Compress_Click); + comp.Tag = t; + } } } } @@ -127,6 +132,64 @@ namespace EveryFileExplorer PendingPath = null; } + void Compress_Click(object sender, EventArgs e) + { + openFileDialog1.Filter = "All Files (*.*)|*.*"; + if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK + && openFileDialog1.FileName.Length > 0) + { + saveFileDialog1.Filter = "All Files (*.*)|*.*"; + saveFileDialog1.FileName = Path.GetFileNameWithoutExtension(openFileDialog1.FileName) + "_comp" + Path.GetExtension(openFileDialog1.FileName); + if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK + && saveFileDialog1.FileName.Length > 0) + { + Type comp = (Type)((MenuItem)sender).Tag; + ICompressable c = (ICompressable)comp.InvokeMember("", BindingFlags.CreateInstance, null, null, new object[0]); + byte[] result = null; + try + { + result = c.Compress(File.ReadAllBytes(openFileDialog1.FileName)); + } + catch (Exception ee) + { + MessageBox.Show("An error occured while trying to compress:\n" + ee); + return; + } + File.Create(saveFileDialog1.FileName).Close(); + File.WriteAllBytes(saveFileDialog1.FileName, result); + } + } + } + + void Decompress_Click(object sender, EventArgs e) + { + openFileDialog1.Filter = "All Files (*.*)|*.*"; + if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK + && openFileDialog1.FileName.Length > 0) + { + Type comp = (Type)((MenuItem)sender).Tag; + CompressionFormatBase c = (CompressionFormatBase)comp.InvokeMember("", BindingFlags.CreateInstance, null, null, new object[0]); + byte[] result = null; + try + { + result = c.Decompress(File.ReadAllBytes(openFileDialog1.FileName)); + } + catch (Exception ee) + { + MessageBox.Show("An error occured while trying to decompress! The file might not be in this compression type or not compressed at all!"); + return; + } + saveFileDialog1.Filter = "All Files (*.*)|*.*"; + saveFileDialog1.FileName = Path.GetFileNameWithoutExtension(openFileDialog1.FileName) + "_dec" + Path.GetExtension(openFileDialog1.FileName); + if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK + && saveFileDialog1.FileName.Length > 0) + { + File.Create(saveFileDialog1.FileName).Close(); + File.WriteAllBytes(saveFileDialog1.FileName, result); + } + } + } + void CreateNewProject_Click(object sender, EventArgs e) { ProjectBase p = (ProjectBase)((Type)((MenuItem)sender).Tag).InvokeMember("", BindingFlags.CreateInstance, null, null, new object[0]); @@ -274,9 +337,9 @@ namespace EveryFileExplorer file.File.Data = data; file.File.Save(); } - catch + catch (Exception ee) { - MessageBox.Show("An error occurred while trying to save!"); + MessageBox.Show("An error occurred while trying to save:\n" + ee); } }