Skip to content

Commit

Permalink
chd: Add precache option
Browse files Browse the repository at this point in the history
  • Loading branch information
retro-wertz committed Dec 9, 2017
1 parent 17889ba commit d4964f6
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 15 deletions.
95 changes: 80 additions & 15 deletions deps/libchdr/chd.c
Expand Up @@ -59,6 +59,8 @@ typedef unsigned char Byte;

#include <retro_inline.h>

#include "../deps/crypto/md5.h"

#define TRUE 1
#define FALSE 0

Expand Down Expand Up @@ -316,6 +318,8 @@ struct _chd_file

UINT32 async_hunknum; /* hunk index for asynchronous operations */
void * async_buffer; /* buffer pointer for asynchronous operations */

UINT8 * file_cache; /* cache of underlying file */
};


Expand Down Expand Up @@ -1490,6 +1494,31 @@ chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **
return err;
}

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_close - close a CHD file for access
Expand Down Expand Up @@ -1567,6 +1596,9 @@ void chd_close(chd_file *chd)

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(chd);
}
Expand Down Expand Up @@ -1990,6 +2022,39 @@ static chd_error hunk_read_into_cache(chd_file *chd, UINT32 hunknum)
return CHDERR_NONE;
}

static UINT8* 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;
}
}

static chd_error 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_memory - read a hunk into
Expand Down Expand Up @@ -2020,28 +2085,25 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des
case V34_MAP_ENTRY_TYPE_COMPRESSED:
{
void* codec;
/* read it into the decompression buffer */
core_fseek(chd->file, entry->offset, SEEK_SET);
bytes = core_fread(chd->file, chd->compressed, entry->length);
if (bytes != entry->length)
return CHDERR_READ_ERROR;
UINT8 *bytes = read_compressed(chd, entry->offset, entry->length);
if (bytes == NULL)
return CHDERR_READ_ERROR;

/* now decompress using the codec */
err = CHDERR_NONE;
codec = &chd->zlib_codec_data;
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, bytes, entry->length, dest, chd->header.hunkbytes);
if (err != CHDERR_NONE)
return err;
}
break;

/* uncompressed data */
case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
core_fseek(chd->file, entry->offset, SEEK_SET);
bytes = core_fread(chd->file, dest, chd->header.hunkbytes);
if (bytes != chd->header.hunkbytes)
return CHDERR_READ_ERROR;
err = read_uncompressed(chd, entry->offset, chd->header.hunkbytes, dest);
if (err != CHDERR_NONE)
return err;
break;

/* mini-compressed data */
Expand Down Expand Up @@ -2075,6 +2137,7 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des
uint16_t blockcrc;
void* codec = NULL;
uint8_t *rawmap = &chd->header.rawmap[chd->header.mapentrybytes * hunknum];
UINT8 *bytes;

// uncompressed case
/* TODO
Expand Down Expand Up @@ -2102,8 +2165,9 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des
case COMPRESSION_TYPE_1:
case COMPRESSION_TYPE_2:
case COMPRESSION_TYPE_3:
core_fseek(chd->file, blockoffs, SEEK_SET);
core_fread(chd->file, chd->compressed, blocklen);
bytes = read_compressed(chd, blockoffs, blocklen);
if (bytes == NULL)
return CHDERR_READ_ERROR;
switch (chd->codecintf[rawmap[0]]->compression)
{
case CHD_CODEC_CD_LZMA:
Expand All @@ -2120,14 +2184,15 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des
}
if (codec==NULL)
return CHDERR_DECOMPRESSION_ERROR;
chd->codecintf[rawmap[0]]->decompress(codec, chd->compressed, blocklen, dest, chd->header.hunkbytes);
chd->codecintf[rawmap[0]]->decompress(codec, bytes, blocklen, dest, chd->header.hunkbytes);
if (dest != NULL && crc16(dest, chd->header.hunkbytes) != blockcrc)
return CHDERR_DECOMPRESSION_ERROR;
return CHDERR_NONE;

case COMPRESSION_NONE:
core_fseek(chd->file, blockoffs, SEEK_SET);
core_fread(chd->file, dest, chd->header.hunkbytes);
err = read_uncompressed(chd, blockoffs, blocklen, dest);
if (err != CHDERR_NONE)
return err;
if (crc16(dest, chd->header.hunkbytes) != blockcrc)
return CHDERR_DECOMPRESSION_ERROR;
return CHDERR_NONE;
Expand Down
2 changes: 2 additions & 0 deletions deps/libchdr/chd.h
Expand Up @@ -349,6 +349,8 @@ struct _chd_verify_result
/* open an existing CHD file */
chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd);

/* precache underlying file */
chd_error chd_precache(chd_file *chd);

/* close a CHD file */
void chd_close(chd_file *chd);
Expand Down

0 comments on commit d4964f6

Please sign in to comment.