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