From fda7339b94e33bed3fee4f48bc5286f27f9eb19b Mon Sep 17 00:00:00 2001 From: kub Date: Tue, 7 Dec 2021 23:59:53 +0100 Subject: [PATCH] core vdp, fix FIFO DMA wait, improve save/load --- pico/videoport.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/pico/videoport.c b/pico/videoport.c index 44a02fbb..a029a15e 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -179,11 +179,11 @@ int (*PicoDmaHook)(u32 source, int len, unsigned short **base, u32 *mask) = NULL // NB code assumes fifo_* arrays have size 2^n static struct VdpFIFO { // XXX this must go into save file! // last transferred FIFO data, ...x = index XXX currently only CPU - unsigned short fifo_data[4], fifo_dx; + u16 fifo_data[4], fifo_dx; // queued FIFO transfers, ...x = index, ...l = queue length // each entry has 2 values: [n]>>3 = #writes, [n]&7 = flags (FQ_*) - unsigned int fifo_queue[8], fifo_qx, fifo_ql; + u32 fifo_queue[8], fifo_qx, fifo_ql; int fifo_total; // total# of pending FIFO entries (w/o BGDMA) unsigned short fifo_slot; // last executed slot in current scanline @@ -212,7 +212,6 @@ static __inline int AdvanceFIFOEntry(struct VdpFIFO *vf, struct PicoVideo *pv, i l = cnt; if (!(vf->fifo_queue[vf->fifo_qx] & FQ_BGDMA)) vf->fifo_total -= ((cnt & b) + l) >> b; - if (vf->fifo_total < 0) vf->fifo_total = 0; cnt -= l; // if entry has been processed... @@ -238,7 +237,7 @@ static __inline int AdvanceFIFOEntry(struct VdpFIFO *vf, struct PicoVideo *pv, i static __inline void SetFIFOState(struct VdpFIFO *vf, struct PicoVideo *pv) { - unsigned int st = pv->status, cmd = pv->command; + u32 st = pv->status, cmd = pv->command; // release CPU and terminate DMA if FIFO isn't blocking the 68k anymore if (vf->fifo_total <= 4) { st &= ~PVS_CPUWR; @@ -287,28 +286,29 @@ static int PicoVideoFIFODrain(int level, int cycles, int bgdma) struct VdpFIFO *vf = &VdpFIFO; struct PicoVideo *pv = &Pico.video; unsigned ocyc = cycles; + int bd = vf->fifo_queue[vf->fifo_qx] & bgdma; int burn = 0; // process FIFO entries until low level is reached - while (vf->fifo_slot <= vf->fifo_maxslot && cycles < 488 && - ((vf->fifo_total > level) | (vf->fifo_queue[vf->fifo_qx] & bgdma))) { + while (vf->fifo_slot < vf->fifo_maxslot && + vf->fifo_ql && ((vf->fifo_total > level) | bd)) { int b = vf->fifo_queue[vf->fifo_qx] & FQ_BYTE; - int cnt = bgdma ? pv->fifo_cnt : ((vf->fifo_total-level)<fifo_cnt&b); + int cnt = bd ? pv->fifo_cnt : ((vf->fifo_total-level)<fifo_cnt&b); int slot = (pv->fifo_cntfifo_cnt:cnt) + vf->fifo_slot; if (slot > vf->fifo_maxslot) { // target slot in later scanline, advance to eol slot = vf->fifo_maxslot; - cycles = 488; - } else { - // advance FIFO to target slot and CPU to cycles at that slot - cycles = Sl2Cyc(vf, slot); } if (slot > vf->fifo_slot) { - AdvanceFIFOEntry(vf, pv, slot - vf->fifo_slot); - vf->fifo_slot = slot; + // advance FIFO to target slot and CPU to cycles at that slot + vf->fifo_slot += AdvanceFIFOEntry(vf, pv, slot - vf->fifo_slot); + cycles = Sl2Cyc(vf, vf->fifo_slot); + bd = vf->fifo_queue[vf->fifo_qx] & bgdma; } } + if (vf->fifo_ql && ((vf->fifo_total > level) | bd)) + cycles = 488; // not completed in this scanline if (cycles > ocyc) burn = cycles - ocyc; @@ -911,6 +911,7 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d) if (num == 12 && ((pvid->reg[12]^d)&0x01)) PicoVideoFIFOMode(pvid->reg[1]&0x40, d & 1); DrawSync(SekCyclesDone() - Pico.t.m68c_line_start <= 488-390); + d &= 0xff; pvid->reg[num]=(unsigned char)d; switch (num) { @@ -1146,14 +1147,24 @@ void PicoVideoLoad(void) { struct VdpFIFO *vf = &VdpFIFO; struct PicoVideo *pv = &Pico.video; + int b = pv->type == 1; // convert former dma_xfers (why was this in PicoMisc anyway?) if (Pico.m.dma_xfers) { - pv->status |= SR_DMA|PVS_FIFORUN; - pv->fifo_cnt = Pico.m.dma_xfers * (pv->type == 1 ? 2 : 1); - vf->fifo_total = Pico.m.dma_xfers; + pv->status |= SR_DMA; + pv->fifo_cnt = Pico.m.dma_xfers * (b ? 2 : 1); Pico.m.dma_xfers = 0; } + // make an entry in the FIFO if there are outstanding transfers + vf->fifo_ql = vf->fifo_total = 0; + if (pv->fifo_cnt) { + pv->status |= PVS_FIFORUN|PVS_CPUWR; + vf->fifo_total = (pv->fifo_cnt + (b)) >> b; + if (pv->status & SR_DMA) + b |= (pv->status & (PVS_DMAFILL|PVS_DMABG)) ? FQ_BGDMA : FQ_FGDMA; + vf->fifo_queue[vf->fifo_qx] = (vf->fifo_total << 3) | b; + vf->fifo_ql = 1; + } PicoVideoCacheSAT(); } // vim:shiftwidth=2:ts=2:expandtab -- 2.39.2