core+gp2x+psp, fix handling mid-frame palette changes
authorkub <derkub@gmail.com>
Wed, 10 Nov 2021 22:06:08 +0000 (23:06 +0100)
committerkub <derkub@gmail.com>
Wed, 10 Nov 2021 22:32:40 +0000 (23:32 +0100)
pico/draw.c
pico/mode4.c
pico/sms.c
platform/common/arm_utils.h
platform/common/arm_utils.s
platform/gp2x/emu.c
platform/linux/blit.c
platform/psp/emu.c

index 38b920d..6dce27c 100644 (file)
@@ -1894,10 +1894,10 @@ PICO_INTERNAL void PicoFrameStart(void)
 \r
   if (FinalizeLine == FinalizeLine8bit) {\r
     // make a backup of the current palette in case Sonic mode is detected later\r
-    Pico.est.SonicPalCount = 0;\r
-    Pico.m.dirtyPal = (Pico.m.dirtyPal ? 2 : 0); // mark as dirty but copied\r
+    Pico.m.dirtyPal = (Pico.m.dirtyPal || Pico.est.SonicPalCount ? 2 : 0);\r
     blockcpy(Pico.est.SonicPal, PicoMem.cram, 0x40*2);\r
   }\r
+  Pico.est.SonicPalCount = 0;\r
 }\r
 \r
 static void DrawBlankedLine(int line, int offs, int sh, int bgc)\r
index 54440e3..55127e3 100644 (file)
@@ -656,10 +656,10 @@ void PicoFrameStartSMS(void)
   Pico.est.DrawLineDest = (char *)DrawLineDestBase + screen_offset * DrawLineDestIncrement;
 
   if (FinalizeLineSMS == FinalizeLine8bitSMS) {
-    Pico.est.SonicPalCount = 0;
-    Pico.m.dirtyPal = (Pico.m.dirtyPal ? 2 : 0);
-    memcpy(Pico.est.SonicPal, PicoMem.cram, 0x20*2);
+    Pico.m.dirtyPal = (Pico.m.dirtyPal || Pico.est.SonicPalCount ? 2 : 0);
+    memcpy(Pico.est.SonicPal, PicoMem.cram, 0x40*2);
   }
+  Pico.est.SonicPalCount = 0;
 }
 
 void PicoParseSATSMS(int line)
@@ -707,13 +707,12 @@ norender:
 
 /* Fixed palette for TMS9918 modes */
 static u16 tmspal[32] = {
-#if 1  // SMS palette
+  // SMS palette
   0x0000, 0x0000, 0x00a0, 0x00f0, 0x0500, 0x0f00, 0x0005, 0x0ff0,
   0x000a, 0x000f, 0x0055, 0x00ff, 0x0050, 0x0f0f, 0x0555, 0x0fff,
-#else  // TMS palette
+  // TMS palette
   0x0000, 0x0000, 0x04c2, 0x07d5, 0x0e55, 0x0f77, 0x045d, 0x0fe4,
   0x055f, 0x077f, 0x05cd, 0x08ce, 0x03b2, 0x0b5c, 0x0ccc, 0x0fff,
-#endif
 };
 
 void PicoDoHighPal555SMS(void)
@@ -737,18 +736,18 @@ void PicoDoHighPal555SMS(void)
     if (!(Pico.video.reg[0] & 0x4))
       spal = (u32 *)tmspal; // fixed palette in TMS modes
     for (i = 0x20/2; i > 0; i--, spal++, dpal++) { 
-     t = *spal;
+      t = *spal;
 #if defined(USE_BGR555)
-     t = ((t & 0x000f000f)<< 1) | ((t & 0x00f000f0)<<2) | ((t & 0x0f000f00)<<3);
-     t |= (t >> 4) & 0x04210421;
+      t = ((t & 0x000f000f)<<1) | ((t & 0x00f000f0)<<2) | ((t & 0x0f000f00)<<3);
+      t |= (t >> 4) & 0x04210421;
 #elif defined(USE_BGR565)
-     t = ((t & 0x000f000f)<< 1) | ((t & 0x00f000f0)<<3) | ((t & 0x0f000f00)<<4);
-     t |= (t >> 4) & 0x08610861;
+      t = ((t & 0x000f000f)<<1) | ((t & 0x00f000f0)<<3) | ((t & 0x0f000f00)<<4);
+      t |= (t >> 4) & 0x08610861;
 #else
-     t = ((t & 0x000f000f)<<12) | ((t & 0x00f000f0)<<3) | ((t & 0x0f000f00)>>7);
-     t |= (t >> 4) & 0x08610861;
+      t = ((t & 0x000f000f)<<12)| ((t & 0x00f000f0)<<3) | ((t & 0x0f000f00)>>7);
+      t |= (t >> 4) & 0x08610861;
 #endif
-     *dpal = t;
+      *dpal = t;
     }
     memcpy(dpal, dpal-0x20/2, 0x20*2); // for prio bit
     spal += 0x20/2, dpal += 0x20/2;
index a62f407..ab8a6f0 100644 (file)
@@ -56,18 +56,19 @@ static void vdp_data_write(unsigned char d)
   struct PicoVideo *pv = &Pico.video;
 
   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
       unsigned a = pv->addr & 0x3f;
       if (a & 0x1) { // write complete color on high byte write
         u16 c = ((d&0x0f) << 8) | Pico.ms.vdp_buffer;
         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)
       unsigned a = pv->addr & 0x1f;
       u16 c = ((d&0x30)<<6) + ((d&0x0c)<<4) + ((d&0x03)<<2);
       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 {
     PicoMem.vramb[MEM_LE2(pv->addr)] = d;
index 21204c9..628daf6 100644 (file)
@@ -1,5 +1,5 @@
 \r
-void bgr444_to_rgb32(void *to, void *from);\r
+void bgr444_to_rgb32(void *to, void *from, unsigned entries);\r
 void bgr444_to_rgb32_sh(void *to, void *from);\r
 \r
 void vidcpy_m2(void *dest, void *src, int m32col, int with_32c_border);\r
index 7dbed97..b4f739d 100644 (file)
 .endm\r
 \r
 \r
-.global bgr444_to_rgb32 @ void *to, void *from\r
+.global bgr444_to_rgb32 @ void *to, void *from, unsigned entries\r
 \r
 bgr444_to_rgb32:\r
     stmfd   sp!, {r4-r7,lr}\r
 \r
-    mov     r12, #0x40>>3 @ repeats\r
+    mov     r12, r2, lsr #3 @ repeats\r
     mov     lr, #0x00f00000\r
     orr     lr, lr, #0x00f0\r
 \r
index 7c94c45..70c6d3d 100644 (file)
@@ -301,26 +301,26 @@ static int make_local_pal_md(int fast_mode)
        int pallen = 0x100;\r
 \r
        if (fast_mode) {\r
-               bgr444_to_rgb32(localPal, PicoMem.cram);\r
+               bgr444_to_rgb32(localPal, PicoMem.cram, 64);\r
                pallen = 0x40;\r
                Pico.m.dirtyPal = 0;\r
        }\r
        else if (Pico.est.rendstatus & PDRAW_SONIC_MODE) { // mid-frame palette changes\r
                switch (Pico.est.SonicPalCount) {\r
-               case 3: bgr444_to_rgb32(localPal+0xc0, Pico.est.SonicPal+0xc0);\r
-               case 2: bgr444_to_rgb32(localPal+0x80, Pico.est.SonicPal+0x80);\r
-               case 1: bgr444_to_rgb32(localPal+0x40, Pico.est.SonicPal+0x40);\r
-               default:bgr444_to_rgb32(localPal, Pico.est.SonicPal);\r
+               case 3: bgr444_to_rgb32(localPal+0xc0, Pico.est.SonicPal+0xc0, 64);\r
+               case 2: bgr444_to_rgb32(localPal+0x80, Pico.est.SonicPal+0x80, 64);\r
+               case 1: bgr444_to_rgb32(localPal+0x40, Pico.est.SonicPal+0x40, 64);\r
+               default:bgr444_to_rgb32(localPal, Pico.est.SonicPal, 64);\r
                }\r
                pallen = (Pico.est.SonicPalCount+1)*0x40;\r
        }\r
        else if (Pico.video.reg[0xC] & 8) { // shadow/hilight mode\r
-               bgr444_to_rgb32(localPal, Pico.est.SonicPal);\r
+               bgr444_to_rgb32(localPal, Pico.est.SonicPal, 64);\r
                bgr444_to_rgb32_sh(localPal, Pico.est.SonicPal);\r
                memcpy(localPal+0xc0, localPal, 0x40*4); // for spr prio mess\r
        }\r
        else {\r
-               bgr444_to_rgb32(localPal, Pico.est.SonicPal);\r
+               bgr444_to_rgb32(localPal, Pico.est.SonicPal, 64);\r
                memcpy(localPal+0x40, localPal, 0x40*4); // for spr prio mess\r
                memcpy(localPal+0x80, localPal, 0x80*4); // for spr prio mess\r
        }\r
@@ -336,9 +336,27 @@ static int make_local_pal_md(int fast_mode)
 \r
 static int make_local_pal_sms(int fast_mode)\r
 {\r
-       bgr444_to_rgb32(localPal, PicoMem.cram);\r
-       Pico.m.dirtyPal = 0;\r
-       return 0x40;\r
+       static u16 tmspal[32] = {\r
+               // SMS palette for TMS modes\r
+               0x0000, 0x0000, 0x00a0, 0x00f0, 0x0500, 0x0f00, 0x0005, 0x0ff0,\r
+               0x000a, 0x000f, 0x0055, 0x00ff, 0x0050, 0x0f0f, 0x0555, 0x0fff,\r
+       };\r
+       int i;\r
+       \r
+       if (!(Pico.video.reg[0] & 0x4)) {\r
+               for (i = Pico.est.SonicPalCount; i >= 0; i--) {\r
+                       bgr444_to_rgb32(localPal+i*0x40, tmspal, 32);\r
+                       memcpy(localPal+i*0x40+0x20, localPal+i*0x40, 0x20*4);\r
+               }\r
+       } else {\r
+               for (i = Pico.est.SonicPalCount; i >= 0; i--) {\r
+                       bgr444_to_rgb32(localPal+i*0x40, Pico.est.SonicPal+i*0x40, 32);\r
+                       memcpy(localPal+i*0x40+0x20, localPal+i*0x40, 0x20*4);\r
+               }\r
+       }\r
+       if (Pico.m.dirtyPal == 2)\r
+               Pico.m.dirtyPal = 0;\r
+       return (Pico.est.SonicPalCount+1)*0x40;\r
 }\r
 \r
 void pemu_finalize_frame(const char *fps, const char *notice)\r
index 82bc4ba..b70262e 100644 (file)
 // to      00000000 rrr00000 ggg00000 bbb00000 ...
 // 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 int   *pd = to;
        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 |= *pd >> 3;
index 89b2c26..59ccab5 100644 (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)
 {
        u32 *dpal=(void *)localPal;
        int i;
 
-       //for (i = 0x3f/2; i >= 0; i--)
-       //      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) {
+       if (PicoIn.opt & POPT_ALT_RENDERER) {
                do_pal_convert(localPal, PicoMem.cram, currentConfig.gamma, currentConfig.gamma2);
                Pico.m.dirtyPal = 0;
        }
        else if (Pico.est.rendstatus & PDRAW_SONIC_MODE)
        {
                switch (Pico.est.SonicPalCount) {
-               case 3: do_pal_convert(localPal+0xc0/2, 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 1: do_pal_convert(localPal+0x40/2, Pico.est.SonicPal+0x40, 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, Pico.est.SonicPal+0x80, 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);
                }
        }
@@ -267,9 +277,12 @@ static void blitscreen_clut(void)
        sceGuTexMode(is_16bit_mode() ? GU_PSM_5650:GU_PSM_T8,0,0,0);
        sceGuTexImage(0,512,512,512,g_screen_ptr);
 
-       if (!is_16bit_mode() && Pico.m.dirtyPal)
-               do_pal_update();
-
+       if (!is_16bit_mode() && Pico.m.dirtyPal) {
+               if (PicoIn.AHW & PAHW_SMS)
+                       do_pal_update_sms();
+               else
+                       do_pal_update();
+       }
 
        if (need_pal_upload) {
                need_pal_upload = 0;