1 /***************************************************************************
5 MAME Compressed Hunks of Data file format
7 ****************************************************************************
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions are
16 * Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
18 * Redistributions in binary form must reproduce the above copyright
19 notice, this list of conditions and the following disclaimer in
20 the documentation and/or other materials provided with the
22 * Neither the name 'MAME' nor the names of its contributors may be
23 used to endorse or promote products derived from this software
24 without specific prior written permission.
26 THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
27 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
30 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
35 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 POSSIBILITY OF SUCH DAMAGE.
38 ***************************************************************************/
45 #include <libchdr/chd.h>
46 #include <libchdr/minmax.h>
47 #include <libchdr/cdrom.h>
48 #include <libchdr/flac.h>
49 #include <libchdr/huffman.h>
52 #include <retro_inline.h>
53 #include <streams/file_stream.h>
58 /***************************************************************************
59 * CD FLAC DECOMPRESSOR
60 ***************************************************************************
63 /*------------------------------------------------------
64 * cdfl_codec_blocksize - return the optimal block size
65 *------------------------------------------------------
68 static uint32_t cdfl_codec_blocksize(uint32_t bytes)
70 /* determine FLAC block size, which must be 16-65535
71 * clamp to 2k since that's supposed to be the sweet spot */
72 uint32_t hunkbytes = bytes / 4;
73 while (hunkbytes > 2048)
78 chd_error cdfl_codec_init(void *codec, uint32_t hunkbytes)
83 uint16_t native_endian = 0;
84 cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
86 /* make sure the CHD's hunk size is an even multiple of the frame size */
87 if (hunkbytes % CD_FRAME_SIZE != 0)
88 return CHDERR_CODEC_ERROR;
90 cdfl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
91 if (cdfl->buffer == NULL)
92 return CHDERR_OUT_OF_MEMORY;
94 /* determine whether we want native or swapped samples */
95 *(uint8_t *)(&native_endian) = 1;
96 cdfl->swap_endian = (native_endian & 1);
99 /* init zlib inflater */
100 ret = zlib_codec_init(&cdfl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
101 if (ret != CHDERR_NONE)
105 /* flac decoder init */
106 flac_decoder_init(&cdfl->decoder);
107 if (cdfl->decoder.decoder == NULL)
108 return CHDERR_OUT_OF_MEMORY;
113 void cdfl_codec_free(void *codec)
115 cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
116 flac_decoder_free(&cdfl->decoder);
118 zlib_codec_free(&cdfl->subcode_decompressor);
124 chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
132 cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
134 /* reset and decode */
135 uint32_t frames = destlen / CD_FRAME_SIZE;
137 if (!flac_decoder_reset(&cdfl->decoder, 44100, 2, cdfl_codec_blocksize(frames * CD_MAX_SECTOR_DATA), src, complen))
138 return CHDERR_DECOMPRESSION_ERROR;
139 buffer = &cdfl->buffer[0];
140 if (!flac_decoder_decode_interleaved(&cdfl->decoder, (int16_t *)(buffer), frames * CD_MAX_SECTOR_DATA/4, cdfl->swap_endian))
141 return CHDERR_DECOMPRESSION_ERROR;
144 /* inflate the subcode data */
145 offset = flac_decoder_finish(&cdfl->decoder);
146 ret = zlib_codec_decompress(&cdfl->subcode_decompressor, src + offset, complen - offset, &cdfl->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA);
147 if (ret != CHDERR_NONE)
150 flac_decoder_finish(&cdfl->decoder);
153 /* reassemble the data */
154 for (framenum = 0; framenum < frames; framenum++)
156 memcpy(&dest[framenum * CD_FRAME_SIZE], &cdfl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
158 memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdfl->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA);