changeset 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 91bf4d905eba
children 54ffba3768d6
files blastem.c blastem.h default.cfg m68k_core.h menu.c render.h render_sdl.c
diffstat 7 files changed, 130 insertions(+), 77 deletions(-) [+]
line wrap: on
line diff
--- 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;
 }
--- 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;
--- 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
 
--- 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;
--- 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;
--- 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);
--- 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;