mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00
core vdp, fix FIFO DMA wait, improve save/load
This commit is contained in:
parent
d650a7a268
commit
fda7339b94
1 changed files with 27 additions and 16 deletions
|
@ -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
|
// NB code assumes fifo_* arrays have size 2^n
|
||||||
static struct VdpFIFO { // XXX this must go into save file!
|
static struct VdpFIFO { // XXX this must go into save file!
|
||||||
// last transferred FIFO data, ...x = index XXX currently only CPU
|
// 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
|
// queued FIFO transfers, ...x = index, ...l = queue length
|
||||||
// each entry has 2 values: [n]>>3 = #writes, [n]&7 = flags (FQ_*)
|
// 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)
|
int fifo_total; // total# of pending FIFO entries (w/o BGDMA)
|
||||||
|
|
||||||
unsigned short fifo_slot; // last executed slot in current scanline
|
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;
|
l = cnt;
|
||||||
if (!(vf->fifo_queue[vf->fifo_qx] & FQ_BGDMA))
|
if (!(vf->fifo_queue[vf->fifo_qx] & FQ_BGDMA))
|
||||||
vf->fifo_total -= ((cnt & b) + l) >> b;
|
vf->fifo_total -= ((cnt & b) + l) >> b;
|
||||||
if (vf->fifo_total < 0) vf->fifo_total = 0;
|
|
||||||
cnt -= l;
|
cnt -= l;
|
||||||
|
|
||||||
// if entry has been processed...
|
// 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)
|
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
|
// release CPU and terminate DMA if FIFO isn't blocking the 68k anymore
|
||||||
if (vf->fifo_total <= 4) {
|
if (vf->fifo_total <= 4) {
|
||||||
st &= ~PVS_CPUWR;
|
st &= ~PVS_CPUWR;
|
||||||
|
@ -287,28 +286,29 @@ static int PicoVideoFIFODrain(int level, int cycles, int bgdma)
|
||||||
struct VdpFIFO *vf = &VdpFIFO;
|
struct VdpFIFO *vf = &VdpFIFO;
|
||||||
struct PicoVideo *pv = &Pico.video;
|
struct PicoVideo *pv = &Pico.video;
|
||||||
unsigned ocyc = cycles;
|
unsigned ocyc = cycles;
|
||||||
|
int bd = vf->fifo_queue[vf->fifo_qx] & bgdma;
|
||||||
int burn = 0;
|
int burn = 0;
|
||||||
|
|
||||||
// process FIFO entries until low level is reached
|
// process FIFO entries until low level is reached
|
||||||
while (vf->fifo_slot <= vf->fifo_maxslot && cycles < 488 &&
|
while (vf->fifo_slot < vf->fifo_maxslot &&
|
||||||
((vf->fifo_total > level) | (vf->fifo_queue[vf->fifo_qx] & bgdma))) {
|
vf->fifo_ql && ((vf->fifo_total > level) | bd)) {
|
||||||
int b = vf->fifo_queue[vf->fifo_qx] & FQ_BYTE;
|
int b = vf->fifo_queue[vf->fifo_qx] & FQ_BYTE;
|
||||||
int cnt = bgdma ? pv->fifo_cnt : ((vf->fifo_total-level)<<b) - (pv->fifo_cnt&b);
|
int cnt = bd ? pv->fifo_cnt : ((vf->fifo_total-level)<<b) - (pv->fifo_cnt&b);
|
||||||
int slot = (pv->fifo_cnt<cnt ? pv->fifo_cnt:cnt) + vf->fifo_slot;
|
int slot = (pv->fifo_cnt<cnt ? pv->fifo_cnt:cnt) + vf->fifo_slot;
|
||||||
|
|
||||||
if (slot > vf->fifo_maxslot) {
|
if (slot > vf->fifo_maxslot) {
|
||||||
// target slot in later scanline, advance to eol
|
// target slot in later scanline, advance to eol
|
||||||
slot = vf->fifo_maxslot;
|
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) {
|
if (slot > vf->fifo_slot) {
|
||||||
AdvanceFIFOEntry(vf, pv, slot - vf->fifo_slot);
|
// advance FIFO to target slot and CPU to cycles at that slot
|
||||||
vf->fifo_slot = 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)
|
if (cycles > ocyc)
|
||||||
burn = 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))
|
if (num == 12 && ((pvid->reg[12]^d)&0x01))
|
||||||
PicoVideoFIFOMode(pvid->reg[1]&0x40, d & 1);
|
PicoVideoFIFOMode(pvid->reg[1]&0x40, d & 1);
|
||||||
DrawSync(SekCyclesDone() - Pico.t.m68c_line_start <= 488-390);
|
DrawSync(SekCyclesDone() - Pico.t.m68c_line_start <= 488-390);
|
||||||
|
d &= 0xff;
|
||||||
pvid->reg[num]=(unsigned char)d;
|
pvid->reg[num]=(unsigned char)d;
|
||||||
switch (num)
|
switch (num)
|
||||||
{
|
{
|
||||||
|
@ -1146,14 +1147,24 @@ void PicoVideoLoad(void)
|
||||||
{
|
{
|
||||||
struct VdpFIFO *vf = &VdpFIFO;
|
struct VdpFIFO *vf = &VdpFIFO;
|
||||||
struct PicoVideo *pv = &Pico.video;
|
struct PicoVideo *pv = &Pico.video;
|
||||||
|
int b = pv->type == 1;
|
||||||
|
|
||||||
// convert former dma_xfers (why was this in PicoMisc anyway?)
|
// convert former dma_xfers (why was this in PicoMisc anyway?)
|
||||||
if (Pico.m.dma_xfers) {
|
if (Pico.m.dma_xfers) {
|
||||||
pv->status |= SR_DMA|PVS_FIFORUN;
|
pv->status |= SR_DMA;
|
||||||
pv->fifo_cnt = Pico.m.dma_xfers * (pv->type == 1 ? 2 : 1);
|
pv->fifo_cnt = Pico.m.dma_xfers * (b ? 2 : 1);
|
||||||
vf->fifo_total = Pico.m.dma_xfers;
|
|
||||||
Pico.m.dma_xfers = 0;
|
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();
|
PicoVideoCacheSAT();
|
||||||
}
|
}
|
||||||
// vim:shiftwidth=2:ts=2:expandtab
|
// vim:shiftwidth=2:ts=2:expandtab
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue