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