summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--blastem.c27
-rw-r--r--runtime.S3
-rw-r--r--vdp.c17
-rw-r--r--vdp.h2
4 files changed, 41 insertions, 8 deletions
diff --git a/blastem.c b/blastem.c
index b0e9e27..7d20095 100644
--- a/blastem.c
+++ b/blastem.c
@@ -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) {
diff --git a/runtime.S b/runtime.S
index ae78bd7..43295d2 100644
--- a/runtime.S
+++ b/runtime.S
@@ -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)
diff --git a/vdp.c b/vdp.c
index f6176a5..7bfcdce 100644
--- a/vdp.c
+++ b/vdp.c
@@ -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;
diff --git a/vdp.h b/vdp.h
index b3d5e17..6d6036e 100644
--- a/vdp.h
+++ b/vdp.h
@@ -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);