reworked palette and buffer handling due to some 32X bugs
authorkub <derkub@gmail.com>
Fri, 22 Mar 2019 22:03:26 +0000 (23:03 +0100)
committerkub <derkub@gmail.com>
Tue, 30 Jul 2019 14:34:40 +0000 (16:34 +0200)
13 files changed:
pico/32x/draw.c
pico/draw.c
pico/draw_arm.S
pico/pico_int.h
pico/videoport.c
platform/common/common.mak
platform/common/emu.c
platform/gizmondo/emu.c
platform/gizmondo/menu.c
platform/gp2x/emu.c
platform/linux/emu.c
platform/psp/emu.c
platform/psp/menu.c

index 2287e24..4bdbc89 100644 (file)
@@ -11,6 +11,9 @@ int (*PicoScan32xBegin)(unsigned int num);
 int (*PicoScan32xEnd)(unsigned int num);
 int Pico32xDrawMode;
 
+void *DrawLineDestBase32x;
+int DrawLineDestIncrement32x;
+
 static void convert_pal555(int invert_prio)
 {
   unsigned int *ps = (void *)Pico32xMem->pal;
@@ -228,13 +231,11 @@ void PicoDraw32xLayer(int offs, int lines, int md_bg)
   int lines_sft_offs;
   int which_func;
 
-  Pico.est.DrawLineDest = (char *)DrawLineDestBase + offs * DrawLineDestIncrement;
+  Pico.est.DrawLineDest = (char *)DrawLineDestBase32x + offs * DrawLineDestIncrement32x;
   dram = Pico32xMem->dram[Pico32x.vdp_regs[0x0a/2] & P32XV_FS];
 
-  if (Pico32xDrawMode == PDM32X_BOTH) {
-    if (Pico.m.dirtyPal)
-      PicoDrawUpdateHighPal();
-  }
+  if (Pico32xDrawMode == PDM32X_BOTH)
+    PicoDrawUpdateHighPal();
 
   if ((Pico32x.vdp_regs[0] & P32XV_Mx) == 2)
   {
@@ -273,20 +274,21 @@ do_it:
 void PicoDraw32xLayerMdOnly(int offs, int lines)
 {
   int have_scan = PicoScan32xBegin != NULL && PicoScan32xEnd != NULL;
-  unsigned short *dst = (void *)((char *)DrawLineDestBase + offs * DrawLineDestIncrement);
+  unsigned short *dst = (void *)((char *)DrawLineDestBase32x + offs * DrawLineDestIncrement32x);
   unsigned char  *pmd = Pico.est.Draw2FB + 328 * offs + 8;
   unsigned short *pal = Pico.est.HighPal;
   int poffs = 0, plen = 320;
   int l, p;
 
   if (!(Pico.video.reg[12] & 1)) {
-    // 32col mode
+    // 32col mode. for some render modes MD pixel data carries an offset
+    if (!(PicoIn.opt & (POPT_ALT_RENDERER|POPT_DIS_32C_BORDER)))
+      pmd += 32;
     poffs = 32;
     plen = 256;
   }
 
-  if (Pico.m.dirtyPal)
-    PicoDrawUpdateHighPal();
+  PicoDrawUpdateHighPal();
 
   dst += poffs;
   for (l = 0; l < lines; l++) {
@@ -300,7 +302,7 @@ void PicoDraw32xLayerMdOnly(int offs, int lines)
       dst[p + 2] = pal[*pmd++];
       dst[p + 3] = pal[*pmd++];
     }
-    dst = (void *)((char *)dst + DrawLineDestIncrement);
+    dst = (void *)((char *)dst + DrawLineDestIncrement32x);
     pmd += 328 - plen;
     if (have_scan)
       PicoScan32xEnd(l + offs);
@@ -314,16 +316,32 @@ void PicoDrawSetOutFormat32x(pdso_t which, int use_32x_line_mode)
   Pico32xNativePal = Pico32xMem->pal_native;
 #endif
 
-  if (which == PDF_RGB555 && use_32x_line_mode) {
-    // we'll draw via FinalizeLine32xRGB555 (rare)
+  if (which == PDF_RGB555) {
+    // need CLUT pixels in PicoDraw2FB for layer transparency
+    PicoDrawSetInternalBuf(Pico.est.Draw2FB, 328);
+    PicoDrawSetOutBufMD(DrawLineDestBase32x, DrawLineDestIncrement32x);
+  } else {
+    // use the same layout as alt renderer
     PicoDrawSetInternalBuf(NULL, 0);
-    Pico32xDrawMode = PDM32X_OFF;
-    return;
+    PicoDrawSetOutBufMD(Pico.est.Draw2FB + 8, 328);
   }
 
-  // use the same layout as alt renderer
-  PicoDrawSetInternalBuf(Pico.est.Draw2FB, 328);
-  Pico32xDrawMode = (which == PDF_RGB555) ? PDM32X_32X_ONLY : PDM32X_BOTH;
+  if (use_32x_line_mode)
+    // we'll draw via FinalizeLine32xRGB555 (rare)
+    Pico32xDrawMode = PDM32X_OFF;
+  else
+    // in RGB555 mode the 32x layer is drawn over the MD layer, in the other
+    // modes 32x and MD layer are merged together by the 32x renderer
+    Pico32xDrawMode = (which == PDF_RGB555) ? PDM32X_32X_ONLY : PDM32X_BOTH;
+}
+
+void PicoDrawSetOutBuf32X(void *dest, int increment)
+{
+  DrawLineDestBase32x = dest;
+  DrawLineDestIncrement32x = increment;
+  // in RGB555 mode this buffer is also used by the MD renderer
+  if (Pico32xDrawMode != PDM32X_BOTH)
+    PicoDrawSetOutBufMD(DrawLineDestBase32x, DrawLineDestIncrement32x);
 }
 
 // vim:shiftwidth=2:ts=2:expandtab
index 680de3d..e345a28 100644 (file)
@@ -1239,6 +1239,49 @@ void BackFill(int reg7, int sh, struct PicoEState *est)
 \r
 // --------------------------------------------\r
 \r
+void PicoDoHighPal555_8bit(int sh, int line, struct PicoEState *est)\r
+{\r
+  unsigned int *spal, *dpal;\r
+  unsigned int cnt = (sh ? 1 : est->SonicPalCount+1);\r
+  unsigned int t, i;\r
+\r
+  // reset dirty only if there are no outstanding changes\r
+  if (Pico.m.dirtyPal == 2)\r
+    Pico.m.dirtyPal = 0;\r
+\r
+  // In Sonic render mode palettes were backuped in SonicPal\r
+  spal = (void *)est->SonicPal;\r
+  dpal = (void *)est->HighPal;\r
+\r
+  // additional palettes stored after in-frame changes\r
+  for (i = 0; i < cnt * 0x40 / 2; i++) {\r
+    t = spal[i];\r
+#ifdef USE_BGR555\r
+    t = ((t & 0x000e000e)<< 1) | ((t & 0x00e000e0)<<3) | ((t & 0x0e000e00)<<4);\r
+#else\r
+    t = ((t & 0x000e000e)<<12) | ((t & 0x00e000e0)<<3) | ((t & 0x0e000e00)>>7);\r
+#endif\r
+    // treat it like it was 4-bit per channel, since in s/h mode it somewhat is that.\r
+    // otherwise intensity difference between this and s/h will be wrong\r
+    t |= (t >> 4) & 0x08610861; // 0x18e318e3\r
+    dpal[i] = t;\r
+  }\r
+\r
+  // norm: xxx0, sh: 0xxx, hi: 0xxx + 7\r
+  if (sh)\r
+  {\r
+    // shadowed pixels\r
+    for (i = 0; i < 0x40 / 2; i++)\r
+      dpal[0x40/2 | i] = dpal[0xc0/2 | i] = (dpal[i] >> 1) & 0x738e738e;\r
+    // hilighted pixels\r
+    for (i = 0; i < 0x40 / 2; i++) {\r
+      t = ((dpal[i] >> 1) & 0x738e738e) + 0x738e738e; // 0x7bef7bef;\r
+      t |= (t >> 4) & 0x08610861;\r
+      dpal[0x80/2 | i] = t;\r
+    }\r
+  }\r
+}\r
+\r
 #ifndef _ASM_DRAW_C\r
 void PicoDoHighPal555(int sh, int line, struct PicoEState *est)\r
 {\r
@@ -1285,8 +1328,7 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est)
   unsigned short *pal=est->HighPal;\r
   int len;\r
 \r
-  if (Pico.m.dirtyPal)\r
-    PicoDoHighPal555(sh, line, est);\r
+  PicoDrawUpdateHighPal();\r
 \r
   if (Pico.video.reg[12]&1) {\r
     len = 320;\r
@@ -1315,22 +1357,21 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est)
 static void FinalizeLine8bit(int sh, int line, struct PicoEState *est)\r
 {\r
   unsigned char *pd = est->DrawLineDest;\r
-  int len, rs = est->rendstatus;\r
-  static int dirty_count;\r
+  int len;\r
+  static int dirty_line;\r
 \r
-  if (!sh && Pico.m.dirtyPal == 1)\r
+  if (Pico.m.dirtyPal == 1)\r
   {\r
     // a hack for mid-frame palette changes\r
-    if (!(rs & PDRAW_SONIC_MODE))\r
-         dirty_count = 1;\r
-    else dirty_count++;\r
-    rs |= PDRAW_SONIC_MODE;\r
-    est->rendstatus = rs;\r
-    if (dirty_count == 3) {\r
-      blockcpy(est->HighPal, PicoMem.cram, 0x40*2);\r
-    } else if (dirty_count == 11) {\r
-      blockcpy(est->HighPal+0x40, PicoMem.cram, 0x40*2);\r
+    if (!(est->rendstatus & PDRAW_SONIC_MODE) || line - dirty_line > 4) {\r
+      // store a maximum of 3 additional palettes in SonicPal\r
+      if (est->SonicPalCount < 3)\r
+        est->SonicPalCount ++;\r
+      dirty_line = line;\r
+      est->rendstatus |= PDRAW_SONIC_MODE;\r
     }\r
+    blockcpy(est->SonicPal+est->SonicPalCount*0x40, PicoMem.cram, 0x40*2);\r
+    Pico.m.dirtyPal = 2;\r
   }\r
 \r
   if (Pico.video.reg[12]&1) {\r
@@ -1341,12 +1382,9 @@ static void FinalizeLine8bit(int sh, int line, struct PicoEState *est)
     len = 256;\r
   }\r
 \r
-  if (!sh && (rs & PDRAW_SONIC_MODE)) {\r
-    if (dirty_count >= 11) {\r
-      blockcpy_or(pd, est->HighCol+8, len, 0x80);\r
-    } else {\r
-      blockcpy_or(pd, est->HighCol+8, len, 0x40);\r
-    }\r
+  if (!sh && (est->rendstatus & PDRAW_SONIC_MODE)) {\r
+    // select active backup palette\r
+    blockcpy_or(pd, est->HighCol+8, len, est->SonicPalCount*0x40);\r
   } else {\r
     blockcpy(pd, est->HighCol+8, len);\r
   }\r
@@ -1478,6 +1516,7 @@ static int DrawDisplay(int sh)
 PICO_INTERNAL void PicoFrameStart(void)\r
 {\r
   int offs = 8, lines = 224;\r
+  int dirty = ((Pico.est.rendstatus & PDRAW_SONIC_MODE) || Pico.m.dirtyPal);\r
 \r
   // prepare to do this frame\r
   Pico.est.rendstatus = 0;\r
@@ -1503,11 +1542,16 @@ PICO_INTERNAL void PicoFrameStart(void)
   Pico.est.DrawScanline = 0;\r
   skip_next_line = 0;\r
 \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 = (dirty ? 2 : 0); // mark as dirty but already copied\r
+    blockcpy(Pico.est.SonicPal, PicoMem.cram, 0x40*2);\r
+  }\r
+\r
   if (PicoIn.opt & POPT_ALT_RENDERER)\r
     return;\r
 \r
-  if (Pico.m.dirtyPal)\r
-    Pico.m.dirtyPal = 2; // reset dirty if needed\r
   PrepareSprites(1);\r
 }\r
 \r
@@ -1598,15 +1642,21 @@ void PicoDrawSync(int to, int blank_last_line)
 void PicoDrawUpdateHighPal(void)\r
 {\r
   struct PicoEState *est = &Pico.est;\r
-  int sh = (Pico.video.reg[0xC] & 8) >> 3; // shadow/hilight?\r
-  if (PicoIn.opt & POPT_ALT_RENDERER)\r
-    sh = 0; // no s/h support\r
+  if (Pico.m.dirtyPal) {\r
+    int sh = (Pico.video.reg[0xC] & 8) >> 3; // shadow/hilight?\r
+    if ((PicoIn.opt & POPT_ALT_RENDERER) | (est->rendstatus & PDRAW_SONIC_MODE))\r
+      sh = 0; // no s/h support\r
+\r
+    if (FinalizeLine == FinalizeLine8bit)\r
+      PicoDoHighPal555_8bit(sh, 0, est);\r
+    else\r
+      PicoDoHighPal555(sh, 0, est);\r
 \r
-  PicoDoHighPal555(sh, 0, &Pico.est);\r
-  if (est->rendstatus & PDRAW_SONIC_MODE) {\r
-    // FIXME?\r
-    memcpy(est->HighPal + 0x40, est->HighPal, 0x40*2);\r
-    memcpy(est->HighPal + 0x80, est->HighPal, 0x40*2);\r
+    // cover for sprite priority bits if not in s/h or sonic mode\r
+    if (!sh && !(est->rendstatus & PDRAW_SONIC_MODE)) {\r
+      blockcpy(est->HighPal+0x40, est->HighPal, 0x40*2);\r
+      blockcpy(est->HighPal+0x80, est->HighPal, 0x80*2);\r
+    }\r
   }\r
 }\r
 \r
@@ -1629,17 +1679,33 @@ void PicoDrawSetOutFormat(pdso_t which, int use_32x_line_mode)
       FinalizeLine = NULL;\r
       break;\r
   }\r
-  PicoDrawSetOutFormat32x(which, use_32x_line_mode);\r
+  if (PicoIn.AHW & PAHW_32X)\r
+    PicoDrawSetOutFormat32x(which, use_32x_line_mode);\r
   PicoDrawSetOutputMode4(which);\r
   rendstatus_old = -1;\r
 }\r
 \r
+void PicoDrawSetOutBufMD(void *dest, int increment)\r
+{\r
+  if (dest != NULL) {\r
+    DrawLineDestBase = dest;\r
+    DrawLineDestIncrement = increment;\r
+    Pico.est.DrawLineDest = DrawLineDestBase + Pico.est.DrawScanline * increment;\r
+  }\r
+  else {\r
+    DrawLineDestBase = DefOutBuff;\r
+    DrawLineDestIncrement = 0;\r
+    Pico.est.DrawLineDest = DefOutBuff;\r
+  }\r
+}\r
+\r
 // note: may be called on the middle of frame\r
 void PicoDrawSetOutBuf(void *dest, int increment)\r
 {\r
-  DrawLineDestBase = dest;\r
-  DrawLineDestIncrement = increment;\r
-  Pico.est.DrawLineDest = (char *)DrawLineDestBase + Pico.est.DrawScanline * increment;\r
+  if (PicoIn.AHW & PAHW_32X)\r
+    PicoDrawSetOutBuf32X(dest, increment);\r
+  else\r
+    PicoDrawSetOutBufMD(dest, increment);\r
 }\r
 \r
 void PicoDrawSetInternalBuf(void *dest, int increment)\r
@@ -1652,6 +1718,7 @@ void PicoDrawSetInternalBuf(void *dest, int increment)
   else {\r
     HighColBase = DefHighCol;\r
     HighColIncrement = 0;\r
+    Pico.est.HighCol = DefHighCol;\r
   }\r
 }\r
 \r
index 29af1c1..3bc2703 100644 (file)
@@ -1498,11 +1498,9 @@ vidConvCpyRGB565: @ void *to, void *from, int pixels
 PicoDoHighPal555:\r
     stmfd   sp!, {r4-r10,lr}\r
     mov     r10,r2               @ est\r
-    mov     r1, #0\r
     ldr     r8, [r10, #OFS_EST_Pico]\r
 \r
-PicoDoHighPal555_nopush:\r
-    orr     r9, r1, r0, lsl #31  @ 0:called from FinalizeLine555, 31: s/h\r
+    mov     r9, r0\r
 \r
     add     r0, r10, #OFS_EST_HighPal\r
 \r
@@ -1517,7 +1515,7 @@ PicoDoHighPal555_nopush:
 \r
     vidConvCpyRGB565_local\r
 \r
-    tst     r9, #(1<<31)\r
+    cmp     r9, #0\r
     beq     PicoDoHighPal555_end\r
 \r
     add     r3, r10, #OFS_EST_HighPal\r
@@ -1560,11 +1558,7 @@ PicoDoHighPal555_nopush:
     mov     r0, #1\r
 \r
 PicoDoHighPal555_end:\r
-    tst     r9, #1\r
-    ldmeqfd sp!, {r4-r10,pc}\r
-\r
-    ldr     r8, [r10, #OFS_EST_Pico]\r
-    b       FinalizeLineRGB555_pal_done\r
+    ldmfd   sp!, {r4-r10,pc}\r
 \r
 \r
 @ void FinalizeLine555(int sh, int line, struct PicoEState *est)\r
@@ -1576,19 +1570,11 @@ FinalizeLine555:
     mov     r10,r2               @ est\r
     ldr     r8, [r10, #OFS_EST_Pico]\r
 \r
-    ldrb    r2, [r8, #OFS_Pico_m_dirtyPal]\r
-    mov     r1, #1\r
-    tst     r2, r2\r
-    bne     PicoDoHighPal555_nopush\r
+    bl      PicoDrawUpdateHighPal\r
 \r
-FinalizeLineRGB555_pal_done:\r
     add     r3, r10, #OFS_EST_HighPal\r
 \r
-    ldr     r12, [r10, #OFS_EST_rendstatus]\r
-    eors    r0, r0, #1           @ sh is 0\r
     mov     lr, #0xff\r
-    tstne   r12,#PDRAW_ACC_SPRITES\r
-    movne   lr, #0x3f\r
 \r
     ldr     r1, [r10, #OFS_EST_HighCol]\r
     ldr     r0, [r10, #OFS_EST_DrawLineDest]\r
index cca7f95..f6d8b37 100644 (file)
@@ -356,6 +356,8 @@ struct PicoEState
   unsigned int  *PicoOpt;\r
   unsigned char *Draw2FB;\r
   unsigned short HighPal[0x100];\r
+  unsigned short SonicPal[0x100];\r
+  int SonicPalCount;\r
 };\r
 \r
 struct PicoMem\r
@@ -923,6 +925,7 @@ void p32x_sh2_poll_event(SH2 *sh2, unsigned int flags, unsigned int m68k_cycles)
 \r
 // 32x/draw.c\r
 void PicoDrawSetOutFormat32x(pdso_t which, int use_32x_line_mode);\r
+void PicoDrawSetOutBuf32X(void *dest, int increment);\r
 void FinalizeLine32xRGB555(int sh, int line, struct PicoEState *est);\r
 void PicoDraw32xLayer(int offs, int lines, int mdbg);\r
 void PicoDraw32xLayerMdOnly(int offs, int lines);\r
index cd76dc0..d18c2cf 100644 (file)
@@ -41,7 +41,7 @@ static void VideoWrite(u16 d)
             if (a - ((unsigned)(Pico.video.reg[5]&0x7f) << 9) < 0x400)\r
               Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;\r
             break;\r
-    case 3: Pico.m.dirtyPal = 1;\r
+    case 3: if (PicoMem.cram [(a >> 1) & 0x3f] != d) Pico.m.dirtyPal = 1;\r
             PicoMem.cram [(a >> 1) & 0x3f] = d; break;\r
     case 5: PicoMem.vsram[(a >> 1) & 0x3f] = d; break;\r
     case 0x81:\r
@@ -441,7 +441,7 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d)
             break;\r
           case 0x0c:\r
             // renderers should update their palettes if sh/hi mode is changed\r
-            if ((d^dold)&8) Pico.m.dirtyPal = 2;\r
+            if ((d^dold)&8) Pico.m.dirtyPal = 1;\r
             break;\r
         }\r
         return;\r
index 197e867..2f676ab 100644 (file)
@@ -70,7 +70,7 @@ SRCS_COMMON += $(R)pico/cd/memory_arm.S
 endif
 ifeq "$(asm_32xdraw)" "1"
 DEFINES += _ASM_32X_DRAW
-SRCS_COMMON += $(R)pico/32x/draw_arm.s
+SRCS_COMMON += $(R)pico/32x/draw_arm.S
 endif
 ifeq "$(asm_mix)" "1"
 SRCS_COMMON += $(R)pico/sound/mix_arm.S
index 0a9f089..da03bff 100644 (file)
@@ -1407,8 +1407,10 @@ void emu_loop(void)
                        {\r
                                notice_msg_time = 0;\r
                                plat_status_msg_clear();\r
+#ifndef __GP2X__\r
                                plat_video_flip();\r
                                plat_status_msg_clear(); /* Do it again in case of double buffering */\r
+#endif\r
                                notice_msg = NULL;\r
                        }\r
                        else {\r
index 86c473c..fcf2712 100644 (file)
@@ -155,7 +155,7 @@ static void blit(const char *fps, const char *notice)
                }
                // a hack for VR
                if (PicoIn.AHW & PAHW_SVP)
-                       memset32((int *)(Pico.est.Draw2FB+328*8+328*223), 0xe0e0e0e0, 328);
+                       memset((int *)(Pico.est.Draw2FB+328*8+328*223), 0xe0e0e0e0, 328*4);
                if (!(Pico.video.reg[12]&1)) lines_flags|=0x10000;
                if (currentConfig.EmuOpt&0x4000)
                        lines_flags|=0x40000; // (Pico.m.frame_count&1)?0x20000:0x40000;
@@ -166,22 +166,25 @@ static void blit(const char *fps, const char *notice)
                int lines_flags;
                // 8bit accurate renderer
                if (Pico.m.dirtyPal) {
-                       Pico.m.dirtyPal = 0;
-                       vidConvCpyRGB565(localPal, Pico.cram, 0x40);
+                       if (Pico.m.dirtyPal == 2)
+                               Pico.m.dirtyPal = 0;
+                       /* no support
+                       switch (Pico.est.SonicPalCount) {
+                       case 3: vidConvCpyRGB565(localPal+0xc0, Pico.est.SonicPal+0xc0, 0x40);
+                       case 2: vidConvCpyRGB565(localPal+0x80, Pico.est.SonicPal+0x80, 0x40);
+                       case 1: vidConvCpyRGB565(localPal+0x40, Pico.est.SonicPal+0x40, 0x40);
+                       default://vidConvCpyRGB565(localPal, Pico.est.SonicPal, 0x40);
+                       } */
+                       vidConvCpyRGB565(localPal, Pico.est.SonicPal, 0x40);
                        if (Pico.video.reg[0xC]&8) { // shadow/hilight mode
-                               //vidConvCpyRGB32sh(localPal+0x40, Pico.cram, 0x40);
-                               //vidConvCpyRGB32hi(localPal+0x80, Pico.cram, 0x40); // TODO?
-                               memcpy32((void *)(localPal+0xc0), (void *)(localPal+0x40), 0x40*2/4);
+                               //vidConvCpyRGB32sh(localPal+0x40, Pico.est.SonicPal, 0x40);
+                               //vidConvCpyRGB32hi(localPal+0x80, Pico.est.SonicPal, 0x40); // TODO?
+                               memcpy((void *)(localPal+0xc0), (void *)(localPal+0x40), 0x40*2);
                                localPal[0xc0] = 0x0600;
                                localPal[0xd0] = 0xc000;
                                localPal[0xe0] = 0x0000; // reserved pixels for OSD
                                localPal[0xf0] = 0xffff;
                        }
-                       /* no support
-                       else if (rendstatus & 0x20) { // mid-frame palette changes
-                               vidConvCpyRGB565(localPal+0x40, HighPal, 0x40);
-                               vidConvCpyRGB565(localPal+0x80, HighPal+0x40, 0x40);
-                       } */
                }
                lines_flags = (Pico.video.reg[1]&8) ? 240 : 224;
                if (!(Pico.video.reg[12]&1)) lines_flags|=0x10000;
index 51f032f..1045f47 100644 (file)
@@ -54,7 +54,7 @@ static unsigned int inp_prev = 0;
 void menu_draw_begin(int use_bgbuff)\r
 {\r
        if (use_bgbuff)\r
-               memcpy32((int *)menu_screen, (int *)bg_buffer, 321*240*2/4);\r
+               memcpy((int *)menu_screen, (int *)bg_buffer, 321*240*2);\r
 }\r
 \r
 \r
@@ -66,7 +66,7 @@ void menu_draw_end(void)
                lprintf("%s: Framework2D_LockBuffer() returned NULL\n", __FUNCTION__);\r
                return;\r
        }\r
-       memcpy32(giz_screen, (int *)menu_screen, 321*240*2/4);\r
+       memcpy(giz_screen, (int *)menu_screen, 321*240*2);\r
        fb_unlock();\r
        giz_screen = NULL;\r
        fb_flip();\r
index 18d8a57..450ac08 100644 (file)
@@ -291,32 +291,45 @@ static int EmuScanEnd16_ld(unsigned int num)
 }\r
 \r
 static int localPal[0x100];\r
+static int localPalSize;\r
+\r
 static void (*vidcpyM2)(void *dest, void *src, int m32col, int with_32c_border);\r
 static int (*make_local_pal)(int fast_mode);\r
 \r
 static int make_local_pal_md(int fast_mode)\r
 {\r
-       int pallen = 0xc0;\r
-\r
-       bgr444_to_rgb32(localPal, PicoMem.cram);\r
-       if (fast_mode)\r
-               return 0x40;\r
+       int pallen = 0x100;\r
 \r
-       if (Pico.video.reg[0xC] & 8) { // shadow/hilight mode\r
-               bgr444_to_rgb32_sh(localPal, PicoMem.cram);\r
-               localPal[0xc0] = 0x0000c000;\r
-               localPal[0xd0] = 0x00c00000;\r
-               localPal[0xe0] = 0x00000000; // reserved pixels for OSD\r
-               localPal[0xf0] = 0x00ffffff;\r
-               pallen = 0x100;\r
+       if (fast_mode) {\r
+               bgr444_to_rgb32(localPal, PicoMem.cram);\r
+               pallen = 0x40;\r
+               Pico.m.dirtyPal = 0;\r
        }\r
        else if (Pico.est.rendstatus & PDRAW_SONIC_MODE) { // mid-frame palette changes\r
-               bgr444_to_rgb32(localPal+0x40, Pico.est.HighPal);\r
-               bgr444_to_rgb32(localPal+0x80, Pico.est.HighPal+0x40);\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
+               }\r
+               pallen = (Pico.est.SonicPalCount+1)*0x40;\r
        }\r
-       else\r
-               memcpy(localPal + 0x80, localPal, 0x40 * 4); // for spr prio mess\r
+       else if (Pico.video.reg[0xC] & 8) { // shadow/hilight mode\r
+               bgr444_to_rgb32(localPal, Pico.est.SonicPal);\r
+               bgr444_to_rgb32_sh(localPal, Pico.est.SonicPal);\r
+       }\r
+       else {\r
+               bgr444_to_rgb32(localPal, Pico.est.SonicPal);\r
+               memcpy(localPal+0x40, localPal, 0x40*4); // for spr prio mess\r
+               memcpy(localPal+0x80, localPal, 0x80*4); // for spr prio mess\r
+       }\r
+       localPal[0xc0] = 0x0000c000;\r
+       localPal[0xd0] = 0x00c00000;\r
+       localPal[0xe0] = 0x00000000; // reserved pixels for OSD\r
+       localPal[0xf0] = 0x00ffffff;\r
 \r
+        if (Pico.m.dirtyPal == 2)\r
+               Pico.m.dirtyPal = 0;\r
        return pallen;\r
 }\r
 \r
@@ -334,25 +347,21 @@ static int make_local_pal_sms(int fast_mode)
                *dpal++ = t;\r
        }\r
 \r
+       Pico.m.dirtyPal = 0;\r
        return 0x40;\r
 }\r
 \r
 void pemu_finalize_frame(const char *fps, const char *notice)\r
 {\r
        int emu_opt = currentConfig.EmuOpt;\r
-       int ret;\r
 \r
        if (PicoIn.AHW & PAHW_32X)\r
-               ; // nothing to do\r
+               localPalSize = 0; // nothing to do\r
        else if (get_renderer() == RT_8BIT_FAST)\r
        {\r
                // 8bit fast renderer\r
-               if (Pico.m.dirtyPal) {\r
-                       Pico.m.dirtyPal = 0;\r
-                       ret = make_local_pal(1);\r
-                       // feed new palette to our device\r
-                       gp2x_video_setpalette(localPal, ret);\r
-               }\r
+               if (Pico.m.dirtyPal)\r
+                       localPalSize = make_local_pal(1);\r
                // a hack for VR\r
                if (PicoIn.AHW & PAHW_SVP)\r
                        memset32((int *)(Pico.est.Draw2FB+328*8+328*223), 0xe0e0e0e0, 328);\r
@@ -364,12 +373,9 @@ void pemu_finalize_frame(const char *fps, const char *notice)
        {\r
                // 8bit accurate renderer\r
                if (Pico.m.dirtyPal)\r
-               {\r
-                       Pico.m.dirtyPal = 0;\r
-                       ret = make_local_pal(0);\r
-                       gp2x_video_setpalette(localPal, ret);\r
-               }\r
+                       localPalSize = make_local_pal(0);\r
        }\r
+       else    localPalSize = 0; // no palette in 16bit mode\r
 \r
        if (notice)\r
                osd_text(4, osd_y, notice);\r
@@ -385,6 +391,10 @@ void plat_video_flip(void)
 {\r
        int stride = g_screen_width;\r
        gp2x_video_flip();\r
+       // switching the palette takes immediate effect, whilst flipping only\r
+       // takes effect with the next vsync; unavoidable flicker may occur!\r
+       if (localPalSize)\r
+               gp2x_video_setpalette(localPal, localPalSize);\r
 \r
        if (is_16bit_mode())\r
                stride *= 2;\r
@@ -502,9 +512,6 @@ static void vid_reset_mode(void)
                if (renderer == RT_16BIT && (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX)) {\r
                        PicoDrawSetOutFormat(PDF_RGB555, 1);\r
                }\r
-               else {\r
-                       PicoDrawSetOutFormat(PDF_NONE, 0);\r
-               }\r
                PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);\r
                gp2x_mode = 16;\r
        }\r
@@ -537,10 +544,7 @@ static void vid_reset_mode(void)
                localPal[0xe0] = 0x00000000; // reserved pixels for OSD\r
                localPal[0xf0] = 0x00ffffff;\r
                gp2x_video_setpalette(localPal, 0x100);\r
-               gp2x_memset_all_buffers(0, 0xe0, 320*240);\r
        }\r
-       else\r
-               gp2x_memset_all_buffers(0, 0, 320*240*2);\r
 \r
        if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX)\r
                gp2x_mode = -gp2x_mode;\r
@@ -723,6 +727,8 @@ void pemu_forced_frame(int no_scale, int do_emu)
        PicoDrawSetCallbacks(NULL, NULL);\r
        Pico.m.dirtyPal = 1;\r
 \r
+       if (!no_scale)\r
+               no_scale = currentConfig.scaling == EOPT_SCALE_NONE;\r
        emu_cmn_forced_frame(no_scale, do_emu);\r
 \r
        g_menubg_src_ptr = g_screen_ptr;\r
index 5d4432f..8af5afa 100644 (file)
@@ -71,8 +71,8 @@ void pemu_finalize_frame(const char *fps, const char *notice)
                unsigned char *ps = Pico.est.Draw2FB + 328*8 + 8;\r
                unsigned short *pal = Pico.est.HighPal;\r
                int i, x;\r
-               if (Pico.m.dirtyPal)\r
-                       PicoDrawUpdateHighPal();\r
+\r
+               PicoDrawUpdateHighPal();\r
                for (i = 0; i < 224; i++, ps += 8)\r
                        for (x = 0; x < 320; x++)\r
                                *pd++ = pal[*ps++];\r
@@ -109,6 +109,8 @@ static void apply_renderer(void)
 \r
        if (PicoIn.AHW & PAHW_32X)\r
                PicoDrawSetOutBuf(g_screen_ptr, g_screen_ppitch * 2);\r
+\r
+       Pico.m.dirtyPal = 1;\r
 }\r
 \r
 void plat_video_toggle_renderer(int change, int is_menu)\r
index 5c0cb57..917ecc8 100644 (file)
@@ -201,13 +201,22 @@ static void do_pal_update(int allow_sh, int allow_as)
 
        //for (i = 0x3f/2; i >= 0; i--)
        //      dpal[i] = ((spal[i]&0x000f000f)<< 1)|((spal[i]&0x00f000f0)<<3)|((spal[i]&0x0f000f00)<<4);
-       do_pal_convert(localPal, Pico.cram, currentConfig.gamma, currentConfig.gamma2);
-
-       Pico.m.dirtyPal = 0;
-       need_pal_upload = 1;
-
-       if (allow_sh && (Pico.video.reg[0xC]&8)) // shadow/hilight?
+       if ((currentConfig.EmuOpt&0x80) || (PicoOpt&0x10)) {
+               do_pal_convert(localPal, Pico.cram, currentConfig.gamma, currentConfig.gamma2);
+               Pico.m.dirtyPal = 0;
+       }
+       else if (Pico.est.rendstatus&0x20)
+       {
+               switch (Pico.est.SonicPalCount) {
+               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);
+               }
+       }
+       else if (allow_sh && (Pico.video.reg[0xC]&8)) // shadow/hilight?
        {
+               do_pal_convert(localPal, Pico.est.SonicPal, currentConfig.gamma, currentConfig.gamma2);
                // shadowed pixels
                for (i = 0x3f/2; i >= 0; i--)
                        dpal[0x20|i] = dpal[0x60|i] = (dpal[i]>>1)&0x7bcf7bcf;
@@ -223,6 +232,16 @@ static void do_pal_update(int allow_sh, int allow_as)
                localPal[0xe0] = 0;
                localPal[0xf0] = 0x001f;
        }
+       else if (allow_as && (Pico.est.rendstatus & PDRAW_SPR_LO_ON_HI))
+       {
+               do_pal_convert(localPal, Pico.est.SonicPal, currentConfig.gamma, currentConfig.gamma2);
+               memcpy((int *)dpal+0x40/2, (void *)localPal, 0x40*2);
+               memcpy((int *)dpal+0x80/2, (void *)localPal, 0x80*2);
+       }
+
+       if (Pico.m.dirtyPal == 2)
+               Pico.m.dirtyPal = 0;
+       need_pal_upload = 1;
 }
 
 static void do_slowmode_lines(int line_to)
@@ -639,7 +658,7 @@ static void writeSound(int len)
 
        PicoIn.sndOut += len / 2;
        /*if (PicoIn.sndOut > sndBuffer_endptr) {
-               memcpy32((int *)(void *)sndBuffer, (int *)endptr, (PicoIn.sndOut - endptr + 1) / 2);
+               memcpy((int *)(void *)sndBuffer, (int *)endptr, (PicoIn.sndOut - endptr + 1) * 2);
                PicoIn.sndOut = &sndBuffer[PicoIn.sndOut - endptr];
                lprintf("mov\n");
        }
index ab022f9..fc31b8e 100644 (file)
@@ -59,7 +59,7 @@ void menu_draw_begin(void)
        // int i;
 
        // for (i = 272; i >= 0; i--, dst += 512, src += 480)
-       //      memcpy32((int *)dst, (int *)src, 480*2/4);
+       //      memcpy((int *)dst, (int *)src, 480*2);
 
        sceGuSync(0,0); // sync with prev
        sceGuStart(GU_DIRECT, guCmdList);