From ac87bfc370ec15c9c81f8738659fb2582b14b792 Mon Sep 17 00:00:00 2001 From: Jeremy Simon Date: Thu, 28 Feb 2002 21:10:42 +0000 Subject: adding modplug Original commit message from CVS: adding modplug --- gst/modplug/libmodplug/mmcmp.cpp | 406 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 406 insertions(+) create mode 100644 gst/modplug/libmodplug/mmcmp.cpp (limited to 'gst/modplug/libmodplug/mmcmp.cpp') diff --git a/gst/modplug/libmodplug/mmcmp.cpp b/gst/modplug/libmodplug/mmcmp.cpp new file mode 100644 index 00000000..200ee3b9 --- /dev/null +++ b/gst/modplug/libmodplug/mmcmp.cpp @@ -0,0 +1,406 @@ +/* + * This source code is public domain. + * + * Authors: Olivier Lapicque +*/ + +#include "stdafx.h" +#include "sndfile.h" + +BOOL PP20_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength); + +typedef struct MMCMPFILEHEADER +{ + DWORD id_ziRC; // "ziRC" + DWORD id_ONia; // "ONia" + WORD hdrsize; +} MMCMPFILEHEADER, *LPMMCMPFILEHEADER; + +typedef struct MMCMPHEADER +{ + WORD version; + WORD nblocks; + DWORD filesize; + DWORD blktable; + BYTE glb_comp; + BYTE fmt_comp; +} MMCMPHEADER, *LPMMCMPHEADER; + +typedef struct MMCMPBLOCK +{ + DWORD unpk_size; + DWORD pk_size; + DWORD xor_chk; + WORD sub_blk; + WORD flags; + WORD tt_entries; + WORD num_bits; +} MMCMPBLOCK, *LPMMCMPBLOCK; + +typedef struct MMCMPSUBBLOCK +{ + DWORD unpk_pos; + DWORD unpk_size; +} MMCMPSUBBLOCK, *LPMMCMPSUBBLOCK; + +#define MMCMP_COMP 0x0001 +#define MMCMP_DELTA 0x0002 +#define MMCMP_16BIT 0x0004 +#define MMCMP_STEREO 0x0100 +#define MMCMP_ABS16 0x0200 +#define MMCMP_ENDIAN 0x0400 + +typedef struct MMCMPBITBUFFER +{ + UINT bitcount; + DWORD bitbuffer; + LPCBYTE pSrc; + LPCBYTE pEnd; + + DWORD GetBits(UINT nBits); +} MMCMPBITBUFFER; + + +DWORD MMCMPBITBUFFER::GetBits(UINT nBits) +//--------------------------------------- +{ + DWORD d; + if (!nBits) return 0; + while (bitcount < 24) + { + bitbuffer |= ((pSrc < pEnd) ? *pSrc++ : 0) << bitcount; + bitcount += 8; + } + d = bitbuffer & ((1 << nBits) - 1); + bitbuffer >>= nBits; + bitcount -= nBits; + return d; +} + +//#define MMCMP_LOG + +#ifdef MMCMP_LOG +extern void Log(LPCSTR s, ...); +#endif + +const DWORD MMCMP8BitCommands[8] = +{ + 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C, 0x78, 0xF8 +}; + +const UINT MMCMP8BitFetch[8] = +{ + 3, 3, 3, 3, 2, 1, 0, 0 +}; + +const DWORD MMCMP16BitCommands[16] = +{ + 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, + 0x1F0, 0x3F0, 0x7F0, 0xFF0, 0x1FF0, 0x3FF0, 0x7FF0, 0xFFF0 +}; + +const UINT MMCMP16BitFetch[16] = +{ + 4, 4, 4, 4, 3, 2, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + + +BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength) +//--------------------------------------------------------- +{ + DWORD dwMemLength = *pdwMemLength; + LPCBYTE lpMemFile = *ppMemFile; + LPBYTE pBuffer; + LPMMCMPFILEHEADER pmfh = (LPMMCMPFILEHEADER)(lpMemFile); + LPMMCMPHEADER pmmh = (LPMMCMPHEADER)(lpMemFile+10); + LPDWORD pblk_table; + DWORD dwFileSize; + + if (PP20_Unpack(ppMemFile, pdwMemLength)) + { + return TRUE; + } + if ((dwMemLength < 256) || (!pmfh) || (pmfh->id_ziRC != 0x4352697A) || (pmfh->id_ONia != 0x61694e4f) || (pmfh->hdrsize < 14) + || (!pmmh->nblocks) || (pmmh->filesize < 16) || (pmmh->filesize > 0x8000000) + || (pmmh->blktable >= dwMemLength) || (pmmh->blktable + 4*pmmh->nblocks > dwMemLength)) return FALSE; + dwFileSize = pmmh->filesize; + if ((pBuffer = (LPBYTE)GlobalAllocPtr(GHND, (dwFileSize + 31) & ~15)) == NULL) return FALSE; + pblk_table = (LPDWORD)(lpMemFile+pmmh->blktable); + for (UINT nBlock=0; nBlocknblocks; nBlock++) + { + DWORD dwMemPos = pblk_table[nBlock]; + LPMMCMPBLOCK pblk = (LPMMCMPBLOCK)(lpMemFile+dwMemPos); + LPMMCMPSUBBLOCK psubblk = (LPMMCMPSUBBLOCK)(lpMemFile+dwMemPos+20); + + if ((dwMemPos + 20 >= dwMemLength) || (dwMemPos + 20 + pblk->sub_blk*8 >= dwMemLength)) break; + dwMemPos += 20 + pblk->sub_blk*8; +#ifdef MMCMP_LOG + Log("block %d: flags=%04X sub_blocks=%d", nBlock, (UINT)pblk->flags, (UINT)pblk->sub_blk); + Log(" pksize=%d unpksize=%d", pblk->pk_size, pblk->unpk_size); + Log(" tt_entries=%d num_bits=%d\n", pblk->tt_entries, pblk->num_bits); +#endif + // Data is not packed + if (!(pblk->flags & MMCMP_COMP)) + { + for (UINT i=0; isub_blk; i++) + { + if ((psubblk->unpk_pos > dwFileSize) || (psubblk->unpk_pos + psubblk->unpk_size > dwFileSize)) break; +#ifdef MMCMP_LOG + Log(" Unpacked sub-block %d: offset %d, size=%d\n", i, psubblk->unpk_pos, psubblk->unpk_size); +#endif + memcpy(pBuffer+psubblk->unpk_pos, lpMemFile+dwMemPos, psubblk->unpk_size); + dwMemPos += psubblk->unpk_size; + psubblk++; + } + } else + // Data is 16-bit packed + if (pblk->flags & MMCMP_16BIT) + { + MMCMPBITBUFFER bb; + LPWORD pDest = (LPWORD)(pBuffer + psubblk->unpk_pos); + DWORD dwSize = psubblk->unpk_size >> 1; + DWORD dwPos = 0; + UINT numbits = pblk->num_bits; + UINT subblk = 0, oldval = 0; + +#ifdef MMCMP_LOG + Log(" 16-bit block: pos=%d size=%d ", psubblk->unpk_pos, psubblk->unpk_size); + if (pblk->flags & MMCMP_DELTA) Log("DELTA "); + if (pblk->flags & MMCMP_ABS16) Log("ABS16 "); + Log("\n"); +#endif + bb.bitcount = 0; + bb.bitbuffer = 0; + bb.pSrc = lpMemFile+dwMemPos+pblk->tt_entries; + bb.pEnd = lpMemFile+dwMemPos+pblk->pk_size; + while (subblk < pblk->sub_blk) + { + UINT newval = 0x10000; + DWORD d = bb.GetBits(numbits+1); + + if (d >= MMCMP16BitCommands[numbits]) + { + UINT nFetch = MMCMP16BitFetch[numbits]; + UINT newbits = bb.GetBits(nFetch) + ((d - MMCMP16BitCommands[numbits]) << nFetch); + if (newbits != numbits) + { + numbits = newbits & 0x0F; + } else + { + if ((d = bb.GetBits(4)) == 0x0F) + { + if (bb.GetBits(1)) break; + newval = 0xFFFF; + } else + { + newval = 0xFFF0 + d; + } + } + } else + { + newval = d; + } + if (newval < 0x10000) + { + newval = (newval & 1) ? (UINT)(-(LONG)((newval+1) >> 1)) : (UINT)(newval >> 1); + if (pblk->flags & MMCMP_DELTA) + { + newval += oldval; + oldval = newval; + } else + if (!(pblk->flags & MMCMP_ABS16)) + { + newval ^= 0x8000; + } + pDest[dwPos++] = (WORD)newval; + } + if (dwPos >= dwSize) + { + subblk++; + dwPos = 0; + dwSize = psubblk[subblk].unpk_size >> 1; + pDest = (LPWORD)(pBuffer + psubblk[subblk].unpk_pos); + } + } + } else + // Data is 8-bit packed + { + MMCMPBITBUFFER bb; + LPBYTE pDest = pBuffer + psubblk->unpk_pos; + DWORD dwSize = psubblk->unpk_size; + DWORD dwPos = 0; + UINT numbits = pblk->num_bits; + UINT subblk = 0, oldval = 0; + LPCBYTE ptable = lpMemFile+dwMemPos; + + bb.bitcount = 0; + bb.bitbuffer = 0; + bb.pSrc = lpMemFile+dwMemPos+pblk->tt_entries; + bb.pEnd = lpMemFile+dwMemPos+pblk->pk_size; + while (subblk < pblk->sub_blk) + { + UINT newval = 0x100; + DWORD d = bb.GetBits(numbits+1); + + if (d >= MMCMP8BitCommands[numbits]) + { + UINT nFetch = MMCMP8BitFetch[numbits]; + UINT newbits = bb.GetBits(nFetch) + ((d - MMCMP8BitCommands[numbits]) << nFetch); + if (newbits != numbits) + { + numbits = newbits & 0x07; + } else + { + if ((d = bb.GetBits(3)) == 7) + { + if (bb.GetBits(1)) break; + newval = 0xFF; + } else + { + newval = 0xF8 + d; + } + } + } else + { + newval = d; + } + if (newval < 0x100) + { + int n = ptable[newval]; + if (pblk->flags & MMCMP_DELTA) + { + n += oldval; + oldval = n; + } + pDest[dwPos++] = (BYTE)n; + } + if (dwPos >= dwSize) + { + subblk++; + dwPos = 0; + dwSize = psubblk[subblk].unpk_size; + pDest = pBuffer + psubblk[subblk].unpk_pos; + } + } + } + } + *ppMemFile = pBuffer; + *pdwMemLength = dwFileSize; + return TRUE; +} + + +////////////////////////////////////////////////////////////////////////////// +// +// PowerPack PP20 Unpacker +// + +typedef struct _PPBITBUFFER +{ + UINT bitcount; + ULONG bitbuffer; + LPCBYTE pStart; + LPCBYTE pSrc; + + ULONG GetBits(UINT n); +} PPBITBUFFER; + + +ULONG PPBITBUFFER::GetBits(UINT n) +{ + ULONG result = 0; + + for (UINT i=0; i>= 1; + bitcount--; + } + return result; +} + + +VOID PP20_DoUnpack(const BYTE *pSrc, UINT nSrcLen, BYTE *pDst, UINT nDstLen) +{ + PPBITBUFFER BitBuffer; + ULONG nBytesLeft; + + BitBuffer.pStart = pSrc; + BitBuffer.pSrc = pSrc + nSrcLen - 4; + BitBuffer.bitbuffer = 0; + BitBuffer.bitcount = 0; + BitBuffer.GetBits(pSrc[nSrcLen-1]); + nBytesLeft = nDstLen; + while (nBytesLeft > 0) + { + if (!BitBuffer.GetBits(1)) + { + UINT n = 1; + while (n < nBytesLeft) + { + UINT code = BitBuffer.GetBits(2); + n += code; + if (code != 3) break; + } + for (UINT i=0; i 0x400000) || (dwDstLen > 16*dwMemLength)) return FALSE; + if ((pBuffer = (LPBYTE)GlobalAllocPtr(GHND, (dwDstLen + 31) & ~15)) == NULL) return FALSE; + PP20_DoUnpack(lpMemFile+4, dwMemLength-4, pBuffer, dwDstLen); + *ppMemFile = pBuffer; + *pdwMemLength = dwDstLen; + return TRUE; +} + + + + + -- cgit v1.2.1