dep: Update libchdr

This commit is contained in:
Connor McLaughlin 2020-09-14 21:52:47 +10:00
parent 4d9e58ac42
commit c8d7b0fc08
3 changed files with 144 additions and 25 deletions

View file

@ -360,6 +360,9 @@ struct _chd_verify_result
chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd); chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd);
chd_error chd_open_file(core_file* file, int mode, chd_file* parent, chd_file** chd); chd_error chd_open_file(core_file* file, int mode, chd_file* parent, chd_file** chd);
/* precache underlying file */
chd_error chd_precache(chd_file *chd);
/* close a CHD file */ /* close a CHD file */
void chd_close(chd_file *chd); void chd_close(chd_file *chd);

View file

@ -4,6 +4,11 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#ifdef _MSC_VER
#include <basetsd.h>
typedef SSIZE_T ssize_t;
#endif
#define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0])) #define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0]))
typedef uint64_t UINT64; typedef uint64_t UINT64;

View file

@ -299,6 +299,8 @@ struct _chd_file
UINT32 async_hunknum; /* hunk index for asynchronous operations */ UINT32 async_hunknum; /* hunk index for asynchronous operations */
void * async_buffer; /* buffer pointer for asynchronous operations */ void * async_buffer; /* buffer pointer for asynchronous operations */
UINT8 * file_cache; /* cache of underlying file */
}; };
/* a single metadata hash entry */ /* a single metadata hash entry */
@ -340,6 +342,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 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 voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size);
static void zlib_fast_free(voidpf opaque, voidpf address); static void zlib_fast_free(voidpf opaque, voidpf address);
static void zlib_allocator_free(voidpf opaque);
/* lzma compression codec */ /* lzma compression codec */
static chd_error lzma_codec_init(void *codec, uint32_t hunkbytes); static chd_error lzma_codec_init(void *codec, uint32_t hunkbytes);
@ -427,7 +430,7 @@ void *lzma_fast_alloc(void *p, size_t size)
} }
/* alloc a new one and put it into the list */ /* alloc a new one and put it into the list */
uint32_t *addr = (uint32_t *)malloc(sizeof(uint8_t) * (size + sizeof(uint32_t))); uint32_t *addr = (uint32_t *)malloc(sizeof(uint8_t) * size + sizeof(uintptr_t));
if (addr==NULL) if (addr==NULL)
return NULL; return NULL;
for (int scan = 0; scan < MAX_LZMA_ALLOCS; scan++) for (int scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
@ -441,7 +444,7 @@ void *lzma_fast_alloc(void *p, size_t size)
/* set the low bit of the size so we don't match next time */ /* set the low bit of the size so we don't match next time */
*addr = size | 1; *addr = size | 1;
return addr + 1; return addr + (sizeof(uint32_t) == sizeof(uintptr_t) ? 1 : 2);
} }
/*------------------------------------------------- /*-------------------------------------------------
@ -538,6 +541,7 @@ void lzma_codec_free(void* codec)
/* free memory */ /* free memory */
LzmaDec_Free(&lzma_codec->decoder, (ISzAlloc*)&lzma_codec->allocator); LzmaDec_Free(&lzma_codec->decoder, (ISzAlloc*)&lzma_codec->allocator);
lzma_allocator_free(&lzma_codec->allocator);
} }
/*------------------------------------------------- /*-------------------------------------------------
@ -582,7 +586,10 @@ chd_error cdlz_codec_init(void* codec, uint32_t hunkbytes)
void cdlz_codec_free(void* codec) void cdlz_codec_free(void* codec)
{ {
/* TODO */ cdlz_codec_data* cdlz = (cdlz_codec_data*) codec;
free(cdlz->buffer);
lzma_codec_free(&cdlz->base_decompressor);
zlib_codec_free(&cdlz->subcode_decompressor);
} }
chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
@ -641,7 +648,10 @@ chd_error cdzl_codec_init(void *codec, uint32_t hunkbytes)
void cdzl_codec_free(void *codec) void cdzl_codec_free(void *codec)
{ {
/* TODO */ cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
zlib_codec_free(&cdzl->base_decompressor);
zlib_codec_free(&cdzl->subcode_decompressor);
free(cdzl->buffer);
} }
chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
@ -741,7 +751,12 @@ chd_error cdfl_codec_init(void *codec, uint32_t hunkbytes)
void cdfl_codec_free(void *codec) void cdfl_codec_free(void *codec)
{ {
cdfl_codec_data *cdfl = (cdfl_codec_data*)codec; cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
free(cdfl->buffer);
inflateEnd(&cdfl->inflater); 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) chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
@ -1211,6 +1226,12 @@ static chd_error decompress_v5_map(chd_file* chd, chd_header* header)
put_bigendian_uint16(&rawmap[10], crc); put_bigendian_uint16(&rawmap[10], crc);
} }
free(compressed);
free(bitbuf);
free(decoder->lookup);
free(decoder->huffnode);
free(decoder);
/* verify the final CRC */ /* verify the final CRC */
if (crc16(&header->rawmap[0], header->hunkcount * 12) != mapcrc) if (crc16(&header->rawmap[0], header->hunkcount * 12) != mapcrc)
return CHDERR_DECOMPRESSION_ERROR; return CHDERR_DECOMPRESSION_ERROR;
@ -1414,6 +1435,37 @@ cleanup:
return err; return err;
} }
/*-------------------------------------------------
chd_precache - precache underlying file in
memory
-------------------------------------------------*/
chd_error chd_precache(chd_file *chd)
{
ssize_t size, count;
if (chd->file_cache == NULL)
{
core_fseek(chd->file, 0, SEEK_END);
size = core_ftell(chd->file);
if (size <= 0)
return CHDERR_INVALID_DATA;
chd->file_cache = malloc(size);
if (chd->file_cache == NULL)
return CHDERR_OUT_OF_MEMORY;
core_fseek(chd->file, 0, SEEK_SET);
count = core_fread(chd->file, chd->file_cache, size);
if (count != size)
{
free(chd->file_cache);
chd->file_cache = NULL;
return CHDERR_READ_ERROR;
}
}
return CHDERR_NONE;
}
/*------------------------------------------------- /*-------------------------------------------------
chd_open - open a CHD file by chd_open - open a CHD file by
filename filename
@ -1542,6 +1594,9 @@ void chd_close(chd_file *chd)
if (PRINTF_MAX_HUNK) printf("Max hunk = %d/%d\n", chd->maxhunk, chd->header.totalhunks); if (PRINTF_MAX_HUNK) printf("Max hunk = %d/%d\n", chd->maxhunk, chd->header.totalhunks);
if (chd->file_cache)
free(chd->file_cache);
/* free our memory */ /* free our memory */
free(chd); free(chd);
} }
@ -1955,6 +2010,50 @@ static chd_error header_read(chd_file *chd, chd_header *header)
INTERNAL HUNK READ/WRITE INTERNAL HUNK READ/WRITE
***************************************************************************/ ***************************************************************************/
/*-------------------------------------------------
hunk_read_compressed - read a compressed
hunk
-------------------------------------------------*/
static UINT8* hunk_read_compressed(chd_file *chd, UINT64 offset, size_t size)
{
ssize_t bytes;
if (chd->file_cache != NULL)
{
return chd->file_cache + offset;
}
else
{
core_fseek(chd->file, offset, SEEK_SET);
bytes = core_fread(chd->file, chd->compressed, size);
if (bytes != size)
return NULL;
return chd->compressed;
}
}
/*-------------------------------------------------
hunk_read_uncompressed - read an uncompressed
hunk
-------------------------------------------------*/
static chd_error hunk_read_uncompressed(chd_file *chd, UINT64 offset, size_t size, UINT8 *dest)
{
ssize_t bytes;
if (chd->file_cache != NULL)
{
memcpy(dest, chd->file_cache + offset, size);
}
else
{
core_fseek(chd->file, offset, SEEK_SET);
bytes = core_fread(chd->file, dest, size);
if (bytes != size)
return CHDERR_READ_ERROR;
}
return CHDERR_NONE;
}
/*------------------------------------------------- /*-------------------------------------------------
hunk_read_into_cache - read a hunk into hunk_read_into_cache - read a hunk into
the CHD's hunk cache the CHD's hunk cache
@ -2004,6 +2103,7 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des
{ {
map_entry *entry = &chd->map[hunknum]; map_entry *entry = &chd->map[hunknum];
UINT32 bytes; UINT32 bytes;
UINT8* compressed_bytes;
/* switch off the entry type */ /* switch off the entry type */
switch (entry->flags & MAP_ENTRY_FLAG_TYPE_MASK) switch (entry->flags & MAP_ENTRY_FLAG_TYPE_MASK)
@ -2012,26 +2112,24 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des
case V34_MAP_ENTRY_TYPE_COMPRESSED: case V34_MAP_ENTRY_TYPE_COMPRESSED:
/* read it into the decompression buffer */ /* read it into the decompression buffer */
core_fseek(chd->file, entry->offset, SEEK_SET); compressed_bytes = hunk_read_compressed(chd, entry->offset, entry->length);
bytes = core_fread(chd->file, chd->compressed, entry->length); if (compressed_bytes == NULL)
if (bytes != entry->length)
return CHDERR_READ_ERROR; return CHDERR_READ_ERROR;
/* now decompress using the codec */ /* now decompress using the codec */
err = CHDERR_NONE; err = CHDERR_NONE;
void* codec = &chd->zlib_codec_data; void* codec = &chd->zlib_codec_data;
if (chd->codecintf[0]->decompress != NULL) if (chd->codecintf[0]->decompress != NULL)
err = (*chd->codecintf[0]->decompress)(codec, chd->compressed, entry->length, dest, chd->header.hunkbytes); err = (*chd->codecintf[0]->decompress)(codec, compressed_bytes, entry->length, dest, chd->header.hunkbytes);
if (err != CHDERR_NONE) if (err != CHDERR_NONE)
return err; return err;
break; break;
/* uncompressed data */ /* uncompressed data */
case V34_MAP_ENTRY_TYPE_UNCOMPRESSED: case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
core_fseek(chd->file, entry->offset, SEEK_SET); err = hunk_read_uncompressed(chd, entry->offset, chd->header.hunkbytes, dest);
bytes = core_fread(chd->file, dest, chd->header.hunkbytes); if (err != CHDERR_NONE)
if (bytes != chd->header.hunkbytes) return err;
return CHDERR_READ_ERROR;
break; break;
/* mini-compressed data */ /* mini-compressed data */
@ -2063,6 +2161,7 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des
uint32_t blocklen; uint32_t blocklen;
uint16_t blockcrc; uint16_t blockcrc;
uint8_t *rawmap = &chd->header.rawmap[chd->header.mapentrybytes * hunknum]; uint8_t *rawmap = &chd->header.rawmap[chd->header.mapentrybytes * hunknum];
UINT8* compressed_bytes;
/* uncompressed case */ /* uncompressed case */
if (!compressed(&chd->header)) if (!compressed(&chd->header))
@ -2094,8 +2193,9 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des
case COMPRESSION_TYPE_1: case COMPRESSION_TYPE_1:
case COMPRESSION_TYPE_2: case COMPRESSION_TYPE_2:
case COMPRESSION_TYPE_3: case COMPRESSION_TYPE_3:
core_fseek(chd->file, blockoffs, SEEK_SET); compressed_bytes = hunk_read_compressed(chd, blockoffs, blocklen);
core_fread(chd->file, chd->compressed, blocklen); if (compressed_bytes == NULL)
return CHDERR_READ_ERROR;
switch (chd->codecintf[rawmap[0]]->compression) switch (chd->codecintf[rawmap[0]]->compression)
{ {
case CHD_CODEC_CD_LZMA: case CHD_CODEC_CD_LZMA:
@ -2116,14 +2216,15 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des
} }
if (codec==NULL) if (codec==NULL)
return CHDERR_DECOMPRESSION_ERROR; return CHDERR_DECOMPRESSION_ERROR;
chd->codecintf[rawmap[0]]->decompress(codec, chd->compressed, blocklen, dest, chd->header.hunkbytes); chd->codecintf[rawmap[0]]->decompress(codec, compressed_bytes, blocklen, dest, chd->header.hunkbytes);
if (dest != NULL && crc16(dest, chd->header.hunkbytes) != blockcrc) if (dest != NULL && crc16(dest, chd->header.hunkbytes) != blockcrc)
return CHDERR_DECOMPRESSION_ERROR; return CHDERR_DECOMPRESSION_ERROR;
return CHDERR_NONE; return CHDERR_NONE;
case COMPRESSION_NONE: case COMPRESSION_NONE:
core_fseek(chd->file, blockoffs, SEEK_SET); err = hunk_read_uncompressed(chd, blockoffs, blocklen, dest);
core_fread(chd->file, dest, chd->header.hunkbytes); if (err != CHDERR_NONE)
return err;
if (crc16(dest, chd->header.hunkbytes) != blockcrc) if (crc16(dest, chd->header.hunkbytes) != blockcrc)
return CHDERR_DECOMPRESSION_ERROR; return CHDERR_DECOMPRESSION_ERROR;
return CHDERR_NONE; return CHDERR_NONE;
@ -2338,15 +2439,12 @@ static void zlib_codec_free(void *codec)
inflateEnd(&data->inflater); inflateEnd(&data->inflater);
/* free our fast memory */ /* free our fast memory */
zlib_allocator alloc = data->allocator; zlib_allocator_free(&data->allocator);
for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
if (alloc.allocptr[i])
free(alloc.allocptr[i]);
} }
} }
/*------------------------------------------------- /*-------------------------------------------------
zlib_codec_decompress - decomrpess data using zlib_codec_decompress - decompress data using
the ZLIB codec the ZLIB codec
-------------------------------------------------*/ -------------------------------------------------*/
@ -2401,7 +2499,7 @@ static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
} }
/* alloc a new one */ /* alloc a new one */
ptr = (UINT32 *)malloc(size + sizeof(UINT32)); ptr = (UINT32 *)malloc(size + sizeof(uintptr_t));
if (!ptr) if (!ptr)
return NULL; return NULL;
@ -2415,7 +2513,7 @@ 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 */ /* set the low bit of the size so we don't match next time */
*ptr = size | 1; *ptr = size | 1;
return ptr + 1; return ptr + (sizeof(uint32_t) == sizeof(uintptr_t) ? 1 : 2);
} }
/*------------------------------------------------- /*-------------------------------------------------
@ -2426,7 +2524,7 @@ static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
static void zlib_fast_free(voidpf opaque, voidpf address) static void zlib_fast_free(voidpf opaque, voidpf address)
{ {
zlib_allocator *alloc = (zlib_allocator *)opaque; zlib_allocator *alloc = (zlib_allocator *)opaque;
UINT32 *ptr = (UINT32 *)address - 1; UINT32 *ptr = (UINT32 *)address - (sizeof(uint32_t) == sizeof(uintptr_t) ? 1 : 2);
int i; int i;
/* find the hunk */ /* find the hunk */
@ -2438,3 +2536,16 @@ static void zlib_fast_free(voidpf opaque, voidpf address)
return; 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]);
}