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