Mercurial > repos > blastem
comparison blastem.c @ 2053:3414a4423de1 segacd
Merge from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 15 Jan 2022 13:15:21 -0800 |
parents | 5dacaef602a7 0f54a898db03 |
children | 6399a776e981 |
comparison
equal
deleted
inserted
replaced
1692:5dacaef602a7 | 2053:3414a4423de1 |
---|---|
9 #include <ctype.h> | 9 #include <ctype.h> |
10 | 10 |
11 #include "system.h" | 11 #include "system.h" |
12 #include "68kinst.h" | 12 #include "68kinst.h" |
13 #include "m68k_core.h" | 13 #include "m68k_core.h" |
14 #ifdef NEW_CORE | |
15 #include "z80.h" | |
16 #else | |
14 #include "z80_to_x86.h" | 17 #include "z80_to_x86.h" |
18 #endif | |
15 #include "mem.h" | 19 #include "mem.h" |
16 #include "vdp.h" | 20 #include "vdp.h" |
17 #include "render.h" | 21 #include "render.h" |
18 #include "genesis.h" | 22 #include "genesis.h" |
19 #include "gdb_remote.h" | 23 #include "gdb_remote.h" |
24 #include "arena.h" | 28 #include "arena.h" |
25 #include "config.h" | 29 #include "config.h" |
26 #include "bindings.h" | 30 #include "bindings.h" |
27 #include "menu.h" | 31 #include "menu.h" |
28 #include "zip.h" | 32 #include "zip.h" |
33 #include "event_log.h" | |
29 #ifndef DISABLE_NUKLEAR | 34 #ifndef DISABLE_NUKLEAR |
30 #include "nuklear_ui/blastem_nuklear.h" | 35 #include "nuklear_ui/blastem_nuklear.h" |
31 #endif | 36 #endif |
32 | 37 |
33 #define BLASTEM_VERSION "0.6.1" | 38 #define BLASTEM_VERSION "0.6.3-pre" |
34 | 39 |
35 #ifdef __ANDROID__ | 40 #ifdef __ANDROID__ |
36 #define FULLSCREEN_DEFAULT 1 | 41 #define FULLSCREEN_DEFAULT 1 |
37 #else | 42 #else |
38 #define FULLSCREEN_DEFAULT 0 | 43 #define FULLSCREEN_DEFAULT 0 |
67 #define romseek gzseek | 72 #define romseek gzseek |
68 #define romgetc gzgetc | 73 #define romgetc gzgetc |
69 #define romclose gzclose | 74 #define romclose gzclose |
70 #endif | 75 #endif |
71 | 76 |
77 uint16_t *process_smd_block(uint16_t *dst, uint8_t *src, size_t bytes) | |
78 { | |
79 for (uint8_t *low = src, *high = (src+bytes/2), *end = src+bytes; high < end; high++, low++) { | |
80 *(dst++) = *low << 8 | *high; | |
81 } | |
82 return dst; | |
83 } | |
84 | |
72 int load_smd_rom(ROMFILE f, void **buffer) | 85 int load_smd_rom(ROMFILE f, void **buffer) |
73 { | 86 { |
74 uint8_t block[SMD_BLOCK_SIZE]; | 87 uint8_t block[SMD_BLOCK_SIZE]; |
75 romseek(f, SMD_HEADER_SIZE, SEEK_SET); | 88 romseek(f, SMD_HEADER_SIZE, SEEK_SET); |
76 | 89 |
77 size_t filesize = 512 * 1024; | 90 size_t filesize = 512 * 1024; |
78 size_t readsize = 0; | 91 size_t readsize = 0; |
79 uint16_t *dst = malloc(filesize); | 92 uint16_t *dst, *buf; |
80 | 93 dst = buf = malloc(filesize); |
94 | |
81 | 95 |
82 size_t read; | 96 size_t read; |
83 do { | 97 do { |
84 if ((readsize + SMD_BLOCK_SIZE > filesize)) { | 98 if ((readsize + SMD_BLOCK_SIZE > filesize)) { |
85 filesize *= 2; | 99 filesize *= 2; |
86 dst = realloc(dst, filesize); | 100 buf = realloc(buf, filesize); |
101 dst = buf + readsize/sizeof(uint16_t); | |
87 } | 102 } |
88 read = romread(block, 1, SMD_BLOCK_SIZE, f); | 103 read = romread(block, 1, SMD_BLOCK_SIZE, f); |
89 if (read > 0) { | 104 if (read > 0) { |
90 for (uint8_t *low = block, *high = (block+read/2), *end = block+read; high < end; high++, low++) { | 105 dst = process_smd_block(dst, block, read); |
91 *(dst++) = *low << 8 | *high; | |
92 } | |
93 readsize += read; | 106 readsize += read; |
94 } | 107 } |
95 } while(read > 0); | 108 } while(read > 0); |
96 romclose(f); | 109 romclose(f); |
97 | 110 |
98 *buffer = dst; | 111 *buffer = buf; |
99 | 112 |
100 return readsize; | 113 return readsize; |
101 } | 114 } |
102 | 115 |
116 uint8_t is_smd_format(const char *filename, uint8_t *header) | |
117 { | |
118 if (header[1] == SMD_MAGIC1 && header[8] == SMD_MAGIC2 && header[9] == SMD_MAGIC3) { | |
119 int i; | |
120 for (i = 3; i < 8; i++) { | |
121 if (header[i] != 0) { | |
122 return 0; | |
123 } | |
124 } | |
125 if (i == 8) { | |
126 if (header[2]) { | |
127 fatal_error("%s is a split SMD ROM which is not currently supported", filename); | |
128 } | |
129 return 1; | |
130 } | |
131 } | |
132 return 0; | |
133 } | |
134 | |
103 uint32_t load_media_zip(const char *filename, system_media *dst) | 135 uint32_t load_media_zip(const char *filename, system_media *dst) |
104 { | 136 { |
105 static const char *valid_exts[] = {"bin", "md", "gen", "sms", "rom"}; | 137 static const char *valid_exts[] = {"bin", "md", "gen", "sms", "rom", "smd"}; |
106 const uint32_t num_exts = sizeof(valid_exts)/sizeof(*valid_exts); | 138 const uint32_t num_exts = sizeof(valid_exts)/sizeof(*valid_exts); |
107 zip_file *z = zip_open(filename); | 139 zip_file *z = zip_open(filename); |
108 if (!z) { | 140 if (!z) { |
109 return 0; | 141 return 0; |
110 } | 142 } |
111 | 143 |
112 for (uint32_t i = 0; i < z->num_entries; i++) | 144 for (uint32_t i = 0; i < z->num_entries; i++) |
113 { | 145 { |
114 char *ext = path_extension(z->entries[i].name); | 146 char *ext = path_extension(z->entries[i].name); |
115 if (!ext) { | 147 if (!ext) { |
116 continue; | 148 continue; |
119 { | 151 { |
120 if (!strcasecmp(ext, valid_exts[j])) { | 152 if (!strcasecmp(ext, valid_exts[j])) { |
121 size_t out_size = nearest_pow2(z->entries[i].size); | 153 size_t out_size = nearest_pow2(z->entries[i].size); |
122 dst->buffer = zip_read(z, i, &out_size); | 154 dst->buffer = zip_read(z, i, &out_size); |
123 if (dst->buffer) { | 155 if (dst->buffer) { |
156 if (is_smd_format(z->entries[i].name, dst->buffer)) { | |
157 size_t offset; | |
158 for (offset = 0; offset + SMD_BLOCK_SIZE + SMD_HEADER_SIZE <= out_size; offset += SMD_BLOCK_SIZE) | |
159 { | |
160 uint8_t tmp[SMD_BLOCK_SIZE]; | |
161 uint8_t *u8dst = dst->buffer; | |
162 memcpy(tmp, u8dst + offset + SMD_HEADER_SIZE, SMD_BLOCK_SIZE); | |
163 process_smd_block((void *)(u8dst + offset), tmp, SMD_BLOCK_SIZE); | |
164 } | |
165 out_size = offset; | |
166 } | |
124 dst->extension = ext; | 167 dst->extension = ext; |
125 dst->dir = path_dirname(filename); | 168 dst->dir = path_dirname(filename); |
126 dst->name = basename_no_extension(filename); | 169 dst->name = basename_no_extension(filename); |
127 dst->size = out_size; | 170 dst->size = out_size; |
128 zip_close(z); | 171 zip_close(z); |
150 return 0; | 193 return 0; |
151 } | 194 } |
152 if (sizeof(header) != romread(header, 1, sizeof(header), f)) { | 195 if (sizeof(header) != romread(header, 1, sizeof(header), f)) { |
153 fatal_error("Error reading from %s\n", filename); | 196 fatal_error("Error reading from %s\n", filename); |
154 } | 197 } |
155 | 198 |
156 uint32_t ret = 0; | 199 uint32_t ret = 0; |
157 if (header[1] == SMD_MAGIC1 && header[8] == SMD_MAGIC2 && header[9] == SMD_MAGIC3) { | 200 if (is_smd_format(filename, header)) { |
158 int i; | |
159 for (i = 3; i < 8; i++) { | |
160 if (header[i] != 0) { | |
161 break; | |
162 } | |
163 } | |
164 if (i == 8) { | |
165 if (header[2]) { | |
166 fatal_error("%s is a split SMD ROM which is not currently supported", filename); | |
167 } | |
168 if (stype) { | 201 if (stype) { |
169 *stype = SYSTEM_GENESIS; | 202 *stype = SYSTEM_GENESIS; |
170 } | 203 } |
171 ret = load_smd_rom(f, &dst->buffer); | 204 ret = load_smd_rom(f, &dst->buffer); |
172 } | 205 } |
173 } | 206 |
174 | |
175 if (!ret) { | 207 if (!ret) { |
176 size_t filesize = 512 * 1024; | 208 size_t filesize = 512 * 1024; |
177 size_t readsize = sizeof(header); | 209 size_t readsize = sizeof(header); |
178 | 210 |
179 char *buf = malloc(filesize); | 211 char *buf = malloc(filesize); |
180 memcpy(buf, header, readsize); | 212 memcpy(buf, header, readsize); |
181 | 213 |
182 size_t read; | 214 size_t read; |
183 do { | 215 do { |
184 read = romread(buf + readsize, 1, filesize - readsize, f); | 216 read = romread(buf + readsize, 1, filesize - readsize, f); |
185 if (read > 0) { | 217 if (read > 0) { |
186 readsize += read; | 218 readsize += read; |
201 } | 233 } |
202 dst->dir = path_dirname(filename); | 234 dst->dir = path_dirname(filename); |
203 dst->name = basename_no_extension(filename); | 235 dst->name = basename_no_extension(filename); |
204 dst->extension = path_extension(filename); | 236 dst->extension = path_extension(filename); |
205 dst->size = ret; | 237 dst->size = ret; |
206 | 238 |
207 romclose(f); | 239 romclose(f); |
208 return ret; | 240 return ret; |
209 } | 241 } |
210 | 242 |
211 | 243 |
245 char *savedir_template = tern_find_path(config, "ui\0save_path\0", TVAL_PTR).ptrval; | 277 char *savedir_template = tern_find_path(config, "ui\0save_path\0", TVAL_PTR).ptrval; |
246 if (!savedir_template) { | 278 if (!savedir_template) { |
247 savedir_template = "$USERDATA/blastem/$ROMNAME"; | 279 savedir_template = "$USERDATA/blastem/$ROMNAME"; |
248 } | 280 } |
249 tern_node *vars = tern_insert_ptr(NULL, "ROMNAME", media->name); | 281 tern_node *vars = tern_insert_ptr(NULL, "ROMNAME", media->name); |
282 vars = tern_insert_ptr(vars, "ROMDIR", media->dir); | |
250 vars = tern_insert_ptr(vars, "HOME", get_home_dir()); | 283 vars = tern_insert_ptr(vars, "HOME", get_home_dir()); |
251 vars = tern_insert_ptr(vars, "EXEDIR", get_exe_dir()); | 284 vars = tern_insert_ptr(vars, "EXEDIR", get_exe_dir()); |
252 vars = tern_insert_ptr(vars, "USERDATA", (char *)get_userdata_dir()); | 285 vars = tern_insert_ptr(vars, "USERDATA", (char *)get_userdata_dir()); |
253 char *save_dir = replace_vars(savedir_template, vars, 1); | 286 char *save_dir = replace_vars(savedir_template, vars, 1); |
254 tern_free(vars); | 287 tern_free(vars); |
256 warning("Failed to create save directory %s\n", save_dir); | 289 warning("Failed to create save directory %s\n", save_dir); |
257 } | 290 } |
258 return save_dir; | 291 return save_dir; |
259 } | 292 } |
260 | 293 |
294 const char *get_save_fname(uint8_t save_type) | |
295 { | |
296 switch(save_type) | |
297 { | |
298 case SAVE_I2C: return "save.eeprom"; | |
299 case SAVE_NOR: return "save.nor"; | |
300 case SAVE_HBPT: return "save.hbpt"; | |
301 default: return "save.sram"; | |
302 } | |
303 } | |
304 | |
261 void setup_saves(system_media *media, system_header *context) | 305 void setup_saves(system_media *media, system_header *context) |
262 { | 306 { |
263 static uint8_t persist_save_registered; | 307 static uint8_t persist_save_registered; |
264 rom_info *info = &context->info; | 308 rom_info *info = &context->info; |
265 char *save_dir = get_save_dir(info->is_save_lock_on ? media->chain : media); | 309 char *save_dir = get_save_dir(info->is_save_lock_on ? media->chain : media); |
266 char const *parts[] = {save_dir, PATH_SEP, info->save_type == SAVE_I2C ? "save.eeprom" : info->save_type == SAVE_NOR ? "save.nor" : "save.sram"}; | 310 char const *parts[] = {save_dir, PATH_SEP, get_save_fname(info->save_type)}; |
267 free(save_filename); | 311 free(save_filename); |
268 save_filename = alloc_concat_m(3, parts); | 312 save_filename = alloc_concat_m(3, parts); |
269 if (info->is_save_lock_on) { | 313 if (info->is_save_lock_on) { |
270 //initial save dir was calculated based on lock-on cartridge because that's where the save device is | 314 //initial save dir was calculated based on lock-on cartridge because that's where the save device is |
271 //save directory used for save states should still be located in the normal place | 315 //save directory used for save states should still be located in the normal place |
302 if (current_system) { | 346 if (current_system) { |
303 if (current_system->next_rom) { | 347 if (current_system->next_rom) { |
304 free(current_system->next_rom); | 348 free(current_system->next_rom); |
305 } | 349 } |
306 current_system->next_rom = strdup(filename); | 350 current_system->next_rom = strdup(filename); |
307 current_system->request_exit(current_system); | 351 system_request_exit(current_system, 1); |
308 if (menu_system && menu_system->type == SYSTEM_GENESIS) { | 352 if (menu_system && menu_system->type == SYSTEM_GENESIS) { |
309 genesis_context *gen = (genesis_context *)menu_system; | 353 genesis_context *gen = (genesis_context *)menu_system; |
310 if (gen->extra) { | 354 if (gen->extra) { |
311 menu_context *menu = gen->extra; | 355 menu_context *menu = gen->extra; |
312 menu->external_game_load = 1; | 356 menu->external_game_load = 1; |
321 } | 365 } |
322 #endif | 366 #endif |
323 } | 367 } |
324 | 368 |
325 static system_media cart, lock_on; | 369 static system_media cart, lock_on; |
370 const system_media *current_media(void) | |
371 { | |
372 return &cart; | |
373 } | |
374 | |
326 void reload_media(void) | 375 void reload_media(void) |
327 { | 376 { |
328 if (!current_system) { | 377 if (!current_system) { |
329 return; | 378 return; |
330 } | 379 } |
338 int num_parts = parts[0] ? 5 : 3; | 387 int num_parts = parts[0] ? 5 : 3; |
339 if (!parts[4]) { | 388 if (!parts[4]) { |
340 num_parts--; | 389 num_parts--; |
341 } | 390 } |
342 current_system->next_rom = alloc_concat_m(num_parts, start); | 391 current_system->next_rom = alloc_concat_m(num_parts, start); |
343 current_system->request_exit(current_system); | 392 system_request_exit(current_system, 1); |
344 } | 393 } |
345 | 394 |
346 void lockon_media(char *lock_on_path) | 395 void lockon_media(char *lock_on_path) |
347 { | 396 { |
348 reload_media(); | 397 reload_media(); |
374 free(cart.extension); | 423 free(cart.extension); |
375 system_type stype = SYSTEM_UNKNOWN; | 424 system_type stype = SYSTEM_UNKNOWN; |
376 if (!(cart.size = load_media(path, &cart, &stype))) { | 425 if (!(cart.size = load_media(path, &cart, &stype))) { |
377 fatal_error("Failed to open %s for reading\n", path); | 426 fatal_error("Failed to open %s for reading\n", path); |
378 } | 427 } |
379 | 428 |
380 if (force_stype != SYSTEM_UNKNOWN) { | 429 if (force_stype != SYSTEM_UNKNOWN) { |
381 stype = force_stype; | 430 stype = force_stype; |
382 } | 431 } |
383 if (stype == SYSTEM_UNKNOWN) { | 432 if (stype == SYSTEM_UNKNOWN) { |
384 stype = detect_system_type(&cart); | 433 stype = detect_system_type(&cart); |
395 menu_system->next_context = game_system; | 444 menu_system->next_context = game_system; |
396 } | 445 } |
397 game_system->next_context = menu_system; | 446 game_system->next_context = menu_system; |
398 setup_saves(&cart, game_system); | 447 setup_saves(&cart, game_system); |
399 update_title(game_system->info.name); | 448 update_title(game_system->info.name); |
449 } | |
450 | |
451 char *parse_addr_port(char *arg) | |
452 { | |
453 while (*arg && *arg != ':') { | |
454 ++arg; | |
455 } | |
456 if (!*arg) { | |
457 return NULL; | |
458 } | |
459 char *end; | |
460 int port = strtol(arg + 1, &end, 10); | |
461 if (port && !*end) { | |
462 *arg = 0; | |
463 return arg + 1; | |
464 } | |
465 return NULL; | |
400 } | 466 } |
401 | 467 |
402 int main(int argc, char ** argv) | 468 int main(int argc, char ** argv) |
403 { | 469 { |
404 set_exe_str(argv[0]); | 470 set_exe_str(argv[0]); |
408 int debug = 0; | 474 int debug = 0; |
409 int loaded = 0; | 475 int loaded = 0; |
410 system_type stype = SYSTEM_UNKNOWN, force_stype = SYSTEM_UNKNOWN; | 476 system_type stype = SYSTEM_UNKNOWN, force_stype = SYSTEM_UNKNOWN; |
411 char * romfname = NULL; | 477 char * romfname = NULL; |
412 char * statefile = NULL; | 478 char * statefile = NULL; |
479 char *reader_addr = NULL, *reader_port = NULL; | |
480 event_reader reader = {0}; | |
413 debugger_type dtype = DEBUGGER_NATIVE; | 481 debugger_type dtype = DEBUGGER_NATIVE; |
414 uint8_t start_in_debugger = 0; | 482 uint8_t start_in_debugger = 0; |
415 uint8_t fullscreen = FULLSCREEN_DEFAULT, use_gl = 1; | 483 uint8_t fullscreen = FULLSCREEN_DEFAULT, use_gl = 1; |
416 uint8_t debug_target = 0; | 484 uint8_t debug_target = 0; |
485 char *port; | |
417 for (int i = 1; i < argc; i++) { | 486 for (int i = 1; i < argc; i++) { |
418 if (argv[i][0] == '-') { | 487 if (argv[i][0] == '-') { |
419 switch(argv[i][1]) { | 488 switch(argv[i][1]) { |
420 case 'b': | 489 case 'b': |
421 i++; | 490 i++; |
434 break; | 503 break; |
435 case 'D': | 504 case 'D': |
436 gdb_remote_init(); | 505 gdb_remote_init(); |
437 dtype = DEBUGGER_GDB; | 506 dtype = DEBUGGER_GDB; |
438 start_in_debugger = 1; | 507 start_in_debugger = 1; |
508 break; | |
509 case 'e': | |
510 i++; | |
511 if (i >= argc) { | |
512 fatal_error("-e must be followed by a file name\n"); | |
513 } | |
514 port = parse_addr_port(argv[i]); | |
515 if (port) { | |
516 event_log_tcp(argv[i], port); | |
517 } else { | |
518 event_log_file(argv[i]); | |
519 } | |
439 break; | 520 break; |
440 case 'f': | 521 case 'f': |
441 fullscreen = !fullscreen; | 522 fullscreen = !fullscreen; |
442 break; | 523 break; |
443 case 'g': | 524 case 'g': |
519 " -d Enter debugger on startup\n" | 600 " -d Enter debugger on startup\n" |
520 " -n Disable Z80\n" | 601 " -n Disable Z80\n" |
521 " -v Display version number and exit\n" | 602 " -v Display version number and exit\n" |
522 " -l Log 68K code addresses (useful for assemblers)\n" | 603 " -l Log 68K code addresses (useful for assemblers)\n" |
523 " -y Log individual YM-2612 channels to WAVE files\n" | 604 " -y Log individual YM-2612 channels to WAVE files\n" |
605 " -e FILE Write hardware event log to FILE\n" | |
524 ); | 606 ); |
525 return 0; | 607 return 0; |
526 default: | 608 default: |
527 fatal_error("Unrecognized switch %s\n", argv[i]); | 609 fatal_error("Unrecognized switch %s\n", argv[i]); |
528 } | 610 } |
529 } else if (!loaded) { | 611 } else if (!loaded) { |
612 reader_port = parse_addr_port(argv[i]); | |
613 if (reader_port) { | |
614 reader_addr = argv[i]; | |
615 } else { | |
530 if (!load_media(argv[i], &cart, stype == SYSTEM_UNKNOWN ? &stype : NULL)) { | 616 if (!load_media(argv[i], &cart, stype == SYSTEM_UNKNOWN ? &stype : NULL)) { |
531 fatal_error("Failed to open %s for reading\n", argv[i]); | 617 fatal_error("Failed to open %s for reading\n", argv[i]); |
618 } | |
532 } | 619 } |
533 romfname = argv[i]; | 620 romfname = argv[i]; |
534 loaded = 1; | 621 loaded = 1; |
535 } else if (width < 0) { | 622 } else if (width < 0) { |
536 width = atoi(argv[i]); | 623 width = atoi(argv[i]); |
537 } else if (height < 0) { | 624 } else if (height < 0) { |
538 height = atoi(argv[i]); | 625 height = atoi(argv[i]); |
539 } | 626 } |
540 } | 627 } |
541 | 628 |
542 int def_width = 0, def_height = 0; | 629 int def_width = 0, def_height = 0; |
543 char *config_width = tern_find_path(config, "video\0width\0", TVAL_PTR).ptrval; | 630 char *config_width = tern_find_path(config, "video\0width\0", TVAL_PTR).ptrval; |
544 if (config_width) { | 631 if (config_width) { |
545 def_width = atoi(config_width); | 632 def_width = atoi(config_width); |
546 } | 633 } |
560 char *config_fullscreen = tern_find_path(config, "video\0fullscreen\0", TVAL_PTR).ptrval; | 647 char *config_fullscreen = tern_find_path(config, "video\0fullscreen\0", TVAL_PTR).ptrval; |
561 if (config_fullscreen && !strcmp("on", config_fullscreen)) { | 648 if (config_fullscreen && !strcmp("on", config_fullscreen)) { |
562 fullscreen = !fullscreen; | 649 fullscreen = !fullscreen; |
563 } | 650 } |
564 if (!headless) { | 651 if (!headless) { |
652 if (reader_addr) { | |
653 render_set_external_sync(1); | |
654 } | |
565 render_init(width, height, "BlastEm", fullscreen); | 655 render_init(width, height, "BlastEm", fullscreen); |
566 render_set_drag_drop_handler(on_drag_drop); | 656 render_set_drag_drop_handler(on_drag_drop); |
567 } | 657 } |
568 set_bindings(); | 658 set_bindings(); |
569 | 659 |
570 uint8_t menu = !loaded; | 660 uint8_t menu = !loaded; |
571 uint8_t use_nuklear = 0; | 661 uint8_t use_nuklear = 0; |
572 #ifndef DISABLE_NUKLEAR | 662 #ifndef DISABLE_NUKLEAR |
573 use_nuklear = !headless && is_nuklear_available(); | 663 use_nuklear = !headless && is_nuklear_available(); |
574 #endif | 664 #endif |
605 use_native_states = 0; | 695 use_native_states = 0; |
606 } else if (state_format && strcmp(state_format, "native")) { | 696 } else if (state_format && strcmp(state_format, "native")) { |
607 warning("%s is not a valid value for the ui.state_format setting. Valid values are gst and native\n", state_format); | 697 warning("%s is not a valid value for the ui.state_format setting. Valid values are gst and native\n", state_format); |
608 } | 698 } |
609 | 699 |
610 if (loaded) { | 700 if (loaded && !reader_addr) { |
611 if (stype == SYSTEM_UNKNOWN) { | 701 if (stype == SYSTEM_UNKNOWN) { |
612 stype = detect_system_type(&cart); | 702 stype = detect_system_type(&cart); |
613 } | 703 } |
614 if (stype == SYSTEM_UNKNOWN) { | 704 if (stype == SYSTEM_UNKNOWN) { |
615 fatal_error("Failed to detect system type for %s\n", romfname); | 705 fatal_error("Failed to detect system type for %s\n", romfname); |
616 } | 706 } |
707 | |
617 current_system = alloc_config_system(stype, &cart, menu ? 0 : opts, force_region); | 708 current_system = alloc_config_system(stype, &cart, menu ? 0 : opts, force_region); |
618 if (!current_system) { | 709 if (!current_system) { |
619 fatal_error("Failed to configure emulated machine for %s\n", romfname); | 710 fatal_error("Failed to configure emulated machine for %s\n", romfname); |
620 } | 711 } |
621 | 712 |
622 setup_saves(&cart, current_system); | 713 setup_saves(&cart, current_system); |
623 update_title(current_system->info.name); | 714 update_title(current_system->info.name); |
624 if (menu) { | 715 if (menu) { |
625 menu_system = current_system; | 716 menu_system = current_system; |
626 } else { | 717 } else { |
627 game_system = current_system; | 718 game_system = current_system; |
628 } | 719 } |
629 } | 720 } |
630 | 721 |
631 #ifndef DISABLE_NUKLEAR | 722 #ifndef DISABLE_NUKLEAR |
632 if (use_nuklear) { | 723 if (use_nuklear) { |
633 blastem_nuklear_init(!menu); | 724 blastem_nuklear_init(!menu); |
634 current_system = game_system; | 725 current_system = game_system; |
635 menu = 0; | 726 menu = 0; |
636 } | 727 } |
637 #endif | 728 #endif |
638 | 729 |
730 if (reader_addr) { | |
731 init_event_reader_tcp(&reader, reader_addr, reader_port); | |
732 stype = reader_system_type(&reader); | |
733 if (stype == SYSTEM_UNKNOWN) { | |
734 fatal_error("Failed to detect system type for %s\n", romfname); | |
735 } | |
736 game_system = current_system = alloc_config_player(stype, &reader); | |
737 //free inflate stream as it was inflateCopied to an internal event reader in the player | |
738 inflateEnd(&reader.input_stream); | |
739 setup_saves(&cart, current_system); | |
740 update_title(current_system->info.name); | |
741 } | |
742 | |
639 current_system->debugger_type = dtype; | 743 current_system->debugger_type = dtype; |
640 current_system->enter_debugger = start_in_debugger && menu == debug_target; | 744 current_system->enter_debugger = start_in_debugger && menu == debug_target; |
641 current_system->start_context(current_system, menu ? NULL : statefile); | 745 current_system->start_context(current_system, menu ? NULL : statefile); |
746 render_video_loop(); | |
642 for(;;) | 747 for(;;) |
643 { | 748 { |
644 if (current_system->should_exit) { | 749 if (current_system->should_exit) { |
645 break; | 750 break; |
646 } | 751 } |
652 menu = 0; | 757 menu = 0; |
653 current_system = game_system; | 758 current_system = game_system; |
654 current_system->debugger_type = dtype; | 759 current_system->debugger_type = dtype; |
655 current_system->enter_debugger = start_in_debugger && menu == debug_target; | 760 current_system->enter_debugger = start_in_debugger && menu == debug_target; |
656 current_system->start_context(current_system, statefile); | 761 current_system->start_context(current_system, statefile); |
762 render_video_loop(); | |
657 } else if (menu && game_system) { | 763 } else if (menu && game_system) { |
658 current_system->arena = set_current_arena(game_system->arena); | 764 current_system->arena = set_current_arena(game_system->arena); |
659 current_system = game_system; | 765 current_system = game_system; |
660 menu = 0; | 766 menu = 0; |
661 current_system->resume_context(current_system); | 767 current_system->resume_context(current_system); |
669 current_system = menu_system; | 775 current_system = menu_system; |
670 menu = 1; | 776 menu = 1; |
671 } | 777 } |
672 if (!current_system->next_rom) { | 778 if (!current_system->next_rom) { |
673 current_system->resume_context(current_system); | 779 current_system->resume_context(current_system); |
780 render_video_loop(); | |
674 } | 781 } |
675 } else { | 782 } else { |
676 break; | 783 break; |
677 } | 784 } |
678 } | 785 } |