core+gp2x+psp, fix handling mid-frame palette changes

This commit is contained in:
kub 2021-11-10 23:06:08 +01:00
parent d05e2eb3d6
commit ace184013b
8 changed files with 82 additions and 51 deletions

View file

@ -1894,10 +1894,10 @@ PICO_INTERNAL void PicoFrameStart(void)
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.est.SonicPalCount = 0; Pico.m.dirtyPal = (Pico.m.dirtyPal || Pico.est.SonicPalCount ? 2 : 0);
Pico.m.dirtyPal = (Pico.m.dirtyPal ? 2 : 0); // mark as dirty but copied
blockcpy(Pico.est.SonicPal, PicoMem.cram, 0x40*2); blockcpy(Pico.est.SonicPal, PicoMem.cram, 0x40*2);
} }
Pico.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)

View file

@ -656,10 +656,10 @@ void PicoFrameStartSMS(void)
Pico.est.DrawLineDest = (char *)DrawLineDestBase + screen_offset * DrawLineDestIncrement; Pico.est.DrawLineDest = (char *)DrawLineDestBase + screen_offset * DrawLineDestIncrement;
if (FinalizeLineSMS == FinalizeLine8bitSMS) { if (FinalizeLineSMS == FinalizeLine8bitSMS) {
Pico.est.SonicPalCount = 0; Pico.m.dirtyPal = (Pico.m.dirtyPal || Pico.est.SonicPalCount ? 2 : 0);
Pico.m.dirtyPal = (Pico.m.dirtyPal ? 2 : 0); memcpy(Pico.est.SonicPal, PicoMem.cram, 0x40*2);
memcpy(Pico.est.SonicPal, PicoMem.cram, 0x20*2);
} }
Pico.est.SonicPalCount = 0;
} }
void PicoParseSATSMS(int line) void PicoParseSATSMS(int line)
@ -707,13 +707,12 @@ norender:
/* Fixed palette for TMS9918 modes */ /* Fixed palette for TMS9918 modes */
static u16 tmspal[32] = { static u16 tmspal[32] = {
#if 1 // SMS palette // SMS palette
0x0000, 0x0000, 0x00a0, 0x00f0, 0x0500, 0x0f00, 0x0005, 0x0ff0, 0x0000, 0x0000, 0x00a0, 0x00f0, 0x0500, 0x0f00, 0x0005, 0x0ff0,
0x000a, 0x000f, 0x0055, 0x00ff, 0x0050, 0x0f0f, 0x0555, 0x0fff, 0x000a, 0x000f, 0x0055, 0x00ff, 0x0050, 0x0f0f, 0x0555, 0x0fff,
#else // TMS palette // TMS palette
0x0000, 0x0000, 0x04c2, 0x07d5, 0x0e55, 0x0f77, 0x045d, 0x0fe4, 0x0000, 0x0000, 0x04c2, 0x07d5, 0x0e55, 0x0f77, 0x045d, 0x0fe4,
0x055f, 0x077f, 0x05cd, 0x08ce, 0x03b2, 0x0b5c, 0x0ccc, 0x0fff, 0x055f, 0x077f, 0x05cd, 0x08ce, 0x03b2, 0x0b5c, 0x0ccc, 0x0fff,
#endif
}; };
void PicoDoHighPal555SMS(void) void PicoDoHighPal555SMS(void)

View file

@ -56,18 +56,19 @@ static void vdp_data_write(unsigned char d)
struct PicoVideo *pv = &Pico.video; struct PicoVideo *pv = &Pico.video;
if (pv->type == 3) { if (pv->type == 3) {
// cram. 32 on SMS, but 64 on MD. Fill 2nd half of cram for prio bit mirror
if (Pico.m.hardware & 0x1) { // GG, same layout as MD if (Pico.m.hardware & 0x1) { // GG, same layout as MD
unsigned a = pv->addr & 0x3f; unsigned a = pv->addr & 0x3f;
if (a & 0x1) { // write complete color on high byte write if (a & 0x1) { // write complete color on high byte write
u16 c = ((d&0x0f) << 8) | Pico.ms.vdp_buffer; u16 c = ((d&0x0f) << 8) | Pico.ms.vdp_buffer;
if (PicoMem.cram[a >> 1] != c) Pico.m.dirtyPal = 1; if (PicoMem.cram[a >> 1] != c) Pico.m.dirtyPal = 1;
PicoMem.cram[a >> 1] = c; PicoMem.cram[a >> 1] = PicoMem.cram[(a >> 1)+0x20] = c;
} }
} else { // SMS, convert to MD layout (00BbGgRr to 0000BbBbGgGgRrRr) } else { // SMS, convert to MD layout (00BbGgRr to 0000BbBbGgGgRrRr)
unsigned a = pv->addr & 0x1f; unsigned a = pv->addr & 0x1f;
u16 c = ((d&0x30)<<6) + ((d&0x0c)<<4) + ((d&0x03)<<2); u16 c = ((d&0x30)<<6) + ((d&0x0c)<<4) + ((d&0x03)<<2);
if (PicoMem.cram[a] != (c | (c>>2))) Pico.m.dirtyPal = 1; if (PicoMem.cram[a] != (c | (c>>2))) Pico.m.dirtyPal = 1;
PicoMem.cram[a] = c | (c>>2); PicoMem.cram[a] = PicoMem.cram[a+0x20] = c | (c>>2);
} }
} else { } else {
PicoMem.vramb[MEM_LE2(pv->addr)] = d; PicoMem.vramb[MEM_LE2(pv->addr)] = d;

View file

@ -1,5 +1,5 @@
void bgr444_to_rgb32(void *to, void *from); void bgr444_to_rgb32(void *to, void *from, unsigned entries);
void bgr444_to_rgb32_sh(void *to, void *from); void bgr444_to_rgb32_sh(void *to, void *from);
void vidcpy_m2(void *dest, void *src, int m32col, int with_32c_border); void vidcpy_m2(void *dest, void *src, int m32col, int with_32c_border);

View file

@ -62,12 +62,12 @@
.endm .endm
.global bgr444_to_rgb32 @ void *to, void *from .global bgr444_to_rgb32 @ void *to, void *from, unsigned entries
bgr444_to_rgb32: bgr444_to_rgb32:
stmfd sp!, {r4-r7,lr} stmfd sp!, {r4-r7,lr}
mov r12, #0x40>>3 @ repeats mov r12, r2, lsr #3 @ repeats
mov lr, #0x00f00000 mov lr, #0x00f00000
orr lr, lr, #0x00f0 orr lr, lr, #0x00f0

View file

@ -301,26 +301,26 @@ static int make_local_pal_md(int fast_mode)
int pallen = 0x100; int pallen = 0x100;
if (fast_mode) { if (fast_mode) {
bgr444_to_rgb32(localPal, PicoMem.cram); bgr444_to_rgb32(localPal, PicoMem.cram, 64);
pallen = 0x40; pallen = 0x40;
Pico.m.dirtyPal = 0; Pico.m.dirtyPal = 0;
} }
else if (Pico.est.rendstatus & PDRAW_SONIC_MODE) { // mid-frame palette changes else if (Pico.est.rendstatus & PDRAW_SONIC_MODE) { // mid-frame palette changes
switch (Pico.est.SonicPalCount) { switch (Pico.est.SonicPalCount) {
case 3: bgr444_to_rgb32(localPal+0xc0, Pico.est.SonicPal+0xc0); case 3: bgr444_to_rgb32(localPal+0xc0, Pico.est.SonicPal+0xc0, 64);
case 2: bgr444_to_rgb32(localPal+0x80, Pico.est.SonicPal+0x80); case 2: bgr444_to_rgb32(localPal+0x80, Pico.est.SonicPal+0x80, 64);
case 1: bgr444_to_rgb32(localPal+0x40, Pico.est.SonicPal+0x40); case 1: bgr444_to_rgb32(localPal+0x40, Pico.est.SonicPal+0x40, 64);
default:bgr444_to_rgb32(localPal, Pico.est.SonicPal); default:bgr444_to_rgb32(localPal, Pico.est.SonicPal, 64);
} }
pallen = (Pico.est.SonicPalCount+1)*0x40; pallen = (Pico.est.SonicPalCount+1)*0x40;
} }
else if (Pico.video.reg[0xC] & 8) { // shadow/hilight mode else if (Pico.video.reg[0xC] & 8) { // shadow/hilight mode
bgr444_to_rgb32(localPal, Pico.est.SonicPal); bgr444_to_rgb32(localPal, Pico.est.SonicPal, 64);
bgr444_to_rgb32_sh(localPal, Pico.est.SonicPal); bgr444_to_rgb32_sh(localPal, Pico.est.SonicPal);
memcpy(localPal+0xc0, localPal, 0x40*4); // for spr prio mess memcpy(localPal+0xc0, localPal, 0x40*4); // for spr prio mess
} }
else { else {
bgr444_to_rgb32(localPal, Pico.est.SonicPal); bgr444_to_rgb32(localPal, Pico.est.SonicPal, 64);
memcpy(localPal+0x40, localPal, 0x40*4); // for spr prio mess memcpy(localPal+0x40, localPal, 0x40*4); // for spr prio mess
memcpy(localPal+0x80, localPal, 0x80*4); // for spr prio mess memcpy(localPal+0x80, localPal, 0x80*4); // for spr prio mess
} }
@ -336,9 +336,27 @@ static int make_local_pal_md(int fast_mode)
static int make_local_pal_sms(int fast_mode) static int make_local_pal_sms(int fast_mode)
{ {
bgr444_to_rgb32(localPal, PicoMem.cram); static u16 tmspal[32] = {
// SMS palette for TMS modes
0x0000, 0x0000, 0x00a0, 0x00f0, 0x0500, 0x0f00, 0x0005, 0x0ff0,
0x000a, 0x000f, 0x0055, 0x00ff, 0x0050, 0x0f0f, 0x0555, 0x0fff,
};
int i;
if (!(Pico.video.reg[0] & 0x4)) {
for (i = Pico.est.SonicPalCount; i >= 0; i--) {
bgr444_to_rgb32(localPal+i*0x40, tmspal, 32);
memcpy(localPal+i*0x40+0x20, localPal+i*0x40, 0x20*4);
}
} else {
for (i = Pico.est.SonicPalCount; i >= 0; i--) {
bgr444_to_rgb32(localPal+i*0x40, Pico.est.SonicPal+i*0x40, 32);
memcpy(localPal+i*0x40+0x20, localPal+i*0x40, 0x20*4);
}
}
if (Pico.m.dirtyPal == 2)
Pico.m.dirtyPal = 0; Pico.m.dirtyPal = 0;
return 0x40; return (Pico.est.SonicPalCount+1)*0x40;
} }
void pemu_finalize_frame(const char *fps, const char *notice) void pemu_finalize_frame(const char *fps, const char *notice)

View file

@ -10,13 +10,13 @@
// to 00000000 rrr00000 ggg00000 bbb00000 ... // to 00000000 rrr00000 ggg00000 bbb00000 ...
// TODO: rm when gp2x/emu.c is no longer used // TODO: rm when gp2x/emu.c is no longer used
void bgr444_to_rgb32(void *to, void *from) void bgr444_to_rgb32(void *to, void *from, unsigned entries)
{ {
unsigned short *ps = from; unsigned short *ps = from;
unsigned int *pd = to; unsigned int *pd = to;
int pixels; int pixels;
for (pixels = 0x40; pixels; pixels--, ps++, pd++) for (pixels = entries; pixels; pixels--, ps++, pd++)
{ {
*pd = ((*ps<<20)&0xe00000) | ((*ps<<8)&0xe000) | ((*ps>>4)&0xe0); *pd = ((*ps<<20)&0xe00000) | ((*ps<<8)&0xe000) | ((*ps>>4)&0xe0);
*pd |= *pd >> 3; *pd |= *pd >> 3;

View file

@ -204,32 +204,42 @@ static void set_scaling_params(void)
*/ */
} }
static void do_pal_update_sms(void)
{
static u16 tmspal[32] = {
// SMS palette
0x0000, 0x0000, 0x00a0, 0x00f0, 0x0500, 0x0f00, 0x0005, 0x0ff0,
0x000a, 0x000f, 0x0055, 0x00ff, 0x0050, 0x0f0f, 0x0555, 0x0fff,
};
int i;
if (!(Pico.video.reg[0] & 0x4)) {
for (i = Pico.est.SonicPalCount; i >= 0; i--)
do_pal_convert(localPal+i*0x40, tmspal, currentConfig.gamma, currentConfig.gamma2);
} else {
for (i = Pico.est.SonicPalCount; i >= 0; i--)
do_pal_convert(localPal+i*0x40, Pico.est.SonicPal+i*0x40, currentConfig.gamma, currentConfig.gamma2);
}
if (Pico.m.dirtyPal == 2)
Pico.m.dirtyPal = 0;
need_pal_upload = 1;
}
static void do_pal_update(void) static void do_pal_update(void)
{ {
u32 *dpal=(void *)localPal; u32 *dpal=(void *)localPal;
int i; int i;
//for (i = 0x3f/2; i >= 0; i--) if (PicoIn.opt & POPT_ALT_RENDERER) {
// dpal[i] = ((spal[i]&0x000f000f)<< 1)|((spal[i]&0x00f000f0)<<3)|((spal[i]&0x0f000f00)<<4);
if (PicoIn.AHW & PAHW_SMS) {
u32 *spal = (void *)PicoMem.cram;
for (i = 0; i < 0x20 / 2; i++) {
u32 t = spal[i];
t = ((t & 0x00030003)<< 3) | ((t & 0x000c000c)<<7) | ((t & 0x00300030)<<10);
t |= (t >> 2) | ((t >> 4) & 0x08610861);
dpal[i] = t;
}
Pico.m.dirtyPal = 0;
} else if (PicoIn.opt & POPT_ALT_RENDERER) {
do_pal_convert(localPal, PicoMem.cram, currentConfig.gamma, currentConfig.gamma2); do_pal_convert(localPal, PicoMem.cram, currentConfig.gamma, currentConfig.gamma2);
Pico.m.dirtyPal = 0; Pico.m.dirtyPal = 0;
} }
else if (Pico.est.rendstatus & PDRAW_SONIC_MODE) else if (Pico.est.rendstatus & PDRAW_SONIC_MODE)
{ {
switch (Pico.est.SonicPalCount) { switch (Pico.est.SonicPalCount) {
case 3: do_pal_convert(localPal+0xc0/2, Pico.est.SonicPal+0xc0, currentConfig.gamma, currentConfig.gamma2); case 3: do_pal_convert(localPal+0xc0, Pico.est.SonicPal+0xc0, currentConfig.gamma, currentConfig.gamma2);
case 2: do_pal_convert(localPal+0x80/2, Pico.est.SonicPal+0x80, currentConfig.gamma, currentConfig.gamma2); case 2: do_pal_convert(localPal+0x80, Pico.est.SonicPal+0x80, currentConfig.gamma, currentConfig.gamma2);
case 1: do_pal_convert(localPal+0x40/2, Pico.est.SonicPal+0x40, currentConfig.gamma, currentConfig.gamma2); case 1: do_pal_convert(localPal+0x40, Pico.est.SonicPal+0x40, currentConfig.gamma, currentConfig.gamma2);
default:do_pal_convert(localPal, Pico.est.SonicPal, currentConfig.gamma, currentConfig.gamma2); default:do_pal_convert(localPal, Pico.est.SonicPal, currentConfig.gamma, currentConfig.gamma2);
} }
} }
@ -267,9 +277,12 @@ static void blitscreen_clut(void)
sceGuTexMode(is_16bit_mode() ? GU_PSM_5650:GU_PSM_T8,0,0,0); sceGuTexMode(is_16bit_mode() ? GU_PSM_5650:GU_PSM_T8,0,0,0);
sceGuTexImage(0,512,512,512,g_screen_ptr); sceGuTexImage(0,512,512,512,g_screen_ptr);
if (!is_16bit_mode() && Pico.m.dirtyPal) if (!is_16bit_mode() && Pico.m.dirtyPal) {
if (PicoIn.AHW & PAHW_SMS)
do_pal_update_sms();
else
do_pal_update(); do_pal_update();
}
if (need_pal_upload) { if (need_pal_upload) {
need_pal_upload = 0; need_pal_upload = 0;