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>
54 #if defined(__PS3__) || defined(__PSL1GHT__)
66 #define MAX(x, y) (((x) > (y)) ? (x) : (y))
67 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
69 #define SHA1_DIGEST_SIZE 20
71 /***************************************************************************
73 ***************************************************************************/
75 #define PRINTF_MAX_HUNK (0)
77 /***************************************************************************
79 ***************************************************************************/
81 #define MAP_STACK_ENTRIES 512 /* max number of entries to use on the stack */
82 #define MAP_ENTRY_SIZE 16 /* V3 and later */
83 #define OLD_MAP_ENTRY_SIZE 8 /* V1-V2 */
84 #define METADATA_HEADER_SIZE 16 /* metadata header size */
86 #define MAP_ENTRY_FLAG_TYPE_MASK 0x0f /* what type of hunk */
87 #define MAP_ENTRY_FLAG_NO_CRC 0x10 /* no CRC is present */
89 #define CHD_V1_SECTOR_SIZE 512 /* size of a "sector" in the V1 header */
91 #define COOKIE_VALUE 0xbaadf00d
92 #define MAX_ZLIB_ALLOCS 64
94 #define END_OF_LIST_COOKIE "EndOfListCookie"
98 #ifdef WANT_RAW_DATA_SECTOR
99 static const uint8_t s_cd_sync_header[12] = { 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 };
102 /* V3-V4 entry types */
105 V34_MAP_ENTRY_TYPE_INVALID = 0, /* invalid type */
106 V34_MAP_ENTRY_TYPE_COMPRESSED = 1, /* standard compression */
107 V34_MAP_ENTRY_TYPE_UNCOMPRESSED = 2, /* uncompressed data */
108 V34_MAP_ENTRY_TYPE_MINI = 3, /* mini: use offset as raw data */
109 V34_MAP_ENTRY_TYPE_SELF_HUNK = 4, /* same as another hunk in this file */
110 V34_MAP_ENTRY_TYPE_PARENT_HUNK = 5, /* same as a hunk in the parent file */
111 V34_MAP_ENTRY_TYPE_2ND_COMPRESSED = 6 /* compressed with secondary algorithm (usually FLAC CDDA) */
114 /* V5 compression types */
118 * these types are live when running */
119 COMPRESSION_TYPE_0 = 0,
121 COMPRESSION_TYPE_1 = 1,
123 COMPRESSION_TYPE_2 = 2,
125 COMPRESSION_TYPE_3 = 3,
126 /* no compression; implicit length = hunkbytes */
127 COMPRESSION_NONE = 4,
128 /* same as another block in this chd */
129 COMPRESSION_SELF = 5,
130 /* same as a hunk's worth of units in the parent chd */
131 COMPRESSION_PARENT = 6,
133 /* start of small RLE run (4-bit length)
134 * these additional pseudo-types are used for compressed encodings: */
135 COMPRESSION_RLE_SMALL,
136 /* start of large RLE run (8-bit length) */
137 COMPRESSION_RLE_LARGE,
138 /* same as the last COMPRESSION_SELF block */
140 /* same as the last COMPRESSION_SELF block + 1 */
142 /* same block in the parent */
143 COMPRESSION_PARENT_SELF,
144 /* same as the last COMPRESSION_PARENT block */
145 COMPRESSION_PARENT_0,
146 /* same as the last COMPRESSION_PARENT block + 1 */
150 /***************************************************************************
152 ***************************************************************************/
154 #define EARLY_EXIT(x) do { (void)(x); goto cleanup; } while (0)
156 /***************************************************************************
158 ***************************************************************************/
160 /* interface to a codec */
161 typedef struct _codec_interface codec_interface;
162 struct _codec_interface
164 UINT32 compression; /* type of compression */
165 const char *compname; /* name of the algorithm */
166 UINT8 lossy; /* is this a lossy algorithm? */
167 chd_error (*init)(void *codec, UINT32 hunkbytes); /* codec initialize */
168 void (*free)(void *codec); /* codec free */
169 chd_error (*decompress)(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); /* decompress data */
170 chd_error (*config)(void *codec, int param, void *config); /* configure */
173 /* a single map entry */
174 typedef struct _map_entry map_entry;
177 UINT64 offset; /* offset within the file of the data */
178 UINT32 crc; /* 32-bit CRC of the data */
179 UINT32 length; /* length of the data */
180 UINT8 flags; /* misc flags */
183 /* a single metadata entry */
184 typedef struct _metadata_entry metadata_entry;
185 struct _metadata_entry
187 UINT64 offset; /* offset within the file of the header */
188 UINT64 next; /* offset within the file of the next header */
189 UINT64 prev; /* offset within the file of the previous header */
190 UINT32 length; /* length of the metadata */
191 UINT32 metatag; /* metadata tag */
192 UINT8 flags; /* flag bits */
195 /* codec-private data for the ZLIB codec */
197 typedef struct _zlib_allocator zlib_allocator;
198 struct _zlib_allocator
200 UINT32 * allocptr[MAX_ZLIB_ALLOCS];
201 UINT32 * allocptr2[MAX_ZLIB_ALLOCS];
204 typedef struct _zlib_codec_data zlib_codec_data;
205 struct _zlib_codec_data
208 zlib_allocator allocator;
211 /* codec-private data for the LZMA codec */
212 #define MAX_LZMA_ALLOCS 64
214 typedef struct _lzma_allocator lzma_allocator;
215 struct _lzma_allocator
217 void *(*Alloc)(void *p, size_t size);
218 void (*Free)(void *p, void *address); /* address can be 0 */
219 void (*FreeSz)(void *p, void *address, size_t size); /* address can be 0 */
220 uint32_t* allocptr[MAX_LZMA_ALLOCS];
221 uint32_t* allocptr2[MAX_LZMA_ALLOCS];
224 typedef struct _lzma_codec_data lzma_codec_data;
225 struct _lzma_codec_data
228 lzma_allocator allocator;
231 typedef struct _huff_codec_data huff_codec_data;
232 struct _huff_codec_data
234 struct huffman_decoder* decoder;
237 typedef struct _zstd_codec_data zstd_codec_data;
238 struct _zstd_codec_data
240 ZSTD_DStream *dstream;
243 /* codec-private data for the CDZL codec */
244 typedef struct _cdzl_codec_data cdzl_codec_data;
245 struct _cdzl_codec_data {
247 zlib_codec_data base_decompressor;
249 zlib_codec_data subcode_decompressor;
254 /* codec-private data for the CDLZ codec */
255 typedef struct _cdlz_codec_data cdlz_codec_data;
256 struct _cdlz_codec_data {
258 lzma_codec_data base_decompressor;
260 zlib_codec_data subcode_decompressor;
265 /* codec-private data for the FLAC codec */
266 typedef struct _flac_codec_data flac_codec_data;
267 struct _flac_codec_data {
270 flac_decoder decoder;
273 /* codec-private data for the CDFL codec */
274 typedef struct _cdfl_codec_data cdfl_codec_data;
275 struct _cdfl_codec_data {
278 flac_decoder decoder;
280 zlib_codec_data subcode_decompressor;
285 typedef struct _cdzs_codec_data cdzs_codec_data;
286 struct _cdzs_codec_data
288 zstd_codec_data base_decompressor;
290 zstd_codec_data subcode_decompressor;
295 /* internal representation of an open CHD file */
298 UINT32 cookie; /* cookie, should equal COOKIE_VALUE */
300 core_file * file; /* handle to the open core file */
301 chd_header header; /* header, extracted from file */
303 chd_file * parent; /* pointer to parent file, or NULL */
305 map_entry * map; /* array of map entries */
307 #ifdef NEED_CACHE_HUNK
308 UINT8 * cache; /* hunk cache pointer */
309 UINT32 cachehunk; /* index of currently cached hunk */
311 UINT8 * compare; /* hunk compare pointer */
312 UINT32 comparehunk; /* index of current compare data */
315 UINT8 * compressed; /* pointer to buffer for compressed data */
316 const codec_interface * codecintf[4]; /* interface to the codec */
318 zlib_codec_data zlib_codec_data; /* zlib codec data */
319 lzma_codec_data lzma_codec_data; /* lzma codec data */
320 huff_codec_data huff_codec_data; /* huff codec data */
321 flac_codec_data flac_codec_data; /* flac codec data */
322 zstd_codec_data zstd_codec_data; /* zstd codec data */
323 cdzl_codec_data cdzl_codec_data; /* cdzl codec data */
324 cdlz_codec_data cdlz_codec_data; /* cdlz codec data */
325 cdfl_codec_data cdfl_codec_data; /* cdfl codec data */
326 cdzs_codec_data cdzs_codec_data; /* cdzs codec data */
328 #ifdef NEED_CACHE_HUNK
329 UINT32 maxhunk; /* maximum hunk accessed */
332 UINT8 * file_cache; /* cache of underlying file */
336 /***************************************************************************
338 ***************************************************************************/
340 static const UINT8 nullmd5[CHD_MD5_BYTES] = { 0 };
341 static const UINT8 nullsha1[CHD_SHA1_BYTES] = { 0 };
343 /***************************************************************************
345 ***************************************************************************/
347 /* core_file wrappers over stdio */
348 static core_file *core_stdio_fopen(char const *path);
349 static UINT64 core_stdio_fsize(core_file *file);
350 static size_t core_stdio_fread(void *ptr, size_t size, size_t nmemb, core_file *file);
351 static int core_stdio_fclose(core_file *file);
352 static int core_stdio_fclose_nonowner(core_file *file); // alternate fclose used by chd_open_file
353 static int core_stdio_fseek(core_file* file, INT64 offset, int whence);
355 /* internal header operations */
356 static chd_error header_validate(const chd_header *header);
357 static chd_error header_read(chd_file *chd, chd_header *header);
359 /* internal hunk read/write */
360 #ifdef NEED_CACHE_HUNK
361 static chd_error hunk_read_into_cache(chd_file *chd, UINT32 hunknum);
363 static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *dest);
365 /* internal map access */
366 static chd_error map_read(chd_file *chd);
368 /* metadata management */
369 static chd_error metadata_find_entry(chd_file *chd, UINT32 metatag, UINT32 metaindex, metadata_entry *metaentry);
371 /* zlib compression codec */
372 static chd_error zlib_codec_init(void *codec, uint32_t hunkbytes);
373 static void zlib_codec_free(void *codec);
374 static chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
375 static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size);
376 static void zlib_fast_free(voidpf opaque, voidpf address);
377 static void zlib_allocator_free(voidpf opaque);
379 /* lzma compression codec */
380 static chd_error lzma_codec_init(void *codec, uint32_t hunkbytes);
381 static void lzma_codec_free(void *codec);
382 static chd_error lzma_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
384 /* huff compression codec */
385 static chd_error huff_codec_init(void *codec, uint32_t hunkbytes);
386 static void huff_codec_free(void *codec);
387 static chd_error huff_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
389 /* flac compression codec */
390 static chd_error flac_codec_init(void *codec, uint32_t hunkbytes);
391 static void flac_codec_free(void *codec);
392 static chd_error flac_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
394 /* zstd compression codec */
395 static chd_error zstd_codec_init(void *codec, uint32_t hunkbytes);
396 static void zstd_codec_free(void *codec);
397 static chd_error zstd_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
400 /* cdzl compression codec */
401 static chd_error cdzl_codec_init(void* codec, uint32_t hunkbytes);
402 static void cdzl_codec_free(void* codec);
403 static chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
405 /* cdlz compression codec */
406 static chd_error cdlz_codec_init(void* codec, uint32_t hunkbytes);
407 static void cdlz_codec_free(void* codec);
408 static chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
410 /* cdfl compression codec */
411 static chd_error cdfl_codec_init(void* codec, uint32_t hunkbytes);
412 static void cdfl_codec_free(void* codec);
413 static chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
415 /* cdzs compression codec */
416 static chd_error cdzs_codec_init(void *codec, uint32_t hunkbytes);
417 static void cdzs_codec_free(void *codec);
418 static chd_error cdzs_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
420 /***************************************************************************
421 * LZMA ALLOCATOR HELPER
422 ***************************************************************************
425 static void *lzma_fast_alloc(void *p, size_t size);
426 static void lzma_fast_free(void *p, void *address);
428 /*-------------------------------------------------
429 * lzma_allocator_init
430 *-------------------------------------------------
433 static void lzma_allocator_init(void* p)
435 lzma_allocator *codec = (lzma_allocator *)(p);
437 /* reset pointer list */
438 memset(codec->allocptr, 0, sizeof(codec->allocptr));
439 memset(codec->allocptr2, 0, sizeof(codec->allocptr2));
440 codec->Alloc = lzma_fast_alloc;
441 codec->Free = lzma_fast_free;
444 /*-------------------------------------------------
445 * lzma_allocator_free
446 *-------------------------------------------------
449 static void lzma_allocator_free(void* p )
452 lzma_allocator *codec = (lzma_allocator *)(p);
454 /* free our memory */
455 for (i = 0 ; i < MAX_LZMA_ALLOCS ; i++)
457 if (codec->allocptr[i] != NULL)
458 free(codec->allocptr[i]);
462 /*-------------------------------------------------
463 * lzma_fast_alloc - fast malloc for lzma, which
464 * allocates and frees memory frequently
465 *-------------------------------------------------
468 /* Huge alignment values for possible SIMD optimization by compiler (NEON, SSE, AVX) */
469 #define LZMA_MIN_ALIGNMENT_BITS 512
470 #define LZMA_MIN_ALIGNMENT_BYTES (LZMA_MIN_ALIGNMENT_BITS / 8)
472 static void *lzma_fast_alloc(void *p, size_t size)
475 uint32_t *addr = NULL;
476 lzma_allocator *codec = (lzma_allocator *)(p);
479 /* compute the size, rounding to the nearest 1k */
480 size = (size + 0x3ff) & ~0x3ff;
482 /* reuse a hunk if we can */
483 for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
485 uint32_t *ptr = codec->allocptr[scan];
486 if (ptr != NULL && size == *ptr)
488 /* set the low bit of the size so we don't match next time */
491 /* return aligned address of the block */
492 return codec->allocptr2[scan];
496 /* alloc a new one and put it into the list */
497 addr = (uint32_t *)malloc(size + sizeof(uint32_t) + LZMA_MIN_ALIGNMENT_BYTES);
500 for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
502 if (codec->allocptr[scan] == NULL)
504 /* store block address */
505 codec->allocptr[scan] = addr;
507 /* compute aligned address, store it */
508 vaddr = (uintptr_t)addr;
509 vaddr = (vaddr + sizeof(uint32_t) + (LZMA_MIN_ALIGNMENT_BYTES-1)) & (~(LZMA_MIN_ALIGNMENT_BYTES-1));
510 codec->allocptr2[scan] = (uint32_t*)vaddr;
515 /* set the low bit of the size so we don't match next time */
518 /* return aligned address */
522 /*-------------------------------------------------
523 * lzma_fast_free - fast free for lzma, which
524 * allocates and frees memory frequently
525 *-------------------------------------------------
528 static void lzma_fast_free(void *p, void *address)
531 uint32_t *ptr = NULL;
532 lzma_allocator *codec = NULL;
537 codec = (lzma_allocator *)(p);
540 ptr = (uint32_t *)address;
541 for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
543 if (ptr == codec->allocptr2[scan])
545 /* clear the low bit of the size to allow matches */
546 *codec->allocptr[scan] &= ~1;
552 /***************************************************************************
554 ***************************************************************************
557 /*-------------------------------------------------
558 * lzma_codec_init - constructor
559 *-------------------------------------------------
562 static chd_error lzma_codec_init(void* codec, uint32_t hunkbytes)
565 CLzmaEncProps encoder_props;
566 Byte decoder_props[LZMA_PROPS_SIZE];
568 lzma_allocator* alloc;
569 lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
571 /* construct the decoder */
572 LzmaDec_Construct(&lzma_codec->decoder);
574 /* FIXME: this code is written in a way that makes it impossible to safely upgrade the LZMA SDK
575 * This code assumes that the current version of the encoder imposes the same requirements on the
576 * decoder as the encoder used to produce the file. This is not necessarily true. The format
577 * needs to be changed so the encoder properties are written to the file.
579 * configure the properties like the compressor did */
580 LzmaEncProps_Init(&encoder_props);
581 encoder_props.level = 9;
582 encoder_props.reduceSize = hunkbytes;
583 LzmaEncProps_Normalize(&encoder_props);
585 /* convert to decoder properties */
586 alloc = &lzma_codec->allocator;
587 lzma_allocator_init(alloc);
588 enc = LzmaEnc_Create((ISzAlloc*)alloc);
590 return CHDERR_DECOMPRESSION_ERROR;
591 if (LzmaEnc_SetProps(enc, &encoder_props) != SZ_OK)
593 LzmaEnc_Destroy(enc, (ISzAlloc*)&alloc, (ISzAlloc*)&alloc);
594 return CHDERR_DECOMPRESSION_ERROR;
596 props_size = sizeof(decoder_props);
597 if (LzmaEnc_WriteProperties(enc, decoder_props, &props_size) != SZ_OK)
599 LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc);
600 return CHDERR_DECOMPRESSION_ERROR;
602 LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc);
604 /* do memory allocations */
605 if (LzmaDec_Allocate(&lzma_codec->decoder, decoder_props, LZMA_PROPS_SIZE, (ISzAlloc*)alloc) != SZ_OK)
606 return CHDERR_DECOMPRESSION_ERROR;
612 /*-------------------------------------------------
614 *-------------------------------------------------
617 static void lzma_codec_free(void* codec)
619 lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
622 LzmaDec_Free(&lzma_codec->decoder, (ISzAlloc*)&lzma_codec->allocator);
623 lzma_allocator_free(&lzma_codec->allocator);
626 /*-------------------------------------------------
627 * decompress - decompress data using the LZMA
629 *-------------------------------------------------
632 static chd_error lzma_codec_decompress(void* codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
636 SizeT consumedlen, decodedlen;
638 lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
639 LzmaDec_Init(&lzma_codec->decoder);
642 consumedlen = complen;
643 decodedlen = destlen;
644 res = LzmaDec_DecodeToBuf(&lzma_codec->decoder, dest, &decodedlen, src, &consumedlen, LZMA_FINISH_END, &status);
645 if ((res != SZ_OK && res != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) || consumedlen != complen || decodedlen != destlen)
646 return CHDERR_DECOMPRESSION_ERROR;
651 static chd_error cdlz_codec_init(void* codec, uint32_t hunkbytes)
654 cdlz_codec_data* cdlz = (cdlz_codec_data*) codec;
656 /* allocate buffer */
657 cdlz->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
658 if (cdlz->buffer == NULL)
659 return CHDERR_OUT_OF_MEMORY;
661 /* make sure the CHD's hunk size is an even multiple of the frame size */
662 ret = lzma_codec_init(&cdlz->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
663 if (ret != CHDERR_NONE)
667 ret = zlib_codec_init(&cdlz->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SUBCODE_DATA);
668 if (ret != CHDERR_NONE)
672 if (hunkbytes % CD_FRAME_SIZE != 0)
673 return CHDERR_CODEC_ERROR;
678 static void cdlz_codec_free(void* codec)
680 cdlz_codec_data* cdlz = (cdlz_codec_data*) codec;
682 lzma_codec_free(&cdlz->base_decompressor);
684 zlib_codec_free(&cdlz->subcode_decompressor);
688 static chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
691 cdlz_codec_data* cdlz = (cdlz_codec_data*)codec;
693 /* determine header bytes */
694 uint32_t frames = destlen / CD_FRAME_SIZE;
695 uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
696 uint32_t ecc_bytes = (frames + 7) / 8;
697 uint32_t header_bytes = ecc_bytes + complen_bytes;
699 /* extract compressed length of base */
700 uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
701 if (complen_bytes > 2)
702 complen_base = (complen_base << 8) | src[ecc_bytes + 2];
704 /* reset and decode */
705 lzma_codec_decompress(&cdlz->base_decompressor, &src[header_bytes], complen_base, &cdlz->buffer[0], frames * CD_MAX_SECTOR_DATA);
707 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);
710 /* reassemble the data */
711 for (framenum = 0; framenum < frames; framenum++)
715 memcpy(&dest[framenum * CD_FRAME_SIZE], &cdlz->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
717 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);
720 #ifdef WANT_RAW_DATA_SECTOR
721 /* reconstitute the ECC data and sync header */
722 sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE];
723 if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
725 memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
726 ecc_generate(sector);
735 static chd_error cdzl_codec_init(void *codec, uint32_t hunkbytes)
738 cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
740 /* make sure the CHD's hunk size is an even multiple of the frame size */
741 if (hunkbytes % CD_FRAME_SIZE != 0)
742 return CHDERR_CODEC_ERROR;
744 cdzl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
745 if (cdzl->buffer == NULL)
746 return CHDERR_OUT_OF_MEMORY;
748 ret = zlib_codec_init(&cdzl->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
749 if (ret != CHDERR_NONE)
753 ret = zlib_codec_init(&cdzl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SUBCODE_DATA);
754 if (ret != CHDERR_NONE)
761 static void cdzl_codec_free(void *codec)
763 cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
764 zlib_codec_free(&cdzl->base_decompressor);
766 zlib_codec_free(&cdzl->subcode_decompressor);
771 static chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
774 cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
776 /* determine header bytes */
777 uint32_t frames = destlen / CD_FRAME_SIZE;
778 uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
779 uint32_t ecc_bytes = (frames + 7) / 8;
780 uint32_t header_bytes = ecc_bytes + complen_bytes;
782 /* extract compressed length of base */
783 uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
784 if (complen_bytes > 2)
785 complen_base = (complen_base << 8) | src[ecc_bytes + 2];
787 /* reset and decode */
788 zlib_codec_decompress(&cdzl->base_decompressor, &src[header_bytes], complen_base, &cdzl->buffer[0], frames * CD_MAX_SECTOR_DATA);
790 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);
793 /* reassemble the data */
794 for (framenum = 0; framenum < frames; framenum++)
798 memcpy(&dest[framenum * CD_FRAME_SIZE], &cdzl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
800 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);
803 #ifdef WANT_RAW_DATA_SECTOR
804 /* reconstitute the ECC data and sync header */
805 sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE];
806 if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
808 memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
809 ecc_generate(sector);
816 /***************************************************************************
817 * HUFFMAN DECOMPRESSOR
818 ***************************************************************************
821 static chd_error huff_codec_init(void* codec, uint32_t hunkbytes)
823 huff_codec_data* huff_codec = (huff_codec_data*) codec;
824 huff_codec->decoder = create_huffman_decoder(256, 16);
828 static void huff_codec_free(void *codec)
830 huff_codec_data* huff_codec = (huff_codec_data*) codec;
831 delete_huffman_decoder(huff_codec->decoder);
834 static chd_error huff_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
836 huff_codec_data* huff_codec = (huff_codec_data*) codec;
837 struct bitstream* bitbuf = create_bitstream(src, complen);
839 // first import the tree
840 enum huffman_error err = huffman_import_tree_huffman(huff_codec->decoder, bitbuf);
841 if (err != HUFFERR_NONE)
844 return CHDERR_DECOMPRESSION_ERROR;
847 // then decode the data
849 for (cur = 0; cur < destlen; cur++)
850 dest[cur] = huffman_decode_one(huff_codec->decoder, bitbuf);
851 bitstream_flush(bitbuf);
852 chd_error result = bitstream_overflow(bitbuf) ? CHDERR_DECOMPRESSION_ERROR : CHDERR_NONE;
858 /***************************************************************************
859 * CD FLAC DECOMPRESSOR
860 ***************************************************************************
863 /*------------------------------------------------------
864 * flac_codec_blocksize - return the optimal block size
865 *------------------------------------------------------
868 static uint32_t flac_codec_blocksize(uint32_t bytes)
870 /* determine FLAC block size, which must be 16-65535
871 * clamp to 2k since that's supposed to be the sweet spot */
872 uint32_t blocksize = bytes / 4;
873 while (blocksize > 2048)
878 static chd_error flac_codec_init(void *codec, uint32_t hunkbytes)
880 uint16_t native_endian = 0;
881 flac_codec_data *flac = (flac_codec_data*)codec;
883 /* make sure the CHD's hunk size is an even multiple of the sample size */
884 if (hunkbytes % 4 != 0)
885 return CHDERR_CODEC_ERROR;
887 /* determine whether we want native or swapped samples */
888 *(uint8_t *)(&native_endian) = 1;
889 flac->native_endian = (native_endian & 1);
891 /* flac decoder init */
892 if (flac_decoder_init(&flac->decoder))
893 return CHDERR_OUT_OF_MEMORY;
898 static void flac_codec_free(void *codec)
900 flac_codec_data *flac = (flac_codec_data*)codec;
901 flac_decoder_free(&flac->decoder);
904 static chd_error flac_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
906 flac_codec_data *flac = (flac_codec_data*)codec;
910 swap_endian = !flac->native_endian;
911 else if (src[0] == 'B')
912 swap_endian = flac->native_endian;
914 return CHDERR_DECOMPRESSION_ERROR;
916 if (!flac_decoder_reset(&flac->decoder, 44100, 2, flac_codec_blocksize(destlen), src + 1, complen - 1))
917 return CHDERR_DECOMPRESSION_ERROR;
918 if (!flac_decoder_decode_interleaved(&flac->decoder, (int16_t *)(dest), destlen/4, swap_endian))
919 return CHDERR_DECOMPRESSION_ERROR;
920 flac_decoder_finish(&flac->decoder);
925 static uint32_t cdfl_codec_blocksize(uint32_t bytes)
927 // for CDs it seems that CD_MAX_SECTOR_DATA is the right target
928 uint32_t blocksize = bytes / 4;
929 while (blocksize > CD_MAX_SECTOR_DATA)
934 static chd_error cdfl_codec_init(void *codec, uint32_t hunkbytes)
939 uint16_t native_endian = 0;
940 cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
942 /* make sure the CHD's hunk size is an even multiple of the frame size */
943 if (hunkbytes % CD_FRAME_SIZE != 0)
944 return CHDERR_CODEC_ERROR;
946 cdfl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
947 if (cdfl->buffer == NULL)
948 return CHDERR_OUT_OF_MEMORY;
950 /* determine whether we want native or swapped samples */
951 *(uint8_t *)(&native_endian) = 1;
952 cdfl->swap_endian = (native_endian & 1);
955 /* init zlib inflater */
956 ret = zlib_codec_init(&cdfl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
957 if (ret != CHDERR_NONE)
961 /* flac decoder init */
962 if (flac_decoder_init(&cdfl->decoder))
963 return CHDERR_OUT_OF_MEMORY;
968 static void cdfl_codec_free(void *codec)
970 cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
971 flac_decoder_free(&cdfl->decoder);
973 zlib_codec_free(&cdfl->subcode_decompressor);
979 static chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
987 cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
989 /* reset and decode */
990 uint32_t frames = destlen / CD_FRAME_SIZE;
992 if (!flac_decoder_reset(&cdfl->decoder, 44100, 2, cdfl_codec_blocksize(frames * CD_MAX_SECTOR_DATA), src, complen))
993 return CHDERR_DECOMPRESSION_ERROR;
994 buffer = &cdfl->buffer[0];
995 if (!flac_decoder_decode_interleaved(&cdfl->decoder, (int16_t *)(buffer), frames * CD_MAX_SECTOR_DATA/4, cdfl->swap_endian))
996 return CHDERR_DECOMPRESSION_ERROR;
999 /* inflate the subcode data */
1000 offset = flac_decoder_finish(&cdfl->decoder);
1001 ret = zlib_codec_decompress(&cdfl->subcode_decompressor, src + offset, complen - offset, &cdfl->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA);
1002 if (ret != CHDERR_NONE)
1005 flac_decoder_finish(&cdfl->decoder);
1008 /* reassemble the data */
1009 for (framenum = 0; framenum < frames; framenum++)
1011 memcpy(&dest[framenum * CD_FRAME_SIZE], &cdfl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
1013 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);
1021 /***************************************************************************
1023 ***************************************************************************
1026 /*-------------------------------------------------
1027 * zstd_codec_init - constructor
1028 *-------------------------------------------------
1031 static chd_error zstd_codec_init(void* codec, uint32_t hunkbytes)
1033 zstd_codec_data* zstd_codec = (zstd_codec_data*) codec;
1035 zstd_codec->dstream = ZSTD_createDStream();
1036 if (!zstd_codec->dstream) {
1037 printf("NO DSTREAM CREATED!\n");
1038 return CHDERR_DECOMPRESSION_ERROR;
1043 /*-------------------------------------------------
1045 *-------------------------------------------------
1048 static void zstd_codec_free(void* codec)
1050 zstd_codec_data* zstd_codec = (zstd_codec_data*) codec;
1052 ZSTD_freeDStream(zstd_codec->dstream);
1055 /*-------------------------------------------------
1056 * decompress - decompress data using the ZSTD
1058 *-------------------------------------------------
1060 static chd_error zstd_codec_decompress(void* codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
1063 zstd_codec_data* zstd_codec = (zstd_codec_data*) codec;
1064 //reset decompressor
1065 size_t zstd_res = ZSTD_initDStream(zstd_codec->dstream);
1066 if (ZSTD_isError(zstd_res))
1068 printf("INITI DSTREAM FAILED!\n");
1069 return CHDERR_DECOMPRESSION_ERROR;
1072 ZSTD_inBuffer input = {src, complen, 0};
1073 ZSTD_outBuffer output = {dest, destlen, 0 };
1075 while ((input.pos < input.size) && (output.pos < output.size))
1077 zstd_res = ZSTD_decompressStream(zstd_codec->dstream, &output, &input);
1078 if (ZSTD_isError(zstd_res))
1080 printf("DECOMPRESSION ERROR IN LOOP\n");
1081 return CHDERR_DECOMPRESSION_ERROR;
1084 if (output.pos != output.size)
1086 printf("OUTPUT DOESN'T MATCH!\n");
1087 return CHDERR_DECOMPRESSION_ERROR;
1094 static chd_error cdzs_codec_init(void* codec, uint32_t hunkbytes)
1097 cdzs_codec_data* cdzs = (cdzs_codec_data*) codec;
1099 /* allocate buffer */
1100 cdzs->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
1101 if (cdzs->buffer == NULL)
1102 return CHDERR_OUT_OF_MEMORY;
1104 /* make sure the CHD's hunk size is an even multiple of the frame size */
1105 ret = zstd_codec_init(&cdzs->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
1106 if (ret != CHDERR_NONE)
1110 ret = zstd_codec_init(&cdzs->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SUBCODE_DATA);
1111 if (ret != CHDERR_NONE)
1115 if (hunkbytes % CD_FRAME_SIZE != 0)
1116 return CHDERR_CODEC_ERROR;
1121 static void cdzs_codec_free(void* codec)
1123 cdzs_codec_data* cdzs = (cdzs_codec_data*) codec;
1125 zstd_codec_free(&cdzs->base_decompressor);
1127 zstd_codec_free(&cdzs->subcode_decompressor);
1131 static chd_error cdzs_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
1134 cdzs_codec_data* cdzs = (cdzs_codec_data*)codec;
1136 /* determine header bytes */
1137 uint32_t frames = destlen / CD_FRAME_SIZE;
1138 uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
1139 uint32_t ecc_bytes = (frames + 7) / 8;
1140 uint32_t header_bytes = ecc_bytes + complen_bytes;
1142 /* extract compressed length of base */
1143 uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
1144 if (complen_bytes > 2)
1145 complen_base = (complen_base << 8) | src[ecc_bytes + 2];
1147 /* reset and decode */
1148 zstd_codec_decompress(&cdzs->base_decompressor, &src[header_bytes], complen_base, &cdzs->buffer[0], frames * CD_MAX_SECTOR_DATA);
1150 zstd_codec_decompress(&cdzs->subcode_decompressor, &src[header_bytes + complen_base], complen - complen_base - header_bytes, &cdzs->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA);
1153 /* reassemble the data */
1154 for (framenum = 0; framenum < frames; framenum++)
1158 memcpy(&dest[framenum * CD_FRAME_SIZE], &cdzs->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
1160 memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdzs->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA);
1163 #ifdef WANT_RAW_DATA_SECTOR
1164 /* reconstitute the ECC data and sync header */
1165 sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE];
1166 if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
1168 memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
1169 ecc_generate(sector);
1176 /***************************************************************************
1178 ***************************************************************************/
1180 static const codec_interface codec_interfaces[] =
1182 /* "none" or no compression */
1184 CHDCOMPRESSION_NONE,
1193 /* standard zlib compression */
1195 CHDCOMPRESSION_ZLIB,
1200 zlib_codec_decompress,
1204 /* zlib+ compression */
1206 CHDCOMPRESSION_ZLIB_PLUS,
1211 zlib_codec_decompress,
1215 /* V5 zlib compression */
1222 zlib_codec_decompress,
1226 /* V5 lzma compression */
1233 lzma_codec_decompress,
1237 /* V5 huffman compression */
1244 huff_codec_decompress,
1248 /* V5 flac compression */
1255 flac_codec_decompress,
1258 /* V5 zstd compression */
1265 zstd_codec_decompress,
1269 /* V5 CD zlib compression */
1272 "cdzl (CD Deflate)",
1276 cdzl_codec_decompress,
1280 /* V5 CD lzma compression */
1287 cdlz_codec_decompress,
1291 /* V5 CD flac compression */
1298 cdfl_codec_decompress,
1301 /* V5 CD zstd compression */
1304 "cdzs (CD ZStandard)",
1308 cdzs_codec_decompress,
1314 /***************************************************************************
1316 ***************************************************************************/
1318 /*-------------------------------------------------
1319 get_bigendian_uint64 - fetch a UINT64 from
1320 the data stream in bigendian order
1321 -------------------------------------------------*/
1323 static inline UINT64 get_bigendian_uint64(const UINT8 *base)
1325 return ((UINT64)base[0] << 56) | ((UINT64)base[1] << 48) | ((UINT64)base[2] << 40) | ((UINT64)base[3] << 32) |
1326 ((UINT64)base[4] << 24) | ((UINT64)base[5] << 16) | ((UINT64)base[6] << 8) | (UINT64)base[7];
1329 /*-------------------------------------------------
1330 put_bigendian_uint64 - write a UINT64 to
1331 the data stream in bigendian order
1332 -------------------------------------------------*/
1334 static inline void put_bigendian_uint64(UINT8 *base, UINT64 value)
1336 base[0] = value >> 56;
1337 base[1] = value >> 48;
1338 base[2] = value >> 40;
1339 base[3] = value >> 32;
1340 base[4] = value >> 24;
1341 base[5] = value >> 16;
1342 base[6] = value >> 8;
1346 /*-------------------------------------------------
1347 get_bigendian_uint48 - fetch a UINT48 from
1348 the data stream in bigendian order
1349 -------------------------------------------------*/
1351 static inline UINT64 get_bigendian_uint48(const UINT8 *base)
1353 return ((UINT64)base[0] << 40) | ((UINT64)base[1] << 32) |
1354 ((UINT64)base[2] << 24) | ((UINT64)base[3] << 16) | ((UINT64)base[4] << 8) | (UINT64)base[5];
1357 /*-------------------------------------------------
1358 put_bigendian_uint48 - write a UINT48 to
1359 the data stream in bigendian order
1360 -------------------------------------------------*/
1362 static inline void put_bigendian_uint48(UINT8 *base, UINT64 value)
1364 value &= 0xffffffffffff;
1365 base[0] = value >> 40;
1366 base[1] = value >> 32;
1367 base[2] = value >> 24;
1368 base[3] = value >> 16;
1369 base[4] = value >> 8;
1372 /*-------------------------------------------------
1373 get_bigendian_uint32 - fetch a UINT32 from
1374 the data stream in bigendian order
1375 -------------------------------------------------*/
1377 static inline UINT32 get_bigendian_uint32(const UINT8 *base)
1379 return (base[0] << 24) | (base[1] << 16) | (base[2] << 8) | base[3];
1382 /*-------------------------------------------------
1383 put_bigendian_uint32 - write a UINT32 to
1384 the data stream in bigendian order
1385 -------------------------------------------------*/
1387 static inline void put_bigendian_uint32(UINT8 *base, UINT32 value)
1389 base[0] = value >> 24;
1390 base[1] = value >> 16;
1391 base[2] = value >> 8;
1395 /*-------------------------------------------------
1396 put_bigendian_uint24 - write a UINT24 to
1397 the data stream in bigendian order
1398 -------------------------------------------------*/
1400 static inline void put_bigendian_uint24(UINT8 *base, UINT32 value)
1403 base[0] = value >> 16;
1404 base[1] = value >> 8;
1408 /*-------------------------------------------------
1409 get_bigendian_uint24 - fetch a UINT24 from
1410 the data stream in bigendian order
1411 -------------------------------------------------*/
1413 static inline UINT32 get_bigendian_uint24(const UINT8 *base)
1415 return (base[0] << 16) | (base[1] << 8) | base[2];
1418 /*-------------------------------------------------
1419 get_bigendian_uint16 - fetch a UINT16 from
1420 the data stream in bigendian order
1421 -------------------------------------------------*/
1423 static inline UINT16 get_bigendian_uint16(const UINT8 *base)
1425 return (base[0] << 8) | base[1];
1428 /*-------------------------------------------------
1429 put_bigendian_uint16 - write a UINT16 to
1430 the data stream in bigendian order
1431 -------------------------------------------------*/
1433 static inline void put_bigendian_uint16(UINT8 *base, UINT16 value)
1435 base[0] = value >> 8;
1439 /*-------------------------------------------------
1440 map_extract - extract a single map
1441 entry from the datastream
1442 -------------------------------------------------*/
1444 static inline void map_extract(const UINT8 *base, map_entry *entry)
1446 entry->offset = get_bigendian_uint64(&base[0]);
1447 entry->crc = get_bigendian_uint32(&base[8]);
1448 entry->length = get_bigendian_uint16(&base[12]) | (base[14] << 16);
1449 entry->flags = base[15];
1452 /*-------------------------------------------------
1453 map_assemble - write a single map
1454 entry to the datastream
1455 -------------------------------------------------*/
1457 static inline void map_assemble(UINT8 *base, map_entry *entry)
1459 put_bigendian_uint64(&base[0], entry->offset);
1460 put_bigendian_uint32(&base[8], entry->crc);
1461 put_bigendian_uint16(&base[12], entry->length);
1462 base[14] = entry->length >> 16;
1463 base[15] = entry->flags;
1466 /*-------------------------------------------------
1467 map_size_v5 - calculate CHDv5 map size
1468 -------------------------------------------------*/
1469 static inline int map_size_v5(chd_header* header)
1471 return header->hunkcount * header->mapentrybytes;
1474 /*-------------------------------------------------
1475 crc16 - calculate CRC16 (from hashing.cpp)
1476 -------------------------------------------------*/
1477 uint16_t crc16(const void *data, uint32_t length)
1479 uint16_t crc = 0xffff;
1481 static const uint16_t s_table[256] =
1483 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1484 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1485 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1486 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1487 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1488 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1489 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1490 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1491 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1492 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1493 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1494 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1495 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1496 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1497 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1498 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1499 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1500 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1501 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1502 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1503 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1504 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1505 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1506 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1507 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1508 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1509 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1510 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1511 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1512 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1513 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1514 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1517 const uint8_t *src = (uint8_t*)data;
1519 /* fetch the current value into a local and rip through the source data */
1520 while (length-- != 0)
1521 crc = (crc << 8) ^ s_table[(crc >> 8) ^ *src++];
1525 /*-------------------------------------------------
1526 compressed - test if CHD file is compressed
1527 +-------------------------------------------------*/
1528 static inline int chd_compressed(chd_header* header) {
1529 return header->compression[0] != CHD_CODEC_NONE;
1532 /*-------------------------------------------------
1533 decompress_v5_map - decompress the v5 map
1534 -------------------------------------------------*/
1536 static chd_error decompress_v5_map(chd_file* chd, chd_header* header)
1541 uint8_t lastcomp = 0;
1542 uint32_t last_self = 0;
1543 uint64_t last_parent = 0;
1544 struct bitstream* bitbuf;
1551 uint8_t *compressed_ptr;
1553 struct huffman_decoder* decoder;
1554 enum huffman_error err;
1556 int rawmapsize = map_size_v5(header);
1558 if (!chd_compressed(header))
1560 header->rawmap = (uint8_t*)malloc(rawmapsize);
1561 if (header->rawmap == NULL)
1562 return CHDERR_OUT_OF_MEMORY;
1563 core_fseek(chd->file, header->mapoffset, SEEK_SET);
1564 result = core_fread(chd->file, header->rawmap, rawmapsize);
1568 /* read the reader */
1569 core_fseek(chd->file, header->mapoffset, SEEK_SET);
1570 result = core_fread(chd->file, rawbuf, sizeof(rawbuf));
1571 mapbytes = get_bigendian_uint32(&rawbuf[0]);
1572 firstoffs = get_bigendian_uint48(&rawbuf[4]);
1573 mapcrc = get_bigendian_uint16(&rawbuf[10]);
1574 lengthbits = rawbuf[12];
1575 selfbits = rawbuf[13];
1576 parentbits = rawbuf[14];
1578 /* now read the map */
1579 compressed_ptr = (uint8_t*)malloc(sizeof(uint8_t) * mapbytes);
1580 if (compressed_ptr == NULL)
1581 return CHDERR_OUT_OF_MEMORY;
1582 core_fseek(chd->file, header->mapoffset + 16, SEEK_SET);
1583 result = core_fread(chd->file, compressed_ptr, mapbytes);
1584 bitbuf = create_bitstream(compressed_ptr, sizeof(uint8_t) * mapbytes);
1585 header->rawmap = (uint8_t*)malloc(rawmapsize);
1586 if (header->rawmap == NULL)
1588 free(compressed_ptr);
1590 return CHDERR_OUT_OF_MEMORY;
1593 /* first decode the compression types */
1594 decoder = create_huffman_decoder(16, 8);
1595 if (decoder == NULL)
1597 free(compressed_ptr);
1599 return CHDERR_OUT_OF_MEMORY;
1602 err = huffman_import_tree_rle(decoder, bitbuf);
1603 if (err != HUFFERR_NONE)
1605 free(compressed_ptr);
1607 delete_huffman_decoder(decoder);
1608 return CHDERR_DECOMPRESSION_ERROR;
1611 for (hunknum = 0; hunknum < header->hunkcount; hunknum++)
1613 uint8_t *rawmap = header->rawmap + (hunknum * 12);
1615 rawmap[0] = lastcomp, repcount--;
1618 uint8_t val = huffman_decode_one(decoder, bitbuf);
1619 if (val == COMPRESSION_RLE_SMALL)
1620 rawmap[0] = lastcomp, repcount = 2 + huffman_decode_one(decoder, bitbuf);
1621 else if (val == COMPRESSION_RLE_LARGE)
1622 rawmap[0] = lastcomp, repcount = 2 + 16 + (huffman_decode_one(decoder, bitbuf) << 4), repcount += huffman_decode_one(decoder, bitbuf);
1624 rawmap[0] = lastcomp = val;
1628 /* then iterate through the hunks and extract the needed data */
1629 curoffset = firstoffs;
1630 for (hunknum = 0; hunknum < header->hunkcount; hunknum++)
1632 uint8_t *rawmap = header->rawmap + (hunknum * 12);
1633 uint64_t offset = curoffset;
1634 uint32_t length = 0;
1639 case COMPRESSION_TYPE_0:
1640 case COMPRESSION_TYPE_1:
1641 case COMPRESSION_TYPE_2:
1642 case COMPRESSION_TYPE_3:
1643 curoffset += length = bitstream_read(bitbuf, lengthbits);
1644 crc = bitstream_read(bitbuf, 16);
1647 case COMPRESSION_NONE:
1648 curoffset += length = header->hunkbytes;
1649 crc = bitstream_read(bitbuf, 16);
1652 case COMPRESSION_SELF:
1653 last_self = offset = bitstream_read(bitbuf, selfbits);
1656 case COMPRESSION_PARENT:
1657 offset = bitstream_read(bitbuf, parentbits);
1658 last_parent = offset;
1661 /* pseudo-types; convert into base types */
1662 case COMPRESSION_SELF_1:
1664 case COMPRESSION_SELF_0:
1665 rawmap[0] = COMPRESSION_SELF;
1669 case COMPRESSION_PARENT_SELF:
1670 rawmap[0] = COMPRESSION_PARENT;
1671 last_parent = offset = ( ((uint64_t)hunknum) * ((uint64_t)header->hunkbytes) ) / header->unitbytes;
1674 case COMPRESSION_PARENT_1:
1675 last_parent += header->hunkbytes / header->unitbytes;
1676 case COMPRESSION_PARENT_0:
1677 rawmap[0] = COMPRESSION_PARENT;
1678 offset = last_parent;
1682 put_bigendian_uint24(&rawmap[1], length);
1685 put_bigendian_uint48(&rawmap[4], offset);
1688 put_bigendian_uint16(&rawmap[10], crc);
1692 free(compressed_ptr);
1694 delete_huffman_decoder(decoder);
1696 /* verify the final CRC */
1697 if (crc16(&header->rawmap[0], header->hunkcount * 12) != mapcrc)
1698 return CHDERR_DECOMPRESSION_ERROR;
1703 /*-------------------------------------------------
1704 map_extract_old - extract a single map
1705 entry in old format from the datastream
1706 -------------------------------------------------*/
1708 static inline void map_extract_old(const UINT8 *base, map_entry *entry, UINT32 hunkbytes)
1710 entry->offset = get_bigendian_uint64(&base[0]);
1712 entry->length = entry->offset >> 44;
1713 entry->flags = MAP_ENTRY_FLAG_NO_CRC | ((entry->length == hunkbytes) ? V34_MAP_ENTRY_TYPE_UNCOMPRESSED : V34_MAP_ENTRY_TYPE_COMPRESSED);
1715 entry->offset = entry->offset & 0x00000FFFFFFFFFFFLL;
1717 entry->offset = (entry->offset << 20) >> 20;
1721 /***************************************************************************
1723 ***************************************************************************/
1725 /*-------------------------------------------------
1726 chd_open_file - open a CHD file for access
1727 -------------------------------------------------*/
1729 CHD_EXPORT chd_error chd_open_file(FILE *file, int mode, chd_file *parent, chd_file **chd) {
1730 core_file *stream = malloc(sizeof(core_file));
1732 return CHDERR_OUT_OF_MEMORY;
1733 stream->argp = file;
1734 stream->fsize = core_stdio_fsize;
1735 stream->fread = core_stdio_fread;
1736 stream->fclose = core_stdio_fclose_nonowner;
1737 stream->fseek = core_stdio_fseek;
1739 return chd_open_core_file(stream, mode, parent, chd);
1742 /*-------------------------------------------------
1743 chd_open_core_file - open a CHD file for access
1744 -------------------------------------------------*/
1746 CHD_EXPORT chd_error chd_open_core_file(core_file *file, int mode, chd_file *parent, chd_file **chd)
1748 chd_file *newchd = NULL;
1752 /* verify parameters */
1754 EARLY_EXIT(err = CHDERR_INVALID_PARAMETER);
1756 /* punt if invalid parent */
1757 if (parent != NULL && parent->cookie != COOKIE_VALUE)
1758 EARLY_EXIT(err = CHDERR_INVALID_PARAMETER);
1760 /* allocate memory for the final result */
1761 newchd = (chd_file *)malloc(sizeof(**chd));
1763 EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
1764 memset(newchd, 0, sizeof(*newchd));
1765 newchd->cookie = COOKIE_VALUE;
1766 newchd->parent = parent;
1767 newchd->file = file;
1769 /* now attempt to read the header */
1770 err = header_read(newchd, &newchd->header);
1771 if (err != CHDERR_NONE)
1774 /* validate the header */
1775 err = header_validate(&newchd->header);
1776 if (err != CHDERR_NONE)
1779 /* make sure we don't open a read-only file writeable */
1780 if (mode == CHD_OPEN_READWRITE && !(newchd->header.flags & CHDFLAGS_IS_WRITEABLE))
1781 EARLY_EXIT(err = CHDERR_FILE_NOT_WRITEABLE);
1783 /* also, never open an older version writeable */
1784 if (mode == CHD_OPEN_READWRITE && newchd->header.version < CHD_HEADER_VERSION)
1785 EARLY_EXIT(err = CHDERR_UNSUPPORTED_VERSION);
1787 /* if we need a parent, make sure we have one */
1790 /* Detect parent requirement for versions below 5 */
1791 if (newchd->header.version < 5 && newchd->header.flags & CHDFLAGS_HAS_PARENT)
1792 EARLY_EXIT(err = CHDERR_REQUIRES_PARENT);
1793 /* Detection for version 5 and above - if parentsha1 != 0, we have a parent */
1794 else if (newchd->header.version >= 5 && memcmp(nullsha1, newchd->header.parentsha1, sizeof(newchd->header.parentsha1)) != 0)
1795 EARLY_EXIT(err = CHDERR_REQUIRES_PARENT);
1798 /* make sure we have a valid parent */
1801 /* check MD5 if it isn't empty */
1802 if (memcmp(nullmd5, newchd->header.parentmd5, sizeof(newchd->header.parentmd5)) != 0 &&
1803 memcmp(nullmd5, newchd->parent->header.md5, sizeof(newchd->parent->header.md5)) != 0 &&
1804 memcmp(newchd->parent->header.md5, newchd->header.parentmd5, sizeof(newchd->header.parentmd5)) != 0)
1805 EARLY_EXIT(err = CHDERR_INVALID_PARENT);
1807 /* check SHA1 if it isn't empty */
1808 if (memcmp(nullsha1, newchd->header.parentsha1, sizeof(newchd->header.parentsha1)) != 0 &&
1809 memcmp(nullsha1, newchd->parent->header.sha1, sizeof(newchd->parent->header.sha1)) != 0 &&
1810 memcmp(newchd->parent->header.sha1, newchd->header.parentsha1, sizeof(newchd->header.parentsha1)) != 0)
1811 EARLY_EXIT(err = CHDERR_INVALID_PARENT);
1814 /* now read the hunk map */
1815 if (newchd->header.version < 5)
1817 err = map_read(newchd);
1818 if (err != CHDERR_NONE)
1823 err = decompress_v5_map(newchd, &(newchd->header));
1825 if (err != CHDERR_NONE)
1828 #ifdef NEED_CACHE_HUNK
1829 /* allocate and init the hunk cache */
1830 newchd->cache = (UINT8 *)malloc(newchd->header.hunkbytes);
1831 newchd->compare = (UINT8 *)malloc(newchd->header.hunkbytes);
1832 if (newchd->cache == NULL || newchd->compare == NULL)
1833 EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
1834 newchd->cachehunk = ~0;
1835 newchd->comparehunk = ~0;
1838 /* allocate the temporary compressed buffer */
1839 newchd->compressed = (UINT8 *)malloc(newchd->header.hunkbytes);
1840 if (newchd->compressed == NULL)
1841 EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
1843 /* find the codec interface */
1844 if (newchd->header.version < 5)
1846 for (intfnum = 0; intfnum < ARRAY_LENGTH(codec_interfaces); intfnum++)
1848 if (codec_interfaces[intfnum].compression == newchd->header.compression[0])
1850 newchd->codecintf[0] = &codec_interfaces[intfnum];
1855 if (intfnum == ARRAY_LENGTH(codec_interfaces))
1856 EARLY_EXIT(err = CHDERR_UNSUPPORTED_FORMAT);
1858 /* initialize the codec */
1859 if (newchd->codecintf[0]->init != NULL)
1861 err = (*newchd->codecintf[0]->init)(&newchd->zlib_codec_data, newchd->header.hunkbytes);
1862 if (err != CHDERR_NONE)
1869 /* verify the compression types and initialize the codecs */
1870 for (decompnum = 0; decompnum < ARRAY_LENGTH(newchd->header.compression); decompnum++)
1873 for (i = 0 ; i < ARRAY_LENGTH(codec_interfaces) ; i++)
1875 if (codec_interfaces[i].compression == newchd->header.compression[decompnum])
1877 newchd->codecintf[decompnum] = &codec_interfaces[i];
1882 if (newchd->codecintf[decompnum] == NULL && newchd->header.compression[decompnum] != 0)
1883 EARLY_EXIT(err = CHDERR_UNSUPPORTED_FORMAT);
1885 /* initialize the codec */
1886 if (newchd->codecintf[decompnum]->init != NULL)
1889 switch (newchd->header.compression[decompnum])
1891 case CHD_CODEC_ZLIB:
1892 codec = &newchd->zlib_codec_data;
1895 case CHD_CODEC_LZMA:
1896 codec = &newchd->lzma_codec_data;
1899 case CHD_CODEC_HUFFMAN:
1900 codec = &newchd->huff_codec_data;
1903 case CHD_CODEC_FLAC:
1904 codec = &newchd->flac_codec_data;
1907 case CHD_CODEC_ZSTD:
1908 codec = &newchd->zstd_codec_data;
1911 case CHD_CODEC_CD_ZLIB:
1912 codec = &newchd->cdzl_codec_data;
1915 case CHD_CODEC_CD_LZMA:
1916 codec = &newchd->cdlz_codec_data;
1919 case CHD_CODEC_CD_FLAC:
1920 codec = &newchd->cdfl_codec_data;
1923 case CHD_CODEC_CD_ZSTD:
1924 codec = &newchd->cdzs_codec_data;
1929 EARLY_EXIT(err = CHDERR_UNSUPPORTED_FORMAT);
1931 err = (*newchd->codecintf[decompnum]->init)(codec, newchd->header.hunkbytes);
1932 if (err != CHDERR_NONE)
1948 /*-------------------------------------------------
1949 chd_precache - precache underlying file in
1951 -------------------------------------------------*/
1953 CHD_EXPORT chd_error chd_precache(chd_file *chd)
1958 if (chd->file_cache == NULL)
1960 size = core_fsize(chd->file);
1961 if ((INT64)size <= 0)
1962 return CHDERR_INVALID_DATA;
1963 chd->file_cache = malloc(size);
1964 if (chd->file_cache == NULL)
1965 return CHDERR_OUT_OF_MEMORY;
1966 core_fseek(chd->file, 0, SEEK_SET);
1967 count = core_fread(chd->file, chd->file_cache, size);
1970 free(chd->file_cache);
1971 chd->file_cache = NULL;
1972 return CHDERR_READ_ERROR;
1979 /*-------------------------------------------------
1980 chd_open - open a CHD file by
1982 -------------------------------------------------*/
1984 CHD_EXPORT chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd)
1987 core_file *file = NULL;
1989 if (filename == NULL)
1991 err = CHDERR_INVALID_PARAMETER;
1995 /* choose the proper mode */
2002 err = CHDERR_INVALID_PARAMETER;
2007 file = core_stdio_fopen(filename);
2010 err = CHDERR_FILE_NOT_FOUND;
2014 /* now open the CHD */
2015 return chd_open_core_file(file, mode, parent, chd);
2018 if ((err != CHDERR_NONE) && (file != NULL))
2023 /*-------------------------------------------------
2024 chd_close - close a CHD file for access
2025 -------------------------------------------------*/
2027 CHD_EXPORT void chd_close(chd_file *chd)
2029 /* punt if NULL or invalid */
2030 if (chd == NULL || chd->cookie != COOKIE_VALUE)
2033 /* deinit the codec */
2034 if (chd->header.version < 5)
2036 if (chd->codecintf[0] != NULL && chd->codecintf[0]->free != NULL)
2037 (*chd->codecintf[0]->free)(&chd->zlib_codec_data);
2042 /* Free the codecs */
2043 for (i = 0 ; i < ARRAY_LENGTH(chd->codecintf); i++)
2047 if (chd->codecintf[i] == NULL)
2050 switch (chd->codecintf[i]->compression)
2052 case CHD_CODEC_ZLIB:
2053 codec = &chd->zlib_codec_data;
2056 case CHD_CODEC_LZMA:
2057 codec = &chd->lzma_codec_data;
2060 case CHD_CODEC_HUFFMAN:
2061 codec = &chd->huff_codec_data;
2064 case CHD_CODEC_FLAC:
2065 codec = &chd->flac_codec_data;
2068 case CHD_CODEC_ZSTD:
2069 codec = &chd->zstd_codec_data;
2072 case CHD_CODEC_CD_ZLIB:
2073 codec = &chd->cdzl_codec_data;
2076 case CHD_CODEC_CD_LZMA:
2077 codec = &chd->cdlz_codec_data;
2080 case CHD_CODEC_CD_FLAC:
2081 codec = &chd->cdfl_codec_data;
2084 case CHD_CODEC_CD_ZSTD:
2085 codec = &chd->cdzs_codec_data;
2091 (*chd->codecintf[i]->free)(codec);
2095 /* Free the raw map */
2096 if (chd->header.rawmap != NULL)
2097 free(chd->header.rawmap);
2100 /* free the compressed data buffer */
2101 if (chd->compressed != NULL)
2102 free(chd->compressed);
2104 #ifdef NEED_CACHE_HUNK
2105 /* free the hunk cache and compare data */
2106 if (chd->compare != NULL)
2108 if (chd->cache != NULL)
2112 /* free the hunk map */
2113 if (chd->map != NULL)
2116 /* close the file */
2117 if (chd->file != NULL)
2118 core_fclose(chd->file);
2120 #ifdef NEED_CACHE_HUNK
2121 if (PRINTF_MAX_HUNK) printf("Max hunk = %d/%d\n", chd->maxhunk, chd->header.totalhunks);
2123 if (chd->file_cache)
2124 free(chd->file_cache);
2127 chd_close(chd->parent);
2129 /* free our memory */
2133 /*-------------------------------------------------
2134 chd_core_file - return the associated
2136 -------------------------------------------------*/
2138 CHD_EXPORT core_file *chd_core_file(chd_file *chd)
2143 /*-------------------------------------------------
2144 chd_error_string - return an error string for
2146 -------------------------------------------------*/
2148 CHD_EXPORT const char *chd_error_string(chd_error err)
2152 case CHDERR_NONE: return "no error";
2153 case CHDERR_NO_INTERFACE: return "no drive interface";
2154 case CHDERR_OUT_OF_MEMORY: return "out of memory";
2155 case CHDERR_INVALID_FILE: return "invalid file";
2156 case CHDERR_INVALID_PARAMETER: return "invalid parameter";
2157 case CHDERR_INVALID_DATA: return "invalid data";
2158 case CHDERR_FILE_NOT_FOUND: return "file not found";
2159 case CHDERR_REQUIRES_PARENT: return "requires parent";
2160 case CHDERR_FILE_NOT_WRITEABLE: return "file not writeable";
2161 case CHDERR_READ_ERROR: return "read error";
2162 case CHDERR_WRITE_ERROR: return "write error";
2163 case CHDERR_CODEC_ERROR: return "codec error";
2164 case CHDERR_INVALID_PARENT: return "invalid parent";
2165 case CHDERR_HUNK_OUT_OF_RANGE: return "hunk out of range";
2166 case CHDERR_DECOMPRESSION_ERROR: return "decompression error";
2167 case CHDERR_COMPRESSION_ERROR: return "compression error";
2168 case CHDERR_CANT_CREATE_FILE: return "can't create file";
2169 case CHDERR_CANT_VERIFY: return "can't verify file";
2170 case CHDERR_NOT_SUPPORTED: return "operation not supported";
2171 case CHDERR_METADATA_NOT_FOUND: return "can't find metadata";
2172 case CHDERR_INVALID_METADATA_SIZE: return "invalid metadata size";
2173 case CHDERR_UNSUPPORTED_VERSION: return "unsupported CHD version";
2174 case CHDERR_VERIFY_INCOMPLETE: return "incomplete verify";
2175 case CHDERR_INVALID_METADATA: return "invalid metadata";
2176 case CHDERR_INVALID_STATE: return "invalid state";
2177 case CHDERR_OPERATION_PENDING: return "operation pending";
2178 case CHDERR_NO_ASYNC_OPERATION: return "no async operation in progress";
2179 case CHDERR_UNSUPPORTED_FORMAT: return "unsupported format";
2180 default: return "undocumented error";
2184 /***************************************************************************
2185 CHD HEADER MANAGEMENT
2186 ***************************************************************************/
2188 /*-------------------------------------------------
2189 chd_get_header - return a pointer to the
2190 extracted header data
2191 -------------------------------------------------*/
2193 CHD_EXPORT const chd_header *chd_get_header(chd_file *chd)
2195 /* punt if NULL or invalid */
2196 if (chd == NULL || chd->cookie != COOKIE_VALUE)
2199 return &chd->header;
2202 /*-------------------------------------------------
2203 chd_read_header - read CHD header data
2204 from file into the pointed struct
2205 -------------------------------------------------*/
2206 CHD_EXPORT chd_error chd_read_header(const char *filename, chd_header *header)
2208 chd_error err = CHDERR_NONE;
2212 if (filename == NULL || header == NULL)
2213 EARLY_EXIT(err = CHDERR_INVALID_PARAMETER);
2216 chd.file = core_stdio_fopen(filename);
2217 if (chd.file == NULL)
2218 EARLY_EXIT(err = CHDERR_FILE_NOT_FOUND);
2220 /* attempt to read the header */
2221 err = header_read(&chd, header);
2222 if (err != CHDERR_NONE)
2225 /* validate the header */
2226 err = header_validate(header);
2227 if (err != CHDERR_NONE)
2231 if (chd.file != NULL)
2232 core_fclose(chd.file);
2237 /***************************************************************************
2238 CORE DATA READ/WRITE
2239 ***************************************************************************/
2241 /*-------------------------------------------------
2242 chd_read - read a single hunk from the CHD
2244 -------------------------------------------------*/
2246 CHD_EXPORT chd_error chd_read(chd_file *chd, UINT32 hunknum, void *buffer)
2248 /* punt if NULL or invalid */
2249 if (chd == NULL || chd->cookie != COOKIE_VALUE)
2250 return CHDERR_INVALID_PARAMETER;
2252 /* if we're past the end, fail */
2253 if (hunknum >= chd->header.totalhunks)
2254 return CHDERR_HUNK_OUT_OF_RANGE;
2256 /* perform the read */
2257 return hunk_read_into_memory(chd, hunknum, (UINT8 *)buffer);
2260 /***************************************************************************
2262 ***************************************************************************/
2264 /*-------------------------------------------------
2265 chd_get_metadata - get the indexed metadata
2267 -------------------------------------------------*/
2269 CHD_EXPORT chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 searchindex, void *output, UINT32 outputlen, UINT32 *resultlen, UINT32 *resulttag, UINT8 *resultflags)
2271 metadata_entry metaentry;
2275 /* if we didn't find it, just return */
2276 err = metadata_find_entry(chd, searchtag, searchindex, &metaentry);
2277 if (err != CHDERR_NONE)
2279 /* unless we're an old version and they are requesting hard disk metadata */
2280 if (chd->header.version < 3 && (searchtag == HARD_DISK_METADATA_TAG || searchtag == CHDMETATAG_WILDCARD) && searchindex == 0)
2282 char faux_metadata[256];
2285 /* fill in the faux metadata */
2286 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);
2287 faux_length = (UINT32)strlen(faux_metadata) + 1;
2289 /* copy the metadata itself */
2290 memcpy(output, faux_metadata, MIN(outputlen, faux_length));
2292 /* return the length of the data and the tag */
2293 if (resultlen != NULL)
2294 *resultlen = faux_length;
2295 if (resulttag != NULL)
2296 *resulttag = HARD_DISK_METADATA_TAG;
2302 /* read the metadata */
2303 outputlen = MIN(outputlen, metaentry.length);
2304 core_fseek(chd->file, metaentry.offset + METADATA_HEADER_SIZE, SEEK_SET);
2305 count = core_fread(chd->file, output, outputlen);
2306 if (count != outputlen)
2307 return CHDERR_READ_ERROR;
2309 /* return the length of the data and the tag */
2310 if (resultlen != NULL)
2311 *resultlen = metaentry.length;
2312 if (resulttag != NULL)
2313 *resulttag = metaentry.metatag;
2314 if (resultflags != NULL)
2315 *resultflags = metaentry.flags;
2319 /***************************************************************************
2321 ***************************************************************************/
2323 /*-------------------------------------------------
2324 chd_codec_config - set internal codec
2326 -------------------------------------------------*/
2328 CHD_EXPORT chd_error chd_codec_config(chd_file *chd, int param, void *config)
2330 return CHDERR_INVALID_PARAMETER;
2333 /*-------------------------------------------------
2334 chd_get_codec_name - get the name of a
2336 -------------------------------------------------*/
2338 CHD_EXPORT const char *chd_get_codec_name(UINT32 codec)
2343 /***************************************************************************
2344 INTERNAL HEADER OPERATIONS
2345 ***************************************************************************/
2347 /*-------------------------------------------------
2348 header_validate - check the validity of a
2350 -------------------------------------------------*/
2352 static chd_error header_validate(const chd_header *header)
2356 /* require a valid version */
2357 if (header->version == 0 || header->version > CHD_HEADER_VERSION)
2358 return CHDERR_UNSUPPORTED_VERSION;
2360 /* require a valid length */
2361 if ((header->version == 1 && header->length != CHD_V1_HEADER_SIZE) ||
2362 (header->version == 2 && header->length != CHD_V2_HEADER_SIZE) ||
2363 (header->version == 3 && header->length != CHD_V3_HEADER_SIZE) ||
2364 (header->version == 4 && header->length != CHD_V4_HEADER_SIZE) ||
2365 (header->version == 5 && header->length != CHD_V5_HEADER_SIZE))
2366 return CHDERR_INVALID_PARAMETER;
2368 /* Do not validate v5 header */
2369 if (header->version <= 4)
2371 /* require valid flags */
2372 if (header->flags & CHDFLAGS_UNDEFINED)
2373 return CHDERR_INVALID_PARAMETER;
2375 /* require a supported compression mechanism */
2376 for (intfnum = 0; intfnum < ARRAY_LENGTH(codec_interfaces); intfnum++)
2377 if (codec_interfaces[intfnum].compression == header->compression[0])
2380 if (intfnum == ARRAY_LENGTH(codec_interfaces))
2381 return CHDERR_INVALID_PARAMETER;
2383 /* require a valid hunksize */
2384 if (header->hunkbytes == 0 || header->hunkbytes >= 65536 * 256)
2385 return CHDERR_INVALID_PARAMETER;
2387 /* require a valid hunk count */
2388 if (header->totalhunks == 0)
2389 return CHDERR_INVALID_PARAMETER;
2391 /* require a valid MD5 and/or SHA1 if we're using a parent */
2392 if ((header->flags & CHDFLAGS_HAS_PARENT) && memcmp(header->parentmd5, nullmd5, sizeof(nullmd5)) == 0 && memcmp(header->parentsha1, nullsha1, sizeof(nullsha1)) == 0)
2393 return CHDERR_INVALID_PARAMETER;
2395 /* if we're V3 or later, the obsolete fields must be 0 */
2396 if (header->version >= 3 &&
2397 (header->obsolete_cylinders != 0 || header->obsolete_sectors != 0 ||
2398 header->obsolete_heads != 0 || header->obsolete_hunksize != 0))
2399 return CHDERR_INVALID_PARAMETER;
2401 /* if we're pre-V3, the obsolete fields must NOT be 0 */
2402 if (header->version < 3 &&
2403 (header->obsolete_cylinders == 0 || header->obsolete_sectors == 0 ||
2404 header->obsolete_heads == 0 || header->obsolete_hunksize == 0))
2405 return CHDERR_INVALID_PARAMETER;
2411 /*-------------------------------------------------
2412 header_guess_unitbytes - for older CHD formats,
2413 guess at the bytes/unit based on metadata
2414 -------------------------------------------------*/
2416 static UINT32 header_guess_unitbytes(chd_file *chd)
2418 /* look for hard disk metadata; if found, then the unit size == sector size */
2421 if (chd_get_metadata(chd, HARD_DISK_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE &&
2422 sscanf(metadata, HARD_DISK_METADATA_FORMAT, &i0, &i1, &i2, &i3) == 4)
2425 /* look for CD-ROM metadata; if found, then the unit size == CD frame size */
2426 if (chd_get_metadata(chd, CDROM_OLD_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
2427 chd_get_metadata(chd, CDROM_TRACK_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
2428 chd_get_metadata(chd, CDROM_TRACK_METADATA2_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
2429 chd_get_metadata(chd, GDROM_OLD_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
2430 chd_get_metadata(chd, GDROM_TRACK_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE)
2431 return CD_FRAME_SIZE;
2433 /* otherwise, just map 1:1 with the hunk size */
2434 return chd->header.hunkbytes;
2437 /*-------------------------------------------------
2438 header_read - read a CHD header into the
2439 internal data structure
2440 -------------------------------------------------*/
2442 static chd_error header_read(chd_file *chd, chd_header *header)
2444 UINT8 rawheader[CHD_MAX_HEADER_SIZE];
2449 return CHDERR_INVALID_PARAMETER;
2451 /* punt if invalid file */
2452 if (chd->file == NULL)
2453 return CHDERR_INVALID_FILE;
2456 core_fseek(chd->file, 0, SEEK_SET);
2457 count = core_fread(chd->file, rawheader, sizeof(rawheader));
2458 if (count != sizeof(rawheader))
2459 return CHDERR_READ_ERROR;
2461 /* verify the tag */
2462 if (strncmp((char *)rawheader, "MComprHD", 8) != 0)
2463 return CHDERR_INVALID_DATA;
2465 /* extract the direct data */
2466 memset(header, 0, sizeof(*header));
2467 header->length = get_bigendian_uint32(&rawheader[8]);
2468 header->version = get_bigendian_uint32(&rawheader[12]);
2470 /* make sure it's a version we understand */
2471 if (header->version == 0 || header->version > CHD_HEADER_VERSION)
2472 return CHDERR_UNSUPPORTED_VERSION;
2474 /* make sure the length is expected */
2475 if ((header->version == 1 && header->length != CHD_V1_HEADER_SIZE) ||
2476 (header->version == 2 && header->length != CHD_V2_HEADER_SIZE) ||
2477 (header->version == 3 && header->length != CHD_V3_HEADER_SIZE) ||
2478 (header->version == 4 && header->length != CHD_V4_HEADER_SIZE) ||
2479 (header->version == 5 && header->length != CHD_V5_HEADER_SIZE))
2481 return CHDERR_INVALID_DATA;
2483 /* extract the common data */
2484 header->flags = get_bigendian_uint32(&rawheader[16]);
2485 header->compression[0] = get_bigendian_uint32(&rawheader[20]);
2486 header->compression[1] = CHD_CODEC_NONE;
2487 header->compression[2] = CHD_CODEC_NONE;
2488 header->compression[3] = CHD_CODEC_NONE;
2490 /* extract the V1/V2-specific data */
2491 if (header->version < 3)
2493 int seclen = (header->version == 1) ? CHD_V1_SECTOR_SIZE : get_bigendian_uint32(&rawheader[76]);
2494 header->obsolete_hunksize = get_bigendian_uint32(&rawheader[24]);
2495 header->totalhunks = get_bigendian_uint32(&rawheader[28]);
2496 header->obsolete_cylinders = get_bigendian_uint32(&rawheader[32]);
2497 header->obsolete_heads = get_bigendian_uint32(&rawheader[36]);
2498 header->obsolete_sectors = get_bigendian_uint32(&rawheader[40]);
2499 memcpy(header->md5, &rawheader[44], CHD_MD5_BYTES);
2500 memcpy(header->parentmd5, &rawheader[60], CHD_MD5_BYTES);
2501 header->logicalbytes = (UINT64)header->obsolete_cylinders * (UINT64)header->obsolete_heads * (UINT64)header->obsolete_sectors * (UINT64)seclen;
2502 header->hunkbytes = seclen * header->obsolete_hunksize;
2503 header->unitbytes = header_guess_unitbytes(chd);
2504 if (header->unitbytes == 0)
2505 return CHDERR_INVALID_DATA;
2506 header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
2507 header->metaoffset = 0;
2510 /* extract the V3-specific data */
2511 else if (header->version == 3)
2513 header->totalhunks = get_bigendian_uint32(&rawheader[24]);
2514 header->logicalbytes = get_bigendian_uint64(&rawheader[28]);
2515 header->metaoffset = get_bigendian_uint64(&rawheader[36]);
2516 memcpy(header->md5, &rawheader[44], CHD_MD5_BYTES);
2517 memcpy(header->parentmd5, &rawheader[60], CHD_MD5_BYTES);
2518 header->hunkbytes = get_bigendian_uint32(&rawheader[76]);
2519 header->unitbytes = header_guess_unitbytes(chd);
2520 if (header->unitbytes == 0)
2521 return CHDERR_INVALID_DATA;
2522 header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
2523 memcpy(header->sha1, &rawheader[80], CHD_SHA1_BYTES);
2524 memcpy(header->parentsha1, &rawheader[100], CHD_SHA1_BYTES);
2527 /* extract the V4-specific data */
2528 else if (header->version == 4)
2530 header->totalhunks = get_bigendian_uint32(&rawheader[24]);
2531 header->logicalbytes = get_bigendian_uint64(&rawheader[28]);
2532 header->metaoffset = get_bigendian_uint64(&rawheader[36]);
2533 header->hunkbytes = get_bigendian_uint32(&rawheader[44]);
2534 header->unitbytes = header_guess_unitbytes(chd);
2535 if (header->unitbytes == 0)
2536 return CHDERR_INVALID_DATA;
2537 header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
2538 memcpy(header->sha1, &rawheader[48], CHD_SHA1_BYTES);
2539 memcpy(header->parentsha1, &rawheader[68], CHD_SHA1_BYTES);
2540 memcpy(header->rawsha1, &rawheader[88], CHD_SHA1_BYTES);
2543 /* extract the V5-specific data */
2544 else if (header->version == 5)
2547 header->compression[0] = get_bigendian_uint32(&rawheader[16]);
2548 header->compression[1] = get_bigendian_uint32(&rawheader[20]);
2549 header->compression[2] = get_bigendian_uint32(&rawheader[24]);
2550 header->compression[3] = get_bigendian_uint32(&rawheader[28]);
2551 header->logicalbytes = get_bigendian_uint64(&rawheader[32]);
2552 header->mapoffset = get_bigendian_uint64(&rawheader[40]);
2553 header->metaoffset = get_bigendian_uint64(&rawheader[48]);
2554 header->hunkbytes = get_bigendian_uint32(&rawheader[56]);
2555 if (header->hunkbytes == 0)
2556 return CHDERR_INVALID_DATA;
2557 header->hunkcount = (header->logicalbytes + header->hunkbytes - 1) / header->hunkbytes;
2558 header->unitbytes = get_bigendian_uint32(&rawheader[60]);
2559 if (header->unitbytes == 0)
2560 return CHDERR_INVALID_DATA;
2561 header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
2562 memcpy(header->sha1, &rawheader[84], CHD_SHA1_BYTES);
2563 memcpy(header->parentsha1, &rawheader[104], CHD_SHA1_BYTES);
2564 memcpy(header->rawsha1, &rawheader[64], CHD_SHA1_BYTES);
2566 /* determine properties of map entries */
2567 header->mapentrybytes = chd_compressed(header) ? 12 : 4;
2570 header->totalhunks = header->hunkcount;
2573 /* Unknown version */
2579 /* guess it worked */
2583 /***************************************************************************
2584 INTERNAL HUNK READ/WRITE
2585 ***************************************************************************/
2587 /*-------------------------------------------------
2588 hunk_read_compressed - read a compressed
2590 -------------------------------------------------*/
2592 static UINT8* hunk_read_compressed(chd_file *chd, UINT64 offset, size_t size)
2599 if (chd->file_cache != NULL)
2601 return chd->file_cache + offset;
2605 core_fseek(chd->file, offset, SEEK_SET);
2606 bytes = core_fread(chd->file, chd->compressed, size);
2609 return chd->compressed;
2613 /*-------------------------------------------------
2614 hunk_read_uncompressed - read an uncompressed
2616 -------------------------------------------------*/
2618 static chd_error hunk_read_uncompressed(chd_file *chd, UINT64 offset, size_t size, UINT8 *dest)
2625 if (chd->file_cache != NULL)
2627 memcpy(dest, chd->file_cache + offset, size);
2631 core_fseek(chd->file, offset, SEEK_SET);
2632 bytes = core_fread(chd->file, dest, size);
2634 return CHDERR_READ_ERROR;
2639 #ifdef NEED_CACHE_HUNK
2640 /*-------------------------------------------------
2641 hunk_read_into_cache - read a hunk into
2642 the CHD's hunk cache
2643 -------------------------------------------------*/
2645 static chd_error hunk_read_into_cache(chd_file *chd, UINT32 hunknum)
2650 if (hunknum > chd->maxhunk)
2651 chd->maxhunk = hunknum;
2653 /* if we're already in the cache, we're done */
2654 if (chd->cachehunk == hunknum)
2656 chd->cachehunk = ~0;
2658 /* otherwise, read the data */
2659 err = hunk_read_into_memory(chd, hunknum, chd->cache);
2660 if (err != CHDERR_NONE)
2663 /* mark the hunk successfully cached in */
2664 chd->cachehunk = hunknum;
2669 /*-------------------------------------------------
2670 hunk_read_into_memory - read a hunk into
2671 memory at the given location
2672 -------------------------------------------------*/
2674 static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *dest)
2678 /* punt if no file */
2679 if (chd->file == NULL)
2680 return CHDERR_INVALID_FILE;
2682 /* return an error if out of range */
2683 if (hunknum >= chd->header.totalhunks)
2684 return CHDERR_HUNK_OUT_OF_RANGE;
2687 return CHDERR_INVALID_PARAMETER;
2689 if (chd->header.version < 5)
2691 map_entry *entry = &chd->map[hunknum];
2693 UINT8* compressed_bytes;
2695 /* switch off the entry type */
2696 switch (entry->flags & MAP_ENTRY_FLAG_TYPE_MASK)
2698 /* compressed data */
2699 case V34_MAP_ENTRY_TYPE_COMPRESSED:
2703 /* read it into the decompression buffer */
2704 compressed_bytes = hunk_read_compressed(chd, entry->offset, entry->length);
2705 if (compressed_bytes == NULL)
2707 return CHDERR_READ_ERROR;
2710 /* now decompress using the codec */
2712 codec = &chd->zlib_codec_data;
2713 if (chd->codecintf[0]->decompress != NULL)
2714 err = (*chd->codecintf[0]->decompress)(codec, compressed_bytes, entry->length, dest, chd->header.hunkbytes);
2715 if (err != CHDERR_NONE)
2720 /* uncompressed data */
2721 case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
2722 err = hunk_read_uncompressed(chd, entry->offset, chd->header.hunkbytes, dest);
2723 if (err != CHDERR_NONE)
2727 /* mini-compressed data */
2728 case V34_MAP_ENTRY_TYPE_MINI:
2729 put_bigendian_uint64(&dest[0], entry->offset);
2730 for (bytes = 8; bytes < chd->header.hunkbytes; bytes++)
2731 dest[bytes] = dest[bytes - 8];
2734 /* self-referenced data */
2735 case V34_MAP_ENTRY_TYPE_SELF_HUNK:
2736 #ifdef NEED_CACHE_HUNK
2737 if (chd->cachehunk == entry->offset && dest == chd->cache)
2740 return hunk_read_into_memory(chd, entry->offset, dest);
2742 /* parent-referenced data */
2743 case V34_MAP_ENTRY_TYPE_PARENT_HUNK:
2744 err = hunk_read_into_memory(chd->parent, entry->offset, dest);
2745 if (err != CHDERR_NONE)
2754 /* get a pointer to the map entry */
2757 #ifdef VERIFY_BLOCK_CRC
2760 uint8_t *rawmap = &chd->header.rawmap[chd->header.mapentrybytes * hunknum];
2761 UINT8* compressed_bytes;
2763 /* uncompressed case */
2764 if (!chd_compressed(&chd->header))
2766 blockoffs = (uint64_t)get_bigendian_uint32(rawmap) * (uint64_t)chd->header.hunkbytes;
2767 if (blockoffs != 0) {
2768 core_fseek(chd->file, blockoffs, SEEK_SET);
2769 int result = core_fread(chd->file, dest, chd->header.hunkbytes);
2771 else if (m_parent_missing)
2772 throw CHDERR_REQUIRES_PARENT; */
2773 } else if (chd->parent) {
2774 err = hunk_read_into_memory(chd->parent, hunknum, dest);
2775 if (err != CHDERR_NONE)
2778 memset(dest, 0, chd->header.hunkbytes);
2784 /* compressed case */
2785 blocklen = get_bigendian_uint24(&rawmap[1]);
2786 blockoffs = get_bigendian_uint48(&rawmap[4]);
2787 #ifdef VERIFY_BLOCK_CRC
2788 blockcrc = get_bigendian_uint16(&rawmap[10]);
2793 case COMPRESSION_TYPE_0:
2794 case COMPRESSION_TYPE_1:
2795 case COMPRESSION_TYPE_2:
2796 case COMPRESSION_TYPE_3:
2797 compressed_bytes = hunk_read_compressed(chd, blockoffs, blocklen);
2798 if (compressed_bytes == NULL)
2799 return CHDERR_READ_ERROR;
2800 switch (chd->codecintf[rawmap[0]]->compression)
2802 case CHD_CODEC_ZLIB:
2803 codec = &chd->zlib_codec_data;
2806 case CHD_CODEC_LZMA:
2807 codec = &chd->lzma_codec_data;
2810 case CHD_CODEC_HUFFMAN:
2811 codec = &chd->huff_codec_data;
2814 case CHD_CODEC_FLAC:
2815 codec = &chd->flac_codec_data;
2818 case CHD_CODEC_ZSTD:
2819 codec = &chd->zstd_codec_data;
2822 case CHD_CODEC_CD_ZLIB:
2823 codec = &chd->cdzl_codec_data;
2826 case CHD_CODEC_CD_LZMA:
2827 codec = &chd->cdlz_codec_data;
2830 case CHD_CODEC_CD_FLAC:
2831 codec = &chd->cdfl_codec_data;
2834 case CHD_CODEC_CD_ZSTD:
2835 codec = &chd->cdzs_codec_data;
2839 return CHDERR_CODEC_ERROR;
2840 err = chd->codecintf[rawmap[0]]->decompress(codec, compressed_bytes, blocklen, dest, chd->header.hunkbytes);
2841 if (err != CHDERR_NONE)
2843 #ifdef VERIFY_BLOCK_CRC
2844 if (crc16(dest, chd->header.hunkbytes) != blockcrc)
2845 return CHDERR_DECOMPRESSION_ERROR;
2849 case COMPRESSION_NONE:
2850 err = hunk_read_uncompressed(chd, blockoffs, blocklen, dest);
2851 if (err != CHDERR_NONE)
2853 #ifdef VERIFY_BLOCK_CRC
2854 if (crc16(dest, chd->header.hunkbytes) != blockcrc)
2855 return CHDERR_DECOMPRESSION_ERROR;
2859 case COMPRESSION_SELF:
2860 return hunk_read_into_memory(chd, blockoffs, dest);
2862 case COMPRESSION_PARENT:
2863 if (chd->parent == NULL)
2864 return CHDERR_REQUIRES_PARENT;
2865 UINT8 units_in_hunk = chd->header.hunkbytes / chd->header.unitbytes;
2867 /* blockoffs is aligned to units_in_hunk */
2868 if (blockoffs % units_in_hunk == 0) {
2869 return hunk_read_into_memory(chd->parent, blockoffs / units_in_hunk, dest);
2870 /* blockoffs is not aligned to units_in_hunk */
2872 UINT32 unit_in_hunk = blockoffs % units_in_hunk;
2873 UINT8 *buf = malloc(chd->header.hunkbytes);
2874 /* Read first half of hunk which contains blockoffs */
2875 err = hunk_read_into_memory(chd->parent, blockoffs / units_in_hunk, buf);
2876 if (err != CHDERR_NONE) {
2880 memcpy(dest, buf + unit_in_hunk * chd->header.unitbytes, (units_in_hunk - unit_in_hunk) * chd->header.unitbytes);
2881 /* Read second half of hunk which contains blockoffs */
2882 err = hunk_read_into_memory(chd->parent, (blockoffs / units_in_hunk) + 1, buf);
2883 if (err != CHDERR_NONE) {
2887 memcpy(dest + (units_in_hunk - unit_in_hunk) * chd->header.unitbytes, buf, unit_in_hunk * chd->header.unitbytes);
2894 /* We should not reach this code */
2895 return CHDERR_DECOMPRESSION_ERROR;
2898 /***************************************************************************
2900 ***************************************************************************/
2902 /*-------------------------------------------------
2903 map_read - read the initial sector map
2904 -------------------------------------------------*/
2906 static chd_error map_read(chd_file *chd)
2908 UINT32 entrysize = (chd->header.version < 3) ? OLD_MAP_ENTRY_SIZE : MAP_ENTRY_SIZE;
2909 UINT8 raw_map_entries[MAP_STACK_ENTRIES * MAP_ENTRY_SIZE];
2910 UINT64 fileoffset, maxoffset = 0;
2911 UINT8 cookie[MAP_ENTRY_SIZE];
2916 /* first allocate memory */
2917 chd->map = (map_entry *)malloc(sizeof(chd->map[0]) * chd->header.totalhunks);
2919 return CHDERR_OUT_OF_MEMORY;
2921 /* read the map entries in in chunks and extract to the map list */
2922 fileoffset = chd->header.length;
2923 for (i = 0; i < chd->header.totalhunks; i += MAP_STACK_ENTRIES)
2925 /* compute how many entries this time */
2926 int entries = chd->header.totalhunks - i, j;
2927 if (entries > MAP_STACK_ENTRIES)
2928 entries = MAP_STACK_ENTRIES;
2930 /* read that many */
2931 core_fseek(chd->file, fileoffset, SEEK_SET);
2932 count = core_fread(chd->file, raw_map_entries, entries * entrysize);
2933 if (count != entries * entrysize)
2935 err = CHDERR_READ_ERROR;
2938 fileoffset += entries * entrysize;
2940 /* process that many */
2941 if (entrysize == MAP_ENTRY_SIZE)
2943 for (j = 0; j < entries; j++)
2944 map_extract(&raw_map_entries[j * MAP_ENTRY_SIZE], &chd->map[i + j]);
2948 for (j = 0; j < entries; j++)
2949 map_extract_old(&raw_map_entries[j * OLD_MAP_ENTRY_SIZE], &chd->map[i + j], chd->header.hunkbytes);
2952 /* track the maximum offset */
2953 for (j = 0; j < entries; j++)
2954 if ((chd->map[i + j].flags & MAP_ENTRY_FLAG_TYPE_MASK) == V34_MAP_ENTRY_TYPE_COMPRESSED ||
2955 (chd->map[i + j].flags & MAP_ENTRY_FLAG_TYPE_MASK) == V34_MAP_ENTRY_TYPE_UNCOMPRESSED)
2956 maxoffset = MAX(maxoffset, chd->map[i + j].offset + chd->map[i + j].length);
2959 /* verify the cookie */
2960 core_fseek(chd->file, fileoffset, SEEK_SET);
2961 count = core_fread(chd->file, &cookie, entrysize);
2962 if (count != entrysize || memcmp(&cookie, END_OF_LIST_COOKIE, entrysize))
2964 err = CHDERR_INVALID_FILE;
2968 /* verify the length */
2969 if (maxoffset > core_fsize(chd->file))
2971 err = CHDERR_INVALID_FILE;
2983 /***************************************************************************
2984 INTERNAL METADATA ACCESS
2985 ***************************************************************************/
2987 /*-------------------------------------------------
2988 metadata_find_entry - find a metadata entry
2989 -------------------------------------------------*/
2991 static chd_error metadata_find_entry(chd_file *chd, UINT32 metatag, UINT32 metaindex, metadata_entry *metaentry)
2993 /* start at the beginning */
2994 metaentry->offset = chd->header.metaoffset;
2995 metaentry->prev = 0;
2997 /* loop until we run out of options */
2998 while (metaentry->offset != 0)
3000 UINT8 raw_meta_header[METADATA_HEADER_SIZE];
3003 /* read the raw header */
3004 core_fseek(chd->file, metaentry->offset, SEEK_SET);
3005 count = core_fread(chd->file, raw_meta_header, sizeof(raw_meta_header));
3006 if (count != sizeof(raw_meta_header))
3009 /* extract the data */
3010 metaentry->metatag = get_bigendian_uint32(&raw_meta_header[0]);
3011 metaentry->length = get_bigendian_uint32(&raw_meta_header[4]);
3012 metaentry->next = get_bigendian_uint64(&raw_meta_header[8]);
3014 /* flags are encoded in the high byte of length */
3015 metaentry->flags = metaentry->length >> 24;
3016 metaentry->length &= 0x00ffffff;
3018 /* if we got a match, proceed */
3019 if (metatag == CHDMETATAG_WILDCARD || metaentry->metatag == metatag)
3020 if (metaindex-- == 0)
3023 /* no match, fetch the next link */
3024 metaentry->prev = metaentry->offset;
3025 metaentry->offset = metaentry->next;
3028 /* if we get here, we didn't find it */
3029 return CHDERR_METADATA_NOT_FOUND;
3032 /***************************************************************************
3033 ZLIB COMPRESSION CODEC
3034 ***************************************************************************/
3036 /*-------------------------------------------------
3037 zlib_codec_init - initialize the ZLIB codec
3038 -------------------------------------------------*/
3040 static chd_error zlib_codec_init(void *codec, uint32_t hunkbytes)
3044 zlib_codec_data *data = (zlib_codec_data*)codec;
3046 /* clear the buffers */
3047 memset(data, 0, sizeof(zlib_codec_data));
3049 /* init the inflater first */
3050 data->inflater.next_in = (Bytef *)data; /* bogus, but that's ok */
3051 data->inflater.avail_in = 0;
3052 data->inflater.zalloc = zlib_fast_alloc;
3053 data->inflater.zfree = zlib_fast_free;
3054 data->inflater.opaque = &data->allocator;
3055 zerr = inflateInit2(&data->inflater, -MAX_WBITS);
3057 /* convert errors */
3058 if (zerr == Z_MEM_ERROR)
3059 err = CHDERR_OUT_OF_MEMORY;
3060 else if (zerr != Z_OK)
3061 err = CHDERR_CODEC_ERROR;
3068 /*-------------------------------------------------
3069 zlib_codec_free - free data for the ZLIB
3071 -------------------------------------------------*/
3073 static void zlib_codec_free(void *codec)
3075 zlib_codec_data *data = (zlib_codec_data *)codec;
3077 /* deinit the streams */
3080 inflateEnd(&data->inflater);
3082 /* free our fast memory */
3083 zlib_allocator_free(&data->allocator);
3087 /*-------------------------------------------------
3088 zlib_codec_decompress - decompress data using
3090 -------------------------------------------------*/
3092 static chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
3094 zlib_codec_data *data = (zlib_codec_data *)codec;
3097 /* reset the decompressor */
3098 data->inflater.next_in = (Bytef *)src;
3099 data->inflater.avail_in = complen;
3100 data->inflater.total_in = 0;
3101 data->inflater.next_out = (Bytef *)dest;
3102 data->inflater.avail_out = destlen;
3103 data->inflater.total_out = 0;
3104 zerr = inflateReset(&data->inflater);
3106 return CHDERR_DECOMPRESSION_ERROR;
3109 zerr = inflate(&data->inflater, Z_FINISH);
3110 if (data->inflater.total_out != destlen)
3111 return CHDERR_DECOMPRESSION_ERROR;
3116 /*-------------------------------------------------
3117 zlib_fast_alloc - fast malloc for ZLIB, which
3118 allocates and frees memory frequently
3119 -------------------------------------------------*/
3121 /* Huge alignment values for possible SIMD optimization by compiler (NEON, SSE, AVX) */
3122 #define ZLIB_MIN_ALIGNMENT_BITS 512
3123 #define ZLIB_MIN_ALIGNMENT_BYTES (ZLIB_MIN_ALIGNMENT_BITS / 8)
3125 static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
3127 zlib_allocator *alloc = (zlib_allocator *)opaque;
3128 uintptr_t paddr = 0;
3132 /* compute the size, rounding to the nearest 1k */
3133 size = (size * items + 0x3ff) & ~0x3ff;
3135 /* reuse a hunk if we can */
3136 for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
3138 ptr = alloc->allocptr[i];
3139 if (ptr && size == *ptr)
3141 /* set the low bit of the size so we don't match next time */
3144 /* return aligned block address */
3145 return (voidpf)(alloc->allocptr2[i]);
3149 /* alloc a new one */
3150 ptr = (UINT32 *)malloc(size + sizeof(UINT32) + ZLIB_MIN_ALIGNMENT_BYTES);
3154 /* put it into the list */
3155 for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
3156 if (!alloc->allocptr[i])
3158 alloc->allocptr[i] = ptr;
3159 paddr = (((uintptr_t)ptr) + sizeof(UINT32) + (ZLIB_MIN_ALIGNMENT_BYTES-1)) & (~(ZLIB_MIN_ALIGNMENT_BYTES-1));
3160 alloc->allocptr2[i] = (uint32_t*)paddr;
3164 /* set the low bit of the size so we don't match next time */
3167 /* return aligned block address */
3168 return (voidpf)paddr;
3171 /*-------------------------------------------------
3172 zlib_fast_free - fast free for ZLIB, which
3173 allocates and frees memory frequently
3174 -------------------------------------------------*/
3176 static void zlib_fast_free(voidpf opaque, voidpf address)
3178 zlib_allocator *alloc = (zlib_allocator *)opaque;
3179 UINT32 *ptr = (UINT32 *)address;
3183 for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
3184 if (ptr == alloc->allocptr2[i])
3186 /* clear the low bit of the size to allow matches */
3187 *(alloc->allocptr[i]) &= ~1;
3192 /*-------------------------------------------------
3194 -------------------------------------------------*/
3195 static void zlib_allocator_free(voidpf opaque)
3197 zlib_allocator *alloc = (zlib_allocator *)opaque;
3200 for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
3201 if (alloc->allocptr[i])
3202 free(alloc->allocptr[i]);
3205 /*-------------------------------------------------
3206 core_stdio_fopen - core_file wrapper over fopen
3207 -------------------------------------------------*/
3208 static core_file *core_stdio_fopen(char const *path) {
3209 core_file *file = malloc(sizeof(core_file));
3212 if (!(file->argp = fopen(path, "rb"))) {
3216 file->fsize = core_stdio_fsize;
3217 file->fread = core_stdio_fread;
3218 file->fclose = core_stdio_fclose;
3219 file->fseek = core_stdio_fseek;
3223 /*-------------------------------------------------
3224 core_stdio_fsize - core_file function for
3225 getting file size with stdio
3226 -------------------------------------------------*/
3227 static UINT64 core_stdio_fsize(core_file *file) {
3228 #if defined USE_LIBRETRO_VFS
3229 #define core_stdio_fseek_impl fseek
3230 #define core_stdio_ftell_impl ftell
3231 #elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WIN64__)
3232 #define core_stdio_fseek_impl _fseeki64
3233 #define core_stdio_ftell_impl _ftelli64
3234 #elif defined(_LARGEFILE_SOURCE) && defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
3235 #define core_stdio_fseek_impl fseeko64
3236 #define core_stdio_ftell_impl ftello64
3237 #elif defined(__PS3__) && !defined(__PSL1GHT__) || defined(__SWITCH__) || defined(__vita__)
3238 #define core_stdio_fseek_impl(x,y,z) fseek(x,(off_t)y,z)
3239 #define core_stdio_ftell_impl(x) (off_t)ftell(x)
3241 #define core_stdio_fseek_impl fseeko
3242 #define core_stdio_ftell_impl ftello
3246 fp = (FILE*)file->argp;
3248 p = core_stdio_ftell_impl(fp);
3249 core_stdio_fseek_impl(fp, 0, SEEK_END);
3250 rv = core_stdio_ftell_impl(fp);
3251 core_stdio_fseek_impl(fp, p, SEEK_SET);
3255 /*-------------------------------------------------
3256 core_stdio_fread - core_file wrapper over fread
3257 -------------------------------------------------*/
3258 static size_t core_stdio_fread(void *ptr, size_t size, size_t nmemb, core_file *file) {
3259 return fread(ptr, size, nmemb, (FILE*)file->argp);
3262 /*-------------------------------------------------
3263 core_stdio_fclose - core_file wrapper over fclose
3264 -------------------------------------------------*/
3265 static int core_stdio_fclose(core_file *file) {
3266 int err = fclose((FILE*)file->argp);
3272 /*-------------------------------------------------
3273 core_stdio_fclose_nonowner - don't call fclose because
3274 we don't own the underlying file, but do free the
3275 core_file because libchdr did allocate that itself.
3276 -------------------------------------------------*/
3277 static int core_stdio_fclose_nonowner(core_file *file) {
3282 /*-------------------------------------------------
3283 core_stdio_fseek - core_file wrapper over fclose
3284 -------------------------------------------------*/
3285 static int core_stdio_fseek(core_file* file, INT64 offset, int whence) {
3286 return core_stdio_fseek_impl((FILE*)file->argp, offset, whence);