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