comparison sms.c @ 1692:5dacaef602a7 segacd

Merge from default
author Michael Pavone <pavone@retrodev.com>
date Sat, 05 Jan 2019 00:58:08 -0800
parents 6909c5d0bbb5
children b7ecd0d6a77b 395f684c5379
comparison
equal deleted inserted replaced
1504:95b3a1a8b26c 1692:5dacaef602a7
4 #include "sms.h" 4 #include "sms.h"
5 #include "blastem.h" 5 #include "blastem.h"
6 #include "render.h" 6 #include "render.h"
7 #include "util.h" 7 #include "util.h"
8 #include "debug.h" 8 #include "debug.h"
9 #include "saves.h"
10 #include "bindings.h"
9 11
10 static void *memory_io_write(uint32_t location, void *vcontext, uint8_t value) 12 static void *memory_io_write(uint32_t location, void *vcontext, uint8_t value)
11 { 13 {
12 z80_context *z80 = vcontext; 14 z80_context *z80 = vcontext;
13 sms_context *sms = z80->system; 15 sms_context *sms = z80->system;
290 } 292 }
291 } 293 }
292 294
293 static void save_state(sms_context *sms, uint8_t slot) 295 static void save_state(sms_context *sms, uint8_t slot)
294 { 296 {
295 char *save_path; 297 char *save_path = get_slot_name(&sms->header, slot, "state");
296 if (slot == QUICK_SAVE_SLOT) {
297 save_path = save_state_path;
298 } else {
299 char slotname[] = "slot_0.state";
300 slotname[5] = '0' + slot;
301 char const *parts[] = {sms->header.save_dir, PATH_SEP, slotname};
302 save_path = alloc_concat_m(3, parts);
303 }
304 serialize_buffer state; 298 serialize_buffer state;
305 init_serialize(&state); 299 init_serialize(&state);
306 sms_serialize(sms, &state); 300 sms_serialize(sms, &state);
307 save_to_file(&state, save_path); 301 save_to_file(&state, save_path);
308 printf("Saved state to %s\n", save_path); 302 printf("Saved state to %s\n", save_path);
303 free(save_path);
309 free(state.data); 304 free(state.data);
310 } 305 }
311 306
312 static uint8_t load_state_path(sms_context *sms, char *path) 307 static uint8_t load_state_path(sms_context *sms, char *path)
313 { 308 {
322 } 317 }
323 318
324 static uint8_t load_state(system_header *system, uint8_t slot) 319 static uint8_t load_state(system_header *system, uint8_t slot)
325 { 320 {
326 sms_context *sms = (sms_context *)system; 321 sms_context *sms = (sms_context *)system;
327 char numslotname[] = "slot_0.state"; 322 char *statepath = get_slot_name(system, slot, "state");
328 char *slotname; 323 uint8_t ret;
329 if (slot == QUICK_SAVE_SLOT) { 324 if (!sms->z80->native_pc) {
330 slotname = "quicksave.state"; 325 ret = get_modification_time(statepath) != 0;
331 } else { 326 if (ret) {
332 numslotname[5] = '0' + slot; 327 system->delayed_load_slot = slot + 1;
333 slotname = numslotname; 328 }
334 } 329 goto done;
335 char const *parts[] = {sms->header.save_dir, PATH_SEP, slotname}; 330
336 char *statepath = alloc_concat_m(3, parts); 331 }
337 uint8_t ret = load_state_path(sms, statepath); 332 ret = load_state_path(sms, statepath);
333 done:
338 free(statepath); 334 free(statepath);
339 return ret; 335 return ret;
340 } 336 }
341 337
342 static void run_sms(system_header *system) 338 static void run_sms(system_header *system)
343 { 339 {
344 render_disable_ym();
345 sms_context *sms = (sms_context *)system; 340 sms_context *sms = (sms_context *)system;
346 uint32_t target_cycle = sms->z80->current_cycle + 3420*16; 341 uint32_t target_cycle = sms->z80->current_cycle + 3420*16;
347 //TODO: PAL support 342 //TODO: PAL support
348 render_set_video_standard(VID_NTSC); 343 render_set_video_standard(VID_NTSC);
349 while (!sms->should_return) 344 while (!sms->should_return)
350 { 345 {
346 if (system->delayed_load_slot) {
347 load_state(system, system->delayed_load_slot - 1);
348 system->delayed_load_slot = 0;
349
350 }
351 if (system->enter_debugger && sms->z80->pc) { 351 if (system->enter_debugger && sms->z80->pc) {
352 system->enter_debugger = 0; 352 system->enter_debugger = 0;
353 zdebugger(sms->z80, sms->z80->pc); 353 zdebugger(sms->z80, sms->z80->pc);
354 } 354 }
355 if (sms->z80->nmi_start == CYCLE_NEVER) { 355 if (sms->z80->nmi_start == CYCLE_NEVER) {
384 vdp_adjust_cycles(sms->vdp, adjust); 384 vdp_adjust_cycles(sms->vdp, adjust);
385 sms->psg->cycles -= adjust; 385 sms->psg->cycles -= adjust;
386 target_cycle -= adjust; 386 target_cycle -= adjust;
387 } 387 }
388 } 388 }
389 bindings_release_capture();
389 vdp_release_framebuffer(sms->vdp); 390 vdp_release_framebuffer(sms->vdp);
391 render_pause_source(sms->psg->audio);
390 sms->should_return = 0; 392 sms->should_return = 0;
391 render_enable_ym();
392 } 393 }
393 394
394 static void resume_sms(system_header *system) 395 static void resume_sms(system_header *system)
395 { 396 {
396 sms_context *sms = (sms_context *)system; 397 sms_context *sms = (sms_context *)system;
398 bindings_reacquire_capture();
397 vdp_reacquire_framebuffer(sms->vdp); 399 vdp_reacquire_framebuffer(sms->vdp);
400 render_resume_source(sms->psg->audio);
398 run_sms(system); 401 run_sms(system);
399 } 402 }
400 403
401 static void start_sms(system_header *system, char *statefile) 404 static void start_sms(system_header *system, char *statefile)
402 { 405 {
403 sms_context *sms = (sms_context *)system; 406 sms_context *sms = (sms_context *)system;
404 set_keybindings(&sms->io);
405 407
406 z80_assert_reset(sms->z80, 0); 408 z80_assert_reset(sms->z80, 0);
407 z80_clear_reset(sms->z80, 128*15); 409 z80_clear_reset(sms->z80, 128*15);
408 410
409 if (statefile) { 411 if (statefile) {
447 } 449 }
448 450
449 static void inc_debug_mode(system_header *system) 451 static void inc_debug_mode(system_header *system)
450 { 452 {
451 sms_context *sms = (sms_context *)system; 453 sms_context *sms = (sms_context *)system;
452 sms->vdp->debug++; 454 vdp_inc_debug_mode(sms->vdp);
453 if (sms->vdp->debug == 7) {
454 sms->vdp->debug = 0;
455 }
456 }
457
458 static void inc_debug_pal(system_header *system)
459 {
460 sms_context *sms = (sms_context *)system;
461 sms->vdp->debug_pal++;
462 if (sms->vdp->debug_pal == 4) {
463 sms->vdp->debug_pal = 0;
464 }
465 } 455 }
466 456
467 static void load_save(system_header *system) 457 static void load_save(system_header *system)
468 { 458 {
469 //TODO: Implement me 459 //TODO: Implement me
472 static void persist_save(system_header *system) 462 static void persist_save(system_header *system)
473 { 463 {
474 //TODO: Implement me 464 //TODO: Implement me
475 } 465 }
476 466
477 sms_context *alloc_configure_sms(system_media *media, uint32_t opts, uint8_t force_region, rom_info *info_out) 467 static void gamepad_down(system_header *system, uint8_t gamepad_num, uint8_t button)
478 { 468 {
479 memset(info_out, 0, sizeof(*info_out)); 469 sms_context *sms = (sms_context *)system;
470 if (gamepad_num == GAMEPAD_MAIN_UNIT) {
471 if (button == MAIN_UNIT_PAUSE) {
472 vdp_pbc_pause(sms->vdp);
473 }
474 } else {
475 io_gamepad_down(&sms->io, gamepad_num, button);
476 }
477 }
478
479 static void gamepad_up(system_header *system, uint8_t gamepad_num, uint8_t button)
480 {
481 sms_context *sms = (sms_context *)system;
482 io_gamepad_up(&sms->io, gamepad_num, button);
483 }
484
485 static void mouse_down(system_header *system, uint8_t mouse_num, uint8_t button)
486 {
487 sms_context *sms = (sms_context *)system;
488 io_mouse_down(&sms->io, mouse_num, button);
489 }
490
491 static void mouse_up(system_header *system, uint8_t mouse_num, uint8_t button)
492 {
493 sms_context *sms = (sms_context *)system;
494 io_mouse_up(&sms->io, mouse_num, button);
495 }
496
497 static void mouse_motion_absolute(system_header *system, uint8_t mouse_num, uint16_t x, uint16_t y)
498 {
499 sms_context *sms = (sms_context *)system;
500 io_mouse_motion_absolute(&sms->io, mouse_num, x, y);
501 }
502
503 static void mouse_motion_relative(system_header *system, uint8_t mouse_num, int32_t x, int32_t y)
504 {
505 sms_context *sms = (sms_context *)system;
506 io_mouse_motion_relative(&sms->io, mouse_num, x, y);
507 }
508
509 static void keyboard_down(system_header *system, uint8_t scancode)
510 {
511 sms_context *sms = (sms_context *)system;
512 io_keyboard_down(&sms->io, scancode);
513 }
514
515 static void keyboard_up(system_header *system, uint8_t scancode)
516 {
517 sms_context *sms = (sms_context *)system;
518 io_keyboard_up(&sms->io, scancode);
519 }
520
521 static void config_updated(system_header *system)
522 {
523 sms_context *sms = (sms_context *)system;
524 setup_io_devices(config, &system->info, &sms->io);
525 }
526
527
528 sms_context *alloc_configure_sms(system_media *media, uint32_t opts, uint8_t force_region)
529 {
480 sms_context *sms = calloc(1, sizeof(sms_context)); 530 sms_context *sms = calloc(1, sizeof(sms_context));
481 uint32_t rom_size = nearest_pow2(media->size); 531 uint32_t rom_size = nearest_pow2(media->size);
482 memmap_chunk memory_map[6]; 532 memmap_chunk memory_map[6];
483 if (media->size > 0xC000) { 533 if (media->size > 0xC000) {
484 info_out->map_chunks = 6; 534 sms->header.info.map_chunks = 6;
485 uint8_t *ram_reg_overlap = sms->ram + sizeof(sms->ram) - 4; 535 uint8_t *ram_reg_overlap = sms->ram + sizeof(sms->ram) - 4;
486 memory_map[0] = (memmap_chunk){0x0000, 0x0400, 0xFFFF, 0, 0, MMAP_READ, media->buffer, NULL, NULL, NULL, NULL}; 536 memory_map[0] = (memmap_chunk){0x0000, 0x0400, 0xFFFF, 0, 0, MMAP_READ, media->buffer, NULL, NULL, NULL, NULL};
487 memory_map[1] = (memmap_chunk){0x0400, 0x4000, 0xFFFF, 0, 0, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, NULL}; 537 memory_map[1] = (memmap_chunk){0x0400, 0x4000, 0xFFFF, 0, 0, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, NULL};
488 memory_map[2] = (memmap_chunk){0x4000, 0x8000, 0x3FFF, 0, 1, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, NULL}; 538 memory_map[2] = (memmap_chunk){0x4000, 0x8000, 0x3FFF, 0, 1, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, NULL};
489 memory_map[3] = (memmap_chunk){0x8000, 0xC000, 0x3FFF, 0, 2, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, cart_ram_write}; 539 memory_map[3] = (memmap_chunk){0x8000, 0xC000, 0x3FFF, 0, 2, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, cart_ram_write};
490 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}; 540 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};
491 memory_map[5] = (memmap_chunk){0xFFFC, 0x10000, 0x0003, 0, 0, MMAP_READ, ram_reg_overlap, NULL, NULL, NULL, mapper_write}; 541 memory_map[5] = (memmap_chunk){0xFFFC, 0x10000, 0x0003, 0, 0, MMAP_READ, ram_reg_overlap, NULL, NULL, NULL, mapper_write};
492 } else { 542 } else {
493 info_out->map_chunks = 2; 543 sms->header.info.map_chunks = 2;
494 memory_map[0] = (memmap_chunk){0x0000, 0xC000, rom_size-1, 0, 0, MMAP_READ, media->buffer, NULL, NULL, NULL, NULL}; 544 memory_map[0] = (memmap_chunk){0x0000, 0xC000, rom_size-1, 0, 0, MMAP_READ, media->buffer, NULL, NULL, NULL, NULL};
495 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}; 545 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};
496 }; 546 };
497 info_out->map = malloc(sizeof(memmap_chunk) * info_out->map_chunks); 547 sms->header.info.map = malloc(sizeof(memmap_chunk) * sms->header.info.map_chunks);
498 memcpy(info_out->map, memory_map, sizeof(memmap_chunk) * info_out->map_chunks); 548 memcpy(sms->header.info.map, memory_map, sizeof(memmap_chunk) * sms->header.info.map_chunks);
499 z80_options *zopts = malloc(sizeof(z80_options)); 549 z80_options *zopts = malloc(sizeof(z80_options));
500 init_z80_opts(zopts, info_out->map, info_out->map_chunks, io_map, 4, 15, 0xFF); 550 init_z80_opts(zopts, sms->header.info.map, sms->header.info.map_chunks, io_map, 4, 15, 0xFF);
501 sms->z80 = init_z80_context(zopts); 551 sms->z80 = init_z80_context(zopts);
502 sms->z80->system = sms; 552 sms->z80->system = sms;
503 sms->z80->options->gen.debug_cmd_handler = debug_commands; 553 sms->z80->options->gen.debug_cmd_handler = debug_commands;
504 554
505 sms->rom = media->buffer; 555 sms->rom = media->buffer;
506 sms->rom_size = rom_size; 556 sms->rom_size = rom_size;
507 if (info_out->map_chunks > 2) { 557 if (sms->header.info.map_chunks > 2) {
508 sms->z80->mem_pointers[0] = sms->rom; 558 sms->z80->mem_pointers[0] = sms->rom;
509 sms->z80->mem_pointers[1] = sms->rom + 0x4000; 559 sms->z80->mem_pointers[1] = sms->rom + 0x4000;
510 sms->z80->mem_pointers[2] = sms->rom + 0x8000; 560 sms->z80->mem_pointers[2] = sms->rom + 0x8000;
511 sms->bank_regs[1] = 0; 561 sms->bank_regs[1] = 0;
512 sms->bank_regs[2] = 0x4000 >> 14; 562 sms->bank_regs[2] = 0x4000 >> 14;
513 sms->bank_regs[3] = 0x8000 >> 14; 563 sms->bank_regs[3] = 0x8000 >> 14;
514 } 564 }
515 565
516 char * lowpass_cutoff_str = tern_find_path(config, "audio\0lowpass_cutoff\0", TVAL_PTR).ptrval;
517 uint32_t lowpass_cutoff = lowpass_cutoff_str ? atoi(lowpass_cutoff_str) : 3390;
518
519 //TODO: Detect region and pick master clock based off of that 566 //TODO: Detect region and pick master clock based off of that
520 sms->normal_clock = sms->master_clock = 53693175; 567 sms->normal_clock = sms->master_clock = 53693175;
521 568
522 sms->psg = malloc(sizeof(psg_context)); 569 sms->psg = malloc(sizeof(psg_context));
523 psg_init(sms->psg, render_sample_rate(), sms->master_clock, 15*16, render_audio_buffer(), lowpass_cutoff); 570 psg_init(sms->psg, sms->master_clock, 15*16);
524 571
525 sms->vdp = malloc(sizeof(vdp_context)); 572 sms->vdp = init_vdp_context(0);
526 init_vdp_context(sms->vdp, 0);
527 sms->vdp->system = &sms->header; 573 sms->vdp->system = &sms->header;
528 574
529 info_out->save_type = SAVE_NONE; 575 sms->header.info.save_type = SAVE_NONE;
530 info_out->name = strdup(media->name); 576 sms->header.info.name = strdup(media->name);
531 577
532 setup_io_devices(config, info_out, &sms->io); 578 setup_io_devices(config, &sms->header.info, &sms->io);
579 sms->header.has_keyboard = io_has_keyboard(&sms->io);
533 580
534 sms->header.set_speed_percent = set_speed_percent; 581 sms->header.set_speed_percent = set_speed_percent;
535 sms->header.start_context = start_sms; 582 sms->header.start_context = start_sms;
536 sms->header.resume_context = resume_sms; 583 sms->header.resume_context = resume_sms;
537 sms->header.load_save = load_save; 584 sms->header.load_save = load_save;
540 sms->header.free_context = free_sms; 587 sms->header.free_context = free_sms;
541 sms->header.get_open_bus_value = get_open_bus_value; 588 sms->header.get_open_bus_value = get_open_bus_value;
542 sms->header.request_exit = request_exit; 589 sms->header.request_exit = request_exit;
543 sms->header.soft_reset = soft_reset; 590 sms->header.soft_reset = soft_reset;
544 sms->header.inc_debug_mode = inc_debug_mode; 591 sms->header.inc_debug_mode = inc_debug_mode;
545 sms->header.inc_debug_pal = inc_debug_pal; 592 sms->header.gamepad_down = gamepad_down;
593 sms->header.gamepad_up = gamepad_up;
594 sms->header.mouse_down = mouse_down;
595 sms->header.mouse_up = mouse_up;
596 sms->header.mouse_motion_absolute = mouse_motion_absolute;
597 sms->header.mouse_motion_relative = mouse_motion_relative;
598 sms->header.keyboard_down = keyboard_down;
599 sms->header.keyboard_up = keyboard_up;
600 sms->header.config_updated = config_updated;
546 sms->header.type = SYSTEM_SMS; 601 sms->header.type = SYSTEM_SMS;
547 602
548 return sms; 603 return sms;
549 } 604 }