pcd_prepare_frame();
PicoFrameStart();
+ if (Pico32xDrawMode != PDM32X_BOTH)
+ Pico.est.rendstatus |= PDRAW_SYNC_NEEDED;
PicoFrameHints();
elprintf(EL_32X, "poll: %02x %02x %02x",
int loffs = 8, lines = 224, coffs = 0, columns = 320;\r
int sprep = est->rendstatus & PDRAW_DIRTY_SPRITES;\r
int skipped = est->rendstatus & PDRAW_SKIP_FRAME;\r
+ int sync = est->rendstatus & (PDRAW_SYNC_NEEDED | PDRAW_SYNC_NEXT);\r
\r
// prepare to do this frame\r
est->rendstatus = 0;\r
// mode_change() might reset rendstatus_old by calling SetColorFormat\r
emu_video_mode_change(loffs, lines, coffs, columns);\r
rendstatus_old = est->rendstatus & (PDRAW_INTERLACE|PDRAW_32_COLS|PDRAW_30_ROWS);\r
+ // mode_change() might clear buffers, redraw needed\r
+ est->rendstatus |= PDRAW_SYNC_NEEDED;\r
}\r
+\r
+ if (sync | skipped)\r
+ est->rendstatus |= PDRAW_SYNC_NEEDED;\r
if (PicoIn.skipFrame) // preserve this until something is rendered at last\r
est->rendstatus |= PDRAW_SKIP_FRAME;\r
if (sprep | skipped)\r
if (est->DrawScanline <= to &&\r
(est->rendstatus & (PDRAW_DIRTY_SPRITES|PDRAW_PARSE_SPRITES)))\r
ParseSprites(to + 1, limit_sprites);\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
+ est->HighCol += count*HighColIncrement;\r
+ est->DrawLineDest = (char *)est->DrawLineDest + count*DrawLineDestIncrement;\r
+ est->DrawScanline = to+1;\r
+ return;\r
+ }\r
\r
for (line = est->DrawScanline; line < to; line++)\r
PicoLine(line, offs, sh, bgc);\r
PicoDrawSetInternalBuf(dest, increment); // needed for SMS\r
PicoDraw2SetOutBuf(dest, increment);\r
} else if (dest != NULL) {\r
+ if (dest != DrawLineDestBase)\r
+ Pico.est.rendstatus |= PDRAW_SYNC_NEEDED;\r
DrawLineDestBase = dest;\r
DrawLineDestIncrement = increment;\r
Pico.est.DrawLineDest = (char *)DrawLineDestBase + Pico.est.DrawScanline * increment;\r
void PicoDrawSetInternalBuf(void *dest, int increment)\r
{\r
if (dest != NULL) {\r
+ if (dest != HighColBase)\r
+ Pico.est.rendstatus |= PDRAW_SYNC_NEEDED;\r
HighColBase = dest;\r
HighColIncrement = increment;\r
Pico.est.HighCol = HighColBase + Pico.est.DrawScanline * increment;\r
#endif\r
void PicoDoHighPal555(int sh, int line, struct PicoEState *est);\r
// internals, NB must keep in sync with ASM draw functions\r
+#define PDRAW_SYNC_NEEDED (1<<0) // redraw needed\r
#define PDRAW_WND_DIFF_PRIO (1<<1) // not all window tiles use same priority\r
#define PDRAW_PARSE_SPRITES (1<<2) // SAT needs parsing\r
#define PDRAW_INTERLACE (1<<3)\r
#define PDRAW_30_ROWS (1<<11) // 30 rows mode (240 lines)\r
#define PDRAW_32X_SCALE (1<<12) // scale CLUT layer for 32X\r
#define PDRAW_SMS_BLANK_1 (1<<13) // 1st column blanked\r
+#define PDRAW_SYNC_NEXT (1<<14) // sync next frame\r
extern int rendstatus_old;\r
extern int rendlines;\r
\r
{
// find the right moment for frame renderer, when display is no longer blanked
if ((pv->reg[1]&0x40) || y > 100) {
- PicoFrameFull();
+ if (Pico.est.rendstatus & PDRAW_SYNC_NEEDED)
+ PicoFrameFull();
#ifdef DRAW_FINISH_FUNC
DRAW_FINISH_FUNC();
#endif
+ Pico.est.rendstatus &= ~PDRAW_SYNC_NEEDED;
skip = 1;
}
}
if (!skip)
{
if (Pico.est.DrawScanline < y)
- PicoDrawSync(y - 1, 0, 0);
+ PicoVideoSync(-1);
#ifdef DRAW_FINISH_FUNC
DRAW_FINISH_FUNC();
#endif
+ Pico.est.rendstatus &= ~PDRAW_SYNC_NEEDED;
}
#ifdef PICO_32X
p32x_render_frame();
void PicoVideoFIFOMode(int active, int h40);\r
int PicoVideoFIFOWrite(int count, int byte_p, unsigned sr_mask, unsigned sr_flags);\r
void PicoVideoInit(void);\r
+void PicoVideoSync(int skip);\r
void PicoVideoSave(void);\r
void PicoVideoLoad(void);\r
void PicoVideoCacheSAT(int load);\r
return SekCyclesDone() - Pico.t.m68c_line_start <= offs;\r
}\r
\r
-static void DrawSync(int skip)\r
+void PicoVideoSync(int skip)\r
{\r
int lines = Pico.video.reg[1]&0x08 ? 240 : 224;\r
- int last = Pico.m.scanline - (skip || blankline == Pico.m.scanline);\r
+ int last = Pico.m.scanline - ((skip > 0) || blankline == Pico.m.scanline);\r
+\r
+ if (!(PicoIn.opt & POPT_ALT_RENDERER) && !PicoIn.skipFrame) {\r
+ if (last >= lines)\r
+ last = lines-1;\r
+ else // in active display, need to sync next frame as well\r
+ Pico.est.rendstatus |= PDRAW_SYNC_NEXT;\r
\r
- if (last < lines && !(PicoIn.opt & POPT_ALT_RENDERER) &&\r
- !PicoIn.skipFrame && Pico.est.DrawScanline <= last) {\r
//elprintf(EL_ANOMALY, "sync");\r
if (blankline >= 0 && blankline < last) {\r
PicoDrawSync(blankline, 1, 0);\r
if (last >= limitsprites)\r
limitsprites = -1;\r
}\r
+ if (skip >= 0)\r
+ Pico.est.rendstatus |= PDRAW_SYNC_NEEDED;\r
}\r
\r
PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d)\r
!(pvid->type == 1 && !(pvid->addr&1) && ((pvid->addr^SATaddr)&SATmask) && PicoMem.vram[pvid->addr>>1] == d) &&\r
!(pvid->type == 3 && PicoMem.cram[(pvid->addr>>1) & 0x3f] == (d & 0xeee)) &&\r
!(pvid->type == 5 && PicoMem.vsram[(pvid->addr>>1) & 0x3f] == (d & 0x7ff)))\r
- DrawSync(InHblank(48)); // experimentally, Overdrive 2\r
+ // the vertical scroll value for this line must be read from VSRAM early,\r
+ // since the A/B tile row to be read depends on it. E.g. Skitchin, OD2\r
+ // in contrast, CRAM writes would have an immediate effect on the current\r
+ // pixel. XXX think about different offset values for different RAM types\r
+ PicoVideoSync(InHblank(30));\r
\r
if (!(PicoIn.opt&POPT_DIS_VDP_FIFO))\r
{\r
CommandChange(pvid);\r
// Check for dma:\r
if (d & 0x80) {\r
- DrawSync(InHblank(93));\r
+ PicoVideoSync(InHblank(93));\r
CommandDma();\r
}\r
}\r
}\r
if (num == 12 && ((pvid->reg[12]^d)&0x01))\r
PicoVideoFIFOMode(pvid->reg[1]&0x40, d & 1);\r
- if (num <= 18 && pvid->reg[num] != d) // no sync for DMA setup\r
- DrawSync(InHblank(93)); // Toy Story\r
- pvid->reg[num]=d;\r
+ 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
\r
switch (num)\r
{\r