# HG changeset patch # User Michael Pavone # Date 1447036713 28800 # Node ID b6842dfb8edfb7ab500ccca9e927f7301e735d29 # Parent 91bf4d905ebaaf735295f84082603cdcbb133fd8 ROM is now run after being selected in menu. Initial path for menu is read from config file. diff -r 91bf4d905eba -r b6842dfb8edf blastem.c --- a/blastem.c Sun Nov 08 15:58:36 2015 -0800 +++ b/blastem.c Sun Nov 08 18:38:33 2015 -0800 @@ -304,8 +304,8 @@ vdp_port &= 0x1F; //printf("vdp_port write: %X, value: %X, cycle: %d\n", vdp_port, value, context->current_cycle); sync_components(context, 0); - vdp_context * v_context = context->video_context; genesis_context * gen = context->system; + vdp_context *v_context = gen->vdp; if (vdp_port < 0x10) { int blocked; uint32_t before_cycle = v_context->cycles; @@ -406,7 +406,8 @@ vdp_port &= 0x1F; uint16_t value; sync_components(context, 0); - vdp_context * v_context = context->video_context; + genesis_context *gen = context->system; + vdp_context * v_context = gen->vdp; uint32_t before_cycle = v_context->cycles; if (vdp_port < 0x10) { if (vdp_port < 4) { @@ -795,7 +796,9 @@ }; char * save_filename; -genesis_context * genesis; +genesis_context *genesis; +genesis_context *menu_context; +genesis_context *game_context; void persist_save() { FILE * f = fopen(save_filename, "wb"); @@ -808,10 +811,50 @@ printf("Saved %s to %s\n", genesis->save_type == SAVE_I2C ? "EEPROM" : "SRAM", save_filename); } -void init_run_cpu(genesis_context * gen, rom_info *rom, FILE * address_log, char * statefile, uint8_t * debugger) +#ifndef NO_Z80 +const memmap_chunk z80_map[] = { + { 0x0000, 0x4000, 0x1FFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, z80_ram, NULL, NULL, NULL, NULL }, + { 0x8000, 0x10000, 0x7FFF, 0, 0, NULL, NULL, NULL, z80_read_bank, z80_write_bank}, + { 0x4000, 0x6000, 0x0003, 0, 0, NULL, NULL, NULL, z80_read_ym, z80_write_ym}, + { 0x6000, 0x6100, 0xFFFF, 0, 0, NULL, NULL, NULL, NULL, z80_write_bank_reg}, + { 0x7F00, 0x8000, 0x00FF, 0, 0, NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write} +}; +#endif + +genesis_context *alloc_init_genesis(rom_info *rom, int fps, uint32_t ym_opts) { - m68k_options opts; + genesis_context *gen = calloc(1, sizeof(genesis_context)); + gen->master_clock = gen->normal_clock = fps == 60 ? MCLKS_NTSC : MCLKS_PAL; + + gen->vdp = malloc(sizeof(vdp_context)); + init_vdp_context(gen->vdp, version_reg & 0x40); + gen->frame_end = vdp_cycles_to_frame_end(gen->vdp); + char * config_cycles = tern_find_path(config, "clocks\0max_cycles\0").ptrval; + gen->max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL; + + gen->ym = malloc(sizeof(ym2612_context)); + ym_init(gen->ym, render_sample_rate(), gen->master_clock, MCLKS_PER_YM, render_audio_buffer(), ym_opts); + + gen->psg = malloc(sizeof(psg_context)); + psg_init(gen->psg, render_sample_rate(), gen->master_clock, MCLKS_PER_PSG, render_audio_buffer()); + gen->z80 = calloc(1, sizeof(z80_context)); +#ifndef NO_Z80 + z80_options *z_opts = malloc(sizeof(z80_options)); + init_z80_opts(z_opts, z80_map, 5, NULL, 0, MCLKS_PER_Z80); + init_z80_context(gen->z80, z_opts); + z80_assert_reset(gen->z80, 0); +#endif + + gen->z80->system = gen; + gen->z80->mem_pointers[0] = z80_ram; + gen->z80->mem_pointers[1] = gen->z80->mem_pointers[2] = (uint8_t *)cart; + + gen->work_ram = ram; + gen->zram = z80_ram; + setup_io_devices(config, gen->ports); + + gen->save_type = rom->save_type; gen->save_type = rom->save_type; if (gen->save_type != SAVE_NONE) { gen->save_ram_mask = rom->save_mask; @@ -835,21 +878,27 @@ gen->save_storage = NULL; } - init_m68k_opts(&opts, rom->map, rom->map_chunks, MCLKS_PER_68K); - opts.address_log = address_log; - opts.gen.flags |= M68K_OPT_BROKEN_READ_MODIFY; - m68k_context *context = init_68k_context(&opts); - gen->m68k = context; + m68k_options *opts = malloc(sizeof(m68k_options)); + init_m68k_opts(opts, rom->map, rom->map_chunks, MCLKS_PER_68K); + //TODO: make this configurable + opts->gen.flags |= M68K_OPT_BROKEN_READ_MODIFY; + gen->m68k = init_68k_context(opts); + gen->m68k->system = gen; - context->video_context = gen->vdp; - context->system = gen; for (int i = 0; i < rom->map_chunks; i++) { if (rom->map[i].flags & MMAP_PTR_IDX) { - context->mem_pointers[rom->map[i].ptr_index] = rom->map[i].buffer; + gen->m68k->mem_pointers[rom->map[i].ptr_index] = rom->map[i].buffer; } } + return gen; +} + +void start_genesis(genesis_context *gen, char *statefile, uint8_t *debugger) +{ + set_keybindings(gen->ports); + if (statefile) { uint32_t pc = load_gst(gen, statefile); if (!pc) { @@ -857,16 +906,16 @@ } printf("Loaded %s\n", statefile); if (debugger) { - insert_breakpoint(context, pc, debugger); + insert_breakpoint(gen->m68k, pc, debugger); } adjust_int_cycle(gen->m68k, gen->vdp); - start_68k_context(context, pc); + start_68k_context(gen->m68k, pc); } else { if (debugger) { uint32_t address = cart[2] << 16 | cart[3]; - insert_breakpoint(context, address, debugger); + insert_breakpoint(gen->m68k, address, debugger); } - m68k_reset(context); + m68k_reset(gen->m68k); } } @@ -879,6 +928,7 @@ title = NULL; } title = alloc_concat(rom_name, " - BlastEm"); + render_update_caption(title); } void set_region(rom_info *info, uint8_t region) @@ -900,16 +950,6 @@ } } -#ifndef NO_Z80 -const memmap_chunk z80_map[] = { - { 0x0000, 0x4000, 0x1FFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, z80_ram, NULL, NULL, NULL, NULL }, - { 0x8000, 0x10000, 0x7FFF, 0, 0, NULL, NULL, NULL, z80_read_bank, z80_write_bank}, - { 0x4000, 0x6000, 0x0003, 0, 0, NULL, NULL, NULL, z80_read_ym, z80_write_ym}, - { 0x6000, 0x6100, 0xFFFF, 0, 0, NULL, NULL, NULL, NULL, z80_write_bank_reg}, - { 0x7F00, 0x8000, 0x00FF, 0, 0, NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write} -}; -#endif - int main(int argc, char ** argv) { set_exe_str(argv[0]); @@ -1014,18 +1054,19 @@ height = atoi(argv[i]); } } + uint8_t menu = !loaded; if (!loaded) { -#ifdef __ANDROID__ - //Temporary hack until UI is in place - if (!(rom_size = load_rom("/mnt/sdcard/rom.bin"))) { - fatal_error("Failed to open /mnt/sdcard/rom.bin for reading"); + //load menu + romfname = tern_find_path(config, "ui\rom\0").ptrval; + if (!romfname) { + romfname = "menu.bin"; + } + //TODO: load relative to executable or from assets depending on platform + if (!(rom_size = load_rom(romfname))) { + fatal_error("Failed to open UI ROM %s for reading", romfname); } - romfname = "/mnt/sdcard/rom.bin"; loaded = 1; -#else - fatal_error("Usage: blastem [OPTIONS] ROMFILE [WIDTH] [HEIGHT]\n"); -#endif } tern_node *rom_db = load_rom_db(); rom_info info = configure_rom(rom_db, cart, rom_size, base_map, sizeof(base_map)/sizeof(base_map[0])); @@ -1049,43 +1090,6 @@ if (!headless) { render_init(width, height, title, fps, fullscreen); } - vdp_context v_context; - genesis_context gen; - memset(&gen, 0, sizeof(gen)); - gen.master_clock = gen.normal_clock = fps == 60 ? MCLKS_NTSC : MCLKS_PAL; - - init_vdp_context(&v_context, version_reg & 0x40); - gen.frame_end = vdp_cycles_to_frame_end(&v_context); - char * config_cycles = tern_find_path(config, "clocks\0max_cycles\0").ptrval; - gen.max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL; - - ym2612_context y_context; - ym_init(&y_context, render_sample_rate(), gen.master_clock, MCLKS_PER_YM, render_audio_buffer(), ym_log ? YM_OPT_WAVE_LOG : 0); - - psg_context p_context; - psg_init(&p_context, render_sample_rate(), gen.master_clock, MCLKS_PER_PSG, render_audio_buffer()); - - z80_context z_context; -#ifndef NO_Z80 - z80_options z_opts; - init_z80_opts(&z_opts, z80_map, 5, NULL, 0, MCLKS_PER_Z80); - init_z80_context(&z_context, &z_opts); - z80_assert_reset(&z_context, 0); -#endif - - z_context.system = &gen; - z_context.mem_pointers[0] = z80_ram; - z_context.mem_pointers[1] = z_context.mem_pointers[2] = (uint8_t *)cart; - - gen.z80 = &z_context; - gen.vdp = &v_context; - gen.ym = &y_context; - gen.psg = &p_context; - gen.work_ram = ram; - gen.zram = z80_ram; - genesis = &gen; - setup_io_devices(config, gen.ports); - int fname_size = strlen(romfname); char * ext = info.save_type == SAVE_I2C ? "eeprom" : "sram"; save_filename = malloc(fname_size+strlen(ext) + 2); @@ -1101,8 +1105,44 @@ save_filename[fname_size] = '.'; strcpy(save_filename + fname_size + 1, ext); } - set_keybindings(gen.ports); + + genesis = alloc_init_genesis(&info, fps, (ym_log && !menu) ? YM_OPT_WAVE_LOG : 0); + if (menu) { + menu_context = genesis; + } else { + genesis->m68k->options->address_log = address_log; + game_context = genesis; + } - init_run_cpu(&gen, &info, address_log, statefile, debuggerfun); + start_genesis(genesis, menu ? NULL : statefile, menu ? NULL : debuggerfun); + if (menu && menu_context->next_rom) { + //TODO: Allow returning to menu + if (!(rom_size = load_rom(menu_context->next_rom))) { + fatal_error("Failed to open %s for reading\n", menu_context->next_rom); + } + info = configure_rom(rom_db, cart, rom_size, base_map, sizeof(base_map)/sizeof(base_map[0])); + byteswap_rom(rom_size); + set_region(&info, force_version); + update_title(info.name); + fname_size = strlen(romfname); + ext = info.save_type == SAVE_I2C ? "eeprom" : "sram"; + save_filename = malloc(fname_size+strlen(ext) + 2); + memcpy(save_filename, romfname, fname_size); + for (i = fname_size-1; fname_size >= 0; --i) { + if (save_filename[i] == '.') { + strcpy(save_filename + i + 1, ext); + break; + } + } + if (i < 0) { + save_filename[fname_size] = '.'; + strcpy(save_filename + fname_size + 1, ext); + } + game_context = alloc_init_genesis(&info, fps, ym_log ? YM_OPT_WAVE_LOG : 0); + genesis->m68k->options->address_log = address_log; + genesis = game_context; + start_genesis(genesis, statefile, debuggerfun); + } + return 0; } diff -r 91bf4d905eba -r b6842dfb8edf blastem.h --- a/blastem.h Sun Nov 08 15:58:36 2015 -0800 +++ b/blastem.h Sun Nov 08 18:38:33 2015 -0800 @@ -25,6 +25,7 @@ uint16_t *work_ram; uint8_t *zram; void *extra; + char *next_rom; uint8_t *save_storage; eeprom_map *eeprom_map; uint32_t num_eeprom; diff -r 91bf4d905eba -r b6842dfb8edf default.cfg --- a/default.cfg Sun Nov 08 15:58:36 2015 -0800 +++ b/default.cfg Sun Nov 08 18:38:33 2015 -0800 @@ -85,5 +85,9 @@ } } +ui { + rom menu.bin +} + default_region U diff -r 91bf4d905eba -r b6842dfb8edf m68k_core.h --- a/m68k_core.h Sun Nov 08 15:58:36 2015 -0800 +++ b/m68k_core.h Sun Nov 08 18:38:33 2015 -0800 @@ -58,7 +58,6 @@ uint32_t int_cycle; uint32_t int_num; uint16_t *mem_pointers[NUM_MEM_AREAS]; - void *video_context; void *resume_pc; native_map_slot *native_code_map; m68k_options *options; diff -r 91bf4d905eba -r b6842dfb8edf menu.c --- a/menu.c Sun Nov 08 15:58:36 2015 -0800 +++ b/menu.c Sun Nov 08 18:38:33 2015 -0800 @@ -58,7 +58,8 @@ menu_context *menu = gen->extra; if (!menu) { gen->extra = menu = calloc(1, sizeof(menu_context)); - menu->curpath = strdup(get_home_dir()); + menu->curpath = tern_find_path(config, "ui\0initial_path\0").ptrval; + menu->curpath = menu->curpath ? strdup(menu->curpath) : strdup(get_home_dir()); } if (menu->state) { uint32_t dst = menu->latch << 16 | value; @@ -137,6 +138,8 @@ case 2: { char buf[4096]; copy_string_from_guest(m68k, dst, buf, sizeof(buf)); + char *pieces[] = {menu->curpath, "/", buf}; + gen->next_rom = alloc_concat_m(3, pieces); m68k->should_return = 1; fprintf(stderr, "MENU: Selected ROM %s\n", buf); break; diff -r 91bf4d905eba -r b6842dfb8edf render.h --- a/render.h Sun Nov 08 15:58:36 2015 -0800 +++ b/render.h Sun Nov 08 18:38:33 2015 -0800 @@ -35,6 +35,7 @@ uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b); void render_alloc_surfaces(vdp_context * context); void render_init(int width, int height, char * title, uint32_t fps, uint8_t fullscreen); +void render_update_caption(char *title); void render_context(vdp_context * context); void render_wait_quit(vdp_context * context); void render_wait_psg(psg_context * context); diff -r 91bf4d905eba -r b6842dfb8edf render_sdl.c --- a/render_sdl.c Sun Nov 08 15:58:36 2015 -0800 +++ b/render_sdl.c Sun Nov 08 18:38:33 2015 -0800 @@ -371,10 +371,15 @@ } } SDL_JoystickEventState(SDL_ENABLE); - + atexit(render_quit); } +void render_update_caption(char *title) +{ + caption = title; +} + void render_context(vdp_context * context) { int width = context->regs[REG_MODE_4] & BIT_H40 ? 320.0f : 256.0f;