1 /***************************************************************************
5 MAME Compressed Hunks of Data file format
7 ****************************************************************************
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions are
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
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.
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.
38 ***************************************************************************/
46 #include <libchdr/chd.h>
47 #include <libchdr/cdrom.h>
48 #include <libchdr/flac.h>
49 #include <libchdr/huffman.h>
53 #if defined(__PS3__) || defined(__PSL1GHT__)
65 #define MAX(x, y) (((x) > (y)) ? (x) : (y))
66 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
68 #define SHA1_DIGEST_SIZE 20
70 /***************************************************************************
72 ***************************************************************************/
74 #define PRINTF_MAX_HUNK (0)
76 /***************************************************************************
78 ***************************************************************************/
80 #define MAP_STACK_ENTRIES 512 /* max number of entries to use on the stack */
81 #define MAP_ENTRY_SIZE 16 /* V3 and later */
82 #define OLD_MAP_ENTRY_SIZE 8 /* V1-V2 */
83 #define METADATA_HEADER_SIZE 16 /* metadata header size */
85 #define MAP_ENTRY_FLAG_TYPE_MASK 0x0f /* what type of hunk */
86 #define MAP_ENTRY_FLAG_NO_CRC 0x10 /* no CRC is present */
88 #define CHD_V1_SECTOR_SIZE 512 /* size of a "sector" in the V1 header */
90 #define COOKIE_VALUE 0xbaadf00d
91 #define MAX_ZLIB_ALLOCS 64
93 #define END_OF_LIST_COOKIE "EndOfListCookie"
97 #ifdef WANT_RAW_DATA_SECTOR
98 static const uint8_t s_cd_sync_header[12] = { 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 };
101 /* V3-V4 entry types */
104 V34_MAP_ENTRY_TYPE_INVALID = 0, /* invalid type */
105 V34_MAP_ENTRY_TYPE_COMPRESSED = 1, /* standard compression */
106 V34_MAP_ENTRY_TYPE_UNCOMPRESSED = 2, /* uncompressed data */
107 V34_MAP_ENTRY_TYPE_MINI = 3, /* mini: use offset as raw data */
108 V34_MAP_ENTRY_TYPE_SELF_HUNK = 4, /* same as another hunk in this file */
109 V34_MAP_ENTRY_TYPE_PARENT_HUNK = 5, /* same as a hunk in the parent file */
110 V34_MAP_ENTRY_TYPE_2ND_COMPRESSED = 6 /* compressed with secondary algorithm (usually FLAC CDDA) */
113 /* V5 compression types */
117 * these types are live when running */
118 COMPRESSION_TYPE_0 = 0,
120 COMPRESSION_TYPE_1 = 1,
122 COMPRESSION_TYPE_2 = 2,
124 COMPRESSION_TYPE_3 = 3,
125 /* no compression; implicit length = hunkbytes */
126 COMPRESSION_NONE = 4,
127 /* same as another block in this chd */
128 COMPRESSION_SELF = 5,
129 /* same as a hunk's worth of units in the parent chd */
130 COMPRESSION_PARENT = 6,
132 /* start of small RLE run (4-bit length)
133 * these additional pseudo-types are used for compressed encodings: */
134 COMPRESSION_RLE_SMALL,
135 /* start of large RLE run (8-bit length) */
136 COMPRESSION_RLE_LARGE,
137 /* same as the last COMPRESSION_SELF block */
139 /* same as the last COMPRESSION_SELF block + 1 */
141 /* same block in the parent */
142 COMPRESSION_PARENT_SELF,
143 /* same as the last COMPRESSION_PARENT block */
144 COMPRESSION_PARENT_0,
145 /* same as the last COMPRESSION_PARENT block + 1 */
149 /***************************************************************************
151 ***************************************************************************/
153 #define EARLY_EXIT(x) do { (void)(x); goto cleanup; } while (0)
155 /***************************************************************************
157 ***************************************************************************/
159 /* interface to a codec */
160 typedef struct _codec_interface codec_interface;
161 struct _codec_interface
163 UINT32 compression; /* type of compression */
164 const char *compname; /* name of the algorithm */
165 UINT8 lossy; /* is this a lossy algorithm? */
166 chd_error (*init)(void *codec, UINT32 hunkbytes); /* codec initialize */
167 void (*free)(void *codec); /* codec free */
168 chd_error (*decompress)(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); /* decompress data */
169 chd_error (*config)(void *codec, int param, void *config); /* configure */
172 /* a single map entry */
173 typedef struct _map_entry map_entry;
176 UINT64 offset; /* offset within the file of the data */
177 UINT32 crc; /* 32-bit CRC of the data */
178 UINT32 length; /* length of the data */
179 UINT8 flags; /* misc flags */
182 /* a single metadata entry */
183 typedef struct _metadata_entry metadata_entry;
184 struct _metadata_entry
186 UINT64 offset; /* offset within the file of the header */
187 UINT64 next; /* offset within the file of the next header */
188 UINT64 prev; /* offset within the file of the previous header */
189 UINT32 length; /* length of the metadata */
190 UINT32 metatag; /* metadata tag */
191 UINT8 flags; /* flag bits */
194 /* codec-private data for the ZLIB codec */
196 typedef struct _zlib_allocator zlib_allocator;
197 struct _zlib_allocator
199 UINT32 * allocptr[MAX_ZLIB_ALLOCS];
200 UINT32 * allocptr2[MAX_ZLIB_ALLOCS];
203 typedef struct _zlib_codec_data zlib_codec_data;
204 struct _zlib_codec_data
207 zlib_allocator allocator;
210 /* codec-private data for the LZMA codec */
211 #define MAX_LZMA_ALLOCS 64
213 typedef struct _lzma_allocator lzma_allocator;
214 struct _lzma_allocator
216 void *(*Alloc)(void *p, size_t size);
217 void (*Free)(void *p, void *address); /* address can be 0 */
218 void (*FreeSz)(void *p, void *address, size_t size); /* address can be 0 */
219 uint32_t* allocptr[MAX_LZMA_ALLOCS];
220 uint32_t* allocptr2[MAX_LZMA_ALLOCS];
223 typedef struct _lzma_codec_data lzma_codec_data;
224 struct _lzma_codec_data
227 lzma_allocator allocator;
230 typedef struct _huff_codec_data huff_codec_data;
231 struct _huff_codec_data
233 struct huffman_decoder* decoder;
236 /* codec-private data for the CDZL codec */
237 typedef struct _cdzl_codec_data cdzl_codec_data;
238 struct _cdzl_codec_data {
240 zlib_codec_data base_decompressor;
242 zlib_codec_data subcode_decompressor;
247 /* codec-private data for the CDLZ codec */
248 typedef struct _cdlz_codec_data cdlz_codec_data;
249 struct _cdlz_codec_data {
251 lzma_codec_data base_decompressor;
253 zlib_codec_data subcode_decompressor;
258 /* codec-private data for the FLAC codec */
259 typedef struct _flac_codec_data flac_codec_data;
260 struct _flac_codec_data {
263 flac_decoder decoder;
266 /* codec-private data for the CDFL codec */
267 typedef struct _cdfl_codec_data cdfl_codec_data;
268 struct _cdfl_codec_data {
271 flac_decoder decoder;
273 zlib_codec_data subcode_decompressor;
278 /* internal representation of an open CHD file */
281 UINT32 cookie; /* cookie, should equal COOKIE_VALUE */
283 core_file * file; /* handle to the open core file */
284 chd_header header; /* header, extracted from file */
286 chd_file * parent; /* pointer to parent file, or NULL */
288 map_entry * map; /* array of map entries */
290 #ifdef NEED_CACHE_HUNK
291 UINT8 * cache; /* hunk cache pointer */
292 UINT32 cachehunk; /* index of currently cached hunk */
294 UINT8 * compare; /* hunk compare pointer */
295 UINT32 comparehunk; /* index of current compare data */
298 UINT8 * compressed; /* pointer to buffer for compressed data */
299 const codec_interface * codecintf[4]; /* interface to the codec */
301 zlib_codec_data zlib_codec_data; /* zlib codec data */
302 lzma_codec_data lzma_codec_data; /* lzma codec data */
303 huff_codec_data huff_codec_data; /* huff codec data */
304 flac_codec_data flac_codec_data; /* flac codec data */
305 cdzl_codec_data cdzl_codec_data; /* cdzl codec data */
306 cdlz_codec_data cdlz_codec_data; /* cdlz codec data */
307 cdfl_codec_data cdfl_codec_data; /* cdfl codec data */
309 #ifdef NEED_CACHE_HUNK
310 UINT32 maxhunk; /* maximum hunk accessed */
313 UINT8 * file_cache; /* cache of underlying file */
317 /***************************************************************************
319 ***************************************************************************/
321 static const UINT8 nullmd5[CHD_MD5_BYTES] = { 0 };
322 static const UINT8 nullsha1[CHD_SHA1_BYTES] = { 0 };
324 /***************************************************************************
326 ***************************************************************************/
328 /* core_file wrappers over stdio */
329 static core_file *core_stdio_fopen(char const *path);
330 static UINT64 core_stdio_fsize(core_file *file);
331 static size_t core_stdio_fread(void *ptr, size_t size, size_t nmemb, core_file *file);
332 static int core_stdio_fclose(core_file *file);
333 static int core_stdio_fclose_nonowner(core_file *file); // alternate fclose used by chd_open_file
334 static int core_stdio_fseek(core_file* file, INT64 offset, int whence);
336 /* internal header operations */
337 static chd_error header_validate(const chd_header *header);
338 static chd_error header_read(chd_file *chd, chd_header *header);
340 /* internal hunk read/write */
341 #ifdef NEED_CACHE_HUNK
342 static chd_error hunk_read_into_cache(chd_file *chd, UINT32 hunknum);
344 static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *dest);
346 /* internal map access */
347 static chd_error map_read(chd_file *chd);
349 /* metadata management */
350 static chd_error metadata_find_entry(chd_file *chd, UINT32 metatag, UINT32 metaindex, metadata_entry *metaentry);
352 /* zlib compression codec */
353 static chd_error zlib_codec_init(void *codec, uint32_t hunkbytes);
354 static void zlib_codec_free(void *codec);
355 static chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
356 static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size);
357 static void zlib_fast_free(voidpf opaque, voidpf address);
358 static void zlib_allocator_free(voidpf opaque);
360 /* lzma compression codec */
361 static chd_error lzma_codec_init(void *codec, uint32_t hunkbytes);
362 static void lzma_codec_free(void *codec);
363 static chd_error lzma_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
365 /* huff compression codec */
366 static chd_error huff_codec_init(void *codec, uint32_t hunkbytes);
367 static void huff_codec_free(void *codec);
368 static chd_error huff_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
370 /* flac compression codec */
371 static chd_error flac_codec_init(void *codec, uint32_t hunkbytes);
372 static void flac_codec_free(void *codec);
373 static chd_error flac_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
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);
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);
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);
390 /***************************************************************************
391 * LZMA ALLOCATOR HELPER
392 ***************************************************************************
395 static void *lzma_fast_alloc(void *p, size_t size);
396 static void lzma_fast_free(void *p, void *address);
398 /*-------------------------------------------------
399 * lzma_allocator_init
400 *-------------------------------------------------
403 static void lzma_allocator_init(void* p)
405 lzma_allocator *codec = (lzma_allocator *)(p);
407 /* reset pointer list */
408 memset(codec->allocptr, 0, sizeof(codec->allocptr));
409 memset(codec->allocptr2, 0, sizeof(codec->allocptr2));
410 codec->Alloc = lzma_fast_alloc;
411 codec->Free = lzma_fast_free;
414 /*-------------------------------------------------
415 * lzma_allocator_free
416 *-------------------------------------------------
419 static void lzma_allocator_free(void* p )
422 lzma_allocator *codec = (lzma_allocator *)(p);
424 /* free our memory */
425 for (i = 0 ; i < MAX_LZMA_ALLOCS ; i++)
427 if (codec->allocptr[i] != NULL)
428 free(codec->allocptr[i]);
432 /*-------------------------------------------------
433 * lzma_fast_alloc - fast malloc for lzma, which
434 * allocates and frees memory frequently
435 *-------------------------------------------------
438 /* Huge alignment values for possible SIMD optimization by compiler (NEON, SSE, AVX) */
439 #define LZMA_MIN_ALIGNMENT_BITS 512
440 #define LZMA_MIN_ALIGNMENT_BYTES (LZMA_MIN_ALIGNMENT_BITS / 8)
442 static void *lzma_fast_alloc(void *p, size_t size)
445 uint32_t *addr = NULL;
446 lzma_allocator *codec = (lzma_allocator *)(p);
449 /* compute the size, rounding to the nearest 1k */
450 size = (size + 0x3ff) & ~0x3ff;
452 /* reuse a hunk if we can */
453 for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
455 uint32_t *ptr = codec->allocptr[scan];
456 if (ptr != NULL && size == *ptr)
458 /* set the low bit of the size so we don't match next time */
461 /* return aligned address of the block */
462 return codec->allocptr2[scan];
466 /* alloc a new one and put it into the list */
467 addr = (uint32_t *)malloc(size + sizeof(uint32_t) + LZMA_MIN_ALIGNMENT_BYTES);
470 for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
472 if (codec->allocptr[scan] == NULL)
474 /* store block address */
475 codec->allocptr[scan] = addr;
477 /* compute aligned address, store it */
478 vaddr = (uintptr_t)addr;
479 vaddr = (vaddr + sizeof(uint32_t) + (LZMA_MIN_ALIGNMENT_BYTES-1)) & (~(LZMA_MIN_ALIGNMENT_BYTES-1));
480 codec->allocptr2[scan] = (uint32_t*)vaddr;
485 /* set the low bit of the size so we don't match next time */
488 /* return aligned address */
492 /*-------------------------------------------------
493 * lzma_fast_free - fast free for lzma, which
494 * allocates and frees memory frequently
495 *-------------------------------------------------
498 static void lzma_fast_free(void *p, void *address)
501 uint32_t *ptr = NULL;
502 lzma_allocator *codec = NULL;
507 codec = (lzma_allocator *)(p);
510 ptr = (uint32_t *)address;
511 for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
513 if (ptr == codec->allocptr2[scan])
515 /* clear the low bit of the size to allow matches */
516 *codec->allocptr[scan] &= ~1;
522 /***************************************************************************
524 ***************************************************************************
527 /*-------------------------------------------------
528 * lzma_codec_init - constructor
529 *-------------------------------------------------
532 static chd_error lzma_codec_init(void* codec, uint32_t hunkbytes)
535 CLzmaEncProps encoder_props;
536 Byte decoder_props[LZMA_PROPS_SIZE];
538 lzma_allocator* alloc;
539 lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
541 /* construct the decoder */
542 LzmaDec_Construct(&lzma_codec->decoder);
544 /* FIXME: this code is written in a way that makes it impossible to safely upgrade the LZMA SDK
545 * This code assumes that the current version of the encoder imposes the same requirements on the
546 * decoder as the encoder used to produce the file. This is not necessarily true. The format
547 * needs to be changed so the encoder properties are written to the file.
549 * configure the properties like the compressor did */
550 LzmaEncProps_Init(&encoder_props);
551 encoder_props.level = 9;
552 encoder_props.reduceSize = hunkbytes;
553 LzmaEncProps_Normalize(&encoder_props);
555 /* convert to decoder properties */
556 alloc = &lzma_codec->allocator;
557 lzma_allocator_init(alloc);
558 enc = LzmaEnc_Create((ISzAlloc*)alloc);
560 return CHDERR_DECOMPRESSION_ERROR;
561 if (LzmaEnc_SetProps(enc, &encoder_props) != SZ_OK)
563 LzmaEnc_Destroy(enc, (ISzAlloc*)&alloc, (ISzAlloc*)&alloc);
564 return CHDERR_DECOMPRESSION_ERROR;
566 props_size = sizeof(decoder_props);
567 if (LzmaEnc_WriteProperties(enc, decoder_props, &props_size) != SZ_OK)
569 LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc);
570 return CHDERR_DECOMPRESSION_ERROR;
572 LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc);
574 /* do memory allocations */
575 if (LzmaDec_Allocate(&lzma_codec->decoder, decoder_props, LZMA_PROPS_SIZE, (ISzAlloc*)alloc) != SZ_OK)
576 return CHDERR_DECOMPRESSION_ERROR;
582 /*-------------------------------------------------
584 *-------------------------------------------------
587 static void lzma_codec_free(void* codec)
589 lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
592 LzmaDec_Free(&lzma_codec->decoder, (ISzAlloc*)&lzma_codec->allocator);
593 lzma_allocator_free(&lzma_codec->allocator);
596 /*-------------------------------------------------
597 * decompress - decompress data using the LZMA
599 *-------------------------------------------------
602 static chd_error lzma_codec_decompress(void* codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
606 SizeT consumedlen, decodedlen;
608 lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
609 LzmaDec_Init(&lzma_codec->decoder);
612 consumedlen = complen;
613 decodedlen = destlen;
614 res = LzmaDec_DecodeToBuf(&lzma_codec->decoder, dest, &decodedlen, src, &consumedlen, LZMA_FINISH_END, &status);
615 if ((res != SZ_OK && res != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) || consumedlen != complen || decodedlen != destlen)
616 return CHDERR_DECOMPRESSION_ERROR;
621 static chd_error cdlz_codec_init(void* codec, uint32_t hunkbytes)
624 cdlz_codec_data* cdlz = (cdlz_codec_data*) codec;
626 /* allocate buffer */
627 cdlz->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
628 if (cdlz->buffer == NULL)
629 return CHDERR_OUT_OF_MEMORY;
631 /* make sure the CHD's hunk size is an even multiple of the frame size */
632 ret = lzma_codec_init(&cdlz->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
633 if (ret != CHDERR_NONE)
637 ret = zlib_codec_init(&cdlz->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SUBCODE_DATA);
638 if (ret != CHDERR_NONE)
642 if (hunkbytes % CD_FRAME_SIZE != 0)
643 return CHDERR_CODEC_ERROR;
648 static void cdlz_codec_free(void* codec)
650 cdlz_codec_data* cdlz = (cdlz_codec_data*) codec;
652 lzma_codec_free(&cdlz->base_decompressor);
654 zlib_codec_free(&cdlz->subcode_decompressor);
658 static chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
661 cdlz_codec_data* cdlz = (cdlz_codec_data*)codec;
663 /* determine header bytes */
664 uint32_t frames = destlen / CD_FRAME_SIZE;
665 uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
666 uint32_t ecc_bytes = (frames + 7) / 8;
667 uint32_t header_bytes = ecc_bytes + complen_bytes;
669 /* extract compressed length of base */
670 uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
671 if (complen_bytes > 2)
672 complen_base = (complen_base << 8) | src[ecc_bytes + 2];
674 /* reset and decode */
675 lzma_codec_decompress(&cdlz->base_decompressor, &src[header_bytes], complen_base, &cdlz->buffer[0], frames * CD_MAX_SECTOR_DATA);
677 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);
680 /* reassemble the data */
681 for (framenum = 0; framenum < frames; framenum++)
685 memcpy(&dest[framenum * CD_FRAME_SIZE], &cdlz->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
687 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);
690 #ifdef WANT_RAW_DATA_SECTOR
691 /* reconstitute the ECC data and sync header */
692 sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE];
693 if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
695 memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
696 ecc_generate(sector);
705 static chd_error cdzl_codec_init(void *codec, uint32_t hunkbytes)
708 cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
710 /* make sure the CHD's hunk size is an even multiple of the frame size */
711 if (hunkbytes % CD_FRAME_SIZE != 0)
712 return CHDERR_CODEC_ERROR;
714 cdzl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
715 if (cdzl->buffer == NULL)
716 return CHDERR_OUT_OF_MEMORY;
718 ret = zlib_codec_init(&cdzl->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
719 if (ret != CHDERR_NONE)
723 ret = zlib_codec_init(&cdzl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SUBCODE_DATA);
724 if (ret != CHDERR_NONE)
731 static void cdzl_codec_free(void *codec)
733 cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
734 zlib_codec_free(&cdzl->base_decompressor);
736 zlib_codec_free(&cdzl->subcode_decompressor);
741 static chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
744 cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
746 /* determine header bytes */
747 uint32_t frames = destlen / CD_FRAME_SIZE;
748 uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
749 uint32_t ecc_bytes = (frames + 7) / 8;
750 uint32_t header_bytes = ecc_bytes + complen_bytes;
752 /* extract compressed length of base */
753 uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
754 if (complen_bytes > 2)
755 complen_base = (complen_base << 8) | src[ecc_bytes + 2];
757 /* reset and decode */
758 zlib_codec_decompress(&cdzl->base_decompressor, &src[header_bytes], complen_base, &cdzl->buffer[0], frames * CD_MAX_SECTOR_DATA);
760 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);
763 /* reassemble the data */
764 for (framenum = 0; framenum < frames; framenum++)
768 memcpy(&dest[framenum * CD_FRAME_SIZE], &cdzl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
770 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);
773 #ifdef WANT_RAW_DATA_SECTOR
774 /* reconstitute the ECC data and sync header */
775 sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE];
776 if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
778 memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
779 ecc_generate(sector);
786 /***************************************************************************
787 * HUFFMAN DECOMPRESSOR
788 ***************************************************************************
791 static chd_error huff_codec_init(void* codec, uint32_t hunkbytes)
793 huff_codec_data* huff_codec = (huff_codec_data*) codec;
794 huff_codec->decoder = create_huffman_decoder(256, 16);
798 static void huff_codec_free(void *codec)
800 huff_codec_data* huff_codec = (huff_codec_data*) codec;
801 delete_huffman_decoder(huff_codec->decoder);
804 static chd_error huff_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
806 huff_codec_data* huff_codec = (huff_codec_data*) codec;
807 struct bitstream* bitbuf = create_bitstream(src, complen);
809 // first import the tree
810 enum huffman_error err = huffman_import_tree_huffman(huff_codec->decoder, bitbuf);
811 if (err != HUFFERR_NONE)
817 // then decode the data
818 for (uint32_t cur = 0; cur < destlen; cur++)
819 dest[cur] = huffman_decode_one(huff_codec->decoder, bitbuf);
820 bitstream_flush(bitbuf);
821 chd_error result = bitstream_overflow(bitbuf) ? CHDERR_DECOMPRESSION_ERROR : CHDERR_NONE;
827 /***************************************************************************
828 * CD FLAC DECOMPRESSOR
829 ***************************************************************************
832 /*------------------------------------------------------
833 * flac_codec_blocksize - return the optimal block size
834 *------------------------------------------------------
837 static uint32_t flac_codec_blocksize(uint32_t bytes)
839 /* determine FLAC block size, which must be 16-65535
840 * clamp to 2k since that's supposed to be the sweet spot */
841 uint32_t blocksize = bytes / 4;
842 while (blocksize > 2048)
847 static chd_error flac_codec_init(void *codec, uint32_t hunkbytes)
849 uint16_t native_endian = 0;
850 flac_codec_data *flac = (flac_codec_data*)codec;
852 /* make sure the CHD's hunk size is an even multiple of the sample size */
853 if (hunkbytes % 4 != 0)
854 return CHDERR_CODEC_ERROR;
856 /* determine whether we want native or swapped samples */
857 *(uint8_t *)(&native_endian) = 1;
858 flac->native_endian = (native_endian & 1);
860 /* flac decoder init */
861 if (flac_decoder_init(&flac->decoder))
862 return CHDERR_OUT_OF_MEMORY;
867 static void flac_codec_free(void *codec)
869 flac_codec_data *flac = (flac_codec_data*)codec;
870 flac_decoder_free(&flac->decoder);
873 static chd_error flac_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
875 flac_codec_data *flac = (flac_codec_data*)codec;
879 swap_endian = !flac->native_endian;
880 else if (src[0] == 'B')
881 swap_endian = flac->native_endian;
883 return CHDERR_DECOMPRESSION_ERROR;
885 if (!flac_decoder_reset(&flac->decoder, 44100, 2, flac_codec_blocksize(destlen), src + 1, complen - 1))
886 return CHDERR_DECOMPRESSION_ERROR;
887 if (!flac_decoder_decode_interleaved(&flac->decoder, (int16_t *)(dest), destlen/4, swap_endian))
888 return CHDERR_DECOMPRESSION_ERROR;
889 flac_decoder_finish(&flac->decoder);
894 static uint32_t cdfl_codec_blocksize(uint32_t bytes)
896 // for CDs it seems that CD_MAX_SECTOR_DATA is the right target
897 uint32_t blocksize = bytes / 4;
898 while (blocksize > CD_MAX_SECTOR_DATA)
903 static chd_error cdfl_codec_init(void *codec, uint32_t hunkbytes)
908 uint16_t native_endian = 0;
909 cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
911 /* make sure the CHD's hunk size is an even multiple of the frame size */
912 if (hunkbytes % CD_FRAME_SIZE != 0)
913 return CHDERR_CODEC_ERROR;
915 cdfl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
916 if (cdfl->buffer == NULL)
917 return CHDERR_OUT_OF_MEMORY;
919 /* determine whether we want native or swapped samples */
920 *(uint8_t *)(&native_endian) = 1;
921 cdfl->swap_endian = (native_endian & 1);
924 /* init zlib inflater */
925 ret = zlib_codec_init(&cdfl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
926 if (ret != CHDERR_NONE)
930 /* flac decoder init */
931 if (flac_decoder_init(&cdfl->decoder))
932 return CHDERR_OUT_OF_MEMORY;
937 static void cdfl_codec_free(void *codec)
939 cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
940 flac_decoder_free(&cdfl->decoder);
942 zlib_codec_free(&cdfl->subcode_decompressor);
948 static chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
956 cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
958 /* reset and decode */
959 uint32_t frames = destlen / CD_FRAME_SIZE;
961 if (!flac_decoder_reset(&cdfl->decoder, 44100, 2, cdfl_codec_blocksize(frames * CD_MAX_SECTOR_DATA), src, complen))
962 return CHDERR_DECOMPRESSION_ERROR;
963 buffer = &cdfl->buffer[0];
964 if (!flac_decoder_decode_interleaved(&cdfl->decoder, (int16_t *)(buffer), frames * CD_MAX_SECTOR_DATA/4, cdfl->swap_endian))
965 return CHDERR_DECOMPRESSION_ERROR;
968 /* inflate the subcode data */
969 offset = flac_decoder_finish(&cdfl->decoder);
970 ret = zlib_codec_decompress(&cdfl->subcode_decompressor, src + offset, complen - offset, &cdfl->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA);
971 if (ret != CHDERR_NONE)
974 flac_decoder_finish(&cdfl->decoder);
977 /* reassemble the data */
978 for (framenum = 0; framenum < frames; framenum++)
980 memcpy(&dest[framenum * CD_FRAME_SIZE], &cdfl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
982 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);
988 /***************************************************************************
990 ***************************************************************************/
992 static const codec_interface codec_interfaces[] =
994 /* "none" or no compression */
1005 /* standard zlib compression */
1007 CHDCOMPRESSION_ZLIB,
1012 zlib_codec_decompress,
1016 /* zlib+ compression */
1018 CHDCOMPRESSION_ZLIB_PLUS,
1023 zlib_codec_decompress,
1027 /* V5 zlib compression */
1034 zlib_codec_decompress,
1038 /* V5 lzma compression */
1045 lzma_codec_decompress,
1049 /* V5 huffman compression */
1056 huff_codec_decompress,
1060 /* V5 flac compression */
1067 flac_codec_decompress,
1071 /* V5 CD zlib compression */
1074 "cdzl (CD Deflate)",
1078 cdzl_codec_decompress,
1082 /* V5 CD lzma compression */
1089 cdlz_codec_decompress,
1093 /* V5 CD flac compression */
1100 cdfl_codec_decompress,
1105 /***************************************************************************
1107 ***************************************************************************/
1109 /*-------------------------------------------------
1110 get_bigendian_uint64 - fetch a UINT64 from
1111 the data stream in bigendian order
1112 -------------------------------------------------*/
1114 static inline UINT64 get_bigendian_uint64(const UINT8 *base)
1116 return ((UINT64)base[0] << 56) | ((UINT64)base[1] << 48) | ((UINT64)base[2] << 40) | ((UINT64)base[3] << 32) |
1117 ((UINT64)base[4] << 24) | ((UINT64)base[5] << 16) | ((UINT64)base[6] << 8) | (UINT64)base[7];
1120 /*-------------------------------------------------
1121 put_bigendian_uint64 - write a UINT64 to
1122 the data stream in bigendian order
1123 -------------------------------------------------*/
1125 static inline void put_bigendian_uint64(UINT8 *base, UINT64 value)
1127 base[0] = value >> 56;
1128 base[1] = value >> 48;
1129 base[2] = value >> 40;
1130 base[3] = value >> 32;
1131 base[4] = value >> 24;
1132 base[5] = value >> 16;
1133 base[6] = value >> 8;
1137 /*-------------------------------------------------
1138 get_bigendian_uint48 - fetch a UINT48 from
1139 the data stream in bigendian order
1140 -------------------------------------------------*/
1142 static inline UINT64 get_bigendian_uint48(const UINT8 *base)
1144 return ((UINT64)base[0] << 40) | ((UINT64)base[1] << 32) |
1145 ((UINT64)base[2] << 24) | ((UINT64)base[3] << 16) | ((UINT64)base[4] << 8) | (UINT64)base[5];
1148 /*-------------------------------------------------
1149 put_bigendian_uint48 - write a UINT48 to
1150 the data stream in bigendian order
1151 -------------------------------------------------*/
1153 static inline void put_bigendian_uint48(UINT8 *base, UINT64 value)
1155 value &= 0xffffffffffff;
1156 base[0] = value >> 40;
1157 base[1] = value >> 32;
1158 base[2] = value >> 24;
1159 base[3] = value >> 16;
1160 base[4] = value >> 8;
1163 /*-------------------------------------------------
1164 get_bigendian_uint32 - fetch a UINT32 from
1165 the data stream in bigendian order
1166 -------------------------------------------------*/
1168 static inline UINT32 get_bigendian_uint32(const UINT8 *base)
1170 return (base[0] << 24) | (base[1] << 16) | (base[2] << 8) | base[3];
1173 /*-------------------------------------------------
1174 put_bigendian_uint32 - write a UINT32 to
1175 the data stream in bigendian order
1176 -------------------------------------------------*/
1178 static inline void put_bigendian_uint32(UINT8 *base, UINT32 value)
1180 base[0] = value >> 24;
1181 base[1] = value >> 16;
1182 base[2] = value >> 8;
1186 /*-------------------------------------------------
1187 put_bigendian_uint24 - write a UINT24 to
1188 the data stream in bigendian order
1189 -------------------------------------------------*/
1191 static inline void put_bigendian_uint24(UINT8 *base, UINT32 value)
1194 base[0] = value >> 16;
1195 base[1] = value >> 8;
1199 /*-------------------------------------------------
1200 get_bigendian_uint24 - fetch a UINT24 from
1201 the data stream in bigendian order
1202 -------------------------------------------------*/
1204 static inline UINT32 get_bigendian_uint24(const UINT8 *base)
1206 return (base[0] << 16) | (base[1] << 8) | base[2];
1209 /*-------------------------------------------------
1210 get_bigendian_uint16 - fetch a UINT16 from
1211 the data stream in bigendian order
1212 -------------------------------------------------*/
1214 static inline UINT16 get_bigendian_uint16(const UINT8 *base)
1216 return (base[0] << 8) | base[1];
1219 /*-------------------------------------------------
1220 put_bigendian_uint16 - write a UINT16 to
1221 the data stream in bigendian order
1222 -------------------------------------------------*/
1224 static inline void put_bigendian_uint16(UINT8 *base, UINT16 value)
1226 base[0] = value >> 8;
1230 /*-------------------------------------------------
1231 map_extract - extract a single map
1232 entry from the datastream
1233 -------------------------------------------------*/
1235 static inline void map_extract(const UINT8 *base, map_entry *entry)
1237 entry->offset = get_bigendian_uint64(&base[0]);
1238 entry->crc = get_bigendian_uint32(&base[8]);
1239 entry->length = get_bigendian_uint16(&base[12]) | (base[14] << 16);
1240 entry->flags = base[15];
1243 /*-------------------------------------------------
1244 map_assemble - write a single map
1245 entry to the datastream
1246 -------------------------------------------------*/
1248 static inline void map_assemble(UINT8 *base, map_entry *entry)
1250 put_bigendian_uint64(&base[0], entry->offset);
1251 put_bigendian_uint32(&base[8], entry->crc);
1252 put_bigendian_uint16(&base[12], entry->length);
1253 base[14] = entry->length >> 16;
1254 base[15] = entry->flags;
1257 /*-------------------------------------------------
1258 map_size_v5 - calculate CHDv5 map size
1259 -------------------------------------------------*/
1260 static inline int map_size_v5(chd_header* header)
1262 return header->hunkcount * header->mapentrybytes;
1265 /*-------------------------------------------------
1266 crc16 - calculate CRC16 (from hashing.cpp)
1267 -------------------------------------------------*/
1268 uint16_t crc16(const void *data, uint32_t length)
1270 uint16_t crc = 0xffff;
1272 static const uint16_t s_table[256] =
1274 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1275 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1276 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1277 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1278 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1279 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1280 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1281 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1282 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1283 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1284 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1285 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1286 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1287 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1288 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1289 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1290 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1291 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1292 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1293 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1294 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1295 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1296 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1297 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1298 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1299 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1300 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1301 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1302 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1303 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1304 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1305 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1308 const uint8_t *src = (uint8_t*)data;
1310 /* fetch the current value into a local and rip through the source data */
1311 while (length-- != 0)
1312 crc = (crc << 8) ^ s_table[(crc >> 8) ^ *src++];
1316 /*-------------------------------------------------
1317 compressed - test if CHD file is compressed
1318 +-------------------------------------------------*/
1319 static inline int chd_compressed(chd_header* header) {
1320 return header->compression[0] != CHD_CODEC_NONE;
1323 /*-------------------------------------------------
1324 decompress_v5_map - decompress the v5 map
1325 -------------------------------------------------*/
1327 static chd_error decompress_v5_map(chd_file* chd, chd_header* header)
1332 uint8_t lastcomp = 0;
1333 uint32_t last_self = 0;
1334 uint64_t last_parent = 0;
1335 struct bitstream* bitbuf;
1342 uint8_t *compressed_ptr;
1344 struct huffman_decoder* decoder;
1345 enum huffman_error err;
1347 int rawmapsize = map_size_v5(header);
1349 if (!chd_compressed(header))
1351 header->rawmap = (uint8_t*)malloc(rawmapsize);
1352 if (header->rawmap == NULL)
1353 return CHDERR_OUT_OF_MEMORY;
1354 core_fseek(chd->file, header->mapoffset, SEEK_SET);
1355 result = core_fread(chd->file, header->rawmap, rawmapsize);
1359 /* read the reader */
1360 core_fseek(chd->file, header->mapoffset, SEEK_SET);
1361 result = core_fread(chd->file, rawbuf, sizeof(rawbuf));
1362 mapbytes = get_bigendian_uint32(&rawbuf[0]);
1363 firstoffs = get_bigendian_uint48(&rawbuf[4]);
1364 mapcrc = get_bigendian_uint16(&rawbuf[10]);
1365 lengthbits = rawbuf[12];
1366 selfbits = rawbuf[13];
1367 parentbits = rawbuf[14];
1369 /* now read the map */
1370 compressed_ptr = (uint8_t*)malloc(sizeof(uint8_t) * mapbytes);
1371 if (compressed_ptr == NULL)
1372 return CHDERR_OUT_OF_MEMORY;
1373 core_fseek(chd->file, header->mapoffset + 16, SEEK_SET);
1374 result = core_fread(chd->file, compressed_ptr, mapbytes);
1375 bitbuf = create_bitstream(compressed_ptr, sizeof(uint8_t) * mapbytes);
1376 header->rawmap = (uint8_t*)malloc(rawmapsize);
1377 if (header->rawmap == NULL)
1379 free(compressed_ptr);
1381 return CHDERR_OUT_OF_MEMORY;
1384 /* first decode the compression types */
1385 decoder = create_huffman_decoder(16, 8);
1386 if (decoder == NULL)
1388 free(compressed_ptr);
1390 return CHDERR_OUT_OF_MEMORY;
1393 err = huffman_import_tree_rle(decoder, bitbuf);
1394 if (err != HUFFERR_NONE)
1396 free(compressed_ptr);
1398 delete_huffman_decoder(decoder);
1399 return CHDERR_DECOMPRESSION_ERROR;
1402 for (hunknum = 0; hunknum < header->hunkcount; hunknum++)
1404 uint8_t *rawmap = header->rawmap + (hunknum * 12);
1406 rawmap[0] = lastcomp, repcount--;
1409 uint8_t val = huffman_decode_one(decoder, bitbuf);
1410 if (val == COMPRESSION_RLE_SMALL)
1411 rawmap[0] = lastcomp, repcount = 2 + huffman_decode_one(decoder, bitbuf);
1412 else if (val == COMPRESSION_RLE_LARGE)
1413 rawmap[0] = lastcomp, repcount = 2 + 16 + (huffman_decode_one(decoder, bitbuf) << 4), repcount += huffman_decode_one(decoder, bitbuf);
1415 rawmap[0] = lastcomp = val;
1419 /* then iterate through the hunks and extract the needed data */
1420 curoffset = firstoffs;
1421 for (hunknum = 0; hunknum < header->hunkcount; hunknum++)
1423 uint8_t *rawmap = header->rawmap + (hunknum * 12);
1424 uint64_t offset = curoffset;
1425 uint32_t length = 0;
1430 case COMPRESSION_TYPE_0:
1431 case COMPRESSION_TYPE_1:
1432 case COMPRESSION_TYPE_2:
1433 case COMPRESSION_TYPE_3:
1434 curoffset += length = bitstream_read(bitbuf, lengthbits);
1435 crc = bitstream_read(bitbuf, 16);
1438 case COMPRESSION_NONE:
1439 curoffset += length = header->hunkbytes;
1440 crc = bitstream_read(bitbuf, 16);
1443 case COMPRESSION_SELF:
1444 last_self = offset = bitstream_read(bitbuf, selfbits);
1447 case COMPRESSION_PARENT:
1448 offset = bitstream_read(bitbuf, parentbits);
1449 last_parent = offset;
1452 /* pseudo-types; convert into base types */
1453 case COMPRESSION_SELF_1:
1455 case COMPRESSION_SELF_0:
1456 rawmap[0] = COMPRESSION_SELF;
1460 case COMPRESSION_PARENT_SELF:
1461 rawmap[0] = COMPRESSION_PARENT;
1462 last_parent = offset = ( ((uint64_t)hunknum) * ((uint64_t)header->hunkbytes) ) / header->unitbytes;
1465 case COMPRESSION_PARENT_1:
1466 last_parent += header->hunkbytes / header->unitbytes;
1467 case COMPRESSION_PARENT_0:
1468 rawmap[0] = COMPRESSION_PARENT;
1469 offset = last_parent;
1473 put_bigendian_uint24(&rawmap[1], length);
1476 put_bigendian_uint48(&rawmap[4], offset);
1479 put_bigendian_uint16(&rawmap[10], crc);
1483 free(compressed_ptr);
1485 delete_huffman_decoder(decoder);
1487 /* verify the final CRC */
1488 if (crc16(&header->rawmap[0], header->hunkcount * 12) != mapcrc)
1489 return CHDERR_DECOMPRESSION_ERROR;
1494 /*-------------------------------------------------
1495 map_extract_old - extract a single map
1496 entry in old format from the datastream
1497 -------------------------------------------------*/
1499 static inline void map_extract_old(const UINT8 *base, map_entry *entry, UINT32 hunkbytes)
1501 entry->offset = get_bigendian_uint64(&base[0]);
1503 entry->length = entry->offset >> 44;
1504 entry->flags = MAP_ENTRY_FLAG_NO_CRC | ((entry->length == hunkbytes) ? V34_MAP_ENTRY_TYPE_UNCOMPRESSED : V34_MAP_ENTRY_TYPE_COMPRESSED);
1506 entry->offset = entry->offset & 0x00000FFFFFFFFFFFLL;
1508 entry->offset = (entry->offset << 20) >> 20;
1512 /***************************************************************************
1514 ***************************************************************************/
1516 /*-------------------------------------------------
1517 chd_open_file - open a CHD file for access
1518 -------------------------------------------------*/
1520 CHD_EXPORT chd_error chd_open_file(FILE *file, int mode, chd_file *parent, chd_file **chd) {
1521 core_file *stream = malloc(sizeof(core_file));
1523 return CHDERR_OUT_OF_MEMORY;
1524 stream->argp = file;
1525 stream->fsize = core_stdio_fsize;
1526 stream->fread = core_stdio_fread;
1527 stream->fclose = core_stdio_fclose_nonowner;
1528 stream->fseek = core_stdio_fseek;
1530 return chd_open_core_file(stream, mode, parent, chd);
1533 /*-------------------------------------------------
1534 chd_open_core_file - open a CHD file for access
1535 -------------------------------------------------*/
1537 CHD_EXPORT chd_error chd_open_core_file(core_file *file, int mode, chd_file *parent, chd_file **chd)
1539 chd_file *newchd = NULL;
1543 /* verify parameters */
1545 EARLY_EXIT(err = CHDERR_INVALID_PARAMETER);
1547 /* punt if invalid parent */
1548 if (parent != NULL && parent->cookie != COOKIE_VALUE)
1549 EARLY_EXIT(err = CHDERR_INVALID_PARAMETER);
1551 /* allocate memory for the final result */
1552 newchd = (chd_file *)malloc(sizeof(**chd));
1554 EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
1555 memset(newchd, 0, sizeof(*newchd));
1556 newchd->cookie = COOKIE_VALUE;
1557 newchd->parent = parent;
1558 newchd->file = file;
1560 /* now attempt to read the header */
1561 err = header_read(newchd, &newchd->header);
1562 if (err != CHDERR_NONE)
1565 /* validate the header */
1566 err = header_validate(&newchd->header);
1567 if (err != CHDERR_NONE)
1570 /* make sure we don't open a read-only file writeable */
1571 if (mode == CHD_OPEN_READWRITE && !(newchd->header.flags & CHDFLAGS_IS_WRITEABLE))
1572 EARLY_EXIT(err = CHDERR_FILE_NOT_WRITEABLE);
1574 /* also, never open an older version writeable */
1575 if (mode == CHD_OPEN_READWRITE && newchd->header.version < CHD_HEADER_VERSION)
1576 EARLY_EXIT(err = CHDERR_UNSUPPORTED_VERSION);
1578 /* if we need a parent, make sure we have one */
1581 /* Detect parent requirement for versions below 5 */
1582 if (newchd->header.version < 5 && newchd->header.flags & CHDFLAGS_HAS_PARENT)
1583 EARLY_EXIT(err = CHDERR_REQUIRES_PARENT);
1584 /* Detection for version 5 and above - if parentsha1 != 0, we have a parent */
1585 else if (newchd->header.version >= 5 && memcmp(nullsha1, newchd->header.parentsha1, sizeof(newchd->header.parentsha1)) != 0)
1586 EARLY_EXIT(err = CHDERR_REQUIRES_PARENT);
1589 /* make sure we have a valid parent */
1592 /* check MD5 if it isn't empty */
1593 if (memcmp(nullmd5, newchd->header.parentmd5, sizeof(newchd->header.parentmd5)) != 0 &&
1594 memcmp(nullmd5, newchd->parent->header.md5, sizeof(newchd->parent->header.md5)) != 0 &&
1595 memcmp(newchd->parent->header.md5, newchd->header.parentmd5, sizeof(newchd->header.parentmd5)) != 0)
1596 EARLY_EXIT(err = CHDERR_INVALID_PARENT);
1598 /* check SHA1 if it isn't empty */
1599 if (memcmp(nullsha1, newchd->header.parentsha1, sizeof(newchd->header.parentsha1)) != 0 &&
1600 memcmp(nullsha1, newchd->parent->header.sha1, sizeof(newchd->parent->header.sha1)) != 0 &&
1601 memcmp(newchd->parent->header.sha1, newchd->header.parentsha1, sizeof(newchd->header.parentsha1)) != 0)
1602 EARLY_EXIT(err = CHDERR_INVALID_PARENT);
1605 /* now read the hunk map */
1606 if (newchd->header.version < 5)
1608 err = map_read(newchd);
1609 if (err != CHDERR_NONE)
1614 err = decompress_v5_map(newchd, &(newchd->header));
1616 if (err != CHDERR_NONE)
1619 #ifdef NEED_CACHE_HUNK
1620 /* allocate and init the hunk cache */
1621 newchd->cache = (UINT8 *)malloc(newchd->header.hunkbytes);
1622 newchd->compare = (UINT8 *)malloc(newchd->header.hunkbytes);
1623 if (newchd->cache == NULL || newchd->compare == NULL)
1624 EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
1625 newchd->cachehunk = ~0;
1626 newchd->comparehunk = ~0;
1629 /* allocate the temporary compressed buffer */
1630 newchd->compressed = (UINT8 *)malloc(newchd->header.hunkbytes);
1631 if (newchd->compressed == NULL)
1632 EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
1634 /* find the codec interface */
1635 if (newchd->header.version < 5)
1637 for (intfnum = 0; intfnum < ARRAY_LENGTH(codec_interfaces); intfnum++)
1639 if (codec_interfaces[intfnum].compression == newchd->header.compression[0])
1641 newchd->codecintf[0] = &codec_interfaces[intfnum];
1646 if (intfnum == ARRAY_LENGTH(codec_interfaces))
1647 EARLY_EXIT(err = CHDERR_UNSUPPORTED_FORMAT);
1649 /* initialize the codec */
1650 if (newchd->codecintf[0]->init != NULL)
1652 err = (*newchd->codecintf[0]->init)(&newchd->zlib_codec_data, newchd->header.hunkbytes);
1653 if (err != CHDERR_NONE)
1660 /* verify the compression types and initialize the codecs */
1661 for (decompnum = 0; decompnum < ARRAY_LENGTH(newchd->header.compression); decompnum++)
1664 for (i = 0 ; i < ARRAY_LENGTH(codec_interfaces) ; i++)
1666 if (codec_interfaces[i].compression == newchd->header.compression[decompnum])
1668 newchd->codecintf[decompnum] = &codec_interfaces[i];
1673 if (newchd->codecintf[decompnum] == NULL && newchd->header.compression[decompnum] != 0)
1674 EARLY_EXIT(err = CHDERR_UNSUPPORTED_FORMAT);
1676 /* initialize the codec */
1677 if (newchd->codecintf[decompnum]->init != NULL)
1680 switch (newchd->header.compression[decompnum])
1682 case CHD_CODEC_ZLIB:
1683 codec = &newchd->zlib_codec_data;
1686 case CHD_CODEC_LZMA:
1687 codec = &newchd->lzma_codec_data;
1690 case CHD_CODEC_HUFFMAN:
1691 codec = &newchd->huff_codec_data;
1694 case CHD_CODEC_FLAC:
1695 codec = &newchd->flac_codec_data;
1698 case CHD_CODEC_CD_ZLIB:
1699 codec = &newchd->cdzl_codec_data;
1702 case CHD_CODEC_CD_LZMA:
1703 codec = &newchd->cdlz_codec_data;
1706 case CHD_CODEC_CD_FLAC:
1707 codec = &newchd->cdfl_codec_data;
1712 EARLY_EXIT(err = CHDERR_UNSUPPORTED_FORMAT);
1714 err = (*newchd->codecintf[decompnum]->init)(codec, newchd->header.hunkbytes);
1715 if (err != CHDERR_NONE)
1731 /*-------------------------------------------------
1732 chd_precache - precache underlying file in
1734 -------------------------------------------------*/
1736 CHD_EXPORT chd_error chd_precache(chd_file *chd)
1741 if (chd->file_cache == NULL)
1743 size = core_fsize(chd->file);
1744 if ((INT64)size <= 0)
1745 return CHDERR_INVALID_DATA;
1746 chd->file_cache = malloc(size);
1747 if (chd->file_cache == NULL)
1748 return CHDERR_OUT_OF_MEMORY;
1749 core_fseek(chd->file, 0, SEEK_SET);
1750 count = core_fread(chd->file, chd->file_cache, size);
1753 free(chd->file_cache);
1754 chd->file_cache = NULL;
1755 return CHDERR_READ_ERROR;
1762 /*-------------------------------------------------
1763 chd_open - open a CHD file by
1765 -------------------------------------------------*/
1767 CHD_EXPORT chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd)
1770 core_file *file = NULL;
1772 if (filename == NULL)
1774 err = CHDERR_INVALID_PARAMETER;
1778 /* choose the proper mode */
1785 err = CHDERR_INVALID_PARAMETER;
1790 file = core_stdio_fopen(filename);
1793 err = CHDERR_FILE_NOT_FOUND;
1797 /* now open the CHD */
1798 return chd_open_core_file(file, mode, parent, chd);
1801 if ((err != CHDERR_NONE) && (file != NULL))
1806 /*-------------------------------------------------
1807 chd_close - close a CHD file for access
1808 -------------------------------------------------*/
1810 CHD_EXPORT void chd_close(chd_file *chd)
1812 /* punt if NULL or invalid */
1813 if (chd == NULL || chd->cookie != COOKIE_VALUE)
1816 /* deinit the codec */
1817 if (chd->header.version < 5)
1819 if (chd->codecintf[0] != NULL && chd->codecintf[0]->free != NULL)
1820 (*chd->codecintf[0]->free)(&chd->zlib_codec_data);
1825 /* Free the codecs */
1826 for (i = 0 ; i < ARRAY_LENGTH(chd->codecintf); i++)
1830 if (chd->codecintf[i] == NULL)
1833 switch (chd->codecintf[i]->compression)
1835 case CHD_CODEC_ZLIB:
1836 codec = &chd->zlib_codec_data;
1839 case CHD_CODEC_LZMA:
1840 codec = &chd->lzma_codec_data;
1843 case CHD_CODEC_HUFFMAN:
1844 codec = &chd->huff_codec_data;
1847 case CHD_CODEC_FLAC:
1848 codec = &chd->flac_codec_data;
1851 case CHD_CODEC_CD_ZLIB:
1852 codec = &chd->cdzl_codec_data;
1855 case CHD_CODEC_CD_LZMA:
1856 codec = &chd->cdlz_codec_data;
1859 case CHD_CODEC_CD_FLAC:
1860 codec = &chd->cdfl_codec_data;
1866 (*chd->codecintf[i]->free)(codec);
1870 /* Free the raw map */
1871 if (chd->header.rawmap != NULL)
1872 free(chd->header.rawmap);
1875 /* free the compressed data buffer */
1876 if (chd->compressed != NULL)
1877 free(chd->compressed);
1879 #ifdef NEED_CACHE_HUNK
1880 /* free the hunk cache and compare data */
1881 if (chd->compare != NULL)
1883 if (chd->cache != NULL)
1887 /* free the hunk map */
1888 if (chd->map != NULL)
1891 /* close the file */
1892 if (chd->file != NULL)
1893 core_fclose(chd->file);
1895 #ifdef NEED_CACHE_HUNK
1896 if (PRINTF_MAX_HUNK) printf("Max hunk = %d/%d\n", chd->maxhunk, chd->header.totalhunks);
1898 if (chd->file_cache)
1899 free(chd->file_cache);
1902 chd_close(chd->parent);
1904 /* free our memory */
1908 /*-------------------------------------------------
1909 chd_core_file - return the associated
1911 -------------------------------------------------*/
1913 CHD_EXPORT core_file *chd_core_file(chd_file *chd)
1918 /*-------------------------------------------------
1919 chd_error_string - return an error string for
1921 -------------------------------------------------*/
1923 CHD_EXPORT const char *chd_error_string(chd_error err)
1927 case CHDERR_NONE: return "no error";
1928 case CHDERR_NO_INTERFACE: return "no drive interface";
1929 case CHDERR_OUT_OF_MEMORY: return "out of memory";
1930 case CHDERR_INVALID_FILE: return "invalid file";
1931 case CHDERR_INVALID_PARAMETER: return "invalid parameter";
1932 case CHDERR_INVALID_DATA: return "invalid data";
1933 case CHDERR_FILE_NOT_FOUND: return "file not found";
1934 case CHDERR_REQUIRES_PARENT: return "requires parent";
1935 case CHDERR_FILE_NOT_WRITEABLE: return "file not writeable";
1936 case CHDERR_READ_ERROR: return "read error";
1937 case CHDERR_WRITE_ERROR: return "write error";
1938 case CHDERR_CODEC_ERROR: return "codec error";
1939 case CHDERR_INVALID_PARENT: return "invalid parent";
1940 case CHDERR_HUNK_OUT_OF_RANGE: return "hunk out of range";
1941 case CHDERR_DECOMPRESSION_ERROR: return "decompression error";
1942 case CHDERR_COMPRESSION_ERROR: return "compression error";
1943 case CHDERR_CANT_CREATE_FILE: return "can't create file";
1944 case CHDERR_CANT_VERIFY: return "can't verify file";
1945 case CHDERR_NOT_SUPPORTED: return "operation not supported";
1946 case CHDERR_METADATA_NOT_FOUND: return "can't find metadata";
1947 case CHDERR_INVALID_METADATA_SIZE: return "invalid metadata size";
1948 case CHDERR_UNSUPPORTED_VERSION: return "unsupported CHD version";
1949 case CHDERR_VERIFY_INCOMPLETE: return "incomplete verify";
1950 case CHDERR_INVALID_METADATA: return "invalid metadata";
1951 case CHDERR_INVALID_STATE: return "invalid state";
1952 case CHDERR_OPERATION_PENDING: return "operation pending";
1953 case CHDERR_NO_ASYNC_OPERATION: return "no async operation in progress";
1954 case CHDERR_UNSUPPORTED_FORMAT: return "unsupported format";
1955 default: return "undocumented error";
1959 /***************************************************************************
1960 CHD HEADER MANAGEMENT
1961 ***************************************************************************/
1963 /*-------------------------------------------------
1964 chd_get_header - return a pointer to the
1965 extracted header data
1966 -------------------------------------------------*/
1968 CHD_EXPORT const chd_header *chd_get_header(chd_file *chd)
1970 /* punt if NULL or invalid */
1971 if (chd == NULL || chd->cookie != COOKIE_VALUE)
1974 return &chd->header;
1977 /*-------------------------------------------------
1978 chd_read_header - read CHD header data
1979 from file into the pointed struct
1980 -------------------------------------------------*/
1981 CHD_EXPORT chd_error chd_read_header(const char *filename, chd_header *header)
1983 chd_error err = CHDERR_NONE;
1987 if (filename == NULL || header == NULL)
1988 EARLY_EXIT(err = CHDERR_INVALID_PARAMETER);
1991 chd.file = core_stdio_fopen(filename);
1992 if (chd.file == NULL)
1993 EARLY_EXIT(err = CHDERR_FILE_NOT_FOUND);
1995 /* attempt to read the header */
1996 err = header_read(&chd, header);
1997 if (err != CHDERR_NONE)
2000 /* validate the header */
2001 err = header_validate(header);
2002 if (err != CHDERR_NONE)
2006 if (chd.file != NULL)
2007 core_fclose(chd.file);
2012 /***************************************************************************
2013 CORE DATA READ/WRITE
2014 ***************************************************************************/
2016 /*-------------------------------------------------
2017 chd_read - read a single hunk from the CHD
2019 -------------------------------------------------*/
2021 CHD_EXPORT chd_error chd_read(chd_file *chd, UINT32 hunknum, void *buffer)
2023 /* punt if NULL or invalid */
2024 if (chd == NULL || chd->cookie != COOKIE_VALUE)
2025 return CHDERR_INVALID_PARAMETER;
2027 /* if we're past the end, fail */
2028 if (hunknum >= chd->header.totalhunks)
2029 return CHDERR_HUNK_OUT_OF_RANGE;
2031 /* perform the read */
2032 return hunk_read_into_memory(chd, hunknum, (UINT8 *)buffer);
2035 /***************************************************************************
2037 ***************************************************************************/
2039 /*-------------------------------------------------
2040 chd_get_metadata - get the indexed metadata
2042 -------------------------------------------------*/
2044 CHD_EXPORT chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 searchindex, void *output, UINT32 outputlen, UINT32 *resultlen, UINT32 *resulttag, UINT8 *resultflags)
2046 metadata_entry metaentry;
2050 /* if we didn't find it, just return */
2051 err = metadata_find_entry(chd, searchtag, searchindex, &metaentry);
2052 if (err != CHDERR_NONE)
2054 /* unless we're an old version and they are requesting hard disk metadata */
2055 if (chd->header.version < 3 && (searchtag == HARD_DISK_METADATA_TAG || searchtag == CHDMETATAG_WILDCARD) && searchindex == 0)
2057 char faux_metadata[256];
2060 /* fill in the faux metadata */
2061 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);
2062 faux_length = (UINT32)strlen(faux_metadata) + 1;
2064 /* copy the metadata itself */
2065 memcpy(output, faux_metadata, MIN(outputlen, faux_length));
2067 /* return the length of the data and the tag */
2068 if (resultlen != NULL)
2069 *resultlen = faux_length;
2070 if (resulttag != NULL)
2071 *resulttag = HARD_DISK_METADATA_TAG;
2077 /* read the metadata */
2078 outputlen = MIN(outputlen, metaentry.length);
2079 core_fseek(chd->file, metaentry.offset + METADATA_HEADER_SIZE, SEEK_SET);
2080 count = core_fread(chd->file, output, outputlen);
2081 if (count != outputlen)
2082 return CHDERR_READ_ERROR;
2084 /* return the length of the data and the tag */
2085 if (resultlen != NULL)
2086 *resultlen = metaentry.length;
2087 if (resulttag != NULL)
2088 *resulttag = metaentry.metatag;
2089 if (resultflags != NULL)
2090 *resultflags = metaentry.flags;
2094 /***************************************************************************
2096 ***************************************************************************/
2098 /*-------------------------------------------------
2099 chd_codec_config - set internal codec
2101 -------------------------------------------------*/
2103 CHD_EXPORT chd_error chd_codec_config(chd_file *chd, int param, void *config)
2105 return CHDERR_INVALID_PARAMETER;
2108 /*-------------------------------------------------
2109 chd_get_codec_name - get the name of a
2111 -------------------------------------------------*/
2113 CHD_EXPORT const char *chd_get_codec_name(UINT32 codec)
2118 /***************************************************************************
2119 INTERNAL HEADER OPERATIONS
2120 ***************************************************************************/
2122 /*-------------------------------------------------
2123 header_validate - check the validity of a
2125 -------------------------------------------------*/
2127 static chd_error header_validate(const chd_header *header)
2131 /* require a valid version */
2132 if (header->version == 0 || header->version > CHD_HEADER_VERSION)
2133 return CHDERR_UNSUPPORTED_VERSION;
2135 /* require a valid length */
2136 if ((header->version == 1 && header->length != CHD_V1_HEADER_SIZE) ||
2137 (header->version == 2 && header->length != CHD_V2_HEADER_SIZE) ||
2138 (header->version == 3 && header->length != CHD_V3_HEADER_SIZE) ||
2139 (header->version == 4 && header->length != CHD_V4_HEADER_SIZE) ||
2140 (header->version == 5 && header->length != CHD_V5_HEADER_SIZE))
2141 return CHDERR_INVALID_PARAMETER;
2143 /* Do not validate v5 header */
2144 if (header->version <= 4)
2146 /* require valid flags */
2147 if (header->flags & CHDFLAGS_UNDEFINED)
2148 return CHDERR_INVALID_PARAMETER;
2150 /* require a supported compression mechanism */
2151 for (intfnum = 0; intfnum < ARRAY_LENGTH(codec_interfaces); intfnum++)
2152 if (codec_interfaces[intfnum].compression == header->compression[0])
2155 if (intfnum == ARRAY_LENGTH(codec_interfaces))
2156 return CHDERR_INVALID_PARAMETER;
2158 /* require a valid hunksize */
2159 if (header->hunkbytes == 0 || header->hunkbytes >= 65536 * 256)
2160 return CHDERR_INVALID_PARAMETER;
2162 /* require a valid hunk count */
2163 if (header->totalhunks == 0)
2164 return CHDERR_INVALID_PARAMETER;
2166 /* require a valid MD5 and/or SHA1 if we're using a parent */
2167 if ((header->flags & CHDFLAGS_HAS_PARENT) && memcmp(header->parentmd5, nullmd5, sizeof(nullmd5)) == 0 && memcmp(header->parentsha1, nullsha1, sizeof(nullsha1)) == 0)
2168 return CHDERR_INVALID_PARAMETER;
2170 /* if we're V3 or later, the obsolete fields must be 0 */
2171 if (header->version >= 3 &&
2172 (header->obsolete_cylinders != 0 || header->obsolete_sectors != 0 ||
2173 header->obsolete_heads != 0 || header->obsolete_hunksize != 0))
2174 return CHDERR_INVALID_PARAMETER;
2176 /* if we're pre-V3, the obsolete fields must NOT be 0 */
2177 if (header->version < 3 &&
2178 (header->obsolete_cylinders == 0 || header->obsolete_sectors == 0 ||
2179 header->obsolete_heads == 0 || header->obsolete_hunksize == 0))
2180 return CHDERR_INVALID_PARAMETER;
2186 /*-------------------------------------------------
2187 header_guess_unitbytes - for older CHD formats,
2188 guess at the bytes/unit based on metadata
2189 -------------------------------------------------*/
2191 static UINT32 header_guess_unitbytes(chd_file *chd)
2193 /* look for hard disk metadata; if found, then the unit size == sector size */
2196 if (chd_get_metadata(chd, HARD_DISK_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE &&
2197 sscanf(metadata, HARD_DISK_METADATA_FORMAT, &i0, &i1, &i2, &i3) == 4)
2200 /* look for CD-ROM metadata; if found, then the unit size == CD frame size */
2201 if (chd_get_metadata(chd, CDROM_OLD_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
2202 chd_get_metadata(chd, CDROM_TRACK_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
2203 chd_get_metadata(chd, CDROM_TRACK_METADATA2_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
2204 chd_get_metadata(chd, GDROM_OLD_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
2205 chd_get_metadata(chd, GDROM_TRACK_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE)
2206 return CD_FRAME_SIZE;
2208 /* otherwise, just map 1:1 with the hunk size */
2209 return chd->header.hunkbytes;
2212 /*-------------------------------------------------
2213 header_read - read a CHD header into the
2214 internal data structure
2215 -------------------------------------------------*/
2217 static chd_error header_read(chd_file *chd, chd_header *header)
2219 UINT8 rawheader[CHD_MAX_HEADER_SIZE];
2224 return CHDERR_INVALID_PARAMETER;
2226 /* punt if invalid file */
2227 if (chd->file == NULL)
2228 return CHDERR_INVALID_FILE;
2231 core_fseek(chd->file, 0, SEEK_SET);
2232 count = core_fread(chd->file, rawheader, sizeof(rawheader));
2233 if (count != sizeof(rawheader))
2234 return CHDERR_READ_ERROR;
2236 /* verify the tag */
2237 if (strncmp((char *)rawheader, "MComprHD", 8) != 0)
2238 return CHDERR_INVALID_DATA;
2240 /* extract the direct data */
2241 memset(header, 0, sizeof(*header));
2242 header->length = get_bigendian_uint32(&rawheader[8]);
2243 header->version = get_bigendian_uint32(&rawheader[12]);
2245 /* make sure it's a version we understand */
2246 if (header->version == 0 || header->version > CHD_HEADER_VERSION)
2247 return CHDERR_UNSUPPORTED_VERSION;
2249 /* make sure the length is expected */
2250 if ((header->version == 1 && header->length != CHD_V1_HEADER_SIZE) ||
2251 (header->version == 2 && header->length != CHD_V2_HEADER_SIZE) ||
2252 (header->version == 3 && header->length != CHD_V3_HEADER_SIZE) ||
2253 (header->version == 4 && header->length != CHD_V4_HEADER_SIZE) ||
2254 (header->version == 5 && header->length != CHD_V5_HEADER_SIZE))
2256 return CHDERR_INVALID_DATA;
2258 /* extract the common data */
2259 header->flags = get_bigendian_uint32(&rawheader[16]);
2260 header->compression[0] = get_bigendian_uint32(&rawheader[20]);
2261 header->compression[1] = CHD_CODEC_NONE;
2262 header->compression[2] = CHD_CODEC_NONE;
2263 header->compression[3] = CHD_CODEC_NONE;
2265 /* extract the V1/V2-specific data */
2266 if (header->version < 3)
2268 int seclen = (header->version == 1) ? CHD_V1_SECTOR_SIZE : get_bigendian_uint32(&rawheader[76]);
2269 header->obsolete_hunksize = get_bigendian_uint32(&rawheader[24]);
2270 header->totalhunks = get_bigendian_uint32(&rawheader[28]);
2271 header->obsolete_cylinders = get_bigendian_uint32(&rawheader[32]);
2272 header->obsolete_heads = get_bigendian_uint32(&rawheader[36]);
2273 header->obsolete_sectors = get_bigendian_uint32(&rawheader[40]);
2274 memcpy(header->md5, &rawheader[44], CHD_MD5_BYTES);
2275 memcpy(header->parentmd5, &rawheader[60], CHD_MD5_BYTES);
2276 header->logicalbytes = (UINT64)header->obsolete_cylinders * (UINT64)header->obsolete_heads * (UINT64)header->obsolete_sectors * (UINT64)seclen;
2277 header->hunkbytes = seclen * header->obsolete_hunksize;
2278 header->unitbytes = header_guess_unitbytes(chd);
2279 if (header->unitbytes == 0)
2280 return CHDERR_INVALID_DATA;
2281 header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
2282 header->metaoffset = 0;
2285 /* extract the V3-specific data */
2286 else if (header->version == 3)
2288 header->totalhunks = get_bigendian_uint32(&rawheader[24]);
2289 header->logicalbytes = get_bigendian_uint64(&rawheader[28]);
2290 header->metaoffset = get_bigendian_uint64(&rawheader[36]);
2291 memcpy(header->md5, &rawheader[44], CHD_MD5_BYTES);
2292 memcpy(header->parentmd5, &rawheader[60], CHD_MD5_BYTES);
2293 header->hunkbytes = get_bigendian_uint32(&rawheader[76]);
2294 header->unitbytes = header_guess_unitbytes(chd);
2295 if (header->unitbytes == 0)
2296 return CHDERR_INVALID_DATA;
2297 header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
2298 memcpy(header->sha1, &rawheader[80], CHD_SHA1_BYTES);
2299 memcpy(header->parentsha1, &rawheader[100], CHD_SHA1_BYTES);
2302 /* extract the V4-specific data */
2303 else if (header->version == 4)
2305 header->totalhunks = get_bigendian_uint32(&rawheader[24]);
2306 header->logicalbytes = get_bigendian_uint64(&rawheader[28]);
2307 header->metaoffset = get_bigendian_uint64(&rawheader[36]);
2308 header->hunkbytes = get_bigendian_uint32(&rawheader[44]);
2309 header->unitbytes = header_guess_unitbytes(chd);
2310 if (header->unitbytes == 0)
2311 return CHDERR_INVALID_DATA;
2312 header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
2313 memcpy(header->sha1, &rawheader[48], CHD_SHA1_BYTES);
2314 memcpy(header->parentsha1, &rawheader[68], CHD_SHA1_BYTES);
2315 memcpy(header->rawsha1, &rawheader[88], CHD_SHA1_BYTES);
2318 /* extract the V5-specific data */
2319 else if (header->version == 5)
2322 header->compression[0] = get_bigendian_uint32(&rawheader[16]);
2323 header->compression[1] = get_bigendian_uint32(&rawheader[20]);
2324 header->compression[2] = get_bigendian_uint32(&rawheader[24]);
2325 header->compression[3] = get_bigendian_uint32(&rawheader[28]);
2326 header->logicalbytes = get_bigendian_uint64(&rawheader[32]);
2327 header->mapoffset = get_bigendian_uint64(&rawheader[40]);
2328 header->metaoffset = get_bigendian_uint64(&rawheader[48]);
2329 header->hunkbytes = get_bigendian_uint32(&rawheader[56]);
2330 if (header->hunkbytes == 0)
2331 return CHDERR_INVALID_DATA;
2332 header->hunkcount = (header->logicalbytes + header->hunkbytes - 1) / header->hunkbytes;
2333 header->unitbytes = get_bigendian_uint32(&rawheader[60]);
2334 if (header->unitbytes == 0)
2335 return CHDERR_INVALID_DATA;
2336 header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
2337 memcpy(header->sha1, &rawheader[84], CHD_SHA1_BYTES);
2338 memcpy(header->parentsha1, &rawheader[104], CHD_SHA1_BYTES);
2339 memcpy(header->rawsha1, &rawheader[64], CHD_SHA1_BYTES);
2341 /* determine properties of map entries */
2342 header->mapentrybytes = chd_compressed(header) ? 12 : 4;
2345 header->totalhunks = header->hunkcount;
2348 /* Unknown version */
2354 /* guess it worked */
2358 /***************************************************************************
2359 INTERNAL HUNK READ/WRITE
2360 ***************************************************************************/
2362 /*-------------------------------------------------
2363 hunk_read_compressed - read a compressed
2365 -------------------------------------------------*/
2367 static UINT8* hunk_read_compressed(chd_file *chd, UINT64 offset, size_t size)
2374 if (chd->file_cache != NULL)
2376 return chd->file_cache + offset;
2380 core_fseek(chd->file, offset, SEEK_SET);
2381 bytes = core_fread(chd->file, chd->compressed, size);
2384 return chd->compressed;
2388 /*-------------------------------------------------
2389 hunk_read_uncompressed - read an uncompressed
2391 -------------------------------------------------*/
2393 static chd_error hunk_read_uncompressed(chd_file *chd, UINT64 offset, size_t size, UINT8 *dest)
2400 if (chd->file_cache != NULL)
2402 memcpy(dest, chd->file_cache + offset, size);
2406 core_fseek(chd->file, offset, SEEK_SET);
2407 bytes = core_fread(chd->file, dest, size);
2409 return CHDERR_READ_ERROR;
2414 #ifdef NEED_CACHE_HUNK
2415 /*-------------------------------------------------
2416 hunk_read_into_cache - read a hunk into
2417 the CHD's hunk cache
2418 -------------------------------------------------*/
2420 static chd_error hunk_read_into_cache(chd_file *chd, UINT32 hunknum)
2425 if (hunknum > chd->maxhunk)
2426 chd->maxhunk = hunknum;
2428 /* if we're already in the cache, we're done */
2429 if (chd->cachehunk == hunknum)
2431 chd->cachehunk = ~0;
2433 /* otherwise, read the data */
2434 err = hunk_read_into_memory(chd, hunknum, chd->cache);
2435 if (err != CHDERR_NONE)
2438 /* mark the hunk successfully cached in */
2439 chd->cachehunk = hunknum;
2444 /*-------------------------------------------------
2445 hunk_read_into_memory - read a hunk into
2446 memory at the given location
2447 -------------------------------------------------*/
2449 static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *dest)
2453 /* punt if no file */
2454 if (chd->file == NULL)
2455 return CHDERR_INVALID_FILE;
2457 /* return an error if out of range */
2458 if (hunknum >= chd->header.totalhunks)
2459 return CHDERR_HUNK_OUT_OF_RANGE;
2462 return CHDERR_INVALID_PARAMETER;
2464 if (chd->header.version < 5)
2466 map_entry *entry = &chd->map[hunknum];
2468 UINT8* compressed_bytes;
2470 /* switch off the entry type */
2471 switch (entry->flags & MAP_ENTRY_FLAG_TYPE_MASK)
2473 /* compressed data */
2474 case V34_MAP_ENTRY_TYPE_COMPRESSED:
2478 /* read it into the decompression buffer */
2479 compressed_bytes = hunk_read_compressed(chd, entry->offset, entry->length);
2480 if (compressed_bytes == NULL)
2481 return CHDERR_READ_ERROR;
2483 /* now decompress using the codec */
2485 codec = &chd->zlib_codec_data;
2486 if (chd->codecintf[0]->decompress != NULL)
2487 err = (*chd->codecintf[0]->decompress)(codec, compressed_bytes, entry->length, dest, chd->header.hunkbytes);
2488 if (err != CHDERR_NONE)
2493 /* uncompressed data */
2494 case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
2495 err = hunk_read_uncompressed(chd, entry->offset, chd->header.hunkbytes, dest);
2496 if (err != CHDERR_NONE)
2500 /* mini-compressed data */
2501 case V34_MAP_ENTRY_TYPE_MINI:
2502 put_bigendian_uint64(&dest[0], entry->offset);
2503 for (bytes = 8; bytes < chd->header.hunkbytes; bytes++)
2504 dest[bytes] = dest[bytes - 8];
2507 /* self-referenced data */
2508 case V34_MAP_ENTRY_TYPE_SELF_HUNK:
2509 #ifdef NEED_CACHE_HUNK
2510 if (chd->cachehunk == entry->offset && dest == chd->cache)
2513 return hunk_read_into_memory(chd, entry->offset, dest);
2515 /* parent-referenced data */
2516 case V34_MAP_ENTRY_TYPE_PARENT_HUNK:
2517 err = hunk_read_into_memory(chd->parent, entry->offset, dest);
2518 if (err != CHDERR_NONE)
2527 /* get a pointer to the map entry */
2530 #ifdef VERIFY_BLOCK_CRC
2533 uint8_t *rawmap = &chd->header.rawmap[chd->header.mapentrybytes * hunknum];
2534 UINT8* compressed_bytes;
2536 /* uncompressed case */
2537 if (!chd_compressed(&chd->header))
2539 blockoffs = (uint64_t)get_bigendian_uint32(rawmap) * (uint64_t)chd->header.hunkbytes;
2540 if (blockoffs != 0) {
2541 core_fseek(chd->file, blockoffs, SEEK_SET);
2542 int result = core_fread(chd->file, dest, chd->header.hunkbytes);
2544 else if (m_parent_missing)
2545 throw CHDERR_REQUIRES_PARENT; */
2546 } else if (chd->parent) {
2547 err = hunk_read_into_memory(chd->parent, hunknum, dest);
2548 if (err != CHDERR_NONE)
2551 memset(dest, 0, chd->header.hunkbytes);
2557 /* compressed case */
2558 blocklen = get_bigendian_uint24(&rawmap[1]);
2559 blockoffs = get_bigendian_uint48(&rawmap[4]);
2560 #ifdef VERIFY_BLOCK_CRC
2561 blockcrc = get_bigendian_uint16(&rawmap[10]);
2566 case COMPRESSION_TYPE_0:
2567 case COMPRESSION_TYPE_1:
2568 case COMPRESSION_TYPE_2:
2569 case COMPRESSION_TYPE_3:
2570 compressed_bytes = hunk_read_compressed(chd, blockoffs, blocklen);
2571 if (compressed_bytes == NULL)
2572 return CHDERR_READ_ERROR;
2573 switch (chd->codecintf[rawmap[0]]->compression)
2575 case CHD_CODEC_ZLIB:
2576 codec = &chd->zlib_codec_data;
2579 case CHD_CODEC_LZMA:
2580 codec = &chd->lzma_codec_data;
2583 case CHD_CODEC_HUFFMAN:
2584 codec = &chd->huff_codec_data;
2587 case CHD_CODEC_FLAC:
2588 codec = &chd->flac_codec_data;
2591 case CHD_CODEC_CD_ZLIB:
2592 codec = &chd->cdzl_codec_data;
2595 case CHD_CODEC_CD_LZMA:
2596 codec = &chd->cdlz_codec_data;
2599 case CHD_CODEC_CD_FLAC:
2600 codec = &chd->cdfl_codec_data;
2604 return CHDERR_CODEC_ERROR;
2605 err = chd->codecintf[rawmap[0]]->decompress(codec, compressed_bytes, blocklen, dest, chd->header.hunkbytes);
2606 if (err != CHDERR_NONE)
2608 #ifdef VERIFY_BLOCK_CRC
2609 if (crc16(dest, chd->header.hunkbytes) != blockcrc)
2610 return CHDERR_DECOMPRESSION_ERROR;
2614 case COMPRESSION_NONE:
2615 err = hunk_read_uncompressed(chd, blockoffs, blocklen, dest);
2616 if (err != CHDERR_NONE)
2618 #ifdef VERIFY_BLOCK_CRC
2619 if (crc16(dest, chd->header.hunkbytes) != blockcrc)
2620 return CHDERR_DECOMPRESSION_ERROR;
2624 case COMPRESSION_SELF:
2625 return hunk_read_into_memory(chd, blockoffs, dest);
2627 case COMPRESSION_PARENT:
2628 if (chd->parent == NULL)
2629 return CHDERR_REQUIRES_PARENT;
2630 UINT8 units_in_hunk = chd->header.hunkbytes / chd->header.unitbytes;
2632 /* blockoffs is aligned to units_in_hunk */
2633 if (blockoffs % units_in_hunk == 0) {
2634 return hunk_read_into_memory(chd->parent, blockoffs / units_in_hunk, dest);
2635 /* blockoffs is not aligned to units_in_hunk */
2637 UINT32 unit_in_hunk = blockoffs % units_in_hunk;
2638 UINT8 *buf = malloc(chd->header.hunkbytes);
2639 /* Read first half of hunk which contains blockoffs */
2640 err = hunk_read_into_memory(chd->parent, blockoffs / units_in_hunk, buf);
2641 if (err != CHDERR_NONE) {
2645 memcpy(dest, buf + unit_in_hunk * chd->header.unitbytes, (units_in_hunk - unit_in_hunk) * chd->header.unitbytes);
2646 /* Read second half of hunk which contains blockoffs */
2647 err = hunk_read_into_memory(chd->parent, (blockoffs / units_in_hunk) + 1, buf);
2648 if (err != CHDERR_NONE) {
2652 memcpy(dest + (units_in_hunk - unit_in_hunk) * chd->header.unitbytes, buf, unit_in_hunk * chd->header.unitbytes);
2659 /* We should not reach this code */
2660 return CHDERR_DECOMPRESSION_ERROR;
2663 /***************************************************************************
2665 ***************************************************************************/
2667 /*-------------------------------------------------
2668 map_read - read the initial sector map
2669 -------------------------------------------------*/
2671 static chd_error map_read(chd_file *chd)
2673 UINT32 entrysize = (chd->header.version < 3) ? OLD_MAP_ENTRY_SIZE : MAP_ENTRY_SIZE;
2674 UINT8 raw_map_entries[MAP_STACK_ENTRIES * MAP_ENTRY_SIZE];
2675 UINT64 fileoffset, maxoffset = 0;
2676 UINT8 cookie[MAP_ENTRY_SIZE];
2681 /* first allocate memory */
2682 chd->map = (map_entry *)malloc(sizeof(chd->map[0]) * chd->header.totalhunks);
2684 return CHDERR_OUT_OF_MEMORY;
2686 /* read the map entries in in chunks and extract to the map list */
2687 fileoffset = chd->header.length;
2688 for (i = 0; i < chd->header.totalhunks; i += MAP_STACK_ENTRIES)
2690 /* compute how many entries this time */
2691 int entries = chd->header.totalhunks - i, j;
2692 if (entries > MAP_STACK_ENTRIES)
2693 entries = MAP_STACK_ENTRIES;
2695 /* read that many */
2696 core_fseek(chd->file, fileoffset, SEEK_SET);
2697 count = core_fread(chd->file, raw_map_entries, entries * entrysize);
2698 if (count != entries * entrysize)
2700 err = CHDERR_READ_ERROR;
2703 fileoffset += entries * entrysize;
2705 /* process that many */
2706 if (entrysize == MAP_ENTRY_SIZE)
2708 for (j = 0; j < entries; j++)
2709 map_extract(&raw_map_entries[j * MAP_ENTRY_SIZE], &chd->map[i + j]);
2713 for (j = 0; j < entries; j++)
2714 map_extract_old(&raw_map_entries[j * OLD_MAP_ENTRY_SIZE], &chd->map[i + j], chd->header.hunkbytes);
2717 /* track the maximum offset */
2718 for (j = 0; j < entries; j++)
2719 if ((chd->map[i + j].flags & MAP_ENTRY_FLAG_TYPE_MASK) == V34_MAP_ENTRY_TYPE_COMPRESSED ||
2720 (chd->map[i + j].flags & MAP_ENTRY_FLAG_TYPE_MASK) == V34_MAP_ENTRY_TYPE_UNCOMPRESSED)
2721 maxoffset = MAX(maxoffset, chd->map[i + j].offset + chd->map[i + j].length);
2724 /* verify the cookie */
2725 core_fseek(chd->file, fileoffset, SEEK_SET);
2726 count = core_fread(chd->file, &cookie, entrysize);
2727 if (count != entrysize || memcmp(&cookie, END_OF_LIST_COOKIE, entrysize))
2729 err = CHDERR_INVALID_FILE;
2733 /* verify the length */
2734 if (maxoffset > core_fsize(chd->file))
2736 err = CHDERR_INVALID_FILE;
2748 /***************************************************************************
2749 INTERNAL METADATA ACCESS
2750 ***************************************************************************/
2752 /*-------------------------------------------------
2753 metadata_find_entry - find a metadata entry
2754 -------------------------------------------------*/
2756 static chd_error metadata_find_entry(chd_file *chd, UINT32 metatag, UINT32 metaindex, metadata_entry *metaentry)
2758 /* start at the beginning */
2759 metaentry->offset = chd->header.metaoffset;
2760 metaentry->prev = 0;
2762 /* loop until we run out of options */
2763 while (metaentry->offset != 0)
2765 UINT8 raw_meta_header[METADATA_HEADER_SIZE];
2768 /* read the raw header */
2769 core_fseek(chd->file, metaentry->offset, SEEK_SET);
2770 count = core_fread(chd->file, raw_meta_header, sizeof(raw_meta_header));
2771 if (count != sizeof(raw_meta_header))
2774 /* extract the data */
2775 metaentry->metatag = get_bigendian_uint32(&raw_meta_header[0]);
2776 metaentry->length = get_bigendian_uint32(&raw_meta_header[4]);
2777 metaentry->next = get_bigendian_uint64(&raw_meta_header[8]);
2779 /* flags are encoded in the high byte of length */
2780 metaentry->flags = metaentry->length >> 24;
2781 metaentry->length &= 0x00ffffff;
2783 /* if we got a match, proceed */
2784 if (metatag == CHDMETATAG_WILDCARD || metaentry->metatag == metatag)
2785 if (metaindex-- == 0)
2788 /* no match, fetch the next link */
2789 metaentry->prev = metaentry->offset;
2790 metaentry->offset = metaentry->next;
2793 /* if we get here, we didn't find it */
2794 return CHDERR_METADATA_NOT_FOUND;
2797 /***************************************************************************
2798 ZLIB COMPRESSION CODEC
2799 ***************************************************************************/
2801 /*-------------------------------------------------
2802 zlib_codec_init - initialize the ZLIB codec
2803 -------------------------------------------------*/
2805 static chd_error zlib_codec_init(void *codec, uint32_t hunkbytes)
2809 zlib_codec_data *data = (zlib_codec_data*)codec;
2811 /* clear the buffers */
2812 memset(data, 0, sizeof(zlib_codec_data));
2814 /* init the inflater first */
2815 data->inflater.next_in = (Bytef *)data; /* bogus, but that's ok */
2816 data->inflater.avail_in = 0;
2817 data->inflater.zalloc = zlib_fast_alloc;
2818 data->inflater.zfree = zlib_fast_free;
2819 data->inflater.opaque = &data->allocator;
2820 zerr = inflateInit2(&data->inflater, -MAX_WBITS);
2822 /* convert errors */
2823 if (zerr == Z_MEM_ERROR)
2824 err = CHDERR_OUT_OF_MEMORY;
2825 else if (zerr != Z_OK)
2826 err = CHDERR_CODEC_ERROR;
2833 /*-------------------------------------------------
2834 zlib_codec_free - free data for the ZLIB
2836 -------------------------------------------------*/
2838 static void zlib_codec_free(void *codec)
2840 zlib_codec_data *data = (zlib_codec_data *)codec;
2842 /* deinit the streams */
2845 inflateEnd(&data->inflater);
2847 /* free our fast memory */
2848 zlib_allocator_free(&data->allocator);
2852 /*-------------------------------------------------
2853 zlib_codec_decompress - decompress data using
2855 -------------------------------------------------*/
2857 static chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
2859 zlib_codec_data *data = (zlib_codec_data *)codec;
2862 /* reset the decompressor */
2863 data->inflater.next_in = (Bytef *)src;
2864 data->inflater.avail_in = complen;
2865 data->inflater.total_in = 0;
2866 data->inflater.next_out = (Bytef *)dest;
2867 data->inflater.avail_out = destlen;
2868 data->inflater.total_out = 0;
2869 zerr = inflateReset(&data->inflater);
2871 return CHDERR_DECOMPRESSION_ERROR;
2874 zerr = inflate(&data->inflater, Z_FINISH);
2875 if (data->inflater.total_out != destlen)
2876 return CHDERR_DECOMPRESSION_ERROR;
2881 /*-------------------------------------------------
2882 zlib_fast_alloc - fast malloc for ZLIB, which
2883 allocates and frees memory frequently
2884 -------------------------------------------------*/
2886 /* Huge alignment values for possible SIMD optimization by compiler (NEON, SSE, AVX) */
2887 #define ZLIB_MIN_ALIGNMENT_BITS 512
2888 #define ZLIB_MIN_ALIGNMENT_BYTES (ZLIB_MIN_ALIGNMENT_BITS / 8)
2890 static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
2892 zlib_allocator *alloc = (zlib_allocator *)opaque;
2893 uintptr_t paddr = 0;
2897 /* compute the size, rounding to the nearest 1k */
2898 size = (size * items + 0x3ff) & ~0x3ff;
2900 /* reuse a hunk if we can */
2901 for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
2903 ptr = alloc->allocptr[i];
2904 if (ptr && size == *ptr)
2906 /* set the low bit of the size so we don't match next time */
2909 /* return aligned block address */
2910 return (voidpf)(alloc->allocptr2[i]);
2914 /* alloc a new one */
2915 ptr = (UINT32 *)malloc(size + sizeof(UINT32) + ZLIB_MIN_ALIGNMENT_BYTES);
2919 /* put it into the list */
2920 for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
2921 if (!alloc->allocptr[i])
2923 alloc->allocptr[i] = ptr;
2924 paddr = (((uintptr_t)ptr) + sizeof(UINT32) + (ZLIB_MIN_ALIGNMENT_BYTES-1)) & (~(ZLIB_MIN_ALIGNMENT_BYTES-1));
2925 alloc->allocptr2[i] = (uint32_t*)paddr;
2929 /* set the low bit of the size so we don't match next time */
2932 /* return aligned block address */
2933 return (voidpf)paddr;
2936 /*-------------------------------------------------
2937 zlib_fast_free - fast free for ZLIB, which
2938 allocates and frees memory frequently
2939 -------------------------------------------------*/
2941 static void zlib_fast_free(voidpf opaque, voidpf address)
2943 zlib_allocator *alloc = (zlib_allocator *)opaque;
2944 UINT32 *ptr = (UINT32 *)address;
2948 for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
2949 if (ptr == alloc->allocptr2[i])
2951 /* clear the low bit of the size to allow matches */
2952 *(alloc->allocptr[i]) &= ~1;
2957 /*-------------------------------------------------
2959 -------------------------------------------------*/
2960 static void zlib_allocator_free(voidpf opaque)
2962 zlib_allocator *alloc = (zlib_allocator *)opaque;
2965 for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
2966 if (alloc->allocptr[i])
2967 free(alloc->allocptr[i]);
2970 /*-------------------------------------------------
2971 core_stdio_fopen - core_file wrapper over fopen
2972 -------------------------------------------------*/
2973 static core_file *core_stdio_fopen(char const *path) {
2974 core_file *file = malloc(sizeof(core_file));
2977 if (!(file->argp = fopen(path, "rb"))) {
2981 file->fsize = core_stdio_fsize;
2982 file->fread = core_stdio_fread;
2983 file->fclose = core_stdio_fclose;
2984 file->fseek = core_stdio_fseek;
2988 /*-------------------------------------------------
2989 core_stdio_fsize - core_file function for
2990 getting file size with stdio
2991 -------------------------------------------------*/
2992 static UINT64 core_stdio_fsize(core_file *file) {
2993 #if defined USE_LIBRETRO_VFS
2994 #define core_stdio_fseek_impl fseek
2995 #define core_stdio_ftell_impl ftell
2996 #elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WIN64__)
2997 #define core_stdio_fseek_impl _fseeki64
2998 #define core_stdio_ftell_impl _ftelli64
2999 #elif defined(_LARGEFILE_SOURCE) && defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
3000 #define core_stdio_fseek_impl fseeko64
3001 #define core_stdio_ftell_impl ftello64
3002 #elif defined(__PS3__) && !defined(__PSL1GHT__) || defined(__SWITCH__) || defined(__vita__)
3003 #define core_stdio_fseek_impl(x,y,z) fseek(x,(off_t)y,z)
3004 #define core_stdio_ftell_impl(x) (off_t)ftell(x)
3006 #define core_stdio_fseek_impl fseeko
3007 #define core_stdio_ftell_impl ftello
3011 fp = (FILE*)file->argp;
3013 p = core_stdio_ftell_impl(fp);
3014 core_stdio_fseek_impl(fp, 0, SEEK_END);
3015 rv = core_stdio_ftell_impl(fp);
3016 core_stdio_fseek_impl(fp, p, SEEK_SET);
3020 /*-------------------------------------------------
3021 core_stdio_fread - core_file wrapper over fread
3022 -------------------------------------------------*/
3023 static size_t core_stdio_fread(void *ptr, size_t size, size_t nmemb, core_file *file) {
3024 return fread(ptr, size, nmemb, (FILE*)file->argp);
3027 /*-------------------------------------------------
3028 core_stdio_fclose - core_file wrapper over fclose
3029 -------------------------------------------------*/
3030 static int core_stdio_fclose(core_file *file) {
3031 int err = fclose((FILE*)file->argp);
3037 /*-------------------------------------------------
3038 core_stdio_fclose_nonowner - don't call fclose because
3039 we don't own the underlying file, but do free the
3040 core_file because libchdr did allocate that itself.
3041 -------------------------------------------------*/
3042 static int core_stdio_fclose_nonowner(core_file *file) {
3047 /*-------------------------------------------------
3048 core_stdio_fseek - core_file wrapper over fclose
3049 -------------------------------------------------*/
3050 static int core_stdio_fseek(core_file* file, INT64 offset, int whence) {
3051 return core_stdio_fseek_impl((FILE*)file->argp, offset, whence);