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