1 /*
2  * Based on the public domain version by Olivier Lapicque
3  * Rewritten for libxmp by Claudio Matsuoka
4  *
5  * Copyright (C) 2012 Claudio Matsuoka
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 
26 #include "common.h"
27 #include "depacker.h"
28 
29 #define MMCMP_COMP	0x0001
30 #define MMCMP_DELTA	0x0002
31 #define MMCMP_16BIT	0x0004
32 #define MMCMP_STEREO	0x0100
33 #define MMCMP_ABS16	0x0200
34 #define MMCMP_ENDIAN	0x0400
35 
36 struct header {
37 	int version;
38 	int nblocks;
39 	int filesize;
40 	int blktable;
41 	int glb_comp;
42 	int fmt_comp;
43 };
44 
45 struct block {
46 	int unpk_size;
47 	int pk_size;
48 	int xor_chk;
49 	int sub_blk;
50 	int flags;
51 	int tt_entries;
52 	int num_bits;
53 };
54 
55 struct sub_block {
56 	int unpk_pos;
57 	int unpk_size;
58 };
59 
60 static const uint32 cmd_8bits[8] = {
61 	0x01, 0x03, 0x07, 0x0f, 0x1e, 0x3c, 0x78, 0xf8
62 };
63 
64 static const uint32 fetch_8bit[8] = {
65 	3, 3, 3, 3, 2, 1, 0, 0
66 };
67 
68 static const uint32 cmd_16bit[16] = {
69 	0x0001, 0x0003, 0x0007, 0x000f, 0x001e, 0x003c, 0x0078, 0x00f0,
70 	0x01f0, 0x03f0, 0x07f0, 0x0ff0, 0x1ff0, 0x3ff0, 0x7ff0, 0xfff0
71 };
72 
73 static const uint32 fetch_16bit[16] = {
74 	4, 4, 4, 4, 3, 2, 1, 0,
75 	0, 0, 0, 0, 0, 0, 0, 0
76 };
77 
78 struct bit_buffer {
79 	uint32 count;
80 	uint32 buffer;
81 };
82 
get_bits(FILE * f,int n,struct bit_buffer * bb)83 static uint32 get_bits(FILE *f, int n, struct bit_buffer *bb)
84 {
85 	uint32 bits;
86 
87 	if (n == 0) {
88 		return 0;
89 	}
90 
91 	while (bb->count < 24) {
92 		bb->buffer |= read8(f, NULL) << bb->count;
93 		bb->count += 8;
94 	}
95 
96 	bits = bb->buffer & ((1 << n) - 1);
97 	bb->buffer >>= n;
98 	bb->count -= n;
99 
100 	return bits;
101 }
102 
block_copy(struct block * block,struct sub_block * sub,FILE * in,FILE * out)103 static void block_copy(struct block *block, struct sub_block *sub,
104 		       FILE *in, FILE *out)
105 {
106 	int i;
107 
108 	for (i = 0; i < block->sub_blk; i++, sub++) {
109 		move_data(out, in, sub->unpk_size);
110 	}
111 }
112 
block_unpack_16bit(struct block * block,struct sub_block * sub,FILE * in,FILE * out)113 static int block_unpack_16bit(struct block *block, struct sub_block *sub,
114 			       FILE *in, FILE *out)
115 {
116 	struct bit_buffer bb;
117 	uint32 pos = 0;
118 	uint32 numbits = block->num_bits;
119 	uint32 j, oldval = 0;
120 
121 	bb.count = 0;
122 	bb.buffer = 0;
123 
124 	if (fseek(out, sub->unpk_pos, SEEK_SET) < 0) {
125 		return -1;
126 	}
127 	if (fseek(in, block->tt_entries, SEEK_SET) < 0) {
128 		return -1;
129 	}
130 
131 	for (j = 0; j < block->sub_blk; ) {
132 		uint32 size = sub[j].unpk_size >> 1;
133 		uint32 newval = 0x10000;
134 		uint32 d = get_bits(in, numbits + 1, &bb);
135 
136 		if (d >= cmd_16bit[numbits]) {
137 			uint32 fetch = fetch_16bit[numbits];
138 			uint32 newbits = get_bits(in, fetch, &bb) +
139 					((d - cmd_16bit[numbits]) << fetch);
140 
141 			if (newbits != numbits) {
142 				numbits = newbits & 0x0f;
143 			} else {
144 				if ((d = get_bits(in, 4, &bb)) == 0x0f) {
145 					if (get_bits(in, 1, &bb))
146 						break;
147 					newval = 0xffff;
148 				} else {
149 					newval = 0xfff0 + d;
150 				}
151 			}
152 		} else {
153 			newval = d;
154 		}
155 
156 		if (newval < 0x10000) {
157 			if (newval & 1) {
158 				newval = (uint32)(-(int32)((newval + 1) >> 1));
159 			} else {
160 				newval = (uint32)(newval >> 1);
161 			}
162 
163 			if (block->flags & MMCMP_DELTA) {
164 				newval += oldval;
165 				oldval = newval;
166 			} else if (!(block->flags & MMCMP_ABS16)) {
167 				newval ^= 0x8000;
168 			}
169 
170 			pos++;
171 			write16l(out, newval);
172 		}
173 
174 		if (pos >= size) {
175 			if (++j >= block->sub_blk)
176 				break;
177 
178 			pos = 0;
179 			if (fseek(out, sub[j].unpk_pos, SEEK_SET) < 0) {
180 				return -1;
181 			}
182 		}
183 	}
184 
185 	return 0;
186 }
187 
block_unpack_8bit(struct block * block,struct sub_block * sub,FILE * in,FILE * out)188 static int block_unpack_8bit(struct block *block, struct sub_block *sub,
189 			      FILE *in, FILE *out)
190 {
191 	struct bit_buffer bb;
192 	uint32 pos = 0;
193 	uint32 numbits = block->num_bits;
194 	uint32 j, oldval = 0;
195 	uint8 ptable[0x100];
196 
197 	if (fread(ptable, 1, 0x100, in) != 0x100) {
198 		return -1;
199 	}
200 
201 	bb.count = 0;
202 	bb.buffer = 0;
203 
204 	if (fseek(out, sub->unpk_pos, SEEK_SET) < 0) {
205 		return -1;
206 	}
207 	if (fseek(in, block->tt_entries, SEEK_SET) < 0) {
208 		return -1;
209 	}
210 
211 	for (j = 0; j < block->sub_blk; ) {
212 		uint32 size = sub[j].unpk_size;
213 		uint32 newval = 0x100;
214 		uint32 d = get_bits(in, numbits+1, &bb);
215 
216 		if (d >= cmd_8bits[numbits]) {
217 			uint32 fetch = fetch_8bit[numbits];
218 			uint32 newbits = get_bits(in, fetch, &bb) +
219 					((d - cmd_8bits[numbits]) << fetch);
220 
221 			if (newbits != numbits) {
222 				numbits = newbits & 0x07;
223 			} else {
224 				if ((d = get_bits(in, 3, &bb)) == 7) {
225 					if (get_bits(in, 1, &bb))
226 						break;
227 					newval = 0xff;
228 				} else {
229 					newval = 0xf8 + d;
230 				}
231 			}
232 		} else {
233 			newval = d;
234 		}
235 
236 		if (newval < 0x100) {
237 			int n = ptable[newval];
238 			if (block->flags & MMCMP_DELTA) {
239 				n += oldval;
240 				oldval = n;
241 			}
242 
243 			pos++;
244 			write8(out, n);
245 		}
246 
247 		if (pos >= size) {
248 			if (++j >= block->sub_blk)
249 				break;
250 
251 			pos = 0;
252 			if (fseek(out, sub[j].unpk_pos, SEEK_SET) < 0) {
253 				return -1;
254 			}
255 		}
256 	}
257 
258 	return 0;
259 }
260 
test_mmcmp(unsigned char * b)261 static int test_mmcmp(unsigned char *b)
262 {
263 	return memcmp(b, "ziRCONia", 8) == 0;
264 }
265 
decrunch_mmcmp(FILE * in,FILE * out)266 static int decrunch_mmcmp(FILE *in, FILE *out)
267 {
268 	struct header h;
269 	uint32 *table;
270 	uint32 i, j;
271 	int error;
272 
273 	/* Read file header */
274 	if (read32l(in, NULL) != 0x4352697A)		/* ziRC */
275 		goto err;
276 	if (read32l(in, NULL) != 0x61694e4f)		/* ONia */
277 		goto err;
278 	if (read16l(in, NULL) < 14)			/* header size */
279 		goto err;
280 
281 	/* Read header */
282 	h.version = read16l(in, &error);
283 	if (error != 0) goto err;
284 	h.nblocks = read16l(in, &error);
285 	if (error != 0) goto err;
286 	h.filesize = read32l(in, &error);
287 	if (error != 0) goto err;
288 	h.blktable = read32l(in, &error);
289 	if (error != 0) goto err;
290 	h.glb_comp = read8(in, &error);
291 	if (error != 0) goto err;
292 	h.fmt_comp = read8(in, &error);
293 	if (error != 0) goto err;
294 
295 	if (h.nblocks == 0)
296 		goto err;
297 
298 	/* Block table */
299 	if (fseek(in, h.blktable, SEEK_SET) < 0) {
300 		goto err;
301 	}
302 
303 	if ((table = malloc(h.nblocks * 4)) == NULL) {
304 		goto err;
305 	}
306 
307 	for (i = 0; i < h.nblocks; i++) {
308 		table[i] = read32l(in, &error);
309 		if (error != 0) goto err2;
310 	}
311 
312 	for (i = 0; i < h.nblocks; i++) {
313 		struct block block;
314 		struct sub_block *sub_block;
315 		uint8 buf[20];
316 
317 		if (fseek(in, table[i], SEEK_SET) < 0) {
318 			goto err2;
319 		}
320 
321 		if (fread(buf, 1, 20, in) != 20) {
322 			goto err2;
323 		}
324 
325 		block.unpk_size  = readmem32l(buf);
326 		block.pk_size    = readmem32l(buf + 4);
327 		block.xor_chk    = readmem32l(buf + 8);
328 		block.sub_blk    = readmem16l(buf + 12);
329 		block.flags      = readmem16l(buf + 14);
330 		block.tt_entries = readmem16l(buf + 16);
331 		block.num_bits   = readmem16l(buf + 18);
332 
333                 /* Sanity check */
334 		if (block.unpk_size <= 0 || block.pk_size <= 0)
335 			goto err2;
336 		if (block.tt_entries < 0 || block.pk_size <= block.tt_entries)
337 			goto err2;
338 		if (block.sub_blk <= 0)
339 			goto err2;
340 		if (block.flags & MMCMP_COMP) {
341 			if (block.flags & MMCMP_16BIT) {
342 				if (block.num_bits >= 16) {
343 					goto err2;
344 				}
345 			} else {
346 				if (block.num_bits >= 8) {
347 					goto err2;
348 				}
349 			}
350 		}
351 
352 		sub_block = malloc(block.sub_blk * sizeof (struct sub_block));
353 		if (sub_block == NULL)
354 			goto err2;
355 
356 		for (j = 0; j < block.sub_blk; j++) {
357 			uint8 buf[8];
358 
359 			if (fread(buf, 1, 8, in) != 8) {
360 				free(sub_block);
361 				goto err2;
362 			}
363 
364 			sub_block[j].unpk_pos  = readmem32l(buf);
365 			sub_block[j].unpk_size = readmem32l(buf + 4);
366 
367 	                /* Sanity check */
368 			if (sub_block[j].unpk_pos < 0 ||
369 			    sub_block[j].unpk_size < 0) {
370 				free(sub_block);
371 				goto err2;
372 			}
373 		}
374 
375 		block.tt_entries += ftell(in);
376 
377 		if (~block.flags & MMCMP_COMP) {
378 			/* Data is not packed */
379 			block_copy(&block, sub_block, in, out);
380 		} else if (block.flags & MMCMP_16BIT) {
381 			/* Data is 16-bit packed */
382 			if (block_unpack_16bit(&block, sub_block, in, out) < 0) {
383 				free(sub_block);
384 				goto err2;
385 			}
386 		} else {
387 			/* Data is 8-bit packed */
388 			if (block_unpack_8bit(&block, sub_block, in, out) < 0) {
389 				free(sub_block);
390 				goto err2;
391 			}
392 		}
393 
394 		free(sub_block);
395 	}
396 
397 	free(table);
398 	return 0;
399 
400     err2:
401 	free(table);
402     err:
403 	return -1;
404 }
405 
406 struct depacker libxmp_depacker_mmcmp = {
407 	test_mmcmp,
408 	decrunch_mmcmp
409 };
410