mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 07:17:45 -04:00
core vdp, some cleanup
This commit is contained in:
parent
133006a9d4
commit
0c9c8e4796
8 changed files with 93 additions and 90 deletions
|
@ -33,7 +33,6 @@ PICO_INTERNAL void DmaSlowCell(u32 source, u32 a, int len, unsigned char inc)
|
||||||
// AutoIncrement
|
// AutoIncrement
|
||||||
a=(u16)(a+inc);
|
a=(u16)(a+inc);
|
||||||
}
|
}
|
||||||
Pico.est.rendstatus |= PDRAW_SPRITES_MOVED;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: // cram
|
case 3: // cram
|
||||||
|
|
105
pico/draw.c
105
pico/draw.c
|
@ -1421,7 +1421,7 @@ static NOINLINE void ParseSprites(int max_lines, int limit)
|
||||||
|
|
||||||
// SAT scanning is one line ahead, but don't overshoot. Technically, SAT
|
// SAT scanning is one line ahead, but don't overshoot. Technically, SAT
|
||||||
// parsing for line 0 is on the last line of the previous frame.
|
// parsing for line 0 is on the last line of the previous frame.
|
||||||
int first_line = Pico.est.DrawScanline + !!Pico.est.DrawScanline;
|
int first_line = est->DrawScanline + !!est->DrawScanline;
|
||||||
if (max_lines > rendlines-1)
|
if (max_lines > rendlines-1)
|
||||||
max_lines = rendlines-1;
|
max_lines = rendlines-1;
|
||||||
|
|
||||||
|
@ -1584,12 +1584,11 @@ static void DrawAllSprites(unsigned char *sprited, int prio, int sh,
|
||||||
|
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
|
|
||||||
void BackFill(int reg7, int sh, struct PicoEState *est)
|
void BackFill(int bgc, int sh, struct PicoEState *est)
|
||||||
{
|
{
|
||||||
unsigned int back;
|
u32 back = bgc;
|
||||||
|
|
||||||
// Start with a blank scanline (background colour):
|
// Start with a blank scanline (background colour):
|
||||||
back=reg7&0x3f;
|
|
||||||
back|=sh<<7; // shadow
|
back|=sh<<7; // shadow
|
||||||
back|=back<<8;
|
back|=back<<8;
|
||||||
back|=back<<16;
|
back|=back<<16;
|
||||||
|
@ -1689,11 +1688,11 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est)
|
||||||
PicoDrawUpdateHighPal();
|
PicoDrawUpdateHighPal();
|
||||||
|
|
||||||
len = 256;
|
len = 256;
|
||||||
if ((PicoIn.AHW & PAHW_GG) && (Pico.m.hardware & PMS_HW_LCD))
|
if (!(PicoIn.AHW & PAHW_8BIT) && (Pico.video.reg[12]&1))
|
||||||
len = 160;
|
|
||||||
else if (!(PicoIn.AHW & PAHW_SMS) && (Pico.video.reg[12]&1))
|
|
||||||
len = 320;
|
len = 320;
|
||||||
if ((PicoIn.AHW & PAHW_SMS) && (Pico.video.reg[0] & 0x20) && len == 256)
|
else if ((PicoIn.AHW & PAHW_GG) && (Pico.m.hardware & PMS_HW_LCD))
|
||||||
|
len = 160;
|
||||||
|
else if ((PicoIn.AHW & PAHW_SMS) && (Pico.video.reg[0] & 0x20))
|
||||||
len -= 8, ps += 8;
|
len -= 8, ps += 8;
|
||||||
|
|
||||||
if ((*est->PicoOpt & POPT_EN_SOFTSCALE) && len < 320) {
|
if ((*est->PicoOpt & POPT_EN_SOFTSCALE) && len < 320) {
|
||||||
|
@ -1741,9 +1740,9 @@ void FinalizeLine8bit(int sh, int line, struct PicoEState *est)
|
||||||
// a hack for mid-frame palette changes
|
// a hack for mid-frame palette changes
|
||||||
if (Pico.m.dirtyPal == 1)
|
if (Pico.m.dirtyPal == 1)
|
||||||
{
|
{
|
||||||
// store a maximum of 2 additional palettes in SonicPal
|
// store a maximum of 3 additional palettes in SonicPal
|
||||||
if (est->SonicPalCount < 2 &&
|
if (est->SonicPalCount < 3 &&
|
||||||
(!(est->rendstatus & PDRAW_SONIC_MODE) || (line - dirty_line > 4))) {
|
(!(est->rendstatus & PDRAW_SONIC_MODE) || (line - dirty_line >= 4))) {
|
||||||
est->SonicPalCount ++;
|
est->SonicPalCount ++;
|
||||||
dirty_line = line;
|
dirty_line = line;
|
||||||
est->rendstatus |= PDRAW_SONIC_MODE;
|
est->rendstatus |= PDRAW_SONIC_MODE;
|
||||||
|
@ -1753,11 +1752,11 @@ void FinalizeLine8bit(int sh, int line, struct PicoEState *est)
|
||||||
}
|
}
|
||||||
|
|
||||||
len = 256;
|
len = 256;
|
||||||
if ((PicoIn.AHW & PAHW_GG) && (Pico.m.hardware & PMS_HW_LCD))
|
if (!(PicoIn.AHW & PAHW_8BIT) && (Pico.video.reg[12]&1))
|
||||||
len = 160;
|
|
||||||
else if (!(PicoIn.AHW & PAHW_SMS) && (Pico.video.reg[12]&1))
|
|
||||||
len = 320;
|
len = 320;
|
||||||
if ((PicoIn.AHW & PAHW_SMS) && (Pico.video.reg[0] & 0x20) && len == 256)
|
else if ((PicoIn.AHW & PAHW_GG) && (Pico.m.hardware & PMS_HW_LCD))
|
||||||
|
len = 160;
|
||||||
|
else if ((PicoIn.AHW & PAHW_SMS) && (Pico.video.reg[0] & 0x20))
|
||||||
len -= 8, ps += 8;
|
len -= 8, ps += 8;
|
||||||
|
|
||||||
if (DrawLineDestIncrement == 0)
|
if (DrawLineDestIncrement == 0)
|
||||||
|
@ -1897,7 +1896,7 @@ static int DrawDisplay(int sh)
|
||||||
for (a = 0, c = HighCacheA; *c; c+=2, a++);
|
for (a = 0, c = HighCacheA; *c; c+=2, a++);
|
||||||
for (b = 0, c = HighCacheB; *c; c+=2, b++);
|
for (b = 0, c = HighCacheB; *c; c+=2, b++);
|
||||||
printf("%i:%03i: a=%i, b=%i\n", Pico.m.frame_count,
|
printf("%i:%03i: a=%i, b=%i\n", Pico.m.frame_count,
|
||||||
Pico.est.DrawScanline, a, b);
|
est->DrawScanline, a, b);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1907,57 +1906,59 @@ static int DrawDisplay(int sh)
|
||||||
// MUST be called every frame
|
// MUST be called every frame
|
||||||
PICO_INTERNAL void PicoFrameStart(void)
|
PICO_INTERNAL void PicoFrameStart(void)
|
||||||
{
|
{
|
||||||
|
struct PicoEState *est = &Pico.est;
|
||||||
int loffs = 8, lines = 224, coffs = 0, columns = 320;
|
int loffs = 8, lines = 224, coffs = 0, columns = 320;
|
||||||
int sprep = Pico.est.rendstatus & (PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES);
|
int sprep = est->rendstatus & PDRAW_DIRTY_SPRITES;
|
||||||
int skipped = Pico.est.rendstatus & PDRAW_SKIP_FRAME;
|
int skipped = est->rendstatus & PDRAW_SKIP_FRAME;
|
||||||
|
|
||||||
// prepare to do this frame
|
// prepare to do this frame
|
||||||
Pico.est.rendstatus = 0;
|
est->rendstatus = 0;
|
||||||
if ((Pico.video.reg[12] & 6) == 6)
|
if ((Pico.video.reg[12] & 6) == 6)
|
||||||
Pico.est.rendstatus |= PDRAW_INTERLACE; // interlace mode
|
est->rendstatus |= PDRAW_INTERLACE; // interlace mode
|
||||||
if (!(Pico.video.reg[12] & 1)) {
|
if (!(Pico.video.reg[12] & 1)) {
|
||||||
Pico.est.rendstatus |= PDRAW_32_COLS;
|
est->rendstatus |= PDRAW_32_COLS;
|
||||||
if (!(PicoIn.opt & POPT_EN_SOFTSCALE)) {
|
if (!(PicoIn.opt & POPT_EN_SOFTSCALE)) {
|
||||||
columns = 256;
|
columns = 256;
|
||||||
coffs = 32;
|
coffs = 32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Pico.video.reg[1] & 8) {
|
if (Pico.video.reg[1] & 8) {
|
||||||
Pico.est.rendstatus |= PDRAW_30_ROWS;
|
est->rendstatus |= PDRAW_30_ROWS;
|
||||||
lines = 240;
|
lines = 240;
|
||||||
loffs = 0;
|
loffs = 0;
|
||||||
}
|
}
|
||||||
if (PicoIn.opt & POPT_DIS_32C_BORDER)
|
if (PicoIn.opt & POPT_DIS_32C_BORDER)
|
||||||
coffs = 0;
|
coffs = 0;
|
||||||
|
|
||||||
if (Pico.est.rendstatus != rendstatus_old || lines != rendlines) {
|
if (est->rendstatus != rendstatus_old || lines != rendlines) {
|
||||||
rendlines = lines;
|
rendlines = lines;
|
||||||
// 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 = Pico.est.rendstatus;
|
rendstatus_old = est->rendstatus & (PDRAW_INTERLACE|PDRAW_32_COLS|PDRAW_30_ROWS);
|
||||||
}
|
}
|
||||||
if (PicoIn.skipFrame) // preserve this until something is rendered at last
|
if (PicoIn.skipFrame) // preserve this until something is rendered at last
|
||||||
Pico.est.rendstatus |= PDRAW_SKIP_FRAME;
|
est->rendstatus |= PDRAW_SKIP_FRAME;
|
||||||
if (sprep | skipped)
|
if (sprep | skipped)
|
||||||
Pico.est.rendstatus |= PDRAW_PARSE_SPRITES;
|
est->rendstatus |= PDRAW_PARSE_SPRITES;
|
||||||
if (PicoIn.AHW & PAHW_32X)
|
if (PicoIn.AHW & PAHW_32X)
|
||||||
Pico.est.rendstatus |= PDRAW_32X_SCALE;
|
est->rendstatus |= PDRAW_32X_SCALE;
|
||||||
|
|
||||||
Pico.est.HighCol = HighColBase + loffs * HighColIncrement;
|
est->HighCol = HighColBase + loffs * HighColIncrement;
|
||||||
Pico.est.DrawLineDest = (char *)DrawLineDestBase + loffs * DrawLineDestIncrement;
|
est->DrawLineDest = (char *)DrawLineDestBase + loffs * DrawLineDestIncrement;
|
||||||
Pico.est.DrawScanline = 0;
|
est->DrawScanline = 0;
|
||||||
skip_next_line = 0;
|
skip_next_line = 0;
|
||||||
|
|
||||||
if (FinalizeLine == FinalizeLine8bit) {
|
if (FinalizeLine == FinalizeLine8bit) {
|
||||||
// make a backup of the current palette in case Sonic mode is detected later
|
// make a backup of the current palette in case Sonic mode is detected later
|
||||||
Pico.m.dirtyPal = (Pico.m.dirtyPal || Pico.est.SonicPalCount ? 2 : 0);
|
Pico.m.dirtyPal = (Pico.m.dirtyPal || est->SonicPalCount ? 2 : 0);
|
||||||
blockcpy(Pico.est.SonicPal, PicoMem.cram, 0x40*2);
|
blockcpy(est->SonicPal, PicoMem.cram, 0x40*2);
|
||||||
}
|
}
|
||||||
Pico.est.SonicPalCount = 0;
|
est->SonicPalCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawBlankedLine(int line, int offs, int sh, int bgc)
|
static void DrawBlankedLine(int line, int offs, int sh, int bgc)
|
||||||
{
|
{
|
||||||
|
struct PicoEState *est = &Pico.est;
|
||||||
int skip = skip_next_line;
|
int skip = skip_next_line;
|
||||||
|
|
||||||
if (PicoScanBegin != NULL && skip == 0)
|
if (PicoScanBegin != NULL && skip == 0)
|
||||||
|
@ -1968,23 +1969,24 @@ static void DrawBlankedLine(int line, int offs, int sh, int bgc)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BackFill(bgc, sh, &Pico.est);
|
BackFill(bgc, sh, est);
|
||||||
|
|
||||||
if (FinalizeLine != NULL)
|
if (FinalizeLine != NULL)
|
||||||
FinalizeLine(sh, line, &Pico.est);
|
FinalizeLine(sh, line, est);
|
||||||
|
|
||||||
if (PicoScanEnd != NULL)
|
if (PicoScanEnd != NULL)
|
||||||
skip_next_line = PicoScanEnd(line + offs);
|
skip_next_line = PicoScanEnd(line + offs);
|
||||||
|
|
||||||
Pico.est.HighCol += HighColIncrement;
|
est->HighCol += HighColIncrement;
|
||||||
Pico.est.DrawLineDest = (char *)Pico.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)
|
||||||
{
|
{
|
||||||
|
struct PicoEState *est = &Pico.est;
|
||||||
int skip = skip_next_line;
|
int skip = skip_next_line;
|
||||||
|
|
||||||
Pico.est.DrawScanline = line;
|
est->DrawScanline = line;
|
||||||
if (PicoScanBegin != NULL && skip == 0)
|
if (PicoScanBegin != NULL && skip == 0)
|
||||||
skip = PicoScanBegin(line + offs);
|
skip = PicoScanBegin(line + offs);
|
||||||
|
|
||||||
|
@ -1997,18 +1999,18 @@ static void PicoLine(int line, int offs, int sh, int bgc)
|
||||||
bgc = 0x3f;
|
bgc = 0x3f;
|
||||||
|
|
||||||
// Draw screen:
|
// Draw screen:
|
||||||
BackFill(bgc, sh, &Pico.est);
|
BackFill(bgc, sh, est);
|
||||||
if (Pico.video.reg[1]&0x40)
|
if (Pico.video.reg[1]&0x40)
|
||||||
DrawDisplay(sh);
|
DrawDisplay(sh);
|
||||||
|
|
||||||
if (FinalizeLine != NULL)
|
if (FinalizeLine != NULL)
|
||||||
FinalizeLine(sh, line, &Pico.est);
|
FinalizeLine(sh, line, est);
|
||||||
|
|
||||||
if (PicoScanEnd != NULL)
|
if (PicoScanEnd != NULL)
|
||||||
skip_next_line = PicoScanEnd(line + offs);
|
skip_next_line = PicoScanEnd(line + offs);
|
||||||
|
|
||||||
Pico.est.HighCol += HighColIncrement;
|
est->HighCol += HighColIncrement;
|
||||||
Pico.est.DrawLineDest = (char *)Pico.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 blank_last_line, int limit_sprites)
|
||||||
|
@ -2016,7 +2018,7 @@ void PicoDrawSync(int to, int blank_last_line, int limit_sprites)
|
||||||
struct PicoEState *est = &Pico.est;
|
struct PicoEState *est = &Pico.est;
|
||||||
int line, offs = 0;
|
int line, offs = 0;
|
||||||
int sh = (Pico.video.reg[0xC] & 8) >> 3; // shadow/hilight?
|
int sh = (Pico.video.reg[0xC] & 8) >> 3; // shadow/hilight?
|
||||||
int bgc = Pico.video.reg[7];
|
int bgc = Pico.video.reg[7] & 0x3f;
|
||||||
|
|
||||||
pprof_start(draw);
|
pprof_start(draw);
|
||||||
|
|
||||||
|
@ -2025,8 +2027,8 @@ void PicoDrawSync(int to, int blank_last_line, int limit_sprites)
|
||||||
if (to > 223)
|
if (to > 223)
|
||||||
to = 223;
|
to = 223;
|
||||||
}
|
}
|
||||||
if (est->DrawScanline <= to && (est->rendstatus &
|
if (est->DrawScanline <= to &&
|
||||||
(PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES|PDRAW_PARSE_SPRITES)))
|
(est->rendstatus & (PDRAW_DIRTY_SPRITES|PDRAW_PARSE_SPRITES)))
|
||||||
ParseSprites(to + 1, limit_sprites);
|
ParseSprites(to + 1, limit_sprites);
|
||||||
|
|
||||||
for (line = est->DrawScanline; line < to; line++)
|
for (line = est->DrawScanline; line < to; line++)
|
||||||
|
@ -2045,12 +2047,13 @@ void PicoDrawSync(int to, int blank_last_line, int limit_sprites)
|
||||||
pprof_end(draw);
|
pprof_end(draw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PicoDrawRefreshSprites()
|
void PicoDrawRefreshSprites(void)
|
||||||
{
|
{
|
||||||
unsigned char *sprited = &HighLnSpr[Pico.est.DrawScanline][0];
|
struct PicoEState *est = &Pico.est;
|
||||||
|
unsigned char *sprited = &HighLnSpr[est->DrawScanline][0];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (Pico.est.DrawScanline == 0 || Pico.est.DrawScanline >= rendlines) return;
|
if (est->DrawScanline == 0 || est->DrawScanline >= rendlines) return;
|
||||||
|
|
||||||
// compute sprite row. The VDP does this by subtracting the sprite y pos from
|
// compute sprite row. The VDP does this by subtracting the sprite y pos from
|
||||||
// the current line and treating the lower 5 bits as the row number. Y pos
|
// the current line and treating the lower 5 bits as the row number. Y pos
|
||||||
|
@ -2062,7 +2065,7 @@ void PicoDrawRefreshSprites()
|
||||||
int sy = (CPU_LE2(VdpSATCache[2*link]) & 0x1ff) - 0x80;
|
int sy = (CPU_LE2(VdpSATCache[2*link]) & 0x1ff) - 0x80;
|
||||||
if (sy != (s16)sp[0]) {
|
if (sy != (s16)sp[0]) {
|
||||||
// Y info in SAT cache has really changed
|
// Y info in SAT cache has really changed
|
||||||
sy = Pico.est.DrawScanline - ((Pico.est.DrawScanline - sy) & 0x1f);
|
sy = est->DrawScanline - ((est->DrawScanline - sy) & 0x1f);
|
||||||
sp[0] = (sp[0] & 0xffff0000) | (u16)sy;
|
sp[0] = (sp[0] & 0xffff0000) | (u16)sy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2089,8 +2092,8 @@ void PicoDrawUpdateHighPal(void)
|
||||||
blockcpy(est->HighPal+0x40, est->HighPal, 0x40*2);
|
blockcpy(est->HighPal+0x40, est->HighPal, 0x40*2);
|
||||||
blockcpy(est->HighPal+0x80, est->HighPal, 0x80*2);
|
blockcpy(est->HighPal+0x80, est->HighPal, 0x80*2);
|
||||||
}
|
}
|
||||||
Pico.est.HighPal[0xe0] = 0x0000; // black and white, reserved for OSD
|
est->HighPal[0xe0] = 0x0000; // black and white, reserved for OSD
|
||||||
Pico.est.HighPal[0xf0] = 0xffff;
|
est->HighPal[0xf0] = 0xffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,7 @@
|
||||||
|
|
||||||
.extern DrawStripInterlace
|
.extern DrawStripInterlace
|
||||||
|
|
||||||
.equ PDRAW_SPRITES_MOVED, (1<<0)
|
|
||||||
.equ PDRAW_WND_DIFF_PRIO, (1<<1)
|
.equ PDRAW_WND_DIFF_PRIO, (1<<1)
|
||||||
.equ PDRAW_PARSE_SPRITES, (1<<2)
|
|
||||||
.equ PDRAW_DIRTY_SPRITES, (1<<4)
|
|
||||||
.equ PDRAW_PLANE_HI_PRIO, (1<<6)
|
.equ PDRAW_PLANE_HI_PRIO, (1<<6)
|
||||||
.equ PDRAW_SHHI_DONE, (1<<7)
|
.equ PDRAW_SHHI_DONE, (1<<7)
|
||||||
.equ PDRAW_32X_SCALE, (1<<12)
|
.equ PDRAW_32X_SCALE, (1<<12)
|
||||||
|
@ -800,11 +797,7 @@ DrawLayer:
|
||||||
BackFill:
|
BackFill:
|
||||||
stmfd sp!, {r4-r9,lr}
|
stmfd sp!, {r4-r9,lr}
|
||||||
|
|
||||||
mov r0, r0, lsl #26
|
|
||||||
ldr lr, [r2, #OFS_EST_HighCol]
|
ldr lr, [r2, #OFS_EST_HighCol]
|
||||||
mov r0, r0, lsr #26
|
|
||||||
add lr, lr, #8
|
|
||||||
|
|
||||||
orr r0, r0, r1, lsl #7
|
orr r0, r0, r1, lsl #7
|
||||||
orr r0, r0, r0, lsl #8
|
orr r0, r0, r0, lsl #8
|
||||||
orr r0, r0, r0, lsl #16
|
orr r0, r0, r0, lsl #16
|
||||||
|
@ -818,6 +811,7 @@ BackFill:
|
||||||
mov r7, r0
|
mov r7, r0
|
||||||
|
|
||||||
@ go go go!
|
@ go go go!
|
||||||
|
add lr, lr, #8
|
||||||
stmia lr!, {r0-r7} @ 10*8*4
|
stmia lr!, {r0-r7} @ 10*8*4
|
||||||
stmia lr!, {r0-r7}
|
stmia lr!, {r0-r7}
|
||||||
stmia lr!, {r0-r7}
|
stmia lr!, {r0-r7}
|
||||||
|
|
|
@ -82,10 +82,12 @@ extern void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
|
||||||
#define PAHW_32X (1<<1)
|
#define PAHW_32X (1<<1)
|
||||||
#define PAHW_SVP (1<<2)
|
#define PAHW_SVP (1<<2)
|
||||||
#define PAHW_PICO (1<<3)
|
#define PAHW_PICO (1<<3)
|
||||||
|
|
||||||
#define PAHW_SMS (1<<4)
|
#define PAHW_SMS (1<<4)
|
||||||
#define PAHW_GG (1<<5)
|
#define PAHW_GG (1<<5)
|
||||||
#define PAHW_SG (1<<6)
|
#define PAHW_SG (1<<6)
|
||||||
#define PAHW_SC (1<<7)
|
#define PAHW_SC (1<<7)
|
||||||
|
#define PAHW_8BIT (PAHW_SMS|PAHW_GG|PAHW_SG|PAHW_SC)
|
||||||
|
|
||||||
#define PHWS_AUTO 0
|
#define PHWS_AUTO 0
|
||||||
#define PHWS_GG 1
|
#define PHWS_GG 1
|
||||||
|
@ -221,7 +223,6 @@ 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_SPRITES_MOVED (1<<0) // SAT address modified
|
|
||||||
#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)
|
||||||
|
|
|
@ -694,6 +694,7 @@ int CM_compareRun(int cyc, int is_sub);
|
||||||
// draw.c
|
// draw.c
|
||||||
void PicoDrawInit(void);
|
void PicoDrawInit(void);
|
||||||
PICO_INTERNAL void PicoFrameStart(void);
|
PICO_INTERNAL void PicoFrameStart(void);
|
||||||
|
void PicoDrawRefreshSprites(void);
|
||||||
void PicoDrawSync(int to, int blank_last_line, int limit_sprites);
|
void PicoDrawSync(int to, int blank_last_line, int limit_sprites);
|
||||||
void BackFill(int reg7, int sh, struct PicoEState *est);
|
void BackFill(int reg7, int sh, struct PicoEState *est);
|
||||||
void FinalizeLine555(int sh, int line, struct PicoEState *est);
|
void FinalizeLine555(int sh, int line, struct PicoEState *est);
|
||||||
|
|
|
@ -191,6 +191,7 @@ static struct VdpFIFO { // XXX this must go into save file!
|
||||||
|
|
||||||
const unsigned short *fifo_cyc2sl;
|
const unsigned short *fifo_cyc2sl;
|
||||||
const unsigned short *fifo_sl2cyc;
|
const unsigned short *fifo_sl2cyc;
|
||||||
|
const unsigned char *fifo_hcounts;
|
||||||
} VdpFIFO;
|
} VdpFIFO;
|
||||||
|
|
||||||
enum { FQ_BYTE = 1, FQ_BGDMA = 2, FQ_FGDMA = 4 }; // queue flags, NB: BYTE = 1!
|
enum { FQ_BYTE = 1, FQ_BGDMA = 2, FQ_FGDMA = 4 }; // queue flags, NB: BYTE = 1!
|
||||||
|
@ -198,8 +199,8 @@ enum { FQ_BYTE = 1, FQ_BGDMA = 2, FQ_FGDMA = 4 }; // queue flags, NB: BYTE = 1!
|
||||||
|
|
||||||
// NB should limit cyc2sl to table size in case 68k overdraws its aim. That can
|
// NB should limit cyc2sl to table size in case 68k overdraws its aim. That can
|
||||||
// happen if the last op is a blocking acess to VDP, or for exceptions (e.g.irq)
|
// happen if the last op is a blocking acess to VDP, or for exceptions (e.g.irq)
|
||||||
#define Cyc2Sl(vf,lc) (vf->fifo_cyc2sl[(lc)/clkdiv])
|
#define Cyc2Sl(vf,lc) ((vf)->fifo_cyc2sl[(lc)/clkdiv])
|
||||||
#define Sl2Cyc(vf,sl) (vf->fifo_sl2cyc[sl]*clkdiv)
|
#define Sl2Cyc(vf,sl) ((vf)->fifo_sl2cyc[sl]*clkdiv)
|
||||||
|
|
||||||
// do the FIFO math
|
// do the FIFO math
|
||||||
static int AdvanceFIFOEntry(struct VdpFIFO *vf, struct PicoVideo *pv, int slots)
|
static int AdvanceFIFOEntry(struct VdpFIFO *vf, struct PicoVideo *pv, int slots)
|
||||||
|
@ -389,6 +390,7 @@ int PicoVideoFIFOHint(void)
|
||||||
|
|
||||||
// reset slot to start of scanline
|
// reset slot to start of scanline
|
||||||
vf->fifo_slot = 0;
|
vf->fifo_slot = 0;
|
||||||
|
// only need to refresh sprite position if we are synced
|
||||||
if (Pico.est.DrawScanline == Pico.m.scanline)
|
if (Pico.est.DrawScanline == Pico.m.scanline)
|
||||||
PicoDrawRefreshSprites();
|
PicoDrawRefreshSprites();
|
||||||
|
|
||||||
|
@ -408,6 +410,8 @@ void PicoVideoFIFOMode(int active, int h40)
|
||||||
{ {vdpcyc2sl_32_bl, vdpcyc2sl_40_bl},{vdpcyc2sl_32_ac, vdpcyc2sl_40_ac} };
|
{ {vdpcyc2sl_32_bl, vdpcyc2sl_40_bl},{vdpcyc2sl_32_ac, vdpcyc2sl_40_ac} };
|
||||||
static const unsigned short *vdpsl2cyc[2][2] =
|
static const unsigned short *vdpsl2cyc[2][2] =
|
||||||
{ {vdpsl2cyc_32_bl, vdpsl2cyc_40_bl},{vdpsl2cyc_32_ac, vdpsl2cyc_40_ac} };
|
{ {vdpsl2cyc_32_bl, vdpsl2cyc_40_bl},{vdpsl2cyc_32_ac, vdpsl2cyc_40_ac} };
|
||||||
|
static const unsigned char *vdphcounts[2] =
|
||||||
|
{ hcounts_32, hcounts_40 };
|
||||||
|
|
||||||
struct VdpFIFO *vf = &VdpFIFO;
|
struct VdpFIFO *vf = &VdpFIFO;
|
||||||
struct PicoVideo *pv = &Pico.video;
|
struct PicoVideo *pv = &Pico.video;
|
||||||
|
@ -419,6 +423,7 @@ void PicoVideoFIFOMode(int active, int h40)
|
||||||
|
|
||||||
vf->fifo_cyc2sl = vdpcyc2sl[active][h40];
|
vf->fifo_cyc2sl = vdpcyc2sl[active][h40];
|
||||||
vf->fifo_sl2cyc = vdpsl2cyc[active][h40];
|
vf->fifo_sl2cyc = vdpsl2cyc[active][h40];
|
||||||
|
vf->fifo_hcounts = vdphcounts[h40];
|
||||||
// recalculate FIFO slot for new mode
|
// recalculate FIFO slot for new mode
|
||||||
vf->fifo_slot = Cyc2Sl(vf, lc);
|
vf->fifo_slot = Cyc2Sl(vf, lc);
|
||||||
vf->fifo_maxslot = Cyc2Sl(vf, 488);
|
vf->fifo_maxslot = Cyc2Sl(vf, 488);
|
||||||
|
@ -508,7 +513,7 @@ static int GetDmaLength(void)
|
||||||
static void DmaSlow(int len, u32 source)
|
static void DmaSlow(int len, u32 source)
|
||||||
{
|
{
|
||||||
u32 inc = Pico.video.reg[0xf];
|
u32 inc = Pico.video.reg[0xf];
|
||||||
u32 a = Pico.video.addr | (Pico.video.addr_u << 16);
|
u32 a = Pico.video.addr | (Pico.video.addr_u << 16), e;
|
||||||
u16 *r, *base = NULL;
|
u16 *r, *base = NULL;
|
||||||
u32 mask = 0x1ffff;
|
u32 mask = 0x1ffff;
|
||||||
|
|
||||||
|
@ -568,10 +573,11 @@ static void DmaSlow(int len, u32 source)
|
||||||
switch (Pico.video.type)
|
switch (Pico.video.type)
|
||||||
{
|
{
|
||||||
case 1: // vram
|
case 1: // vram
|
||||||
|
e = a + len*2-1;
|
||||||
r = PicoMem.vram;
|
r = PicoMem.vram;
|
||||||
if (inc == 2 && !(a & 1) && (a & ~0xffff) == ((a + len*2-1) & ~0xffff) &&
|
if (inc == 2 && !(a & 1) && !((a ^ e) >> 16) &&
|
||||||
((a >= SATaddr+0x280) | ((a + len*2-1) < SATaddr)) &&
|
((a >= SATaddr + 0x280) | (e < SATaddr)) &&
|
||||||
(source & ~mask) == ((source + len-1) & ~mask))
|
!((source ^ (source + len-1)) & ~mask))
|
||||||
{
|
{
|
||||||
// most used DMA mode
|
// most used DMA mode
|
||||||
memcpy((char *)r + a, base + (source & mask), len * 2);
|
memcpy((char *)r + a, base + (source & mask), len * 2);
|
||||||
|
@ -659,7 +665,7 @@ static void DmaCopy(int len)
|
||||||
|
|
||||||
static NOINLINE void DmaFill(int data)
|
static NOINLINE void DmaFill(int data)
|
||||||
{
|
{
|
||||||
u32 a = Pico.video.addr | (Pico.video.addr_u << 16);
|
u32 a = Pico.video.addr | (Pico.video.addr_u << 16), e;
|
||||||
u8 *vr = (u8 *)PicoMem.vram;
|
u8 *vr = (u8 *)PicoMem.vram;
|
||||||
u8 high = (u8)(data >> 8);
|
u8 high = (u8)(data >> 8);
|
||||||
u8 inc = Pico.video.reg[0xf];
|
u8 inc = Pico.video.reg[0xf];
|
||||||
|
@ -675,8 +681,9 @@ static NOINLINE void DmaFill(int data)
|
||||||
switch (Pico.video.type)
|
switch (Pico.video.type)
|
||||||
{
|
{
|
||||||
case 1: // vram
|
case 1: // vram
|
||||||
if (inc == 1 && (a & ~0xffff) == ((a + len-1) & ~0xffff) &&
|
e = a + len-1;
|
||||||
((a >= SATaddr+0x280) | ((a + len-1) < SATaddr)))
|
if (inc == 1 && !((a ^ e) >> 16) &&
|
||||||
|
((a >= SATaddr + 0x280) | (e < SATaddr)))
|
||||||
{
|
{
|
||||||
// most used DMA mode
|
// most used DMA mode
|
||||||
memset(vr + (u16)a, high, len);
|
memset(vr + (u16)a, high, len);
|
||||||
|
@ -798,7 +805,8 @@ static NOINLINE void CommandChange(struct PicoVideo *pvid)
|
||||||
|
|
||||||
static inline int InHblank(int offs)
|
static inline int InHblank(int offs)
|
||||||
{
|
{
|
||||||
return SekCyclesDone() - Pico.t.m68c_line_start <= 488-offs;
|
// check if in left border (14 pixels) or HBLANK (86 pixels), 116 68k cycles
|
||||||
|
return SekCyclesDone() - Pico.t.m68c_line_start <= offs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawSync(int skip)
|
static void DrawSync(int skip)
|
||||||
|
@ -835,12 +843,13 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d)
|
||||||
pvid->pending=0;
|
pvid->pending=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// try avoiding the sync. can't easily do this for VRAM writes since they
|
// try avoiding the sync if the data doesn't change.
|
||||||
// might update the SAT cache
|
// Writes to the SAT in VRAM are special since they update the SAT cache.
|
||||||
if (Pico.m.scanline < (pvid->reg[1]&0x08 ? 240 : 224) && (pvid->reg[1]&0x40) &&
|
if ((pvid->reg[1]&0x40) &&
|
||||||
|
!(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(440)); // experimentally, Overdrive 2
|
DrawSync(InHblank(48)); // experimentally, Overdrive 2
|
||||||
|
|
||||||
if (!(PicoIn.opt&POPT_DIS_VDP_FIFO))
|
if (!(PicoIn.opt&POPT_DIS_VDP_FIFO))
|
||||||
{
|
{
|
||||||
|
@ -872,7 +881,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(390));
|
DrawSync(InHblank(93));
|
||||||
CommandDma();
|
CommandDma();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -889,12 +898,13 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)) {
|
if (num == 1 && ((pvid->reg[1]^d)&0x40)) {
|
||||||
PicoVideoFIFOMode(d & 0x40, pvid->reg[12]&1);
|
PicoVideoFIFOMode(d & 0x40, pvid->reg[12]&1);
|
||||||
// handle line blanking before line rendering
|
// handle line blanking before line rendering
|
||||||
if (InHblank(390)) {
|
if (InHblank(93)) {
|
||||||
// sprite rendering is limited if display is disabled and reenabled
|
// sprite rendering is limited if display is disabled and reenabled
|
||||||
// in HBLANK of the same scanline (Overdrive)
|
// in HBLANK of the same scanline (Overdrive)
|
||||||
limitsprites = (d&0x40) && blankline == Pico.m.scanline ? Pico.m.scanline : -1;
|
limitsprites = (d&0x40) && blankline == Pico.m.scanline ? Pico.m.scanline : -1;
|
||||||
|
@ -903,10 +913,10 @@ 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) // no sync needed for DMA setup registers
|
if (num <= 18 && pvid->reg[num] != d) // no sync for DMA setup
|
||||||
DrawSync(InHblank(390));
|
DrawSync(InHblank(93)); // Toy Story
|
||||||
d &= 0xff;
|
pvid->reg[num]=d;
|
||||||
pvid->reg[num]=(unsigned char)d;
|
|
||||||
switch (num)
|
switch (num)
|
||||||
{
|
{
|
||||||
case 0x00:
|
case 0x00:
|
||||||
|
@ -922,7 +932,7 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d)
|
||||||
goto update_irq;
|
goto update_irq;
|
||||||
case 0x05:
|
case 0x05:
|
||||||
case 0x06:
|
case 0x06:
|
||||||
if (d^dold) Pico.est.rendstatus |= PDRAW_SPRITES_MOVED;
|
if (d^dold) Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;
|
||||||
break;
|
break;
|
||||||
case 0x0c:
|
case 0x0c:
|
||||||
// renderers should update their palettes if sh/hi mode is changed
|
// renderers should update their palettes if sh/hi mode is changed
|
||||||
|
@ -1039,9 +1049,7 @@ PICO_INTERNAL_ASM u32 PicoVideoRead(u32 a)
|
||||||
c = SekCyclesDone() - Pico.t.m68c_line_start;
|
c = SekCyclesDone() - Pico.t.m68c_line_start;
|
||||||
if (Pico.video.reg[0]&2)
|
if (Pico.video.reg[0]&2)
|
||||||
d = Pico.video.hv_latch;
|
d = Pico.video.hv_latch;
|
||||||
else if (Pico.video.reg[12]&1)
|
else d = VdpFIFO.fifo_hcounts[c/clkdiv] | (Pico.video.v_counter << 8);
|
||||||
d = hcounts_40[c/clkdiv] | (Pico.video.v_counter << 8);
|
|
||||||
else d = hcounts_32[c/clkdiv] | (Pico.video.v_counter << 8);
|
|
||||||
|
|
||||||
elprintf(EL_HVCNT, "hv: %02x %02x [%u] @ %06x", d, Pico.video.v_counter, SekCyclesDone(), SekPc);
|
elprintf(EL_HVCNT, "hv: %02x %02x [%u] @ %06x", d, Pico.video.v_counter, SekCyclesDone(), SekPc);
|
||||||
return d;
|
return d;
|
||||||
|
@ -1101,9 +1109,7 @@ unsigned char PicoVideoRead8HV_L(int is_from_z80)
|
||||||
u32 d = SekCyclesDone() - Pico.t.m68c_line_start;
|
u32 d = SekCyclesDone() - Pico.t.m68c_line_start;
|
||||||
if (Pico.video.reg[0]&2)
|
if (Pico.video.reg[0]&2)
|
||||||
d = Pico.video.hv_latch;
|
d = Pico.video.hv_latch;
|
||||||
else if (Pico.video.reg[12]&1)
|
else d = VdpFIFO.fifo_hcounts[d/clkdiv];
|
||||||
d = hcounts_40[d/clkdiv];
|
|
||||||
else d = hcounts_32[d/clkdiv];
|
|
||||||
elprintf(EL_HVCNT, "hcounter: %02x [%u] @ %06x", d, SekCyclesDone(), SekPc);
|
elprintf(EL_HVCNT, "hcounter: %02x [%u] @ %06x", d, SekCyclesDone(), SekPc);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
@ -1125,7 +1131,7 @@ void PicoVideoCacheSAT(int load)
|
||||||
((u16 *)VdpSATCache)[l*2 + 1] = PicoMem.vram[(addr>>1) + 1];
|
((u16 *)VdpSATCache)[l*2 + 1] = PicoMem.vram[(addr>>1) + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
Pico.est.rendstatus |= PDRAW_SPRITES_MOVED;
|
Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PicoVideoSave(void)
|
void PicoVideoSave(void)
|
||||||
|
|
|
@ -1251,7 +1251,6 @@ void emu_cmn_forced_frame(int no_scale, int do_emu, void *buf)
|
||||||
PicoDrawSetOutFormat(PDF_RGB555, 1);
|
PicoDrawSetOutFormat(PDF_RGB555, 1);
|
||||||
PicoDrawSetOutBuf(buf, g_screen_ppitch * 2);
|
PicoDrawSetOutBuf(buf, g_screen_ppitch * 2);
|
||||||
Pico.m.dirtyPal = 1;
|
Pico.m.dirtyPal = 1;
|
||||||
Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;
|
|
||||||
if (do_emu)
|
if (do_emu)
|
||||||
PicoFrame();
|
PicoFrame();
|
||||||
else
|
else
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 1889fe241c1c6059f8955a331dd07f08a47cd0b4
|
Subproject commit 7b58e15633b54621f9508cb673da61a6b0844955
|
Loading…
Add table
Add a link
Reference in a new issue