Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

mmcmp.cpp

Go to the documentation of this file.
00001 /*
00002  * This program is  free software; you can redistribute it  and modify it
00003  * under the terms of the GNU  General Public License as published by the
00004  * Free Software Foundation; either version 2  of the license or (at your
00005  * option) any later version.
00006  *
00007  * Authors: Olivier Lapicque <olivierl@jps.net>
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;  // "ziRC"
00018         DWORD id_ONia;  // "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 //#define MMCMP_LOG
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                 // Data is not packed
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                 // Data is 16-bit packed
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                 // Data is 8-bit packed
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 // PowerPack PP20 Unpacker
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         //Log("PP20 detected: Packed length=%d, Unpacked length=%d\n", dwMemLength, dwDstLen);
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 

Generated on Sat Nov 5 16:15:41 2005 for OPIE by  doxygen 1.4.2