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