Mercurial > repos > blastem
comparison blastem.c @ 1692:5dacaef602a7 segacd
Merge from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 05 Jan 2019 00:58:08 -0800 |
parents | d2d637dbacfb 357b4951d9b2 |
children | 3414a4423de1 |
comparison
equal
deleted
inserted
replaced
1504:95b3a1a8b26c | 1692:5dacaef602a7 |
---|---|
21 #include "util.h" | 21 #include "util.h" |
22 #include "romdb.h" | 22 #include "romdb.h" |
23 #include "terminal.h" | 23 #include "terminal.h" |
24 #include "arena.h" | 24 #include "arena.h" |
25 #include "config.h" | 25 #include "config.h" |
26 #include "bindings.h" | |
26 #include "menu.h" | 27 #include "menu.h" |
27 | 28 #include "zip.h" |
28 #define BLASTEM_VERSION "0.5.2-pre" | 29 #ifndef DISABLE_NUKLEAR |
30 #include "nuklear_ui/blastem_nuklear.h" | |
31 #endif | |
32 | |
33 #define BLASTEM_VERSION "0.6.1" | |
29 | 34 |
30 #ifdef __ANDROID__ | 35 #ifdef __ANDROID__ |
31 #define FULLSCREEN_DEFAULT 1 | 36 #define FULLSCREEN_DEFAULT 1 |
32 #else | 37 #else |
33 #define FULLSCREEN_DEFAULT 0 | 38 #define FULLSCREEN_DEFAULT 0 |
45 #define SMD_MAGIC1 0x03 | 50 #define SMD_MAGIC1 0x03 |
46 #define SMD_MAGIC2 0xAA | 51 #define SMD_MAGIC2 0xAA |
47 #define SMD_MAGIC3 0xBB | 52 #define SMD_MAGIC3 0xBB |
48 #define SMD_BLOCK_SIZE 0x4000 | 53 #define SMD_BLOCK_SIZE 0x4000 |
49 | 54 |
50 int load_smd_rom(long filesize, FILE * f, void **buffer) | 55 #ifdef DISABLE_ZLIB |
56 #define ROMFILE FILE* | |
57 #define romopen fopen | |
58 #define romread fread | |
59 #define romseek fseek | |
60 #define romgetc fgetc | |
61 #define romclose fclose | |
62 #else | |
63 #include "zlib/zlib.h" | |
64 #define ROMFILE gzFile | |
65 #define romopen gzopen | |
66 #define romread gzfread | |
67 #define romseek gzseek | |
68 #define romgetc gzgetc | |
69 #define romclose gzclose | |
70 #endif | |
71 | |
72 int load_smd_rom(ROMFILE f, void **buffer) | |
51 { | 73 { |
52 uint8_t block[SMD_BLOCK_SIZE]; | 74 uint8_t block[SMD_BLOCK_SIZE]; |
53 filesize -= SMD_HEADER_SIZE; | 75 romseek(f, SMD_HEADER_SIZE, SEEK_SET); |
54 fseek(f, SMD_HEADER_SIZE, SEEK_SET); | 76 |
55 | 77 size_t filesize = 512 * 1024; |
56 uint16_t *dst = *buffer = malloc(nearest_pow2(filesize)); | 78 size_t readsize = 0; |
57 int rom_size = filesize; | 79 uint16_t *dst = malloc(filesize); |
58 while (filesize > 0) { | 80 |
59 fread(block, 1, SMD_BLOCK_SIZE, f); | 81 |
60 for (uint8_t *low = block, *high = (block+SMD_BLOCK_SIZE/2), *end = block+SMD_BLOCK_SIZE; high < end; high++, low++) { | 82 size_t read; |
61 *(dst++) = *low << 8 | *high; | 83 do { |
62 } | 84 if ((readsize + SMD_BLOCK_SIZE > filesize)) { |
63 filesize -= SMD_BLOCK_SIZE; | 85 filesize *= 2; |
64 } | 86 dst = realloc(dst, filesize); |
65 return rom_size; | 87 } |
66 } | 88 read = romread(block, 1, SMD_BLOCK_SIZE, f); |
67 | 89 if (read > 0) { |
68 uint32_t load_media(char * filename, system_media *dst, system_type *stype) | 90 for (uint8_t *low = block, *high = (block+read/2), *end = block+read; high < end; high++, low++) { |
91 *(dst++) = *low << 8 | *high; | |
92 } | |
93 readsize += read; | |
94 } | |
95 } while(read > 0); | |
96 romclose(f); | |
97 | |
98 *buffer = dst; | |
99 | |
100 return readsize; | |
101 } | |
102 | |
103 uint32_t load_media_zip(const char *filename, system_media *dst) | |
104 { | |
105 static const char *valid_exts[] = {"bin", "md", "gen", "sms", "rom"}; | |
106 const uint32_t num_exts = sizeof(valid_exts)/sizeof(*valid_exts); | |
107 zip_file *z = zip_open(filename); | |
108 if (!z) { | |
109 return 0; | |
110 } | |
111 | |
112 for (uint32_t i = 0; i < z->num_entries; i++) | |
113 { | |
114 char *ext = path_extension(z->entries[i].name); | |
115 if (!ext) { | |
116 continue; | |
117 } | |
118 for (uint32_t j = 0; j < num_exts; j++) | |
119 { | |
120 if (!strcasecmp(ext, valid_exts[j])) { | |
121 size_t out_size = nearest_pow2(z->entries[i].size); | |
122 dst->buffer = zip_read(z, i, &out_size); | |
123 if (dst->buffer) { | |
124 dst->extension = ext; | |
125 dst->dir = path_dirname(filename); | |
126 dst->name = basename_no_extension(filename); | |
127 dst->size = out_size; | |
128 zip_close(z); | |
129 return out_size; | |
130 } | |
131 } | |
132 } | |
133 free(ext); | |
134 } | |
135 zip_close(z); | |
136 return 0; | |
137 } | |
138 | |
139 uint32_t load_media(const char * filename, system_media *dst, system_type *stype) | |
69 { | 140 { |
70 uint8_t header[10]; | 141 uint8_t header[10]; |
71 FILE * f = fopen(filename, "rb"); | 142 char *ext = path_extension(filename); |
143 if (ext && !strcasecmp(ext, "zip")) { | |
144 free(ext); | |
145 return load_media_zip(filename, dst); | |
146 } | |
147 free(ext); | |
148 ROMFILE f = romopen(filename, "rb"); | |
72 if (!f) { | 149 if (!f) { |
73 return 0; | 150 return 0; |
74 } | 151 } |
75 if (sizeof(header) != fread(header, 1, sizeof(header), f)) { | 152 if (sizeof(header) != romread(header, 1, sizeof(header), f)) { |
76 fatal_error("Error reading from %s\n", filename); | 153 fatal_error("Error reading from %s\n", filename); |
77 } | 154 } |
78 fseek(f, 0, SEEK_END); | 155 |
79 long filesize = ftell(f); | |
80 fseek(f, 0, SEEK_SET); | |
81 uint32_t ret = 0; | 156 uint32_t ret = 0; |
82 if (header[1] == SMD_MAGIC1 && header[8] == SMD_MAGIC2 && header[9] == SMD_MAGIC3) { | 157 if (header[1] == SMD_MAGIC1 && header[8] == SMD_MAGIC2 && header[9] == SMD_MAGIC3) { |
83 int i; | 158 int i; |
84 for (i = 3; i < 8; i++) { | 159 for (i = 3; i < 8; i++) { |
85 if (header[i] != 0) { | 160 if (header[i] != 0) { |
91 fatal_error("%s is a split SMD ROM which is not currently supported", filename); | 166 fatal_error("%s is a split SMD ROM which is not currently supported", filename); |
92 } | 167 } |
93 if (stype) { | 168 if (stype) { |
94 *stype = SYSTEM_GENESIS; | 169 *stype = SYSTEM_GENESIS; |
95 } | 170 } |
96 ret = load_smd_rom(filesize, f, &dst->buffer); | 171 ret = load_smd_rom(f, &dst->buffer); |
97 } | 172 } |
98 } | 173 } |
174 | |
99 if (!ret) { | 175 if (!ret) { |
100 dst->buffer = malloc(nearest_pow2(filesize)); | 176 size_t filesize = 512 * 1024; |
101 if (filesize != fread(dst->buffer, 1, filesize, f)) { | 177 size_t readsize = sizeof(header); |
102 fatal_error("Error reading from %s\n", filename); | 178 |
103 } | 179 char *buf = malloc(filesize); |
104 ret = filesize; | 180 memcpy(buf, header, readsize); |
181 | |
182 size_t read; | |
183 do { | |
184 read = romread(buf + readsize, 1, filesize - readsize, f); | |
185 if (read > 0) { | |
186 readsize += read; | |
187 if (readsize == filesize) { | |
188 int one_more = romgetc(f); | |
189 if (one_more >= 0) { | |
190 filesize *= 2; | |
191 buf = realloc(buf, filesize); | |
192 buf[readsize++] = one_more; | |
193 } else { | |
194 read = 0; | |
195 } | |
196 } | |
197 } | |
198 } while (read > 0); | |
199 dst->buffer = buf; | |
200 ret = (uint32_t)readsize; | |
105 } | 201 } |
106 dst->dir = path_dirname(filename); | 202 dst->dir = path_dirname(filename); |
107 dst->name = basename_no_extension(filename); | 203 dst->name = basename_no_extension(filename); |
108 dst->extension = path_extension(filename); | 204 dst->extension = path_extension(filename); |
109 dst->size = ret; | 205 dst->size = ret; |
110 fclose(f); | 206 |
207 romclose(f); | |
111 return ret; | 208 return ret; |
112 } | 209 } |
113 | 210 |
114 | 211 |
115 | 212 |
159 warning("Failed to create save directory %s\n", save_dir); | 256 warning("Failed to create save directory %s\n", save_dir); |
160 } | 257 } |
161 return save_dir; | 258 return save_dir; |
162 } | 259 } |
163 | 260 |
164 void setup_saves(system_media *media, rom_info *info, system_header *context) | 261 void setup_saves(system_media *media, system_header *context) |
165 { | 262 { |
166 static uint8_t persist_save_registered; | 263 static uint8_t persist_save_registered; |
264 rom_info *info = &context->info; | |
167 char *save_dir = get_save_dir(info->is_save_lock_on ? media->chain : media); | 265 char *save_dir = get_save_dir(info->is_save_lock_on ? media->chain : media); |
168 char const *parts[] = {save_dir, PATH_SEP, info->save_type == SAVE_I2C ? "save.eeprom" : info->save_type == SAVE_NOR ? "save.nor" : "save.sram"}; | 266 char const *parts[] = {save_dir, PATH_SEP, info->save_type == SAVE_I2C ? "save.eeprom" : info->save_type == SAVE_NOR ? "save.nor" : "save.sram"}; |
169 free(save_filename); | 267 free(save_filename); |
170 save_filename = alloc_concat_m(3, parts); | 268 save_filename = alloc_concat_m(3, parts); |
171 if (info->is_save_lock_on) { | 269 if (info->is_save_lock_on) { |
172 //initial save dir was calculated based on lock-on cartridge because that's where the save device is | 270 //initial save dir was calculated based on lock-on cartridge because that's where the save device is |
173 //save directory used for save states should still be located in the normal place | 271 //save directory used for save states should still be located in the normal place |
174 free(save_dir); | 272 free(save_dir); |
175 save_dir = get_save_dir(media); | 273 parts[0] = save_dir = get_save_dir(media); |
176 } | 274 } |
177 if (use_native_states || context->type != SYSTEM_GENESIS) { | 275 if (use_native_states || context->type != SYSTEM_GENESIS) { |
178 parts[2] = "quicksave.state"; | 276 parts[2] = "quicksave.state"; |
179 } else { | 277 } else { |
180 parts[2] = "quicksave.gst"; | 278 parts[2] = "quicksave.gst"; |
189 persist_save_registered = 1; | 287 persist_save_registered = 1; |
190 } | 288 } |
191 } | 289 } |
192 } | 290 } |
193 | 291 |
292 void apply_updated_config(void) | |
293 { | |
294 render_config_updated(); | |
295 if (current_system && current_system->config_updated) { | |
296 current_system->config_updated(current_system); | |
297 } | |
298 } | |
299 | |
194 static void on_drag_drop(const char *filename) | 300 static void on_drag_drop(const char *filename) |
195 { | 301 { |
196 if (current_system->next_rom) { | 302 if (current_system) { |
197 free(current_system->next_rom); | 303 if (current_system->next_rom) { |
198 } | 304 free(current_system->next_rom); |
199 current_system->next_rom = strdup(filename); | 305 } |
200 current_system->request_exit(current_system); | 306 current_system->next_rom = strdup(filename); |
201 if (menu_system && menu_system->type == SYSTEM_GENESIS) { | 307 current_system->request_exit(current_system); |
202 genesis_context *gen = (genesis_context *)menu_system; | 308 if (menu_system && menu_system->type == SYSTEM_GENESIS) { |
203 if (gen->extra) { | 309 genesis_context *gen = (genesis_context *)menu_system; |
204 menu_context *menu = gen->extra; | 310 if (gen->extra) { |
205 menu->external_game_load = 1; | 311 menu_context *menu = gen->extra; |
206 } else { | 312 menu->external_game_load = 1; |
207 puts("No extra"); | 313 } |
208 } | 314 } |
209 } else { | 315 } else { |
210 puts("no menu"); | 316 init_system_with_media(filename, SYSTEM_UNKNOWN); |
211 } | 317 } |
318 #ifndef DISABLE_NUKLEAR | |
319 if (is_nuklear_active()) { | |
320 show_play_view(); | |
321 } | |
322 #endif | |
212 } | 323 } |
213 | 324 |
214 static system_media cart, lock_on; | 325 static system_media cart, lock_on; |
215 void reload_media(void) | 326 void reload_media(void) |
216 { | 327 { |
328 if (!current_system) { | |
329 return; | |
330 } | |
217 if (current_system->next_rom) { | 331 if (current_system->next_rom) { |
218 free(current_system->next_rom); | 332 free(current_system->next_rom); |
219 } | 333 } |
220 char const *parts[] = { | 334 char const *parts[] = { |
221 cart.dir, PATH_SEP, cart.name, ".", cart.extension | 335 cart.dir, PATH_SEP, cart.name, ".", cart.extension |
237 free(lock_on.name); | 351 free(lock_on.name); |
238 free(lock_on.extension); | 352 free(lock_on.extension); |
239 load_media(lock_on_path, &lock_on, NULL); | 353 load_media(lock_on_path, &lock_on, NULL); |
240 } | 354 } |
241 | 355 |
356 static uint32_t opts = 0; | |
357 static uint8_t force_region = 0; | |
358 void init_system_with_media(const char *path, system_type force_stype) | |
359 { | |
360 if (game_system) { | |
361 game_system->persist_save(game_system); | |
362 //swap to game context arena and mark all allocated pages in it free | |
363 if (current_system == menu_system) { | |
364 current_system->arena = set_current_arena(game_system->arena); | |
365 } | |
366 mark_all_free(); | |
367 game_system->free_context(game_system); | |
368 } else if(current_system) { | |
369 //start a new arena and save old one in suspended system context | |
370 current_system->arena = start_new_arena(); | |
371 } | |
372 free(cart.dir); | |
373 free(cart.name); | |
374 free(cart.extension); | |
375 system_type stype = SYSTEM_UNKNOWN; | |
376 if (!(cart.size = load_media(path, &cart, &stype))) { | |
377 fatal_error("Failed to open %s for reading\n", path); | |
378 } | |
379 | |
380 if (force_stype != SYSTEM_UNKNOWN) { | |
381 stype = force_stype; | |
382 } | |
383 if (stype == SYSTEM_UNKNOWN) { | |
384 stype = detect_system_type(&cart); | |
385 } | |
386 if (stype == SYSTEM_UNKNOWN) { | |
387 fatal_error("Failed to detect system type for %s\n", path); | |
388 } | |
389 //allocate new system context | |
390 game_system = alloc_config_system(stype, &cart, opts, force_region); | |
391 if (!game_system) { | |
392 fatal_error("Failed to configure emulated machine for %s\n", path); | |
393 } | |
394 if (menu_system) { | |
395 menu_system->next_context = game_system; | |
396 } | |
397 game_system->next_context = menu_system; | |
398 setup_saves(&cart, game_system); | |
399 update_title(game_system->info.name); | |
400 } | |
401 | |
242 int main(int argc, char ** argv) | 402 int main(int argc, char ** argv) |
243 { | 403 { |
244 set_exe_str(argv[0]); | 404 set_exe_str(argv[0]); |
245 config = load_config(); | 405 config = load_config(); |
246 int width = -1; | 406 int width = -1; |
247 int height = -1; | 407 int height = -1; |
248 int debug = 0; | 408 int debug = 0; |
249 uint32_t opts = 0; | |
250 int loaded = 0; | 409 int loaded = 0; |
251 system_type stype = SYSTEM_UNKNOWN, force_stype = SYSTEM_UNKNOWN; | 410 system_type stype = SYSTEM_UNKNOWN, force_stype = SYSTEM_UNKNOWN; |
252 uint8_t force_region = 0; | |
253 char * romfname = NULL; | 411 char * romfname = NULL; |
254 char * statefile = NULL; | 412 char * statefile = NULL; |
255 debugger_type dtype = DEBUGGER_NATIVE; | 413 debugger_type dtype = DEBUGGER_NATIVE; |
256 uint8_t start_in_debugger = 0; | 414 uint8_t start_in_debugger = 0; |
257 uint8_t fullscreen = FULLSCREEN_DEFAULT, use_gl = 1; | 415 uint8_t fullscreen = FULLSCREEN_DEFAULT, use_gl = 1; |
378 width = atoi(argv[i]); | 536 width = atoi(argv[i]); |
379 } else if (height < 0) { | 537 } else if (height < 0) { |
380 height = atoi(argv[i]); | 538 height = atoi(argv[i]); |
381 } | 539 } |
382 } | 540 } |
541 | |
542 int def_width = 0, def_height = 0; | |
543 char *config_width = tern_find_path(config, "video\0width\0", TVAL_PTR).ptrval; | |
544 if (config_width) { | |
545 def_width = atoi(config_width); | |
546 } | |
547 if (!def_width) { | |
548 def_width = 640; | |
549 } | |
550 char *config_height = tern_find_path(config, "video\0height\0", TVAL_PTR).ptrval; | |
551 if (config_height) { | |
552 def_height = atoi(config_height); | |
553 } | |
554 if (!def_height) { | |
555 def_height = -1; | |
556 } | |
557 width = width < 1 ? def_width : width; | |
558 height = height < 1 ? def_height : height; | |
559 | |
560 char *config_fullscreen = tern_find_path(config, "video\0fullscreen\0", TVAL_PTR).ptrval; | |
561 if (config_fullscreen && !strcmp("on", config_fullscreen)) { | |
562 fullscreen = !fullscreen; | |
563 } | |
564 if (!headless) { | |
565 render_init(width, height, "BlastEm", fullscreen); | |
566 render_set_drag_drop_handler(on_drag_drop); | |
567 } | |
568 set_bindings(); | |
569 | |
383 uint8_t menu = !loaded; | 570 uint8_t menu = !loaded; |
384 if (!loaded) { | 571 uint8_t use_nuklear = 0; |
572 #ifndef DISABLE_NUKLEAR | |
573 use_nuklear = !headless && is_nuklear_available(); | |
574 #endif | |
575 if (!loaded && !use_nuklear) { | |
385 //load menu | 576 //load menu |
386 romfname = tern_find_path(config, "ui\0rom\0", TVAL_PTR).ptrval; | 577 romfname = tern_find_path(config, "ui\0rom\0", TVAL_PTR).ptrval; |
387 if (!romfname) { | 578 if (!romfname) { |
388 romfname = "menu.bin"; | 579 romfname = "menu.bin"; |
389 } | 580 } |
390 if (is_absolute_path(romfname)) { | 581 if (is_absolute_path(romfname)) { |
391 if (!load_media(romfname, &cart, &stype)) { | 582 if (!(cart.size = load_media(romfname, &cart, &stype))) { |
392 fatal_error("Failed to open UI ROM %s for reading", romfname); | 583 fatal_error("Failed to open UI ROM %s for reading", romfname); |
393 } | 584 } |
394 } else { | 585 } else { |
395 cart.buffer = (uint16_t *)read_bundled_file(romfname, &cart.size); | 586 cart.buffer = (uint16_t *)read_bundled_file(romfname, &cart.size); |
396 if (!cart.buffer) { | 587 if (!cart.buffer) { |
406 cart.extension = path_extension(romfname); | 597 cart.extension = path_extension(romfname); |
407 } | 598 } |
408 //force system detection, value on command line is only for games not the menu | 599 //force system detection, value on command line is only for games not the menu |
409 stype = detect_system_type(&cart); | 600 stype = detect_system_type(&cart); |
410 loaded = 1; | 601 loaded = 1; |
411 } | |
412 | |
413 int def_width = 0, def_height = 0; | |
414 char *config_width = tern_find_path(config, "video\0width\0", TVAL_PTR).ptrval; | |
415 if (config_width) { | |
416 def_width = atoi(config_width); | |
417 } | |
418 if (!def_width) { | |
419 def_width = 640; | |
420 } | |
421 char *config_height = tern_find_path(config, "video\0height\0", TVAL_PTR).ptrval; | |
422 if (config_height) { | |
423 def_height = atoi(config_height); | |
424 } | |
425 if (!def_height) { | |
426 def_height = -1; | |
427 } | |
428 width = width < 1 ? def_width : width; | |
429 height = height < 1 ? def_height : height; | |
430 | |
431 char *config_fullscreen = tern_find_path(config, "video\0fullscreen\0", TVAL_PTR).ptrval; | |
432 if (config_fullscreen && !strcmp("on", config_fullscreen)) { | |
433 fullscreen = !fullscreen; | |
434 } | |
435 if (!headless) { | |
436 render_init(width, height, "BlastEm", fullscreen); | |
437 render_set_drag_drop_handler(on_drag_drop); | |
438 } | |
439 | |
440 if (stype == SYSTEM_UNKNOWN) { | |
441 stype = detect_system_type(&cart); | |
442 } | |
443 if (stype == SYSTEM_UNKNOWN) { | |
444 fatal_error("Failed to detect system type for %s\n", romfname); | |
445 } | |
446 rom_info info; | |
447 current_system = alloc_config_system(stype, &cart, menu ? 0 : opts, force_region, &info); | |
448 if (!current_system) { | |
449 fatal_error("Failed to configure emulated machine for %s\n", romfname); | |
450 } | 602 } |
451 char *state_format = tern_find_path(config, "ui\0state_format\0", TVAL_PTR).ptrval; | 603 char *state_format = tern_find_path(config, "ui\0state_format\0", TVAL_PTR).ptrval; |
452 if (state_format && !strcmp(state_format, "gst")) { | 604 if (state_format && !strcmp(state_format, "gst")) { |
453 use_native_states = 0; | 605 use_native_states = 0; |
454 } else if (state_format && strcmp(state_format, "native")) { | 606 } else if (state_format && strcmp(state_format, "native")) { |
455 warning("%s is not a valid value for the ui.state_format setting. Valid values are gst and native\n", state_format); | 607 warning("%s is not a valid value for the ui.state_format setting. Valid values are gst and native\n", state_format); |
456 } | 608 } |
457 setup_saves(&cart, &info, current_system); | 609 |
458 update_title(info.name); | 610 if (loaded) { |
459 if (menu) { | 611 if (stype == SYSTEM_UNKNOWN) { |
460 menu_system = current_system; | 612 stype = detect_system_type(&cart); |
461 } else { | 613 } |
462 game_system = current_system; | 614 if (stype == SYSTEM_UNKNOWN) { |
463 } | 615 fatal_error("Failed to detect system type for %s\n", romfname); |
464 | 616 } |
617 current_system = alloc_config_system(stype, &cart, menu ? 0 : opts, force_region); | |
618 if (!current_system) { | |
619 fatal_error("Failed to configure emulated machine for %s\n", romfname); | |
620 } | |
621 | |
622 setup_saves(&cart, current_system); | |
623 update_title(current_system->info.name); | |
624 if (menu) { | |
625 menu_system = current_system; | |
626 } else { | |
627 game_system = current_system; | |
628 } | |
629 } | |
630 | |
631 #ifndef DISABLE_NUKLEAR | |
632 if (use_nuklear) { | |
633 blastem_nuklear_init(!menu); | |
634 current_system = game_system; | |
635 menu = 0; | |
636 } | |
637 #endif | |
638 | |
465 current_system->debugger_type = dtype; | 639 current_system->debugger_type = dtype; |
466 current_system->enter_debugger = start_in_debugger && menu == debug_target; | 640 current_system->enter_debugger = start_in_debugger && menu == debug_target; |
467 current_system->start_context(current_system, menu ? NULL : statefile); | 641 current_system->start_context(current_system, menu ? NULL : statefile); |
468 for(;;) | 642 for(;;) |
469 { | 643 { |
471 break; | 645 break; |
472 } | 646 } |
473 if (current_system->next_rom) { | 647 if (current_system->next_rom) { |
474 char *next_rom = current_system->next_rom; | 648 char *next_rom = current_system->next_rom; |
475 current_system->next_rom = NULL; | 649 current_system->next_rom = NULL; |
476 if (game_system) { | 650 init_system_with_media(next_rom, force_stype); |
477 game_system->persist_save(game_system); | |
478 //swap to game context arena and mark all allocated pages in it free | |
479 if (menu) { | |
480 current_system->arena = set_current_arena(game_system->arena); | |
481 } | |
482 mark_all_free(); | |
483 game_system->free_context(game_system); | |
484 } else { | |
485 //start a new arena and save old one in suspended genesis context | |
486 current_system->arena = start_new_arena(); | |
487 } | |
488 free(cart.dir); | |
489 free(cart.name); | |
490 free(cart.extension); | |
491 if (!load_media(next_rom, &cart, &stype)) { | |
492 fatal_error("Failed to open %s for reading\n", next_rom); | |
493 } | |
494 stype = force_stype; | |
495 if (stype == SYSTEM_UNKNOWN) { | |
496 stype = detect_system_type(&cart); | |
497 } | |
498 if (stype == SYSTEM_UNKNOWN) { | |
499 fatal_error("Failed to detect system type for %s\n", next_rom); | |
500 } | |
501 //allocate new system context | |
502 game_system = alloc_config_system(stype, &cart, opts,force_region, &info); | |
503 if (!game_system) { | |
504 fatal_error("Failed to configure emulated machine for %s\n", next_rom); | |
505 } | |
506 if (menu_system) { | |
507 menu_system->next_context = game_system; | |
508 } | |
509 game_system->next_context = menu_system; | |
510 setup_saves(&cart, &info, game_system); | |
511 update_title(info.name); | |
512 free(next_rom); | 651 free(next_rom); |
513 menu = 0; | 652 menu = 0; |
514 current_system = game_system; | 653 current_system = game_system; |
515 current_system->debugger_type = dtype; | 654 current_system->debugger_type = dtype; |
516 current_system->enter_debugger = start_in_debugger && menu == debug_target; | 655 current_system->enter_debugger = start_in_debugger && menu == debug_target; |
518 } else if (menu && game_system) { | 657 } else if (menu && game_system) { |
519 current_system->arena = set_current_arena(game_system->arena); | 658 current_system->arena = set_current_arena(game_system->arena); |
520 current_system = game_system; | 659 current_system = game_system; |
521 menu = 0; | 660 menu = 0; |
522 current_system->resume_context(current_system); | 661 current_system->resume_context(current_system); |
523 } else if (!menu && menu_system) { | 662 } else if (!menu && (menu_system || use_nuklear)) { |
524 current_system->arena = set_current_arena(menu_system->arena); | 663 if (use_nuklear) { |
525 current_system = menu_system; | 664 #ifndef DISABLE_NUKLEAR |
526 menu = 1; | 665 ui_idle_loop(); |
527 current_system->resume_context(current_system); | 666 #endif |
667 } else { | |
668 current_system->arena = set_current_arena(menu_system->arena); | |
669 current_system = menu_system; | |
670 menu = 1; | |
671 } | |
672 if (!current_system->next_rom) { | |
673 current_system->resume_context(current_system); | |
674 } | |
528 } else { | 675 } else { |
529 break; | 676 break; |
530 } | 677 } |
531 } | 678 } |
532 | 679 |