1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
diff --git a/libgambatte/libretro/libretro.cpp b/libgambatte/libretro/libretro.cpp
index 61a2949..8f0e0aa 100644
--- a/libgambatte/libretro/libretro.cpp
+++ b/libgambatte/libretro/libretro.cpp
@@ -123,7 +123,8 @@ enum frame_blend_method
FRAME_BLEND_NONE = 0,
FRAME_BLEND_MIX,
FRAME_BLEND_LCD_GHOSTING,
- FRAME_BLEND_LCD_GHOSTING_FAST
+ FRAME_BLEND_LCD_GHOSTING_FAST,
+ FRAME_BLEND_LCD_GHOSTING_FASTEST
};
static enum frame_blend_method frame_blend_type = FRAME_BLEND_NONE;
@@ -177,6 +178,41 @@ static void blend_frames_mix(void)
}
}
+/* Same as blend_frames_mix, but blending already blended frames to
+ * simulate lcd response */
+static void blend_frames_lcd_ghost_fastest(void)
+{
+ gambatte::video_pixel_t *curr = video_buf;
+ gambatte::video_pixel_t *prev = video_buf_prev_1;
+ size_t x, y;
+
+ for (y = 0; y < VIDEO_HEIGHT; y++)
+ {
+ for (x = 0; x < VIDEO_WIDTH; x++)
+ {
+ /* Get colours from current + previous frames */
+ gambatte::video_pixel_t rgb_curr = *(curr + x);
+ gambatte::video_pixel_t rgb_prev = *(prev + x);
+
+ /* Mix colours
+ * > "Mixing Packed RGB Pixels Efficiently"
+ * http://blargg.8bitalley.com/info/rgb_mixing.html */
+#ifdef VIDEO_RGB565
+ *(curr + x) = (rgb_curr + rgb_prev + ((rgb_curr ^ rgb_prev) & 0x821)) >> 1;
+#elif defined(VIDEO_ABGR1555)
+ *(curr + x) = (rgb_curr + rgb_prev + ((rgb_curr ^ rgb_prev) & 0x521)) >> 1;
+#else
+ *(curr + x) = (rgb_curr + rgb_prev + ((rgb_curr ^ rgb_prev) & 0x10101)) >> 1;
+#endif
+ /* Store colours for next frame */
+ *(prev + x) = rgb_prev == *(curr + x) ? rgb_curr : *(curr + x);
+ }
+
+ curr += VIDEO_PITCH;
+ prev += VIDEO_PITCH;
+ }
+}
+
static void blend_frames_lcd_ghost(void)
{
gambatte::video_pixel_t *curr = video_buf;
@@ -451,6 +487,11 @@ static void init_frame_blending(void)
if (!allocate_video_buf_acc())
return;
break;
+ case FRAME_BLEND_LCD_GHOSTING_FASTEST:
+ /* Fastest ghosting requires a single accumulator buffer */
+ if (!allocate_video_buf_prev(&video_buf_prev_1))
+ return;
+ break;
case FRAME_BLEND_NONE:
default:
/* Error condition - cannot happen
@@ -494,6 +535,9 @@ static void init_frame_blending(void)
case FRAME_BLEND_LCD_GHOSTING_FAST:
blend_frames = blend_frames_lcd_ghost_fast;
return;
+ case FRAME_BLEND_LCD_GHOSTING_FASTEST:
+ blend_frames = blend_frames_lcd_ghost_fastest;
+ return;
case FRAME_BLEND_NONE:
default:
/* Error condition - cannot happen
@@ -568,6 +612,8 @@ static void check_frame_blend_variable(void)
frame_blend_type = FRAME_BLEND_LCD_GHOSTING;
else if (!strcmp(var.value, "lcd_ghosting_fast"))
frame_blend_type = FRAME_BLEND_LCD_GHOSTING_FAST;
+ else if (!strcmp(var.value, "lcd_ghosting_fastest"))
+ frame_blend_type = FRAME_BLEND_LCD_GHOSTING_FASTEST;
}
if (frame_blend_type == FRAME_BLEND_NONE)
diff --git a/libgambatte/libretro/libretro_core_options.h b/libgambatte/libretro/libretro_core_options.h
index ca5d896..e76c29f 100644
--- a/libgambatte/libretro/libretro_core_options.h
+++ b/libgambatte/libretro/libretro_core_options.h
@@ -471,10 +471,11 @@ struct retro_core_option_v2_definition option_defs_us[] = {
NULL,
NULL,
{
- { "disabled", NULL },
- { "mix", "Simple" },
- { "lcd_ghosting", "LCD Ghosting (Accurate)" },
- { "lcd_ghosting_fast", "LCD Ghosting (Fast)" },
+ { "disabled", NULL },
+ { "mix", "Simple" },
+ { "lcd_ghosting", "LCD Ghosting (Accurate)" },
+ { "lcd_ghosting_fast", "LCD Ghosting (Fast)" },
+ { "lcd_ghosting_fastest", "LCD Ghosting (Fastest)" },
{ NULL, NULL },
},
"disabled"
|