Mercurial > repos > blastem
comparison sms.c @ 1648:b7ecd0d6a77b mame_interp
Merge from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 25 Dec 2018 11:12:26 -0800 |
parents | 2455662378ed 6909c5d0bbb5 |
children | 956c1cce05e2 |
comparison
equal
deleted
inserted
replaced
1509:36732f5c2281 | 1648:b7ecd0d6a77b |
---|---|
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 #ifdef USE_NATIVE |
330 slotname = "quicksave.state"; | 325 if (!sms->z80->native_pc) { |
331 } else { | 326 ret = get_modification_time(statepath) != 0; |
332 numslotname[5] = '0' + slot; | 327 if (ret) { |
333 slotname = numslotname; | 328 system->delayed_load_slot = slot + 1; |
334 } | 329 } |
335 char const *parts[] = {sms->header.save_dir, PATH_SEP, slotname}; | 330 goto done; |
336 char *statepath = alloc_concat_m(3, parts); | 331 |
337 uint8_t ret = load_state_path(sms, statepath); | 332 } |
333 #endif | |
334 ret = load_state_path(sms, statepath); | |
335 done: | |
338 free(statepath); | 336 free(statepath); |
339 return ret; | 337 return ret; |
340 } | 338 } |
341 | 339 |
342 static void run_sms(system_header *system) | 340 static void run_sms(system_header *system) |
343 { | 341 { |
344 render_disable_ym(); | |
345 sms_context *sms = (sms_context *)system; | 342 sms_context *sms = (sms_context *)system; |
346 uint32_t target_cycle = sms->z80->current_cycle + 3420*16; | 343 uint32_t target_cycle = sms->z80->current_cycle + 3420*16; |
347 //TODO: PAL support | 344 //TODO: PAL support |
348 render_set_video_standard(VID_NTSC); | 345 render_set_video_standard(VID_NTSC); |
349 while (!sms->should_return) | 346 while (!sms->should_return) |
350 { | 347 { |
351 #ifdef USE_NATIVE | 348 #ifdef USE_NATIVE |
349 if (system->delayed_load_slot) { | |
350 load_state(system, system->delayed_load_slot - 1); | |
351 system->delayed_load_slot = 0; | |
352 | |
353 } | |
352 if (system->enter_debugger && sms->z80->pc) { | 354 if (system->enter_debugger && sms->z80->pc) { |
353 system->enter_debugger = 0; | 355 system->enter_debugger = 0; |
354 zdebugger(sms->z80, sms->z80->pc); | 356 zdebugger(sms->z80, sms->z80->pc); |
355 } | 357 } |
356 #endif | 358 #endif |
388 vdp_adjust_cycles(sms->vdp, adjust); | 390 vdp_adjust_cycles(sms->vdp, adjust); |
389 sms->psg->cycles -= adjust; | 391 sms->psg->cycles -= adjust; |
390 target_cycle -= adjust; | 392 target_cycle -= adjust; |
391 } | 393 } |
392 } | 394 } |
395 bindings_release_capture(); | |
393 vdp_release_framebuffer(sms->vdp); | 396 vdp_release_framebuffer(sms->vdp); |
397 render_pause_source(sms->psg->audio); | |
394 sms->should_return = 0; | 398 sms->should_return = 0; |
395 render_enable_ym(); | |
396 } | 399 } |
397 | 400 |
398 static void resume_sms(system_header *system) | 401 static void resume_sms(system_header *system) |
399 { | 402 { |
400 sms_context *sms = (sms_context *)system; | 403 sms_context *sms = (sms_context *)system; |
404 bindings_reacquire_capture(); | |
401 vdp_reacquire_framebuffer(sms->vdp); | 405 vdp_reacquire_framebuffer(sms->vdp); |
406 render_resume_source(sms->psg->audio); | |
402 run_sms(system); | 407 run_sms(system); |
403 } | 408 } |
404 | 409 |
405 static void start_sms(system_header *system, char *statefile) | 410 static void start_sms(system_header *system, char *statefile) |
406 { | 411 { |
407 sms_context *sms = (sms_context *)system; | 412 sms_context *sms = (sms_context *)system; |
408 set_keybindings(&sms->io); | |
409 | 413 |
410 z80_assert_reset(sms->z80, 0); | 414 z80_assert_reset(sms->z80, 0); |
411 z80_clear_reset(sms->z80, 128*15); | 415 z80_clear_reset(sms->z80, 128*15); |
412 | 416 |
413 if (statefile) { | 417 if (statefile) { |
455 } | 459 } |
456 | 460 |
457 static void inc_debug_mode(system_header *system) | 461 static void inc_debug_mode(system_header *system) |
458 { | 462 { |
459 sms_context *sms = (sms_context *)system; | 463 sms_context *sms = (sms_context *)system; |
460 sms->vdp->debug++; | 464 vdp_inc_debug_mode(sms->vdp); |
461 if (sms->vdp->debug == 7) { | |
462 sms->vdp->debug = 0; | |
463 } | |
464 } | |
465 | |
466 static void inc_debug_pal(system_header *system) | |
467 { | |
468 sms_context *sms = (sms_context *)system; | |
469 sms->vdp->debug_pal++; | |
470 if (sms->vdp->debug_pal == 4) { | |
471 sms->vdp->debug_pal = 0; | |
472 } | |
473 } | 465 } |
474 | 466 |
475 static void load_save(system_header *system) | 467 static void load_save(system_header *system) |
476 { | 468 { |
477 //TODO: Implement me | 469 //TODO: Implement me |
480 static void persist_save(system_header *system) | 472 static void persist_save(system_header *system) |
481 { | 473 { |
482 //TODO: Implement me | 474 //TODO: Implement me |
483 } | 475 } |
484 | 476 |
485 sms_context *alloc_configure_sms(system_media *media, uint32_t opts, uint8_t force_region, rom_info *info_out) | 477 static void gamepad_down(system_header *system, uint8_t gamepad_num, uint8_t button) |
486 { | 478 { |
487 memset(info_out, 0, sizeof(*info_out)); | 479 sms_context *sms = (sms_context *)system; |
480 if (gamepad_num == GAMEPAD_MAIN_UNIT) { | |
481 if (button == MAIN_UNIT_PAUSE) { | |
482 vdp_pbc_pause(sms->vdp); | |
483 } | |
484 } else { | |
485 io_gamepad_down(&sms->io, gamepad_num, button); | |
486 } | |
487 } | |
488 | |
489 static void gamepad_up(system_header *system, uint8_t gamepad_num, uint8_t button) | |
490 { | |
491 sms_context *sms = (sms_context *)system; | |
492 io_gamepad_up(&sms->io, gamepad_num, button); | |
493 } | |
494 | |
495 static void mouse_down(system_header *system, uint8_t mouse_num, uint8_t button) | |
496 { | |
497 sms_context *sms = (sms_context *)system; | |
498 io_mouse_down(&sms->io, mouse_num, button); | |
499 } | |
500 | |
501 static void mouse_up(system_header *system, uint8_t mouse_num, uint8_t button) | |
502 { | |
503 sms_context *sms = (sms_context *)system; | |
504 io_mouse_up(&sms->io, mouse_num, button); | |
505 } | |
506 | |
507 static void mouse_motion_absolute(system_header *system, uint8_t mouse_num, uint16_t x, uint16_t y) | |
508 { | |
509 sms_context *sms = (sms_context *)system; | |
510 io_mouse_motion_absolute(&sms->io, mouse_num, x, y); | |
511 } | |
512 | |
513 static void mouse_motion_relative(system_header *system, uint8_t mouse_num, int32_t x, int32_t y) | |
514 { | |
515 sms_context *sms = (sms_context *)system; | |
516 io_mouse_motion_relative(&sms->io, mouse_num, x, y); | |
517 } | |
518 | |
519 static void keyboard_down(system_header *system, uint8_t scancode) | |
520 { | |
521 sms_context *sms = (sms_context *)system; | |
522 io_keyboard_down(&sms->io, scancode); | |
523 } | |
524 | |
525 static void keyboard_up(system_header *system, uint8_t scancode) | |
526 { | |
527 sms_context *sms = (sms_context *)system; | |
528 io_keyboard_up(&sms->io, scancode); | |
529 } | |
530 | |
531 static void config_updated(system_header *system) | |
532 { | |
533 sms_context *sms = (sms_context *)system; | |
534 setup_io_devices(config, &system->info, &sms->io); | |
535 } | |
536 | |
537 | |
538 sms_context *alloc_configure_sms(system_media *media, uint32_t opts, uint8_t force_region) | |
539 { | |
488 sms_context *sms = calloc(1, sizeof(sms_context)); | 540 sms_context *sms = calloc(1, sizeof(sms_context)); |
489 uint32_t rom_size = nearest_pow2(media->size); | 541 uint32_t rom_size = nearest_pow2(media->size); |
490 memmap_chunk memory_map[6]; | 542 memmap_chunk memory_map[6]; |
491 if (media->size > 0xC000) { | 543 if (media->size > 0xC000) { |
492 info_out->map_chunks = 6; | 544 sms->header.info.map_chunks = 6; |
493 uint8_t *ram_reg_overlap = sms->ram + sizeof(sms->ram) - 4; | 545 uint8_t *ram_reg_overlap = sms->ram + sizeof(sms->ram) - 4; |
494 memory_map[0] = (memmap_chunk){0x0000, 0x0400, 0xFFFF, 0, 0, MMAP_READ, media->buffer, NULL, NULL, NULL, NULL}; | 546 memory_map[0] = (memmap_chunk){0x0000, 0x0400, 0xFFFF, 0, 0, MMAP_READ, media->buffer, NULL, NULL, NULL, NULL}; |
495 memory_map[1] = (memmap_chunk){0x0400, 0x4000, 0xFFFF, 0, 0, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, NULL}; | 547 memory_map[1] = (memmap_chunk){0x0400, 0x4000, 0xFFFF, 0, 0, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, NULL}; |
496 memory_map[2] = (memmap_chunk){0x4000, 0x8000, 0x3FFF, 0, 1, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, NULL}; | 548 memory_map[2] = (memmap_chunk){0x4000, 0x8000, 0x3FFF, 0, 1, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, NULL}; |
497 memory_map[3] = (memmap_chunk){0x8000, 0xC000, 0x3FFF, 0, 2, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, cart_ram_write}; | 549 memory_map[3] = (memmap_chunk){0x8000, 0xC000, 0x3FFF, 0, 2, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL, NULL, NULL, NULL, cart_ram_write}; |
498 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}; | 550 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}; |
499 memory_map[5] = (memmap_chunk){0xFFFC, 0x10000, 0x0003, 0, 0, MMAP_READ, ram_reg_overlap, NULL, NULL, NULL, mapper_write}; | 551 memory_map[5] = (memmap_chunk){0xFFFC, 0x10000, 0x0003, 0, 0, MMAP_READ, ram_reg_overlap, NULL, NULL, NULL, mapper_write}; |
500 } else { | 552 } else { |
501 info_out->map_chunks = 2; | 553 sms->header.info.map_chunks = 2; |
502 memory_map[0] = (memmap_chunk){0x0000, 0xC000, rom_size-1, 0, 0, MMAP_READ, media->buffer, NULL, NULL, NULL, NULL}; | 554 memory_map[0] = (memmap_chunk){0x0000, 0xC000, rom_size-1, 0, 0, MMAP_READ, media->buffer, NULL, NULL, NULL, NULL}; |
503 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}; | 555 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}; |
504 }; | 556 }; |
505 info_out->map = malloc(sizeof(memmap_chunk) * info_out->map_chunks); | 557 sms->header.info.map = malloc(sizeof(memmap_chunk) * sms->header.info.map_chunks); |
506 memcpy(info_out->map, memory_map, sizeof(memmap_chunk) * info_out->map_chunks); | 558 memcpy(sms->header.info.map, memory_map, sizeof(memmap_chunk) * sms->header.info.map_chunks); |
507 z80_options *zopts = malloc(sizeof(z80_options)); | 559 z80_options *zopts = malloc(sizeof(z80_options)); |
508 init_z80_opts(zopts, info_out->map, info_out->map_chunks, io_map, 4, 15, 0xFF); | 560 init_z80_opts(zopts, sms->header.info.map, sms->header.info.map_chunks, io_map, 4, 15, 0xFF); |
509 sms->z80 = init_z80_context(zopts); | 561 sms->z80 = init_z80_context(zopts); |
510 sms->z80->system = sms; | 562 sms->z80->system = sms; |
511 sms->z80->options->gen.debug_cmd_handler = debug_commands; | 563 sms->z80->options->gen.debug_cmd_handler = debug_commands; |
512 | 564 |
513 sms->rom = media->buffer; | 565 sms->rom = media->buffer; |
514 sms->rom_size = rom_size; | 566 sms->rom_size = rom_size; |
515 if (info_out->map_chunks > 2) { | 567 if (sms->header.info.map_chunks > 2) { |
516 sms->z80->mem_pointers[0] = sms->rom; | 568 sms->z80->mem_pointers[0] = sms->rom; |
517 sms->z80->mem_pointers[1] = sms->rom + 0x4000; | 569 sms->z80->mem_pointers[1] = sms->rom + 0x4000; |
518 sms->z80->mem_pointers[2] = sms->rom + 0x8000; | 570 sms->z80->mem_pointers[2] = sms->rom + 0x8000; |
519 sms->bank_regs[1] = 0; | 571 sms->bank_regs[1] = 0; |
520 sms->bank_regs[2] = 0x4000 >> 14; | 572 sms->bank_regs[2] = 0x4000 >> 14; |
521 sms->bank_regs[3] = 0x8000 >> 14; | 573 sms->bank_regs[3] = 0x8000 >> 14; |
522 } | 574 } |
523 | 575 |
524 char * lowpass_cutoff_str = tern_find_path(config, "audio\0lowpass_cutoff\0", TVAL_PTR).ptrval; | |
525 uint32_t lowpass_cutoff = lowpass_cutoff_str ? atoi(lowpass_cutoff_str) : 3390; | |
526 | |
527 //TODO: Detect region and pick master clock based off of that | 576 //TODO: Detect region and pick master clock based off of that |
528 sms->normal_clock = sms->master_clock = 53693175; | 577 sms->normal_clock = sms->master_clock = 53693175; |
529 | 578 |
530 sms->psg = malloc(sizeof(psg_context)); | 579 sms->psg = malloc(sizeof(psg_context)); |
531 psg_init(sms->psg, render_sample_rate(), sms->master_clock, 15*16, render_audio_buffer(), lowpass_cutoff); | 580 psg_init(sms->psg, sms->master_clock, 15*16); |
532 | 581 |
533 sms->vdp = malloc(sizeof(vdp_context)); | 582 sms->vdp = init_vdp_context(0); |
534 init_vdp_context(sms->vdp, 0); | |
535 sms->vdp->system = &sms->header; | 583 sms->vdp->system = &sms->header; |
536 | 584 |
537 info_out->save_type = SAVE_NONE; | 585 sms->header.info.save_type = SAVE_NONE; |
538 info_out->name = strdup(media->name); | 586 sms->header.info.name = strdup(media->name); |
539 | 587 |
540 setup_io_devices(config, info_out, &sms->io); | 588 setup_io_devices(config, &sms->header.info, &sms->io); |
589 sms->header.has_keyboard = io_has_keyboard(&sms->io); | |
541 | 590 |
542 sms->header.set_speed_percent = set_speed_percent; | 591 sms->header.set_speed_percent = set_speed_percent; |
543 sms->header.start_context = start_sms; | 592 sms->header.start_context = start_sms; |
544 sms->header.resume_context = resume_sms; | 593 sms->header.resume_context = resume_sms; |
545 sms->header.load_save = load_save; | 594 sms->header.load_save = load_save; |
548 sms->header.free_context = free_sms; | 597 sms->header.free_context = free_sms; |
549 sms->header.get_open_bus_value = get_open_bus_value; | 598 sms->header.get_open_bus_value = get_open_bus_value; |
550 sms->header.request_exit = request_exit; | 599 sms->header.request_exit = request_exit; |
551 sms->header.soft_reset = soft_reset; | 600 sms->header.soft_reset = soft_reset; |
552 sms->header.inc_debug_mode = inc_debug_mode; | 601 sms->header.inc_debug_mode = inc_debug_mode; |
553 sms->header.inc_debug_pal = inc_debug_pal; | 602 sms->header.gamepad_down = gamepad_down; |
603 sms->header.gamepad_up = gamepad_up; | |
604 sms->header.mouse_down = mouse_down; | |
605 sms->header.mouse_up = mouse_up; | |
606 sms->header.mouse_motion_absolute = mouse_motion_absolute; | |
607 sms->header.mouse_motion_relative = mouse_motion_relative; | |
608 sms->header.keyboard_down = keyboard_down; | |
609 sms->header.keyboard_up = keyboard_up; | |
610 sms->header.config_updated = config_updated; | |
554 sms->header.type = SYSTEM_SMS; | 611 sms->header.type = SYSTEM_SMS; |
555 | 612 |
556 return sms; | 613 return sms; |
557 } | 614 } |