\r
// --------------------------------------------\r
\r
-void PicoDoHighPal555_8bit(int sh, int line, struct PicoEState *est)\r
+static u16 *BgcDMAbase;\r
+static u32 BgcDMAsrc, BgcDMAmask;\r
+static int BgcDMAlen, BgcDMAoffs;\r
+\r
+#ifndef _ASM_DRAW_C\r
+static\r
+#endif\r
+// handle DMA to background color\r
+int BgcDMA(u16 *pd, int len, struct PicoEState *est)\r
+{\r
+ int xl = (len == 320 ? 38 : 33); // DMA slots during HSYNC\r
+ int upscale = (est->rendstatus & PDRAW_SOFTSCALE) && len < 320;\r
+\r
+ if (BgcDMAlen > 0) {\r
+ // BG color DMA under way. TODO for now handles the line as all background.\r
+ int i, l = len;\r
+ u16 *q = upscale ? DefOutBuff : pd;\r
+ u16 t;\r
+\r
+ if ((est->rendstatus & PDRAW_BORDER_32) && !upscale)\r
+ q += (320-len) / 2;\r
+\r
+ BgcDMAlen -= (l>>1)+xl;\r
+ if (BgcDMAlen < 0)\r
+ // partial line\r
+ l += 2*BgcDMAlen;\r
+\r
+ for (i = 0; i < l; i += 2) {\r
+ // TODO use ps to overwrite only real bg pixels\r
+ t = BgcDMAbase[BgcDMAsrc++ & BgcDMAmask];\r
+ q[i] = q[i+1] = PXCONV(t);\r
+ }\r
+ BgcDMAsrc += xl; // HSYNC DMA\r
+\r
+ t = est->HighPal[Pico.video.reg[7] & 0x3f];\r
+ while (i < len) q[i++] = t; // fill partial line with BG\r
+\r
+ if (upscale) {\r
+ switch (PicoIn.filter) {\r
+ case 3: h_upscale_bl4_4_5(pd, 320, q, 256, len, f_nop); break;\r
+ case 2: h_upscale_bl2_4_5(pd, 320, q, 256, len, f_nop); break;\r
+ case 1: h_upscale_snn_4_5(pd, 320, q, 256, len, f_nop); break;\r
+ default: h_upscale_nn_4_5(pd, 320, q, 256, len, f_nop); break;\r
+ }\r
+ }\r
+ return 1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+// --------------------------------------------\r
+\r
+static void PicoDoHighPal555_8bit(int sh, int line, struct PicoEState *est)\r
{\r
unsigned int *spal, *dpal;\r
unsigned int cnt = (sh ? 1 : est->SonicPalCount+1);\r
else if ((PicoIn.AHW & PAHW_SMS) && (est->Pico->video.reg[0] & 0x20))\r
len -= 8, ps += 8;\r
\r
+ if (BgcDMA(pd, len, est))\r
+ return;\r
+\r
if ((est->rendstatus & PDRAW_SOFTSCALE) && len < 320) {\r
if (len >= 240 && len <= 256) {\r
pd += (256-len)>>1;\r
}\r
}\r
\r
+void PicoDrawBgcDMA(u16 *base, u32 source, u32 mask, int dlen, int sl)\r
+{\r
+ struct PicoEState *est = &Pico.est;\r
+ int len = (est->Pico->video.reg[12]&1) ? 320 : 256;\r
+ int xl = (est->Pico->video.reg[12]&1) ? 38 : 33; // DMA slots during HSYNC\r
+\r
+ BgcDMAbase = base;\r
+ BgcDMAsrc = source;\r
+ BgcDMAmask = mask;\r
+ BgcDMAlen = dlen;\r
+ BgcDMAoffs = 0;\r
+\r
+ // handle slot offset in 1st line\r
+ if (sl-12 > 0) // active display output only starts at slot 12\r
+ BgcDMAoffs = 2*(sl-12);\r
+ else if (sl < 0) { // DMA starts before active display\r
+ BgcDMAsrc += 2*-sl;\r
+ BgcDMAlen -= 2*-sl;\r
+ }\r
+\r
+ // skip 1st line if it had been drawn already\r
+ if (Pico.est.DrawScanline > Pico.m.scanline) {\r
+ len -= BgcDMAoffs;\r
+ BgcDMAsrc += (len>>1)+xl;\r
+ BgcDMAlen -= (len>>1)+xl;\r
+ BgcDMAoffs = 0;\r
+ }\r
+}\r
+\r
// also works for fast renderer\r
void PicoDrawUpdateHighPal(void)\r
{\r
u32 a = Pico.video.addr | (Pico.video.addr_u << 16), e;\r
u16 *r, *base = NULL;\r
u32 mask = 0x1ffff;\r
+ int lc = SekCyclesDone()-Pico.t.m68c_line_start;\r
\r
elprintf(EL_VDPDMA, "DmaSlow[%i] %06x->%04x len %i inc=%i blank %i [%u] @ %06x",\r
Pico.video.type, source, a, len, inc, (Pico.video.status&SR_VB)||!(Pico.video.reg[1]&0x40),\r
case 3: // cram\r
Pico.m.dirtyPal = 1;\r
r = PicoMem.cram;\r
+ if (inc == 0 && (Pico.video.reg[7] & 0x3f) == ((a/2) & 0x3f)) { // bg color DMA\r
+ PicoVideoSync(1);\r
+ int sl = VdpFIFO.fifo_hcounts[lc/clkdiv];\r
+ if (sl > VdpFIFO.fifo_hcounts[0]-5) // hint delay is 5 slots\r
+ sl = (s8)sl;\r
+ // TODO this is needed to cover timing inaccuracies\r
+ if (sl <= 12) sl = -2;\r
+ PicoDrawBgcDMA(base, source, mask, len, sl);\r
+ }\r
for (; len; len--)\r
{\r
r[(a / 2) & 0x3f] = base[source++ & mask] & 0xeee;\r