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