lzo1x_c.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Command & Conquer *
  23. * *
  24. * $Archive:: /Commando/Code/wwlib/lzo1x_c.cpp $*
  25. * *
  26. * $Author:: Jani_p $*
  27. * *
  28. * $Modtime:: 6/28/00 10:13a $*
  29. * *
  30. * $Revision:: 2 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. /* $Header: /Commando/Code/wwlib/lzo1x_c.cpp 2 7/05/00 6:26p Jani_p $ */
  36. /* lzo1x_c.c -- standalone LZO1X-1 compressor
  37. This file is part of the LZO real-time data compression library.
  38. Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
  39. The LZO library is free software; you can redistribute it and/or
  40. modify it under the terms of the GNU Library General Public
  41. License as published by the Free Software Foundation; either
  42. version 2 of the License, or (at your option) any later version.
  43. The LZO library is distributed in the hope that it will be useful,
  44. but WITHOUT ANY WARRANTY; without even the implied warranty of
  45. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  46. Library General Public License for more details.
  47. You should have received a copy of the GNU Library General Public
  48. License along with the LZO library; see the file COPYING.LIB.
  49. If not, write to the Free Software Foundation, Inc.,
  50. 675 Mass Ave, Cambridge, MA 02139, USA.
  51. Markus F.X.J. Oberhumer
  52. [email protected]
  53. */
  54. #include "always.h"
  55. #include "lzo1x.h"
  56. #include "lzo_conf.h"
  57. #include "wwdebug.h"
  58. #include <assert.h>
  59. #if !defined(LZO1X) && !defined(LZO1Y)
  60. # define LZO1X
  61. #endif
  62. /***********************************************************************
  63. //
  64. ************************************************************************/
  65. #define M1_MAX_OFFSET 0x0400
  66. #if defined(LZO1X)
  67. #define M2_MAX_OFFSET 0x0800
  68. #elif defined(LZO1Y)
  69. #define M2_MAX_OFFSET 0x0400
  70. #endif
  71. #define M3_MAX_OFFSET 0x4000
  72. #define M4_MAX_OFFSET 0xbfff
  73. #define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET)
  74. #define M1_MARKER 0
  75. #define M2_MARKER 64
  76. #define M3_MARKER 32
  77. #define M4_MARKER 16
  78. #define _DV2(p,shift1,shift2) \
  79. (((( (lzo_uint)(p[2]) << shift1) ^ p[1]) << shift2) ^ p[0])
  80. #define DVAL_NEXT(dv,p) \
  81. dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_uint)(p[2]) << (2*5)))
  82. #define _DV(p,shift) _DV2(p,shift,shift)
  83. #define DVAL_FIRST(dv,p) dv = _DV((p),5)
  84. #define _DINDEX(dv,p) ((40799u * (dv)) >> 5)
  85. #define DINDEX(dv,p) (((_DINDEX(dv,p)) & 0x3fff) << 0)
  86. #define UPDATE_D(dict,cycle,dv,p) dict[ DINDEX(dv,p) ] = (p)
  87. #define UPDATE_I(dict,cycle,index,p) dict[index] = (p)
  88. /***********************************************************************
  89. // compress a block of data.
  90. ************************************************************************/
  91. static int do_compress(const lzo_byte * in, lzo_uint in_len,
  92. lzo_byte *out, lzo_uint *out_len,
  93. lzo_voidp wrkmem )
  94. {
  95. register const lzo_byte *ip;
  96. lzo_uint dv;
  97. lzo_byte *op;
  98. const lzo_byte * const in_end = in + in_len;
  99. const lzo_byte * const ip_end = in + in_len - 9 - 4;
  100. const lzo_byte *ii;
  101. const lzo_bytepp const dict = (const lzo_bytepp) wrkmem;
  102. op = out;
  103. ip = in;
  104. ii = ip;
  105. DVAL_FIRST(dv,ip); UPDATE_D(dict,cycle,dv,ip); ip++;
  106. DVAL_NEXT(dv,ip); UPDATE_D(dict,cycle,dv,ip); ip++;
  107. DVAL_NEXT(dv,ip); UPDATE_D(dict,cycle,dv,ip); ip++;
  108. DVAL_NEXT(dv,ip); UPDATE_D(dict,cycle,dv,ip); ip++;
  109. for (;;) {
  110. register const lzo_byte *m_pos;
  111. lzo_uint m_len;
  112. lzo_ptrdiff_t m_off;
  113. lzo_uint lit;
  114. lzo_uint dindex = DINDEX(dv,ip);
  115. m_pos = dict[dindex];
  116. UPDATE_I(dict,cycle,dindex,ip);
  117. if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) {
  118. }
  119. #if defined(LZO_UNALIGNED_OK_2)
  120. else
  121. if (* (unsigned short *) m_pos != * (unsigned short *) ip)
  122. #else
  123. else
  124. if (m_pos[0] != ip[0] || m_pos[1] != ip[1])
  125. #endif
  126. {
  127. } else {
  128. if (m_pos[2] == ip[2]) {
  129. lit = ip - ii;
  130. m_pos += 3;
  131. if (m_off <= M2_MAX_OFFSET)
  132. goto match;
  133. /* better compression, but slower */
  134. if (lit == 3) {
  135. assert(op - 2 > out); op[-2] |= LZO_BYTE(3);
  136. *op++ = *ii++; *op++ = *ii++; *op++ = *ii++;
  137. goto code_match;
  138. }
  139. if (*m_pos == ip[3]) {
  140. goto match;
  141. }
  142. } else {
  143. /* still need a better way for finding M1 matches */
  144. }
  145. }
  146. /* a literal */
  147. ++ip;
  148. if (ip >= ip_end) {
  149. break;
  150. }
  151. DVAL_NEXT(dv,ip);
  152. continue;
  153. /* a match */
  154. match:
  155. /* store current literal run */
  156. if (lit > 0) {
  157. register lzo_uint t = lit;
  158. if (t <= 3) {
  159. assert(op - 2 > out);
  160. op[-2] |= LZO_BYTE(t);
  161. } else {
  162. if (t <= 18) {
  163. *op++ = LZO_BYTE(t - 3);
  164. } else {
  165. register lzo_uint tt = t - 18;
  166. *op++ = 0;
  167. while (tt > 255) {
  168. tt -= 255;
  169. *op++ = 0;
  170. }
  171. assert(tt > 0);
  172. *op++ = LZO_BYTE(tt);
  173. }
  174. }
  175. do {
  176. *op++ = *ii++;
  177. } while (--t > 0);
  178. }
  179. /* code the match */
  180. code_match:
  181. assert(ii == ip);
  182. ip += 3;
  183. if (*m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++ ||
  184. *m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++)
  185. {
  186. --ip;
  187. m_len = ip - ii;
  188. assert(m_len >= 3); assert(m_len <= 8);
  189. if (m_off <= M2_MAX_OFFSET) {
  190. m_off -= 1;
  191. *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2));
  192. *op++ = LZO_BYTE(m_off >> 3);
  193. } else {
  194. if (m_off <= M3_MAX_OFFSET) {
  195. m_off -= 1;
  196. *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
  197. goto m3_m4_offset;
  198. } else {
  199. m_off -= 0x4000;
  200. assert(m_off > 0); assert(m_off <= 0x7fff);
  201. *op++ = LZO_BYTE(M4_MARKER |
  202. ((m_off & 0x4000) >> 11) | (m_len - 2));
  203. goto m3_m4_offset;
  204. }
  205. }
  206. } else {
  207. const lzo_byte *end;
  208. end = in_end;
  209. while (ip < end && *m_pos == *ip) {
  210. m_pos++;
  211. ip++;
  212. }
  213. m_len = (ip - ii);
  214. assert(m_len >= 3);
  215. if (m_off <= M3_MAX_OFFSET) {
  216. m_off -= 1;
  217. if (m_len <= 33) {
  218. *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
  219. } else {
  220. m_len -= 33;
  221. *op++ = M3_MARKER | 0;
  222. goto m3_m4_len;
  223. }
  224. } else {
  225. m_off -= 0x4000;
  226. assert(m_off > 0); assert(m_off <= 0x7fff);
  227. if (m_len <= 9) {
  228. *op++ = LZO_BYTE(M4_MARKER |
  229. ((m_off & 0x4000) >> 11) | (m_len - 2));
  230. } else {
  231. m_len -= 9;
  232. *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11));
  233. m3_m4_len:
  234. while (m_len > 255) {
  235. m_len -= 255;
  236. *op++ = 0;
  237. }
  238. assert(m_len > 0);
  239. *op++ = LZO_BYTE(m_len);
  240. }
  241. }
  242. m3_m4_offset:
  243. *op++ = LZO_BYTE((m_off & 63) << 2);
  244. *op++ = LZO_BYTE(m_off >> 6);
  245. }
  246. ii = ip;
  247. if (ip >= ip_end) {
  248. break;
  249. }
  250. DVAL_FIRST(dv,ip);
  251. }
  252. /* store final literal run */
  253. if (in_end - ii > 0) {
  254. register lzo_uint t = in_end - ii;
  255. if (op == out && t <= 238) {
  256. *op++ = LZO_BYTE(17 + t);
  257. } else {
  258. if (t <= 3) {
  259. op[-2] |= LZO_BYTE(t);
  260. } else {
  261. if (t <= 18) {
  262. *op++ = LZO_BYTE(t - 3);
  263. } else {
  264. register lzo_uint tt = t - 18;
  265. *op++ = 0;
  266. while (tt > 255) {
  267. tt -= 255;
  268. *op++ = 0;
  269. }
  270. assert(tt > 0);
  271. *op++ = LZO_BYTE(tt);
  272. }
  273. }
  274. }
  275. do {
  276. *op++ = *ii++;
  277. } while (--t > 0);
  278. }
  279. *out_len = op - out;
  280. return LZO_E_OK;
  281. }
  282. /***********************************************************************
  283. // public entry point
  284. ************************************************************************/
  285. int lzo1x_1_compress ( const lzo_byte * in, lzo_uint in_len,
  286. lzo_byte * out, lzo_uint *out_len,
  287. lzo_voidp wrkmem )
  288. {
  289. lzo_byte *op = out;
  290. int r = LZO_E_OK;
  291. if (in_len <= 0) {
  292. *out_len = 0;
  293. } else {
  294. if (in_len <= 9 + 4) {
  295. *op++ = LZO_BYTE(17 + in_len);
  296. do *op++ = *in++; while (--in_len > 0);
  297. *out_len = op - out;
  298. } else {
  299. r = do_compress(in,in_len,out,out_len,wrkmem);
  300. }
  301. }
  302. if (r == LZO_E_OK) {
  303. op = out + *out_len;
  304. *op++ = M4_MARKER | 1;
  305. *op++ = 0;
  306. *op = 0;
  307. *out_len += 3;
  308. }
  309. return r;
  310. }
  311. /*
  312. vi:ts=4
  313. */