chd 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +30 -0
  3. data/chd.gemspec +29 -0
  4. data/ext/chd.c +1008 -0
  5. data/ext/extconf.rb +60 -0
  6. data/lib/chd/cd.rb +272 -0
  7. data/lib/chd/metadata.rb +196 -0
  8. data/lib/chd/version.rb +4 -0
  9. data/lib/chd.rb +21 -0
  10. data/libchdr/CMakeLists.txt +104 -0
  11. data/libchdr/LICENSE.txt +24 -0
  12. data/libchdr/README.md +7 -0
  13. data/libchdr/deps/lzma-19.00/CMakeLists.txt +33 -0
  14. data/libchdr/deps/lzma-19.00/LICENSE +3 -0
  15. data/libchdr/deps/lzma-19.00/include/7zTypes.h +375 -0
  16. data/libchdr/deps/lzma-19.00/include/Alloc.h +51 -0
  17. data/libchdr/deps/lzma-19.00/include/Bra.h +64 -0
  18. data/libchdr/deps/lzma-19.00/include/Compiler.h +33 -0
  19. data/libchdr/deps/lzma-19.00/include/CpuArch.h +336 -0
  20. data/libchdr/deps/lzma-19.00/include/Delta.h +19 -0
  21. data/libchdr/deps/lzma-19.00/include/LzFind.h +121 -0
  22. data/libchdr/deps/lzma-19.00/include/LzHash.h +57 -0
  23. data/libchdr/deps/lzma-19.00/include/Lzma86.h +111 -0
  24. data/libchdr/deps/lzma-19.00/include/LzmaDec.h +234 -0
  25. data/libchdr/deps/lzma-19.00/include/LzmaEnc.h +76 -0
  26. data/libchdr/deps/lzma-19.00/include/LzmaLib.h +131 -0
  27. data/libchdr/deps/lzma-19.00/include/Precomp.h +10 -0
  28. data/libchdr/deps/lzma-19.00/include/Sort.h +18 -0
  29. data/libchdr/deps/lzma-19.00/lzma-history.txt +446 -0
  30. data/libchdr/deps/lzma-19.00/lzma.txt +328 -0
  31. data/libchdr/deps/lzma-19.00/lzma.vcxproj +543 -0
  32. data/libchdr/deps/lzma-19.00/lzma.vcxproj.filters +17 -0
  33. data/libchdr/deps/lzma-19.00/src/Alloc.c +455 -0
  34. data/libchdr/deps/lzma-19.00/src/Bra86.c +82 -0
  35. data/libchdr/deps/lzma-19.00/src/BraIA64.c +53 -0
  36. data/libchdr/deps/lzma-19.00/src/CpuArch.c +218 -0
  37. data/libchdr/deps/lzma-19.00/src/Delta.c +64 -0
  38. data/libchdr/deps/lzma-19.00/src/LzFind.c +1127 -0
  39. data/libchdr/deps/lzma-19.00/src/Lzma86Dec.c +54 -0
  40. data/libchdr/deps/lzma-19.00/src/LzmaDec.c +1185 -0
  41. data/libchdr/deps/lzma-19.00/src/LzmaEnc.c +1330 -0
  42. data/libchdr/deps/lzma-19.00/src/Sort.c +141 -0
  43. data/libchdr/deps/zlib-1.2.11/CMakeLists.txt +29 -0
  44. data/libchdr/deps/zlib-1.2.11/ChangeLog +1515 -0
  45. data/libchdr/deps/zlib-1.2.11/FAQ +368 -0
  46. data/libchdr/deps/zlib-1.2.11/INDEX +68 -0
  47. data/libchdr/deps/zlib-1.2.11/Makefile +5 -0
  48. data/libchdr/deps/zlib-1.2.11/Makefile.in +410 -0
  49. data/libchdr/deps/zlib-1.2.11/README +115 -0
  50. data/libchdr/deps/zlib-1.2.11/adler32.c +186 -0
  51. data/libchdr/deps/zlib-1.2.11/compress.c +86 -0
  52. data/libchdr/deps/zlib-1.2.11/configure +921 -0
  53. data/libchdr/deps/zlib-1.2.11/crc32.c +442 -0
  54. data/libchdr/deps/zlib-1.2.11/crc32.h +441 -0
  55. data/libchdr/deps/zlib-1.2.11/deflate.c +2163 -0
  56. data/libchdr/deps/zlib-1.2.11/deflate.h +349 -0
  57. data/libchdr/deps/zlib-1.2.11/doc/algorithm.txt +209 -0
  58. data/libchdr/deps/zlib-1.2.11/doc/rfc1950.txt +619 -0
  59. data/libchdr/deps/zlib-1.2.11/doc/rfc1951.txt +955 -0
  60. data/libchdr/deps/zlib-1.2.11/doc/rfc1952.txt +675 -0
  61. data/libchdr/deps/zlib-1.2.11/doc/txtvsbin.txt +107 -0
  62. data/libchdr/deps/zlib-1.2.11/gzclose.c +25 -0
  63. data/libchdr/deps/zlib-1.2.11/gzguts.h +218 -0
  64. data/libchdr/deps/zlib-1.2.11/gzlib.c +637 -0
  65. data/libchdr/deps/zlib-1.2.11/gzread.c +654 -0
  66. data/libchdr/deps/zlib-1.2.11/gzwrite.c +665 -0
  67. data/libchdr/deps/zlib-1.2.11/infback.c +640 -0
  68. data/libchdr/deps/zlib-1.2.11/inffast.c +323 -0
  69. data/libchdr/deps/zlib-1.2.11/inffast.h +11 -0
  70. data/libchdr/deps/zlib-1.2.11/inffixed.h +94 -0
  71. data/libchdr/deps/zlib-1.2.11/inflate.c +1561 -0
  72. data/libchdr/deps/zlib-1.2.11/inflate.h +125 -0
  73. data/libchdr/deps/zlib-1.2.11/inftrees.c +304 -0
  74. data/libchdr/deps/zlib-1.2.11/inftrees.h +62 -0
  75. data/libchdr/deps/zlib-1.2.11/make_vms.com +867 -0
  76. data/libchdr/deps/zlib-1.2.11/treebuild.xml +116 -0
  77. data/libchdr/deps/zlib-1.2.11/trees.c +1203 -0
  78. data/libchdr/deps/zlib-1.2.11/trees.h +128 -0
  79. data/libchdr/deps/zlib-1.2.11/uncompr.c +93 -0
  80. data/libchdr/deps/zlib-1.2.11/zconf.h +534 -0
  81. data/libchdr/deps/zlib-1.2.11/zconf.h.cmakein +536 -0
  82. data/libchdr/deps/zlib-1.2.11/zconf.h.in +534 -0
  83. data/libchdr/deps/zlib-1.2.11/zlib.3 +149 -0
  84. data/libchdr/deps/zlib-1.2.11/zlib.3.pdf +0 -0
  85. data/libchdr/deps/zlib-1.2.11/zlib.h +1912 -0
  86. data/libchdr/deps/zlib-1.2.11/zlib.map +94 -0
  87. data/libchdr/deps/zlib-1.2.11/zlib.pc.cmakein +13 -0
  88. data/libchdr/deps/zlib-1.2.11/zlib.pc.in +13 -0
  89. data/libchdr/deps/zlib-1.2.11/zlib2ansi +152 -0
  90. data/libchdr/deps/zlib-1.2.11/zutil.c +325 -0
  91. data/libchdr/deps/zlib-1.2.11/zutil.h +271 -0
  92. data/libchdr/include/dr_libs/dr_flac.h +12280 -0
  93. data/libchdr/include/libchdr/bitstream.h +43 -0
  94. data/libchdr/include/libchdr/cdrom.h +110 -0
  95. data/libchdr/include/libchdr/chd.h +427 -0
  96. data/libchdr/include/libchdr/chdconfig.h +10 -0
  97. data/libchdr/include/libchdr/coretypes.h +60 -0
  98. data/libchdr/include/libchdr/flac.h +50 -0
  99. data/libchdr/include/libchdr/huffman.h +90 -0
  100. data/libchdr/pkg-config.pc.in +10 -0
  101. data/libchdr/src/libchdr_bitstream.c +125 -0
  102. data/libchdr/src/libchdr_cdrom.c +415 -0
  103. data/libchdr/src/libchdr_chd.c +2744 -0
  104. data/libchdr/src/libchdr_flac.c +302 -0
  105. data/libchdr/src/libchdr_huffman.c +545 -0
  106. data/libchdr/src/link.T +5 -0
  107. data/libchdr/tests/CMakeLists.txt +2 -0
  108. data/libchdr/tests/benchmark.c +52 -0
  109. metadata +183 -0
@@ -0,0 +1,2744 @@
1
+ /***************************************************************************
2
+
3
+ chd.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 <stdio.h>
42
+ #include <stdlib.h>
43
+ #include <string.h>
44
+ #include <time.h>
45
+
46
+ #include <libchdr/chd.h>
47
+ #include <libchdr/cdrom.h>
48
+ #include <libchdr/flac.h>
49
+ #include <libchdr/huffman.h>
50
+
51
+ #include "LzmaEnc.h"
52
+ #include "LzmaDec.h"
53
+ #if defined(__PS3__) || defined(__PSL1GHT__)
54
+ #define __MACTYPES__
55
+ #endif
56
+ #include "zlib.h"
57
+
58
+ #undef TRUE
59
+ #undef FALSE
60
+ #define TRUE 1
61
+ #define FALSE 0
62
+
63
+ #undef MAX
64
+ #undef MIN
65
+ #define MAX(x, y) (((x) > (y)) ? (x) : (y))
66
+ #define MIN(x, y) (((x) < (y)) ? (x) : (y))
67
+
68
+ #define SHA1_DIGEST_SIZE 20
69
+
70
+ /***************************************************************************
71
+ DEBUGGING
72
+ ***************************************************************************/
73
+
74
+ #define PRINTF_MAX_HUNK (0)
75
+
76
+ /***************************************************************************
77
+ CONSTANTS
78
+ ***************************************************************************/
79
+
80
+ #define MAP_STACK_ENTRIES 512 /* max number of entries to use on the stack */
81
+ #define MAP_ENTRY_SIZE 16 /* V3 and later */
82
+ #define OLD_MAP_ENTRY_SIZE 8 /* V1-V2 */
83
+ #define METADATA_HEADER_SIZE 16 /* metadata header size */
84
+
85
+ #define MAP_ENTRY_FLAG_TYPE_MASK 0x0f /* what type of hunk */
86
+ #define MAP_ENTRY_FLAG_NO_CRC 0x10 /* no CRC is present */
87
+
88
+ #define CHD_V1_SECTOR_SIZE 512 /* size of a "sector" in the V1 header */
89
+
90
+ #define COOKIE_VALUE 0xbaadf00d
91
+ #define MAX_ZLIB_ALLOCS 64
92
+
93
+ #define END_OF_LIST_COOKIE "EndOfListCookie"
94
+
95
+ #define NO_MATCH (~0)
96
+
97
+ #ifdef WANT_RAW_DATA_SECTOR
98
+ static const uint8_t s_cd_sync_header[12] = { 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 };
99
+ #endif
100
+
101
+ /* V3-V4 entry types */
102
+ enum
103
+ {
104
+ V34_MAP_ENTRY_TYPE_INVALID = 0, /* invalid type */
105
+ V34_MAP_ENTRY_TYPE_COMPRESSED = 1, /* standard compression */
106
+ V34_MAP_ENTRY_TYPE_UNCOMPRESSED = 2, /* uncompressed data */
107
+ V34_MAP_ENTRY_TYPE_MINI = 3, /* mini: use offset as raw data */
108
+ V34_MAP_ENTRY_TYPE_SELF_HUNK = 4, /* same as another hunk in this file */
109
+ V34_MAP_ENTRY_TYPE_PARENT_HUNK = 5, /* same as a hunk in the parent file */
110
+ V34_MAP_ENTRY_TYPE_2ND_COMPRESSED = 6 /* compressed with secondary algorithm (usually FLAC CDDA) */
111
+ };
112
+
113
+ /* V5 compression types */
114
+ enum
115
+ {
116
+ /* codec #0
117
+ * these types are live when running */
118
+ COMPRESSION_TYPE_0 = 0,
119
+ /* codec #1 */
120
+ COMPRESSION_TYPE_1 = 1,
121
+ /* codec #2 */
122
+ COMPRESSION_TYPE_2 = 2,
123
+ /* codec #3 */
124
+ COMPRESSION_TYPE_3 = 3,
125
+ /* no compression; implicit length = hunkbytes */
126
+ COMPRESSION_NONE = 4,
127
+ /* same as another block in this chd */
128
+ COMPRESSION_SELF = 5,
129
+ /* same as a hunk's worth of units in the parent chd */
130
+ COMPRESSION_PARENT = 6,
131
+
132
+ /* start of small RLE run (4-bit length)
133
+ * these additional pseudo-types are used for compressed encodings: */
134
+ COMPRESSION_RLE_SMALL,
135
+ /* start of large RLE run (8-bit length) */
136
+ COMPRESSION_RLE_LARGE,
137
+ /* same as the last COMPRESSION_SELF block */
138
+ COMPRESSION_SELF_0,
139
+ /* same as the last COMPRESSION_SELF block + 1 */
140
+ COMPRESSION_SELF_1,
141
+ /* same block in the parent */
142
+ COMPRESSION_PARENT_SELF,
143
+ /* same as the last COMPRESSION_PARENT block */
144
+ COMPRESSION_PARENT_0,
145
+ /* same as the last COMPRESSION_PARENT block + 1 */
146
+ COMPRESSION_PARENT_1
147
+ };
148
+
149
+ /***************************************************************************
150
+ MACROS
151
+ ***************************************************************************/
152
+
153
+ #define EARLY_EXIT(x) do { (void)(x); goto cleanup; } while (0)
154
+
155
+ /***************************************************************************
156
+ TYPE DEFINITIONS
157
+ ***************************************************************************/
158
+
159
+ /* interface to a codec */
160
+ typedef struct _codec_interface codec_interface;
161
+ struct _codec_interface
162
+ {
163
+ UINT32 compression; /* type of compression */
164
+ const char *compname; /* name of the algorithm */
165
+ UINT8 lossy; /* is this a lossy algorithm? */
166
+ chd_error (*init)(void *codec, UINT32 hunkbytes); /* codec initialize */
167
+ void (*free)(void *codec); /* codec free */
168
+ chd_error (*decompress)(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen); /* decompress data */
169
+ chd_error (*config)(void *codec, int param, void *config); /* configure */
170
+ };
171
+
172
+ /* a single map entry */
173
+ typedef struct _map_entry map_entry;
174
+ struct _map_entry
175
+ {
176
+ UINT64 offset; /* offset within the file of the data */
177
+ UINT32 crc; /* 32-bit CRC of the data */
178
+ UINT32 length; /* length of the data */
179
+ UINT8 flags; /* misc flags */
180
+ };
181
+
182
+ /* a single metadata entry */
183
+ typedef struct _metadata_entry metadata_entry;
184
+ struct _metadata_entry
185
+ {
186
+ UINT64 offset; /* offset within the file of the header */
187
+ UINT64 next; /* offset within the file of the next header */
188
+ UINT64 prev; /* offset within the file of the previous header */
189
+ UINT32 length; /* length of the metadata */
190
+ UINT32 metatag; /* metadata tag */
191
+ UINT8 flags; /* flag bits */
192
+ };
193
+
194
+ /* codec-private data for the ZLIB codec */
195
+
196
+ typedef struct _zlib_allocator zlib_allocator;
197
+ struct _zlib_allocator
198
+ {
199
+ UINT32 * allocptr[MAX_ZLIB_ALLOCS];
200
+ UINT32 * allocptr2[MAX_ZLIB_ALLOCS];
201
+ };
202
+
203
+ typedef struct _zlib_codec_data zlib_codec_data;
204
+ struct _zlib_codec_data
205
+ {
206
+ z_stream inflater;
207
+ zlib_allocator allocator;
208
+ };
209
+
210
+ /* codec-private data for the LZMA codec */
211
+ #define MAX_LZMA_ALLOCS 64
212
+
213
+ typedef struct _lzma_allocator lzma_allocator;
214
+ struct _lzma_allocator
215
+ {
216
+ void *(*Alloc)(void *p, size_t size);
217
+ void (*Free)(void *p, void *address); /* address can be 0 */
218
+ void (*FreeSz)(void *p, void *address, size_t size); /* address can be 0 */
219
+ uint32_t* allocptr[MAX_LZMA_ALLOCS];
220
+ uint32_t* allocptr2[MAX_LZMA_ALLOCS];
221
+ };
222
+
223
+ typedef struct _lzma_codec_data lzma_codec_data;
224
+ struct _lzma_codec_data
225
+ {
226
+ CLzmaDec decoder;
227
+ lzma_allocator allocator;
228
+ };
229
+
230
+ /* codec-private data for the CDZL codec */
231
+ typedef struct _cdzl_codec_data cdzl_codec_data;
232
+ struct _cdzl_codec_data {
233
+ /* internal state */
234
+ zlib_codec_data base_decompressor;
235
+ #ifdef WANT_SUBCODE
236
+ zlib_codec_data subcode_decompressor;
237
+ #endif
238
+ uint8_t* buffer;
239
+ };
240
+
241
+ /* codec-private data for the CDLZ codec */
242
+ typedef struct _cdlz_codec_data cdlz_codec_data;
243
+ struct _cdlz_codec_data {
244
+ /* internal state */
245
+ lzma_codec_data base_decompressor;
246
+ #ifdef WANT_SUBCODE
247
+ zlib_codec_data subcode_decompressor;
248
+ #endif
249
+ uint8_t* buffer;
250
+ };
251
+
252
+ /* codec-private data for the CDFL codec */
253
+ typedef struct _cdfl_codec_data cdfl_codec_data;
254
+ struct _cdfl_codec_data {
255
+ /* internal state */
256
+ int swap_endian;
257
+ flac_decoder decoder;
258
+ #ifdef WANT_SUBCODE
259
+ zlib_codec_data subcode_decompressor;
260
+ #endif
261
+ uint8_t* buffer;
262
+ };
263
+
264
+ /* internal representation of an open CHD file */
265
+ struct _chd_file
266
+ {
267
+ UINT32 cookie; /* cookie, should equal COOKIE_VALUE */
268
+
269
+ core_file * file; /* handle to the open core file */
270
+ UINT8 owns_file; /* flag indicating if this file should be closed on chd_close() */
271
+ chd_header header; /* header, extracted from file */
272
+
273
+ chd_file * parent; /* pointer to parent file, or NULL */
274
+
275
+ map_entry * map; /* array of map entries */
276
+
277
+ #ifdef NEED_CACHE_HUNK
278
+ UINT8 * cache; /* hunk cache pointer */
279
+ UINT32 cachehunk; /* index of currently cached hunk */
280
+
281
+ UINT8 * compare; /* hunk compare pointer */
282
+ UINT32 comparehunk; /* index of current compare data */
283
+ #endif
284
+
285
+ UINT8 * compressed; /* pointer to buffer for compressed data */
286
+ const codec_interface * codecintf[4]; /* interface to the codec */
287
+
288
+ zlib_codec_data zlib_codec_data; /* zlib codec data */
289
+ cdzl_codec_data cdzl_codec_data; /* cdzl codec data */
290
+ cdlz_codec_data cdlz_codec_data; /* cdlz codec data */
291
+ cdfl_codec_data cdfl_codec_data; /* cdfl codec data */
292
+
293
+ #ifdef NEED_CACHE_HUNK
294
+ UINT32 maxhunk; /* maximum hunk accessed */
295
+ #endif
296
+
297
+ UINT8 * file_cache; /* cache of underlying file */
298
+ };
299
+
300
+
301
+ /***************************************************************************
302
+ GLOBAL VARIABLES
303
+ ***************************************************************************/
304
+
305
+ static const UINT8 nullmd5[CHD_MD5_BYTES] = { 0 };
306
+ static const UINT8 nullsha1[CHD_SHA1_BYTES] = { 0 };
307
+
308
+ /***************************************************************************
309
+ PROTOTYPES
310
+ ***************************************************************************/
311
+
312
+ /* internal header operations */
313
+ static chd_error header_validate(const chd_header *header);
314
+ static chd_error header_read(chd_file *chd, chd_header *header);
315
+
316
+ /* internal hunk read/write */
317
+ #ifdef NEED_CACHE_HUNK
318
+ static chd_error hunk_read_into_cache(chd_file *chd, UINT32 hunknum);
319
+ #endif
320
+ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *dest);
321
+
322
+ /* internal map access */
323
+ static chd_error map_read(chd_file *chd);
324
+
325
+ /* metadata management */
326
+ static chd_error metadata_find_entry(chd_file *chd, UINT32 metatag, UINT32 metaindex, metadata_entry *metaentry);
327
+
328
+ /* zlib compression codec */
329
+ static chd_error zlib_codec_init(void *codec, uint32_t hunkbytes);
330
+ static void zlib_codec_free(void *codec);
331
+ static chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
332
+ static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size);
333
+ static void zlib_fast_free(voidpf opaque, voidpf address);
334
+ static void zlib_allocator_free(voidpf opaque);
335
+
336
+ /* lzma compression codec */
337
+ static chd_error lzma_codec_init(void *codec, uint32_t hunkbytes);
338
+ static void lzma_codec_free(void *codec);
339
+ static chd_error lzma_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
340
+
341
+ /* cdzl compression codec */
342
+ static chd_error cdzl_codec_init(void* codec, uint32_t hunkbytes);
343
+ static void cdzl_codec_free(void* codec);
344
+ static chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
345
+
346
+ /* cdlz compression codec */
347
+ static chd_error cdlz_codec_init(void* codec, uint32_t hunkbytes);
348
+ static void cdlz_codec_free(void* codec);
349
+ static chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
350
+
351
+ /* cdfl compression codec */
352
+ static chd_error cdfl_codec_init(void* codec, uint32_t hunkbytes);
353
+ static void cdfl_codec_free(void* codec);
354
+ static chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen);
355
+
356
+ /***************************************************************************
357
+ * LZMA ALLOCATOR HELPER
358
+ ***************************************************************************
359
+ */
360
+
361
+ static void *lzma_fast_alloc(void *p, size_t size);
362
+ static void lzma_fast_free(void *p, void *address);
363
+
364
+ /*-------------------------------------------------
365
+ * lzma_allocator_init
366
+ *-------------------------------------------------
367
+ */
368
+
369
+ static void lzma_allocator_init(void* p)
370
+ {
371
+ lzma_allocator *codec = (lzma_allocator *)(p);
372
+
373
+ /* reset pointer list */
374
+ memset(codec->allocptr, 0, sizeof(codec->allocptr));
375
+ memset(codec->allocptr2, 0, sizeof(codec->allocptr2));
376
+ codec->Alloc = lzma_fast_alloc;
377
+ codec->Free = lzma_fast_free;
378
+ }
379
+
380
+ /*-------------------------------------------------
381
+ * lzma_allocator_free
382
+ *-------------------------------------------------
383
+ */
384
+
385
+ static void lzma_allocator_free(void* p )
386
+ {
387
+ int i;
388
+ lzma_allocator *codec = (lzma_allocator *)(p);
389
+
390
+ /* free our memory */
391
+ for (i = 0 ; i < MAX_LZMA_ALLOCS ; i++)
392
+ {
393
+ if (codec->allocptr[i] != NULL)
394
+ free(codec->allocptr[i]);
395
+ }
396
+ }
397
+
398
+ /*-------------------------------------------------
399
+ * lzma_fast_alloc - fast malloc for lzma, which
400
+ * allocates and frees memory frequently
401
+ *-------------------------------------------------
402
+ */
403
+
404
+ /* Huge alignment values for possible SIMD optimization by compiler (NEON, SSE, AVX) */
405
+ #define LZMA_MIN_ALIGNMENT_BITS 512
406
+ #define LZMA_MIN_ALIGNMENT_BYTES (LZMA_MIN_ALIGNMENT_BITS / 8)
407
+
408
+ static void *lzma_fast_alloc(void *p, size_t size)
409
+ {
410
+ int scan;
411
+ uint32_t *addr = NULL;
412
+ lzma_allocator *codec = (lzma_allocator *)(p);
413
+ uintptr_t vaddr = 0;
414
+
415
+ /* compute the size, rounding to the nearest 1k */
416
+ size = (size + 0x3ff) & ~0x3ff;
417
+
418
+ /* reuse a hunk if we can */
419
+ for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
420
+ {
421
+ uint32_t *ptr = codec->allocptr[scan];
422
+ if (ptr != NULL && size == *ptr)
423
+ {
424
+ /* set the low bit of the size so we don't match next time */
425
+ *ptr |= 1;
426
+
427
+ /* return aligned address of the block */
428
+ return codec->allocptr2[scan];
429
+ }
430
+ }
431
+
432
+ /* alloc a new one and put it into the list */
433
+ addr = (uint32_t *)malloc(size + sizeof(uint32_t) + LZMA_MIN_ALIGNMENT_BYTES);
434
+ if (addr==NULL)
435
+ return NULL;
436
+ for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
437
+ {
438
+ if (codec->allocptr[scan] == NULL)
439
+ {
440
+ /* store block address */
441
+ codec->allocptr[scan] = addr;
442
+
443
+ /* compute aligned address, store it */
444
+ vaddr = (uintptr_t)addr;
445
+ vaddr = (vaddr + sizeof(uint32_t) + (LZMA_MIN_ALIGNMENT_BYTES-1)) & (~(LZMA_MIN_ALIGNMENT_BYTES-1));
446
+ codec->allocptr2[scan] = (uint32_t*)vaddr;
447
+ break;
448
+ }
449
+ }
450
+
451
+ /* set the low bit of the size so we don't match next time */
452
+ *addr = size | 1;
453
+
454
+ /* return aligned address */
455
+ return (void*)vaddr;
456
+ }
457
+
458
+ /*-------------------------------------------------
459
+ * lzma_fast_free - fast free for lzma, which
460
+ * allocates and frees memory frequently
461
+ *-------------------------------------------------
462
+ */
463
+
464
+ static void lzma_fast_free(void *p, void *address)
465
+ {
466
+ int scan;
467
+ uint32_t *ptr = NULL;
468
+ lzma_allocator *codec = NULL;
469
+
470
+ if (address == NULL)
471
+ return;
472
+
473
+ codec = (lzma_allocator *)(p);
474
+
475
+ /* find the hunk */
476
+ ptr = (uint32_t *)address;
477
+ for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
478
+ {
479
+ if (ptr == codec->allocptr2[scan])
480
+ {
481
+ /* clear the low bit of the size to allow matches */
482
+ *codec->allocptr[scan] &= ~1;
483
+ return;
484
+ }
485
+ }
486
+ }
487
+
488
+ /***************************************************************************
489
+ * LZMA DECOMPRESSOR
490
+ ***************************************************************************
491
+ */
492
+
493
+ /*-------------------------------------------------
494
+ * lzma_codec_init - constructor
495
+ *-------------------------------------------------
496
+ */
497
+
498
+ static chd_error lzma_codec_init(void* codec, uint32_t hunkbytes)
499
+ {
500
+ CLzmaEncHandle enc;
501
+ CLzmaEncProps encoder_props;
502
+ Byte decoder_props[LZMA_PROPS_SIZE];
503
+ SizeT props_size;
504
+ lzma_allocator* alloc;
505
+ lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
506
+
507
+ /* construct the decoder */
508
+ LzmaDec_Construct(&lzma_codec->decoder);
509
+
510
+ /* FIXME: this code is written in a way that makes it impossible to safely upgrade the LZMA SDK
511
+ * This code assumes that the current version of the encoder imposes the same requirements on the
512
+ * decoder as the encoder used to produce the file. This is not necessarily true. The format
513
+ * needs to be changed so the encoder properties are written to the file.
514
+
515
+ * configure the properties like the compressor did */
516
+ LzmaEncProps_Init(&encoder_props);
517
+ encoder_props.level = 9;
518
+ encoder_props.reduceSize = hunkbytes;
519
+ LzmaEncProps_Normalize(&encoder_props);
520
+
521
+ /* convert to decoder properties */
522
+ alloc = &lzma_codec->allocator;
523
+ lzma_allocator_init(alloc);
524
+ enc = LzmaEnc_Create((ISzAlloc*)alloc);
525
+ if (!enc)
526
+ return CHDERR_DECOMPRESSION_ERROR;
527
+ if (LzmaEnc_SetProps(enc, &encoder_props) != SZ_OK)
528
+ {
529
+ LzmaEnc_Destroy(enc, (ISzAlloc*)&alloc, (ISzAlloc*)&alloc);
530
+ return CHDERR_DECOMPRESSION_ERROR;
531
+ }
532
+ props_size = sizeof(decoder_props);
533
+ if (LzmaEnc_WriteProperties(enc, decoder_props, &props_size) != SZ_OK)
534
+ {
535
+ LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc);
536
+ return CHDERR_DECOMPRESSION_ERROR;
537
+ }
538
+ LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc);
539
+
540
+ /* do memory allocations */
541
+ if (LzmaDec_Allocate(&lzma_codec->decoder, decoder_props, LZMA_PROPS_SIZE, (ISzAlloc*)alloc) != SZ_OK)
542
+ return CHDERR_DECOMPRESSION_ERROR;
543
+
544
+ /* Okay */
545
+ return CHDERR_NONE;
546
+ }
547
+
548
+ /*-------------------------------------------------
549
+ * lzma_codec_free
550
+ *-------------------------------------------------
551
+ */
552
+
553
+ static void lzma_codec_free(void* codec)
554
+ {
555
+ lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
556
+
557
+ /* free memory */
558
+ LzmaDec_Free(&lzma_codec->decoder, (ISzAlloc*)&lzma_codec->allocator);
559
+ lzma_allocator_free(&lzma_codec->allocator);
560
+ }
561
+
562
+ /*-------------------------------------------------
563
+ * decompress - decompress data using the LZMA
564
+ * codec
565
+ *-------------------------------------------------
566
+ */
567
+
568
+ static chd_error lzma_codec_decompress(void* codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
569
+ {
570
+ ELzmaStatus status;
571
+ SRes res;
572
+ SizeT consumedlen, decodedlen;
573
+ /* initialize */
574
+ lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
575
+ LzmaDec_Init(&lzma_codec->decoder);
576
+
577
+ /* decode */
578
+ consumedlen = complen;
579
+ decodedlen = destlen;
580
+ res = LzmaDec_DecodeToBuf(&lzma_codec->decoder, dest, &decodedlen, src, &consumedlen, LZMA_FINISH_END, &status);
581
+ if ((res != SZ_OK && res != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) || consumedlen != complen || decodedlen != destlen)
582
+ return CHDERR_DECOMPRESSION_ERROR;
583
+ return CHDERR_NONE;
584
+ }
585
+
586
+ /* cdlz */
587
+ static chd_error cdlz_codec_init(void* codec, uint32_t hunkbytes)
588
+ {
589
+ chd_error ret;
590
+ cdlz_codec_data* cdlz = (cdlz_codec_data*) codec;
591
+
592
+ /* allocate buffer */
593
+ cdlz->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
594
+ if (cdlz->buffer == NULL)
595
+ return CHDERR_OUT_OF_MEMORY;
596
+
597
+ /* make sure the CHD's hunk size is an even multiple of the frame size */
598
+ ret = lzma_codec_init(&cdlz->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
599
+ if (ret != CHDERR_NONE)
600
+ return ret;
601
+
602
+ #ifdef WANT_SUBCODE
603
+ ret = zlib_codec_init(&cdlz->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SUBCODE_DATA);
604
+ if (ret != CHDERR_NONE)
605
+ return ret;
606
+ #endif
607
+
608
+ if (hunkbytes % CD_FRAME_SIZE != 0)
609
+ return CHDERR_CODEC_ERROR;
610
+
611
+ return CHDERR_NONE;
612
+ }
613
+
614
+ static void cdlz_codec_free(void* codec)
615
+ {
616
+ cdlz_codec_data* cdlz = (cdlz_codec_data*) codec;
617
+ free(cdlz->buffer);
618
+ lzma_codec_free(&cdlz->base_decompressor);
619
+ #ifdef WANT_SUBCODE
620
+ zlib_codec_free(&cdlz->subcode_decompressor);
621
+ #endif
622
+ }
623
+
624
+ static chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
625
+ {
626
+ uint32_t framenum;
627
+ cdlz_codec_data* cdlz = (cdlz_codec_data*)codec;
628
+
629
+ /* determine header bytes */
630
+ uint32_t frames = destlen / CD_FRAME_SIZE;
631
+ uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
632
+ uint32_t ecc_bytes = (frames + 7) / 8;
633
+ uint32_t header_bytes = ecc_bytes + complen_bytes;
634
+
635
+ /* extract compressed length of base */
636
+ uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
637
+ if (complen_bytes > 2)
638
+ complen_base = (complen_base << 8) | src[ecc_bytes + 2];
639
+
640
+ /* reset and decode */
641
+ lzma_codec_decompress(&cdlz->base_decompressor, &src[header_bytes], complen_base, &cdlz->buffer[0], frames * CD_MAX_SECTOR_DATA);
642
+ #ifdef WANT_SUBCODE
643
+ zlib_codec_decompress(&cdlz->subcode_decompressor, &src[header_bytes + complen_base], complen - complen_base - header_bytes, &cdlz->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA);
644
+ #endif
645
+
646
+ /* reassemble the data */
647
+ for (framenum = 0; framenum < frames; framenum++)
648
+ {
649
+ uint8_t *sector;
650
+
651
+ memcpy(&dest[framenum * CD_FRAME_SIZE], &cdlz->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
652
+ #ifdef WANT_SUBCODE
653
+ memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdlz->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA);
654
+ #endif
655
+
656
+ #ifdef WANT_RAW_DATA_SECTOR
657
+ /* reconstitute the ECC data and sync header */
658
+ sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE];
659
+ if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
660
+ {
661
+ memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
662
+ ecc_generate(sector);
663
+ }
664
+ #endif
665
+ }
666
+ return CHDERR_NONE;
667
+ }
668
+
669
+ /* cdzl */
670
+
671
+ static chd_error cdzl_codec_init(void *codec, uint32_t hunkbytes)
672
+ {
673
+ chd_error ret;
674
+ cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
675
+
676
+ /* make sure the CHD's hunk size is an even multiple of the frame size */
677
+ if (hunkbytes % CD_FRAME_SIZE != 0)
678
+ return CHDERR_CODEC_ERROR;
679
+
680
+ cdzl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
681
+ if (cdzl->buffer == NULL)
682
+ return CHDERR_OUT_OF_MEMORY;
683
+
684
+ ret = zlib_codec_init(&cdzl->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
685
+ if (ret != CHDERR_NONE)
686
+ return ret;
687
+
688
+ #ifdef WANT_SUBCODE
689
+ ret = zlib_codec_init(&cdzl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SUBCODE_DATA);
690
+ if (ret != CHDERR_NONE)
691
+ return ret;
692
+ #endif
693
+
694
+ return CHDERR_NONE;
695
+ }
696
+
697
+ static void cdzl_codec_free(void *codec)
698
+ {
699
+ cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
700
+ zlib_codec_free(&cdzl->base_decompressor);
701
+ #ifdef WANT_SUBCODE
702
+ zlib_codec_free(&cdzl->subcode_decompressor);
703
+ #endif
704
+ free(cdzl->buffer);
705
+ }
706
+
707
+ static chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
708
+ {
709
+ uint32_t framenum;
710
+ cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
711
+
712
+ /* determine header bytes */
713
+ uint32_t frames = destlen / CD_FRAME_SIZE;
714
+ uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
715
+ uint32_t ecc_bytes = (frames + 7) / 8;
716
+ uint32_t header_bytes = ecc_bytes + complen_bytes;
717
+
718
+ /* extract compressed length of base */
719
+ uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
720
+ if (complen_bytes > 2)
721
+ complen_base = (complen_base << 8) | src[ecc_bytes + 2];
722
+
723
+ /* reset and decode */
724
+ zlib_codec_decompress(&cdzl->base_decompressor, &src[header_bytes], complen_base, &cdzl->buffer[0], frames * CD_MAX_SECTOR_DATA);
725
+ #ifdef WANT_SUBCODE
726
+ 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);
727
+ #endif
728
+
729
+ /* reassemble the data */
730
+ for (framenum = 0; framenum < frames; framenum++)
731
+ {
732
+ uint8_t *sector;
733
+
734
+ memcpy(&dest[framenum * CD_FRAME_SIZE], &cdzl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
735
+ #ifdef WANT_SUBCODE
736
+ 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);
737
+ #endif
738
+
739
+ #ifdef WANT_RAW_DATA_SECTOR
740
+ /* reconstitute the ECC data and sync header */
741
+ sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE];
742
+ if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
743
+ {
744
+ memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
745
+ ecc_generate(sector);
746
+ }
747
+ #endif
748
+ }
749
+ return CHDERR_NONE;
750
+ }
751
+
752
+ /***************************************************************************
753
+ * CD FLAC DECOMPRESSOR
754
+ ***************************************************************************
755
+ */
756
+
757
+ /*------------------------------------------------------
758
+ * cdfl_codec_blocksize - return the optimal block size
759
+ *------------------------------------------------------
760
+ */
761
+
762
+ static uint32_t cdfl_codec_blocksize(uint32_t bytes)
763
+ {
764
+ /* determine FLAC block size, which must be 16-65535
765
+ * clamp to 2k since that's supposed to be the sweet spot */
766
+ uint32_t hunkbytes = bytes / 4;
767
+ while (hunkbytes > 2048)
768
+ hunkbytes /= 2;
769
+ return hunkbytes;
770
+ }
771
+
772
+ static chd_error cdfl_codec_init(void *codec, uint32_t hunkbytes)
773
+ {
774
+ #ifdef WANT_SUBCODE
775
+ chd_error ret;
776
+ #endif
777
+ uint16_t native_endian = 0;
778
+ cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
779
+
780
+ /* make sure the CHD's hunk size is an even multiple of the frame size */
781
+ if (hunkbytes % CD_FRAME_SIZE != 0)
782
+ return CHDERR_CODEC_ERROR;
783
+
784
+ cdfl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
785
+ if (cdfl->buffer == NULL)
786
+ return CHDERR_OUT_OF_MEMORY;
787
+
788
+ /* determine whether we want native or swapped samples */
789
+ *(uint8_t *)(&native_endian) = 1;
790
+ cdfl->swap_endian = (native_endian & 1);
791
+
792
+ #ifdef WANT_SUBCODE
793
+ /* init zlib inflater */
794
+ ret = zlib_codec_init(&cdfl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
795
+ if (ret != CHDERR_NONE)
796
+ return ret;
797
+ #endif
798
+
799
+ /* flac decoder init */
800
+ if (flac_decoder_init(&cdfl->decoder))
801
+ return CHDERR_OUT_OF_MEMORY;
802
+
803
+ return CHDERR_NONE;
804
+ }
805
+
806
+ static void cdfl_codec_free(void *codec)
807
+ {
808
+ cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
809
+ flac_decoder_free(&cdfl->decoder);
810
+ #ifdef WANT_SUBCODE
811
+ zlib_codec_free(&cdfl->subcode_decompressor);
812
+ #endif
813
+ if (cdfl->buffer)
814
+ free(cdfl->buffer);
815
+ }
816
+
817
+ static chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
818
+ {
819
+ uint32_t framenum;
820
+ uint8_t *buffer;
821
+ #ifdef WANT_SUBCODE
822
+ uint32_t offset;
823
+ chd_error ret;
824
+ #endif
825
+ cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
826
+
827
+ /* reset and decode */
828
+ uint32_t frames = destlen / CD_FRAME_SIZE;
829
+
830
+ if (!flac_decoder_reset(&cdfl->decoder, 44100, 2, cdfl_codec_blocksize(frames * CD_MAX_SECTOR_DATA), src, complen))
831
+ return CHDERR_DECOMPRESSION_ERROR;
832
+ buffer = &cdfl->buffer[0];
833
+ if (!flac_decoder_decode_interleaved(&cdfl->decoder, (int16_t *)(buffer), frames * CD_MAX_SECTOR_DATA/4, cdfl->swap_endian))
834
+ return CHDERR_DECOMPRESSION_ERROR;
835
+
836
+ #ifdef WANT_SUBCODE
837
+ /* inflate the subcode data */
838
+ offset = flac_decoder_finish(&cdfl->decoder);
839
+ ret = zlib_codec_decompress(&cdfl->subcode_decompressor, src + offset, complen - offset, &cdfl->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA);
840
+ if (ret != CHDERR_NONE)
841
+ return ret;
842
+ #else
843
+ flac_decoder_finish(&cdfl->decoder);
844
+ #endif
845
+
846
+ /* reassemble the data */
847
+ for (framenum = 0; framenum < frames; framenum++)
848
+ {
849
+ memcpy(&dest[framenum * CD_FRAME_SIZE], &cdfl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
850
+ #ifdef WANT_SUBCODE
851
+ 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);
852
+ #endif
853
+ }
854
+
855
+ return CHDERR_NONE;
856
+ }
857
+ /***************************************************************************
858
+ CODEC INTERFACES
859
+ ***************************************************************************/
860
+
861
+ static const codec_interface codec_interfaces[] =
862
+ {
863
+ /* "none" or no compression */
864
+ {
865
+ CHDCOMPRESSION_NONE,
866
+ "none",
867
+ FALSE,
868
+ NULL,
869
+ NULL,
870
+ NULL,
871
+ NULL
872
+ },
873
+
874
+ /* standard zlib compression */
875
+ {
876
+ CHDCOMPRESSION_ZLIB,
877
+ "zlib",
878
+ FALSE,
879
+ zlib_codec_init,
880
+ zlib_codec_free,
881
+ zlib_codec_decompress,
882
+ NULL
883
+ },
884
+
885
+ /* zlib+ compression */
886
+ {
887
+ CHDCOMPRESSION_ZLIB_PLUS,
888
+ "zlib+",
889
+ FALSE,
890
+ zlib_codec_init,
891
+ zlib_codec_free,
892
+ zlib_codec_decompress,
893
+ NULL
894
+ },
895
+
896
+ /* V5 zlib compression */
897
+ {
898
+ CHD_CODEC_ZLIB,
899
+ "zlib (Deflate)",
900
+ FALSE,
901
+ zlib_codec_init,
902
+ zlib_codec_free,
903
+ zlib_codec_decompress,
904
+ NULL
905
+ },
906
+
907
+ /* V5 CD zlib compression */
908
+ {
909
+ CHD_CODEC_CD_ZLIB,
910
+ "cdzl (CD Deflate)",
911
+ FALSE,
912
+ cdzl_codec_init,
913
+ cdzl_codec_free,
914
+ cdzl_codec_decompress,
915
+ NULL
916
+ },
917
+
918
+ /* V5 CD lzma compression */
919
+ {
920
+ CHD_CODEC_CD_LZMA,
921
+ "cdlz (CD LZMA)",
922
+ FALSE,
923
+ cdlz_codec_init,
924
+ cdlz_codec_free,
925
+ cdlz_codec_decompress,
926
+ NULL
927
+ },
928
+
929
+ /* V5 CD flac compression */
930
+ {
931
+ CHD_CODEC_CD_FLAC,
932
+ "cdfl (CD FLAC)",
933
+ FALSE,
934
+ cdfl_codec_init,
935
+ cdfl_codec_free,
936
+ cdfl_codec_decompress,
937
+ NULL
938
+ },
939
+ };
940
+
941
+ /***************************************************************************
942
+ INLINE FUNCTIONS
943
+ ***************************************************************************/
944
+
945
+ /*-------------------------------------------------
946
+ get_bigendian_uint64 - fetch a UINT64 from
947
+ the data stream in bigendian order
948
+ -------------------------------------------------*/
949
+
950
+ static inline UINT64 get_bigendian_uint64(const UINT8 *base)
951
+ {
952
+ return ((UINT64)base[0] << 56) | ((UINT64)base[1] << 48) | ((UINT64)base[2] << 40) | ((UINT64)base[3] << 32) |
953
+ ((UINT64)base[4] << 24) | ((UINT64)base[5] << 16) | ((UINT64)base[6] << 8) | (UINT64)base[7];
954
+ }
955
+
956
+ /*-------------------------------------------------
957
+ put_bigendian_uint64 - write a UINT64 to
958
+ the data stream in bigendian order
959
+ -------------------------------------------------*/
960
+
961
+ static inline void put_bigendian_uint64(UINT8 *base, UINT64 value)
962
+ {
963
+ base[0] = value >> 56;
964
+ base[1] = value >> 48;
965
+ base[2] = value >> 40;
966
+ base[3] = value >> 32;
967
+ base[4] = value >> 24;
968
+ base[5] = value >> 16;
969
+ base[6] = value >> 8;
970
+ base[7] = value;
971
+ }
972
+
973
+ /*-------------------------------------------------
974
+ get_bigendian_uint48 - fetch a UINT48 from
975
+ the data stream in bigendian order
976
+ -------------------------------------------------*/
977
+
978
+ static inline UINT64 get_bigendian_uint48(const UINT8 *base)
979
+ {
980
+ return ((UINT64)base[0] << 40) | ((UINT64)base[1] << 32) |
981
+ ((UINT64)base[2] << 24) | ((UINT64)base[3] << 16) | ((UINT64)base[4] << 8) | (UINT64)base[5];
982
+ }
983
+
984
+ /*-------------------------------------------------
985
+ put_bigendian_uint48 - write a UINT48 to
986
+ the data stream in bigendian order
987
+ -------------------------------------------------*/
988
+
989
+ static inline void put_bigendian_uint48(UINT8 *base, UINT64 value)
990
+ {
991
+ value &= 0xffffffffffff;
992
+ base[0] = value >> 40;
993
+ base[1] = value >> 32;
994
+ base[2] = value >> 24;
995
+ base[3] = value >> 16;
996
+ base[4] = value >> 8;
997
+ base[5] = value;
998
+ }
999
+ /*-------------------------------------------------
1000
+ get_bigendian_uint32 - fetch a UINT32 from
1001
+ the data stream in bigendian order
1002
+ -------------------------------------------------*/
1003
+
1004
+ static inline UINT32 get_bigendian_uint32(const UINT8 *base)
1005
+ {
1006
+ return (base[0] << 24) | (base[1] << 16) | (base[2] << 8) | base[3];
1007
+ }
1008
+
1009
+ /*-------------------------------------------------
1010
+ put_bigendian_uint32 - write a UINT32 to
1011
+ the data stream in bigendian order
1012
+ -------------------------------------------------*/
1013
+
1014
+ static inline void put_bigendian_uint32(UINT8 *base, UINT32 value)
1015
+ {
1016
+ base[0] = value >> 24;
1017
+ base[1] = value >> 16;
1018
+ base[2] = value >> 8;
1019
+ base[3] = value;
1020
+ }
1021
+
1022
+ /*-------------------------------------------------
1023
+ put_bigendian_uint24 - write a UINT24 to
1024
+ the data stream in bigendian order
1025
+ -------------------------------------------------*/
1026
+
1027
+ static inline void put_bigendian_uint24(UINT8 *base, UINT32 value)
1028
+ {
1029
+ value &= 0xffffff;
1030
+ base[0] = value >> 16;
1031
+ base[1] = value >> 8;
1032
+ base[2] = value;
1033
+ }
1034
+
1035
+ /*-------------------------------------------------
1036
+ get_bigendian_uint24 - fetch a UINT24 from
1037
+ the data stream in bigendian order
1038
+ -------------------------------------------------*/
1039
+
1040
+ static inline UINT32 get_bigendian_uint24(const UINT8 *base)
1041
+ {
1042
+ return (base[0] << 16) | (base[1] << 8) | base[2];
1043
+ }
1044
+
1045
+ /*-------------------------------------------------
1046
+ get_bigendian_uint16 - fetch a UINT16 from
1047
+ the data stream in bigendian order
1048
+ -------------------------------------------------*/
1049
+
1050
+ static inline UINT16 get_bigendian_uint16(const UINT8 *base)
1051
+ {
1052
+ return (base[0] << 8) | base[1];
1053
+ }
1054
+
1055
+ /*-------------------------------------------------
1056
+ put_bigendian_uint16 - write a UINT16 to
1057
+ the data stream in bigendian order
1058
+ -------------------------------------------------*/
1059
+
1060
+ static inline void put_bigendian_uint16(UINT8 *base, UINT16 value)
1061
+ {
1062
+ base[0] = value >> 8;
1063
+ base[1] = value;
1064
+ }
1065
+
1066
+ /*-------------------------------------------------
1067
+ map_extract - extract a single map
1068
+ entry from the datastream
1069
+ -------------------------------------------------*/
1070
+
1071
+ static inline void map_extract(const UINT8 *base, map_entry *entry)
1072
+ {
1073
+ entry->offset = get_bigendian_uint64(&base[0]);
1074
+ entry->crc = get_bigendian_uint32(&base[8]);
1075
+ entry->length = get_bigendian_uint16(&base[12]) | (base[14] << 16);
1076
+ entry->flags = base[15];
1077
+ }
1078
+
1079
+ /*-------------------------------------------------
1080
+ map_assemble - write a single map
1081
+ entry to the datastream
1082
+ -------------------------------------------------*/
1083
+
1084
+ static inline void map_assemble(UINT8 *base, map_entry *entry)
1085
+ {
1086
+ put_bigendian_uint64(&base[0], entry->offset);
1087
+ put_bigendian_uint32(&base[8], entry->crc);
1088
+ put_bigendian_uint16(&base[12], entry->length);
1089
+ base[14] = entry->length >> 16;
1090
+ base[15] = entry->flags;
1091
+ }
1092
+
1093
+ /*-------------------------------------------------
1094
+ map_size_v5 - calculate CHDv5 map size
1095
+ -------------------------------------------------*/
1096
+ static inline int map_size_v5(chd_header* header)
1097
+ {
1098
+ return header->hunkcount * header->mapentrybytes;
1099
+ }
1100
+
1101
+ /*-------------------------------------------------
1102
+ crc16 - calculate CRC16 (from hashing.cpp)
1103
+ -------------------------------------------------*/
1104
+ uint16_t crc16(const void *data, uint32_t length)
1105
+ {
1106
+ uint16_t crc = 0xffff;
1107
+
1108
+ static const uint16_t s_table[256] =
1109
+ {
1110
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1111
+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1112
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1113
+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1114
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1115
+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1116
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1117
+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1118
+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1119
+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1120
+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1121
+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1122
+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1123
+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1124
+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1125
+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1126
+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1127
+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1128
+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1129
+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1130
+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1131
+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1132
+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1133
+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1134
+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1135
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1136
+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1137
+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1138
+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1139
+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1140
+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1141
+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1142
+ };
1143
+
1144
+ const uint8_t *src = (uint8_t*)data;
1145
+
1146
+ /* fetch the current value into a local and rip through the source data */
1147
+ while (length-- != 0)
1148
+ crc = (crc << 8) ^ s_table[(crc >> 8) ^ *src++];
1149
+ return crc;
1150
+ }
1151
+
1152
+ /*-------------------------------------------------
1153
+ compressed - test if CHD file is compressed
1154
+ +-------------------------------------------------*/
1155
+ static inline int chd_compressed(chd_header* header) {
1156
+ return header->compression[0] != CHD_CODEC_NONE;
1157
+ }
1158
+
1159
+ /*-------------------------------------------------
1160
+ decompress_v5_map - decompress the v5 map
1161
+ -------------------------------------------------*/
1162
+
1163
+ static chd_error decompress_v5_map(chd_file* chd, chd_header* header)
1164
+ {
1165
+ int result = 0;
1166
+ uint32_t hunknum;
1167
+ int repcount = 0;
1168
+ uint8_t lastcomp = 0;
1169
+ uint32_t last_self = 0;
1170
+ uint64_t last_parent = 0;
1171
+ struct bitstream* bitbuf;
1172
+ uint32_t mapbytes;
1173
+ uint64_t firstoffs;
1174
+ uint16_t mapcrc;
1175
+ uint8_t lengthbits;
1176
+ uint8_t selfbits;
1177
+ uint8_t parentbits;
1178
+ uint8_t *compressed_ptr;
1179
+ uint8_t rawbuf[16];
1180
+ struct huffman_decoder* decoder;
1181
+ enum huffman_error err;
1182
+ uint64_t curoffset;
1183
+ int rawmapsize = map_size_v5(header);
1184
+
1185
+ if (!chd_compressed(header))
1186
+ {
1187
+ header->rawmap = (uint8_t*)malloc(rawmapsize);
1188
+ core_fseek(chd->file, header->mapoffset, SEEK_SET);
1189
+ result = core_fread(chd->file, header->rawmap, rawmapsize);
1190
+ return CHDERR_NONE;
1191
+ }
1192
+
1193
+ /* read the reader */
1194
+ core_fseek(chd->file, header->mapoffset, SEEK_SET);
1195
+ result = core_fread(chd->file, rawbuf, sizeof(rawbuf));
1196
+ mapbytes = get_bigendian_uint32(&rawbuf[0]);
1197
+ firstoffs = get_bigendian_uint48(&rawbuf[4]);
1198
+ mapcrc = get_bigendian_uint16(&rawbuf[10]);
1199
+ lengthbits = rawbuf[12];
1200
+ selfbits = rawbuf[13];
1201
+ parentbits = rawbuf[14];
1202
+
1203
+ /* now read the map */
1204
+ compressed_ptr = (uint8_t*)malloc(sizeof(uint8_t) * mapbytes);
1205
+ core_fseek(chd->file, header->mapoffset + 16, SEEK_SET);
1206
+ result = core_fread(chd->file, compressed_ptr, mapbytes);
1207
+ bitbuf = create_bitstream(compressed_ptr, sizeof(uint8_t) * mapbytes);
1208
+ header->rawmap = (uint8_t*)malloc(rawmapsize);
1209
+
1210
+ /* first decode the compression types */
1211
+ decoder = create_huffman_decoder(16, 8);
1212
+ if (decoder == NULL)
1213
+ {
1214
+ free(compressed_ptr);
1215
+ free(bitbuf);
1216
+ return CHDERR_OUT_OF_MEMORY;
1217
+ }
1218
+
1219
+ err = huffman_import_tree_rle(decoder, bitbuf);
1220
+ if (err != HUFFERR_NONE)
1221
+ {
1222
+ free(compressed_ptr);
1223
+ free(bitbuf);
1224
+ delete_huffman_decoder(decoder);
1225
+ return CHDERR_DECOMPRESSION_ERROR;
1226
+ }
1227
+
1228
+ for (hunknum = 0; hunknum < header->hunkcount; hunknum++)
1229
+ {
1230
+ uint8_t *rawmap = header->rawmap + (hunknum * 12);
1231
+ if (repcount > 0)
1232
+ rawmap[0] = lastcomp, repcount--;
1233
+ else
1234
+ {
1235
+ uint8_t val = huffman_decode_one(decoder, bitbuf);
1236
+ if (val == COMPRESSION_RLE_SMALL)
1237
+ rawmap[0] = lastcomp, repcount = 2 + huffman_decode_one(decoder, bitbuf);
1238
+ else if (val == COMPRESSION_RLE_LARGE)
1239
+ rawmap[0] = lastcomp, repcount = 2 + 16 + (huffman_decode_one(decoder, bitbuf) << 4), repcount += huffman_decode_one(decoder, bitbuf);
1240
+ else
1241
+ rawmap[0] = lastcomp = val;
1242
+ }
1243
+ }
1244
+
1245
+ /* then iterate through the hunks and extract the needed data */
1246
+ curoffset = firstoffs;
1247
+ for (hunknum = 0; hunknum < header->hunkcount; hunknum++)
1248
+ {
1249
+ uint8_t *rawmap = header->rawmap + (hunknum * 12);
1250
+ uint64_t offset = curoffset;
1251
+ uint32_t length = 0;
1252
+ uint16_t crc = 0;
1253
+ switch (rawmap[0])
1254
+ {
1255
+ /* base types */
1256
+ case COMPRESSION_TYPE_0:
1257
+ case COMPRESSION_TYPE_1:
1258
+ case COMPRESSION_TYPE_2:
1259
+ case COMPRESSION_TYPE_3:
1260
+ curoffset += length = bitstream_read(bitbuf, lengthbits);
1261
+ crc = bitstream_read(bitbuf, 16);
1262
+ break;
1263
+
1264
+ case COMPRESSION_NONE:
1265
+ curoffset += length = header->hunkbytes;
1266
+ crc = bitstream_read(bitbuf, 16);
1267
+ break;
1268
+
1269
+ case COMPRESSION_SELF:
1270
+ last_self = offset = bitstream_read(bitbuf, selfbits);
1271
+ break;
1272
+
1273
+ case COMPRESSION_PARENT:
1274
+ offset = bitstream_read(bitbuf, parentbits);
1275
+ last_parent = offset;
1276
+ break;
1277
+
1278
+ /* pseudo-types; convert into base types */
1279
+ case COMPRESSION_SELF_1:
1280
+ last_self++;
1281
+ case COMPRESSION_SELF_0:
1282
+ rawmap[0] = COMPRESSION_SELF;
1283
+ offset = last_self;
1284
+ break;
1285
+
1286
+ case COMPRESSION_PARENT_SELF:
1287
+ rawmap[0] = COMPRESSION_PARENT;
1288
+ last_parent = offset = ( ((uint64_t)hunknum) * ((uint64_t)header->hunkbytes) ) / header->unitbytes;
1289
+ break;
1290
+
1291
+ case COMPRESSION_PARENT_1:
1292
+ last_parent += header->hunkbytes / header->unitbytes;
1293
+ case COMPRESSION_PARENT_0:
1294
+ rawmap[0] = COMPRESSION_PARENT;
1295
+ offset = last_parent;
1296
+ break;
1297
+ }
1298
+ /* UINT24 length */
1299
+ put_bigendian_uint24(&rawmap[1], length);
1300
+
1301
+ /* UINT48 offset */
1302
+ put_bigendian_uint48(&rawmap[4], offset);
1303
+
1304
+ /* crc16 */
1305
+ put_bigendian_uint16(&rawmap[10], crc);
1306
+ }
1307
+
1308
+ /* free memory */
1309
+ free(compressed_ptr);
1310
+ free(bitbuf);
1311
+ delete_huffman_decoder(decoder);
1312
+
1313
+ /* verify the final CRC */
1314
+ if (crc16(&header->rawmap[0], header->hunkcount * 12) != mapcrc)
1315
+ return CHDERR_DECOMPRESSION_ERROR;
1316
+
1317
+ return CHDERR_NONE;
1318
+ }
1319
+
1320
+ /*-------------------------------------------------
1321
+ map_extract_old - extract a single map
1322
+ entry in old format from the datastream
1323
+ -------------------------------------------------*/
1324
+
1325
+ static inline void map_extract_old(const UINT8 *base, map_entry *entry, UINT32 hunkbytes)
1326
+ {
1327
+ entry->offset = get_bigendian_uint64(&base[0]);
1328
+ entry->crc = 0;
1329
+ entry->length = entry->offset >> 44;
1330
+ entry->flags = MAP_ENTRY_FLAG_NO_CRC | ((entry->length == hunkbytes) ? V34_MAP_ENTRY_TYPE_UNCOMPRESSED : V34_MAP_ENTRY_TYPE_COMPRESSED);
1331
+ #ifdef __MWERKS__
1332
+ entry->offset = entry->offset & 0x00000FFFFFFFFFFFLL;
1333
+ #else
1334
+ entry->offset = (entry->offset << 20) >> 20;
1335
+ #endif
1336
+ }
1337
+
1338
+ /***************************************************************************
1339
+ CHD FILE MANAGEMENT
1340
+ ***************************************************************************/
1341
+
1342
+ /*-------------------------------------------------
1343
+ chd_open_file - open a CHD file for access
1344
+ -------------------------------------------------*/
1345
+
1346
+ CHD_EXPORT chd_error chd_open_file(core_file *file, int mode, chd_file *parent, chd_file **chd)
1347
+ {
1348
+ chd_file *newchd = NULL;
1349
+ chd_error err;
1350
+ int intfnum;
1351
+
1352
+ /* verify parameters */
1353
+ if (file == NULL)
1354
+ EARLY_EXIT(err = CHDERR_INVALID_PARAMETER);
1355
+
1356
+ /* punt if invalid parent */
1357
+ if (parent != NULL && parent->cookie != COOKIE_VALUE)
1358
+ EARLY_EXIT(err = CHDERR_INVALID_PARAMETER);
1359
+
1360
+ /* allocate memory for the final result */
1361
+ newchd = (chd_file *)malloc(sizeof(**chd));
1362
+ if (newchd == NULL)
1363
+ EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
1364
+ memset(newchd, 0, sizeof(*newchd));
1365
+ newchd->cookie = COOKIE_VALUE;
1366
+ newchd->parent = parent;
1367
+ newchd->file = file;
1368
+
1369
+ /* now attempt to read the header */
1370
+ err = header_read(newchd, &newchd->header);
1371
+ if (err != CHDERR_NONE)
1372
+ EARLY_EXIT(err);
1373
+
1374
+ /* validate the header */
1375
+ err = header_validate(&newchd->header);
1376
+ if (err != CHDERR_NONE)
1377
+ EARLY_EXIT(err);
1378
+
1379
+ /* make sure we don't open a read-only file writeable */
1380
+ if (mode == CHD_OPEN_READWRITE && !(newchd->header.flags & CHDFLAGS_IS_WRITEABLE))
1381
+ EARLY_EXIT(err = CHDERR_FILE_NOT_WRITEABLE);
1382
+
1383
+ /* also, never open an older version writeable */
1384
+ if (mode == CHD_OPEN_READWRITE && newchd->header.version < CHD_HEADER_VERSION)
1385
+ EARLY_EXIT(err = CHDERR_UNSUPPORTED_VERSION);
1386
+
1387
+ /* if we need a parent, make sure we have one */
1388
+ if (parent == NULL)
1389
+ {
1390
+ /* Detect parent requirement for versions below 5 */
1391
+ if (newchd->header.version < 5 && newchd->header.flags & CHDFLAGS_HAS_PARENT)
1392
+ EARLY_EXIT(err = CHDERR_REQUIRES_PARENT);
1393
+ /* Detection for version 5 and above - if parentsha1 != 0, we have a parent */
1394
+ else if (newchd->header.version >= 5 && memcmp(nullsha1, newchd->header.parentsha1, sizeof(newchd->header.parentsha1)) != 0)
1395
+ EARLY_EXIT(err = CHDERR_REQUIRES_PARENT);
1396
+ }
1397
+
1398
+ /* make sure we have a valid parent */
1399
+ if (parent != NULL)
1400
+ {
1401
+ /* check MD5 if it isn't empty */
1402
+ if (memcmp(nullmd5, newchd->header.parentmd5, sizeof(newchd->header.parentmd5)) != 0 &&
1403
+ memcmp(nullmd5, newchd->parent->header.md5, sizeof(newchd->parent->header.md5)) != 0 &&
1404
+ memcmp(newchd->parent->header.md5, newchd->header.parentmd5, sizeof(newchd->header.parentmd5)) != 0)
1405
+ EARLY_EXIT(err = CHDERR_INVALID_PARENT);
1406
+
1407
+ /* check SHA1 if it isn't empty */
1408
+ if (memcmp(nullsha1, newchd->header.parentsha1, sizeof(newchd->header.parentsha1)) != 0 &&
1409
+ memcmp(nullsha1, newchd->parent->header.sha1, sizeof(newchd->parent->header.sha1)) != 0 &&
1410
+ memcmp(newchd->parent->header.sha1, newchd->header.parentsha1, sizeof(newchd->header.parentsha1)) != 0)
1411
+ EARLY_EXIT(err = CHDERR_INVALID_PARENT);
1412
+ }
1413
+
1414
+ /* now read the hunk map */
1415
+ if (newchd->header.version < 5)
1416
+ {
1417
+ err = map_read(newchd);
1418
+ if (err != CHDERR_NONE)
1419
+ EARLY_EXIT(err);
1420
+ }
1421
+ else
1422
+ {
1423
+ err = decompress_v5_map(newchd, &(newchd->header));
1424
+ }
1425
+ if (err != CHDERR_NONE)
1426
+ EARLY_EXIT(err);
1427
+
1428
+ #ifdef NEED_CACHE_HUNK
1429
+ /* allocate and init the hunk cache */
1430
+ newchd->cache = (UINT8 *)malloc(newchd->header.hunkbytes);
1431
+ newchd->compare = (UINT8 *)malloc(newchd->header.hunkbytes);
1432
+ if (newchd->cache == NULL || newchd->compare == NULL)
1433
+ EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
1434
+ newchd->cachehunk = ~0;
1435
+ newchd->comparehunk = ~0;
1436
+ #endif
1437
+
1438
+ /* allocate the temporary compressed buffer */
1439
+ newchd->compressed = (UINT8 *)malloc(newchd->header.hunkbytes);
1440
+ if (newchd->compressed == NULL)
1441
+ EARLY_EXIT(err = CHDERR_OUT_OF_MEMORY);
1442
+
1443
+ /* find the codec interface */
1444
+ if (newchd->header.version < 5)
1445
+ {
1446
+ for (intfnum = 0; intfnum < ARRAY_LENGTH(codec_interfaces); intfnum++)
1447
+ {
1448
+ if (codec_interfaces[intfnum].compression == newchd->header.compression[0])
1449
+ {
1450
+ newchd->codecintf[0] = &codec_interfaces[intfnum];
1451
+ break;
1452
+ }
1453
+ }
1454
+
1455
+ if (intfnum == ARRAY_LENGTH(codec_interfaces))
1456
+ EARLY_EXIT(err = CHDERR_UNSUPPORTED_FORMAT);
1457
+
1458
+ /* initialize the codec */
1459
+ if (newchd->codecintf[0]->init != NULL)
1460
+ {
1461
+ err = (*newchd->codecintf[0]->init)(&newchd->zlib_codec_data, newchd->header.hunkbytes);
1462
+ if (err != CHDERR_NONE)
1463
+ EARLY_EXIT(err);
1464
+ }
1465
+ }
1466
+ else
1467
+ {
1468
+ int decompnum;
1469
+ /* verify the compression types and initialize the codecs */
1470
+ for (decompnum = 0; decompnum < ARRAY_LENGTH(newchd->header.compression); decompnum++)
1471
+ {
1472
+ int i;
1473
+ for (i = 0 ; i < ARRAY_LENGTH(codec_interfaces) ; i++)
1474
+ {
1475
+ if (codec_interfaces[i].compression == newchd->header.compression[decompnum])
1476
+ {
1477
+ newchd->codecintf[decompnum] = &codec_interfaces[i];
1478
+ break;
1479
+ }
1480
+ }
1481
+
1482
+ if (newchd->codecintf[decompnum] == NULL && newchd->header.compression[decompnum] != 0)
1483
+ EARLY_EXIT(err = CHDERR_UNSUPPORTED_FORMAT);
1484
+
1485
+ /* initialize the codec */
1486
+ if (newchd->codecintf[decompnum]->init != NULL)
1487
+ {
1488
+ void* codec = NULL;
1489
+ switch (newchd->header.compression[decompnum])
1490
+ {
1491
+ case CHD_CODEC_ZLIB:
1492
+ codec = &newchd->zlib_codec_data;
1493
+ break;
1494
+
1495
+ case CHD_CODEC_CD_ZLIB:
1496
+ codec = &newchd->cdzl_codec_data;
1497
+ break;
1498
+
1499
+ case CHD_CODEC_CD_LZMA:
1500
+ codec = &newchd->cdlz_codec_data;
1501
+ break;
1502
+
1503
+ case CHD_CODEC_CD_FLAC:
1504
+ codec = &newchd->cdfl_codec_data;
1505
+ break;
1506
+ }
1507
+
1508
+ if (codec == NULL)
1509
+ EARLY_EXIT(err = CHDERR_UNSUPPORTED_FORMAT);
1510
+
1511
+ err = (*newchd->codecintf[decompnum]->init)(codec, newchd->header.hunkbytes);
1512
+ if (err != CHDERR_NONE)
1513
+ EARLY_EXIT(err);
1514
+ }
1515
+ }
1516
+ }
1517
+
1518
+ /* all done */
1519
+ *chd = newchd;
1520
+ return CHDERR_NONE;
1521
+
1522
+ cleanup:
1523
+ if (newchd != NULL)
1524
+ chd_close(newchd);
1525
+ return err;
1526
+ }
1527
+
1528
+ /*-------------------------------------------------
1529
+ chd_precache - precache underlying file in
1530
+ memory
1531
+ -------------------------------------------------*/
1532
+
1533
+ CHD_EXPORT chd_error chd_precache(chd_file *chd)
1534
+ {
1535
+ #ifdef _MSC_VER
1536
+ size_t size, count;
1537
+ #else
1538
+ ssize_t size, count;
1539
+ #endif
1540
+
1541
+ if (chd->file_cache == NULL)
1542
+ {
1543
+ core_fseek(chd->file, 0, SEEK_END);
1544
+ size = core_ftell(chd->file);
1545
+ if (size <= 0)
1546
+ return CHDERR_INVALID_DATA;
1547
+ chd->file_cache = malloc(size);
1548
+ if (chd->file_cache == NULL)
1549
+ return CHDERR_OUT_OF_MEMORY;
1550
+ core_fseek(chd->file, 0, SEEK_SET);
1551
+ count = core_fread(chd->file, chd->file_cache, size);
1552
+ if (count != size)
1553
+ {
1554
+ free(chd->file_cache);
1555
+ chd->file_cache = NULL;
1556
+ return CHDERR_READ_ERROR;
1557
+ }
1558
+ }
1559
+
1560
+ return CHDERR_NONE;
1561
+ }
1562
+
1563
+ /*-------------------------------------------------
1564
+ chd_open - open a CHD file by
1565
+ filename
1566
+ -------------------------------------------------*/
1567
+
1568
+ CHD_EXPORT chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd)
1569
+ {
1570
+ chd_error err;
1571
+ core_file *file = NULL;
1572
+
1573
+ if (filename == NULL)
1574
+ {
1575
+ err = CHDERR_INVALID_PARAMETER;
1576
+ goto cleanup;
1577
+ }
1578
+
1579
+ /* choose the proper mode */
1580
+ switch(mode)
1581
+ {
1582
+ case CHD_OPEN_READ:
1583
+ break;
1584
+
1585
+ default:
1586
+ err = CHDERR_INVALID_PARAMETER;
1587
+ goto cleanup;
1588
+ }
1589
+
1590
+ /* open the file */
1591
+ file = core_fopen(filename);
1592
+ if (file == 0)
1593
+ {
1594
+ err = CHDERR_FILE_NOT_FOUND;
1595
+ goto cleanup;
1596
+ }
1597
+
1598
+ /* now open the CHD */
1599
+ err = chd_open_file(file, mode, parent, chd);
1600
+ if (err != CHDERR_NONE)
1601
+ goto cleanup;
1602
+
1603
+ /* we now own this file */
1604
+ (*chd)->owns_file = TRUE;
1605
+
1606
+ cleanup:
1607
+ if ((err != CHDERR_NONE) && (file != NULL))
1608
+ core_fclose(file);
1609
+ return err;
1610
+ }
1611
+
1612
+ /*-------------------------------------------------
1613
+ chd_close - close a CHD file for access
1614
+ -------------------------------------------------*/
1615
+
1616
+ CHD_EXPORT void chd_close(chd_file *chd)
1617
+ {
1618
+ /* punt if NULL or invalid */
1619
+ if (chd == NULL || chd->cookie != COOKIE_VALUE)
1620
+ return;
1621
+
1622
+ /* deinit the codec */
1623
+ if (chd->header.version < 5)
1624
+ {
1625
+ if (chd->codecintf[0] != NULL && chd->codecintf[0]->free != NULL)
1626
+ (*chd->codecintf[0]->free)(&chd->zlib_codec_data);
1627
+ }
1628
+ else
1629
+ {
1630
+ int i;
1631
+ /* Free the codecs */
1632
+ for (i = 0 ; i < ARRAY_LENGTH(chd->codecintf); i++)
1633
+ {
1634
+ void* codec = NULL;
1635
+
1636
+ if (chd->codecintf[i] == NULL)
1637
+ continue;
1638
+
1639
+ switch (chd->codecintf[i]->compression)
1640
+ {
1641
+ case CHD_CODEC_CD_LZMA:
1642
+ codec = &chd->cdlz_codec_data;
1643
+ break;
1644
+
1645
+ case CHD_CODEC_ZLIB:
1646
+ codec = &chd->zlib_codec_data;
1647
+ break;
1648
+
1649
+ case CHD_CODEC_CD_ZLIB:
1650
+ codec = &chd->cdzl_codec_data;
1651
+ break;
1652
+
1653
+ case CHD_CODEC_CD_FLAC:
1654
+ codec = &chd->cdfl_codec_data;
1655
+ break;
1656
+ }
1657
+
1658
+ if (codec)
1659
+ {
1660
+ (*chd->codecintf[i]->free)(codec);
1661
+ }
1662
+ }
1663
+
1664
+ /* Free the raw map */
1665
+ if (chd->header.rawmap != NULL)
1666
+ free(chd->header.rawmap);
1667
+ }
1668
+
1669
+ /* free the compressed data buffer */
1670
+ if (chd->compressed != NULL)
1671
+ free(chd->compressed);
1672
+
1673
+ #ifdef NEED_CACHE_HUNK
1674
+ /* free the hunk cache and compare data */
1675
+ if (chd->compare != NULL)
1676
+ free(chd->compare);
1677
+ if (chd->cache != NULL)
1678
+ free(chd->cache);
1679
+ #endif
1680
+
1681
+ /* free the hunk map */
1682
+ if (chd->map != NULL)
1683
+ free(chd->map);
1684
+
1685
+ /* close the file */
1686
+ if (chd->owns_file && chd->file != NULL)
1687
+ core_fclose(chd->file);
1688
+
1689
+ #ifdef NEED_CACHE_HUNK
1690
+ if (PRINTF_MAX_HUNK) printf("Max hunk = %d/%d\n", chd->maxhunk, chd->header.totalhunks);
1691
+ #endif
1692
+ if (chd->file_cache)
1693
+ free(chd->file_cache);
1694
+
1695
+ if (chd->parent)
1696
+ chd_close(chd->parent);
1697
+
1698
+ /* free our memory */
1699
+ free(chd);
1700
+ }
1701
+
1702
+ /*-------------------------------------------------
1703
+ chd_core_file - return the associated
1704
+ core_file
1705
+ -------------------------------------------------*/
1706
+
1707
+ CHD_EXPORT core_file *chd_core_file(chd_file *chd)
1708
+ {
1709
+ return chd->file;
1710
+ }
1711
+
1712
+ /*-------------------------------------------------
1713
+ chd_error_string - return an error string for
1714
+ the given CHD error
1715
+ -------------------------------------------------*/
1716
+
1717
+ CHD_EXPORT const char *chd_error_string(chd_error err)
1718
+ {
1719
+ switch (err)
1720
+ {
1721
+ case CHDERR_NONE: return "no error";
1722
+ case CHDERR_NO_INTERFACE: return "no drive interface";
1723
+ case CHDERR_OUT_OF_MEMORY: return "out of memory";
1724
+ case CHDERR_INVALID_FILE: return "invalid file";
1725
+ case CHDERR_INVALID_PARAMETER: return "invalid parameter";
1726
+ case CHDERR_INVALID_DATA: return "invalid data";
1727
+ case CHDERR_FILE_NOT_FOUND: return "file not found";
1728
+ case CHDERR_REQUIRES_PARENT: return "requires parent";
1729
+ case CHDERR_FILE_NOT_WRITEABLE: return "file not writeable";
1730
+ case CHDERR_READ_ERROR: return "read error";
1731
+ case CHDERR_WRITE_ERROR: return "write error";
1732
+ case CHDERR_CODEC_ERROR: return "codec error";
1733
+ case CHDERR_INVALID_PARENT: return "invalid parent";
1734
+ case CHDERR_HUNK_OUT_OF_RANGE: return "hunk out of range";
1735
+ case CHDERR_DECOMPRESSION_ERROR: return "decompression error";
1736
+ case CHDERR_COMPRESSION_ERROR: return "compression error";
1737
+ case CHDERR_CANT_CREATE_FILE: return "can't create file";
1738
+ case CHDERR_CANT_VERIFY: return "can't verify file";
1739
+ case CHDERR_NOT_SUPPORTED: return "operation not supported";
1740
+ case CHDERR_METADATA_NOT_FOUND: return "can't find metadata";
1741
+ case CHDERR_INVALID_METADATA_SIZE: return "invalid metadata size";
1742
+ case CHDERR_UNSUPPORTED_VERSION: return "unsupported CHD version";
1743
+ case CHDERR_VERIFY_INCOMPLETE: return "incomplete verify";
1744
+ case CHDERR_INVALID_METADATA: return "invalid metadata";
1745
+ case CHDERR_INVALID_STATE: return "invalid state";
1746
+ case CHDERR_OPERATION_PENDING: return "operation pending";
1747
+ case CHDERR_NO_ASYNC_OPERATION: return "no async operation in progress";
1748
+ case CHDERR_UNSUPPORTED_FORMAT: return "unsupported format";
1749
+ default: return "undocumented error";
1750
+ }
1751
+ }
1752
+
1753
+ /***************************************************************************
1754
+ CHD HEADER MANAGEMENT
1755
+ ***************************************************************************/
1756
+
1757
+ /*-------------------------------------------------
1758
+ chd_get_header - return a pointer to the
1759
+ extracted header data
1760
+ -------------------------------------------------*/
1761
+
1762
+ CHD_EXPORT const chd_header *chd_get_header(chd_file *chd)
1763
+ {
1764
+ /* punt if NULL or invalid */
1765
+ if (chd == NULL || chd->cookie != COOKIE_VALUE)
1766
+ return NULL;
1767
+
1768
+ return &chd->header;
1769
+ }
1770
+
1771
+ /*-------------------------------------------------
1772
+ chd_read_header - read CHD header data
1773
+ from file into the pointed struct
1774
+ -------------------------------------------------*/
1775
+ CHD_EXPORT chd_error chd_read_header(const char *filename, chd_header *header)
1776
+ {
1777
+ chd_error err = CHDERR_NONE;
1778
+ chd_file chd;
1779
+
1780
+ /* punt if NULL */
1781
+ if (filename == NULL || header == NULL)
1782
+ EARLY_EXIT(err = CHDERR_INVALID_PARAMETER);
1783
+
1784
+ /* open the file */
1785
+ chd.file = core_fopen(filename);
1786
+ if (chd.file == NULL)
1787
+ EARLY_EXIT(err = CHDERR_FILE_NOT_FOUND);
1788
+
1789
+ /* attempt to read the header */
1790
+ err = header_read(&chd, header);
1791
+ if (err != CHDERR_NONE)
1792
+ EARLY_EXIT(err);
1793
+
1794
+ /* validate the header */
1795
+ err = header_validate(header);
1796
+ if (err != CHDERR_NONE)
1797
+ EARLY_EXIT(err);
1798
+
1799
+ cleanup:
1800
+ if (chd.file != NULL)
1801
+ core_fclose(chd.file);
1802
+
1803
+ return err;
1804
+ }
1805
+
1806
+ /***************************************************************************
1807
+ CORE DATA READ/WRITE
1808
+ ***************************************************************************/
1809
+
1810
+ /*-------------------------------------------------
1811
+ chd_read - read a single hunk from the CHD
1812
+ file
1813
+ -------------------------------------------------*/
1814
+
1815
+ CHD_EXPORT chd_error chd_read(chd_file *chd, UINT32 hunknum, void *buffer)
1816
+ {
1817
+ /* punt if NULL or invalid */
1818
+ if (chd == NULL || chd->cookie != COOKIE_VALUE)
1819
+ return CHDERR_INVALID_PARAMETER;
1820
+
1821
+ /* if we're past the end, fail */
1822
+ if (hunknum >= chd->header.totalhunks)
1823
+ return CHDERR_HUNK_OUT_OF_RANGE;
1824
+
1825
+ /* perform the read */
1826
+ return hunk_read_into_memory(chd, hunknum, (UINT8 *)buffer);
1827
+ }
1828
+
1829
+ /***************************************************************************
1830
+ METADATA MANAGEMENT
1831
+ ***************************************************************************/
1832
+
1833
+ /*-------------------------------------------------
1834
+ chd_get_metadata - get the indexed metadata
1835
+ of the given type
1836
+ -------------------------------------------------*/
1837
+
1838
+ CHD_EXPORT chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 searchindex, void *output, UINT32 outputlen, UINT32 *resultlen, UINT32 *resulttag, UINT8 *resultflags)
1839
+ {
1840
+ metadata_entry metaentry;
1841
+ chd_error err;
1842
+ UINT32 count;
1843
+
1844
+ /* if we didn't find it, just return */
1845
+ err = metadata_find_entry(chd, searchtag, searchindex, &metaentry);
1846
+ if (err != CHDERR_NONE)
1847
+ {
1848
+ /* unless we're an old version and they are requesting hard disk metadata */
1849
+ if (chd->header.version < 3 && (searchtag == HARD_DISK_METADATA_TAG || searchtag == CHDMETATAG_WILDCARD) && searchindex == 0)
1850
+ {
1851
+ char faux_metadata[256];
1852
+ UINT32 faux_length;
1853
+
1854
+ /* fill in the faux metadata */
1855
+ sprintf(faux_metadata, HARD_DISK_METADATA_FORMAT, chd->header.obsolete_cylinders, chd->header.obsolete_heads, chd->header.obsolete_sectors, chd->header.hunkbytes / chd->header.obsolete_hunksize);
1856
+ faux_length = (UINT32)strlen(faux_metadata) + 1;
1857
+
1858
+ /* copy the metadata itself */
1859
+ memcpy(output, faux_metadata, MIN(outputlen, faux_length));
1860
+
1861
+ /* return the length of the data and the tag */
1862
+ if (resultlen != NULL)
1863
+ *resultlen = faux_length;
1864
+ if (resulttag != NULL)
1865
+ *resulttag = HARD_DISK_METADATA_TAG;
1866
+ return CHDERR_NONE;
1867
+ }
1868
+ return err;
1869
+ }
1870
+
1871
+ /* read the metadata */
1872
+ outputlen = MIN(outputlen, metaentry.length);
1873
+ core_fseek(chd->file, metaentry.offset + METADATA_HEADER_SIZE, SEEK_SET);
1874
+ count = core_fread(chd->file, output, outputlen);
1875
+ if (count != outputlen)
1876
+ return CHDERR_READ_ERROR;
1877
+
1878
+ /* return the length of the data and the tag */
1879
+ if (resultlen != NULL)
1880
+ *resultlen = metaentry.length;
1881
+ if (resulttag != NULL)
1882
+ *resulttag = metaentry.metatag;
1883
+ if (resultflags != NULL)
1884
+ *resultflags = metaentry.flags;
1885
+ return CHDERR_NONE;
1886
+ }
1887
+
1888
+ /***************************************************************************
1889
+ CODEC INTERFACES
1890
+ ***************************************************************************/
1891
+
1892
+ /*-------------------------------------------------
1893
+ chd_codec_config - set internal codec
1894
+ parameters
1895
+ -------------------------------------------------*/
1896
+
1897
+ CHD_EXPORT chd_error chd_codec_config(chd_file *chd, int param, void *config)
1898
+ {
1899
+ return CHDERR_INVALID_PARAMETER;
1900
+ }
1901
+
1902
+ /*-------------------------------------------------
1903
+ chd_get_codec_name - get the name of a
1904
+ particular codec
1905
+ -------------------------------------------------*/
1906
+
1907
+ CHD_EXPORT const char *chd_get_codec_name(UINT32 codec)
1908
+ {
1909
+ return "Unknown";
1910
+ }
1911
+
1912
+ /***************************************************************************
1913
+ INTERNAL HEADER OPERATIONS
1914
+ ***************************************************************************/
1915
+
1916
+ /*-------------------------------------------------
1917
+ header_validate - check the validity of a
1918
+ CHD header
1919
+ -------------------------------------------------*/
1920
+
1921
+ static chd_error header_validate(const chd_header *header)
1922
+ {
1923
+ int intfnum;
1924
+
1925
+ /* require a valid version */
1926
+ if (header->version == 0 || header->version > CHD_HEADER_VERSION)
1927
+ return CHDERR_UNSUPPORTED_VERSION;
1928
+
1929
+ /* require a valid length */
1930
+ if ((header->version == 1 && header->length != CHD_V1_HEADER_SIZE) ||
1931
+ (header->version == 2 && header->length != CHD_V2_HEADER_SIZE) ||
1932
+ (header->version == 3 && header->length != CHD_V3_HEADER_SIZE) ||
1933
+ (header->version == 4 && header->length != CHD_V4_HEADER_SIZE) ||
1934
+ (header->version == 5 && header->length != CHD_V5_HEADER_SIZE))
1935
+ return CHDERR_INVALID_PARAMETER;
1936
+
1937
+ /* Do not validate v5 header */
1938
+ if (header->version <= 4)
1939
+ {
1940
+ /* require valid flags */
1941
+ if (header->flags & CHDFLAGS_UNDEFINED)
1942
+ return CHDERR_INVALID_PARAMETER;
1943
+
1944
+ /* require a supported compression mechanism */
1945
+ for (intfnum = 0; intfnum < ARRAY_LENGTH(codec_interfaces); intfnum++)
1946
+ if (codec_interfaces[intfnum].compression == header->compression[0])
1947
+ break;
1948
+
1949
+ if (intfnum == ARRAY_LENGTH(codec_interfaces))
1950
+ return CHDERR_INVALID_PARAMETER;
1951
+
1952
+ /* require a valid hunksize */
1953
+ if (header->hunkbytes == 0 || header->hunkbytes >= 65536 * 256)
1954
+ return CHDERR_INVALID_PARAMETER;
1955
+
1956
+ /* require a valid hunk count */
1957
+ if (header->totalhunks == 0)
1958
+ return CHDERR_INVALID_PARAMETER;
1959
+
1960
+ /* require a valid MD5 and/or SHA1 if we're using a parent */
1961
+ if ((header->flags & CHDFLAGS_HAS_PARENT) && memcmp(header->parentmd5, nullmd5, sizeof(nullmd5)) == 0 && memcmp(header->parentsha1, nullsha1, sizeof(nullsha1)) == 0)
1962
+ return CHDERR_INVALID_PARAMETER;
1963
+
1964
+ /* if we're V3 or later, the obsolete fields must be 0 */
1965
+ if (header->version >= 3 &&
1966
+ (header->obsolete_cylinders != 0 || header->obsolete_sectors != 0 ||
1967
+ header->obsolete_heads != 0 || header->obsolete_hunksize != 0))
1968
+ return CHDERR_INVALID_PARAMETER;
1969
+
1970
+ /* if we're pre-V3, the obsolete fields must NOT be 0 */
1971
+ if (header->version < 3 &&
1972
+ (header->obsolete_cylinders == 0 || header->obsolete_sectors == 0 ||
1973
+ header->obsolete_heads == 0 || header->obsolete_hunksize == 0))
1974
+ return CHDERR_INVALID_PARAMETER;
1975
+ }
1976
+
1977
+ return CHDERR_NONE;
1978
+ }
1979
+
1980
+ /*-------------------------------------------------
1981
+ header_guess_unitbytes - for older CHD formats,
1982
+ guess at the bytes/unit based on metadata
1983
+ -------------------------------------------------*/
1984
+
1985
+ static UINT32 header_guess_unitbytes(chd_file *chd)
1986
+ {
1987
+ /* look for hard disk metadata; if found, then the unit size == sector size */
1988
+ char metadata[512];
1989
+ int i0, i1, i2, i3;
1990
+ if (chd_get_metadata(chd, HARD_DISK_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE &&
1991
+ sscanf(metadata, HARD_DISK_METADATA_FORMAT, &i0, &i1, &i2, &i3) == 4)
1992
+ return i3;
1993
+
1994
+ /* look for CD-ROM metadata; if found, then the unit size == CD frame size */
1995
+ if (chd_get_metadata(chd, CDROM_OLD_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
1996
+ chd_get_metadata(chd, CDROM_TRACK_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
1997
+ chd_get_metadata(chd, CDROM_TRACK_METADATA2_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
1998
+ chd_get_metadata(chd, GDROM_OLD_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE ||
1999
+ chd_get_metadata(chd, GDROM_TRACK_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL) == CHDERR_NONE)
2000
+ return CD_FRAME_SIZE;
2001
+
2002
+ /* otherwise, just map 1:1 with the hunk size */
2003
+ return chd->header.hunkbytes;
2004
+ }
2005
+
2006
+ /*-------------------------------------------------
2007
+ header_read - read a CHD header into the
2008
+ internal data structure
2009
+ -------------------------------------------------*/
2010
+
2011
+ static chd_error header_read(chd_file *chd, chd_header *header)
2012
+ {
2013
+ UINT8 rawheader[CHD_MAX_HEADER_SIZE];
2014
+ UINT32 count;
2015
+
2016
+ /* punt if NULL */
2017
+ if (header == NULL)
2018
+ return CHDERR_INVALID_PARAMETER;
2019
+
2020
+ /* punt if invalid file */
2021
+ if (chd->file == NULL)
2022
+ return CHDERR_INVALID_FILE;
2023
+
2024
+ /* seek and read */
2025
+ core_fseek(chd->file, 0, SEEK_SET);
2026
+ count = core_fread(chd->file, rawheader, sizeof(rawheader));
2027
+ if (count != sizeof(rawheader))
2028
+ return CHDERR_READ_ERROR;
2029
+
2030
+ /* verify the tag */
2031
+ if (strncmp((char *)rawheader, "MComprHD", 8) != 0)
2032
+ return CHDERR_INVALID_DATA;
2033
+
2034
+ /* extract the direct data */
2035
+ memset(header, 0, sizeof(*header));
2036
+ header->length = get_bigendian_uint32(&rawheader[8]);
2037
+ header->version = get_bigendian_uint32(&rawheader[12]);
2038
+
2039
+ /* make sure it's a version we understand */
2040
+ if (header->version == 0 || header->version > CHD_HEADER_VERSION)
2041
+ return CHDERR_UNSUPPORTED_VERSION;
2042
+
2043
+ /* make sure the length is expected */
2044
+ if ((header->version == 1 && header->length != CHD_V1_HEADER_SIZE) ||
2045
+ (header->version == 2 && header->length != CHD_V2_HEADER_SIZE) ||
2046
+ (header->version == 3 && header->length != CHD_V3_HEADER_SIZE) ||
2047
+ (header->version == 4 && header->length != CHD_V4_HEADER_SIZE) ||
2048
+ (header->version == 5 && header->length != CHD_V5_HEADER_SIZE))
2049
+
2050
+ return CHDERR_INVALID_DATA;
2051
+
2052
+ /* extract the common data */
2053
+ header->flags = get_bigendian_uint32(&rawheader[16]);
2054
+ header->compression[0] = get_bigendian_uint32(&rawheader[20]);
2055
+ header->compression[1] = CHD_CODEC_NONE;
2056
+ header->compression[2] = CHD_CODEC_NONE;
2057
+ header->compression[3] = CHD_CODEC_NONE;
2058
+
2059
+ /* extract the V1/V2-specific data */
2060
+ if (header->version < 3)
2061
+ {
2062
+ int seclen = (header->version == 1) ? CHD_V1_SECTOR_SIZE : get_bigendian_uint32(&rawheader[76]);
2063
+ header->obsolete_hunksize = get_bigendian_uint32(&rawheader[24]);
2064
+ header->totalhunks = get_bigendian_uint32(&rawheader[28]);
2065
+ header->obsolete_cylinders = get_bigendian_uint32(&rawheader[32]);
2066
+ header->obsolete_heads = get_bigendian_uint32(&rawheader[36]);
2067
+ header->obsolete_sectors = get_bigendian_uint32(&rawheader[40]);
2068
+ memcpy(header->md5, &rawheader[44], CHD_MD5_BYTES);
2069
+ memcpy(header->parentmd5, &rawheader[60], CHD_MD5_BYTES);
2070
+ header->logicalbytes = (UINT64)header->obsolete_cylinders * (UINT64)header->obsolete_heads * (UINT64)header->obsolete_sectors * (UINT64)seclen;
2071
+ header->hunkbytes = seclen * header->obsolete_hunksize;
2072
+ header->unitbytes = header_guess_unitbytes(chd);
2073
+ header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
2074
+ header->metaoffset = 0;
2075
+ }
2076
+
2077
+ /* extract the V3-specific data */
2078
+ else if (header->version == 3)
2079
+ {
2080
+ header->totalhunks = get_bigendian_uint32(&rawheader[24]);
2081
+ header->logicalbytes = get_bigendian_uint64(&rawheader[28]);
2082
+ header->metaoffset = get_bigendian_uint64(&rawheader[36]);
2083
+ memcpy(header->md5, &rawheader[44], CHD_MD5_BYTES);
2084
+ memcpy(header->parentmd5, &rawheader[60], CHD_MD5_BYTES);
2085
+ header->hunkbytes = get_bigendian_uint32(&rawheader[76]);
2086
+ header->unitbytes = header_guess_unitbytes(chd);
2087
+ header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
2088
+ memcpy(header->sha1, &rawheader[80], CHD_SHA1_BYTES);
2089
+ memcpy(header->parentsha1, &rawheader[100], CHD_SHA1_BYTES);
2090
+ }
2091
+
2092
+ /* extract the V4-specific data */
2093
+ else if (header->version == 4)
2094
+ {
2095
+ header->totalhunks = get_bigendian_uint32(&rawheader[24]);
2096
+ header->logicalbytes = get_bigendian_uint64(&rawheader[28]);
2097
+ header->metaoffset = get_bigendian_uint64(&rawheader[36]);
2098
+ header->hunkbytes = get_bigendian_uint32(&rawheader[44]);
2099
+ header->unitbytes = header_guess_unitbytes(chd);
2100
+ header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
2101
+ memcpy(header->sha1, &rawheader[48], CHD_SHA1_BYTES);
2102
+ memcpy(header->parentsha1, &rawheader[68], CHD_SHA1_BYTES);
2103
+ memcpy(header->rawsha1, &rawheader[88], CHD_SHA1_BYTES);
2104
+ }
2105
+
2106
+ /* extract the V5-specific data */
2107
+ else if (header->version == 5)
2108
+ {
2109
+ /* TODO */
2110
+ header->compression[0] = get_bigendian_uint32(&rawheader[16]);
2111
+ header->compression[1] = get_bigendian_uint32(&rawheader[20]);
2112
+ header->compression[2] = get_bigendian_uint32(&rawheader[24]);
2113
+ header->compression[3] = get_bigendian_uint32(&rawheader[28]);
2114
+ header->logicalbytes = get_bigendian_uint64(&rawheader[32]);
2115
+ header->mapoffset = get_bigendian_uint64(&rawheader[40]);
2116
+ header->metaoffset = get_bigendian_uint64(&rawheader[48]);
2117
+ header->hunkbytes = get_bigendian_uint32(&rawheader[56]);
2118
+ header->hunkcount = (header->logicalbytes + header->hunkbytes - 1) / header->hunkbytes;
2119
+ header->unitbytes = get_bigendian_uint32(&rawheader[60]);
2120
+ header->unitcount = (header->logicalbytes + header->unitbytes - 1) / header->unitbytes;
2121
+ memcpy(header->sha1, &rawheader[84], CHD_SHA1_BYTES);
2122
+ memcpy(header->parentsha1, &rawheader[104], CHD_SHA1_BYTES);
2123
+ memcpy(header->rawsha1, &rawheader[64], CHD_SHA1_BYTES);
2124
+
2125
+ /* determine properties of map entries */
2126
+ header->mapentrybytes = chd_compressed(header) ? 12 : 4;
2127
+
2128
+ /* hack */
2129
+ header->totalhunks = header->hunkcount;
2130
+ }
2131
+
2132
+ /* Unknown version */
2133
+ else
2134
+ {
2135
+ /* TODO */
2136
+ }
2137
+
2138
+ /* guess it worked */
2139
+ return CHDERR_NONE;
2140
+ }
2141
+
2142
+ /***************************************************************************
2143
+ INTERNAL HUNK READ/WRITE
2144
+ ***************************************************************************/
2145
+
2146
+ /*-------------------------------------------------
2147
+ hunk_read_compressed - read a compressed
2148
+ hunk
2149
+ -------------------------------------------------*/
2150
+
2151
+ static UINT8* hunk_read_compressed(chd_file *chd, UINT64 offset, size_t size)
2152
+ {
2153
+ #ifdef _MSC_VER
2154
+ size_t bytes;
2155
+ #else
2156
+ ssize_t bytes;
2157
+ #endif
2158
+ if (chd->file_cache != NULL)
2159
+ {
2160
+ return chd->file_cache + offset;
2161
+ }
2162
+ else
2163
+ {
2164
+ core_fseek(chd->file, offset, SEEK_SET);
2165
+ bytes = core_fread(chd->file, chd->compressed, size);
2166
+ if (bytes != size)
2167
+ return NULL;
2168
+ return chd->compressed;
2169
+ }
2170
+ }
2171
+
2172
+ /*-------------------------------------------------
2173
+ hunk_read_uncompressed - read an uncompressed
2174
+ hunk
2175
+ -------------------------------------------------*/
2176
+
2177
+ static chd_error hunk_read_uncompressed(chd_file *chd, UINT64 offset, size_t size, UINT8 *dest)
2178
+ {
2179
+ #ifdef _MSC_VER
2180
+ size_t bytes;
2181
+ #else
2182
+ ssize_t bytes;
2183
+ #endif
2184
+ if (chd->file_cache != NULL)
2185
+ {
2186
+ memcpy(dest, chd->file_cache + offset, size);
2187
+ }
2188
+ else
2189
+ {
2190
+ core_fseek(chd->file, offset, SEEK_SET);
2191
+ bytes = core_fread(chd->file, dest, size);
2192
+ if (bytes != size)
2193
+ return CHDERR_READ_ERROR;
2194
+ }
2195
+ return CHDERR_NONE;
2196
+ }
2197
+
2198
+ #ifdef NEED_CACHE_HUNK
2199
+ /*-------------------------------------------------
2200
+ hunk_read_into_cache - read a hunk into
2201
+ the CHD's hunk cache
2202
+ -------------------------------------------------*/
2203
+
2204
+ static chd_error hunk_read_into_cache(chd_file *chd, UINT32 hunknum)
2205
+ {
2206
+ chd_error err;
2207
+
2208
+ /* track the max */
2209
+ if (hunknum > chd->maxhunk)
2210
+ chd->maxhunk = hunknum;
2211
+
2212
+ /* if we're already in the cache, we're done */
2213
+ if (chd->cachehunk == hunknum)
2214
+ return CHDERR_NONE;
2215
+ chd->cachehunk = ~0;
2216
+
2217
+ /* otherwise, read the data */
2218
+ err = hunk_read_into_memory(chd, hunknum, chd->cache);
2219
+ if (err != CHDERR_NONE)
2220
+ return err;
2221
+
2222
+ /* mark the hunk successfully cached in */
2223
+ chd->cachehunk = hunknum;
2224
+ return CHDERR_NONE;
2225
+ }
2226
+ #endif
2227
+
2228
+ /*-------------------------------------------------
2229
+ hunk_read_into_memory - read a hunk into
2230
+ memory at the given location
2231
+ -------------------------------------------------*/
2232
+
2233
+ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *dest)
2234
+ {
2235
+ chd_error err;
2236
+
2237
+ /* punt if no file */
2238
+ if (chd->file == NULL)
2239
+ return CHDERR_INVALID_FILE;
2240
+
2241
+ /* return an error if out of range */
2242
+ if (hunknum >= chd->header.totalhunks)
2243
+ return CHDERR_HUNK_OUT_OF_RANGE;
2244
+
2245
+ if (dest == NULL)
2246
+ return CHDERR_INVALID_PARAMETER;
2247
+
2248
+ if (chd->header.version < 5)
2249
+ {
2250
+ map_entry *entry = &chd->map[hunknum];
2251
+ UINT32 bytes;
2252
+ UINT8* compressed_bytes;
2253
+
2254
+ /* switch off the entry type */
2255
+ switch (entry->flags & MAP_ENTRY_FLAG_TYPE_MASK)
2256
+ {
2257
+ /* compressed data */
2258
+ case V34_MAP_ENTRY_TYPE_COMPRESSED:
2259
+ {
2260
+ void *codec = NULL;
2261
+
2262
+ /* read it into the decompression buffer */
2263
+ compressed_bytes = hunk_read_compressed(chd, entry->offset, entry->length);
2264
+ if (compressed_bytes == NULL)
2265
+ return CHDERR_READ_ERROR;
2266
+
2267
+ /* now decompress using the codec */
2268
+ err = CHDERR_NONE;
2269
+ codec = &chd->zlib_codec_data;
2270
+ if (chd->codecintf[0]->decompress != NULL)
2271
+ err = (*chd->codecintf[0]->decompress)(codec, compressed_bytes, entry->length, dest, chd->header.hunkbytes);
2272
+ if (err != CHDERR_NONE)
2273
+ return err;
2274
+ break;
2275
+ }
2276
+
2277
+ /* uncompressed data */
2278
+ case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
2279
+ err = hunk_read_uncompressed(chd, entry->offset, chd->header.hunkbytes, dest);
2280
+ if (err != CHDERR_NONE)
2281
+ return err;
2282
+ break;
2283
+
2284
+ /* mini-compressed data */
2285
+ case V34_MAP_ENTRY_TYPE_MINI:
2286
+ put_bigendian_uint64(&dest[0], entry->offset);
2287
+ for (bytes = 8; bytes < chd->header.hunkbytes; bytes++)
2288
+ dest[bytes] = dest[bytes - 8];
2289
+ break;
2290
+
2291
+ /* self-referenced data */
2292
+ case V34_MAP_ENTRY_TYPE_SELF_HUNK:
2293
+ #ifdef NEED_CACHE_HUNK
2294
+ if (chd->cachehunk == entry->offset && dest == chd->cache)
2295
+ break;
2296
+ #endif
2297
+ return hunk_read_into_memory(chd, entry->offset, dest);
2298
+
2299
+ /* parent-referenced data */
2300
+ case V34_MAP_ENTRY_TYPE_PARENT_HUNK:
2301
+ err = hunk_read_into_memory(chd->parent, entry->offset, dest);
2302
+ if (err != CHDERR_NONE)
2303
+ return err;
2304
+ break;
2305
+ }
2306
+ return CHDERR_NONE;
2307
+ }
2308
+ else
2309
+ {
2310
+ void* codec = NULL;
2311
+ /* get a pointer to the map entry */
2312
+ uint64_t blockoffs;
2313
+ uint32_t blocklen;
2314
+ #ifdef VERIFY_BLOCK_CRC
2315
+ uint16_t blockcrc;
2316
+ #endif
2317
+ uint8_t *rawmap = &chd->header.rawmap[chd->header.mapentrybytes * hunknum];
2318
+ UINT8* compressed_bytes;
2319
+
2320
+ /* uncompressed case */
2321
+ if (!chd_compressed(&chd->header))
2322
+ {
2323
+ blockoffs = (uint64_t)get_bigendian_uint32(rawmap) * (uint64_t)chd->header.hunkbytes;
2324
+ if (blockoffs != 0) {
2325
+ core_fseek(chd->file, blockoffs, SEEK_SET);
2326
+ int result = core_fread(chd->file, dest, chd->header.hunkbytes);
2327
+ /* TODO
2328
+ else if (m_parent_missing)
2329
+ throw CHDERR_REQUIRES_PARENT; */
2330
+ } else if (chd->parent) {
2331
+ err = hunk_read_into_memory(chd->parent, hunknum, dest);
2332
+ if (err != CHDERR_NONE)
2333
+ return err;
2334
+ } else {
2335
+ memset(dest, 0, chd->header.hunkbytes);
2336
+ }
2337
+
2338
+ return CHDERR_NONE;
2339
+ }
2340
+
2341
+ /* compressed case */
2342
+ blocklen = get_bigendian_uint24(&rawmap[1]);
2343
+ blockoffs = get_bigendian_uint48(&rawmap[4]);
2344
+ #ifdef VERIFY_BLOCK_CRC
2345
+ blockcrc = get_bigendian_uint16(&rawmap[10]);
2346
+ #endif
2347
+ codec = NULL;
2348
+ switch (rawmap[0])
2349
+ {
2350
+ case COMPRESSION_TYPE_0:
2351
+ case COMPRESSION_TYPE_1:
2352
+ case COMPRESSION_TYPE_2:
2353
+ case COMPRESSION_TYPE_3:
2354
+ compressed_bytes = hunk_read_compressed(chd, blockoffs, blocklen);
2355
+ if (compressed_bytes == NULL)
2356
+ return CHDERR_READ_ERROR;
2357
+ switch (chd->codecintf[rawmap[0]]->compression)
2358
+ {
2359
+ case CHD_CODEC_CD_LZMA:
2360
+ codec = &chd->cdlz_codec_data;
2361
+ break;
2362
+
2363
+ case CHD_CODEC_ZLIB:
2364
+ codec = &chd->zlib_codec_data;
2365
+ break;
2366
+
2367
+ case CHD_CODEC_CD_ZLIB:
2368
+ codec = &chd->cdzl_codec_data;
2369
+ break;
2370
+
2371
+ case CHD_CODEC_CD_FLAC:
2372
+ codec = &chd->cdfl_codec_data;
2373
+ break;
2374
+ }
2375
+ if (codec==NULL)
2376
+ return CHDERR_CODEC_ERROR;
2377
+ err = chd->codecintf[rawmap[0]]->decompress(codec, compressed_bytes, blocklen, dest, chd->header.hunkbytes);
2378
+ if (err != CHDERR_NONE)
2379
+ return err;
2380
+ #ifdef VERIFY_BLOCK_CRC
2381
+ if (crc16(dest, chd->header.hunkbytes) != blockcrc)
2382
+ return CHDERR_DECOMPRESSION_ERROR;
2383
+ #endif
2384
+ return CHDERR_NONE;
2385
+
2386
+ case COMPRESSION_NONE:
2387
+ err = hunk_read_uncompressed(chd, blockoffs, blocklen, dest);
2388
+ if (err != CHDERR_NONE)
2389
+ return err;
2390
+ #ifdef VERIFY_BLOCK_CRC
2391
+ if (crc16(dest, chd->header.hunkbytes) != blockcrc)
2392
+ return CHDERR_DECOMPRESSION_ERROR;
2393
+ #endif
2394
+ return CHDERR_NONE;
2395
+
2396
+ case COMPRESSION_SELF:
2397
+ return hunk_read_into_memory(chd, blockoffs, dest);
2398
+
2399
+ case COMPRESSION_PARENT:
2400
+ if (chd->parent == NULL)
2401
+ return CHDERR_REQUIRES_PARENT;
2402
+ UINT8 units_in_hunk = chd->header.hunkbytes / chd->header.unitbytes;
2403
+
2404
+ /* blockoffs is aligned to units_in_hunk */
2405
+ if (blockoffs % units_in_hunk == 0) {
2406
+ return hunk_read_into_memory(chd->parent, blockoffs / units_in_hunk, dest);
2407
+ /* blockoffs is not aligned to units_in_hunk */
2408
+ } else {
2409
+ UINT32 unit_in_hunk = blockoffs % units_in_hunk;
2410
+ UINT8 *buf = malloc(chd->header.hunkbytes);
2411
+ /* Read first half of hunk which contains blockoffs */
2412
+ err = hunk_read_into_memory(chd->parent, blockoffs / units_in_hunk, buf);
2413
+ if (err != CHDERR_NONE) {
2414
+ free(buf);
2415
+ return err;
2416
+ }
2417
+ memcpy(dest, buf + unit_in_hunk * chd->header.unitbytes, (units_in_hunk - unit_in_hunk) * chd->header.unitbytes);
2418
+ /* Read second half of hunk which contains blockoffs */
2419
+ err = hunk_read_into_memory(chd->parent, (blockoffs / units_in_hunk) + 1, buf);
2420
+ if (err != CHDERR_NONE) {
2421
+ free(buf);
2422
+ return err;
2423
+ }
2424
+ memcpy(dest + (units_in_hunk - unit_in_hunk) * chd->header.unitbytes, buf, unit_in_hunk * chd->header.unitbytes);
2425
+ free(buf);
2426
+ }
2427
+ }
2428
+ return CHDERR_NONE;
2429
+ }
2430
+
2431
+ /* We should not reach this code */
2432
+ return CHDERR_DECOMPRESSION_ERROR;
2433
+ }
2434
+
2435
+ /***************************************************************************
2436
+ INTERNAL MAP ACCESS
2437
+ ***************************************************************************/
2438
+
2439
+ /*-------------------------------------------------
2440
+ map_read - read the initial sector map
2441
+ -------------------------------------------------*/
2442
+
2443
+ static chd_error map_read(chd_file *chd)
2444
+ {
2445
+ UINT32 entrysize = (chd->header.version < 3) ? OLD_MAP_ENTRY_SIZE : MAP_ENTRY_SIZE;
2446
+ UINT8 raw_map_entries[MAP_STACK_ENTRIES * MAP_ENTRY_SIZE];
2447
+ UINT64 fileoffset, maxoffset = 0;
2448
+ UINT8 cookie[MAP_ENTRY_SIZE];
2449
+ UINT32 count;
2450
+ chd_error err;
2451
+ UINT32 i;
2452
+
2453
+ /* first allocate memory */
2454
+ chd->map = (map_entry *)malloc(sizeof(chd->map[0]) * chd->header.totalhunks);
2455
+ if (!chd->map)
2456
+ return CHDERR_OUT_OF_MEMORY;
2457
+
2458
+ /* read the map entries in in chunks and extract to the map list */
2459
+ fileoffset = chd->header.length;
2460
+ for (i = 0; i < chd->header.totalhunks; i += MAP_STACK_ENTRIES)
2461
+ {
2462
+ /* compute how many entries this time */
2463
+ int entries = chd->header.totalhunks - i, j;
2464
+ if (entries > MAP_STACK_ENTRIES)
2465
+ entries = MAP_STACK_ENTRIES;
2466
+
2467
+ /* read that many */
2468
+ core_fseek(chd->file, fileoffset, SEEK_SET);
2469
+ count = core_fread(chd->file, raw_map_entries, entries * entrysize);
2470
+ if (count != entries * entrysize)
2471
+ {
2472
+ err = CHDERR_READ_ERROR;
2473
+ goto cleanup;
2474
+ }
2475
+ fileoffset += entries * entrysize;
2476
+
2477
+ /* process that many */
2478
+ if (entrysize == MAP_ENTRY_SIZE)
2479
+ {
2480
+ for (j = 0; j < entries; j++)
2481
+ map_extract(&raw_map_entries[j * MAP_ENTRY_SIZE], &chd->map[i + j]);
2482
+ }
2483
+ else
2484
+ {
2485
+ for (j = 0; j < entries; j++)
2486
+ map_extract_old(&raw_map_entries[j * OLD_MAP_ENTRY_SIZE], &chd->map[i + j], chd->header.hunkbytes);
2487
+ }
2488
+
2489
+ /* track the maximum offset */
2490
+ for (j = 0; j < entries; j++)
2491
+ if ((chd->map[i + j].flags & MAP_ENTRY_FLAG_TYPE_MASK) == V34_MAP_ENTRY_TYPE_COMPRESSED ||
2492
+ (chd->map[i + j].flags & MAP_ENTRY_FLAG_TYPE_MASK) == V34_MAP_ENTRY_TYPE_UNCOMPRESSED)
2493
+ maxoffset = MAX(maxoffset, chd->map[i + j].offset + chd->map[i + j].length);
2494
+ }
2495
+
2496
+ /* verify the cookie */
2497
+ core_fseek(chd->file, fileoffset, SEEK_SET);
2498
+ count = core_fread(chd->file, &cookie, entrysize);
2499
+ if (count != entrysize || memcmp(&cookie, END_OF_LIST_COOKIE, entrysize))
2500
+ {
2501
+ err = CHDERR_INVALID_FILE;
2502
+ goto cleanup;
2503
+ }
2504
+
2505
+ /* verify the length */
2506
+ if (maxoffset > core_fsize(chd->file))
2507
+ {
2508
+ err = CHDERR_INVALID_FILE;
2509
+ goto cleanup;
2510
+ }
2511
+ return CHDERR_NONE;
2512
+
2513
+ cleanup:
2514
+ if (chd->map)
2515
+ free(chd->map);
2516
+ chd->map = NULL;
2517
+ return err;
2518
+ }
2519
+
2520
+ /***************************************************************************
2521
+ INTERNAL METADATA ACCESS
2522
+ ***************************************************************************/
2523
+
2524
+ /*-------------------------------------------------
2525
+ metadata_find_entry - find a metadata entry
2526
+ -------------------------------------------------*/
2527
+
2528
+ static chd_error metadata_find_entry(chd_file *chd, UINT32 metatag, UINT32 metaindex, metadata_entry *metaentry)
2529
+ {
2530
+ /* start at the beginning */
2531
+ metaentry->offset = chd->header.metaoffset;
2532
+ metaentry->prev = 0;
2533
+
2534
+ /* loop until we run out of options */
2535
+ while (metaentry->offset != 0)
2536
+ {
2537
+ UINT8 raw_meta_header[METADATA_HEADER_SIZE];
2538
+ UINT32 count;
2539
+
2540
+ /* read the raw header */
2541
+ core_fseek(chd->file, metaentry->offset, SEEK_SET);
2542
+ count = core_fread(chd->file, raw_meta_header, sizeof(raw_meta_header));
2543
+ if (count != sizeof(raw_meta_header))
2544
+ break;
2545
+
2546
+ /* extract the data */
2547
+ metaentry->metatag = get_bigendian_uint32(&raw_meta_header[0]);
2548
+ metaentry->length = get_bigendian_uint32(&raw_meta_header[4]);
2549
+ metaentry->next = get_bigendian_uint64(&raw_meta_header[8]);
2550
+
2551
+ /* flags are encoded in the high byte of length */
2552
+ metaentry->flags = metaentry->length >> 24;
2553
+ metaentry->length &= 0x00ffffff;
2554
+
2555
+ /* if we got a match, proceed */
2556
+ if (metatag == CHDMETATAG_WILDCARD || metaentry->metatag == metatag)
2557
+ if (metaindex-- == 0)
2558
+ return CHDERR_NONE;
2559
+
2560
+ /* no match, fetch the next link */
2561
+ metaentry->prev = metaentry->offset;
2562
+ metaentry->offset = metaentry->next;
2563
+ }
2564
+
2565
+ /* if we get here, we didn't find it */
2566
+ return CHDERR_METADATA_NOT_FOUND;
2567
+ }
2568
+
2569
+ /***************************************************************************
2570
+ ZLIB COMPRESSION CODEC
2571
+ ***************************************************************************/
2572
+
2573
+ /*-------------------------------------------------
2574
+ zlib_codec_init - initialize the ZLIB codec
2575
+ -------------------------------------------------*/
2576
+
2577
+ static chd_error zlib_codec_init(void *codec, uint32_t hunkbytes)
2578
+ {
2579
+ int zerr;
2580
+ chd_error err;
2581
+ zlib_codec_data *data = (zlib_codec_data*)codec;
2582
+
2583
+ /* clear the buffers */
2584
+ memset(data, 0, sizeof(zlib_codec_data));
2585
+
2586
+ /* init the inflater first */
2587
+ data->inflater.next_in = (Bytef *)data; /* bogus, but that's ok */
2588
+ data->inflater.avail_in = 0;
2589
+ data->inflater.zalloc = zlib_fast_alloc;
2590
+ data->inflater.zfree = zlib_fast_free;
2591
+ data->inflater.opaque = &data->allocator;
2592
+ zerr = inflateInit2(&data->inflater, -MAX_WBITS);
2593
+
2594
+ /* convert errors */
2595
+ if (zerr == Z_MEM_ERROR)
2596
+ err = CHDERR_OUT_OF_MEMORY;
2597
+ else if (zerr != Z_OK)
2598
+ err = CHDERR_CODEC_ERROR;
2599
+ else
2600
+ err = CHDERR_NONE;
2601
+
2602
+ /* handle an error */
2603
+ if (err != CHDERR_NONE)
2604
+ free(data);
2605
+
2606
+ return err;
2607
+ }
2608
+
2609
+ /*-------------------------------------------------
2610
+ zlib_codec_free - free data for the ZLIB
2611
+ codec
2612
+ -------------------------------------------------*/
2613
+
2614
+ static void zlib_codec_free(void *codec)
2615
+ {
2616
+ zlib_codec_data *data = (zlib_codec_data *)codec;
2617
+
2618
+ /* deinit the streams */
2619
+ if (data != NULL)
2620
+ {
2621
+ inflateEnd(&data->inflater);
2622
+
2623
+ /* free our fast memory */
2624
+ zlib_allocator_free(&data->allocator);
2625
+ }
2626
+ }
2627
+
2628
+ /*-------------------------------------------------
2629
+ zlib_codec_decompress - decompress data using
2630
+ the ZLIB codec
2631
+ -------------------------------------------------*/
2632
+
2633
+ static chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
2634
+ {
2635
+ zlib_codec_data *data = (zlib_codec_data *)codec;
2636
+ int zerr;
2637
+
2638
+ /* reset the decompressor */
2639
+ data->inflater.next_in = (Bytef *)src;
2640
+ data->inflater.avail_in = complen;
2641
+ data->inflater.total_in = 0;
2642
+ data->inflater.next_out = (Bytef *)dest;
2643
+ data->inflater.avail_out = destlen;
2644
+ data->inflater.total_out = 0;
2645
+ zerr = inflateReset(&data->inflater);
2646
+ if (zerr != Z_OK)
2647
+ return CHDERR_DECOMPRESSION_ERROR;
2648
+
2649
+ /* do it */
2650
+ zerr = inflate(&data->inflater, Z_FINISH);
2651
+ if (data->inflater.total_out != destlen)
2652
+ return CHDERR_DECOMPRESSION_ERROR;
2653
+
2654
+ return CHDERR_NONE;
2655
+ }
2656
+
2657
+ /*-------------------------------------------------
2658
+ zlib_fast_alloc - fast malloc for ZLIB, which
2659
+ allocates and frees memory frequently
2660
+ -------------------------------------------------*/
2661
+
2662
+ /* Huge alignment values for possible SIMD optimization by compiler (NEON, SSE, AVX) */
2663
+ #define ZLIB_MIN_ALIGNMENT_BITS 512
2664
+ #define ZLIB_MIN_ALIGNMENT_BYTES (ZLIB_MIN_ALIGNMENT_BITS / 8)
2665
+
2666
+ static voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
2667
+ {
2668
+ zlib_allocator *alloc = (zlib_allocator *)opaque;
2669
+ uintptr_t paddr = 0;
2670
+ UINT32 *ptr;
2671
+ int i;
2672
+
2673
+ /* compute the size, rounding to the nearest 1k */
2674
+ size = (size * items + 0x3ff) & ~0x3ff;
2675
+
2676
+ /* reuse a hunk if we can */
2677
+ for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
2678
+ {
2679
+ ptr = alloc->allocptr[i];
2680
+ if (ptr && size == *ptr)
2681
+ {
2682
+ /* set the low bit of the size so we don't match next time */
2683
+ *ptr |= 1;
2684
+
2685
+ /* return aligned block address */
2686
+ return (voidpf)(alloc->allocptr2[i]);
2687
+ }
2688
+ }
2689
+
2690
+ /* alloc a new one */
2691
+ ptr = (UINT32 *)malloc(size + sizeof(UINT32) + ZLIB_MIN_ALIGNMENT_BYTES);
2692
+ if (!ptr)
2693
+ return NULL;
2694
+
2695
+ /* put it into the list */
2696
+ for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
2697
+ if (!alloc->allocptr[i])
2698
+ {
2699
+ alloc->allocptr[i] = ptr;
2700
+ paddr = (((uintptr_t)ptr) + sizeof(UINT32) + (ZLIB_MIN_ALIGNMENT_BYTES-1)) & (~(ZLIB_MIN_ALIGNMENT_BYTES-1));
2701
+ alloc->allocptr2[i] = (uint32_t*)paddr;
2702
+ break;
2703
+ }
2704
+
2705
+ /* set the low bit of the size so we don't match next time */
2706
+ *ptr = size | 1;
2707
+
2708
+ /* return aligned block address */
2709
+ return (voidpf)paddr;
2710
+ }
2711
+
2712
+ /*-------------------------------------------------
2713
+ zlib_fast_free - fast free for ZLIB, which
2714
+ allocates and frees memory frequently
2715
+ -------------------------------------------------*/
2716
+
2717
+ static void zlib_fast_free(voidpf opaque, voidpf address)
2718
+ {
2719
+ zlib_allocator *alloc = (zlib_allocator *)opaque;
2720
+ UINT32 *ptr = (UINT32 *)address;
2721
+ int i;
2722
+
2723
+ /* find the hunk */
2724
+ for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
2725
+ if (ptr == alloc->allocptr2[i])
2726
+ {
2727
+ /* clear the low bit of the size to allow matches */
2728
+ *(alloc->allocptr[i]) &= ~1;
2729
+ return;
2730
+ }
2731
+ }
2732
+
2733
+ /*-------------------------------------------------
2734
+ zlib_allocator_free
2735
+ -------------------------------------------------*/
2736
+ static void zlib_allocator_free(voidpf opaque)
2737
+ {
2738
+ zlib_allocator *alloc = (zlib_allocator *)opaque;
2739
+ int i;
2740
+
2741
+ for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
2742
+ if (alloc->allocptr[i])
2743
+ free(alloc->allocptr[i]);
2744
+ }