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