From a39a82cc9773c8336eaa48379f2d2fe3615f178c Mon Sep 17 00:00:00 2001 From: Mike Pavone Date: Tue, 17 Jun 2014 01:50:29 -0400 Subject: blastem builds and almost works on OS X now --- blastem.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 52de892..962ea9b 100644 --- a/blastem.c +++ b/blastem.c @@ -383,6 +383,7 @@ m68k_context * vdp_port_write_b(uint32_t vdp_port, m68k_context * context, uint8 return vdp_port_write(vdp_port, context, vdp_port < 0x10 ? value | value << 8 : ((vdp_port & 1) ? value : 0)); } +z80_context * z80_vdp_port_write(uint16_t vdp_port, z80_context * context, uint8_t value) asm("z80_vdp_port_write"); z80_context * z80_vdp_port_write(uint16_t vdp_port, z80_context * context, uint8_t value) { genesis_context * gen = context->system; @@ -674,6 +675,7 @@ uint16_t io_read_w(uint32_t location, m68k_context * context) return value; } +extern z80_context * z80_write_ym(uint16_t location, z80_context * context, uint8_t value) asm("z80_write_ym"); z80_context * z80_write_ym(uint16_t location, z80_context * context, uint8_t value) { genesis_context * gen = context->system; @@ -688,6 +690,7 @@ z80_context * z80_write_ym(uint16_t location, z80_context * context, uint8_t val return context; } +extern uint8_t z80_read_ym(uint16_t location, z80_context * context) asm("z80_read_ym"); uint8_t z80_read_ym(uint16_t location, z80_context * context) { genesis_context * gen = context->system; -- cgit v1.2.3 From b28dc876ea3d900787f2c953ddd84056924f7308 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Wed, 18 Jun 2014 16:30:19 -0700 Subject: Fix most of the breakage caused by the vcounter/hcounter changes --- blastem.c | 53 +++++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 26 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index c4072e3..83c2c23 100644 --- a/blastem.c +++ b/blastem.c @@ -33,7 +33,7 @@ #define MAX_SOUND_CYCLES 100000 -uint32_t mclks_per_frame = MCLKS_LINE*LINES_NTSC; +uint32_t mclk_target = 0; uint16_t cart[CARTRIDGE_WORDS]; uint16_t ram[RAM_WORDS]; @@ -231,15 +231,15 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) z80_context * z_context = gen->z80; uint32_t mclks = context->current_cycle * MCLKS_PER_68K; sync_z80(z_context, mclks); - if (mclks >= mclks_per_frame) { + if (mclks >= mclk_target) { sync_sound(gen, mclks); - gen->ym->current_cycle -= mclks_per_frame; - gen->psg->cycles -= mclks_per_frame; + gen->ym->current_cycle -= mclk_target; + gen->psg->cycles -= mclk_target; if (gen->ym->write_cycle != CYCLE_NEVER) { - gen->ym->write_cycle = gen->ym->write_cycle >= mclks_per_frame/MCLKS_PER_68K ? gen->ym->write_cycle - mclks_per_frame/MCLKS_PER_68K : 0; + gen->ym->write_cycle = gen->ym->write_cycle >= mclk_target/MCLKS_PER_68K ? gen->ym->write_cycle - mclk_target/MCLKS_PER_68K : 0; } //printf("reached frame end | 68K Cycles: %d, MCLK Cycles: %d\n", context->current_cycle, mclks); - vdp_run_context(v_context, mclks_per_frame); + vdp_run_context(v_context, mclk_target); if (!headless) { break_on_sync |= wait_render_frame(v_context, frame_limit); @@ -250,28 +250,29 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) } } frame++; - mclks -= mclks_per_frame; - vdp_adjust_cycles(v_context, mclks_per_frame); - io_adjust_cycles(gen->ports, context->current_cycle, mclks_per_frame/MCLKS_PER_68K); - io_adjust_cycles(gen->ports+1, context->current_cycle, mclks_per_frame/MCLKS_PER_68K); - io_adjust_cycles(gen->ports+2, context->current_cycle, mclks_per_frame/MCLKS_PER_68K); + mclks -= mclk_target; + vdp_adjust_cycles(v_context, mclk_target); + io_adjust_cycles(gen->ports, context->current_cycle, mclk_target/MCLKS_PER_68K); + io_adjust_cycles(gen->ports+1, context->current_cycle, mclk_target/MCLKS_PER_68K); + io_adjust_cycles(gen->ports+2, context->current_cycle, mclk_target/MCLKS_PER_68K); if (busack_cycle != CYCLE_NEVER) { - if (busack_cycle > mclks_per_frame/MCLKS_PER_68K) { - busack_cycle -= mclks_per_frame/MCLKS_PER_68K; + if (busack_cycle > mclk_target/MCLKS_PER_68K) { + busack_cycle -= mclk_target/MCLKS_PER_68K; } else { busack_cycle = CYCLE_NEVER; busack = new_busack; } } - context->current_cycle -= mclks_per_frame/MCLKS_PER_68K; - if (z_context->current_cycle >= mclks_per_frame/MCLKS_PER_Z80) { - z_context->current_cycle -= mclks_per_frame/MCLKS_PER_Z80; + context->current_cycle -= mclk_target/MCLKS_PER_68K; + if (z_context->current_cycle >= mclk_target/MCLKS_PER_Z80) { + z_context->current_cycle -= mclk_target/MCLKS_PER_Z80; } else { z_context->current_cycle = 0; } if (mclks) { vdp_run_context(v_context, mclks); } + mclk_target = vdp_cycles_to_frame_end(v_context); } else { //printf("running VDP for %d cycles\n", mclks - v_context->cycles); vdp_run_context(v_context, mclks); @@ -317,10 +318,10 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ gen->bus_busy = 1; while (vdp_data_port_write(v_context, value) < 0) { while(v_context->flags & FLAG_DMA_RUN) { - vdp_run_dma_done(v_context, mclks_per_frame); - if (v_context->cycles >= mclks_per_frame) { + vdp_run_dma_done(v_context, mclk_target); + if (v_context->cycles >= mclk_target) { context->current_cycle = v_context->cycles / MCLKS_PER_68K; - if (context->current_cycle * MCLKS_PER_68K < mclks_per_frame) { + if (context->current_cycle * MCLKS_PER_68K < mclk_target) { ++context->current_cycle; } sync_components(context, 0); @@ -334,10 +335,10 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ if (blocked) { while (blocked) { while(v_context->flags & FLAG_DMA_RUN) { - vdp_run_dma_done(v_context, mclks_per_frame); - if (v_context->cycles >= mclks_per_frame) { + vdp_run_dma_done(v_context, mclk_target); + if (v_context->cycles >= mclk_target) { context->current_cycle = v_context->cycles / MCLKS_PER_68K; - if (context->current_cycle * MCLKS_PER_68K < mclks_per_frame) { + if (context->current_cycle * MCLKS_PER_68K < mclk_target) { ++context->current_cycle; } sync_components(context, 0); @@ -966,7 +967,7 @@ void init_run_cpu(genesis_context * gen, FILE * address_log, char * statefile, u context.system = gen; //cartridge ROM context.mem_pointers[0] = cart; - context.target_cycle = context.sync_cycle = mclks_per_frame/MCLKS_PER_68K; + context.target_cycle = context.sync_cycle = mclk_target/MCLKS_PER_68K; //work RAM context.mem_pointers[1] = ram; //save RAM/map @@ -1210,7 +1211,6 @@ int main(int argc, char ** argv) height = height < 240 ? (width/320) * 240 : height; uint32_t fps = 60; if (version_reg & 0x40) { - mclks_per_frame = MCLKS_LINE * LINES_PAL; fps = 50; } if (!headless) { @@ -1221,7 +1221,8 @@ int main(int argc, char ** argv) memset(&gen, 0, sizeof(gen)); gen.master_clock = gen.normal_clock = fps == 60 ? MCLKS_NTSC : MCLKS_PAL; - init_vdp_context(&v_context); + init_vdp_context(&v_context, version_reg & 0x40); + mclk_target = vdp_cycles_to_frame_end(&v_context); ym2612_context y_context; ym_init(&y_context, render_sample_rate(), gen.master_clock, MCLKS_PER_YM, render_audio_buffer(), ym_log ? YM_OPT_WAVE_LOG : 0); @@ -1236,7 +1237,7 @@ int main(int argc, char ** argv) z_context.system = &gen; z_context.mem_pointers[0] = z80_ram; - z_context.sync_cycle = z_context.target_cycle = mclks_per_frame/MCLKS_PER_Z80; + z_context.sync_cycle = z_context.target_cycle = mclk_target/MCLKS_PER_Z80; z_context.int_cycle = CYCLE_NEVER; z_context.mem_pointers[1] = z_context.mem_pointers[2] = (uint8_t *)cart; -- cgit v1.2.3 From e8e8075b59f9e4a6a8e9b1cc96f2fcb447fa508e Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Thu, 19 Jun 2014 08:14:35 -0700 Subject: Slight cleanup of vint handling on the Z80 --- blastem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 83c2c23..15f7932 100644 --- a/blastem.c +++ b/blastem.c @@ -192,11 +192,11 @@ void sync_z80(z80_context * z_context, uint32_t mclks) } uint32_t vint_cycle = vdp_next_vint_z80(gen->vdp) / MCLKS_PER_Z80; while (z_context->current_cycle < z_context->sync_cycle) { - if (z_context->iff1 && z_context->current_cycle < (vint_cycle + Z80_VINT_DURATION)) { + if (z_context->iff1 && z_context->int_cycle == CYCLE_NEVER && z_context->current_cycle < (vint_cycle + Z80_VINT_DURATION)) { z_context->int_cycle = vint_cycle < z_context->int_enable_cycle ? z_context->int_enable_cycle : vint_cycle; } z_context->target_cycle = z_context->sync_cycle < z_context->int_cycle ? z_context->sync_cycle : z_context->int_cycle; - dprintf("Running Z80 from cycle %d to cycle %d. Native PC: %p\n", z_context->current_cycle, z_context->sync_cycle, z_context->native_pc); + dprintf("Running Z80 from cycle %d to cycle %d. Int cycle: %d\n", z_context->current_cycle, z_context->sync_cycle, z_context->int_cycle); z80_run(z_context); dprintf("Z80 ran to cycle %d\n", z_context->current_cycle); } -- cgit v1.2.3 From 24d56647b3b2baa4e7016ac5d66c0167d51688be Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Sat, 21 Jun 2014 09:36:15 -0700 Subject: Fix Z80 interrupts --- blastem.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 15f7932..18e11b6 100644 --- a/blastem.c +++ b/blastem.c @@ -190,10 +190,14 @@ void sync_z80(z80_context * z_context, uint32_t mclks) z80_reset(z_context); need_reset = 0; } - uint32_t vint_cycle = vdp_next_vint_z80(gen->vdp) / MCLKS_PER_Z80; + while (z_context->current_cycle < z_context->sync_cycle) { - if (z_context->iff1 && z_context->int_cycle == CYCLE_NEVER && z_context->current_cycle < (vint_cycle + Z80_VINT_DURATION)) { - z_context->int_cycle = vint_cycle < z_context->int_enable_cycle ? z_context->int_enable_cycle : vint_cycle; + if (z_context->int_pulse_end < z_context->current_cycle || z_context->int_pulse_end == CYCLE_NEVER) { + z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp) / MCLKS_PER_Z80; + z_context->int_pulse_end = z_context->int_pulse_start + Z80_VINT_DURATION; + } + if (z_context->iff1) { + z_context->int_cycle = z_context->int_pulse_start < z_context->int_enable_cycle ? z_context->int_enable_cycle : z_context->int_pulse_start; } z_context->target_cycle = z_context->sync_cycle < z_context->int_cycle ? z_context->sync_cycle : z_context->int_cycle; dprintf("Running Z80 from cycle %d to cycle %d. Int cycle: %d\n", z_context->current_cycle, z_context->sync_cycle, z_context->int_cycle); @@ -269,6 +273,31 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) } else { z_context->current_cycle = 0; } + if (z_context->int_cycle != CYCLE_NEVER) { + if (z_context->int_cycle >= mclk_target/MCLKS_PER_Z80) { + z_context->int_cycle -= mclk_target/MCLKS_PER_Z80; + } else { + z_context->int_cycle = 0; + } + } + if (z_context->int_pulse_start != CYCLE_NEVER) { + if (z_context->int_pulse_end >= mclk_target/MCLKS_PER_Z80) { + z_context->int_pulse_end -= mclk_target/MCLKS_PER_Z80; + if (z_context->int_pulse_start >= mclk_target/MCLKS_PER_Z80) { + z_context->int_pulse_start -= mclk_target/MCLKS_PER_Z80; + } else { + z_context->int_pulse_start = 0; + } + } + } else { + z_context->int_pulse_start = CYCLE_NEVER; + z_context->int_pulse_end = CYCLE_NEVER; + } + if (z_context->int_enable_cycle >= mclk_target/MCLKS_PER_Z80) { + z_context->int_enable_cycle -= mclk_target/MCLKS_PER_Z80; + } else { + z_context->int_enable_cycle = 0; + } if (mclks) { vdp_run_context(v_context, mclks); } -- cgit v1.2.3 From 77b05f2312cde22951903192667d2a23823890c5 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Wed, 3 Dec 2014 09:32:32 -0800 Subject: Initial support for configurable IO, custom IO and sega transfer board emulation --- blastem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 18e11b6..de2d5a5 100644 --- a/blastem.c +++ b/blastem.c @@ -1289,7 +1289,7 @@ int main(int argc, char ** argv) if (i < 0) { strcpy(sram_filename + fname_size, ".sram"); } - set_keybindings(); + set_keybindings(gen.ports); init_run_cpu(&gen, address_log, statefile, debuggerfun); return 0; -- cgit v1.2.3 From d07b907bc7889308890b590d2aaf88dfc44ae616 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Sun, 14 Dec 2014 16:45:23 -0800 Subject: WIP effort to update z80 core for code gen changes --- blastem.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 7d31540..4555f86 100644 --- a/blastem.c +++ b/blastem.c @@ -1072,6 +1072,15 @@ void detect_region() } } } +#ifndef NO_Z80 +const memmap_chunk z80_map[] = { + { 0x0000, 0x4000, 0x1FFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, z80_ram, NULL, NULL, NULL, NULL }, + { 0x8000, 0x10000, 0xFFFF, 1, MMAP_READ | MMAP_WRITE | MMAP_PTR_IDX | MMAP_FUNC_NULL, NULL, NULL, NULL, z80_read_bank, z80_write_bank}, + { 0x4000, 0x6000, 0x0003, 0, MMAP_READ | MMAP_WRITE, NULL, NULL, NULL, z80_read_ym, z80_write_ym}, + { 0x6000, 0x6100, 0xFFFF, 0, MMAP_WRITE | MMAP_CUSTOM, NULL, NULL, NULL, NULL, (write_8_fun)z80_gen_bank_write}, + { 0x7F00, 0x8000, 0x00FF, 0, MMAP_READ | MMAP_WRITE, NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write} +}; +#endif int main(int argc, char ** argv) { @@ -1237,9 +1246,9 @@ int main(int argc, char ** argv) psg_init(&p_context, render_sample_rate(), gen.master_clock, MCLKS_PER_PSG, render_audio_buffer()); z80_context z_context; - x86_z80_options z_opts; #ifndef NO_Z80 - init_x86_z80_opts(&z_opts); + z80_options z_opts; + init_x86_z80_opts(&z_opts, z80_map, 5); init_z80_context(&z_context, &z_opts); #endif -- cgit v1.2.3 From 4cad512b6d7ac0f7042b90e1029626fb14788bf0 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Wed, 17 Dec 2014 23:03:19 -0800 Subject: Get rest of emulator compiling again with Z80 core enabled --- blastem.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 4555f86..2659fa4 100644 --- a/blastem.c +++ b/blastem.c @@ -383,8 +383,9 @@ m68k_context * vdp_port_write_b(uint32_t vdp_port, m68k_context * context, uint8 return vdp_port_write(vdp_port, context, vdp_port < 0x10 ? value | value << 8 : ((vdp_port & 1) ? value : 0)); } -z80_context * z80_vdp_port_write(uint16_t vdp_port, z80_context * context, uint8_t value) +void * z80_vdp_port_write(uint32_t vdp_port, void * vcontext, uint8_t value) { + z80_context * context = vcontext; genesis_context * gen = context->system; if (vdp_port & 0xE0) { printf("machine freeze due to write to Z80 address %X\n", 0x7F00 | vdp_port); @@ -453,6 +454,34 @@ uint8_t vdp_port_read_b(uint32_t vdp_port, m68k_context * context) } } +uint8_t z80_vdp_port_read(uint32_t vdp_port, void * vcontext) +{ + z80_context * context = vcontext; + if (vdp_port & 0xE0) { + printf("machine freeze due to read from Z80 address %X\n", 0x7F00 | vdp_port); + exit(1); + } + genesis_context * gen = context->system; + vdp_port &= 0x1F; + uint16_t ret; + if (vdp_port < 0x10) { + //These probably won't currently interact well with the 68K accessing the VDP + vdp_run_context(gen->vdp, context->current_cycle * MCLKS_PER_Z80); + if (vdp_port < 4) { + ret = vdp_data_port_read(gen->vdp); + } else if (vdp_port < 8) { + ret = vdp_control_port_read(gen->vdp); + } else { + printf("Illegal write to HV Counter port %X\n", vdp_port); + exit(1); + } + } else { + //TODO: Figure out the correct value today + ret = 0xFFFF; + } + return vdp_port & 1 ? ret : ret >> 8; +} + uint32_t zram_counter = 0; #define Z80_ACK_DELAY 3 #define Z80_BUSY_DELAY 1//TODO: Find the actual value for this @@ -674,8 +703,9 @@ uint16_t io_read_w(uint32_t location, m68k_context * context) return value; } -z80_context * z80_write_ym(uint16_t location, z80_context * context, uint8_t value) +void * z80_write_ym(uint32_t location, void * vcontext, uint8_t value) { + z80_context * context = vcontext; genesis_context * gen = context->system; sync_sound(gen, context->current_cycle * MCLKS_PER_Z80); if (location & 1) { @@ -688,13 +718,28 @@ z80_context * z80_write_ym(uint16_t location, z80_context * context, uint8_t val return context; } -uint8_t z80_read_ym(uint16_t location, z80_context * context) +uint8_t z80_read_ym(uint32_t location, void * vcontext) { + z80_context * context = vcontext; genesis_context * gen = context->system; sync_sound(gen, context->current_cycle * MCLKS_PER_Z80); return ym_read_status(gen->ym); } +uint8_t z80_read_bank(uint32_t location, void * vcontext) +{ + z80_context * context = vcontext; + //TODO: Implement me + return 0; +} + +void *z80_write_bank(uint32_t location, void * vcontext, uint8_t value) +{ + z80_context * context = vcontext; + //TODO: Implement me + return context; +} + uint16_t read_sram_w(uint32_t address, m68k_context * context) { genesis_context * gen = context->system; -- cgit v1.2.3 From 12c73dc400c1b6b61531df4ff0fd1efe4ef7ae12 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Mon, 22 Dec 2014 20:55:10 -0800 Subject: Z80 core is sort of working again --- blastem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 2659fa4..c704ef2 100644 --- a/blastem.c +++ b/blastem.c @@ -198,7 +198,7 @@ void sync_z80(z80_context * z_context, uint32_t mclks) } z_context->target_cycle = z_context->sync_cycle < z_context->int_cycle ? z_context->sync_cycle : z_context->int_cycle; dprintf("Running Z80 from cycle %d to cycle %d. Native PC: %p\n", z_context->current_cycle, z_context->sync_cycle, z_context->native_pc); - z80_run(z_context); + z_context->run(z_context); dprintf("Z80 ran to cycle %d\n", z_context->current_cycle); } } -- cgit v1.2.3 From f9dade6a1ea8e660735a684ce9b80168e50064f7 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Fri, 26 Dec 2014 15:46:53 -0800 Subject: Set int_cycle to CYCLE_NEVER in sync_z80 so that the interrupt routine isn't taken inappropriately now that the kludge in handle_cycle_limit_int has been removed --- blastem.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index c704ef2..13b3429 100644 --- a/blastem.c +++ b/blastem.c @@ -195,6 +195,8 @@ void sync_z80(z80_context * z_context, uint32_t mclks) while (z_context->current_cycle < z_context->sync_cycle) { if (z_context->iff1 && z_context->current_cycle < (vint_cycle + Z80_VINT_DURATION)) { z_context->int_cycle = vint_cycle < z_context->int_enable_cycle ? z_context->int_enable_cycle : vint_cycle; + } else { + z_context->int_cycle = CYCLE_NEVER; } z_context->target_cycle = z_context->sync_cycle < z_context->int_cycle ? z_context->sync_cycle : z_context->int_cycle; dprintf("Running Z80 from cycle %d to cycle %d. Native PC: %p\n", z_context->current_cycle, z_context->sync_cycle, z_context->native_pc); -- cgit v1.2.3 From 21cbee7575fce46e9730bef9df4d1e7eea819793 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Fri, 26 Dec 2014 19:37:59 -0800 Subject: Get Z80 banked access sort of working again --- blastem.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 13b3429..3500ec3 100644 --- a/blastem.c +++ b/blastem.c @@ -731,14 +731,35 @@ uint8_t z80_read_ym(uint32_t location, void * vcontext) uint8_t z80_read_bank(uint32_t location, void * vcontext) { z80_context * context = vcontext; - //TODO: Implement me + uint32_t address = context->bank_reg << 15 | location; + fprintf(stderr, "Unhandled read by Z80 from address %X through banked memory area\n", address); return 0; } void *z80_write_bank(uint32_t location, void * vcontext, uint8_t value) { z80_context * context = vcontext; - //TODO: Implement me + uint32_t address = context->bank_reg << 15 | location; + if (address >= 0xE00000) { + address &= 0xFFFF; + ((uint8_t *)ram)[address ^ 1] = value; + } else { + fprintf(stderr, "Unhandled write by Z80 to address %X through banked memory area\n", address); + } + return context; +} + +void *z80_write_bank_reg(uint32_t location, void * vcontext, uint8_t value) +{ + z80_context * context = vcontext; + + context->bank_reg = (context->bank_reg >> 1 | value << 8) & 0x1FF; + if (context->bank_reg < 0x80) { + context->mem_pointers[1] = context->mem_pointers[2] + (context->bank_reg << 15); + } else { + context->mem_pointers[1] = NULL; + } + return context; } @@ -1121,11 +1142,11 @@ void detect_region() } #ifndef NO_Z80 const memmap_chunk z80_map[] = { - { 0x0000, 0x4000, 0x1FFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, z80_ram, NULL, NULL, NULL, NULL }, - { 0x8000, 0x10000, 0xFFFF, 1, MMAP_READ | MMAP_WRITE | MMAP_PTR_IDX | MMAP_FUNC_NULL, NULL, NULL, NULL, z80_read_bank, z80_write_bank}, - { 0x4000, 0x6000, 0x0003, 0, MMAP_READ | MMAP_WRITE, NULL, NULL, NULL, z80_read_ym, z80_write_ym}, - { 0x6000, 0x6100, 0xFFFF, 0, MMAP_WRITE | MMAP_CUSTOM, NULL, NULL, NULL, NULL, (write_8_fun)z80_gen_bank_write}, - { 0x7F00, 0x8000, 0x00FF, 0, MMAP_READ | MMAP_WRITE, NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write} + { 0x0000, 0x4000, 0x1FFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, z80_ram, NULL, NULL, NULL, NULL }, + { 0x8000, 0x10000, 0xFFFF, 1, MMAP_READ | MMAP_PTR_IDX | MMAP_FUNC_NULL | MMAP_BYTESWAP, NULL, NULL, NULL, z80_read_bank, z80_write_bank}, + { 0x4000, 0x6000, 0x0003, 0, 0, NULL, NULL, NULL, z80_read_ym, z80_write_ym}, + { 0x6000, 0x6100, 0xFFFF, 0, 0, NULL, NULL, NULL, NULL, z80_write_bank_reg}, + { 0x7F00, 0x8000, 0x00FF, 0, 0, NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write} }; #endif -- cgit v1.2.3 From 1d301541a75bbc1cde775ce5deaef43c5cbb663f Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Fri, 26 Dec 2014 20:46:56 -0800 Subject: Fix mask for bank area in Z80 memory map --- blastem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 3500ec3..02e2450 100644 --- a/blastem.c +++ b/blastem.c @@ -1143,7 +1143,7 @@ void detect_region() #ifndef NO_Z80 const memmap_chunk z80_map[] = { { 0x0000, 0x4000, 0x1FFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, z80_ram, NULL, NULL, NULL, NULL }, - { 0x8000, 0x10000, 0xFFFF, 1, MMAP_READ | MMAP_PTR_IDX | MMAP_FUNC_NULL | MMAP_BYTESWAP, NULL, NULL, NULL, z80_read_bank, z80_write_bank}, + { 0x8000, 0x10000, 0x7FFF, 1, MMAP_READ | MMAP_PTR_IDX | MMAP_FUNC_NULL | MMAP_BYTESWAP, NULL, NULL, NULL, z80_read_bank, z80_write_bank}, { 0x4000, 0x6000, 0x0003, 0, 0, NULL, NULL, NULL, z80_read_ym, z80_write_ym}, { 0x6000, 0x6100, 0xFFFF, 0, 0, NULL, NULL, NULL, NULL, z80_write_bank_reg}, { 0x7F00, 0x8000, 0x00FF, 0, 0, NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write} -- cgit v1.2.3 From dcaf14476d62f2d20420226b968156f14d394450 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Mon, 29 Dec 2014 00:41:36 -0800 Subject: Add support for Z80 access to VDP via bank area --- blastem.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 02e2450..0ffa4ea 100644 --- a/blastem.c +++ b/blastem.c @@ -732,7 +732,11 @@ uint8_t z80_read_bank(uint32_t location, void * vcontext) { z80_context * context = vcontext; uint32_t address = context->bank_reg << 15 | location; - fprintf(stderr, "Unhandled read by Z80 from address %X through banked memory area\n", address); + if (address >= 0xC00000 && address < 0xE00000) { + return z80_vdp_port_read(location & 0xFF, context); + } else { + fprintf(stderr, "Unhandled read by Z80 from address %X through banked memory area\n", address); + } return 0; } @@ -743,6 +747,8 @@ void *z80_write_bank(uint32_t location, void * vcontext, uint8_t value) if (address >= 0xE00000) { address &= 0xFFFF; ((uint8_t *)ram)[address ^ 1] = value; + } else if (address >= 0xC00000) { + z80_vdp_port_write(location & 0xFF, context, value); } else { fprintf(stderr, "Unhandled write by Z80 to address %X through banked memory area\n", address); } -- cgit v1.2.3 From d41ae43228509a1a67446492b844013cf1e68c36 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Thu, 1 Jan 2015 20:26:22 -0800 Subject: Minor Z80 core cleanup --- blastem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index ddbf8ae..1e396d7 100644 --- a/blastem.c +++ b/blastem.c @@ -1352,7 +1352,7 @@ int main(int argc, char ** argv) z80_context z_context; #ifndef NO_Z80 z80_options z_opts; - init_x86_z80_opts(&z_opts, z80_map, 5); + init_z80_opts(&z_opts, z80_map, 5); init_z80_context(&z_context, &z_opts); #endif -- cgit v1.2.3 From 758586c1b7feec3c4fa3761ed17d1a6ea3cbab00 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Thu, 1 Jan 2015 22:18:32 -0800 Subject: Add the 3 cycle delay back in to Z80 bank area access --- blastem.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 1e396d7..46dbdc9 100644 --- a/blastem.c +++ b/blastem.c @@ -419,6 +419,7 @@ void * z80_vdp_port_write(uint32_t vdp_port, void * vcontext, uint8_t value) { z80_context * context = vcontext; genesis_context * gen = context->system; + vdp_port &= 0xFF; if (vdp_port & 0xE0) { printf("machine freeze due to write to Z80 address %X\n", 0x7F00 | vdp_port); exit(1); @@ -761,11 +762,20 @@ uint8_t z80_read_ym(uint32_t location, void * vcontext) uint8_t z80_read_bank(uint32_t location, void * vcontext) { z80_context * context = vcontext; + //typical delay from bus arbitration + context->current_cycle += 3; + + location &= 0x7FFF; + //TODO: add cycle for an access right after a previous one + //TODO: block Z80 if VDP has the bus or the 68K is blocked on a VDP access + if (context->mem_pointers[1]) { + return context->mem_pointers[1][location ^ 1]; + } uint32_t address = context->bank_reg << 15 | location; if (address >= 0xC00000 && address < 0xE00000) { return z80_vdp_port_read(location & 0xFF, context); } else { - fprintf(stderr, "Unhandled read by Z80 from address %X through banked memory area\n", address); + fprintf(stderr, "Unhandled read by Z80 from address %X through banked memory area (%X)\n", address, context->bank_reg << 15); } return 0; } @@ -773,6 +783,11 @@ uint8_t z80_read_bank(uint32_t location, void * vcontext) void *z80_write_bank(uint32_t location, void * vcontext, uint8_t value) { z80_context * context = vcontext; + //typical delay from bus arbitration + context->current_cycle += 3; + location &= 0x7FFF; + //TODO: add cycle for an access right after a previous one + //TODO: block Z80 if VDP has the bus or the 68K is blocked on a VDP access uint32_t address = context->bank_reg << 15 | location; if (address >= 0xE00000) { address &= 0xFFFF; @@ -791,7 +806,8 @@ void *z80_write_bank_reg(uint32_t location, void * vcontext, uint8_t value) context->bank_reg = (context->bank_reg >> 1 | value << 8) & 0x1FF; if (context->bank_reg < 0x80) { - context->mem_pointers[1] = context->mem_pointers[2] + (context->bank_reg << 15); + genesis_context *gen = context->system; + context->mem_pointers[1] = get_native_pointer(context->bank_reg << 15, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen); } else { context->mem_pointers[1] = NULL; } @@ -1178,11 +1194,11 @@ void detect_region() } #ifndef NO_Z80 const memmap_chunk z80_map[] = { - { 0x0000, 0x4000, 0x1FFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, z80_ram, NULL, NULL, NULL, NULL }, - { 0x8000, 0x10000, 0x7FFF, 1, MMAP_READ | MMAP_PTR_IDX | MMAP_FUNC_NULL | MMAP_BYTESWAP, NULL, NULL, NULL, z80_read_bank, z80_write_bank}, - { 0x4000, 0x6000, 0x0003, 0, 0, NULL, NULL, NULL, z80_read_ym, z80_write_ym}, - { 0x6000, 0x6100, 0xFFFF, 0, 0, NULL, NULL, NULL, NULL, z80_write_bank_reg}, - { 0x7F00, 0x8000, 0x00FF, 0, 0, NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write} + { 0x0000, 0x4000, 0x1FFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, z80_ram, NULL, NULL, NULL, NULL }, + { 0x8000, 0x10000, 0x7FFF, 0, 0, NULL, NULL, NULL, z80_read_bank, z80_write_bank}, + { 0x4000, 0x6000, 0x0003, 0, 0, NULL, NULL, NULL, z80_read_ym, z80_write_ym}, + { 0x6000, 0x6100, 0xFFFF, 0, 0, NULL, NULL, NULL, NULL, z80_write_bank_reg}, + { 0x7F00, 0x8000, 0x00FF, 0, 0, NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write} }; #endif -- cgit v1.2.3 From 0611fe0f3eec53148200fc8575bfab7d09a9e6db Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Thu, 1 Jan 2015 22:52:18 -0800 Subject: Adjust 68K sync cycle when mclk_target gets adjusted --- blastem.c | 1 + 1 file changed, 1 insertion(+) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 46dbdc9..8c375ad 100644 --- a/blastem.c +++ b/blastem.c @@ -307,6 +307,7 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) vdp_run_context(v_context, mclks); } mclk_target = vdp_cycles_to_frame_end(v_context); + context->sync_cycle = mclk_target/MCLKS_PER_68K; } else { //printf("running VDP for %d cycles\n", mclks - v_context->cycles); vdp_run_context(v_context, mclks); -- cgit v1.2.3 From 8ac1e753e1af481b2090a4c1b7395853f30b5e8f Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Sat, 3 Jan 2015 16:08:23 -0800 Subject: All cycle counters are now based off the master clock. This seems to have messed up Z80 interrupt timing (music in Sonic 2 is too slow for instance), but things are generally working --- blastem.c | 121 +++++++++++++++++++++++++++++--------------------------------- 1 file changed, 57 insertions(+), 64 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 8c375ad..bf82f3e 100644 --- a/blastem.c +++ b/blastem.c @@ -125,26 +125,18 @@ uint16_t read_dma_value(uint32_t address) return 0; } -//TODO: Make these dependent on the video mode -//#define VINT_CYCLE ((MCLKS_LINE * 225 + (148 + 40) * 4)/MCLKS_PER_68K) -#define ZVINT_CYCLE ((MCLKS_LINE * 225 + (148 + 40) * 4)/MCLKS_PER_Z80) -//#define VINT_CYCLE ((MCLKS_LINE * 226)/MCLKS_PER_68K) -//#define ZVINT_CYCLE ((MCLKS_LINE * 226)/MCLKS_PER_Z80) - void adjust_int_cycle(m68k_context * context, vdp_context * v_context) { context->int_cycle = CYCLE_NEVER; if ((context->status & 0x7) < 6) { uint32_t next_vint = vdp_next_vint(v_context); if (next_vint != CYCLE_NEVER) { - next_vint /= MCLKS_PER_68K; context->int_cycle = next_vint; context->int_num = 6; } if ((context->status & 0x7) < 4) { uint32_t next_hint = vdp_next_hint(v_context); if (next_hint != CYCLE_NEVER) { - next_hint /= MCLKS_PER_68K; if (next_hint < context->int_cycle) { context->int_cycle = next_hint; context->int_num = 4; @@ -185,7 +177,7 @@ void sync_z80(z80_context * z_context, uint32_t mclks) #ifndef NO_Z80 if (z80_enabled && !reset && !busreq) { genesis_context * gen = z_context->system; - z_context->sync_cycle = mclks / MCLKS_PER_Z80; + z_context->sync_cycle = mclks; if (z_context->current_cycle < z_context->sync_cycle) { if (need_reset) { z80_reset(z_context); @@ -194,7 +186,7 @@ void sync_z80(z80_context * z_context, uint32_t mclks) while (z_context->current_cycle < z_context->sync_cycle) { if (z_context->int_pulse_end < z_context->current_cycle || z_context->int_pulse_end == CYCLE_NEVER) { - z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp) / MCLKS_PER_Z80; + z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp); z_context->int_pulse_end = z_context->int_pulse_start + Z80_VINT_DURATION; } if (z_context->iff1) { @@ -211,7 +203,7 @@ void sync_z80(z80_context * z_context, uint32_t mclks) } else #endif { - z_context->current_cycle = mclks / MCLKS_PER_Z80; + z_context->current_cycle = mclks; } } @@ -238,14 +230,14 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) genesis_context * gen = context->system; vdp_context * v_context = gen->vdp; z80_context * z_context = gen->z80; - uint32_t mclks = context->current_cycle * MCLKS_PER_68K; + uint32_t mclks = context->current_cycle; sync_z80(z_context, mclks); if (mclks >= mclk_target) { sync_sound(gen, mclks); gen->ym->current_cycle -= mclk_target; gen->psg->cycles -= mclk_target; if (gen->ym->write_cycle != CYCLE_NEVER) { - gen->ym->write_cycle = gen->ym->write_cycle >= mclk_target/MCLKS_PER_68K ? gen->ym->write_cycle - mclk_target/MCLKS_PER_68K : 0; + gen->ym->write_cycle = gen->ym->write_cycle >= mclk_target ? gen->ym->write_cycle - mclk_target : 0; } //printf("reached frame end | 68K Cycles: %d, MCLK Cycles: %d\n", context->current_cycle, mclks); vdp_run_context(v_context, mclk_target); @@ -261,35 +253,35 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) frame++; mclks -= mclk_target; vdp_adjust_cycles(v_context, mclk_target); - io_adjust_cycles(gen->ports, context->current_cycle, mclk_target/MCLKS_PER_68K); - io_adjust_cycles(gen->ports+1, context->current_cycle, mclk_target/MCLKS_PER_68K); - io_adjust_cycles(gen->ports+2, context->current_cycle, mclk_target/MCLKS_PER_68K); + io_adjust_cycles(gen->ports, context->current_cycle, mclk_target); + io_adjust_cycles(gen->ports+1, context->current_cycle, mclk_target); + io_adjust_cycles(gen->ports+2, context->current_cycle, mclk_target); if (busack_cycle != CYCLE_NEVER) { - if (busack_cycle > mclk_target/MCLKS_PER_68K) { - busack_cycle -= mclk_target/MCLKS_PER_68K; + if (busack_cycle > mclk_target) { + busack_cycle -= mclk_target; } else { busack_cycle = CYCLE_NEVER; busack = new_busack; } } - context->current_cycle -= mclk_target/MCLKS_PER_68K; - if (z_context->current_cycle >= mclk_target/MCLKS_PER_Z80) { - z_context->current_cycle -= mclk_target/MCLKS_PER_Z80; + context->current_cycle -= mclk_target; + if (z_context->current_cycle >= mclk_target) { + z_context->current_cycle -= mclk_target; } else { z_context->current_cycle = 0; } if (z_context->int_cycle != CYCLE_NEVER) { - if (z_context->int_cycle >= mclk_target/MCLKS_PER_Z80) { - z_context->int_cycle -= mclk_target/MCLKS_PER_Z80; + if (z_context->int_cycle >= mclk_target) { + z_context->int_cycle -= mclk_target; } else { z_context->int_cycle = 0; } } if (z_context->int_pulse_start != CYCLE_NEVER) { - if (z_context->int_pulse_end >= mclk_target/MCLKS_PER_Z80) { - z_context->int_pulse_end -= mclk_target/MCLKS_PER_Z80; - if (z_context->int_pulse_start >= mclk_target/MCLKS_PER_Z80) { - z_context->int_pulse_start -= mclk_target/MCLKS_PER_Z80; + if (z_context->int_pulse_end >= mclk_target) { + z_context->int_pulse_end -= mclk_target; + if (z_context->int_pulse_start >= mclk_target) { + z_context->int_pulse_start -= mclk_target; } else { z_context->int_pulse_start = 0; } @@ -298,8 +290,8 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) z_context->int_pulse_start = CYCLE_NEVER; z_context->int_pulse_end = CYCLE_NEVER; } - if (z_context->int_enable_cycle >= mclk_target/MCLKS_PER_Z80) { - z_context->int_enable_cycle -= mclk_target/MCLKS_PER_Z80; + if (z_context->int_enable_cycle >= mclk_target) { + z_context->int_enable_cycle -= mclk_target; } else { z_context->int_enable_cycle = 0; } @@ -307,7 +299,7 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) vdp_run_context(v_context, mclks); } mclk_target = vdp_cycles_to_frame_end(v_context); - context->sync_cycle = mclk_target/MCLKS_PER_68K; + context->sync_cycle = mclk_target; } else { //printf("running VDP for %d cycles\n", mclks - v_context->cycles); vdp_run_context(v_context, mclks); @@ -325,9 +317,10 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) } if (save_state) { save_state = 0; + //advance Z80 core to the start of an instruction while (!z_context->pc) { - sync_z80(z_context, z_context->current_cycle * MCLKS_PER_Z80 + MCLKS_PER_Z80); + sync_z80(z_context, z_context->current_cycle + MCLKS_PER_Z80); } save_gst(gen, "savestate.gst", address); } @@ -355,14 +348,14 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ while(v_context->flags & FLAG_DMA_RUN) { vdp_run_dma_done(v_context, mclk_target); if (v_context->cycles >= mclk_target) { - context->current_cycle = v_context->cycles / MCLKS_PER_68K; - if (context->current_cycle * MCLKS_PER_68K < mclk_target) { - ++context->current_cycle; + context->current_cycle = v_context->cycles; + if (context->current_cycle < mclk_target) { + context->current_cycle += MCLKS_PER_68K; } sync_components(context, 0); } } - //context->current_cycle = v_context->cycles / MCLKS_PER_68K; + //context->current_cycle = v_context->cycles; } } else if(vdp_port < 8) { gen->bus_busy = 1; @@ -372,9 +365,9 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ while(v_context->flags & FLAG_DMA_RUN) { vdp_run_dma_done(v_context, mclk_target); if (v_context->cycles >= mclk_target) { - context->current_cycle = v_context->cycles / MCLKS_PER_68K; - if (context->current_cycle * MCLKS_PER_68K < mclk_target) { - ++context->current_cycle; + context->current_cycle = v_context->cycles; + if (context->current_cycle < mclk_target) { + context->current_cycle += MCLKS_PER_68K; } sync_components(context, 0); } @@ -393,11 +386,11 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ exit(1); } if (v_context->cycles != before_cycle) { - //printf("68K paused for %d (%d) cycles at cycle %d (%d) for write\n", v_context->cycles / MCLKS_PER_68K - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle); - context->current_cycle = v_context->cycles / MCLKS_PER_68K; + //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); + context->current_cycle = v_context->cycles; } } else if (vdp_port < 0x18) { - sync_sound(gen, context->current_cycle * MCLKS_PER_68K); + sync_sound(gen, context->current_cycle); psg_write(gen->psg, value); } else { //TODO: Implement undocumented test register(s) @@ -427,7 +420,7 @@ void * z80_vdp_port_write(uint32_t vdp_port, void * vcontext, uint8_t value) } if (vdp_port < 0x10) { //These probably won't currently interact well with the 68K accessing the VDP - vdp_run_context(gen->vdp, context->current_cycle * MCLKS_PER_Z80); + vdp_run_context(gen->vdp, context->current_cycle); if (vdp_port < 4) { vdp_data_port_write(gen->vdp, value << 8 | value); } else if (vdp_port < 8) { @@ -437,7 +430,7 @@ void * z80_vdp_port_write(uint32_t vdp_port, void * vcontext, uint8_t value) exit(1); } } else if (vdp_port < 0x18) { - sync_sound(gen, context->current_cycle * MCLKS_PER_Z80); + sync_sound(gen, context->current_cycle); psg_write(gen->psg, value); } else { vdp_test_port_write(gen->vdp, value); @@ -472,8 +465,8 @@ uint16_t vdp_port_read(uint32_t vdp_port, m68k_context * context) value = vdp_test_port_read(v_context); } if (v_context->cycles != before_cycle) { - //printf("68K paused for %d (%d) cycles at cycle %d (%d) for read\n", v_context->cycles / MCLKS_PER_68K - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle); - context->current_cycle = v_context->cycles / MCLKS_PER_68K; + //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); + context->current_cycle = v_context->cycles; } return value; } @@ -500,7 +493,7 @@ uint8_t z80_vdp_port_read(uint32_t vdp_port, void * vcontext) uint16_t ret; if (vdp_port < 0x10) { //These probably won't currently interact well with the 68K accessing the VDP - vdp_run_context(gen->vdp, context->current_cycle * MCLKS_PER_Z80); + vdp_run_context(gen->vdp, context->current_cycle); if (vdp_port < 4) { ret = vdp_data_port_read(gen->vdp); } else if (vdp_port < 8) { @@ -539,7 +532,7 @@ m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value z80_handle_code_write(location & 0x1FFF, gen->z80); #endif } else if (location < 0x6000) { - sync_sound(gen, context->current_cycle * MCLKS_PER_68K); + sync_sound(gen, context->current_cycle); if (location & 1) { ym_data_write(gen->ym, value); } else if(location & 2) { @@ -593,13 +586,13 @@ m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value dputs("bus requesting Z80"); if(!reset && !busreq) { - sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K + Z80_ACK_DELAY*MCLKS_PER_Z80); - busack_cycle = (gen->z80->current_cycle * MCLKS_PER_Z80) / MCLKS_PER_68K;//context->current_cycle + Z80_ACK_DELAY; + sync_z80(gen->z80, context->current_cycle + Z80_ACK_DELAY*MCLKS_PER_Z80); + busack_cycle = gen->z80->current_cycle;//context->current_cycle + Z80_ACK_DELAY; new_busack = Z80_REQ_ACK; } busreq = 1; } else { - sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K); + sync_z80(gen->z80, context->current_cycle); if (busreq) { dputs("releasing z80 bus"); #ifdef DO_DEBUG_PRINT @@ -609,7 +602,7 @@ m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value fwrite(z80_ram, 1, sizeof(z80_ram), f); fclose(f); #endif - busack_cycle = ((gen->z80->current_cycle + Z80_BUSY_DELAY) * MCLKS_PER_Z80) / MCLKS_PER_68K; + busack_cycle = gen->z80->current_cycle + Z80_BUSY_DELAY; new_busack = Z80_REQ_BUSY; busreq = 0; } @@ -618,17 +611,17 @@ m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value } } else if (location == 0x1200) { - sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K); + sync_z80(gen->z80, context->current_cycle); if (value & 1) { if (reset && busreq) { new_busack = 0; - busack_cycle = ((gen->z80->current_cycle + Z80_ACK_DELAY) * MCLKS_PER_Z80) / MCLKS_PER_68K;//context->current_cycle + Z80_ACK_DELAY; + busack_cycle = gen->z80->current_cycle + Z80_ACK_DELAY;//context->current_cycle + Z80_ACK_DELAY; } //TODO: Deal with the scenario in which reset is not asserted long enough if (reset) { need_reset = 1; //TODO: Add necessary delay between release of reset and start of execution - gen->z80->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80 + 16; + gen->z80->current_cycle = context->current_cycle + 16 * MCLKS_PER_Z80; } reset = 0; } else { @@ -669,7 +662,7 @@ uint8_t io_read(uint32_t location, m68k_context * context) if (location < 0x4000) { value = z80_ram[location & 0x1FFF]; } else if (location < 0x6000) { - sync_sound(gen, context->current_cycle * MCLKS_PER_68K); + sync_sound(gen, context->current_cycle); value = ym_read_status(gen->ym); } else { value = 0xFF; @@ -741,7 +734,7 @@ void * z80_write_ym(uint32_t location, void * vcontext, uint8_t value) { z80_context * context = vcontext; genesis_context * gen = context->system; - sync_sound(gen, context->current_cycle * MCLKS_PER_Z80); + sync_sound(gen, context->current_cycle); if (location & 1) { ym_data_write(gen->ym, value); } else if (location & 2) { @@ -756,7 +749,7 @@ uint8_t z80_read_ym(uint32_t location, void * vcontext) { z80_context * context = vcontext; genesis_context * gen = context->system; - sync_sound(gen, context->current_cycle * MCLKS_PER_Z80); + sync_sound(gen, context->current_cycle); return ym_read_status(gen->ym); } @@ -765,7 +758,7 @@ uint8_t z80_read_bank(uint32_t location, void * vcontext) z80_context * context = vcontext; //typical delay from bus arbitration context->current_cycle += 3; - + location &= 0x7FFF; //TODO: add cycle for an access right after a previous one //TODO: block Z80 if VDP has the bus or the 68K is blocked on a VDP access @@ -804,7 +797,7 @@ void *z80_write_bank(uint32_t location, void * vcontext, uint8_t value) void *z80_write_bank_reg(uint32_t location, void * vcontext, uint8_t value) { z80_context * context = vcontext; - + context->bank_reg = (context->bank_reg >> 1 | value << 8) & 0x1FF; if (context->bank_reg < 0x80) { genesis_context *gen = context->system; @@ -812,7 +805,7 @@ void *z80_write_bank_reg(uint32_t location, void * vcontext, uint8_t value) } else { context->mem_pointers[1] = NULL; } - + return context; } @@ -1084,7 +1077,7 @@ void init_run_cpu(genesis_context * gen, FILE * address_log, char * statefile, u } atexit(save_sram); } - init_m68k_opts(&opts, memmap, num_chunks); + init_m68k_opts(&opts, memmap, num_chunks, MCLKS_PER_68K); opts.address_log = address_log; init_68k_context(&context, opts.gen.native_code_map, &opts); @@ -1092,7 +1085,7 @@ void init_run_cpu(genesis_context * gen, FILE * address_log, char * statefile, u context.system = gen; //cartridge ROM context.mem_pointers[0] = cart; - context.target_cycle = context.sync_cycle = mclk_target/MCLKS_PER_68K; + context.target_cycle = context.sync_cycle = mclk_target; //work RAM context.mem_pointers[1] = ram; //save RAM/map @@ -1369,13 +1362,13 @@ int main(int argc, char ** argv) z80_context z_context; #ifndef NO_Z80 z80_options z_opts; - init_z80_opts(&z_opts, z80_map, 5); + init_z80_opts(&z_opts, z80_map, 5, MCLKS_PER_Z80); init_z80_context(&z_context, &z_opts); #endif z_context.system = &gen; z_context.mem_pointers[0] = z80_ram; - z_context.sync_cycle = z_context.target_cycle = mclk_target/MCLKS_PER_Z80; + z_context.sync_cycle = z_context.target_cycle = mclk_target; z_context.int_cycle = CYCLE_NEVER; z_context.mem_pointers[1] = z_context.mem_pointers[2] = (uint8_t *)cart; -- cgit v1.2.3 From e6216d5d0a9f8cdb700124558d38cd47e63fbdda Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Sat, 3 Jan 2015 18:23:04 -0800 Subject: Made the Z80 core more contained by refactoring some code in blastem.c into z80_to_x86.c --- blastem.c | 155 ++++++++++++++------------------------------------------------ 1 file changed, 34 insertions(+), 121 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index bf82f3e..1ee89aa 100644 --- a/blastem.c +++ b/blastem.c @@ -155,12 +155,6 @@ void adjust_int_cycle(m68k_context * context, vdp_context * v_context) int break_on_sync = 0; int save_state = 0; -uint8_t reset = 1; -uint8_t need_reset = 0; -uint8_t busreq = 0; -uint8_t busack = 0; -uint32_t busack_cycle = CYCLE_NEVER; -uint8_t new_busack = 0; //#define DO_DEBUG_PRINT #ifdef DO_DEBUG_PRINT #define dprintf printf @@ -172,34 +166,18 @@ uint8_t new_busack = 0; #define Z80_VINT_DURATION 128 +void z80_next_int_pulse(z80_context * z_context) +{ + genesis_context * gen = z_context->system; + z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp); + z_context->int_pulse_end = z_context->int_pulse_start + Z80_VINT_DURATION; +} + void sync_z80(z80_context * z_context, uint32_t mclks) { #ifndef NO_Z80 - if (z80_enabled && !reset && !busreq) { - genesis_context * gen = z_context->system; - z_context->sync_cycle = mclks; - if (z_context->current_cycle < z_context->sync_cycle) { - if (need_reset) { - z80_reset(z_context); - need_reset = 0; - } - - while (z_context->current_cycle < z_context->sync_cycle) { - if (z_context->int_pulse_end < z_context->current_cycle || z_context->int_pulse_end == CYCLE_NEVER) { - z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp); - z_context->int_pulse_end = z_context->int_pulse_start + Z80_VINT_DURATION; - } - if (z_context->iff1) { - z_context->int_cycle = z_context->int_pulse_start < z_context->int_enable_cycle ? z_context->int_enable_cycle : z_context->int_pulse_start; - } else { - z_context->int_cycle = CYCLE_NEVER; - } - z_context->target_cycle = z_context->sync_cycle < z_context->int_cycle ? z_context->sync_cycle : z_context->int_cycle; - dprintf("Running Z80 from cycle %d to cycle %d. Int cycle: %d\n", z_context->current_cycle, z_context->sync_cycle, z_context->int_cycle); - z_context->run(z_context); - dprintf("Z80 ran to cycle %d\n", z_context->current_cycle); - } - } + if (z80_enabled) { + z80_run(z_context, mclks); } else #endif { @@ -256,45 +234,8 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) io_adjust_cycles(gen->ports, context->current_cycle, mclk_target); io_adjust_cycles(gen->ports+1, context->current_cycle, mclk_target); io_adjust_cycles(gen->ports+2, context->current_cycle, mclk_target); - if (busack_cycle != CYCLE_NEVER) { - if (busack_cycle > mclk_target) { - busack_cycle -= mclk_target; - } else { - busack_cycle = CYCLE_NEVER; - busack = new_busack; - } - } context->current_cycle -= mclk_target; - if (z_context->current_cycle >= mclk_target) { - z_context->current_cycle -= mclk_target; - } else { - z_context->current_cycle = 0; - } - if (z_context->int_cycle != CYCLE_NEVER) { - if (z_context->int_cycle >= mclk_target) { - z_context->int_cycle -= mclk_target; - } else { - z_context->int_cycle = 0; - } - } - if (z_context->int_pulse_start != CYCLE_NEVER) { - if (z_context->int_pulse_end >= mclk_target) { - z_context->int_pulse_end -= mclk_target; - if (z_context->int_pulse_start >= mclk_target) { - z_context->int_pulse_start -= mclk_target; - } else { - z_context->int_pulse_start = 0; - } - } - } else { - z_context->int_pulse_start = CYCLE_NEVER; - z_context->int_pulse_end = CYCLE_NEVER; - } - if (z_context->int_enable_cycle >= mclk_target) { - z_context->int_enable_cycle -= mclk_target; - } else { - z_context->int_enable_cycle = 0; - } + z80_adjust_cycles(z_context, mclk_target); if (mclks) { vdp_run_context(v_context, mclks); } @@ -458,7 +399,7 @@ uint16_t vdp_port_read(uint32_t vdp_port, m68k_context * context) value = vdp_hv_counter_read(v_context); //printf("HV Counter: %X at cycle %d\n", value, v_context->cycles); } - } else if (vdp_port < 0x18){ + } else if (vdp_port < 0x18) { printf("Illegal read from PSG port %X\n", vdp_port); exit(1); } else { @@ -520,11 +461,7 @@ m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value { genesis_context * gen = context->system; if (location < 0x10000) { - if (busack_cycle <= context->current_cycle) { - busack = new_busack; - busack_cycle = CYCLE_NEVER; - } - if (!(busack || reset)) { + if (!z80_enabled || z80_get_busack(gen->z80, context->current_cycle)) { location &= 0x7FFF; if (location < 0x4000) { z80_ram[location & 0x1FFF] = value; @@ -578,54 +515,40 @@ m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value } } else { if (location == 0x1100) { - if (busack_cycle <= context->current_cycle) { - busack = new_busack; - busack_cycle = CYCLE_NEVER; - } if (value & 1) { dputs("bus requesting Z80"); - - if(!reset && !busreq) { - sync_z80(gen->z80, context->current_cycle + Z80_ACK_DELAY*MCLKS_PER_Z80); - busack_cycle = gen->z80->current_cycle;//context->current_cycle + Z80_ACK_DELAY; - new_busack = Z80_REQ_ACK; + if (z80_enabled) { + z80_assert_busreq(gen->z80, context->current_cycle); } - busreq = 1; } else { - sync_z80(gen->z80, context->current_cycle); - if (busreq) { + if (gen->z80->busreq) { dputs("releasing z80 bus"); - #ifdef DO_DEBUG_PRINT +#ifdef DO_DEBUG_PRINT char fname[20]; sprintf(fname, "zram-%d", zram_counter++); FILE * f = fopen(fname, "wb"); fwrite(z80_ram, 1, sizeof(z80_ram), f); fclose(f); - #endif - busack_cycle = gen->z80->current_cycle + Z80_BUSY_DELAY; - new_busack = Z80_REQ_BUSY; - busreq = 0; +#endif + } + if (z80_enabled) { + z80_clear_busreq(gen->z80, context->current_cycle); } - //busack_cycle = CYCLE_NEVER; - //busack = Z80_REQ_BUSY; - } } else if (location == 0x1200) { sync_z80(gen->z80, context->current_cycle); if (value & 1) { - if (reset && busreq) { - new_busack = 0; - busack_cycle = gen->z80->current_cycle + Z80_ACK_DELAY;//context->current_cycle + Z80_ACK_DELAY; - } - //TODO: Deal with the scenario in which reset is not asserted long enough - if (reset) { - need_reset = 1; - //TODO: Add necessary delay between release of reset and start of execution - gen->z80->current_cycle = context->current_cycle + 16 * MCLKS_PER_Z80; + if (z80_enabled) { + z80_clear_reset(gen->z80, context->current_cycle); + } else { + gen->z80->reset = 0; } - reset = 0; } else { - reset = 1; + if (z80_enabled) { + z80_assert_reset(gen->z80, context->current_cycle); + } else { + gen->z80->reset = 1; + } } } } @@ -653,11 +576,7 @@ uint8_t io_read(uint32_t location, m68k_context * context) uint8_t value; genesis_context *gen = context->system; if (location < 0x10000) { - if (busack_cycle <= context->current_cycle) { - busack = new_busack; - busack_cycle = CYCLE_NEVER; - } - if (!(busack==Z80_REQ_BUSY || reset)) { + if (!z80_enabled || z80_get_busack(gen->z80, context->current_cycle)) { location &= 0x7FFF; if (location < 0x4000) { value = z80_ram[location & 0x1FFF]; @@ -702,14 +621,10 @@ uint8_t io_read(uint32_t location, m68k_context * context) } } else { if (location == 0x1100) { - if (busack_cycle <= context->current_cycle) { - busack = new_busack; - busack_cycle = CYCLE_NEVER; - } - value = Z80_RES_BUSACK || busack; - dprintf("Byte read of BUSREQ returned %d @ %d (reset: %d, busack: %d, busack_cycle %d)\n", value, context->current_cycle, reset, busack, busack_cycle); + value = z80_enabled ? !z80_get_busack(gen->z80, context->current_cycle) : 0; + dprintf("Byte read of BUSREQ returned %d @ %d (reset: %d)\n", value, context->current_cycle, gen->z80->reset); } else if (location == 0x1200) { - value = !reset; + value = !gen->z80->reset; } else { value = 0xFF; printf("Byte read of unknown IO location: %X\n", location); @@ -1105,9 +1020,6 @@ void init_run_cpu(genesis_context * gen, FILE * address_log, char * statefile, u insert_breakpoint(&context, pc, debugger); } adjust_int_cycle(gen->m68k, gen->vdp); -#ifndef NO_Z80 - gen->z80->native_pc = z80_get_native_address_trans(gen->z80, gen->z80->pc); -#endif start_68k_context(&context, pc); } else { if (debugger) { @@ -1364,6 +1276,7 @@ int main(int argc, char ** argv) z80_options z_opts; init_z80_opts(&z_opts, z80_map, 5, MCLKS_PER_Z80); init_z80_context(&z_context, &z_opts); + z80_assert_reset(&z_context, 0); #endif z_context.system = &gen; -- cgit v1.2.3 From 102d10b6f2892826ba5c7efd901052e543886816 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Sat, 3 Jan 2015 18:27:29 -0800 Subject: Removed some obsolete defines --- blastem.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 1ee89aa..3bc2752 100644 --- a/blastem.c +++ b/blastem.c @@ -451,11 +451,6 @@ uint8_t z80_vdp_port_read(uint32_t vdp_port, void * vcontext) } uint32_t zram_counter = 0; -#define Z80_ACK_DELAY 3 -#define Z80_BUSY_DELAY 1//TODO: Find the actual value for this -#define Z80_REQ_BUSY 1 -#define Z80_REQ_ACK 0 -#define Z80_RES_BUSACK reset m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value) { @@ -1281,8 +1276,6 @@ int main(int argc, char ** argv) z_context.system = &gen; z_context.mem_pointers[0] = z80_ram; - z_context.sync_cycle = z_context.target_cycle = mclk_target; - z_context.int_cycle = CYCLE_NEVER; z_context.mem_pointers[1] = z_context.mem_pointers[2] = (uint8_t *)cart; gen.z80 = &z_context; -- cgit v1.2.3 From d57873760390a393e784d1339b1d64564fe83234 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Sat, 3 Jan 2015 18:49:07 -0800 Subject: Restore Z80 interrupt pulse duration and make a small improvement to debug print output --- blastem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 3bc2752..b06ccc3 100644 --- a/blastem.c +++ b/blastem.c @@ -170,7 +170,7 @@ void z80_next_int_pulse(z80_context * z_context) { genesis_context * gen = z_context->system; z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp); - z_context->int_pulse_end = z_context->int_pulse_start + Z80_VINT_DURATION; + z_context->int_pulse_end = z_context->int_pulse_start + Z80_VINT_DURATION * MCLKS_PER_Z80; } void sync_z80(z80_context * z_context, uint32_t mclks) -- cgit v1.2.3 From ba230802d2dc53066d94a70cc27c0ca6cf1502b6 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Sat, 3 Jan 2015 20:13:51 -0800 Subject: Fix bank area access delay for master clock change --- blastem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index b06ccc3..3b02567 100644 --- a/blastem.c +++ b/blastem.c @@ -667,7 +667,7 @@ uint8_t z80_read_bank(uint32_t location, void * vcontext) { z80_context * context = vcontext; //typical delay from bus arbitration - context->current_cycle += 3; + context->current_cycle += 3 * MCLKS_PER_Z80; location &= 0x7FFF; //TODO: add cycle for an access right after a previous one @@ -688,7 +688,7 @@ void *z80_write_bank(uint32_t location, void * vcontext, uint8_t value) { z80_context * context = vcontext; //typical delay from bus arbitration - context->current_cycle += 3; + context->current_cycle += 3 * MCLKS_PER_Z80; location &= 0x7FFF; //TODO: add cycle for an access right after a previous one //TODO: block Z80 if VDP has the bus or the 68K is blocked on a VDP access -- cgit v1.2.3 From 64168b8e1d6d46e3569d190ea79aa372b5c86fc2 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Sat, 3 Jan 2015 20:20:15 -0800 Subject: Restore emulation of Z80 being locked out of the 68K bus during DMA and the like --- blastem.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 3b02567..2c83075 100644 --- a/blastem.c +++ b/blastem.c @@ -666,12 +666,15 @@ uint8_t z80_read_ym(uint32_t location, void * vcontext) uint8_t z80_read_bank(uint32_t location, void * vcontext) { z80_context * context = vcontext; + genesis_context *gen = context->system; + if (gen->bus_busy) { + context->current_cycle = context->sync_cycle; + } //typical delay from bus arbitration context->current_cycle += 3 * MCLKS_PER_Z80; + //TODO: add cycle for an access right after a previous one location &= 0x7FFF; - //TODO: add cycle for an access right after a previous one - //TODO: block Z80 if VDP has the bus or the 68K is blocked on a VDP access if (context->mem_pointers[1]) { return context->mem_pointers[1][location ^ 1]; } @@ -687,11 +690,15 @@ uint8_t z80_read_bank(uint32_t location, void * vcontext) void *z80_write_bank(uint32_t location, void * vcontext, uint8_t value) { z80_context * context = vcontext; + genesis_context *gen = context->system; + if (gen->bus_busy) { + context->current_cycle = context->sync_cycle; + } //typical delay from bus arbitration context->current_cycle += 3 * MCLKS_PER_Z80; - location &= 0x7FFF; //TODO: add cycle for an access right after a previous one - //TODO: block Z80 if VDP has the bus or the 68K is blocked on a VDP access + + location &= 0x7FFF; uint32_t address = context->bank_reg << 15 | location; if (address >= 0xE00000) { address &= 0xFFFF; -- cgit v1.2.3 From bb5e4d5126fb6c6b64ef84615ec9e5e15848575d Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Sat, 3 Jan 2015 21:54:41 -0800 Subject: Fake busack when Z80 is disabled --- blastem.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 2c83075..bf8a333 100644 --- a/blastem.c +++ b/blastem.c @@ -514,6 +514,8 @@ m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value dputs("bus requesting Z80"); if (z80_enabled) { z80_assert_busreq(gen->z80, context->current_cycle); + } else { + gen->z80->busack = 1; } } else { if (gen->z80->busreq) { @@ -528,6 +530,8 @@ m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value } if (z80_enabled) { z80_clear_busreq(gen->z80, context->current_cycle); + } else { + gen->z80->busack = 0; } } } else if (location == 0x1200) { @@ -616,7 +620,7 @@ uint8_t io_read(uint32_t location, m68k_context * context) } } else { if (location == 0x1100) { - value = z80_enabled ? !z80_get_busack(gen->z80, context->current_cycle) : 0; + value = z80_enabled ? !z80_get_busack(gen->z80, context->current_cycle) : !gen->z80->busack; dprintf("Byte read of BUSREQ returned %d @ %d (reset: %d)\n", value, context->current_cycle, gen->z80->reset); } else if (location == 0x1200) { value = !gen->z80->reset; -- cgit v1.2.3 From 52fb42428540e149d7ae6b53bdb52603b8e1947f Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Sun, 4 Jan 2015 12:25:33 -0800 Subject: Removed some code that tried to deal with the 68K not using master clocks that is no longer necessary --- blastem.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index bf8a333..21e59ab 100644 --- a/blastem.c +++ b/blastem.c @@ -217,8 +217,8 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) if (gen->ym->write_cycle != CYCLE_NEVER) { gen->ym->write_cycle = gen->ym->write_cycle >= mclk_target ? gen->ym->write_cycle - mclk_target : 0; } - //printf("reached frame end | 68K Cycles: %d, MCLK Cycles: %d\n", context->current_cycle, mclks); vdp_run_context(v_context, mclk_target); + //printf("reached frame end | MCLK Cycles: %d, Target: %d, VDP cycles: %d\n", mclks, mclk_target, v_context->cycles); if (!headless) { break_on_sync |= wait_render_frame(v_context, frame_limit); @@ -290,9 +290,6 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ vdp_run_dma_done(v_context, mclk_target); if (v_context->cycles >= mclk_target) { context->current_cycle = v_context->cycles; - if (context->current_cycle < mclk_target) { - context->current_cycle += MCLKS_PER_68K; - } sync_components(context, 0); } } @@ -307,9 +304,6 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ vdp_run_dma_done(v_context, mclk_target); if (v_context->cycles >= mclk_target) { context->current_cycle = v_context->cycles; - if (context->current_cycle < mclk_target) { - context->current_cycle += MCLKS_PER_68K; - } sync_components(context, 0); } } -- cgit v1.2.3 From d8bb1db03b5f3c3beb86dce633f89872d05318a5 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Sun, 4 Jan 2015 23:05:37 -0800 Subject: Some small synchronization improvements that do not seem to fix anything --- blastem.c | 76 +++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 40 insertions(+), 36 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 21e59ab..bbb9c51 100644 --- a/blastem.c +++ b/blastem.c @@ -210,41 +210,45 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) z80_context * z_context = gen->z80; uint32_t mclks = context->current_cycle; sync_z80(z_context, mclks); + sync_sound(gen, mclks); if (mclks >= mclk_target) { - sync_sound(gen, mclks); - gen->ym->current_cycle -= mclk_target; - gen->psg->cycles -= mclk_target; - if (gen->ym->write_cycle != CYCLE_NEVER) { - gen->ym->write_cycle = gen->ym->write_cycle >= mclk_target ? gen->ym->write_cycle - mclk_target : 0; - } vdp_run_context(v_context, mclk_target); - //printf("reached frame end | MCLK Cycles: %d, Target: %d, VDP cycles: %d\n", mclks, mclk_target, v_context->cycles); - - if (!headless) { - break_on_sync |= wait_render_frame(v_context, frame_limit); - } else if(exit_after){ - --exit_after; - if (!exit_after) { - exit(0); + if (vdp_is_frame_over(v_context)) { + //printf("reached frame end | MCLK Cycles: %d, Target: %d, VDP cycles: %d\n", mclks, mclk_target, v_context->cycles); + + if (!headless) { + break_on_sync |= wait_render_frame(v_context, frame_limit); + } else if(exit_after){ + --exit_after; + if (!exit_after) { + exit(0); + } } - } - frame++; - mclks -= mclk_target; - vdp_adjust_cycles(v_context, mclk_target); - io_adjust_cycles(gen->ports, context->current_cycle, mclk_target); - io_adjust_cycles(gen->ports+1, context->current_cycle, mclk_target); - io_adjust_cycles(gen->ports+2, context->current_cycle, mclk_target); - context->current_cycle -= mclk_target; - z80_adjust_cycles(z_context, mclk_target); - if (mclks) { + frame++; + mclks -= mclk_target; + vdp_adjust_cycles(v_context, mclk_target); + io_adjust_cycles(gen->ports, context->current_cycle, mclk_target); + io_adjust_cycles(gen->ports+1, context->current_cycle, mclk_target); + io_adjust_cycles(gen->ports+2, context->current_cycle, mclk_target); + context->current_cycle -= mclk_target; + z80_adjust_cycles(z_context, mclk_target); + gen->ym->current_cycle -= mclk_target; + gen->psg->cycles -= mclk_target; + if (gen->ym->write_cycle != CYCLE_NEVER) { + gen->ym->write_cycle = gen->ym->write_cycle >= mclk_target ? gen->ym->write_cycle - mclk_target : 0; + } + if (mclks) { + vdp_run_context(v_context, mclks); + } + mclk_target = vdp_cycles_to_frame_end(v_context); + context->sync_cycle = mclk_target; + } else { vdp_run_context(v_context, mclks); + mclk_target = vdp_cycles_to_frame_end(v_context); } - mclk_target = vdp_cycles_to_frame_end(v_context); - context->sync_cycle = mclk_target; } else { //printf("running VDP for %d cycles\n", mclks - v_context->cycles); vdp_run_context(v_context, mclks); - sync_sound(gen, mclks); } if (context->int_ack) { vdp_int_ack(v_context, context->int_ack); @@ -284,7 +288,6 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ int blocked; uint32_t before_cycle = v_context->cycles; if (vdp_port < 4) { - gen->bus_busy = 1; while (vdp_data_port_write(v_context, value) < 0) { while(v_context->flags & FLAG_DMA_RUN) { vdp_run_dma_done(v_context, mclk_target); @@ -296,7 +299,6 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ //context->current_cycle = v_context->cycles; } } else if(vdp_port < 8) { - gen->bus_busy = 1; blocked = vdp_control_port_write(v_context, value); if (blocked) { while (blocked) { @@ -323,19 +325,16 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ if (v_context->cycles != before_cycle) { //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); context->current_cycle = v_context->cycles; + //Lock the Z80 out of the bus until the VDP access is complete + gen->bus_busy = 1; + sync_z80(gen->z80, v_context->cycles); + gen->bus_busy = 0; } } else if (vdp_port < 0x18) { - sync_sound(gen, context->current_cycle); psg_write(gen->psg, value); } else { //TODO: Implement undocumented test register(s) } - if (gen->bus_busy) - { - //Lock the Z80 out of the bus until the VDP access is complete - sync_z80(gen->z80, v_context->cycles); - gen->bus_busy = 0; - } return context; } @@ -402,6 +401,11 @@ uint16_t vdp_port_read(uint32_t vdp_port, m68k_context * context) if (v_context->cycles != before_cycle) { //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); context->current_cycle = v_context->cycles; + //Lock the Z80 out of the bus until the VDP access is complete + genesis_context *gen = context->system; + gen->bus_busy = 1; + sync_z80(gen->z80, v_context->cycles); + gen->bus_busy = 0; } return value; } -- cgit v1.2.3 From bd14f5b08583c050e8e23af5814908b99ba8d547 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Tue, 6 Jan 2015 19:09:00 -0800 Subject: Move detect_region down so that it once again occurs after load_rom since it won't work before the ROM is loaded --- blastem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index e41f550..684f644 100644 --- a/blastem.c +++ b/blastem.c @@ -1120,7 +1120,6 @@ int main(int argc, char ** argv) } set_exe_str(argv[0]); config = load_config(); - detect_region(); int width = -1; int height = -1; int debug = 0; @@ -1242,6 +1241,8 @@ int main(int argc, char ** argv) } if (force_version) { version_reg = force_version; + } else { + detect_region(); } update_title(); int def_width = 0; -- cgit v1.2.3 From f439d8688758710b74d4909e77ebce6444b8a448 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Wed, 14 Jan 2015 09:38:54 -0800 Subject: Removed hardcoded assumptions in M68K core about which parts of the memory map are RAM --- blastem.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 684f644..27b9d07 100644 --- a/blastem.c +++ b/blastem.c @@ -901,9 +901,7 @@ void save_sram() void init_run_cpu(genesis_context * gen, FILE * address_log, char * statefile, uint8_t * debugger) { - m68k_context context; m68k_options opts; - gen->m68k = &context; memmap_chunk memmap[MAX_MAP_CHUNKS]; uint32_t num_chunks; void * initial_mapped = NULL; @@ -998,21 +996,22 @@ void init_run_cpu(genesis_context * gen, FILE * address_log, char * statefile, u } init_m68k_opts(&opts, memmap, num_chunks, MCLKS_PER_68K); opts.address_log = address_log; - init_68k_context(&context, opts.gen.native_code_map, &opts); + m68k_context *context = init_68k_context(&opts); + gen->m68k = context; - context.video_context = gen->vdp; - context.system = gen; + context->video_context = gen->vdp; + context->system = gen; //cartridge ROM - context.mem_pointers[0] = cart; - context.target_cycle = context.sync_cycle = mclk_target; + context->mem_pointers[0] = cart; + context->target_cycle = context->sync_cycle = mclk_target; //work RAM - context.mem_pointers[1] = ram; + context->mem_pointers[1] = ram; //save RAM/map - context.mem_pointers[2] = initial_mapped; - context.mem_pointers[3] = (uint16_t *)gen->save_ram; + context->mem_pointers[2] = initial_mapped; + context->mem_pointers[3] = (uint16_t *)gen->save_ram; uint32_t address; address = cart[2] << 16 | cart[3]; - translate_m68k_stream(address, &context); + translate_m68k_stream(address, context); if (statefile) { uint32_t pc = load_gst(gen, statefile); if (!pc) { @@ -1021,15 +1020,15 @@ void init_run_cpu(genesis_context * gen, FILE * address_log, char * statefile, u } printf("Loaded %s\n", statefile); if (debugger) { - insert_breakpoint(&context, pc, debugger); + insert_breakpoint(context, pc, debugger); } adjust_int_cycle(gen->m68k, gen->vdp); - start_68k_context(&context, pc); + start_68k_context(context, pc); } else { if (debugger) { - insert_breakpoint(&context, address, debugger); + insert_breakpoint(context, address, debugger); } - m68k_reset(&context); + m68k_reset(context); } } -- cgit v1.2.3 From d11ec6908700a7eb34c326159826fcfbd04c1ab6 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Thu, 30 Apr 2015 19:28:01 -0700 Subject: Fix missing call to setup_io_devices --- blastem.c | 1 + 1 file changed, 1 insertion(+) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 27b9d07..e278488 100644 --- a/blastem.c +++ b/blastem.c @@ -1292,6 +1292,7 @@ int main(int argc, char ** argv) gen.ym = &y_context; gen.psg = &p_context; genesis = &gen; + setup_io_devices(config, gen.ports); int fname_size = strlen(romfname); sram_filename = malloc(fname_size+6); -- cgit v1.2.3 From d9ede1d212bee27df782abffdc1817203358f621 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Mon, 4 May 2015 08:48:10 -0700 Subject: Indentation fixup --- blastem.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index e278488..fe2ba8b 100644 --- a/blastem.c +++ b/blastem.c @@ -210,21 +210,21 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) z80_context * z_context = gen->z80; uint32_t mclks = context->current_cycle; sync_z80(z_context, mclks); - sync_sound(gen, mclks); + sync_sound(gen, mclks); if (mclks >= mclk_target) { vdp_run_context(v_context, mclk_target); if (vdp_is_frame_over(v_context)) { //printf("reached frame end | MCLK Cycles: %d, Target: %d, VDP cycles: %d\n", mclks, mclk_target, v_context->cycles); - if (!headless) { - break_on_sync |= wait_render_frame(v_context, frame_limit); - } else if(exit_after){ - --exit_after; - if (!exit_after) { - exit(0); + if (!headless) { + break_on_sync |= wait_render_frame(v_context, frame_limit); + } else if(exit_after){ + --exit_after; + if (!exit_after) { + exit(0); + } } - } - frame++; + frame++; mclks -= mclk_target; vdp_adjust_cycles(v_context, mclk_target); io_adjust_cycles(gen->ports, context->current_cycle, mclk_target); @@ -239,7 +239,7 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) } if (mclks) { vdp_run_context(v_context, mclks); - } + } mclk_target = vdp_cycles_to_frame_end(v_context); context->sync_cycle = mclk_target; } else { @@ -257,9 +257,9 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) adjust_int_cycle(context, v_context); if (address) { if (break_on_sync) { - break_on_sync = 0; - debugger(context, address); - } + break_on_sync = 0; + debugger(context, address); + } if (save_state) { save_state = 0; //advance Z80 core to the start of an instruction -- cgit v1.2.3 From 89ca3bce585f06927569ed1f18ad433d33e320e9 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Tue, 5 May 2015 08:42:27 -0700 Subject: Added config option to allow specifying a max sync cycle smaller than the end of frame --- blastem.c | 53 ++++++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 25 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index fe2ba8b..51a39b1 100644 --- a/blastem.c +++ b/blastem.c @@ -33,8 +33,6 @@ #define MAX_SOUND_CYCLES 100000 -uint32_t mclk_target = 0; - uint16_t cart[CARTRIDGE_WORDS]; uint16_t ram[RAM_WORDS]; uint8_t z80_ram[Z80_RAM_BYTES]; @@ -127,6 +125,10 @@ uint16_t read_dma_value(uint32_t address) void adjust_int_cycle(m68k_context * context, vdp_context * v_context) { + genesis_context *gen = context->system; + if (context->sync_cycle - context->current_cycle > gen->max_cycles) { + context->sync_cycle = context->current_cycle + gen->max_cycles; + } context->int_cycle = CYCLE_NEVER; if ((context->status & 0x7) < 6) { uint32_t next_vint = vdp_next_vint(v_context); @@ -204,17 +206,16 @@ void sync_sound(genesis_context * gen, uint32_t target) uint32_t frame=0; m68k_context * sync_components(m68k_context * context, uint32_t address) { - //TODO: Handle sync targets smaller than a single frame genesis_context * gen = context->system; vdp_context * v_context = gen->vdp; z80_context * z_context = gen->z80; uint32_t mclks = context->current_cycle; sync_z80(z_context, mclks); sync_sound(gen, mclks); - if (mclks >= mclk_target) { - vdp_run_context(v_context, mclk_target); + if (mclks >= gen->frame_end) { + vdp_run_context(v_context, gen->frame_end); if (vdp_is_frame_over(v_context)) { - //printf("reached frame end | MCLK Cycles: %d, Target: %d, VDP cycles: %d\n", mclks, mclk_target, v_context->cycles); + //printf("reached frame end | MCLK Cycles: %d, Target: %d, VDP cycles: %d\n", mclks, gen->frame_end, v_context->cycles); if (!headless) { break_on_sync |= wait_render_frame(v_context, frame_limit); @@ -225,27 +226,27 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) } } frame++; - mclks -= mclk_target; - vdp_adjust_cycles(v_context, mclk_target); - io_adjust_cycles(gen->ports, context->current_cycle, mclk_target); - io_adjust_cycles(gen->ports+1, context->current_cycle, mclk_target); - io_adjust_cycles(gen->ports+2, context->current_cycle, mclk_target); - context->current_cycle -= mclk_target; - z80_adjust_cycles(z_context, mclk_target); - gen->ym->current_cycle -= mclk_target; - gen->psg->cycles -= mclk_target; + mclks -= gen->frame_end; + vdp_adjust_cycles(v_context, gen->frame_end); + io_adjust_cycles(gen->ports, context->current_cycle, gen->frame_end); + io_adjust_cycles(gen->ports+1, context->current_cycle, gen->frame_end); + io_adjust_cycles(gen->ports+2, context->current_cycle, gen->frame_end); + context->current_cycle -= gen->frame_end; + z80_adjust_cycles(z_context, gen->frame_end); + gen->ym->current_cycle -= gen->frame_end; + gen->psg->cycles -= gen->frame_end; if (gen->ym->write_cycle != CYCLE_NEVER) { - gen->ym->write_cycle = gen->ym->write_cycle >= mclk_target ? gen->ym->write_cycle - mclk_target : 0; + gen->ym->write_cycle = gen->ym->write_cycle >= gen->frame_end ? gen->ym->write_cycle - gen->frame_end : 0; } if (mclks) { vdp_run_context(v_context, mclks); } - mclk_target = vdp_cycles_to_frame_end(v_context); - context->sync_cycle = mclk_target; + gen->frame_end = vdp_cycles_to_frame_end(v_context); } else { vdp_run_context(v_context, mclks); - mclk_target = vdp_cycles_to_frame_end(v_context); + gen->frame_end = vdp_cycles_to_frame_end(v_context); } + context->sync_cycle = gen->frame_end; } else { //printf("running VDP for %d cycles\n", mclks - v_context->cycles); vdp_run_context(v_context, mclks); @@ -290,8 +291,8 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ if (vdp_port < 4) { while (vdp_data_port_write(v_context, value) < 0) { while(v_context->flags & FLAG_DMA_RUN) { - vdp_run_dma_done(v_context, mclk_target); - if (v_context->cycles >= mclk_target) { + vdp_run_dma_done(v_context, gen->frame_end); + if (v_context->cycles >= gen->frame_end) { context->current_cycle = v_context->cycles; sync_components(context, 0); } @@ -303,8 +304,8 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ if (blocked) { while (blocked) { while(v_context->flags & FLAG_DMA_RUN) { - vdp_run_dma_done(v_context, mclk_target); - if (v_context->cycles >= mclk_target) { + vdp_run_dma_done(v_context, gen->frame_end); + if (v_context->cycles >= gen->frame_end) { context->current_cycle = v_context->cycles; sync_components(context, 0); } @@ -1003,7 +1004,7 @@ void init_run_cpu(genesis_context * gen, FILE * address_log, char * statefile, u context->system = gen; //cartridge ROM context->mem_pointers[0] = cart; - context->target_cycle = context->sync_cycle = mclk_target; + context->target_cycle = context->sync_cycle = gen->frame_end > gen->max_cycles ? gen->frame_end : gen->max_cycles; //work RAM context->mem_pointers[1] = ram; //save RAM/map @@ -1267,7 +1268,9 @@ int main(int argc, char ** argv) gen.master_clock = gen.normal_clock = fps == 60 ? MCLKS_NTSC : MCLKS_PAL; init_vdp_context(&v_context, version_reg & 0x40); - mclk_target = vdp_cycles_to_frame_end(&v_context); + gen.frame_end = vdp_cycles_to_frame_end(&v_context); + char * config_cycles = tern_find_ptr(config, "clocksmax_cycles"); + gen.max_cycles = config_cycles ? atoi(config_cycles) : 10000000; ym2612_context y_context; ym_init(&y_context, render_sample_rate(), gen.master_clock, MCLKS_PER_YM, render_audio_buffer(), ym_log ? YM_OPT_WAVE_LOG : 0); -- cgit v1.2.3 From b3e40bd29176e1c4cf53f8542628e48e1eb5dcb0 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Mon, 11 May 2015 00:28:47 -0700 Subject: Sync fixes and logging to fix more sync issues --- blastem.c | 71 +++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 35 insertions(+), 36 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 51a39b1..9a26e4b 100644 --- a/blastem.c +++ b/blastem.c @@ -203,7 +203,7 @@ void sync_sound(genesis_context * gen, uint32_t target) //printf("Target: %d, YM bufferpos: %d, PSG bufferpos: %d\n", target, gen->ym->buffer_pos, gen->psg->buffer_pos * 2); } -uint32_t frame=0; +uint32_t last_frame_num; m68k_context * sync_components(m68k_context * context, uint32_t address) { genesis_context * gen = context->system; @@ -212,45 +212,37 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) uint32_t mclks = context->current_cycle; sync_z80(z_context, mclks); sync_sound(gen, mclks); - if (mclks >= gen->frame_end) { - vdp_run_context(v_context, gen->frame_end); - if (vdp_is_frame_over(v_context)) { - //printf("reached frame end | MCLK Cycles: %d, Target: %d, VDP cycles: %d\n", mclks, gen->frame_end, v_context->cycles); - - if (!headless) { - break_on_sync |= wait_render_frame(v_context, frame_limit); - } else if(exit_after){ - --exit_after; - if (!exit_after) { - exit(0); - } - } - frame++; - mclks -= gen->frame_end; - vdp_adjust_cycles(v_context, gen->frame_end); - io_adjust_cycles(gen->ports, context->current_cycle, gen->frame_end); - io_adjust_cycles(gen->ports+1, context->current_cycle, gen->frame_end); - io_adjust_cycles(gen->ports+2, context->current_cycle, gen->frame_end); - context->current_cycle -= gen->frame_end; - z80_adjust_cycles(z_context, gen->frame_end); - gen->ym->current_cycle -= gen->frame_end; - gen->psg->cycles -= gen->frame_end; - if (gen->ym->write_cycle != CYCLE_NEVER) { - gen->ym->write_cycle = gen->ym->write_cycle >= gen->frame_end ? gen->ym->write_cycle - gen->frame_end : 0; - } - if (mclks) { - vdp_run_context(v_context, mclks); + vdp_run_context(v_context, mclks); + if (v_context->frame != last_frame_num) { + //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); + last_frame_num = v_context->frame; + + if (!headless) { + break_on_sync |= wait_render_frame(v_context, frame_limit); + } else if(exit_after){ + --exit_after; + if (!exit_after) { + exit(0); } - gen->frame_end = vdp_cycles_to_frame_end(v_context); - } else { - vdp_run_context(v_context, mclks); - gen->frame_end = vdp_cycles_to_frame_end(v_context); } - context->sync_cycle = gen->frame_end; + + vdp_adjust_cycles(v_context, mclks); + io_adjust_cycles(gen->ports, context->current_cycle, mclks); + io_adjust_cycles(gen->ports+1, context->current_cycle, mclks); + io_adjust_cycles(gen->ports+2, context->current_cycle, mclks); + context->current_cycle -= mclks; + z80_adjust_cycles(z_context, mclks); + gen->ym->current_cycle -= mclks; + gen->psg->cycles -= mclks; + if (gen->ym->write_cycle != CYCLE_NEVER) { + gen->ym->write_cycle = gen->ym->write_cycle >= mclks ? gen->ym->write_cycle - mclks : 0; + } + gen->frame_end = vdp_cycles_to_frame_end(v_context); } else { - //printf("running VDP for %d cycles\n", mclks - v_context->cycles); - vdp_run_context(v_context, mclks); + gen->frame_end = vdp_cycles_to_frame_end(v_context); } + context->sync_cycle = gen->frame_end; + //printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot); if (context->int_ack) { vdp_int_ack(v_context, context->int_ack); context->int_ack = 0; @@ -289,12 +281,15 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ int blocked; uint32_t before_cycle = v_context->cycles; if (vdp_port < 4) { + while (vdp_data_port_write(v_context, value) < 0) { while(v_context->flags & FLAG_DMA_RUN) { vdp_run_dma_done(v_context, gen->frame_end); if (v_context->cycles >= gen->frame_end) { context->current_cycle = v_context->cycles; + gen->bus_busy = 1; sync_components(context, 0); + gen->bus_busy = 0; } } //context->current_cycle = v_context->cycles; @@ -307,7 +302,9 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ vdp_run_dma_done(v_context, gen->frame_end); if (v_context->cycles >= gen->frame_end) { context->current_cycle = v_context->cycles; + gen->bus_busy = 1; sync_components(context, 0); + gen->bus_busy = 0; } } if (blocked < 0) { @@ -317,6 +314,8 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ } } } else { + context->sync_cycle = gen->frame_end = vdp_cycles_to_frame_end(v_context); + //printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot); adjust_int_cycle(context, v_context); } } else { -- cgit v1.2.3 From 92699df4cb844ec29bcb2c55e5d68d747aabb6a8 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Mon, 11 May 2015 20:31:59 -0700 Subject: Tiny cleanup --- blastem.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 9a26e4b..56f3ca9 100644 --- a/blastem.c +++ b/blastem.c @@ -237,10 +237,8 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) if (gen->ym->write_cycle != CYCLE_NEVER) { gen->ym->write_cycle = gen->ym->write_cycle >= mclks ? gen->ym->write_cycle - mclks : 0; } - gen->frame_end = vdp_cycles_to_frame_end(v_context); - } else { - gen->frame_end = vdp_cycles_to_frame_end(v_context); } + gen->frame_end = vdp_cycles_to_frame_end(v_context); context->sync_cycle = gen->frame_end; //printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot); if (context->int_ack) { -- cgit v1.2.3 From b06a76dab4014a5ea1046eee6e4fdd819dbe7cbb Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Tue, 19 May 2015 23:23:53 -0700 Subject: Small correction to VBLANK flag timing. Fixed some inconsistencies in interrupt timing calculation. --- blastem.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 56f3ca9..48f1883 100644 --- a/blastem.c +++ b/blastem.c @@ -125,6 +125,7 @@ uint16_t read_dma_value(uint32_t address) void adjust_int_cycle(m68k_context * context, vdp_context * v_context) { + //static int old_int_cycle = CYCLE_NEVER; genesis_context *gen = context->system; if (context->sync_cycle - context->current_cycle > gen->max_cycles) { context->sync_cycle = context->current_cycle + gen->max_cycles; @@ -147,6 +148,10 @@ void adjust_int_cycle(m68k_context * context, vdp_context * v_context) } } } + /*if (context->int_cycle != old_int_cycle) { + 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); + old_int_cycle = context->int_cycle; + }*/ context->target_cycle = context->int_cycle < context->sync_cycle ? context->int_cycle : context->sync_cycle; /*printf("Cyc: %d, Trgt: %d, Int Cyc: %d, Int: %d, Mask: %X, V: %d, H: %d, HICount: %d, HReg: %d, Line: %d\n", @@ -242,6 +247,7 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) context->sync_cycle = gen->frame_end; //printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot); if (context->int_ack) { + 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); vdp_int_ack(v_context, context->int_ack); context->int_ack = 0; } -- cgit v1.2.3 From 265a11e776d9708483024f48a9e0eaaf6686d00b Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Wed, 20 May 2015 10:35:03 -0700 Subject: Update vscroll latch implementation to be more in line with what Eke-Eke has observed. Revert the change to vdp_cycles_to_line because it breaks hints on line 0. H-Int timing is still a little messed up, but the previous change made things worse. --- blastem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 48f1883..c11c4a4 100644 --- a/blastem.c +++ b/blastem.c @@ -247,7 +247,7 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) context->sync_cycle = gen->frame_end; //printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot); if (context->int_ack) { - 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); + //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); vdp_int_ack(v_context, context->int_ack); context->int_ack = 0; } -- cgit v1.2.3 From 863ea0b3f8b8879ac3092f391a68dc95d0d04de2 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Wed, 20 May 2015 19:05:11 -0700 Subject: Upgrade to SDL 2.0 and drop support for the non-OpenGL render path --- blastem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index c11c4a4..60a5fa6 100644 --- a/blastem.c +++ b/blastem.c @@ -1263,7 +1263,7 @@ int main(int argc, char ** argv) fps = 50; } if (!headless) { - render_init(width, height, title, fps, fullscreen, use_gl); + render_init(width, height, title, fps, fullscreen); } vdp_context v_context; genesis_context gen; -- cgit v1.2.3 From c16bdc99580a5867127efb1fad51c79f7c0804a7 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Wed, 20 May 2015 23:34:12 -0700 Subject: Better handling of savestate and debug break events with "uncooperative" games/demos --- blastem.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 60a5fa6..148b6c4 100644 --- a/blastem.c +++ b/blastem.c @@ -251,6 +251,9 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) vdp_int_ack(v_context, context->int_ack); context->int_ack = 0; } + if (!address && (break_on_sync || save_state)) { + context->sync_cycle = context->current_cycle + 1; + } adjust_int_cycle(context, v_context); if (address) { if (break_on_sync) { @@ -265,6 +268,7 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) sync_z80(z_context, z_context->current_cycle + MCLKS_PER_Z80); } save_gst(gen, "savestate.gst", address); + puts("Saved state to savestate.gst"); } } return context; -- cgit v1.2.3 From 09f4bd8615c8c0bec0888fee26093381e4d93477 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Mon, 25 May 2015 23:37:13 -0700 Subject: Implement cycles being stolen from 68K when the Z80 accesses the bank area or VDP/PSG. Small fix to code that tries to get system into a consistent state for a savestate --- blastem.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 148b6c4..4c1af0d 100644 --- a/blastem.c +++ b/blastem.c @@ -217,6 +217,11 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) uint32_t mclks = context->current_cycle; sync_z80(z_context, mclks); sync_sound(gen, mclks); + while (context->current_cycle > mclks) { + mclks = context->current_cycle; + sync_z80(z_context, mclks); + sync_sound(gen, mclks); + } vdp_run_context(v_context, mclks); if (v_context->frame != last_frame_num) { //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); @@ -260,7 +265,7 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) break_on_sync = 0; debugger(context, address); } - if (save_state) { + if (save_state && (z_context->pc || (!z_context->reset && !z_context->busreq))) { save_state = 0; //advance Z80 core to the start of an instruction while (!z_context->pc) @@ -269,6 +274,8 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) } save_gst(gen, "savestate.gst", address); puts("Saved state to savestate.gst"); + } else if(save_state) { + context->sync_cycle = context->current_cycle + 1; } } return context; @@ -436,6 +443,15 @@ uint8_t z80_vdp_port_read(uint32_t vdp_port, void * vcontext) exit(1); } genesis_context * gen = context->system; + //VDP access goes over the 68K bus like a bank area access + //typical delay from bus arbitration + context->current_cycle += 3 * MCLKS_PER_Z80; + //TODO: add cycle for an access right after a previous one + //TODO: Below cycle time is an estimate based on the time between 68K !BG goes low and Z80 !MREQ goes high + // Needs a new logic analyzer capture to get the actual delay on the 68K side + gen->m68k->current_cycle += 8 * MCLKS_PER_68K; + + vdp_port &= 0x1F; uint16_t ret; if (vdp_port < 0x10) { @@ -683,6 +699,9 @@ uint8_t z80_read_bank(uint32_t location, void * vcontext) //typical delay from bus arbitration context->current_cycle += 3 * MCLKS_PER_Z80; //TODO: add cycle for an access right after a previous one + //TODO: Below cycle time is an estimate based on the time between 68K !BG goes low and Z80 !MREQ goes high + // Needs a new logic analyzer capture to get the actual delay on the 68K side + gen->m68k->current_cycle += 8 * MCLKS_PER_68K; location &= 0x7FFF; if (context->mem_pointers[1]) { @@ -707,6 +726,9 @@ void *z80_write_bank(uint32_t location, void * vcontext, uint8_t value) //typical delay from bus arbitration context->current_cycle += 3 * MCLKS_PER_Z80; //TODO: add cycle for an access right after a previous one + //TODO: Below cycle time is an estimate based on the time between 68K !BG goes low and Z80 !MREQ goes high + // Needs a new logic analyzer capture to get the actual delay on the 68K side + gen->m68k->current_cycle += 8 * MCLKS_PER_68K; location &= 0x7FFF; uint32_t address = context->bank_reg << 15 | location; -- cgit v1.2.3