1 /* MikMod sound library (c) 2003-2015 Raphael Assenat and others -
2 * see AUTHORS file for a complete list.
4 * This library is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Library General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 * StoneCracker S404 algorithm data decompression routine
22 * (c) 2006 Jouni 'Mr.Spiv' Korhonen. The code is in public domain.
24 * modified for xmp by Claudio Matsuoka, Jan 2010
25 * modified for libmikmod by O. Sezer -- May 2015
41 /*#include <assert.h>*/
43 #include "mikmod_internals.h"
46 extern int fprintf(FILE *, const char *, ...);
52 static UWORD readmem16b(UBYTE *m)
61 /* bit buffer for rolling data bit by bit from the compressed file */
64 /* bits left in the bit buffer */
67 /* compressed data source */
72 static int initGetb(struct bitstream *bs, UBYTE *src, ULONG src_length)
76 bs->src = (UWORD *) (src + src_length);
79 bs->left = readmem16b((UBYTE *)bs->src); /* bit counter */
81 if (bs->left & (~0xf))
82 fprintf(stderr, "Worked around an ancient stc bug\n");
84 /* mask off any corrupt bits */
88 /* get the first 16-bits of the compressed stream */
89 bs->word = readmem16b((UBYTE *)bs->src);
92 eff = readmem16b((UBYTE *)bs->src); /* efficiency */
98 /* get nbits from the compressed stream */
99 static int getb(struct bitstream *bs, int nbits)
101 bs->word &= 0x0000ffff;
103 /* If not enough bits in the bit buffer, get more */
104 if (bs->left < nbits) {
105 bs->word <<= bs->left;
106 /*assert((bs->word & 0x0000ffffU) == 0);*/
108 /* Check that we don't go out of bounds */
109 if (bs->orgsrc > (UBYTE *)bs->src) {
113 bs->word |= readmem16b((UBYTE *)bs->src);
117 bs->left = 16; /* 16 unused (and some used) bits left in the word */
120 /* Shift nbits off the word and return them */
123 return bs->word >> 16;
126 static int decompressS404(UBYTE *src, UBYTE *orgdst,
127 SLONG dst_length, SLONG src_length)
133 SLONG oLen = dst_length;
139 eff = initGetb(&bs, src, src_length);
156 } else if (w == 0x13e || w == 0x13f) {
184 n = w & 0x40 ? 3 : 2;
188 w = (w & 0x1f) << (eff - 5);
189 x = getb(&bs, eff - 5);
196 } else if (w & 0x30) {
216 } else if (w >= 0x140) {
218 n = ((w & 0x30) >> 4) + 4;
222 w = (w & 0x07) << (eff - 3);
223 x = getb(&bs, eff - 3);
230 } else if (w & 0x0c) {
250 } else if (w >= 0x120) {
252 n = ((w & 0x1e) >> 1) + 8;
312 w = (w & 0x3f) << (eff - 6);
313 x = getb(&bs, eff - 6);
320 } else if (w & 0x20) {
324 /* dist 33 -> 544; */
340 if (dst < orgdst || (dst + w + 1) >= (orgdst + dst_length))
350 BOOL S404_Unpack(MREADER *reader, void **out, long *outlen)
352 SLONG iLen, sLen, oLen, pLen;
353 UBYTE *src, *dst = NULL;
356 _mm_fseek(reader,0,SEEK_END);
357 iLen = _mm_ftell(reader);
358 if (iLen <= 16) return 0;
361 if (_mm_read_M_ULONG(reader) != 0x53343034) /* S404 */
364 sLen = _mm_read_M_SLONG(reader); /* Security length */
365 oLen = _mm_read_M_SLONG(reader); /* Depacked length */
366 pLen = _mm_read_M_SLONG(reader); /* Packed length */
368 fprintf(stderr,"S404: iLen= %d, sLen= %d, pLen= %d, oLen= %d\n",
369 iLen, sLen, pLen, oLen);
371 if (sLen < 0 || oLen <= 0 || pLen <= 0) return 0;
372 if (pLen + 16 >= iLen) return 0; /* sanity check */
374 if (!(src = (UBYTE*) MikMod_malloc(iLen - 16)))
376 if (!(dst = (UBYTE*) MikMod_malloc(oLen))) {
381 _mm_read_UBYTES(src, iLen - 16, reader);
382 err = decompressS404(src, dst, oLen, pLen);