mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00
core vdp, avoid rendering if no changes to RAMs/registers
mainly benefits 32X in faster/fastest rendering mode, 0-5% saved
This commit is contained in:
parent
0c9c8e4796
commit
f9ed944604
6 changed files with 48 additions and 11 deletions
|
@ -587,6 +587,8 @@ void PicoFrame32x(void)
|
||||||
pcd_prepare_frame();
|
pcd_prepare_frame();
|
||||||
|
|
||||||
PicoFrameStart();
|
PicoFrameStart();
|
||||||
|
if (Pico32xDrawMode != PDM32X_BOTH)
|
||||||
|
Pico.est.rendstatus |= PDRAW_SYNC_NEEDED;
|
||||||
PicoFrameHints();
|
PicoFrameHints();
|
||||||
|
|
||||||
elprintf(EL_32X, "poll: %02x %02x %02x",
|
elprintf(EL_32X, "poll: %02x %02x %02x",
|
||||||
|
|
18
pico/draw.c
18
pico/draw.c
|
@ -1910,6 +1910,7 @@ PICO_INTERNAL void PicoFrameStart(void)
|
||||||
int loffs = 8, lines = 224, coffs = 0, columns = 320;
|
int loffs = 8, lines = 224, coffs = 0, columns = 320;
|
||||||
int sprep = est->rendstatus & PDRAW_DIRTY_SPRITES;
|
int sprep = est->rendstatus & PDRAW_DIRTY_SPRITES;
|
||||||
int skipped = est->rendstatus & PDRAW_SKIP_FRAME;
|
int skipped = est->rendstatus & PDRAW_SKIP_FRAME;
|
||||||
|
int sync = est->rendstatus & (PDRAW_SYNC_NEEDED | PDRAW_SYNC_NEXT);
|
||||||
|
|
||||||
// prepare to do this frame
|
// prepare to do this frame
|
||||||
est->rendstatus = 0;
|
est->rendstatus = 0;
|
||||||
|
@ -1935,7 +1936,12 @@ PICO_INTERNAL void PicoFrameStart(void)
|
||||||
// mode_change() might reset rendstatus_old by calling SetColorFormat
|
// mode_change() might reset rendstatus_old by calling SetColorFormat
|
||||||
emu_video_mode_change(loffs, lines, coffs, columns);
|
emu_video_mode_change(loffs, lines, coffs, columns);
|
||||||
rendstatus_old = est->rendstatus & (PDRAW_INTERLACE|PDRAW_32_COLS|PDRAW_30_ROWS);
|
rendstatus_old = est->rendstatus & (PDRAW_INTERLACE|PDRAW_32_COLS|PDRAW_30_ROWS);
|
||||||
|
// mode_change() might clear buffers, redraw needed
|
||||||
|
est->rendstatus |= PDRAW_SYNC_NEEDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sync | skipped)
|
||||||
|
est->rendstatus |= PDRAW_SYNC_NEEDED;
|
||||||
if (PicoIn.skipFrame) // preserve this until something is rendered at last
|
if (PicoIn.skipFrame) // preserve this until something is rendered at last
|
||||||
est->rendstatus |= PDRAW_SKIP_FRAME;
|
est->rendstatus |= PDRAW_SKIP_FRAME;
|
||||||
if (sprep | skipped)
|
if (sprep | skipped)
|
||||||
|
@ -2030,6 +2036,14 @@ void PicoDrawSync(int to, int blank_last_line, int limit_sprites)
|
||||||
if (est->DrawScanline <= to &&
|
if (est->DrawScanline <= to &&
|
||||||
(est->rendstatus & (PDRAW_DIRTY_SPRITES|PDRAW_PARSE_SPRITES)))
|
(est->rendstatus & (PDRAW_DIRTY_SPRITES|PDRAW_PARSE_SPRITES)))
|
||||||
ParseSprites(to + 1, limit_sprites);
|
ParseSprites(to + 1, limit_sprites);
|
||||||
|
else if (!(est->rendstatus & PDRAW_SYNC_NEEDED)) {
|
||||||
|
// nothing has changed in VDP/VRAM and buffer is the same -> no sync needed
|
||||||
|
int count = to+1 - est->DrawScanline;
|
||||||
|
est->HighCol += count*HighColIncrement;
|
||||||
|
est->DrawLineDest = (char *)est->DrawLineDest + count*DrawLineDestIncrement;
|
||||||
|
est->DrawScanline = to+1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (line = est->DrawScanline; line < to; line++)
|
for (line = est->DrawScanline; line < to; line++)
|
||||||
PicoLine(line, offs, sh, bgc);
|
PicoLine(line, offs, sh, bgc);
|
||||||
|
@ -2135,6 +2149,8 @@ void PicoDrawSetOutBufMD(void *dest, int increment)
|
||||||
PicoDrawSetInternalBuf(dest, increment); // needed for SMS
|
PicoDrawSetInternalBuf(dest, increment); // needed for SMS
|
||||||
PicoDraw2SetOutBuf(dest, increment);
|
PicoDraw2SetOutBuf(dest, increment);
|
||||||
} else if (dest != NULL) {
|
} else if (dest != NULL) {
|
||||||
|
if (dest != DrawLineDestBase)
|
||||||
|
Pico.est.rendstatus |= PDRAW_SYNC_NEEDED;
|
||||||
DrawLineDestBase = dest;
|
DrawLineDestBase = dest;
|
||||||
DrawLineDestIncrement = increment;
|
DrawLineDestIncrement = increment;
|
||||||
Pico.est.DrawLineDest = (char *)DrawLineDestBase + Pico.est.DrawScanline * increment;
|
Pico.est.DrawLineDest = (char *)DrawLineDestBase + Pico.est.DrawScanline * increment;
|
||||||
|
@ -2157,6 +2173,8 @@ void PicoDrawSetOutBuf(void *dest, int increment)
|
||||||
void PicoDrawSetInternalBuf(void *dest, int increment)
|
void PicoDrawSetInternalBuf(void *dest, int increment)
|
||||||
{
|
{
|
||||||
if (dest != NULL) {
|
if (dest != NULL) {
|
||||||
|
if (dest != HighColBase)
|
||||||
|
Pico.est.rendstatus |= PDRAW_SYNC_NEEDED;
|
||||||
HighColBase = dest;
|
HighColBase = dest;
|
||||||
HighColIncrement = increment;
|
HighColIncrement = increment;
|
||||||
Pico.est.HighCol = HighColBase + Pico.est.DrawScanline * increment;
|
Pico.est.HighCol = HighColBase + Pico.est.DrawScanline * increment;
|
||||||
|
|
|
@ -223,6 +223,7 @@ void vidConvCpyRGB565(void *to, void *from, int pixels);
|
||||||
#endif
|
#endif
|
||||||
void PicoDoHighPal555(int sh, int line, struct PicoEState *est);
|
void PicoDoHighPal555(int sh, int line, struct PicoEState *est);
|
||||||
// internals, NB must keep in sync with ASM draw functions
|
// internals, NB must keep in sync with ASM draw functions
|
||||||
|
#define PDRAW_SYNC_NEEDED (1<<0) // redraw needed
|
||||||
#define PDRAW_WND_DIFF_PRIO (1<<1) // not all window tiles use same priority
|
#define PDRAW_WND_DIFF_PRIO (1<<1) // not all window tiles use same priority
|
||||||
#define PDRAW_PARSE_SPRITES (1<<2) // SAT needs parsing
|
#define PDRAW_PARSE_SPRITES (1<<2) // SAT needs parsing
|
||||||
#define PDRAW_INTERLACE (1<<3)
|
#define PDRAW_INTERLACE (1<<3)
|
||||||
|
@ -236,6 +237,7 @@ void PicoDoHighPal555(int sh, int line, struct PicoEState *est);
|
||||||
#define PDRAW_30_ROWS (1<<11) // 30 rows mode (240 lines)
|
#define PDRAW_30_ROWS (1<<11) // 30 rows mode (240 lines)
|
||||||
#define PDRAW_32X_SCALE (1<<12) // scale CLUT layer for 32X
|
#define PDRAW_32X_SCALE (1<<12) // scale CLUT layer for 32X
|
||||||
#define PDRAW_SMS_BLANK_1 (1<<13) // 1st column blanked
|
#define PDRAW_SMS_BLANK_1 (1<<13) // 1st column blanked
|
||||||
|
#define PDRAW_SYNC_NEXT (1<<14) // sync next frame
|
||||||
extern int rendstatus_old;
|
extern int rendstatus_old;
|
||||||
extern int rendlines;
|
extern int rendlines;
|
||||||
|
|
||||||
|
|
|
@ -168,10 +168,12 @@ static int PicoFrameHints(void)
|
||||||
{
|
{
|
||||||
// find the right moment for frame renderer, when display is no longer blanked
|
// find the right moment for frame renderer, when display is no longer blanked
|
||||||
if ((pv->reg[1]&0x40) || y > 100) {
|
if ((pv->reg[1]&0x40) || y > 100) {
|
||||||
|
if (Pico.est.rendstatus & PDRAW_SYNC_NEEDED)
|
||||||
PicoFrameFull();
|
PicoFrameFull();
|
||||||
#ifdef DRAW_FINISH_FUNC
|
#ifdef DRAW_FINISH_FUNC
|
||||||
DRAW_FINISH_FUNC();
|
DRAW_FINISH_FUNC();
|
||||||
#endif
|
#endif
|
||||||
|
Pico.est.rendstatus &= ~PDRAW_SYNC_NEEDED;
|
||||||
skip = 1;
|
skip = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,10 +193,11 @@ static int PicoFrameHints(void)
|
||||||
if (!skip)
|
if (!skip)
|
||||||
{
|
{
|
||||||
if (Pico.est.DrawScanline < y)
|
if (Pico.est.DrawScanline < y)
|
||||||
PicoDrawSync(y - 1, 0, 0);
|
PicoVideoSync(-1);
|
||||||
#ifdef DRAW_FINISH_FUNC
|
#ifdef DRAW_FINISH_FUNC
|
||||||
DRAW_FINISH_FUNC();
|
DRAW_FINISH_FUNC();
|
||||||
#endif
|
#endif
|
||||||
|
Pico.est.rendstatus &= ~PDRAW_SYNC_NEEDED;
|
||||||
}
|
}
|
||||||
#ifdef PICO_32X
|
#ifdef PICO_32X
|
||||||
p32x_render_frame();
|
p32x_render_frame();
|
||||||
|
|
|
@ -917,6 +917,7 @@ int PicoVideoFIFOHint(void);
|
||||||
void PicoVideoFIFOMode(int active, int h40);
|
void PicoVideoFIFOMode(int active, int h40);
|
||||||
int PicoVideoFIFOWrite(int count, int byte_p, unsigned sr_mask, unsigned sr_flags);
|
int PicoVideoFIFOWrite(int count, int byte_p, unsigned sr_mask, unsigned sr_flags);
|
||||||
void PicoVideoInit(void);
|
void PicoVideoInit(void);
|
||||||
|
void PicoVideoSync(int skip);
|
||||||
void PicoVideoSave(void);
|
void PicoVideoSave(void);
|
||||||
void PicoVideoLoad(void);
|
void PicoVideoLoad(void);
|
||||||
void PicoVideoCacheSAT(int load);
|
void PicoVideoCacheSAT(int load);
|
||||||
|
|
|
@ -809,13 +809,17 @@ static inline int InHblank(int offs)
|
||||||
return SekCyclesDone() - Pico.t.m68c_line_start <= offs;
|
return SekCyclesDone() - Pico.t.m68c_line_start <= offs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawSync(int skip)
|
void PicoVideoSync(int skip)
|
||||||
{
|
{
|
||||||
int lines = Pico.video.reg[1]&0x08 ? 240 : 224;
|
int lines = Pico.video.reg[1]&0x08 ? 240 : 224;
|
||||||
int last = Pico.m.scanline - (skip || blankline == Pico.m.scanline);
|
int last = Pico.m.scanline - ((skip > 0) || blankline == Pico.m.scanline);
|
||||||
|
|
||||||
|
if (!(PicoIn.opt & POPT_ALT_RENDERER) && !PicoIn.skipFrame) {
|
||||||
|
if (last >= lines)
|
||||||
|
last = lines-1;
|
||||||
|
else // in active display, need to sync next frame as well
|
||||||
|
Pico.est.rendstatus |= PDRAW_SYNC_NEXT;
|
||||||
|
|
||||||
if (last < lines && !(PicoIn.opt & POPT_ALT_RENDERER) &&
|
|
||||||
!PicoIn.skipFrame && Pico.est.DrawScanline <= last) {
|
|
||||||
//elprintf(EL_ANOMALY, "sync");
|
//elprintf(EL_ANOMALY, "sync");
|
||||||
if (blankline >= 0 && blankline < last) {
|
if (blankline >= 0 && blankline < last) {
|
||||||
PicoDrawSync(blankline, 1, 0);
|
PicoDrawSync(blankline, 1, 0);
|
||||||
|
@ -825,6 +829,8 @@ static void DrawSync(int skip)
|
||||||
if (last >= limitsprites)
|
if (last >= limitsprites)
|
||||||
limitsprites = -1;
|
limitsprites = -1;
|
||||||
}
|
}
|
||||||
|
if (skip >= 0)
|
||||||
|
Pico.est.rendstatus |= PDRAW_SYNC_NEEDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d)
|
PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d)
|
||||||
|
@ -849,7 +855,11 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d)
|
||||||
!(pvid->type == 1 && !(pvid->addr&1) && ((pvid->addr^SATaddr)&SATmask) && PicoMem.vram[pvid->addr>>1] == d) &&
|
!(pvid->type == 1 && !(pvid->addr&1) && ((pvid->addr^SATaddr)&SATmask) && PicoMem.vram[pvid->addr>>1] == d) &&
|
||||||
!(pvid->type == 3 && PicoMem.cram[(pvid->addr>>1) & 0x3f] == (d & 0xeee)) &&
|
!(pvid->type == 3 && PicoMem.cram[(pvid->addr>>1) & 0x3f] == (d & 0xeee)) &&
|
||||||
!(pvid->type == 5 && PicoMem.vsram[(pvid->addr>>1) & 0x3f] == (d & 0x7ff)))
|
!(pvid->type == 5 && PicoMem.vsram[(pvid->addr>>1) & 0x3f] == (d & 0x7ff)))
|
||||||
DrawSync(InHblank(48)); // experimentally, Overdrive 2
|
// the vertical scroll value for this line must be read from VSRAM early,
|
||||||
|
// since the A/B tile row to be read depends on it. E.g. Skitchin, OD2
|
||||||
|
// in contrast, CRAM writes would have an immediate effect on the current
|
||||||
|
// pixel. XXX think about different offset values for different RAM types
|
||||||
|
PicoVideoSync(InHblank(30));
|
||||||
|
|
||||||
if (!(PicoIn.opt&POPT_DIS_VDP_FIFO))
|
if (!(PicoIn.opt&POPT_DIS_VDP_FIFO))
|
||||||
{
|
{
|
||||||
|
@ -881,7 +891,7 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d)
|
||||||
CommandChange(pvid);
|
CommandChange(pvid);
|
||||||
// Check for dma:
|
// Check for dma:
|
||||||
if (d & 0x80) {
|
if (d & 0x80) {
|
||||||
DrawSync(InHblank(93));
|
PicoVideoSync(InHblank(93));
|
||||||
CommandDma();
|
CommandDma();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -913,8 +923,9 @@ 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);
|
||||||
if (num <= 18 && pvid->reg[num] != d) // no sync for DMA setup
|
if (((1<<num) & 0x738ff) && pvid->reg[num] != d)
|
||||||
DrawSync(InHblank(93)); // Toy Story
|
// VDP regs 0-7,11-13,16-18 influence rendering, ignore all others
|
||||||
|
PicoVideoSync(InHblank(93)); // Toy Story
|
||||||
pvid->reg[num] = d;
|
pvid->reg[num] = d;
|
||||||
|
|
||||||
switch (num)
|
switch (num)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue