comparison blastem.c @ 792:724bbec47f86

Use a new fatal_error function instead of calling fprintf and exit for fatal errors. This new function more gracefully handles the case in which BlastEm was not started from a terminal or disconnected from ther terminal (Windows).
author Michael Pavone <pavone@retrodev.com>
date Sat, 25 Jul 2015 18:22:07 -0700
parents 283bdcd5bdb8
children 092524bb2e8f
comparison
equal deleted inserted replaced
791:60686f8d5e48 792:724bbec47f86
89 FILE * f = fopen(filename, "rb"); 89 FILE * f = fopen(filename, "rb");
90 if (!f) { 90 if (!f) {
91 return 0; 91 return 0;
92 } 92 }
93 if (sizeof(header) != fread(header, 1, sizeof(header), f)) { 93 if (sizeof(header) != fread(header, 1, sizeof(header), f)) {
94 fprintf(stderr, "Error reading from %s\n", filename); 94 fatal_error("Error reading from %s\n", filename);
95 exit(1);
96 } 95 }
97 fseek(f, 0, SEEK_END); 96 fseek(f, 0, SEEK_END);
98 long filesize = ftell(f); 97 long filesize = ftell(f);
99 fseek(f, 0, SEEK_SET); 98 fseek(f, 0, SEEK_SET);
100 if (header[1] == SMD_MAGIC1 && header[8] == SMD_MAGIC2 && header[9] == SMD_MAGIC3) { 99 if (header[1] == SMD_MAGIC1 && header[8] == SMD_MAGIC2 && header[9] == SMD_MAGIC3) {
104 break; 103 break;
105 } 104 }
106 } 105 }
107 if (i == 8) { 106 if (i == 8) {
108 if (header[2]) { 107 if (header[2]) {
109 fprintf(stderr, "%s is a split SMD ROM which is not currently supported", filename); 108 fatal_error("%s is a split SMD ROM which is not currently supported", filename);
110 exit(1);
111 } 109 }
112 return load_smd_rom(filesize, f); 110 return load_smd_rom(filesize, f);
113 } 111 }
114 } 112 }
115 cart = malloc(nearest_pow2(filesize)); 113 cart = malloc(nearest_pow2(filesize));
116 if (filesize != fread(cart, 1, filesize, f)) { 114 if (filesize != fread(cart, 1, filesize, f)) {
117 fprintf(stderr, "Error reading from %s\n", filename); 115 fatal_error("Error reading from %s\n", filename);
118 exit(1);
119 } 116 }
120 fclose(f); 117 fclose(f);
121 return filesize; 118 return filesize;
122 } 119 }
123 120
287 } 284 }
288 285
289 m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_t value) 286 m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_t value)
290 { 287 {
291 if (vdp_port & 0x2700E0) { 288 if (vdp_port & 0x2700E0) {
292 printf("machine freeze due to write to address %X\n", 0xC00000 | vdp_port); 289 fatal_error("machine freeze due to write to address %X\n", 0xC00000 | vdp_port);
293 exit(1);
294 } 290 }
295 vdp_port &= 0x1F; 291 vdp_port &= 0x1F;
296 //printf("vdp_port write: %X, value: %X, cycle: %d\n", vdp_port, value, context->current_cycle); 292 //printf("vdp_port write: %X, value: %X, cycle: %d\n", vdp_port, value, context->current_cycle);
297 sync_components(context, 0); 293 sync_components(context, 0);
298 vdp_context * v_context = context->video_context; 294 vdp_context * v_context = context->video_context;
337 context->sync_cycle = gen->frame_end = vdp_cycles_to_frame_end(v_context); 333 context->sync_cycle = gen->frame_end = vdp_cycles_to_frame_end(v_context);
338 //printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot); 334 //printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot);
339 adjust_int_cycle(context, v_context); 335 adjust_int_cycle(context, v_context);
340 } 336 }
341 } else { 337 } else {
342 printf("Illegal write to HV Counter port %X\n", vdp_port); 338 fatal_error("Illegal write to HV Counter port %X\n", vdp_port);
343 exit(1);
344 } 339 }
345 if (v_context->cycles != before_cycle) { 340 if (v_context->cycles != before_cycle) {
346 //printf("68K paused for %d (%d) cycles at cycle %d (%d) for write\n", v_context->cycles - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle); 341 //printf("68K paused for %d (%d) cycles at cycle %d (%d) for write\n", v_context->cycles - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle);
347 context->current_cycle = v_context->cycles; 342 context->current_cycle = v_context->cycles;
348 //Lock the Z80 out of the bus until the VDP access is complete 343 //Lock the Z80 out of the bus until the VDP access is complete
367 { 362 {
368 z80_context * context = vcontext; 363 z80_context * context = vcontext;
369 genesis_context * gen = context->system; 364 genesis_context * gen = context->system;
370 vdp_port &= 0xFF; 365 vdp_port &= 0xFF;
371 if (vdp_port & 0xE0) { 366 if (vdp_port & 0xE0) {
372 printf("machine freeze due to write to Z80 address %X\n", 0x7F00 | vdp_port); 367 fatal_error("machine freeze due to write to Z80 address %X\n", 0x7F00 | vdp_port);
373 exit(1);
374 } 368 }
375 if (vdp_port < 0x10) { 369 if (vdp_port < 0x10) {
376 //These probably won't currently interact well with the 68K accessing the VDP 370 //These probably won't currently interact well with the 68K accessing the VDP
377 vdp_run_context(gen->vdp, context->current_cycle); 371 vdp_run_context(gen->vdp, context->current_cycle);
378 if (vdp_port < 4) { 372 if (vdp_port < 4) {
379 vdp_data_port_write(gen->vdp, value << 8 | value); 373 vdp_data_port_write(gen->vdp, value << 8 | value);
380 } else if (vdp_port < 8) { 374 } else if (vdp_port < 8) {
381 vdp_control_port_write(gen->vdp, value << 8 | value); 375 vdp_control_port_write(gen->vdp, value << 8 | value);
382 } else { 376 } else {
383 printf("Illegal write to HV Counter port %X\n", vdp_port); 377 fatal_error("Illegal write to HV Counter port %X\n", vdp_port);
384 exit(1);
385 } 378 }
386 } else if (vdp_port < 0x18) { 379 } else if (vdp_port < 0x18) {
387 sync_sound(gen, context->current_cycle); 380 sync_sound(gen, context->current_cycle);
388 psg_write(gen->psg, value); 381 psg_write(gen->psg, value);
389 } else { 382 } else {
393 } 386 }
394 387
395 uint16_t vdp_port_read(uint32_t vdp_port, m68k_context * context) 388 uint16_t vdp_port_read(uint32_t vdp_port, m68k_context * context)
396 { 389 {
397 if (vdp_port & 0x2700E0) { 390 if (vdp_port & 0x2700E0) {
398 printf("machine freeze due to read from address %X\n", 0xC00000 | vdp_port); 391 fatal_error("machine freeze due to read from address %X\n", 0xC00000 | vdp_port);
399 exit(1);
400 } 392 }
401 vdp_port &= 0x1F; 393 vdp_port &= 0x1F;
402 uint16_t value; 394 uint16_t value;
403 sync_components(context, 0); 395 sync_components(context, 0);
404 vdp_context * v_context = context->video_context; 396 vdp_context * v_context = context->video_context;
411 } else { 403 } else {
412 value = vdp_hv_counter_read(v_context); 404 value = vdp_hv_counter_read(v_context);
413 //printf("HV Counter: %X at cycle %d\n", value, v_context->cycles); 405 //printf("HV Counter: %X at cycle %d\n", value, v_context->cycles);
414 } 406 }
415 } else if (vdp_port < 0x18){ 407 } else if (vdp_port < 0x18){
416 printf("Illegal read from PSG port %X\n", vdp_port); 408 fatal_error("Illegal read from PSG port %X\n", vdp_port);
417 exit(1);
418 } else { 409 } else {
419 value = vdp_test_port_read(v_context); 410 value = vdp_test_port_read(v_context);
420 } 411 }
421 if (v_context->cycles != before_cycle) { 412 if (v_context->cycles != before_cycle) {
422 //printf("68K paused for %d (%d) cycles at cycle %d (%d) for read\n", v_context->cycles - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle); 413 //printf("68K paused for %d (%d) cycles at cycle %d (%d) for read\n", v_context->cycles - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle);
442 433
443 uint8_t z80_vdp_port_read(uint32_t vdp_port, void * vcontext) 434 uint8_t z80_vdp_port_read(uint32_t vdp_port, void * vcontext)
444 { 435 {
445 z80_context * context = vcontext; 436 z80_context * context = vcontext;
446 if (vdp_port & 0xE0) { 437 if (vdp_port & 0xE0) {
447 printf("machine freeze due to read from Z80 address %X\n", 0x7F00 | vdp_port); 438 fatal_error("machine freeze due to read from Z80 address %X\n", 0x7F00 | vdp_port);
448 exit(1);
449 } 439 }
450 genesis_context * gen = context->system; 440 genesis_context * gen = context->system;
451 //VDP access goes over the 68K bus like a bank area access 441 //VDP access goes over the 68K bus like a bank area access
452 //typical delay from bus arbitration 442 //typical delay from bus arbitration
453 context->current_cycle += 3 * MCLKS_PER_Z80; 443 context->current_cycle += 3 * MCLKS_PER_Z80;
465 if (vdp_port < 4) { 455 if (vdp_port < 4) {
466 ret = vdp_data_port_read(gen->vdp); 456 ret = vdp_data_port_read(gen->vdp);
467 } else if (vdp_port < 8) { 457 } else if (vdp_port < 8) {
468 ret = vdp_control_port_read(gen->vdp); 458 ret = vdp_control_port_read(gen->vdp);
469 } else { 459 } else {
470 printf("Illegal write to HV Counter port %X\n", vdp_port); 460 fatal_error("Illegal write to HV Counter port %X\n", vdp_port);
471 exit(1);
472 } 461 }
473 } else { 462 } else {
474 //TODO: Figure out the correct value today 463 //TODO: Figure out the correct value today
475 ret = 0xFFFF; 464 ret = 0xFFFF;
476 } 465 }
505 gen->z80->mem_pointers[1] = (gen->z80->bank_reg << 15) + ((char *)gen->z80->mem_pointers[2]); 494 gen->z80->mem_pointers[1] = (gen->z80->bank_reg << 15) + ((char *)gen->z80->mem_pointers[2]);
506 } else { 495 } else {
507 gen->z80->mem_pointers[1] = NULL; 496 gen->z80->mem_pointers[1] = NULL;
508 } 497 }
509 } else { 498 } else {
510 printf("68K write to unhandled Z80 address %X\n", location); 499 fatal_error("68K write to unhandled Z80 address %X\n", location);
511 exit(1);
512 } 500 }
513 } 501 }
514 } else { 502 } else {
515 location &= 0x1FFF; 503 location &= 0x1FFF;
516 if (location < 0x100) { 504 if (location < 0x100) {
845 } 833 }
846 834
847 if (statefile) { 835 if (statefile) {
848 uint32_t pc = load_gst(gen, statefile); 836 uint32_t pc = load_gst(gen, statefile);
849 if (!pc) { 837 if (!pc) {
850 fprintf(stderr, "Failed to load save state %s\n", statefile); 838 fatal_error("Failed to load save state %s\n", statefile);
851 exit(1);
852 } 839 }
853 printf("Loaded %s\n", statefile); 840 printf("Loaded %s\n", statefile);
854 if (debugger) { 841 if (debugger) {
855 insert_breakpoint(context, pc, debugger); 842 insert_breakpoint(context, pc, debugger);
856 } 843 }
905 }; 892 };
906 #endif 893 #endif
907 894
908 int main(int argc, char ** argv) 895 int main(int argc, char ** argv)
909 { 896 {
910 if (argc < 2) {
911 fputs("Usage: blastem [OPTIONS] ROMFILE [WIDTH] [HEIGHT]\n", stderr);
912 return 1;
913 }
914 set_exe_str(argv[0]); 897 set_exe_str(argv[0]);
915 config = load_config(); 898 config = load_config();
916 int width = -1; 899 int width = -1;
917 int height = -1; 900 int height = -1;
918 int debug = 0; 901 int debug = 0;
929 if (argv[i][0] == '-') { 912 if (argv[i][0] == '-') {
930 switch(argv[i][1]) { 913 switch(argv[i][1]) {
931 case 'b': 914 case 'b':
932 i++; 915 i++;
933 if (i >= argc) { 916 if (i >= argc) {
934 fputs("-b must be followed by a frame count\n", stderr); 917 fatal_error("-b must be followed by a frame count\n");
935 return 1;
936 } 918 }
937 headless = 1; 919 headless = 1;
938 exit_after = atoi(argv[i]); 920 exit_after = atoi(argv[i]);
939 break; 921 break;
940 case 'd': 922 case 'd':
952 break; 934 break;
953 case 'l': 935 case 'l':
954 address_log = fopen("address.log", "w"); 936 address_log = fopen("address.log", "w");
955 break; 937 break;
956 case 'v': 938 case 'v':
957 printf("blastem %s\n", BLASTEM_VERSION); 939 info_message("blastem %s\n", BLASTEM_VERSION);
958 return 0; 940 return 0;
959 break; 941 break;
960 case 'n': 942 case 'n':
961 z80_enabled = 0; 943 z80_enabled = 0;
962 break; 944 break;
963 case 'r': 945 case 'r':
964 i++; 946 i++;
965 if (i >= argc) { 947 if (i >= argc) {
966 fputs("-r must be followed by region (J, U or E)\n", stderr); 948 fatal_error("-r must be followed by region (J, U or E)\n");
967 return 1;
968 } 949 }
969 force_version = translate_region_char(toupper(argv[i][0])); 950 force_version = translate_region_char(toupper(argv[i][0]));
970 if (!force_version) { 951 if (!force_version) {
971 fprintf(stderr, "'%c' is not a valid region character for the -r option\n", argv[i][0]); 952 fatal_error("'%c' is not a valid region character for the -r option\n", argv[i][0]);
972 return 1;
973 } 953 }
974 break; 954 break;
975 case 's': 955 case 's':
976 i++; 956 i++;
977 if (i >= argc) { 957 if (i >= argc) {
978 fputs("-s must be followed by a savestate filename\n", stderr); 958 fatal_error("-s must be followed by a savestate filename\n");
979 return 1;
980 } 959 }
981 statefile = argv[i]; 960 statefile = argv[i];
982 break; 961 break;
983 case 'y': 962 case 'y':
984 ym_log = 1; 963 ym_log = 1;
985 break; 964 break;
986 case 'h': 965 case 'h':
987 puts( 966 info_message(
988 "Usage: blastem [OPTIONS] ROMFILE [WIDTH] [HEIGHT]\n" 967 "Usage: blastem [OPTIONS] ROMFILE [WIDTH] [HEIGHT]\n"
989 "Options:\n" 968 "Options:\n"
990 " -h Print this help text\n" 969 " -h Print this help text\n"
991 " -r (J|U|E) Force region to Japan, US or Europe respectively\n" 970 " -r (J|U|E) Force region to Japan, US or Europe respectively\n"
992 " -f Start in fullscreen mode\n" 971 " -f Start in fullscreen mode\n"
998 " -l Log 68K code addresses (useful for assemblers)\n" 977 " -l Log 68K code addresses (useful for assemblers)\n"
999 " -y Log individual YM-2612 channels to WAVE files\n" 978 " -y Log individual YM-2612 channels to WAVE files\n"
1000 ); 979 );
1001 return 0; 980 return 0;
1002 default: 981 default:
1003 fprintf(stderr, "Unrecognized switch %s\n", argv[i]); 982 fatal_error("Unrecognized switch %s\n", argv[i]);
1004 return 1;
1005 } 983 }
1006 } else if (!loaded) { 984 } else if (!loaded) {
1007 if (!(rom_size = load_rom(argv[i]))) { 985 if (!(rom_size = load_rom(argv[i]))) {
1008 fprintf(stderr, "Failed to open %s for reading\n", argv[i]); 986 fatal_error("Failed to open %s for reading\n", argv[i]);
1009 return 1;
1010 } 987 }
1011 romfname = argv[i]; 988 romfname = argv[i];
1012 loaded = 1; 989 loaded = 1;
1013 } else if (width < 0) { 990 } else if (width < 0) {
1014 width = atoi(argv[i]); 991 width = atoi(argv[i]);
1015 } else if (height < 0) { 992 } else if (height < 0) {
1016 height = atoi(argv[i]); 993 height = atoi(argv[i]);
1017 } 994 }
1018 } 995 }
1019 if (!loaded) { 996 if (!loaded) {
1020 fputs("You must specify a ROM filename!\n", stderr); 997 fatal_error("Usage: blastem [OPTIONS] ROMFILE [WIDTH] [HEIGHT]\n");
1021 return 1;
1022 } 998 }
1023 tern_node *rom_db = load_rom_db(); 999 tern_node *rom_db = load_rom_db();
1024 rom_info info = configure_rom(rom_db, cart, rom_size, base_map, sizeof(base_map)/sizeof(base_map[0])); 1000 rom_info info = configure_rom(rom_db, cart, rom_size, base_map, sizeof(base_map)/sizeof(base_map[0]));
1025 byteswap_rom(rom_size); 1001 byteswap_rom(rom_size);
1026 set_region(&info, force_version); 1002 set_region(&info, force_version);