aboutsummaryrefslogtreecommitdiff
path: root/deps/libchdr/chd.c
diff options
context:
space:
mode:
Diffstat (limited to 'deps/libchdr/chd.c')
-rw-r--r--deps/libchdr/chd.c216
1 files changed, 144 insertions, 72 deletions
diff --git a/deps/libchdr/chd.c b/deps/libchdr/chd.c
index 096ba9e..a77a523 100644
--- a/deps/libchdr/chd.c
+++ b/deps/libchdr/chd.c
@@ -197,6 +197,7 @@ typedef struct _zlib_allocator zlib_allocator;
struct _zlib_allocator
{
UINT32 * allocptr[MAX_ZLIB_ALLOCS];
+ UINT32 * allocptr2[MAX_ZLIB_ALLOCS];
};
typedef struct _zlib_codec_data zlib_codec_data;
@@ -216,6 +217,7 @@ struct _lzma_allocator
void (*Free)(void *p, void *address); /* address can be 0 */
void (*FreeSz)(void *p, void *address, size_t size); /* address can be 0 */
uint32_t* allocptr[MAX_LZMA_ALLOCS];
+ uint32_t* allocptr2[MAX_LZMA_ALLOCS];
};
typedef struct _lzma_codec_data lzma_codec_data;
@@ -342,6 +344,7 @@ static void zlib_codec_free(void *codec);
static chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size);
static void zlib_fast_free(voidpf opaque, voidpf address);
+static void zlib_allocator_free(voidpf opaque);
/* lzma compression codec */
static chd_error lzma_codec_init(void *codec, uint32_t hunkbytes);
@@ -382,6 +385,7 @@ void lzma_allocator_init(void* p)
/* reset pointer list */
memset(codec->allocptr, 0, sizeof(codec->allocptr));
+ memset(codec->allocptr2, 0, sizeof(codec->allocptr2));
codec->Alloc = lzma_fast_alloc;
codec->Free = lzma_fast_free;
}
@@ -393,10 +397,11 @@ void lzma_allocator_init(void* p)
void lzma_allocator_free(void* p )
{
+ int i;
lzma_allocator *codec = (lzma_allocator *)(p);
/* free our memory */
- for (int i = 0 ; i < MAX_LZMA_ALLOCS ; i++)
+ for (i = 0 ; i < MAX_LZMA_ALLOCS ; i++)
{
if (codec->allocptr[i] != NULL)
free(codec->allocptr[i]);
@@ -409,27 +414,33 @@ void lzma_allocator_free(void* p )
*-------------------------------------------------
*/
+#define LZMA_MIN_ALIGNMENT_BITS 512
+#define LZMA_MIN_ALIGNMENT_BYTES (LZMA_MIN_ALIGNMENT_BITS / 8)
void *lzma_fast_alloc(void *p, size_t size)
{
+ int scan;
+ uint32_t *addr = NULL;
lzma_allocator *codec = (lzma_allocator *)(p);
+
+ uintptr_t vaddr = 0;
/* compute the size, rounding to the nearest 1k */
size = (size + 0x3ff) & ~0x3ff;
/* reuse a hunk if we can */
- for (int scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
+ for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
{
uint32_t *ptr = codec->allocptr[scan];
if (ptr != NULL && size == *ptr)
{
/* set the low bit of the size so we don't match next time */
*ptr |= 1;
- return ptr + 1;
+ return codec->allocptr2[scan];
}
}
/* alloc a new one and put it into the list */
- uint32_t *addr = (uint32_t *)malloc(sizeof(uint8_t) * size + sizeof(uintptr_t));
+ addr = (uint32_t *)malloc(size + sizeof(uint32_t) + LZMA_MIN_ALIGNMENT_BYTES);
if (addr==NULL)
return NULL;
for (int scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
@@ -437,13 +448,16 @@ void *lzma_fast_alloc(void *p, size_t size)
if (codec->allocptr[scan] == NULL)
{
codec->allocptr[scan] = addr;
+ vaddr = (uintptr_t)addr;
+ vaddr = (vaddr + sizeof(uint32_t) + (LZMA_MIN_ALIGNMENT_BYTES-1)) & (~(LZMA_MIN_ALIGNMENT_BYTES-1));
+ codec->allocptr2[scan] = (uint32_t*)vaddr;
break;
}
}
/* set the low bit of the size so we don't match next time */
*addr = size | 1;
- return addr + (sizeof(uint32_t) == sizeof(uintptr_t) ? 1 : 2);
+ return (void*)vaddr;
}
/*-------------------------------------------------
@@ -454,19 +468,23 @@ void *lzma_fast_alloc(void *p, size_t size)
void lzma_fast_free(void *p, void *address)
{
+ int scan;
+ uint32_t *ptr = NULL;
+ lzma_allocator *codec = NULL;
+
if (address == NULL)
return;
- lzma_allocator *codec = (lzma_allocator *)(p);
+ codec = (lzma_allocator *)(p);
/* find the hunk */
- uint32_t *ptr = (uint32_t *)(address) - 1;
- for (int scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
+ ptr = (uint32_t *)address;
+ for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
{
- if (ptr == codec->allocptr[scan])
+ if (ptr == codec->allocptr2[scan])
{
/* clear the low bit of the size to allow matches */
- *ptr &= ~1;
+ *codec->allocptr[scan] &= ~1;
return;
}
}
@@ -484,6 +502,11 @@ void lzma_fast_free(void *p, void *address)
chd_error lzma_codec_init(void* codec, uint32_t hunkbytes)
{
+ CLzmaEncHandle enc;
+ CLzmaEncProps encoder_props;
+ Byte decoder_props[LZMA_PROPS_SIZE];
+ SizeT props_size;
+ lzma_allocator* alloc;
lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
/* construct the decoder */
@@ -495,16 +518,15 @@ chd_error lzma_codec_init(void* codec, uint32_t hunkbytes)
* needs to be changed so the encoder properties are written to the file.
* configure the properties like the compressor did */
- CLzmaEncProps encoder_props;
LzmaEncProps_Init(&encoder_props);
encoder_props.level = 9;
encoder_props.reduceSize = hunkbytes;
LzmaEncProps_Normalize(&encoder_props);
/* convert to decoder properties */
- lzma_allocator* alloc = &lzma_codec->allocator;
+ alloc = &lzma_codec->allocator;
lzma_allocator_init(alloc);
- CLzmaEncHandle enc = LzmaEnc_Create((ISzAlloc*)alloc);
+ enc = LzmaEnc_Create((ISzAlloc*)alloc);
if (!enc)
return CHDERR_DECOMPRESSION_ERROR;
if (LzmaEnc_SetProps(enc, &encoder_props) != SZ_OK)
@@ -512,8 +534,7 @@ chd_error lzma_codec_init(void* codec, uint32_t hunkbytes)
LzmaEnc_Destroy(enc, (ISzAlloc*)&alloc, (ISzAlloc*)&alloc);
return CHDERR_DECOMPRESSION_ERROR;
}
- Byte decoder_props[LZMA_PROPS_SIZE];
- SizeT props_size = sizeof(decoder_props);
+ props_size = sizeof(decoder_props);
if (LzmaEnc_WriteProperties(enc, decoder_props, &props_size) != SZ_OK)
{
LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc);
@@ -551,15 +572,17 @@ void lzma_codec_free(void* codec)
chd_error lzma_codec_decompress(void* codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
+ ELzmaStatus status;
+ SRes res;
+ SizeT consumedlen, decodedlen;
/* initialize */
lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
LzmaDec_Init(&lzma_codec->decoder);
/* decode */
- SizeT consumedlen = complen;
- SizeT decodedlen = destlen;
- ELzmaStatus status;
- SRes res = LzmaDec_DecodeToBuf(&lzma_codec->decoder, dest, &decodedlen, src, &consumedlen, LZMA_FINISH_END, &status);
+ consumedlen = complen;
+ decodedlen = destlen;
+ res = LzmaDec_DecodeToBuf(&lzma_codec->decoder, dest, &decodedlen, src, &consumedlen, LZMA_FINISH_END, &status);
if ((res != SZ_OK && res != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) || consumedlen != complen || decodedlen != destlen)
return CHDERR_DECOMPRESSION_ERROR;
return CHDERR_NONE;
@@ -593,7 +616,7 @@ void cdlz_codec_free(void* codec)
chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
- uint8_t *sector;
+ uint32_t framenum;
cdlz_codec_data* cdlz = (cdlz_codec_data*)codec;
/* determine header bytes */
@@ -612,8 +635,10 @@ chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t comple
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);
/* reassemble the data */
- for (uint32_t framenum = 0; framenum < frames; framenum++)
+ for (framenum = 0; framenum < frames; framenum++)
{
+ uint8_t *sector;
+
memcpy(&dest[framenum * CD_FRAME_SIZE], &cdlz->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
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);
@@ -655,7 +680,7 @@ void cdzl_codec_free(void *codec)
chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
- uint8_t *sector;
+ uint32_t framenum;
cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
/* determine header bytes */
@@ -674,8 +699,10 @@ chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t comple
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);
/* reassemble the data */
- for (uint32_t framenum = 0; framenum < frames; framenum++)
+ for (framenum = 0; framenum < frames; framenum++)
{
+ uint8_t *sector;
+
memcpy(&dest[framenum * CD_FRAME_SIZE], &cdzl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
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);
@@ -712,6 +739,8 @@ static uint32_t cdfl_codec_blocksize(uint32_t bytes)
chd_error cdfl_codec_init(void *codec, uint32_t hunkbytes)
{
+ int zerr;
+ uint16_t native_endian = 0;
cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
cdfl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
@@ -721,7 +750,6 @@ chd_error cdfl_codec_init(void *codec, uint32_t hunkbytes)
return CHDERR_CODEC_ERROR;
/* determine whether we want native or swapped samples */
- uint16_t native_endian = 0;
*(uint8_t *)(&native_endian) = 1;
cdfl->swap_endian = (native_endian & 1);
@@ -734,7 +762,7 @@ chd_error cdfl_codec_init(void *codec, uint32_t hunkbytes)
cdfl->inflater.zalloc = zlib_fast_alloc;
cdfl->inflater.zfree = zlib_fast_free;
cdfl->inflater.opaque = &cdfl->allocator;
- int zerr = inflateInit2(&cdfl->inflater, -MAX_WBITS);
+ zerr = inflateInit2(&cdfl->inflater, -MAX_WBITS);
/* convert errors */
if (zerr == Z_MEM_ERROR)
@@ -753,10 +781,16 @@ void cdfl_codec_free(void *codec)
free(cdfl->buffer);
inflateEnd(&cdfl->inflater);
flac_decoder_free(&cdfl->decoder);
+
+ /* free our fast memory */
+ zlib_allocator_free(&cdfl->allocator);
}
chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
+ int zerr;
+ uint8_t *buffer;
+ uint32_t framenum, offset;
cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
/* reset and decode */
@@ -764,19 +798,19 @@ chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t comple
if (!flac_decoder_reset(&cdfl->decoder, 44100, 2, cdfl_codec_blocksize(frames * CD_MAX_SECTOR_DATA), src, complen))
return CHDERR_DECOMPRESSION_ERROR;
- uint8_t *buffer = &cdfl->buffer[0];
+ buffer = &cdfl->buffer[0];
if (!flac_decoder_decode_interleaved(&cdfl->decoder, (int16_t *)(buffer), frames * CD_MAX_SECTOR_DATA/4, cdfl->swap_endian))
return CHDERR_DECOMPRESSION_ERROR;
/* inflate the subcode data */
- uint32_t offset = flac_decoder_finish(&cdfl->decoder);
+ offset = flac_decoder_finish(&cdfl->decoder);
cdfl->inflater.next_in = (Bytef *)(src + offset);
cdfl->inflater.avail_in = complen - offset;
cdfl->inflater.total_in = 0;
cdfl->inflater.next_out = &cdfl->buffer[frames * CD_MAX_SECTOR_DATA];
cdfl->inflater.avail_out = frames * CD_MAX_SUBCODE_DATA;
cdfl->inflater.total_out = 0;
- int zerr = inflateReset(&cdfl->inflater);
+ zerr = inflateReset(&cdfl->inflater);
if (zerr != Z_OK)
return CHDERR_DECOMPRESSION_ERROR;
@@ -788,7 +822,7 @@ chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t comple
return CHDERR_DECOMPRESSION_ERROR;
/* reassemble the data */
- for (uint32_t framenum = 0; framenum < frames; framenum++)
+ for (framenum = 0; framenum < frames; framenum++)
{
memcpy(&dest[framenum * CD_FRAME_SIZE], &cdfl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
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);
@@ -1095,7 +1129,7 @@ uint16_t crc16(const void *data, uint32_t length)
compressed - test if CHD file is compressed
+-------------------------------------------------*/
-static inline int compressed(chd_header* header) {
+static inline int chd_compressed(chd_header* header) {
return header->compression[0] != CHD_CODEC_NONE;
}
@@ -1105,42 +1139,58 @@ static inline int compressed(chd_header* header) {
static chd_error decompress_v5_map(chd_file* chd, chd_header* header)
{
+ int result = 0;
+ int hunknum;
+ int repcount = 0;
+ uint8_t lastcomp = 0;
+ uint32_t last_self = 0;
+ uint64_t last_parent = 0;
+ struct bitstream* bitbuf;
+ uint32_t mapbytes;
+ uint64_t firstoffs;
+ uint16_t mapcrc;
+ uint8_t lengthbits;
+ uint8_t selfbits;
+ uint8_t parentbits;
+ uint8_t *compressed_ptr;
+ uint8_t rawbuf[16];
+ struct huffman_decoder* decoder;
+ enum huffman_error err;
+ uint64_t curoffset;
int rawmapsize = map_size_v5(header);
- if (!compressed(header))
+ if (!chd_compressed(header))
{
header->rawmap = (uint8_t*)malloc(rawmapsize);
+ int result;
core_fseek(chd->file, header->mapoffset, SEEK_SET);
- core_fread(chd->file, header->rawmap, rawmapsize);
+ result = core_fread(chd->file, header->rawmap, rawmapsize);
return CHDERR_NONE;
}
/* read the reader */
- uint8_t rawbuf[16];
core_fseek(chd->file, header->mapoffset, SEEK_SET);
- core_fread(chd->file, rawbuf, sizeof(rawbuf));
- uint32_t const mapbytes = get_bigendian_uint32(&rawbuf[0]);
- uint64_t const firstoffs = get_bigendian_uint48(&rawbuf[4]);
- uint16_t const mapcrc = get_bigendian_uint16(&rawbuf[10]);
- uint8_t const lengthbits = rawbuf[12];
- uint8_t const selfbits = rawbuf[13];
- uint8_t const parentbits = rawbuf[14];
+ result = core_fread(chd->file, rawbuf, sizeof(rawbuf));
+ mapbytes = get_bigendian_uint32(&rawbuf[0]);
+ firstoffs = get_bigendian_uint48(&rawbuf[4]);
+ mapcrc = get_bigendian_uint16(&rawbuf[10]);
+ lengthbits = rawbuf[12];
+ selfbits = rawbuf[13];
+ parentbits = rawbuf[14];
/* now read the map */
- uint8_t* compressed = (uint8_t*)malloc(sizeof(uint8_t) * mapbytes);
+ compressed_ptr = (uint8_t*)malloc(sizeof(uint8_t) * mapbytes);
core_fseek(chd->file, header->mapoffset + 16, SEEK_SET);
- core_fread(chd->file, compressed, mapbytes);
- struct bitstream* bitbuf = create_bitstream(compressed, sizeof(uint8_t) * mapbytes);
+ result = core_fread(chd->file, compressed_ptr, mapbytes);
+ bitbuf = create_bitstream(compressed_ptr, sizeof(uint8_t) * mapbytes);
header->rawmap = (uint8_t*)malloc(rawmapsize);
/* first decode the compression types */
- struct huffman_decoder* decoder = create_huffman_decoder(16, 8);
- enum huffman_error err = huffman_import_tree_rle(decoder, bitbuf);
+ decoder = create_huffman_decoder(16, 8);
+ err = huffman_import_tree_rle(decoder, bitbuf);
if (err != HUFFERR_NONE)
return CHDERR_DECOMPRESSION_ERROR;
- uint8_t lastcomp = 0;
- int repcount = 0;
- for (int hunknum = 0; hunknum < header->hunkcount; hunknum++)
+ for (hunknum = 0; hunknum < header->hunkcount; hunknum++)
{
uint8_t *rawmap = header->rawmap + (hunknum * 12);
if (repcount > 0)
@@ -1158,10 +1208,8 @@ static chd_error decompress_v5_map(chd_file* chd, chd_header* header)
}
/* then iterate through the hunks and extract the needed data */
- uint64_t curoffset = firstoffs;
- uint32_t last_self = 0;
- uint64_t last_parent = 0;
- for (int hunknum = 0; hunknum < header->hunkcount; hunknum++)
+ curoffset = firstoffs;
+ for (hunknum = 0; hunknum < header->hunkcount; hunknum++)
{
uint8_t *rawmap = header->rawmap + (hunknum * 12);
uint64_t offset = curoffset;
@@ -1222,7 +1270,7 @@ static chd_error decompress_v5_map(chd_file* chd, chd_header* header)
put_bigendian_uint16(&rawmap[10], crc);
}
- free(compressed);
+ free(compressed_ptr);
free(bitbuf);
free(decoder->lookup);
free(decoder->huffnode);
@@ -1373,10 +1421,12 @@ chd_error chd_open_file(core_file *file, int mode, chd_file *parent, chd_file **
}
else
{
+ int decompnum;
/* verify the compression types and initialize the codecs */
- for (int decompnum = 0; decompnum < ARRAY_LENGTH(newchd->header.compression); decompnum++)
+ for (decompnum = 0; decompnum < ARRAY_LENGTH(newchd->header.compression); decompnum++)
{
- for (int i = 0 ; i < ARRAY_LENGTH(codec_interfaces) ; i++)
+ int i;
+ for (i = 0 ; i < ARRAY_LENGTH(codec_interfaces) ; i++)
{
if (codec_interfaces[i].compression == newchd->header.compression[decompnum])
{
@@ -1524,8 +1574,9 @@ void chd_close(chd_file *chd)
}
else
{
+ int i;
/* Free the codecs */
- for (int i = 0 ; i < ARRAY_LENGTH(chd->codecintf); i++)
+ for (i = 0 ; i < ARRAY_LENGTH(chd->codecintf); i++)
{
void* codec = NULL;
@@ -1986,7 +2037,7 @@ static chd_error header_read(chd_file *chd, chd_header *header)
memcpy(header->rawsha1, &rawheader[64], CHD_SHA1_BYTES);
/* determine properties of map entries */
- header->mapentrybytes = compressed(header) ? 12 : 4;
+ header->mapentrybytes = chd_compressed(header) ? 12 : 4;
/* hack */
header->totalhunks = header->hunkcount;
@@ -2106,6 +2157,8 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des
{
/* compressed data */
case V34_MAP_ENTRY_TYPE_COMPRESSED:
+ {
+ void *codec = NULL;
/* read it into the decompression buffer */
compressed_bytes = hunk_read_compressed(chd, entry->offset, entry->length);
@@ -2114,12 +2167,13 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des
/* now decompress using the codec */
err = CHDERR_NONE;
- void* codec = &chd->zlib_codec_data;
+ codec = &chd->zlib_codec_data;
if (chd->codecintf[0]->decompress != NULL)
err = (*chd->codecintf[0]->decompress)(codec, compressed_bytes, entry->length, dest, chd->header.hunkbytes);
if (err != CHDERR_NONE)
return err;
break;
+ }
/* uncompressed data */
case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
@@ -2156,16 +2210,18 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des
uint64_t blockoffs;
uint32_t blocklen;
uint16_t blockcrc;
+ void* codec = NULL;
uint8_t *rawmap = &chd->header.rawmap[chd->header.mapentrybytes * hunknum];
UINT8* compressed_bytes;
/* uncompressed case */
- if (!compressed(&chd->header))
+ if (!chd_compressed(&chd->header))
{
blockoffs = (uint64_t)get_bigendian_uint32(rawmap) * (uint64_t)chd->header.hunkbytes;
if (blockoffs != 0) {
+ int result;
core_fseek(chd->file, blockoffs, SEEK_SET);
- core_fread(chd->file, dest, chd->header.hunkbytes);
+ result = core_fread(chd->file, dest, chd->header.hunkbytes);
/* TODO
else if (m_parent_missing)
throw CHDERR_REQUIRES_PARENT; */
@@ -2176,13 +2232,14 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des
} else {
memset(dest, 0, chd->header.hunkbytes);
}
+ return CHDERR_NONE;
}
/* compressed case */
blocklen = get_bigendian_uint24(&rawmap[1]);
blockoffs = get_bigendian_uint48(&rawmap[4]);
blockcrc = get_bigendian_uint16(&rawmap[10]);
- void* codec = NULL;
+ codec = NULL;
switch (rawmap[0])
{
case COMPRESSION_TYPE_0:
@@ -2435,15 +2492,12 @@ static void zlib_codec_free(void *codec)
inflateEnd(&data->inflater);
/* free our fast memory */
- zlib_allocator alloc = data->allocator;
- for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
- if (alloc.allocptr[i])
- free(alloc.allocptr[i]);
+ zlib_allocator_free(&data->allocator);
}
}
/*-------------------------------------------------
- zlib_codec_decompress - decomrpess data using
+ zlib_codec_decompress - decompress data using
the ZLIB codec
-------------------------------------------------*/
@@ -2475,10 +2529,13 @@ static chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t
zlib_fast_alloc - fast malloc for ZLIB, which
allocates and frees memory frequently
-------------------------------------------------*/
+#define ZLIB_MIN_ALIGNMENT_BITS 512
+#define ZLIB_MIN_ALIGNMENT_BYTES (ZLIB_MIN_ALIGNMENT_BITS / 8)
static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
{
zlib_allocator *alloc = (zlib_allocator *)opaque;
+ uintptr_t paddr = 0;
UINT32 *ptr;
int i;
@@ -2493,12 +2550,12 @@ static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
{
/* set the low bit of the size so we don't match next time */
*ptr |= 1;
- return ptr + 1;
+ return (voidpf)(alloc->allocptr2[i]);
}
}
/* alloc a new one */
- ptr = (UINT32 *)malloc(size + sizeof(uintptr_t));
+ ptr = (UINT32 *)malloc(size + sizeof(UINT32) + ZLIB_MIN_ALIGNMENT_BYTES);
if (!ptr)
return NULL;
@@ -2507,12 +2564,14 @@ static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
if (!alloc->allocptr[i])
{
alloc->allocptr[i] = ptr;
+ paddr = (((uintptr_t)ptr) + sizeof(UINT32) + (ZLIB_MIN_ALIGNMENT_BYTES-1)) & (~(ZLIB_MIN_ALIGNMENT_BYTES-1));
+ alloc->allocptr2[i] = (uint32_t*)paddr;
break;
}
/* set the low bit of the size so we don't match next time */
*ptr = size | 1;
- return ptr + (sizeof(uint32_t) == sizeof(uintptr_t) ? 1 : 2);
+ return (voidpf)paddr;
}
/*-------------------------------------------------
@@ -2523,15 +2582,28 @@ static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
static void zlib_fast_free(voidpf opaque, voidpf address)
{
zlib_allocator *alloc = (zlib_allocator *)opaque;
- UINT32 *ptr = (UINT32 *)address - (sizeof(uint32_t) == sizeof(uintptr_t) ? 1 : 2);
+ UINT32 *ptr = (UINT32 *)address;
int i;
/* find the hunk */
for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
- if (ptr == alloc->allocptr[i])
+ if (ptr == alloc->allocptr2[i])
{
/* clear the low bit of the size to allow matches */
- *ptr &= ~1;
+ *(alloc->allocptr[i]) &= ~1;
return;
}
}
+
+/*-------------------------------------------------
+ zlib_allocator_free
+-------------------------------------------------*/
+static void zlib_allocator_free(voidpf opaque)
+{
+ zlib_allocator *alloc = (zlib_allocator *)opaque;
+ int i;
+
+ for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
+ if (alloc->allocptr[i])
+ free(alloc->allocptr[i]);
+}