It is now possible to switch back and forth between the menu ROM and the game

This commit is contained in:
Michael Pavone committed 2015-11-13 19:15:37 -08:00
1 parent 3834192b16
commit 802454482c
11 files changed
+207 -52

No files matched your search

+1 -1
View File
@@ -91,7 +91,7 @@ ifndef CPU
CPU:=$(shell uname -m)
endif
TRANSOBJS=gen.o backend.o $(MEM)
TRANSOBJS=gen.o backend.o $(MEM) arena.o
M68KOBJS=68kinst.o m68k_core.o
ifeq ($(CPU),x86_64)
M68KOBJS+= m68k_core_x86.o
+81
View File
@@ -0,0 +1,81 @@
/*
Copyright 2015 Michael Pavone
This file is part of BlastEm.
BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
*/
#include <stdlib.h>
#include <stdint.h>
#include "arena.h"
struct arena {
void **used_blocks;
void **free_blocks;
size_t used_count;
size_t used_storage;
size_t free_count;
size_t free_storage;
};
static arena *current_arena;
arena *get_current_arena()
{
if (!current_arena) {
current_arena = calloc(1, sizeof(arena));
}
return current_arena;
}
arena *set_current_arena(arena *a)
{
arena *tmp = current_arena;
current_arena = a;
return tmp;
}
arena *start_new_arena()
{
arena *tmp = current_arena;
current_arena = NULL;
return tmp;
}
void track_block(void *block)
{
arena *cur = get_current_arena();
if (cur->used_count == cur->used_storage) {
cur->used_storage *= 2;
cur->used_blocks = realloc(cur->used_blocks, cur->used_storage * sizeof(void *));
}
cur->used_blocks[cur->used_count++] = block;
}
void mark_all_free()
{
arena *cur = get_current_arena();
if (!cur->free_blocks) {
cur->free_blocks = cur->used_blocks;
cur->free_storage = cur->used_storage;
cur->free_count = cur->used_count;
cur->used_count = cur->used_storage = 0;
cur->used_blocks = NULL;
} else {
if (cur->free_storage < cur->used_count + cur->free_count) {
cur->free_storage = cur->used_count + cur->free_count;
cur->free_blocks = realloc(cur->free_blocks, cur->free_storage * sizeof(void*));
}
for (; cur->used_count > 0; cur->used_count--)
{
cur->free_blocks[cur->free_count++] = cur->used_blocks[cur->used_count-1];
}
}
}
void *try_alloc_arena()
{
if (!current_arena || !current_arena->free_count) {
return NULL;
}
return current_arena->free_blocks[--current_arena->free_count];
}
+18
View File
@@ -0,0 +1,18 @@
/*
Copyright 2015 Michael Pavone
This file is part of BlastEm.
BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
*/
#ifndef ARENA_H_
#define ARENA_H_
typedef struct arena arena;
arena *get_current_arena();
arena *set_current_arena(arena *a);
arena *start_new_arena();
void track_block(void *block);
void mark_all_free();
void *try_alloc_arena();
#endif //ARENA_H_
+77 -40
View File
@@ -3,6 +3,11 @@
This file is part of BlastEm.
BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "68kinst.h"
#include "m68k_core.h"
#include "z80_to_x86.h"
@@ -15,10 +20,7 @@
#include "util.h"
#include "romdb.h"
#include "terminal.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "arena.h"
#define BLASTEM_VERSION "0.3.X"
@@ -44,7 +46,7 @@
#endif
uint16_t *cart;
uint16_t ram[RAM_WORDS];
uint16_t *ram;
uint8_t z80_ram[Z80_RAM_BYTES];
int headless = 0;
@@ -784,17 +786,6 @@ void set_speed_percent(genesis_context * context, uint32_t percent)
psg_adjust_master_clock(context->psg, context->master_clock);
}
const memmap_chunk base_map[] = {
{0xE00000, 0x1000000, 0xFFFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, ram,
NULL, NULL, NULL, NULL},
{0xC00000, 0xE00000, 0x1FFFFF, 0, 0, NULL,
(read_16_fun)vdp_port_read, (write_16_fun)vdp_port_write,
(read_8_fun)vdp_port_read_b, (write_8_fun)vdp_port_write_b},
{0xA00000, 0xA12000, 0x1FFFF, 0, 0, NULL,
(read_16_fun)io_read_w, (write_16_fun)io_write_w,
(read_8_fun)io_read, (write_8_fun)io_write}
};
char * save_filename;
genesis_context *genesis;
genesis_context *menu_context;
@@ -850,6 +841,7 @@ genesis_context *alloc_init_genesis(rom_info *rom, int fps, uint32_t ym_opts)
gen->z80->mem_pointers[0] = z80_ram;
gen->z80->mem_pointers[1] = gen->z80->mem_pointers[2] = (uint8_t *)cart;
gen->cart = cart;
gen->work_ram = ram;
gen->zram = z80_ram;
setup_io_devices(config, gen->ports);
@@ -1080,6 +1072,17 @@ int main(int argc, char ** argv)
loaded = 1;
}
ram = malloc(RAM_WORDS * sizeof(uint16_t));
memmap_chunk base_map[] = {
{0xE00000, 0x1000000, 0xFFFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, ram,
NULL, NULL, NULL, NULL},
{0xC00000, 0xE00000, 0x1FFFFF, 0, 0, NULL,
(read_16_fun)vdp_port_read, (write_16_fun)vdp_port_write,
(read_8_fun)vdp_port_read_b, (write_8_fun)vdp_port_write_b},
{0xA00000, 0xA12000, 0x1FFFF, 0, 0, NULL,
(read_16_fun)io_read_w, (write_16_fun)io_write_w,
(read_8_fun)io_read, (write_8_fun)io_write}
};
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]));
byteswap_rom(rom_size);
@@ -1127,33 +1130,67 @@ int main(int argc, char ** argv)
}
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;
for(;;)
{
if (menu && menu_context->next_rom) {
if (!(rom_size = load_rom(menu_context->next_rom))) {
fatal_error("Failed to open %s for reading\n", menu_context->next_rom);
}
base_map[0].buffer = ram = malloc(RAM_WORDS * sizeof(uint16_t));
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);
}
if (!game_context) {
//start a new arena and save old one in suspended genesis context
genesis->arena = start_new_arena();
//allocate new genesis context
game_context = alloc_init_genesis(&info, fps, ym_log ? YM_OPT_WAVE_LOG : 0);
} else {
//TODO: hard reset of context with new ROM
}
free(menu_context->next_rom);
menu_context->next_rom = NULL;
menu = 0;
genesis = game_context;
genesis->m68k->options->address_log = address_log;
start_genesis(genesis, statefile, debuggerfun);
}
if (i < 0) {
save_filename[fname_size] = '.';
strcpy(save_filename + fname_size + 1, ext);
else if (menu && game_context) {
puts("Switching back to game context");
genesis->arena = set_current_arena(game_context->arena);
genesis = game_context;
cart = genesis->cart;
ram = genesis->work_ram;
menu = 0;
set_keybindings(genesis->ports);
resume_68k(genesis->m68k);
} else if (!menu && menu_context) {
puts("Switching back to menu context");
genesis->arena = set_current_arena(menu_context->arena);
genesis = menu_context;
cart = genesis->cart;
ram = genesis->work_ram;
menu = 1;
set_keybindings(genesis->ports);
resume_68k(genesis->m68k);
} else {
break;
}
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;
+4 -1
View File
@@ -15,6 +15,7 @@
#include "io.h"
#include "config.h"
#include "romdb.h"
#include "arena.h"
typedef struct {
m68k_context *m68k;
@@ -22,9 +23,11 @@ typedef struct {
vdp_context *vdp;
ym2612_context *ym;
psg_context *psg;
uint16_t *cart;
uint16_t *work_ram;
uint8_t *zram;
void *extra;
arena *arena;
char *next_rom;
uint8_t *save_storage;
eeprom_map *eeprom_map;
@@ -53,7 +56,7 @@ extern tern_node * config;
#define Z80_RAM_BYTES 8 * 1024
extern uint16_t *cart;
extern uint16_t ram[RAM_WORDS];
extern uint16_t *ram;
extern uint8_t z80_ram[Z80_RAM_BYTES];
uint16_t read_dma_value(uint32_t address);
+3 -3
View File
@@ -293,7 +293,7 @@ void handle_binding_up(keybinding * binding)
}
break;
case UI_EXIT:
exit(0);
genesis->m68k->should_return = 1;
}
break;
}
@@ -609,7 +609,7 @@ cleanup_sock:
close(ports[i].device.stream.listen_fd);
ports[i].device_type = IO_NONE;
}
} else
} else
#endif
if (ports[i].device_type == IO_GAMEPAD3 || ports[i].device_type == IO_GAMEPAD6) {
printf("IO port %s connected to gamepad #%d with type '%s'\n", io_name(i), ports[i].device.pad.gamepad_num + 1, device_type_names[ports[i].device_type]);
@@ -672,7 +672,7 @@ void set_keybindings(io_port *ports)
if (pads) {
for (int i = 0; i < 100 && i < render_num_joysticks(); i++)
{
if (i < 10) {
numstr[0] = i + '0';
numstr[1] = 0;
+10
View File
@@ -983,6 +983,16 @@ void start_68k_context(m68k_context * context, uint32_t address)
{
code_ptr addr = get_native_address_trans(context, address);
m68k_options * options = context->options;
context->should_return = 0;
options->start_context(addr, context);
}
void resume_68k(m68k_context *context)
{
code_ptr addr = context->resume_pc;
context->resume_pc = NULL;
m68k_options * options = context->options;
context->should_return = 0;
options->start_context(addr, context);
}
+2 -1
View File
@@ -58,7 +58,7 @@ typedef struct {
uint32_t int_cycle;
uint32_t int_num;
uint16_t *mem_pointers[NUM_MEM_AREAS];
void *resume_pc;
code_ptr resume_pc;
native_map_slot *native_code_map;
m68k_options *options;
void *system;
@@ -70,6 +70,7 @@ typedef struct {
void translate_m68k(m68k_options * opts, struct m68kinst * inst);
void translate_m68k_stream(uint32_t address, m68k_context * context);
void start_68k_context(m68k_context * context, uint32_t address);
void resume_68k(m68k_context *context);
void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks, uint32_t clock_divider);
m68k_context * init_68k_context(m68k_options * opts);
void m68k_reset(m68k_context * context);
+1 -1
View File
@@ -2515,8 +2515,8 @@ void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chu
retn(code);
*do_ret = code->cur - (do_ret+1);
pop_r(code, opts->gen.scratch1);
retn(code);
mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, resume_pc), SZ_PTR);
retn(code);
*do_int = code->cur - (do_int+1);
//implement 1 instruction latency
cmp_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
+7 -2
View File
@@ -1,6 +1,6 @@
/*
Copyright 2013 Michael Pavone
This file is part of BlastEm.
This file is part of BlastEm.
BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
*/
#include <sys/mman.h>
@@ -12,6 +12,7 @@
#include <stdio.h>
#include "mem.h"
#include "arena.h"
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
@@ -25,8 +26,12 @@ void * alloc_code(size_t *size)
//start at the 1GB mark to allow plenty of room for sbrk based malloc implementations
//while still keeping well within 32-bit displacement range for calling code compiled into the executable
static uint8_t *next = (uint8_t *)0x40000000;
uint8_t *ret = try_alloc_arena();
if (ret) {
return ret;
}
*size += PAGE_SIZE - (*size & (PAGE_SIZE - 1));
uint8_t *ret = mmap(NULL, *size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
ret = mmap(NULL, *size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
if (ret == MAP_FAILED) {
perror("alloc_code");
return NULL;
+3 -3
View File
@@ -23,9 +23,9 @@
#define warning_puts(msg) fputs(stderr, msg);
#define fatal_puts(msg) fputs(stderr, msg);
#define info_printf(msg, args vprintf(msg, args)
#define warning_printf(msg, args vfprintf(stderr, msg, args)
#define fatal_printf(msg, args vfprintf(stderr, msg, args)
#define info_printf(msg, args) vprintf(msg, args)
#define warning_printf(msg, args) vfprintf(stderr, msg, args)
#define fatal_printf(msg, args) vfprintf(stderr, msg, args)
#endif
#include "blastem.h" //for headless global