PageRenderTime 56ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/BSNES/bsnes/nall/inflate.hpp

http://github.com/OpenEmu/OpenEmu
C++ Header | 358 lines | 289 code | 62 blank | 7 comment | 86 complexity | 0a77dfe4f382f485c46dda156731cb68 MD5 | raw file
Possible License(s): Unlicense, LGPL-2.1
  1. #ifndef NALL_INFLATE_HPP
  2. #define NALL_INFLATE_HPP
  3. #include <setjmp.h>
  4. namespace nall {
  5. namespace puff {
  6. inline int puff(
  7. unsigned char *dest, unsigned long *destlen,
  8. unsigned char *source, unsigned long *sourcelen
  9. );
  10. }
  11. inline bool inflate(
  12. uint8_t *target, unsigned targetLength,
  13. const uint8_t *source, unsigned sourceLength
  14. ) {
  15. unsigned long tl = targetLength, sl = sourceLength;
  16. int result = puff::puff((unsigned char*)target, &tl, (unsigned char*)source, &sl);
  17. return result == 0;
  18. }
  19. namespace puff {
  20. //zlib/contrib/puff.c
  21. //version 2.1*
  22. //author: Mark Adler
  23. //license: zlib
  24. //ported by: byuu
  25. //* I have corrected a bug in fixed(), where it was accessing uninitialized
  26. // memory: calling construct() with lencode prior to initializing lencode.count
  27. enum {
  28. MAXBITS = 15,
  29. MAXLCODES = 286,
  30. MAXDCODES = 30,
  31. FIXLCODES = 288,
  32. MAXCODES = MAXLCODES + MAXDCODES,
  33. };
  34. struct state {
  35. unsigned char *out;
  36. unsigned long outlen;
  37. unsigned long outcnt;
  38. unsigned char *in;
  39. unsigned long inlen;
  40. unsigned long incnt;
  41. int bitbuf;
  42. int bitcnt;
  43. jmp_buf env;
  44. };
  45. struct huffman {
  46. short *count;
  47. short *symbol;
  48. };
  49. inline int bits(state *s, int need) {
  50. long val;
  51. val = s->bitbuf;
  52. while(s->bitcnt < need) {
  53. if(s->incnt == s->inlen) longjmp(s->env, 1);
  54. val |= (long)(s->in[s->incnt++]) << s->bitcnt;
  55. s->bitcnt += 8;
  56. }
  57. s->bitbuf = (int)(val >> need);
  58. s->bitcnt -= need;
  59. return (int)(val & ((1L << need) - 1));
  60. }
  61. inline int stored(state *s) {
  62. unsigned len;
  63. s->bitbuf = 0;
  64. s->bitcnt = 0;
  65. if(s->incnt + 4 > s->inlen) return 2;
  66. len = s->in[s->incnt++];
  67. len |= s->in[s->incnt++] << 8;
  68. if(s->in[s->incnt++] != (~len & 0xff) ||
  69. s->in[s->incnt++] != ((~len >> 8) & 0xff)
  70. ) return 2;
  71. if(s->incnt + len > s->inlen) return 2;
  72. if(s->out != 0) {
  73. if(s->outcnt + len > s->outlen) return 1;
  74. while(len--) s->out[s->outcnt++] = s->in[s->incnt++];
  75. } else {
  76. s->outcnt += len;
  77. s->incnt += len;
  78. }
  79. return 0;
  80. }
  81. inline int decode(state *s, huffman *h) {
  82. int len, code, first, count, index, bitbuf, left;
  83. short *next;
  84. bitbuf = s->bitbuf;
  85. left = s->bitcnt;
  86. code = first = index = 0;
  87. len = 1;
  88. next = h->count + 1;
  89. while(true) {
  90. while(left--) {
  91. code |= bitbuf & 1;
  92. bitbuf >>= 1;
  93. count = *next++;
  94. if(code - count < first) {
  95. s->bitbuf = bitbuf;
  96. s->bitcnt = (s->bitcnt - len) & 7;
  97. return h->symbol[index + (code - first)];
  98. }
  99. index += count;
  100. first += count;
  101. first <<= 1;
  102. code <<= 1;
  103. len++;
  104. }
  105. left = (MAXBITS + 1) - len;
  106. if(left == 0) break;
  107. if(s->incnt == s->inlen) longjmp(s->env, 1);
  108. bitbuf = s->in[s->incnt++];
  109. if(left > 8) left = 8;
  110. }
  111. return -10;
  112. }
  113. inline int construct(huffman *h, short *length, int n) {
  114. int symbol, len, left;
  115. short offs[MAXBITS + 1];
  116. for(len = 0; len <= MAXBITS; len++) h->count[len] = 0;
  117. for(symbol = 0; symbol < n; symbol++) h->count[length[symbol]]++;
  118. if(h->count[0] == n) return 0;
  119. left = 1;
  120. for(len = 1; len <= MAXBITS; len++) {
  121. left <<= 1;
  122. left -= h->count[len];
  123. if(left < 0) return left;
  124. }
  125. offs[1] = 0;
  126. for(len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + h->count[len];
  127. for(symbol = 0; symbol < n; symbol++) {
  128. if(length[symbol] != 0) h->symbol[offs[length[symbol]]++] = symbol;
  129. }
  130. return left;
  131. }
  132. inline int codes(state *s, huffman *lencode, huffman *distcode) {
  133. int symbol, len;
  134. unsigned dist;
  135. static const short lens[29] = {
  136. 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
  137. 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
  138. };
  139. static const short lext[29] = {
  140. 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
  141. 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
  142. };
  143. static const short dists[30] = {
  144. 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
  145. 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
  146. 8193, 12289, 16385, 24577
  147. };
  148. static const short dext[30] = {
  149. 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
  150. 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
  151. 12, 12, 13, 13
  152. };
  153. do {
  154. symbol = decode(s, lencode);
  155. if(symbol < 0) return symbol;
  156. if(symbol < 256) {
  157. if(s->out != 0) {
  158. if(s->outcnt == s->outlen) return 1;
  159. s->out[s->outcnt] = symbol;
  160. }
  161. s->outcnt++;
  162. } else if(symbol > 256) {
  163. symbol -= 257;
  164. if(symbol >= 29) return -10;
  165. len = lens[symbol] + bits(s, lext[symbol]);
  166. symbol = decode(s, distcode);
  167. if(symbol < 0) return symbol;
  168. dist = dists[symbol] + bits(s, dext[symbol]);
  169. #ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOO_FAR
  170. if(dist > s->outcnt) return -11;
  171. #endif
  172. if(s->out != 0) {
  173. if(s->outcnt + len > s->outlen) return 1;
  174. while(len--) {
  175. s->out[s->outcnt] =
  176. #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOO_FAR
  177. dist > s->outcnt ? 0 :
  178. #endif
  179. s->out[s->outcnt - dist];
  180. s->outcnt++;
  181. }
  182. } else {
  183. s->outcnt += len;
  184. }
  185. }
  186. } while(symbol != 256);
  187. return 0;
  188. }
  189. inline int fixed(state *s) {
  190. static int virgin = 1;
  191. static short lencnt[MAXBITS + 1], lensym[FIXLCODES];
  192. static short distcnt[MAXBITS + 1], distsym[MAXDCODES];
  193. static huffman lencode, distcode;
  194. if(virgin) {
  195. int symbol = 0;
  196. short lengths[FIXLCODES];
  197. lencode.count = lencnt;
  198. lencode.symbol = lensym;
  199. distcode.count = distcnt;
  200. distcode.symbol = distsym;
  201. for(; symbol < 144; symbol++) lengths[symbol] = 8;
  202. for(; symbol < 256; symbol++) lengths[symbol] = 9;
  203. for(; symbol < 280; symbol++) lengths[symbol] = 7;
  204. for(; symbol < FIXLCODES; symbol++) lengths[symbol] = 8;
  205. construct(&lencode, lengths, FIXLCODES);
  206. for(symbol = 0; symbol < MAXDCODES; symbol++) lengths[symbol] = 5;
  207. construct(&distcode, lengths, MAXDCODES);
  208. virgin = 0;
  209. }
  210. return codes(s, &lencode, &distcode);
  211. }
  212. inline int dynamic(state *s) {
  213. int nlen, ndist, ncode, index, err;
  214. short lengths[MAXCODES];
  215. short lencnt[MAXBITS + 1], lensym[MAXLCODES];
  216. short distcnt[MAXBITS + 1], distsym[MAXDCODES];
  217. huffman lencode, distcode;
  218. static const short order[19] = {
  219. 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
  220. };
  221. lencode.count = lencnt;
  222. lencode.symbol = lensym;
  223. distcode.count = distcnt;
  224. distcode.symbol = distsym;
  225. nlen = bits(s, 5) + 257;
  226. ndist = bits(s, 5) + 1;
  227. ncode = bits(s, 4) + 4;
  228. if(nlen > MAXLCODES || ndist > MAXDCODES) return -3;
  229. for(index = 0; index < ncode; index++) lengths[order[index]] = bits(s, 3);
  230. for(; index < 19; index++) lengths[order[index]] = 0;
  231. err = construct(&lencode, lengths, 19);
  232. if(err != 0) return -4;
  233. index = 0;
  234. while(index < nlen + ndist) {
  235. int symbol, len;
  236. symbol = decode(s, &lencode);
  237. if(symbol < 16) {
  238. lengths[index++] = symbol;
  239. } else {
  240. len = 0;
  241. if(symbol == 16) {
  242. if(index == 0) return -5;
  243. len = lengths[index - 1];
  244. symbol = 3 + bits(s, 2);
  245. } else if(symbol == 17) {
  246. symbol = 3 + bits(s, 3);
  247. } else {
  248. symbol = 11 + bits(s, 7);
  249. }
  250. if(index + symbol > nlen + ndist) return -6;
  251. while(symbol--) lengths[index++] = len;
  252. }
  253. }
  254. if(lengths[256] == 0) return -9;
  255. err = construct(&lencode, lengths, nlen);
  256. if(err < 0 || (err > 0 && nlen - lencode.count[0] != 1)) return -7;
  257. err = construct(&distcode, lengths + nlen, ndist);
  258. if(err < 0 || (err > 0 && ndist - distcode.count[0] != 1)) return -8;
  259. return codes(s, &lencode, &distcode);
  260. }
  261. inline int puff(
  262. unsigned char *dest, unsigned long *destlen,
  263. unsigned char *source, unsigned long *sourcelen
  264. ) {
  265. state s;
  266. int last, type, err;
  267. s.out = dest;
  268. s.outlen = *destlen;
  269. s.outcnt = 0;
  270. s.in = source;
  271. s.inlen = *sourcelen;
  272. s.incnt = 0;
  273. s.bitbuf = 0;
  274. s.bitcnt = 0;
  275. if(setjmp(s.env) != 0) {
  276. err = 2;
  277. } else {
  278. do {
  279. last = bits(&s, 1);
  280. type = bits(&s, 2);
  281. err = type == 0 ? stored(&s)
  282. : type == 1 ? fixed(&s)
  283. : type == 2 ? dynamic(&s)
  284. : -1;
  285. if(err != 0) break;
  286. } while(!last);
  287. }
  288. if(err <= 0) {
  289. *destlen = s.outcnt;
  290. *sourcelen = s.incnt;
  291. }
  292. return err;
  293. }
  294. }
  295. }
  296. #endif