main sms.c
  1#include <string.h>
  2#include <stdlib.h>
  3#include <stddef.h>
  4#include "sms.h"
  5#include "blastem.h"
  6#include "render.h"
  7#include "util.h"
  8#include "debug.h"
  9#include "saves.h"
 10#include "bindings.h"
 11
 12#define Z80_CYCLE current_cycle
 13#define Z80_OPTS options
 14
 15static void *memory_io_write(uint32_t location, void *vcontext, uint8_t value)
 16{
 17	z80_context *z80 = vcontext;
 18	sms_context *sms = z80->system;
 19	if (location & 1) {
 20		uint8_t fuzzy_ctrl_0 = sms->io.ports[0].control, fuzzy_ctrl_1 = sms->io.ports[1].control;
 21		io_control_write(sms->io.ports, (~value) << 5 & 0x60, z80->Z80_CYCLE);
 22		fuzzy_ctrl_0 |= sms->io.ports[0].control;
 23		io_control_write(sms->io.ports+1, (~value) << 3 & 0x60, z80->Z80_CYCLE);
 24		fuzzy_ctrl_1 |= sms->io.ports[1].control;
 25		if (
 26			(fuzzy_ctrl_0 & 0x40 & (sms->io.ports[0].output ^ (value << 1)) & (value << 1))
 27			|| (fuzzy_ctrl_0 & 0x40 & (sms->io.ports[1].output ^ (value >> 1)) & (value >> 1))
 28		) {
 29			//TH is an output and it went from 0 -> 1
 30			vdp_run_context(sms->vdp, z80->Z80_CYCLE);
 31			vdp_latch_hv(sms->vdp);
 32		}
 33		io_data_write(sms->io.ports, value << 1, z80->Z80_CYCLE);
 34		io_data_write(sms->io.ports + 1, value >> 1, z80->Z80_CYCLE);
 35	} else {
 36		//TODO: memory control write
 37	}
 38	return vcontext;
 39}
 40
 41static uint8_t hv_read(uint32_t location, void *vcontext)
 42{
 43	z80_context *z80 = vcontext;
 44	sms_context *sms = z80->system;
 45	vdp_run_context(sms->vdp, z80->Z80_CYCLE);
 46	uint16_t hv = vdp_hv_counter_read(sms->vdp);
 47	if (location & 1) {
 48		return hv;
 49	} else {
 50		return hv >> 8;
 51	}
 52}
 53
 54static void *sms_psg_write(uint32_t location, void *vcontext, uint8_t value)
 55{
 56	z80_context *z80 = vcontext;
 57	sms_context *sms = z80->system;
 58	psg_run(sms->psg, z80->Z80_CYCLE);
 59	psg_write(sms->psg, value);
 60	return vcontext;
 61}
 62
 63static void update_interrupts(sms_context *sms)
 64{
 65	uint32_t vint = vdp_next_vint(sms->vdp);
 66	uint32_t hint = vdp_next_hint(sms->vdp);
 67	sms->z80->int_pulse_start = vint < hint ? vint : hint;
 68}
 69
 70static uint8_t vdp_read(uint32_t location, void *vcontext)
 71{
 72	z80_context *z80 = vcontext;
 73	sms_context *sms = z80->system;
 74	vdp_run_context(sms->vdp, z80->Z80_CYCLE);
 75	if (location & 1) {
 76		uint8_t ret = vdp_control_port_read(sms->vdp);
 77		sms->vdp->flags2 &= ~(FLAG2_VINT_PENDING|FLAG2_HINT_PENDING);
 78		update_interrupts(sms);
 79		return ret;
 80	} else {
 81		return vdp_data_port_read_pbc(sms->vdp);
 82	}
 83}
 84
 85static void *vdp_write(uint32_t location, void *vcontext, uint8_t value)
 86{
 87	z80_context *z80 = vcontext;
 88	sms_context *sms = z80->system;
 89	if (location & 1) {
 90		vdp_run_context_full(sms->vdp, z80->Z80_CYCLE);
 91		vdp_control_port_write_pbc(sms->vdp, value);
 92		update_interrupts(sms);
 93	} else {
 94		vdp_run_context(sms->vdp, z80->Z80_CYCLE);
 95		vdp_data_port_write_pbc(sms->vdp, value);
 96	}
 97	return vcontext;
 98}
 99
100static uint8_t io_read(uint32_t location, void *vcontext)
101{
102	z80_context *z80 = vcontext;
103	sms_context *sms = z80->system;
104	if (location == 0xC0 || location == 0xDC) {
105		uint8_t port_a = io_data_read(sms->io.ports, z80->Z80_CYCLE);
106		uint8_t port_b = io_data_read(sms->io.ports+1, z80->Z80_CYCLE);
107		return (port_a & 0x3F) | (port_b << 6);
108	}
109	if (location == 0xC1 || location == 0xDD) {
110		uint8_t port_a = io_data_read(sms->io.ports, z80->Z80_CYCLE);
111		uint8_t port_b = io_data_read(sms->io.ports+1, z80->Z80_CYCLE);
112		return (port_a & 0x40) | (port_b >> 2 & 0xF) | (port_b << 1 & 0x80) | 0x10;
113	}
114	return 0xFF;
115}
116
117static void update_mem_map(uint32_t location, sms_context *sms, uint8_t value)
118{
119	z80_context *z80 = sms->z80;
120	void *old_value;
121	if (location) {
122		uint32_t idx = location - 1;
123		old_value = z80->mem_pointers[idx];
124		z80->mem_pointers[idx] = sms->rom + (value << 14 & (sms->rom_size-1));
125		if (old_value != z80->mem_pointers[idx]) {
126			//invalidate any code we translated for the relevant bank
127			z80_invalidate_code_range(z80, idx ? idx * 0x4000 : 0x400, idx * 0x4000 + 0x4000);
128		}
129	} else {
130		old_value = z80->mem_pointers[2];
131		if (value & 8) {
132			//cartridge RAM is enabled
133			z80->mem_pointers[2] = sms->cart_ram + (value & 4 ? (SMS_CART_RAM_SIZE/2) : 0);
134		} else {
135			//cartridge RAM is disabled
136			z80->mem_pointers[2] = sms->rom + (sms->bank_regs[3] << 14 & (sms->rom_size-1));
137		}
138		if (old_value != z80->mem_pointers[2]) {
139			//invalidate any code we translated for the relevant bank
140			z80_invalidate_code_range(z80, 0x8000, 0xC000);
141		}
142	}
143}
144
145static void *mapper_write(uint32_t location, void *vcontext, uint8_t value)
146{
147	z80_context *z80 = vcontext;
148	sms_context *sms = z80->system;
149	location &= 3;
150	sms->ram[0x1FFC + location] = value;
151	sms->bank_regs[location] = value;
152	update_mem_map(location, sms, value);
153	return vcontext;
154}
155
156static void *cart_ram_write(uint32_t location, void *vcontext, uint8_t value)
157{
158	z80_context *z80 = vcontext;
159	sms_context *sms = z80->system;
160	if (sms->bank_regs[0] & 8) {
161		//cartridge RAM is enabled
162		location &= 0x3FFF;
163		z80->mem_pointers[2][location] = value;
164		z80_handle_code_write(0x8000 + location, z80);
165	}
166	return vcontext;
167}
168
169uint8_t debug_commands(system_header *system, char *input_buf)
170{
171	sms_context *sms = (sms_context *)system;
172	switch(input_buf[0])
173	{
174	case 'v':
175		if (input_buf[1] == 'r') {
176			vdp_print_reg_explain(sms->vdp);
177		} else if (input_buf[1] == 's') {
178			vdp_print_sprite_table(sms->vdp);
179		} else {
180			return 0;
181		}
182		break;
183	}
184	return 1;
185}
186
187static memmap_chunk io_map[] = {
188	{0x00, 0x40, 0xFF, 0, 0, 0, NULL, NULL, NULL, NULL,     memory_io_write},
189	{0x40, 0x80, 0xFF, 0, 0, 0, NULL, NULL, NULL, hv_read,  sms_psg_write},
190	{0x80, 0xC0, 0xFF, 0, 0, 0, NULL, NULL, NULL, vdp_read, vdp_write},
191	{0xC0, 0x100,0xFF, 0, 0, 0, NULL, NULL, NULL, io_read,  NULL}
192};
193
194static void set_speed_percent(system_header * system, uint32_t percent)
195{
196	sms_context *context = (sms_context *)system;
197	uint32_t old_clock = context->master_clock;
198	context->master_clock = ((uint64_t)context->normal_clock * (uint64_t)percent) / 100;
199
200	psg_adjust_master_clock(context->psg, context->master_clock);
201}
202
203void sms_serialize(sms_context *sms, serialize_buffer *buf)
204{
205	start_section(buf, SECTION_Z80);
206	z80_serialize(sms->z80, buf);
207	end_section(buf);
208	
209	start_section(buf, SECTION_VDP);
210	vdp_serialize(sms->vdp, buf);
211	end_section(buf);
212	
213	start_section(buf, SECTION_PSG);
214	psg_serialize(sms->psg, buf);
215	end_section(buf);
216	
217	start_section(buf, SECTION_SEGA_IO_1);
218	io_serialize(sms->io.ports, buf);
219	end_section(buf);
220	
221	start_section(buf, SECTION_SEGA_IO_2);
222	io_serialize(sms->io.ports + 1, buf);
223	end_section(buf);
224	
225	start_section(buf, SECTION_MAIN_RAM);
226	save_int8(buf, sizeof(sms->ram) / 1024);
227	save_buffer8(buf, sms->ram, sizeof(sms->ram));
228	end_section(buf);
229	
230	start_section(buf, SECTION_MAPPER);
231	save_int8(buf, 1);//mapper type, 1 for Sega mapper
232	save_buffer8(buf, sms->bank_regs, sizeof(sms->bank_regs));
233	end_section(buf);
234	
235	start_section(buf, SECTION_CART_RAM);
236	save_int8(buf, SMS_CART_RAM_SIZE / 1024);
237	save_buffer8(buf, sms->cart_ram, SMS_CART_RAM_SIZE);
238	end_section(buf);
239}
240
241static uint8_t *serialize(system_header *sys, size_t *size_out)
242{
243	sms_context *sms = (sms_context *)sys;
244	serialize_buffer state;
245	init_serialize(&state);
246	sms_serialize(sms, &state);
247	if (size_out) {
248		*size_out = state.size;
249	}
250	return state.data;
251}
252
253static void ram_deserialize(deserialize_buffer *buf, void *vsms)
254{
255	sms_context *sms = vsms;
256	uint32_t ram_size = load_int8(buf) * 1024;
257	if (ram_size > sizeof(sms->ram)) {
258		fatal_error("State has a RAM size of %d bytes", ram_size);
259	}
260	load_buffer8(buf, sms->ram, ram_size);
261}
262
263static void cart_ram_deserialize(deserialize_buffer *buf, void *vsms)
264{
265	sms_context *sms = vsms;
266	uint32_t ram_size = load_int8(buf) * 1024;
267	if (ram_size > SMS_CART_RAM_SIZE) {
268		fatal_error("State has a cart RAM size of %d bytes", ram_size);
269	}
270	load_buffer8(buf, sms->cart_ram, ram_size);
271}
272
273static void mapper_deserialize(deserialize_buffer *buf, void *vsms)
274{
275	sms_context *sms = vsms;
276	uint8_t mapper_type = load_int8(buf);
277	if (mapper_type != 1) {
278		warning("State contains an unrecognized mapper type %d, it may be from a newer version of BlastEm\n", mapper_type);
279		return;
280	}
281	for (int i = 0; i < sizeof(sms->bank_regs); i++)
282	{
283		sms->bank_regs[i] = load_int8(buf);
284		update_mem_map(i, sms, sms->bank_regs[i]);
285	}
286}
287
288void sms_deserialize(deserialize_buffer *buf, sms_context *sms)
289{
290	register_section_handler(buf, (section_handler){.fun = z80_deserialize, .data = sms->z80}, SECTION_Z80);
291	register_section_handler(buf, (section_handler){.fun = vdp_deserialize, .data = sms->vdp}, SECTION_VDP);
292	register_section_handler(buf, (section_handler){.fun = psg_deserialize, .data = sms->psg}, SECTION_PSG);
293	register_section_handler(buf, (section_handler){.fun = io_deserialize, .data = sms->io.ports}, SECTION_SEGA_IO_1);
294	register_section_handler(buf, (section_handler){.fun = io_deserialize, .data = sms->io.ports + 1}, SECTION_SEGA_IO_2);
295	register_section_handler(buf, (section_handler){.fun = ram_deserialize, .data = sms}, SECTION_MAIN_RAM);
296	register_section_handler(buf, (section_handler){.fun = mapper_deserialize, .data = sms}, SECTION_MAPPER);
297	register_section_handler(buf, (section_handler){.fun = cart_ram_deserialize, .data = sms}, SECTION_CART_RAM);
298	//TODO: cart RAM
299	while (buf->cur_pos < buf->size)
300	{
301		load_section(buf);
302	}
303	z80_invalidate_code_range(sms->z80, 0xC000, 0x10000);
304	if (sms->bank_regs[0] & 8) {
305		//cart RAM is enabled, invalidate the region in case there is any code there
306		z80_invalidate_code_range(sms->z80, 0x8000, 0xC000);
307	}
308	free(buf->handlers);
309	buf->handlers = NULL;
310}
311
312static void deserialize(system_header *sys, uint8_t *data, size_t size)
313{
314	sms_context *sms = (sms_context *)sys;
315	deserialize_buffer buffer;
316	init_deserialize(&buffer, data, size);
317	sms_deserialize(&buffer, sms);
318}
319
320static void save_state(sms_context *sms, uint8_t slot)
321{
322	char *save_path = get_slot_name(&sms->header, slot, "state");
323	serialize_buffer state;
324	init_serialize(&state);
325	sms_serialize(sms, &state);
326	save_to_file(&state, save_path);
327	printf("Saved state to %s\n", save_path);
328	free(save_path);
329	free(state.data);
330}
331
332static uint8_t load_state_path(sms_context *sms, char *path)
333{
334	deserialize_buffer state;
335	uint8_t ret;
336	if ((ret = load_from_file(&state, path))) {
337		sms_deserialize(&state, sms);
338		free(state.data);
339		printf("Loaded %s\n", path);
340	}
341	return ret;
342}
343
344static uint8_t load_state(system_header *system, uint8_t slot)
345{
346	sms_context *sms = (sms_context *)system;
347	char *statepath = get_slot_name(system, slot, "state");
348	uint8_t ret;
349	if (!sms->z80->native_pc) {
350		ret = get_modification_time(statepath) != 0;
351		if (ret) {
352			system->delayed_load_slot = slot + 1;
353		}
354		goto done;
355		
356	}
357	ret = load_state_path(sms, statepath);
358done:
359	free(statepath);
360	return ret;
361}
362
363static void run_sms(system_header *system)
364{
365	sms_context *sms = (sms_context *)system;
366	uint32_t target_cycle = sms->z80->Z80_CYCLE + 3420*16;
367	//TODO: PAL support
368	render_set_video_standard(VID_NTSC);
369	while (!sms->should_return)
370	{
371		if (system->delayed_load_slot) {
372			load_state(system, system->delayed_load_slot - 1);
373			system->delayed_load_slot = 0;
374			
375		}
376		if (system->enter_debugger && sms->z80->pc) {
377			system->enter_debugger = 0;
378			zdebugger(sms->z80, sms->z80->pc);
379		}
380		if (sms->z80->nmi_start == CYCLE_NEVER) {
381			uint32_t nmi = vdp_next_nmi(sms->vdp);
382			if (nmi != CYCLE_NEVER) {
383				z80_assert_nmi(sms->z80, nmi);
384			}
385		}
386		z80_run(sms->z80, target_cycle);
387		if (sms->z80->reset) {
388			z80_clear_reset(sms->z80, sms->z80->Z80_CYCLE + 128*15);
389		}
390		target_cycle = sms->z80->Z80_CYCLE;
391		vdp_run_context(sms->vdp, target_cycle);
392		psg_run(sms->psg, target_cycle);
393		
394		if (system->save_state) {
395			while (!sms->z80->pc) {
396				//advance Z80 to an instruction boundary
397				z80_run(sms->z80, sms->z80->Z80_CYCLE + 1);
398			}
399			save_state(sms, system->save_state - 1);
400			system->save_state = 0;
401		}
402		
403		target_cycle += 3420*16;
404		if (target_cycle > 0x10000000) {
405			uint32_t adjust = sms->z80->Z80_CYCLE - 3420*262*2;
406			io_adjust_cycles(sms->io.ports, sms->z80->Z80_CYCLE, adjust);
407			io_adjust_cycles(sms->io.ports+1, sms->z80->Z80_CYCLE, adjust);
408			z80_adjust_cycles(sms->z80, adjust);
409			vdp_adjust_cycles(sms->vdp, adjust);
410			sms->psg->cycles -= adjust;
411			target_cycle -= adjust;
412		}
413	}
414	bindings_release_capture();
415	vdp_release_framebuffer(sms->vdp);
416	render_pause_source(sms->psg->audio);
417	sms->should_return = 0;
418}
419
420static void resume_sms(system_header *system)
421{
422	sms_context *sms = (sms_context *)system;
423	bindings_reacquire_capture();
424	vdp_reacquire_framebuffer(sms->vdp);
425	render_resume_source(sms->psg->audio);
426	run_sms(system);
427}
428
429static void start_sms(system_header *system, char *statefile)
430{
431	sms_context *sms = (sms_context *)system;
432	
433	z80_assert_reset(sms->z80, 0);
434	z80_clear_reset(sms->z80, 128*15);
435	
436	if (statefile) {
437		load_state_path(sms, statefile);
438	}
439	
440	if (system->enter_debugger) {
441		system->enter_debugger = 0;
442		zinsert_breakpoint(sms->z80, sms->z80->pc, (uint8_t *)zdebugger);
443	}
444	
445	run_sms(system);
446}
447
448static void soft_reset(system_header *system)
449{
450	sms_context *sms = (sms_context *)system;
451	z80_assert_reset(sms->z80, sms->z80->Z80_CYCLE);
452	sms->z80->target_cycle = sms->z80->sync_cycle = sms->z80->Z80_CYCLE;
453}
454
455static void free_sms(system_header *system)
456{
457	sms_context *sms = (sms_context *)system;
458	vdp_free(sms->vdp);
459	z80_options_free(sms->z80->Z80_OPTS);
460	free(sms->z80);
461	psg_free(sms->psg);
462	free(sms);
463}
464
465static uint16_t get_open_bus_value(system_header *system)
466{
467	return 0xFFFF;
468}
469
470static void request_exit(system_header *system)
471{
472	sms_context *sms = (sms_context *)system;
473	sms->should_return = 1;
474	sms->z80->target_cycle = sms->z80->sync_cycle = sms->z80->Z80_CYCLE;
475}
476
477static void inc_debug_mode(system_header *system)
478{
479	sms_context *sms = (sms_context *)system;
480	vdp_inc_debug_mode(sms->vdp);
481}
482
483static void load_save(system_header *system)
484{
485	//TODO: Implement me
486}
487
488static void persist_save(system_header *system)
489{
490	//TODO: Implement me
491}
492
493static void gamepad_down(system_header *system, uint8_t gamepad_num, uint8_t button)
494{
495	sms_context *sms = (sms_context *)system;
496	if (gamepad_num == GAMEPAD_MAIN_UNIT) {
497		if (button == MAIN_UNIT_PAUSE) {
498			vdp_pbc_pause(sms->vdp);
499		}
500	} else {
501		io_gamepad_down(&sms->io, gamepad_num, button);
502	}
503}
504
505static void gamepad_up(system_header *system, uint8_t gamepad_num, uint8_t button)
506{
507	sms_context *sms = (sms_context *)system;
508	io_gamepad_up(&sms->io, gamepad_num, button);
509}
510
511static void mouse_down(system_header *system, uint8_t mouse_num, uint8_t button)
512{
513	sms_context *sms = (sms_context *)system;
514	io_mouse_down(&sms->io, mouse_num, button);
515}
516
517static void mouse_up(system_header *system, uint8_t mouse_num, uint8_t button)
518{
519	sms_context *sms = (sms_context *)system;
520	io_mouse_up(&sms->io, mouse_num, button);
521}
522
523static void mouse_motion_absolute(system_header *system, uint8_t mouse_num, uint16_t x, uint16_t y)
524{
525	sms_context *sms = (sms_context *)system;
526	io_mouse_motion_absolute(&sms->io, mouse_num, x, y);
527}
528
529static void mouse_motion_relative(system_header *system, uint8_t mouse_num, int32_t x, int32_t y)
530{
531	sms_context *sms = (sms_context *)system;
532	io_mouse_motion_relative(&sms->io, mouse_num, x, y);
533}
534
535static void keyboard_down(system_header *system, uint8_t scancode)
536{
537	sms_context *sms = (sms_context *)system;
538	io_keyboard_down(&sms->io, scancode);
539}
540
541static void keyboard_up(system_header *system, uint8_t scancode)
542{
543	sms_context *sms = (sms_context *)system;
544	io_keyboard_up(&sms->io, scancode);
545}
546
547static void set_gain_config(sms_context *sms)
548{
549	char *config_gain;
550	config_gain = tern_find_path(config, "audio\0psg_gain\0", TVAL_PTR).ptrval;
551	render_audio_source_gaindb(sms->psg->audio, config_gain ? atof(config_gain) : 0.0f);
552}
553
554static void config_updated(system_header *system)
555{
556	sms_context *sms = (sms_context *)system;
557	setup_io_devices(config, &system->info, &sms->io);
558}
559
560
561sms_context *alloc_configure_sms(system_media *media, uint32_t opts, uint8_t force_region)
562{
563	sms_context *sms = calloc(1, sizeof(sms_context));
564	uint32_t rom_size = nearest_pow2(media->size);
565	memmap_chunk memory_map[6];
566	if (media->size > 0xC000)  {
567		sms->header.info.map_chunks = 6;
568		uint8_t *ram_reg_overlap = sms->ram + sizeof(sms->ram) - 4;
569		memory_map[0] = (memmap_chunk){0x0000, 0x0400,  0xFFFF,             0, 0, MMAP_READ,                        media->buffer, NULL, NULL, NULL, NULL};
570		memory_map[1] = (memmap_chunk){0x0400, 0x4000,  0xFFFF,             0, 0, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL,     NULL, NULL, NULL, NULL};
571		memory_map[2] = (memmap_chunk){0x4000, 0x8000,  0x3FFF,             0, 1, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL,     NULL, NULL, NULL, NULL};
572		memory_map[3] = (memmap_chunk){0x8000, 0xC000,  0x3FFF,             0, 2, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL,     NULL, NULL, NULL, cart_ram_write};
573		memory_map[4] = (memmap_chunk){0xC000, 0xFFFC,  sizeof(sms->ram)-1, 0, 0, MMAP_READ|MMAP_WRITE|MMAP_CODE,   sms->ram, NULL, NULL, NULL, NULL};
574		memory_map[5] = (memmap_chunk){0xFFFC, 0x10000, 0x0003,             0, 0, MMAP_READ,                        ram_reg_overlap, NULL, NULL, NULL, mapper_write};
575	} else {
576		sms->header.info.map_chunks = 2;
577		memory_map[0] = (memmap_chunk){0x0000, 0xC000,  rom_size-1,         0, 0, MMAP_READ,                      media->buffer,  NULL, NULL, NULL, NULL};
578		memory_map[1] = (memmap_chunk){0xC000, 0x10000, sizeof(sms->ram)-1, 0, 0, MMAP_READ|MMAP_WRITE|MMAP_CODE, sms->ram, NULL, NULL, NULL, NULL};
579	};
580	sms->header.info.map = malloc(sizeof(memmap_chunk) * sms->header.info.map_chunks);
581	memcpy(sms->header.info.map, memory_map, sizeof(memmap_chunk) * sms->header.info.map_chunks);
582	z80_options *zopts = malloc(sizeof(z80_options));
583	init_z80_opts(zopts, sms->header.info.map, sms->header.info.map_chunks, io_map, 4, 15, 0xFF);
584	sms->z80 = init_z80_context(zopts);
585	sms->z80->system = sms;
586	sms->z80->Z80_OPTS->gen.debug_cmd_handler = debug_commands;
587	
588	sms->rom = media->buffer;
589	sms->rom_size = rom_size;
590	if (sms->header.info.map_chunks > 2) {
591		sms->z80->mem_pointers[0] = sms->rom;
592		sms->z80->mem_pointers[1] = sms->rom + 0x4000;
593		sms->z80->mem_pointers[2] = sms->rom + 0x8000;
594		sms->bank_regs[1] = 0;
595		sms->bank_regs[2] = 0x4000 >> 14;
596		sms->bank_regs[3] = 0x8000 >> 14;
597	}
598	
599	//TODO: Detect region and pick master clock based off of that
600	sms->normal_clock = sms->master_clock = 53693175;
601	
602	sms->psg = malloc(sizeof(psg_context));
603	psg_init(sms->psg, sms->master_clock, 15*16);
604	
605	set_gain_config(sms);
606	
607	sms->vdp = init_vdp_context(0);
608	sms->vdp->system = &sms->header;
609	
610	sms->header.info.save_type = SAVE_NONE;
611	sms->header.info.name = strdup(media->name);
612	
613	setup_io_devices(config, &sms->header.info, &sms->io);
614	sms->header.has_keyboard = io_has_keyboard(&sms->io);
615	
616	sms->header.set_speed_percent = set_speed_percent;
617	sms->header.start_context = start_sms;
618	sms->header.resume_context = resume_sms;
619	sms->header.load_save = load_save;
620	sms->header.persist_save = persist_save;
621	sms->header.load_state = load_state;
622	sms->header.free_context = free_sms;
623	sms->header.get_open_bus_value = get_open_bus_value;
624	sms->header.request_exit = request_exit;
625	sms->header.soft_reset = soft_reset;
626	sms->header.inc_debug_mode = inc_debug_mode;
627	sms->header.gamepad_down = gamepad_down;
628	sms->header.gamepad_up = gamepad_up;
629	sms->header.mouse_down = mouse_down;
630	sms->header.mouse_up = mouse_up;
631	sms->header.mouse_motion_absolute = mouse_motion_absolute;
632	sms->header.mouse_motion_relative = mouse_motion_relative;
633	sms->header.keyboard_down = keyboard_down;
634	sms->header.keyboard_up = keyboard_up;
635	sms->header.config_updated = config_updated;
636	sms->header.serialize = serialize;
637	sms->header.deserialize = deserialize;
638	sms->header.type = SYSTEM_SMS;
639	
640	return sms;
641}