cdrom: fix a copy-paste mistake
[pcsx_rearmed.git] / deps / libretro-common / formats / libchdr / libchdr_zlib.c
1 /***************************************************************************
2
3     libchdr_zlib.c
4
5     MAME Compressed Hunks of Data file format
6
7 ****************************************************************************
8
9     Copyright Aaron Giles
10     All rights reserved.
11
12     Redistribution and use in source and binary forms, with or without
13     modification, are permitted provided that the following conditions are
14     met:
15
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
21           distribution.
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.
25
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.
37
38 ***************************************************************************/
39
40 #include <stddef.h>
41 #include <stdint.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <libchdr/chd.h>
46 #include <libchdr/minmax.h>
47 #include <libchdr/cdrom.h>
48 #include <libchdr/huffman.h>
49 #include <libchdr/libchdr_zlib.h>
50 #include <zlib.h>
51
52 #include <retro_inline.h>
53 #include <streams/file_stream.h>
54
55 #define TRUE 1
56 #define FALSE 0
57
58 /* cdzl */
59
60 chd_error cdzl_codec_init(void *codec, uint32_t hunkbytes)
61 {
62         chd_error ret;
63         cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
64
65         /* make sure the CHD's hunk size is an even multiple of the frame size */
66         if (hunkbytes % CD_FRAME_SIZE != 0)
67                 return CHDERR_CODEC_ERROR;
68
69         cdzl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
70         if (cdzl->buffer == NULL)
71                 return CHDERR_OUT_OF_MEMORY;
72
73         ret = zlib_codec_init(&cdzl->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
74         if (ret != CHDERR_NONE)
75                 return ret;
76
77 #ifdef WANT_SUBCODE
78         ret = zlib_codec_init(&cdzl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
79         if (ret != CHDERR_NONE)
80                 return ret;
81 #endif
82
83         return CHDERR_NONE;
84 }
85
86 void cdzl_codec_free(void *codec)
87 {
88         cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
89
90         zlib_codec_free(&cdzl->base_decompressor);
91 #ifdef WANT_SUBCODE
92         zlib_codec_free(&cdzl->subcode_decompressor);
93 #endif
94         if (cdzl->buffer)
95                 free(cdzl->buffer);
96 }
97
98 chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
99 {
100 #ifdef WANT_RAW_DATA_SECTOR
101         uint8_t *sector;
102 #endif
103         uint32_t framenum;
104         cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
105
106         /* determine header bytes */
107         uint32_t frames = destlen / CD_FRAME_SIZE;
108         uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
109         uint32_t ecc_bytes = (frames + 7) / 8;
110         uint32_t header_bytes = ecc_bytes + complen_bytes;
111
112         /* extract compressed length of base */
113         uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
114         if (complen_bytes > 2)
115                 complen_base = (complen_base << 8) | src[ecc_bytes + 2];
116
117         /* reset and decode */
118         zlib_codec_decompress(&cdzl->base_decompressor, &src[header_bytes], complen_base, &cdzl->buffer[0], frames * CD_MAX_SECTOR_DATA);
119 #ifdef WANT_SUBCODE
120         zlib_codec_decompress(&cdzl->subcode_decompressor, &src[header_bytes + complen_base], complen - complen_base - header_bytes, &cdzl->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA);
121 #endif
122
123         /* reassemble the data */
124         for (framenum = 0; framenum < frames; framenum++)
125         {
126                 memcpy(&dest[framenum * CD_FRAME_SIZE], &cdzl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
127 #ifdef WANT_SUBCODE
128                 memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdzl->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA);
129 #endif
130
131 #ifdef WANT_RAW_DATA_SECTOR
132                 /* reconstitute the ECC data and sync header */
133                 sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE];
134                 if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
135                 {
136                         memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
137                         ecc_generate(sector);
138                 }
139 #endif
140         }
141         return CHDERR_NONE;
142 }
143
144 /***************************************************************************
145     ZLIB COMPRESSION CODEC
146 ***************************************************************************/
147
148 /*-------------------------------------------------
149     zlib_codec_init - initialize the ZLIB codec
150 -------------------------------------------------*/
151
152 chd_error zlib_codec_init(void *codec, uint32_t hunkbytes)
153 {
154         int zerr;
155         chd_error err;
156         zlib_codec_data *data = (zlib_codec_data*)codec;
157
158         /* clear the buffers */
159         memset(data, 0, sizeof(zlib_codec_data));
160
161         /* init the inflater first */
162         data->inflater.next_in = (Bytef *)data; /* bogus, but that's ok */
163         data->inflater.avail_in = 0;
164         data->inflater.zalloc = zlib_fast_alloc;
165         data->inflater.zfree = zlib_fast_free;
166         data->inflater.opaque = &data->allocator;
167         zerr = inflateInit2(&data->inflater, -MAX_WBITS);
168
169         /* convert errors */
170         if (zerr == Z_MEM_ERROR)
171                 err = CHDERR_OUT_OF_MEMORY;
172         else if (zerr != Z_OK)
173                 err = CHDERR_CODEC_ERROR;
174         else
175                 err = CHDERR_NONE;
176
177         /* handle an error */
178         if (err != CHDERR_NONE)
179                 zlib_codec_free(data);
180
181         return err;
182 }
183
184 /*-------------------------------------------------
185     zlib_codec_free - free data for the ZLIB
186     codec
187 -------------------------------------------------*/
188
189 void zlib_codec_free(void *codec)
190 {
191         zlib_codec_data *data = (zlib_codec_data *)codec;
192
193         /* deinit the streams */
194         if (data != NULL)
195         {
196                 int i;
197                 zlib_allocator alloc;
198
199                 inflateEnd(&data->inflater);
200
201                 /* free our fast memory */
202                 alloc = data->allocator;
203                 for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
204                         if (alloc.allocptr[i])
205                                 free(alloc.allocptr[i]);
206         }
207 }
208
209 /*-------------------------------------------------
210     zlib_codec_decompress - decomrpess data using
211     the ZLIB codec
212 -------------------------------------------------*/
213
214 chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
215 {
216         zlib_codec_data *data = (zlib_codec_data *)codec;
217         int zerr;
218
219         /* reset the decompressor */
220         data->inflater.next_in = (Bytef *)src;
221         data->inflater.avail_in = complen;
222         data->inflater.total_in = 0;
223         data->inflater.next_out = (Bytef *)dest;
224         data->inflater.avail_out = destlen;
225         data->inflater.total_out = 0;
226         zerr = inflateReset(&data->inflater);
227         if (zerr != Z_OK)
228                 return CHDERR_DECOMPRESSION_ERROR;
229
230         /* do it */
231         zerr = inflate(&data->inflater, Z_FINISH);
232         (void)zerr;
233         if (data->inflater.total_out != destlen)
234                 return CHDERR_DECOMPRESSION_ERROR;
235
236         return CHDERR_NONE;
237 }
238
239 /*-------------------------------------------------
240     zlib_fast_alloc - fast malloc for ZLIB, which
241     allocates and frees memory frequently
242 -------------------------------------------------*/
243
244 /* Huge alignment values for possible SIMD optimization by compiler (NEON, SSE, AVX) */
245 #define ZLIB_MIN_ALIGNMENT_BITS 512
246 #define ZLIB_MIN_ALIGNMENT_BYTES (ZLIB_MIN_ALIGNMENT_BITS / 8)
247
248 voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
249 {
250         zlib_allocator *alloc = (zlib_allocator *)opaque;
251         uintptr_t paddr = 0;
252         UINT32 *ptr;
253         int i;
254
255         /* compute the size, rounding to the nearest 1k */
256         size = (size * items + 0x3ff) & ~0x3ff;
257
258         /* reuse a hunk if we can */
259         for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
260         {
261                 ptr = alloc->allocptr[i];
262                 if (ptr && size == *ptr)
263                 {
264                         /* set the low bit of the size so we don't match next time */
265                         *ptr |= 1;
266
267                         /* return aligned block address */
268                         return (voidpf)(alloc->allocptr2[i]);
269                 }
270         }
271
272         /* alloc a new one */
273         ptr = (UINT32 *)malloc(size + sizeof(UINT32) + ZLIB_MIN_ALIGNMENT_BYTES);
274         if (!ptr)
275                 return NULL;
276
277         /* put it into the list */
278         for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
279                 if (!alloc->allocptr[i])
280                 {
281                         alloc->allocptr[i] = ptr;
282                         paddr = (((uintptr_t)ptr) + sizeof(UINT32) + (ZLIB_MIN_ALIGNMENT_BYTES-1)) & (~(ZLIB_MIN_ALIGNMENT_BYTES-1));
283                         alloc->allocptr2[i] = (uint32_t*)paddr;
284                         break;
285                 }
286
287         /* set the low bit of the size so we don't match next time */
288         *ptr = size | 1;
289
290         /* return aligned block address */
291         return (voidpf)paddr;
292 }
293
294 /*-------------------------------------------------
295     zlib_fast_free - fast free for ZLIB, which
296     allocates and frees memory frequently
297 -------------------------------------------------*/
298
299 void zlib_fast_free(voidpf opaque, voidpf address)
300 {
301         zlib_allocator *alloc = (zlib_allocator *)opaque;
302         UINT32 *ptr = (UINT32 *)address;
303         int i;
304
305         /* find the hunk */
306         for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
307                 if (ptr == alloc->allocptr2[i])
308                 {
309                         /* clear the low bit of the size to allow matches */
310                         *(alloc->allocptr[i]) &= ~1;
311                         return;
312                 }
313 }