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"