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