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