# HG changeset patch # User Michael Pavone # Date 1420330103 28800 # Node ID 30ccf56842d66acd339fc290e205fb8dc0a51108 # Parent b68039895627ef8e7f9c796c1b1e4c671dc30871 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 diff -r b68039895627 -r 30ccf56842d6 backend.h --- a/backend.h Fri Jan 02 13:47:34 2015 -0800 +++ b/backend.h Sat Jan 03 16:08:23 2015 -0800 @@ -89,6 +89,7 @@ uint32_t address_mask; uint32_t max_address; uint32_t bus_cycles; + uint32_t clock_divider; int32_t mem_ptr_off; int32_t ram_flags_off; uint8_t ram_flags_shift; diff -r b68039895627 -r 30ccf56842d6 backend_x86.c --- a/backend_x86.c Fri Jan 02 13:47:34 2015 -0800 +++ b/backend_x86.c Sat Jan 03 16:08:23 2015 -0800 @@ -3,7 +3,7 @@ void cycles(cpu_options *opts, uint32_t num) { - add_ir(&opts->code, num, opts->cycles, SZ_D); + add_ir(&opts->code, num*opts->clock_divider, opts->cycles, SZ_D); } void check_cycles_int(cpu_options *opts, uint32_t address) diff -r b68039895627 -r 30ccf56842d6 blastem.c --- a/blastem.c Fri Jan 02 13:47:34 2015 -0800 +++ b/blastem.c Sat Jan 03 16:08:23 2015 -0800 @@ -125,26 +125,18 @@ 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 @@ #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 @@ 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 @@ } else #endif { - z_context->current_cycle = mclks / MCLKS_PER_Z80; + z_context->current_cycle = mclks; } } @@ -238,14 +230,14 @@ 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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } } 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 @@ 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 @@ { 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 @@ { 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 @@ 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_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 @@ } else { context->mem_pointers[1] = NULL; } - + return context; } @@ -1084,7 +1077,7 @@ } 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 @@ 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 @@ 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; diff -r b68039895627 -r 30ccf56842d6 m68k_core.h --- a/m68k_core.h Fri Jan 02 13:47:34 2015 -0800 +++ b/m68k_core.h Sat Jan 03 16:08:23 2015 -0800 @@ -67,7 +67,7 @@ void translate_m68k(m68k_options * opts, struct m68kinst * inst); void translate_m68k_stream(uint32_t address, m68k_context * context); void start_68k_context(m68k_context * context, uint32_t address); -void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks); +void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks, uint32_t clock_divider); void init_68k_context(m68k_context * context, native_map_slot * native_code_map, void * opts); void m68k_reset(m68k_context * context); void insert_breakpoint(m68k_context * context, uint32_t address, uint8_t * bp_handler); diff -r b68039895627 -r 30ccf56842d6 m68k_core_x86.c --- a/m68k_core_x86.c Fri Jan 02 13:47:34 2015 -0800 +++ b/m68k_core_x86.c Sat Jan 03 16:08:23 2015 -0800 @@ -1012,8 +1012,8 @@ //Memory shift shift_ir(code, 1, dst_op->base, SZ_W); } else { - cycles(&opts->gen, inst->extra.size == OPSIZE_LONG ? 8 : 6); if (src_op->mode == MODE_IMMED) { + cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + 2 * src_op->disp); if (src_op->disp != 1 && inst->op == M68K_ASL) { set_flag(opts, 0, FLAG_V); for (int i = 0; i < src_op->disp; i++) { @@ -1037,6 +1037,7 @@ set_flag_cond(opts, CC_O, FLAG_V); } } else { + cycles(&opts->gen, inst->extra.size == OPSIZE_LONG ? 8 : 6); if (src_op->base != RCX) { if (src_op->mode == MODE_REG_DIRECT) { mov_rr(code, src_op->base, RCX, SZ_B); @@ -1066,8 +1067,9 @@ jmp(code, code->cur + 2); *nz_off = code->cur - (nz_off + 1); //add 2 cycles for every bit shifted - add_rr(code, RCX, opts->gen.cycles, SZ_D); - add_rr(code, RCX, opts->gen.cycles, SZ_D); + mov_ir(code, 2 * opts->gen.clock_divider, opts->gen.scratch2, SZ_D); + imul_rr(code, RCX, opts->gen.scratch2, SZ_D); + add_rr(code, opts->gen.scratch2, opts->gen.cycles, SZ_D); if (inst->op == M68K_ASL) { //ASL has Overflow flag behavior that depends on all of the bits shifted through the MSB //Easiest way to deal with this is to shift one bit at a time @@ -1865,8 +1867,10 @@ and_ir(code, 63, opts->gen.scratch1, SZ_D); code_ptr zero_off = code->cur + 1; jcc(code, CC_Z, code->cur + 2); - add_rr(code, opts->gen.scratch1, opts->gen.cycles, SZ_D); - add_rr(code, opts->gen.scratch1, opts->gen.cycles, SZ_D); + //add 2 cycles for every bit shifted + mov_ir(code, 2 * opts->gen.clock_divider, opts->gen.scratch2, SZ_D); + imul_rr(code, RCX, opts->gen.scratch2, SZ_D); + add_rr(code, opts->gen.scratch2, opts->gen.cycles, SZ_D); cmp_ir(code, 32, opts->gen.scratch1, SZ_B); code_ptr norm_off = code->cur + 1; jcc(code, CC_L, code->cur + 2); @@ -2186,7 +2190,7 @@ } } -void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks) +void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks, uint32_t clock_divider) { memset(opts, 0, sizeof(*opts)); opts->gen.memmap = memmap; @@ -2196,6 +2200,7 @@ opts->gen.byte_swap = 1; opts->gen.max_address = 0x1000000; opts->gen.bus_cycles = BUS; + opts->gen.clock_divider = clock_divider; opts->gen.mem_ptr_off = offsetof(m68k_context, mem_pointers); opts->gen.ram_flags_off = offsetof(m68k_context, ram_code_flags); opts->gen.ram_flags_shift = 11; @@ -2308,7 +2313,7 @@ opts->native_addr_and_sync = code->cur; call(code, opts->gen.save_context); push_r(code, opts->gen.scratch1); - + xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_D); call_args_abi(code, (code_ptr)sync_components, 2, opts->gen.context_reg, opts->gen.scratch1); pop_r(code, RSI); //restore saved address from opts->gen.scratch1 diff -r b68039895627 -r 30ccf56842d6 z80_to_x86.c --- a/z80_to_x86.c Fri Jan 02 13:47:34 2015 -0800 +++ b/z80_to_x86.c Sat Jan 03 16:08:23 2015 -0800 @@ -879,20 +879,11 @@ } break; case Z80_HALT: { + code_ptr loop_top = code->cur; + //this isn't terribly efficient, but it's good enough for now cycles(&opts->gen, 4); - mov_ir(code, address, opts->gen.scratch1, SZ_W); - uint8_t * call_inst = code->cur; - mov_rr(code, opts->gen.limit, opts->gen.scratch2, SZ_D); - sub_rr(code, opts->gen.cycles, opts->gen.scratch2, SZ_D); - and_ir(code, 0xFFFFFFFC, opts->gen.scratch2, SZ_D); - add_rr(code, opts->gen.scratch2, opts->gen.cycles, SZ_D); - cmp_rr(code, opts->gen.limit, opts->gen.cycles, SZ_D); - code_ptr skip_last = code->cur+1; - jcc(code, CC_NB, code->cur+2); - cycles(&opts->gen, 4); - *skip_last = code->cur - (skip_last+1); - call(code, opts->gen.handle_cycle_limit_int); - jmp(code, call_inst); + check_cycles_int(&opts->gen, address); + jmp(code, loop_top); break; } case Z80_DI: @@ -908,7 +899,7 @@ mov_irdisp(code, 1, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B); mov_irdisp(code, 1, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B); //interrupt enable has a one-instruction latency, minimum instruction duration is 4 cycles - add_irdisp(code, 4, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D); + add_irdisp(code, 4*opts->gen.clock_divider, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D); call(code, opts->do_sync); break; case Z80_IM: @@ -1932,7 +1923,7 @@ } while (opts->gen.deferred); } -void init_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks) +void init_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks, uint32_t clock_divider) { memset(options, 0, sizeof(*options)); @@ -1942,6 +1933,7 @@ options->gen.address_mask = 0xFFFF; options->gen.max_address = 0x10000; options->gen.bus_cycles = 3; + options->gen.clock_divider = clock_divider; options->gen.mem_ptr_off = offsetof(z80_context, mem_pointers); options->gen.ram_flags_off = offsetof(z80_context, ram_code_flags); options->gen.ram_flags_shift = 7; @@ -1968,18 +1960,18 @@ options->regs[Z80_AF] = -1; options->regs[Z80_IX] = RDX; options->regs[Z80_IY] = R8; - + options->gen.scratch1 = R13; options->gen.scratch2 = R14; #else memset(options->regs, -1, sizeof(options->regs)); options->regs[Z80_A] = RAX; options->regx[Z80_SP] = RBX; - + options->gen.scratch1 = RCX; options->gen.scratch2 = RDX; #endif - + options->gen.context_reg = RSI; options->gen.cycles = RBP; options->gen.limit = RDI; diff -r b68039895627 -r 30ccf56842d6 z80_to_x86.h --- a/z80_to_x86.h Fri Jan 02 13:47:34 2015 -0800 +++ b/z80_to_x86.h Sat Jan 03 16:08:23 2015 -0800 @@ -1,6 +1,6 @@ /* Copyright 2013 Michael Pavone - This file is part of BlastEm. + This file is part of BlastEm. BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. */ #ifndef Z80_TO_X86_H_ @@ -82,7 +82,7 @@ } z80_context; void translate_z80_stream(z80_context * context, uint32_t address); -void init_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks); +void init_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks, uint32_t clock_divider); void init_z80_context(z80_context * context, z80_options * options); code_ptr z80_get_native_address(z80_context * context, uint32_t address); code_ptr z80_get_native_address_trans(z80_context * context, uint32_t address);