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