/src/vlc/contrib/contrib-build/libmodplug/src/mmcmp.cpp
Line | Count | Source |
1 | | /* |
2 | | * This source code is public domain. |
3 | | * |
4 | | * Handles unpacking of Powerpack PP20 |
5 | | * Authors: Olivier Lapicque <olivierl@jps.net> |
6 | | */ |
7 | | |
8 | | #include "stdafx.h" |
9 | | #include "sndfile.h" |
10 | | |
11 | | BOOL PP20_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength); |
12 | | |
13 | | #pragma pack(1) |
14 | | typedef struct MMCMPFILEHEADER |
15 | | { |
16 | | char id[8]; // "ziRCONia" |
17 | | WORD hdrsize; |
18 | | } MMCMPFILEHEADER, *LPMMCMPFILEHEADER; |
19 | | |
20 | | typedef struct MMCMPHEADER |
21 | | { |
22 | | WORD version; |
23 | | WORD nblocks; |
24 | | DWORD filesize; |
25 | | DWORD blktable; |
26 | | BYTE glb_comp; |
27 | | BYTE fmt_comp; |
28 | | } MMCMPHEADER, *LPMMCMPHEADER; |
29 | | |
30 | | typedef struct MMCMPBLOCK |
31 | | { |
32 | | DWORD unpk_size; |
33 | | DWORD pk_size; |
34 | | DWORD xor_chk; |
35 | | WORD sub_blk; |
36 | | WORD flags; |
37 | | WORD tt_entries; |
38 | | USHORT num_bits; |
39 | | } MMCMPBLOCK, *LPMMCMPBLOCK; |
40 | | |
41 | | typedef struct MMCMPSUBBLOCK |
42 | | { |
43 | | DWORD unpk_pos; |
44 | | DWORD unpk_size; |
45 | | } MMCMPSUBBLOCK, *LPMMCMPSUBBLOCK; |
46 | | #pragma pack() |
47 | | |
48 | | // make sure of structure sizes |
49 | | typedef int chk_MMCMPFILEHEADER[(sizeof(struct MMCMPFILEHEADER) == 10) * 2 - 1]; |
50 | | typedef int chk_MMCMPHEADER[(sizeof(struct MMCMPHEADER) == 14) * 2 - 1]; |
51 | | typedef int chk_MMCMPBLOCK[(sizeof(struct MMCMPBLOCK) == 20) * 2 - 1]; |
52 | | typedef int chk_MMCMPSUBBLOCK[(sizeof(struct MMCMPSUBBLOCK) == 8) * 2 - 1]; |
53 | | |
54 | 0 | #define MMCMP_COMP 0x0001 |
55 | 0 | #define MMCMP_DELTA 0x0002 |
56 | 0 | #define MMCMP_16BIT 0x0004 |
57 | | #define MMCMP_STEREO 0x0100 |
58 | 0 | #define MMCMP_ABS16 0x0200 |
59 | | #define MMCMP_ENDIAN 0x0400 |
60 | | |
61 | | typedef struct MMCMPBITBUFFER |
62 | | { |
63 | | UINT bitcount; |
64 | | DWORD bitbuffer; |
65 | | LPCBYTE pSrc; |
66 | | LPCBYTE pEnd; |
67 | | |
68 | | DWORD GetBits(UINT nBits); |
69 | | } MMCMPBITBUFFER; |
70 | | |
71 | | |
72 | | DWORD MMCMPBITBUFFER::GetBits(UINT nBits) |
73 | | //--------------------------------------- |
74 | 0 | { |
75 | 0 | DWORD d; |
76 | 0 | if (!nBits) return 0; |
77 | 0 | while (bitcount < 24) |
78 | 0 | { |
79 | 0 | bitbuffer |= ((pSrc < pEnd) ? *pSrc++ : 0) << bitcount; |
80 | 0 | bitcount += 8; |
81 | 0 | } |
82 | 0 | d = bitbuffer & ((1 << nBits) - 1); |
83 | 0 | bitbuffer >>= nBits; |
84 | 0 | bitcount -= nBits; |
85 | 0 | return d; |
86 | 0 | } |
87 | | |
88 | | //#define MMCMP_LOG |
89 | | |
90 | | #ifdef MMCMP_LOG |
91 | | extern void Log(LPCSTR s, ...); |
92 | | #endif |
93 | | |
94 | | static const DWORD MMCMP8BitCommands[8] = |
95 | | { |
96 | | 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C, 0x78, 0xF8 |
97 | | }; |
98 | | |
99 | | static const UINT MMCMP8BitFetch[8] = |
100 | | { |
101 | | 3, 3, 3, 3, 2, 1, 0, 0 |
102 | | }; |
103 | | |
104 | | static const DWORD MMCMP16BitCommands[16] = |
105 | | { |
106 | | 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, |
107 | | 0x1F0, 0x3F0, 0x7F0, 0xFF0, 0x1FF0, 0x3FF0, 0x7FF0, 0xFFF0 |
108 | | }; |
109 | | |
110 | | static const UINT MMCMP16BitFetch[16] = |
111 | | { |
112 | | 4, 4, 4, 4, 3, 2, 1, 0, |
113 | | 0, 0, 0, 0, 0, 0, 0, 0 |
114 | | }; |
115 | | |
116 | | |
117 | | static void swap_mfh(LPMMCMPFILEHEADER fh) |
118 | 3.38k | { |
119 | 3.38k | fh->hdrsize = bswapLE16(fh->hdrsize); |
120 | 3.38k | } |
121 | | |
122 | | static void swap_mmh(LPMMCMPHEADER mh) |
123 | 3.38k | { |
124 | 3.38k | mh->version = bswapLE16(mh->version); |
125 | 3.38k | mh->nblocks = bswapLE16(mh->nblocks); |
126 | 3.38k | mh->filesize = bswapLE32(mh->filesize); |
127 | 3.38k | mh->blktable = bswapLE32(mh->blktable); |
128 | 3.38k | } |
129 | | |
130 | | static void swap_block (LPMMCMPBLOCK blk) |
131 | 0 | { |
132 | 0 | blk->unpk_size = bswapLE32(blk->unpk_size); |
133 | 0 | blk->pk_size = bswapLE32(blk->pk_size); |
134 | 0 | blk->xor_chk = bswapLE32(blk->xor_chk); |
135 | 0 | blk->sub_blk = bswapLE16(blk->sub_blk); |
136 | 0 | blk->flags = bswapLE16(blk->flags); |
137 | 0 | blk->tt_entries = bswapLE16(blk->tt_entries); |
138 | 0 | blk->num_bits = bswapLE16(blk->num_bits); |
139 | 0 | } |
140 | | |
141 | | static void swap_subblock (LPMMCMPSUBBLOCK sblk) |
142 | 0 | { |
143 | 0 | sblk->unpk_pos = bswapLE32(sblk->unpk_pos); |
144 | 0 | sblk->unpk_size = bswapLE32(sblk->unpk_size); |
145 | 0 | } |
146 | | |
147 | | |
148 | | BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength) |
149 | | //--------------------------------------------------------- |
150 | 4.68k | { |
151 | 4.68k | DWORD dwMemLength; |
152 | 4.68k | LPCBYTE lpMemFile; |
153 | 4.68k | LPBYTE pBuffer; |
154 | 4.68k | LPMMCMPFILEHEADER pmfh; |
155 | 4.68k | LPMMCMPHEADER pmmh; |
156 | 4.68k | const DWORD *pblk_table; |
157 | 4.68k | DWORD dwFileSize; |
158 | 4.68k | BYTE tmp0[32], tmp1[32]; |
159 | | |
160 | 4.68k | if (PP20_Unpack(ppMemFile, pdwMemLength)) |
161 | 240 | { |
162 | 240 | return TRUE; |
163 | 240 | } |
164 | | |
165 | 4.44k | dwMemLength = *pdwMemLength; |
166 | 4.44k | lpMemFile = *ppMemFile; |
167 | 4.44k | if ((dwMemLength < 256) || (!lpMemFile)) return FALSE; |
168 | 3.38k | memcpy(tmp0, lpMemFile, 24); |
169 | 3.38k | pmfh = (LPMMCMPFILEHEADER)(tmp0); |
170 | 3.38k | pmmh = (LPMMCMPHEADER)(tmp0+10); |
171 | 3.38k | swap_mfh(pmfh); |
172 | 3.38k | swap_mmh(pmmh); |
173 | | |
174 | 3.38k | if ((memcmp(pmfh->id,"ziRCONia",8) != 0) || (pmfh->hdrsize < 14) |
175 | 10 | || (!pmmh->nblocks) || (pmmh->filesize < 16) || (pmmh->filesize > 0x8000000) |
176 | 3.38k | || (pmmh->blktable >= dwMemLength) || (pmmh->blktable + 4*pmmh->nblocks > dwMemLength)) return FALSE; |
177 | 0 | dwFileSize = pmmh->filesize; |
178 | 0 | if ((pBuffer = (LPBYTE)GlobalAllocPtr(GHND, (dwFileSize + 31) & ~15)) == NULL) return FALSE; |
179 | 0 | pblk_table = (const DWORD *)(lpMemFile+pmmh->blktable); |
180 | 0 | for (UINT nBlock=0; nBlock<pmmh->nblocks; nBlock++) |
181 | 0 | { |
182 | 0 | DWORD dwMemPos = bswapLE32(pblk_table[nBlock]); |
183 | 0 | DWORD dwSubPos; |
184 | 0 | LPMMCMPBLOCK pblk; |
185 | 0 | LPMMCMPSUBBLOCK psubblk; |
186 | |
|
187 | 0 | if (dwMemPos >= dwMemLength - 20) break; |
188 | 0 | memcpy(tmp1, lpMemFile+dwMemPos, 28); |
189 | 0 | pblk = (LPMMCMPBLOCK)(tmp1); |
190 | 0 | psubblk = (LPMMCMPSUBBLOCK)(tmp1+20); |
191 | 0 | swap_block(pblk); |
192 | 0 | swap_subblock(psubblk); |
193 | |
|
194 | 0 | if (dwMemPos + 20 + pblk->sub_blk*8 >= dwMemLength) break; |
195 | 0 | dwSubPos = dwMemPos + 20; |
196 | 0 | dwMemPos += 20 + pblk->sub_blk*8; |
197 | | #ifdef MMCMP_LOG |
198 | | Log("block %d: flags=%04X sub_blocks=%d", nBlock, (UINT)pblk->flags, (UINT)pblk->sub_blk); |
199 | | Log(" pksize=%d unpksize=%d", pblk->pk_size, pblk->unpk_size); |
200 | | Log(" tt_entries=%d num_bits=%d\n", pblk->tt_entries, pblk->num_bits); |
201 | | #endif |
202 | | // Data is not packed |
203 | 0 | if (!(pblk->flags & MMCMP_COMP)) |
204 | 0 | { |
205 | 0 | for (UINT i=0; i<pblk->sub_blk; i++) |
206 | 0 | { |
207 | 0 | if ((psubblk->unpk_pos >= dwFileSize) || |
208 | 0 | (psubblk->unpk_size >= dwFileSize) || |
209 | 0 | (psubblk->unpk_size > dwFileSize - psubblk->unpk_pos) || |
210 | 0 | psubblk->unpk_size > dwMemLength - dwMemPos) break; |
211 | | #ifdef MMCMP_LOG |
212 | | Log(" Unpacked sub-block %d: offset %d, size=%d\n", i, psubblk->unpk_pos, psubblk->unpk_size); |
213 | | #endif |
214 | 0 | memcpy(pBuffer+psubblk->unpk_pos, lpMemFile+dwMemPos, psubblk->unpk_size); |
215 | 0 | dwMemPos += psubblk->unpk_size; |
216 | 0 | memcpy(tmp1+20,lpMemFile+dwSubPos+i*8,8); |
217 | 0 | swap_subblock(psubblk); |
218 | 0 | } |
219 | 0 | } else |
220 | | // Data is 16-bit packed |
221 | 0 | if (pblk->flags & MMCMP_16BIT && pblk->num_bits < 16) |
222 | 0 | { |
223 | 0 | MMCMPBITBUFFER bb; |
224 | 0 | LPWORD pDest = (LPWORD)(pBuffer + psubblk->unpk_pos); |
225 | 0 | DWORD dwSize = psubblk->unpk_size >> 1; |
226 | 0 | DWORD dwPos = 0; |
227 | 0 | UINT numbits = pblk->num_bits; |
228 | 0 | UINT subblk = 0, oldval = 0; |
229 | |
|
230 | 0 | if (dwSize * 2 > dwFileSize-psubblk->unpk_pos || |
231 | 0 | psubblk->unpk_pos > dwMemLength-dwMemPos) |
232 | 0 | break; |
233 | | |
234 | | #ifdef MMCMP_LOG |
235 | | Log(" 16-bit block: pos=%d size=%d ", psubblk->unpk_pos, psubblk->unpk_size); |
236 | | if (pblk->flags & MMCMP_DELTA) Log("DELTA "); |
237 | | if (pblk->flags & MMCMP_ABS16) Log("ABS16 "); |
238 | | Log("\n"); |
239 | | #endif |
240 | 0 | bb.bitcount = 0; |
241 | 0 | bb.bitbuffer = 0; |
242 | 0 | bb.pSrc = lpMemFile+dwMemPos+pblk->tt_entries; |
243 | 0 | bb.pEnd = lpMemFile+dwMemPos+pblk->pk_size; |
244 | 0 | if (bb.pEnd > lpMemFile+dwMemLength) |
245 | 0 | bb.pEnd = lpMemFile+dwMemLength; |
246 | 0 | while (subblk < pblk->sub_blk) |
247 | 0 | { |
248 | 0 | UINT newval = 0x10000; |
249 | 0 | DWORD d = bb.GetBits(numbits+1); |
250 | |
|
251 | 0 | if ((psubblk->unpk_pos >= dwFileSize) || |
252 | 0 | (psubblk->unpk_size >= dwFileSize) || |
253 | 0 | (psubblk->unpk_size > dwFileSize - psubblk->unpk_pos)) |
254 | 0 | dwPos = dwSize; |
255 | |
|
256 | 0 | if (d >= MMCMP16BitCommands[numbits]) |
257 | 0 | { |
258 | 0 | UINT nFetch = MMCMP16BitFetch[numbits]; |
259 | 0 | UINT newbits = bb.GetBits(nFetch) + ((d - MMCMP16BitCommands[numbits]) << nFetch); |
260 | 0 | if (newbits != numbits) |
261 | 0 | { |
262 | 0 | numbits = newbits & 0x0F; |
263 | 0 | } else |
264 | 0 | { |
265 | 0 | if ((d = bb.GetBits(4)) == 0x0F) |
266 | 0 | { |
267 | 0 | if (bb.GetBits(1)) break; |
268 | 0 | newval = 0xFFFF; |
269 | 0 | } else |
270 | 0 | { |
271 | 0 | newval = 0xFFF0 + d; |
272 | 0 | } |
273 | 0 | } |
274 | 0 | } else |
275 | 0 | { |
276 | 0 | newval = d; |
277 | 0 | } |
278 | 0 | if (newval < 0x10000 && dwPos < dwSize) |
279 | 0 | { |
280 | 0 | newval = (newval & 1) ? (UINT)(-(LONG)((newval+1) >> 1)) : (UINT)(newval >> 1); |
281 | 0 | if (pblk->flags & MMCMP_DELTA) |
282 | 0 | { |
283 | 0 | newval += oldval; |
284 | 0 | oldval = newval; |
285 | 0 | } else |
286 | 0 | if (!(pblk->flags & MMCMP_ABS16)) |
287 | 0 | { |
288 | 0 | newval ^= 0x8000; |
289 | 0 | } |
290 | 0 | WORD swapped = (WORD)newval; |
291 | 0 | pDest[dwPos++] = bswapLE16(swapped); |
292 | 0 | } |
293 | 0 | if (dwPos >= dwSize) |
294 | 0 | { |
295 | 0 | subblk++; |
296 | 0 | memcpy(tmp1+20,lpMemFile+dwSubPos+subblk*8,8); |
297 | 0 | swap_subblock(psubblk); |
298 | 0 | dwPos = 0; |
299 | 0 | dwSize = psubblk->unpk_size >> 1; |
300 | 0 | if ( psubblk->unpk_pos >= dwFileSize || |
301 | 0 | dwSize * 2 > dwFileSize ) { |
302 | 0 | break; |
303 | 0 | } |
304 | 0 | pDest = (LPWORD)(pBuffer + psubblk->unpk_pos); |
305 | 0 | } |
306 | 0 | } |
307 | 0 | } else if (pblk->num_bits < 8) |
308 | | // Data is 8-bit packed |
309 | 0 | { |
310 | 0 | MMCMPBITBUFFER bb; |
311 | 0 | LPBYTE pDest = pBuffer + psubblk->unpk_pos; |
312 | 0 | DWORD dwSize = psubblk->unpk_size; |
313 | 0 | DWORD dwPos = 0; |
314 | 0 | UINT numbits = pblk->num_bits; |
315 | 0 | UINT subblk = 0, oldval = 0; |
316 | 0 | LPCBYTE ptable = lpMemFile+dwMemPos; |
317 | |
|
318 | 0 | if (dwSize > dwFileSize-psubblk->unpk_pos || |
319 | 0 | psubblk->unpk_pos > dwMemLength-dwMemPos) |
320 | 0 | break; |
321 | | |
322 | 0 | bb.bitcount = 0; |
323 | 0 | bb.bitbuffer = 0; |
324 | 0 | bb.pSrc = lpMemFile+dwMemPos+pblk->tt_entries; |
325 | 0 | bb.pEnd = lpMemFile+dwMemPos+pblk->pk_size; |
326 | 0 | if (bb.pEnd > lpMemFile+dwMemLength) |
327 | 0 | bb.pEnd = lpMemFile+dwMemLength; |
328 | 0 | while (subblk < pblk->sub_blk) |
329 | 0 | { |
330 | 0 | UINT newval = 0x100; |
331 | 0 | DWORD d = bb.GetBits(numbits+1); |
332 | |
|
333 | 0 | if ((psubblk->unpk_pos >= dwFileSize) || |
334 | 0 | (psubblk->unpk_size >= dwFileSize) || |
335 | 0 | (psubblk->unpk_size > dwFileSize - (psubblk->unpk_pos))) |
336 | 0 | dwPos = dwSize; |
337 | |
|
338 | 0 | if (d >= MMCMP8BitCommands[numbits]) |
339 | 0 | { |
340 | 0 | UINT nFetch = MMCMP8BitFetch[numbits]; |
341 | 0 | UINT newbits = bb.GetBits(nFetch) + ((d - MMCMP8BitCommands[numbits]) << nFetch); |
342 | 0 | if (newbits != numbits) |
343 | 0 | { |
344 | 0 | numbits = newbits & 0x07; |
345 | 0 | } else |
346 | 0 | { |
347 | 0 | if ((d = bb.GetBits(3)) == 7) |
348 | 0 | { |
349 | 0 | if (bb.GetBits(1)) break; |
350 | 0 | newval = 0xFF; |
351 | 0 | } else |
352 | 0 | { |
353 | 0 | newval = 0xF8 + d; |
354 | 0 | } |
355 | 0 | } |
356 | 0 | } else |
357 | 0 | { |
358 | 0 | newval = d; |
359 | 0 | } |
360 | 0 | if (newval < 0x100 && dwPos < dwSize && dwMemPos < dwMemLength - newval) |
361 | 0 | { |
362 | 0 | int n = ptable[newval]; |
363 | 0 | if (pblk->flags & MMCMP_DELTA) |
364 | 0 | { |
365 | 0 | n += oldval; |
366 | 0 | oldval = n; |
367 | 0 | } |
368 | 0 | pDest[dwPos++] = (BYTE)n; |
369 | 0 | } |
370 | 0 | if (dwPos >= dwSize) |
371 | 0 | { |
372 | 0 | subblk++; |
373 | 0 | memcpy(tmp1+20,lpMemFile+dwSubPos+subblk*8,8); |
374 | 0 | swap_subblock(psubblk); |
375 | 0 | dwPos = 0; |
376 | 0 | dwSize = psubblk->unpk_size; |
377 | 0 | if ( psubblk->unpk_pos >= dwFileSize || |
378 | 0 | dwSize > dwFileSize ) |
379 | 0 | break; |
380 | 0 | pDest = pBuffer + psubblk->unpk_pos; |
381 | 0 | } |
382 | 0 | } |
383 | 0 | } else |
384 | 0 | { |
385 | 0 | GlobalFreePtr(pBuffer); |
386 | 0 | return FALSE; |
387 | 0 | } |
388 | 0 | } |
389 | 0 | *ppMemFile = pBuffer; |
390 | 0 | *pdwMemLength = dwFileSize; |
391 | 0 | return TRUE; |
392 | 0 | } |
393 | | |
394 | | |
395 | | ////////////////////////////////////////////////////////////////////////////// |
396 | | // |
397 | | // PowerPack PP20 Unpacker |
398 | | // |
399 | | |
400 | | typedef struct _PPBITBUFFER |
401 | | { |
402 | | UINT bitcount; |
403 | | ULONG bitbuffer; |
404 | | LPCBYTE pStart; |
405 | | LPCBYTE pSrc; |
406 | | |
407 | | ULONG GetBits(UINT n); |
408 | | } PPBITBUFFER; |
409 | | |
410 | | |
411 | | ULONG PPBITBUFFER::GetBits(UINT n) |
412 | 2.14M | { |
413 | 2.14M | ULONG result = 0; |
414 | | |
415 | 8.68M | for (UINT i=0; i<n; i++) |
416 | 6.54M | { |
417 | 6.54M | if (!bitcount) |
418 | 817k | { |
419 | 817k | bitcount = 8; |
420 | 817k | if (pSrc != pStart) pSrc--; |
421 | 817k | bitbuffer = *pSrc; |
422 | 817k | } |
423 | 6.54M | result = (result<<1) | (bitbuffer&1); |
424 | 6.54M | bitbuffer >>= 1; |
425 | 6.54M | bitcount--; |
426 | 6.54M | } |
427 | 2.14M | return result; |
428 | 2.14M | } |
429 | | |
430 | | |
431 | | static VOID PP20_DoUnpack(const BYTE *pSrc, UINT nSrcLen, BYTE *pDst, UINT nDstLen) |
432 | 240 | { |
433 | 240 | PPBITBUFFER BitBuffer; |
434 | 240 | ULONG nBytesLeft; |
435 | | |
436 | 240 | BitBuffer.pStart = pSrc; |
437 | 240 | BitBuffer.pSrc = pSrc + nSrcLen - 4; |
438 | 240 | BitBuffer.bitbuffer = 0; |
439 | 240 | BitBuffer.bitcount = 0; |
440 | 240 | BitBuffer.GetBits(pSrc[nSrcLen-1]); |
441 | 240 | nBytesLeft = nDstLen; |
442 | 470k | while (nBytesLeft > 0) |
443 | 470k | { |
444 | 470k | if (!BitBuffer.GetBits(1)) |
445 | 326k | { |
446 | 326k | UINT n = 1; |
447 | 336k | while (n < nBytesLeft) |
448 | 336k | { |
449 | 336k | UINT code = BitBuffer.GetBits(2); |
450 | 336k | n += code; |
451 | 336k | if (code != 3) break; |
452 | 336k | } |
453 | 691k | for (UINT i=0; i<n; i++) |
454 | 365k | { |
455 | 365k | pDst[nBytesLeft - 1] = (BYTE)BitBuffer.GetBits(8); |
456 | 365k | if (!--nBytesLeft) break; |
457 | 365k | } |
458 | 326k | if (!nBytesLeft) break; |
459 | 326k | } |
460 | 470k | { |
461 | 470k | UINT n = BitBuffer.GetBits(2)+1; |
462 | 470k | UINT nbits = pSrc[n-1]; |
463 | 470k | UINT nofs; |
464 | 470k | if (n==4) |
465 | 7.27k | { |
466 | 7.27k | nofs = BitBuffer.GetBits( (BitBuffer.GetBits(1)) ? nbits : 7 ); |
467 | 20.7k | while (n < nBytesLeft) |
468 | 20.7k | { |
469 | 20.7k | UINT code = BitBuffer.GetBits(3); |
470 | 20.7k | n += code; |
471 | 20.7k | if (code != 7) break; |
472 | 20.7k | } |
473 | 7.27k | } else |
474 | 462k | { |
475 | 462k | nofs = BitBuffer.GetBits(nbits); |
476 | 462k | } |
477 | 1.55M | for (UINT i=0; i<=n; i++) |
478 | 1.08M | { |
479 | 1.08M | pDst[nBytesLeft-1] = (nBytesLeft+nofs < nDstLen) ? pDst[nBytesLeft+nofs] : 0; |
480 | 1.08M | if (!--nBytesLeft) break; |
481 | 1.08M | } |
482 | 470k | } |
483 | 470k | } |
484 | 240 | } |
485 | | |
486 | | |
487 | | BOOL PP20_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength) |
488 | 4.68k | { |
489 | 4.68k | DWORD dwMemLength = *pdwMemLength; |
490 | 4.68k | LPCBYTE lpMemFile = *ppMemFile; |
491 | 4.68k | DWORD dwDstLen; |
492 | 4.68k | LPBYTE pBuffer; |
493 | | |
494 | 4.68k | if ((!lpMemFile) || (dwMemLength < 256) || (memcmp(lpMemFile,"PP20",4) != 0)) return FALSE; |
495 | 258 | dwDstLen = (lpMemFile[dwMemLength-4]<<16) | (lpMemFile[dwMemLength-3]<<8) | (lpMemFile[dwMemLength-2]); |
496 | | //Log("PP20 detected: Packed length=%d, Unpacked length=%d\n", dwMemLength, dwDstLen); |
497 | 258 | if ((dwDstLen < 512) || (dwDstLen > 0x400000) || (dwDstLen > 16*dwMemLength)) return FALSE; |
498 | 240 | if ((pBuffer = (LPBYTE)GlobalAllocPtr(GHND, (dwDstLen + 31) & ~15)) == NULL) return FALSE; |
499 | 240 | PP20_DoUnpack(lpMemFile+4, dwMemLength-4, pBuffer, dwDstLen); |
500 | 240 | *ppMemFile = pBuffer; |
501 | 240 | *pdwMemLength = dwDstLen; |
502 | 240 | return TRUE; |
503 | 240 | } |