From d2ac6e64a4cd3870d331f379e29c11ad7f0fd57e Mon Sep 17 00:00:00 2001 From: BahaBulle Date: Tue, 21 Feb 2017 14:10:56 +0100 Subject: [PATCH] Init assembly with Valis compression --- .gitattributes | 63 +++ .gitignore | 189 ++++++++ Fr.BahaBulle.Compression.sln | 22 + Fr.BahaBulle.Compression/Compression.cs | 17 + .../Fr.BahaBulle.Compression.csproj | 70 +++ .../Properties/AssemblyInfo.cs | 36 ++ Fr.BahaBulle.Compression/Valis/Valis.cs | 404 ++++++++++++++++++ 7 files changed, 801 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 Fr.BahaBulle.Compression.sln create mode 100644 Fr.BahaBulle.Compression/Compression.cs create mode 100644 Fr.BahaBulle.Compression/Fr.BahaBulle.Compression.csproj create mode 100644 Fr.BahaBulle.Compression/Properties/AssemblyInfo.cs create mode 100644 Fr.BahaBulle.Compression/Valis/Valis.cs diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7964536 --- /dev/null +++ b/.gitignore @@ -0,0 +1,189 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +x64/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Roslyn cache directories +*.ide/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +#NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +## TODO: Comment the next line if you want to checkin your +## web deploy settings but do note that will include unencrypted +## passwords +#*.pubxml + +# NuGet Packages Directory +packages/* +## TODO: If the tool you use requires repositories.config +## uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since +# NuGet packages use it for MSBuild targets. +# This line needs to be after the ignore of the build folder +# (and the packages folder if the line above has been uncommented) +!packages/build/ + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml \ No newline at end of file diff --git a/Fr.BahaBulle.Compression.sln b/Fr.BahaBulle.Compression.sln new file mode 100644 index 0000000..7aa373a --- /dev/null +++ b/Fr.BahaBulle.Compression.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Fr.BahaBulle.Compression", "Fr.BahaBulle.Compression\Fr.BahaBulle.Compression.csproj", "{611D58ED-62D2-4B2F-8DBD-B9172AD37A52}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {611D58ED-62D2-4B2F-8DBD-B9172AD37A52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {611D58ED-62D2-4B2F-8DBD-B9172AD37A52}.Debug|Any CPU.Build.0 = Debug|Any CPU + {611D58ED-62D2-4B2F-8DBD-B9172AD37A52}.Release|Any CPU.ActiveCfg = Release|Any CPU + {611D58ED-62D2-4B2F-8DBD-B9172AD37A52}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Fr.BahaBulle.Compression/Compression.cs b/Fr.BahaBulle.Compression/Compression.cs new file mode 100644 index 0000000..0b246ff --- /dev/null +++ b/Fr.BahaBulle.Compression/Compression.cs @@ -0,0 +1,17 @@ +using Fr.BahaBulle.Compression.Valis; +using Fr.BahaBulle.Tools.Parser; + +namespace Fr.BahaBulle.Compression +{ + public class Compression + { + public static void InitModule() + { + Parser parser = Parser.INSTANCE; + + parser.AddMethod("decomp-valis", new Parser.ProcessMethod(cValis.ValisDecompression)); + parser.AddMethod("comp-valis", new Parser.ProcessMethod(cValis.ValisCompression)); + } + + } +} diff --git a/Fr.BahaBulle.Compression/Fr.BahaBulle.Compression.csproj b/Fr.BahaBulle.Compression/Fr.BahaBulle.Compression.csproj new file mode 100644 index 0000000..514a325 --- /dev/null +++ b/Fr.BahaBulle.Compression/Fr.BahaBulle.Compression.csproj @@ -0,0 +1,70 @@ + + + + + Debug + AnyCPU + {611D58ED-62D2-4B2F-8DBD-B9172AD37A52} + Library + Properties + Fr.BahaBulle.Compression + Fr.BahaBulle.Compression + v4.5.2 + 512 + + + + true + full + false + ..\Build\bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Build\obj + + + pdbonly + true + ..\Build\bin\Release\ + TRACE + prompt + 4 + ..\Build\obj + + + true + + + Fr.BahaBulle.Key.pfx + + + + False + ..\..\Fr.BahaBulle.Tools\Build\bin\Release\Fr.BahaBulle.Tools.dll + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Fr.BahaBulle.Compression/Properties/AssemblyInfo.cs b/Fr.BahaBulle.Compression/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..00db8e5 --- /dev/null +++ b/Fr.BahaBulle.Compression/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Les informations générales relatives à un assembly dépendent de +// l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations +// associées à un assembly. +[assembly: AssemblyTitle("Fr.BahaBulle.Compression")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("BahaBulle")] +[assembly: AssemblyProduct("Fr.BahaBulle.Compression")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// L'affectation de la valeur false à ComVisible rend les types invisibles dans cet assembly +// aux composants COM. Si vous devez accéder à un type dans cet assembly à partir de +// COM, affectez la valeur true à l'attribut ComVisible sur ce type. +[assembly: ComVisible(false)] + +// Le GUID suivant est pour l'ID de la typelib si ce projet est exposé à COM +[assembly: Guid("f93fea32-332e-485b-ad8b-2e4126a35a47")] + +// Les informations de version pour un assembly se composent des quatre valeurs suivantes : +// +// Version principale +// Version secondaire +// Numéro de build +// Révision +// +// Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut +// en utilisant '*', comme indiqué ci-dessous : +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Fr.BahaBulle.Compression/Valis/Valis.cs b/Fr.BahaBulle.Compression/Valis/Valis.cs new file mode 100644 index 0000000..c778612 --- /dev/null +++ b/Fr.BahaBulle.Compression/Valis/Valis.cs @@ -0,0 +1,404 @@ +using Fr.BahaBulle.Tools.Common; +using Fr.BahaBulle.Tools.Parser; +using Fr.BahaBulle.Tools.TraceLog; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text; + +namespace Fr.BahaBulle.Compression.Valis +{ + internal static class cValis + { + private struct st_param + { + public int length; + public int offset; + } + + public static bool ValisDecompression(List param) + { + Parser parser = Parser.INSTANCE; + + if (param.Count != 2) + { + Trace.WriteLine(string.Format("Number of parameters incorrect - 2 waited ; got {0}", param.Count)); + return false; + } + + Parser.stStream source = default(Parser.stStream); + long source_adress = 0; + + Parser.stStream destination = default(Parser.stStream); + + object obj; + + foreach (Parser.stParam arg in param) + { + if (arg.name == "source") + { + obj = parser.GetParam(arg.param, "file"); + if (obj == null) + { + Trace.WriteLine("Parameter file not found"); + return false; + } + else + source = (Parser.stStream)obj; + + obj = parser.GetParam(arg.param, "adress", "long"); + if (obj != null) + source_adress = (long)obj; + else + source_adress = 0; + } + else if (arg.name == "dest") + { + obj = parser.GetParam(arg.param, "file", null, true); + if (obj == null) + destination = parser.NewStream(arg.param["file"], true); + else + destination = (Parser.stStream)obj; + } + else + { + Trace.WriteLine(string.Format("Incorrect option - source, dest, pointer ; get {0}", arg.name)); + return false; + } + } + + source.file.Position = source_adress; + + if (!Decomp(source, destination)) + return false; + + if (!string.IsNullOrEmpty(destination.filename)) + parser.WriteStream(destination); + + return true; + } + + public static bool ValisCompression(List param) + { + Parser parser = Parser.INSTANCE; + + if (param.Count != 2) + { + Trace.WriteLine(string.Format("Number of parameters incorrect - 2 waited ; got {0}", param.Count)); + return false; + } + + Parser.stStream source = default(Parser.stStream); + + Parser.stStream destination = default(Parser.stStream); + + object obj; + + foreach (Parser.stParam arg in param) + { + if (arg.name == "source") + { + obj = parser.GetParam(arg.param, "file"); + if (obj == null) + { + Trace.WriteLine("Parameter file not found"); + return false; + } + else + source = (Parser.stStream)obj; + } + else if (arg.name == "dest") + { + obj = parser.GetParam(arg.param, "file", null, true); + if (obj == null) + destination = parser.NewStream(arg.param["file"], true); + else + destination = (Parser.stStream)obj; + } + else + { + Trace.WriteLine(string.Format("Incorrect option - source, dest, pointer ; get {0}", arg.name)); + return false; + } + } + + if (!Comp(source, destination)) + return false; + + return true; + } + + #region Private methods + + /// + /// Initialise the buffer + /// + /// + private static byte[] InitBuffer(int size = 0x1000) + { + byte[] buffer = new byte[size]; + + int pos = 0; + byte value = 0x00; + for (int i = 0; i < 0x100; i++) + { + for (int j = 0; j < 13; j++) + { + buffer[pos++] = value; + } + + value++; + } + + value = 0x00; + for (int i = 0; i < 0x100; i++) + { + buffer[pos++] = value++; + } + + value = 0xFF; + for (int i = 0; i < 0x100; i++) + { + buffer[pos++] = value--; + } + + for (int i = 0; i < 0x80; i++) + { + buffer[pos++] = 0x00; + } + + for (int i = 0; i < 0x80; i++) + { + buffer[pos++] = 0x20; + } + + return buffer; + } + + /// + /// Find the greater LZ compression from a position + /// + /// Array of bytes where look for RLE compression + /// Current position in the array + /// + private static st_param FindLZInBuffer(byte[] a_bytes, int pos, int size_buffer, int len_max) + { + st_param param; + int dict = 0; + int pos_result = 0; + int len_result = 0; + + if (pos > 0x1000) + dict = pos - 0xFFF; + + while (dict < pos) + { + int len = 0; + + while (pos + len < a_bytes.Length && a_bytes[dict + len] == a_bytes[pos + len] && (len < len_max)) + len++; + + if (len >= len_result) + { + pos_result = dict; + len_result = len; + } + + dict++; + } + + param.length = len_result; + param.offset = pos_result; + + return param; + } + + /// + /// Decompress a stream + /// + /// Stream to decompress + /// Destination stream + /// + private static bool Decomp(Parser.stStream Source, Parser.stStream Destination) + { + int pos = 0xFEE; + int curr_pos = 0; + byte[] bytes = new byte[0x1000]; + byte one_byte; + UInt16 two_bytes; + + LogTrace trace = LogTrace.INSTANCE; + + try + { + using (BinaryReader br = new BinaryReader(Source.file, Encoding.Default, true)) + { + UInt32 size_in = br.ReadUInt32().ToBigEndian32(); + UInt32 size_out = br.ReadUInt32().ToBigEndian32(); + + bytes = InitBuffer(); + + if (trace.TSwitch.TraceVerbose) + { + using (BinaryWriter bw = new BinaryWriter(File.Open("buffer.bin", FileMode.Create))) + { + bw.Write(bytes); + } + } + + Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format("Size IN {0}\nSize OUT {1}", size_in, size_out)); + + while (curr_pos < size_out) + { + byte header = br.ReadByte(); + + Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format("header {0:X08} : {1:X02}", br.BaseStream.Position - 1, header)); + + for (int i = 0; i < 8; i++) + { + if ((header & 1) == 1) + { + one_byte = br.ReadByte(); + + Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format(" {0} - Ecrit {1:X08} : {2:X02}", i, Destination.file.Position, one_byte)); + + Destination.file.WriteByte(one_byte); + curr_pos++; + bytes[pos] = one_byte; + + pos = (pos + 1) & 0xFFF; + } + else + { + two_bytes = br.ReadUInt16(); + + int nb = ((two_bytes >> 8) & 0x0F) + 3; + int pos_lz = ((two_bytes & 0xF000) >> 4) | (two_bytes & 0xFF); + + Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format(" {0} - LZ : {1:X04}", i, two_bytes)); + Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format(" nb : 0x{0:X02} ({1})", nb, nb)); + Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format(" Pos : 0x{0:X04} ({1})", pos_lz, pos_lz)); + Trace.WriteIf(trace.TSwitch.TraceVerbose, string.Format(" Ecrit {0:X08} : ", Destination.file.Position)); + + for (int j = 0; j < nb; j++) + { + Destination.file.WriteByte(bytes[pos_lz]); + curr_pos++; + bytes[pos] = bytes[pos_lz]; + Trace.WriteIf(trace.TSwitch.TraceVerbose, string.Format("{0:X02} ", bytes[pos_lz])); + + pos = (pos + 1) & 0xFFF; + pos_lz = (pos_lz + 1) & 0xFFF; + } + + Trace.WriteLineIf(trace.TSwitch.TraceVerbose, ""); + } + + header >>= 1; + + if (curr_pos >= size_out) + break; + } + + Trace.WriteLineIf(trace.TSwitch.TraceVerbose, ""); + } + } + + return true; + } + catch (Exception ex) + { + Trace.WriteLine(string.Format("(EE) {0}", ex.Message)); + return false; + } + } + + /// + /// Compress a stream + /// + /// Stream to compress + /// Destination stream + /// + private static bool Comp(Parser.stStream Source, Parser.stStream Destination) + { + st_param param_lz; + int size_out = (int)Source.file.Length; + int pos_temp = 0; + int pos = 0xFEE; + int curr_pos = pos; + byte[] b_size_out = BitConverter.GetBytes(size_out.ToBigEndian32()); + byte[] temp = new byte[24]; + int buffer_size = 0x1000; + + LogTrace trace = LogTrace.INSTANCE; + + try + { + Source.file.Position = 0; + Destination.file.Position = 0; + + Destination.file.Write(b_size_out, 0, 4); + Destination.file.Write(b_size_out, 0, 4); + + byte[] bytes = InitBuffer(pos + size_out); + Source.file.Read(bytes, pos, size_out); + + while (curr_pos < size_out + pos) + { + byte header = 0; + + for (int i = 0; i < 8; i++) + { + if (curr_pos >= size_out + pos) + break; + + Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format("{0} - Pos : {1:X}", i, curr_pos - pos)); + + param_lz = FindLZInBuffer(bytes, curr_pos, buffer_size, 0x12); + Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format(" nb LZ : {0:000}", param_lz.length)); + + if (param_lz.length < 3) + { + Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format(" -> Byte : {0:X02}", bytes[curr_pos])); + + temp[pos_temp++] = bytes[curr_pos]; + + header |= (byte)(1 << i); + curr_pos++; + } + else + { + Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format(" POS_LZ : {0:X04}", param_lz.offset)); + Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format(" -> LZ : {0:X02}{1:X02}", (byte)(((param_lz.offset & 0xF00) >> 4) | ((param_lz.length - 3) & 0x0F)), (byte)(param_lz.offset & 0xFF))); + + temp[pos_temp++] = (byte)(param_lz.offset & 0xFF); + temp[pos_temp++] = (byte)(((param_lz.offset & 0xF00) >> 4) | ((param_lz.length - 3) & 0x0F)); + + curr_pos += param_lz.length; + } + } + + Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format("Header : {0:X02}\n", header)); + Destination.file.WriteByte(header); + Destination.file.Write(temp, 0, pos_temp); + pos_temp = 0; + } + + byte[] b_size_in = BitConverter.GetBytes((int)((Destination.file.Length - 8).ToBigEndian32())); + + Destination.file.Position = 0; + Destination.file.Write(b_size_in, 0, 4); + + return true; + } + catch (Exception ex) + { + Trace.WriteLine(string.Format("(EE) {0}", ex.Message)); + return false; + } + } + + #endregion + } +}