From e1acac6d83b36531e543e39a9e1a363e681083e6 Mon Sep 17 00:00:00 2001 From: Anthony Pesch Date: Thu, 10 May 2018 01:10:56 -0400 Subject: [PATCH] backported support for loading uncompressed chd files handle errors from both map_read as well as decompress_v5_map --- src/chd.c | 58 +++++++++++++++++++++++++++++++++---------------------- src/chd.h | 1 + 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/src/chd.c b/src/chd.c index d9a26a7..6acf5e6 100644 --- a/src/chd.c +++ b/src/chd.c @@ -789,7 +789,6 @@ chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t comple CODEC INTERFACES ***************************************************************************/ - static const codec_interface codec_interfaces[] = { /* "none" or no compression */ @@ -1081,18 +1080,28 @@ uint16_t crc16(const void *data, uint32_t length) return crc; } +/*------------------------------------------------- + compressed - test if CHD file is compressed ++-------------------------------------------------*/ + +static inline int compressed(chd_header* header) { + return header->compression[0] != CHD_CODEC_NONE; +} + /*------------------------------------------------- decompress_v5_map - decompress the v5 map -------------------------------------------------*/ static chd_error decompress_v5_map(chd_file* chd, chd_header* header) { - if (header->mapoffset == 0) + int rawmapsize = map_size_v5(header); + + if (!compressed(header)) { -#if 0 - memset(header->rawmap, 0xff,map_size_v5(header)); -#endif - return CHDERR_READ_ERROR; + header->rawmap = (uint8_t*)malloc(rawmapsize); + core_fseek(chd->file, header->mapoffset, SEEK_SET); + core_fread(chd->file, header->rawmap, rawmapsize); + return CHDERR_NONE; } /* read the reader */ @@ -1111,7 +1120,7 @@ static chd_error decompress_v5_map(chd_file* chd, chd_header* header) 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); - header->rawmap = (uint8_t*)malloc(sizeof(uint8_t) * map_size_v5(header)); + header->rawmap = (uint8_t*)malloc(rawmapsize); /* first decode the compression types */ struct huffman_decoder* decoder = create_huffman_decoder(16, 8); @@ -1300,13 +1309,14 @@ chd_error chd_open_file(core_file *file, int mode, chd_file *parent, chd_file ** if (newchd->header.version < 5) { err = map_read(newchd); - if (err != CHDERR_NONE) - EARLY_EXIT(err); } else { err = decompress_v5_map(newchd, &(newchd->header)); } + if (err != CHDERR_NONE) + EARLY_EXIT(err); + /* allocate and init the hunk cache */ newchd->cache = (UINT8 *)malloc(newchd->header.hunkbytes); @@ -1910,7 +1920,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 = 12; /* TODO compressed() ? 12 : 4; */ + header->mapentrybytes = compressed(header) ? 12 : 4; /* hack */ header->totalhunks = header->hunkcount; @@ -2039,22 +2049,24 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des uint16_t blockcrc; uint8_t *rawmap = &chd->header.rawmap[chd->header.mapentrybytes * hunknum]; -#if 0 - /* uncompressed case - TODO */ - if (!compressed()) + /* uncompressed case */ + if (!compressed(&chd->header)) { - blockoffs = uint64_t(be_read(rawmap, 4)) * uint64_t(m_hunkbytes); - if (blockoffs != 0) - file_read(blockoffs, dest, m_hunkbytes); + blockoffs = (uint64_t)get_bigendian_uint32(rawmap) * (uint64_t)chd->header.hunkbytes; + if (blockoffs != 0) { + core_fseek(chd->file, blockoffs, SEEK_SET); + core_fread(chd->file, dest, chd->header.hunkbytes); + /* TODO else if (m_parent_missing) - throw CHDERR_REQUIRES_PARENT; - else if (m_parent != nullptr) - m_parent->read_hunk(hunknum, dest); - else - memset(dest, 0, m_hunkbytes); - return CHDERR_NONE; + throw CHDERR_REQUIRES_PARENT; */ + } else if (chd->parent) { + err = hunk_read_into_memory(chd->parent, hunknum, dest); + if (err != CHDERR_NONE) + return err; + } else { + memset(dest, 0, chd->header.hunkbytes); + } } -#endif /* compressed case */ blocklen = get_bigendian_uint24(&rawmap[1]); diff --git a/src/chd.h b/src/chd.h index 42c38c0..dc95071 100644 --- a/src/chd.h +++ b/src/chd.h @@ -202,6 +202,7 @@ extern "C" { #define CHDCOMPRESSION_ZLIB_PLUS 2 #define CHDCOMPRESSION_AV 3 +#define CHD_CODEC_NONE 0 #define CHD_CODEC_ZLIB CHD_MAKE_TAG('z','l','i','b') /* general codecs with CD frontend */ #define CHD_CODEC_CD_ZLIB CHD_MAKE_TAG('c','d','z','l')