You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

404 lines
14 KiB

  1. using Fr.BahaBulle.Tools.Common;
  2. using Fr.BahaBulle.Tools.Parser;
  3. using Fr.BahaBulle.Tools.TraceLog;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Diagnostics;
  7. using System.IO;
  8. using System.Text;
  9. namespace Fr.BahaBulle.Compression.Valis
  10. {
  11. internal static class cValis
  12. {
  13. private struct st_param
  14. {
  15. public int length;
  16. public int offset;
  17. }
  18. public static bool ValisDecompression(List<Parser.stParam> param)
  19. {
  20. Parser parser = Parser.INSTANCE;
  21. if (param.Count != 2)
  22. {
  23. Trace.WriteLine(string.Format("Number of parameters incorrect - 2 waited ; got {0}", param.Count));
  24. return false;
  25. }
  26. Parser.stStream source = default(Parser.stStream);
  27. long source_adress = 0;
  28. Parser.stStream destination = default(Parser.stStream);
  29. object obj;
  30. foreach (Parser.stParam arg in param)
  31. {
  32. if (arg.name == "source")
  33. {
  34. obj = parser.GetParam(arg.param, "file");
  35. if (obj == null)
  36. {
  37. Trace.WriteLine("Parameter file not found");
  38. return false;
  39. }
  40. else
  41. source = (Parser.stStream)obj;
  42. obj = parser.GetParam(arg.param, "adress", "long");
  43. if (obj != null)
  44. source_adress = (long)obj;
  45. else
  46. source_adress = 0;
  47. }
  48. else if (arg.name == "dest")
  49. {
  50. obj = parser.GetParam(arg.param, "file", null, true);
  51. if (obj == null)
  52. destination = parser.NewStream(arg.param["file"], true);
  53. else
  54. destination = (Parser.stStream)obj;
  55. }
  56. else
  57. {
  58. Trace.WriteLine(string.Format("Incorrect option - source, dest, pointer ; get {0}", arg.name));
  59. return false;
  60. }
  61. }
  62. source.file.Position = source_adress;
  63. if (!Decomp(source, destination))
  64. return false;
  65. if (!string.IsNullOrEmpty(destination.filename))
  66. parser.WriteStream(destination);
  67. return true;
  68. }
  69. public static bool ValisCompression(List<Parser.stParam> param)
  70. {
  71. Parser parser = Parser.INSTANCE;
  72. if (param.Count != 2)
  73. {
  74. Trace.WriteLine(string.Format("Number of parameters incorrect - 2 waited ; got {0}", param.Count));
  75. return false;
  76. }
  77. Parser.stStream source = default(Parser.stStream);
  78. Parser.stStream destination = default(Parser.stStream);
  79. object obj;
  80. foreach (Parser.stParam arg in param)
  81. {
  82. if (arg.name == "source")
  83. {
  84. obj = parser.GetParam(arg.param, "file");
  85. if (obj == null)
  86. {
  87. Trace.WriteLine("Parameter file not found");
  88. return false;
  89. }
  90. else
  91. source = (Parser.stStream)obj;
  92. }
  93. else if (arg.name == "dest")
  94. {
  95. obj = parser.GetParam(arg.param, "file", null, true);
  96. if (obj == null)
  97. destination = parser.NewStream(arg.param["file"], true);
  98. else
  99. destination = (Parser.stStream)obj;
  100. }
  101. else
  102. {
  103. Trace.WriteLine(string.Format("Incorrect option - source, dest, pointer ; get {0}", arg.name));
  104. return false;
  105. }
  106. }
  107. if (!Comp(source, destination))
  108. return false;
  109. return true;
  110. }
  111. #region Private methods
  112. /// <summary>
  113. /// Initialise the buffer
  114. /// </summary>
  115. /// <returns></returns>
  116. private static byte[] InitBuffer(int size = 0x1000)
  117. {
  118. byte[] buffer = new byte[size];
  119. int pos = 0;
  120. byte value = 0x00;
  121. for (int i = 0; i < 0x100; i++)
  122. {
  123. for (int j = 0; j < 13; j++)
  124. {
  125. buffer[pos++] = value;
  126. }
  127. value++;
  128. }
  129. value = 0x00;
  130. for (int i = 0; i < 0x100; i++)
  131. {
  132. buffer[pos++] = value++;
  133. }
  134. value = 0xFF;
  135. for (int i = 0; i < 0x100; i++)
  136. {
  137. buffer[pos++] = value--;
  138. }
  139. for (int i = 0; i < 0x80; i++)
  140. {
  141. buffer[pos++] = 0x00;
  142. }
  143. for (int i = 0; i < 0x80; i++)
  144. {
  145. buffer[pos++] = 0x20;
  146. }
  147. return buffer;
  148. }
  149. /// <summary>
  150. /// Find the greater LZ compression from a position
  151. /// </summary>
  152. /// <param name="a_bytes">Array of bytes where look for RLE compression</param>
  153. /// <param name="pos">Current position in the array</param>
  154. /// <returns></returns>
  155. private static st_param FindLZInBuffer(byte[] a_bytes, int pos, int size_buffer, int len_max)
  156. {
  157. st_param param;
  158. int dict = 0;
  159. int pos_result = 0;
  160. int len_result = 0;
  161. if (pos > 0x1000)
  162. dict = pos - 0xFFF;
  163. while (dict < pos)
  164. {
  165. int len = 0;
  166. while (pos + len < a_bytes.Length && a_bytes[dict + len] == a_bytes[pos + len] && (len < len_max))
  167. len++;
  168. if (len >= len_result)
  169. {
  170. pos_result = dict;
  171. len_result = len;
  172. }
  173. dict++;
  174. }
  175. param.length = len_result;
  176. param.offset = pos_result;
  177. return param;
  178. }
  179. /// <summary>
  180. /// Decompress a stream
  181. /// </summary>
  182. /// <param name="Source">Stream to decompress</param>
  183. /// <param name="Destination">Destination stream</param>
  184. /// <returns></returns>
  185. private static bool Decomp(Parser.stStream Source, Parser.stStream Destination)
  186. {
  187. int pos = 0xFEE;
  188. int curr_pos = 0;
  189. byte[] bytes = new byte[0x1000];
  190. byte one_byte;
  191. UInt16 two_bytes;
  192. LogTrace trace = LogTrace.INSTANCE;
  193. try
  194. {
  195. using (BinaryReader br = new BinaryReader(Source.file, Encoding.Default, true))
  196. {
  197. UInt32 size_in = br.ReadUInt32().ToBigEndian32();
  198. UInt32 size_out = br.ReadUInt32().ToBigEndian32();
  199. bytes = InitBuffer();
  200. if (trace.TSwitch.TraceVerbose)
  201. {
  202. using (BinaryWriter bw = new BinaryWriter(File.Open("buffer.bin", FileMode.Create)))
  203. {
  204. bw.Write(bytes);
  205. }
  206. }
  207. Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format("Size IN {0}\nSize OUT {1}", size_in, size_out));
  208. while (curr_pos < size_out)
  209. {
  210. byte header = br.ReadByte();
  211. Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format("header {0:X08} : {1:X02}", br.BaseStream.Position - 1, header));
  212. for (int i = 0; i < 8; i++)
  213. {
  214. if ((header & 1) == 1)
  215. {
  216. one_byte = br.ReadByte();
  217. Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format(" {0} - Ecrit {1:X08} : {2:X02}", i, Destination.file.Position, one_byte));
  218. Destination.file.WriteByte(one_byte);
  219. curr_pos++;
  220. bytes[pos] = one_byte;
  221. pos = (pos + 1) & 0xFFF;
  222. }
  223. else
  224. {
  225. two_bytes = br.ReadUInt16();
  226. int nb = ((two_bytes >> 8) & 0x0F) + 3;
  227. int pos_lz = ((two_bytes & 0xF000) >> 4) | (two_bytes & 0xFF);
  228. Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format(" {0} - LZ : {1:X04}", i, two_bytes));
  229. Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format(" nb : 0x{0:X02} ({1})", nb, nb));
  230. Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format(" Pos : 0x{0:X04} ({1})", pos_lz, pos_lz));
  231. Trace.WriteIf(trace.TSwitch.TraceVerbose, string.Format(" Ecrit {0:X08} : ", Destination.file.Position));
  232. for (int j = 0; j < nb; j++)
  233. {
  234. Destination.file.WriteByte(bytes[pos_lz]);
  235. curr_pos++;
  236. bytes[pos] = bytes[pos_lz];
  237. Trace.WriteIf(trace.TSwitch.TraceVerbose, string.Format("{0:X02} ", bytes[pos_lz]));
  238. pos = (pos + 1) & 0xFFF;
  239. pos_lz = (pos_lz + 1) & 0xFFF;
  240. }
  241. Trace.WriteLineIf(trace.TSwitch.TraceVerbose, "");
  242. }
  243. header >>= 1;
  244. if (curr_pos >= size_out)
  245. break;
  246. }
  247. Trace.WriteLineIf(trace.TSwitch.TraceVerbose, "");
  248. }
  249. }
  250. return true;
  251. }
  252. catch (Exception ex)
  253. {
  254. Trace.WriteLine(string.Format("(EE) {0}", ex.Message));
  255. return false;
  256. }
  257. }
  258. /// <summary>
  259. /// Compress a stream
  260. /// </summary>
  261. /// <param name="Source">Stream to compress</param>
  262. /// <param name="Destination">Destination stream</param>
  263. /// <returns></returns>
  264. private static bool Comp(Parser.stStream Source, Parser.stStream Destination)
  265. {
  266. st_param param_lz;
  267. int size_out = (int)Source.file.Length;
  268. int pos_temp = 0;
  269. int pos = 0xFEE;
  270. int curr_pos = pos;
  271. byte[] b_size_out = BitConverter.GetBytes(size_out.ToBigEndian32());
  272. byte[] temp = new byte[24];
  273. int buffer_size = 0x1000;
  274. LogTrace trace = LogTrace.INSTANCE;
  275. try
  276. {
  277. Source.file.Position = 0;
  278. Destination.file.Position = 0;
  279. Destination.file.Write(b_size_out, 0, 4);
  280. Destination.file.Write(b_size_out, 0, 4);
  281. byte[] bytes = InitBuffer(pos + size_out);
  282. Source.file.Read(bytes, pos, size_out);
  283. while (curr_pos < size_out + pos)
  284. {
  285. byte header = 0;
  286. for (int i = 0; i < 8; i++)
  287. {
  288. if (curr_pos >= size_out + pos)
  289. break;
  290. Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format("{0} - Pos : {1:X}", i, curr_pos - pos));
  291. param_lz = FindLZInBuffer(bytes, curr_pos, buffer_size, 0x12);
  292. Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format(" nb LZ : {0:000}", param_lz.length));
  293. if (param_lz.length < 3)
  294. {
  295. Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format(" -> Byte : {0:X02}", bytes[curr_pos]));
  296. temp[pos_temp++] = bytes[curr_pos];
  297. header |= (byte)(1 << i);
  298. curr_pos++;
  299. }
  300. else
  301. {
  302. Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format(" POS_LZ : {0:X04}", param_lz.offset));
  303. 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)));
  304. temp[pos_temp++] = (byte)(param_lz.offset & 0xFF);
  305. temp[pos_temp++] = (byte)(((param_lz.offset & 0xF00) >> 4) | ((param_lz.length - 3) & 0x0F));
  306. curr_pos += param_lz.length;
  307. }
  308. }
  309. Trace.WriteLineIf(trace.TSwitch.TraceVerbose, string.Format("Header : {0:X02}\n", header));
  310. Destination.file.WriteByte(header);
  311. Destination.file.Write(temp, 0, pos_temp);
  312. pos_temp = 0;
  313. }
  314. byte[] b_size_in = BitConverter.GetBytes((int)((Destination.file.Length - 8).ToBigEndian32()));
  315. Destination.file.Position = 0;
  316. Destination.file.Write(b_size_in, 0, 4);
  317. return true;
  318. }
  319. catch (Exception ex)
  320. {
  321. Trace.WriteLine(string.Format("(EE) {0}", ex.Message));
  322. return false;
  323. }
  324. }
  325. #endregion
  326. }
  327. }