main genesis.c
   1/*
   2 Copyright 2013-2016 Michael Pavone
   3 This file is part of BlastEm.
   4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
   5*/
   6#include "genesis.h"
   7#include "blastem.h"
   8#include "nor.h"
   9#include <stdlib.h>
  10#include <ctype.h>
  11#include <time.h>
  12#include <string.h>
  13#include "render.h"
  14#include "gst.h"
  15#include "util.h"
  16#include "debug.h"
  17#include "gdb_remote.h"
  18#include "saves.h"
  19#include "bindings.h"
  20#include "jcart.h"
  21#define MCLKS_NTSC 53693175
  22#define MCLKS_PAL  53203395
  23
  24uint32_t MCLKS_PER_68K;
  25#define MCLKS_PER_YM  7
  26#define MCLKS_PER_Z80 15
  27#define MCLKS_PER_PSG (MCLKS_PER_Z80*16)
  28#define Z80_INT_PULSE_MCLKS 2573 //measured value is ~171.5 Z80 clocks
  29#define DEFAULT_SYNC_INTERVAL MCLKS_LINE
  30#define DEFAULT_LOWPASS_CUTOFF 3390
  31
  32//TODO: Figure out the exact value for this
  33#define LINES_NTSC 262
  34#define LINES_PAL 313
  35
  36#define MAX_SOUND_CYCLES 100000	
  37
  38#define Z80_CYCLE current_cycle
  39#define Z80_OPTS options
  40
  41void genesis_serialize(genesis_context *gen, serialize_buffer *buf, uint32_t m68k_pc)
  42{
  43	start_section(buf, SECTION_68000);
  44	m68k_serialize(gen->m68k, m68k_pc, buf);
  45	end_section(buf);
  46	
  47	start_section(buf, SECTION_Z80);
  48	z80_serialize(gen->z80, buf);
  49	end_section(buf);
  50	
  51	start_section(buf, SECTION_VDP);
  52	vdp_serialize(gen->vdp, buf);
  53	end_section(buf);
  54	
  55	start_section(buf, SECTION_YM2612);
  56	ym_serialize(gen->ym, buf);
  57	end_section(buf);
  58	
  59	start_section(buf, SECTION_PSG);
  60	psg_serialize(gen->psg, buf);
  61	end_section(buf);
  62	
  63	start_section(buf, SECTION_GEN_BUS_ARBITER);
  64	save_int8(buf, gen->z80->reset);
  65	save_int8(buf, gen->z80->busreq);
  66	save_int16(buf, gen->z80_bank_reg);
  67	end_section(buf);
  68	
  69	start_section(buf, SECTION_SEGA_IO_1);
  70	io_serialize(gen->io.ports, buf);
  71	end_section(buf);
  72	
  73	start_section(buf, SECTION_SEGA_IO_2);
  74	io_serialize(gen->io.ports + 1, buf);
  75	end_section(buf);
  76	
  77	start_section(buf, SECTION_SEGA_IO_EXT);
  78	io_serialize(gen->io.ports + 2, buf);
  79	end_section(buf);
  80	
  81	start_section(buf, SECTION_MAIN_RAM);
  82	save_int8(buf, RAM_WORDS * 2 / 1024);
  83	save_buffer16(buf, gen->work_ram, RAM_WORDS);
  84	end_section(buf);
  85	
  86	start_section(buf, SECTION_SOUND_RAM);
  87	save_int8(buf, Z80_RAM_BYTES / 1024);
  88	save_buffer8(buf, gen->zram, Z80_RAM_BYTES);
  89	end_section(buf);
  90	
  91	cart_serialize(&gen->header, buf);
  92}
  93
  94static uint8_t *serialize(system_header *sys, size_t *size_out)
  95{
  96	genesis_context *gen = (genesis_context *)sys;
  97	uint32_t address;
  98	if (gen->m68k->resume_pc) {
  99		gen->m68k->target_cycle = gen->m68k->current_cycle;
 100		gen->header.save_state = SERIALIZE_SLOT+1;
 101		resume_68k(gen->m68k);
 102		if (size_out) {
 103			*size_out = gen->serialize_size;
 104		}
 105		return gen->serialize_tmp;
 106	} else {
 107		serialize_buffer state;
 108		init_serialize(&state);
 109		uint32_t address = read_word(4, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen, gen->m68k) << 16;
 110		address |= read_word(6, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen, gen->m68k);
 111		genesis_serialize(gen, &state, address);
 112		if (size_out) {
 113			*size_out = state.size;
 114		}
 115		return state.data;
 116	}
 117}
 118
 119static void ram_deserialize(deserialize_buffer *buf, void *vgen)
 120{
 121	genesis_context *gen = vgen;
 122	uint32_t ram_size = load_int8(buf) * 1024 / 2;
 123	if (ram_size > RAM_WORDS) {
 124		fatal_error("State has a RAM size of %d bytes", ram_size * 2);
 125	}
 126	load_buffer16(buf, gen->work_ram, ram_size);
 127	m68k_invalidate_code_range(gen->m68k, 0xE00000, 0x1000000);
 128}
 129
 130static void zram_deserialize(deserialize_buffer *buf, void *vgen)
 131{
 132	genesis_context *gen = vgen;
 133	uint32_t ram_size = load_int8(buf) * 1024;
 134	if (ram_size > Z80_RAM_BYTES) {
 135		fatal_error("State has a Z80 RAM size of %d bytes", ram_size);
 136	}
 137	load_buffer8(buf, gen->zram, ram_size);
 138	z80_invalidate_code_range(gen->z80, 0, 0x4000);
 139}
 140
 141static void update_z80_bank_pointer(genesis_context *gen)
 142{
 143	if (gen->z80_bank_reg < 0x140) {
 144		gen->z80->mem_pointers[1] = get_native_pointer(gen->z80_bank_reg << 15, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen);
 145	} else {
 146		gen->z80->mem_pointers[1] = NULL;
 147	}
 148	z80_invalidate_code_range(gen->z80, 0x8000, 0xFFFF);
 149}
 150
 151static void bus_arbiter_deserialize(deserialize_buffer *buf, void *vgen)
 152{
 153	genesis_context *gen = vgen;
 154	gen->z80->reset = load_int8(buf);
 155	gen->z80->busreq = load_int8(buf);
 156	gen->z80_bank_reg = load_int16(buf) & 0x1FF;
 157}
 158
 159static void adjust_int_cycle(m68k_context * context, vdp_context * v_context);
 160void genesis_deserialize(deserialize_buffer *buf, genesis_context *gen)
 161{
 162	register_section_handler(buf, (section_handler){.fun = m68k_deserialize, .data = gen->m68k}, SECTION_68000);
 163	register_section_handler(buf, (section_handler){.fun = z80_deserialize, .data = gen->z80}, SECTION_Z80);
 164	register_section_handler(buf, (section_handler){.fun = vdp_deserialize, .data = gen->vdp}, SECTION_VDP);
 165	register_section_handler(buf, (section_handler){.fun = ym_deserialize, .data = gen->ym}, SECTION_YM2612);
 166	register_section_handler(buf, (section_handler){.fun = psg_deserialize, .data = gen->psg}, SECTION_PSG);
 167	register_section_handler(buf, (section_handler){.fun = bus_arbiter_deserialize, .data = gen}, SECTION_GEN_BUS_ARBITER);
 168	register_section_handler(buf, (section_handler){.fun = io_deserialize, .data = gen->io.ports}, SECTION_SEGA_IO_1);
 169	register_section_handler(buf, (section_handler){.fun = io_deserialize, .data = gen->io.ports + 1}, SECTION_SEGA_IO_2);
 170	register_section_handler(buf, (section_handler){.fun = io_deserialize, .data = gen->io.ports + 2}, SECTION_SEGA_IO_EXT);
 171	register_section_handler(buf, (section_handler){.fun = ram_deserialize, .data = gen}, SECTION_MAIN_RAM);
 172	register_section_handler(buf, (section_handler){.fun = zram_deserialize, .data = gen}, SECTION_SOUND_RAM);
 173	register_section_handler(buf, (section_handler){.fun = cart_deserialize, .data = gen}, SECTION_MAPPER);
 174	while (buf->cur_pos < buf->size)
 175	{
 176		load_section(buf);
 177	}
 178	update_z80_bank_pointer(gen);
 179	adjust_int_cycle(gen->m68k, gen->vdp);
 180	free(buf->handlers);
 181	buf->handlers = NULL;
 182}
 183
 184#include "m68k_internal.h" //needed for get_native_address_trans, should be eliminated once handling of PC is cleaned up
 185static void deserialize(system_header *sys, uint8_t *data, size_t size)
 186{
 187	genesis_context *gen = (genesis_context *)sys;
 188	deserialize_buffer buffer;
 189	init_deserialize(&buffer, data, size);
 190	genesis_deserialize(&buffer, gen);
 191	//HACK: Fix this once PC/IR is represented in a better way in 68K core
 192	gen->m68k->resume_pc = get_native_address_trans(gen->m68k, gen->m68k->last_prefetch_address);
 193}
 194
 195uint16_t read_dma_value(uint32_t address)
 196{
 197	genesis_context *genesis = (genesis_context *)current_system;
 198	//TODO: Figure out what happens when you try to DMA from weird adresses like IO or banked Z80 area
 199	if ((address >= 0xA00000 && address < 0xB00000) || (address >= 0xC00000 && address <= 0xE00000)) {
 200		return 0;
 201	}
 202	
 203	//addresses here are word addresses (i.e. bit 0 corresponds to A1), so no need to do multiply by 2
 204	return read_word(address * 2, (void **)genesis->m68k->mem_pointers, &genesis->m68k->options->gen, genesis->m68k);
 205}
 206
 207static uint16_t get_open_bus_value(system_header *system)
 208{
 209	genesis_context *genesis = (genesis_context *)system;
 210	return read_dma_value(genesis->m68k->last_prefetch_address/2);
 211}
 212
 213static void adjust_int_cycle(m68k_context * context, vdp_context * v_context)
 214{
 215	//static int old_int_cycle = CYCLE_NEVER;
 216	genesis_context *gen = context->system;
 217	if (context->sync_cycle - context->current_cycle > gen->max_cycles) {
 218		context->sync_cycle = context->current_cycle + gen->max_cycles;
 219	}
 220	context->int_cycle = CYCLE_NEVER;
 221	if ((context->status & 0x7) < 6) {
 222		uint32_t next_vint = vdp_next_vint(v_context);
 223		if (next_vint != CYCLE_NEVER) {
 224			context->int_cycle = next_vint;
 225			context->int_num = 6;
 226		}
 227		if ((context->status & 0x7) < 4) {
 228			uint32_t next_hint = vdp_next_hint(v_context);
 229			if (next_hint != CYCLE_NEVER) {
 230				next_hint = next_hint < context->current_cycle ? context->current_cycle : next_hint;
 231				if (next_hint < context->int_cycle) {
 232					context->int_cycle = next_hint;
 233					context->int_num = 4;
 234
 235				}
 236			}
 237		}
 238	}
 239	if (context->int_cycle > context->current_cycle && context->int_pending == INT_PENDING_SR_CHANGE) {
 240		context->int_pending = INT_PENDING_NONE;
 241	}
 242	/*if (context->int_cycle != old_int_cycle) {
 243		printf("int cycle changed to: %d, level: %d @ %d(%d), frame: %d, vcounter: %d, hslot: %d, mask: %d, hint_counter: %d\n", context->int_cycle, context->int_num, v_context->cycles, context->current_cycle, v_context->frame, v_context->vcounter, v_context->hslot, context->status & 0x7, v_context->hint_counter);
 244		old_int_cycle = context->int_cycle;
 245	}*/
 246	
 247	if (context->status & M68K_STATUS_TRACE || context->trace_pending) {
 248		context->target_cycle = context->current_cycle;
 249		return;
 250	}
 251
 252	context->target_cycle = context->int_cycle < context->sync_cycle ? context->int_cycle : context->sync_cycle;
 253	if (context->should_return) {
 254		context->target_cycle = context->current_cycle;
 255	} else if (context->target_cycle < context->current_cycle) {
 256		//Changes to SR can result in an interrupt cycle that's in the past
 257		//This can cause issues with the implementation of STOP though
 258		context->target_cycle = context->current_cycle;
 259	}
 260	if (context->target_cycle == context->int_cycle) {
 261		//Currently delays from Z80 access and refresh are applied only when we sync
 262		//this can cause extra latency when it comes to interrupts
 263		//to prevent this code forces some extra synchronization in the period immediately before an interrupt
 264		if ((context->target_cycle - context->current_cycle) > gen->int_latency_prev1) {
 265			context->target_cycle = context->sync_cycle = context->int_cycle - gen->int_latency_prev1;
 266		} else if ((context->target_cycle - context->current_cycle) > gen->int_latency_prev2) {
 267			context->target_cycle = context->sync_cycle = context->int_cycle - gen->int_latency_prev2;
 268		} else {
 269			context->target_cycle = context->sync_cycle = context->current_cycle;
 270		}
 271		
 272	}
 273	/*printf("Cyc: %d, Trgt: %d, Int Cyc: %d, Int: %d, Mask: %X, V: %d, H: %d, HICount: %d, HReg: %d, Line: %d\n",
 274		context->current_cycle, context->target_cycle, context->int_cycle, context->int_num, (context->status & 0x7),
 275		v_context->regs[REG_MODE_2] & 0x20, v_context->regs[REG_MODE_1] & 0x10, v_context->hint_counter, v_context->regs[REG_HINT], v_context->cycles / MCLKS_LINE);*/
 276}
 277
 278//#define DO_DEBUG_PRINT
 279#ifdef DO_DEBUG_PRINT
 280#define dprintf printf
 281#define dputs puts
 282#else
 283#define dprintf
 284#define dputs
 285#endif
 286
 287static void z80_next_int_pulse(z80_context * z_context)
 288{
 289	genesis_context * gen = z_context->system;
 290	z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp);
 291	z_context->int_pulse_end = z_context->int_pulse_start + Z80_INT_PULSE_MCLKS;
 292	z_context->im2_vector = 0xFF;
 293}
 294
 295static void sync_z80(z80_context * z_context, uint32_t mclks)
 296{
 297	if (z80_enabled) {
 298		z80_run(z_context, mclks);
 299	} else
 300	{
 301		z_context->Z80_CYCLE = mclks;
 302	}
 303}
 304
 305static void sync_sound(genesis_context * gen, uint32_t target)
 306{
 307	//printf("YM | Cycle: %d, bpos: %d, PSG | Cycle: %d, bpos: %d\n", gen->ym->current_cycle, gen->ym->buffer_pos, gen->psg->cycles, gen->psg->buffer_pos * 2);
 308	while (target > gen->psg->cycles && target - gen->psg->cycles > MAX_SOUND_CYCLES) {
 309		uint32_t cur_target = gen->psg->cycles + MAX_SOUND_CYCLES;
 310		//printf("Running PSG to cycle %d\n", cur_target);
 311		psg_run(gen->psg, cur_target);
 312		//printf("Running YM-2612 to cycle %d\n", cur_target);
 313		ym_run(gen->ym, cur_target);
 314	}
 315	psg_run(gen->psg, target);
 316	ym_run(gen->ym, target);
 317
 318	//printf("Target: %d, YM bufferpos: %d, PSG bufferpos: %d\n", target, gen->ym->buffer_pos, gen->psg->buffer_pos * 2);
 319}
 320
 321//TODO: move this inside the system context
 322static uint32_t last_frame_num;
 323
 324//My refresh emulation isn't currently good enough and causes more problems than it solves
 325#define REFRESH_EMULATION
 326#ifdef REFRESH_EMULATION
 327#define REFRESH_INTERVAL 128
 328#define REFRESH_DELAY 2
 329uint32_t last_sync_cycle;
 330uint32_t refresh_counter;
 331#endif
 332
 333#include <limits.h>
 334#define ADJUST_BUFFER (8*MCLKS_LINE*313)
 335#define MAX_NO_ADJUST (UINT_MAX-ADJUST_BUFFER)
 336
 337m68k_context * sync_components(m68k_context * context, uint32_t address)
 338{
 339	genesis_context * gen = context->system;
 340	vdp_context * v_context = gen->vdp;
 341	z80_context * z_context = gen->z80;
 342#ifdef REFRESH_EMULATION
 343	//lame estimation of refresh cycle delay
 344	refresh_counter += context->current_cycle - last_sync_cycle;
 345	if (!gen->bus_busy) {
 346		context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL));
 347	}
 348	refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL);
 349#endif
 350
 351	uint32_t mclks = context->current_cycle;
 352	sync_z80(z_context, mclks);
 353	sync_sound(gen, mclks);
 354	vdp_run_context(v_context, mclks);
 355	if (mclks >= gen->reset_cycle) {
 356		gen->reset_requested = 1;
 357		context->should_return = 1;
 358		gen->reset_cycle = CYCLE_NEVER;
 359	}
 360	if (v_context->frame != last_frame_num) {
 361		//printf("reached frame end %d | MCLK Cycles: %d, Target: %d, VDP cycles: %d, vcounter: %d, hslot: %d\n", last_frame_num, mclks, gen->frame_end, v_context->cycles, v_context->vcounter, v_context->hslot);
 362		last_frame_num = v_context->frame;
 363
 364		if(exit_after){
 365			--exit_after;
 366			if (!exit_after) {
 367				exit(0);
 368			}
 369		}
 370		if (context->current_cycle > MAX_NO_ADJUST) {
 371			uint32_t deduction = mclks - ADJUST_BUFFER;
 372			vdp_adjust_cycles(v_context, deduction);
 373			io_adjust_cycles(gen->io.ports, context->current_cycle, deduction);
 374			io_adjust_cycles(gen->io.ports+1, context->current_cycle, deduction);
 375			io_adjust_cycles(gen->io.ports+2, context->current_cycle, deduction);
 376			if (gen->mapper_type == MAPPER_JCART) {
 377				jcart_adjust_cycles(gen, deduction);
 378			}
 379			context->current_cycle -= deduction;
 380			z80_adjust_cycles(z_context, deduction);
 381			gen->ym->current_cycle -= deduction;
 382			gen->psg->cycles -= deduction;
 383			if (gen->ym->write_cycle != CYCLE_NEVER) {
 384				gen->ym->write_cycle = gen->ym->write_cycle >= deduction ? gen->ym->write_cycle - deduction : 0;
 385			}
 386			if (gen->reset_cycle != CYCLE_NEVER) {
 387				gen->reset_cycle -= deduction;
 388			}
 389		}
 390	}
 391	gen->frame_end = vdp_cycles_to_frame_end(v_context);
 392	context->sync_cycle = gen->frame_end;
 393	//printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot);
 394	if (context->int_ack) {
 395		//printf("acknowledging %d @ %d:%d, vcounter: %d, hslot: %d\n", context->int_ack, context->current_cycle, v_context->cycles, v_context->vcounter, v_context->hslot);
 396		vdp_int_ack(v_context);
 397		context->int_ack = 0;
 398	}
 399	if (!address && (gen->header.enter_debugger || gen->header.save_state)) {
 400		context->sync_cycle = context->current_cycle + 1;
 401	}
 402	adjust_int_cycle(context, v_context);
 403	if (gen->reset_cycle < context->target_cycle) {
 404		context->target_cycle = gen->reset_cycle;
 405	}
 406	if (address) {
 407		if (gen->header.enter_debugger) {
 408			gen->header.enter_debugger = 0;
 409			debugger(context, address);
 410		}
 411		if (gen->header.save_state && (z_context->pc || !z_context->native_pc || z_context->reset || !z_context->busreq)) {
 412			uint8_t slot = gen->header.save_state - 1;
 413			gen->header.save_state = 0;
 414			if (z_context->native_pc && !z_context->reset) {
 415				//advance Z80 core to the start of an instruction
 416				while (!z_context->pc)
 417				{
 418					sync_z80(z_context, z_context->current_cycle + MCLKS_PER_Z80);
 419				}
 420			}
 421			char *save_path = slot == SERIALIZE_SLOT ? NULL : get_slot_name(&gen->header, slot, use_native_states ? "state" : "gst");
 422			if (use_native_states || slot == SERIALIZE_SLOT) {
 423				serialize_buffer state;
 424				init_serialize(&state);
 425				genesis_serialize(gen, &state, address);
 426				if (slot == SERIALIZE_SLOT) {
 427					gen->serialize_tmp = state.data;
 428					gen->serialize_size = state.size;
 429					context->sync_cycle = context->current_cycle;
 430					context->should_return = 1;
 431				} else {
 432					save_to_file(&state, save_path);
 433					free(state.data);
 434				}
 435			} else {
 436				save_gst(gen, save_path, address);
 437			}
 438			printf("Saved state to %s\n", save_path);
 439			free(save_path);
 440		} else if(gen->header.save_state) {
 441			context->sync_cycle = context->current_cycle + 1;
 442		}
 443	}
 444#ifdef REFRESH_EMULATION
 445	last_sync_cycle = context->current_cycle;
 446#endif
 447	return context;
 448}
 449
 450static m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_t value)
 451{
 452	if (vdp_port & 0x2700E0) {
 453		fatal_error("machine freeze due to write to address %X\n", 0xC00000 | vdp_port);
 454	}
 455	vdp_port &= 0x1F;
 456	//printf("vdp_port write: %X, value: %X, cycle: %d\n", vdp_port, value, context->current_cycle);
 457#ifdef REFRESH_EMULATION
 458	//do refresh check here so we can avoid adding a penalty for a refresh that happens during a VDP access
 459	refresh_counter += context->current_cycle - 4*MCLKS_PER_68K - last_sync_cycle;
 460	context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL));
 461	refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL);
 462	last_sync_cycle = context->current_cycle;
 463#endif
 464	sync_components(context, 0);
 465	genesis_context * gen = context->system;
 466	vdp_context *v_context = gen->vdp;
 467	uint32_t before_cycle = v_context->cycles;
 468	if (vdp_port < 0x10) {
 469		int blocked;
 470		if (vdp_port < 4) {
 471			while (vdp_data_port_write(v_context, value) < 0) {
 472				while(v_context->flags & FLAG_DMA_RUN) {
 473					vdp_run_dma_done(v_context, gen->frame_end);
 474					if (v_context->cycles >= gen->frame_end) {
 475						uint32_t cycle_diff = v_context->cycles - context->current_cycle;
 476						uint32_t m68k_cycle_diff = (cycle_diff / MCLKS_PER_68K) * MCLKS_PER_68K;
 477						if (m68k_cycle_diff < cycle_diff) {
 478							m68k_cycle_diff += MCLKS_PER_68K;
 479						}
 480						context->current_cycle += m68k_cycle_diff;
 481						gen->bus_busy = 1;
 482						sync_components(context, 0);
 483						gen->bus_busy = 0;
 484					}
 485				}
 486				//context->current_cycle = v_context->cycles;
 487			}
 488		} else if(vdp_port < 8) {
 489			vdp_run_context_full(v_context, context->current_cycle);
 490			before_cycle = v_context->cycles;
 491			blocked = vdp_control_port_write(v_context, value);
 492			if (blocked) {
 493				while (blocked) {
 494					while(v_context->flags & FLAG_DMA_RUN) {
 495						vdp_run_dma_done(v_context, gen->frame_end);
 496						if (v_context->cycles >= gen->frame_end) {
 497							uint32_t cycle_diff = v_context->cycles - context->current_cycle;
 498							uint32_t m68k_cycle_diff = (cycle_diff / MCLKS_PER_68K) * MCLKS_PER_68K;
 499							if (m68k_cycle_diff < cycle_diff) {
 500								m68k_cycle_diff += MCLKS_PER_68K;
 501							}
 502							context->current_cycle += m68k_cycle_diff;
 503							gen->bus_busy = 1;
 504							sync_components(context, 0);
 505							gen->bus_busy = 0;
 506						}
 507					}
 508					
 509					if (blocked < 0) {
 510						blocked = vdp_control_port_write(v_context, value);
 511					} else {
 512						blocked = 0;
 513					}
 514				}
 515			} else {
 516				context->sync_cycle = gen->frame_end = vdp_cycles_to_frame_end(v_context);
 517				//printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot);
 518				adjust_int_cycle(context, v_context);
 519			}
 520		} else {
 521			fatal_error("Illegal write to HV Counter port %X\n", vdp_port);
 522		}
 523		if (v_context->cycles != before_cycle) {
 524			//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);
 525			uint32_t cycle_diff = v_context->cycles - context->current_cycle;
 526			uint32_t m68k_cycle_diff = (cycle_diff / MCLKS_PER_68K) * MCLKS_PER_68K;
 527			if (m68k_cycle_diff < cycle_diff) {
 528				m68k_cycle_diff += MCLKS_PER_68K;
 529			}
 530			context->current_cycle += m68k_cycle_diff;
 531			//Lock the Z80 out of the bus until the VDP access is complete
 532			gen->bus_busy = 1;
 533			sync_z80(gen->z80, v_context->cycles);
 534			gen->bus_busy = 0;
 535		}
 536	} else if (vdp_port < 0x18) {
 537		psg_write(gen->psg, value);
 538	} else {
 539		vdp_test_port_write(gen->vdp, value);
 540	}
 541#ifdef REFRESH_EMULATION
 542	last_sync_cycle -= 4;
 543	//refresh may have happened while we were waiting on the VDP,
 544	//so advance refresh_counter but don't add any delays
 545	if (vdp_port >= 4 && vdp_port < 8 && v_context->cycles != before_cycle) {
 546		refresh_counter = 0;
 547	} else {
 548		refresh_counter += (context->current_cycle - last_sync_cycle);
 549		refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL);
 550	}
 551	last_sync_cycle = context->current_cycle;
 552#endif
 553	return context;
 554}
 555
 556static m68k_context * vdp_port_write_b(uint32_t vdp_port, m68k_context * context, uint8_t value)
 557{
 558	return vdp_port_write(vdp_port, context, vdp_port < 0x10 ? value | value << 8 : ((vdp_port & 1) ? value : 0));
 559}
 560
 561static void * z80_vdp_port_write(uint32_t vdp_port, void * vcontext, uint8_t value)
 562{
 563	z80_context * context = vcontext;
 564	genesis_context * gen = context->system;
 565	vdp_port &= 0xFF;
 566	if (vdp_port & 0xE0) {
 567		fatal_error("machine freeze due to write to Z80 address %X\n", 0x7F00 | vdp_port);
 568	}
 569	if (vdp_port < 0x10) {
 570		//These probably won't currently interact well with the 68K accessing the VDP
 571		if (vdp_port < 4) {
 572			vdp_run_context(gen->vdp, context->Z80_CYCLE);
 573			vdp_data_port_write(gen->vdp, value << 8 | value);
 574		} else if (vdp_port < 8) {
 575			vdp_run_context_full(gen->vdp, context->Z80_CYCLE);
 576			vdp_control_port_write(gen->vdp, value << 8 | value);
 577		} else {
 578			fatal_error("Illegal write to HV Counter port %X\n", vdp_port);
 579		}
 580	} else if (vdp_port < 0x18) {
 581		sync_sound(gen, context->Z80_CYCLE);
 582		psg_write(gen->psg, value);
 583	} else {
 584		vdp_test_port_write(gen->vdp, value);
 585	}
 586	return context;
 587}
 588
 589static uint16_t vdp_port_read(uint32_t vdp_port, m68k_context * context)
 590{
 591	if (vdp_port & 0x2700E0) {
 592		fatal_error("machine freeze due to read from address %X\n", 0xC00000 | vdp_port);
 593	}
 594	vdp_port &= 0x1F;
 595	uint16_t value;
 596#ifdef REFRESH_EMULATION
 597	//do refresh check here so we can avoid adding a penalty for a refresh that happens during a VDP access
 598	refresh_counter += context->current_cycle - 4*MCLKS_PER_68K - last_sync_cycle;
 599	context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL));
 600	refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL);
 601	last_sync_cycle = context->current_cycle;
 602#endif
 603	sync_components(context, 0);
 604	genesis_context *gen = context->system;
 605	vdp_context * v_context = gen->vdp;
 606	uint32_t before_cycle = v_context->cycles;
 607	if (vdp_port < 0x10) {
 608		if (vdp_port < 4) {
 609			value = vdp_data_port_read(v_context);
 610		} else if(vdp_port < 8) {
 611			value = vdp_control_port_read(v_context);
 612		} else {
 613			value = vdp_hv_counter_read(v_context);
 614			//printf("HV Counter: %X at cycle %d\n", value, v_context->cycles);
 615		}
 616	} else if (vdp_port < 0x18){
 617		fatal_error("Illegal read from PSG  port %X\n", vdp_port);
 618	} else {
 619		value = vdp_test_port_read(v_context);
 620	}
 621	if (v_context->cycles != before_cycle) {
 622		//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);
 623		context->current_cycle = v_context->cycles;
 624		//Lock the Z80 out of the bus until the VDP access is complete
 625		genesis_context *gen = context->system;
 626		gen->bus_busy = 1;
 627		sync_z80(gen->z80, v_context->cycles);
 628		gen->bus_busy = 0;
 629	}
 630#ifdef REFRESH_EMULATION
 631	last_sync_cycle -= 4;
 632	//refresh may have happened while we were waiting on the VDP,
 633	//so advance refresh_counter but don't add any delays
 634	refresh_counter += (context->current_cycle - last_sync_cycle);
 635	refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL);
 636	last_sync_cycle = context->current_cycle;
 637#endif
 638	return value;
 639}
 640
 641static uint8_t vdp_port_read_b(uint32_t vdp_port, m68k_context * context)
 642{
 643	uint16_t value = vdp_port_read(vdp_port, context);
 644	if (vdp_port & 1) {
 645		return value;
 646	} else {
 647		return value >> 8;
 648	}
 649}
 650
 651static uint8_t z80_vdp_port_read(uint32_t vdp_port, void * vcontext)
 652{
 653	z80_context * context = vcontext;
 654	if (vdp_port & 0xE0) {
 655		fatal_error("machine freeze due to read from Z80 address %X\n", 0x7F00 | vdp_port);
 656	}
 657	genesis_context * gen = context->system;
 658	//VDP access goes over the 68K bus like a bank area access
 659	//typical delay from bus arbitration
 660	context->Z80_CYCLE += 3 * MCLKS_PER_Z80;
 661	//TODO: add cycle for an access right after a previous one
 662	//TODO: Below cycle time is an estimate based on the time between 68K !BG goes low and Z80 !MREQ goes high
 663	//      Needs a new logic analyzer capture to get the actual delay on the 68K side
 664	gen->m68k->current_cycle += 8 * MCLKS_PER_68K;
 665
 666
 667	vdp_port &= 0x1F;
 668	uint16_t ret;
 669	if (vdp_port < 0x10) {
 670		//These probably won't currently interact well with the 68K accessing the VDP
 671		vdp_run_context(gen->vdp, context->Z80_CYCLE);
 672		if (vdp_port < 4) {
 673			ret = vdp_data_port_read(gen->vdp);
 674		} else if (vdp_port < 8) {
 675			ret = vdp_control_port_read(gen->vdp);
 676		} else {
 677			ret = vdp_hv_counter_read(gen->vdp);
 678		}
 679	} else {
 680		//TODO: Figure out the correct value today
 681		ret = 0xFFFF;
 682	}
 683	return vdp_port & 1 ? ret : ret >> 8;
 684}
 685
 686//TODO: Move this inside the system context
 687static uint32_t zram_counter = 0;
 688
 689static m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value)
 690{
 691	genesis_context * gen = context->system;
 692	if (location < 0x10000) {
 693		//Access to Z80 memory incurs a one 68K cycle wait state
 694		context->current_cycle += MCLKS_PER_68K;
 695		if (!z80_enabled || z80_get_busack(gen->z80, context->current_cycle)) {
 696			location &= 0x7FFF;
 697			if (location < 0x4000) {
 698				gen->zram[location & 0x1FFF] = value;
 699				z80_handle_code_write(location & 0x1FFF, gen->z80);
 700			} else if (location < 0x6000) {
 701				sync_sound(gen, context->current_cycle);
 702				if (location & 1) {
 703					ym_data_write(gen->ym, value);
 704				} else if(location & 2) {
 705					ym_address_write_part2(gen->ym, value);
 706				} else {
 707					ym_address_write_part1(gen->ym, value);
 708				}
 709			} else if (location == 0x6000) {
 710				gen->z80_bank_reg = (gen->z80_bank_reg >> 1 | value << 8) & 0x1FF;
 711				if (gen->z80_bank_reg < 0x80) {
 712					gen->z80->mem_pointers[1] = (gen->z80_bank_reg << 15) + ((char *)gen->z80->mem_pointers[2]);
 713				} else {
 714					gen->z80->mem_pointers[1] = NULL;
 715				}
 716			} else {
 717				fatal_error("68K write to unhandled Z80 address %X\n", location);
 718			}
 719		}
 720	} else {
 721		location &= 0x1FFF;
 722		if (location < 0x100) {
 723			switch(location/2)
 724			{
 725			case 0x1:
 726				io_data_write(gen->io.ports, value, context->current_cycle);
 727				break;
 728			case 0x2:
 729				io_data_write(gen->io.ports+1, value, context->current_cycle);
 730				break;
 731			case 0x3:
 732				io_data_write(gen->io.ports+2, value, context->current_cycle);
 733				break;
 734			case 0x4:
 735				io_control_write(gen->io.ports, value, context->current_cycle);
 736				break;
 737			case 0x5:
 738				io_control_write(gen->io.ports+1, value, context->current_cycle);
 739				break;
 740			case 0x6:
 741				io_control_write(gen->io.ports+2, value, context->current_cycle);
 742				break;
 743			case 0x7:
 744				gen->io.ports[0].serial_out = value;
 745				break;
 746			case 0x8:
 747			case 0xB:
 748			case 0xE:
 749				//serial input port is not writeable
 750				break;
 751			case 0x9:
 752				gen->io.ports[0].serial_ctrl = value;
 753				break;
 754			case 0xA:
 755				gen->io.ports[1].serial_out = value;
 756				break;
 757			case 0xC:
 758				gen->io.ports[1].serial_ctrl = value;
 759				break;
 760			case 0xD:
 761				gen->io.ports[2].serial_out = value;
 762				break;
 763			case 0xF:
 764				gen->io.ports[2].serial_ctrl = value;
 765				break;
 766			}
 767		} else {
 768			if (location == 0x1100) {
 769				if (value & 1) {
 770					dputs("bus requesting Z80");
 771					if (z80_enabled) {
 772						z80_assert_busreq(gen->z80, context->current_cycle);
 773					} else {
 774						gen->z80->busack = 1;
 775					}
 776				} else {
 777					if (gen->z80->busreq) {
 778						dputs("releasing z80 bus");
 779						#ifdef DO_DEBUG_PRINT
 780						char fname[20];
 781						sprintf(fname, "zram-%d", zram_counter++);
 782						FILE * f = fopen(fname, "wb");
 783						fwrite(z80_ram, 1, sizeof(z80_ram), f);
 784						fclose(f);
 785						#endif
 786					}
 787					if (z80_enabled) {
 788						z80_clear_busreq(gen->z80, context->current_cycle);
 789					} else {
 790						gen->z80->busack = 0;
 791					}
 792				}
 793			} else if (location == 0x1200) {
 794				sync_z80(gen->z80, context->current_cycle);
 795				if (value & 1) {
 796					if (z80_enabled) {
 797						z80_clear_reset(gen->z80, context->current_cycle);
 798					} else {
 799						gen->z80->reset = 0;
 800					}
 801				} else {
 802					if (z80_enabled) {
 803						z80_assert_reset(gen->z80, context->current_cycle);
 804					} else {
 805						gen->z80->reset = 1;
 806					}
 807					ym_reset(gen->ym);
 808				}
 809			}
 810		}
 811	}
 812	return context;
 813}
 814
 815static m68k_context * io_write_w(uint32_t location, m68k_context * context, uint16_t value)
 816{
 817	if (location < 0x10000 || (location & 0x1FFF) >= 0x100) {
 818		return io_write(location, context, value >> 8);
 819	} else {
 820		return io_write(location, context, value);
 821	}
 822}
 823
 824#define FOREIGN 0x80
 825#define HZ50 0x40
 826#define USA FOREIGN
 827#define JAP 0x00
 828#define EUR (HZ50|FOREIGN)
 829#define NO_DISK 0x20
 830
 831static uint8_t io_read(uint32_t location, m68k_context * context)
 832{
 833	uint8_t value;
 834	genesis_context *gen = context->system;
 835	if (location < 0x10000) {
 836		//Access to Z80 memory incurs a one 68K cycle wait state
 837		context->current_cycle += MCLKS_PER_68K;
 838		if (!z80_enabled || z80_get_busack(gen->z80, context->current_cycle)) {
 839			location &= 0x7FFF;
 840			if (location < 0x4000) {
 841				value = gen->zram[location & 0x1FFF];
 842			} else if (location < 0x6000) {
 843				sync_sound(gen, context->current_cycle);
 844				value = ym_read_status(gen->ym);
 845			} else {
 846				value = 0xFF;
 847			}
 848		} else {
 849			value = 0xFF;
 850		}
 851	} else {
 852		location &= 0x1FFF;
 853		if (location < 0x100) {
 854			switch(location/2)
 855			{
 856			case 0x0:
 857				//version bits should be 0 for now since we're not emulating TMSS
 858				value = gen->version_reg;
 859				break;
 860			case 0x1:
 861				value = io_data_read(gen->io.ports, context->current_cycle);
 862				break;
 863			case 0x2:
 864				value = io_data_read(gen->io.ports+1, context->current_cycle);
 865				break;
 866			case 0x3:
 867				value = io_data_read(gen->io.ports+2, context->current_cycle);
 868				break;
 869			case 0x4:
 870				value = gen->io.ports[0].control;
 871				break;
 872			case 0x5:
 873				value = gen->io.ports[1].control;
 874				break;
 875			case 0x6:
 876				value = gen->io.ports[2].control;
 877				break;
 878			case 0x7:
 879				value = gen->io.ports[0].serial_out;
 880				break;
 881			case 0x8:
 882				value = gen->io.ports[0].serial_in;
 883				break;
 884			case 0x9:
 885				value = gen->io.ports[0].serial_ctrl;
 886				break;
 887			case 0xA:
 888				value = gen->io.ports[1].serial_out;
 889				break;
 890			case 0xB:
 891				value = gen->io.ports[1].serial_in;
 892				break;
 893			case 0xC:
 894				value = gen->io.ports[1].serial_ctrl;
 895				break;
 896			case 0xD:
 897				value = gen->io.ports[2].serial_out;
 898				break;
 899			case 0xE:
 900				value = gen->io.ports[2].serial_in;
 901				break;
 902			case 0xF:
 903				value = gen->io.ports[2].serial_ctrl;
 904				break;
 905			default:
 906				value = 0xFF;
 907			}
 908		} else {
 909			if (location == 0x1100) {
 910				value = z80_enabled ? !z80_get_busack(gen->z80, context->current_cycle) : !gen->z80->busack;
 911				value |= (get_open_bus_value(&gen->header) >> 8) & 0xFE;
 912				dprintf("Byte read of BUSREQ returned %d @ %d (reset: %d)\n", value, context->current_cycle, gen->z80->reset);
 913			} else if (location == 0x1200) {
 914				value = !gen->z80->reset;
 915			} else {
 916				value = 0xFF;
 917				printf("Byte read of unknown IO location: %X\n", location);
 918			}
 919		}
 920	}
 921	return value;
 922}
 923
 924static uint16_t io_read_w(uint32_t location, m68k_context * context)
 925{
 926	genesis_context *gen = context->system;
 927	uint16_t value = io_read(location, context);
 928	if (location < 0x10000 || (location & 0x1FFF) < 0x100) {
 929		value = value | (value << 8);
 930	} else {
 931		value <<= 8;
 932		value |= get_open_bus_value(&gen->header) & 0xFF;
 933	}
 934	return value;
 935}
 936
 937static void * z80_write_ym(uint32_t location, void * vcontext, uint8_t value)
 938{
 939	z80_context * context = vcontext;
 940	genesis_context * gen = context->system;
 941	sync_sound(gen, context->Z80_CYCLE);
 942	if (location & 1) {
 943		ym_data_write(gen->ym, value);
 944	} else if (location & 2) {
 945		ym_address_write_part2(gen->ym, value);
 946	} else {
 947		ym_address_write_part1(gen->ym, value);
 948	}
 949	return context;
 950}
 951
 952static uint8_t z80_read_ym(uint32_t location, void * vcontext)
 953{
 954	z80_context * context = vcontext;
 955	genesis_context * gen = context->system;
 956	sync_sound(gen, context->Z80_CYCLE);
 957	return ym_read_status(gen->ym);
 958}
 959
 960static uint8_t z80_read_bank(uint32_t location, void * vcontext)
 961{
 962	z80_context * context = vcontext;
 963	genesis_context *gen = context->system;
 964	if (gen->bus_busy) {
 965		context->Z80_CYCLE = gen->m68k->current_cycle;
 966	}
 967	//typical delay from bus arbitration
 968	context->Z80_CYCLE += 3 * MCLKS_PER_Z80;
 969	//TODO: add cycle for an access right after a previous one
 970	//TODO: Below cycle time is an estimate based on the time between 68K !BG goes low and Z80 !MREQ goes high
 971	//      Needs a new logic analyzer capture to get the actual delay on the 68K side
 972	gen->m68k->current_cycle += 8 * MCLKS_PER_68K;
 973
 974	location &= 0x7FFF;
 975	if (context->mem_pointers[1]) {
 976		return context->mem_pointers[1][location ^ 1];
 977	}
 978	uint32_t address = gen->z80_bank_reg << 15 | location;
 979	if (address >= 0xC00000 && address < 0xE00000) {
 980		return z80_vdp_port_read(location & 0xFF, context);
 981	} else {
 982		fprintf(stderr, "Unhandled read by Z80 from address %X through banked memory area (%X)\n", address, gen->z80_bank_reg << 15);
 983	}
 984	return 0;
 985}
 986
 987static void *z80_write_bank(uint32_t location, void * vcontext, uint8_t value)
 988{
 989	z80_context * context = vcontext;
 990	genesis_context *gen = context->system;
 991	if (gen->bus_busy) {
 992		context->Z80_CYCLE = gen->m68k->current_cycle;
 993	}
 994	//typical delay from bus arbitration
 995	context->Z80_CYCLE += 3 * MCLKS_PER_Z80;
 996	//TODO: add cycle for an access right after a previous one
 997	//TODO: Below cycle time is an estimate based on the time between 68K !BG goes low and Z80 !MREQ goes high
 998	//      Needs a new logic analyzer capture to get the actual delay on the 68K side
 999	gen->m68k->current_cycle += 8 * MCLKS_PER_68K;
1000
1001	location &= 0x7FFF;
1002	uint32_t address = gen->z80_bank_reg << 15 | location;
1003	if (address >= 0xE00000) {
1004		address &= 0xFFFF;
1005		((uint8_t *)gen->work_ram)[address ^ 1] = value;
1006	} else if (address >= 0xC00000) {
1007		z80_vdp_port_write(location & 0xFF, context, value);
1008	} else {
1009		fprintf(stderr, "Unhandled write by Z80 to address %X through banked memory area\n", address);
1010	}
1011	return context;
1012}
1013
1014static void *z80_write_bank_reg(uint32_t location, void * vcontext, uint8_t value)
1015{
1016	z80_context * context = vcontext;
1017	genesis_context *gen = context->system;
1018
1019	gen->z80_bank_reg = (gen->z80_bank_reg >> 1 | value << 8) & 0x1FF;
1020	update_z80_bank_pointer(context->system);
1021
1022	return context;
1023}
1024
1025static void set_speed_percent(system_header * system, uint32_t percent)
1026{
1027	genesis_context *context = (genesis_context *)system;
1028	uint32_t old_clock = context->master_clock;
1029	context->master_clock = ((uint64_t)context->normal_clock * (uint64_t)percent) / 100;
1030	while (context->ym->current_cycle != context->psg->cycles) {
1031		sync_sound(context, context->psg->cycles + MCLKS_PER_PSG);
1032	}
1033	ym_adjust_master_clock(context->ym, context->master_clock);
1034	psg_adjust_master_clock(context->psg, context->master_clock);
1035}
1036
1037void set_region(genesis_context *gen, rom_info *info, uint8_t region)
1038{
1039	if (!region) {
1040		char * def_region = tern_find_path_default(config, "system\0default_region\0", (tern_val){.ptrval = "U"}, TVAL_PTR).ptrval;
1041		if (!info->regions || (info->regions & translate_region_char(toupper(*def_region)))) {
1042			region = translate_region_char(toupper(*def_region));
1043		} else {
1044			region = info->regions;
1045		}
1046	}
1047	if (region & REGION_E) {
1048		gen->version_reg = NO_DISK | EUR;
1049	} else if (region & REGION_J) {
1050		gen->version_reg = NO_DISK | JAP;
1051	} else {
1052		gen->version_reg = NO_DISK | USA;
1053	}
1054	
1055	if (region & HZ50) {
1056		gen->normal_clock = MCLKS_PAL;
1057	} else {
1058		gen->normal_clock = MCLKS_NTSC;
1059	}
1060	gen->master_clock = gen->normal_clock;
1061}
1062
1063static uint8_t load_state(system_header *system, uint8_t slot)
1064{
1065	genesis_context *gen = (genesis_context *)system;
1066	char *statepath = get_slot_name(system, slot, "state");
1067	deserialize_buffer state;
1068	uint32_t pc = 0;
1069	uint8_t ret;
1070	if (!gen->m68k->resume_pc) {
1071		system->delayed_load_slot = slot + 1;
1072		gen->m68k->should_return = 1;
1073		ret = get_modification_time(statepath) != 0;
1074		if (!ret) {
1075			strcpy(statepath + strlen(statepath)-strlen("state"), "gst");
1076			ret = get_modification_time(statepath) != 0;
1077		}
1078		goto done;
1079	}
1080	if (load_from_file(&state, statepath)) {
1081		genesis_deserialize(&state, gen);
1082		free(state.data);
1083		//HACK
1084		pc = gen->m68k->last_prefetch_address;
1085		ret = 1;
1086	} else {
1087		strcpy(statepath + strlen(statepath)-strlen("state"), "gst");
1088		pc = load_gst(gen, statepath);
1089		ret = pc != 0;
1090	}
1091	if (ret) {
1092		gen->m68k->resume_pc = get_native_address_trans(gen->m68k, pc);
1093	}
1094done:
1095	free(statepath);
1096	return ret;
1097}
1098
1099static void handle_reset_requests(genesis_context *gen)
1100{
1101	while (gen->reset_requested || gen->header.delayed_load_slot)
1102	{
1103		if (gen->reset_requested) {
1104			gen->reset_requested = 0;
1105			gen->m68k->should_return = 0;
1106			z80_assert_reset(gen->z80, gen->m68k->current_cycle);
1107			z80_clear_busreq(gen->z80, gen->m68k->current_cycle);
1108			ym_reset(gen->ym);
1109			//Is there any sort of VDP reset?
1110			m68k_reset(gen->m68k);
1111		}
1112		if (gen->header.delayed_load_slot) {
1113			load_state(&gen->header, gen->header.delayed_load_slot - 1);
1114			gen->header.delayed_load_slot = 0;
1115			resume_68k(gen->m68k);
1116		}
1117	}
1118	bindings_release_capture();
1119	vdp_release_framebuffer(gen->vdp);
1120	render_pause_source(gen->ym->audio);
1121	render_pause_source(gen->psg->audio);
1122}
1123
1124static void start_genesis(system_header *system, char *statefile)
1125{
1126	genesis_context *gen = (genesis_context *)system;
1127	if (statefile) {
1128		//first try loading as a native format savestate
1129		deserialize_buffer state;
1130		uint32_t pc;
1131		if (load_from_file(&state, statefile)) {
1132			genesis_deserialize(&state, gen);
1133			free(state.data);
1134			//HACK
1135			pc = gen->m68k->last_prefetch_address;
1136		} else {
1137			pc = load_gst(gen, statefile);
1138			if (!pc) {
1139				fatal_error("Failed to load save state %s\n", statefile);
1140			}
1141		}
1142		printf("Loaded %s\n", statefile);
1143		if (gen->header.enter_debugger) {
1144			gen->header.enter_debugger = 0;
1145			insert_breakpoint(gen->m68k, pc, gen->header.debugger_type == DEBUGGER_NATIVE ? debugger : gdb_debug_enter);
1146		}
1147		adjust_int_cycle(gen->m68k, gen->vdp);
1148		start_68k_context(gen->m68k, pc);
1149	} else {
1150		if (gen->header.enter_debugger) {
1151			gen->header.enter_debugger = 0;
1152			uint32_t address = gen->cart[2] << 16 | gen->cart[3];
1153			insert_breakpoint(gen->m68k, address, gen->header.debugger_type == DEBUGGER_NATIVE ? debugger : gdb_debug_enter);
1154		}
1155		m68k_reset(gen->m68k);
1156	}
1157	handle_reset_requests(gen);
1158	return;
1159}
1160
1161static void resume_genesis(system_header *system)
1162{
1163	genesis_context *gen = (genesis_context *)system;
1164	render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC);
1165	bindings_reacquire_capture();
1166	vdp_reacquire_framebuffer(gen->vdp);
1167	render_resume_source(gen->ym->audio);
1168	render_resume_source(gen->psg->audio);
1169	resume_68k(gen->m68k);
1170	handle_reset_requests(gen);
1171}
1172
1173static void inc_debug_mode(system_header *system)
1174{
1175	genesis_context *gen = (genesis_context *)system;
1176	vdp_inc_debug_mode(gen->vdp);
1177}
1178
1179static void request_exit(system_header *system)
1180{
1181	genesis_context *gen = (genesis_context *)system;
1182	gen->m68k->target_cycle = gen->m68k->current_cycle;
1183	gen->m68k->should_return = 1;
1184}
1185
1186static void persist_save(system_header *system)
1187{
1188	genesis_context *gen = (genesis_context *)system;
1189	if (gen->save_type == SAVE_NONE) {
1190		return;
1191	}
1192	FILE * f = fopen(save_filename, "wb");
1193	if (!f) {
1194		fprintf(stderr, "Failed to open %s file %s for writing\n", save_type_name(gen->save_type), save_filename);
1195		return;
1196	}
1197	fwrite(gen->save_storage, 1, gen->save_size, f);
1198	fclose(f);
1199	printf("Saved %s to %s\n", save_type_name(gen->save_type), save_filename);
1200}
1201
1202static void load_save(system_header *system)
1203{
1204	genesis_context *gen = (genesis_context *)system;
1205	FILE * f = fopen(save_filename, "rb");
1206	if (f) {
1207		uint32_t read = fread(gen->save_storage, 1, gen->save_size, f);
1208		fclose(f);
1209		if (read > 0) {
1210			printf("Loaded %s from %s\n", save_type_name(gen->save_type), save_filename);
1211		}
1212	}
1213}
1214
1215static void soft_reset(system_header *system)
1216{
1217	genesis_context *gen = (genesis_context *)system;
1218	if (gen->reset_cycle == CYCLE_NEVER) {
1219		double random = (double)rand()/(double)RAND_MAX;
1220		gen->reset_cycle = gen->m68k->current_cycle + random * MCLKS_LINE * (gen->version_reg & HZ50 ? LINES_PAL : LINES_NTSC);
1221		if (gen->reset_cycle < gen->m68k->target_cycle) {
1222			gen->m68k->target_cycle = gen->reset_cycle;
1223		}
1224	}
1225}
1226
1227static void free_genesis(system_header *system)
1228{
1229	genesis_context *gen = (genesis_context *)system;
1230	vdp_free(gen->vdp);
1231	memmap_chunk *map = (memmap_chunk *)gen->m68k->options->gen.memmap;
1232	m68k_options_free(gen->m68k->options);
1233	free(gen->cart);
1234	free(gen->m68k);
1235	free(gen->work_ram);
1236	z80_options_free(gen->z80->Z80_OPTS);
1237	free(gen->z80);
1238	free(gen->zram);
1239	ym_free(gen->ym);
1240	psg_free(gen->psg);
1241	free(gen->header.save_dir);
1242	free_rom_info(&gen->header.info);
1243	free(gen->lock_on);
1244	free(gen);
1245}
1246
1247static void gamepad_down(system_header *system, uint8_t gamepad_num, uint8_t button)
1248{
1249	genesis_context *gen = (genesis_context *)system;
1250	io_gamepad_down(&gen->io, gamepad_num, button);
1251	if (gen->mapper_type == MAPPER_JCART) {
1252		jcart_gamepad_down(gen, gamepad_num, button);
1253	}
1254}
1255
1256static void gamepad_up(system_header *system, uint8_t gamepad_num, uint8_t button)
1257{
1258	genesis_context *gen = (genesis_context *)system;
1259	io_gamepad_up(&gen->io, gamepad_num, button);
1260	if (gen->mapper_type == MAPPER_JCART) {
1261		jcart_gamepad_up(gen, gamepad_num, button);
1262	}
1263}
1264
1265static void mouse_down(system_header *system, uint8_t mouse_num, uint8_t button)
1266{
1267	genesis_context *gen = (genesis_context *)system;
1268	io_mouse_down(&gen->io, mouse_num, button);
1269}
1270
1271static void mouse_up(system_header *system, uint8_t mouse_num, uint8_t button)
1272{
1273	genesis_context *gen = (genesis_context *)system;
1274	io_mouse_up(&gen->io, mouse_num, button);
1275}
1276
1277static void mouse_motion_absolute(system_header *system, uint8_t mouse_num, uint16_t x, uint16_t y)
1278{
1279	genesis_context *gen = (genesis_context *)system;
1280	io_mouse_motion_absolute(&gen->io, mouse_num, x, y);
1281}
1282
1283static void mouse_motion_relative(system_header *system, uint8_t mouse_num, int32_t x, int32_t y)
1284{
1285	genesis_context *gen = (genesis_context *)system;
1286	io_mouse_motion_relative(&gen->io, mouse_num, x, y);
1287}
1288
1289static void keyboard_down(system_header *system, uint8_t scancode)
1290{
1291	genesis_context *gen = (genesis_context *)system;
1292	io_keyboard_down(&gen->io, scancode);
1293}
1294
1295static void keyboard_up(system_header *system, uint8_t scancode)
1296{
1297	genesis_context *gen = (genesis_context *)system;
1298	io_keyboard_up(&gen->io, scancode);
1299}
1300
1301static void set_audio_config(genesis_context *gen)
1302{
1303	char *config_gain;
1304	config_gain = tern_find_path(config, "audio\0psg_gain\0", TVAL_PTR).ptrval;
1305	render_audio_source_gaindb(gen->psg->audio, config_gain ? atof(config_gain) : 0.0f);
1306	config_gain = tern_find_path(config, "audio\0fm_gain\0", TVAL_PTR).ptrval;
1307	render_audio_source_gaindb(gen->ym->audio, config_gain ? atof(config_gain) : 0.0f);
1308	
1309	char *config_dac = tern_find_path_default(config, "audio\0fm_dac\0", (tern_val){.ptrval="zero_offset"}, TVAL_PTR).ptrval;
1310	ym_enable_zero_offset(gen->ym, !strcmp(config_dac, "zero_offset"));
1311}
1312
1313static void config_updated(system_header *system)
1314{
1315	genesis_context *gen = (genesis_context *)system;
1316	setup_io_devices(config, &system->info, &gen->io);
1317	set_audio_config(gen);
1318}
1319
1320genesis_context *alloc_init_genesis(rom_info *rom, void *main_rom, void *lock_on, uint32_t system_opts, uint8_t force_region)
1321{
1322	static memmap_chunk z80_map[] = {
1323		{ 0x0000, 0x4000,  0x1FFF, 0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, NULL, NULL, NULL, NULL,              NULL },
1324		{ 0x8000, 0x10000, 0x7FFF, 0, 0, 0,                                  NULL, NULL, NULL, z80_read_bank,     z80_write_bank},
1325		{ 0x4000, 0x6000,  0x0003, 0, 0, 0,                                  NULL, NULL, NULL, z80_read_ym,       z80_write_ym},
1326		{ 0x6000, 0x6100,  0xFFFF, 0, 0, 0,                                  NULL, NULL, NULL, NULL,              z80_write_bank_reg},
1327		{ 0x7F00, 0x8000,  0x00FF, 0, 0, 0,                                  NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write}
1328	};
1329	genesis_context *gen = calloc(1, sizeof(genesis_context));
1330	gen->header.set_speed_percent = set_speed_percent;
1331	gen->header.start_context = start_genesis;
1332	gen->header.resume_context = resume_genesis;
1333	gen->header.load_save = load_save;
1334	gen->header.persist_save = persist_save;
1335	gen->header.load_state = load_state;
1336	gen->header.soft_reset = soft_reset;
1337	gen->header.free_context = free_genesis;
1338	gen->header.get_open_bus_value = get_open_bus_value;
1339	gen->header.request_exit = request_exit;
1340	gen->header.inc_debug_mode = inc_debug_mode;
1341	gen->header.gamepad_down = gamepad_down;
1342	gen->header.gamepad_up = gamepad_up;
1343	gen->header.mouse_down = mouse_down;
1344	gen->header.mouse_up = mouse_up;
1345	gen->header.mouse_motion_absolute = mouse_motion_absolute;
1346	gen->header.mouse_motion_relative = mouse_motion_relative;
1347	gen->header.keyboard_down = keyboard_down;
1348	gen->header.keyboard_up = keyboard_up;
1349	gen->header.config_updated = config_updated;
1350	gen->header.serialize = serialize;
1351	gen->header.deserialize = deserialize;
1352	gen->header.type = SYSTEM_GENESIS;
1353	gen->header.info = *rom;
1354	set_region(gen, rom, force_region);
1355
1356	gen->vdp = init_vdp_context(gen->version_reg & 0x40);
1357	gen->vdp->system = &gen->header;
1358	gen->frame_end = vdp_cycles_to_frame_end(gen->vdp);
1359	char * config_cycles = tern_find_path(config, "clocks\0max_cycles\0", TVAL_PTR).ptrval;
1360	gen->max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL;
1361	gen->int_latency_prev1 = MCLKS_PER_68K * 32;
1362	gen->int_latency_prev2 = MCLKS_PER_68K * 16;
1363	
1364	render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC);
1365	
1366	gen->ym = malloc(sizeof(ym2612_context));
1367	ym_init(gen->ym, gen->master_clock, MCLKS_PER_YM, system_opts);
1368
1369	gen->psg = malloc(sizeof(psg_context));
1370	psg_init(gen->psg, gen->master_clock, MCLKS_PER_PSG);
1371	
1372	set_audio_config(gen);
1373
1374	z80_map[0].buffer = gen->zram = calloc(1, Z80_RAM_BYTES);
1375	z80_options *z_opts = malloc(sizeof(z80_options));
1376	init_z80_opts(z_opts, z80_map, 5, NULL, 0, MCLKS_PER_Z80, 0xFFFF);
1377	gen->z80 = init_z80_context(z_opts);
1378	gen->z80->next_int_pulse = z80_next_int_pulse;
1379	z80_assert_reset(gen->z80, 0);
1380
1381	gen->z80->system = gen;
1382	gen->z80->mem_pointers[0] = gen->zram;
1383	gen->z80->mem_pointers[1] = gen->z80->mem_pointers[2] = (uint8_t *)main_rom;
1384
1385	gen->cart = main_rom;
1386	gen->lock_on = lock_on;
1387	gen->work_ram = calloc(2, RAM_WORDS);
1388	if (!strcmp("random", tern_find_path_default(config, "system\0ram_init\0", (tern_val){.ptrval = "zero"}, TVAL_PTR).ptrval))
1389	{
1390		srand(time(NULL));
1391		for (int i = 0; i < RAM_WORDS; i++)
1392		{
1393			gen->work_ram[i] = rand();
1394		}
1395		for (int i = 0; i < Z80_RAM_BYTES; i++)
1396		{
1397			gen->zram[i] = rand();
1398		}
1399		for (int i = 0; i < VRAM_SIZE; i++)
1400		{
1401			gen->vdp->vdpmem[i] = rand();
1402		}
1403		for (int i = 0; i < SAT_CACHE_SIZE; i++)
1404		{
1405			gen->vdp->sat_cache[i] = rand();
1406		}
1407		for (int i = 0; i < CRAM_SIZE; i++)
1408		{
1409			write_cram_internal(gen->vdp, i, rand());
1410		}
1411		for (int i = 0; i < VSRAM_SIZE; i++)
1412		{
1413			gen->vdp->vsram[i] = rand();
1414		}
1415	}
1416	setup_io_devices(config, rom, &gen->io);
1417	gen->header.has_keyboard = io_has_keyboard(&gen->io);
1418
1419	gen->mapper_type = rom->mapper_type;
1420	gen->save_type = rom->save_type;
1421	if (gen->save_type != SAVE_NONE) {
1422		gen->save_ram_mask = rom->save_mask;
1423		gen->save_size = rom->save_size;
1424		gen->save_storage = rom->save_buffer;
1425		gen->eeprom_map = rom->eeprom_map;
1426		gen->num_eeprom = rom->num_eeprom;
1427		if (gen->save_type == SAVE_I2C) {
1428			eeprom_init(&gen->eeprom, gen->save_storage, gen->save_size);
1429		} else if (gen->save_type == SAVE_NOR) {
1430			memcpy(&gen->nor, rom->nor, sizeof(gen->nor));
1431			//nor_flash_init(&gen->nor, gen->save_storage, gen->save_size, rom->save_page_size, rom->save_product_id, rom->save_bus);
1432		}
1433	} else {
1434		gen->save_storage = NULL;
1435	}
1436	
1437	//This must happen before we generate memory access functions in init_m68k_opts
1438	for (int i = 0; i < rom->map_chunks; i++)
1439	{
1440		if (rom->map[i].start == 0xE00000) {
1441			rom->map[i].buffer = gen->work_ram;
1442			break;
1443		}
1444	}
1445
1446	m68k_options *opts = malloc(sizeof(m68k_options));
1447	init_m68k_opts(opts, rom->map, rom->map_chunks, MCLKS_PER_68K);
1448	//TODO: make this configurable
1449	opts->gen.flags |= M68K_OPT_BROKEN_READ_MODIFY;
1450	gen->m68k = init_68k_context(opts, NULL);
1451	gen->m68k->system = gen;
1452	opts->address_log = (system_opts & OPT_ADDRESS_LOG) ? fopen("address.log", "w") : NULL;
1453	
1454	//This must happen after the 68K context has been allocated
1455	for (int i = 0; i < rom->map_chunks; i++)
1456	{
1457		if (rom->map[i].flags & MMAP_PTR_IDX) {
1458			gen->m68k->mem_pointers[rom->map[i].ptr_index] = rom->map[i].buffer;
1459		}
1460	}
1461	
1462	if (gen->mapper_type == MAPPER_SEGA) {
1463		//initialize bank registers
1464		for (int i = 1; i < sizeof(gen->bank_regs); i++)
1465		{
1466			gen->bank_regs[i] = i;
1467		}
1468	}
1469
1470	return gen;
1471}
1472
1473genesis_context *alloc_config_genesis(void *rom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, uint32_t ym_opts, uint8_t force_region)
1474{
1475	static memmap_chunk base_map[] = {
1476		{0xE00000, 0x1000000, 0xFFFF,   0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, NULL,
1477		           NULL,          NULL,         NULL,            NULL},
1478		{0xC00000, 0xE00000,  0x1FFFFF, 0, 0, 0,                                  NULL,
1479		           (read_16_fun)vdp_port_read,  (write_16_fun)vdp_port_write,
1480		           (read_8_fun)vdp_port_read_b, (write_8_fun)vdp_port_write_b},
1481		{0xA00000, 0xA12000,  0x1FFFF,  0, 0, 0,                                  NULL,
1482		           (read_16_fun)io_read_w,      (write_16_fun)io_write_w,
1483		           (read_8_fun)io_read,         (write_8_fun)io_write}
1484	};
1485	static tern_node *rom_db;
1486	if (!rom_db) {
1487		rom_db = load_rom_db();
1488	}
1489	rom_info info = configure_rom(rom_db, rom, rom_size, lock_on, lock_on_size, base_map, sizeof(base_map)/sizeof(base_map[0]));
1490	rom = info.rom;
1491	rom_size = info.rom_size;
1492#ifndef BLASTEM_BIG_ENDIAN
1493	byteswap_rom(rom_size, rom);
1494	if (lock_on) {
1495		byteswap_rom(lock_on_size, lock_on);
1496	}
1497#endif
1498	char *m68k_divider = tern_find_path(config, "clocks\0m68k_divider\0", TVAL_PTR).ptrval;
1499	if (!m68k_divider) {
1500		m68k_divider = "7";
1501	}
1502	MCLKS_PER_68K = atoi(m68k_divider);
1503	if (!MCLKS_PER_68K) {
1504		MCLKS_PER_68K = 7;
1505	}
1506	return alloc_init_genesis(&info, rom, lock_on, ym_opts, force_region);
1507}