duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

libchdr_chd.c (102173B)


      1 /***************************************************************************
      2 
      3     chd.c
      4 
      5     MAME Compressed Hunks of Data file format
      6 
      7 ****************************************************************************
      8 
      9     Copyright Aaron Giles
     10     All rights reserved.
     11 
     12     Redistribution and use in source and binary forms, with or without
     13     modification, are permitted provided that the following conditions are
     14     met:
     15 
     16         * Redistributions of source code must retain the above copyright
     17           notice, this list of conditions and the following disclaimer.
     18         * Redistributions in binary form must reproduce the above copyright
     19           notice, this list of conditions and the following disclaimer in
     20           the documentation and/or other materials provided with the
     21           distribution.
     22         * Neither the name 'MAME' nor the names of its contributors may be
     23           used to endorse or promote products derived from this software
     24           without specific prior written permission.
     25 
     26     THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
     27     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     28     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     29     DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
     30     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     31     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     32     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     33     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     34     STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     35     IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36     POSSIBILITY OF SUCH DAMAGE.
     37 
     38 ***************************************************************************/
     39 
     40 #include <stddef.h>
     41 #include <stdio.h>
     42 #include <stdlib.h>
     43 #include <string.h>
     44 #include <time.h>
     45 #include <limits.h>
     46 
     47 #include <libchdr/chd.h>
     48 #include <libchdr/cdrom.h>
     49 #include <libchdr/flac.h>
     50 #include <libchdr/huffman.h>
     51 #include <zstd.h>
     52 
     53 #include "LzmaEnc.h"
     54 #include "LzmaDec.h"
     55 #if defined(__PS3__) || defined(__PSL1GHT__)
     56 #define __MACTYPES__
     57 #endif
     58 #include <zlib.h>
     59 
     60 #undef TRUE
     61 #undef FALSE
     62 #define TRUE 1
     63 #define FALSE 0
     64 
     65 #undef MAX
     66 #undef MIN
     67 #define MAX(x, y) (((x) > (y)) ? (x) : (y))
     68 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
     69 
     70 #define SHA1_DIGEST_SIZE 20
     71 
     72 /***************************************************************************
     73     DEBUGGING
     74 ***************************************************************************/
     75 
     76 #define PRINTF_MAX_HUNK				(0)
     77 
     78 /***************************************************************************
     79     CONSTANTS
     80 ***************************************************************************/
     81 
     82 #define MAP_STACK_ENTRIES			512			/* max number of entries to use on the stack */
     83 #define MAP_ENTRY_SIZE				16			/* V3 and later */
     84 #define OLD_MAP_ENTRY_SIZE			8			/* V1-V2 */
     85 #define METADATA_HEADER_SIZE		16			/* metadata header size */
     86 
     87 #define MAP_ENTRY_FLAG_TYPE_MASK	0x0f		/* what type of hunk */
     88 #define MAP_ENTRY_FLAG_NO_CRC		0x10		/* no CRC is present */
     89 
     90 #define CHD_V1_SECTOR_SIZE			512			/* size of a "sector" in the V1 header */
     91 
     92 #define COOKIE_VALUE				0xbaadf00d
     93 #define MAX_ZLIB_ALLOCS				64
     94 
     95 #define END_OF_LIST_COOKIE			"EndOfListCookie"
     96 
     97 #define NO_MATCH					(~0)
     98 
     99 #ifdef WANT_RAW_DATA_SECTOR
    100 static const uint8_t s_cd_sync_header[12] = { 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 };
    101 #endif
    102 
    103 /* V3-V4 entry types */
    104 enum
    105 {
    106 	V34_MAP_ENTRY_TYPE_INVALID = 0,             /* invalid type */
    107 	V34_MAP_ENTRY_TYPE_COMPRESSED = 1,          /* standard compression */
    108 	V34_MAP_ENTRY_TYPE_UNCOMPRESSED = 2,        /* uncompressed data */
    109 	V34_MAP_ENTRY_TYPE_MINI = 3,                /* mini: use offset as raw data */
    110 	V34_MAP_ENTRY_TYPE_SELF_HUNK = 4,           /* same as another hunk in this file */
    111 	V34_MAP_ENTRY_TYPE_PARENT_HUNK = 5,         /* same as a hunk in the parent file */
    112 	V34_MAP_ENTRY_TYPE_2ND_COMPRESSED = 6       /* compressed with secondary algorithm (usually FLAC CDDA) */
    113 };
    114 
    115 /* V5 compression types */
    116 enum
    117 {
    118 	/* codec #0
    119 	 * these types are live when running */
    120 	COMPRESSION_TYPE_0 = 0,
    121 	/* codec #1 */
    122 	COMPRESSION_TYPE_1 = 1,
    123 	/* codec #2 */
    124 	COMPRESSION_TYPE_2 = 2,
    125 	/* codec #3 */
    126 	COMPRESSION_TYPE_3 = 3,
    127 	/* no compression; implicit length = hunkbytes */
    128 	COMPRESSION_NONE = 4,
    129 	/* same as another block in this chd */
    130 	COMPRESSION_SELF = 5,
    131 	/* same as a hunk's worth of units in the parent chd */
    132 	COMPRESSION_PARENT = 6,
    133 
    134 	/* start of small RLE run (4-bit length)
    135 	 * these additional pseudo-types are used for compressed encodings: */
    136 	COMPRESSION_RLE_SMALL,
    137 	/* start of large RLE run (8-bit length) */
    138 	COMPRESSION_RLE_LARGE,
    139 	/* same as the last COMPRESSION_SELF block */
    140 	COMPRESSION_SELF_0,
    141 	/* same as the last COMPRESSION_SELF block + 1 */
    142 	COMPRESSION_SELF_1,
    143 	/* same block in the parent */
    144 	COMPRESSION_PARENT_SELF,
    145 	/* same as the last COMPRESSION_PARENT block */
    146 	COMPRESSION_PARENT_0,
    147 	/* same as the last COMPRESSION_PARENT block + 1 */
    148 	COMPRESSION_PARENT_1
    149 };
    150 
    151 /***************************************************************************
    152     MACROS
    153 ***************************************************************************/
    154 
    155 #define EARLY_EXIT(x)				do { (void)(x); goto cleanup; } while (0)
    156 
    157 /***************************************************************************
    158     TYPE DEFINITIONS
    159 ***************************************************************************/
    160 
    161 /* interface to a codec */
    162 typedef struct _codec_interface codec_interface;
    163 struct _codec_interface
    164 {
    165 	UINT32		compression;								/* type of compression */
    166 	const char *compname;									/* name of the algorithm */
    167 	UINT8		lossy;										/* is this a lossy algorithm? */
    168 	chd_error	(*init)(void *codec, UINT32 hunkbytes);		/* codec initialize */
    169 	void		(*free)(void *codec);						/* codec free */
    170 	chd_error	(*decompress)(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); /* decompress data */
    171 	chd_error	(*config)(void *codec, int param, void *config); /* configure */
    172 };
    173 
    174 /* a single map entry */
    175 typedef struct _map_entry map_entry;
    176 struct _map_entry
    177 {
    178 	UINT64					offset;			/* offset within the file of the data */
    179 	UINT32					crc;			/* 32-bit CRC of the data */
    180 	UINT32					length;			/* length of the data */
    181 	UINT8					flags;			/* misc flags */
    182 };
    183 
    184 /* a single metadata entry */
    185 typedef struct _metadata_entry metadata_entry;
    186 struct _metadata_entry
    187 {
    188 	UINT64					offset;			/* offset within the file of the header */
    189 	UINT64					next;			/* offset within the file of the next header */
    190 	UINT64					prev;			/* offset within the file of the previous header */
    191 	UINT32					length;			/* length of the metadata */
    192 	UINT32					metatag;		/* metadata tag */
    193 	UINT8					flags;			/* flag bits */
    194 };
    195 
    196 /* codec-private data for the ZLIB codec */
    197 
    198 typedef struct _zlib_allocator zlib_allocator;
    199 struct _zlib_allocator
    200 {
    201 	UINT32 *				allocptr[MAX_ZLIB_ALLOCS];
    202 	UINT32 *				allocptr2[MAX_ZLIB_ALLOCS];
    203 };
    204 
    205 typedef struct _zlib_codec_data zlib_codec_data;
    206 struct _zlib_codec_data
    207 {
    208 	z_stream				inflater;
    209 	zlib_allocator			allocator;
    210 };
    211 
    212 /* codec-private data for the LZMA codec */
    213 #define MAX_LZMA_ALLOCS 64
    214 
    215 typedef struct _lzma_allocator lzma_allocator;
    216 struct _lzma_allocator
    217 {
    218 	void *(*Alloc)(void *p, size_t size);
    219  	void (*Free)(void *p, void *address); /* address can be 0 */
    220 	void (*FreeSz)(void *p, void *address, size_t size); /* address can be 0 */
    221 	uint32_t*	allocptr[MAX_LZMA_ALLOCS];
    222 	uint32_t*	allocptr2[MAX_LZMA_ALLOCS];
    223 };
    224 
    225 typedef struct _lzma_codec_data lzma_codec_data;
    226 struct _lzma_codec_data
    227 {
    228 	CLzmaDec		decoder;
    229 	lzma_allocator	allocator;
    230 };
    231 
    232 typedef struct _huff_codec_data huff_codec_data;
    233 struct _huff_codec_data
    234 {
    235 	struct huffman_decoder* decoder;
    236 };
    237 
    238 typedef struct _zstd_codec_data zstd_codec_data;
    239 struct _zstd_codec_data
    240 {
    241 	ZSTD_DStream *dstream;
    242 };
    243 
    244 /* codec-private data for the CDZL codec */
    245 typedef struct _cdzl_codec_data cdzl_codec_data;
    246 struct _cdzl_codec_data {
    247 	/* internal state */
    248 	zlib_codec_data		base_decompressor;
    249 #ifdef WANT_SUBCODE
    250 	zlib_codec_data		subcode_decompressor;
    251 #endif
    252 	uint8_t*			buffer;
    253 };
    254 
    255 /* codec-private data for the CDLZ codec */
    256 typedef struct _cdlz_codec_data cdlz_codec_data;
    257 struct _cdlz_codec_data {
    258 	/* internal state */
    259 	lzma_codec_data		base_decompressor;
    260 #ifdef WANT_SUBCODE
    261 	zlib_codec_data		subcode_decompressor;
    262 #endif
    263 	uint8_t*			buffer;
    264 };
    265 
    266 /* codec-private data for the FLAC codec */
    267 typedef struct _flac_codec_data flac_codec_data;
    268 struct _flac_codec_data {
    269 	/* internal state */
    270 	int		native_endian;
    271 	flac_decoder	decoder;
    272 };
    273 
    274 /* codec-private data for the CDFL codec */
    275 typedef struct _cdfl_codec_data cdfl_codec_data;
    276 struct _cdfl_codec_data {
    277 	/* internal state */
    278 	int		swap_endian;
    279 	flac_decoder	decoder;
    280 #ifdef WANT_SUBCODE
    281 	zlib_codec_data		subcode_decompressor;
    282 #endif
    283 	uint8_t*	buffer;
    284 };
    285 
    286 typedef struct _cdzs_codec_data cdzs_codec_data;
    287 struct _cdzs_codec_data 
    288 {
    289 	zstd_codec_data base_decompressor;
    290 #ifdef WANT_SUBCODE
    291 	zstd_codec_data subcode_decompressor;
    292 #endif
    293 	uint8_t*				buffer;
    294 };
    295 
    296 /* internal representation of an open CHD file */
    297 struct _chd_file
    298 {
    299 	UINT32					cookie;			/* cookie, should equal COOKIE_VALUE */
    300 
    301 	core_file *				file;			/* handle to the open core file */
    302 	chd_header				header;			/* header, extracted from file */
    303 
    304 	chd_file *				parent;			/* pointer to parent file, or NULL */
    305 
    306 	map_entry *				map;			/* array of map entries */
    307 
    308 #ifdef NEED_CACHE_HUNK
    309 	UINT8 *					cache;			/* hunk cache pointer */
    310 	UINT32					cachehunk;		/* index of currently cached hunk */
    311 
    312 	UINT8 *					compare;		/* hunk compare pointer */
    313 	UINT32					comparehunk;	/* index of current compare data */
    314 #endif
    315 
    316 	UINT8 *					compressed;		/* pointer to buffer for compressed data */
    317 	const codec_interface *	codecintf[4];	/* interface to the codec */
    318 
    319 	zlib_codec_data			zlib_codec_data;		/* zlib codec data */
    320 	lzma_codec_data			lzma_codec_data;		/* lzma codec data */
    321 	huff_codec_data			huff_codec_data;		/* huff codec data */
    322 	flac_codec_data			flac_codec_data;		/* flac codec data */
    323 	zstd_codec_data			zstd_codec_data;		/* zstd codec data */
    324 	cdzl_codec_data			cdzl_codec_data;		/* cdzl codec data */
    325 	cdlz_codec_data			cdlz_codec_data;		/* cdlz codec data */
    326 	cdfl_codec_data			cdfl_codec_data;		/* cdfl codec data */
    327 	cdzs_codec_data			cdzs_codec_data;		/* cdzs codec data */
    328 
    329 #ifdef NEED_CACHE_HUNK
    330 	UINT32					maxhunk;		/* maximum hunk accessed */
    331 #endif
    332 
    333 	UINT8 *					file_cache;		/* cache of underlying file */
    334 };
    335 
    336 
    337 /***************************************************************************
    338     GLOBAL VARIABLES
    339 ***************************************************************************/
    340 
    341 static const UINT8 nullmd5[CHD_MD5_BYTES] = { 0 };
    342 static const UINT8 nullsha1[CHD_SHA1_BYTES] = { 0 };
    343 
    344 /***************************************************************************
    345     PROTOTYPES
    346 ***************************************************************************/
    347 
    348 /* core_file wrappers over stdio */
    349 static core_file *core_stdio_fopen(char const *path);
    350 static UINT64 core_stdio_fsize(core_file *file);
    351 static size_t core_stdio_fread(void *ptr, size_t size, size_t nmemb, core_file *file);
    352 static int core_stdio_fclose(core_file *file);
    353 static int core_stdio_fclose_nonowner(core_file *file); // alternate fclose used by chd_open_file
    354 static int core_stdio_fseek(core_file* file, INT64 offset, int whence);
    355 
    356 /* internal header operations */
    357 static chd_error header_validate(const chd_header *header);
    358 static chd_error header_read(chd_file *chd, chd_header *header);
    359 
    360 /* internal hunk read/write */
    361 #ifdef NEED_CACHE_HUNK
    362 static chd_error hunk_read_into_cache(chd_file *chd, UINT32 hunknum);
    363 #endif
    364 static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *dest);
    365 
    366 /* internal map access */
    367 static chd_error map_read(chd_file *chd);
    368 
    369 /* metadata management */
    370 static chd_error metadata_find_entry(chd_file *chd, UINT32 metatag, UINT32 metaindex, metadata_entry *metaentry);
    371 
    372 /* zlib compression codec */
    373 static chd_error zlib_codec_init(void *codec, uint32_t hunkbytes);
    374 static void zlib_codec_free(void *codec);
    375 static chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
    376 static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size);
    377 static void zlib_fast_free(voidpf opaque, voidpf address);
    378 static void zlib_allocator_free(voidpf opaque);
    379 
    380 /* lzma compression codec */
    381 static chd_error lzma_codec_init(void *codec, uint32_t hunkbytes);
    382 static void lzma_codec_free(void *codec);
    383 static chd_error lzma_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
    384 
    385 /* huff compression codec */
    386 static chd_error huff_codec_init(void *codec, uint32_t hunkbytes);
    387 static void huff_codec_free(void *codec);
    388 static chd_error huff_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
    389 
    390 /* flac compression codec */
    391 static chd_error flac_codec_init(void *codec, uint32_t hunkbytes);
    392 static void flac_codec_free(void *codec);
    393 static chd_error flac_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
    394 
    395 /* zstd compression codec */
    396 static chd_error zstd_codec_init(void *codec, uint32_t hunkbytes);
    397 static void zstd_codec_free(void *codec);
    398 static chd_error zstd_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
    399 
    400 
    401 /* cdzl compression codec */
    402 static chd_error cdzl_codec_init(void* codec, uint32_t hunkbytes);
    403 static void cdzl_codec_free(void* codec);
    404 static chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
    405 
    406 /* cdlz compression codec */
    407 static chd_error cdlz_codec_init(void* codec, uint32_t hunkbytes);
    408 static void cdlz_codec_free(void* codec);
    409 static chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
    410 
    411 /* cdfl compression codec */
    412 static chd_error cdfl_codec_init(void* codec, uint32_t hunkbytes);
    413 static void cdfl_codec_free(void* codec);
    414 static chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
    415 
    416 /* cdzs compression codec */
    417 static chd_error cdzs_codec_init(void *codec, uint32_t hunkbytes);
    418 static void cdzs_codec_free(void *codec);
    419 static chd_error cdzs_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
    420 
    421 /***************************************************************************
    422  *  LZMA ALLOCATOR HELPER
    423  ***************************************************************************
    424  */
    425 
    426 static void *lzma_fast_alloc(void *p, size_t size);
    427 static void lzma_fast_free(void *p, void *address);
    428 
    429 /*-------------------------------------------------
    430  *  lzma_allocator_init
    431  *-------------------------------------------------
    432  */
    433 
    434 static void lzma_allocator_init(void* p)
    435 {
    436 	lzma_allocator *codec = (lzma_allocator *)(p);
    437 
    438 	/* reset pointer list */
    439 	memset(codec->allocptr, 0, sizeof(codec->allocptr));
    440 	memset(codec->allocptr2, 0, sizeof(codec->allocptr2));
    441 	codec->Alloc = lzma_fast_alloc;
    442 	codec->Free = lzma_fast_free;
    443 }
    444 
    445 /*-------------------------------------------------
    446  *  lzma_allocator_free
    447  *-------------------------------------------------
    448  */
    449 
    450 static void lzma_allocator_free(void* p )
    451 {
    452 	int i;
    453 	lzma_allocator *codec = (lzma_allocator *)(p);
    454 
    455 	/* free our memory */
    456 	for (i = 0 ; i < MAX_LZMA_ALLOCS ; i++)
    457 	{
    458 		if (codec->allocptr[i] != NULL)
    459 			free(codec->allocptr[i]);
    460 	}
    461 }
    462 
    463 /*-------------------------------------------------
    464  *  lzma_fast_alloc - fast malloc for lzma, which
    465  *  allocates and frees memory frequently
    466  *-------------------------------------------------
    467  */
    468 
    469 /* Huge alignment values for possible SIMD optimization by compiler (NEON, SSE, AVX) */
    470 #define LZMA_MIN_ALIGNMENT_BITS 512
    471 #define LZMA_MIN_ALIGNMENT_BYTES (LZMA_MIN_ALIGNMENT_BITS / 8)
    472 
    473 static void *lzma_fast_alloc(void *p, size_t size)
    474 {
    475 	int scan;
    476 	uint32_t *addr        = NULL;
    477 	lzma_allocator *codec = (lzma_allocator *)(p);
    478 	uintptr_t vaddr = 0;
    479 
    480 	/* compute the size, rounding to the nearest 1k */
    481 	size = (size + 0x3ff) & ~0x3ff;
    482 
    483 	/* reuse a hunk if we can */
    484 	for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
    485 	{
    486 		uint32_t *ptr = codec->allocptr[scan];
    487 		if (ptr != NULL && size == *ptr)
    488 		{
    489 			/* set the low bit of the size so we don't match next time */
    490 			*ptr |= 1;
    491 
    492 			/* return aligned address of the block */
    493 			return codec->allocptr2[scan];
    494 		}
    495 	}
    496 
    497 	/* alloc a new one and put it into the list */
    498 	addr = (uint32_t *)malloc(size + sizeof(uint32_t) + LZMA_MIN_ALIGNMENT_BYTES);
    499 	if (addr==NULL)
    500 		return NULL;
    501 	for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
    502 	{
    503 		if (codec->allocptr[scan] == NULL)
    504 		{
    505 			/* store block address */
    506 			codec->allocptr[scan] = addr;
    507 
    508 			/* compute aligned address, store it */
    509 			vaddr = (uintptr_t)addr;
    510 			vaddr = (vaddr + sizeof(uint32_t) + (LZMA_MIN_ALIGNMENT_BYTES-1)) & (~(LZMA_MIN_ALIGNMENT_BYTES-1));
    511 			codec->allocptr2[scan] = (uint32_t*)vaddr;
    512 			break;
    513 		}
    514 	}
    515 
    516 	/* set the low bit of the size so we don't match next time */
    517 	*addr = size | 1;
    518 
    519 	/* return aligned address */
    520 	return (void*)vaddr;
    521 }
    522 
    523 /*-------------------------------------------------
    524  *  lzma_fast_free - fast free for lzma, which
    525  *  allocates and frees memory frequently
    526  *-------------------------------------------------
    527  */
    528 
    529 static void lzma_fast_free(void *p, void *address)
    530 {
    531 	int scan;
    532 	uint32_t *ptr = NULL;
    533 	lzma_allocator *codec = NULL;
    534 
    535 	if (address == NULL)
    536 		return;
    537 
    538 	codec = (lzma_allocator *)(p);
    539 
    540 	/* find the hunk */
    541 	ptr = (uint32_t *)address;
    542 	for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
    543 	{
    544 		if (ptr == codec->allocptr2[scan])
    545 		{
    546 			/* clear the low bit of the size to allow matches */
    547 			*codec->allocptr[scan] &= ~1;
    548 			return;
    549 		}
    550 	}
    551 }
    552 
    553 /***************************************************************************
    554  *  LZMA DECOMPRESSOR
    555  ***************************************************************************
    556  */
    557 
    558 /*-------------------------------------------------
    559  *  lzma_codec_init - constructor
    560  *-------------------------------------------------
    561  */
    562 
    563 static chd_error lzma_codec_init(void* codec, uint32_t hunkbytes)
    564 {
    565 	CLzmaEncHandle enc;
    566 	CLzmaEncProps encoder_props;
    567 	Byte decoder_props[LZMA_PROPS_SIZE];
    568 	SizeT props_size;
    569 	lzma_allocator* alloc;
    570 	lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
    571 
    572 	/* construct the decoder */
    573 	LzmaDec_Construct(&lzma_codec->decoder);
    574 
    575 	/* FIXME: this code is written in a way that makes it impossible to safely upgrade the LZMA SDK
    576 	 * This code assumes that the current version of the encoder imposes the same requirements on the
    577 	 * decoder as the encoder used to produce the file.  This is not necessarily true.  The format
    578 	 * needs to be changed so the encoder properties are written to the file.
    579 
    580 	 * configure the properties like the compressor did */
    581 	LzmaEncProps_Init(&encoder_props);
    582 	encoder_props.level = 9;
    583 	encoder_props.reduceSize = hunkbytes;
    584 	LzmaEncProps_Normalize(&encoder_props);
    585 
    586 	/* convert to decoder properties */
    587 	alloc = &lzma_codec->allocator;
    588 	lzma_allocator_init(alloc);
    589 	enc = LzmaEnc_Create((ISzAlloc*)alloc);
    590 	if (!enc)
    591 		return CHDERR_DECOMPRESSION_ERROR;
    592 	if (LzmaEnc_SetProps(enc, &encoder_props) != SZ_OK)
    593 	{
    594 		LzmaEnc_Destroy(enc, (ISzAlloc*)&alloc, (ISzAlloc*)&alloc);
    595 		return CHDERR_DECOMPRESSION_ERROR;
    596 	}
    597 	props_size = sizeof(decoder_props);
    598 	if (LzmaEnc_WriteProperties(enc, decoder_props, &props_size) != SZ_OK)
    599 	{
    600 		LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc);
    601 		return CHDERR_DECOMPRESSION_ERROR;
    602 	}
    603 	LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc);
    604 
    605 	/* do memory allocations */
    606 	if (LzmaDec_Allocate(&lzma_codec->decoder, decoder_props, LZMA_PROPS_SIZE, (ISzAlloc*)alloc) != SZ_OK)
    607 		return CHDERR_DECOMPRESSION_ERROR;
    608 
    609 	/* Okay */
    610 	return CHDERR_NONE;
    611 }
    612 
    613 /*-------------------------------------------------
    614  *  lzma_codec_free
    615  *-------------------------------------------------
    616  */
    617 
    618 static void lzma_codec_free(void* codec)
    619 {
    620 	lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
    621 
    622 	/* free memory */
    623 	LzmaDec_Free(&lzma_codec->decoder, (ISzAlloc*)&lzma_codec->allocator);
    624 	lzma_allocator_free(&lzma_codec->allocator);
    625 }
    626 
    627 /*-------------------------------------------------
    628  *  decompress - decompress data using the LZMA
    629  *  codec
    630  *-------------------------------------------------
    631  */
    632 
    633 static chd_error lzma_codec_decompress(void* codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
    634 {
    635 	ELzmaStatus status;
    636 	SRes res;
    637 	SizeT consumedlen, decodedlen;
    638 	/* initialize */
    639 	lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
    640 	LzmaDec_Init(&lzma_codec->decoder);
    641 
    642 	/* decode */
    643 	consumedlen = complen;
    644 	decodedlen = destlen;
    645 	res = LzmaDec_DecodeToBuf(&lzma_codec->decoder, dest, &decodedlen, src, &consumedlen, LZMA_FINISH_END, &status);
    646 	if ((res != SZ_OK && res != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) || consumedlen != complen || decodedlen != destlen)
    647 		return CHDERR_DECOMPRESSION_ERROR;
    648 	return CHDERR_NONE;
    649 }
    650 
    651 /* cdlz */
    652 static chd_error cdlz_codec_init(void* codec, uint32_t hunkbytes)
    653 {
    654 	chd_error ret;
    655 	cdlz_codec_data* cdlz = (cdlz_codec_data*) codec;
    656 
    657 	/* allocate buffer */
    658 	cdlz->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
    659 	if (cdlz->buffer == NULL)
    660 		return CHDERR_OUT_OF_MEMORY;
    661 
    662 	/* make sure the CHD's hunk size is an even multiple of the frame size */
    663 	ret = lzma_codec_init(&cdlz->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
    664 	if (ret != CHDERR_NONE)
    665 		return ret;
    666 
    667 #ifdef WANT_SUBCODE
    668 	ret = zlib_codec_init(&cdlz->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SUBCODE_DATA);
    669 	if (ret != CHDERR_NONE)
    670 		return ret;
    671 #endif
    672 
    673 	if (hunkbytes % CD_FRAME_SIZE != 0)
    674 		return CHDERR_CODEC_ERROR;
    675 
    676 	return CHDERR_NONE;
    677 }
    678 
    679 static void cdlz_codec_free(void* codec)
    680 {
    681 	cdlz_codec_data* cdlz = (cdlz_codec_data*) codec;
    682 	free(cdlz->buffer);
    683 	lzma_codec_free(&cdlz->base_decompressor);
    684 #ifdef WANT_SUBCODE
    685 	zlib_codec_free(&cdlz->subcode_decompressor);
    686 #endif
    687 }
    688 
    689 static chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
    690 {
    691 	uint32_t framenum;
    692 	cdlz_codec_data* cdlz = (cdlz_codec_data*)codec;
    693 
    694 	/* determine header bytes */
    695 	uint32_t frames = destlen / CD_FRAME_SIZE;
    696 	uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
    697 	uint32_t ecc_bytes = (frames + 7) / 8;
    698 	uint32_t header_bytes = ecc_bytes + complen_bytes;
    699 
    700 	/* extract compressed length of base */
    701 	uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
    702 	if (complen_bytes > 2)
    703 		complen_base = (complen_base << 8) | src[ecc_bytes + 2];
    704 
    705 	/* reset and decode */
    706 	lzma_codec_decompress(&cdlz->base_decompressor, &src[header_bytes], complen_base, &cdlz->buffer[0], frames * CD_MAX_SECTOR_DATA);
    707 #ifdef WANT_SUBCODE
    708 	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);
    709 #endif
    710 
    711 	/* reassemble the data */
    712 	for (framenum = 0; framenum < frames; framenum++)
    713 	{
    714 		uint8_t *sector;
    715 
    716 		memcpy(&dest[framenum * CD_FRAME_SIZE], &cdlz->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
    717 #ifdef WANT_SUBCODE
    718 		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);
    719 #endif
    720 
    721 #ifdef WANT_RAW_DATA_SECTOR
    722 		/* reconstitute the ECC data and sync header */
    723 		sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE];
    724 		if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
    725 		{
    726 			memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
    727 			ecc_generate(sector);
    728 		}
    729 #endif
    730 	}
    731 	return CHDERR_NONE;
    732 }
    733 
    734 /* cdzl */
    735 
    736 static chd_error cdzl_codec_init(void *codec, uint32_t hunkbytes)
    737 {
    738 	chd_error ret;
    739 	cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
    740 
    741 	/* make sure the CHD's hunk size is an even multiple of the frame size */
    742 	if (hunkbytes % CD_FRAME_SIZE != 0)
    743 		return CHDERR_CODEC_ERROR;
    744 
    745 	cdzl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
    746 	if (cdzl->buffer == NULL)
    747 		return CHDERR_OUT_OF_MEMORY;
    748 
    749 	ret = zlib_codec_init(&cdzl->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
    750 	if (ret != CHDERR_NONE)
    751 		return ret;
    752 
    753 #ifdef WANT_SUBCODE
    754 	ret = zlib_codec_init(&cdzl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SUBCODE_DATA);
    755 	if (ret != CHDERR_NONE)
    756 		return ret;
    757 #endif
    758 
    759 	return CHDERR_NONE;
    760 }
    761 
    762 static void cdzl_codec_free(void *codec)
    763 {
    764 	cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
    765 	zlib_codec_free(&cdzl->base_decompressor);
    766 #ifdef WANT_SUBCODE
    767 	zlib_codec_free(&cdzl->subcode_decompressor);
    768 #endif
    769 	free(cdzl->buffer);
    770 }
    771 
    772 static chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
    773 {
    774 	uint32_t framenum;
    775 	cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
    776 
    777 	/* determine header bytes */
    778 	uint32_t frames = destlen / CD_FRAME_SIZE;
    779 	uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
    780 	uint32_t ecc_bytes = (frames + 7) / 8;
    781 	uint32_t header_bytes = ecc_bytes + complen_bytes;
    782 
    783 	/* extract compressed length of base */
    784 	uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
    785 	if (complen_bytes > 2)
    786 		complen_base = (complen_base << 8) | src[ecc_bytes + 2];
    787 
    788 	/* reset and decode */
    789 	zlib_codec_decompress(&cdzl->base_decompressor, &src[header_bytes], complen_base, &cdzl->buffer[0], frames * CD_MAX_SECTOR_DATA);
    790 #ifdef WANT_SUBCODE
    791 	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);
    792 #endif
    793 
    794 	/* reassemble the data */
    795 	for (framenum = 0; framenum < frames; framenum++)
    796 	{
    797 		uint8_t *sector;
    798 
    799 		memcpy(&dest[framenum * CD_FRAME_SIZE], &cdzl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
    800 #ifdef WANT_SUBCODE
    801 		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);
    802 #endif
    803 
    804 #ifdef WANT_RAW_DATA_SECTOR
    805 		/* reconstitute the ECC data and sync header */
    806 		sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE];
    807 		if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
    808 		{
    809 			memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
    810 			ecc_generate(sector);
    811 		}
    812 #endif
    813 	}
    814 	return CHDERR_NONE;
    815 }
    816 
    817 /***************************************************************************
    818  *  HUFFMAN DECOMPRESSOR
    819  ***************************************************************************
    820  */
    821 
    822 static chd_error huff_codec_init(void* codec, uint32_t hunkbytes)
    823 {
    824 	huff_codec_data* huff_codec = (huff_codec_data*) codec;
    825 	huff_codec->decoder = create_huffman_decoder(256, 16);
    826 	return CHDERR_NONE;
    827 }
    828 
    829 static void huff_codec_free(void *codec)
    830 {
    831 	huff_codec_data* huff_codec = (huff_codec_data*) codec;
    832 	delete_huffman_decoder(huff_codec->decoder);
    833 }
    834 
    835 static chd_error huff_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
    836 {
    837 	huff_codec_data* huff_codec = (huff_codec_data*) codec;
    838 	struct bitstream* bitbuf = create_bitstream(src, complen);
    839 
    840 	// first import the tree
    841 	enum huffman_error err = huffman_import_tree_huffman(huff_codec->decoder, bitbuf);
    842 	if (err != HUFFERR_NONE)
    843 	{
    844 		free(bitbuf);
    845 		return CHDERR_DECOMPRESSION_ERROR;
    846 	}
    847 
    848 	// then decode the data
    849 	uint32_t cur;
    850 	for (cur = 0; cur < destlen; cur++)
    851 		dest[cur] = huffman_decode_one(huff_codec->decoder, bitbuf);
    852 	bitstream_flush(bitbuf);
    853 	chd_error result = bitstream_overflow(bitbuf) ? CHDERR_DECOMPRESSION_ERROR : CHDERR_NONE;
    854 
    855 	free(bitbuf);
    856 	return result;
    857 }
    858  
    859 /***************************************************************************
    860  *  CD FLAC DECOMPRESSOR
    861  ***************************************************************************
    862  */
    863 
    864 /*------------------------------------------------------
    865  *  flac_codec_blocksize - return the optimal block size
    866  *------------------------------------------------------
    867  */
    868 
    869 static uint32_t flac_codec_blocksize(uint32_t bytes)
    870 {
    871 	/* determine FLAC block size, which must be 16-65535
    872 	 * clamp to 2k since that's supposed to be the sweet spot */
    873 	uint32_t blocksize = bytes / 4;
    874 	while (blocksize > 2048)
    875 		blocksize /= 2;
    876 	return blocksize;
    877 }
    878 
    879 static chd_error flac_codec_init(void *codec, uint32_t hunkbytes)
    880 {
    881 	uint16_t native_endian = 0;
    882 	flac_codec_data *flac = (flac_codec_data*)codec;
    883 
    884 	/* make sure the CHD's hunk size is an even multiple of the sample size */
    885 	if (hunkbytes % 4 != 0)
    886 		return CHDERR_CODEC_ERROR;
    887 
    888 	/* determine whether we want native or swapped samples */
    889 	*(uint8_t *)(&native_endian) = 1;
    890 	flac->native_endian = (native_endian & 1);
    891 
    892 	/* flac decoder init */
    893 	if (flac_decoder_init(&flac->decoder))
    894 		return CHDERR_OUT_OF_MEMORY;
    895 
    896 	return CHDERR_NONE;
    897 }
    898 
    899 static void flac_codec_free(void *codec)
    900 {
    901 	flac_codec_data *flac = (flac_codec_data*)codec;
    902 	flac_decoder_free(&flac->decoder);
    903 }
    904 
    905 static chd_error flac_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
    906 {
    907 	flac_codec_data *flac = (flac_codec_data*)codec;
    908 	int swap_endian;
    909 
    910 	if (src[0] == 'L')
    911 		swap_endian = !flac->native_endian;
    912 	else if (src[0] == 'B')
    913 		swap_endian = flac->native_endian;
    914 	else
    915 		return CHDERR_DECOMPRESSION_ERROR;
    916 
    917 	if (!flac_decoder_reset(&flac->decoder, 44100, 2, flac_codec_blocksize(destlen), src + 1, complen - 1))
    918 		return CHDERR_DECOMPRESSION_ERROR;
    919 	if (!flac_decoder_decode_interleaved(&flac->decoder, (int16_t *)(dest), destlen/4, swap_endian))
    920 		return CHDERR_DECOMPRESSION_ERROR;
    921 	flac_decoder_finish(&flac->decoder);
    922 
    923 	return CHDERR_NONE;
    924 }
    925 
    926 static uint32_t cdfl_codec_blocksize(uint32_t bytes)
    927 {
    928 	// for CDs it seems that CD_MAX_SECTOR_DATA is the right target
    929 	uint32_t blocksize = bytes / 4;
    930 	while (blocksize > CD_MAX_SECTOR_DATA)
    931 		blocksize /= 2;
    932 	return blocksize;
    933 }
    934 
    935 static chd_error cdfl_codec_init(void *codec, uint32_t hunkbytes)
    936 {
    937 #ifdef WANT_SUBCODE
    938 	chd_error ret;
    939 #endif
    940 	uint16_t native_endian = 0;
    941 	cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
    942 
    943 	/* make sure the CHD's hunk size is an even multiple of the frame size */
    944 	if (hunkbytes % CD_FRAME_SIZE != 0)
    945 		return CHDERR_CODEC_ERROR;
    946 
    947 	cdfl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
    948 	if (cdfl->buffer == NULL)
    949 		return CHDERR_OUT_OF_MEMORY;
    950 
    951 	/* determine whether we want native or swapped samples */
    952 	*(uint8_t *)(&native_endian) = 1;
    953 	cdfl->swap_endian = (native_endian & 1);
    954 
    955 #ifdef WANT_SUBCODE
    956 	/* init zlib inflater */
    957 	ret = zlib_codec_init(&cdfl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
    958 	if (ret != CHDERR_NONE)
    959 		return ret;
    960 #endif
    961 
    962 	/* flac decoder init */
    963 	if (flac_decoder_init(&cdfl->decoder))
    964 		return CHDERR_OUT_OF_MEMORY;
    965 
    966 	return CHDERR_NONE;
    967 }
    968 
    969 static void cdfl_codec_free(void *codec)
    970 {
    971 	cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
    972 	flac_decoder_free(&cdfl->decoder);
    973 #ifdef WANT_SUBCODE
    974 	zlib_codec_free(&cdfl->subcode_decompressor);
    975 #endif
    976 	if (cdfl->buffer)
    977 		free(cdfl->buffer);
    978 }
    979 
    980 static chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
    981 {
    982 	uint32_t framenum;
    983 	uint8_t *buffer;
    984 #ifdef WANT_SUBCODE
    985 	uint32_t offset;
    986 	chd_error ret;
    987 #endif
    988 	cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
    989 
    990 	/* reset and decode */
    991 	uint32_t frames = destlen / CD_FRAME_SIZE;
    992 
    993 	if (!flac_decoder_reset(&cdfl->decoder, 44100, 2, cdfl_codec_blocksize(frames * CD_MAX_SECTOR_DATA), src, complen))
    994 		return CHDERR_DECOMPRESSION_ERROR;
    995 	buffer = &cdfl->buffer[0];
    996 	if (!flac_decoder_decode_interleaved(&cdfl->decoder, (int16_t *)(buffer), frames * CD_MAX_SECTOR_DATA/4, cdfl->swap_endian))
    997 		return CHDERR_DECOMPRESSION_ERROR;
    998 
    999 #ifdef WANT_SUBCODE
   1000 	/* inflate the subcode data */
   1001 	offset = flac_decoder_finish(&cdfl->decoder);
   1002 	ret = zlib_codec_decompress(&cdfl->subcode_decompressor, src + offset, complen - offset, &cdfl->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA);
   1003 	if (ret != CHDERR_NONE)
   1004 		return ret;
   1005 #else
   1006 	flac_decoder_finish(&cdfl->decoder);
   1007 #endif
   1008 
   1009 	/* reassemble the data */
   1010 	for (framenum = 0; framenum < frames; framenum++)
   1011 	{
   1012 		memcpy(&dest[framenum * CD_FRAME_SIZE], &cdfl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
   1013 #ifdef WANT_SUBCODE
   1014 		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);
   1015 #endif
   1016 	}
   1017 
   1018 	return CHDERR_NONE;
   1019 }
   1020 
   1021 
   1022 /***************************************************************************
   1023  *  ZSTD DECOMPRESSOR
   1024  ***************************************************************************
   1025  */
   1026 
   1027 /*-------------------------------------------------
   1028  *  zstd_codec_init - constructor
   1029  *-------------------------------------------------
   1030  */
   1031 
   1032 static chd_error zstd_codec_init(void* codec, uint32_t hunkbytes)
   1033 {
   1034 	zstd_codec_data* zstd_codec = (zstd_codec_data*) codec;
   1035 
   1036 	zstd_codec->dstream = ZSTD_createDStream();
   1037 	if (!zstd_codec->dstream) {
   1038 		printf("NO DSTREAM CREATED!\n");
   1039 		return CHDERR_DECOMPRESSION_ERROR;
   1040 	}
   1041 	return CHDERR_NONE;
   1042 }
   1043 
   1044 /*-------------------------------------------------
   1045  *  zstd_codec_free
   1046  *-------------------------------------------------
   1047  */
   1048 
   1049 static void zstd_codec_free(void* codec)
   1050 {
   1051 	zstd_codec_data* zstd_codec = (zstd_codec_data*) codec;
   1052 
   1053 	ZSTD_freeDStream(zstd_codec->dstream);
   1054 }
   1055 
   1056 /*-------------------------------------------------
   1057  *  decompress - decompress data using the ZSTD 
   1058  *  codec
   1059  *-------------------------------------------------
   1060  */
   1061 static chd_error zstd_codec_decompress(void* codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
   1062 {
   1063 	/* initialize */
   1064 	zstd_codec_data* zstd_codec = (zstd_codec_data*) codec;
   1065 	//reset decompressor
   1066 	size_t zstd_res =  ZSTD_initDStream(zstd_codec->dstream);
   1067 	if (ZSTD_isError(zstd_res)) 
   1068 	{
   1069 		printf("INITI DSTREAM FAILED!\n");
   1070 		return CHDERR_DECOMPRESSION_ERROR;
   1071 	}
   1072 
   1073 	ZSTD_inBuffer input =  {src, complen, 0};
   1074 	ZSTD_outBuffer output = {dest, destlen, 0 };
   1075 
   1076 	while ((input.pos < input.size) && (output.pos < output.size))
   1077 	{
   1078 		zstd_res = ZSTD_decompressStream(zstd_codec->dstream, &output, &input);
   1079 		if (ZSTD_isError(zstd_res))
   1080 		{
   1081 			printf("DECOMPRESSION ERROR IN LOOP\n");
   1082 			return CHDERR_DECOMPRESSION_ERROR;
   1083 		}
   1084 	}
   1085 	if (output.pos != output.size)
   1086 	{
   1087 		printf("OUTPUT DOESN'T MATCH!\n");
   1088 		return CHDERR_DECOMPRESSION_ERROR;
   1089 	}
   1090 	return CHDERR_NONE;
   1091 
   1092 }
   1093 
   1094 /* cdzs */
   1095 static chd_error cdzs_codec_init(void* codec, uint32_t hunkbytes)
   1096 {
   1097 	chd_error ret;
   1098 	cdzs_codec_data* cdzs = (cdzs_codec_data*) codec;
   1099 
   1100 	/* allocate buffer */
   1101 	cdzs->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
   1102 	if (cdzs->buffer == NULL)
   1103 		return CHDERR_OUT_OF_MEMORY;
   1104 
   1105 	/* make sure the CHD's hunk size is an even multiple of the frame size */
   1106 	ret = zstd_codec_init(&cdzs->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
   1107 	if (ret != CHDERR_NONE)
   1108 		return ret;
   1109 
   1110 #ifdef WANT_SUBCODE
   1111 	ret = zstd_codec_init(&cdzs->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SUBCODE_DATA);
   1112 	if (ret != CHDERR_NONE)
   1113 		return ret;
   1114 #endif
   1115 
   1116 	if (hunkbytes % CD_FRAME_SIZE != 0)
   1117 		return CHDERR_CODEC_ERROR;
   1118 
   1119 	return CHDERR_NONE;
   1120 }
   1121 
   1122 static void cdzs_codec_free(void* codec)
   1123 {
   1124 	cdzs_codec_data* cdzs = (cdzs_codec_data*) codec;
   1125 	free(cdzs->buffer);
   1126 	zstd_codec_free(&cdzs->base_decompressor);
   1127 #ifdef WANT_SUBCODE
   1128 	zstd_codec_free(&cdzs->subcode_decompressor);
   1129 #endif
   1130 }
   1131 
   1132 static chd_error cdzs_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
   1133 {
   1134 	uint32_t framenum;
   1135 	cdzs_codec_data* cdzs = (cdzs_codec_data*)codec;
   1136 
   1137 	/* determine header bytes */
   1138 	uint32_t frames = destlen / CD_FRAME_SIZE;
   1139 	uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
   1140 	uint32_t ecc_bytes = (frames + 7) / 8;
   1141 	uint32_t header_bytes = ecc_bytes + complen_bytes;
   1142 
   1143 	/* extract compressed length of base */
   1144 	uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
   1145 	if (complen_bytes > 2)
   1146 		complen_base = (complen_base << 8) | src[ecc_bytes + 2];
   1147 
   1148 	/* reset and decode */
   1149 	zstd_codec_decompress(&cdzs->base_decompressor, &src[header_bytes], complen_base, &cdzs->buffer[0], frames * CD_MAX_SECTOR_DATA);
   1150 #ifdef WANT_SUBCODE
   1151 	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);
   1152 #endif
   1153 
   1154 	/* reassemble the data */
   1155 	for (framenum = 0; framenum < frames; framenum++)
   1156 	{
   1157 		uint8_t *sector;
   1158 
   1159 		memcpy(&dest[framenum * CD_FRAME_SIZE], &cdzs->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
   1160 #ifdef WANT_SUBCODE
   1161 		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);
   1162 #endif
   1163 
   1164 #ifdef WANT_RAW_DATA_SECTOR
   1165 		/* reconstitute the ECC data and sync header */
   1166 		sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE];
   1167 		if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
   1168 		{
   1169 			memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
   1170 			ecc_generate(sector);
   1171 		}
   1172 #endif
   1173 	}
   1174 	return CHDERR_NONE;
   1175 }
   1176 
   1177 /***************************************************************************
   1178     CODEC INTERFACES
   1179 ***************************************************************************/
   1180 
   1181 static const codec_interface codec_interfaces[] =
   1182 {
   1183 	/* "none" or no compression */
   1184 	{
   1185 		CHDCOMPRESSION_NONE,
   1186 		"none",
   1187 		FALSE,
   1188 		NULL,
   1189 		NULL,
   1190 		NULL,
   1191 		NULL
   1192 	},
   1193 
   1194 	/* standard zlib compression */
   1195 	{
   1196 		CHDCOMPRESSION_ZLIB,
   1197 		"zlib",
   1198 		FALSE,
   1199 		zlib_codec_init,
   1200 		zlib_codec_free,
   1201 		zlib_codec_decompress,
   1202 		NULL
   1203 	},
   1204 
   1205 	/* zlib+ compression */
   1206 	{
   1207 		CHDCOMPRESSION_ZLIB_PLUS,
   1208 		"zlib+",
   1209 		FALSE,
   1210 		zlib_codec_init,
   1211 		zlib_codec_free,
   1212 		zlib_codec_decompress,
   1213 		NULL
   1214 	},
   1215 
   1216 	/* V5 zlib compression */
   1217 	{
   1218 		CHD_CODEC_ZLIB,
   1219 		"zlib (Deflate)",
   1220 		FALSE,
   1221 		zlib_codec_init,
   1222 		zlib_codec_free,
   1223 		zlib_codec_decompress,
   1224 		NULL
   1225 	},
   1226 
   1227 	/* V5 lzma compression */
   1228 	{
   1229 		CHD_CODEC_LZMA,
   1230 		"lzma (LZMA)",
   1231 		FALSE,
   1232 		lzma_codec_init,
   1233 		lzma_codec_free,
   1234 		lzma_codec_decompress,
   1235 		NULL
   1236 	},
   1237 
   1238 	/* V5 huffman compression */
   1239 	{
   1240 		CHD_CODEC_HUFFMAN,
   1241 		"Huffman",
   1242 		FALSE,
   1243 		huff_codec_init,
   1244 		huff_codec_free,
   1245 		huff_codec_decompress,
   1246 		NULL
   1247 	},
   1248 
   1249 	/* V5 flac compression */
   1250 	{
   1251 		CHD_CODEC_FLAC,
   1252 		"flac (FLAC)",
   1253 		FALSE,
   1254 		flac_codec_init,
   1255 		flac_codec_free,
   1256 		flac_codec_decompress,
   1257 		NULL
   1258 	},
   1259 	/* V5 zstd compression */
   1260 	{
   1261 		CHD_CODEC_ZSTD,
   1262 		"ZStandard",
   1263 		FALSE,
   1264 		zstd_codec_init,
   1265 		zstd_codec_free,
   1266 		zstd_codec_decompress,
   1267 		NULL
   1268 	},
   1269 
   1270 	/* V5 CD zlib compression */
   1271 	{
   1272 		CHD_CODEC_CD_ZLIB,
   1273 		"cdzl (CD Deflate)",
   1274 		FALSE,
   1275 		cdzl_codec_init,
   1276 		cdzl_codec_free,
   1277 		cdzl_codec_decompress,
   1278 		NULL
   1279 	},
   1280 
   1281 	/* V5 CD lzma compression */
   1282 	{
   1283 		CHD_CODEC_CD_LZMA,
   1284 		"cdlz (CD LZMA)",
   1285 		FALSE,
   1286 		cdlz_codec_init,
   1287 		cdlz_codec_free,
   1288 		cdlz_codec_decompress,
   1289 		NULL
   1290 	},
   1291 
   1292 	/* V5 CD flac compression */
   1293 	{
   1294 		CHD_CODEC_CD_FLAC,
   1295 		"cdfl (CD FLAC)",
   1296 		FALSE,
   1297 		cdfl_codec_init,
   1298 		cdfl_codec_free,
   1299 		cdfl_codec_decompress,
   1300 		NULL
   1301 	},
   1302 	/* V5 CD zstd compression */
   1303 	{
   1304 		CHD_CODEC_CD_ZSTD,
   1305 		"cdzs (CD ZStandard)",
   1306 		FALSE,
   1307 		cdzs_codec_init,
   1308 		cdzs_codec_free,
   1309 		cdzs_codec_decompress,
   1310 		NULL
   1311 	}
   1312 	
   1313 };
   1314 
   1315 /***************************************************************************
   1316     INLINE FUNCTIONS
   1317 ***************************************************************************/
   1318 
   1319 /*-------------------------------------------------
   1320     get_bigendian_uint64 - fetch a UINT64 from
   1321     the data stream in bigendian order
   1322 -------------------------------------------------*/
   1323 
   1324 static inline UINT64 get_bigendian_uint64(const UINT8 *base)
   1325 {
   1326 	return ((UINT64)base[0] << 56) | ((UINT64)base[1] << 48) | ((UINT64)base[2] << 40) | ((UINT64)base[3] << 32) |
   1327 			((UINT64)base[4] << 24) | ((UINT64)base[5] << 16) | ((UINT64)base[6] << 8) | (UINT64)base[7];
   1328 }
   1329 
   1330 /*-------------------------------------------------
   1331     put_bigendian_uint64 - write a UINT64 to
   1332     the data stream in bigendian order
   1333 -------------------------------------------------*/
   1334 
   1335 static inline void put_bigendian_uint64(UINT8 *base, UINT64 value)
   1336 {
   1337 	base[0] = value >> 56;
   1338 	base[1] = value >> 48;
   1339 	base[2] = value >> 40;
   1340 	base[3] = value >> 32;
   1341 	base[4] = value >> 24;
   1342 	base[5] = value >> 16;
   1343 	base[6] = value >> 8;
   1344 	base[7] = value;
   1345 }
   1346 
   1347 /*-------------------------------------------------
   1348     get_bigendian_uint48 - fetch a UINT48 from
   1349     the data stream in bigendian order
   1350 -------------------------------------------------*/
   1351 
   1352 static inline UINT64 get_bigendian_uint48(const UINT8 *base)
   1353 {
   1354 	return  ((UINT64)base[0] << 40) | ((UINT64)base[1] << 32) |
   1355 			((UINT64)base[2] << 24) | ((UINT64)base[3] << 16) | ((UINT64)base[4] << 8) | (UINT64)base[5];
   1356 }
   1357 
   1358 /*-------------------------------------------------
   1359     put_bigendian_uint48 - write a UINT48 to
   1360     the data stream in bigendian order
   1361 -------------------------------------------------*/
   1362 
   1363 static inline void put_bigendian_uint48(UINT8 *base, UINT64 value)
   1364 {
   1365 	value &= 0xffffffffffff;
   1366 	base[0] = value >> 40;
   1367 	base[1] = value >> 32;
   1368 	base[2] = value >> 24;
   1369 	base[3] = value >> 16;
   1370 	base[4] = value >> 8;
   1371 	base[5] = value;
   1372 }
   1373 /*-------------------------------------------------
   1374     get_bigendian_uint32 - fetch a UINT32 from
   1375     the data stream in bigendian order
   1376 -------------------------------------------------*/
   1377 
   1378 static inline UINT32 get_bigendian_uint32(const UINT8 *base)
   1379 {
   1380 	return (base[0] << 24) | (base[1] << 16) | (base[2] << 8) | base[3];
   1381 }
   1382 
   1383 /*-------------------------------------------------
   1384     put_bigendian_uint32 - write a UINT32 to
   1385     the data stream in bigendian order
   1386 -------------------------------------------------*/
   1387 
   1388 static inline void put_bigendian_uint32(UINT8 *base, UINT32 value)
   1389 {
   1390 	base[0] = value >> 24;
   1391 	base[1] = value >> 16;
   1392 	base[2] = value >> 8;
   1393 	base[3] = value;
   1394 }
   1395 
   1396 /*-------------------------------------------------
   1397     put_bigendian_uint24 - write a UINT24 to
   1398     the data stream in bigendian order
   1399 -------------------------------------------------*/
   1400 
   1401 static inline void put_bigendian_uint24(UINT8 *base, UINT32 value)
   1402 {
   1403 	value &= 0xffffff;
   1404 	base[0] = value >> 16;
   1405 	base[1] = value >> 8;
   1406 	base[2] = value;
   1407 }
   1408 
   1409 /*-------------------------------------------------
   1410     get_bigendian_uint24 - fetch a UINT24 from
   1411     the data stream in bigendian order
   1412 -------------------------------------------------*/
   1413 
   1414 static inline UINT32 get_bigendian_uint24(const UINT8 *base)
   1415 {
   1416 	return (base[0] << 16) | (base[1] << 8) | base[2];
   1417 }
   1418 
   1419 /*-------------------------------------------------
   1420     get_bigendian_uint16 - fetch a UINT16 from
   1421     the data stream in bigendian order
   1422 -------------------------------------------------*/
   1423 
   1424 static inline UINT16 get_bigendian_uint16(const UINT8 *base)
   1425 {
   1426 	return (base[0] << 8) | base[1];
   1427 }
   1428 
   1429 /*-------------------------------------------------
   1430     put_bigendian_uint16 - write a UINT16 to
   1431     the data stream in bigendian order
   1432 -------------------------------------------------*/
   1433 
   1434 static inline void put_bigendian_uint16(UINT8 *base, UINT16 value)
   1435 {
   1436 	base[0] = value >> 8;
   1437 	base[1] = value;
   1438 }
   1439 
   1440 /*-------------------------------------------------
   1441     map_extract - extract a single map
   1442     entry from the datastream
   1443 -------------------------------------------------*/
   1444 
   1445 static inline void map_extract(const UINT8 *base, map_entry *entry)
   1446 {
   1447 	entry->offset = get_bigendian_uint64(&base[0]);
   1448 	entry->crc = get_bigendian_uint32(&base[8]);
   1449 	entry->length = get_bigendian_uint16(&base[12]) | (base[14] << 16);
   1450 	entry->flags = base[15];
   1451 }
   1452 
   1453 /*-------------------------------------------------
   1454     map_assemble - write a single map
   1455     entry to the datastream
   1456 -------------------------------------------------*/
   1457 
   1458 static inline void map_assemble(UINT8 *base, map_entry *entry)
   1459 {
   1460 	put_bigendian_uint64(&base[0], entry->offset);
   1461 	put_bigendian_uint32(&base[8], entry->crc);
   1462 	put_bigendian_uint16(&base[12], entry->length);
   1463 	base[14] = entry->length >> 16;
   1464 	base[15] = entry->flags;
   1465 }
   1466 
   1467 /*-------------------------------------------------
   1468     map_size_v5 - calculate CHDv5 map size
   1469 -------------------------------------------------*/
   1470 static inline int map_size_v5(chd_header* header)
   1471 {
   1472 	return header->hunkcount * header->mapentrybytes;
   1473 }
   1474 
   1475 /*-------------------------------------------------
   1476     crc16 - calculate CRC16 (from hashing.cpp)
   1477 -------------------------------------------------*/
   1478 uint16_t crc16(const void *data, uint32_t length)
   1479 {
   1480 	uint16_t crc = 0xffff;
   1481 
   1482 	static const uint16_t s_table[256] =
   1483 	{
   1484 		0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
   1485 		0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
   1486 		0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
   1487 		0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
   1488 		0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
   1489 		0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
   1490 		0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
   1491 		0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
   1492 		0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
   1493 		0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
   1494 		0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
   1495 		0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
   1496 		0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
   1497 		0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
   1498 		0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
   1499 		0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
   1500 		0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
   1501 		0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
   1502 		0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
   1503 		0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
   1504 		0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
   1505 		0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
   1506 		0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
   1507 		0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
   1508 		0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
   1509 		0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
   1510 		0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
   1511 		0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
   1512 		0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
   1513 		0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
   1514 		0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
   1515 		0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
   1516 	};
   1517 
   1518 	const uint8_t *src = (uint8_t*)data;
   1519 
   1520 	/* fetch the current value into a local and rip through the source data */
   1521 	while (length-- != 0)
   1522 		crc = (crc << 8) ^ s_table[(crc >> 8) ^ *src++];
   1523 	return crc;
   1524 }
   1525 
   1526 /*-------------------------------------------------
   1527 	compressed - test if CHD file is compressed
   1528 +-------------------------------------------------*/
   1529 static inline int chd_compressed(chd_header* header) {
   1530 	return header->compression[0] != CHD_CODEC_NONE;
   1531 }
   1532 
   1533 /*-------------------------------------------------
   1534 	decompress_v5_map - decompress the v5 map
   1535 -------------------------------------------------*/
   1536 
   1537 static chd_error decompress_v5_map(chd_file* chd, chd_header* header)
   1538 {
   1539 	int result = 0;
   1540 	uint32_t hunknum;
   1541 	int repcount = 0;
   1542 	uint8_t lastcomp = 0;
   1543 	uint32_t last_self = 0;
   1544 	uint64_t last_parent = 0;
   1545 	struct bitstream* bitbuf;
   1546 	uint32_t mapbytes;
   1547 	uint64_t firstoffs;
   1548 	uint16_t mapcrc;
   1549 	uint8_t lengthbits;
   1550 	uint8_t selfbits;
   1551 	uint8_t parentbits;
   1552 	uint8_t *compressed_ptr;
   1553 	uint8_t rawbuf[16];
   1554 	struct huffman_decoder* decoder;
   1555 	enum huffman_error err;
   1556 	uint64_t curoffset;	
   1557 	int rawmapsize = map_size_v5(header);
   1558 
   1559 	if (!chd_compressed(header))
   1560 	{
   1561 		header->rawmap = (uint8_t*)malloc(rawmapsize);
   1562 		if (header->rawmap == NULL)
   1563 			return CHDERR_OUT_OF_MEMORY;
   1564 		core_fseek(chd->file, header->mapoffset, SEEK_SET);
   1565 		result = core_fread(chd->file, header->rawmap, rawmapsize);
   1566 		return CHDERR_NONE;
   1567 	}
   1568 
   1569 	/* read the reader */
   1570 	core_fseek(chd->file, header->mapoffset, SEEK_SET);
   1571 	result = core_fread(chd->file, rawbuf, sizeof(rawbuf));
   1572 	mapbytes = get_bigendian_uint32(&rawbuf[0]);
   1573 	firstoffs = get_bigendian_uint48(&rawbuf[4]);
   1574 	mapcrc = get_bigendian_uint16(&rawbuf[10]);
   1575 	lengthbits = rawbuf[12];
   1576 	selfbits = rawbuf[13];
   1577 	parentbits = rawbuf[14];
   1578 
   1579 	/* now read the map */
   1580 	compressed_ptr = (uint8_t*)malloc(sizeof(uint8_t) * mapbytes);
   1581 	if (compressed_ptr == NULL)
   1582 		return CHDERR_OUT_OF_MEMORY;
   1583 	core_fseek(chd->file, header->mapoffset + 16, SEEK_SET);
   1584 	result = core_fread(chd->file, compressed_ptr, mapbytes);
   1585 	bitbuf = create_bitstream(compressed_ptr, sizeof(uint8_t) * mapbytes);
   1586 	header->rawmap = (uint8_t*)malloc(rawmapsize);
   1587 	if (header->rawmap == NULL)
   1588 	{
   1589 		free(compressed_ptr);
   1590 		free(bitbuf);
   1591 		return CHDERR_OUT_OF_MEMORY;
   1592 	}
   1593 
   1594 	/* first decode the compression types */
   1595 	decoder = create_huffman_decoder(16, 8);
   1596 	if (decoder == NULL)
   1597 	{
   1598 		free(compressed_ptr);
   1599 		free(bitbuf);
   1600 		return CHDERR_OUT_OF_MEMORY;
   1601 	}
   1602 
   1603 	err = huffman_import_tree_rle(decoder, bitbuf);
   1604 	if (err != HUFFERR_NONE)
   1605 	{
   1606 		free(compressed_ptr);
   1607 		free(bitbuf);
   1608 		delete_huffman_decoder(decoder);
   1609 		return CHDERR_DECOMPRESSION_ERROR;
   1610 	}
   1611 
   1612 	for (hunknum = 0; hunknum < header->hunkcount; hunknum++)
   1613 	{
   1614 		uint8_t *rawmap = header->rawmap + (hunknum * 12);
   1615 		if (repcount > 0)
   1616 			rawmap[0] = lastcomp, repcount--;
   1617 		else
   1618 		{
   1619 			uint8_t val = huffman_decode_one(decoder, bitbuf);
   1620 			if (val == COMPRESSION_RLE_SMALL)
   1621 				rawmap[0] = lastcomp, repcount = 2 + huffman_decode_one(decoder, bitbuf);
   1622 			else if (val == COMPRESSION_RLE_LARGE)
   1623 				rawmap[0] = lastcomp, repcount = 2 + 16 + (huffman_decode_one(decoder, bitbuf) << 4), repcount += huffman_decode_one(decoder, bitbuf);
   1624 			else
   1625 				rawmap[0] = lastcomp = val;
   1626 		}
   1627 	}
   1628 
   1629 	/* then iterate through the hunks and extract the needed data */
   1630 	curoffset = firstoffs;
   1631 	for (hunknum = 0; hunknum < header->hunkcount; hunknum++)
   1632 	{
   1633 		uint8_t *rawmap = header->rawmap + (hunknum * 12);
   1634 		uint64_t offset = curoffset;
   1635 		uint32_t length = 0;
   1636 		uint16_t crc = 0;
   1637 		switch (rawmap[0])
   1638 		{
   1639 			/* base types */
   1640 			case COMPRESSION_TYPE_0:
   1641 			case COMPRESSION_TYPE_1:
   1642 			case COMPRESSION_TYPE_2:
   1643 			case COMPRESSION_TYPE_3:
   1644 				curoffset += length = bitstream_read(bitbuf, lengthbits);
   1645 				crc = bitstream_read(bitbuf, 16);
   1646 				break;
   1647 
   1648 			case COMPRESSION_NONE:
   1649 				curoffset += length = header->hunkbytes;
   1650 				crc = bitstream_read(bitbuf, 16);
   1651 				break;
   1652 
   1653 			case COMPRESSION_SELF:
   1654 				last_self = offset = bitstream_read(bitbuf, selfbits);
   1655 				break;
   1656 
   1657 			case COMPRESSION_PARENT:
   1658 				offset = bitstream_read(bitbuf, parentbits);
   1659 				last_parent = offset;
   1660 				break;
   1661 
   1662 			/* pseudo-types; convert into base types */
   1663 			case COMPRESSION_SELF_1:
   1664 				last_self++;
   1665 			case COMPRESSION_SELF_0:
   1666 				rawmap[0] = COMPRESSION_SELF;
   1667 				offset = last_self;
   1668 				break;
   1669 
   1670 			case COMPRESSION_PARENT_SELF:
   1671 				rawmap[0] = COMPRESSION_PARENT;
   1672 				last_parent = offset = ( ((uint64_t)hunknum) * ((uint64_t)header->hunkbytes) ) / header->unitbytes;
   1673 				break;
   1674 
   1675 			case COMPRESSION_PARENT_1:
   1676 				last_parent += header->hunkbytes / header->unitbytes;
   1677 			case COMPRESSION_PARENT_0:
   1678 				rawmap[0] = COMPRESSION_PARENT;
   1679 				offset = last_parent;
   1680 				break;
   1681 		}
   1682 		/* UINT24 length */
   1683 		put_bigendian_uint24(&rawmap[1], length);
   1684 
   1685 		/* UINT48 offset */
   1686 		put_bigendian_uint48(&rawmap[4], offset);
   1687 
   1688 		/* crc16 */
   1689 		put_bigendian_uint16(&rawmap[10], crc);
   1690 	}
   1691 
   1692 	/* free memory */
   1693 	free(compressed_ptr);
   1694 	free(bitbuf);
   1695 	delete_huffman_decoder(decoder);
   1696 
   1697 	/* verify the final CRC */
   1698 	if (crc16(&header->rawmap[0], header->hunkcount * 12) != mapcrc)
   1699 		return CHDERR_DECOMPRESSION_ERROR;
   1700 
   1701 	return CHDERR_NONE;
   1702 }
   1703 
   1704 /*-------------------------------------------------
   1705     map_extract_old - extract a single map
   1706     entry in old format from the datastream
   1707 -------------------------------------------------*/
   1708 
   1709 static inline void map_extract_old(const UINT8 *base, map_entry *entry, UINT32 hunkbytes)
   1710 {
   1711 	entry->offset = get_bigendian_uint64(&base[0]);
   1712 	entry->crc = 0;
   1713 	entry->length = entry->offset >> 44;
   1714 	entry->flags = MAP_ENTRY_FLAG_NO_CRC | ((entry->length == hunkbytes) ? V34_MAP_ENTRY_TYPE_UNCOMPRESSED : V34_MAP_ENTRY_TYPE_COMPRESSED);
   1715 #ifdef __MWERKS__
   1716 	entry->offset = entry->offset & 0x00000FFFFFFFFFFFLL;
   1717 #else
   1718 	entry->offset = (entry->offset << 20) >> 20;
   1719 #endif
   1720 }
   1721 
   1722 /***************************************************************************
   1723     CHD FILE MANAGEMENT
   1724 ***************************************************************************/
   1725 
   1726 /*-------------------------------------------------
   1727     chd_open_file - open a CHD file for access
   1728 -------------------------------------------------*/
   1729 
   1730 CHD_EXPORT chd_error chd_open_file(FILE *file, int mode, chd_file *parent, chd_file **chd) {
   1731 	core_file *stream = malloc(sizeof(core_file));
   1732 	if (!stream)
   1733 		return CHDERR_OUT_OF_MEMORY;
   1734 	stream->argp = file;
   1735 	stream->fsize = core_stdio_fsize;
   1736 	stream->fread = core_stdio_fread;
   1737 	stream->fclose = core_stdio_fclose_nonowner;
   1738 	stream->fseek = core_stdio_fseek;
   1739 
   1740 	chd_error err = chd_open_core_file(stream, mode, parent, chd);
   1741 	if (err != CHDERR_NONE)
   1742 		return err;
   1743 
   1744 	// swap out the fclose so that we close it on chd clost
   1745 	stream->fclose = core_stdio_fclose;
   1746 	return CHDERR_NONE;
   1747 }
   1748 
   1749 /*-------------------------------------------------
   1750     chd_open_core_file - open a CHD file for access
   1751 -------------------------------------------------*/
   1752 
   1753 CHD_EXPORT chd_error chd_open_core_file(core_file *file, int mode, chd_file *parent, chd_file **chd)
   1754 {
   1755 	chd_file *newchd = NULL;
   1756 	chd_error err;
   1757 	int intfnum;
   1758 
   1759 	/* verify parameters */
   1760 	if (file == NULL)
   1761 		EARLY_EXIT(err = CHDERR_INVALID_PARAMETER);
   1762 
   1763 	/* punt if invalid parent */
   1764 	if (parent != NULL && parent->cookie != COOKIE_VALUE)
   1765 		EARLY_EXIT(err = CHDERR_INVALID_PARAMETER);
   1766 
   1767 	/* allocate memory for the final result */
   1768 	newchd = (chd_file *)malloc(sizeof(**chd));
   1769 	if (newchd == NULL)
   1770 		EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
   1771 	memset(newchd, 0, sizeof(*newchd));
   1772 	newchd->cookie = COOKIE_VALUE;
   1773 	newchd->parent = parent;
   1774 	newchd->file = file;
   1775 
   1776 	/* now attempt to read the header */
   1777 	err = header_read(newchd, &newchd->header);
   1778 	if (err != CHDERR_NONE)
   1779 		EARLY_EXIT(err);
   1780 
   1781 	/* validate the header */
   1782 	err = header_validate(&newchd->header);
   1783 	if (err != CHDERR_NONE)
   1784 		EARLY_EXIT(err);
   1785 
   1786 	/* make sure we don't open a read-only file writeable */
   1787 	if (mode == CHD_OPEN_READWRITE && !(newchd->header.flags & CHDFLAGS_IS_WRITEABLE))
   1788 		EARLY_EXIT(err = CHDERR_FILE_NOT_WRITEABLE);
   1789 
   1790 	/* also, never open an older version writeable */
   1791 	if (mode == CHD_OPEN_READWRITE && newchd->header.version < CHD_HEADER_VERSION)
   1792 		EARLY_EXIT(err = CHDERR_UNSUPPORTED_VERSION);
   1793 
   1794 	/* if we need a parent, make sure we have one */
   1795 	if (parent == NULL)
   1796 	{
   1797 		/* Detect parent requirement for versions below 5 */
   1798 		if (newchd->header.version < 5 && newchd->header.flags & CHDFLAGS_HAS_PARENT)
   1799 			EARLY_EXIT(err = CHDERR_REQUIRES_PARENT);
   1800 		/* Detection for version 5 and above - if parentsha1 != 0, we have a parent */
   1801 		else if (newchd->header.version >= 5 && memcmp(nullsha1, newchd->header.parentsha1, sizeof(newchd->header.parentsha1)) != 0)
   1802 			EARLY_EXIT(err = CHDERR_REQUIRES_PARENT);
   1803 	}
   1804 
   1805 	/* make sure we have a valid parent */
   1806 	if (parent != NULL)
   1807 	{
   1808 		/* check MD5 if it isn't empty */
   1809 		if (memcmp(nullmd5, newchd->header.parentmd5, sizeof(newchd->header.parentmd5)) != 0 &&
   1810 			memcmp(nullmd5, newchd->parent->header.md5, sizeof(newchd->parent->header.md5)) != 0 &&
   1811 			memcmp(newchd->parent->header.md5, newchd->header.parentmd5, sizeof(newchd->header.parentmd5)) != 0)
   1812 			EARLY_EXIT(err = CHDERR_INVALID_PARENT);
   1813 
   1814 		/* check SHA1 if it isn't empty */
   1815 		if (memcmp(nullsha1, newchd->header.parentsha1, sizeof(newchd->header.parentsha1)) != 0 &&
   1816 			memcmp(nullsha1, newchd->parent->header.sha1, sizeof(newchd->parent->header.sha1)) != 0 &&
   1817 			memcmp(newchd->parent->header.sha1, newchd->header.parentsha1, sizeof(newchd->header.parentsha1)) != 0)
   1818 			EARLY_EXIT(err = CHDERR_INVALID_PARENT);
   1819 	}
   1820 
   1821 	/* now read the hunk map */
   1822 	if (newchd->header.version < 5)
   1823 	{
   1824 		err = map_read(newchd);
   1825 		if (err != CHDERR_NONE)
   1826 			EARLY_EXIT(err);
   1827 	}
   1828 	else
   1829 	{
   1830 		err = decompress_v5_map(newchd, &(newchd->header));
   1831 	}
   1832 	if (err != CHDERR_NONE)
   1833 		EARLY_EXIT(err);
   1834 
   1835 #ifdef NEED_CACHE_HUNK
   1836 	/* allocate and init the hunk cache */
   1837 	newchd->cache = (UINT8 *)malloc(newchd->header.hunkbytes);
   1838 	newchd->compare = (UINT8 *)malloc(newchd->header.hunkbytes);
   1839 	if (newchd->cache == NULL || newchd->compare == NULL)
   1840 		EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
   1841 	newchd->cachehunk = ~0;
   1842 	newchd->comparehunk = ~0;
   1843 #endif
   1844 
   1845 	/* allocate the temporary compressed buffer */
   1846 	newchd->compressed = (UINT8 *)malloc(newchd->header.hunkbytes);
   1847 	if (newchd->compressed == NULL)
   1848 		EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
   1849 
   1850 	/* find the codec interface */
   1851 	if (newchd->header.version < 5)
   1852 	{
   1853 		for (intfnum = 0; intfnum < ARRAY_LENGTH(codec_interfaces); intfnum++)
   1854 		{
   1855 			if (codec_interfaces[intfnum].compression == newchd->header.compression[0])
   1856 			{
   1857 				newchd->codecintf[0] = &codec_interfaces[intfnum];
   1858 				break;
   1859 			}
   1860 		}
   1861 
   1862 		if (intfnum == ARRAY_LENGTH(codec_interfaces))
   1863 			EARLY_EXIT(err = CHDERR_UNSUPPORTED_FORMAT);
   1864 
   1865 		/* initialize the codec */
   1866 		if (newchd->codecintf[0]->init != NULL)
   1867 		{
   1868 			err = (*newchd->codecintf[0]->init)(&newchd->zlib_codec_data, newchd->header.hunkbytes);
   1869 			if (err != CHDERR_NONE)
   1870 				EARLY_EXIT(err);
   1871 		}
   1872 	}
   1873 	else
   1874 	{
   1875 		int decompnum;
   1876 		/* verify the compression types and initialize the codecs */
   1877 		for (decompnum = 0; decompnum < ARRAY_LENGTH(newchd->header.compression); decompnum++)
   1878 		{
   1879 			int i;
   1880 			for (i = 0 ; i < ARRAY_LENGTH(codec_interfaces) ; i++)
   1881 			{
   1882 				if (codec_interfaces[i].compression == newchd->header.compression[decompnum])
   1883 				{
   1884 					newchd->codecintf[decompnum] = &codec_interfaces[i];
   1885 					break;
   1886 				}
   1887 			}
   1888 
   1889 			if (newchd->codecintf[decompnum] == NULL && newchd->header.compression[decompnum] != 0)
   1890 				EARLY_EXIT(err = CHDERR_UNSUPPORTED_FORMAT);
   1891 
   1892 			/* initialize the codec */
   1893 			if (newchd->codecintf[decompnum]->init != NULL)
   1894 			{
   1895 				void* codec = NULL;
   1896 				switch (newchd->header.compression[decompnum])
   1897 				{
   1898 					case CHD_CODEC_ZLIB:
   1899 						codec = &newchd->zlib_codec_data;
   1900 						break;
   1901 
   1902 					case CHD_CODEC_LZMA:
   1903 						codec = &newchd->lzma_codec_data;
   1904 						break;
   1905 
   1906 					case CHD_CODEC_HUFFMAN:
   1907 						codec = &newchd->huff_codec_data;
   1908 						break;
   1909 
   1910 					case CHD_CODEC_FLAC:
   1911 						codec = &newchd->flac_codec_data;
   1912 						break;
   1913 
   1914 					case CHD_CODEC_ZSTD:
   1915 						codec = &newchd->zstd_codec_data;
   1916 						break;
   1917 
   1918 					case CHD_CODEC_CD_ZLIB:
   1919 						codec = &newchd->cdzl_codec_data;
   1920 						break;
   1921 
   1922 					case CHD_CODEC_CD_LZMA:
   1923 						codec = &newchd->cdlz_codec_data;
   1924 						break;
   1925 
   1926 					case CHD_CODEC_CD_FLAC:
   1927 						codec = &newchd->cdfl_codec_data;
   1928 						break;
   1929 
   1930 					case CHD_CODEC_CD_ZSTD:
   1931 						codec = &newchd->cdzs_codec_data;
   1932 						break;
   1933 				}
   1934 
   1935 				if (codec == NULL)
   1936 					EARLY_EXIT(err = CHDERR_UNSUPPORTED_FORMAT);
   1937 
   1938 				err = (*newchd->codecintf[decompnum]->init)(codec, newchd->header.hunkbytes);
   1939 				if (err != CHDERR_NONE)
   1940 					EARLY_EXIT(err);
   1941 			}
   1942 		}
   1943 	}
   1944 
   1945 	/* all done */
   1946 	*chd = newchd;
   1947 	return CHDERR_NONE;
   1948 
   1949 cleanup:
   1950 	if (newchd != NULL)
   1951 		chd_close(newchd);
   1952 	return err;
   1953 }
   1954 
   1955 /*-------------------------------------------------
   1956     chd_precache - precache underlying file in
   1957     memory
   1958 -------------------------------------------------*/
   1959 
   1960 CHD_EXPORT chd_error chd_precache(chd_file* chd)
   1961 {
   1962   return chd_precache_progress(chd, NULL, NULL);
   1963 }
   1964 
   1965 CHD_EXPORT chd_error chd_precache_progress(chd_file* chd, void(*progress)(size_t pos, size_t total, void* param), void* param)
   1966 {
   1967 #define PRECACHE_CHUNK_SIZE 16 * 1024 * 1024
   1968 
   1969   size_t count;
   1970   UINT64 size, done, req_count, last_update_done, update_interval;
   1971 
   1972   if (chd->file_cache == NULL)
   1973   {
   1974     size = core_fsize(chd->file);
   1975     if ((INT64)size <= 0)
   1976       return CHDERR_INVALID_DATA;
   1977 
   1978 		if (size > SIZE_MAX)
   1979 			return CHDERR_OUT_OF_MEMORY;
   1980 
   1981     chd->file_cache = malloc(size);
   1982     if (chd->file_cache == NULL)
   1983       return CHDERR_OUT_OF_MEMORY;
   1984     core_fseek(chd->file, 0, SEEK_SET);
   1985 
   1986 		done = 0;
   1987     last_update_done = 0;
   1988     update_interval = ((size + 99) / 100);
   1989 
   1990 		while (done < size)
   1991 		{
   1992 			req_count = size - done;
   1993 			if (req_count > PRECACHE_CHUNK_SIZE)
   1994 				req_count = PRECACHE_CHUNK_SIZE;
   1995 
   1996 			count = core_fread(chd->file, chd->file_cache + (size_t)done, (size_t)req_count);
   1997 			if (count != (size_t)req_count)
   1998 			{
   1999 				free(chd->file_cache);
   2000 				chd->file_cache = NULL;
   2001 				return CHDERR_READ_ERROR;
   2002 			}
   2003 
   2004 			done += req_count;
   2005 			if (progress != NULL && (done - last_update_done) >= update_interval && done != size)
   2006 			{
   2007 				last_update_done = done;
   2008 				progress(done, size, param);
   2009 			}
   2010 		}
   2011   }
   2012 
   2013   return CHDERR_NONE;
   2014 }
   2015 
   2016 /*-------------------------------------------------
   2017     chd_open - open a CHD file by
   2018     filename
   2019 -------------------------------------------------*/
   2020 
   2021 CHD_EXPORT chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd)
   2022 {
   2023 	chd_error err;
   2024 	core_file *file = NULL;
   2025 
   2026 	if (filename == NULL)
   2027 	{
   2028 		err = CHDERR_INVALID_PARAMETER;
   2029 		goto cleanup;
   2030 	}
   2031 
   2032 	/* choose the proper mode */
   2033 	switch(mode)
   2034 	{
   2035 		case CHD_OPEN_READ:
   2036 			break;
   2037 
   2038 		default:
   2039 			err = CHDERR_INVALID_PARAMETER;
   2040 			goto cleanup;
   2041 	}
   2042 
   2043 	/* open the file */
   2044 	file = core_stdio_fopen(filename);
   2045 	if (file == 0)
   2046 	{
   2047 		err = CHDERR_FILE_NOT_FOUND;
   2048 		goto cleanup;
   2049 	}
   2050 
   2051 	/* now open the CHD */
   2052 	return chd_open_core_file(file, mode, parent, chd);
   2053 
   2054 cleanup:
   2055 	if ((err != CHDERR_NONE) && (file != NULL))
   2056 		core_fclose(file);
   2057 	return err;
   2058 }
   2059 
   2060 /*-------------------------------------------------
   2061     chd_close - close a CHD file for access
   2062 -------------------------------------------------*/
   2063 
   2064 CHD_EXPORT void chd_close(chd_file *chd)
   2065 {
   2066 	/* punt if NULL or invalid */
   2067 	if (chd == NULL || chd->cookie != COOKIE_VALUE)
   2068 		return;
   2069 
   2070 	/* deinit the codec */
   2071 	if (chd->header.version < 5)
   2072 	{
   2073 		if (chd->codecintf[0] != NULL && chd->codecintf[0]->free != NULL)
   2074 			(*chd->codecintf[0]->free)(&chd->zlib_codec_data);
   2075 	}
   2076 	else
   2077 	{
   2078 		int i;
   2079 		/* Free the codecs */
   2080 		for (i = 0 ; i < ARRAY_LENGTH(chd->codecintf); i++)
   2081 		{
   2082 			void* codec = NULL;
   2083 
   2084 			if (chd->codecintf[i] == NULL)
   2085 				continue;
   2086 
   2087 			switch (chd->codecintf[i]->compression)
   2088 			{
   2089 				case CHD_CODEC_ZLIB:
   2090 					codec = &chd->zlib_codec_data;
   2091 					break;
   2092 
   2093 				case CHD_CODEC_LZMA:
   2094 					codec = &chd->lzma_codec_data;
   2095 					break;
   2096 
   2097 				case CHD_CODEC_HUFFMAN:
   2098 					codec = &chd->huff_codec_data;
   2099 					break;
   2100 
   2101 				case CHD_CODEC_FLAC:
   2102 					codec = &chd->flac_codec_data;
   2103 					break;
   2104 
   2105 				case CHD_CODEC_ZSTD:
   2106 					codec = &chd->zstd_codec_data;
   2107 					break;
   2108 
   2109 				case CHD_CODEC_CD_ZLIB:
   2110 					codec = &chd->cdzl_codec_data;
   2111 					break;
   2112 
   2113 				case CHD_CODEC_CD_LZMA:
   2114 					codec = &chd->cdlz_codec_data;
   2115 					break;
   2116 
   2117 				case CHD_CODEC_CD_FLAC:
   2118 					codec = &chd->cdfl_codec_data;
   2119 					break;
   2120 
   2121 				case CHD_CODEC_CD_ZSTD:
   2122 					codec = &chd->cdzs_codec_data;
   2123 					break;
   2124 			}
   2125 
   2126 			if (codec)
   2127 			{
   2128 				(*chd->codecintf[i]->free)(codec);
   2129 			}
   2130 		}
   2131 
   2132 		/* Free the raw map */
   2133 		if (chd->header.rawmap != NULL)
   2134 			free(chd->header.rawmap);
   2135 	}
   2136 
   2137 	/* free the compressed data buffer */
   2138 	if (chd->compressed != NULL)
   2139 		free(chd->compressed);
   2140 
   2141 #ifdef NEED_CACHE_HUNK
   2142 	/* free the hunk cache and compare data */
   2143 	if (chd->compare != NULL)
   2144 		free(chd->compare);
   2145 	if (chd->cache != NULL)
   2146 		free(chd->cache);
   2147 #endif
   2148 
   2149 	/* free the hunk map */
   2150 	if (chd->map != NULL)
   2151 		free(chd->map);
   2152 
   2153 	/* close the file */
   2154 	if (chd->file != NULL)
   2155 		core_fclose(chd->file);
   2156 
   2157 #ifdef NEED_CACHE_HUNK
   2158 	if (PRINTF_MAX_HUNK) printf("Max hunk = %d/%d\n", chd->maxhunk, chd->header.totalhunks);
   2159 #endif
   2160 	if (chd->file_cache)
   2161 		free(chd->file_cache);
   2162 
   2163 	if (chd->parent)
   2164 		chd_close(chd->parent);
   2165 
   2166 	/* free our memory */
   2167 	free(chd);
   2168 }
   2169 
   2170 /*-------------------------------------------------
   2171     chd_core_file - return the associated
   2172     core_file
   2173 -------------------------------------------------*/
   2174 
   2175 CHD_EXPORT core_file *chd_core_file(chd_file *chd)
   2176 {
   2177 	return chd->file;
   2178 }
   2179 
   2180 CHD_EXPORT UINT64 chd_get_compressed_size(chd_file *chd)
   2181 {
   2182 	UINT64 size = chd->file->fsize(chd->file);
   2183 	if (chd->parent)
   2184 		size += chd_get_compressed_size(chd->parent);
   2185 	return size;
   2186 }
   2187 
   2188 /*-------------------------------------------------
   2189     chd_error_string - return an error string for
   2190     the given CHD error
   2191 -------------------------------------------------*/
   2192 
   2193 CHD_EXPORT const char *chd_error_string(chd_error err)
   2194 {
   2195 	switch (err)
   2196 	{
   2197 		case CHDERR_NONE:						return "no error";
   2198 		case CHDERR_NO_INTERFACE:				return "no drive interface";
   2199 		case CHDERR_OUT_OF_MEMORY:				return "out of memory";
   2200 		case CHDERR_INVALID_FILE:				return "invalid file";
   2201 		case CHDERR_INVALID_PARAMETER:			return "invalid parameter";
   2202 		case CHDERR_INVALID_DATA:				return "invalid data";
   2203 		case CHDERR_FILE_NOT_FOUND:				return "file not found";
   2204 		case CHDERR_REQUIRES_PARENT:			return "requires parent";
   2205 		case CHDERR_FILE_NOT_WRITEABLE:			return "file not writeable";
   2206 		case CHDERR_READ_ERROR:					return "read error";
   2207 		case CHDERR_WRITE_ERROR:				return "write error";
   2208 		case CHDERR_CODEC_ERROR:				return "codec error";
   2209 		case CHDERR_INVALID_PARENT:				return "invalid parent";
   2210 		case CHDERR_HUNK_OUT_OF_RANGE:			return "hunk out of range";
   2211 		case CHDERR_DECOMPRESSION_ERROR:		return "decompression error";
   2212 		case CHDERR_COMPRESSION_ERROR:			return "compression error";
   2213 		case CHDERR_CANT_CREATE_FILE:			return "can't create file";
   2214 		case CHDERR_CANT_VERIFY:				return "can't verify file";
   2215 		case CHDERR_NOT_SUPPORTED:				return "operation not supported";
   2216 		case CHDERR_METADATA_NOT_FOUND:			return "can't find metadata";
   2217 		case CHDERR_INVALID_METADATA_SIZE:		return "invalid metadata size";
   2218 		case CHDERR_UNSUPPORTED_VERSION:		return "unsupported CHD version";
   2219 		case CHDERR_VERIFY_INCOMPLETE:			return "incomplete verify";
   2220 		case CHDERR_INVALID_METADATA:			return "invalid metadata";
   2221 		case CHDERR_INVALID_STATE:				return "invalid state";
   2222 		case CHDERR_OPERATION_PENDING:			return "operation pending";
   2223 		case CHDERR_NO_ASYNC_OPERATION:			return "no async operation in progress";
   2224 		case CHDERR_UNSUPPORTED_FORMAT:			return "unsupported format";
   2225 		default:								return "undocumented error";
   2226 	}
   2227 }
   2228 
   2229 /***************************************************************************
   2230     CHD HEADER MANAGEMENT
   2231 ***************************************************************************/
   2232 
   2233 /*-------------------------------------------------
   2234     chd_get_header - return a pointer to the
   2235     extracted header data
   2236 -------------------------------------------------*/
   2237 
   2238 CHD_EXPORT const chd_header *chd_get_header(chd_file *chd)
   2239 {
   2240 	/* punt if NULL or invalid */
   2241 	if (chd == NULL || chd->cookie != COOKIE_VALUE)
   2242 		return NULL;
   2243 
   2244 	return &chd->header;
   2245 }
   2246 
   2247 /*-------------------------------------------------
   2248     chd_read_header - read CHD header data
   2249 	from file into the pointed struct
   2250 -------------------------------------------------*/
   2251 CHD_EXPORT chd_error chd_read_header_core_file(core_file* file, chd_header* header)
   2252 {
   2253 	chd_file chd;
   2254 	chd.file = file;
   2255 
   2256 	/* attempt to read the header */
   2257 	const chd_error err = header_read(&chd, header);
   2258 	if (err != CHDERR_NONE)
   2259 		return err;
   2260 
   2261 	/* validate the header */
   2262 	return header_validate(header);
   2263 }
   2264 
   2265 CHD_EXPORT chd_error chd_read_header_file(FILE *file, chd_header *header)
   2266 {
   2267   core_file stream;
   2268   stream.argp = file;
   2269   stream.fsize = core_stdio_fsize;
   2270   stream.fread = core_stdio_fread;
   2271   stream.fclose = core_stdio_fclose_nonowner;
   2272   stream.fseek = core_stdio_fseek;
   2273 
   2274 	return chd_read_header_core_file(&stream, header);
   2275 }
   2276 
   2277 CHD_EXPORT chd_error chd_read_header(const char *filename, chd_header *header)
   2278 {
   2279 	if (filename == NULL)
   2280 		return CHDERR_INVALID_PARAMETER;
   2281 
   2282 	core_file* file = core_stdio_fopen(filename);
   2283 	if (file == NULL)
   2284 		return CHDERR_FILE_NOT_FOUND;
   2285 
   2286 	chd_error err = chd_read_header_core_file(file, header);
   2287 	
   2288 	core_fclose(file);
   2289 	return err;
   2290 }
   2291 
   2292 CHD_EXPORT bool chd_is_matching_parent(const chd_header* header, const chd_header* parent_header)
   2293 {
   2294   /* check MD5 if it isn't empty */
   2295   if (memcmp(nullmd5, header->parentmd5, sizeof(header->parentmd5)) != 0 &&
   2296       memcmp(nullmd5, parent_header->md5, sizeof(parent_header->md5)) != 0 &&
   2297       memcmp(parent_header->md5, header->parentmd5, sizeof(header->parentmd5)) != 0)
   2298 	{
   2299 		return false;
   2300 	}
   2301 
   2302   /* check SHA1 if it isn't empty */
   2303   if (memcmp(nullsha1, header->parentsha1, sizeof(header->parentsha1)) != 0 &&
   2304       memcmp(nullsha1, parent_header->sha1, sizeof(parent_header->sha1)) != 0 &&
   2305       memcmp(parent_header->sha1, header->parentsha1, sizeof(header->parentsha1)) != 0)
   2306 	{
   2307 		return false;
   2308 	}
   2309 
   2310 	return true;
   2311 }
   2312 
   2313 /***************************************************************************
   2314     CORE DATA READ/WRITE
   2315 ***************************************************************************/
   2316 
   2317 /*-------------------------------------------------
   2318     chd_read - read a single hunk from the CHD
   2319     file
   2320 -------------------------------------------------*/
   2321 
   2322 CHD_EXPORT chd_error chd_read(chd_file *chd, UINT32 hunknum, void *buffer)
   2323 {
   2324 	/* punt if NULL or invalid */
   2325 	if (chd == NULL || chd->cookie != COOKIE_VALUE)
   2326 		return CHDERR_INVALID_PARAMETER;
   2327 
   2328 	/* if we're past the end, fail */
   2329 	if (hunknum >= chd->header.totalhunks)
   2330 		return CHDERR_HUNK_OUT_OF_RANGE;
   2331 
   2332 	/* perform the read */
   2333 	return hunk_read_into_memory(chd, hunknum, (UINT8 *)buffer);
   2334 }
   2335 
   2336 /***************************************************************************
   2337     METADATA MANAGEMENT
   2338 ***************************************************************************/
   2339 
   2340 /*-------------------------------------------------
   2341     chd_get_metadata - get the indexed metadata
   2342     of the given type
   2343 -------------------------------------------------*/
   2344 
   2345 CHD_EXPORT chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 searchindex, void *output, UINT32 outputlen, UINT32 *resultlen, UINT32 *resulttag, UINT8 *resultflags)
   2346 {
   2347 	metadata_entry metaentry;
   2348 	chd_error err;
   2349 	UINT32 count;
   2350 
   2351 	/* if we didn't find it, just return */
   2352 	err = metadata_find_entry(chd, searchtag, searchindex, &metaentry);
   2353 	if (err != CHDERR_NONE)
   2354 	{
   2355 		/* unless we're an old version and they are requesting hard disk metadata */
   2356 		if (chd->header.version < 3 && (searchtag == HARD_DISK_METADATA_TAG || searchtag == CHDMETATAG_WILDCARD) && searchindex == 0)
   2357 		{
   2358 			char faux_metadata[256];
   2359 			UINT32 faux_length;
   2360 
   2361 			/* fill in the faux metadata */
   2362 			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);
   2363 			faux_length = (UINT32)strlen(faux_metadata) + 1;
   2364 
   2365 			/* copy the metadata itself */
   2366 			memcpy(output, faux_metadata, MIN(outputlen, faux_length));
   2367 
   2368 			/* return the length of the data and the tag */
   2369 			if (resultlen != NULL)
   2370 				*resultlen = faux_length;
   2371 			if (resulttag != NULL)
   2372 				*resulttag = HARD_DISK_METADATA_TAG;
   2373 			return CHDERR_NONE;
   2374 		}
   2375 		return err;
   2376 	}
   2377 
   2378 	/* read the metadata */
   2379 	outputlen = MIN(outputlen, metaentry.length);
   2380 	core_fseek(chd->file, metaentry.offset + METADATA_HEADER_SIZE, SEEK_SET);
   2381 	count = core_fread(chd->file, output, outputlen);
   2382 	if (count != outputlen)
   2383 		return CHDERR_READ_ERROR;
   2384 
   2385 	/* return the length of the data and the tag */
   2386 	if (resultlen != NULL)
   2387 		*resultlen = metaentry.length;
   2388 	if (resulttag != NULL)
   2389 		*resulttag = metaentry.metatag;
   2390 	if (resultflags != NULL)
   2391 		*resultflags = metaentry.flags;
   2392 	return CHDERR_NONE;
   2393 }
   2394 
   2395 /***************************************************************************
   2396     CODEC INTERFACES
   2397 ***************************************************************************/
   2398 
   2399 /*-------------------------------------------------
   2400     chd_codec_config - set internal codec
   2401     parameters
   2402 -------------------------------------------------*/
   2403 
   2404 CHD_EXPORT chd_error chd_codec_config(chd_file *chd, int param, void *config)
   2405 {
   2406 	return CHDERR_INVALID_PARAMETER;
   2407 }
   2408 
   2409 /*-------------------------------------------------
   2410     chd_get_codec_name - get the name of a
   2411     particular codec
   2412 -------------------------------------------------*/
   2413 
   2414 CHD_EXPORT const char *chd_get_codec_name(UINT32 codec)
   2415 {
   2416 	return "Unknown";
   2417 }
   2418 
   2419 /***************************************************************************
   2420     INTERNAL HEADER OPERATIONS
   2421 ***************************************************************************/
   2422 
   2423 /*-------------------------------------------------
   2424     header_validate - check the validity of a
   2425     CHD header
   2426 -------------------------------------------------*/
   2427 
   2428 static chd_error header_validate(const chd_header *header)
   2429 {
   2430 	int intfnum;
   2431 
   2432 	/* require a valid version */
   2433 	if (header->version == 0 || header->version > CHD_HEADER_VERSION)
   2434 		return CHDERR_UNSUPPORTED_VERSION;
   2435 
   2436 	/* require a valid length */
   2437 	if ((header->version == 1 && header->length != CHD_V1_HEADER_SIZE) ||
   2438 		(header->version == 2 && header->length != CHD_V2_HEADER_SIZE) ||
   2439 		(header->version == 3 && header->length != CHD_V3_HEADER_SIZE) ||
   2440 		(header->version == 4 && header->length != CHD_V4_HEADER_SIZE) ||
   2441 		(header->version == 5 && header->length != CHD_V5_HEADER_SIZE))
   2442 		return CHDERR_INVALID_PARAMETER;
   2443 
   2444 	/* Do not validate v5 header */
   2445 	if (header->version <= 4)
   2446 	{
   2447 		/* require valid flags */
   2448 		if (header->flags & CHDFLAGS_UNDEFINED)
   2449 			return CHDERR_INVALID_PARAMETER;
   2450 
   2451 		/* require a supported compression mechanism */
   2452 		for (intfnum = 0; intfnum < ARRAY_LENGTH(codec_interfaces); intfnum++)
   2453 			if (codec_interfaces[intfnum].compression == header->compression[0])
   2454 				break;
   2455 
   2456 		if (intfnum == ARRAY_LENGTH(codec_interfaces))
   2457 			return CHDERR_INVALID_PARAMETER;
   2458 
   2459 		/* require a valid hunksize */
   2460 		if (header->hunkbytes == 0 || header->hunkbytes >= 65536 * 256)
   2461 			return CHDERR_INVALID_PARAMETER;
   2462 
   2463 		/* require a valid hunk count */
   2464 		if (header->totalhunks == 0)
   2465 			return CHDERR_INVALID_PARAMETER;
   2466 
   2467 		/* require a valid MD5 and/or SHA1 if we're using a parent */
   2468 		if ((header->flags & CHDFLAGS_HAS_PARENT) && memcmp(header->parentmd5, nullmd5, sizeof(nullmd5)) == 0 && memcmp(header->parentsha1, nullsha1, sizeof(nullsha1)) == 0)
   2469 			return CHDERR_INVALID_PARAMETER;
   2470 
   2471 		/* if we're V3 or later, the obsolete fields must be 0 */
   2472 		if (header->version >= 3 &&
   2473 			(header->obsolete_cylinders != 0 || header->obsolete_sectors != 0 ||
   2474 			 header->obsolete_heads != 0 || header->obsolete_hunksize != 0))
   2475 			return CHDERR_INVALID_PARAMETER;
   2476 
   2477 		/* if we're pre-V3, the obsolete fields must NOT be 0 */
   2478 		if (header->version < 3 &&
   2479 			(header->obsolete_cylinders == 0 || header->obsolete_sectors == 0 ||
   2480 			 header->obsolete_heads == 0 || header->obsolete_hunksize == 0))
   2481 			return CHDERR_INVALID_PARAMETER;
   2482 	}
   2483 
   2484 	return CHDERR_NONE;
   2485 }
   2486 
   2487 /*-------------------------------------------------
   2488     header_guess_unitbytes - for older CHD formats,
   2489     guess at the bytes/unit based on metadata
   2490 -------------------------------------------------*/
   2491 
   2492 static UINT32 header_guess_unitbytes(chd_file *chd)
   2493 {
   2494 	/* look for hard disk metadata; if found, then the unit size == sector size */
   2495 	char metadata[512];
   2496 	int i0, i1, i2, i3;
   2497 	if (chd_get_metadata(chd, HARD_DISK_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE &&
   2498 		sscanf(metadata, HARD_DISK_METADATA_FORMAT, &i0, &i1, &i2, &i3) == 4)
   2499 		return i3;
   2500 
   2501 	/* look for CD-ROM metadata; if found, then the unit size == CD frame size */
   2502 	if (chd_get_metadata(chd, CDROM_OLD_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
   2503 		chd_get_metadata(chd, CDROM_TRACK_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
   2504 		chd_get_metadata(chd, CDROM_TRACK_METADATA2_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
   2505 		chd_get_metadata(chd, GDROM_OLD_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
   2506 		chd_get_metadata(chd, GDROM_TRACK_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE)
   2507 		return CD_FRAME_SIZE;
   2508 
   2509 	/* otherwise, just map 1:1 with the hunk size */
   2510 	return chd->header.hunkbytes;
   2511 }
   2512 
   2513 /*-------------------------------------------------
   2514     header_read - read a CHD header into the
   2515     internal data structure
   2516 -------------------------------------------------*/
   2517 
   2518 static chd_error header_read(chd_file *chd, chd_header *header)
   2519 {
   2520 	UINT8 rawheader[CHD_MAX_HEADER_SIZE];
   2521 	UINT32 count;
   2522 
   2523 	/* punt if NULL */
   2524 	if (header == NULL)
   2525 		return CHDERR_INVALID_PARAMETER;
   2526 
   2527 	/* punt if invalid file */
   2528 	if (chd->file == NULL)
   2529 		return CHDERR_INVALID_FILE;
   2530 
   2531 	/* seek and read */
   2532 	core_fseek(chd->file, 0, SEEK_SET);
   2533 	count = core_fread(chd->file, rawheader, sizeof(rawheader));
   2534 	if (count != sizeof(rawheader))
   2535 		return CHDERR_READ_ERROR;
   2536 
   2537 	/* verify the tag */
   2538 	if (strncmp((char *)rawheader, "MComprHD", 8) != 0)
   2539 		return CHDERR_INVALID_DATA;
   2540 
   2541 	/* extract the direct data */
   2542 	memset(header, 0, sizeof(*header));
   2543 	header->length        = get_bigendian_uint32(&rawheader[8]);
   2544 	header->version       = get_bigendian_uint32(&rawheader[12]);
   2545 
   2546 	/* make sure it's a version we understand */
   2547 	if (header->version == 0 || header->version > CHD_HEADER_VERSION)
   2548 		return CHDERR_UNSUPPORTED_VERSION;
   2549 
   2550 	/* make sure the length is expected */
   2551 	if ((header->version == 1 && header->length != CHD_V1_HEADER_SIZE) ||
   2552 		(header->version == 2 && header->length != CHD_V2_HEADER_SIZE) ||
   2553 		(header->version == 3 && header->length != CHD_V3_HEADER_SIZE) ||
   2554 		(header->version == 4 && header->length != CHD_V4_HEADER_SIZE) ||
   2555 		(header->version == 5 && header->length != CHD_V5_HEADER_SIZE))
   2556 
   2557 		return CHDERR_INVALID_DATA;
   2558 
   2559 	/* extract the common data */
   2560 	header->flags         	= get_bigendian_uint32(&rawheader[16]);
   2561 	header->compression[0]	= get_bigendian_uint32(&rawheader[20]);
   2562 	header->compression[1]	= CHD_CODEC_NONE;
   2563 	header->compression[2]	= CHD_CODEC_NONE;
   2564 	header->compression[3]	= CHD_CODEC_NONE;
   2565 
   2566 	/* extract the V1/V2-specific data */
   2567 	if (header->version < 3)
   2568 	{
   2569 		int seclen = (header->version == 1) ? CHD_V1_SECTOR_SIZE : get_bigendian_uint32(&rawheader[76]);
   2570 		header->obsolete_hunksize  = get_bigendian_uint32(&rawheader[24]);
   2571 		header->totalhunks         = get_bigendian_uint32(&rawheader[28]);
   2572 		header->obsolete_cylinders = get_bigendian_uint32(&rawheader[32]);
   2573 		header->obsolete_heads     = get_bigendian_uint32(&rawheader[36]);
   2574 		header->obsolete_sectors   = get_bigendian_uint32(&rawheader[40]);
   2575 		memcpy(header->md5, &rawheader[44], CHD_MD5_BYTES);
   2576 		memcpy(header->parentmd5, &rawheader[60], CHD_MD5_BYTES);
   2577 		header->logicalbytes = (UINT64)header->obsolete_cylinders * (UINT64)header->obsolete_heads * (UINT64)header->obsolete_sectors * (UINT64)seclen;
   2578 		header->hunkbytes = seclen * header->obsolete_hunksize;
   2579 		header->unitbytes          = header_guess_unitbytes(chd);
   2580 		if (header->unitbytes == 0)
   2581 			return CHDERR_INVALID_DATA;
   2582 		header->unitcount          = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
   2583 		header->metaoffset = 0;
   2584 	}
   2585 
   2586 	/* extract the V3-specific data */
   2587 	else if (header->version == 3)
   2588 	{
   2589 		header->totalhunks   = get_bigendian_uint32(&rawheader[24]);
   2590 		header->logicalbytes = get_bigendian_uint64(&rawheader[28]);
   2591 		header->metaoffset   = get_bigendian_uint64(&rawheader[36]);
   2592 		memcpy(header->md5, &rawheader[44], CHD_MD5_BYTES);
   2593 		memcpy(header->parentmd5, &rawheader[60], CHD_MD5_BYTES);
   2594 		header->hunkbytes    = get_bigendian_uint32(&rawheader[76]);
   2595 		header->unitbytes    = header_guess_unitbytes(chd);
   2596 		if (header->unitbytes == 0)
   2597 			return CHDERR_INVALID_DATA;
   2598 		header->unitcount    = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
   2599 		memcpy(header->sha1, &rawheader[80], CHD_SHA1_BYTES);
   2600 		memcpy(header->parentsha1, &rawheader[100], CHD_SHA1_BYTES);
   2601 	}
   2602 
   2603 	/* extract the V4-specific data */
   2604 	else if (header->version == 4)
   2605 	{
   2606 		header->totalhunks   = get_bigendian_uint32(&rawheader[24]);
   2607 		header->logicalbytes = get_bigendian_uint64(&rawheader[28]);
   2608 		header->metaoffset   = get_bigendian_uint64(&rawheader[36]);
   2609 		header->hunkbytes    = get_bigendian_uint32(&rawheader[44]);
   2610 		header->unitbytes    = header_guess_unitbytes(chd);
   2611 		if (header->unitbytes == 0)
   2612 			return CHDERR_INVALID_DATA;
   2613 		header->unitcount    = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
   2614 		memcpy(header->sha1, &rawheader[48], CHD_SHA1_BYTES);
   2615 		memcpy(header->parentsha1, &rawheader[68], CHD_SHA1_BYTES);
   2616 		memcpy(header->rawsha1, &rawheader[88], CHD_SHA1_BYTES);
   2617 	}
   2618 
   2619 	/* extract the V5-specific data */
   2620 	else if (header->version == 5)
   2621 	{
   2622 		/* TODO */
   2623 		header->compression[0]  = get_bigendian_uint32(&rawheader[16]);
   2624 		header->compression[1]  = get_bigendian_uint32(&rawheader[20]);
   2625 		header->compression[2]  = get_bigendian_uint32(&rawheader[24]);
   2626 		header->compression[3]  = get_bigendian_uint32(&rawheader[28]);
   2627 		header->logicalbytes    = get_bigendian_uint64(&rawheader[32]);
   2628 		header->mapoffset       = get_bigendian_uint64(&rawheader[40]);
   2629 		header->metaoffset      = get_bigendian_uint64(&rawheader[48]);
   2630 		header->hunkbytes       = get_bigendian_uint32(&rawheader[56]);
   2631 		if (header->hunkbytes == 0)
   2632 			return CHDERR_INVALID_DATA;
   2633 		header->hunkcount       = (header->logicalbytes + header->hunkbytes - 1) / header->hunkbytes;
   2634 		header->unitbytes       = get_bigendian_uint32(&rawheader[60]);
   2635 		if (header->unitbytes == 0)
   2636 			return CHDERR_INVALID_DATA;
   2637 		header->unitcount       = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
   2638 		memcpy(header->sha1, &rawheader[84], CHD_SHA1_BYTES);
   2639 		memcpy(header->parentsha1, &rawheader[104], CHD_SHA1_BYTES);
   2640 		memcpy(header->rawsha1, &rawheader[64], CHD_SHA1_BYTES);
   2641 
   2642 		/* determine properties of map entries */
   2643 		header->mapentrybytes = chd_compressed(header) ? 12 : 4;
   2644 
   2645 		/* hack */
   2646 		header->totalhunks 		= header->hunkcount;
   2647 	}
   2648 
   2649 	/* Unknown version */
   2650 	else
   2651 	{
   2652 		/* TODO */
   2653 	}
   2654 
   2655 	/* guess it worked */
   2656 	return CHDERR_NONE;
   2657 }
   2658 
   2659 /***************************************************************************
   2660     INTERNAL HUNK READ/WRITE
   2661 ***************************************************************************/
   2662 
   2663 /*-------------------------------------------------
   2664     hunk_read_compressed - read a compressed
   2665     hunk
   2666 -------------------------------------------------*/
   2667 
   2668 static UINT8* hunk_read_compressed(chd_file *chd, UINT64 offset, size_t size)
   2669 {
   2670 #ifdef _MSC_VER
   2671 	size_t bytes;
   2672 #else
   2673 	ssize_t bytes;
   2674 #endif
   2675 	if (chd->file_cache != NULL)
   2676 	{
   2677 		return chd->file_cache + offset;
   2678 	}
   2679 	else
   2680 	{
   2681 		core_fseek(chd->file, offset, SEEK_SET);
   2682 		bytes = core_fread(chd->file, chd->compressed, size);
   2683 		if (bytes != size)
   2684 			return NULL;
   2685 		return chd->compressed;
   2686 	}
   2687 }
   2688 
   2689 /*-------------------------------------------------
   2690     hunk_read_uncompressed - read an uncompressed
   2691     hunk
   2692 -------------------------------------------------*/
   2693 
   2694 static chd_error hunk_read_uncompressed(chd_file *chd, UINT64 offset, size_t size, UINT8 *dest)
   2695 {
   2696 #ifdef _MSC_VER
   2697 	size_t bytes;
   2698 #else
   2699 	ssize_t bytes;
   2700 #endif
   2701 	if (chd->file_cache != NULL)
   2702 	{
   2703 		memcpy(dest, chd->file_cache + offset, size);
   2704 	}
   2705 	else
   2706 	{
   2707 		core_fseek(chd->file, offset, SEEK_SET);
   2708 		bytes = core_fread(chd->file, dest, size);
   2709 		if (bytes != size)
   2710 			return CHDERR_READ_ERROR;
   2711 	}
   2712 	return CHDERR_NONE;
   2713 }
   2714 
   2715 #ifdef NEED_CACHE_HUNK
   2716 /*-------------------------------------------------
   2717     hunk_read_into_cache - read a hunk into
   2718     the CHD's hunk cache
   2719 -------------------------------------------------*/
   2720 
   2721 static chd_error hunk_read_into_cache(chd_file *chd, UINT32 hunknum)
   2722 {
   2723 	chd_error err;
   2724 
   2725 	/* track the max */
   2726 	if (hunknum > chd->maxhunk)
   2727 		chd->maxhunk = hunknum;
   2728 
   2729 	/* if we're already in the cache, we're done */
   2730 	if (chd->cachehunk == hunknum)
   2731 		return CHDERR_NONE;
   2732 	chd->cachehunk = ~0;
   2733 
   2734 	/* otherwise, read the data */
   2735 	err = hunk_read_into_memory(chd, hunknum, chd->cache);
   2736 	if (err != CHDERR_NONE)
   2737 		return err;
   2738 
   2739 	/* mark the hunk successfully cached in */
   2740 	chd->cachehunk = hunknum;
   2741 	return CHDERR_NONE;
   2742 }
   2743 #endif
   2744 
   2745 /*-------------------------------------------------
   2746     hunk_read_into_memory - read a hunk into
   2747     memory at the given location
   2748 -------------------------------------------------*/
   2749 
   2750 static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *dest)
   2751 {
   2752 	chd_error err;
   2753 
   2754 	/* punt if no file */
   2755 	if (chd->file == NULL)
   2756 		return CHDERR_INVALID_FILE;
   2757 
   2758 	/* return an error if out of range */
   2759 	if (hunknum >= chd->header.totalhunks)
   2760 		return CHDERR_HUNK_OUT_OF_RANGE;
   2761 
   2762 	if (dest == NULL)
   2763 		return CHDERR_INVALID_PARAMETER;
   2764 
   2765 	if (chd->header.version < 5)
   2766 	{
   2767 		map_entry *entry = &chd->map[hunknum];
   2768 		UINT32 bytes;
   2769 		UINT8* compressed_bytes;
   2770 
   2771 		/* switch off the entry type */
   2772 		switch (entry->flags & MAP_ENTRY_FLAG_TYPE_MASK)
   2773 		{
   2774 			/* compressed data */
   2775 			case V34_MAP_ENTRY_TYPE_COMPRESSED:
   2776             {
   2777                void *codec = NULL;
   2778 
   2779 				/* read it into the decompression buffer */
   2780 				compressed_bytes = hunk_read_compressed(chd, entry->offset, entry->length);
   2781 				if (compressed_bytes == NULL)
   2782 					{
   2783 					return CHDERR_READ_ERROR;
   2784 					}
   2785 
   2786 				/* now decompress using the codec */
   2787 				err = CHDERR_NONE;
   2788 				codec = &chd->zlib_codec_data;
   2789 				if (chd->codecintf[0]->decompress != NULL)
   2790 					err = (*chd->codecintf[0]->decompress)(codec, compressed_bytes, entry->length, dest, chd->header.hunkbytes);
   2791 				if (err != CHDERR_NONE)
   2792 					return err;
   2793 				break;
   2794 			}
   2795 
   2796 			/* uncompressed data */
   2797 			case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
   2798 				err = hunk_read_uncompressed(chd, entry->offset, chd->header.hunkbytes, dest);
   2799 				if (err != CHDERR_NONE)
   2800 					return err;
   2801 				break;
   2802 
   2803 			/* mini-compressed data */
   2804 			case V34_MAP_ENTRY_TYPE_MINI:
   2805 				put_bigendian_uint64(&dest[0], entry->offset);
   2806 				for (bytes = 8; bytes < chd->header.hunkbytes; bytes++)
   2807 					dest[bytes] = dest[bytes - 8];
   2808 				break;
   2809 
   2810 			/* self-referenced data */
   2811 			case V34_MAP_ENTRY_TYPE_SELF_HUNK:
   2812 #ifdef NEED_CACHE_HUNK
   2813 				if (chd->cachehunk == entry->offset && dest == chd->cache)
   2814 					break;
   2815 #endif
   2816 				return hunk_read_into_memory(chd, entry->offset, dest);
   2817 
   2818 			/* parent-referenced data */
   2819 			case V34_MAP_ENTRY_TYPE_PARENT_HUNK:
   2820 				err = hunk_read_into_memory(chd->parent, entry->offset, dest);
   2821 				if (err != CHDERR_NONE)
   2822 					return err;
   2823 				break;
   2824 		}
   2825 		return CHDERR_NONE;
   2826 	}
   2827 	else
   2828 	{
   2829 		void* codec = NULL;
   2830 		/* get a pointer to the map entry */
   2831 		uint64_t blockoffs;
   2832 		uint32_t blocklen;
   2833 #ifdef VERIFY_BLOCK_CRC
   2834 		uint16_t blockcrc;
   2835 #endif
   2836 		uint8_t *rawmap = &chd->header.rawmap[chd->header.mapentrybytes * hunknum];
   2837 		UINT8* compressed_bytes;
   2838 
   2839 		/* uncompressed case */
   2840 		if (!chd_compressed(&chd->header))
   2841 		{
   2842 			blockoffs = (uint64_t)get_bigendian_uint32(rawmap) * (uint64_t)chd->header.hunkbytes;
   2843 			if (blockoffs != 0) {
   2844 				core_fseek(chd->file, blockoffs, SEEK_SET);
   2845 				int result = core_fread(chd->file, dest, chd->header.hunkbytes);
   2846 			/* TODO
   2847 			else if (m_parent_missing)
   2848 				throw CHDERR_REQUIRES_PARENT; */
   2849 			} else if (chd->parent) {
   2850 				err = hunk_read_into_memory(chd->parent, hunknum, dest);
   2851 				if (err != CHDERR_NONE)
   2852 					return err;
   2853 			} else {
   2854 				memset(dest, 0, chd->header.hunkbytes);
   2855 			}
   2856 
   2857 			return CHDERR_NONE;
   2858 		}
   2859 
   2860 		/* compressed case */
   2861 		blocklen = get_bigendian_uint24(&rawmap[1]);
   2862 		blockoffs = get_bigendian_uint48(&rawmap[4]);
   2863 #ifdef VERIFY_BLOCK_CRC
   2864 		blockcrc = get_bigendian_uint16(&rawmap[10]);
   2865 #endif
   2866 		codec = NULL;
   2867 		switch (rawmap[0])
   2868 		{
   2869 			case COMPRESSION_TYPE_0:
   2870 			case COMPRESSION_TYPE_1:
   2871 			case COMPRESSION_TYPE_2:
   2872 			case COMPRESSION_TYPE_3:
   2873 				compressed_bytes = hunk_read_compressed(chd, blockoffs, blocklen);
   2874 				if (compressed_bytes == NULL)
   2875 					return CHDERR_READ_ERROR;
   2876 				switch (chd->codecintf[rawmap[0]]->compression)
   2877 				{
   2878 					case CHD_CODEC_ZLIB:
   2879 						codec = &chd->zlib_codec_data;
   2880 						break;
   2881 
   2882 					case CHD_CODEC_LZMA:
   2883 						codec = &chd->lzma_codec_data;
   2884 						break;
   2885 
   2886 					case CHD_CODEC_HUFFMAN:
   2887 						codec = &chd->huff_codec_data;
   2888 						break;
   2889 
   2890 					case CHD_CODEC_FLAC:
   2891 						codec = &chd->flac_codec_data;
   2892 						break;
   2893 
   2894 					case CHD_CODEC_ZSTD:
   2895 						codec = &chd->zstd_codec_data;
   2896 						break;
   2897 
   2898 					case CHD_CODEC_CD_ZLIB:
   2899 						codec = &chd->cdzl_codec_data;
   2900 						break;
   2901 
   2902 					case CHD_CODEC_CD_LZMA:
   2903 						codec = &chd->cdlz_codec_data;
   2904 						break;
   2905 
   2906 					case CHD_CODEC_CD_FLAC:
   2907 						codec = &chd->cdfl_codec_data;
   2908 						break;
   2909 
   2910 					case CHD_CODEC_CD_ZSTD:
   2911 						codec = &chd->cdzs_codec_data;
   2912 						break;
   2913 				}
   2914 				if (codec==NULL)
   2915 					return CHDERR_CODEC_ERROR;
   2916 				err = chd->codecintf[rawmap[0]]->decompress(codec, compressed_bytes, blocklen, dest, chd->header.hunkbytes);
   2917 				if (err != CHDERR_NONE)
   2918 					return err;
   2919 #ifdef VERIFY_BLOCK_CRC
   2920 				if (crc16(dest, chd->header.hunkbytes) != blockcrc)
   2921 					return CHDERR_DECOMPRESSION_ERROR;
   2922 #endif
   2923 				return CHDERR_NONE;
   2924 
   2925 			case COMPRESSION_NONE:
   2926 				err = hunk_read_uncompressed(chd, blockoffs, blocklen, dest);
   2927 				if (err != CHDERR_NONE)
   2928 					return err;
   2929 #ifdef VERIFY_BLOCK_CRC
   2930 				if (crc16(dest, chd->header.hunkbytes) != blockcrc)
   2931 					return CHDERR_DECOMPRESSION_ERROR;
   2932 #endif
   2933 				return CHDERR_NONE;
   2934 
   2935 			case COMPRESSION_SELF:
   2936 				return hunk_read_into_memory(chd, blockoffs, dest);
   2937 
   2938 			case COMPRESSION_PARENT:
   2939 				if (chd->parent == NULL)
   2940 					return CHDERR_REQUIRES_PARENT;
   2941 				UINT8 units_in_hunk = chd->header.hunkbytes / chd->header.unitbytes;
   2942 
   2943 				/* blockoffs is aligned to units_in_hunk */
   2944 				if (blockoffs % units_in_hunk == 0) {
   2945 					return hunk_read_into_memory(chd->parent, blockoffs / units_in_hunk, dest);
   2946 				/* blockoffs is not aligned to units_in_hunk */
   2947 				} else {
   2948 					UINT32 unit_in_hunk = blockoffs % units_in_hunk;
   2949 					UINT8 *buf = malloc(chd->header.hunkbytes);
   2950 					/* Read first half of hunk which contains blockoffs */
   2951 					err = hunk_read_into_memory(chd->parent, blockoffs / units_in_hunk, buf);
   2952 					if (err != CHDERR_NONE) {
   2953 						free(buf);
   2954 						return err;
   2955 					}
   2956 					memcpy(dest, buf + unit_in_hunk * chd->header.unitbytes, (units_in_hunk - unit_in_hunk) * chd->header.unitbytes);
   2957 					/* Read second half of hunk which contains blockoffs */
   2958 					err = hunk_read_into_memory(chd->parent, (blockoffs / units_in_hunk) + 1, buf);
   2959 					if (err != CHDERR_NONE) {
   2960 						free(buf);
   2961 						return err;
   2962 					}
   2963 					memcpy(dest + (units_in_hunk - unit_in_hunk) * chd->header.unitbytes, buf, unit_in_hunk * chd->header.unitbytes);
   2964 					free(buf);
   2965 				}
   2966 		}
   2967 		return CHDERR_NONE;
   2968 	}
   2969 
   2970 	/* We should not reach this code */
   2971 	return CHDERR_DECOMPRESSION_ERROR;
   2972 }
   2973 
   2974 /***************************************************************************
   2975     INTERNAL MAP ACCESS
   2976 ***************************************************************************/
   2977 
   2978 /*-------------------------------------------------
   2979     map_read - read the initial sector map
   2980 -------------------------------------------------*/
   2981 
   2982 static chd_error map_read(chd_file *chd)
   2983 {
   2984 	UINT32 entrysize = (chd->header.version < 3) ? OLD_MAP_ENTRY_SIZE : MAP_ENTRY_SIZE;
   2985 	UINT8 raw_map_entries[MAP_STACK_ENTRIES * MAP_ENTRY_SIZE];
   2986 	UINT64 fileoffset, maxoffset = 0;
   2987 	UINT8 cookie[MAP_ENTRY_SIZE];
   2988 	UINT32 count;
   2989 	chd_error err;
   2990 	UINT32 i;
   2991 
   2992 	/* first allocate memory */
   2993 	chd->map = (map_entry *)malloc(sizeof(chd->map[0]) * chd->header.totalhunks);
   2994 	if (!chd->map)
   2995 		return CHDERR_OUT_OF_MEMORY;
   2996 
   2997 	/* read the map entries in in chunks and extract to the map list */
   2998 	fileoffset = chd->header.length;
   2999 	for (i = 0; i < chd->header.totalhunks; i += MAP_STACK_ENTRIES)
   3000 	{
   3001 		/* compute how many entries this time */
   3002 		int entries = chd->header.totalhunks - i, j;
   3003 		if (entries > MAP_STACK_ENTRIES)
   3004 			entries = MAP_STACK_ENTRIES;
   3005 
   3006 		/* read that many */
   3007 		core_fseek(chd->file, fileoffset, SEEK_SET);
   3008 		count = core_fread(chd->file, raw_map_entries, entries * entrysize);
   3009 		if (count != entries * entrysize)
   3010 		{
   3011 			err = CHDERR_READ_ERROR;
   3012 			goto cleanup;
   3013 		}
   3014 		fileoffset += entries * entrysize;
   3015 
   3016 		/* process that many */
   3017 		if (entrysize == MAP_ENTRY_SIZE)
   3018 		{
   3019 			for (j = 0; j < entries; j++)
   3020 				map_extract(&raw_map_entries[j * MAP_ENTRY_SIZE], &chd->map[i + j]);
   3021 		}
   3022 		else
   3023 		{
   3024 			for (j = 0; j < entries; j++)
   3025 				map_extract_old(&raw_map_entries[j * OLD_MAP_ENTRY_SIZE], &chd->map[i + j], chd->header.hunkbytes);
   3026 		}
   3027 
   3028 		/* track the maximum offset */
   3029 		for (j = 0; j < entries; j++)
   3030 			if ((chd->map[i + j].flags & MAP_ENTRY_FLAG_TYPE_MASK) == V34_MAP_ENTRY_TYPE_COMPRESSED ||
   3031 				(chd->map[i + j].flags & MAP_ENTRY_FLAG_TYPE_MASK) == V34_MAP_ENTRY_TYPE_UNCOMPRESSED)
   3032 				maxoffset = MAX(maxoffset, chd->map[i + j].offset + chd->map[i + j].length);
   3033 	}
   3034 
   3035 	/* verify the cookie */
   3036 	core_fseek(chd->file, fileoffset, SEEK_SET);
   3037 	count = core_fread(chd->file, &cookie, entrysize);
   3038 	if (count != entrysize || memcmp(&cookie, END_OF_LIST_COOKIE, entrysize))
   3039 	{
   3040 		err = CHDERR_INVALID_FILE;
   3041 		goto cleanup;
   3042 	}
   3043 
   3044 	/* verify the length */
   3045 	if (maxoffset > core_fsize(chd->file))
   3046 	{
   3047 		err = CHDERR_INVALID_FILE;
   3048 		goto cleanup;
   3049 	}
   3050 	return CHDERR_NONE;
   3051 
   3052 cleanup:
   3053 	if (chd->map)
   3054 		free(chd->map);
   3055 	chd->map = NULL;
   3056 	return err;
   3057 }
   3058 
   3059 /***************************************************************************
   3060     INTERNAL METADATA ACCESS
   3061 ***************************************************************************/
   3062 
   3063 /*-------------------------------------------------
   3064     metadata_find_entry - find a metadata entry
   3065 -------------------------------------------------*/
   3066 
   3067 static chd_error metadata_find_entry(chd_file *chd, UINT32 metatag, UINT32 metaindex, metadata_entry *metaentry)
   3068 {
   3069 	/* start at the beginning */
   3070 	metaentry->offset = chd->header.metaoffset;
   3071 	metaentry->prev = 0;
   3072 
   3073 	/* loop until we run out of options */
   3074 	while (metaentry->offset != 0)
   3075 	{
   3076 		UINT8	raw_meta_header[METADATA_HEADER_SIZE];
   3077 		UINT32	count;
   3078 
   3079 		/* read the raw header */
   3080 		core_fseek(chd->file, metaentry->offset, SEEK_SET);
   3081 		count = core_fread(chd->file, raw_meta_header, sizeof(raw_meta_header));
   3082 		if (count != sizeof(raw_meta_header))
   3083 			break;
   3084 
   3085 		/* extract the data */
   3086 		metaentry->metatag = get_bigendian_uint32(&raw_meta_header[0]);
   3087 		metaentry->length = get_bigendian_uint32(&raw_meta_header[4]);
   3088 		metaentry->next = get_bigendian_uint64(&raw_meta_header[8]);
   3089 
   3090 		/* flags are encoded in the high byte of length */
   3091 		metaentry->flags = metaentry->length >> 24;
   3092 		metaentry->length &= 0x00ffffff;
   3093 
   3094 		/* if we got a match, proceed */
   3095 		if (metatag == CHDMETATAG_WILDCARD || metaentry->metatag == metatag)
   3096 			if (metaindex-- == 0)
   3097 				return CHDERR_NONE;
   3098 
   3099 		/* no match, fetch the next link */
   3100 		metaentry->prev = metaentry->offset;
   3101 		metaentry->offset = metaentry->next;
   3102 	}
   3103 
   3104 	/* if we get here, we didn't find it */
   3105 	return CHDERR_METADATA_NOT_FOUND;
   3106 }
   3107 
   3108 /***************************************************************************
   3109     ZLIB COMPRESSION CODEC
   3110 ***************************************************************************/
   3111 
   3112 /*-------------------------------------------------
   3113     zlib_codec_init - initialize the ZLIB codec
   3114 -------------------------------------------------*/
   3115 
   3116 static chd_error zlib_codec_init(void *codec, uint32_t hunkbytes)
   3117 {
   3118 	int zerr;
   3119 	chd_error err;
   3120 	zlib_codec_data *data = (zlib_codec_data*)codec;
   3121 
   3122 	/* clear the buffers */
   3123 	memset(data, 0, sizeof(zlib_codec_data));
   3124 
   3125 	/* init the inflater first */
   3126 	data->inflater.next_in = (Bytef *)data;	/* bogus, but that's ok */
   3127 	data->inflater.avail_in = 0;
   3128 	data->inflater.zalloc = zlib_fast_alloc;
   3129 	data->inflater.zfree = zlib_fast_free;
   3130 	data->inflater.opaque = &data->allocator;
   3131 	zerr = inflateInit2(&data->inflater, -MAX_WBITS);
   3132 
   3133 	/* convert errors */
   3134 	if (zerr == Z_MEM_ERROR)
   3135 		err = CHDERR_OUT_OF_MEMORY;
   3136 	else if (zerr != Z_OK)
   3137 		err = CHDERR_CODEC_ERROR;
   3138 	else
   3139 		err = CHDERR_NONE;
   3140 
   3141 	return err;
   3142 }
   3143 
   3144 /*-------------------------------------------------
   3145     zlib_codec_free - free data for the ZLIB
   3146     codec
   3147 -------------------------------------------------*/
   3148 
   3149 static void zlib_codec_free(void *codec)
   3150 {
   3151 	zlib_codec_data *data = (zlib_codec_data *)codec;
   3152 
   3153 	/* deinit the streams */
   3154 	if (data != NULL)
   3155 	{
   3156 		inflateEnd(&data->inflater);
   3157 
   3158 		/* free our fast memory */
   3159 		zlib_allocator_free(&data->allocator);
   3160 	}
   3161 }
   3162 
   3163 /*-------------------------------------------------
   3164     zlib_codec_decompress - decompress data using
   3165     the ZLIB codec
   3166 -------------------------------------------------*/
   3167 
   3168 static chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
   3169 {
   3170 	zlib_codec_data *data = (zlib_codec_data *)codec;
   3171 	int zerr;
   3172 
   3173 	/* reset the decompressor */
   3174 	data->inflater.next_in = (Bytef *)src;
   3175 	data->inflater.avail_in = complen;
   3176 	data->inflater.total_in = 0;
   3177 	data->inflater.next_out = (Bytef *)dest;
   3178 	data->inflater.avail_out = destlen;
   3179 	data->inflater.total_out = 0;
   3180 	zerr = inflateReset(&data->inflater);
   3181 	if (zerr != Z_OK)
   3182 		return CHDERR_DECOMPRESSION_ERROR;
   3183 
   3184 	/* do it */
   3185 	zerr = inflate(&data->inflater, Z_FINISH);
   3186 	if (data->inflater.total_out != destlen)
   3187 		return CHDERR_DECOMPRESSION_ERROR;
   3188 
   3189 	return CHDERR_NONE;
   3190 }
   3191 
   3192 /*-------------------------------------------------
   3193     zlib_fast_alloc - fast malloc for ZLIB, which
   3194     allocates and frees memory frequently
   3195 -------------------------------------------------*/
   3196 
   3197 /* Huge alignment values for possible SIMD optimization by compiler (NEON, SSE, AVX) */
   3198 #define ZLIB_MIN_ALIGNMENT_BITS 512
   3199 #define ZLIB_MIN_ALIGNMENT_BYTES (ZLIB_MIN_ALIGNMENT_BITS / 8)
   3200 
   3201 static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
   3202 {
   3203 	zlib_allocator *alloc = (zlib_allocator *)opaque;
   3204 	uintptr_t paddr = 0;
   3205 	UINT32 *ptr;
   3206 	int i;
   3207 
   3208 	/* compute the size, rounding to the nearest 1k */
   3209 	size = (size * items + 0x3ff) & ~0x3ff;
   3210 
   3211 	/* reuse a hunk if we can */
   3212 	for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
   3213 	{
   3214 		ptr = alloc->allocptr[i];
   3215 		if (ptr && size == *ptr)
   3216 		{
   3217 			/* set the low bit of the size so we don't match next time */
   3218 			*ptr |= 1;
   3219 
   3220 			/* return aligned block address */
   3221 			return (voidpf)(alloc->allocptr2[i]);
   3222 		}
   3223 	}
   3224 
   3225 	/* alloc a new one */
   3226     ptr = (UINT32 *)malloc(size + sizeof(UINT32) + ZLIB_MIN_ALIGNMENT_BYTES);
   3227 	if (!ptr)
   3228 		return NULL;
   3229 
   3230 	/* put it into the list */
   3231 	for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
   3232 		if (!alloc->allocptr[i])
   3233 		{
   3234 			alloc->allocptr[i] = ptr;
   3235 			paddr = (((uintptr_t)ptr) + sizeof(UINT32) + (ZLIB_MIN_ALIGNMENT_BYTES-1)) & (~(ZLIB_MIN_ALIGNMENT_BYTES-1));
   3236 			alloc->allocptr2[i] = (uint32_t*)paddr;
   3237 			break;
   3238 		}
   3239 
   3240 	/* set the low bit of the size so we don't match next time */
   3241 	*ptr = size | 1;
   3242 
   3243 	/* return aligned block address */
   3244 	return (voidpf)paddr;
   3245 }
   3246 
   3247 /*-------------------------------------------------
   3248     zlib_fast_free - fast free for ZLIB, which
   3249     allocates and frees memory frequently
   3250 -------------------------------------------------*/
   3251 
   3252 static void zlib_fast_free(voidpf opaque, voidpf address)
   3253 {
   3254 	zlib_allocator *alloc = (zlib_allocator *)opaque;
   3255 	UINT32 *ptr = (UINT32 *)address;
   3256 	int i;
   3257 
   3258 	/* find the hunk */
   3259 	for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
   3260 		if (ptr == alloc->allocptr2[i])
   3261 		{
   3262 			/* clear the low bit of the size to allow matches */
   3263 			*(alloc->allocptr[i]) &= ~1;
   3264 			return;
   3265 		}
   3266 }
   3267 
   3268 /*-------------------------------------------------
   3269     zlib_allocator_free
   3270 -------------------------------------------------*/
   3271 static void zlib_allocator_free(voidpf opaque)
   3272 {
   3273 	zlib_allocator *alloc = (zlib_allocator *)opaque;
   3274 	int i;
   3275 
   3276 	for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
   3277 		if (alloc->allocptr[i])
   3278 			free(alloc->allocptr[i]);
   3279 }
   3280 
   3281 /*-------------------------------------------------
   3282 	core_stdio_fopen - core_file wrapper over fopen
   3283 -------------------------------------------------*/
   3284 static core_file *core_stdio_fopen(char const *path) {
   3285 	core_file *file = malloc(sizeof(core_file));
   3286 	if (!file)
   3287 		return NULL;
   3288 	if (!(file->argp = fopen(path, "rb"))) {
   3289 		free(file);
   3290 		return NULL;
   3291 	}
   3292 	file->fsize = core_stdio_fsize;
   3293 	file->fread = core_stdio_fread;
   3294 	file->fclose = core_stdio_fclose;
   3295 	file->fseek = core_stdio_fseek;
   3296 	return file;
   3297 }
   3298 
   3299 /*-------------------------------------------------
   3300 	core_stdio_fsize - core_file function for
   3301 	getting file size with stdio
   3302 -------------------------------------------------*/
   3303 static UINT64 core_stdio_fsize(core_file *file) {
   3304 #if defined USE_LIBRETRO_VFS
   3305 	#define core_stdio_fseek_impl fseek
   3306 	#define core_stdio_ftell_impl ftell
   3307 #elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WIN64__)
   3308 	#define core_stdio_fseek_impl _fseeki64
   3309 	#define core_stdio_ftell_impl _ftelli64
   3310 #elif defined(_LARGEFILE_SOURCE) && defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
   3311 	#define core_stdio_fseek_impl fseeko64
   3312 	#define core_stdio_ftell_impl ftello64
   3313 #elif defined(__PS3__) && !defined(__PSL1GHT__) || defined(__SWITCH__) || defined(__vita__)
   3314 	#define core_stdio_fseek_impl(x,y,z) fseek(x,(off_t)y,z)
   3315 	#define core_stdio_ftell_impl(x) (off_t)ftell(x)
   3316 #else
   3317 	#define core_stdio_fseek_impl fseeko
   3318 	#define core_stdio_ftell_impl ftello
   3319 #endif
   3320 	FILE *fp;
   3321 	UINT64 p, rv;
   3322 	fp = (FILE*)file->argp;
   3323 
   3324 	p = core_stdio_ftell_impl(fp);
   3325 	core_stdio_fseek_impl(fp, 0, SEEK_END);
   3326 	rv = core_stdio_ftell_impl(fp);
   3327 	core_stdio_fseek_impl(fp, p, SEEK_SET);
   3328 	return rv;
   3329 }
   3330 
   3331 /*-------------------------------------------------
   3332 	core_stdio_fread - core_file wrapper over fread
   3333 -------------------------------------------------*/
   3334 static size_t core_stdio_fread(void *ptr, size_t size, size_t nmemb, core_file *file) {
   3335 	return fread(ptr, size, nmemb, (FILE*)file->argp);
   3336 }
   3337 
   3338 /*-------------------------------------------------
   3339 	core_stdio_fclose - core_file wrapper over fclose
   3340 -------------------------------------------------*/
   3341 static int core_stdio_fclose(core_file *file) {
   3342 	int err = fclose((FILE*)file->argp);
   3343 	if (err == 0)
   3344 		free(file);
   3345 	return err;
   3346 }
   3347 
   3348 /*-------------------------------------------------
   3349 	core_stdio_fclose_nonowner - don't call fclose because
   3350 		we don't own the underlying file, but do free the
   3351 		core_file because libchdr did allocate that itself.
   3352 -------------------------------------------------*/
   3353 static int core_stdio_fclose_nonowner(core_file *file) {
   3354 	free(file);
   3355 	return 0;
   3356 }
   3357 
   3358 /*-------------------------------------------------
   3359 	core_stdio_fseek - core_file wrapper over fclose
   3360 -------------------------------------------------*/
   3361 static int core_stdio_fseek(core_file* file, INT64 offset, int whence) {
   3362 	return core_stdio_fseek_impl((FILE*)file->argp, offset, whence);
   3363 }