1 /*
2 * This program is free software; you can redistribute it and modify it
3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation; either version 2 of the license or (at your
5 * option) any later version.
6 *
7 * Author: Olivier Lapicque <olivierl@jps.net>
8 * Modified by Claudio Matsuoka for xmp
9 * Modified again by Storlek to de-xmp-ify it.
10 */
11
12 #define NEED_BYTESWAP
13 #include "headers.h"
14
15 #include "slurp.h" // for definition of mmcmp_unpack
16
17 #pragma pack(push, 1)
18 typedef struct mm_header {
19 char zirconia[8]; // "ziRCONia"
20 uint16_t hdrsize;
21
22 uint16_t version;
23 uint16_t blocks;
24 uint32_t filesize;
25 uint32_t blktable;
26 uint8_t glb_comp;
27 uint8_t fmt_comp;
28 } mm_header_t;
29
30 typedef struct mm_block {
31 uint32_t unpk_size;
32 uint32_t pk_size;
33 uint32_t xor_chk;
34 uint16_t sub_blk;
35 uint16_t flags;
36 uint16_t tt_entries;
37 uint16_t num_bits;
38 } mm_block_t;
39
40 typedef struct mm_subblock {
41 uint32_t unpk_pos;
42 uint32_t unpk_size;
jmx_verify(const char * exp_swname,const char * exp_swversion)43 } mm_subblock_t;
44 #pragma pack(pop)
45
46
47 // only used internally
48 typedef struct mm_bit_buffer {
49 uint32_t bits, buffer;
50 uint8_t *src, *end;
51 } mm_bit_buffer_t;
52
53
54 enum {
55 MM_COMP = 0x0001,
56 MM_DELTA = 0x0002,
57 MM_16BIT = 0x0004,
58 MM_STEREO = 0x0100, // unused?
59 MM_ABS16 = 0x0200,
60 MM_ENDIAN = 0x0400, // unused?
61 };
62
63
64 static const uint32_t mm_8bit_commands[8] = { 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C, 0x78, 0xF8 };
65
66 static const uint32_t mm_8bit_fetch[8] = { 3, 3, 3, 3, 2, 1, 0, 0 };
67
68 static const uint32_t mm_16bit_commands[16] = {
69 0x0001, 0x0003, 0x0007, 0x000F, 0x001E, 0x003C, 0x0078, 0x00F0,
70 0x01F0, 0x03F0, 0x07F0, 0x0FF0, 0x1FF0, 0x3FF0, 0x7FF0, 0xFFF0,
71 };
72
do_test_swname(const char * broker,const char * swname,const char * swversion,const char * exp_swname,const char * exp_swversion)73 static const uint32_t mm_16bit_fetch[16] = { 4, 4, 4, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
74
75
76
77 static uint32_t get_bits(mm_bit_buffer_t *bb, uint32_t bits)
78 {
79 uint32_t d;
80 if (!bits) return 0;
81 while (bb->bits < 24) {
82 bb->buffer |= ((bb->src < bb->end) ? *bb->src++ : 0) << bb->bits;
83 bb->bits += 8;
84 }
85 d = bb->buffer & ((1 << bits) - 1);
86 bb->buffer >>= bits;
87 bb->bits -= bits;
88 return d;
89 }
90
91
92 int mmcmp_unpack(uint8_t **data, size_t *length)
93 {
94 size_t memlength;
95 uint8_t *memfile;
96 uint8_t *buffer;
97 mm_header_t hdr;
98 uint32_t *pblk_table;
99 size_t filesize;
100 uint32_t block, i;
101
102 if (!data || !*data || !length || *length < 256) {
103 return 0;
104 }
105 memlength = *length;
106 memfile = *data;
107
108 memcpy(&hdr, memfile, sizeof(hdr));
main_0016_client_swname(int argc,char ** argv)109 hdr.hdrsize = bswapLE16(hdr.hdrsize);
110 hdr.version = bswapLE16(hdr.version);
111 hdr.blocks = bswapLE16(hdr.blocks);
112 hdr.filesize = bswapLE32(hdr.filesize);
113 hdr.blktable = bswapLE32(hdr.blktable);
114
115 if (memcmp(hdr.zirconia, "ziRCONia", 8) != 0
116 || hdr.hdrsize < 14
117 || hdr.blocks == 0
118 || hdr.filesize < 16
119 || hdr.filesize > 0x8000000
120 || hdr.blktable >= memlength
121 || hdr.blktable + 4 * hdr.blocks > memlength) {
122 return 0;
123 }
124 filesize = hdr.filesize;
125 if ((buffer = calloc(1, (filesize + 31) & ~15)) == NULL)
126 return 0;
127
128 pblk_table = (uint32_t *) (memfile + hdr.blktable);
129
130 for (block = 0; block < hdr.blocks; block++) {
131 uint32_t pos = bswapLE32(pblk_table[block]);
132 mm_subblock_t *psubblk = (mm_subblock_t *) (memfile + pos + 20);
133 mm_block_t pblk;
134
135 memcpy(&pblk, memfile + pos, sizeof(pblk));
136 pblk.unpk_size = bswapLE32(pblk.unpk_size);
137 pblk.pk_size = bswapLE32(pblk.pk_size);
138 pblk.xor_chk = bswapLE32(pblk.xor_chk);
139 pblk.sub_blk = bswapLE16(pblk.sub_blk);
140 pblk.flags = bswapLE16(pblk.flags);
141 pblk.tt_entries = bswapLE16(pblk.tt_entries);
142 pblk.num_bits = bswapLE16(pblk.num_bits);
143
144 if ((pos + 20 >= memlength)
145 || (pos + 20 + pblk.sub_blk * 8 >= memlength)) {
146 break;
147 }
148 pos += 20 + pblk.sub_blk * 8;
149
150 if (!(pblk.flags & MM_COMP)) {
151 /* Data is not packed */
152 for (i = 0; i < pblk.sub_blk; i++) {
153 uint32_t unpk_pos = bswapLE32(psubblk->unpk_pos);
154 uint32_t unpk_size = bswapLE32(psubblk->unpk_size);
155 if ((unpk_pos > filesize)
156 || (unpk_pos + unpk_size > filesize)) {
157 break;
158 }
159 memcpy(buffer + unpk_pos, memfile + pos, unpk_size);
160 pos += unpk_size;
161 psubblk++;
162 }
163 } else if (pblk.flags & MM_16BIT) {
164 /* Data is 16-bit packed */
165 uint16_t *dest = (uint16_t *) (buffer + bswapLE32(psubblk->unpk_pos));
166 uint32_t size = bswapLE32(psubblk->unpk_size) >> 1;
167 uint32_t destpos = 0;
168 uint32_t numbits = pblk.num_bits;
169 uint32_t subblk = 0, oldval = 0;
170
171 mm_bit_buffer_t bb = {
172 .bits = 0,
173 .buffer = 0,
174 .src = memfile + pos + pblk.tt_entries,
175 .end = memfile + pos + pblk.pk_size,
176 };
177
178 while (subblk < pblk.sub_blk) {
179 uint32_t newval = 0x10000;
180 uint32_t d = get_bits(&bb, numbits + 1);
181
182 if (d >= mm_16bit_commands[numbits]) {
183 uint32_t fetch = mm_16bit_fetch[numbits];
184 uint32_t newbits = get_bits(&bb, fetch)
185 + ((d - mm_16bit_commands[numbits]) << fetch);
186 if (newbits != numbits) {
187 numbits = newbits & 0x0F;
188 } else {
189 if ((d = get_bits(&bb, 4)) == 0x0F) {
190 if (get_bits(&bb, 1))
191 break;
192 newval = 0xFFFF;
193 } else {
194 newval = 0xFFF0 + d;
195 }
196 }
197 } else {
198 newval = d;
199 }
200 if (newval < 0x10000) {
201 newval = (newval & 1)
202 ? (uint32_t) (-(int32_t)((newval + 1) >> 1))
203 : (uint32_t) (newval >> 1);
204 if (pblk.flags & MM_DELTA) {
205 newval += oldval;
206 oldval = newval;
207 } else if (!(pblk.flags & MM_ABS16)) {
208 newval ^= 0x8000;
209 }
210 dest[destpos++] = bswapLE16((uint16_t) newval);
211 }
212 if (destpos >= size) {
213 subblk++;
214 destpos = 0;
215 size = bswapLE32(psubblk[subblk].unpk_size) >> 1;
216 dest = (uint16_t *)(buffer + bswapLE32(psubblk[subblk].unpk_pos));
217 }
218 }
219 } else {
220 /* Data is 8-bit packed */
221 uint8_t *dest = buffer + bswapLE32(psubblk->unpk_pos);
222 uint32_t size = bswapLE32(psubblk->unpk_size);
223 uint32_t destpos = 0;
224 uint32_t numbits = pblk.num_bits;
225 uint32_t subblk = 0, oldval = 0;
226 uint8_t *ptable = memfile + pos;
227
228 mm_bit_buffer_t bb = {
229 .bits = 0,
230 .buffer = 0,
231 .src = memfile + pos + pblk.tt_entries,
232 .end = memfile + pos + pblk.pk_size,
233 };
234
235 while (subblk < pblk.sub_blk) {
236 uint32_t newval = 0x100;
237 uint32_t d = get_bits(&bb, numbits + 1);
238
239 if (d >= mm_8bit_commands[numbits]) {
240 uint32_t fetch = mm_8bit_fetch[numbits];
241 uint32_t newbits = get_bits(&bb, fetch)
242 + ((d - mm_8bit_commands[numbits]) << fetch);
243 if (newbits != numbits) {
244 numbits = newbits & 0x07;
245 } else {
246 if ((d = get_bits(&bb, 3)) == 7) {
247 if (get_bits(&bb, 1))
248 break;
249 newval = 0xFF;
250 } else {
251 newval = 0xF8 + d;
252 }
253 }
254 } else {
255 newval = d;
256 }
257 if (newval < 0x100) {
258 int n = ptable[newval];
259 if (pblk.flags & MM_DELTA) {
260 n += oldval;
261 oldval = n;
262 }
263 dest[destpos++] = (uint8_t) n;
264 }
265 if (destpos >= size) {
266 subblk++;
267 destpos = 0;
268 size = bswapLE32(psubblk[subblk].unpk_size);
269 dest = buffer + bswapLE32(psubblk[subblk].unpk_pos);
270 }
271 }
272 }
273 }
274 *data = buffer;
275 *length = filesize;
276 return 1;
277 }
278
279