Update libchdr (replace libflac with dr_flac)
[pcsx_rearmed.git] / deps / libchdr / src / libchdr_chd.c
CommitLineData
ce188d4d 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***************************************************************************/
ce188d4d 39
9c659ffe 40#include <stddef.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <time.h>
2ff0b512 45
46#include <libchdr/chd.h>
47#include <libchdr/cdrom.h>
48#include <libchdr/flac.h>
49#include <libchdr/huffman.h>
50
ce188d4d 51#include "LzmaEnc.h"
52#include "LzmaDec.h"
9c659ffe 53#include "zlib.h"
ce188d4d 54
2ff0b512 55#undef TRUE
56#undef FALSE
ce188d4d 57#define TRUE 1
58#define FALSE 0
59
2ff0b512 60#undef MAX
61#undef MIN
ce188d4d 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
ce188d4d 67/***************************************************************************
68 DEBUGGING
69***************************************************************************/
70
71#define PRINTF_MAX_HUNK (0)
72
ce188d4d 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 */
ce188d4d 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
2ff0b512 94#ifdef WANT_RAW_DATA_SECTOR
ce188d4d 95static const uint8_t s_cd_sync_header[12] = { 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 };
2ff0b512 96#endif
ce188d4d 97
9c659ffe 98/* V3-V4 entry types */
ce188d4d 99enum
100{
9c659ffe 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) */
ce188d4d 108};
109
9c659ffe 110/* V5 compression types */
ce188d4d 111enum
112{
9c659ffe 113 /* codec #0
114 * these types are live when running */
ce188d4d 115 COMPRESSION_TYPE_0 = 0,
9c659ffe 116 /* codec #1 */
ce188d4d 117 COMPRESSION_TYPE_1 = 1,
9c659ffe 118 /* codec #2 */
ce188d4d 119 COMPRESSION_TYPE_2 = 2,
9c659ffe 120 /* codec #3 */
ce188d4d 121 COMPRESSION_TYPE_3 = 3,
9c659ffe 122 /* no compression; implicit length = hunkbytes */
ce188d4d 123 COMPRESSION_NONE = 4,
9c659ffe 124 /* same as another block in this chd */
ce188d4d 125 COMPRESSION_SELF = 5,
9c659ffe 126 /* same as a hunk's worth of units in the parent chd */
ce188d4d 127 COMPRESSION_PARENT = 6,
128
9c659ffe 129 /* start of small RLE run (4-bit length)
130 * these additional pseudo-types are used for compressed encodings: */
ce188d4d 131 COMPRESSION_RLE_SMALL,
9c659ffe 132 /* start of large RLE run (8-bit length) */
ce188d4d 133 COMPRESSION_RLE_LARGE,
9c659ffe 134 /* same as the last COMPRESSION_SELF block */
ce188d4d 135 COMPRESSION_SELF_0,
9c659ffe 136 /* same as the last COMPRESSION_SELF block + 1 */
ce188d4d 137 COMPRESSION_SELF_1,
9c659ffe 138 /* same block in the parent */
ce188d4d 139 COMPRESSION_PARENT_SELF,
9c659ffe 140 /* same as the last COMPRESSION_PARENT block */
ce188d4d 141 COMPRESSION_PARENT_0,
9c659ffe 142 /* same as the last COMPRESSION_PARENT block + 1 */
ce188d4d 143 COMPRESSION_PARENT_1
144};
145
ce188d4d 146/***************************************************************************
147 MACROS
148***************************************************************************/
149
150#define EARLY_EXIT(x) do { (void)(x); goto cleanup; } while (0)
151
ce188d4d 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
ce188d4d 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
ce188d4d 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];
dcd8e4fd 197 UINT32 * allocptr2[MAX_ZLIB_ALLOCS];
ce188d4d 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];
dcd8e4fd 217 uint32_t* allocptr2[MAX_LZMA_ALLOCS];
ce188d4d 218};
219
220typedef struct _lzma_codec_data lzma_codec_data;
9c659ffe 221struct _lzma_codec_data
ce188d4d 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 {
9c659ffe 230 /* internal state */
ce188d4d 231 zlib_codec_data base_decompressor;
2ff0b512 232#ifdef WANT_SUBCODE
ce188d4d 233 zlib_codec_data subcode_decompressor;
2ff0b512 234#endif
ce188d4d 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 {
9c659ffe 241 /* internal state */
ce188d4d 242 lzma_codec_data base_decompressor;
2ff0b512 243#ifdef WANT_SUBCODE
ce188d4d 244 zlib_codec_data subcode_decompressor;
2ff0b512 245#endif
ce188d4d 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 {
9c659ffe 252 /* internal state */
ce188d4d 253 int swap_endian;
254 flac_decoder decoder;
2ff0b512 255#ifdef WANT_SUBCODE
256 zlib_codec_data subcode_decompressor;
257#endif
ce188d4d 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
2ff0b512 274#ifdef NEED_CACHE_HUNK
ce188d4d 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 */
2ff0b512 280#endif
ce188d4d 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
2ff0b512 290#ifdef NEED_CACHE_HUNK
ce188d4d 291 UINT32 maxhunk; /* maximum hunk accessed */
2ff0b512 292#endif
ce188d4d 293
9c659ffe 294 UINT8 * file_cache; /* cache of underlying file */
ce188d4d 295};
296
ce188d4d 297
ce188d4d 298/***************************************************************************
299 GLOBAL VARIABLES
300***************************************************************************/
301
302static const UINT8 nullmd5[CHD_MD5_BYTES] = { 0 };
303static const UINT8 nullsha1[CHD_SHA1_BYTES] = { 0 };
304
ce188d4d 305/***************************************************************************
306 PROTOTYPES
307***************************************************************************/
308
309/* internal header operations */
310static chd_error header_validate(const chd_header *header);
9c659ffe 311static chd_error header_read(chd_file *chd, chd_header *header);
ce188d4d 312
313/* internal hunk read/write */
2ff0b512 314#ifdef NEED_CACHE_HUNK
ce188d4d 315static chd_error hunk_read_into_cache(chd_file *chd, UINT32 hunknum);
2ff0b512 316#endif
ce188d4d 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
ce188d4d 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);
dcd8e4fd 331static void zlib_allocator_free(voidpf opaque);
ce188d4d 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
9c659ffe 353/***************************************************************************
354 * LZMA ALLOCATOR HELPER
355 ***************************************************************************
356 */
ce188d4d 357
2ff0b512 358static void *lzma_fast_alloc(void *p, size_t size);
359static void lzma_fast_free(void *p, void *address);
ce188d4d 360
9c659ffe 361/*-------------------------------------------------
362 * lzma_allocator_init
363 *-------------------------------------------------
364 */
ce188d4d 365
2ff0b512 366static void lzma_allocator_init(void* p)
ce188d4d 367{
368 lzma_allocator *codec = (lzma_allocator *)(p);
369
9c659ffe 370 /* reset pointer list */
ce188d4d 371 memset(codec->allocptr, 0, sizeof(codec->allocptr));
dcd8e4fd 372 memset(codec->allocptr2, 0, sizeof(codec->allocptr2));
ce188d4d 373 codec->Alloc = lzma_fast_alloc;
374 codec->Free = lzma_fast_free;
375}
376
9c659ffe 377/*-------------------------------------------------
378 * lzma_allocator_free
379 *-------------------------------------------------
380 */
ce188d4d 381
2ff0b512 382static void lzma_allocator_free(void* p )
ce188d4d 383{
dcd8e4fd 384 int i;
ce188d4d 385 lzma_allocator *codec = (lzma_allocator *)(p);
386
9c659ffe 387 /* free our memory */
dcd8e4fd 388 for (i = 0 ; i < MAX_LZMA_ALLOCS ; i++)
ce188d4d 389 {
390 if (codec->allocptr[i] != NULL)
391 free(codec->allocptr[i]);
392 }
393}
394
9c659ffe 395/*-------------------------------------------------
396 * lzma_fast_alloc - fast malloc for lzma, which
397 * allocates and frees memory frequently
398 *-------------------------------------------------
399 */
ce188d4d 400
2ff0b512 401/* Huge alignment values for possible SIMD optimization by compiler (NEON, SSE, AVX) */
dcd8e4fd 402#define LZMA_MIN_ALIGNMENT_BITS 512
403#define LZMA_MIN_ALIGNMENT_BYTES (LZMA_MIN_ALIGNMENT_BITS / 8)
2ff0b512 404
405static void *lzma_fast_alloc(void *p, size_t size)
ce188d4d 406{
dcd8e4fd 407 int scan;
408 uint32_t *addr = NULL;
ce188d4d 409 lzma_allocator *codec = (lzma_allocator *)(p);
dcd8e4fd 410 uintptr_t vaddr = 0;
ce188d4d 411
9c659ffe 412 /* compute the size, rounding to the nearest 1k */
ce188d4d 413 size = (size + 0x3ff) & ~0x3ff;
414
9c659ffe 415 /* reuse a hunk if we can */
dcd8e4fd 416 for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
ce188d4d 417 {
418 uint32_t *ptr = codec->allocptr[scan];
419 if (ptr != NULL && size == *ptr)
420 {
9c659ffe 421 /* set the low bit of the size so we don't match next time */
ce188d4d 422 *ptr |= 1;
2ff0b512 423
424 /* return aligned address of the block */
dcd8e4fd 425 return codec->allocptr2[scan];
ce188d4d 426 }
427 }
428
9c659ffe 429 /* alloc a new one and put it into the list */
dcd8e4fd 430 addr = (uint32_t *)malloc(size + sizeof(uint32_t) + LZMA_MIN_ALIGNMENT_BYTES);
ce188d4d 431 if (addr==NULL)
432 return NULL;
2ff0b512 433 for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
ce188d4d 434 {
435 if (codec->allocptr[scan] == NULL)
436 {
2ff0b512 437 /* store block address */
ce188d4d 438 codec->allocptr[scan] = addr;
2ff0b512 439
440 /* compute aligned address, store it */
dcd8e4fd 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;
ce188d4d 444 break;
445 }
446 }
447
9c659ffe 448 /* set the low bit of the size so we don't match next time */
ce188d4d 449 *addr = size | 1;
2ff0b512 450
451 /* return aligned address */
dcd8e4fd 452 return (void*)vaddr;
ce188d4d 453}
454
9c659ffe 455/*-------------------------------------------------
456 * lzma_fast_free - fast free for lzma, which
457 * allocates and frees memory frequently
458 *-------------------------------------------------
459 */
ce188d4d 460
2ff0b512 461static void lzma_fast_free(void *p, void *address)
ce188d4d 462{
dcd8e4fd 463 int scan;
464 uint32_t *ptr = NULL;
465 lzma_allocator *codec = NULL;
466
ce188d4d 467 if (address == NULL)
468 return;
469
dcd8e4fd 470 codec = (lzma_allocator *)(p);
ce188d4d 471
9c659ffe 472 /* find the hunk */
dcd8e4fd 473 ptr = (uint32_t *)address;
474 for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
ce188d4d 475 {
dcd8e4fd 476 if (ptr == codec->allocptr2[scan])
ce188d4d 477 {
9c659ffe 478 /* clear the low bit of the size to allow matches */
dcd8e4fd 479 *codec->allocptr[scan] &= ~1;
ce188d4d 480 return;
481 }
482 }
483}
484
9c659ffe 485/***************************************************************************
486 * LZMA DECOMPRESSOR
487 ***************************************************************************
488 */
ce188d4d 489
9c659ffe 490/*-------------------------------------------------
491 * lzma_codec_init - constructor
492 *-------------------------------------------------
493 */
ce188d4d 494
2ff0b512 495static chd_error lzma_codec_init(void* codec, uint32_t hunkbytes)
ce188d4d 496{
dcd8e4fd 497 CLzmaEncHandle enc;
498 CLzmaEncProps encoder_props;
499 Byte decoder_props[LZMA_PROPS_SIZE];
500 SizeT props_size;
501 lzma_allocator* alloc;
ce188d4d 502 lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
503
9c659ffe 504 /* construct the decoder */
ce188d4d 505 LzmaDec_Construct(&lzma_codec->decoder);
506
9c659ffe 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.
ce188d4d 511
9c659ffe 512 * configure the properties like the compressor did */
ce188d4d 513 LzmaEncProps_Init(&encoder_props);
514 encoder_props.level = 9;
515 encoder_props.reduceSize = hunkbytes;
516 LzmaEncProps_Normalize(&encoder_props);
517
9c659ffe 518 /* convert to decoder properties */
dcd8e4fd 519 alloc = &lzma_codec->allocator;
ce188d4d 520 lzma_allocator_init(alloc);
dcd8e4fd 521 enc = LzmaEnc_Create((ISzAlloc*)alloc);
ce188d4d 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 }
dcd8e4fd 529 props_size = sizeof(decoder_props);
ce188d4d 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
9c659ffe 537 /* do memory allocations */
ce188d4d 538 if (LzmaDec_Allocate(&lzma_codec->decoder, decoder_props, LZMA_PROPS_SIZE, (ISzAlloc*)alloc) != SZ_OK)
539 return CHDERR_DECOMPRESSION_ERROR;
9c659ffe 540
541 /* Okay */
ce188d4d 542 return CHDERR_NONE;
543}
544
9c659ffe 545/*-------------------------------------------------
546 * lzma_codec_free
547 *-------------------------------------------------
548 */
ce188d4d 549
2ff0b512 550static void lzma_codec_free(void* codec)
ce188d4d 551{
552 lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
553
9c659ffe 554 /* free memory */
ce188d4d 555 LzmaDec_Free(&lzma_codec->decoder, (ISzAlloc*)&lzma_codec->allocator);
9c659ffe 556 lzma_allocator_free(&lzma_codec->allocator);
ce188d4d 557}
558
9c659ffe 559/*-------------------------------------------------
560 * decompress - decompress data using the LZMA
561 * codec
562 *-------------------------------------------------
563 */
ce188d4d 564
2ff0b512 565static chd_error lzma_codec_decompress(void* codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
ce188d4d 566{
dcd8e4fd 567 ELzmaStatus status;
568 SRes res;
569 SizeT consumedlen, decodedlen;
9c659ffe 570 /* initialize */
ce188d4d 571 lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
572 LzmaDec_Init(&lzma_codec->decoder);
573
9c659ffe 574 /* decode */
dcd8e4fd 575 consumedlen = complen;
576 decodedlen = destlen;
577 res = LzmaDec_DecodeToBuf(&lzma_codec->decoder, dest, &decodedlen, src, &consumedlen, LZMA_FINISH_END, &status);
ce188d4d 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
9c659ffe 583/* cdlz */
2ff0b512 584static chd_error cdlz_codec_init(void* codec, uint32_t hunkbytes)
ce188d4d 585{
2ff0b512 586 chd_error ret;
ce188d4d 587 cdlz_codec_data* cdlz = (cdlz_codec_data*) codec;
588
9c659ffe 589 /* allocate buffer */
ce188d4d 590 cdlz->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
2ff0b512 591 if (cdlz->buffer == NULL)
592 return CHDERR_OUT_OF_MEMORY;
9c659ffe 593
594 /* make sure the CHD's hunk size is an even multiple of the frame size */
2ff0b512 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
ce188d4d 604
605 if (hunkbytes % CD_FRAME_SIZE != 0)
606 return CHDERR_CODEC_ERROR;
607
608 return CHDERR_NONE;
609}
610
2ff0b512 611static void cdlz_codec_free(void* codec)
ce188d4d 612{
9c659ffe 613 cdlz_codec_data* cdlz = (cdlz_codec_data*) codec;
614 free(cdlz->buffer);
615 lzma_codec_free(&cdlz->base_decompressor);
2ff0b512 616#ifdef WANT_SUBCODE
9c659ffe 617 zlib_codec_free(&cdlz->subcode_decompressor);
2ff0b512 618#endif
ce188d4d 619}
620
2ff0b512 621static chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
ce188d4d 622{
dcd8e4fd 623 uint32_t framenum;
ce188d4d 624 cdlz_codec_data* cdlz = (cdlz_codec_data*)codec;
625
9c659ffe 626 /* determine header bytes */
ce188d4d 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
9c659ffe 632 /* extract compressed length of base */
ce188d4d 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
9c659ffe 637 /* reset and decode */
ce188d4d 638 lzma_codec_decompress(&cdlz->base_decompressor, &src[header_bytes], complen_base, &cdlz->buffer[0], frames * CD_MAX_SECTOR_DATA);
2ff0b512 639#ifdef WANT_SUBCODE
ce188d4d 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);
2ff0b512 641#endif
ce188d4d 642
9c659ffe 643 /* reassemble the data */
dcd8e4fd 644 for (framenum = 0; framenum < frames; framenum++)
ce188d4d 645 {
dcd8e4fd 646 uint8_t *sector;
647
ce188d4d 648 memcpy(&dest[framenum * CD_FRAME_SIZE], &cdlz->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
2ff0b512 649#ifdef WANT_SUBCODE
ce188d4d 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);
2ff0b512 651#endif
ce188d4d 652
2ff0b512 653#ifdef WANT_RAW_DATA_SECTOR
9c659ffe 654 /* reconstitute the ECC data and sync header */
655 sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE];
ce188d4d 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 }
2ff0b512 661#endif
ce188d4d 662 }
663 return CHDERR_NONE;
664}
665
9c659ffe 666/* cdzl */
ce188d4d 667
2ff0b512 668static chd_error cdzl_codec_init(void *codec, uint32_t hunkbytes)
ce188d4d 669{
2ff0b512 670 chd_error ret;
ce188d4d 671 cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
672
9c659ffe 673 /* make sure the CHD's hunk size is an even multiple of the frame size */
ce188d4d 674 if (hunkbytes % CD_FRAME_SIZE != 0)
675 return CHDERR_CODEC_ERROR;
676
2ff0b512 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
ce188d4d 691 return CHDERR_NONE;
692}
693
2ff0b512 694static void cdzl_codec_free(void *codec)
ce188d4d 695{
9c659ffe 696 cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
697 zlib_codec_free(&cdzl->base_decompressor);
2ff0b512 698#ifdef WANT_SUBCODE
9c659ffe 699 zlib_codec_free(&cdzl->subcode_decompressor);
2ff0b512 700#endif
9c659ffe 701 free(cdzl->buffer);
ce188d4d 702}
703
2ff0b512 704static chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
ce188d4d 705{
dcd8e4fd 706 uint32_t framenum;
ce188d4d 707 cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
9c659ffe 708
709 /* determine header bytes */
ce188d4d 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
9c659ffe 715 /* extract compressed length of base */
ce188d4d 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
9c659ffe 720 /* reset and decode */
ce188d4d 721 zlib_codec_decompress(&cdzl->base_decompressor, &src[header_bytes], complen_base, &cdzl->buffer[0], frames * CD_MAX_SECTOR_DATA);
2ff0b512 722#ifdef WANT_SUBCODE
ce188d4d 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);
2ff0b512 724#endif
ce188d4d 725
9c659ffe 726 /* reassemble the data */
dcd8e4fd 727 for (framenum = 0; framenum < frames; framenum++)
ce188d4d 728 {
dcd8e4fd 729 uint8_t *sector;
730
ce188d4d 731 memcpy(&dest[framenum * CD_FRAME_SIZE], &cdzl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
2ff0b512 732#ifdef WANT_SUBCODE
ce188d4d 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);
2ff0b512 734#endif
ce188d4d 735
2ff0b512 736#ifdef WANT_RAW_DATA_SECTOR
9c659ffe 737 /* reconstitute the ECC data and sync header */
738 sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE];
ce188d4d 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 }
2ff0b512 744#endif
ce188d4d 745 }
746 return CHDERR_NONE;
747}
748
9c659ffe 749/***************************************************************************
750 * CD FLAC DECOMPRESSOR
751 ***************************************************************************
752 */
ce188d4d 753
9c659ffe 754/*------------------------------------------------------
755 * cdfl_codec_blocksize - return the optimal block size
756 *------------------------------------------------------
757 */
ce188d4d 758
759static uint32_t cdfl_codec_blocksize(uint32_t bytes)
760{
9c659ffe 761 /* determine FLAC block size, which must be 16-65535
762 * clamp to 2k since that's supposed to be the sweet spot */
ce188d4d 763 uint32_t hunkbytes = bytes / 4;
764 while (hunkbytes > 2048)
765 hunkbytes /= 2;
766 return hunkbytes;
767}
768
2ff0b512 769static chd_error cdfl_codec_init(void *codec, uint32_t hunkbytes)
ce188d4d 770{
2ff0b512 771#ifdef WANT_SUBCODE
772 chd_error ret;
773#endif
dcd8e4fd 774 uint16_t native_endian = 0;
ce188d4d 775 cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
776
9c659ffe 777 /* make sure the CHD's hunk size is an even multiple of the frame size */
ce188d4d 778 if (hunkbytes % CD_FRAME_SIZE != 0)
779 return CHDERR_CODEC_ERROR;
780
2ff0b512 781 cdfl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
782 if (cdfl->buffer == NULL)
783 return CHDERR_OUT_OF_MEMORY;
784
9c659ffe 785 /* determine whether we want native or swapped samples */
ce188d4d 786 *(uint8_t *)(&native_endian) = 1;
787 cdfl->swap_endian = (native_endian & 1);
788
2ff0b512 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;
9c659ffe 794#endif
ce188d4d 795
2ff0b512 796 /* flac decoder init */
797 if (flac_decoder_init(&cdfl->decoder))
ce188d4d 798 return CHDERR_OUT_OF_MEMORY;
ce188d4d 799
ce188d4d 800 return CHDERR_NONE;
801}
802
2ff0b512 803static void cdfl_codec_free(void *codec)
ce188d4d 804{
805 cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
9c659ffe 806 flac_decoder_free(&cdfl->decoder);
2ff0b512 807#ifdef WANT_SUBCODE
808 zlib_codec_free(&cdfl->subcode_decompressor);
809#endif
810 if (cdfl->buffer)
811 free(cdfl->buffer);
ce188d4d 812}
813
2ff0b512 814static chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
ce188d4d 815{
2ff0b512 816 uint32_t framenum;
dcd8e4fd 817 uint8_t *buffer;
2ff0b512 818#ifdef WANT_SUBCODE
819 uint32_t offset;
820 chd_error ret;
821#endif
ce188d4d 822 cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
823
9c659ffe 824 /* reset and decode */
ce188d4d 825 uint32_t frames = destlen / CD_FRAME_SIZE;
9c659ffe 826
ce188d4d 827 if (!flac_decoder_reset(&cdfl->decoder, 44100, 2, cdfl_codec_blocksize(frames * CD_MAX_SECTOR_DATA), src, complen))
828 return CHDERR_DECOMPRESSION_ERROR;
dcd8e4fd 829 buffer = &cdfl->buffer[0];
ce188d4d 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
2ff0b512 833#ifdef WANT_SUBCODE
9c659ffe 834 /* inflate the subcode data */
dcd8e4fd 835 offset = flac_decoder_finish(&cdfl->decoder);
2ff0b512 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
ce188d4d 842
9c659ffe 843 /* reassemble the data */
dcd8e4fd 844 for (framenum = 0; framenum < frames; framenum++)
ce188d4d 845 {
846 memcpy(&dest[framenum * CD_FRAME_SIZE], &cdfl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
2ff0b512 847#ifdef WANT_SUBCODE
ce188d4d 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);
2ff0b512 849#endif
ce188d4d 850 }
851
852 return CHDERR_NONE;
853}
854/***************************************************************************
855 CODEC INTERFACES
856***************************************************************************/
857
ce188d4d 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
9c659ffe 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
ce188d4d 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
9c659ffe 913 },
ce188d4d 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
9c659ffe 924 },
ce188d4d 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
9c659ffe 935 },
ce188d4d 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
ce188d4d 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{
9c659ffe 988 value &= 0xffffffffffff;
ce188d4d 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
ce188d4d 1006/*-------------------------------------------------
1007 put_bigendian_uint32 - write a UINT32 to
1008 the data stream in bigendian order
1009-------------------------------------------------*/
1010
9c659ffe 1011static inline void put_bigendian_uint32(UINT8 *base, UINT32 value)
ce188d4d 1012{
9c659ffe 1013 base[0] = value >> 24;
1014 base[1] = value >> 16;
1015 base[2] = value >> 8;
1016 base[3] = value;
ce188d4d 1017}
1018
ce188d4d 1019/*-------------------------------------------------
1020 put_bigendian_uint24 - write a UINT24 to
1021 the data stream in bigendian order
1022-------------------------------------------------*/
1023
9c659ffe 1024static inline void put_bigendian_uint24(UINT8 *base, UINT32 value)
ce188d4d 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
ce188d4d 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
ce188d4d 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
ce188d4d 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
ce188d4d 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
9c659ffe 1143 /* fetch the current value into a local and rip through the source data */
ce188d4d 1144 while (length-- != 0)
1145 crc = (crc << 8) ^ s_table[(crc >> 8) ^ *src++];
1146 return crc;
1147}
1148
9c659ffe 1149/*-------------------------------------------------
1150 compressed - test if CHD file is compressed
1151+-------------------------------------------------*/
dcd8e4fd 1152static inline int chd_compressed(chd_header* header) {
9c659ffe 1153 return header->compression[0] != CHD_CODEC_NONE;
1154}
1155
ce188d4d 1156/*-------------------------------------------------
1157 decompress_v5_map - decompress the v5 map
1158-------------------------------------------------*/
1159
1160static chd_error decompress_v5_map(chd_file* chd, chd_header* header)
1161{
dcd8e4fd 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;
2ff0b512 1179 uint64_t curoffset;
9c659ffe 1180 int rawmapsize = map_size_v5(header);
ce188d4d 1181
dcd8e4fd 1182 if (!chd_compressed(header))
ce188d4d 1183 {
9c659ffe 1184 header->rawmap = (uint8_t*)malloc(rawmapsize);
1185 core_fseek(chd->file, header->mapoffset, SEEK_SET);
dcd8e4fd 1186 result = core_fread(chd->file, header->rawmap, rawmapsize);
9c659ffe 1187 return CHDERR_NONE;
ce188d4d 1188 }
1189
9c659ffe 1190 /* read the reader */
ce188d4d 1191 core_fseek(chd->file, header->mapoffset, SEEK_SET);
dcd8e4fd 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];
9c659ffe 1199
1200 /* now read the map */
dcd8e4fd 1201 compressed_ptr = (uint8_t*)malloc(sizeof(uint8_t) * mapbytes);
ce188d4d 1202 core_fseek(chd->file, header->mapoffset + 16, SEEK_SET);
dcd8e4fd 1203 result = core_fread(chd->file, compressed_ptr, mapbytes);
1204 bitbuf = create_bitstream(compressed_ptr, sizeof(uint8_t) * mapbytes);
9c659ffe 1205 header->rawmap = (uint8_t*)malloc(rawmapsize);
ce188d4d 1206
9c659ffe 1207 /* first decode the compression types */
dcd8e4fd 1208 decoder = create_huffman_decoder(16, 8);
2ff0b512 1209 if (decoder == NULL)
1210 {
1211 free(compressed_ptr);
1212 free(bitbuf);
1213 return CHDERR_OUT_OF_MEMORY;
1214 }
1215
dcd8e4fd 1216 err = huffman_import_tree_rle(decoder, bitbuf);
ce188d4d 1217 if (err != HUFFERR_NONE)
2ff0b512 1218 {
1219 free(compressed_ptr);
1220 free(bitbuf);
1221 delete_huffman_decoder(decoder);
ce188d4d 1222 return CHDERR_DECOMPRESSION_ERROR;
2ff0b512 1223 }
1224
dcd8e4fd 1225 for (hunknum = 0; hunknum < header->hunkcount; hunknum++)
ce188d4d 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
9c659ffe 1242 /* then iterate through the hunks and extract the needed data */
dcd8e4fd 1243 curoffset = firstoffs;
1244 for (hunknum = 0; hunknum < header->hunkcount; hunknum++)
ce188d4d 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 {
9c659ffe 1252 /* base types */
ce188d4d 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
9c659ffe 1275 /* pseudo-types; convert into base types */
ce188d4d 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 }
9c659ffe 1295 /* UINT24 length */
ce188d4d 1296 put_bigendian_uint24(&rawmap[1], length);
1297
9c659ffe 1298 /* UINT48 offset */
ce188d4d 1299 put_bigendian_uint48(&rawmap[4], offset);
1300
9c659ffe 1301 /* crc16 */
ce188d4d 1302 put_bigendian_uint16(&rawmap[10], crc);
1303 }
1304
2ff0b512 1305 /* free memory */
dcd8e4fd 1306 free(compressed_ptr);
9c659ffe 1307 free(bitbuf);
2ff0b512 1308 delete_huffman_decoder(decoder);
9c659ffe 1309
1310 /* verify the final CRC */
ce188d4d 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
ce188d4d 1335/***************************************************************************
1336 CHD FILE MANAGEMENT
1337***************************************************************************/
1338
ce188d4d 1339/*-------------------------------------------------
1340 chd_open_file - open a CHD file for access
1341-------------------------------------------------*/
1342
2ff0b512 1343CHD_EXPORT chd_error chd_open_file(core_file *file, int mode, chd_file *parent, chd_file **chd)
ce188d4d 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 */
9c659ffe 1358 newchd = (chd_file *)malloc(sizeof(**chd));
ce188d4d 1359 if (newchd == NULL)
1360 EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
9c659ffe 1361 memset(newchd, 0, sizeof(*newchd));
ce188d4d 1362 newchd->cookie = COOKIE_VALUE;
1363 newchd->parent = parent;
1364 newchd->file = file;
1365
1366 /* now attempt to read the header */
9c659ffe 1367 err = header_read(newchd, &newchd->header);
ce188d4d 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 && (newchd->header.flags & CHDFLAGS_HAS_PARENT))
1386 EARLY_EXIT(err = CHDERR_REQUIRES_PARENT);
1387
1388 /* make sure we have a valid parent */
1389 if (parent != NULL)
1390 {
1391 /* check MD5 if it isn't empty */
1392 if (memcmp(nullmd5, newchd->header.parentmd5, sizeof(newchd->header.parentmd5)) != 0 &&
1393 memcmp(nullmd5, newchd->parent->header.md5, sizeof(newchd->parent->header.md5)) != 0 &&
1394 memcmp(newchd->parent->header.md5, newchd->header.parentmd5, sizeof(newchd->header.parentmd5)) != 0)
1395 EARLY_EXIT(err = CHDERR_INVALID_PARENT);
1396
1397 /* check SHA1 if it isn't empty */
1398 if (memcmp(nullsha1, newchd->header.parentsha1, sizeof(newchd->header.parentsha1)) != 0 &&
1399 memcmp(nullsha1, newchd->parent->header.sha1, sizeof(newchd->parent->header.sha1)) != 0 &&
1400 memcmp(newchd->parent->header.sha1, newchd->header.parentsha1, sizeof(newchd->header.parentsha1)) != 0)
1401 EARLY_EXIT(err = CHDERR_INVALID_PARENT);
1402 }
1403
1404 /* now read the hunk map */
1405 if (newchd->header.version < 5)
1406 {
1407 err = map_read(newchd);
2ff0b512 1408 if (err != CHDERR_NONE)
1409 EARLY_EXIT(err);
ce188d4d 1410 }
9c659ffe 1411 else
ce188d4d 1412 {
1413 err = decompress_v5_map(newchd, &(newchd->header));
1414 }
9c659ffe 1415 if (err != CHDERR_NONE)
1416 EARLY_EXIT(err);
1417
2ff0b512 1418#ifdef NEED_CACHE_HUNK
ce188d4d 1419 /* allocate and init the hunk cache */
1420 newchd->cache = (UINT8 *)malloc(newchd->header.hunkbytes);
1421 newchd->compare = (UINT8 *)malloc(newchd->header.hunkbytes);
1422 if (newchd->cache == NULL || newchd->compare == NULL)
1423 EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
1424 newchd->cachehunk = ~0;
1425 newchd->comparehunk = ~0;
2ff0b512 1426#endif
ce188d4d 1427
1428 /* allocate the temporary compressed buffer */
1429 newchd->compressed = (UINT8 *)malloc(newchd->header.hunkbytes);
1430 if (newchd->compressed == NULL)
1431 EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
1432
1433 /* find the codec interface */
1434 if (newchd->header.version < 5)
1435 {
1436 for (intfnum = 0; intfnum < ARRAY_LENGTH(codec_interfaces); intfnum++)
9c659ffe 1437 {
ce188d4d 1438 if (codec_interfaces[intfnum].compression == newchd->header.compression[0])
1439 {
1440 newchd->codecintf[0] = &codec_interfaces[intfnum];
1441 break;
1442 }
9c659ffe 1443 }
1444
ce188d4d 1445 if (intfnum == ARRAY_LENGTH(codec_interfaces))
1446 EARLY_EXIT(err = CHDERR_UNSUPPORTED_FORMAT);
1447
1448 /* initialize the codec */
1449 if (newchd->codecintf[0]->init != NULL)
9c659ffe 1450 {
ce188d4d 1451 err = (*newchd->codecintf[0]->init)(&newchd->zlib_codec_data, newchd->header.hunkbytes);
9c659ffe 1452 if (err != CHDERR_NONE)
1453 EARLY_EXIT(err);
1454 }
ce188d4d 1455 }
1456 else
1457 {
dcd8e4fd 1458 int decompnum;
9c659ffe 1459 /* verify the compression types and initialize the codecs */
dcd8e4fd 1460 for (decompnum = 0; decompnum < ARRAY_LENGTH(newchd->header.compression); decompnum++)
ce188d4d 1461 {
dcd8e4fd 1462 int i;
1463 for (i = 0 ; i < ARRAY_LENGTH(codec_interfaces) ; i++)
ce188d4d 1464 {
1465 if (codec_interfaces[i].compression == newchd->header.compression[decompnum])
1466 {
1467 newchd->codecintf[decompnum] = &codec_interfaces[i];
9c659ffe 1468 break;
ce188d4d 1469 }
1470 }
9c659ffe 1471
1472 if (newchd->codecintf[decompnum] == NULL && newchd->header.compression[decompnum] != 0)
1473 EARLY_EXIT(err = CHDERR_UNSUPPORTED_FORMAT);
1474
1475 /* initialize the codec */
1476 if (newchd->codecintf[decompnum]->init != NULL)
1477 {
1478 void* codec = NULL;
1479 switch (newchd->header.compression[decompnum])
1480 {
1481 case CHD_CODEC_ZLIB:
1482 codec = &newchd->zlib_codec_data;
1483 break;
1484
1485 case CHD_CODEC_CD_ZLIB:
1486 codec = &newchd->cdzl_codec_data;
1487 break;
1488
1489 case CHD_CODEC_CD_LZMA:
1490 codec = &newchd->cdlz_codec_data;
1491 break;
1492
1493 case CHD_CODEC_CD_FLAC:
1494 codec = &newchd->cdfl_codec_data;
1495 break;
1496 }
1497
1498 if (codec == NULL)
1499 EARLY_EXIT(err = CHDERR_UNSUPPORTED_FORMAT);
1500
1501 err = (*newchd->codecintf[decompnum]->init)(codec, newchd->header.hunkbytes);
1502 if (err != CHDERR_NONE)
1503 EARLY_EXIT(err);
1504 }
ce188d4d 1505 }
1506 }
1507
ce188d4d 1508 /* all done */
1509 *chd = newchd;
1510 return CHDERR_NONE;
1511
1512cleanup:
1513 if (newchd != NULL)
1514 chd_close(newchd);
1515 return err;
1516}
1517
9c659ffe 1518/*-------------------------------------------------
1519 chd_precache - precache underlying file in
1520 memory
1521-------------------------------------------------*/
1522
2ff0b512 1523CHD_EXPORT chd_error chd_precache(chd_file *chd)
9c659ffe 1524{
2ff0b512 1525#ifdef _MSC_VER
1526 size_t size, count;
1527#else
9c659ffe 1528 ssize_t size, count;
2ff0b512 1529#endif
9c659ffe 1530
1531 if (chd->file_cache == NULL)
1532 {
1533 core_fseek(chd->file, 0, SEEK_END);
1534 size = core_ftell(chd->file);
1535 if (size <= 0)
1536 return CHDERR_INVALID_DATA;
1537 chd->file_cache = malloc(size);
1538 if (chd->file_cache == NULL)
1539 return CHDERR_OUT_OF_MEMORY;
1540 core_fseek(chd->file, 0, SEEK_SET);
1541 count = core_fread(chd->file, chd->file_cache, size);
1542 if (count != size)
1543 {
1544 free(chd->file_cache);
1545 chd->file_cache = NULL;
1546 return CHDERR_READ_ERROR;
1547 }
1548 }
1549
1550 return CHDERR_NONE;
1551}
1552
ce188d4d 1553/*-------------------------------------------------
1554 chd_open - open a CHD file by
1555 filename
1556-------------------------------------------------*/
1557
2ff0b512 1558CHD_EXPORT chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd)
ce188d4d 1559{
1560 chd_error err;
1561 core_file *file = NULL;
ce188d4d 1562
1563 /* choose the proper mode */
1564 switch(mode)
1565 {
1566 case CHD_OPEN_READ:
1567 break;
1568
1569 default:
1570 err = CHDERR_INVALID_PARAMETER;
1571 goto cleanup;
1572 }
1573
1574 /* open the file */
1575 file = core_fopen(filename);
1576 if (file == 0)
1577 {
1578 err = CHDERR_FILE_NOT_FOUND;
1579 goto cleanup;
1580 }
1581
1582 /* now open the CHD */
1583 err = chd_open_file(file, mode, parent, chd);
1584 if (err != CHDERR_NONE)
1585 goto cleanup;
1586
1587 /* we now own this file */
1588 (*chd)->owns_file = TRUE;
1589
1590cleanup:
1591 if ((err != CHDERR_NONE) && (file != NULL))
1592 core_fclose(file);
1593 return err;
1594}
1595
ce188d4d 1596/*-------------------------------------------------
1597 chd_close - close a CHD file for access
1598-------------------------------------------------*/
1599
2ff0b512 1600CHD_EXPORT void chd_close(chd_file *chd)
ce188d4d 1601{
1602 /* punt if NULL or invalid */
1603 if (chd == NULL || chd->cookie != COOKIE_VALUE)
1604 return;
1605
1606 /* deinit the codec */
1607 if (chd->header.version < 5)
1608 {
9c659ffe 1609 if (chd->codecintf[0] != NULL && chd->codecintf[0]->free != NULL)
1610 (*chd->codecintf[0]->free)(&chd->zlib_codec_data);
ce188d4d 1611 }
1612 else
1613 {
2ff0b512 1614 int i;
9c659ffe 1615 /* Free the codecs */
dcd8e4fd 1616 for (i = 0 ; i < ARRAY_LENGTH(chd->codecintf); i++)
ce188d4d 1617 {
1618 void* codec = NULL;
9c659ffe 1619
1620 if (chd->codecintf[i] == NULL)
1621 continue;
1622
ce188d4d 1623 switch (chd->codecintf[i]->compression)
1624 {
1625 case CHD_CODEC_CD_LZMA:
1626 codec = &chd->cdlz_codec_data;
1627 break;
1628
9c659ffe 1629 case CHD_CODEC_ZLIB:
1630 codec = &chd->zlib_codec_data;
1631 break;
1632
ce188d4d 1633 case CHD_CODEC_CD_ZLIB:
1634 codec = &chd->cdzl_codec_data;
1635 break;
1636
1637 case CHD_CODEC_CD_FLAC:
1638 codec = &chd->cdfl_codec_data;
1639 break;
9c659ffe 1640 }
1641
ce188d4d 1642 if (codec)
1643 {
1644 (*chd->codecintf[i]->free)(codec);
1645 }
1646 }
1647
9c659ffe 1648 /* Free the raw map */
ce188d4d 1649 if (chd->header.rawmap != NULL)
1650 free(chd->header.rawmap);
1651 }
1652
1653 /* free the compressed data buffer */
1654 if (chd->compressed != NULL)
1655 free(chd->compressed);
1656
2ff0b512 1657#ifdef NEED_CACHE_HUNK
ce188d4d 1658 /* free the hunk cache and compare data */
1659 if (chd->compare != NULL)
1660 free(chd->compare);
1661 if (chd->cache != NULL)
1662 free(chd->cache);
2ff0b512 1663#endif
ce188d4d 1664
1665 /* free the hunk map */
1666 if (chd->map != NULL)
1667 free(chd->map);
1668
ce188d4d 1669 /* close the file */
1670 if (chd->owns_file && chd->file != NULL)
1671 core_fclose(chd->file);
1672
2ff0b512 1673#ifdef NEED_CACHE_HUNK
ce188d4d 1674 if (PRINTF_MAX_HUNK) printf("Max hunk = %d/%d\n", chd->maxhunk, chd->header.totalhunks);
2ff0b512 1675#endif
ce188d4d 1676 if (chd->file_cache)
1677 free(chd->file_cache);
1678
1679 /* free our memory */
1680 free(chd);
1681}
1682
ce188d4d 1683/*-------------------------------------------------
1684 chd_core_file - return the associated
1685 core_file
1686-------------------------------------------------*/
1687
2ff0b512 1688CHD_EXPORT core_file *chd_core_file(chd_file *chd)
ce188d4d 1689{
1690 return chd->file;
1691}
1692
ce188d4d 1693/*-------------------------------------------------
1694 chd_error_string - return an error string for
1695 the given CHD error
1696-------------------------------------------------*/
1697
2ff0b512 1698CHD_EXPORT const char *chd_error_string(chd_error err)
ce188d4d 1699{
1700 switch (err)
1701 {
1702 case CHDERR_NONE: return "no error";
1703 case CHDERR_NO_INTERFACE: return "no drive interface";
1704 case CHDERR_OUT_OF_MEMORY: return "out of memory";
1705 case CHDERR_INVALID_FILE: return "invalid file";
1706 case CHDERR_INVALID_PARAMETER: return "invalid parameter";
1707 case CHDERR_INVALID_DATA: return "invalid data";
1708 case CHDERR_FILE_NOT_FOUND: return "file not found";
1709 case CHDERR_REQUIRES_PARENT: return "requires parent";
1710 case CHDERR_FILE_NOT_WRITEABLE: return "file not writeable";
1711 case CHDERR_READ_ERROR: return "read error";
1712 case CHDERR_WRITE_ERROR: return "write error";
1713 case CHDERR_CODEC_ERROR: return "codec error";
1714 case CHDERR_INVALID_PARENT: return "invalid parent";
1715 case CHDERR_HUNK_OUT_OF_RANGE: return "hunk out of range";
1716 case CHDERR_DECOMPRESSION_ERROR: return "decompression error";
1717 case CHDERR_COMPRESSION_ERROR: return "compression error";
1718 case CHDERR_CANT_CREATE_FILE: return "can't create file";
1719 case CHDERR_CANT_VERIFY: return "can't verify file";
1720 case CHDERR_NOT_SUPPORTED: return "operation not supported";
1721 case CHDERR_METADATA_NOT_FOUND: return "can't find metadata";
1722 case CHDERR_INVALID_METADATA_SIZE: return "invalid metadata size";
1723 case CHDERR_UNSUPPORTED_VERSION: return "unsupported CHD version";
1724 case CHDERR_VERIFY_INCOMPLETE: return "incomplete verify";
1725 case CHDERR_INVALID_METADATA: return "invalid metadata";
1726 case CHDERR_INVALID_STATE: return "invalid state";
1727 case CHDERR_OPERATION_PENDING: return "operation pending";
1728 case CHDERR_NO_ASYNC_OPERATION: return "no async operation in progress";
1729 case CHDERR_UNSUPPORTED_FORMAT: return "unsupported format";
1730 default: return "undocumented error";
1731 }
1732}
1733
ce188d4d 1734/***************************************************************************
1735 CHD HEADER MANAGEMENT
1736***************************************************************************/
1737
1738/*-------------------------------------------------
1739 chd_get_header - return a pointer to the
1740 extracted header data
1741-------------------------------------------------*/
1742
2ff0b512 1743CHD_EXPORT const chd_header *chd_get_header(chd_file *chd)
ce188d4d 1744{
1745 /* punt if NULL or invalid */
1746 if (chd == NULL || chd->cookie != COOKIE_VALUE)
1747 return NULL;
1748
1749 return &chd->header;
1750}
1751
ce188d4d 1752/***************************************************************************
1753 CORE DATA READ/WRITE
1754***************************************************************************/
1755
1756/*-------------------------------------------------
1757 chd_read - read a single hunk from the CHD
1758 file
1759-------------------------------------------------*/
1760
2ff0b512 1761CHD_EXPORT chd_error chd_read(chd_file *chd, UINT32 hunknum, void *buffer)
ce188d4d 1762{
1763 /* punt if NULL or invalid */
1764 if (chd == NULL || chd->cookie != COOKIE_VALUE)
1765 return CHDERR_INVALID_PARAMETER;
1766
1767 /* if we're past the end, fail */
1768 if (hunknum >= chd->header.totalhunks)
1769 return CHDERR_HUNK_OUT_OF_RANGE;
1770
1771 /* perform the read */
1772 return hunk_read_into_memory(chd, hunknum, (UINT8 *)buffer);
1773}
1774
ce188d4d 1775/***************************************************************************
1776 METADATA MANAGEMENT
1777***************************************************************************/
1778
1779/*-------------------------------------------------
1780 chd_get_metadata - get the indexed metadata
1781 of the given type
1782-------------------------------------------------*/
1783
2ff0b512 1784CHD_EXPORT chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 searchindex, void *output, UINT32 outputlen, UINT32 *resultlen, UINT32 *resulttag, UINT8 *resultflags)
ce188d4d 1785{
1786 metadata_entry metaentry;
1787 chd_error err;
1788 UINT32 count;
1789
1790 /* if we didn't find it, just return */
1791 err = metadata_find_entry(chd, searchtag, searchindex, &metaentry);
1792 if (err != CHDERR_NONE)
1793 {
1794 /* unless we're an old version and they are requesting hard disk metadata */
1795 if (chd->header.version < 3 && (searchtag == HARD_DISK_METADATA_TAG || searchtag == CHDMETATAG_WILDCARD) && searchindex == 0)
1796 {
1797 char faux_metadata[256];
1798 UINT32 faux_length;
1799
1800 /* fill in the faux metadata */
1801 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);
1802 faux_length = (UINT32)strlen(faux_metadata) + 1;
1803
1804 /* copy the metadata itself */
1805 memcpy(output, faux_metadata, MIN(outputlen, faux_length));
1806
1807 /* return the length of the data and the tag */
1808 if (resultlen != NULL)
1809 *resultlen = faux_length;
1810 if (resulttag != NULL)
1811 *resulttag = HARD_DISK_METADATA_TAG;
1812 return CHDERR_NONE;
1813 }
1814 return err;
1815 }
1816
1817 /* read the metadata */
1818 outputlen = MIN(outputlen, metaentry.length);
1819 core_fseek(chd->file, metaentry.offset + METADATA_HEADER_SIZE, SEEK_SET);
1820 count = core_fread(chd->file, output, outputlen);
1821 if (count != outputlen)
1822 return CHDERR_READ_ERROR;
1823
1824 /* return the length of the data and the tag */
1825 if (resultlen != NULL)
1826 *resultlen = metaentry.length;
1827 if (resulttag != NULL)
1828 *resulttag = metaentry.metatag;
1829 if (resultflags != NULL)
1830 *resultflags = metaentry.flags;
1831 return CHDERR_NONE;
1832}
1833
ce188d4d 1834/***************************************************************************
1835 CODEC INTERFACES
1836***************************************************************************/
1837
1838/*-------------------------------------------------
1839 chd_codec_config - set internal codec
1840 parameters
1841-------------------------------------------------*/
1842
2ff0b512 1843CHD_EXPORT chd_error chd_codec_config(chd_file *chd, int param, void *config)
ce188d4d 1844{
ce188d4d 1845 return CHDERR_INVALID_PARAMETER;
1846}
1847
ce188d4d 1848/*-------------------------------------------------
1849 chd_get_codec_name - get the name of a
1850 particular codec
1851-------------------------------------------------*/
1852
2ff0b512 1853CHD_EXPORT const char *chd_get_codec_name(UINT32 codec)
ce188d4d 1854{
1855 return "Unknown";
1856}
1857
ce188d4d 1858/***************************************************************************
1859 INTERNAL HEADER OPERATIONS
1860***************************************************************************/
1861
1862/*-------------------------------------------------
1863 header_validate - check the validity of a
1864 CHD header
1865-------------------------------------------------*/
1866
1867static chd_error header_validate(const chd_header *header)
1868{
1869 int intfnum;
9c659ffe 1870
ce188d4d 1871 /* require a valid version */
1872 if (header->version == 0 || header->version > CHD_HEADER_VERSION)
1873 return CHDERR_UNSUPPORTED_VERSION;
9c659ffe 1874
ce188d4d 1875 /* require a valid length */
1876 if ((header->version == 1 && header->length != CHD_V1_HEADER_SIZE) ||
1877 (header->version == 2 && header->length != CHD_V2_HEADER_SIZE) ||
1878 (header->version == 3 && header->length != CHD_V3_HEADER_SIZE) ||
1879 (header->version == 4 && header->length != CHD_V4_HEADER_SIZE) ||
1880 (header->version == 5 && header->length != CHD_V5_HEADER_SIZE))
1881 return CHDERR_INVALID_PARAMETER;
9c659ffe 1882
ce188d4d 1883 /* Do not validate v5 header */
1884 if (header->version <= 4)
1885 {
1886 /* require valid flags */
1887 if (header->flags & CHDFLAGS_UNDEFINED)
1888 return CHDERR_INVALID_PARAMETER;
1889
1890 /* require a supported compression mechanism */
1891 for (intfnum = 0; intfnum < ARRAY_LENGTH(codec_interfaces); intfnum++)
1892 if (codec_interfaces[intfnum].compression == header->compression[0])
1893 break;
1894
1895 if (intfnum == ARRAY_LENGTH(codec_interfaces))
1896 return CHDERR_INVALID_PARAMETER;
1897
1898 /* require a valid hunksize */
1899 if (header->hunkbytes == 0 || header->hunkbytes >= 65536 * 256)
1900 return CHDERR_INVALID_PARAMETER;
1901
1902 /* require a valid hunk count */
1903 if (header->totalhunks == 0)
1904 return CHDERR_INVALID_PARAMETER;
1905
1906 /* require a valid MD5 and/or SHA1 if we're using a parent */
1907 if ((header->flags & CHDFLAGS_HAS_PARENT) && memcmp(header->parentmd5, nullmd5, sizeof(nullmd5)) == 0 && memcmp(header->parentsha1, nullsha1, sizeof(nullsha1)) == 0)
1908 return CHDERR_INVALID_PARAMETER;
1909
1910 /* if we're V3 or later, the obsolete fields must be 0 */
1911 if (header->version >= 3 &&
1912 (header->obsolete_cylinders != 0 || header->obsolete_sectors != 0 ||
1913 header->obsolete_heads != 0 || header->obsolete_hunksize != 0))
1914 return CHDERR_INVALID_PARAMETER;
1915
1916 /* if we're pre-V3, the obsolete fields must NOT be 0 */
1917 if (header->version < 3 &&
1918 (header->obsolete_cylinders == 0 || header->obsolete_sectors == 0 ||
1919 header->obsolete_heads == 0 || header->obsolete_hunksize == 0))
1920 return CHDERR_INVALID_PARAMETER;
1921 }
1922
1923 return CHDERR_NONE;
1924}
1925
9c659ffe 1926/*-------------------------------------------------
1927 header_guess_unitbytes - for older CHD formats,
1928 guess at the bytes/unit based on metadata
1929-------------------------------------------------*/
1930
1931static UINT32 header_guess_unitbytes(chd_file *chd)
1932{
1933 /* look for hard disk metadata; if found, then the unit size == sector size */
1934 char metadata[512];
1935 int i0, i1, i2, i3;
1936 if (chd_get_metadata(chd, HARD_DISK_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE &&
1937 sscanf(metadata, HARD_DISK_METADATA_FORMAT, &i0, &i1, &i2, &i3) == 4)
1938 return i3;
1939
1940 /* look for CD-ROM metadata; if found, then the unit size == CD frame size */
1941 if (chd_get_metadata(chd, CDROM_OLD_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
1942 chd_get_metadata(chd, CDROM_TRACK_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
1943 chd_get_metadata(chd, CDROM_TRACK_METADATA2_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
1944 chd_get_metadata(chd, GDROM_OLD_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
1945 chd_get_metadata(chd, GDROM_TRACK_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE)
1946 return CD_FRAME_SIZE;
1947
1948 /* otherwise, just map 1:1 with the hunk size */
1949 return chd->header.hunkbytes;
1950}
ce188d4d 1951
1952/*-------------------------------------------------
1953 header_read - read a CHD header into the
1954 internal data structure
1955-------------------------------------------------*/
1956
9c659ffe 1957static chd_error header_read(chd_file *chd, chd_header *header)
ce188d4d 1958{
1959 UINT8 rawheader[CHD_MAX_HEADER_SIZE];
1960 UINT32 count;
1961
1962 /* punt if NULL */
1963 if (header == NULL)
1964 return CHDERR_INVALID_PARAMETER;
1965
1966 /* punt if invalid file */
9c659ffe 1967 if (chd->file == NULL)
ce188d4d 1968 return CHDERR_INVALID_FILE;
1969
1970 /* seek and read */
9c659ffe 1971 core_fseek(chd->file, 0, SEEK_SET);
1972 count = core_fread(chd->file, rawheader, sizeof(rawheader));
ce188d4d 1973 if (count != sizeof(rawheader))
1974 return CHDERR_READ_ERROR;
1975
1976 /* verify the tag */
1977 if (strncmp((char *)rawheader, "MComprHD", 8) != 0)
1978 return CHDERR_INVALID_DATA;
1979
1980 /* extract the direct data */
1981 memset(header, 0, sizeof(*header));
1982 header->length = get_bigendian_uint32(&rawheader[8]);
1983 header->version = get_bigendian_uint32(&rawheader[12]);
1984
1985 /* make sure it's a version we understand */
1986 if (header->version == 0 || header->version > CHD_HEADER_VERSION)
1987 return CHDERR_UNSUPPORTED_VERSION;
1988
1989 /* make sure the length is expected */
1990 if ((header->version == 1 && header->length != CHD_V1_HEADER_SIZE) ||
1991 (header->version == 2 && header->length != CHD_V2_HEADER_SIZE) ||
1992 (header->version == 3 && header->length != CHD_V3_HEADER_SIZE) ||
1993 (header->version == 4 && header->length != CHD_V4_HEADER_SIZE) ||
1994 (header->version == 5 && header->length != CHD_V5_HEADER_SIZE))
9c659ffe 1995
ce188d4d 1996 return CHDERR_INVALID_DATA;
1997
1998 /* extract the common data */
1999 header->flags = get_bigendian_uint32(&rawheader[16]);
2000 header->compression[0] = get_bigendian_uint32(&rawheader[20]);
9c659ffe 2001 header->compression[1] = CHD_CODEC_NONE;
2002 header->compression[2] = CHD_CODEC_NONE;
2003 header->compression[3] = CHD_CODEC_NONE;
ce188d4d 2004
2005 /* extract the V1/V2-specific data */
2006 if (header->version < 3)
2007 {
2008 int seclen = (header->version == 1) ? CHD_V1_SECTOR_SIZE : get_bigendian_uint32(&rawheader[76]);
2009 header->obsolete_hunksize = get_bigendian_uint32(&rawheader[24]);
2010 header->totalhunks = get_bigendian_uint32(&rawheader[28]);
2011 header->obsolete_cylinders = get_bigendian_uint32(&rawheader[32]);
2012 header->obsolete_heads = get_bigendian_uint32(&rawheader[36]);
2013 header->obsolete_sectors = get_bigendian_uint32(&rawheader[40]);
2014 memcpy(header->md5, &rawheader[44], CHD_MD5_BYTES);
2015 memcpy(header->parentmd5, &rawheader[60], CHD_MD5_BYTES);
2016 header->logicalbytes = (UINT64)header->obsolete_cylinders * (UINT64)header->obsolete_heads * (UINT64)header->obsolete_sectors * (UINT64)seclen;
2017 header->hunkbytes = seclen * header->obsolete_hunksize;
9c659ffe 2018 header->unitbytes = header_guess_unitbytes(chd);
2019 header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
ce188d4d 2020 header->metaoffset = 0;
2021 }
2022
2023 /* extract the V3-specific data */
2024 else if (header->version == 3)
2025 {
2026 header->totalhunks = get_bigendian_uint32(&rawheader[24]);
2027 header->logicalbytes = get_bigendian_uint64(&rawheader[28]);
2028 header->metaoffset = get_bigendian_uint64(&rawheader[36]);
2029 memcpy(header->md5, &rawheader[44], CHD_MD5_BYTES);
2030 memcpy(header->parentmd5, &rawheader[60], CHD_MD5_BYTES);
2031 header->hunkbytes = get_bigendian_uint32(&rawheader[76]);
9c659ffe 2032 header->unitbytes = header_guess_unitbytes(chd);
2033 header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
ce188d4d 2034 memcpy(header->sha1, &rawheader[80], CHD_SHA1_BYTES);
2035 memcpy(header->parentsha1, &rawheader[100], CHD_SHA1_BYTES);
2036 }
2037
2038 /* extract the V4-specific data */
2039 else if (header->version == 4)
2040 {
2041 header->totalhunks = get_bigendian_uint32(&rawheader[24]);
2042 header->logicalbytes = get_bigendian_uint64(&rawheader[28]);
2043 header->metaoffset = get_bigendian_uint64(&rawheader[36]);
2044 header->hunkbytes = get_bigendian_uint32(&rawheader[44]);
9c659ffe 2045 header->unitbytes = header_guess_unitbytes(chd);
2046 header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
ce188d4d 2047 memcpy(header->sha1, &rawheader[48], CHD_SHA1_BYTES);
2048 memcpy(header->parentsha1, &rawheader[68], CHD_SHA1_BYTES);
2049 memcpy(header->rawsha1, &rawheader[88], CHD_SHA1_BYTES);
2050 }
2051
2052 /* extract the V5-specific data */
2053 else if (header->version == 5)
2054 {
2055 /* TODO */
9c659ffe 2056 header->compression[0] = get_bigendian_uint32(&rawheader[16]);
2057 header->compression[1] = get_bigendian_uint32(&rawheader[20]);
2058 header->compression[2] = get_bigendian_uint32(&rawheader[24]);
2059 header->compression[3] = get_bigendian_uint32(&rawheader[28]);
2060 header->logicalbytes = get_bigendian_uint64(&rawheader[32]);
2061 header->mapoffset = get_bigendian_uint64(&rawheader[40]);
2062 header->metaoffset = get_bigendian_uint64(&rawheader[48]);
2063 header->hunkbytes = get_bigendian_uint32(&rawheader[56]);
2064 header->hunkcount = (header->logicalbytes + header->hunkbytes - 1) / header->hunkbytes;
2065 header->unitbytes = get_bigendian_uint32(&rawheader[60]);
2066 header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
ce188d4d 2067 memcpy(header->sha1, &rawheader[84], CHD_SHA1_BYTES);
2068 memcpy(header->parentsha1, &rawheader[104], CHD_SHA1_BYTES);
2069 memcpy(header->rawsha1, &rawheader[64], CHD_SHA1_BYTES);
2070
9c659ffe 2071 /* determine properties of map entries */
dcd8e4fd 2072 header->mapentrybytes = chd_compressed(header) ? 12 : 4;
ce188d4d 2073
9c659ffe 2074 /* hack */
ce188d4d 2075 header->totalhunks = header->hunkcount;
2076 }
2077
2078 /* Unknown version */
9c659ffe 2079 else
ce188d4d 2080 {
2081 /* TODO */
2082 }
2083
2084 /* guess it worked */
2085 return CHDERR_NONE;
2086}
2087
ce188d4d 2088/***************************************************************************
2089 INTERNAL HUNK READ/WRITE
2090***************************************************************************/
2091
2092/*-------------------------------------------------
9c659ffe 2093 hunk_read_compressed - read a compressed
2094 hunk
ce188d4d 2095-------------------------------------------------*/
2096
9c659ffe 2097static UINT8* hunk_read_compressed(chd_file *chd, UINT64 offset, size_t size)
ce188d4d 2098{
2ff0b512 2099#ifdef _MSC_VER
2100 size_t bytes;
2101#else
ce188d4d 2102 ssize_t bytes;
2ff0b512 2103#endif
ce188d4d 2104 if (chd->file_cache != NULL)
2105 {
2106 return chd->file_cache + offset;
2107 }
2108 else
2109 {
2110 core_fseek(chd->file, offset, SEEK_SET);
2111 bytes = core_fread(chd->file, chd->compressed, size);
2112 if (bytes != size)
2113 return NULL;
2114 return chd->compressed;
2115 }
2116}
2117
9c659ffe 2118/*-------------------------------------------------
2119 hunk_read_uncompressed - read an uncompressed
2120 hunk
2121-------------------------------------------------*/
2122
2123static chd_error hunk_read_uncompressed(chd_file *chd, UINT64 offset, size_t size, UINT8 *dest)
ce188d4d 2124{
2ff0b512 2125#ifdef _MSC_VER
2126 size_t bytes;
2127#else
ce188d4d 2128 ssize_t bytes;
2ff0b512 2129#endif
ce188d4d 2130 if (chd->file_cache != NULL)
2131 {
2132 memcpy(dest, chd->file_cache + offset, size);
2133 }
2134 else
2135 {
2136 core_fseek(chd->file, offset, SEEK_SET);
2137 bytes = core_fread(chd->file, dest, size);
2138 if (bytes != size)
2139 return CHDERR_READ_ERROR;
2140 }
2141 return CHDERR_NONE;
2142}
2143
2ff0b512 2144#ifdef NEED_CACHE_HUNK
9c659ffe 2145/*-------------------------------------------------
2146 hunk_read_into_cache - read a hunk into
2147 the CHD's hunk cache
2148-------------------------------------------------*/
2149
2150static chd_error hunk_read_into_cache(chd_file *chd, UINT32 hunknum)
2151{
2152 chd_error err;
2153
2154 /* track the max */
2155 if (hunknum > chd->maxhunk)
2156 chd->maxhunk = hunknum;
2157
2158 /* if we're already in the cache, we're done */
2159 if (chd->cachehunk == hunknum)
2160 return CHDERR_NONE;
2161 chd->cachehunk = ~0;
2162
2163 /* otherwise, read the data */
2164 err = hunk_read_into_memory(chd, hunknum, chd->cache);
2165 if (err != CHDERR_NONE)
2166 return err;
2167
2168 /* mark the hunk successfully cached in */
2169 chd->cachehunk = hunknum;
2170 return CHDERR_NONE;
2171}
2ff0b512 2172#endif
9c659ffe 2173
ce188d4d 2174/*-------------------------------------------------
2175 hunk_read_into_memory - read a hunk into
2176 memory at the given location
2177-------------------------------------------------*/
2178
2179static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *dest)
2180{
2181 chd_error err;
2182
9c659ffe 2183 /* punt if no file */
ce188d4d 2184 if (chd->file == NULL)
2185 return CHDERR_INVALID_FILE;
2186
2187 /* return an error if out of range */
2188 if (hunknum >= chd->header.totalhunks)
2189 return CHDERR_HUNK_OUT_OF_RANGE;
2190
2ff0b512 2191 if (dest == NULL)
2192 return CHDERR_INVALID_PARAMETER;
2193
ce188d4d 2194 if (chd->header.version < 5)
2195 {
2196 map_entry *entry = &chd->map[hunknum];
2197 UINT32 bytes;
9c659ffe 2198 UINT8* compressed_bytes;
ce188d4d 2199
2200 /* switch off the entry type */
2201 switch (entry->flags & MAP_ENTRY_FLAG_TYPE_MASK)
2202 {
2203 /* compressed data */
2204 case V34_MAP_ENTRY_TYPE_COMPRESSED:
dcd8e4fd 2205 {
2ff0b512 2206 void *codec = NULL;
9c659ffe 2207
2208 /* read it into the decompression buffer */
2209 compressed_bytes = hunk_read_compressed(chd, entry->offset, entry->length);
2210 if (compressed_bytes == NULL)
2211 return CHDERR_READ_ERROR;
2212
2213 /* now decompress using the codec */
2214 err = CHDERR_NONE;
dcd8e4fd 2215 codec = &chd->zlib_codec_data;
9c659ffe 2216 if (chd->codecintf[0]->decompress != NULL)
2217 err = (*chd->codecintf[0]->decompress)(codec, compressed_bytes, entry->length, dest, chd->header.hunkbytes);
2218 if (err != CHDERR_NONE)
2219 return err;
ce188d4d 2220 break;
dcd8e4fd 2221 }
ce188d4d 2222
2223 /* uncompressed data */
2224 case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
9c659ffe 2225 err = hunk_read_uncompressed(chd, entry->offset, chd->header.hunkbytes, dest);
ce188d4d 2226 if (err != CHDERR_NONE)
2227 return err;
2228 break;
2229
2230 /* mini-compressed data */
2231 case V34_MAP_ENTRY_TYPE_MINI:
2232 put_bigendian_uint64(&dest[0], entry->offset);
2233 for (bytes = 8; bytes < chd->header.hunkbytes; bytes++)
2234 dest[bytes] = dest[bytes - 8];
2235 break;
2236
2237 /* self-referenced data */
2238 case V34_MAP_ENTRY_TYPE_SELF_HUNK:
2ff0b512 2239#ifdef NEED_CACHE_HUNK
ce188d4d 2240 if (chd->cachehunk == entry->offset && dest == chd->cache)
2241 break;
2ff0b512 2242#endif
ce188d4d 2243 return hunk_read_into_memory(chd, entry->offset, dest);
2244
2245 /* parent-referenced data */
2246 case V34_MAP_ENTRY_TYPE_PARENT_HUNK:
2247 err = hunk_read_into_memory(chd->parent, entry->offset, dest);
2248 if (err != CHDERR_NONE)
2249 return err;
2250 break;
2251 }
2252 return CHDERR_NONE;
2253 }
2254 else
2255 {
2ff0b512 2256 void* codec = NULL;
9c659ffe 2257 /* get a pointer to the map entry */
ce188d4d 2258 uint64_t blockoffs;
2259 uint32_t blocklen;
2ff0b512 2260#ifdef VERIFY_BLOCK_CRC
ce188d4d 2261 uint16_t blockcrc;
2ff0b512 2262#endif
ce188d4d 2263 uint8_t *rawmap = &chd->header.rawmap[chd->header.mapentrybytes * hunknum];
9c659ffe 2264 UINT8* compressed_bytes;
ce188d4d 2265
9c659ffe 2266 /* uncompressed case */
dcd8e4fd 2267 if (!chd_compressed(&chd->header))
ce188d4d 2268 {
9c659ffe 2269 blockoffs = (uint64_t)get_bigendian_uint32(rawmap) * (uint64_t)chd->header.hunkbytes;
2270 if (blockoffs != 0) {
2271 core_fseek(chd->file, blockoffs, SEEK_SET);
2ff0b512 2272 int result = core_fread(chd->file, dest, chd->header.hunkbytes);
9c659ffe 2273 /* TODO
ce188d4d 2274 else if (m_parent_missing)
9c659ffe 2275 throw CHDERR_REQUIRES_PARENT; */
2276 } else if (chd->parent) {
2277 err = hunk_read_into_memory(chd->parent, hunknum, dest);
2278 if (err != CHDERR_NONE)
2279 return err;
2280 } else {
2281 memset(dest, 0, chd->header.hunkbytes);
2282 }
2ff0b512 2283
dcd8e4fd 2284 return CHDERR_NONE;
9c659ffe 2285 }
ce188d4d 2286
9c659ffe 2287 /* compressed case */
ce188d4d 2288 blocklen = get_bigendian_uint24(&rawmap[1]);
2289 blockoffs = get_bigendian_uint48(&rawmap[4]);
2ff0b512 2290#ifdef VERIFY_BLOCK_CRC
ce188d4d 2291 blockcrc = get_bigendian_uint16(&rawmap[10]);
2ff0b512 2292#endif
dcd8e4fd 2293 codec = NULL;
ce188d4d 2294 switch (rawmap[0])
2295 {
2296 case COMPRESSION_TYPE_0:
2297 case COMPRESSION_TYPE_1:
2298 case COMPRESSION_TYPE_2:
2299 case COMPRESSION_TYPE_3:
9c659ffe 2300 compressed_bytes = hunk_read_compressed(chd, blockoffs, blocklen);
2301 if (compressed_bytes == NULL)
ce188d4d 2302 return CHDERR_READ_ERROR;
2303 switch (chd->codecintf[rawmap[0]]->compression)
2304 {
2305 case CHD_CODEC_CD_LZMA:
2306 codec = &chd->cdlz_codec_data;
2307 break;
2308
9c659ffe 2309 case CHD_CODEC_ZLIB:
2310 codec = &chd->zlib_codec_data;
2311 break;
2312
ce188d4d 2313 case CHD_CODEC_CD_ZLIB:
2314 codec = &chd->cdzl_codec_data;
2315 break;
2316
2317 case CHD_CODEC_CD_FLAC:
2318 codec = &chd->cdfl_codec_data;
2319 break;
2320 }
2321 if (codec==NULL)
2ff0b512 2322 return CHDERR_CODEC_ERROR;
2323 err = chd->codecintf[rawmap[0]]->decompress(codec, compressed_bytes, blocklen, dest, chd->header.hunkbytes);
2324 if (err != CHDERR_NONE)
2325 return err;
2326#ifdef VERIFY_BLOCK_CRC
2327 if (crc16(dest, chd->header.hunkbytes) != blockcrc)
ce188d4d 2328 return CHDERR_DECOMPRESSION_ERROR;
2ff0b512 2329#endif
ce188d4d 2330 return CHDERR_NONE;
2331
2332 case COMPRESSION_NONE:
9c659ffe 2333 err = hunk_read_uncompressed(chd, blockoffs, blocklen, dest);
ce188d4d 2334 if (err != CHDERR_NONE)
2335 return err;
2ff0b512 2336#ifdef VERIFY_BLOCK_CRC
ce188d4d 2337 if (crc16(dest, chd->header.hunkbytes) != blockcrc)
2338 return CHDERR_DECOMPRESSION_ERROR;
2ff0b512 2339#endif
ce188d4d 2340 return CHDERR_NONE;
2341
2342 case COMPRESSION_SELF:
2343 return hunk_read_into_memory(chd, blockoffs, dest);
2344
2345 case COMPRESSION_PARENT:
9c659ffe 2346#if 0
2347 /* TODO */
2348 if (m_parent_missing)
2349 return CHDERR_REQUIRES_PARENT;
2350 return m_parent->read_bytes(uint64_t(blockoffs) * uint64_t(m_parent->unit_bytes()), dest, m_hunkbytes);
2351#endif
ce188d4d 2352 return CHDERR_DECOMPRESSION_ERROR;
2353 }
2354 return CHDERR_NONE;
2355 }
2356
9c659ffe 2357 /* We should not reach this code */
ce188d4d 2358 return CHDERR_DECOMPRESSION_ERROR;
2359}
2360
ce188d4d 2361/***************************************************************************
2362 INTERNAL MAP ACCESS
2363***************************************************************************/
2364
2365/*-------------------------------------------------
2366 map_read - read the initial sector map
2367-------------------------------------------------*/
2368
2369static chd_error map_read(chd_file *chd)
2370{
2371 UINT32 entrysize = (chd->header.version < 3) ? OLD_MAP_ENTRY_SIZE : MAP_ENTRY_SIZE;
2372 UINT8 raw_map_entries[MAP_STACK_ENTRIES * MAP_ENTRY_SIZE];
2373 UINT64 fileoffset, maxoffset = 0;
2374 UINT8 cookie[MAP_ENTRY_SIZE];
2375 UINT32 count;
2376 chd_error err;
2377 int i;
2378
2379 /* first allocate memory */
2380 chd->map = (map_entry *)malloc(sizeof(chd->map[0]) * chd->header.totalhunks);
2381 if (!chd->map)
2382 return CHDERR_OUT_OF_MEMORY;
2383
2384 /* read the map entries in in chunks and extract to the map list */
2385 fileoffset = chd->header.length;
2386 for (i = 0; i < chd->header.totalhunks; i += MAP_STACK_ENTRIES)
2387 {
2388 /* compute how many entries this time */
2389 int entries = chd->header.totalhunks - i, j;
2390 if (entries > MAP_STACK_ENTRIES)
2391 entries = MAP_STACK_ENTRIES;
2392
2393 /* read that many */
2394 core_fseek(chd->file, fileoffset, SEEK_SET);
2395 count = core_fread(chd->file, raw_map_entries, entries * entrysize);
2396 if (count != entries * entrysize)
2397 {
2398 err = CHDERR_READ_ERROR;
2399 goto cleanup;
2400 }
2401 fileoffset += entries * entrysize;
2402
2403 /* process that many */
2404 if (entrysize == MAP_ENTRY_SIZE)
2405 {
2406 for (j = 0; j < entries; j++)
2407 map_extract(&raw_map_entries[j * MAP_ENTRY_SIZE], &chd->map[i + j]);
2408 }
2409 else
2410 {
2411 for (j = 0; j < entries; j++)
2412 map_extract_old(&raw_map_entries[j * OLD_MAP_ENTRY_SIZE], &chd->map[i + j], chd->header.hunkbytes);
2413 }
2414
2415 /* track the maximum offset */
2416 for (j = 0; j < entries; j++)
2417 if ((chd->map[i + j].flags & MAP_ENTRY_FLAG_TYPE_MASK) == V34_MAP_ENTRY_TYPE_COMPRESSED ||
2418 (chd->map[i + j].flags & MAP_ENTRY_FLAG_TYPE_MASK) == V34_MAP_ENTRY_TYPE_UNCOMPRESSED)
2419 maxoffset = MAX(maxoffset, chd->map[i + j].offset + chd->map[i + j].length);
2420 }
2421
2422 /* verify the cookie */
2423 core_fseek(chd->file, fileoffset, SEEK_SET);
2424 count = core_fread(chd->file, &cookie, entrysize);
2425 if (count != entrysize || memcmp(&cookie, END_OF_LIST_COOKIE, entrysize))
2426 {
2427 err = CHDERR_INVALID_FILE;
2428 goto cleanup;
2429 }
2430
2431 /* verify the length */
2432 if (maxoffset > core_fsize(chd->file))
2433 {
2434 err = CHDERR_INVALID_FILE;
2435 goto cleanup;
2436 }
2437 return CHDERR_NONE;
2438
2439cleanup:
2440 if (chd->map)
2441 free(chd->map);
2442 chd->map = NULL;
2443 return err;
2444}
2445
ce188d4d 2446/***************************************************************************
2447 INTERNAL METADATA ACCESS
2448***************************************************************************/
2449
2450/*-------------------------------------------------
2451 metadata_find_entry - find a metadata entry
2452-------------------------------------------------*/
2453
2454static chd_error metadata_find_entry(chd_file *chd, UINT32 metatag, UINT32 metaindex, metadata_entry *metaentry)
2455{
2456 /* start at the beginning */
2457 metaentry->offset = chd->header.metaoffset;
2458 metaentry->prev = 0;
2459
2460 /* loop until we run out of options */
2461 while (metaentry->offset != 0)
2462 {
2463 UINT8 raw_meta_header[METADATA_HEADER_SIZE];
2464 UINT32 count;
2465
2466 /* read the raw header */
2467 core_fseek(chd->file, metaentry->offset, SEEK_SET);
2468 count = core_fread(chd->file, raw_meta_header, sizeof(raw_meta_header));
2469 if (count != sizeof(raw_meta_header))
2470 break;
2471
2472 /* extract the data */
2473 metaentry->metatag = get_bigendian_uint32(&raw_meta_header[0]);
2474 metaentry->length = get_bigendian_uint32(&raw_meta_header[4]);
2475 metaentry->next = get_bigendian_uint64(&raw_meta_header[8]);
2476
2477 /* flags are encoded in the high byte of length */
2478 metaentry->flags = metaentry->length >> 24;
2479 metaentry->length &= 0x00ffffff;
2480
2481 /* if we got a match, proceed */
2482 if (metatag == CHDMETATAG_WILDCARD || metaentry->metatag == metatag)
2483 if (metaindex-- == 0)
2484 return CHDERR_NONE;
2485
2486 /* no match, fetch the next link */
2487 metaentry->prev = metaentry->offset;
2488 metaentry->offset = metaentry->next;
2489 }
2490
2491 /* if we get here, we didn't find it */
2492 return CHDERR_METADATA_NOT_FOUND;
2493}
2494
ce188d4d 2495/***************************************************************************
2496 ZLIB COMPRESSION CODEC
2497***************************************************************************/
2498
2499/*-------------------------------------------------
2500 zlib_codec_init - initialize the ZLIB codec
2501-------------------------------------------------*/
2502
2503static chd_error zlib_codec_init(void *codec, uint32_t hunkbytes)
2504{
ce188d4d 2505 int zerr;
2ff0b512 2506 chd_error err;
2507 zlib_codec_data *data = (zlib_codec_data*)codec;
ce188d4d 2508
2509 /* clear the buffers */
2510 memset(data, 0, sizeof(zlib_codec_data));
2511
2512 /* init the inflater first */
2513 data->inflater.next_in = (Bytef *)data; /* bogus, but that's ok */
2514 data->inflater.avail_in = 0;
2515 data->inflater.zalloc = zlib_fast_alloc;
2516 data->inflater.zfree = zlib_fast_free;
2517 data->inflater.opaque = &data->allocator;
2518 zerr = inflateInit2(&data->inflater, -MAX_WBITS);
2519
2520 /* convert errors */
2521 if (zerr == Z_MEM_ERROR)
2522 err = CHDERR_OUT_OF_MEMORY;
2523 else if (zerr != Z_OK)
2524 err = CHDERR_CODEC_ERROR;
2525 else
2526 err = CHDERR_NONE;
2527
2528 /* handle an error */
2529 if (err != CHDERR_NONE)
2530 free(data);
2531
2532 return err;
2533}
2534
ce188d4d 2535/*-------------------------------------------------
2536 zlib_codec_free - free data for the ZLIB
2537 codec
2538-------------------------------------------------*/
2539
2540static void zlib_codec_free(void *codec)
2541{
2542 zlib_codec_data *data = (zlib_codec_data *)codec;
2543
2544 /* deinit the streams */
2545 if (data != NULL)
2546 {
2547 int i;
ce188d4d 2548
2549 inflateEnd(&data->inflater);
2550
2551 /* free our fast memory */
dcd8e4fd 2552 zlib_allocator_free(&data->allocator);
ce188d4d 2553 }
2554}
2555
ce188d4d 2556/*-------------------------------------------------
dcd8e4fd 2557 zlib_codec_decompress - decompress data using
ce188d4d 2558 the ZLIB codec
2559-------------------------------------------------*/
2560
2561static chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
2562{
2563 zlib_codec_data *data = (zlib_codec_data *)codec;
2564 int zerr;
2565
2566 /* reset the decompressor */
2567 data->inflater.next_in = (Bytef *)src;
2568 data->inflater.avail_in = complen;
2569 data->inflater.total_in = 0;
2570 data->inflater.next_out = (Bytef *)dest;
2571 data->inflater.avail_out = destlen;
2572 data->inflater.total_out = 0;
2573 zerr = inflateReset(&data->inflater);
2574 if (zerr != Z_OK)
2575 return CHDERR_DECOMPRESSION_ERROR;
2576
2577 /* do it */
2578 zerr = inflate(&data->inflater, Z_FINISH);
2579 if (data->inflater.total_out != destlen)
2580 return CHDERR_DECOMPRESSION_ERROR;
2581
2582 return CHDERR_NONE;
2583}
2584
ce188d4d 2585/*-------------------------------------------------
2586 zlib_fast_alloc - fast malloc for ZLIB, which
2587 allocates and frees memory frequently
2588-------------------------------------------------*/
2ff0b512 2589
2590/* Huge alignment values for possible SIMD optimization by compiler (NEON, SSE, AVX) */
dcd8e4fd 2591#define ZLIB_MIN_ALIGNMENT_BITS 512
2592#define ZLIB_MIN_ALIGNMENT_BYTES (ZLIB_MIN_ALIGNMENT_BITS / 8)
ce188d4d 2593
2594static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
2595{
2596 zlib_allocator *alloc = (zlib_allocator *)opaque;
dcd8e4fd 2597 uintptr_t paddr = 0;
ce188d4d 2598 UINT32 *ptr;
2599 int i;
2600
2601 /* compute the size, rounding to the nearest 1k */
2602 size = (size * items + 0x3ff) & ~0x3ff;
2603
2604 /* reuse a hunk if we can */
2605 for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
2606 {
2607 ptr = alloc->allocptr[i];
2608 if (ptr && size == *ptr)
2609 {
2610 /* set the low bit of the size so we don't match next time */
2611 *ptr |= 1;
2ff0b512 2612
2613 /* return aligned block address */
dcd8e4fd 2614 return (voidpf)(alloc->allocptr2[i]);
ce188d4d 2615 }
2616 }
2617
2618 /* alloc a new one */
dcd8e4fd 2619 ptr = (UINT32 *)malloc(size + sizeof(UINT32) + ZLIB_MIN_ALIGNMENT_BYTES);
ce188d4d 2620 if (!ptr)
2621 return NULL;
2622
2623 /* put it into the list */
2624 for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
2625 if (!alloc->allocptr[i])
2626 {
2627 alloc->allocptr[i] = ptr;
dcd8e4fd 2628 paddr = (((uintptr_t)ptr) + sizeof(UINT32) + (ZLIB_MIN_ALIGNMENT_BYTES-1)) & (~(ZLIB_MIN_ALIGNMENT_BYTES-1));
2629 alloc->allocptr2[i] = (uint32_t*)paddr;
ce188d4d 2630 break;
2631 }
2632
2633 /* set the low bit of the size so we don't match next time */
2634 *ptr = size | 1;
2ff0b512 2635
2636 /* return aligned block address */
dcd8e4fd 2637 return (voidpf)paddr;
ce188d4d 2638}
2639
ce188d4d 2640/*-------------------------------------------------
2641 zlib_fast_free - fast free for ZLIB, which
2642 allocates and frees memory frequently
2643-------------------------------------------------*/
2644
2645static void zlib_fast_free(voidpf opaque, voidpf address)
2646{
2647 zlib_allocator *alloc = (zlib_allocator *)opaque;
dcd8e4fd 2648 UINT32 *ptr = (UINT32 *)address;
ce188d4d 2649 int i;
2650
2651 /* find the hunk */
2652 for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
dcd8e4fd 2653 if (ptr == alloc->allocptr2[i])
ce188d4d 2654 {
2655 /* clear the low bit of the size to allow matches */
dcd8e4fd 2656 *(alloc->allocptr[i]) &= ~1;
ce188d4d 2657 return;
2658 }
2659}
dcd8e4fd 2660
2661/*-------------------------------------------------
2662 zlib_allocator_free
2663-------------------------------------------------*/
2664static void zlib_allocator_free(voidpf opaque)
2665{
2666 zlib_allocator *alloc = (zlib_allocator *)opaque;
2667 int i;
2668
2669 for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
2670 if (alloc->allocptr[i])
2671 free(alloc->allocptr[i]);
2672}