diff options
author | Mike Pavone <pavone@retrodev.com> | 2013-01-01 07:06:57 -0800 |
---|---|---|
committer | Mike Pavone <pavone@retrodev.com> | 2013-01-01 07:06:57 -0800 |
commit | 88d0d276444ed44b8dbfb29eebf14e87ebf0e403 (patch) | |
tree | f48c3962cd762f780c218224e7fd441d1687571b | |
parent | 4bf659a1272fdf8d1e4d8213aa584adf591dad76 (diff) |
Make writes to control and data port block when DMA is in progress
-rw-r--r-- | blastem.c | 27 | ||||
-rw-r--r-- | runtime.S | 3 | ||||
-rw-r--r-- | vdp.c | 17 | ||||
-rw-r--r-- | vdp.h | 2 |
4 files changed, 41 insertions, 8 deletions
@@ -115,11 +115,9 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ sync_components(context); vdp_context * v_context = context->next_context; if (vdp_port < 0x10) { + int blocked; if (vdp_port < 4) { - vdp_data_port_write(v_context, value); - } else if(vdp_port < 8) { - int blocked = vdp_control_port_write(v_context, value); - if (blocked) { + 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) { @@ -130,6 +128,27 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ } } context->current_cycle = v_context->cycles / MCLKS_PER_68K; + } + } else if(vdp_port < 8) { + blocked = vdp_control_port_write(v_context, value); + 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) { + wait_render_frame(v_context); + vdp_adjust_cycles(v_context, MCLKS_PER_FRAME); + io_adjust_cycles(&gamepad_1, v_context->cycles/MCLKS_PER_68K, MCLKS_PER_FRAME/MCLKS_PER_68K); + io_adjust_cycles(&gamepad_2, v_context->cycles/MCLKS_PER_68K, MCLKS_PER_FRAME/MCLKS_PER_68K); + } + } + if (blocked < 0) { + blocked = vdp_control_port_write(v_context, value); + } else { + blocked = 0; + } + } + context->current_cycle = v_context->cycles / MCLKS_PER_68K; } else { if (v_context->regs[REG_MODE_2] & 0x20 && ((context->status & 0x7) < 6)) { if (context->int_cycle > VINT_CYCLE) { @@ -209,6 +209,9 @@ try_fifo_write: push %rbx /* fetch VDP context pointer from 68K context */ mov 128(%rsi), %rdx + /* check DMA flag */ + bt $6, 19(%rdx) + jc fifo_fallback /* get fifo_cur and compare it to fifo_end */ mov (%rdx), %rbx cmp %rbx, 8(%rdx) @@ -184,7 +184,7 @@ void external_slot(vdp_context * context) //TODO: Figure out what happens if CD bit 4 is not set in DMA copy mode //TODO: Figure out what happens when CD:0-3 is not set to a write mode in DMA operations //TODO: Figure out what happens if DMA gets disabled part way through a DMA fill or DMA copy - if((context->regs[REG_MODE_2] & BIT_DMA_ENABLE) && (context->flags & FLAG_DMA_RUN)) { + if(context->flags & FLAG_DMA_RUN) { uint16_t dma_len; switch(context->regs[REG_DMASRC_H] & 0xC0) { @@ -1022,6 +1022,9 @@ void vdp_run_dma_done(vdp_context * context, uint32_t target_cycles) int vdp_control_port_write(vdp_context * context, uint16_t value) { //printf("control port write: %X\n", value); + if (context->flags & FLAG_DMA_RUN) { + return -1; + } if (context->flags & FLAG_PENDING) { context->address = (context->address & 0x3FFF) | (value << 14); context->cd = (context->cd & 0x3) | ((value >> 2) & 0x3C); @@ -1057,9 +1060,16 @@ int vdp_control_port_write(vdp_context * context, uint16_t value) return 0; } -void vdp_data_port_write(vdp_context * context, uint16_t value) +int vdp_data_port_write(vdp_context * context, uint16_t value) { //printf("data port write: %X\n", value); + if (context->flags & FLAG_DMA_RUN) { + return -1; + } + if (!(context->cd & 1)) { + //ignore writes when cd is configured for read + return 0; + } context->flags &= ~FLAG_PENDING; /*if (context->fifo_cur == context->fifo_end) { printf("FIFO full, waiting for space before next write at cycle %X\n", context->cycles); @@ -1074,6 +1084,7 @@ void vdp_data_port_write(vdp_context * context, uint16_t value) context->fifo_cur->partial = 0; context->fifo_cur++; context->address += context->regs[REG_AUTOINC]; + return 0; } uint16_t vdp_control_port_read(vdp_context * context) @@ -1086,7 +1097,7 @@ uint16_t vdp_control_port_read(vdp_context * context) if (context->fifo_cur == context->fifo_end) { value |= 0x100; } - if ((context->regs[REG_MODE_2] & BIT_DMA_ENABLE) && (context->flags & FLAG_DMA_RUN)) { + if (context->flags & FLAG_DMA_RUN) { value |= 0x2; } uint32_t line= context->cycles / MCLKS_LINE; @@ -126,7 +126,7 @@ void vdp_run_dma_done(vdp_context * context, uint32_t target_cycles); void vdp_load_savestate(vdp_context * context, FILE * state_file); void vdp_save_state(vdp_context * context, FILE * outfile); int vdp_control_port_write(vdp_context * context, uint16_t value); -void vdp_data_port_write(vdp_context * context, uint16_t value); +int vdp_data_port_write(vdp_context * context, uint16_t value); uint16_t vdp_control_port_read(vdp_context * context); uint16_t vdp_data_port_read(vdp_context * context); uint16_t vdp_hv_counter_read(vdp_context * context); |