mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00
core, handle background color DMA (aka fantom bitmap)
This commit is contained in:
parent
68e06234e3
commit
724db457da
4 changed files with 97 additions and 1 deletions
86
pico/draw.c
86
pico/draw.c
|
@ -1599,7 +1599,59 @@ void BackFill(int bgc, int sh, struct PicoEState *est)
|
||||||
|
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
|
|
||||||
void PicoDoHighPal555_8bit(int sh, int line, struct PicoEState *est)
|
static u16 *BgcDMAbase;
|
||||||
|
static u32 BgcDMAsrc, BgcDMAmask;
|
||||||
|
static int BgcDMAlen, BgcDMAoffs;
|
||||||
|
|
||||||
|
#ifndef _ASM_DRAW_C
|
||||||
|
static
|
||||||
|
#endif
|
||||||
|
// handle DMA to background color
|
||||||
|
int BgcDMA(u16 *pd, int len, struct PicoEState *est)
|
||||||
|
{
|
||||||
|
int xl = (len == 320 ? 38 : 33); // DMA slots during HSYNC
|
||||||
|
int upscale = (est->rendstatus & PDRAW_SOFTSCALE) && len < 320;
|
||||||
|
|
||||||
|
if (BgcDMAlen > 0) {
|
||||||
|
// BG color DMA under way. TODO for now handles the line as all background.
|
||||||
|
int i, l = len;
|
||||||
|
u16 *q = upscale ? DefOutBuff : pd;
|
||||||
|
u16 t;
|
||||||
|
|
||||||
|
if ((est->rendstatus & PDRAW_BORDER_32) && !upscale)
|
||||||
|
q += (320-len) / 2;
|
||||||
|
|
||||||
|
BgcDMAlen -= (l>>1)+xl;
|
||||||
|
if (BgcDMAlen < 0)
|
||||||
|
// partial line
|
||||||
|
l += 2*BgcDMAlen;
|
||||||
|
|
||||||
|
for (i = 0; i < l; i += 2) {
|
||||||
|
// TODO use ps to overwrite only real bg pixels
|
||||||
|
t = BgcDMAbase[BgcDMAsrc++ & BgcDMAmask];
|
||||||
|
q[i] = q[i+1] = PXCONV(t);
|
||||||
|
}
|
||||||
|
BgcDMAsrc += xl; // HSYNC DMA
|
||||||
|
|
||||||
|
t = est->HighPal[Pico.video.reg[7] & 0x3f];
|
||||||
|
while (i < len) q[i++] = t; // fill partial line with BG
|
||||||
|
|
||||||
|
if (upscale) {
|
||||||
|
switch (PicoIn.filter) {
|
||||||
|
case 3: h_upscale_bl4_4_5(pd, 320, q, 256, len, f_nop); break;
|
||||||
|
case 2: h_upscale_bl2_4_5(pd, 320, q, 256, len, f_nop); break;
|
||||||
|
case 1: h_upscale_snn_4_5(pd, 320, q, 256, len, f_nop); break;
|
||||||
|
default: h_upscale_nn_4_5(pd, 320, q, 256, len, f_nop); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------
|
||||||
|
|
||||||
|
static void PicoDoHighPal555_8bit(int sh, int line, struct PicoEState *est)
|
||||||
{
|
{
|
||||||
unsigned int *spal, *dpal;
|
unsigned int *spal, *dpal;
|
||||||
unsigned int cnt = (sh ? 1 : est->SonicPalCount+1);
|
unsigned int cnt = (sh ? 1 : est->SonicPalCount+1);
|
||||||
|
@ -1695,6 +1747,9 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est)
|
||||||
else if ((PicoIn.AHW & PAHW_SMS) && (est->Pico->video.reg[0] & 0x20))
|
else if ((PicoIn.AHW & PAHW_SMS) && (est->Pico->video.reg[0] & 0x20))
|
||||||
len -= 8, ps += 8;
|
len -= 8, ps += 8;
|
||||||
|
|
||||||
|
if (BgcDMA(pd, len, est))
|
||||||
|
return;
|
||||||
|
|
||||||
if ((est->rendstatus & PDRAW_SOFTSCALE) && len < 320) {
|
if ((est->rendstatus & PDRAW_SOFTSCALE) && len < 320) {
|
||||||
if (len >= 240 && len <= 256) {
|
if (len >= 240 && len <= 256) {
|
||||||
pd += (256-len)>>1;
|
pd += (256-len)>>1;
|
||||||
|
@ -2111,6 +2166,35 @@ void PicoDrawRefreshSprites(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PicoDrawBgcDMA(u16 *base, u32 source, u32 mask, int dlen, int sl)
|
||||||
|
{
|
||||||
|
struct PicoEState *est = &Pico.est;
|
||||||
|
int len = (est->Pico->video.reg[12]&1) ? 320 : 256;
|
||||||
|
int xl = (est->Pico->video.reg[12]&1) ? 38 : 33; // DMA slots during HSYNC
|
||||||
|
|
||||||
|
BgcDMAbase = base;
|
||||||
|
BgcDMAsrc = source;
|
||||||
|
BgcDMAmask = mask;
|
||||||
|
BgcDMAlen = dlen;
|
||||||
|
BgcDMAoffs = 0;
|
||||||
|
|
||||||
|
// handle slot offset in 1st line
|
||||||
|
if (sl-12 > 0) // active display output only starts at slot 12
|
||||||
|
BgcDMAoffs = 2*(sl-12);
|
||||||
|
else if (sl < 0) { // DMA starts before active display
|
||||||
|
BgcDMAsrc += 2*-sl;
|
||||||
|
BgcDMAlen -= 2*-sl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip 1st line if it had been drawn already
|
||||||
|
if (Pico.est.DrawScanline > Pico.m.scanline) {
|
||||||
|
len -= BgcDMAoffs;
|
||||||
|
BgcDMAsrc += (len>>1)+xl;
|
||||||
|
BgcDMAlen -= (len>>1)+xl;
|
||||||
|
BgcDMAoffs = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// also works for fast renderer
|
// also works for fast renderer
|
||||||
void PicoDrawUpdateHighPal(void)
|
void PicoDrawUpdateHighPal(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -190,6 +190,7 @@ int PicoReset(void)
|
||||||
|
|
||||||
// create an empty "dma" to cause 68k exec start at random frame location
|
// create an empty "dma" to cause 68k exec start at random frame location
|
||||||
Pico.t.m68c_line_start = Pico.t.m68c_aim;
|
Pico.t.m68c_line_start = Pico.t.m68c_aim;
|
||||||
|
PicoDrawBgcDMA(NULL, 0, 0, 0, 0);
|
||||||
PicoVideoFIFOWrite(rand() & 0x1fff, 0, 0, PVS_CPURD);
|
PicoVideoFIFOWrite(rand() & 0x1fff, 0, 0, PVS_CPURD);
|
||||||
|
|
||||||
SekFinishIdleDet();
|
SekFinishIdleDet();
|
||||||
|
|
|
@ -704,6 +704,7 @@ int CM_compareRun(int cyc, int is_sub);
|
||||||
void PicoDrawInit(void);
|
void PicoDrawInit(void);
|
||||||
PICO_INTERNAL void PicoFrameStart(void);
|
PICO_INTERNAL void PicoFrameStart(void);
|
||||||
void PicoDrawRefreshSprites(void);
|
void PicoDrawRefreshSprites(void);
|
||||||
|
void PicoDrawBgcDMA(u16 *base, u32 source, u32 mask, int len, int sl);
|
||||||
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);
|
||||||
|
|
|
@ -522,6 +522,7 @@ static void DmaSlow(int len, u32 source)
|
||||||
u32 a = Pico.video.addr | (Pico.video.addr_u << 16), e;
|
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;
|
||||||
|
int lc = SekCyclesDone()-Pico.t.m68c_line_start;
|
||||||
|
|
||||||
elprintf(EL_VDPDMA, "DmaSlow[%i] %06x->%04x len %i inc=%i blank %i [%u] @ %06x",
|
elprintf(EL_VDPDMA, "DmaSlow[%i] %06x->%04x len %i inc=%i blank %i [%u] @ %06x",
|
||||||
Pico.video.type, source, a, len, inc, (Pico.video.status&SR_VB)||!(Pico.video.reg[1]&0x40),
|
Pico.video.type, source, a, len, inc, (Pico.video.status&SR_VB)||!(Pico.video.reg[1]&0x40),
|
||||||
|
@ -603,6 +604,15 @@ static void DmaSlow(int len, u32 source)
|
||||||
case 3: // cram
|
case 3: // cram
|
||||||
Pico.m.dirtyPal = 1;
|
Pico.m.dirtyPal = 1;
|
||||||
r = PicoMem.cram;
|
r = PicoMem.cram;
|
||||||
|
if (inc == 0 && (Pico.video.reg[7] & 0x3f) == ((a/2) & 0x3f)) { // bg color DMA
|
||||||
|
PicoVideoSync(1);
|
||||||
|
int sl = VdpFIFO.fifo_hcounts[lc/clkdiv];
|
||||||
|
if (sl > VdpFIFO.fifo_hcounts[0]-5) // hint delay is 5 slots
|
||||||
|
sl = (s8)sl;
|
||||||
|
// TODO this is needed to cover timing inaccuracies
|
||||||
|
if (sl <= 12) sl = -2;
|
||||||
|
PicoDrawBgcDMA(base, source, mask, len, sl);
|
||||||
|
}
|
||||||
for (; len; len--)
|
for (; len; len--)
|
||||||
{
|
{
|
||||||
r[(a / 2) & 0x3f] = base[source++ & mask] & 0xeee;
|
r[(a / 2) & 0x3f] = base[source++ & mask] & 0xeee;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue