X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=deps%2Flibchdr%2Fsrc%2Flibchdr_chd.c;fp=deps%2Flibchdr%2Fsrc%2Flibchdr_chd.c;h=076202b3bfdfa8506520ac7062e173947910a547;hb=648db22b0750712da893c306efcc8e4b2d3a4e3c;hp=d2bf4d04eea00c7f2381651ab549bea7b1448fa6;hpb=e2fb1389dc12376acb84e4993ed3b08760257252;p=pcsx_rearmed.git diff --git a/deps/libchdr/src/libchdr_chd.c b/deps/libchdr/src/libchdr_chd.c index d2bf4d04..076202b3 100644 --- a/deps/libchdr/src/libchdr_chd.c +++ b/deps/libchdr/src/libchdr_chd.c @@ -47,13 +47,14 @@ #include #include #include +#include #include "LzmaEnc.h" #include "LzmaDec.h" #if defined(__PS3__) || defined(__PSL1GHT__) #define __MACTYPES__ #endif -#include "zlib.h" +#include #undef TRUE #undef FALSE @@ -233,6 +234,12 @@ struct _huff_codec_data struct huffman_decoder* decoder; }; +typedef struct _zstd_codec_data zstd_codec_data; +struct _zstd_codec_data +{ + ZSTD_DStream *dstream; +}; + /* codec-private data for the CDZL codec */ typedef struct _cdzl_codec_data cdzl_codec_data; struct _cdzl_codec_data { @@ -275,6 +282,16 @@ struct _cdfl_codec_data { uint8_t* buffer; }; +typedef struct _cdzs_codec_data cdzs_codec_data; +struct _cdzs_codec_data +{ + zstd_codec_data base_decompressor; +#ifdef WANT_SUBCODE + zstd_codec_data subcode_decompressor; +#endif + uint8_t* buffer; +}; + /* internal representation of an open CHD file */ struct _chd_file { @@ -302,9 +319,11 @@ struct _chd_file lzma_codec_data lzma_codec_data; /* lzma codec data */ huff_codec_data huff_codec_data; /* huff codec data */ flac_codec_data flac_codec_data; /* flac codec data */ + zstd_codec_data zstd_codec_data; /* zstd codec data */ cdzl_codec_data cdzl_codec_data; /* cdzl codec data */ cdlz_codec_data cdlz_codec_data; /* cdlz codec data */ cdfl_codec_data cdfl_codec_data; /* cdfl codec data */ + cdzs_codec_data cdzs_codec_data; /* cdzs codec data */ #ifdef NEED_CACHE_HUNK UINT32 maxhunk; /* maximum hunk accessed */ @@ -372,6 +391,12 @@ static chd_error flac_codec_init(void *codec, uint32_t hunkbytes); static void flac_codec_free(void *codec); static chd_error flac_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); +/* zstd compression codec */ +static chd_error zstd_codec_init(void *codec, uint32_t hunkbytes); +static void zstd_codec_free(void *codec); +static chd_error zstd_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); + + /* cdzl compression codec */ static chd_error cdzl_codec_init(void* codec, uint32_t hunkbytes); static void cdzl_codec_free(void* codec); @@ -387,6 +412,11 @@ static chd_error cdfl_codec_init(void* codec, uint32_t hunkbytes); static void cdfl_codec_free(void* codec); static chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); +/* cdzs compression codec */ +static chd_error cdzs_codec_init(void *codec, uint32_t hunkbytes); +static void cdzs_codec_free(void *codec); +static chd_error cdzs_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); + /*************************************************************************** * LZMA ALLOCATOR HELPER *************************************************************************** @@ -811,11 +841,12 @@ static chd_error huff_codec_decompress(void *codec, const uint8_t *src, uint32_t if (err != HUFFERR_NONE) { free(bitbuf); - return err; + return CHDERR_DECOMPRESSION_ERROR; } // then decode the data - for (uint32_t cur = 0; cur < destlen; cur++) + uint32_t cur; + for (cur = 0; cur < destlen; cur++) dest[cur] = huffman_decode_one(huff_codec->decoder, bitbuf); bitstream_flush(bitbuf); chd_error result = bitstream_overflow(bitbuf) ? CHDERR_DECOMPRESSION_ERROR : CHDERR_NONE; @@ -985,6 +1016,163 @@ static chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t return CHDERR_NONE; } + + +/*************************************************************************** + * ZSTD DECOMPRESSOR + *************************************************************************** + */ + +/*------------------------------------------------- + * zstd_codec_init - constructor + *------------------------------------------------- + */ + +static chd_error zstd_codec_init(void* codec, uint32_t hunkbytes) +{ + zstd_codec_data* zstd_codec = (zstd_codec_data*) codec; + + zstd_codec->dstream = ZSTD_createDStream(); + if (!zstd_codec->dstream) { + printf("NO DSTREAM CREATED!\n"); + return CHDERR_DECOMPRESSION_ERROR; + } + return CHDERR_NONE; +} + +/*------------------------------------------------- + * zstd_codec_free + *------------------------------------------------- + */ + +static void zstd_codec_free(void* codec) +{ + zstd_codec_data* zstd_codec = (zstd_codec_data*) codec; + + ZSTD_freeDStream(zstd_codec->dstream); +} + +/*------------------------------------------------- + * decompress - decompress data using the ZSTD + * codec + *------------------------------------------------- + */ +static chd_error zstd_codec_decompress(void* codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) +{ + /* initialize */ + zstd_codec_data* zstd_codec = (zstd_codec_data*) codec; + //reset decompressor + size_t zstd_res = ZSTD_initDStream(zstd_codec->dstream); + if (ZSTD_isError(zstd_res)) + { + printf("INITI DSTREAM FAILED!\n"); + return CHDERR_DECOMPRESSION_ERROR; + } + + ZSTD_inBuffer input = {src, complen, 0}; + ZSTD_outBuffer output = {dest, destlen, 0 }; + + while ((input.pos < input.size) && (output.pos < output.size)) + { + zstd_res = ZSTD_decompressStream(zstd_codec->dstream, &output, &input); + if (ZSTD_isError(zstd_res)) + { + printf("DECOMPRESSION ERROR IN LOOP\n"); + return CHDERR_DECOMPRESSION_ERROR; + } + } + if (output.pos != output.size) + { + printf("OUTPUT DOESN'T MATCH!\n"); + return CHDERR_DECOMPRESSION_ERROR; + } + return CHDERR_NONE; + +} + +/* cdzs */ +static chd_error cdzs_codec_init(void* codec, uint32_t hunkbytes) +{ + chd_error ret; + cdzs_codec_data* cdzs = (cdzs_codec_data*) codec; + + /* allocate buffer */ + cdzs->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes); + if (cdzs->buffer == NULL) + return CHDERR_OUT_OF_MEMORY; + + /* make sure the CHD's hunk size is an even multiple of the frame size */ + ret = zstd_codec_init(&cdzs->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA); + if (ret != CHDERR_NONE) + return ret; + +#ifdef WANT_SUBCODE + ret = zstd_codec_init(&cdzs->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SUBCODE_DATA); + if (ret != CHDERR_NONE) + return ret; +#endif + + if (hunkbytes % CD_FRAME_SIZE != 0) + return CHDERR_CODEC_ERROR; + + return CHDERR_NONE; +} + +static void cdzs_codec_free(void* codec) +{ + cdzs_codec_data* cdzs = (cdzs_codec_data*) codec; + free(cdzs->buffer); + zstd_codec_free(&cdzs->base_decompressor); +#ifdef WANT_SUBCODE + zstd_codec_free(&cdzs->subcode_decompressor); +#endif +} + +static chd_error cdzs_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) +{ + uint32_t framenum; + cdzs_codec_data* cdzs = (cdzs_codec_data*)codec; + + /* determine header bytes */ + uint32_t frames = destlen / CD_FRAME_SIZE; + uint32_t complen_bytes = (destlen < 65536) ? 2 : 3; + uint32_t ecc_bytes = (frames + 7) / 8; + uint32_t header_bytes = ecc_bytes + complen_bytes; + + /* extract compressed length of base */ + uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1]; + if (complen_bytes > 2) + complen_base = (complen_base << 8) | src[ecc_bytes + 2]; + + /* reset and decode */ + zstd_codec_decompress(&cdzs->base_decompressor, &src[header_bytes], complen_base, &cdzs->buffer[0], frames * CD_MAX_SECTOR_DATA); +#ifdef WANT_SUBCODE + zstd_codec_decompress(&cdzs->subcode_decompressor, &src[header_bytes + complen_base], complen - complen_base - header_bytes, &cdzs->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA); +#endif + + /* reassemble the data */ + for (framenum = 0; framenum < frames; framenum++) + { + uint8_t *sector; + + memcpy(&dest[framenum * CD_FRAME_SIZE], &cdzs->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA); +#ifdef WANT_SUBCODE + memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdzs->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA); +#endif + +#ifdef WANT_RAW_DATA_SECTOR + /* reconstitute the ECC data and sync header */ + sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE]; + if ((src[framenum / 8] & (1 << (framenum % 8))) != 0) + { + memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header)); + ecc_generate(sector); + } +#endif + } + return CHDERR_NONE; +} + /*************************************************************************** CODEC INTERFACES ***************************************************************************/ @@ -1067,6 +1255,16 @@ static const codec_interface codec_interfaces[] = flac_codec_decompress, NULL }, + /* V5 zstd compression */ + { + CHD_CODEC_ZSTD, + "ZStandard", + FALSE, + zstd_codec_init, + zstd_codec_free, + zstd_codec_decompress, + NULL + }, /* V5 CD zlib compression */ { @@ -1100,6 +1298,17 @@ static const codec_interface codec_interfaces[] = cdfl_codec_decompress, NULL }, + /* V5 CD zstd compression */ + { + CHD_CODEC_CD_ZSTD, + "cdzs (CD ZStandard)", + FALSE, + cdzs_codec_init, + cdzs_codec_free, + cdzs_codec_decompress, + NULL + } + }; /*************************************************************************** @@ -1695,6 +1904,10 @@ CHD_EXPORT chd_error chd_open_core_file(core_file *file, int mode, chd_file *par codec = &newchd->flac_codec_data; break; + case CHD_CODEC_ZSTD: + codec = &newchd->zstd_codec_data; + break; + case CHD_CODEC_CD_ZLIB: codec = &newchd->cdzl_codec_data; break; @@ -1706,6 +1919,10 @@ CHD_EXPORT chd_error chd_open_core_file(core_file *file, int mode, chd_file *par case CHD_CODEC_CD_FLAC: codec = &newchd->cdfl_codec_data; break; + + case CHD_CODEC_CD_ZSTD: + codec = &newchd->cdzs_codec_data; + break; } if (codec == NULL) @@ -1848,6 +2065,10 @@ CHD_EXPORT void chd_close(chd_file *chd) codec = &chd->flac_codec_data; break; + case CHD_CODEC_ZSTD: + codec = &chd->zstd_codec_data; + break; + case CHD_CODEC_CD_ZLIB: codec = &chd->cdzl_codec_data; break; @@ -1859,6 +2080,10 @@ CHD_EXPORT void chd_close(chd_file *chd) case CHD_CODEC_CD_FLAC: codec = &chd->cdfl_codec_data; break; + + case CHD_CODEC_CD_ZSTD: + codec = &chd->cdzs_codec_data; + break; } if (codec) @@ -2478,7 +2703,9 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des /* read it into the decompression buffer */ compressed_bytes = hunk_read_compressed(chd, entry->offset, entry->length); if (compressed_bytes == NULL) + { return CHDERR_READ_ERROR; + } /* now decompress using the codec */ err = CHDERR_NONE; @@ -2588,6 +2815,10 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des codec = &chd->flac_codec_data; break; + case CHD_CODEC_ZSTD: + codec = &chd->zstd_codec_data; + break; + case CHD_CODEC_CD_ZLIB: codec = &chd->cdzl_codec_data; break; @@ -2599,6 +2830,10 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des case CHD_CODEC_CD_FLAC: codec = &chd->cdfl_codec_data; break; + + case CHD_CODEC_CD_ZSTD: + codec = &chd->cdzs_codec_data; + break; } if (codec==NULL) return CHDERR_CODEC_ERROR;