LZO1X_D.CPP 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. //
  2. // Copyright 2020 Electronic Arts Inc.
  3. //
  4. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
  5. // software: you can redistribute it and/or modify it under the terms of
  6. // the GNU General Public License as published by the Free Software Foundation,
  7. // either version 3 of the License, or (at your option) any later version.
  8. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  9. // in the hope that it will be useful, but with permitted additional restrictions
  10. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. // distributed with this program. You should have received a copy of the
  12. // GNU General Public License along with permitted additional restrictions
  13. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  14. /* lzo1x_d.c -- standalone LZO1X decompressor
  15. This file is part of the LZO real-time data compression library.
  16. Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
  17. The LZO library is free software; you can redistribute it and/or
  18. modify it under the terms of the GNU Library General Public
  19. License as published by the Free Software Foundation; either
  20. version 2 of the License, or (at your option) any later version.
  21. The LZO library is distributed in the hope that it will be useful,
  22. but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  24. Library General Public License for more details.
  25. You should have received a copy of the GNU Library General Public
  26. License along with the LZO library; see the file COPYING.LIB.
  27. If not, write to the Free Software Foundation, Inc.,
  28. 675 Mass Ave, Cambridge, MA 02139, USA.
  29. Markus F.X.J. Oberhumer
  30. [email protected]
  31. */
  32. #include "lzo1x.h"
  33. #ifndef NDEBUG
  34. #define NDEBUG
  35. #endif
  36. #include <assert.h>
  37. #if !defined(LZO1X) && !defined(LZO1Y)
  38. # define LZO1X
  39. #endif
  40. #if 1
  41. # define TEST_IP 1
  42. #else
  43. # define TEST_IP (ip < ip_end)
  44. #endif
  45. /***********************************************************************
  46. // decompress a block of data.
  47. ************************************************************************/
  48. int lzo1x_decompress ( const lzo_byte *in , lzo_uint in_len,
  49. lzo_byte *out, lzo_uint *out_len,
  50. lzo_voidp )
  51. {
  52. register lzo_byte *op;
  53. register const lzo_byte *ip;
  54. register lzo_uint t;
  55. register const lzo_byte *m_pos;
  56. const lzo_byte * const ip_end = in + in_len;
  57. *out_len = 0;
  58. op = out;
  59. ip = in;
  60. if (*ip > 17)
  61. {
  62. t = *ip++ - 17;
  63. goto first_literal_run;
  64. }
  65. while (TEST_IP)
  66. {
  67. t = *ip++;
  68. if (t >= 16)
  69. goto match;
  70. /* a literal run */
  71. if (t == 0)
  72. {
  73. t = 15;
  74. while (*ip == 0)
  75. t += 255, ip++;
  76. t += *ip++;
  77. }
  78. /* copy literals */
  79. *op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
  80. first_literal_run:
  81. do *op++ = *ip++; while (--t > 0);
  82. t = *ip++;
  83. if (t >= 16)
  84. goto match;
  85. #if defined(LZO1X)
  86. m_pos = op - 1 - 0x800;
  87. #elif defined(LZO1Y)
  88. m_pos = op - 1 - 0x400;
  89. #endif
  90. m_pos -= t >> 2;
  91. m_pos -= *ip++ << 2;
  92. *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos++;
  93. goto match_done;
  94. /* handle matches */
  95. while (TEST_IP)
  96. {
  97. if (t < 16) /* a M1 match */
  98. {
  99. m_pos = op - 1;
  100. m_pos -= t >> 2;
  101. m_pos -= *ip++ << 2;
  102. *op++ = *m_pos++; *op++ = *m_pos++;
  103. }
  104. else
  105. {
  106. match:
  107. if (t >= 64) /* a M2 match */
  108. {
  109. m_pos = op - 1;
  110. #if defined(LZO1X)
  111. m_pos -= (t >> 2) & 7;
  112. m_pos -= *ip++ << 3;
  113. t = (t >> 5) - 1;
  114. #elif defined(LZO1Y)
  115. m_pos -= (t >> 2) & 3;
  116. m_pos -= *ip++ << 2;
  117. t = (t >> 4) - 3;
  118. #endif
  119. }
  120. else if (t >= 32) /* a M3 match */
  121. {
  122. t &= 31;
  123. if (t == 0)
  124. {
  125. t = 31;
  126. while (*ip == 0)
  127. t += 255, ip++;
  128. t += *ip++;
  129. }
  130. m_pos = op - 1;
  131. m_pos -= *ip++ >> 2;
  132. m_pos -= *ip++ << 6;
  133. }
  134. else /* a M4 match */
  135. {
  136. m_pos = op;
  137. m_pos -= (t & 8) << 11;
  138. t &= 7;
  139. if (t == 0)
  140. {
  141. t = 7;
  142. while (*ip == 0)
  143. t += 255, ip++;
  144. t += *ip++;
  145. }
  146. m_pos -= *ip++ >> 2;
  147. m_pos -= *ip++ << 6;
  148. if (m_pos == op)
  149. goto eof_found;
  150. m_pos -= 0x4000;
  151. }
  152. *op++ = *m_pos++; *op++ = *m_pos++;
  153. do *op++ = *m_pos++; while (--t > 0);
  154. }
  155. match_done:
  156. t = ip[-2] & 3;
  157. if (t == 0)
  158. break;
  159. /* copy literals */
  160. do *op++ = *ip++; while (--t > 0);
  161. t = *ip++;
  162. }
  163. }
  164. /* ip == ip_end and no EOF code was found */
  165. //Unreachable - ST 9/5/96 5:07PM
  166. //*out_len = op - out;
  167. //return (ip == ip_end ? LZO_E_EOF_NOT_FOUND : LZO_E_ERROR);
  168. eof_found:
  169. assert(t == 1);
  170. *out_len = op - out;
  171. return (ip == ip_end ? LZO_E_OK : LZO_E_ERROR);
  172. }
  173. /*
  174. vi:ts=4
  175. */