// NB code assumes fifo_* arrays have size 2^n\r
static struct VdpFIFO { // XXX this must go into save file!\r
// last transferred FIFO data, ...x = index XXX currently only CPU\r
- unsigned short fifo_data[4], fifo_dx;\r
+ u16 fifo_data[4], fifo_dx;\r
\r
// queued FIFO transfers, ...x = index, ...l = queue length\r
// each entry has 2 values: [n]>>3 = #writes, [n]&7 = flags (FQ_*)\r
- unsigned int fifo_queue[8], fifo_qx, fifo_ql;\r
+ u32 fifo_queue[8], fifo_qx, fifo_ql;\r
int fifo_total; // total# of pending FIFO entries (w/o BGDMA)\r
\r
unsigned short fifo_slot; // last executed slot in current scanline\r
l = cnt;\r
if (!(vf->fifo_queue[vf->fifo_qx] & FQ_BGDMA))\r
vf->fifo_total -= ((cnt & b) + l) >> b;\r
- if (vf->fifo_total < 0) vf->fifo_total = 0;\r
cnt -= l;\r
\r
// if entry has been processed...\r
\r
static __inline void SetFIFOState(struct VdpFIFO *vf, struct PicoVideo *pv)\r
{\r
- unsigned int st = pv->status, cmd = pv->command;\r
+ u32 st = pv->status, cmd = pv->command;\r
// release CPU and terminate DMA if FIFO isn't blocking the 68k anymore\r
if (vf->fifo_total <= 4) {\r
st &= ~PVS_CPUWR;\r
struct VdpFIFO *vf = &VdpFIFO;\r
struct PicoVideo *pv = &Pico.video;\r
unsigned ocyc = cycles;\r
+ int bd = vf->fifo_queue[vf->fifo_qx] & bgdma;\r
int burn = 0;\r
\r
// process FIFO entries until low level is reached\r
- while (vf->fifo_slot <= vf->fifo_maxslot && cycles < 488 &&\r
- ((vf->fifo_total > level) | (vf->fifo_queue[vf->fifo_qx] & bgdma))) {\r
+ while (vf->fifo_slot < vf->fifo_maxslot &&\r
+ vf->fifo_ql && ((vf->fifo_total > level) | bd)) {\r
int b = vf->fifo_queue[vf->fifo_qx] & FQ_BYTE;\r
- int cnt = bgdma ? pv->fifo_cnt : ((vf->fifo_total-level)<<b) - (pv->fifo_cnt&b);\r
+ int cnt = bd ? pv->fifo_cnt : ((vf->fifo_total-level)<<b) - (pv->fifo_cnt&b);\r
int slot = (pv->fifo_cnt<cnt ? pv->fifo_cnt:cnt) + vf->fifo_slot;\r
\r
if (slot > vf->fifo_maxslot) {\r
// target slot in later scanline, advance to eol\r
slot = vf->fifo_maxslot;\r
- cycles = 488;\r
- } else {\r
- // advance FIFO to target slot and CPU to cycles at that slot\r
- cycles = Sl2Cyc(vf, slot);\r
}\r
if (slot > vf->fifo_slot) {\r
- AdvanceFIFOEntry(vf, pv, slot - vf->fifo_slot);\r
- vf->fifo_slot = slot;\r
+ // advance FIFO to target slot and CPU to cycles at that slot\r
+ vf->fifo_slot += AdvanceFIFOEntry(vf, pv, slot - vf->fifo_slot);\r
+ cycles = Sl2Cyc(vf, vf->fifo_slot);\r
+ bd = vf->fifo_queue[vf->fifo_qx] & bgdma;\r
}\r
}\r
+ if (vf->fifo_ql && ((vf->fifo_total > level) | bd))\r
+ cycles = 488; // not completed in this scanline\r
if (cycles > ocyc)\r
burn = cycles - ocyc;\r
\r
if (num == 12 && ((pvid->reg[12]^d)&0x01))\r
PicoVideoFIFOMode(pvid->reg[1]&0x40, d & 1);\r
DrawSync(SekCyclesDone() - Pico.t.m68c_line_start <= 488-390);\r
+ d &= 0xff;\r
pvid->reg[num]=(unsigned char)d;\r
switch (num)\r
{\r
{\r
struct VdpFIFO *vf = &VdpFIFO;\r
struct PicoVideo *pv = &Pico.video;\r
+ int b = pv->type == 1;\r
\r
// convert former dma_xfers (why was this in PicoMisc anyway?)\r
if (Pico.m.dma_xfers) {\r
- pv->status |= SR_DMA|PVS_FIFORUN;\r
- pv->fifo_cnt = Pico.m.dma_xfers * (pv->type == 1 ? 2 : 1);\r
- vf->fifo_total = Pico.m.dma_xfers;\r
+ pv->status |= SR_DMA;\r
+ pv->fifo_cnt = Pico.m.dma_xfers * (b ? 2 : 1);\r
Pico.m.dma_xfers = 0;\r
}\r
+ // make an entry in the FIFO if there are outstanding transfers\r
+ vf->fifo_ql = vf->fifo_total = 0;\r
+ if (pv->fifo_cnt) {\r
+ pv->status |= PVS_FIFORUN|PVS_CPUWR;\r
+ vf->fifo_total = (pv->fifo_cnt + (b)) >> b;\r
+ if (pv->status & SR_DMA)\r
+ b |= (pv->status & (PVS_DMAFILL|PVS_DMABG)) ? FQ_BGDMA : FQ_FGDMA;\r
+ vf->fifo_queue[vf->fifo_qx] = (vf->fifo_total << 3) | b;\r
+ vf->fifo_ql = 1;\r
+ }\r
PicoVideoCacheSAT();\r
}\r
// vim:shiftwidth=2:ts=2:expandtab\r