1 /***************************************************************************
2 
3     chd.c
4 
5     MAME Compressed Hunks of Data file format
6 
7 ****************************************************************************
8 
9     Copyright Aaron Giles
10     All rights reserved.
11 
12     Redistribution and use in source and binary forms, with or without
13     modification, are permitted provided that the following conditions are
14     met:
15 
16         * Redistributions of source code must retain the above copyright
17           notice, this list of conditions and the following disclaimer.
18         * Redistributions in binary form must reproduce the above copyright
19           notice, this list of conditions and the following disclaimer in
20           the documentation and/or other materials provided with the
21           distribution.
22         * Neither the name 'MAME' nor the names of its contributors may be
23           used to endorse or promote products derived from this software
24           without specific prior written permission.
25 
26     THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
27     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29     DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
30     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34     STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
35     IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36     POSSIBILITY OF SUCH DAMAGE.
37 
38 ***************************************************************************/
39 #define DONT_SET_BYTE
40 typedef unsigned char Byte;
41 
42 #include "chd.h"
43 #include "cdrom.h"
44 #include "huffman.h"
45 #include "flac.h"
46 
47 #include "md5.h"
48 #include "sha1.h"
49 #include "LzmaEnc.h"
50 #include "LzmaDec.h"
51 
52 #include <string.h>
53 #include <zlib.h>
54 
55 #include <time.h>
56 #include <stddef.h>
57 #include <stdlib.h>
58 #include <stdio.h>
59 
60 #include <retro_inline.h>
61 
62 #include "../deps/crypto/md5.h"
63 
64 #define TRUE 1
65 #define FALSE 0
66 
67 #define MAX(x, y) (((x) > (y)) ? (x) : (y))
68 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
69 
70 #define SHA1_DIGEST_SIZE 20
71 
72 #define CHD_MAKE_TAG(a,b,c,d)       (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
73 
74 /***************************************************************************
75     DEBUGGING
76 ***************************************************************************/
77 
78 #define PRINTF_MAX_HUNK				(0)
79 
80 
81 
82 /***************************************************************************
83     CONSTANTS
84 ***************************************************************************/
85 
86 #define MAP_STACK_ENTRIES			512			/* max number of entries to use on the stack */
87 #define MAP_ENTRY_SIZE				16			/* V3 and later */
88 #define OLD_MAP_ENTRY_SIZE			8			/* V1-V2 */
89 #define METADATA_HEADER_SIZE		16			/* metadata header size */
90 #define CRCMAP_HASH_SIZE			4095		/* number of CRC hashtable entries */
91 
92 #define MAP_ENTRY_FLAG_TYPE_MASK	0x0f		/* what type of hunk */
93 #define MAP_ENTRY_FLAG_NO_CRC		0x10		/* no CRC is present */
94 
95 #define CHD_V1_SECTOR_SIZE			512			/* size of a "sector" in the V1 header */
96 
97 #define COOKIE_VALUE				0xbaadf00d
98 #define MAX_ZLIB_ALLOCS				64
99 
100 #define END_OF_LIST_COOKIE			"EndOfListCookie"
101 
102 #define NO_MATCH					(~0)
103 
104 static const uint8_t s_cd_sync_header[12] = { 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 };
105 
106 // V3-V4 entry types
107 enum
108 {
109 	V34_MAP_ENTRY_TYPE_INVALID = 0,             // invalid type
110 	V34_MAP_ENTRY_TYPE_COMPRESSED = 1,          // standard compression
111 	V34_MAP_ENTRY_TYPE_UNCOMPRESSED = 2,        // uncompressed data
112 	V34_MAP_ENTRY_TYPE_MINI = 3,                // mini: use offset as raw data
113 	V34_MAP_ENTRY_TYPE_SELF_HUNK = 4,           // same as another hunk in this file
114 	V34_MAP_ENTRY_TYPE_PARENT_HUNK = 5,         // same as a hunk in the parent file
115 	V34_MAP_ENTRY_TYPE_2ND_COMPRESSED = 6       // compressed with secondary algorithm (usually FLAC CDDA)
116 };
117 
118 // V5 compression types
119 enum
120 {
121 	///< codec #0
122 	// these types are live when running
123 	COMPRESSION_TYPE_0 = 0,
124 	///< codec #1
125 	COMPRESSION_TYPE_1 = 1,
126 	///< codec #2
127 	COMPRESSION_TYPE_2 = 2,
128 	///< codec #3
129 	COMPRESSION_TYPE_3 = 3,
130 	///< no compression; implicit length = hunkbytes
131 	COMPRESSION_NONE = 4,
132 	///< same as another block in this chd
133 	COMPRESSION_SELF = 5,
134 	///< same as a hunk's worth of units in the parent chd
135 	COMPRESSION_PARENT = 6,
136 
137 	///< start of small RLE run (4-bit length)
138 	// these additional pseudo-types are used for compressed encodings:
139 	COMPRESSION_RLE_SMALL,
140 	///< start of large RLE run (8-bit length)
141 	COMPRESSION_RLE_LARGE,
142 	///< same as the last COMPRESSION_SELF block
143 	COMPRESSION_SELF_0,
144 	///< same as the last COMPRESSION_SELF block + 1
145 	COMPRESSION_SELF_1,
146 	///< same block in the parent
147 	COMPRESSION_PARENT_SELF,
148 	///< same as the last COMPRESSION_PARENT block
149 	COMPRESSION_PARENT_0,
150 	///< same as the last COMPRESSION_PARENT block + 1
151 	COMPRESSION_PARENT_1
152 };
153 
154 
155 /***************************************************************************
156     MACROS
157 ***************************************************************************/
158 
159 #define EARLY_EXIT(x)				do { (void)(x); goto cleanup; } while (0)
160 
161 
162 
163 /***************************************************************************
164     TYPE DEFINITIONS
165 ***************************************************************************/
166 
167 /* interface to a codec */
168 typedef struct _codec_interface codec_interface;
169 struct _codec_interface
170 {
171 	UINT32		compression;								/* type of compression */
172 	const char *compname;									/* name of the algorithm */
173 	UINT8		lossy;										/* is this a lossy algorithm? */
174 	chd_error	(*init)(void *codec, UINT32 hunkbytes);		/* codec initialize */
175 	void		(*free)(void *codec);						/* codec free */
176 	chd_error	(*decompress)(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); /* decompress data */
177 	chd_error	(*config)(void *codec, int param, void *config); /* configure */
178 };
179 
180 
181 /* a single map entry */
182 typedef struct _map_entry map_entry;
183 struct _map_entry
184 {
185 	UINT64					offset;			/* offset within the file of the data */
186 	UINT32					crc;			/* 32-bit CRC of the data */
187 	UINT32					length;			/* length of the data */
188 	UINT8					flags;			/* misc flags */
189 };
190 
191 
192 /* simple linked-list of hunks used for our CRC map */
193 typedef struct _crcmap_entry crcmap_entry;
194 struct _crcmap_entry
195 {
196 	UINT32					hunknum;		/* hunk number */
197 	crcmap_entry *			next;			/* next entry in list */
198 };
199 
200 
201 /* a single metadata entry */
202 typedef struct _metadata_entry metadata_entry;
203 struct _metadata_entry
204 {
205 	UINT64					offset;			/* offset within the file of the header */
206 	UINT64					next;			/* offset within the file of the next header */
207 	UINT64					prev;			/* offset within the file of the previous header */
208 	UINT32					length;			/* length of the metadata */
209 	UINT32					metatag;		/* metadata tag */
210 	UINT8					flags;			/* flag bits */
211 };
212 
213 /* codec-private data for the ZLIB codec */
214 
215 typedef struct _zlib_allocator zlib_allocator;
216 struct _zlib_allocator
217 {
218 	UINT32 *				allocptr[MAX_ZLIB_ALLOCS];
219 };
220 
221 typedef struct _zlib_codec_data zlib_codec_data;
222 struct _zlib_codec_data
223 {
224 	z_stream				inflater;
225 	zlib_allocator			allocator;
226 };
227 
228 /* codec-private data for the LZMA codec */
229 #define MAX_LZMA_ALLOCS 64
230 
231 typedef struct _lzma_allocator lzma_allocator;
232 struct _lzma_allocator
233 {
234 	void *(*Alloc)(void *p, size_t size);
235  	void (*Free)(void *p, void *address); /* address can be 0 */
236 	void (*FreeSz)(void *p, void *address, size_t size); /* address can be 0 */
237 	uint32_t*	allocptr[MAX_LZMA_ALLOCS];
238 };
239 
240 typedef struct _lzma_codec_data lzma_codec_data;
241 struct _lzma_codec_data
242 {
243 	CLzmaDec		decoder;
244 	lzma_allocator	allocator;
245 };
246 
247 /* codec-private data for the CDZL codec */
248 typedef struct _cdzl_codec_data cdzl_codec_data;
249 struct _cdzl_codec_data {
250 	// internal state
251 	zlib_codec_data		base_decompressor;
252 	zlib_codec_data		subcode_decompressor;
253 	uint8_t*			buffer;
254 };
255 
256 /* codec-private data for the CDLZ codec */
257 typedef struct _cdlz_codec_data cdlz_codec_data;
258 struct _cdlz_codec_data {
259 	// internal state
260 	lzma_codec_data		base_decompressor;
261 	zlib_codec_data		subcode_decompressor;
262 	uint8_t*			buffer;
263 };
264 
265 /* codec-private data for the CDFL codec */
266 typedef struct _cdfl_codec_data cdfl_codec_data;
267 struct _cdfl_codec_data {
268 	// internal state
269 	int		swap_endian;
270 	flac_decoder	decoder;
271 	z_stream	inflater;
272 	zlib_allocator	allocator;
273 	uint8_t*	buffer;
274 };
275 
276 /* internal representation of an open CHD file */
277 struct _chd_file
278 {
279 	UINT32					cookie;			/* cookie, should equal COOKIE_VALUE */
280 
281 	core_file *				file;			/* handle to the open core file */
282 	UINT8					owns_file;		/* flag indicating if this file should be closed on chd_close() */
283 	chd_header				header;			/* header, extracted from file */
284 
285 	chd_file *				parent;			/* pointer to parent file, or NULL */
286 
287 	map_entry *				map;			/* array of map entries */
288 
289 	UINT8 *					cache;			/* hunk cache pointer */
290 	UINT32					cachehunk;		/* index of currently cached hunk */
291 
292 	UINT8 *					compare;		/* hunk compare pointer */
293 	UINT32					comparehunk;	/* index of current compare data */
294 
295 	UINT8 *					compressed;		/* pointer to buffer for compressed data */
296 	const codec_interface *	codecintf[4];	/* interface to the codec */
297 
298 	zlib_codec_data			zlib_codec_data;		/* zlib codec data */
299 	cdzl_codec_data			cdzl_codec_data;		/* cdzl codec data */
300 	cdlz_codec_data			cdlz_codec_data;		/* cdlz codec data */
301 	cdfl_codec_data			cdfl_codec_data;		/* cdfl codec data */
302 
303 	crcmap_entry *			crcmap;			/* CRC map entries */
304 	crcmap_entry *			crcfree;		/* free list CRC entries */
305 	crcmap_entry **			crctable;		/* table of CRC entries */
306 
307 	UINT32					maxhunk;		/* maximum hunk accessed */
308 
309 	UINT8					compressing;	/* are we compressing? */
310 	MD5_CTX					compmd5;		/* running MD5 during compression */
311 	SHA1_CTX				compsha1;		/* running SHA1 during compression */
312 	UINT32					comphunk;		/* next hunk we will compress */
313 
314 	UINT8					verifying;		/* are we verifying? */
315 	MD5_CTX					vermd5; 		/* running MD5 during verification */
316 	SHA1_CTX				versha1;		/* running SHA1 during verification */
317 	UINT32					verhunk;		/* next hunk we will verify */
318 
319 	UINT32					async_hunknum;	/* hunk index for asynchronous operations */
320 	void *					async_buffer;	/* buffer pointer for asynchronous operations */
321 };
322 
323 
324 /* a single metadata hash entry */
325 typedef struct _metadata_hash metadata_hash;
326 struct _metadata_hash
327 {
328 	UINT8					tag[4];			/* tag of the metadata in big-endian */
329 	UINT8					sha1[CHD_SHA1_BYTES]; /* hash */
330 };
331 
332 
333 
334 /***************************************************************************
335     GLOBAL VARIABLES
336 ***************************************************************************/
337 
338 static const UINT8 nullmd5[CHD_MD5_BYTES] = { 0 };
339 static const UINT8 nullsha1[CHD_SHA1_BYTES] = { 0 };
340 
341 
342 
343 /***************************************************************************
344     PROTOTYPES
345 ***************************************************************************/
346 
347 /* internal header operations */
348 static chd_error header_validate(const chd_header *header);
349 static chd_error header_read(core_file *file, chd_header *header);
350 
351 
352 /* internal hunk read/write */
353 static chd_error hunk_read_into_cache(chd_file *chd, UINT32 hunknum);
354 static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *dest);
355 
356 /* internal map access */
357 static chd_error map_read(chd_file *chd);
358 
359 /* metadata management */
360 static chd_error metadata_find_entry(chd_file *chd, UINT32 metatag, UINT32 metaindex, metadata_entry *metaentry);
361 
362 
363 /* zlib compression codec */
364 static chd_error zlib_codec_init(void *codec, uint32_t hunkbytes);
365 static void zlib_codec_free(void *codec);
366 static chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
367 static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size);
368 static void zlib_fast_free(voidpf opaque, voidpf address);
369 
370 /* lzma compression codec */
371 static chd_error lzma_codec_init(void *codec, uint32_t hunkbytes);
372 static void lzma_codec_free(void *codec);
373 static chd_error lzma_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
374 
375 /* cdzl compression codec */
376 static chd_error cdzl_codec_init(void* codec, uint32_t hunkbytes);
377 static void cdzl_codec_free(void* codec);
378 static chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
379 
380 /* cdlz compression codec */
381 static chd_error cdlz_codec_init(void* codec, uint32_t hunkbytes);
382 static void cdlz_codec_free(void* codec);
383 static chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
384 
385 /* cdfl compression codec */
386 static chd_error cdfl_codec_init(void* codec, uint32_t hunkbytes);
387 static void cdfl_codec_free(void* codec);
388 static chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
389 
390 //**************************************************************************
391 //  LZMA ALLOCATOR HELPER
392 //**************************************************************************
393 
394 void *lzma_fast_alloc(void *p, size_t size);
395 void lzma_fast_free(void *p, void *address);
396 
397 //-------------------------------------------------
398 //  lzma_allocator_init
399 //-------------------------------------------------
400 
lzma_allocator_init(void * p)401 void lzma_allocator_init(void* p)
402 {
403 	lzma_allocator *codec = (lzma_allocator *)(p);
404 
405 	// reset pointer list
406 	memset(codec->allocptr, 0, sizeof(codec->allocptr));
407 	codec->Alloc = lzma_fast_alloc;
408 	codec->Free = lzma_fast_free;
409 }
410 
411 //-------------------------------------------------
412 //  lzma_allocator_free
413 //-------------------------------------------------
414 
lzma_allocator_free(void * p)415 void lzma_allocator_free(void* p )
416 {
417    int i;
418 	lzma_allocator *codec = (lzma_allocator *)(p);
419 
420 	// free our memory
421 	for (i = 0 ; i < MAX_LZMA_ALLOCS ; i++)
422 	{
423 		if (codec->allocptr[i] != NULL)
424 			free(codec->allocptr[i]);
425 	}
426 }
427 
428 //-------------------------------------------------
429 //  lzma_fast_alloc - fast malloc for lzma, which
430 //  allocates and frees memory frequently
431 //-------------------------------------------------
432 
lzma_fast_alloc(void * p,size_t size)433 void *lzma_fast_alloc(void *p, size_t size)
434 {
435    int scan;
436    uint32_t *addr        = NULL;
437 	lzma_allocator *codec = (lzma_allocator *)(p);
438 
439 	// compute the size, rounding to the nearest 1k
440 	size = (size + 0x3ff) & ~0x3ff;
441 
442 	// reuse a hunk if we can
443 	for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
444 	{
445 		uint32_t *ptr = codec->allocptr[scan];
446 		if (ptr != NULL && size == *ptr)
447 		{
448 			// set the low bit of the size so we don't match next time
449 			*ptr |= 1;
450 			return ptr + 1;
451 		}
452 	}
453 
454 	// alloc a new one and put it into the list
455 	addr = (uint32_t *)malloc(sizeof(uint8_t) * (size + sizeof(uint32_t)));
456 	if (addr==NULL)
457 		return NULL;
458 	for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
459 	{
460 		if (codec->allocptr[scan] == NULL)
461 		{
462 			codec->allocptr[scan] = addr;
463 			break;
464 		}
465 	}
466 
467 	// set the low bit of the size so we don't match next time
468 	*addr = size | 1;
469 	return addr + 1;
470 }
471 
472 
473 //-------------------------------------------------
474 //  lzma_fast_free - fast free for lzma, which
475 //  allocates and frees memory frequently
476 //-------------------------------------------------
477 
lzma_fast_free(void * p,void * address)478 void lzma_fast_free(void *p, void *address)
479 {
480    int scan;
481    uint32_t *ptr;
482    lzma_allocator *codec;
483 	if (address == NULL)
484 		return;
485 
486 	codec = (lzma_allocator *)(p);
487 
488 	// find the hunk
489 	ptr = (uint32_t *)(address) - 1;
490 	for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
491 	{
492 		if (ptr == codec->allocptr[scan])
493 		{
494 			// clear the low bit of the size to allow matches
495 			*ptr &= ~1;
496 			return;
497 		}
498 	}
499 }
500 
501 //**************************************************************************
502 //  LZMA DECOMPRESSOR
503 //**************************************************************************
504 
505 
506 //-------------------------------------------------
507 //  lzma_codec_init - constructor
508 //-------------------------------------------------
509 
lzma_codec_init(void * codec,uint32_t hunkbytes)510 chd_error lzma_codec_init(void* codec, uint32_t hunkbytes)
511 {
512    CLzmaEncHandle enc;
513 	CLzmaEncProps encoder_props;
514 	Byte decoder_props[LZMA_PROPS_SIZE];
515    SizeT props_size;
516    lzma_allocator* alloc;
517 	lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
518 
519 	// construct the decoder
520 	LzmaDec_Construct(&lzma_codec->decoder);
521 
522 	// FIXME: this code is written in a way that makes it impossible to safely upgrade the LZMA SDK
523 	// This code assumes that the current version of the encoder imposes the same requirements on the
524 	// decoder as the encoder used to produce the file.  This is not necessarily true.  The format
525 	// needs to be changed so the encoder properties are written to the file.
526 
527 	// configure the properties like the compressor did
528 	LzmaEncProps_Init(&encoder_props);
529 	encoder_props.level = 9;
530 	encoder_props.reduceSize = hunkbytes;
531 	LzmaEncProps_Normalize(&encoder_props);
532 
533 	// convert to decoder properties
534 	alloc = &lzma_codec->allocator;
535 	lzma_allocator_init(alloc);
536 	enc = LzmaEnc_Create((ISzAlloc*)alloc);
537 	if (!enc)
538 		return CHDERR_DECOMPRESSION_ERROR;
539 	if (LzmaEnc_SetProps(enc, &encoder_props) != SZ_OK)
540 	{
541 		LzmaEnc_Destroy(enc, (ISzAlloc*)&alloc, (ISzAlloc*)&alloc);
542 		return CHDERR_DECOMPRESSION_ERROR;
543 	}
544 	props_size = sizeof(decoder_props);
545 	if (LzmaEnc_WriteProperties(enc, decoder_props, &props_size) != SZ_OK)
546 	{
547 		LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc);
548 		return CHDERR_DECOMPRESSION_ERROR;
549 	}
550 	LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc);
551 
552 	// do memory allocations
553 	if (LzmaDec_Allocate(&lzma_codec->decoder, decoder_props, LZMA_PROPS_SIZE, (ISzAlloc*)alloc) != SZ_OK)
554 		return CHDERR_DECOMPRESSION_ERROR;
555 
556 	// Okay
557 	return CHDERR_NONE;
558 }
559 
560 
561 //-------------------------------------------------
562 //  lzma_codec_free
563 //-------------------------------------------------
564 
lzma_codec_free(void * codec)565 void lzma_codec_free(void* codec)
566 {
567 	lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
568 
569 	// free memory
570 	LzmaDec_Free(&lzma_codec->decoder, (ISzAlloc*)&lzma_codec->allocator);
571 }
572 
573 
574 //-------------------------------------------------
575 //  decompress - decompress data using the LZMA
576 //  codec
577 //-------------------------------------------------
578 
lzma_codec_decompress(void * codec,const uint8_t * src,uint32_t complen,uint8_t * dest,uint32_t destlen)579 chd_error lzma_codec_decompress(void* codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
580 {
581 	ELzmaStatus status;
582    SRes res;
583    SizeT consumedlen, decodedlen;
584 	// initialize
585 	lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
586 	LzmaDec_Init(&lzma_codec->decoder);
587 
588 	// decode
589 	consumedlen = complen;
590 	decodedlen = destlen;
591 	res = LzmaDec_DecodeToBuf(&lzma_codec->decoder, dest, &decodedlen, src, &consumedlen, LZMA_FINISH_END, &status);
592 	if ((res != SZ_OK && res != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) || consumedlen != complen || decodedlen != destlen)
593 		return CHDERR_DECOMPRESSION_ERROR;
594 	return CHDERR_NONE;
595 }
596 
597 // cdlz
cdlz_codec_init(void * codec,uint32_t hunkbytes)598 chd_error cdlz_codec_init(void* codec, uint32_t hunkbytes)
599 {
600 	cdlz_codec_data* cdlz = (cdlz_codec_data*) codec;
601 
602 	// allocate buffer
603 	cdlz->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
604 
605 	// make sure the CHD's hunk size is an even multiple of the frame size
606 	lzma_codec_init(&cdlz->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
607 	zlib_codec_init(&cdlz->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SUBCODE_DATA);
608 
609 	if (hunkbytes % CD_FRAME_SIZE != 0)
610 		return CHDERR_CODEC_ERROR;
611 
612 	return CHDERR_NONE;
613 }
614 
cdlz_codec_free(void * codec)615 void cdlz_codec_free(void* codec)
616 {
617 	// TODO
618 }
619 
cdlz_codec_decompress(void * codec,const uint8_t * src,uint32_t complen,uint8_t * dest,uint32_t destlen)620 chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
621 {
622    uint32_t framenum;
623 	cdlz_codec_data* cdlz = (cdlz_codec_data*)codec;
624 
625 	// determine header bytes
626 	uint32_t frames = destlen / CD_FRAME_SIZE;
627 	uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
628 	uint32_t ecc_bytes = (frames + 7) / 8;
629 	uint32_t header_bytes = ecc_bytes + complen_bytes;
630 
631 	// extract compressed length of base
632 	uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
633 	if (complen_bytes > 2)
634 		complen_base = (complen_base << 8) | src[ecc_bytes + 2];
635 
636 	// reset and decode
637 	lzma_codec_decompress(&cdlz->base_decompressor, &src[header_bytes], complen_base, &cdlz->buffer[0], frames * CD_MAX_SECTOR_DATA);
638 	zlib_codec_decompress(&cdlz->subcode_decompressor, &src[header_bytes + complen_base], complen - complen_base - header_bytes, &cdlz->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA);
639 
640 	// reassemble the data
641 	for (framenum = 0; framenum < frames; framenum++)
642 	{
643       uint8_t *sector;
644 
645 		memcpy(&dest[framenum * CD_FRAME_SIZE], &cdlz->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
646 		memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdlz->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA);
647 
648 		// reconstitute the ECC data and sync header
649 		sector = &dest[framenum * CD_FRAME_SIZE];
650 		if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
651 		{
652 			memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
653 			ecc_generate(sector);
654 		}
655 	}
656 	return CHDERR_NONE;
657 }
658 
659 
660 // cdzl
661 
cdzl_codec_init(void * codec,uint32_t hunkbytes)662 chd_error cdzl_codec_init(void *codec, uint32_t hunkbytes)
663 {
664 	cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
665 
666 	// make sure the CHD's hunk size is an even multiple of the frame size
667 	zlib_codec_init(&cdzl->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
668 	zlib_codec_init(&cdzl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SUBCODE_DATA);
669 
670 	cdzl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
671 	if (hunkbytes % CD_FRAME_SIZE != 0)
672 		return CHDERR_CODEC_ERROR;
673 
674 	return CHDERR_NONE;
675 }
676 
cdzl_codec_free(void * codec)677 void cdzl_codec_free(void *codec)
678 {
679 	// TODO
680 }
681 
cdzl_codec_decompress(void * codec,const uint8_t * src,uint32_t complen,uint8_t * dest,uint32_t destlen)682 chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
683 {
684    uint32_t framenum;
685 	cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
686 
687 	// determine header bytes
688 	uint32_t frames = destlen / CD_FRAME_SIZE;
689 	uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
690 	uint32_t ecc_bytes = (frames + 7) / 8;
691 	uint32_t header_bytes = ecc_bytes + complen_bytes;
692 
693 	// extract compressed length of base
694 	uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
695 	if (complen_bytes > 2)
696 		complen_base = (complen_base << 8) | src[ecc_bytes + 2];
697 
698 	// reset and decode
699 	zlib_codec_decompress(&cdzl->base_decompressor, &src[header_bytes], complen_base, &cdzl->buffer[0], frames * CD_MAX_SECTOR_DATA);
700 	zlib_codec_decompress(&cdzl->subcode_decompressor, &src[header_bytes + complen_base], complen - complen_base - header_bytes, &cdzl->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA);
701 
702 	// reassemble the data
703 	for (framenum = 0; framenum < frames; framenum++)
704 	{
705       uint8_t *sector;
706 		memcpy(&dest[framenum * CD_FRAME_SIZE], &cdzl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
707 		memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdzl->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA);
708 
709 		// reconstitute the ECC data and sync header
710 		sector = &dest[framenum * CD_FRAME_SIZE];
711 		if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
712 		{
713 			memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
714 			ecc_generate(sector);
715 		}
716 	}
717 	return CHDERR_NONE;
718 }
719 
720 //**************************************************************************
721 //  CD FLAC DECOMPRESSOR
722 //**************************************************************************
723 
724 
725 
726 //------------------------------------------------------
727 //  cdfl_codec_blocksize - return the optimal block size
728 //------------------------------------------------------
729 
cdfl_codec_blocksize(uint32_t bytes)730 static uint32_t cdfl_codec_blocksize(uint32_t bytes)
731 {
732 	// determine FLAC block size, which must be 16-65535
733 	// clamp to 2k since that's supposed to be the sweet spot
734 	uint32_t hunkbytes = bytes / 4;
735 	while (hunkbytes > 2048)
736 		hunkbytes /= 2;
737 	return hunkbytes;
738 }
739 
cdfl_codec_init(void * codec,uint32_t hunkbytes)740 chd_error cdfl_codec_init(void *codec, uint32_t hunkbytes)
741 {
742    int zerr;
743 	uint16_t native_endian = 0;
744 	cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
745 
746 	cdfl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
747 
748 	// make sure the CHD's hunk size is an even multiple of the frame size
749 	if (hunkbytes % CD_FRAME_SIZE != 0)
750 		return CHDERR_CODEC_ERROR;
751 
752 	// determine whether we want native or swapped samples
753 	*(uint8_t *)(&native_endian) = 1;
754 	cdfl->swap_endian = (native_endian & 1);
755 
756 	// init the inflater
757 	cdfl->inflater.next_in = (Bytef *)cdfl; // bogus, but that's ok
758 	cdfl->inflater.avail_in = 0;
759     //cdfl->allocator.install(cdfl->inflater);
760 	cdfl->inflater.zalloc = zlib_fast_alloc;
761 	cdfl->inflater.zfree = zlib_fast_free;
762 	cdfl->inflater.opaque = &cdfl->allocator;
763 	zerr = inflateInit2(&cdfl->inflater, -MAX_WBITS);
764 
765 	// convert errors
766 	if (zerr == Z_MEM_ERROR)
767 		return CHDERR_OUT_OF_MEMORY;
768 	else if (zerr != Z_OK)
769 		return CHDERR_CODEC_ERROR;
770 
771 	// init flac decoder
772 	flac_decoder_init(&cdfl->decoder);
773 
774 	return CHDERR_NONE;
775 }
776 
cdfl_codec_free(void * codec)777 void cdfl_codec_free(void *codec)
778 {
779 	cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
780 	inflateEnd(&cdfl->inflater);
781 }
782 
cdfl_codec_decompress(void * codec,const uint8_t * src,uint32_t complen,uint8_t * dest,uint32_t destlen)783 chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
784 {
785    int zerr;
786    uint8_t *buffer;
787    uint32_t framenum, offset;
788 	cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
789 
790 	// reset and decode
791 	uint32_t frames = destlen / CD_FRAME_SIZE;
792 	if (!flac_decoder_reset(&cdfl->decoder, 44100, 2, cdfl_codec_blocksize(frames * CD_MAX_SECTOR_DATA), src, complen))
793 		return CHDERR_DECOMPRESSION_ERROR;
794 	buffer = &cdfl->buffer[0];
795 	if (!flac_decoder_decode_interleaved(&cdfl->decoder, (int16_t *)(buffer), frames * CD_MAX_SECTOR_DATA/4, cdfl->swap_endian))
796 		return CHDERR_DECOMPRESSION_ERROR;
797 
798 	// inflate the subcode data
799 	offset = flac_decoder_finish(&cdfl->decoder);
800 	cdfl->inflater.next_in = (Bytef *)(src + offset);
801 	cdfl->inflater.avail_in = complen - offset;
802 	cdfl->inflater.total_in = 0;
803 	cdfl->inflater.next_out = &cdfl->buffer[frames * CD_MAX_SECTOR_DATA];
804 	cdfl->inflater.avail_out = frames * CD_MAX_SUBCODE_DATA;
805 	cdfl->inflater.total_out = 0;
806 	zerr = inflateReset(&cdfl->inflater);
807 	if (zerr != Z_OK)
808 		return CHDERR_DECOMPRESSION_ERROR;
809 
810 	// do it
811 	zerr = inflate(&cdfl->inflater, Z_FINISH);
812 	if (zerr != Z_STREAM_END)
813 		return CHDERR_DECOMPRESSION_ERROR;
814 	if (cdfl->inflater.total_out != frames * CD_MAX_SUBCODE_DATA)
815 		return CHDERR_DECOMPRESSION_ERROR;
816 
817 	// reassemble the data
818 	for (framenum = 0; framenum < frames; framenum++)
819 	{
820 		memcpy(&dest[framenum * CD_FRAME_SIZE], &cdfl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
821 		memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdfl->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA);
822 	}
823 
824 	return CHDERR_NONE;
825 }
826 /***************************************************************************
827     CODEC INTERFACES
828 ***************************************************************************/
829 
830 #define CHD_MAKE_TAG(a,b,c,d)       (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
831 
832 // general codecs with CD frontend
833 #define CHD_CODEC_CD_ZLIB CHD_MAKE_TAG('c','d','z','l')
834 #define CHD_CODEC_CD_LZMA CHD_MAKE_TAG('c','d','l','z')
835 #define CHD_CODEC_CD_FLAC CHD_MAKE_TAG('c','d','f','l')
836 
837 static const codec_interface codec_interfaces[] =
838 {
839 	/* "none" or no compression */
840 	{
841 		CHDCOMPRESSION_NONE,
842 		"none",
843 		FALSE,
844 		NULL,
845 		NULL,
846 		NULL,
847 		NULL
848 	},
849 
850 	/* standard zlib compression */
851 	{
852 		CHDCOMPRESSION_ZLIB,
853 		"zlib",
854 		FALSE,
855 		zlib_codec_init,
856 		zlib_codec_free,
857 		zlib_codec_decompress,
858 		NULL
859 	},
860 
861 	/* zlib+ compression */
862 	{
863 		CHDCOMPRESSION_ZLIB_PLUS,
864 		"zlib+",
865 		FALSE,
866 		zlib_codec_init,
867 		zlib_codec_free,
868 		zlib_codec_decompress,
869 		NULL
870 	},
871 
872 	/* V5 CD zlib compression */
873 	{
874 		CHD_CODEC_CD_ZLIB,
875 		"cdzl (CD Deflate)",
876 		FALSE,
877 		cdzl_codec_init,
878 		cdzl_codec_free,
879 		cdzl_codec_decompress,
880 		NULL
881 	},
882 
883 	/* V5 CD lzma compression */
884 	{
885 		CHD_CODEC_CD_LZMA,
886 		"cdlz (CD LZMA)",
887 		FALSE,
888 		cdlz_codec_init,
889 		cdlz_codec_free,
890 		cdlz_codec_decompress,
891 		NULL
892 	},
893 
894 	/* V5 CD flac compression */
895 	{
896 		CHD_CODEC_CD_FLAC,
897 		"cdfl (CD FLAC)",
898 		FALSE,
899 		cdfl_codec_init,
900 		cdfl_codec_free,
901 		cdfl_codec_decompress,
902 		NULL
903 	},
904 };
905 
906 /***************************************************************************
907     INLINE FUNCTIONS
908 ***************************************************************************/
909 
910 /*-------------------------------------------------
911     get_bigendian_uint64 - fetch a UINT64 from
912     the data stream in bigendian order
913 -------------------------------------------------*/
914 
get_bigendian_uint64(const UINT8 * base)915 static INLINE UINT64 get_bigendian_uint64(const UINT8 *base)
916 {
917 	return ((UINT64)base[0] << 56) | ((UINT64)base[1] << 48) | ((UINT64)base[2] << 40) | ((UINT64)base[3] << 32) |
918 			((UINT64)base[4] << 24) | ((UINT64)base[5] << 16) | ((UINT64)base[6] << 8) | (UINT64)base[7];
919 }
920 
921 
922 /*-------------------------------------------------
923     put_bigendian_uint64 - write a UINT64 to
924     the data stream in bigendian order
925 -------------------------------------------------*/
926 
put_bigendian_uint64(UINT8 * base,UINT64 value)927 static INLINE void put_bigendian_uint64(UINT8 *base, UINT64 value)
928 {
929 	base[0] = value >> 56;
930 	base[1] = value >> 48;
931 	base[2] = value >> 40;
932 	base[3] = value >> 32;
933 	base[4] = value >> 24;
934 	base[5] = value >> 16;
935 	base[6] = value >> 8;
936 	base[7] = value;
937 }
938 
939 /*-------------------------------------------------
940     get_bigendian_uint48 - fetch a UINT48 from
941     the data stream in bigendian order
942 -------------------------------------------------*/
943 
get_bigendian_uint48(const UINT8 * base)944 static INLINE UINT64 get_bigendian_uint48(const UINT8 *base)
945 {
946 	return  ((UINT64)base[0] << 40) | ((UINT64)base[1] << 32) |
947 			((UINT64)base[2] << 24) | ((UINT64)base[3] << 16) | ((UINT64)base[4] << 8) | (UINT64)base[5];
948 }
949 
950 /*-------------------------------------------------
951     put_bigendian_uint48 - write a UINT48 to
952     the data stream in bigendian order
953 -------------------------------------------------*/
954 
put_bigendian_uint48(UINT8 * base,UINT64 value)955 static INLINE void put_bigendian_uint48(UINT8 *base, UINT64 value)
956 {
957 	value &= 0xffffffffffff;
958 	base[0] = value >> 40;
959 	base[1] = value >> 32;
960 	base[2] = value >> 24;
961 	base[3] = value >> 16;
962 	base[4] = value >> 8;
963 	base[5] = value;
964 }
965 /*-------------------------------------------------
966     get_bigendian_uint32 - fetch a UINT32 from
967     the data stream in bigendian order
968 -------------------------------------------------*/
969 
get_bigendian_uint32(const UINT8 * base)970 static INLINE UINT32 get_bigendian_uint32(const UINT8 *base)
971 {
972 	return (base[0] << 24) | (base[1] << 16) | (base[2] << 8) | base[3];
973 }
974 
975 
976 /*-------------------------------------------------
977     put_bigendian_uint32 - write a UINT32 to
978     the data stream in bigendian order
979 -------------------------------------------------*/
980 
put_bigendian_uint24(UINT8 * base,UINT32 value)981 static INLINE void put_bigendian_uint24(UINT8 *base, UINT32 value)
982 {
983 	value &= 0xffffff;
984 	base[0] = value >> 16;
985 	base[1] = value >> 8;
986 	base[2] = value;
987 }
988 
989 
990 /*-------------------------------------------------
991     put_bigendian_uint24 - write a UINT24 to
992     the data stream in bigendian order
993 -------------------------------------------------*/
994 
put_bigendian_uint32(UINT8 * base,UINT32 value)995 static INLINE void put_bigendian_uint32(UINT8 *base, UINT32 value)
996 {
997 	value &= 0xffffff;
998 	base[0] = value >> 16;
999 	base[1] = value >> 8;
1000 	base[2] = value;
1001 }
1002 
1003 /*-------------------------------------------------
1004     get_bigendian_uint24 - fetch a UINT24 from
1005     the data stream in bigendian order
1006 -------------------------------------------------*/
1007 
get_bigendian_uint24(const UINT8 * base)1008 static INLINE UINT32 get_bigendian_uint24(const UINT8 *base)
1009 {
1010 	return (base[0] << 16) | (base[1] << 8) | base[2];
1011 }
1012 
1013 /*-------------------------------------------------
1014     get_bigendian_uint16 - fetch a UINT16 from
1015     the data stream in bigendian order
1016 -------------------------------------------------*/
1017 
get_bigendian_uint16(const UINT8 * base)1018 static INLINE UINT16 get_bigendian_uint16(const UINT8 *base)
1019 {
1020 	return (base[0] << 8) | base[1];
1021 }
1022 
1023 
1024 /*-------------------------------------------------
1025     put_bigendian_uint16 - write a UINT16 to
1026     the data stream in bigendian order
1027 -------------------------------------------------*/
1028 
put_bigendian_uint16(UINT8 * base,UINT16 value)1029 static INLINE void put_bigendian_uint16(UINT8 *base, UINT16 value)
1030 {
1031 	base[0] = value >> 8;
1032 	base[1] = value;
1033 }
1034 
1035 
1036 /*-------------------------------------------------
1037     map_extract - extract a single map
1038     entry from the datastream
1039 -------------------------------------------------*/
1040 
map_extract(const UINT8 * base,map_entry * entry)1041 static INLINE void map_extract(const UINT8 *base, map_entry *entry)
1042 {
1043 	entry->offset = get_bigendian_uint64(&base[0]);
1044 	entry->crc = get_bigendian_uint32(&base[8]);
1045 	entry->length = get_bigendian_uint16(&base[12]) | (base[14] << 16);
1046 	entry->flags = base[15];
1047 }
1048 
1049 
1050 /*-------------------------------------------------
1051     map_assemble - write a single map
1052     entry to the datastream
1053 -------------------------------------------------*/
1054 
map_assemble(UINT8 * base,map_entry * entry)1055 static INLINE void map_assemble(UINT8 *base, map_entry *entry)
1056 {
1057 	put_bigendian_uint64(&base[0], entry->offset);
1058 	put_bigendian_uint32(&base[8], entry->crc);
1059 	put_bigendian_uint16(&base[12], entry->length);
1060 	base[14] = entry->length >> 16;
1061 	base[15] = entry->flags;
1062 }
1063 
1064 /*-------------------------------------------------
1065     map_size_v5 - calculate CHDv5 map size
1066 -------------------------------------------------*/
map_size_v5(chd_header * header)1067 static INLINE int map_size_v5(chd_header* header)
1068 {
1069 	return header->hunkcount * header->mapentrybytes;
1070 }
1071 
1072 
1073 /*-------------------------------------------------
1074     crc16 - calculate CRC16 (from hashing.cpp)
1075 -------------------------------------------------*/
crc16(const void * data,uint32_t length)1076 uint16_t crc16(const void *data, uint32_t length)
1077 {
1078 	uint16_t crc = 0xffff;
1079 
1080 	static const uint16_t s_table[256] =
1081 	{
1082 		0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1083 		0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1084 		0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1085 		0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1086 		0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1087 		0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1088 		0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1089 		0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1090 		0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1091 		0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1092 		0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1093 		0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1094 		0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1095 		0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1096 		0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1097 		0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1098 		0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1099 		0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1100 		0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1101 		0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1102 		0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1103 		0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1104 		0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1105 		0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1106 		0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1107 		0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1108 		0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1109 		0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1110 		0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1111 		0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1112 		0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1113 		0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1114 	};
1115 
1116 	const uint8_t *src = (uint8_t*)data;
1117 
1118 	// fetch the current value into a local and rip through the source data
1119 	while (length-- != 0)
1120 		crc = (crc << 8) ^ s_table[(crc >> 8) ^ *src++];
1121 	return crc;
1122 }
1123 
1124 /*-------------------------------------------------
1125 	decompress_v5_map - decompress the v5 map
1126 -------------------------------------------------*/
1127 
decompress_v5_map(chd_file * chd,chd_header * header)1128 static chd_error decompress_v5_map(chd_file* chd, chd_header* header)
1129 {
1130    int hunknum;
1131 	uint8_t lastcomp = 0;
1132 	int repcount = 0;
1133 	uint32_t last_self = 0;
1134 	uint64_t last_parent = 0;
1135    struct bitstream* bitbuf;
1136    uint32_t mapbytes;
1137    uint64_t firstoffs;
1138    uint16_t mapcrc;
1139    uint8_t lengthbits;
1140    uint8_t selfbits;
1141    uint8_t parentbits;
1142    uint8_t *compressed;
1143 	uint8_t rawbuf[16];
1144    struct huffman_decoder* decoder;
1145    enum huffman_error err;
1146    uint64_t curoffset;
1147 
1148 	if (header->mapoffset == 0)
1149 	{
1150 		//memset(header->rawmap, 0xff,map_size_v5(header));
1151 		return CHDERR_READ_ERROR;
1152 	}
1153 
1154 	// read the reader
1155 	core_fseek(chd->file, header->mapoffset, SEEK_SET);
1156 	core_fread(chd->file, rawbuf, sizeof(rawbuf));
1157 	mapbytes = get_bigendian_uint32(&rawbuf[0]);
1158 	firstoffs = get_bigendian_uint48(&rawbuf[4]);
1159 	mapcrc = get_bigendian_uint16(&rawbuf[10]);
1160 	lengthbits = rawbuf[12];
1161 	selfbits = rawbuf[13];
1162 	parentbits = rawbuf[14];
1163 
1164 	// now read the map
1165 	compressed = (uint8_t*)malloc(sizeof(uint8_t) * mapbytes);
1166 	core_fseek(chd->file, header->mapoffset + 16, SEEK_SET);
1167 	core_fread(chd->file, compressed, mapbytes);
1168 	bitbuf = create_bitstream(compressed, sizeof(uint8_t) * mapbytes);
1169 	header->rawmap = (uint8_t*)malloc(sizeof(uint8_t) * map_size_v5(header));
1170 
1171 	// first decode the compression types
1172 	decoder = create_huffman_decoder(16, 8);
1173 	err = huffman_import_tree_rle(decoder, bitbuf);
1174 	if (err != HUFFERR_NONE)
1175 		return CHDERR_DECOMPRESSION_ERROR;
1176 	for (hunknum = 0; hunknum < header->hunkcount; hunknum++)
1177 	{
1178 		uint8_t *rawmap = header->rawmap + (hunknum * 12);
1179 		if (repcount > 0)
1180 			rawmap[0] = lastcomp, repcount--;
1181 		else
1182 		{
1183 			uint8_t val = huffman_decode_one(decoder, bitbuf);
1184 			if (val == COMPRESSION_RLE_SMALL)
1185 				rawmap[0] = lastcomp, repcount = 2 + huffman_decode_one(decoder, bitbuf);
1186 			else if (val == COMPRESSION_RLE_LARGE)
1187 				rawmap[0] = lastcomp, repcount = 2 + 16 + (huffman_decode_one(decoder, bitbuf) << 4), repcount += huffman_decode_one(decoder, bitbuf);
1188 			else
1189 				rawmap[0] = lastcomp = val;
1190 		}
1191 	}
1192 
1193 	// then iterate through the hunks and extract the needed data
1194 	curoffset = firstoffs;
1195 	for (hunknum = 0; hunknum < header->hunkcount; hunknum++)
1196 	{
1197 		uint8_t *rawmap = header->rawmap + (hunknum * 12);
1198 		uint64_t offset = curoffset;
1199 		uint32_t length = 0;
1200 		uint16_t crc = 0;
1201 		switch (rawmap[0])
1202 		{
1203 			// base types
1204 			case COMPRESSION_TYPE_0:
1205 			case COMPRESSION_TYPE_1:
1206 			case COMPRESSION_TYPE_2:
1207 			case COMPRESSION_TYPE_3:
1208 				curoffset += length = bitstream_read(bitbuf, lengthbits);
1209 				crc = bitstream_read(bitbuf, 16);
1210 				break;
1211 
1212 			case COMPRESSION_NONE:
1213 				curoffset += length = header->hunkbytes;
1214 				crc = bitstream_read(bitbuf, 16);
1215 				break;
1216 
1217 			case COMPRESSION_SELF:
1218 				last_self = offset = bitstream_read(bitbuf, selfbits);
1219 				break;
1220 
1221 			case COMPRESSION_PARENT:
1222 				offset = bitstream_read(bitbuf, parentbits);
1223 				last_parent = offset;
1224 				break;
1225 
1226 			// pseudo-types; convert into base types
1227 			case COMPRESSION_SELF_1:
1228 				last_self++;
1229 			case COMPRESSION_SELF_0:
1230 				rawmap[0] = COMPRESSION_SELF;
1231 				offset = last_self;
1232 				break;
1233 
1234 			case COMPRESSION_PARENT_SELF:
1235 				rawmap[0] = COMPRESSION_PARENT;
1236 				last_parent = offset = ( ((uint64_t)hunknum) * ((uint64_t)header->hunkbytes) ) / header->unitbytes;
1237 				break;
1238 
1239 			case COMPRESSION_PARENT_1:
1240 				last_parent += header->hunkbytes / header->unitbytes;
1241 			case COMPRESSION_PARENT_0:
1242 				rawmap[0] = COMPRESSION_PARENT;
1243 				offset = last_parent;
1244 				break;
1245 		}
1246 		// UINT24 length
1247 		put_bigendian_uint24(&rawmap[1], length);
1248 
1249 		// UINT48 offset
1250 		put_bigendian_uint48(&rawmap[4], offset);
1251 
1252 		// crc16
1253 		put_bigendian_uint16(&rawmap[10], crc);
1254 	}
1255 
1256 	// verify the final CRC
1257 	if (crc16(&header->rawmap[0], header->hunkcount * 12) != mapcrc)
1258 		return CHDERR_DECOMPRESSION_ERROR;
1259 
1260 	return CHDERR_NONE;
1261 }
1262 
1263 /*-------------------------------------------------
1264     map_extract_old - extract a single map
1265     entry in old format from the datastream
1266 -------------------------------------------------*/
1267 
map_extract_old(const UINT8 * base,map_entry * entry,UINT32 hunkbytes)1268 static INLINE void map_extract_old(const UINT8 *base, map_entry *entry, UINT32 hunkbytes)
1269 {
1270 	entry->offset = get_bigendian_uint64(&base[0]);
1271 	entry->crc = 0;
1272 	entry->length = entry->offset >> 44;
1273 	entry->flags = MAP_ENTRY_FLAG_NO_CRC | ((entry->length == hunkbytes) ? V34_MAP_ENTRY_TYPE_UNCOMPRESSED : V34_MAP_ENTRY_TYPE_COMPRESSED);
1274 #ifdef __MWERKS__
1275 	entry->offset = entry->offset & 0x00000FFFFFFFFFFFLL;
1276 #else
1277 	entry->offset = (entry->offset << 20) >> 20;
1278 #endif
1279 }
1280 
1281 
1282 /***************************************************************************
1283     CHD FILE MANAGEMENT
1284 ***************************************************************************/
1285 
1286 
1287 /*-------------------------------------------------
1288     chd_open_file - open a CHD file for access
1289 -------------------------------------------------*/
1290 
chd_open_file(core_file * file,int mode,chd_file * parent,chd_file ** chd)1291 chd_error chd_open_file(core_file *file, int mode, chd_file *parent, chd_file **chd)
1292 {
1293 	chd_file *newchd = NULL;
1294 	chd_error err;
1295 	int intfnum;
1296 
1297 	/* verify parameters */
1298 	if (file == NULL)
1299 		EARLY_EXIT(err = CHDERR_INVALID_PARAMETER);
1300 
1301 	/* punt if invalid parent */
1302 	if (parent != NULL && parent->cookie != COOKIE_VALUE)
1303 		EARLY_EXIT(err = CHDERR_INVALID_PARAMETER);
1304 
1305 	/* allocate memory for the final result */
1306 	newchd = (chd_file *)malloc(sizeof(chd_file));
1307 	if (newchd == NULL)
1308 		EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
1309 	memset(newchd, 0, sizeof(chd_file));
1310 	newchd->cookie = COOKIE_VALUE;
1311 	newchd->parent = parent;
1312 	newchd->file = file;
1313 
1314 	/* now attempt to read the header */
1315 	err = header_read(newchd->file, &newchd->header);
1316 	if (err != CHDERR_NONE)
1317 		EARLY_EXIT(err);
1318 
1319 	/* validate the header */
1320 	err = header_validate(&newchd->header);
1321 	if (err != CHDERR_NONE)
1322 		EARLY_EXIT(err);
1323 
1324 	/* make sure we don't open a read-only file writeable */
1325 	if (mode == CHD_OPEN_READWRITE && !(newchd->header.flags & CHDFLAGS_IS_WRITEABLE))
1326 		EARLY_EXIT(err = CHDERR_FILE_NOT_WRITEABLE);
1327 
1328 	/* also, never open an older version writeable */
1329 	if (mode == CHD_OPEN_READWRITE && newchd->header.version < CHD_HEADER_VERSION)
1330 		EARLY_EXIT(err = CHDERR_UNSUPPORTED_VERSION);
1331 
1332 	/* if we need a parent, make sure we have one */
1333 	if (parent == NULL && (newchd->header.flags & CHDFLAGS_HAS_PARENT))
1334 		EARLY_EXIT(err = CHDERR_REQUIRES_PARENT);
1335 
1336 	/* make sure we have a valid parent */
1337 	if (parent != NULL)
1338 	{
1339 		/* check MD5 if it isn't empty */
1340 		if (memcmp(nullmd5, newchd->header.parentmd5, sizeof(newchd->header.parentmd5)) != 0 &&
1341 			memcmp(nullmd5, newchd->parent->header.md5, sizeof(newchd->parent->header.md5)) != 0 &&
1342 			memcmp(newchd->parent->header.md5, newchd->header.parentmd5, sizeof(newchd->header.parentmd5)) != 0)
1343 			EARLY_EXIT(err = CHDERR_INVALID_PARENT);
1344 
1345 		/* check SHA1 if it isn't empty */
1346 		if (memcmp(nullsha1, newchd->header.parentsha1, sizeof(newchd->header.parentsha1)) != 0 &&
1347 			memcmp(nullsha1, newchd->parent->header.sha1, sizeof(newchd->parent->header.sha1)) != 0 &&
1348 			memcmp(newchd->parent->header.sha1, newchd->header.parentsha1, sizeof(newchd->header.parentsha1)) != 0)
1349 			EARLY_EXIT(err = CHDERR_INVALID_PARENT);
1350 	}
1351 
1352 	/* now read the hunk map */
1353 	if (newchd->header.version < 5)
1354 	{
1355 		err = map_read(newchd);
1356 		if (err != CHDERR_NONE)
1357 			EARLY_EXIT(err);
1358 	}
1359 	else
1360 	{
1361 		err = decompress_v5_map(newchd, &(newchd->header));
1362 	}
1363 
1364 	/* allocate and init the hunk cache */
1365 	newchd->cache = (UINT8 *)malloc(newchd->header.hunkbytes);
1366 	newchd->compare = (UINT8 *)malloc(newchd->header.hunkbytes);
1367 	if (newchd->cache == NULL || newchd->compare == NULL)
1368 		EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
1369 	newchd->cachehunk = ~0;
1370 	newchd->comparehunk = ~0;
1371 
1372 	/* allocate the temporary compressed buffer */
1373 	newchd->compressed = (UINT8 *)malloc(newchd->header.hunkbytes);
1374 	if (newchd->compressed == NULL)
1375 		EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
1376 
1377 	/* find the codec interface */
1378 	if (newchd->header.version < 5)
1379 	{
1380 		for (intfnum = 0; intfnum < ARRAY_LENGTH(codec_interfaces); intfnum++)
1381 			if (codec_interfaces[intfnum].compression == newchd->header.compression[0])
1382 			{
1383 				newchd->codecintf[0] = &codec_interfaces[intfnum];
1384 				break;
1385 			}
1386 		if (intfnum == ARRAY_LENGTH(codec_interfaces))
1387 			EARLY_EXIT(err = CHDERR_UNSUPPORTED_FORMAT);
1388 
1389 		/* initialize the codec */
1390 		if (newchd->codecintf[0]->init != NULL)
1391 			err = (*newchd->codecintf[0]->init)(&newchd->zlib_codec_data, newchd->header.hunkbytes);
1392 	}
1393 	else
1394 	{
1395       int decompnum;
1396 
1397 		// verify the compression types and initialize the codecs
1398 		for (decompnum = 0; decompnum < ARRAY_LENGTH(newchd->header.compression); decompnum++)
1399 		{
1400          int i;
1401 			for (i = 0 ; i < ARRAY_LENGTH(codec_interfaces) ; i++)
1402 			{
1403 				if (codec_interfaces[i].compression == newchd->header.compression[decompnum])
1404 				{
1405 					newchd->codecintf[decompnum] = &codec_interfaces[i];
1406 					if (newchd->codecintf[decompnum] == NULL && newchd->header.compression[decompnum] != 0)
1407 						err = CHDERR_UNSUPPORTED_FORMAT;
1408 
1409 					/* initialize the codec */
1410 					if (newchd->codecintf[decompnum]->init != NULL)
1411 					{
1412 						void* codec = NULL;
1413 						switch (newchd->header.compression[decompnum])
1414 						{
1415 							case CHD_CODEC_CD_ZLIB:
1416 								codec = &newchd->cdzl_codec_data;
1417 								break;
1418 
1419 							case CHD_CODEC_CD_LZMA:
1420 								codec = &newchd->cdlz_codec_data;
1421 								break;
1422 
1423 							case CHD_CODEC_CD_FLAC:
1424 								codec = &newchd->cdfl_codec_data;
1425 								break;
1426 						}
1427 						if (codec != NULL)
1428 						{
1429 							err = (*newchd->codecintf[decompnum]->init)(codec, newchd->header.hunkbytes);
1430 						}
1431 					}
1432 				}
1433 			}
1434 		}
1435 	}
1436 
1437 	// HACK
1438 	//if (err != CHDERR_NONE)
1439 	//	EARLY_EXIT(err);
1440 
1441 	/* all done */
1442 	*chd = newchd;
1443 	return CHDERR_NONE;
1444 
1445 cleanup:
1446 	if (newchd != NULL)
1447 		chd_close(newchd);
1448 	return err;
1449 }
1450 
1451 /*-------------------------------------------------
1452     chd_open - open a CHD file by
1453     filename
1454 -------------------------------------------------*/
1455 
chd_open(const char * filename,int mode,chd_file * parent,chd_file ** chd)1456 chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd)
1457 {
1458 	chd_error err;
1459 	core_file *file = NULL;
1460 	UINT32 openflags;
1461 
1462 	/* choose the proper mode */
1463 	switch(mode)
1464 	{
1465 		case CHD_OPEN_READ:
1466 			break;
1467 
1468 		default:
1469 			err = CHDERR_INVALID_PARAMETER;
1470 			goto cleanup;
1471 	}
1472 
1473 	/* open the file */
1474 	file = core_fopen(filename);
1475 	if (file == 0)
1476 	{
1477 		err = CHDERR_FILE_NOT_FOUND;
1478 		goto cleanup;
1479 	}
1480 
1481 	/* now open the CHD */
1482 	err = chd_open_file(file, mode, parent, chd);
1483 	if (err != CHDERR_NONE)
1484 		goto cleanup;
1485 
1486 	/* we now own this file */
1487 	(*chd)->owns_file = TRUE;
1488 
1489 cleanup:
1490 	if ((err != CHDERR_NONE) && (file != NULL))
1491 		core_fclose(file);
1492 	return err;
1493 }
1494 
1495 
1496 /*-------------------------------------------------
1497     chd_close - close a CHD file for access
1498 -------------------------------------------------*/
1499 
chd_close(chd_file * chd)1500 void chd_close(chd_file *chd)
1501 {
1502 	/* punt if NULL or invalid */
1503 	if (chd == NULL || chd->cookie != COOKIE_VALUE)
1504 		return;
1505 
1506 	/* deinit the codec */
1507 	if (chd->header.version < 5)
1508 	{
1509 	if (chd->codecintf[0] != NULL && chd->codecintf[0]->free != NULL)
1510 		(*chd->codecintf[0]->free)(&chd->zlib_codec_data);
1511 	}
1512 	else
1513 	{
1514       int i;
1515 		// Free the codecs
1516 		for (i = 0 ; i < 4 ; i++)
1517 		{
1518 			void* codec = NULL;
1519 			switch (chd->codecintf[i]->compression)
1520 			{
1521 				case CHD_CODEC_CD_LZMA:
1522 					codec = &chd->cdlz_codec_data;
1523 					break;
1524 
1525 				case CHD_CODEC_CD_ZLIB:
1526 					codec = &chd->cdzl_codec_data;
1527 					break;
1528 
1529 				case CHD_CODEC_CD_FLAC:
1530 					codec = &chd->cdfl_codec_data;
1531 					break;
1532 			}
1533 			if (codec)
1534 			{
1535 				(*chd->codecintf[i]->free)(codec);
1536 			}
1537 		}
1538 
1539 		// Free the raw map
1540 		if (chd->header.rawmap != NULL)
1541 			free(chd->header.rawmap);
1542 	}
1543 
1544 	/* free the compressed data buffer */
1545 	if (chd->compressed != NULL)
1546 		free(chd->compressed);
1547 
1548 	/* free the hunk cache and compare data */
1549 	if (chd->compare != NULL)
1550 		free(chd->compare);
1551 	if (chd->cache != NULL)
1552 		free(chd->cache);
1553 
1554 	/* free the hunk map */
1555 	if (chd->map != NULL)
1556 		free(chd->map);
1557 
1558 	/* free the CRC table */
1559 	if (chd->crctable != NULL)
1560 		free(chd->crctable);
1561 
1562 	/* free the CRC map */
1563 	if (chd->crcmap != NULL)
1564 		free(chd->crcmap);
1565 
1566 	/* close the file */
1567 	if (chd->owns_file && chd->file != NULL)
1568 		core_fclose(chd->file);
1569 
1570 	if (PRINTF_MAX_HUNK) printf("Max hunk = %d/%d\n", chd->maxhunk, chd->header.totalhunks);
1571 
1572 	/* free our memory */
1573 	free(chd);
1574 }
1575 
1576 
1577 /*-------------------------------------------------
1578     chd_core_file - return the associated
1579     core_file
1580 -------------------------------------------------*/
1581 
chd_core_file(chd_file * chd)1582 core_file *chd_core_file(chd_file *chd)
1583 {
1584 	return chd->file;
1585 }
1586 
1587 
1588 /*-------------------------------------------------
1589     chd_error_string - return an error string for
1590     the given CHD error
1591 -------------------------------------------------*/
1592 
chd_error_string(chd_error err)1593 const char *chd_error_string(chd_error err)
1594 {
1595 	switch (err)
1596 	{
1597 		case CHDERR_NONE:						return "no error";
1598 		case CHDERR_NO_INTERFACE:				return "no drive interface";
1599 		case CHDERR_OUT_OF_MEMORY:				return "out of memory";
1600 		case CHDERR_INVALID_FILE:				return "invalid file";
1601 		case CHDERR_INVALID_PARAMETER:			return "invalid parameter";
1602 		case CHDERR_INVALID_DATA:				return "invalid data";
1603 		case CHDERR_FILE_NOT_FOUND:				return "file not found";
1604 		case CHDERR_REQUIRES_PARENT:			return "requires parent";
1605 		case CHDERR_FILE_NOT_WRITEABLE:			return "file not writeable";
1606 		case CHDERR_READ_ERROR:					return "read error";
1607 		case CHDERR_WRITE_ERROR:				return "write error";
1608 		case CHDERR_CODEC_ERROR:				return "codec error";
1609 		case CHDERR_INVALID_PARENT:				return "invalid parent";
1610 		case CHDERR_HUNK_OUT_OF_RANGE:			return "hunk out of range";
1611 		case CHDERR_DECOMPRESSION_ERROR:		return "decompression error";
1612 		case CHDERR_COMPRESSION_ERROR:			return "compression error";
1613 		case CHDERR_CANT_CREATE_FILE:			return "can't create file";
1614 		case CHDERR_CANT_VERIFY:				return "can't verify file";
1615 		case CHDERR_NOT_SUPPORTED:				return "operation not supported";
1616 		case CHDERR_METADATA_NOT_FOUND:			return "can't find metadata";
1617 		case CHDERR_INVALID_METADATA_SIZE:		return "invalid metadata size";
1618 		case CHDERR_UNSUPPORTED_VERSION:		return "unsupported CHD version";
1619 		case CHDERR_VERIFY_INCOMPLETE:			return "incomplete verify";
1620 		case CHDERR_INVALID_METADATA:			return "invalid metadata";
1621 		case CHDERR_INVALID_STATE:				return "invalid state";
1622 		case CHDERR_OPERATION_PENDING:			return "operation pending";
1623 		case CHDERR_NO_ASYNC_OPERATION:			return "no async operation in progress";
1624 		case CHDERR_UNSUPPORTED_FORMAT:			return "unsupported format";
1625 		default:								return "undocumented error";
1626 	}
1627 }
1628 
1629 
1630 
1631 /***************************************************************************
1632     CHD HEADER MANAGEMENT
1633 ***************************************************************************/
1634 
1635 /*-------------------------------------------------
1636     chd_get_header - return a pointer to the
1637     extracted header data
1638 -------------------------------------------------*/
1639 
chd_get_header(chd_file * chd)1640 const chd_header *chd_get_header(chd_file *chd)
1641 {
1642 	/* punt if NULL or invalid */
1643 	if (chd == NULL || chd->cookie != COOKIE_VALUE)
1644 		return NULL;
1645 
1646 	return &chd->header;
1647 }
1648 
1649 
1650 
1651 /***************************************************************************
1652     CORE DATA READ/WRITE
1653 ***************************************************************************/
1654 
1655 /*-------------------------------------------------
1656     chd_read - read a single hunk from the CHD
1657     file
1658 -------------------------------------------------*/
1659 
chd_read(chd_file * chd,UINT32 hunknum,void * buffer)1660 chd_error chd_read(chd_file *chd, UINT32 hunknum, void *buffer)
1661 {
1662 	/* punt if NULL or invalid */
1663 	if (chd == NULL || chd->cookie != COOKIE_VALUE)
1664 		return CHDERR_INVALID_PARAMETER;
1665 
1666 	/* if we're past the end, fail */
1667 	if (hunknum >= chd->header.totalhunks)
1668 		return CHDERR_HUNK_OUT_OF_RANGE;
1669 
1670 	/* perform the read */
1671 	return hunk_read_into_memory(chd, hunknum, (UINT8 *)buffer);
1672 }
1673 
1674 
1675 
1676 
1677 
1678 /***************************************************************************
1679     METADATA MANAGEMENT
1680 ***************************************************************************/
1681 
1682 /*-------------------------------------------------
1683     chd_get_metadata - get the indexed metadata
1684     of the given type
1685 -------------------------------------------------*/
1686 
chd_get_metadata(chd_file * chd,UINT32 searchtag,UINT32 searchindex,void * output,UINT32 outputlen,UINT32 * resultlen,UINT32 * resulttag,UINT8 * resultflags)1687 chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 searchindex, void *output, UINT32 outputlen, UINT32 *resultlen, UINT32 *resulttag, UINT8 *resultflags)
1688 {
1689 	metadata_entry metaentry;
1690 	chd_error err;
1691 	UINT32 count;
1692 
1693 	/* if we didn't find it, just return */
1694 	err = metadata_find_entry(chd, searchtag, searchindex, &metaentry);
1695 	if (err != CHDERR_NONE)
1696 	{
1697 		/* unless we're an old version and they are requesting hard disk metadata */
1698 		if (chd->header.version < 3 && (searchtag == HARD_DISK_METADATA_TAG || searchtag == CHDMETATAG_WILDCARD) && searchindex == 0)
1699 		{
1700 			char faux_metadata[256];
1701 			UINT32 faux_length;
1702 
1703 			/* fill in the faux metadata */
1704 			sprintf(faux_metadata, HARD_DISK_METADATA_FORMAT, chd->header.obsolete_cylinders, chd->header.obsolete_heads, chd->header.obsolete_sectors, chd->header.hunkbytes / chd->header.obsolete_hunksize);
1705 			faux_length = (UINT32)strlen(faux_metadata) + 1;
1706 
1707 			/* copy the metadata itself */
1708 			memcpy(output, faux_metadata, MIN(outputlen, faux_length));
1709 
1710 			/* return the length of the data and the tag */
1711 			if (resultlen != NULL)
1712 				*resultlen = faux_length;
1713 			if (resulttag != NULL)
1714 				*resulttag = HARD_DISK_METADATA_TAG;
1715 			return CHDERR_NONE;
1716 		}
1717 		return err;
1718 	}
1719 
1720 	/* read the metadata */
1721 	outputlen = MIN(outputlen, metaentry.length);
1722 	core_fseek(chd->file, metaentry.offset + METADATA_HEADER_SIZE, SEEK_SET);
1723 	count = core_fread(chd->file, output, outputlen);
1724 	if (count != outputlen)
1725 		return CHDERR_READ_ERROR;
1726 
1727 	/* return the length of the data and the tag */
1728 	if (resultlen != NULL)
1729 		*resultlen = metaentry.length;
1730 	if (resulttag != NULL)
1731 		*resulttag = metaentry.metatag;
1732 	if (resultflags != NULL)
1733 		*resultflags = metaentry.flags;
1734 	return CHDERR_NONE;
1735 }
1736 
1737 
1738 
1739 /***************************************************************************
1740     CODEC INTERFACES
1741 ***************************************************************************/
1742 
1743 /*-------------------------------------------------
1744     chd_codec_config - set internal codec
1745     parameters
1746 -------------------------------------------------*/
1747 
chd_codec_config(chd_file * chd,int param,void * config)1748 chd_error chd_codec_config(chd_file *chd, int param, void *config)
1749 {
1750 
1751 	return CHDERR_INVALID_PARAMETER;
1752 }
1753 
1754 
1755 /*-------------------------------------------------
1756     chd_get_codec_name - get the name of a
1757     particular codec
1758 -------------------------------------------------*/
1759 
chd_get_codec_name(UINT32 codec)1760 const char *chd_get_codec_name(UINT32 codec)
1761 {
1762 	return "Unknown";
1763 }
1764 
1765 
1766 /***************************************************************************
1767     INTERNAL HEADER OPERATIONS
1768 ***************************************************************************/
1769 
1770 /*-------------------------------------------------
1771     header_validate - check the validity of a
1772     CHD header
1773 -------------------------------------------------*/
1774 
header_validate(const chd_header * header)1775 static chd_error header_validate(const chd_header *header)
1776 {
1777 	int intfnum;
1778 
1779 	/* require a valid version */
1780 	if (header->version == 0 || header->version > CHD_HEADER_VERSION)
1781 		return CHDERR_UNSUPPORTED_VERSION;
1782 
1783 	/* require a valid length */
1784 	if ((header->version == 1 && header->length != CHD_V1_HEADER_SIZE) ||
1785 		(header->version == 2 && header->length != CHD_V2_HEADER_SIZE) ||
1786 		(header->version == 3 && header->length != CHD_V3_HEADER_SIZE) ||
1787 		(header->version == 4 && header->length != CHD_V4_HEADER_SIZE) ||
1788 		(header->version == 5 && header->length != CHD_V5_HEADER_SIZE))
1789 		return CHDERR_INVALID_PARAMETER;
1790 
1791 	/* Do not validate v5 header */
1792 	if (header->version <= 4)
1793 	{
1794 		/* require valid flags */
1795 		if (header->flags & CHDFLAGS_UNDEFINED)
1796 			return CHDERR_INVALID_PARAMETER;
1797 
1798 		/* require a supported compression mechanism */
1799 		for (intfnum = 0; intfnum < ARRAY_LENGTH(codec_interfaces); intfnum++)
1800 			if (codec_interfaces[intfnum].compression == header->compression[0])
1801 				break;
1802 
1803 		if (intfnum == ARRAY_LENGTH(codec_interfaces))
1804 			return CHDERR_INVALID_PARAMETER;
1805 
1806 		/* require a valid hunksize */
1807 		if (header->hunkbytes == 0 || header->hunkbytes >= 65536 * 256)
1808 			return CHDERR_INVALID_PARAMETER;
1809 
1810 		/* require a valid hunk count */
1811 		if (header->totalhunks == 0)
1812 			return CHDERR_INVALID_PARAMETER;
1813 
1814 		/* require a valid MD5 and/or SHA1 if we're using a parent */
1815 		if ((header->flags & CHDFLAGS_HAS_PARENT) && memcmp(header->parentmd5, nullmd5, sizeof(nullmd5)) == 0 && memcmp(header->parentsha1, nullsha1, sizeof(nullsha1)) == 0)
1816 			return CHDERR_INVALID_PARAMETER;
1817 
1818 		/* if we're V3 or later, the obsolete fields must be 0 */
1819 		if (header->version >= 3 &&
1820 			(header->obsolete_cylinders != 0 || header->obsolete_sectors != 0 ||
1821 			 header->obsolete_heads != 0 || header->obsolete_hunksize != 0))
1822 			return CHDERR_INVALID_PARAMETER;
1823 
1824 		/* if we're pre-V3, the obsolete fields must NOT be 0 */
1825 		if (header->version < 3 &&
1826 			(header->obsolete_cylinders == 0 || header->obsolete_sectors == 0 ||
1827 			 header->obsolete_heads == 0 || header->obsolete_hunksize == 0))
1828 			return CHDERR_INVALID_PARAMETER;
1829 	}
1830 
1831 	return CHDERR_NONE;
1832 }
1833 
1834 
1835 /*-------------------------------------------------
1836     header_read - read a CHD header into the
1837     internal data structure
1838 -------------------------------------------------*/
1839 
header_read(core_file * file,chd_header * header)1840 static chd_error header_read(core_file *file, chd_header *header)
1841 {
1842 	UINT8 rawheader[CHD_MAX_HEADER_SIZE];
1843 	UINT32 count;
1844 
1845 	/* punt if NULL */
1846 	if (header == NULL)
1847 		return CHDERR_INVALID_PARAMETER;
1848 
1849 	/* punt if invalid file */
1850 	if (file == NULL)
1851 		return CHDERR_INVALID_FILE;
1852 
1853 	/* seek and read */
1854 	core_fseek(file, 0, SEEK_SET);
1855 	count = core_fread(file, rawheader, sizeof(rawheader));
1856 	if (count != sizeof(rawheader))
1857 		return CHDERR_READ_ERROR;
1858 
1859 	/* verify the tag */
1860 	if (strncmp((char *)rawheader, "MComprHD", 8) != 0)
1861 		return CHDERR_INVALID_DATA;
1862 
1863 	/* extract the direct data */
1864 	memset(header, 0, sizeof(*header));
1865 	header->length        = get_bigendian_uint32(&rawheader[8]);
1866 	header->version       = get_bigendian_uint32(&rawheader[12]);
1867 
1868 	/* make sure it's a version we understand */
1869 	if (header->version == 0 || header->version > CHD_HEADER_VERSION)
1870 		return CHDERR_UNSUPPORTED_VERSION;
1871 
1872 	/* make sure the length is expected */
1873 	if ((header->version == 1 && header->length != CHD_V1_HEADER_SIZE) ||
1874 		(header->version == 2 && header->length != CHD_V2_HEADER_SIZE) ||
1875 		(header->version == 3 && header->length != CHD_V3_HEADER_SIZE) ||
1876 		(header->version == 4 && header->length != CHD_V4_HEADER_SIZE) ||
1877 		(header->version == 5 && header->length != CHD_V5_HEADER_SIZE))
1878 
1879 		return CHDERR_INVALID_DATA;
1880 
1881 	/* extract the common data */
1882 	header->flags         	= get_bigendian_uint32(&rawheader[16]);
1883 	header->compression[0]	= get_bigendian_uint32(&rawheader[20]);
1884 
1885 	/* extract the V1/V2-specific data */
1886 	if (header->version < 3)
1887 	{
1888 		int seclen = (header->version == 1) ? CHD_V1_SECTOR_SIZE : get_bigendian_uint32(&rawheader[76]);
1889 		header->obsolete_hunksize  = get_bigendian_uint32(&rawheader[24]);
1890 		header->totalhunks         = get_bigendian_uint32(&rawheader[28]);
1891 		header->obsolete_cylinders = get_bigendian_uint32(&rawheader[32]);
1892 		header->obsolete_heads     = get_bigendian_uint32(&rawheader[36]);
1893 		header->obsolete_sectors   = get_bigendian_uint32(&rawheader[40]);
1894 		memcpy(header->md5, &rawheader[44], CHD_MD5_BYTES);
1895 		memcpy(header->parentmd5, &rawheader[60], CHD_MD5_BYTES);
1896 		header->logicalbytes = (UINT64)header->obsolete_cylinders * (UINT64)header->obsolete_heads * (UINT64)header->obsolete_sectors * (UINT64)seclen;
1897 		header->hunkbytes = seclen * header->obsolete_hunksize;
1898 		header->metaoffset = 0;
1899 	}
1900 
1901 	/* extract the V3-specific data */
1902 	else if (header->version == 3)
1903 	{
1904 		header->totalhunks   = get_bigendian_uint32(&rawheader[24]);
1905 		header->logicalbytes = get_bigendian_uint64(&rawheader[28]);
1906 		header->metaoffset   = get_bigendian_uint64(&rawheader[36]);
1907 		memcpy(header->md5, &rawheader[44], CHD_MD5_BYTES);
1908 		memcpy(header->parentmd5, &rawheader[60], CHD_MD5_BYTES);
1909 		header->hunkbytes    = get_bigendian_uint32(&rawheader[76]);
1910 		memcpy(header->sha1, &rawheader[80], CHD_SHA1_BYTES);
1911 		memcpy(header->parentsha1, &rawheader[100], CHD_SHA1_BYTES);
1912 	}
1913 
1914 	/* extract the V4-specific data */
1915 	else if (header->version == 4)
1916 	{
1917 		header->totalhunks   = get_bigendian_uint32(&rawheader[24]);
1918 		header->logicalbytes = get_bigendian_uint64(&rawheader[28]);
1919 		header->metaoffset   = get_bigendian_uint64(&rawheader[36]);
1920 		header->hunkbytes    = get_bigendian_uint32(&rawheader[44]);
1921 		memcpy(header->sha1, &rawheader[48], CHD_SHA1_BYTES);
1922 		memcpy(header->parentsha1, &rawheader[68], CHD_SHA1_BYTES);
1923 		memcpy(header->rawsha1, &rawheader[88], CHD_SHA1_BYTES);
1924 	}
1925 
1926 	/* extract the V5-specific data */
1927 	else if (header->version == 5)
1928 	{
1929 		/* TODO */
1930 		header->compression[0]	= get_bigendian_uint32(&rawheader[16]);
1931 		header->compression[1] 	= get_bigendian_uint32(&rawheader[20]);
1932 		header->compression[2] 	= get_bigendian_uint32(&rawheader[24]);
1933 		header->compression[3] 	= get_bigendian_uint32(&rawheader[28]);
1934 		header->logicalbytes 	= get_bigendian_uint64(&rawheader[32]);
1935 		header->mapoffset    	= get_bigendian_uint64(&rawheader[40]);
1936 		header->metaoffset   	= get_bigendian_uint64(&rawheader[48]);
1937 		header->hunkbytes    	= get_bigendian_uint32(&rawheader[56]);
1938 		header->hunkcount 	 	= (header->logicalbytes + header->hunkbytes - 1) / header->hunkbytes;
1939 		header->unitbytes    	= get_bigendian_uint32(&rawheader[60]);
1940 		header->unitcount    	= (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
1941 		memcpy(header->sha1, &rawheader[84], CHD_SHA1_BYTES);
1942 		memcpy(header->parentsha1, &rawheader[104], CHD_SHA1_BYTES);
1943 		memcpy(header->rawsha1, &rawheader[64], CHD_SHA1_BYTES);
1944 
1945 		// determine properties of map entries
1946 		header->mapentrybytes = 12; //TODO compressed() ? 12 : 4;
1947 
1948 		// hack
1949 		header->totalhunks 		= header->hunkcount;
1950 	}
1951 
1952 	/* Unknown version */
1953 	else
1954 	{
1955 		/* TODO */
1956 	}
1957 
1958 	/* guess it worked */
1959 	return CHDERR_NONE;
1960 }
1961 
1962 
1963 /***************************************************************************
1964     INTERNAL HUNK READ/WRITE
1965 ***************************************************************************/
1966 
1967 /*-------------------------------------------------
1968     hunk_read_into_cache - read a hunk into
1969     the CHD's hunk cache
1970 -------------------------------------------------*/
1971 
hunk_read_into_cache(chd_file * chd,UINT32 hunknum)1972 static chd_error hunk_read_into_cache(chd_file *chd, UINT32 hunknum)
1973 {
1974 	chd_error err;
1975 
1976 	/* track the max */
1977 	if (hunknum > chd->maxhunk)
1978 		chd->maxhunk = hunknum;
1979 
1980 	/* if we're already in the cache, we're done */
1981 	if (chd->cachehunk == hunknum)
1982 		return CHDERR_NONE;
1983 	chd->cachehunk = ~0;
1984 
1985 	/* otherwise, read the data */
1986 	err = hunk_read_into_memory(chd, hunknum, chd->cache);
1987 	if (err != CHDERR_NONE)
1988 		return err;
1989 
1990 	/* mark the hunk successfully cached in */
1991 	chd->cachehunk = hunknum;
1992 	return CHDERR_NONE;
1993 }
1994 
1995 
1996 /*-------------------------------------------------
1997     hunk_read_into_memory - read a hunk into
1998     memory at the given location
1999 -------------------------------------------------*/
2000 
hunk_read_into_memory(chd_file * chd,UINT32 hunknum,UINT8 * dest)2001 static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *dest)
2002 {
2003 	chd_error err;
2004 
2005 	// punt if no file
2006 	if (chd->file == NULL)
2007 		return CHDERR_INVALID_FILE;
2008 
2009 	/* return an error if out of range */
2010 	if (hunknum >= chd->header.totalhunks)
2011 		return CHDERR_HUNK_OUT_OF_RANGE;
2012 
2013 	if (chd->header.version < 5)
2014 	{
2015 		map_entry *entry = &chd->map[hunknum];
2016 		UINT32 bytes;
2017 
2018 		/* switch off the entry type */
2019 		switch (entry->flags & MAP_ENTRY_FLAG_TYPE_MASK)
2020 		{
2021 			/* compressed data */
2022 			case V34_MAP_ENTRY_TYPE_COMPRESSED:
2023             {
2024                void* codec;
2025                   /* read it into the decompression buffer */
2026                   core_fseek(chd->file, entry->offset, SEEK_SET);
2027                bytes = core_fread(chd->file, chd->compressed, entry->length);
2028                if (bytes != entry->length)
2029                   return CHDERR_READ_ERROR;
2030 
2031                /* now decompress using the codec */
2032                err   = CHDERR_NONE;
2033                codec = &chd->zlib_codec_data;
2034                if (chd->codecintf[0]->decompress != NULL)
2035                   err = (*chd->codecintf[0]->decompress)(codec, chd->compressed, entry->length, dest, chd->header.hunkbytes);
2036                if (err != CHDERR_NONE)
2037                   return err;
2038             }
2039 				break;
2040 
2041 			/* uncompressed data */
2042 			case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
2043 				core_fseek(chd->file, entry->offset, SEEK_SET);
2044 				bytes = core_fread(chd->file, dest, chd->header.hunkbytes);
2045 				if (bytes != chd->header.hunkbytes)
2046 					return CHDERR_READ_ERROR;
2047 				break;
2048 
2049 			/* mini-compressed data */
2050 			case V34_MAP_ENTRY_TYPE_MINI:
2051 				put_bigendian_uint64(&dest[0], entry->offset);
2052 				for (bytes = 8; bytes < chd->header.hunkbytes; bytes++)
2053 					dest[bytes] = dest[bytes - 8];
2054 				break;
2055 
2056 			/* self-referenced data */
2057 			case V34_MAP_ENTRY_TYPE_SELF_HUNK:
2058 				if (chd->cachehunk == entry->offset && dest == chd->cache)
2059 					break;
2060 				return hunk_read_into_memory(chd, entry->offset, dest);
2061 
2062 			/* parent-referenced data */
2063 			case V34_MAP_ENTRY_TYPE_PARENT_HUNK:
2064 				err = hunk_read_into_memory(chd->parent, entry->offset, dest);
2065 				if (err != CHDERR_NONE)
2066 					return err;
2067 				break;
2068 		}
2069 		return CHDERR_NONE;
2070 	}
2071 	else
2072 	{
2073 
2074 		// get a pointer to the map entry
2075 		uint64_t blockoffs;
2076 		uint32_t blocklen;
2077 		uint16_t blockcrc;
2078       void* codec = NULL;
2079 		uint8_t *rawmap = &chd->header.rawmap[chd->header.mapentrybytes * hunknum];
2080 
2081 		// uncompressed case
2082 		/* TODO
2083 		if (!compressed())
2084 		{
2085 			blockoffs = uint64_t(be_read(rawmap, 4)) * uint64_t(m_hunkbytes);
2086 			if (blockoffs != 0)
2087 				file_read(blockoffs, dest, m_hunkbytes);
2088 			else if (m_parent_missing)
2089 				throw CHDERR_REQUIRES_PARENT;
2090 			else if (m_parent != nullptr)
2091 				m_parent->read_hunk(hunknum, dest);
2092 			else
2093 				memset(dest, 0, m_hunkbytes);
2094 			return CHDERR_NONE;
2095 		}*/
2096 
2097 		// compressed case
2098 		blocklen = get_bigendian_uint24(&rawmap[1]);
2099 		blockoffs = get_bigendian_uint48(&rawmap[4]);
2100 		blockcrc = get_bigendian_uint16(&rawmap[10]);
2101 		switch (rawmap[0])
2102 		{
2103 			case COMPRESSION_TYPE_0:
2104 			case COMPRESSION_TYPE_1:
2105 			case COMPRESSION_TYPE_2:
2106 			case COMPRESSION_TYPE_3:
2107 				core_fseek(chd->file, blockoffs, SEEK_SET);
2108 				core_fread(chd->file, chd->compressed, blocklen);
2109 				switch (chd->codecintf[rawmap[0]]->compression)
2110 				{
2111 					case CHD_CODEC_CD_LZMA:
2112 						codec = &chd->cdlz_codec_data;
2113 						break;
2114 
2115 					case CHD_CODEC_CD_ZLIB:
2116 						codec = &chd->cdzl_codec_data;
2117 						break;
2118 
2119 					case CHD_CODEC_CD_FLAC:
2120 						codec = &chd->cdfl_codec_data;
2121 						break;
2122 				}
2123 				if (codec==NULL)
2124 					return CHDERR_DECOMPRESSION_ERROR;
2125 				chd->codecintf[rawmap[0]]->decompress(codec, chd->compressed, blocklen, dest, chd->header.hunkbytes);
2126 				if (dest != NULL && crc16(dest, chd->header.hunkbytes) != blockcrc)
2127 					return CHDERR_DECOMPRESSION_ERROR;
2128 				return CHDERR_NONE;
2129 
2130 			case COMPRESSION_NONE:
2131 				core_fseek(chd->file, blockoffs, SEEK_SET);
2132 				core_fread(chd->file, dest, chd->header.hunkbytes);
2133 				if (crc16(dest, chd->header.hunkbytes) != blockcrc)
2134 					return CHDERR_DECOMPRESSION_ERROR;
2135 				return CHDERR_NONE;
2136 
2137 			case COMPRESSION_SELF:
2138 				return hunk_read_into_memory(chd, blockoffs, dest);
2139 
2140 			case COMPRESSION_PARENT:
2141 				// TODO
2142 				//if (m_parent_missing)
2143 				//	return CHDERR_REQUIRES_PARENT;
2144 				//return m_parent->read_bytes(uint64_t(blockoffs) * uint64_t(m_parent->unit_bytes()), dest, m_hunkbytes);
2145 				return CHDERR_DECOMPRESSION_ERROR;
2146 		}
2147 		return CHDERR_NONE;
2148 	}
2149 
2150 	// We should not reach this code
2151 	return CHDERR_DECOMPRESSION_ERROR;
2152 }
2153 
2154 
2155 /***************************************************************************
2156     INTERNAL MAP ACCESS
2157 ***************************************************************************/
2158 
2159 /*-------------------------------------------------
2160     map_read - read the initial sector map
2161 -------------------------------------------------*/
2162 
map_read(chd_file * chd)2163 static chd_error map_read(chd_file *chd)
2164 {
2165 	UINT32 entrysize = (chd->header.version < 3) ? OLD_MAP_ENTRY_SIZE : MAP_ENTRY_SIZE;
2166 	UINT8 raw_map_entries[MAP_STACK_ENTRIES * MAP_ENTRY_SIZE];
2167 	UINT64 fileoffset, maxoffset = 0;
2168 	UINT8 cookie[MAP_ENTRY_SIZE];
2169 	UINT32 count;
2170 	chd_error err;
2171 	int i;
2172 
2173 	/* first allocate memory */
2174 	chd->map = (map_entry *)malloc(sizeof(chd->map[0]) * chd->header.totalhunks);
2175 	if (!chd->map)
2176 		return CHDERR_OUT_OF_MEMORY;
2177 
2178 	/* read the map entries in in chunks and extract to the map list */
2179 	fileoffset = chd->header.length;
2180 	for (i = 0; i < chd->header.totalhunks; i += MAP_STACK_ENTRIES)
2181 	{
2182 		/* compute how many entries this time */
2183 		int entries = chd->header.totalhunks - i, j;
2184 		if (entries > MAP_STACK_ENTRIES)
2185 			entries = MAP_STACK_ENTRIES;
2186 
2187 		/* read that many */
2188 		core_fseek(chd->file, fileoffset, SEEK_SET);
2189 		count = core_fread(chd->file, raw_map_entries, entries * entrysize);
2190 		if (count != entries * entrysize)
2191 		{
2192 			err = CHDERR_READ_ERROR;
2193 			goto cleanup;
2194 		}
2195 		fileoffset += entries * entrysize;
2196 
2197 		/* process that many */
2198 		if (entrysize == MAP_ENTRY_SIZE)
2199 		{
2200 			for (j = 0; j < entries; j++)
2201 				map_extract(&raw_map_entries[j * MAP_ENTRY_SIZE], &chd->map[i + j]);
2202 		}
2203 		else
2204 		{
2205 			for (j = 0; j < entries; j++)
2206 				map_extract_old(&raw_map_entries[j * OLD_MAP_ENTRY_SIZE], &chd->map[i + j], chd->header.hunkbytes);
2207 		}
2208 
2209 		/* track the maximum offset */
2210 		for (j = 0; j < entries; j++)
2211 			if ((chd->map[i + j].flags & MAP_ENTRY_FLAG_TYPE_MASK) == V34_MAP_ENTRY_TYPE_COMPRESSED ||
2212 				(chd->map[i + j].flags & MAP_ENTRY_FLAG_TYPE_MASK) == V34_MAP_ENTRY_TYPE_UNCOMPRESSED)
2213 				maxoffset = MAX(maxoffset, chd->map[i + j].offset + chd->map[i + j].length);
2214 	}
2215 
2216 	/* verify the cookie */
2217 	core_fseek(chd->file, fileoffset, SEEK_SET);
2218 	count = core_fread(chd->file, &cookie, entrysize);
2219 	if (count != entrysize || memcmp(&cookie, END_OF_LIST_COOKIE, entrysize))
2220 	{
2221 		err = CHDERR_INVALID_FILE;
2222 		goto cleanup;
2223 	}
2224 
2225 	/* verify the length */
2226 	if (maxoffset > core_fsize(chd->file))
2227 	{
2228 		err = CHDERR_INVALID_FILE;
2229 		goto cleanup;
2230 	}
2231 	return CHDERR_NONE;
2232 
2233 cleanup:
2234 	if (chd->map)
2235 		free(chd->map);
2236 	chd->map = NULL;
2237 	return err;
2238 }
2239 
2240 
2241 
2242 
2243 /***************************************************************************
2244     INTERNAL METADATA ACCESS
2245 ***************************************************************************/
2246 
2247 /*-------------------------------------------------
2248     metadata_find_entry - find a metadata entry
2249 -------------------------------------------------*/
2250 
metadata_find_entry(chd_file * chd,UINT32 metatag,UINT32 metaindex,metadata_entry * metaentry)2251 static chd_error metadata_find_entry(chd_file *chd, UINT32 metatag, UINT32 metaindex, metadata_entry *metaentry)
2252 {
2253 	/* start at the beginning */
2254 	metaentry->offset = chd->header.metaoffset;
2255 	metaentry->prev = 0;
2256 
2257 	/* loop until we run out of options */
2258 	while (metaentry->offset != 0)
2259 	{
2260 		UINT8	raw_meta_header[METADATA_HEADER_SIZE];
2261 		UINT32	count;
2262 
2263 		/* read the raw header */
2264 		core_fseek(chd->file, metaentry->offset, SEEK_SET);
2265 		count = core_fread(chd->file, raw_meta_header, sizeof(raw_meta_header));
2266 		if (count != sizeof(raw_meta_header))
2267 			break;
2268 
2269 		/* extract the data */
2270 		metaentry->metatag = get_bigendian_uint32(&raw_meta_header[0]);
2271 		metaentry->length = get_bigendian_uint32(&raw_meta_header[4]);
2272 		metaentry->next = get_bigendian_uint64(&raw_meta_header[8]);
2273 
2274 		/* flags are encoded in the high byte of length */
2275 		metaentry->flags = metaentry->length >> 24;
2276 		metaentry->length &= 0x00ffffff;
2277 
2278 		/* if we got a match, proceed */
2279 		if (metatag == CHDMETATAG_WILDCARD || metaentry->metatag == metatag)
2280 			if (metaindex-- == 0)
2281 				return CHDERR_NONE;
2282 
2283 		/* no match, fetch the next link */
2284 		metaentry->prev = metaentry->offset;
2285 		metaentry->offset = metaentry->next;
2286 	}
2287 
2288 	/* if we get here, we didn't find it */
2289 	return CHDERR_METADATA_NOT_FOUND;
2290 }
2291 
2292 
2293 
2294 /***************************************************************************
2295     ZLIB COMPRESSION CODEC
2296 ***************************************************************************/
2297 
2298 /*-------------------------------------------------
2299     zlib_codec_init - initialize the ZLIB codec
2300 -------------------------------------------------*/
2301 
zlib_codec_init(void * codec,uint32_t hunkbytes)2302 static chd_error zlib_codec_init(void *codec, uint32_t hunkbytes)
2303 {
2304 	zlib_codec_data *data = (zlib_codec_data*)codec;
2305 	chd_error err;
2306 	int zerr;
2307 
2308 	/* clear the buffers */
2309 	memset(data, 0, sizeof(zlib_codec_data));
2310 
2311 	/* init the inflater first */
2312 	data->inflater.next_in = (Bytef *)data;	/* bogus, but that's ok */
2313 	data->inflater.avail_in = 0;
2314 	data->inflater.zalloc = zlib_fast_alloc;
2315 	data->inflater.zfree = zlib_fast_free;
2316 	data->inflater.opaque = &data->allocator;
2317 	zerr = inflateInit2(&data->inflater, -MAX_WBITS);
2318 
2319 	/* convert errors */
2320 	if (zerr == Z_MEM_ERROR)
2321 		err = CHDERR_OUT_OF_MEMORY;
2322 	else if (zerr != Z_OK)
2323 		err = CHDERR_CODEC_ERROR;
2324 	else
2325 		err = CHDERR_NONE;
2326 
2327 	/* handle an error */
2328 	if (err != CHDERR_NONE)
2329 		free(data);
2330 
2331 	return err;
2332 }
2333 
2334 
2335 /*-------------------------------------------------
2336     zlib_codec_free - free data for the ZLIB
2337     codec
2338 -------------------------------------------------*/
2339 
zlib_codec_free(void * codec)2340 static void zlib_codec_free(void *codec)
2341 {
2342 	zlib_codec_data *data = (zlib_codec_data *)codec;
2343 
2344 	/* deinit the streams */
2345 	if (data != NULL)
2346 	{
2347 		int i;
2348       zlib_allocator alloc;
2349 
2350 		inflateEnd(&data->inflater);
2351 
2352 		/* free our fast memory */
2353 		alloc = data->allocator;
2354 		for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
2355 			if (alloc.allocptr[i])
2356 				free(alloc.allocptr[i]);
2357 	}
2358 }
2359 
2360 
2361 /*-------------------------------------------------
2362     zlib_codec_decompress - decomrpess data using
2363     the ZLIB codec
2364 -------------------------------------------------*/
2365 
zlib_codec_decompress(void * codec,const uint8_t * src,uint32_t complen,uint8_t * dest,uint32_t destlen)2366 static chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
2367 {
2368 	zlib_codec_data *data = (zlib_codec_data *)codec;
2369 	int zerr;
2370 
2371 	/* reset the decompressor */
2372 	data->inflater.next_in = (Bytef *)src;
2373 	data->inflater.avail_in = complen;
2374 	data->inflater.total_in = 0;
2375 	data->inflater.next_out = (Bytef *)dest;
2376 	data->inflater.avail_out = destlen;
2377 	data->inflater.total_out = 0;
2378 	zerr = inflateReset(&data->inflater);
2379 	if (zerr != Z_OK)
2380 		return CHDERR_DECOMPRESSION_ERROR;
2381 
2382 	/* do it */
2383 	zerr = inflate(&data->inflater, Z_FINISH);
2384 	if (data->inflater.total_out != destlen)
2385 		return CHDERR_DECOMPRESSION_ERROR;
2386 
2387 	return CHDERR_NONE;
2388 }
2389 
2390 
2391 /*-------------------------------------------------
2392     zlib_fast_alloc - fast malloc for ZLIB, which
2393     allocates and frees memory frequently
2394 -------------------------------------------------*/
2395 
zlib_fast_alloc(voidpf opaque,uInt items,uInt size)2396 static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
2397 {
2398 	zlib_allocator *alloc = (zlib_allocator *)opaque;
2399 	UINT32 *ptr;
2400 	int i;
2401 
2402 	/* compute the size, rounding to the nearest 1k */
2403 	size = (size * items + 0x3ff) & ~0x3ff;
2404 
2405 	/* reuse a hunk if we can */
2406 	for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
2407 	{
2408 		ptr = alloc->allocptr[i];
2409 		if (ptr && size == *ptr)
2410 		{
2411 			/* set the low bit of the size so we don't match next time */
2412 			*ptr |= 1;
2413 			return ptr + 1;
2414 		}
2415 	}
2416 
2417 	/* alloc a new one */
2418 	ptr = (UINT32 *)malloc(size + sizeof(UINT32));
2419 	if (!ptr)
2420 		return NULL;
2421 
2422 	/* put it into the list */
2423 	for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
2424 		if (!alloc->allocptr[i])
2425 		{
2426 			alloc->allocptr[i] = ptr;
2427 			break;
2428 		}
2429 
2430 	/* set the low bit of the size so we don't match next time */
2431 	*ptr = size | 1;
2432 	return ptr + 1;
2433 }
2434 
2435 
2436 /*-------------------------------------------------
2437     zlib_fast_free - fast free for ZLIB, which
2438     allocates and frees memory frequently
2439 -------------------------------------------------*/
2440 
zlib_fast_free(voidpf opaque,voidpf address)2441 static void zlib_fast_free(voidpf opaque, voidpf address)
2442 {
2443 	zlib_allocator *alloc = (zlib_allocator *)opaque;
2444 	UINT32 *ptr = (UINT32 *)address - 1;
2445 	int i;
2446 
2447 	/* find the hunk */
2448 	for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
2449 		if (ptr == alloc->allocptr[i])
2450 		{
2451 			/* clear the low bit of the size to allow matches */
2452 			*ptr &= ~1;
2453 			return;
2454 		}
2455 }
2456