comparison blastem.c @ 874:b6842dfb8edf

ROM is now run after being selected in menu. Initial path for menu is read from config file.
author Michael Pavone <pavone@retrodev.com>
date Sun, 08 Nov 2015 18:38:33 -0800
parents 7022ba865cfd
children 54ffba3768d6
comparison
equal deleted inserted replaced
873:91bf4d905eba 874:b6842dfb8edf
302 fatal_error("machine freeze due to write to address %X\n", 0xC00000 | vdp_port); 302 fatal_error("machine freeze due to write to address %X\n", 0xC00000 | vdp_port);
303 } 303 }
304 vdp_port &= 0x1F; 304 vdp_port &= 0x1F;
305 //printf("vdp_port write: %X, value: %X, cycle: %d\n", vdp_port, value, context->current_cycle); 305 //printf("vdp_port write: %X, value: %X, cycle: %d\n", vdp_port, value, context->current_cycle);
306 sync_components(context, 0); 306 sync_components(context, 0);
307 vdp_context * v_context = context->video_context;
308 genesis_context * gen = context->system; 307 genesis_context * gen = context->system;
308 vdp_context *v_context = gen->vdp;
309 if (vdp_port < 0x10) { 309 if (vdp_port < 0x10) {
310 int blocked; 310 int blocked;
311 uint32_t before_cycle = v_context->cycles; 311 uint32_t before_cycle = v_context->cycles;
312 if (vdp_port < 4) { 312 if (vdp_port < 4) {
313 313
404 fatal_error("machine freeze due to read from address %X\n", 0xC00000 | vdp_port); 404 fatal_error("machine freeze due to read from address %X\n", 0xC00000 | vdp_port);
405 } 405 }
406 vdp_port &= 0x1F; 406 vdp_port &= 0x1F;
407 uint16_t value; 407 uint16_t value;
408 sync_components(context, 0); 408 sync_components(context, 0);
409 vdp_context * v_context = context->video_context; 409 genesis_context *gen = context->system;
410 vdp_context * v_context = gen->vdp;
410 uint32_t before_cycle = v_context->cycles; 411 uint32_t before_cycle = v_context->cycles;
411 if (vdp_port < 0x10) { 412 if (vdp_port < 0x10) {
412 if (vdp_port < 4) { 413 if (vdp_port < 4) {
413 value = vdp_data_port_read(v_context); 414 value = vdp_data_port_read(v_context);
414 } else if(vdp_port < 8) { 415 } else if(vdp_port < 8) {
793 (read_16_fun)io_read_w, (write_16_fun)io_write_w, 794 (read_16_fun)io_read_w, (write_16_fun)io_write_w,
794 (read_8_fun)io_read, (write_8_fun)io_write} 795 (read_8_fun)io_read, (write_8_fun)io_write}
795 }; 796 };
796 797
797 char * save_filename; 798 char * save_filename;
798 genesis_context * genesis; 799 genesis_context *genesis;
800 genesis_context *menu_context;
801 genesis_context *game_context;
799 void persist_save() 802 void persist_save()
800 { 803 {
801 FILE * f = fopen(save_filename, "wb"); 804 FILE * f = fopen(save_filename, "wb");
802 if (!f) { 805 if (!f) {
803 fprintf(stderr, "Failed to open %s file %s for writing\n", genesis->save_type == SAVE_I2C ? "EEPROM" : "SRAM", save_filename); 806 fprintf(stderr, "Failed to open %s file %s for writing\n", genesis->save_type == SAVE_I2C ? "EEPROM" : "SRAM", save_filename);
806 fwrite(genesis->save_storage, 1, genesis->save_size, f); 809 fwrite(genesis->save_storage, 1, genesis->save_size, f);
807 fclose(f); 810 fclose(f);
808 printf("Saved %s to %s\n", genesis->save_type == SAVE_I2C ? "EEPROM" : "SRAM", save_filename); 811 printf("Saved %s to %s\n", genesis->save_type == SAVE_I2C ? "EEPROM" : "SRAM", save_filename);
809 } 812 }
810 813
811 void init_run_cpu(genesis_context * gen, rom_info *rom, FILE * address_log, char * statefile, uint8_t * debugger) 814 #ifndef NO_Z80
812 { 815 const memmap_chunk z80_map[] = {
813 m68k_options opts; 816 { 0x0000, 0x4000, 0x1FFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, z80_ram, NULL, NULL, NULL, NULL },
814 817 { 0x8000, 0x10000, 0x7FFF, 0, 0, NULL, NULL, NULL, z80_read_bank, z80_write_bank},
818 { 0x4000, 0x6000, 0x0003, 0, 0, NULL, NULL, NULL, z80_read_ym, z80_write_ym},
819 { 0x6000, 0x6100, 0xFFFF, 0, 0, NULL, NULL, NULL, NULL, z80_write_bank_reg},
820 { 0x7F00, 0x8000, 0x00FF, 0, 0, NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write}
821 };
822 #endif
823
824 genesis_context *alloc_init_genesis(rom_info *rom, int fps, uint32_t ym_opts)
825 {
826 genesis_context *gen = calloc(1, sizeof(genesis_context));
827 gen->master_clock = gen->normal_clock = fps == 60 ? MCLKS_NTSC : MCLKS_PAL;
828
829 gen->vdp = malloc(sizeof(vdp_context));
830 init_vdp_context(gen->vdp, version_reg & 0x40);
831 gen->frame_end = vdp_cycles_to_frame_end(gen->vdp);
832 char * config_cycles = tern_find_path(config, "clocks\0max_cycles\0").ptrval;
833 gen->max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL;
834
835 gen->ym = malloc(sizeof(ym2612_context));
836 ym_init(gen->ym, render_sample_rate(), gen->master_clock, MCLKS_PER_YM, render_audio_buffer(), ym_opts);
837
838 gen->psg = malloc(sizeof(psg_context));
839 psg_init(gen->psg, render_sample_rate(), gen->master_clock, MCLKS_PER_PSG, render_audio_buffer());
840
841 gen->z80 = calloc(1, sizeof(z80_context));
842 #ifndef NO_Z80
843 z80_options *z_opts = malloc(sizeof(z80_options));
844 init_z80_opts(z_opts, z80_map, 5, NULL, 0, MCLKS_PER_Z80);
845 init_z80_context(gen->z80, z_opts);
846 z80_assert_reset(gen->z80, 0);
847 #endif
848
849 gen->z80->system = gen;
850 gen->z80->mem_pointers[0] = z80_ram;
851 gen->z80->mem_pointers[1] = gen->z80->mem_pointers[2] = (uint8_t *)cart;
852
853 gen->work_ram = ram;
854 gen->zram = z80_ram;
855 setup_io_devices(config, gen->ports);
856
857 gen->save_type = rom->save_type;
815 gen->save_type = rom->save_type; 858 gen->save_type = rom->save_type;
816 if (gen->save_type != SAVE_NONE) { 859 if (gen->save_type != SAVE_NONE) {
817 gen->save_ram_mask = rom->save_mask; 860 gen->save_ram_mask = rom->save_mask;
818 gen->save_size = rom->save_size; 861 gen->save_size = rom->save_size;
819 gen->save_storage = rom->save_buffer; 862 gen->save_storage = rom->save_buffer;
833 } 876 }
834 } else { 877 } else {
835 gen->save_storage = NULL; 878 gen->save_storage = NULL;
836 } 879 }
837 880
838 init_m68k_opts(&opts, rom->map, rom->map_chunks, MCLKS_PER_68K); 881 m68k_options *opts = malloc(sizeof(m68k_options));
839 opts.address_log = address_log; 882 init_m68k_opts(opts, rom->map, rom->map_chunks, MCLKS_PER_68K);
840 opts.gen.flags |= M68K_OPT_BROKEN_READ_MODIFY; 883 //TODO: make this configurable
841 m68k_context *context = init_68k_context(&opts); 884 opts->gen.flags |= M68K_OPT_BROKEN_READ_MODIFY;
842 gen->m68k = context; 885 gen->m68k = init_68k_context(opts);
843 886 gen->m68k->system = gen;
844 context->video_context = gen->vdp; 887
845 context->system = gen;
846 for (int i = 0; i < rom->map_chunks; i++) 888 for (int i = 0; i < rom->map_chunks; i++)
847 { 889 {
848 if (rom->map[i].flags & MMAP_PTR_IDX) { 890 if (rom->map[i].flags & MMAP_PTR_IDX) {
849 context->mem_pointers[rom->map[i].ptr_index] = rom->map[i].buffer; 891 gen->m68k->mem_pointers[rom->map[i].ptr_index] = rom->map[i].buffer;
850 } 892 }
851 } 893 }
894
895 return gen;
896 }
897
898 void start_genesis(genesis_context *gen, char *statefile, uint8_t *debugger)
899 {
900 set_keybindings(gen->ports);
852 901
853 if (statefile) { 902 if (statefile) {
854 uint32_t pc = load_gst(gen, statefile); 903 uint32_t pc = load_gst(gen, statefile);
855 if (!pc) { 904 if (!pc) {
856 fatal_error("Failed to load save state %s\n", statefile); 905 fatal_error("Failed to load save state %s\n", statefile);
857 } 906 }
858 printf("Loaded %s\n", statefile); 907 printf("Loaded %s\n", statefile);
859 if (debugger) { 908 if (debugger) {
860 insert_breakpoint(context, pc, debugger); 909 insert_breakpoint(gen->m68k, pc, debugger);
861 } 910 }
862 adjust_int_cycle(gen->m68k, gen->vdp); 911 adjust_int_cycle(gen->m68k, gen->vdp);
863 start_68k_context(context, pc); 912 start_68k_context(gen->m68k, pc);
864 } else { 913 } else {
865 if (debugger) { 914 if (debugger) {
866 uint32_t address = cart[2] << 16 | cart[3]; 915 uint32_t address = cart[2] << 16 | cart[3];
867 insert_breakpoint(context, address, debugger); 916 insert_breakpoint(gen->m68k, address, debugger);
868 } 917 }
869 m68k_reset(context); 918 m68k_reset(gen->m68k);
870 } 919 }
871 } 920 }
872 921
873 char *title; 922 char *title;
874 923
877 if (title) { 926 if (title) {
878 free(title); 927 free(title);
879 title = NULL; 928 title = NULL;
880 } 929 }
881 title = alloc_concat(rom_name, " - BlastEm"); 930 title = alloc_concat(rom_name, " - BlastEm");
931 render_update_caption(title);
882 } 932 }
883 933
884 void set_region(rom_info *info, uint8_t region) 934 void set_region(rom_info *info, uint8_t region)
885 { 935 {
886 if (!region) { 936 if (!region) {
897 version_reg = NO_DISK | JAP; 947 version_reg = NO_DISK | JAP;
898 } else { 948 } else {
899 version_reg = NO_DISK | USA; 949 version_reg = NO_DISK | USA;
900 } 950 }
901 } 951 }
902
903 #ifndef NO_Z80
904 const memmap_chunk z80_map[] = {
905 { 0x0000, 0x4000, 0x1FFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, z80_ram, NULL, NULL, NULL, NULL },
906 { 0x8000, 0x10000, 0x7FFF, 0, 0, NULL, NULL, NULL, z80_read_bank, z80_write_bank},
907 { 0x4000, 0x6000, 0x0003, 0, 0, NULL, NULL, NULL, z80_read_ym, z80_write_ym},
908 { 0x6000, 0x6100, 0xFFFF, 0, 0, NULL, NULL, NULL, NULL, z80_write_bank_reg},
909 { 0x7F00, 0x8000, 0x00FF, 0, 0, NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write}
910 };
911 #endif
912 952
913 int main(int argc, char ** argv) 953 int main(int argc, char ** argv)
914 { 954 {
915 set_exe_str(argv[0]); 955 set_exe_str(argv[0]);
916 config = load_config(); 956 config = load_config();
1012 width = atoi(argv[i]); 1052 width = atoi(argv[i]);
1013 } else if (height < 0) { 1053 } else if (height < 0) {
1014 height = atoi(argv[i]); 1054 height = atoi(argv[i]);
1015 } 1055 }
1016 } 1056 }
1057 uint8_t menu = !loaded;
1017 if (!loaded) { 1058 if (!loaded) {
1018 #ifdef __ANDROID__ 1059 //load menu
1019 //Temporary hack until UI is in place 1060 romfname = tern_find_path(config, "ui\rom\0").ptrval;
1020 if (!(rom_size = load_rom("/mnt/sdcard/rom.bin"))) { 1061 if (!romfname) {
1021 fatal_error("Failed to open /mnt/sdcard/rom.bin for reading"); 1062 romfname = "menu.bin";
1022 1063 }
1023 } 1064 //TODO: load relative to executable or from assets depending on platform
1024 romfname = "/mnt/sdcard/rom.bin"; 1065 if (!(rom_size = load_rom(romfname))) {
1066 fatal_error("Failed to open UI ROM %s for reading", romfname);
1067
1068 }
1025 loaded = 1; 1069 loaded = 1;
1026 #else
1027 fatal_error("Usage: blastem [OPTIONS] ROMFILE [WIDTH] [HEIGHT]\n");
1028 #endif
1029 } 1070 }
1030 tern_node *rom_db = load_rom_db(); 1071 tern_node *rom_db = load_rom_db();
1031 rom_info info = configure_rom(rom_db, cart, rom_size, base_map, sizeof(base_map)/sizeof(base_map[0])); 1072 rom_info info = configure_rom(rom_db, cart, rom_size, base_map, sizeof(base_map)/sizeof(base_map[0]));
1032 byteswap_rom(rom_size); 1073 byteswap_rom(rom_size);
1033 set_region(&info, force_version); 1074 set_region(&info, force_version);
1047 fps = 50; 1088 fps = 50;
1048 } 1089 }
1049 if (!headless) { 1090 if (!headless) {
1050 render_init(width, height, title, fps, fullscreen); 1091 render_init(width, height, title, fps, fullscreen);
1051 } 1092 }
1052 vdp_context v_context;
1053 genesis_context gen;
1054 memset(&gen, 0, sizeof(gen));
1055 gen.master_clock = gen.normal_clock = fps == 60 ? MCLKS_NTSC : MCLKS_PAL;
1056
1057 init_vdp_context(&v_context, version_reg & 0x40);
1058 gen.frame_end = vdp_cycles_to_frame_end(&v_context);
1059 char * config_cycles = tern_find_path(config, "clocks\0max_cycles\0").ptrval;
1060 gen.max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL;
1061
1062 ym2612_context y_context;
1063 ym_init(&y_context, render_sample_rate(), gen.master_clock, MCLKS_PER_YM, render_audio_buffer(), ym_log ? YM_OPT_WAVE_LOG : 0);
1064
1065 psg_context p_context;
1066 psg_init(&p_context, render_sample_rate(), gen.master_clock, MCLKS_PER_PSG, render_audio_buffer());
1067
1068 z80_context z_context;
1069 #ifndef NO_Z80
1070 z80_options z_opts;
1071 init_z80_opts(&z_opts, z80_map, 5, NULL, 0, MCLKS_PER_Z80);
1072 init_z80_context(&z_context, &z_opts);
1073 z80_assert_reset(&z_context, 0);
1074 #endif
1075
1076 z_context.system = &gen;
1077 z_context.mem_pointers[0] = z80_ram;
1078 z_context.mem_pointers[1] = z_context.mem_pointers[2] = (uint8_t *)cart;
1079
1080 gen.z80 = &z_context;
1081 gen.vdp = &v_context;
1082 gen.ym = &y_context;
1083 gen.psg = &p_context;
1084 gen.work_ram = ram;
1085 gen.zram = z80_ram;
1086 genesis = &gen;
1087 setup_io_devices(config, gen.ports);
1088
1089 int fname_size = strlen(romfname); 1093 int fname_size = strlen(romfname);
1090 char * ext = info.save_type == SAVE_I2C ? "eeprom" : "sram"; 1094 char * ext = info.save_type == SAVE_I2C ? "eeprom" : "sram";
1091 save_filename = malloc(fname_size+strlen(ext) + 2); 1095 save_filename = malloc(fname_size+strlen(ext) + 2);
1092 memcpy(save_filename, romfname, fname_size); 1096 memcpy(save_filename, romfname, fname_size);
1093 int i; 1097 int i;
1099 } 1103 }
1100 if (i < 0) { 1104 if (i < 0) {
1101 save_filename[fname_size] = '.'; 1105 save_filename[fname_size] = '.';
1102 strcpy(save_filename + fname_size + 1, ext); 1106 strcpy(save_filename + fname_size + 1, ext);
1103 } 1107 }
1104 set_keybindings(gen.ports); 1108
1105 1109 genesis = alloc_init_genesis(&info, fps, (ym_log && !menu) ? YM_OPT_WAVE_LOG : 0);
1106 init_run_cpu(&gen, &info, address_log, statefile, debuggerfun); 1110 if (menu) {
1111 menu_context = genesis;
1112 } else {
1113 genesis->m68k->options->address_log = address_log;
1114 game_context = genesis;
1115 }
1116
1117 start_genesis(genesis, menu ? NULL : statefile, menu ? NULL : debuggerfun);
1118 if (menu && menu_context->next_rom) {
1119 //TODO: Allow returning to menu
1120 if (!(rom_size = load_rom(menu_context->next_rom))) {
1121 fatal_error("Failed to open %s for reading\n", menu_context->next_rom);
1122 }
1123 info = configure_rom(rom_db, cart, rom_size, base_map, sizeof(base_map)/sizeof(base_map[0]));
1124 byteswap_rom(rom_size);
1125 set_region(&info, force_version);
1126 update_title(info.name);
1127 fname_size = strlen(romfname);
1128 ext = info.save_type == SAVE_I2C ? "eeprom" : "sram";
1129 save_filename = malloc(fname_size+strlen(ext) + 2);
1130 memcpy(save_filename, romfname, fname_size);
1131 for (i = fname_size-1; fname_size >= 0; --i) {
1132 if (save_filename[i] == '.') {
1133 strcpy(save_filename + i + 1, ext);
1134 break;
1135 }
1136 }
1137 if (i < 0) {
1138 save_filename[fname_size] = '.';
1139 strcpy(save_filename + fname_size + 1, ext);
1140 }
1141 game_context = alloc_init_genesis(&info, fps, ym_log ? YM_OPT_WAVE_LOG : 0);
1142 genesis->m68k->options->address_log = address_log;
1143 genesis = game_context;
1144 start_genesis(genesis, statefile, debuggerfun);
1145 }
1146
1107 return 0; 1147 return 0;
1108 } 1148 }