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