est->DrawLineDest = (char *)est->DrawLineDest + DrawLineDestIncrement;\r
}\r
\r
-static void PicoLine(int line, int offs, int sh, int bgc)\r
+static void PicoLine(int line, int offs, int sh, int bgc, int off, int on)\r
{\r
struct PicoEState *est = &Pico.est;\r
int skip = skip_next_line;\r
\r
// Draw screen:\r
BackFill(bgc, sh, est);\r
- if (Pico.video.reg[1]&0x40)\r
+ if (Pico.video.reg[1]&0x40) {\r
+ int width = (Pico.video.reg[12]&1) ? 320 : 256;\r
DrawDisplay(sh);\r
+ // partial line blanking (display on or off inside the line)\r
+ if (unlikely(off|on)) {\r
+ if (off > 0)\r
+ memset(est->HighCol+8 + off, bgc, width-off);\r
+ if (on > 0)\r
+ memset(est->HighCol+8, bgc, on);\r
+ }\r
+ }\r
\r
if (FinalizeLine != NULL)\r
FinalizeLine(sh, line, est);\r
est->DrawLineDest = (char *)est->DrawLineDest + DrawLineDestIncrement;\r
}\r
\r
-void PicoDrawSync(int to, int blank_last_line, int limit_sprites)\r
+void PicoDrawSync(int to, int off, int on)\r
{\r
struct PicoEState *est = &Pico.est;\r
int line, offs = 0;\r
}\r
if (est->DrawScanline <= to &&\r
(est->rendstatus & (PDRAW_DIRTY_SPRITES|PDRAW_PARSE_SPRITES)))\r
- ParseSprites(to + 1, limit_sprites);\r
+ ParseSprites(to + 1, on);\r
else if (!(est->rendstatus & PDRAW_SYNC_NEEDED)) {\r
// nothing has changed in VDP/VRAM and buffer is the same -> no sync needed\r
int count = to+1 - est->DrawScanline;\r
}\r
\r
for (line = est->DrawScanline; line < to; line++)\r
- PicoLine(line, offs, sh, bgc);\r
+ PicoLine(line, offs, sh, bgc, 0, 0);\r
\r
// last line\r
if (line <= to)\r
{\r
- if (blank_last_line)\r
- DrawBlankedLine(line, offs, sh, bgc);\r
- else PicoLine(line, offs, sh, bgc);\r
+ int width2 = (Pico.video.reg[12]&1) ? 160 : 128;\r
+\r
+ // technically, VDP starts active display output at slot 12\r
+ if (unlikely(on|off) && (off >= width2 ||\r
+ // hack for timing inaccuracy, if on/off near borders\r
+ (off && off <= 24) || (on < width2 && on >= width2-24)))\r
+ DrawBlankedLine(line, offs, sh, bgc);\r
+ else {\r
+ if (on > width2) on = 0; // on, before start of line?\r
+ PicoLine(line, offs, sh, bgc, 2*off, 2*on);\r
+ }\r
line++;\r
}\r
est->DrawScanline = line;\r
}\r
\r
\r
-static int blankline; // display disabled for this line\r
-static int limitsprites;\r
+static int linedisabled; // display disabled on this line\r
+static int lineenabled; // display enabled on this line\r
+static int lineoffset; // offset at which dis/enable took place\r
\r
-u32 SATaddr, SATmask; // VRAM addr of sprite attribute table\r
+u32 SATaddr, SATmask; // VRAM addr of sprite attribute table\r
\r
int (*PicoDmaHook)(u32 source, int len, unsigned short **base, u32 *mask) = NULL;\r
\r
\r
void PicoVideoSync(int skip)\r
{\r
+ struct VdpFIFO *vf = &VdpFIFO;\r
int lines = Pico.video.reg[1]&0x08 ? 240 : 224;\r
- int last = Pico.m.scanline - ((skip > 0) || blankline == Pico.m.scanline);\r
+ int last = Pico.m.scanline - (skip > 0);\r
\r
if (!(PicoIn.opt & POPT_ALT_RENDERER) && !PicoIn.skipFrame) {\r
if (last >= lines)\r
Pico.est.rendstatus |= PDRAW_SYNC_NEXT;\r
\r
//elprintf(EL_ANOMALY, "sync");\r
- if (blankline >= 0 && blankline < last) {\r
- PicoDrawSync(blankline, 1, 0);\r
- blankline = -1;\r
+ if (unlikely(linedisabled >= 0 && linedisabled <= last)) {\r
+ if (Pico.est.DrawScanline <= linedisabled) {\r
+ int sl = vf->fifo_hcounts[lineoffset/clkdiv];\r
+ PicoDrawSync(linedisabled, sl ? sl : 1, 0);\r
+ }\r
+ linedisabled = -1;\r
}\r
- PicoDrawSync(last, 0, last == limitsprites);\r
- if (last >= limitsprites)\r
- limitsprites = -1;\r
+ if (unlikely(lineenabled >= 0 && lineenabled <= last)) {\r
+ if (Pico.est.DrawScanline <= lineenabled) {\r
+ int sl = vf->fifo_hcounts[lineoffset/clkdiv];\r
+ PicoDrawSync(lineenabled, 0, sl ? sl : 1);\r
+ }\r
+ lineenabled = -1;\r
+ }\r
+ if (Pico.est.DrawScanline <= last)\r
+ PicoDrawSync(last, 0, 0);\r
}\r
if (skip >= 0)\r
Pico.est.rendstatus |= PDRAW_SYNC_NEEDED;\r
d &= 0xff;\r
if (num == 0 && !(pvid->reg[0]&2) && (d&2))\r
pvid->hv_latch = PicoVideoRead(0x08);\r
- if (num == 1 && ((pvid->reg[1]^d)&0x40)) {\r
- PicoVideoFIFOMode(d & 0x40, pvid->reg[12]&1);\r
- // handle line blanking before line rendering\r
- if (InHblank(93)) {\r
- // sprite rendering is limited if display is disabled and reenabled\r
- // in HBLANK of the same scanline (Overdrive)\r
- limitsprites = (d&0x40) && blankline == Pico.m.scanline ? Pico.m.scanline : -1;\r
- blankline = (d&0x40) ? -1 : Pico.m.scanline;\r
- }\r
- }\r
if (num == 12 && ((pvid->reg[12]^d)&0x01))\r
PicoVideoFIFOMode(pvid->reg[1]&0x40, d & 1);\r
- if (((1<<num) & 0x738ff) && pvid->reg[num] != d)\r
+\r
+ if (num == 1 && ((pvid->reg[1]^d)&0x40)) {\r
+ PicoVideoFIFOMode(d & 0x40, pvid->reg[12]&1);\r
+ // handle line blanking before line rendering. Only the last switch\r
+ // before the 1st sync for other reasons is honoured.\r
+ PicoVideoSync(1);\r
+ lineenabled = (d&0x40) ? Pico.m.scanline : -1;\r
+ linedisabled = (d&0x40) ? -1 : Pico.m.scanline;\r
+ lineoffset = SekCyclesDone() - Pico.t.m68c_line_start;\r
+ } else if (((1<<num) & 0x738ff) && pvid->reg[num] != d)\r
// VDP regs 0-7,11-13,16-18 influence rendering, ignore all others\r
PicoVideoSync(InHblank(93)); // Toy Story\r
pvid->reg[num] = d;\r