frontend: scanline efect and memcard saving
authornotaz <notasas@gmail.com>
Thu, 25 Dec 2014 02:44:22 +0000 (04:44 +0200)
committernotaz <notasas@gmail.com>
Thu, 25 Dec 2014 02:44:22 +0000 (04:44 +0200)
frontend/cspace.h
frontend/cspace_neon.S
frontend/menu.c
frontend/menu.h
frontend/plugin_lib.c

index 1a9e339..8c92d2d 100644 (file)
@@ -8,6 +8,9 @@ void bgr888_to_rgb888(void *dst, const void *src, int bytes);
 void bgr888_to_rgb565(void *dst, const void *src, int bytes);
 void rgb888_to_rgb565(void *dst, const void *src, int bytes);
 
+void bgr555_to_rgb565_b(void *dst, const void *src, int bytes,
+       int brightness2k); // 0-0x0800
+
 void bgr_to_uyvy_init(void);
 void rgb565_to_uyvy(void *d, const void *s, int pixels);
 void bgr555_to_uyvy(void *d, const void *s, int pixels);
index 342876f..8b201db 100644 (file)
@@ -72,12 +72,93 @@ btr16_end16:
     bxlt        lr
 
     @ very rare
-    vld1.16     d0, [r1]!
+    vld1.16     {d0}, [r1]!
     vshl.u16    d1, d0, #11
     vshl.u16    d2, d0, #1
     vsri.u16    d1, d0, #10
     vbit        d1, d2, d30
-    vst1.16     d1, [r0]!
+    vst1.16     {d1}, [r0]!
+    bx          lr
+
+
+@ note: may overflow source
+FUNCTION(bgr555_to_rgb565_b): @ dst, src, bytes, int brightness2k // 0-0x0800
+    pld         [r1]
+    vdup.16     q15, r3
+    vpush       {q4-q7}
+    mov         r3, #0x1f
+    vdup.16     q14, r3
+0:
+    pld         [r1, #64*2]
+    vldmia      r1!, {q0-q3}
+    vand.u16    q8,  q0, q14
+    vand.u16    q9,  q1, q14
+    vand.u16    q10, q2, q14
+    vand.u16    q11, q3, q14
+    vmul.u16    q4, q8,  q15
+    vmul.u16    q5, q9,  q15
+    vmul.u16    q6, q10, q15
+    vmul.u16    q7, q11, q15
+
+    vshr.u16    q8,  q0, #5
+    vshr.u16    q9,  q1, #5
+    vshr.u16    q10, q2, #5
+    vshr.u16    q11, q3, #5
+    vand.u16    q8,  q14
+    vand.u16    q9,  q14
+    vand.u16    q10, q14
+    vand.u16    q11, q14
+    vmul.u16    q8,  q15
+    vmul.u16    q9,  q15
+    vmul.u16    q10, q15
+    vmul.u16    q11, q15
+    vsri.u16    q4, q8,  #5
+    vsri.u16    q5, q9,  #5
+    vsri.u16    q6, q10, #5
+    vsri.u16    q7, q11, #5
+
+    vshr.u16    q8,  q0, #10
+    vshr.u16    q9,  q1, #10
+    vshr.u16    q10, q2, #10
+    vshr.u16    q11, q3, #10
+    vand.u16    q8,  q14
+    vand.u16    q9,  q14
+    vand.u16    q10, q14
+    vand.u16    q11, q14
+    vmul.u16    q8,  q15
+    vmul.u16    q9,  q15
+    vmul.u16    q10, q15
+    vmul.u16    q11, q15
+    vsri.u16    q4, q8,  #11
+    vsri.u16    q5, q9,  #11
+    vsri.u16    q6, q10, #11
+    vsri.u16    q7, q11, #11
+
+    subs        r2, r2, #64
+    ble         1f
+    vstmia      r0!, {q4-q7}
+    b           0b
+
+1:
+    blt         0f
+    vstmia      r0!, {q4-q7}
+    b           btr16b_end
+0:
+    subs        r2, r2, #8
+    blt         btr16b_end
+    vst1.16     {q4}, [r0]!
+    subs        r2, r2, #8
+    blt         btr16b_end
+    vst1.16     {q5}, [r0]!
+    subs        r2, r2, #8
+    blt         btr16b_end
+    vst1.16     {q6}, [r0]!
+    subs        r2, r2, #8
+    blt         btr16b_end
+    vst1.16     {q7}, [r0]!
+
+btr16b_end:
+    vpop        {q4-q7}
     bx          lr
 
 
index a37ab05..cfa3284 100644 (file)
@@ -83,6 +83,8 @@ typedef enum
        MA_OPT_SWFILTER,
        MA_OPT_GAMMA,
        MA_OPT_VOUT_MODE,
+       MA_OPT_SCANLINES,
+       MA_OPT_SCANLINE_LEVEL,
 } menu_id;
 
 static int last_vout_w, last_vout_h, last_vout_bpp;
@@ -90,8 +92,9 @@ static int cpu_clock, cpu_clock_st, volume_boost, frameskip;
 static char last_selected_fname[MAXPATHLEN];
 static int config_save_counter, region, in_type_sel1, in_type_sel2;
 static int psx_clock;
-static int memcard1_sel, memcard2_sel;
+static int memcard1_sel = -1, memcard2_sel = -1;
 int g_opts, g_scaler, g_gamma = 100;
+int scanlines, scanline_level = 20;
 int soft_scaling, analog_deadzone; // for Caanoo
 int soft_filter;
 
@@ -333,6 +336,8 @@ static void menu_set_defconfig(void)
        analog_deadzone = 50;
        soft_scaling = 1;
        soft_filter = 0;
+       scanlines = 0;
+       scanline_level = 20;
        plat_target.vout_fullscreen = 0;
        psx_clock = DEFAULT_PSX_CLOCK;
 
@@ -398,6 +403,8 @@ static const struct {
        CE_INTVAL(g_layer_w),
        CE_INTVAL(g_layer_h),
        CE_INTVAL(soft_filter),
+       CE_INTVAL(scanlines),
+       CE_INTVAL(scanline_level),
        CE_INTVAL(plat_target.vout_method),
        CE_INTVAL(plat_target.hwfilter),
        CE_INTVAL(plat_target.vout_fullscreen),
@@ -407,6 +414,8 @@ static const struct {
        CE_INTVAL(in_type_sel1),
        CE_INTVAL(in_type_sel2),
        CE_INTVAL(analog_deadzone),
+       CE_INTVAL(memcard1_sel),
+       CE_INTVAL(memcard2_sel),
        CE_INTVAL_N("adev0_is_nublike", in_adev_is_nublike[0]),
        CE_INTVAL_N("adev1_is_nublike", in_adev_is_nublike[1]),
        CE_INTVAL_V(frameskip, 3),
@@ -664,6 +673,29 @@ fail:
                if (strcmp(Config.Spu, spu_plugins[i]) == 0)
                        { spu_plugsel = i; break; }
 
+       // memcard selections
+       char mcd1_old[sizeof(Config.Mcd1)];
+       char mcd2_old[sizeof(Config.Mcd2)];
+       strcpy(mcd1_old, Config.Mcd1);
+       strcpy(mcd2_old, Config.Mcd2);
+
+       if ((unsigned int)memcard1_sel < ARRAY_SIZE(memcards)) {
+               if (memcard1_sel == 0)
+                       strcpy(Config.Mcd1, "none");
+               else if (memcards[memcard1_sel] != NULL)
+                       snprintf(Config.Mcd1, sizeof(Config.Mcd1), ".%s%s",
+                               MEMCARD_DIR, memcards[memcard1_sel]);
+       }
+       if ((unsigned int)memcard2_sel < ARRAY_SIZE(memcards)) {
+               if (memcard2_sel == 0)
+                       strcpy(Config.Mcd2, "none");
+               else if (memcards[memcard2_sel] != NULL)
+                       snprintf(Config.Mcd2, sizeof(Config.Mcd2), ".%s%s",
+                               MEMCARD_DIR, memcards[memcard2_sel]);
+       }
+       if (strcmp(mcd1_old, Config.Mcd1) || strcmp(mcd2_old, Config.Mcd2))
+               LoadMcds(Config.Mcd1, Config.Mcd2);
+
        return ret;
 }
 
@@ -1209,6 +1241,7 @@ static const char h_cscaler[]   = "Displays the scaler layer, you can resize it\
                                  "using d-pad or move it using R+d-pad";
 static const char h_overlay[]   = "Overlay provides hardware accelerated scaling";
 static const char h_soft_filter[] = "Works only if game uses low resolution modes";
+static const char h_scanline_l[]  = "Scanline brightness, 0-100%";
 static const char h_gamma[]     = "Gamma/brightness adjustment (default 100)";
 
 static int menu_loop_cscaler(int id, int keys)
@@ -1270,6 +1303,10 @@ static menu_entry e_menu_gfx_options[] =
        mee_onoff     ("Software Scaling",         MA_OPT_SCALER2, soft_scaling, 1),
        mee_enum      ("Hardware Filter",          MA_OPT_HWFILTER, plat_target.hwfilter, men_dummy),
        mee_enum_h    ("Software Filter",          MA_OPT_SWFILTER, soft_filter, men_soft_filter, h_soft_filter),
+#ifdef __ARM_NEON__
+       mee_onoff     ("Scanlines",                MA_OPT_SCANLINES, scanlines, 1),
+       mee_range_h   ("Scanline brightness",      MA_OPT_SCANLINE_LEVEL, scanline_level, 0, 100, h_scanline_l),
+#endif
        mee_range_h   ("Gamma adjustment",         MA_OPT_GAMMA, g_gamma, 1, 200, h_gamma),
 //     mee_onoff     ("Vsync",                    0, vsync, 1),
        mee_cust_h    ("Setup custom scaler",      MA_OPT_VARSCALER_C, menu_loop_cscaler, NULL, h_cscaler),
index 6b1e55f..81cd1ba 100644 (file)
@@ -29,6 +29,7 @@ enum g_soft_filter_opts {
 };
 
 extern int g_opts, g_scaler, g_gamma;
+extern int scanlines, scanline_level;
 extern int soft_scaling, analog_deadzone;
 extern int soft_filter;
 
index 64f96a0..163d4f1 100644 (file)
@@ -371,6 +371,19 @@ static void pl_vout_flip(const void *vram, int stride, int bgr24, int w, int h)
                neon_eagle2x_16_16(src, (void *)dest, w,
                        stride * 2, dstride * 2, h);
        }
+       else if (scanlines != 0 && scanline_level != 100)
+       {
+               int l = scanline_level * 2048 / 100;
+
+               for (; h1 >= 2; h1 -= 2)
+               {
+                       bgr555_to_rgb565(dest, src, w * 2);
+                       dest += dstride * 2, src += stride;
+
+                       bgr555_to_rgb565_b(dest, src, w * 2, l);
+                       dest += dstride * 2, src += stride;
+               }
+       }
 #endif
        else
        {