00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "stdafx.h"
00011 #include "sndfile.h"
00012
00013 BOOL PP20_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength);
00014
00015 typedef struct MMCMPFILEHEADER
00016 {
00017 DWORD id_ziRC;
00018 DWORD id_ONia;
00019 WORD hdrsize;
00020 } Q_PACKED MMCMPFILEHEADER, *LPMMCMPFILEHEADER;
00021
00022 typedef struct MMCMPHEADER
00023 {
00024 WORD version;
00025 WORD nblocks;
00026 DWORD filesize;
00027 DWORD blktable;
00028 BYTE glb_comp;
00029 BYTE fmt_comp;
00030 } Q_PACKED MMCMPHEADER, *LPMMCMPHEADER;
00031
00032 typedef struct MMCMPBLOCK
00033 {
00034 DWORD unpk_size;
00035 DWORD pk_size;
00036 DWORD xor_chk;
00037 WORD sub_blk;
00038 WORD flags;
00039 WORD tt_entries;
00040 WORD num_bits;
00041 } Q_PACKED MMCMPBLOCK, *LPMMCMPBLOCK;
00042
00043 typedef struct MMCMPSUBBLOCK
00044 {
00045 DWORD unpk_pos;
00046 DWORD unpk_size;
00047 } Q_PACKED MMCMPSUBBLOCK, *LPMMCMPSUBBLOCK;
00048
00049 #define MMCMP_COMP 0x0001
00050 #define MMCMP_DELTA 0x0002
00051 #define MMCMP_16BIT 0x0004
00052 #define MMCMP_STEREO 0x0100
00053 #define MMCMP_ABS16 0x0200
00054 #define MMCMP_ENDIAN 0x0400
00055
00056 typedef struct MMCMPBITBUFFER
00057 {
00058 UINT bitcount;
00059 DWORD bitbuffer;
00060 LPCBYTE pSrc;
00061 LPCBYTE pEnd;
00062
00063 DWORD GetBits(UINT nBits);
00064 } Q_PACKED MMCMPBITBUFFER;
00065
00066
00067 DWORD MMCMPBITBUFFER::GetBits(UINT nBits)
00068
00069 {
00070 DWORD d;
00071 if (!nBits) return 0;
00072 while (bitcount < 24)
00073 {
00074 bitbuffer |= ((pSrc < pEnd) ? *pSrc++ : 0) << bitcount;
00075 bitcount += 8;
00076 }
00077 d = bitbuffer & ((1 << nBits) - 1);
00078 bitbuffer >>= nBits;
00079 bitcount -= nBits;
00080 return d;
00081 }
00082
00083
00084
00085 #ifdef MMCMP_LOG
00086 extern void Log(LPCSTR s, ...);
00087 #endif
00088
00089 const DWORD MMCMP8BitCommands[8] =
00090 {
00091 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C, 0x78, 0xF8
00092 };
00093
00094 const UINT MMCMP8BitFetch[8] =
00095 {
00096 3, 3, 3, 3, 2, 1, 0, 0
00097 };
00098
00099 const DWORD MMCMP16BitCommands[16] =
00100 {
00101 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C, 0x78, 0xF0,
00102 0x1F0, 0x3F0, 0x7F0, 0xFF0, 0x1FF0, 0x3FF0, 0x7FF0, 0xFFF0
00103 };
00104
00105 const UINT MMCMP16BitFetch[16] =
00106 {
00107 4, 4, 4, 4, 3, 2, 1, 0,
00108 0, 0, 0, 0, 0, 0, 0, 0
00109 };
00110
00111
00112 BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength)
00113
00114 {
00115 DWORD dwMemLength = *pdwMemLength;
00116 LPCBYTE lpMemFile = *ppMemFile;
00117 LPBYTE pBuffer;
00118 LPMMCMPFILEHEADER pmfh = (LPMMCMPFILEHEADER)(lpMemFile);
00119 LPMMCMPHEADER pmmh = (LPMMCMPHEADER)(lpMemFile+10);
00120 LPDWORD pblk_table;
00121 DWORD dwFileSize;
00122
00123 if (PP20_Unpack(ppMemFile, pdwMemLength))
00124 {
00125 return TRUE;
00126 }
00127 if ((dwMemLength < 256) || (!pmfh) || (pmfh->id_ziRC != 0x4352697A) || (pmfh->id_ONia != 0x61694e4f) || (pmfh->hdrsize < 14)
00128 || (!pmmh->nblocks) || (pmmh->filesize < 16) || (pmmh->filesize > 0x8000000)
00129 || (pmmh->blktable >= dwMemLength) || (pmmh->blktable + 4*pmmh->nblocks > dwMemLength)) return FALSE;
00130 dwFileSize = pmmh->filesize;
00131 if ((pBuffer = (LPBYTE)GlobalAllocPtr(GHND, (dwFileSize + 31) & ~15)) == NULL) return FALSE;
00132 pblk_table = (LPDWORD)(lpMemFile+pmmh->blktable);
00133 for (UINT nBlock=0; nBlock<pmmh->nblocks; nBlock++)
00134 {
00135 DWORD dwMemPos = pblk_table[nBlock];
00136 LPMMCMPBLOCK pblk = (LPMMCMPBLOCK)(lpMemFile+dwMemPos);
00137 LPMMCMPSUBBLOCK psubblk = (LPMMCMPSUBBLOCK)(lpMemFile+dwMemPos+20);
00138
00139 if ((dwMemPos + 20 >= dwMemLength) || (dwMemPos + 20 + pblk->sub_blk*8 >= dwMemLength)) break;
00140 dwMemPos += 20 + pblk->sub_blk*8;
00141 #ifdef MMCMP_LOG
00142 Log("block %d: flags=%04X sub_blocks=%d", nBlock, (UINT)pblk->flags, (UINT)pblk->sub_blk);
00143 Log(" pksize=%d unpksize=%d", pblk->pk_size, pblk->unpk_size);
00144 Log(" tt_entries=%d num_bits=%d\n", pblk->tt_entries, pblk->num_bits);
00145 #endif
00146
00147 if (!(pblk->flags & MMCMP_COMP))
00148 {
00149 for (UINT i=0; i<pblk->sub_blk; i++)
00150 {
00151 if ((psubblk->unpk_pos > dwFileSize) || (psubblk->unpk_pos + psubblk->unpk_size > dwFileSize)) break;
00152 #ifdef MMCMP_LOG
00153 Log(" Unpacked sub-block %d: offset %d, size=%d\n", i, psubblk->unpk_pos, psubblk->unpk_size);
00154 #endif
00155 memcpy(pBuffer+psubblk->unpk_pos, lpMemFile+dwMemPos, psubblk->unpk_size);
00156 dwMemPos += psubblk->unpk_size;
00157 psubblk++;
00158 }
00159 } else
00160
00161 if (pblk->flags & MMCMP_16BIT)
00162 {
00163 MMCMPBITBUFFER bb;
00164 LPWORD pDest = (LPWORD)(pBuffer + psubblk->unpk_pos);
00165 DWORD dwSize = psubblk->unpk_size >> 1;
00166 DWORD dwPos = 0;
00167 UINT numbits = pblk->num_bits;
00168 UINT subblk = 0, oldval = 0;
00169
00170 #ifdef MMCMP_LOG
00171 Log(" 16-bit block: pos=%d size=%d ", psubblk->unpk_pos, psubblk->unpk_size);
00172 if (pblk->flags & MMCMP_DELTA) Log("DELTA ");
00173 if (pblk->flags & MMCMP_ABS16) Log("ABS16 ");
00174 Log("\n");
00175 #endif
00176 bb.bitcount = 0;
00177 bb.bitbuffer = 0;
00178 bb.pSrc = lpMemFile+dwMemPos+pblk->tt_entries;
00179 bb.pEnd = lpMemFile+dwMemPos+pblk->pk_size;
00180 while (subblk < pblk->sub_blk)
00181 {
00182 UINT newval = 0x10000;
00183 DWORD d = bb.GetBits(numbits+1);
00184
00185 if (d >= MMCMP16BitCommands[numbits])
00186 {
00187 UINT nFetch = MMCMP16BitFetch[numbits];
00188 UINT newbits = bb.GetBits(nFetch) + ((d - MMCMP16BitCommands[numbits]) << nFetch);
00189 if (newbits != numbits)
00190 {
00191 numbits = newbits & 0x0F;
00192 } else
00193 {
00194 if ((d = bb.GetBits(4)) == 0x0F)
00195 {
00196 if (bb.GetBits(1)) break;
00197 newval = 0xFFFF;
00198 } else
00199 {
00200 newval = 0xFFF0 + d;
00201 }
00202 }
00203 } else
00204 {
00205 newval = d;
00206 }
00207 if (newval < 0x10000)
00208 {
00209 newval = (newval & 1) ? (UINT)(-(LONG)((newval+1) >> 1)) : (UINT)(newval >> 1);
00210 if (pblk->flags & MMCMP_DELTA)
00211 {
00212 newval += oldval;
00213 oldval = newval;
00214 } else
00215 if (!(pblk->flags & MMCMP_ABS16))
00216 {
00217 newval ^= 0x8000;
00218 }
00219 pDest[dwPos++] = (WORD)newval;
00220 }
00221 if (dwPos >= dwSize)
00222 {
00223 subblk++;
00224 dwPos = 0;
00225 dwSize = psubblk[subblk].unpk_size >> 1;
00226 pDest = (LPWORD)(pBuffer + psubblk[subblk].unpk_pos);
00227 }
00228 }
00229 } else
00230
00231 {
00232 MMCMPBITBUFFER bb;
00233 LPBYTE pDest = pBuffer + psubblk->unpk_pos;
00234 DWORD dwSize = psubblk->unpk_size;
00235 DWORD dwPos = 0;
00236 UINT numbits = pblk->num_bits;
00237 UINT subblk = 0, oldval = 0;
00238 LPCBYTE ptable = lpMemFile+dwMemPos;
00239
00240 bb.bitcount = 0;
00241 bb.bitbuffer = 0;
00242 bb.pSrc = lpMemFile+dwMemPos+pblk->tt_entries;
00243 bb.pEnd = lpMemFile+dwMemPos+pblk->pk_size;
00244 while (subblk < pblk->sub_blk)
00245 {
00246 UINT newval = 0x100;
00247 DWORD d = bb.GetBits(numbits+1);
00248
00249 if (d >= MMCMP8BitCommands[numbits])
00250 {
00251 UINT nFetch = MMCMP8BitFetch[numbits];
00252 UINT newbits = bb.GetBits(nFetch) + ((d - MMCMP8BitCommands[numbits]) << nFetch);
00253 if (newbits != numbits)
00254 {
00255 numbits = newbits & 0x07;
00256 } else
00257 {
00258 if ((d = bb.GetBits(3)) == 7)
00259 {
00260 if (bb.GetBits(1)) break;
00261 newval = 0xFF;
00262 } else
00263 {
00264 newval = 0xF8 + d;
00265 }
00266 }
00267 } else
00268 {
00269 newval = d;
00270 }
00271 if (newval < 0x100)
00272 {
00273 int n = ptable[newval];
00274 if (pblk->flags & MMCMP_DELTA)
00275 {
00276 n += oldval;
00277 oldval = n;
00278 }
00279 pDest[dwPos++] = (BYTE)n;
00280 }
00281 if (dwPos >= dwSize)
00282 {
00283 subblk++;
00284 dwPos = 0;
00285 dwSize = psubblk[subblk].unpk_size;
00286 pDest = pBuffer + psubblk[subblk].unpk_pos;
00287 }
00288 }
00289 }
00290 }
00291 *ppMemFile = pBuffer;
00292 *pdwMemLength = dwFileSize;
00293 return TRUE;
00294 }
00295
00296
00298
00299
00300
00301
00302 typedef struct _PPBITBUFFER
00303 {
00304 UINT bitcount;
00305 ULONG bitbuffer;
00306 LPCBYTE pStart;
00307 LPCBYTE pSrc;
00308
00309 ULONG GetBits(UINT n);
00310 } Q_PACKED PPBITBUFFER;
00311
00312
00313 ULONG PPBITBUFFER::GetBits(UINT n)
00314 {
00315 ULONG result = 0;
00316
00317 for (UINT i=0; i<n; i++)
00318 {
00319 if (!bitcount)
00320 {
00321 bitcount = 8;
00322 if (pSrc != pStart) pSrc--;
00323 bitbuffer = *pSrc;
00324 }
00325 result = (result<<1) | (bitbuffer&1);
00326 bitbuffer >>= 1;
00327 bitcount--;
00328 }
00329 return result;
00330 }
00331
00332
00333 VOID PP20_DoUnpack(const BYTE *pSrc, UINT nSrcLen, BYTE *pDst, UINT nDstLen)
00334 {
00335 PPBITBUFFER BitBuffer;
00336 ULONG nBytesLeft;
00337
00338 BitBuffer.pStart = pSrc;
00339 BitBuffer.pSrc = pSrc + nSrcLen - 4;
00340 BitBuffer.bitbuffer = 0;
00341 BitBuffer.bitcount = 0;
00342 BitBuffer.GetBits(pSrc[nSrcLen-1]);
00343 nBytesLeft = nDstLen;
00344 while (nBytesLeft > 0)
00345 {
00346 if (!BitBuffer.GetBits(1))
00347 {
00348 UINT n = 1;
00349 while (n < nBytesLeft)
00350 {
00351 UINT code = BitBuffer.GetBits(2);
00352 n += code;
00353 if (code != 3) break;
00354 }
00355 for (UINT i=0; i<n; i++)
00356 {
00357 pDst[--nBytesLeft] = (BYTE)BitBuffer.GetBits(8);
00358 }
00359 if (!nBytesLeft) break;
00360 }
00361 {
00362 UINT n = BitBuffer.GetBits(2)+1;
00363 UINT nbits = pSrc[n-1];
00364 UINT nofs;
00365 if (n==4)
00366 {
00367 nofs = BitBuffer.GetBits( (BitBuffer.GetBits(1)) ? nbits : 7 );
00368 while (n < nBytesLeft)
00369 {
00370 UINT code = BitBuffer.GetBits(3);
00371 n += code;
00372 if (code != 7) break;
00373 }
00374 } else
00375 {
00376 nofs = BitBuffer.GetBits(nbits);
00377 }
00378 for (UINT i=0; i<=n; i++)
00379 {
00380 pDst[nBytesLeft-1] = (nBytesLeft+nofs < nDstLen) ? pDst[nBytesLeft+nofs] : 0;
00381 if (!--nBytesLeft) break;
00382 }
00383 }
00384 }
00385 }
00386
00387
00388 BOOL PP20_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength)
00389 {
00390 DWORD dwMemLength = *pdwMemLength;
00391 LPCBYTE lpMemFile = *ppMemFile;
00392 DWORD dwDstLen;
00393 LPBYTE pBuffer;
00394
00395 if ((!lpMemFile) || (dwMemLength < 256) || (*(DWORD *)lpMemFile != 0x30325050)) return FALSE;
00396 dwDstLen = (lpMemFile[dwMemLength-4]<<16) | (lpMemFile[dwMemLength-3]<<8) | (lpMemFile[dwMemLength-2]);
00397
00398 if ((dwDstLen < 512) || (dwDstLen > 0x400000) || (dwDstLen > 16*dwMemLength)) return FALSE;
00399 if ((pBuffer = (LPBYTE)GlobalAllocPtr(GHND, (dwDstLen + 31) & ~15)) == NULL) return FALSE;
00400 PP20_DoUnpack(lpMemFile+4, dwMemLength-4, pBuffer, dwDstLen);
00401 *ppMemFile = pBuffer;
00402 *pdwMemLength = dwDstLen;
00403 return TRUE;
00404 }
00405
00406
00407
00408
00409