Skip to content

Commit

Permalink
Add support for 'huff' codec.
Browse files Browse the repository at this point in the history
  • Loading branch information
jpd002 committed Dec 30, 2022
1 parent a20e04c commit 5715077
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 2 deletions.
1 change: 1 addition & 0 deletions include/libchdr/chd.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ extern "C" {
#define CHD_CODEC_NONE 0
#define CHD_CODEC_ZLIB CHD_MAKE_TAG('z','l','i','b')
#define CHD_CODEC_LZMA CHD_MAKE_TAG('l','z','m','a')
#define CHD_CODEC_HUFFMAN CHD_MAKE_TAG('h','u','f','f')
#define CHD_CODEC_FLAC CHD_MAKE_TAG('f','l','a','c')
/* general codecs with CD frontend */
#define CHD_CODEC_CD_ZLIB CHD_MAKE_TAG('c','d','z','l')
Expand Down
80 changes: 78 additions & 2 deletions src/libchdr_chd.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,12 @@ struct _lzma_codec_data
lzma_allocator allocator;
};

typedef struct _huff_codec_data huff_codec_data;
struct _huff_codec_data
{
struct huffman_decoder* decoder;
};

/* codec-private data for the CDZL codec */
typedef struct _cdzl_codec_data cdzl_codec_data;
struct _cdzl_codec_data {
Expand Down Expand Up @@ -293,8 +299,9 @@ struct _chd_file
const codec_interface * codecintf[4]; /* interface to the codec */

zlib_codec_data zlib_codec_data; /* zlib codec data */
lzma_codec_data lzma_codec_data; /* zlib codec data */
flac_codec_data flac_codec_data; /* zlib codec data */
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 */
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 */
Expand Down Expand Up @@ -355,6 +362,11 @@ static chd_error lzma_codec_init(void *codec, uint32_t hunkbytes);
static void lzma_codec_free(void *codec);
static chd_error lzma_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);

/* huff compression codec */
static chd_error huff_codec_init(void *codec, uint32_t hunkbytes);
static void huff_codec_free(void *codec);
static chd_error huff_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);

/* flac compression codec */
static chd_error flac_codec_init(void *codec, uint32_t hunkbytes);
static void flac_codec_free(void *codec);
Expand Down Expand Up @@ -771,6 +783,47 @@ static chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t
return CHDERR_NONE;
}

/***************************************************************************
* HUFFMAN DECOMPRESSOR
***************************************************************************
*/

static chd_error huff_codec_init(void* codec, uint32_t hunkbytes)
{
huff_codec_data* huff_codec = (huff_codec_data*) codec;
huff_codec->decoder = create_huffman_decoder(256, 16);
return CHDERR_NONE;
}

static void huff_codec_free(void *codec)
{
huff_codec_data* huff_codec = (huff_codec_data*) codec;
delete_huffman_decoder(huff_codec->decoder);
}

static chd_error huff_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
huff_codec_data* huff_codec = (huff_codec_data*) codec;
struct bitstream* bitbuf = create_bitstream(src, complen);

// first import the tree
enum huffman_error err = huffman_import_tree_huffman(huff_codec->decoder, bitbuf);
if (err != HUFFERR_NONE)
{
free(bitbuf);
return err;
}

// then decode the data
for (uint32_t 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;

free(bitbuf);
return result;
}

/***************************************************************************
* CD FLAC DECOMPRESSOR
***************************************************************************
Expand Down Expand Up @@ -993,6 +1046,17 @@ static const codec_interface codec_interfaces[] =
NULL
},

/* V5 huffman compression */
{
CHD_CODEC_HUFFMAN,
"Huffman",
FALSE,
huff_codec_init,
huff_codec_free,
huff_codec_decompress,
NULL
},

/* V5 flac compression */
{
CHD_CODEC_FLAC,
Expand Down Expand Up @@ -1613,6 +1677,10 @@ CHD_EXPORT chd_error chd_open_core_file(core_file *file, int mode, chd_file *par
codec = &newchd->lzma_codec_data;
break;

case CHD_CODEC_HUFFMAN:
codec = &newchd->huff_codec_data;
break;

case CHD_CODEC_FLAC:
codec = &newchd->flac_codec_data;
break;
Expand Down Expand Up @@ -1762,6 +1830,10 @@ CHD_EXPORT void chd_close(chd_file *chd)
codec = &chd->lzma_codec_data;
break;

case CHD_CODEC_HUFFMAN:
codec = &chd->huff_codec_data;
break;

case CHD_CODEC_FLAC:
codec = &chd->flac_codec_data;
break;
Expand Down Expand Up @@ -2488,6 +2560,10 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des
codec = &chd->lzma_codec_data;
break;

case CHD_CODEC_HUFFMAN:
codec = &chd->huff_codec_data;
break;

case CHD_CODEC_FLAC:
codec = &chd->flac_codec_data;
break;
Expand Down

0 comments on commit 5715077

Please sign in to comment.