summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/modplug/mmcmp.cpp
Unidiff
Diffstat (limited to 'core/multimedia/opieplayer/modplug/mmcmp.cpp') (more/less context) (show whitespace changes)
-rw-r--r--core/multimedia/opieplayer/modplug/mmcmp.cpp409
1 files changed, 409 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/modplug/mmcmp.cpp b/core/multimedia/opieplayer/modplug/mmcmp.cpp
new file mode 100644
index 0000000..8c32eb2
--- a/dev/null
+++ b/core/multimedia/opieplayer/modplug/mmcmp.cpp
@@ -0,0 +1,409 @@
1/*
2 * This program is free software; you can redistribute it and modify it
3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation; either version 2 of the license or (at your
5 * option) any later version.
6 *
7 * Authors: Olivier Lapicque <olivierl@jps.net>
8*/
9
10#include "stdafx.h"
11#include "sndfile.h"
12
13BOOL PP20_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength);
14
15typedef struct MMCMPFILEHEADER
16{
17 DWORD id_ziRC;// "ziRC"
18 DWORD id_ONia;// "ONia"
19 WORD hdrsize;
20} Q_PACKED MMCMPFILEHEADER, *LPMMCMPFILEHEADER;
21
22typedef struct MMCMPHEADER
23{
24 WORD version;
25 WORD nblocks;
26 DWORD filesize;
27 DWORD blktable;
28 BYTE glb_comp;
29 BYTE fmt_comp;
30} Q_PACKED MMCMPHEADER, *LPMMCMPHEADER;
31
32typedef struct MMCMPBLOCK
33{
34 DWORD unpk_size;
35 DWORD pk_size;
36 DWORD xor_chk;
37 WORD sub_blk;
38 WORD flags;
39 WORD tt_entries;
40 WORD num_bits;
41} Q_PACKED MMCMPBLOCK, *LPMMCMPBLOCK;
42
43typedef struct MMCMPSUBBLOCK
44{
45 DWORD unpk_pos;
46 DWORD unpk_size;
47} Q_PACKED MMCMPSUBBLOCK, *LPMMCMPSUBBLOCK;
48
49 #define MMCMP_COMP 0x0001
50 #define MMCMP_DELTA 0x0002
51 #define MMCMP_16BIT 0x0004
52 #define MMCMP_STEREO0x0100
53 #define MMCMP_ABS16 0x0200
54 #define MMCMP_ENDIAN0x0400
55
56typedef struct MMCMPBITBUFFER
57{
58 UINT bitcount;
59 DWORD bitbuffer;
60 LPCBYTE pSrc;
61 LPCBYTE pEnd;
62
63 DWORD GetBits(UINT nBits);
64} Q_PACKED MMCMPBITBUFFER;
65
66
67DWORD MMCMPBITBUFFER::GetBits(UINT nBits)
68//---------------------------------------
69{
70 DWORD d;
71 if (!nBits) return 0;
72 while (bitcount < 24)
73 {
74 bitbuffer |= ((pSrc < pEnd) ? *pSrc++ : 0) << bitcount;
75 bitcount += 8;
76 }
77 d = bitbuffer & ((1 << nBits) - 1);
78 bitbuffer >>= nBits;
79 bitcount -= nBits;
80 return d;
81}
82
83//#define MMCMP_LOG
84
85#ifdef MMCMP_LOG
86extern void Log(LPCSTR s, ...);
87#endif
88
89const DWORD MMCMP8BitCommands[8] =
90{
91 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C,0x78, 0xF8
92};
93
94const UINT MMCMP8BitFetch[8] =
95{
96 3, 3, 3, 3, 2, 1, 0, 0
97};
98
99const DWORD MMCMP16BitCommands[16] =
100{
101 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C,0x78, 0xF0,
102 0x1F0, 0x3F0, 0x7F0, 0xFF0, 0x1FF0, 0x3FF0, 0x7FF0, 0xFFF0
103};
104
105const UINT MMCMP16BitFetch[16] =
106{
107 4, 4, 4, 4, 3, 2, 1, 0,
108 0, 0, 0, 0, 0, 0, 0, 0
109};
110
111
112BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength)
113//---------------------------------------------------------
114{
115 DWORD dwMemLength = *pdwMemLength;
116 LPCBYTE lpMemFile = *ppMemFile;
117 LPBYTE pBuffer;
118 LPMMCMPFILEHEADER pmfh = (LPMMCMPFILEHEADER)(lpMemFile);
119 LPMMCMPHEADER pmmh = (LPMMCMPHEADER)(lpMemFile+10);
120 LPDWORD pblk_table;
121 DWORD dwFileSize;
122
123 if (PP20_Unpack(ppMemFile, pdwMemLength))
124 {
125 return TRUE;
126 }
127 if ((dwMemLength < 256) || (!pmfh) || (pmfh->id_ziRC != 0x4352697A) || (pmfh->id_ONia != 0x61694e4f) || (pmfh->hdrsize < 14)
128 || (!pmmh->nblocks) || (pmmh->filesize < 16) || (pmmh->filesize > 0x8000000)
129 || (pmmh->blktable >= dwMemLength) || (pmmh->blktable + 4*pmmh->nblocks > dwMemLength)) return FALSE;
130 dwFileSize = pmmh->filesize;
131 if ((pBuffer = (LPBYTE)GlobalAllocPtr(GHND, (dwFileSize + 31) & ~15)) == NULL) return FALSE;
132 pblk_table = (LPDWORD)(lpMemFile+pmmh->blktable);
133 for (UINT nBlock=0; nBlock<pmmh->nblocks; nBlock++)
134 {
135 DWORD dwMemPos = pblk_table[nBlock];
136 LPMMCMPBLOCK pblk = (LPMMCMPBLOCK)(lpMemFile+dwMemPos);
137 LPMMCMPSUBBLOCK psubblk = (LPMMCMPSUBBLOCK)(lpMemFile+dwMemPos+20);
138
139 if ((dwMemPos + 20 >= dwMemLength) || (dwMemPos + 20 + pblk->sub_blk*8 >= dwMemLength)) break;
140 dwMemPos += 20 + pblk->sub_blk*8;
141#ifdef MMCMP_LOG
142 Log("block %d: flags=%04X sub_blocks=%d", nBlock, (UINT)pblk->flags, (UINT)pblk->sub_blk);
143 Log(" pksize=%d unpksize=%d", pblk->pk_size, pblk->unpk_size);
144 Log(" tt_entries=%d num_bits=%d\n", pblk->tt_entries, pblk->num_bits);
145#endif
146 // Data is not packed
147 if (!(pblk->flags & MMCMP_COMP))
148 {
149 for (UINT i=0; i<pblk->sub_blk; i++)
150 {
151 if ((psubblk->unpk_pos > dwFileSize) || (psubblk->unpk_pos + psubblk->unpk_size > dwFileSize)) break;
152#ifdef MMCMP_LOG
153 Log(" Unpacked sub-block %d: offset %d, size=%d\n", i, psubblk->unpk_pos, psubblk->unpk_size);
154#endif
155 memcpy(pBuffer+psubblk->unpk_pos, lpMemFile+dwMemPos, psubblk->unpk_size);
156 dwMemPos += psubblk->unpk_size;
157 psubblk++;
158 }
159 } else
160 // Data is 16-bit packed
161 if (pblk->flags & MMCMP_16BIT)
162 {
163 MMCMPBITBUFFER bb;
164 LPWORD pDest = (LPWORD)(pBuffer + psubblk->unpk_pos);
165 DWORD dwSize = psubblk->unpk_size >> 1;
166 DWORD dwPos = 0;
167 UINT numbits = pblk->num_bits;
168 UINT subblk = 0, oldval = 0;
169
170#ifdef MMCMP_LOG
171 Log(" 16-bit block: pos=%d size=%d ", psubblk->unpk_pos, psubblk->unpk_size);
172 if (pblk->flags & MMCMP_DELTA) Log("DELTA ");
173 if (pblk->flags & MMCMP_ABS16) Log("ABS16 ");
174 Log("\n");
175#endif
176 bb.bitcount = 0;
177 bb.bitbuffer = 0;
178 bb.pSrc = lpMemFile+dwMemPos+pblk->tt_entries;
179 bb.pEnd = lpMemFile+dwMemPos+pblk->pk_size;
180 while (subblk < pblk->sub_blk)
181 {
182 UINT newval = 0x10000;
183 DWORD d = bb.GetBits(numbits+1);
184
185 if (d >= MMCMP16BitCommands[numbits])
186 {
187 UINT nFetch = MMCMP16BitFetch[numbits];
188 UINT newbits = bb.GetBits(nFetch) + ((d - MMCMP16BitCommands[numbits]) << nFetch);
189 if (newbits != numbits)
190 {
191 numbits = newbits & 0x0F;
192 } else
193 {
194 if ((d = bb.GetBits(4)) == 0x0F)
195 {
196 if (bb.GetBits(1)) break;
197 newval = 0xFFFF;
198 } else
199 {
200 newval = 0xFFF0 + d;
201 }
202 }
203 } else
204 {
205 newval = d;
206 }
207 if (newval < 0x10000)
208 {
209 newval = (newval & 1) ? (UINT)(-(LONG)((newval+1) >> 1)) : (UINT)(newval >> 1);
210 if (pblk->flags & MMCMP_DELTA)
211 {
212 newval += oldval;
213 oldval = newval;
214 } else
215 if (!(pblk->flags & MMCMP_ABS16))
216 {
217 newval ^= 0x8000;
218 }
219 pDest[dwPos++] = (WORD)newval;
220 }
221 if (dwPos >= dwSize)
222 {
223 subblk++;
224 dwPos = 0;
225 dwSize = psubblk[subblk].unpk_size >> 1;
226 pDest = (LPWORD)(pBuffer + psubblk[subblk].unpk_pos);
227 }
228 }
229 } else
230 // Data is 8-bit packed
231 {
232 MMCMPBITBUFFER bb;
233 LPBYTE pDest = pBuffer + psubblk->unpk_pos;
234 DWORD dwSize = psubblk->unpk_size;
235 DWORD dwPos = 0;
236 UINT numbits = pblk->num_bits;
237 UINT subblk = 0, oldval = 0;
238 LPCBYTE ptable = lpMemFile+dwMemPos;
239
240 bb.bitcount = 0;
241 bb.bitbuffer = 0;
242 bb.pSrc = lpMemFile+dwMemPos+pblk->tt_entries;
243 bb.pEnd = lpMemFile+dwMemPos+pblk->pk_size;
244 while (subblk < pblk->sub_blk)
245 {
246 UINT newval = 0x100;
247 DWORD d = bb.GetBits(numbits+1);
248
249 if (d >= MMCMP8BitCommands[numbits])
250 {
251 UINT nFetch = MMCMP8BitFetch[numbits];
252 UINT newbits = bb.GetBits(nFetch) + ((d - MMCMP8BitCommands[numbits]) << nFetch);
253 if (newbits != numbits)
254 {
255 numbits = newbits & 0x07;
256 } else
257 {
258 if ((d = bb.GetBits(3)) == 7)
259 {
260 if (bb.GetBits(1)) break;
261 newval = 0xFF;
262 } else
263 {
264 newval = 0xF8 + d;
265 }
266 }
267 } else
268 {
269 newval = d;
270 }
271 if (newval < 0x100)
272 {
273 int n = ptable[newval];
274 if (pblk->flags & MMCMP_DELTA)
275 {
276 n += oldval;
277 oldval = n;
278 }
279 pDest[dwPos++] = (BYTE)n;
280 }
281 if (dwPos >= dwSize)
282 {
283 subblk++;
284 dwPos = 0;
285 dwSize = psubblk[subblk].unpk_size;
286 pDest = pBuffer + psubblk[subblk].unpk_pos;
287 }
288 }
289 }
290 }
291 *ppMemFile = pBuffer;
292 *pdwMemLength = dwFileSize;
293 return TRUE;
294}
295
296
297//////////////////////////////////////////////////////////////////////////////
298//
299// PowerPack PP20 Unpacker
300//
301
302typedef struct _PPBITBUFFER
303{
304 UINT bitcount;
305 ULONG bitbuffer;
306 LPCBYTE pStart;
307 LPCBYTE pSrc;
308
309 ULONG GetBits(UINT n);
310} Q_PACKED PPBITBUFFER;
311
312
313ULONG PPBITBUFFER::GetBits(UINT n)
314{
315 ULONG result = 0;
316
317 for (UINT i=0; i<n; i++)
318 {
319 if (!bitcount)
320 {
321 bitcount = 8;
322 if (pSrc != pStart) pSrc--;
323 bitbuffer = *pSrc;
324 }
325 result = (result<<1) | (bitbuffer&1);
326 bitbuffer >>= 1;
327 bitcount--;
328 }
329 return result;
330}
331
332
333VOID PP20_DoUnpack(const BYTE *pSrc, UINT nSrcLen, BYTE *pDst, UINT nDstLen)
334{
335 PPBITBUFFER BitBuffer;
336 ULONG nBytesLeft;
337
338 BitBuffer.pStart = pSrc;
339 BitBuffer.pSrc = pSrc + nSrcLen - 4;
340 BitBuffer.bitbuffer = 0;
341 BitBuffer.bitcount = 0;
342 BitBuffer.GetBits(pSrc[nSrcLen-1]);
343 nBytesLeft = nDstLen;
344 while (nBytesLeft > 0)
345 {
346 if (!BitBuffer.GetBits(1))
347 {
348 UINT n = 1;
349 while (n < nBytesLeft)
350 {
351 UINT code = BitBuffer.GetBits(2);
352 n += code;
353 if (code != 3) break;
354 }
355 for (UINT i=0; i<n; i++)
356 {
357 pDst[--nBytesLeft] = (BYTE)BitBuffer.GetBits(8);
358 }
359 if (!nBytesLeft) break;
360 }
361 {
362 UINT n = BitBuffer.GetBits(2)+1;
363 UINT nbits = pSrc[n-1];
364 UINT nofs;
365 if (n==4)
366 {
367 nofs = BitBuffer.GetBits( (BitBuffer.GetBits(1)) ? nbits : 7 );
368 while (n < nBytesLeft)
369 {
370 UINT code = BitBuffer.GetBits(3);
371 n += code;
372 if (code != 7) break;
373 }
374 } else
375 {
376 nofs = BitBuffer.GetBits(nbits);
377 }
378 for (UINT i=0; i<=n; i++)
379 {
380 pDst[nBytesLeft-1] = (nBytesLeft+nofs < nDstLen) ? pDst[nBytesLeft+nofs] : 0;
381 if (!--nBytesLeft) break;
382 }
383 }
384 }
385}
386
387
388BOOL PP20_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength)
389{
390 DWORD dwMemLength = *pdwMemLength;
391 LPCBYTE lpMemFile = *ppMemFile;
392 DWORD dwDstLen;
393 LPBYTE pBuffer;
394
395 if ((!lpMemFile) || (dwMemLength < 256) || (*(DWORD *)lpMemFile != 0x30325050)) return FALSE;
396 dwDstLen = (lpMemFile[dwMemLength-4]<<16) | (lpMemFile[dwMemLength-3]<<8) | (lpMemFile[dwMemLength-2]);
397 //Log("PP20 detected: Packed length=%d, Unpacked length=%d\n", dwMemLength, dwDstLen);
398 if ((dwDstLen < 512) || (dwDstLen > 0x400000) || (dwDstLen > 16*dwMemLength)) return FALSE;
399 if ((pBuffer = (LPBYTE)GlobalAllocPtr(GHND, (dwDstLen + 31) & ~15)) == NULL) return FALSE;
400 PP20_DoUnpack(lpMemFile+4, dwMemLength-4, pBuffer, dwDstLen);
401 *ppMemFile = pBuffer;
402 *pdwMemLength = dwDstLen;
403 return TRUE;
404}
405
406
407
408
409