Mercurial > repos > blastem
comparison genesis.c @ 1116:fe8c79f82c22
More cleanup in preparation for SMS/Mark III support
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 22 Dec 2016 10:51:33 -0800 |
parents | 45db303fc705 |
children | 928a65750345 |
comparison
equal
deleted
inserted
replaced
1115:c1e78a101912 | 1116:fe8c79f82c22 |
---|---|
43 { | 43 { |
44 genesis_context *genesis = (genesis_context *)current_system; | 44 genesis_context *genesis = (genesis_context *)current_system; |
45 return read_dma_value(genesis->m68k->last_prefetch_address/2); | 45 return read_dma_value(genesis->m68k->last_prefetch_address/2); |
46 } | 46 } |
47 | 47 |
48 void adjust_int_cycle(m68k_context * context, vdp_context * v_context) | 48 static void adjust_int_cycle(m68k_context * context, vdp_context * v_context) |
49 { | 49 { |
50 //static int old_int_cycle = CYCLE_NEVER; | 50 //static int old_int_cycle = CYCLE_NEVER; |
51 genesis_context *gen = context->system; | 51 genesis_context *gen = context->system; |
52 if (context->sync_cycle - context->current_cycle > gen->max_cycles) { | 52 if (context->sync_cycle - context->current_cycle > gen->max_cycles) { |
53 context->sync_cycle = context->current_cycle + gen->max_cycles; | 53 context->sync_cycle = context->current_cycle + gen->max_cycles; |
107 z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp); | 107 z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp); |
108 //Notes in the Genesis Plus GX code suggest this is asserted for one line | 108 //Notes in the Genesis Plus GX code suggest this is asserted for one line |
109 z_context->int_pulse_end = z_context->int_pulse_start + MCLKS_LINE; | 109 z_context->int_pulse_end = z_context->int_pulse_start + MCLKS_LINE; |
110 } | 110 } |
111 | 111 |
112 void sync_z80(z80_context * z_context, uint32_t mclks) | 112 static void sync_z80(z80_context * z_context, uint32_t mclks) |
113 { | 113 { |
114 #ifndef NO_Z80 | 114 #ifndef NO_Z80 |
115 if (z80_enabled) { | 115 if (z80_enabled) { |
116 z80_run(z_context, mclks); | 116 z80_run(z_context, mclks); |
117 } else | 117 } else |
119 { | 119 { |
120 z_context->current_cycle = mclks; | 120 z_context->current_cycle = mclks; |
121 } | 121 } |
122 } | 122 } |
123 | 123 |
124 void sync_sound(genesis_context * gen, uint32_t target) | 124 static void sync_sound(genesis_context * gen, uint32_t target) |
125 { | 125 { |
126 //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); | 126 //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); |
127 while (target > gen->psg->cycles && target - gen->psg->cycles > MAX_SOUND_CYCLES) { | 127 while (target > gen->psg->cycles && target - gen->psg->cycles > MAX_SOUND_CYCLES) { |
128 uint32_t cur_target = gen->psg->cycles + MAX_SOUND_CYCLES; | 128 uint32_t cur_target = gen->psg->cycles + MAX_SOUND_CYCLES; |
129 //printf("Running PSG to cycle %d\n", cur_target); | 129 //printf("Running PSG to cycle %d\n", cur_target); |
135 ym_run(gen->ym, target); | 135 ym_run(gen->ym, target); |
136 | 136 |
137 //printf("Target: %d, YM bufferpos: %d, PSG bufferpos: %d\n", target, gen->ym->buffer_pos, gen->psg->buffer_pos * 2); | 137 //printf("Target: %d, YM bufferpos: %d, PSG bufferpos: %d\n", target, gen->ym->buffer_pos, gen->psg->buffer_pos * 2); |
138 } | 138 } |
139 | 139 |
140 uint32_t last_frame_num; | 140 //TODO: move this inside the system context |
141 static uint32_t last_frame_num; | |
141 | 142 |
142 //My refresh emulation isn't currently good enough and causes more problems than it solves | 143 //My refresh emulation isn't currently good enough and causes more problems than it solves |
143 #ifdef REFRESH_EMULATION | 144 #ifdef REFRESH_EMULATION |
144 #define REFRESH_INTERVAL 128 | 145 #define REFRESH_INTERVAL 128 |
145 #define REFRESH_DELAY 2 | 146 #define REFRESH_DELAY 2 |
235 last_sync_cycle = context->current_cycle; | 236 last_sync_cycle = context->current_cycle; |
236 #endif | 237 #endif |
237 return context; | 238 return context; |
238 } | 239 } |
239 | 240 |
240 m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_t value) | 241 static m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_t value) |
241 { | 242 { |
242 if (vdp_port & 0x2700E0) { | 243 if (vdp_port & 0x2700E0) { |
243 fatal_error("machine freeze due to write to address %X\n", 0xC00000 | vdp_port); | 244 fatal_error("machine freeze due to write to address %X\n", 0xC00000 | vdp_port); |
244 } | 245 } |
245 vdp_port &= 0x1F; | 246 vdp_port &= 0x1F; |
330 //TODO: Implement undocumented test register(s) | 331 //TODO: Implement undocumented test register(s) |
331 } | 332 } |
332 return context; | 333 return context; |
333 } | 334 } |
334 | 335 |
335 m68k_context * vdp_port_write_b(uint32_t vdp_port, m68k_context * context, uint8_t value) | 336 static m68k_context * vdp_port_write_b(uint32_t vdp_port, m68k_context * context, uint8_t value) |
336 { | 337 { |
337 return vdp_port_write(vdp_port, context, vdp_port < 0x10 ? value | value << 8 : ((vdp_port & 1) ? value : 0)); | 338 return vdp_port_write(vdp_port, context, vdp_port < 0x10 ? value | value << 8 : ((vdp_port & 1) ? value : 0)); |
338 } | 339 } |
339 | 340 |
340 void * z80_vdp_port_write(uint32_t vdp_port, void * vcontext, uint8_t value) | 341 static void * z80_vdp_port_write(uint32_t vdp_port, void * vcontext, uint8_t value) |
341 { | 342 { |
342 z80_context * context = vcontext; | 343 z80_context * context = vcontext; |
343 genesis_context * gen = context->system; | 344 genesis_context * gen = context->system; |
344 vdp_port &= 0xFF; | 345 vdp_port &= 0xFF; |
345 if (vdp_port & 0xE0) { | 346 if (vdp_port & 0xE0) { |
362 vdp_test_port_write(gen->vdp, value); | 363 vdp_test_port_write(gen->vdp, value); |
363 } | 364 } |
364 return context; | 365 return context; |
365 } | 366 } |
366 | 367 |
367 uint16_t vdp_port_read(uint32_t vdp_port, m68k_context * context) | 368 static uint16_t vdp_port_read(uint32_t vdp_port, m68k_context * context) |
368 { | 369 { |
369 if (vdp_port & 0x2700E0) { | 370 if (vdp_port & 0x2700E0) { |
370 fatal_error("machine freeze due to read from address %X\n", 0xC00000 | vdp_port); | 371 fatal_error("machine freeze due to read from address %X\n", 0xC00000 | vdp_port); |
371 } | 372 } |
372 vdp_port &= 0x1F; | 373 vdp_port &= 0x1F; |
402 gen->bus_busy = 0; | 403 gen->bus_busy = 0; |
403 } | 404 } |
404 return value; | 405 return value; |
405 } | 406 } |
406 | 407 |
407 uint8_t vdp_port_read_b(uint32_t vdp_port, m68k_context * context) | 408 static uint8_t vdp_port_read_b(uint32_t vdp_port, m68k_context * context) |
408 { | 409 { |
409 uint16_t value = vdp_port_read(vdp_port, context); | 410 uint16_t value = vdp_port_read(vdp_port, context); |
410 if (vdp_port & 1) { | 411 if (vdp_port & 1) { |
411 return value; | 412 return value; |
412 } else { | 413 } else { |
413 return value >> 8; | 414 return value >> 8; |
414 } | 415 } |
415 } | 416 } |
416 | 417 |
417 uint8_t z80_vdp_port_read(uint32_t vdp_port, void * vcontext) | 418 static uint8_t z80_vdp_port_read(uint32_t vdp_port, void * vcontext) |
418 { | 419 { |
419 z80_context * context = vcontext; | 420 z80_context * context = vcontext; |
420 if (vdp_port & 0xE0) { | 421 if (vdp_port & 0xE0) { |
421 fatal_error("machine freeze due to read from Z80 address %X\n", 0x7F00 | vdp_port); | 422 fatal_error("machine freeze due to read from Z80 address %X\n", 0x7F00 | vdp_port); |
422 } | 423 } |
447 ret = 0xFFFF; | 448 ret = 0xFFFF; |
448 } | 449 } |
449 return vdp_port & 1 ? ret : ret >> 8; | 450 return vdp_port & 1 ? ret : ret >> 8; |
450 } | 451 } |
451 | 452 |
452 uint32_t zram_counter = 0; | 453 //TODO: Move this inside the system context |
453 | 454 static uint32_t zram_counter = 0; |
454 m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value) | 455 |
456 static m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value) | |
455 { | 457 { |
456 genesis_context * gen = context->system; | 458 genesis_context * gen = context->system; |
457 if (location < 0x10000) { | 459 if (location < 0x10000) { |
458 //Access to Z80 memory incurs a one 68K cycle wait state | 460 //Access to Z80 memory incurs a one 68K cycle wait state |
459 context->current_cycle += MCLKS_PER_68K; | 461 context->current_cycle += MCLKS_PER_68K; |
553 } | 555 } |
554 } | 556 } |
555 return context; | 557 return context; |
556 } | 558 } |
557 | 559 |
558 m68k_context * io_write_w(uint32_t location, m68k_context * context, uint16_t value) | 560 static m68k_context * io_write_w(uint32_t location, m68k_context * context, uint16_t value) |
559 { | 561 { |
560 if (location < 0x10000 || (location & 0x1FFF) >= 0x100) { | 562 if (location < 0x10000 || (location & 0x1FFF) >= 0x100) { |
561 return io_write(location, context, value >> 8); | 563 return io_write(location, context, value >> 8); |
562 } else { | 564 } else { |
563 return io_write(location, context, value); | 565 return io_write(location, context, value); |
569 #define USA FOREIGN | 571 #define USA FOREIGN |
570 #define JAP 0x00 | 572 #define JAP 0x00 |
571 #define EUR (HZ50|FOREIGN) | 573 #define EUR (HZ50|FOREIGN) |
572 #define NO_DISK 0x20 | 574 #define NO_DISK 0x20 |
573 | 575 |
574 uint8_t io_read(uint32_t location, m68k_context * context) | 576 static uint8_t io_read(uint32_t location, m68k_context * context) |
575 { | 577 { |
576 uint8_t value; | 578 uint8_t value; |
577 genesis_context *gen = context->system; | 579 genesis_context *gen = context->system; |
578 if (location < 0x10000) { | 580 if (location < 0x10000) { |
579 //Access to Z80 memory incurs a one 68K cycle wait state | 581 //Access to Z80 memory incurs a one 68K cycle wait state |
635 } | 637 } |
636 } | 638 } |
637 return value; | 639 return value; |
638 } | 640 } |
639 | 641 |
640 uint16_t io_read_w(uint32_t location, m68k_context * context) | 642 static uint16_t io_read_w(uint32_t location, m68k_context * context) |
641 { | 643 { |
642 uint16_t value = io_read(location, context); | 644 uint16_t value = io_read(location, context); |
643 if (location < 0x10000 || (location & 0x1FFF) < 0x100) { | 645 if (location < 0x10000 || (location & 0x1FFF) < 0x100) { |
644 value = value | (value << 8); | 646 value = value | (value << 8); |
645 } else { | 647 } else { |
647 value |= get_open_bus_value() & 0xFF; | 649 value |= get_open_bus_value() & 0xFF; |
648 } | 650 } |
649 return value; | 651 return value; |
650 } | 652 } |
651 | 653 |
652 void * z80_write_ym(uint32_t location, void * vcontext, uint8_t value) | 654 static void * z80_write_ym(uint32_t location, void * vcontext, uint8_t value) |
653 { | 655 { |
654 z80_context * context = vcontext; | 656 z80_context * context = vcontext; |
655 genesis_context * gen = context->system; | 657 genesis_context * gen = context->system; |
656 sync_sound(gen, context->current_cycle); | 658 sync_sound(gen, context->current_cycle); |
657 if (location & 1) { | 659 if (location & 1) { |
662 ym_address_write_part1(gen->ym, value); | 664 ym_address_write_part1(gen->ym, value); |
663 } | 665 } |
664 return context; | 666 return context; |
665 } | 667 } |
666 | 668 |
667 uint8_t z80_read_ym(uint32_t location, void * vcontext) | 669 static uint8_t z80_read_ym(uint32_t location, void * vcontext) |
668 { | 670 { |
669 z80_context * context = vcontext; | 671 z80_context * context = vcontext; |
670 genesis_context * gen = context->system; | 672 genesis_context * gen = context->system; |
671 sync_sound(gen, context->current_cycle); | 673 sync_sound(gen, context->current_cycle); |
672 return ym_read_status(gen->ym); | 674 return ym_read_status(gen->ym); |
673 } | 675 } |
674 | 676 |
675 uint8_t z80_read_bank(uint32_t location, void * vcontext) | 677 static uint8_t z80_read_bank(uint32_t location, void * vcontext) |
676 { | 678 { |
677 z80_context * context = vcontext; | 679 z80_context * context = vcontext; |
678 genesis_context *gen = context->system; | 680 genesis_context *gen = context->system; |
679 if (gen->bus_busy) { | 681 if (gen->bus_busy) { |
680 context->current_cycle = context->sync_cycle; | 682 context->current_cycle = context->sync_cycle; |
697 fprintf(stderr, "Unhandled read by Z80 from address %X through banked memory area (%X)\n", address, context->bank_reg << 15); | 699 fprintf(stderr, "Unhandled read by Z80 from address %X through banked memory area (%X)\n", address, context->bank_reg << 15); |
698 } | 700 } |
699 return 0; | 701 return 0; |
700 } | 702 } |
701 | 703 |
702 void *z80_write_bank(uint32_t location, void * vcontext, uint8_t value) | 704 static void *z80_write_bank(uint32_t location, void * vcontext, uint8_t value) |
703 { | 705 { |
704 z80_context * context = vcontext; | 706 z80_context * context = vcontext; |
705 genesis_context *gen = context->system; | 707 genesis_context *gen = context->system; |
706 if (gen->bus_busy) { | 708 if (gen->bus_busy) { |
707 context->current_cycle = context->sync_cycle; | 709 context->current_cycle = context->sync_cycle; |
724 fprintf(stderr, "Unhandled write by Z80 to address %X through banked memory area\n", address); | 726 fprintf(stderr, "Unhandled write by Z80 to address %X through banked memory area\n", address); |
725 } | 727 } |
726 return context; | 728 return context; |
727 } | 729 } |
728 | 730 |
729 void *z80_write_bank_reg(uint32_t location, void * vcontext, uint8_t value) | 731 static void *z80_write_bank_reg(uint32_t location, void * vcontext, uint8_t value) |
730 { | 732 { |
731 z80_context * context = vcontext; | 733 z80_context * context = vcontext; |
732 | 734 |
733 context->bank_reg = (context->bank_reg >> 1 | value << 8) & 0x1FF; | 735 context->bank_reg = (context->bank_reg >> 1 | value << 8) & 0x1FF; |
734 if (context->bank_reg < 0x100) { | 736 if (context->bank_reg < 0x100) { |
746 genesis_context *context = (genesis_context *)system; | 748 genesis_context *context = (genesis_context *)system; |
747 uint32_t old_clock = context->master_clock; | 749 uint32_t old_clock = context->master_clock; |
748 context->master_clock = ((uint64_t)context->normal_clock * (uint64_t)percent) / 100; | 750 context->master_clock = ((uint64_t)context->normal_clock * (uint64_t)percent) / 100; |
749 while (context->ym->current_cycle != context->psg->cycles) { | 751 while (context->ym->current_cycle != context->psg->cycles) { |
750 sync_sound(context, context->psg->cycles + MCLKS_PER_PSG); | 752 sync_sound(context, context->psg->cycles + MCLKS_PER_PSG); |
751 } | 753 } |
752 ym_adjust_master_clock(context->ym, context->master_clock); | 754 ym_adjust_master_clock(context->ym, context->master_clock); |
753 psg_adjust_master_clock(context->psg, context->master_clock); | 755 psg_adjust_master_clock(context->psg, context->master_clock); |
754 } | 756 } |
755 | 757 |
756 void set_region(genesis_context *gen, rom_info *info, uint8_t region) | 758 void set_region(genesis_context *gen, rom_info *info, uint8_t region) |
868 static void free_genesis(system_header *system) | 870 static void free_genesis(system_header *system) |
869 { | 871 { |
870 genesis_context *gen = (genesis_context *)system; | 872 genesis_context *gen = (genesis_context *)system; |
871 vdp_free(gen->vdp); | 873 vdp_free(gen->vdp); |
872 m68k_options_free(gen->m68k->options); | 874 m68k_options_free(gen->m68k->options); |
875 free(gen->cart); | |
873 free(gen->m68k); | 876 free(gen->m68k); |
874 free(gen->work_ram); | 877 free(gen->work_ram); |
875 z80_options_free(gen->z80->options); | 878 z80_options_free(gen->z80->options); |
876 free(gen->z80); | 879 free(gen->z80); |
877 free(gen->zram); | 880 free(gen->zram); |
878 ym_free(gen->ym); | 881 ym_free(gen->ym); |
879 psg_free(gen->psg); | 882 psg_free(gen->psg); |
880 free(gen->save_storage); | 883 free(gen->save_storage); |
881 free(gen->header.save_dir); | 884 free(gen->header.save_dir); |
882 free(gen->lock_on); | 885 free(gen->lock_on); |
886 free(gen); | |
883 } | 887 } |
884 | 888 |
885 genesis_context *alloc_init_genesis(rom_info *rom, void *main_rom, void *lock_on, uint32_t system_opts, uint8_t force_region) | 889 genesis_context *alloc_init_genesis(rom_info *rom, void *main_rom, void *lock_on, uint32_t system_opts, uint8_t force_region) |
886 { | 890 { |
887 static memmap_chunk z80_map[] = { | 891 static memmap_chunk z80_map[] = { |
921 gen->z80 = calloc(1, sizeof(z80_context)); | 925 gen->z80 = calloc(1, sizeof(z80_context)); |
922 gen->zram = calloc(1, Z80_RAM_BYTES); | 926 gen->zram = calloc(1, Z80_RAM_BYTES); |
923 z80_map[0].buffer = gen->zram = calloc(1, Z80_RAM_BYTES); | 927 z80_map[0].buffer = gen->zram = calloc(1, Z80_RAM_BYTES); |
924 #ifndef NO_Z80 | 928 #ifndef NO_Z80 |
925 z80_options *z_opts = malloc(sizeof(z80_options)); | 929 z80_options *z_opts = malloc(sizeof(z80_options)); |
926 init_z80_opts(z_opts, z80_map, 5, NULL, 0, MCLKS_PER_Z80); | 930 init_z80_opts(z_opts, z80_map, 5, NULL, 0, MCLKS_PER_Z80, 0xFFFF); |
927 init_z80_context(gen->z80, z_opts); | 931 init_z80_context(gen->z80, z_opts); |
928 z80_assert_reset(gen->z80, 0); | 932 z80_assert_reset(gen->z80, 0); |
929 #endif | 933 #endif |
930 | 934 |
931 gen->z80->system = gen; | 935 gen->z80->system = gen; |
933 gen->z80->mem_pointers[1] = gen->z80->mem_pointers[2] = (uint8_t *)main_rom; | 937 gen->z80->mem_pointers[1] = gen->z80->mem_pointers[2] = (uint8_t *)main_rom; |
934 | 938 |
935 gen->cart = main_rom; | 939 gen->cart = main_rom; |
936 gen->lock_on = lock_on; | 940 gen->lock_on = lock_on; |
937 gen->work_ram = calloc(2, RAM_WORDS); | 941 gen->work_ram = calloc(2, RAM_WORDS); |
938 setup_io_devices(config, rom, gen); | 942 setup_io_devices(config, rom, &gen->io); |
939 | 943 |
940 gen->save_type = rom->save_type; | 944 gen->save_type = rom->save_type; |
941 gen->save_type = rom->save_type; | 945 gen->save_type = rom->save_type; |
942 if (gen->save_type != SAVE_NONE) { | 946 if (gen->save_type != SAVE_NONE) { |
943 gen->save_ram_mask = rom->save_mask; | 947 gen->save_ram_mask = rom->save_mask; |