Mercurial > repos > blastem
comparison blastem.c @ 263:2989ed7b8608
Add a second context pointer to m68k_context so that try_fifo_write can still have easy access to the VDP. Handle writes to Z80 code addresses from the 68K.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 30 Apr 2013 20:36:15 -0700 |
parents | 625f8e4d5fd2 |
children | 8fd6652e56f8 |
comparison
equal
deleted
inserted
replaced
262:d97c9eca49f4 | 263:2989ed7b8608 |
---|---|
134 uint8_t new_busack = 0; | 134 uint8_t new_busack = 0; |
135 | 135 |
136 m68k_context * sync_components(m68k_context * context, uint32_t address) | 136 m68k_context * sync_components(m68k_context * context, uint32_t address) |
137 { | 137 { |
138 //TODO: Handle sync targets smaller than a single frame | 138 //TODO: Handle sync targets smaller than a single frame |
139 z80_context * z_context = context->next_context; | 139 z80_context * z_context = context->next_cpu; |
140 vdp_context * v_context = z_context->next_context; | 140 vdp_context * v_context = context->video_context; |
141 uint32_t mclks = context->current_cycle * MCLKS_PER_68K; | 141 uint32_t mclks = context->current_cycle * MCLKS_PER_68K; |
142 if (!reset && !busreq) { | 142 if (!reset && !busreq) { |
143 if (need_reset) { | 143 if (need_reset) { |
144 z80_reset(z_context); | 144 z80_reset(z_context); |
145 need_reset = 0; | 145 need_reset = 0; |
148 while (z_context->current_cycle < z_context->sync_cycle) { | 148 while (z_context->current_cycle < z_context->sync_cycle) { |
149 if (z_context->iff1 && z_context->current_cycle < ZVINT_CYCLE) { | 149 if (z_context->iff1 && z_context->current_cycle < ZVINT_CYCLE) { |
150 z_context->int_cycle = ZVINT_CYCLE; | 150 z_context->int_cycle = ZVINT_CYCLE; |
151 } | 151 } |
152 z_context->target_cycle = z_context->sync_cycle < z_context->int_cycle ? z_context->sync_cycle : z_context->int_cycle; | 152 z_context->target_cycle = z_context->sync_cycle < z_context->int_cycle ? z_context->sync_cycle : z_context->int_cycle; |
153 printf("Running Z80 from cycle %d to cycle %d\n", z_context->current_cycle, z_context->sync_cycle); | |
154 printf("HL: %X, Native PC: %p\n", (z_context->regs[Z80_H] << 8) | z_context->regs[Z80_L], z_context->native_pc); | |
153 z80_run(z_context); | 155 z80_run(z_context); |
156 printf("Z80 returned at cycle %d\n", z_context->current_cycle); | |
154 } | 157 } |
155 } | 158 } |
156 if (mclks >= MCLKS_PER_FRAME) { | 159 if (mclks >= MCLKS_PER_FRAME) { |
157 //printf("reached frame end | 68K Cycles: %d, MCLK Cycles: %d\n", context->current_cycle, mclks); | 160 //printf("reached frame end | 68K Cycles: %d, MCLK Cycles: %d\n", context->current_cycle, mclks); |
158 vdp_run_context(v_context, MCLKS_PER_FRAME); | 161 vdp_run_context(v_context, MCLKS_PER_FRAME); |
186 | 189 |
187 m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_t value) | 190 m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_t value) |
188 { | 191 { |
189 //printf("vdp_port write: %X, value: %X, cycle: %d\n", vdp_port, value, context->current_cycle); | 192 //printf("vdp_port write: %X, value: %X, cycle: %d\n", vdp_port, value, context->current_cycle); |
190 sync_components(context, 0); | 193 sync_components(context, 0); |
191 z80_context * z_context = context->next_context; | 194 vdp_context * v_context = context->video_context; |
192 vdp_context * v_context = z_context->next_context; | |
193 if (vdp_port < 0x10) { | 195 if (vdp_port < 0x10) { |
194 int blocked; | 196 int blocked; |
195 if (vdp_port < 4) { | 197 if (vdp_port < 4) { |
196 while (vdp_data_port_write(v_context, value) < 0) { | 198 while (vdp_data_port_write(v_context, value) < 0) { |
197 while(v_context->flags & FLAG_DMA_RUN) { | 199 while(v_context->flags & FLAG_DMA_RUN) { |
246 } | 248 } |
247 | 249 |
248 m68k_context * vdp_port_read(uint32_t vdp_port, m68k_context * context) | 250 m68k_context * vdp_port_read(uint32_t vdp_port, m68k_context * context) |
249 { | 251 { |
250 sync_components(context, 0); | 252 sync_components(context, 0); |
251 z80_context * z_context = context->next_context; | 253 vdp_context * v_context = context->video_context; |
252 vdp_context * v_context = z_context->next_context; | |
253 if (vdp_port < 0x10) { | 254 if (vdp_port < 0x10) { |
254 if (vdp_port < 4) { | 255 if (vdp_port < 4) { |
255 context->value = vdp_data_port_read(v_context); | 256 context->value = vdp_data_port_read(v_context); |
256 } else if(vdp_port < 8) { | 257 } else if(vdp_port < 8) { |
257 context->value = vdp_control_port_read(v_context); | 258 context->value = vdp_control_port_read(v_context); |
345 } | 346 } |
346 if (!(busack || reset)) { | 347 if (!(busack || reset)) { |
347 location &= 0x7FFF; | 348 location &= 0x7FFF; |
348 if (location < 0x4000) { | 349 if (location < 0x4000) { |
349 z80_ram[location & 0x1FFF] = value; | 350 z80_ram[location & 0x1FFF] = value; |
351 z80_handle_code_write(location & 0x1FFF, context->next_cpu); | |
350 } | 352 } |
351 } | 353 } |
352 } else { | 354 } else { |
353 location &= 0x1FFF; | 355 location &= 0x1FFF; |
354 if (location < 0x100) { | 356 if (location < 0x100) { |
381 busack_cycle = context->current_cycle + Z80_ACK_DELAY; | 383 busack_cycle = context->current_cycle + Z80_ACK_DELAY; |
382 new_busack = 0; | 384 new_busack = 0; |
383 } | 385 } |
384 } else { | 386 } else { |
385 if (busreq) { | 387 if (busreq) { |
386 z80_context * z_context = context->next_context; | 388 z80_context * z_context = context->next_cpu; |
387 //TODO: Add necessary delay between release of busreq and resumption of execution | 389 //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; | 390 z_context->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80; |
389 } | 391 } |
390 busreq = 0; | 392 busreq = 0; |
391 busack_cycle = CYCLE_NEVER; | 393 busack_cycle = CYCLE_NEVER; |
397 new_busack = 0; | 399 new_busack = 0; |
398 busack_cycle = context->current_cycle + Z80_ACK_DELAY; | 400 busack_cycle = context->current_cycle + Z80_ACK_DELAY; |
399 } | 401 } |
400 //TODO: Deal with the scenario in which reset is not asserted long enough | 402 //TODO: Deal with the scenario in which reset is not asserted long enough |
401 if (reset) { | 403 if (reset) { |
402 z80_context * z_context = context->next_context; | 404 z80_context * z_context = context->next_cpu; |
403 need_reset = 1; | 405 need_reset = 1; |
404 //TODO: Add necessary delay between release of reset and start of execution | 406 //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; | 407 z_context->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80; |
406 } | 408 } |
407 reset = 0; | 409 reset = 0; |
423 } | 425 } |
424 if (!(busack || reset)) { | 426 if (!(busack || reset)) { |
425 location &= 0x7FFF; | 427 location &= 0x7FFF; |
426 if (location < 0x4000) { | 428 if (location < 0x4000) { |
427 z80_ram[location & 0x1FFE] = value >> 8; | 429 z80_ram[location & 0x1FFE] = value >> 8; |
430 z80_handle_code_write(location & 0x1FFE, context->next_cpu); | |
428 } | 431 } |
429 } | 432 } |
430 } else { | 433 } else { |
431 location &= 0x1FFF; | 434 location &= 0x1FFF; |
432 if (location < 0x100) { | 435 if (location < 0x100) { |
460 busack_cycle = context->current_cycle + Z80_ACK_DELAY; | 463 busack_cycle = context->current_cycle + Z80_ACK_DELAY; |
461 new_busack = 0; | 464 new_busack = 0; |
462 } | 465 } |
463 } else { | 466 } else { |
464 if (busreq) { | 467 if (busreq) { |
465 z80_context * z_context = context->next_context; | 468 z80_context * z_context = context->next_cpu; |
466 //TODO: Add necessary delay between release of busreq and resumption of execution | 469 //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; | 470 z_context->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80; |
468 } | 471 } |
469 busreq = 0; | 472 busreq = 0; |
470 busack_cycle = CYCLE_NEVER; | 473 busack_cycle = CYCLE_NEVER; |
476 new_busack = 0; | 479 new_busack = 0; |
477 busack_cycle = context->current_cycle + Z80_ACK_DELAY; | 480 busack_cycle = context->current_cycle + Z80_ACK_DELAY; |
478 } | 481 } |
479 //TODO: Deal with the scenario in which reset is not asserted long enough | 482 //TODO: Deal with the scenario in which reset is not asserted long enough |
480 if (reset) { | 483 if (reset) { |
481 z80_context * z_context = context->next_context; | 484 z80_context * z_context = context->next_cpu; |
482 need_reset = 1; | 485 need_reset = 1; |
483 //TODO: Add necessary delay between release of reset and start of execution | 486 //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; | 487 z_context->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80; |
485 } | 488 } |
486 reset = 0; | 489 reset = 0; |
852 } | 855 } |
853 } | 856 } |
854 return context; | 857 return context; |
855 } | 858 } |
856 | 859 |
857 void init_run_cpu(z80_context * zcontext, int debug, FILE * address_log) | 860 void init_run_cpu(vdp_context * vcontext, z80_context * zcontext, int debug, FILE * address_log) |
858 { | 861 { |
859 m68k_context context; | 862 m68k_context context; |
860 x86_68k_options opts; | 863 x86_68k_options opts; |
861 init_x86_68k_opts(&opts); | 864 init_x86_68k_opts(&opts); |
862 opts.address_log = address_log; | 865 opts.address_log = address_log; |
863 init_68k_context(&context, opts.native_code_map, &opts); | 866 init_68k_context(&context, opts.native_code_map, &opts); |
864 | 867 |
865 context.next_context = zcontext; | 868 context.video_context = vcontext; |
869 context.next_cpu = zcontext; | |
866 //cartridge ROM | 870 //cartridge ROM |
867 context.mem_pointers[0] = cart; | 871 context.mem_pointers[0] = cart; |
868 context.target_cycle = context.sync_cycle = MCLKS_PER_FRAME/MCLKS_PER_68K; | 872 context.target_cycle = context.sync_cycle = MCLKS_PER_FRAME/MCLKS_PER_68K; |
869 //work RAM | 873 //work RAM |
870 context.mem_pointers[1] = ram; | 874 context.mem_pointers[1] = ram; |
936 z_context.mem_pointers[0] = z80_ram; | 940 z_context.mem_pointers[0] = z80_ram; |
937 z_context.sync_cycle = z_context.target_cycle = MCLKS_PER_FRAME/MCLKS_PER_Z80; | 941 z_context.sync_cycle = z_context.target_cycle = MCLKS_PER_FRAME/MCLKS_PER_Z80; |
938 z_context.int_cycle = CYCLE_NEVER; | 942 z_context.int_cycle = CYCLE_NEVER; |
939 z_context.mem_pointers[1] = z_context.mem_pointers[2] = (uint8_t *)cart; | 943 z_context.mem_pointers[1] = z_context.mem_pointers[2] = (uint8_t *)cart; |
940 | 944 |
941 init_run_cpu(&z_context, debug, address_log); | 945 init_run_cpu(&v_context, &z_context, debug, address_log); |
942 return 0; | 946 return 0; |
943 } | 947 } |