Mercurial > repos > blastem
comparison system.c @ 2546:6aa3025bbf5f
Merge
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 02 Jan 2025 23:03:50 -0800 |
parents | c076a96f1668 |
children | c30f0a288ccf |
comparison
equal
deleted
inserted
replaced
2544:99e59fdddbc3 | 2546:6aa3025bbf5f |
---|---|
6 #include "sms.h" | 6 #include "sms.h" |
7 #include "mediaplayer.h" | 7 #include "mediaplayer.h" |
8 #include "coleco.h" | 8 #include "coleco.h" |
9 #include "paths.h" | 9 #include "paths.h" |
10 #include "util.h" | 10 #include "util.h" |
11 #include "cdimage.h" | |
12 | |
13 #define SMD_HEADER_SIZE 512 | |
14 #define SMD_MAGIC1 0x03 | |
15 #define SMD_MAGIC2 0xAA | |
16 #define SMD_MAGIC3 0xBB | |
17 #define SMD_BLOCK_SIZE 0x4000 | |
18 | |
19 #ifdef DISABLE_ZLIB | |
20 #define ROMFILE FILE* | |
21 #define romopen fopen | |
22 #define romread fread | |
23 #define romseek fseek | |
24 #define romgetc fgetc | |
25 #define romclose fclose | |
26 #else | |
27 #include "zlib/zlib.h" | |
28 #define ROMFILE gzFile | |
29 #define romopen gzopen | |
30 #define romread gzfread | |
31 #define romseek gzseek | |
32 #define romgetc gzgetc | |
33 #define romclose gzclose | |
34 #endif | |
35 | |
36 uint16_t *process_smd_block(uint16_t *dst, uint8_t *src, size_t bytes) | |
37 { | |
38 for (uint8_t *low = src, *high = (src+bytes/2), *end = src+bytes; high < end; high++, low++) { | |
39 *(dst++) = *low << 8 | *high; | |
40 } | |
41 return dst; | |
42 } | |
43 | |
44 int load_smd_rom(ROMFILE f, void **buffer) | |
45 { | |
46 uint8_t block[SMD_BLOCK_SIZE]; | |
47 romseek(f, SMD_HEADER_SIZE, SEEK_SET); | |
48 | |
49 size_t filesize = 512 * 1024; | |
50 size_t readsize = 0; | |
51 uint16_t *dst, *buf; | |
52 dst = buf = malloc(filesize); | |
53 | |
54 | |
55 size_t read; | |
56 do { | |
57 if ((readsize + SMD_BLOCK_SIZE > filesize)) { | |
58 filesize *= 2; | |
59 buf = realloc(buf, filesize); | |
60 dst = buf + readsize/sizeof(uint16_t); | |
61 } | |
62 read = romread(block, 1, SMD_BLOCK_SIZE, f); | |
63 if (read > 0) { | |
64 dst = process_smd_block(dst, block, read); | |
65 readsize += read; | |
66 } | |
67 } while(read > 0); | |
68 romclose(f); | |
69 | |
70 *buffer = buf; | |
71 | |
72 return readsize; | |
73 } | |
74 | |
75 uint8_t is_smd_format(const char *filename, uint8_t *header) | |
76 { | |
77 if (header[1] == SMD_MAGIC1 && header[8] == SMD_MAGIC2 && header[9] == SMD_MAGIC3) { | |
78 int i; | |
79 for (i = 3; i < 8; i++) { | |
80 if (header[i] != 0) { | |
81 return 0; | |
82 } | |
83 } | |
84 if (i == 8) { | |
85 if (header[2]) { | |
86 fatal_error("%s is a split SMD ROM which is not currently supported", filename); | |
87 } | |
88 return 1; | |
89 } | |
90 } | |
91 return 0; | |
92 } | |
93 | |
94 #ifndef IS_LIB | |
95 uint32_t load_media_zip(const char *filename, system_media *dst) | |
96 { | |
97 static const char *valid_exts[] = {"bin", "md", "gen", "sms", "gg", "rom", "smd", "sg", "sc", "sf7"}; | |
98 const uint32_t num_exts = sizeof(valid_exts)/sizeof(*valid_exts); | |
99 zip_file *z = zip_open(filename); | |
100 if (!z) { | |
101 return 0; | |
102 } | |
103 | |
104 for (uint32_t i = 0; i < z->num_entries; i++) | |
105 { | |
106 char *ext = path_extension(z->entries[i].name); | |
107 if (!ext) { | |
108 continue; | |
109 } | |
110 for (uint32_t j = 0; j < num_exts; j++) | |
111 { | |
112 if (!strcasecmp(ext, valid_exts[j])) { | |
113 size_t out_size = nearest_pow2(z->entries[i].size); | |
114 dst->buffer = zip_read(z, i, &out_size); | |
115 if (dst->buffer) { | |
116 if (is_smd_format(z->entries[i].name, dst->buffer)) { | |
117 size_t offset; | |
118 for (offset = 0; offset + SMD_BLOCK_SIZE + SMD_HEADER_SIZE <= out_size; offset += SMD_BLOCK_SIZE) | |
119 { | |
120 uint8_t tmp[SMD_BLOCK_SIZE]; | |
121 uint8_t *u8dst = dst->buffer; | |
122 memcpy(tmp, u8dst + offset + SMD_HEADER_SIZE, SMD_BLOCK_SIZE); | |
123 process_smd_block((void *)(u8dst + offset), tmp, SMD_BLOCK_SIZE); | |
124 } | |
125 out_size = offset; | |
126 } | |
127 dst->extension = ext; | |
128 dst->dir = path_dirname(filename); | |
129 if (!dst->dir) { | |
130 dst->dir = path_current_dir(); | |
131 } | |
132 dst->name = basename_no_extension(filename); | |
133 dst->size = out_size; | |
134 dst->zip = z; | |
135 return out_size; | |
136 } | |
137 } | |
138 } | |
139 free(ext); | |
140 } | |
141 zip_close(z); | |
142 return 0; | |
143 } | |
144 #endif | |
145 | |
146 uint32_t load_media(char * filename, system_media *dst, system_type *stype) | |
147 { | |
148 uint8_t header[10]; | |
149 #ifndef IS_LIB | |
150 if (dst->zip) { | |
151 zip_close(dst->zip); | |
152 } | |
153 #endif | |
154 dst->orig_path = filename; | |
155 char *ext = path_extension(filename); | |
156 #ifndef IS_LIB | |
157 if (ext && !strcasecmp(ext, "zip")) { | |
158 free(ext); | |
159 return load_media_zip(filename, dst); | |
160 } | |
161 #endif | |
162 if (ext && !strcasecmp(ext, "iso")) { | |
163 if (stype) { | |
164 *stype = SYSTEM_SEGACD; | |
165 } | |
166 return make_iso_media(dst, filename); | |
167 } | |
168 | |
169 ROMFILE f = romopen(filename, "rb"); | |
170 if (!f) { | |
171 free(ext); | |
172 return 0; | |
173 } | |
174 #ifndef DISABLE_ZLIB | |
175 char *to_free = NULL; | |
176 if (!gzdirect(f) && ext && !strcasecmp(ext, "gz")) { | |
177 size_t without_gz = strlen(filename) - 2; | |
178 to_free = calloc(1, without_gz); | |
179 memcpy(to_free, filename, without_gz - 1); | |
180 to_free[without_gz - 1] = 0; | |
181 free(ext); | |
182 filename = to_free; | |
183 ext = path_extension(filename); | |
184 } | |
185 #endif //DISABLE_ZLIB | |
186 | |
187 if (sizeof(header) != romread(header, 1, sizeof(header), f)) { | |
188 fatal_error("Error reading from %s\n", filename); | |
189 } | |
190 | |
191 uint32_t ret = 0; | |
192 if (is_smd_format(filename, header)) { | |
193 if (stype) { | |
194 *stype = SYSTEM_GENESIS; | |
195 } | |
196 ret = load_smd_rom(f, &dst->buffer); | |
197 } | |
198 | |
199 if (!ret) { | |
200 size_t filesize = 512 * 1024; | |
201 size_t readsize = sizeof(header); | |
202 | |
203 char *buf = malloc(filesize); | |
204 memcpy(buf, header, readsize); | |
205 | |
206 size_t read; | |
207 do { | |
208 read = romread(buf + readsize, 1, filesize - readsize, f); | |
209 if (read > 0) { | |
210 readsize += read; | |
211 if (readsize == filesize) { | |
212 int one_more = romgetc(f); | |
213 if (one_more >= 0) { | |
214 filesize *= 2; | |
215 buf = realloc(buf, filesize); | |
216 buf[readsize++] = one_more; | |
217 } else { | |
218 read = 0; | |
219 } | |
220 } | |
221 } | |
222 } while (read > 0); | |
223 dst->buffer = buf; | |
224 ret = (uint32_t)readsize; | |
225 } | |
226 dst->dir = path_dirname(filename); | |
227 if (!dst->dir) { | |
228 dst->dir = path_current_dir(); | |
229 } | |
230 dst->name = basename_no_extension(filename); | |
231 dst->extension = ext; | |
232 dst->size = ret; | |
233 romclose(f); | |
234 if (!strcasecmp(dst->extension, "cue")) { | |
235 if (parse_cue(dst)) { | |
236 if (stype) { | |
237 *stype = SYSTEM_SEGACD; | |
238 } | |
239 } | |
240 } else if (!strcasecmp(dst->extension, "toc")) { | |
241 if (parse_toc(dst)) { | |
242 if (stype) { | |
243 *stype = SYSTEM_SEGACD; | |
244 } | |
245 } | |
246 } | |
247 #ifndef DISABLE_ZLIB | |
248 if (to_free) { | |
249 free(to_free); | |
250 } | |
251 #endif | |
252 | |
253 return ret; | |
254 } | |
11 | 255 |
12 uint8_t safe_cmp(char *str, long offset, uint8_t *buffer, long filesize) | 256 uint8_t safe_cmp(char *str, long offset, uint8_t *buffer, long filesize) |
13 { | 257 { |
14 long len = strlen(str); | 258 long len = strlen(str); |
15 return filesize >= offset+len && !memcmp(str, buffer + offset, len); | 259 return filesize >= offset+len && !memcmp(str, buffer + offset, len); |