# HG changeset patch # User Michael Pavone # Date 1461533415 25200 # Node ID bd4d698d995bae116c4c5f11937dd3cbc1f082b1 # Parent 14d2f3b0e45da7079a36cc0fe58fc8e9d4402262 FIFO should show as empty during a DMA fill after the initial write is done. BlastEm now gets a perfect score in VDP FIFO Testing diff -r 14d2f3b0e45d -r bd4d698d995b vdp.c --- a/vdp.c Sun Apr 24 11:53:59 2016 -0700 +++ b/vdp.c Sun Apr 24 14:30:15 2016 -0700 @@ -487,8 +487,32 @@ #define VSRAM_BITS 0x7FF #define VSRAM_DIRTY_BITS 0xF800 +void vdp_advance_dma(vdp_context * context) +{ + context->regs[REG_DMASRC_L] += 1; + if (!context->regs[REG_DMASRC_L]) { + context->regs[REG_DMASRC_M] += 1; + } + context->address += context->regs[REG_AUTOINC]; + uint16_t dma_len = ((context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L]) - 1; + context->regs[REG_DMALEN_H] = dma_len >> 8; + context->regs[REG_DMALEN_L] = dma_len; + if (!dma_len) { + context->flags &= ~FLAG_DMA_RUN; + context->cd &= 0xF; + } +} + void external_slot(vdp_context * context) { + if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80 && context->fifo_read < 0) { + context->fifo_read = (context->fifo_write-1) & (FIFO_SIZE-1); + fifo_entry * cur = context->fifo + context->fifo_read; + cur->cycle = context->cycles; + cur->address = context->address; + cur->partial = 2; + vdp_advance_dma(context); + } fifo_entry * start = context->fifo + context->fifo_read; if (context->fifo_read >= 0 && start->cycle <= context->cycles) { switch (start->cd & 0xF) @@ -530,18 +554,7 @@ context->vdpmem[context->address ^ 1] = context->prefetch; //Update DMA state - context->regs[REG_DMASRC_L] += 1; - if (!context->regs[REG_DMASRC_L]) { - context->regs[REG_DMASRC_M] += 1; - } - context->address += context->regs[REG_AUTOINC]; - uint16_t dma_len = ((context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L]) - 1; - context->regs[REG_DMALEN_H] = dma_len >> 8; - context->regs[REG_DMALEN_L] = dma_len; - if (!dma_len) { - context->flags &= ~FLAG_DMA_RUN; - context->cd &= 0xF; - } + vdp_advance_dma(context); context->flags &= ~FLAG_READ_FETCHED; } else { @@ -598,16 +611,13 @@ { //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->fifo_write == context->fifo_read) { return; } fifo_entry * cur = NULL; - switch(context->regs[REG_DMASRC_H] & 0xC0) + if (!(context->regs[REG_DMASRC_H] & 0x80)) { - //68K -> VDP - case 0: - case 0x40: + //68K -> VDP if (slot == -1 || !is_refresh(context, slot-1)) { cur = context->fifo + context->fifo_write; cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY; @@ -619,33 +629,7 @@ context->fifo_read = context->fifo_write; } context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1); - } - break; - //Fill - case 0x80: - if (context->fifo_read < 0) { - context->fifo_read = (context->fifo_write-1) & (FIFO_SIZE-1); - cur = context->fifo + context->fifo_read; - cur->cycle = context->cycles; - cur->address = context->address; - cur->partial = 2; - } - break; - } - - if (cur) { - context->regs[REG_DMASRC_L] += 1; - if (!context->regs[REG_DMASRC_L]) { - context->regs[REG_DMASRC_M] += 1; - } - context->address += context->regs[REG_AUTOINC]; - uint16_t dma_len = ((context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L]) - 1; - context->regs[REG_DMALEN_H] = dma_len >> 8; - context->regs[REG_DMALEN_L] = dma_len; - if (!dma_len) { - //printf("DMA end at cycle %d, frame: %d, vcounter: %d, hslot: %d\n", context->cycles, context->frame, context->vcounter, context->hslot); - context->flags &= ~FLAG_DMA_RUN; - context->cd &= 0xF; + vdp_advance_dma(context); } } }