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