sms, basic gamegear support
authorkub <derkub@gmail.com>
Wed, 13 Oct 2021 19:30:54 +0000 (21:30 +0200)
committerkub <derkub@gmail.com>
Thu, 14 Oct 2021 21:08:17 +0000 (23:08 +0200)
16 files changed:
pico/draw.c
pico/draw_arm.S
pico/media.c
pico/mode4.c
pico/pico.h
pico/pico_int.h
pico/sms.c
platform/common/arm_utils.s
platform/common/emu.c
platform/common/menu_pico.c
platform/common/menu_pico.h
platform/common/upscale.h
platform/gp2x/emu.c
platform/libretro/libretro.c
platform/linux/emu.c
tools/mkoffsets.sh

index 3ae05c5..2b34922 100644 (file)
@@ -135,7 +135,7 @@ void blockcpy_or(void *dst, void *src, size_t n, int pat)
   for (; n; n--)\r
     *pd++ = (unsigned char) (*ps++ | pat);\r
 }\r
-#define blockcpy memcpy\r
+#define blockcpy memmove\r
 #endif\r
 \r
 #define TileNormMaker_(pix_func,ret)                         \\r
@@ -1642,21 +1642,28 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est)
 \r
   PicoDrawUpdateHighPal();\r
 \r
-  if (Pico.video.reg[12]&1) {\r
-    len = 320;\r
-  } else {\r
-    len = 256;\r
-  }\r
-\r
-  if ((*est->PicoOpt & POPT_EN_SOFTSCALE) && len == 256) {\r
-    switch (PicoIn.filter) {\r
-    case 3: h_upscale_bl4_4_5(pd, 320, ps, 256, 256, f_pal); break;\r
-    case 2: h_upscale_bl2_4_5(pd, 320, ps, 256, 256, f_pal); break;\r
-    case 1: h_upscale_snn_4_5(pd, 320, ps, 256, 256, f_pal); break;\r
-    default: h_upscale_nn_4_5(pd, 320, ps, 256, 256, f_pal); break;\r
-    }\r
+  if ((PicoIn.AHW & PAHW_SMS) && (Pico.m.hardware & 0x3) == 0x3)\r
+                                        len = 160;\r
+  else if (Pico.video.reg[12]&1)        len = 320;\r
+  else                                  len = 256;\r
+\r
+  if ((*est->PicoOpt & POPT_EN_SOFTSCALE) && len < 320) {\r
+    if (len == 256)\r
+      switch (PicoIn.filter) {\r
+      case 3: h_upscale_bl4_4_5(pd, 320, ps, 256, len, f_pal); break;\r
+      case 2: h_upscale_bl2_4_5(pd, 320, ps, 256, len, f_pal); break;\r
+      case 1: h_upscale_snn_4_5(pd, 320, ps, 256, len, f_pal); break;\r
+      default: h_upscale_nn_4_5(pd, 320, ps, 256, len, f_pal); break;\r
+      }\r
+    else if (len == 160)\r
+      switch (PicoIn.filter) {\r
+      case 3:\r
+      case 2: h_upscale_bl2_1_2(pd, 320, ps, 160, len, f_pal); break;\r
+      default: h_upscale_nn_1_2(pd, 320, ps, 160, len, f_pal); break;\r
+      }\r
   } else {\r
-    if (!(*est->PicoOpt & POPT_DIS_32C_BORDER) && len == 256) pd += 32;\r
+    if (!(*est->PicoOpt & POPT_DIS_32C_BORDER) && len < 320)\r
+      pd += (320-len) / 2;\r
 #if 1\r
     h_copy(pd, 320, ps, 320, len, f_pal);\r
 #else\r
@@ -1670,9 +1677,10 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est)
 }\r
 #endif\r
 \r
-static void FinalizeLine8bit(int sh, int line, struct PicoEState *est)\r
+void FinalizeLine8bit(int sh, int line, struct PicoEState *est)\r
 {\r
   unsigned char *pd = est->DrawLineDest;\r
+  unsigned char *ps = est->HighCol+8;\r
   int len;\r
   static int dirty_line;\r
 \r
@@ -1680,8 +1688,8 @@ static void FinalizeLine8bit(int sh, int line, struct PicoEState *est)
   {\r
     // a hack for mid-frame palette changes\r
     if (!(est->rendstatus & PDRAW_SONIC_MODE) | (line - dirty_line > 4)) {\r
-      // store a maximum of 2 additional palettes in SonicPal\r
-      if (est->SonicPalCount < 2)\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
@@ -1690,35 +1698,33 @@ static void FinalizeLine8bit(int sh, int line, struct PicoEState *est)
     Pico.m.dirtyPal = 2;\r
   }\r
 \r
-  if (Pico.video.reg[12]&1) {\r
-    len = 320;\r
-  } else {\r
-    len = 256;\r
-  }\r
+  if ((PicoIn.AHW & PAHW_SMS) && (Pico.m.hardware & 0x3) == 0x3)\r
+                                        len = 160;\r
+  else if (Pico.video.reg[12]&1)        len = 320;\r
+  else                                  len = 256;\r
+\r
+  if (DrawLineDestIncrement == 0)\r
+    pd = est->HighCol+8;\r
 \r
-  if ((PicoIn.opt & POPT_EN_SOFTSCALE) && len == 256) {\r
-    unsigned char *ps = est->HighCol+8;\r
+  if ((PicoIn.opt & POPT_EN_SOFTSCALE) && len < 320) {\r
     unsigned char pal = 0;\r
 \r
     if (!sh && (est->rendstatus & PDRAW_SONIC_MODE))\r
       pal = est->SonicPalCount*0x40;\r
-    if (DrawLineDestIncrement == 0)\r
-      pd = est->HighCol+8;\r
     // Smoothing can't be used with CLUT, hence it's always Nearest Neighbour.\r
-    // use reverse version since src and dest ptr may be the same.\r
-    rh_upscale_nn_4_5(pd, 320, ps, 256, len, f_or);\r
-  } else if (DrawLineDestIncrement == 0) {\r
-    if (!sh && (est->rendstatus & PDRAW_SONIC_MODE))\r
-      blockcpy_or(est->HighCol+8, est->HighCol+8, len, est->SonicPalCount*0x40);\r
+    if (len == 256)\r
+      // use reverse version since src and dest ptr may be the same.\r
+      rh_upscale_nn_4_5(pd, 320, ps, 256, len, f_or);\r
+    else\r
+      rh_upscale_nn_1_2(pd, 320, ps, 256, len, f_or);\r
   } else {\r
-    if (!(PicoIn.opt & POPT_DIS_32C_BORDER))\r
-      pd += 32;\r
-    if (!sh && (est->rendstatus & PDRAW_SONIC_MODE)) {\r
+    if (!(*est->PicoOpt & POPT_DIS_32C_BORDER) && len < 320)\r
+      pd += (320-len) / 2;\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
+      blockcpy_or(pd, ps, len, est->SonicPalCount*0x40);\r
+    else if (pd != ps)\r
+      blockcpy(pd, ps, len);\r
   }\r
 }\r
 \r
@@ -1893,8 +1899,15 @@ PICO_INTERNAL void PicoFrameStart(void)
 \r
 static void DrawBlankedLine(int line, int offs, int sh, int bgc)\r
 {\r
-  if (PicoScanBegin != NULL)\r
-    PicoScanBegin(line + offs);\r
+  int skip = skip_next_line;\r
+\r
+  if (PicoScanBegin != NULL && skip == 0)\r
+    skip = PicoScanBegin(line + offs);\r
+\r
+  if (skip) {\r
+    skip_next_line = skip - 1;\r
+    return;\r
+  }\r
 \r
   BackFill(bgc, sh, &Pico.est);\r
 \r
@@ -1902,7 +1915,7 @@ static void DrawBlankedLine(int line, int offs, int sh, int bgc)
     FinalizeLine(sh, line, &Pico.est);\r
 \r
   if (PicoScanEnd != NULL)\r
-    PicoScanEnd(line + offs);\r
+    skip_next_line = PicoScanEnd(line + offs);\r
 \r
   Pico.est.HighCol += HighColIncrement;\r
   Pico.est.DrawLineDest = (char *)Pico.est.DrawLineDest + DrawLineDestIncrement;\r
@@ -1910,15 +1923,10 @@ static void DrawBlankedLine(int line, int offs, int sh, int bgc)
 \r
 static void PicoLine(int line, int offs, int sh, int bgc)\r
 {\r
-  int skip = 0;\r
-\r
-  if (skip_next_line > 0) {\r
-    skip_next_line--;\r
-    return;\r
-  }\r
+  int skip = skip_next_line;\r
 \r
   Pico.est.DrawScanline = line;\r
-  if (PicoScanBegin != NULL)\r
+  if (PicoScanBegin != NULL && skip == 0)\r
     skip = PicoScanBegin(line + offs);\r
 \r
   if (skip) {\r
index 38d831f..6a3641b 100644 (file)
@@ -1642,27 +1642,42 @@ FinalizeLine555:
     add     r3, r10, #OFS_EST_HighPal\r
 \r
     mov     lr, #0xff\r
+    mov     lr, lr, lsl #1\r
 \r
+    ldr     r5, [r10, #OFS_EST_PicoOpt]\r
     ldr     r1, [r10, #OFS_EST_HighCol]\r
     ldr     r0, [r10, #OFS_EST_DrawLineDest]\r
+    ldr     r4, [r5]\r
+    ldr     r7, [r5, #OFS_PicoIn_AHW-OFS_PicoIn_opt]\r
+    ldrb    r12,[r8, #OFS_Pico_video_reg+12]\r
+    ldr     r2, [r8, #OFS_Pico_m_hardware]\r
     add     r1, r1, #8\r
 \r
-    ldrb    r12, [r8, #OFS_Pico_video_reg+12]\r
-    mov     lr, lr, lsl #1\r
+    tst     r7, #0x10\r
+    beq     .fl_no20colRGB555\r
+    and     r7, r2, #0x3\r
+    cmp     r7, #0x3           @ Game Gear, LCD?\r
+    bne     .fl_no20colRGB555\r
 \r
-    tst     r12, #1\r
-    movne   r2, #320/8           @ len\r
+    mov     r2, #160/8         @ len = 160\r
+    tst     r4, #0x4000                @ EN_SOFTSCALE?\r
+    bne     .fl_20scale_RGB555 @ scale 160->320\r
+    beq     .fl_checkborder\r
+\r
+.fl_no20colRGB555:\r
+    tst     r12, #1            @ h32?\r
+    movne   r2, #320/8          @ len = 320\r
     bne     .fl_no32colRGB555\r
-    ldr     r5, [r10, #OFS_EST_PicoOpt]\r
-    mov     r2, #256/8\r
-    ldr     r4, [r5]\r
-    tst     r4, #0x4000\r
-    bne     .fl_32scale_RGB555\r
-    tst     r4, #0x0100\r
-    addeq   r0, r0, #32*2\r
+    moveq   r2, #256/8         @ len = 256\r
+    tst     r4, #0x4000                @ EN_SOFTSCALE?\r
+    bne     .fl_32scale_RGB555 @ scale 256->320\r
 \r
-.fl_no32colRGB555:\r
+.fl_checkborder:\r
+    tst     r4, #0x0100                @ DIS_32C_BORDER?\r
+    rsbeq   r4, r2, #320/8     @ pd += (320-len)/2\r
+    addeq   r0, r0, r4, lsl #3\r
 \r
+.fl_no32colRGB555:\r
 #ifdef UNALIGNED_DRAWLINEDEST\r
     @ this is basically for Gizmondo, which has unaligned odd lines in the framebuffer\r
     tst     r0, #2\r
@@ -1715,9 +1730,9 @@ FinalizeLine555:
     bne     .fl_32scale_RGB555u\r
 #endif\r
 \r
-    ands    r5, r5, #0x3\r
-    addne   pc, pc, r5, lsl #2\r
-    b       .fl_32scale_nn\r
+    and     r5, r5, #0x3\r
+    add     pc, pc, r5, lsl #2\r
+    nop\r
     b       .fl_32scale_nn\r
     b       .fl_32scale_snn\r
     b       .fl_32scale_bl2\r
@@ -1866,6 +1881,9 @@ FinalizeLine555:
     ldmfd   sp!, {r4-r10,pc}\r
 \r
 .fl_32scale_bl4:\r
+    // TODO this should reflect the bl4 C algorithm, but it doesn't, it's bln.\r
+    and     r9, r9, r9, lsl #1        @ nuke 2 LSBs to avoid spilling for n/4\r
+.fl_32loop_bl4:\r
     ldr     r12, [r1], #4\r
     ldr     r7,  [r1], #4\r
 \r
@@ -1926,10 +1944,147 @@ FinalizeLine555:
     subs    r2, r2, #1\r
 \r
     stmia   r0!, {r4,r5,r6,r8,r10}\r
-    bne     .fl_32scale_bl4\r
+    bne     .fl_32loop_bl4\r
+\r
+    ldmfd   sp!, {r4-r10,pc}\r
+\r
+.fl_20scale_RGB555:\r
+    ldr     r5, [r5, #OFS_PicoIn_filter-OFS_PicoIn_opt]\r
+\r
+    mov     r9, #0xf700 @ f800 07e0 001f | e000 0780 001c | 3800 01e0 0007\r
+    orr     r9, r9, #0x00de\r
+\r
+#ifdef UNALIGNED_DRAWLINEDEST\r
+    tst     r0, #2\r
+    bne     .fl_20scale_RGB555u\r
+#endif\r
+\r
+    and     r5, r5, #0x2\r
+    add     pc, pc, r5, lsl #1\r
+    nop\r
+    b       .fl_20scale_nn\r
+    b       .fl_20scale_bl2\r
+\r
+.fl_20scale_nn:\r
+    ldr     r12, [r1], #4\r
+    ldr     r7,  [r1], #4\r
+\r
+    and     r4, lr, r12, lsl #1\r
+    ldrh    r4, [r3, r4]\r
+    and     r5, lr, r12, lsr #7\r
+    ldrh    r5, [r3, r5]\r
+    and     r6, lr, r12, lsr #15\r
+    ldrh    r6, [r3, r6]\r
+    and     r8 ,lr, r12, lsr #23\r
+    ldrh    r8 ,[r3, r8 ]\r
+\r
+    orr     r4, r4, r4, lsl #16\r
+    orr     r5, r5, r5, lsl #16\r
+    orr     r6, r6, r6, lsl #16\r
+    orr     r8, r8, r8, lsl #16\r
+    stmia   r0!, {r4,r5,r6,r8}\r
+\r
+    and     r4, lr, r7, lsl #1\r
+    ldrh    r4, [r3, r4]\r
+    and     r5, lr, r7, lsr #7\r
+    ldrh    r5, [r3, r5]\r
+    and     r6 ,lr, r7, lsr #15\r
+    ldrh    r6 ,[r3, r6]\r
+    and     r8, lr, r7, lsr #23\r
+    ldrh    r8, [r3, r8]\r
+\r
+    orr     r4, r4, r4, lsl #16\r
+    orr     r5, r5, r5, lsl #16\r
+    orr     r6, r6, r6, lsl #16\r
+    orr     r8, r8, r8, lsl #16\r
+    stmia   r0!, {r4,r5,r6,r8}\r
+\r
+    subs    r2, r2, #1\r
+    bne     .fl_20scale_nn\r
+\r
+    ldmfd   sp!, {r4-r10,pc}\r
+\r
+\r
+.fl_20scale_bl2:\r
+    ldr     r8,  [r1]\r
+    and     r8, lr, r8, lsl #1\r
+    ldrh    r8, [r3, r8]\r
+    and     r8, r8, r9\r
+    lsl     r8, r8, #16\r
+\r
+.fl_20loop_bl2:\r
+    ldr     r12, [r1], #4\r
+    ldr     r7,  [r1], #4\r
+\r
+    and     r4, lr, r12, lsl #1\r
+    ldrh    r4, [r3, r4]\r
+    and     r5, lr, r12, lsr #7\r
+    ldrh    r5, [r3, r5]\r
+    and     r6, lr, r12, lsr #15\r
+    ldrh    r6, [r3, r6]\r
+\r
+    and     r4, r4, r9\r
+    add     r10,r4, r8, lsr #16\r
+    mov     r10,r10,lsr #1\r
+    orr     r4, r10,r4, lsl #16                @ (px-1+px0)/2 | px0\r
+\r
+    and     r8 ,lr, r12, lsr #23\r
+    ldrh    r8 ,[r3, r8]\r
+\r
+    and     r5, r5, r9\r
+    add     r10,r5, r4, lsr #16\r
+    mov     r10,r10,lsr #1\r
+    orr     r5, r10,r5, lsl #16                @ (px0 +px1)/2 | px1\r
+\r
+    and     r6, r6, r9\r
+    add     r10,r6, r5, lsr #16\r
+    mov     r10,r10,lsr #1\r
+    orr     r6, r10,r6, lsl #16                @ (px1 +px2)/2 | px2\r
+\r
+    and     r8, r8, r9\r
+    add     r10,r8, r6, lsr #16\r
+    mov     r10,r10,lsr #1\r
+    orr     r8, r10,r8, lsl #16                @ (px2 +px3)/2 | px3\r
+\r
+    stmia   r0!, {r4,r5,r6,r8}\r
+\r
+    and     r4, lr, r7, lsl #1\r
+    ldrh    r4, [r3, r4]\r
+    and     r5, lr, r7, lsr #7\r
+    ldrh    r5, [r3, r5]\r
+    and     r6, lr, r7, lsr #15\r
+    ldrh    r6, [r3, r6]\r
+\r
+    and     r4, r4, r9\r
+    add     r10,r4, r8, lsr #16\r
+    mov     r10,r10,lsr #1\r
+    orr     r4, r10,r4, lsl #16                @ (px-1+px0)/2 | px0\r
+\r
+    and     r8 ,lr, r7, lsr #23\r
+    ldrh    r8 ,[r3, r8]\r
+\r
+    and     r5, r5, r9\r
+    add     r10,r5, r4, lsr #16\r
+    mov     r10,r10,lsr #1\r
+    orr     r5, r10,r5, lsl #16                @ (px0 +px1)/2 | px1\r
+\r
+    and     r6, r6, r9\r
+    add     r10,r6, r5, lsr #16\r
+    mov     r10,r10,lsr #1\r
+    orr     r6, r10,r6, lsl #16                @ (px1 +px2)/2 | px2\r
+\r
+    and     r8, r8, r9\r
+    add     r10,r8, r6, lsr #16\r
+    mov     r10,r10,lsr #1\r
+    orr     r8, r10,r8, lsl #16                @ (px2 +px3)/2 | px3\r
+\r
+    subs    r2, r2, #1\r
+    stmia   r0!, {r4,r5,r6,r8}\r
+    bne     .fl_20loop_bl2\r
 \r
     ldmfd   sp!, {r4-r10,pc}\r
 \r
+\r
 #ifdef UNALIGNED_DRAWLINEDEST\r
     @ unaligned versions of loops\r
     @ warning: starts drawing 2bytes before dst\r
index f4ad8cd..d7e91a0 100644 (file)
@@ -248,7 +248,6 @@ enum media_type_e PicoLoadMedia(const char *filename,
     }
   }
   else if (media_type == PM_MARK3) {
-    lprintf("detected SMS ROM\n");
     PicoIn.AHW = PAHW_SMS;
   }
 
@@ -297,9 +296,18 @@ enum media_type_e PicoLoadMedia(const char *filename,
     goto out;
   }
   rom_data = NULL; // now belongs to PicoCart
-  Pico.m.ncart_in = 0;
+
+  // simple test for GG. Do this here since m.hardware is nulled in Insert
+  if (PicoIn.AHW & PAHW_SMS) {
+    if (strstr(filename,".gg")) {
+      Pico.m.hardware |= 0x1;
+      lprintf("detected GG ROM\n");
+    } else
+      lprintf("detected SMS ROM\n");
+  }
 
   // insert CD if it was detected
+  Pico.m.ncart_in = 0;
   if (cd_img_type != CT_UNKNOWN) {
     ret = cdd_load(filename, cd_img_type);
     if (ret != 0) {
index 889a43e..2406dd4 100644 (file)
@@ -141,6 +141,8 @@ static void DrawSpritesM4(int scanline)
   if (pv->reg[0] & 8)
     xoff = 0;
   xoff += line_offset;
+  if ((Pico.m.hardware & 0x3) == 0x3)
+    xoff -= 48; // GG LCD, adjust to center 160 px
 
   sat = (u8 *)PicoMem.vram + ((pv->reg[5] & 0x7e) << 7);
   if (pv->reg[1] & 2) {
@@ -164,10 +166,12 @@ static void DrawSpritesM4(int scanline)
       break;
     }
 
-    sprites_x[s] = xoff + sat[MEM_LE2(0x80 + i*2)];
-    sprites_addr[s] = sprite_base + ((sat[MEM_LE2(0x80 + i*2 + 1)] & addr_mask) << (5-1)) +
-      ((scanline - y) >> zoomed << (2-1));
-    s++;
+    if (xoff + sat[MEM_LE2(0x80 + i*2)] >= 0) {
+      sprites_x[s] = xoff + sat[MEM_LE2(0x80 + i*2)];
+      sprites_addr[s] = sprite_base + ((sat[MEM_LE2(0x80 + i*2 + 1)] & addr_mask) << (5-1)) +
+        ((scanline - y) >> zoomed << (2-1));
+      s++;
+    }
   }
 
   // really half-assed but better than nothing
@@ -296,9 +300,12 @@ static void DrawDisplayM4(int scanline)
 
   // low priority tiles
   if (!(pv->debug_p & PVD_KILL_B)) {
-    if (pv->reg[0] & 0x80) {
+    if ((Pico.m.hardware & 0x3) == 0x3) {
+      // on GG render only the center 160 px
+      DrawStripLowM4(nametab , dx | ((cells-12)<< 16),(tilex+6) | (ty  << 16));
+    } else if (pv->reg[0] & 0x80) {
       // vscroll disabled for rightmost 8 columns (e.g. Gauntlet)
-      int dx2 = dx + (cells-8)*8, tilex2 = tilex + (cells-8), ty2 = scanline & 7;
+      int dx2 = dx + (cells-8)*8, tilex2 = tilex + (cells-8), ty2 = scanline&7;
       DrawStripLowM4(nametab,  dx | ((cells-8) << 16), tilex  | (ty  << 16));
       DrawStripLowM4(nametab2, dx2 |       (8  << 16), tilex2 | (ty2 << 17));
     } else
@@ -311,8 +318,10 @@ static void DrawDisplayM4(int scanline)
 
   // high priority tiles (use virtual layer switch just for fun)
   if (!(pv->debug_p & PVD_KILL_A)) {
-    if (pv->reg[0] & 0x80) {
-      int dx2 = dx + (cells-8)*8, tilex2 = tilex + (cells-8), ty2 = scanline & 7;
+    if ((Pico.m.hardware & 0x3) == 0x3) {
+      DrawStripHighM4(nametab , dx | ((cells-12)<< 16),(tilex+6) | (ty  << 16));
+    } else if (pv->reg[0] & 0x80) {
+      int dx2 = dx + (cells-8)*8, tilex2 = tilex + (cells-8), ty2 = scanline&7;
       DrawStripHighM4(nametab,  dx | ((cells-8) << 16), tilex  | (ty  << 16));
       DrawStripHighM4(nametab2, dx2 |       (8  << 16), tilex2 | (ty2 << 17));
     } else
@@ -451,20 +460,21 @@ static void DrawSpritesM2(int scanline)
 
   // now draw all sprites backwards
   for (--s; s >= 0; s--) {
-    int x, w = (zoomed ? 16: 8);
+    int x, c, w = (zoomed ? 16: 8);
     i = sprites_x[s];
     x = sat[MEM_LE2(i+1)] + xoff;
     if (sat[MEM_LE2(i+3)] & 0x80)
       x -= 32;
+    c = sat[MEM_LE2(i+3)] & 0x0f;
     if (x > 0) {
       pack = PicoMem.vramb[MEM_LE2(sprites_addr[s])];
-      if (zoomed) TileDoubleSprM2(x, pack, sat[MEM_LE2(i+3)] & 0xf);
-      else        TileNormSprM2(x, pack, sat[MEM_LE2(i+3)] & 0xf);
+      if (zoomed) TileDoubleSprM2(x, pack, c);
+      else        TileNormSprM2(x, pack, c);
     }
     if((pv->reg[1] & 0x2) && (x+=w) > 0) {
       pack = PicoMem.vramb[MEM_LE2(sprites_addr[s]+0x10)];
-      if (zoomed) TileDoubleSprM2(x, pack, sat[MEM_LE2(i+3)] & 0xf);
-      else        TileNormSprM2(x, pack, sat[MEM_LE2(i+3)] & 0xf);
+      if (zoomed) TileDoubleSprM2(x, pack, c);
+      else        TileNormSprM2(x, pack, c);
     }
   }
 }
@@ -524,34 +534,45 @@ static void FinalizeLineRGB555SMS(int line);
 
 void PicoFrameStartSMS(void)
 {
-  int lines = 192, columns = 256, coffs;
+  int lines = 192, columns = 256, loffs, coffs;
   skip_next_line = 0;
-  screen_offset = 24;
+  loffs = screen_offset = 24; // 192 lines is really 224 with top/bottom bars
   Pico.est.rendstatus = PDRAW_32_COLS;
 
-  switch ((Pico.video.reg[0]&0x06) | (Pico.video.reg[1]&0x18)) {
+  // Copy LCD enable flag for easier handling
+  Pico.m.hardware &= ~0x2;
+  if (PicoIn.opt & POPT_EN_GG_LCD)
+    Pico.m.hardware |= 0x2;
+
+  if ((Pico.m.hardware & 0x3) == 0x3) {
+    // GG LCD always has 160x144 regardless of settings
+    screen_offset = 24; // nonetheless the vdp timing has 224 lines
+    loffs = 48;
+    lines = 144;
+    columns = 160;
+  } else switch ((Pico.video.reg[0]&0x06) | (Pico.video.reg[1]&0x18)) {
   // SMS2 only 224/240 line modes, e.g. Micro Machines
   case 0x06|0x08:
-      screen_offset = 0;
+      loffs = screen_offset = 0;
       lines = 240;
       break;
   case 0x06|0x10:
-      screen_offset = 8;
+      loffs = screen_offset = 8;
       lines = 224;
       break;
   }
   if (PicoIn.opt & POPT_EN_SOFTSCALE) {
-    line_offset = 0;
+    coffs = 0;
     columns = 320;
   } else
-    line_offset = PicoIn.opt & POPT_DIS_32C_BORDER ? 0 : 32;
+    coffs = PicoIn.opt & POPT_DIS_32C_BORDER ? 0:(320-columns)/2;
+  line_offset = (PicoIn.opt & POPT_ALT_RENDERER ? coffs : 0);
 
-  coffs = line_offset;
   if (FinalizeLineSMS == FinalizeLineRGB555SMS)
     line_offset = 0 /* done in FinalizeLine */;
 
   if (Pico.est.rendstatus != rendstatus_old || lines != rendlines) {
-    emu_video_mode_change(screen_offset, lines, coffs, columns);
+    emu_video_mode_change(loffs, lines, coffs, columns);
     rendstatus_old = Pico.est.rendstatus;
     rendlines = lines;
   }
@@ -562,14 +583,20 @@ void PicoFrameStartSMS(void)
 
 void PicoLineSMS(int line)
 {
-  if (skip_next_line > 0) {
-    skip_next_line--;
+  int skip = skip_next_line;
+
+  // GG LCD, render only visible part of screen
+  if ((Pico.m.hardware & 0x3) == 0x3 && (line < 24 || line >= 24+144))
+    goto norender;
+
+  if (PicoScanBegin != NULL && skip == 0)
+    skip = PicoScanBegin(line + screen_offset);
+
+  if (skip) {
+    skip_next_line = skip - 1;
     return;
   }
 
-  if (PicoScanBegin != NULL)
-    skip_next_line = PicoScanBegin(line + screen_offset);
-
   // Draw screen:
   BackFill(Pico.video.reg[7] & 0x0f, 0, &Pico.est);
   if (Pico.video.reg[1] & 0x40) {
@@ -583,19 +610,21 @@ void PicoLineSMS(int line)
   if (PicoScanEnd != NULL)
     skip_next_line = PicoScanEnd(line + screen_offset);
 
+norender:
   Pico.est.HighCol += HighColIncrement;
   Pico.est.DrawLineDest = (char *)Pico.est.DrawLineDest + DrawLineDestIncrement;
 }
 
 /* Fixed palette for TMS9918 modes */
 static u16 tmspal[32] = {
- 0x00,0x00,0x08,0x0c,0x10,0x30,0x01,0x3c,0x02,0x03,0x05,0x0f,0x04,0x33,0x15,0x3f
+  0x0000, 0x0000, 0x00a0, 0x00f0, 0x0500, 0x0f00, 0x0005, 0x0ff0,
+  0x000a, 0x000f, 0x0055, 0x00ff, 0x0050, 0x0f0f, 0x0555, 0x0fff,
 };
 
 void PicoDoHighPal555SMS(void)
 {
-  unsigned int *spal=(void *)PicoMem.cram;
-  unsigned int *dpal=(void *)Pico.est.HighPal;
+  u32 *spal=(void *)PicoMem.cram;
+  u32 *dpal=(void *)Pico.est.HighPal;
   unsigned int t;
   int i;
 
@@ -603,21 +632,9 @@ void PicoDoHighPal555SMS(void)
   if (!(Pico.video.reg[0] & 0x4))
     spal = (u32 *)tmspal;
 
-  /* cram is always stored as shorts, even though real hardware probably uses bytes */
-  if (PicoIn.AHW & PAHW_SMS) for (i = 0x20/2; i > 0; i--, spal++, dpal++) { 
-    t = *spal;
-#if defined(USE_BGR555)
-    t = ((t & 0x00030003)<< 3) | ((t & 0x000c000c)<<6) | ((t & 0x00300030)<<9);
-    t |= (t >> 2) | ((t >> 4) & 0x04210421);
-#elif defined(USE_BGR565)
-    t = ((t & 0x00030003)<< 3) | ((t & 0x000c000c)<<7) | ((t & 0x00300030)<<10);
-    t |= (t >> 2) | ((t >> 4) & 0x08610861);
-#else
-    t = ((t & 0x00030003)<<14) | ((t & 0x000c000c)<<7) | ((t & 0x00300030)>>1);
-    t |= (t >> 2) | ((t >> 4) & 0x08610861);
-#endif
-    *dpal = t;
-  } else for (i = 0x20/2; i > 0; i--, spal++, dpal++) { // GG palette 4 bit/col
+  /* SMS 6 bit cram data was already converted to MD/GG format by vdp write,
+   * hence GG/SMS/TMS can all be handled the same here */
+  for (i = 0x20/2; i > 0; i--, spal++, dpal++) { 
     t = *spal;
 #if defined(USE_BGR555)
     t = ((t & 0x000f000f)<< 1) | ((t & 0x00f000f0)<<2) | ((t & 0x0f000f00)<<3);
@@ -646,15 +663,7 @@ static void FinalizeLineRGB555SMS(int line)
 
 static void FinalizeLine8bitSMS(int line)
 {
-  u8 *pd = Pico.est.DrawLineDest + line_offset;
-  u8 *ps = Pico.est.HighCol + line_offset + 8;
-
-  if (DrawLineDestIncrement) {
-    if (PicoIn.opt & POPT_EN_SOFTSCALE)
-      rh_upscale_nn_4_5(pd, 320, ps, 256, 256, f_nop);
-    else if (pd != ps)
-      memcpy(pd, ps, 256);
-  }
+  FinalizeLine8bit(0, line, &Pico.est);
 }
 
 void PicoDrawSetOutputSMS(pdso_t which)
index 76786d6..dc615d1 100644 (file)
@@ -64,7 +64,7 @@ extern void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
 #define POPT_EN_MCD_PCM     (1<<10)\r
 #define POPT_EN_MCD_CDDA    (1<<11)\r
 #define POPT_EN_MCD_GFX     (1<<12) // 00 x000\r
-// unused                   (1<<13)\r
+#define POPT_EN_GG_LCD      (1<<13)\r
 #define POPT_EN_SOFTSCALE   (1<<14)\r
 #define POPT_EN_MCD_RAMCART (1<<15)\r
 #define POPT_DIS_VDP_FIFO   (1<<16) // 0x 0000\r
index 9a66344..e601929 100644 (file)
@@ -670,6 +670,7 @@ PICO_INTERNAL void PicoFrameStart(void);
 void PicoDrawSync(int to, int blank_last_line);\r
 void BackFill(int reg7, int sh, struct PicoEState *est);\r
 void FinalizeLine555(int sh, int line, struct PicoEState *est);\r
+void FinalizeLine8bit(int sh, int line, struct PicoEState *est);\r
 void PicoDrawSetOutBufMD(void *dest, int increment);\r
 extern int (*PicoScanBegin)(unsigned int num);\r
 extern int (*PicoScanEnd)(unsigned int num);\r
index 5f175ca..6c8ce35 100644 (file)
@@ -52,8 +52,17 @@ static void vdp_data_write(unsigned char d)
   struct PicoVideo *pv = &Pico.video;
 
   if (pv->type == 3) {
-    if (PicoMem.cram[pv->addr & 0x1f] != d) Pico.m.dirtyPal = 1;
-    PicoMem.cram[pv->addr & 0x1f] = d;
+    if (Pico.m.hardware & 0x1) { // GG, same layout as MD
+      unsigned a = pv->addr & 0x3f;
+      if (a & 0x1) d &= 0x0f;
+      if (((u8 *)PicoMem.cram)[MEM_LE2(a)] != d) Pico.m.dirtyPal = 1;
+      ((u8 *)PicoMem.cram)[MEM_LE2(a)] = d;
+    } else { // SMS, convert to MD layout (00BbGgRr to 0000BbBbGgGgRrRr)
+      unsigned a = pv->addr & 0x1f;
+      u16 c = (d&0x30)*0x40 + (d&0x0c)*0x10 + (d&0x03)*0x04;
+      if (PicoMem.cram[a] != (c | (c>>2))) Pico.m.dirtyPal = 1;
+      PicoMem.cram[a] = c | (c>>2);
+    }
   } else {
     PicoMem.vramb[MEM_LE2(pv->addr)] = d;
   }
@@ -130,7 +139,7 @@ static unsigned char z80_sms_in(unsigned short a)
     {
       case 0x00:
       case 0x01:
-        d = 0xff;
+        d = 0xff & ~(PicoIn.pad[0] & 0x80);
         break;
 
       case 0x40: /* V counter */
index 6696e5a..5f0c46c 100644 (file)
@@ -58,9 +58,6 @@
 .endif\r
 \r
     orr     r2,  r2,   r2,  lsr #3\r
-.if \sh == 1\r
-    str     r2, [r0, #0x40*2*4]\r
-.endif\r
     str     r2, [r0], #4\r
 .endm\r
 \r
@@ -101,10 +98,10 @@ bgr444_to_rgb32_sh:
     subs    r12, r12, #1\r
 \r
     ldmia    r1!, {r4-r7}\r
-    convRGB32_2 r4, 1\r
-    convRGB32_2 r5, 1\r
-    convRGB32_2 r6, 1\r
-    convRGB32_2 r7, 1\r
+    convRGB32_2 r4, 2\r
+    convRGB32_2 r5, 2\r
+    convRGB32_2 r6, 2\r
+    convRGB32_2 r7, 2\r
     bgt     .loopRGB32sh\r
 \r
     mov     r12, #0x40>>3 @ repeats\r
@@ -112,10 +109,10 @@ bgr444_to_rgb32_sh:
 \r
 .loopRGB32hi:\r
      ldmia    r1!, {r4-r7}\r
-    convRGB32_2 r4, 2\r
-    convRGB32_2 r5, 2\r
-    convRGB32_2 r6, 2\r
-    convRGB32_2 r7, 2\r
+    convRGB32_2 r4, 1\r
+    convRGB32_2 r5, 1\r
+    convRGB32_2 r6, 1\r
+    convRGB32_2 r7, 1\r
 \r
     subs    r12, r12, #1\r
     bgt     .loopRGB32hi\r
index fd4a251..1ae8cdb 100644 (file)
@@ -326,6 +326,8 @@ static void system_announce(void)
 \r
        if (PicoIn.AHW & PAHW_SMS) {\r
                sys_name = "Master System";\r
+               if (Pico.m.hardware & 0x1)\r
+                       sys_name = "Game Gear";\r
 #ifdef NO_SMS\r
                extra = " [no support]";\r
 #endif\r
@@ -587,7 +589,7 @@ void emu_prep_defconfig(void)
        memset(&defaultConfig, 0, sizeof(defaultConfig));\r
        defaultConfig.EmuOpt    = EOPT_EN_SRAM | EOPT_EN_SOUND | EOPT_16BPP |\r
                                  EOPT_EN_CD_LEDS | EOPT_GZIP_SAVES | 0x10/*?*/;\r
-       defaultConfig.s_PicoOpt = POPT_EN_SNDFILTER|POPT_EN_YM2413|\r
+       defaultConfig.s_PicoOpt = POPT_EN_SNDFILTER|POPT_EN_YM2413|POPT_EN_GG_LCD |\r
                                  POPT_EN_STEREO|POPT_EN_FM|POPT_EN_PSG|POPT_EN_Z80 |\r
                                  POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_MCD_GFX |\r
                                  POPT_EN_DRC|POPT_ACC_SPRITES |\r
index 6a6da39..c616298 100644 (file)
@@ -42,7 +42,7 @@ static const char *rom_exts[] = {
        "bin", "smd", "gen", "md",
        "iso", "cso", "cue", "chd",
        "32x",
-       "sms",
+       "sms", "gg",
        NULL
 };
 
@@ -536,6 +536,7 @@ static menu_entry e_menu_adv_options[] =
        mee_onoff     ("Disable YM2612 SSG-EG",    MA_OPT2_DISABLE_YM_SSG,PicoIn.opt, POPT_DIS_FM_SSGEG),
        mee_onoff     ("Emulate SN76496 (PSG)",    MA_OPT2_ENABLE_SN76496,PicoIn.opt, POPT_EN_PSG),
        mee_onoff     ("Emulate YM2413 (FM)",      MA_OPT2_ENABLE_YM2413 ,PicoIn.opt, POPT_EN_YM2413),
+       mee_onoff     ("Emulate Game Gear LCD",    MA_OPT2_ENABLE_GGLCD  ,PicoIn.opt, POPT_EN_GG_LCD),
        mee_onoff     ("Disable idle loop patching",MA_OPT2_NO_IDLE_LOOPS,PicoIn.opt, POPT_DIS_IDLE_DET),
        mee_onoff     ("Disable frame limiter",    MA_OPT2_NO_FRAME_LIMIT,currentConfig.EmuOpt, EOPT_NO_FRMLIMIT),
        mee_onoff     ("Enable dynarecs",          MA_OPT2_DYNARECS,      PicoIn.opt, POPT_EN_DRC),
index 2b699ef..af365db 100644 (file)
@@ -52,6 +52,7 @@ typedef enum
        MA_OPT2_DISABLE_YM_SSG,
        MA_OPT2_ENABLE_SN76496,
        MA_OPT2_ENABLE_YM2413,
+       MA_OPT2_ENABLE_GGLCD,
        MA_OPT2_NO_LAST_ROM,
        MA_OPT2_RAMTIMINGS,     /* gp2x */
        MA_OPT2_NO_FRAME_LIMIT, /* psp */
index 9719981..1cf0fd9 100644 (file)
  */
 #include <pico/pico_types.h>
 
+
+/* LSB of all colors in a pixel */
+#if defined(USE_BGR555)
+#define PXLSB          0x0421
+#else
+#define PXLSB          0x0821
+#endif
+
 /* RGB565 pixel mixing, see https://www.compuphase.com/graphic/scale3.htm and
                            http://blargg.8bitalley.com/info/rgb_mixing.html */
 /* 2-level mixing */
-//#define p_05(d,p1,p2)        d=(((p1)+(p2)  + ( ((p1)^(p2))&0x0821))>>1) // round up
-//#define p_05(d,p1,p2)        d=(((p1)+(p2)  - ( ((p1)^(p2))&0x0821))>>1) // round down
-#define p_05(d,p1,p2)  d=(((p1)&(p2)) + ((((p1)^(p2))&~0x0821)>>1))
+//#define p_05(d,p1,p2)        d=(((p1)+(p2)  + ( ((p1)^(p2))&PXLSB))>>1) // round up
+//#define p_05(d,p1,p2)        d=(((p1)+(p2)  - ( ((p1)^(p2))&PXLSB))>>1) // round down
+#define p_05(d,p1,p2)  d=(((p1)&(p2)) + ((((p1)^(p2))&~PXLSB)>>1))
 /* 4-level mixing, 2 times slower */
 // 1/4*p1 + 3/4*p2 = 1/2*(1/2*(p1+p2) + p2)
 #define p_025(d,p1,p2) p_05(t, p1, p2); p_05( d, t, p2)
@@ -322,6 +330,21 @@ scalers h:
        si += ss - w;                                   \
 } while (0)
 
+// reverse version for overlapping buffers
+#define rh_upscale_nn_1_2(di,ds,si,ss,w,f) do {        \
+       int i;                                          \
+       di += w*2;                                      \
+       si += w;                                        \
+       for (i = w/2; i > 0; i--, si -= 2, di -= 4) {   \
+               di[-1] = f(si[-1]);                     \
+               di[-2] = f(si[-1]);                     \
+               di[-3] = f(si[-2]);                     \
+               di[-4] = f(si[-2]);                     \
+       }                                               \
+       di += ds;                                       \
+       si += ss;                                       \
+} while (0)
+
 #define h_upscale_bl2_1_2(di,ds,si,ss,w,f) do {                \
        int i; uint p = f(si[0]);                       \
        for (i = w/2; i > 0; i--, si += 2, di += 4) {   \
@@ -514,11 +537,12 @@ scalers v:
        } else  {                                       \
                int j;                                  \
                l = 0;                                  \
-               di -= 4*ds;                             \
+               di -= 3*ds;                             \
                for (j = 0; j < 2; j++) {               \
                        v_copy(&di[0], &di[-ds], w, f_nop); \
                        di += 2*ds;                     \
                }                                       \
+               di -= ds;                       \
        }                                               \
 } while (0)
 
@@ -528,11 +552,12 @@ scalers v:
        } else  {                                       \
                int j;                                  \
                l = 0;                                  \
-               di -= 4*ds;                             \
+               di -= 3*ds;                             \
                for (j = 0; j < 2; j++) {               \
                        v_mix(&di[0], &di[-ds], &di[ds], w, p_05, f_nop); \
                        di += 2*ds;                     \
                }                                       \
+               di -= ds;                       \
        }                                               \
 } while (0)
 
index 0622691..deb8658 100644 (file)
@@ -105,7 +105,7 @@ static void change_renderer(int diff)
 }\r
 \r
 #define is_16bit_mode() \\r
-       (currentConfig.renderer == RT_16BIT || (PicoIn.AHW & PAHW_32X))\r
+       (currentConfig.renderer == RT_16BIT || (PicoIn.AHW & PAHW_32X) || doing_bg_frame)\r
 \r
 static void (*osd_text)(int x, int y, const char *text);\r
 \r
@@ -248,7 +248,7 @@ static int EmuScanEnd8_rot(unsigned int num)
 \r
 /* line doublers */\r
 static unsigned int ld_counter;\r
-static int ld_left, ld_lines;\r
+static int ld_left, ld_lines; // numbers in Q1 format\r
 \r
 static int EmuScanBegin16_ld(unsigned int num)\r
 {\r
@@ -271,9 +271,9 @@ static int EmuScanEnd16_ld(unsigned int num)
                emu_scan_end(ld_counter);\r
 \r
        ld_counter++;\r
-       ld_left--;\r
+       ld_left -= 2;\r
        if (ld_left <= 0) {\r
-               ld_left = ld_lines;\r
+               ld_left += ld_lines;\r
 \r
                EmuScanBegin16_ld(num);\r
                memcpy(Pico.est.DrawLineDest, oldline, 320 * gp2x_current_bpp / 8);\r
@@ -313,6 +313,7 @@ static int make_local_pal_md(int fast_mode)
        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
+               memcpy(localPal+0xc0, localPal, 0x40*4); // for spr prio mess\r
        }\r
        else {\r
                bgr444_to_rgb32(localPal, Pico.est.SonicPal);\r
@@ -331,18 +332,7 @@ static int make_local_pal_md(int fast_mode)
 \r
 static int make_local_pal_sms(int fast_mode)\r
 {\r
-       unsigned short *spal = PicoMem.cram;\r
-       unsigned int *dpal = (void *)localPal;\r
-       unsigned int i, t;\r
-\r
-       for (i = 0x40; i > 0; i--) {\r
-               t = *spal++;\r
-               t = ((t & 0x0003) << 22) | ((t & 0x000c) << 12) | ((t & 0x0030) << 2);\r
-               t |= t >> 2;\r
-               t |= t >> 4;\r
-               *dpal++ = t;\r
-       }\r
-\r
+       bgr444_to_rgb32(localPal, PicoMem.cram);\r
        Pico.m.dirtyPal = 0;\r
        return 0x40;\r
 }\r
@@ -486,6 +476,9 @@ static void vid_reset_mode(void)
        int gp2x_mode = 16;\r
        int renderer = get_renderer();\r
 \r
+       if (doing_bg_frame)\r
+               renderer = RT_16BIT;\r
+\r
        PicoIn.opt &= ~POPT_ALT_RENDERER;\r
        emu_scan_begin = NULL;\r
        emu_scan_end = NULL;\r
@@ -557,11 +550,13 @@ static void vid_reset_mode(void)
 \r
        Pico.m.dirtyPal = 1;\r
 \r
-       PicoIn.opt &= ~POPT_EN_SOFTSCALE;\r
+       PicoIn.opt &= ~(POPT_DIS_32C_BORDER|POPT_EN_SOFTSCALE);\r
        if (currentConfig.scaling == EOPT_SCALE_SW) {\r
                PicoIn.opt |= POPT_EN_SOFTSCALE;\r
                PicoIn.filter = EOPT_FILTER_BILINEAR2;\r
-       }\r
+       } else if (currentConfig.scaling == EOPT_SCALE_HW && is_16bit_mode())\r
+               // hw scaling, render without any padding\r
+               PicoIn.opt |= POPT_DIS_32C_BORDER;\r
 \r
        // palette converters for 8bit modes\r
        make_local_pal = (PicoIn.AHW & PAHW_SMS) ? make_local_pal_sms : make_local_pal_md;\r
@@ -572,6 +567,12 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co
        int scalex = 320, scaley = 240;\r
        int ln_offs = 0;\r
 \r
+       /* line doubling for swscaling, also needed for bg frames */\r
+       if (currentConfig.vscaling == EOPT_SCALE_SW && line_count < 240) {\r
+               ld_lines = ld_left = 2*line_count / (240 - line_count);\r
+               PicoDrawSetCallbacks(EmuScanBegin16_ld, EmuScanEnd16_ld);\r
+       }\r
+\r
        if (doing_bg_frame)\r
                return;\r
 \r
@@ -579,10 +580,8 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co
        osd_y = 232;\r
 \r
        /* set up hwscaling here */\r
-       PicoIn.opt &= ~POPT_DIS_32C_BORDER;\r
        if (col_count < 320 && currentConfig.scaling == EOPT_SCALE_HW) {\r
                scalex = col_count;\r
-               PicoIn.opt |= POPT_DIS_32C_BORDER;\r
                osd_fps_x = col_count - (320-OSD_FPS_X);\r
        }\r
 \r
@@ -594,11 +593,6 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co
 \r
        gp2x_video_RGB_setscaling(ln_offs, scalex, scaley);\r
 \r
-       /* line doubling */\r
-       if (currentConfig.vscaling == EOPT_SCALE_SW && line_count < 240) {\r
-               ld_lines = ld_left = line_count / (240 - line_count);\r
-               PicoDrawSetCallbacks(EmuScanBegin16_ld, EmuScanEnd16_ld);\r
-       }\r
 \r
        // clear whole screen in all buffers\r
        if (!is_16bit_mode())\r
@@ -731,6 +725,8 @@ void pemu_forced_frame(int no_scale, int do_emu)
        doing_bg_frame = 1;\r
        PicoDrawSetCallbacks(NULL, NULL);\r
        Pico.m.dirtyPal = 1;\r
+       PicoIn.opt &= ~POPT_DIS_32C_BORDER;\r
+       gp2x_current_bpp = 16;\r
 \r
        if (!no_scale)\r
                no_scale = currentConfig.scaling == EOPT_SCALE_NONE;\r
@@ -749,6 +745,7 @@ void plat_video_loop_prepare(void)
        // make sure we are in correct mode\r
        change_renderer(0);\r
        vid_reset_mode();\r
+       rendstatus_old = -1;\r
 }\r
 \r
 void pemu_loop_prep(void)\r
index 7c63c97..4a9abea 100644 (file)
@@ -89,8 +89,8 @@ static retro_audio_sample_batch_t audio_batch_cb;
 #define INITIAL_SND_RATE 44100
 
 static const float VOUT_PAR = 0.0;
-static const float VOUT_4_3 = (224.0f * (4.0f / 3.0f));
-static const float VOUT_CRT = (224.0f * 1.29911f);
+static const float VOUT_4_3 = (4.0f / 3.0f);
+static const float VOUT_CRT = (1.29911f);
 
 static bool show_overscan = false;
 static bool old_show_overscan = false;
@@ -746,7 +746,7 @@ void retro_get_system_info(struct retro_system_info *info)
 #define _GIT_VERSION "-" GIT_VERSION
 #endif
    info->library_version = VERSION _GIT_VERSION;
-   info->valid_extensions = "bin|gen|smd|md|32x|cue|iso|chd|sms";
+   info->valid_extensions = "bin|gen|smd|md|32x|cue|iso|chd|sms|gg";
    info->need_fullpath = true;
 }
 
@@ -899,7 +899,7 @@ typedef struct patch
 } patch;
 
 extern void decode(char *buff, patch *dest);
-extern uint16_t m68k_read16(uint32_t a);
+extern uint32_t m68k_read16(uint32_t a);
 extern void m68k_write16(uint32_t a, uint16_t d);
 
 void retro_cheat_reset(void)
@@ -1494,12 +1494,13 @@ static void update_variables(bool first_run)
    var.value = NULL;
    var.key = "picodrive_aspect";
    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
+      int height = vout_height >= 192 && vout_height <= 224 ? 224 : vout_height;
       if (strcmp(var.value, "4/3") == 0)
-         user_vout_width = VOUT_4_3;
+         user_vout_width = VOUT_4_3 * height;
       else if (strcmp(var.value, "CRT") == 0)
-         user_vout_width = VOUT_CRT;
+         user_vout_width = VOUT_CRT * height;
       else
-         user_vout_width = VOUT_PAR;
+         user_vout_width = VOUT_PAR * height;
    }
 
    if (user_vout_width != old_user_vout_width)
@@ -1801,7 +1802,8 @@ void retro_init(void)
    sceBlock = getVMBlock();
 #endif
 
-   PicoIn.opt = POPT_EN_STEREO|POPT_EN_FM|POPT_EN_PSG|POPT_EN_Z80|POPT_EN_YM2413
+   PicoIn.opt = POPT_EN_STEREO|POPT_EN_FM
+      | POPT_EN_PSG|POPT_EN_Z80|POPT_EN_YM2413|POPT_EN_GG_LCD
       | POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_MCD_GFX
       | POPT_EN_32X|POPT_EN_PWM
       | POPT_ACC_SPRITES|POPT_DIS_32C_BORDER;
index 36898e6..1b228e9 100644 (file)
@@ -95,7 +95,7 @@ static void draw_cd_leds(void)
  * for display isn't always possible.\r
  */\r
 \r
-static u16 *screen_buffer(u16 *buf)\r
+static inline u16 *screen_buffer(u16 *buf)\r
 {\r
        return buf + screen_y * g_screen_ppitch + screen_x -\r
                        (out_y * g_screen_ppitch + out_x);\r
@@ -105,34 +105,46 @@ void screen_blit(u16 *pd, int pp, u8* ps, int ss, u16 *pal)
 {\r
        typedef void (*upscale_t)\r
                        (u16 *di,int ds, u8 *si,int ss, int w,int h, u16 *pal);\r
-       upscale_t upscale_hv[] = {\r
+       static const upscale_t upscale_256_224_hv[] = {\r
                upscale_rgb_nn_x_4_5_y_16_17,   upscale_rgb_snn_x_4_5_y_16_17,\r
                upscale_rgb_bl2_x_4_5_y_16_17,  upscale_rgb_bl4_x_4_5_y_16_17,\r
        };\r
-       upscale_t upscale_h[] = {\r
+       static const upscale_t upscale_256_224_h[] = {\r
                upscale_rgb_nn_x_4_5,           upscale_rgb_snn_x_4_5,\r
                upscale_rgb_bl2_x_4_5,          upscale_rgb_bl4_x_4_5,\r
        };\r
-       upscale_t upscale_v[] = {\r
+       static const upscale_t upscale_256_224_v[] = {\r
                upscale_rgb_nn_y_16_17,         upscale_rgb_snn_y_16_17,\r
                upscale_rgb_bl2_y_16_17,        upscale_rgb_bl4_y_16_17,\r
        };\r
-       upscale_t *upscale;\r
+       static const upscale_t upscale_160_144_hv[] = {\r
+               upscale_rgb_nn_x_1_2_y_3_5,     upscale_rgb_nn_x_1_2_y_3_5,\r
+               upscale_rgb_bl2_x_1_2_y_3_5,    upscale_rgb_bl4_x_1_2_y_3_5,\r
+       };\r
+       static const upscale_t upscale_160_144_h[] = {\r
+               upscale_rgb_nn_x_1_2,           upscale_rgb_nn_x_1_2,\r
+               upscale_rgb_bl2_x_1_2,          upscale_rgb_bl2_x_1_2,\r
+       };\r
+       static const upscale_t upscale_160_144_v[] = {\r
+               upscale_rgb_nn_y_3_5,           upscale_rgb_nn_y_3_5,\r
+               upscale_rgb_bl2_y_3_5,          upscale_rgb_bl4_y_3_5,\r
+       };\r
+       const upscale_t *upscale;\r
        int y;\r
 \r
        // handle software upscaling\r
        upscale = NULL;\r
-       if (currentConfig.scaling == EOPT_SCALE_SW && out_w == 256) {\r
-               if (currentConfig.vscaling == EOPT_SCALE_SW && out_h <= 224)\r
-                       // h+v scaling\r
-                       upscale = upscale_hv;\r
-               else\r
-                       // h scaling\r
-                       upscale = upscale_h;\r
-       } else if (currentConfig.vscaling == EOPT_SCALE_SW && out_h <= 224) {\r
-                       // v scaling\r
-                       upscale = upscale_v;\r
-       } else {\r
+       if (currentConfig.scaling == EOPT_SCALE_SW) {\r
+           if (currentConfig.vscaling == EOPT_SCALE_SW && out_h <= 224)\r
+               // h+v scaling\r
+               upscale = out_w == 256 ? upscale_256_224_hv: upscale_160_144_hv;\r
+           else\r
+               // h scaling\r
+               upscale = out_w == 256 ? upscale_256_224_h : upscale_160_144_h;\r
+       } else if (currentConfig.vscaling == EOPT_SCALE_SW && out_h <= 224)\r
+               // v scaling\r
+               upscale = out_w == 256 ? upscale_256_224_v : upscale_160_144_v;\r
+       if (!upscale) {\r
                // no scaling\r
                for (y = 0; y < out_h; y++)\r
                        h_copy(pd, pp, ps, 328, out_w, f_pal);\r
@@ -280,16 +292,16 @@ static int vscale_state;
 \r
 static int cb_vscaling_begin(unsigned int line)\r
 {\r
-       static int prevline = 999;\r
-\r
        // at start of new frame?\r
-       if (line < prevline) {\r
-               // set y frame offset (see emu_change_video_mode)\r
+       if (line <= out_y) {\r
+               // set y frame offset (see emu_video_mode_change)\r
                Pico.est.DrawLineDest = screen_buffer(g_screen_ptr) +\r
-                               (out_y * g_screen_ppitch + out_x);\r
+                               (out_y * g_screen_ppitch /*+ out_x*/);\r
                vscale_state = 0;\r
-       }\r
-       prevline = line;\r
+               return out_y - line;\r
+       } else if (line > out_y + out_h)\r
+               return 1;\r
+\r
        return 0;\r
 }\r
 \r
@@ -301,16 +313,25 @@ static int cb_vscaling_nop(unsigned int line)
 static int cb_vscaling_end(unsigned int line)\r
 {\r
        u16 *dest = Pico.est.DrawLineDest;\r
-       switch (currentConfig.filter) {\r
-       case 3: v_upscale_bl4_16_17(dest, g_screen_ppitch, 320, vscale_state);\r
-               break;\r
-       case 2: v_upscale_bl2_16_17(dest, g_screen_ppitch, 320, vscale_state);\r
-               break;\r
-       case 1: v_upscale_snn_16_17(dest, g_screen_ppitch, 320, vscale_state);\r
-               break;\r
-       default: v_upscale_nn_16_17(dest, g_screen_ppitch, 320, vscale_state);\r
-               break;\r
-       }\r
+\r
+       if (out_h == 144)\r
+         switch (currentConfig.filter) {\r
+         case 0: v_upscale_nn_3_5(dest, g_screen_ppitch, 320, vscale_state);\r
+                 break;\r
+         default: v_upscale_snn_3_5(dest, g_screen_ppitch, 320, vscale_state);\r
+                 break;\r
+         }\r
+       else\r
+         switch (currentConfig.filter) {\r
+         case 3: v_upscale_bl4_16_17(dest, g_screen_ppitch, 320, vscale_state);\r
+                 break;\r
+         case 2: v_upscale_bl2_16_17(dest, g_screen_ppitch, 320, vscale_state);\r
+                 break;\r
+         case 1: v_upscale_snn_16_17(dest, g_screen_ppitch, 320, vscale_state);\r
+                 break;\r
+         default: v_upscale_nn_16_17(dest, g_screen_ppitch, 320, vscale_state);\r
+                 break;\r
+         }\r
        Pico.est.DrawLineDest = dest;\r
        return 0;\r
 }\r
@@ -337,10 +358,10 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co
        }\r
        switch (currentConfig.vscaling) {\r
        case EOPT_SCALE_HW:\r
-               screen_h = (out_h < 224 ? 224 : out_h);\r
+               screen_h = (out_h < 224 && out_h > 144 ? 224 : out_h);\r
                screen_y = 0;\r
                // NTSC always has 224 visible lines, anything smaller has bars\r
-               if (out_h < 224)\r
+               if (out_h < 224 && out_h > 144)\r
                        screen_y += (224 - out_h)/2;\r
                // handle vertical centering for 16 bit mode\r
                if (is_16bit_mode())\r
@@ -349,7 +370,7 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co
        case EOPT_SCALE_SW:\r
                screen_y = (screen_h - 240)/2;\r
                // NTSC always has 224 visible lines, anything smaller has bars\r
-               if (out_h < 224)\r
+               if (out_h < 224 && out_h > 144)\r
                        screen_y += (224 - out_h)/2;\r
                // in 16 bit mode sw scaling is divided between core and platform\r
                if (is_16bit_mode() && out_h < 240)\r
index 615e347..d9a8db5 100755 (executable)
@@ -136,6 +136,7 @@ get_define OFS_Pico_ Pico est                       ; echo "$line" >>$fn
 
 get_define OFS_PicoIn_ PicoInterface opt       ; echo "$line" >>$fn
 get_define OFS_PicoIn_ PicoInterface filter    ; echo "$line" >>$fn
+get_define OFS_PicoIn_ PicoInterface AHW       ; echo "$line" >>$fn
 
 get_define OFS_EST_ PicoEState DrawScanline    ; echo "$line" >>$fn
 get_define OFS_EST_ PicoEState rendstatus      ; echo "$line" >>$fn