mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00
core vdp, implement partial line blanking
This commit is contained in:
parent
f9ed944604
commit
97232a47c9
2 changed files with 56 additions and 29 deletions
33
pico/draw.c
33
pico/draw.c
|
@ -1987,7 +1987,7 @@ static void DrawBlankedLine(int line, int offs, int sh, int bgc)
|
||||||
est->DrawLineDest = (char *)est->DrawLineDest + DrawLineDestIncrement;
|
est->DrawLineDest = (char *)est->DrawLineDest + DrawLineDestIncrement;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PicoLine(int line, int offs, int sh, int bgc)
|
static void PicoLine(int line, int offs, int sh, int bgc, int off, int on)
|
||||||
{
|
{
|
||||||
struct PicoEState *est = &Pico.est;
|
struct PicoEState *est = &Pico.est;
|
||||||
int skip = skip_next_line;
|
int skip = skip_next_line;
|
||||||
|
@ -2006,8 +2006,17 @@ static void PicoLine(int line, int offs, int sh, int bgc)
|
||||||
|
|
||||||
// Draw screen:
|
// Draw screen:
|
||||||
BackFill(bgc, sh, est);
|
BackFill(bgc, sh, est);
|
||||||
if (Pico.video.reg[1]&0x40)
|
if (Pico.video.reg[1]&0x40) {
|
||||||
|
int width = (Pico.video.reg[12]&1) ? 320 : 256;
|
||||||
DrawDisplay(sh);
|
DrawDisplay(sh);
|
||||||
|
// partial line blanking (display on or off inside the line)
|
||||||
|
if (unlikely(off|on)) {
|
||||||
|
if (off > 0)
|
||||||
|
memset(est->HighCol+8 + off, bgc, width-off);
|
||||||
|
if (on > 0)
|
||||||
|
memset(est->HighCol+8, bgc, on);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (FinalizeLine != NULL)
|
if (FinalizeLine != NULL)
|
||||||
FinalizeLine(sh, line, est);
|
FinalizeLine(sh, line, est);
|
||||||
|
@ -2019,7 +2028,7 @@ static void PicoLine(int line, int offs, int sh, int bgc)
|
||||||
est->DrawLineDest = (char *)est->DrawLineDest + DrawLineDestIncrement;
|
est->DrawLineDest = (char *)est->DrawLineDest + DrawLineDestIncrement;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PicoDrawSync(int to, int blank_last_line, int limit_sprites)
|
void PicoDrawSync(int to, int off, int on)
|
||||||
{
|
{
|
||||||
struct PicoEState *est = &Pico.est;
|
struct PicoEState *est = &Pico.est;
|
||||||
int line, offs = 0;
|
int line, offs = 0;
|
||||||
|
@ -2035,7 +2044,7 @@ 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, on);
|
||||||
else if (!(est->rendstatus & PDRAW_SYNC_NEEDED)) {
|
else if (!(est->rendstatus & PDRAW_SYNC_NEEDED)) {
|
||||||
// nothing has changed in VDP/VRAM and buffer is the same -> no sync needed
|
// nothing has changed in VDP/VRAM and buffer is the same -> no sync needed
|
||||||
int count = to+1 - est->DrawScanline;
|
int count = to+1 - est->DrawScanline;
|
||||||
|
@ -2046,14 +2055,22 @@ void PicoDrawSync(int to, int blank_last_line, int limit_sprites)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (line = est->DrawScanline; line < to; line++)
|
for (line = est->DrawScanline; line < to; line++)
|
||||||
PicoLine(line, offs, sh, bgc);
|
PicoLine(line, offs, sh, bgc, 0, 0);
|
||||||
|
|
||||||
// last line
|
// last line
|
||||||
if (line <= to)
|
if (line <= to)
|
||||||
{
|
{
|
||||||
if (blank_last_line)
|
int width2 = (Pico.video.reg[12]&1) ? 160 : 128;
|
||||||
DrawBlankedLine(line, offs, sh, bgc);
|
|
||||||
else PicoLine(line, offs, sh, bgc);
|
// technically, VDP starts active display output at slot 12
|
||||||
|
if (unlikely(on|off) && (off >= width2 ||
|
||||||
|
// hack for timing inaccuracy, if on/off near borders
|
||||||
|
(off && off <= 24) || (on < width2 && on >= width2-24)))
|
||||||
|
DrawBlankedLine(line, offs, sh, bgc);
|
||||||
|
else {
|
||||||
|
if (on > width2) on = 0; // on, before start of line?
|
||||||
|
PicoLine(line, offs, sh, bgc, 2*off, 2*on);
|
||||||
|
}
|
||||||
line++;
|
line++;
|
||||||
}
|
}
|
||||||
est->DrawScanline = line;
|
est->DrawScanline = line;
|
||||||
|
|
|
@ -138,10 +138,11 @@ void PicoVideoInit(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int blankline; // display disabled for this line
|
static int linedisabled; // display disabled on this line
|
||||||
static int limitsprites;
|
static int lineenabled; // display enabled on this line
|
||||||
|
static int lineoffset; // offset at which dis/enable took place
|
||||||
|
|
||||||
u32 SATaddr, SATmask; // VRAM addr of sprite attribute table
|
u32 SATaddr, SATmask; // VRAM addr of sprite attribute table
|
||||||
|
|
||||||
int (*PicoDmaHook)(u32 source, int len, unsigned short **base, u32 *mask) = NULL;
|
int (*PicoDmaHook)(u32 source, int len, unsigned short **base, u32 *mask) = NULL;
|
||||||
|
|
||||||
|
@ -811,8 +812,9 @@ static inline int InHblank(int offs)
|
||||||
|
|
||||||
void PicoVideoSync(int skip)
|
void PicoVideoSync(int skip)
|
||||||
{
|
{
|
||||||
|
struct VdpFIFO *vf = &VdpFIFO;
|
||||||
int lines = Pico.video.reg[1]&0x08 ? 240 : 224;
|
int lines = Pico.video.reg[1]&0x08 ? 240 : 224;
|
||||||
int last = Pico.m.scanline - ((skip > 0) || blankline == Pico.m.scanline);
|
int last = Pico.m.scanline - (skip > 0);
|
||||||
|
|
||||||
if (!(PicoIn.opt & POPT_ALT_RENDERER) && !PicoIn.skipFrame) {
|
if (!(PicoIn.opt & POPT_ALT_RENDERER) && !PicoIn.skipFrame) {
|
||||||
if (last >= lines)
|
if (last >= lines)
|
||||||
|
@ -821,13 +823,22 @@ void PicoVideoSync(int skip)
|
||||||
Pico.est.rendstatus |= PDRAW_SYNC_NEXT;
|
Pico.est.rendstatus |= PDRAW_SYNC_NEXT;
|
||||||
|
|
||||||
//elprintf(EL_ANOMALY, "sync");
|
//elprintf(EL_ANOMALY, "sync");
|
||||||
if (blankline >= 0 && blankline < last) {
|
if (unlikely(linedisabled >= 0 && linedisabled <= last)) {
|
||||||
PicoDrawSync(blankline, 1, 0);
|
if (Pico.est.DrawScanline <= linedisabled) {
|
||||||
blankline = -1;
|
int sl = vf->fifo_hcounts[lineoffset/clkdiv];
|
||||||
|
PicoDrawSync(linedisabled, sl ? sl : 1, 0);
|
||||||
|
}
|
||||||
|
linedisabled = -1;
|
||||||
}
|
}
|
||||||
PicoDrawSync(last, 0, last == limitsprites);
|
if (unlikely(lineenabled >= 0 && lineenabled <= last)) {
|
||||||
if (last >= limitsprites)
|
if (Pico.est.DrawScanline <= lineenabled) {
|
||||||
limitsprites = -1;
|
int sl = vf->fifo_hcounts[lineoffset/clkdiv];
|
||||||
|
PicoDrawSync(lineenabled, 0, sl ? sl : 1);
|
||||||
|
}
|
||||||
|
lineenabled = -1;
|
||||||
|
}
|
||||||
|
if (Pico.est.DrawScanline <= last)
|
||||||
|
PicoDrawSync(last, 0, 0);
|
||||||
}
|
}
|
||||||
if (skip >= 0)
|
if (skip >= 0)
|
||||||
Pico.est.rendstatus |= PDRAW_SYNC_NEEDED;
|
Pico.est.rendstatus |= PDRAW_SYNC_NEEDED;
|
||||||
|
@ -911,19 +922,18 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d)
|
||||||
d &= 0xff;
|
d &= 0xff;
|
||||||
if (num == 0 && !(pvid->reg[0]&2) && (d&2))
|
if (num == 0 && !(pvid->reg[0]&2) && (d&2))
|
||||||
pvid->hv_latch = PicoVideoRead(0x08);
|
pvid->hv_latch = PicoVideoRead(0x08);
|
||||||
if (num == 1 && ((pvid->reg[1]^d)&0x40)) {
|
|
||||||
PicoVideoFIFOMode(d & 0x40, pvid->reg[12]&1);
|
|
||||||
// handle line blanking before line rendering
|
|
||||||
if (InHblank(93)) {
|
|
||||||
// sprite rendering is limited if display is disabled and reenabled
|
|
||||||
// in HBLANK of the same scanline (Overdrive)
|
|
||||||
limitsprites = (d&0x40) && blankline == Pico.m.scanline ? Pico.m.scanline : -1;
|
|
||||||
blankline = (d&0x40) ? -1 : Pico.m.scanline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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 (((1<<num) & 0x738ff) && pvid->reg[num] != d)
|
|
||||||
|
if (num == 1 && ((pvid->reg[1]^d)&0x40)) {
|
||||||
|
PicoVideoFIFOMode(d & 0x40, pvid->reg[12]&1);
|
||||||
|
// handle line blanking before line rendering. Only the last switch
|
||||||
|
// before the 1st sync for other reasons is honoured.
|
||||||
|
PicoVideoSync(1);
|
||||||
|
lineenabled = (d&0x40) ? Pico.m.scanline : -1;
|
||||||
|
linedisabled = (d&0x40) ? -1 : Pico.m.scanline;
|
||||||
|
lineoffset = SekCyclesDone() - Pico.t.m68c_line_start;
|
||||||
|
} else if (((1<<num) & 0x738ff) && pvid->reg[num] != d)
|
||||||
// VDP regs 0-7,11-13,16-18 influence rendering, ignore all others
|
// VDP regs 0-7,11-13,16-18 influence rendering, ignore all others
|
||||||
PicoVideoSync(InHblank(93)); // Toy Story
|
PicoVideoSync(InHblank(93)); // Toy Story
|
||||||
pvid->reg[num] = d;
|
pvid->reg[num] = d;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue