extern const unsigned char hcounts_32[];\r
extern const unsigned char hcounts_40[];\r
\r
-static unsigned hvlatch; // latched hvcounter value\r
static int blankline; // display disabled for this line\r
\r
int (*PicoDmaHook)(unsigned int source, int len, unsigned short **base, unsigned int *mask) = NULL;\r
14,14,14,14,14,14,14,14,15,16,16,16,16,16,16,16,\r
};\r
const unsigned char vdpsl2cyc_32[] = { // slot # to 68k cycles/4 since HINT\r
- 0, 9, 19, 30, 35, 41, 52, 58, 64, 75, 81, 87, 98,104,110,120,121,123,123\r
+ 0, 9, 19, 30, 35, 41, 52, 58, 64, 75, 81, 87, 98,104,110,120,121,123\r
};\r
\r
// VDP transfer slots in active display 40col mode. 1 slot is 488/210 = 2.3238\r
16,16,16,16,16,16,16,16,17,18,18,18,18,18,18,18,\r
};\r
const unsigned char vdpsl2cyc_40[] = { // slot # to 68k cycles/4 since HINT\r
- 0, 13, 28, 33, 37, 47, 51, 56, 65, 70, 74, 84, 88, 93,102,107,112,120,121,123,123\r
+ 0, 13, 28, 33, 37, 47, 51, 56, 65, 70, 74, 84, 88, 93,102,107,112,120,121,123\r
};\r
\r
// NB code assumes fifo_* arrays have size 2^n\r
// last transferred FIFO data, ...x = index XXX currently only CPU\r
-static short fifo_data[4], fifo_dx;\r
+static short fifo_data[4], fifo_dx; // XXX must go into save?\r
+\r
// queued FIFO transfers, ...x = index, ...l = queue length\r
// each entry has 2 values: [n]>>2=#writes, [n]&3=flags:2=DMA fill 1=byte access\r
-static int fifo_queue[8], fifo_qx, fifo_ql;\r
+static int fifo_queue[8], fifo_qx, fifo_ql; // XXX must go into save?\r
+unsigned int fifo_total; // total# of pending FIFO entries\r
\r
-signed int fifo_cnt; // pending slots for current queue entry\r
unsigned short fifo_slot; // last executed slot in current scanline\r
-unsigned int fifo_total; // total# of pending FIFO entries\r
\r
// do the FIFO math\r
-static __inline int AdvanceFIFOEntry(int slots)\r
+static __inline int AdvanceFIFOEntry(struct PicoVideo *pv, int slots)\r
{\r
int l = slots, b = fifo_queue[fifo_qx&7] & 1;\r
\r
- if (l > fifo_cnt)\r
- l = fifo_cnt;\r
- fifo_total -= ((fifo_cnt & b) + l) >> b;\r
- fifo_cnt -= l;\r
+ if (l > pv->fifo_cnt)\r
+ l = pv->fifo_cnt;\r
+ fifo_total -= ((pv->fifo_cnt & b) + l) >> b;\r
+ pv->fifo_cnt -= l;\r
\r
- if (fifo_cnt == 0) {\r
- fifo_qx ++, fifo_ql --;\r
- fifo_cnt= (fifo_queue[fifo_qx&7] >> 2) << (fifo_queue[fifo_qx&7] & 1);\r
+ if (pv->fifo_cnt == 0) {\r
+ if (fifo_ql)\r
+ fifo_qx ++, fifo_ql --;\r
+ if (fifo_ql)\r
+ pv->fifo_cnt= (fifo_queue[fifo_qx&7] >> 2) << (fifo_queue[fifo_qx&7] & 1);\r
+ else\r
+ fifo_total = 0;\r
}\r
return l;\r
}\r
else return (cycles * vdpcyc2sl_bl[h40] + cycles) >> 16;\r
}\r
\r
-static inline int GetFIFOCycles(struct PicoVideo *pv, int slot)\r
+static __inline int GetFIFOCycles(struct PicoVideo *pv, int slot)\r
{\r
int active = !(pv->status & SR_VB) && (pv->reg[1] & 0x40);\r
int h40 = pv->reg[12] & 1;\r
int slots, done;\r
\r
// calculate #slots since last executed slot\r
- slots = GetFIFOSlot(pv, cycles);\r
- slots -= fifo_slot;\r
+ slots = GetFIFOSlot(pv, cycles) - fifo_slot;\r
\r
// advance FIFO queue by #done slots\r
done = slots;\r
- while (done > 0 && fifo_ql) {\r
- int l = AdvanceFIFOEntry(done);\r
+ while (done > 0 && pv->fifo_cnt) {\r
+ int l = AdvanceFIFOEntry(pv, done);\r
fifo_slot += l;\r
done -= l;\r
}\r
int b = fifo_queue[fifo_qx&7] & 1;\r
int cnt = (fifo_total-level) << b;\r
int last = fifo_slot;\r
- int slot = (fifo_cnt<cnt?fifo_cnt:cnt) + last; // target slot\r
+ int slot = (pv->fifo_cnt<cnt?pv->fifo_cnt:cnt) + last; // target slot\r
unsigned ocyc = cycles;\r
\r
if (slot > maxsl) {\r
}\r
burn += cycles - ocyc;\r
\r
- AdvanceFIFOEntry(slot - last);\r
+ AdvanceFIFOEntry(pv, slot - last);\r
}\r
\r
// release CPU and terminate DMA if FIFO isn't blocking the bus anymore\r
// update FIFO state if it was empty\r
if (fifo_total == 0 && count) {\r
fifo_slot = GetFIFOSlot(pv, lc);\r
- fifo_cnt = count << (flags&1);\r
+ pv->fifo_cnt = count << (flags&1);\r
}\r
\r
// create xfer queue entry\r
if ((pv->status & (PVS_CPUWR|PVS_DMAFILL)) == PVS_CPUWR)\r
burn = PicoVideoFIFODrain(4, lc);\r
else if (fifo_queue[fifo_qx&7]&2) {\r
- // if interrupting a DMA fill terminate it\r
- AdvanceFIFOEntry(fifo_cnt);\r
+ // if interrupting a DMA fill terminate it XXX wrong, changes fill data\r
+ AdvanceFIFOEntry(pv, pv->fifo_cnt);\r
pv->status &= ~PVS_DMAFILL;\r
}\r
\r
// try avoiding the sync..\r
if (Pico.m.scanline < (pvid->reg[1]&0x08 ? 240 : 224) && (pvid->reg[1]&0x40) &&\r
!(!pvid->pending &&\r
- ((pvid->command & 0xc00000f0) == 0x40000010 && PicoMem.vsram[pvid->addr>>1] == d))\r
+ ((pvid->command & 0xc00000f0) == 0x40000010 && PicoMem.vsram[pvid->addr>>1] == (d & 0x7ff)))\r
)\r
- DrawSync(0);\r
+ DrawSync(SekCyclesDone() - Pico.t.m68c_line_start <= 488-440);\r
\r
if (pvid->pending) {\r
CommandChange();\r
CommandChange();\r
// Check for dma:\r
if (d & 0x80) {\r
- DrawSync(0);\r
+ DrawSync(SekCyclesDone() - Pico.t.m68c_line_start <= 488-390);\r
CommandDma();\r
}\r
}\r
// Register write:\r
int num=(d>>8)&0x1f;\r
int dold=pvid->reg[num];\r
- int skip=0;\r
pvid->type=0; // register writes clear command (else no Sega logo in Golden Axe II)\r
if (num > 0x0a && !(pvid->reg[1]&4)) {\r
elprintf(EL_ANOMALY, "%02x written to reg %02x in SMS mode @ %06x", d, num, SekPc);\r
}\r
\r
if (num == 0 && !(pvid->reg[0]&2) && (d&2))\r
- hvlatch = PicoVideoRead(0x08);\r
+ pvid->hv_latch = PicoVideoRead(0x08);\r
if (num == 1 && ((pvid->reg[1]^d)&0x40)) {\r
PicoVideoFIFOMode(d & 0x40);\r
// handle line blanking before line rendering\r
- if (SekCyclesDone() - Pico.t.m68c_line_start <= 488-390) {\r
- skip = 1;\r
+ if (SekCyclesDone() - Pico.t.m68c_line_start <= 488-390)\r
blankline = d&0x40 ? -1 : Pico.m.scanline;\r
- }\r
}\r
- DrawSync(skip);\r
+ DrawSync(SekCyclesDone() - Pico.t.m68c_line_start <= 488-390);\r
pvid->reg[num]=(unsigned char)d;\r
switch (num)\r
{\r
\r
d = (SekCyclesDone() - Pico.t.m68c_line_start) & 0x1ff; // FIXME\r
if (Pico.video.reg[0]&2)\r
- d = hvlatch;\r
+ d = Pico.video.hv_latch;\r
else if (Pico.video.reg[12]&1)\r
d = hcounts_40[d] | (Pico.video.v_counter << 8);\r
else d = hcounts_32[d] | (Pico.video.v_counter << 8);\r
return d;\r
}\r
\r
+void PicoVideoSave(void)\r
+{\r
+ struct PicoVideo *pv = &Pico.video;\r
+ int l, x;\r
+\r
+ // account for all outstanding xfers XXX kludge, entry attr's not saved\r
+ for (l = fifo_ql, x = fifo_qx + l-1; l > 1; l--, x--)\r
+ pv->fifo_cnt += (fifo_queue[x&7] >> 2) << (fifo_queue[x&7] & 1);\r
+}\r
+\r
+void PicoVideoLoad(void)\r
+{\r
+ struct PicoVideo *pv = &Pico.video;\r
+ int l;\r
+\r
+ // convert former dma_xfers (why was this in PicoMisc anyway?)\r
+ if (Pico.m.dma_xfers) {\r
+ pv->fifo_cnt = Pico.m.dma_xfers * (pv->type == 1 ? 2 : 1);\r
+ fifo_total = Pico.m.dma_xfers;\r
+ Pico.m.dma_xfers = 0;\r
+ }\r
+\r
+ // rebuild SAT cache XXX wrong since cache and memory can differ\r
+ for (l = 0; l < 80; l++) {\r
+ *((u16 *)VdpSATCache + 2*l ) = PicoMem.vram[(sat>>1) + l*4 ];\r
+ *((u16 *)VdpSATCache + 2*l+1) = PicoMem.vram[(sat>>1) + l*4 + 1];\r
+ }\r
+}\r
+\r
// vim:shiftwidth=2:ts=2:expandtab\r