comparison blastem.c @ 260:625f8e4d5fd2

Initial stab at integartiong Z80 core
author Mike Pavone <pavone@retrodev.com>
date Tue, 30 Apr 2013 00:39:31 -0700
parents 2b1c2c28b261
children 2989ed7b8608
comparison
equal deleted inserted replaced
259:d9417261366f 260:625f8e4d5fd2
1 #include "68kinst.h" 1 #include "68kinst.h"
2 #include "m68k_to_x86.h" 2 #include "m68k_to_x86.h"
3 #include "z80_to_x86.h"
3 #include "mem.h" 4 #include "mem.h"
4 #include "vdp.h" 5 #include "vdp.h"
5 #include "render.h" 6 #include "render.h"
6 #include "blastem.h" 7 #include "blastem.h"
7 #include <stdio.h> 8 #include <stdio.h>
10 11
11 #define CARTRIDGE_WORDS 0x200000 12 #define CARTRIDGE_WORDS 0x200000
12 #define RAM_WORDS 32 * 1024 13 #define RAM_WORDS 32 * 1024
13 #define Z80_RAM_BYTES 8 * 1024 14 #define Z80_RAM_BYTES 8 * 1024
14 #define MCLKS_PER_68K 7 15 #define MCLKS_PER_68K 7
16 #define MCLKS_PER_Z80 15
15 //TODO: Figure out the exact value for this 17 //TODO: Figure out the exact value for this
16 #define MCLKS_PER_FRAME (MCLKS_LINE*262) 18 #define MCLKS_PER_FRAME (MCLKS_LINE*262)
17 #define CYCLE_NEVER 0xFFFFFFFF 19 #define CYCLE_NEVER 0xFFFFFFFF
18 20
19 uint16_t cart[CARTRIDGE_WORDS]; 21 uint16_t cart[CARTRIDGE_WORDS];
103 //TODO: Figure out what happens when you try to DMA from weird adresses like IO or banked Z80 area 105 //TODO: Figure out what happens when you try to DMA from weird adresses like IO or banked Z80 area
104 return 0; 106 return 0;
105 } 107 }
106 108
107 #define VINT_CYCLE ((MCLKS_LINE * 226)/MCLKS_PER_68K) 109 #define VINT_CYCLE ((MCLKS_LINE * 226)/MCLKS_PER_68K)
110 #define ZVINT_CYCLE ((MCLKS_LINE * 226)/MCLKS_PER_Z80)
108 111
109 void adjust_int_cycle(m68k_context * context, vdp_context * v_context) 112 void adjust_int_cycle(m68k_context * context, vdp_context * v_context)
110 { 113 {
111 if (!(v_context->regs[REG_MODE_2] & 0x20 && ((context->status & 0x7) < 6)) || context->current_cycle >= VINT_CYCLE) { 114 if (!(v_context->regs[REG_MODE_2] & 0x20 && ((context->status & 0x7) < 6)) || context->current_cycle >= VINT_CYCLE) {
112 context->int_cycle = CYCLE_NEVER; 115 context->int_cycle = CYCLE_NEVER;
119 } 122 }
120 } 123 }
121 } 124 }
122 125
123 int break_on_sync = 0; 126 int break_on_sync = 0;
127 #define Z80_ACK_DELAY 3 //TODO: Calculate this on the fly based on how synced up the Z80 and 68K clocks are
128
129 uint8_t reset = 1;
130 uint8_t need_reset = 0;
131 uint8_t busreq = 0;
132 uint8_t busack = 0;
133 uint32_t busack_cycle = CYCLE_NEVER;
134 uint8_t new_busack = 0;
124 135
125 m68k_context * sync_components(m68k_context * context, uint32_t address) 136 m68k_context * sync_components(m68k_context * context, uint32_t address)
126 { 137 {
127 //TODO: Handle sync targets smaller than a single frame 138 //TODO: Handle sync targets smaller than a single frame
128 vdp_context * v_context = context->next_context; 139 z80_context * z_context = context->next_context;
140 vdp_context * v_context = z_context->next_context;
129 uint32_t mclks = context->current_cycle * MCLKS_PER_68K; 141 uint32_t mclks = context->current_cycle * MCLKS_PER_68K;
142 if (!reset && !busreq) {
143 if (need_reset) {
144 z80_reset(z_context);
145 need_reset = 0;
146 }
147 z_context->sync_cycle = mclks / MCLKS_PER_Z80;
148 while (z_context->current_cycle < z_context->sync_cycle) {
149 if (z_context->iff1 && z_context->current_cycle < ZVINT_CYCLE) {
150 z_context->int_cycle = ZVINT_CYCLE;
151 }
152 z_context->target_cycle = z_context->sync_cycle < z_context->int_cycle ? z_context->sync_cycle : z_context->int_cycle;
153 z80_run(z_context);
154 }
155 }
130 if (mclks >= MCLKS_PER_FRAME) { 156 if (mclks >= MCLKS_PER_FRAME) {
131 //printf("reached frame end | 68K Cycles: %d, MCLK Cycles: %d\n", context->current_cycle, mclks); 157 //printf("reached frame end | 68K Cycles: %d, MCLK Cycles: %d\n", context->current_cycle, mclks);
132 vdp_run_context(v_context, MCLKS_PER_FRAME); 158 vdp_run_context(v_context, MCLKS_PER_FRAME);
133 if (!headless) { 159 if (!headless) {
134 break_on_sync |= wait_render_frame(v_context); 160 break_on_sync |= wait_render_frame(v_context);
136 mclks -= MCLKS_PER_FRAME; 162 mclks -= MCLKS_PER_FRAME;
137 vdp_adjust_cycles(v_context, MCLKS_PER_FRAME); 163 vdp_adjust_cycles(v_context, MCLKS_PER_FRAME);
138 io_adjust_cycles(&gamepad_1, context->current_cycle, MCLKS_PER_FRAME/MCLKS_PER_68K); 164 io_adjust_cycles(&gamepad_1, context->current_cycle, MCLKS_PER_FRAME/MCLKS_PER_68K);
139 io_adjust_cycles(&gamepad_2, context->current_cycle, MCLKS_PER_FRAME/MCLKS_PER_68K); 165 io_adjust_cycles(&gamepad_2, context->current_cycle, MCLKS_PER_FRAME/MCLKS_PER_68K);
140 context->current_cycle -= MCLKS_PER_FRAME/MCLKS_PER_68K; 166 context->current_cycle -= MCLKS_PER_FRAME/MCLKS_PER_68K;
167 if (z_context->current_cycle >= MCLKS_PER_FRAME/MCLKS_PER_Z80) {
168 z_context->current_cycle -= MCLKS_PER_FRAME/MCLKS_PER_Z80;
169 } else {
170 z_context->current_cycle = 0;
171 }
141 if (mclks) { 172 if (mclks) {
142 vdp_run_context(v_context, mclks); 173 vdp_run_context(v_context, mclks);
143 } 174 }
144 } else { 175 } else {
145 //printf("running VDP for %d cycles\n", mclks - v_context->cycles); 176 //printf("running VDP for %d cycles\n", mclks - v_context->cycles);
155 186
156 m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_t value) 187 m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_t value)
157 { 188 {
158 //printf("vdp_port write: %X, value: %X, cycle: %d\n", vdp_port, value, context->current_cycle); 189 //printf("vdp_port write: %X, value: %X, cycle: %d\n", vdp_port, value, context->current_cycle);
159 sync_components(context, 0); 190 sync_components(context, 0);
160 vdp_context * v_context = context->next_context; 191 z80_context * z_context = context->next_context;
192 vdp_context * v_context = z_context->next_context;
161 if (vdp_port < 0x10) { 193 if (vdp_port < 0x10) {
162 int blocked; 194 int blocked;
163 if (vdp_port < 4) { 195 if (vdp_port < 4) {
164 while (vdp_data_port_write(v_context, value) < 0) { 196 while (vdp_data_port_write(v_context, value) < 0) {
165 while(v_context->flags & FLAG_DMA_RUN) { 197 while(v_context->flags & FLAG_DMA_RUN) {
214 } 246 }
215 247
216 m68k_context * vdp_port_read(uint32_t vdp_port, m68k_context * context) 248 m68k_context * vdp_port_read(uint32_t vdp_port, m68k_context * context)
217 { 249 {
218 sync_components(context, 0); 250 sync_components(context, 0);
219 vdp_context * v_context = context->next_context; 251 z80_context * z_context = context->next_context;
252 vdp_context * v_context = z_context->next_context;
220 if (vdp_port < 0x10) { 253 if (vdp_port < 0x10) {
221 if (vdp_port < 4) { 254 if (vdp_port < 4) {
222 context->value = vdp_data_port_read(v_context); 255 context->value = vdp_data_port_read(v_context);
223 } else if(vdp_port < 8) { 256 } else if(vdp_port < 8) {
224 context->value = vdp_control_port_read(v_context); 257 context->value = vdp_control_port_read(v_context);
234 return context; 267 return context;
235 } 268 }
236 269
237 #define TH 0x40 270 #define TH 0x40
238 #define TH_TIMEOUT 8000 271 #define TH_TIMEOUT 8000
239 #define Z80_ACK_DELAY 3 //TODO: Calculate this on the fly based on how synced up the Z80 and 68K clocks are
240
241 uint8_t reset = 1;
242 uint8_t busreq = 0;
243 uint8_t busack = 0;
244 uint32_t busack_cycle = CYCLE_NEVER;
245 uint8_t new_busack = 0;
246 272
247 void io_adjust_cycles(io_port * pad, uint32_t current_cycle, uint32_t deduction) 273 void io_adjust_cycles(io_port * pad, uint32_t current_cycle, uint32_t deduction)
248 { 274 {
249 /*uint8_t control = pad->control | 0x80; 275 /*uint8_t control = pad->control | 0x80;
250 uint8_t th = control & pad->output; 276 uint8_t th = control & pad->output;
354 if(!reset) { 380 if(!reset) {
355 busack_cycle = context->current_cycle + Z80_ACK_DELAY; 381 busack_cycle = context->current_cycle + Z80_ACK_DELAY;
356 new_busack = 0; 382 new_busack = 0;
357 } 383 }
358 } else { 384 } else {
385 if (busreq) {
386 z80_context * z_context = context->next_context;
387 //TODO: Add necessary delay between release of busreq and resumption of execution
388 z_context->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80;
389 }
359 busreq = 0; 390 busreq = 0;
360 busack_cycle = CYCLE_NEVER; 391 busack_cycle = CYCLE_NEVER;
361 busack = 1; 392 busack = 1;
362 } 393 }
363 } else if (location == 0x1200) { 394 } else if (location == 0x1200) {
364 if (value & 1) { 395 if (value & 1) {
365 if (reset && busreq) { 396 if (reset && busreq) {
366 new_busack = 0; 397 new_busack = 0;
367 busack_cycle = context->current_cycle + Z80_ACK_DELAY; 398 busack_cycle = context->current_cycle + Z80_ACK_DELAY;
399 }
400 //TODO: Deal with the scenario in which reset is not asserted long enough
401 if (reset) {
402 z80_context * z_context = context->next_context;
403 need_reset = 1;
404 //TODO: Add necessary delay between release of reset and start of execution
405 z_context->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80;
368 } 406 }
369 reset = 0; 407 reset = 0;
370 } else { 408 } else {
371 reset = 1; 409 reset = 1;
372 } 410 }
421 if(!reset) { 459 if(!reset) {
422 busack_cycle = context->current_cycle + Z80_ACK_DELAY; 460 busack_cycle = context->current_cycle + Z80_ACK_DELAY;
423 new_busack = 0; 461 new_busack = 0;
424 } 462 }
425 } else { 463 } else {
464 if (busreq) {
465 z80_context * z_context = context->next_context;
466 //TODO: Add necessary delay between release of busreq and resumption of execution
467 z_context->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80;
468 }
426 busreq = 0; 469 busreq = 0;
427 busack_cycle = CYCLE_NEVER; 470 busack_cycle = CYCLE_NEVER;
428 busack = 1; 471 busack = 1;
429 } 472 }
430 } else if (location == 0x1200) { 473 } else if (location == 0x1200) {
431 if (value & 0x100) { 474 if (value & 0x100) {
432 if (reset && busreq) { 475 if (reset && busreq) {
433 new_busack = 0; 476 new_busack = 0;
434 busack_cycle = context->current_cycle + Z80_ACK_DELAY; 477 busack_cycle = context->current_cycle + Z80_ACK_DELAY;
478 }
479 //TODO: Deal with the scenario in which reset is not asserted long enough
480 if (reset) {
481 z80_context * z_context = context->next_context;
482 need_reset = 1;
483 //TODO: Add necessary delay between release of reset and start of execution
484 z_context->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80;
435 } 485 }
436 reset = 0; 486 reset = 0;
437 } else { 487 } else {
438 reset = 1; 488 reset = 1;
439 } 489 }
802 } 852 }
803 } 853 }
804 return context; 854 return context;
805 } 855 }
806 856
807 void init_run_cpu(vdp_context * vcontext, int debug, FILE * address_log) 857 void init_run_cpu(z80_context * zcontext, int debug, FILE * address_log)
808 { 858 {
809 m68k_context context; 859 m68k_context context;
810 x86_68k_options opts; 860 x86_68k_options opts;
811 init_x86_68k_opts(&opts); 861 init_x86_68k_opts(&opts);
812 opts.address_log = address_log; 862 opts.address_log = address_log;
813 init_68k_context(&context, opts.native_code_map, &opts); 863 init_68k_context(&context, opts.native_code_map, &opts);
814 864
815 context.next_context = vcontext; 865 context.next_context = zcontext;
816 //cartridge ROM 866 //cartridge ROM
817 context.mem_pointers[0] = cart; 867 context.mem_pointers[0] = cart;
818 context.target_cycle = context.sync_cycle = MCLKS_PER_FRAME/MCLKS_PER_68K; 868 context.target_cycle = context.sync_cycle = MCLKS_PER_FRAME/MCLKS_PER_68K;
819 //work RAM 869 //work RAM
820 context.mem_pointers[1] = ram; 870 context.mem_pointers[1] = ram;
875 render_init(width, height); 925 render_init(width, height);
876 } 926 }
877 vdp_context v_context; 927 vdp_context v_context;
878 928
879 init_vdp_context(&v_context); 929 init_vdp_context(&v_context);
880 init_run_cpu(&v_context, debug, address_log); 930
931 z80_context z_context;
932 x86_z80_options z_opts;
933 init_x86_z80_opts(&z_opts);
934 init_z80_context(&z_context, &z_opts);
935 z_context.next_context = &v_context;
936 z_context.mem_pointers[0] = z80_ram;
937 z_context.sync_cycle = z_context.target_cycle = MCLKS_PER_FRAME/MCLKS_PER_Z80;
938 z_context.int_cycle = CYCLE_NEVER;
939 z_context.mem_pointers[1] = z_context.mem_pointers[2] = (uint8_t *)cart;
940
941 init_run_cpu(&z_context, debug, address_log);
881 return 0; 942 return 0;
882 } 943 }