From 77075043fa22602441fc59c3dd615046686f1f89 Mon Sep 17 00:00:00 2001 From: jdgleaver Date: Tue, 22 Sep 2020 10:49:44 +0100 Subject: [PATCH] Interframe Blending: Improve accuracy of 'Simple (Fast)' method, remove 'Simple (Accurate)' method --- libgambatte/libretro/libretro.cpp | 83 +++++--------------- libgambatte/libretro/libretro_core_options.h | 3 +- 2 files changed, 19 insertions(+), 67 deletions(-) diff --git a/libgambatte/libretro/libretro.cpp b/libgambatte/libretro/libretro.cpp index 2ff558f..76ff615 100644 --- a/libgambatte/libretro/libretro.cpp +++ b/libgambatte/libretro/libretro.cpp @@ -90,7 +90,6 @@ enum frame_blend_method { FRAME_BLEND_NONE = 0, FRAME_BLEND_MIX, - FRAME_BLEND_MIX_FAST, FRAME_BLEND_LCD_GHOSTING, FRAME_BLEND_LCD_GHOSTING_FAST }; @@ -129,33 +128,30 @@ static void blend_frames_mix(void) /* Store colours for next frame */ *(prev + x) = rgb_curr; - /* Unpack colours and convert to float */ + /* Unpack colours */ #ifdef VIDEO_RGB565 - float r_curr = static_cast(rgb_curr >> 11 & 0x1F); - float g_curr = static_cast(rgb_curr >> 6 & 0x1F); - float b_curr = static_cast(rgb_curr & 0x1F); + gambatte::video_pixel_t r_curr = rgb_curr >> 11 & 0x1F; + gambatte::video_pixel_t g_curr = rgb_curr >> 6 & 0x1F; + gambatte::video_pixel_t b_curr = rgb_curr & 0x1F; - float r_prev = static_cast(rgb_prev >> 11 & 0x1F); - float g_prev = static_cast(rgb_prev >> 6 & 0x1F); - float b_prev = static_cast(rgb_prev & 0x1F); + gambatte::video_pixel_t r_prev = rgb_prev >> 11 & 0x1F; + gambatte::video_pixel_t g_prev = rgb_prev >> 6 & 0x1F; + gambatte::video_pixel_t b_prev = rgb_prev & 0x1F; #else - float r_curr = static_cast(rgb_curr >> 16 & 0x1F); - float g_curr = static_cast(rgb_curr >> 8 & 0x1F); - float b_curr = static_cast(rgb_curr & 0x1F); + gambatte::video_pixel_t r_curr = rgb_curr >> 16 & 0x1F; + gambatte::video_pixel_t g_curr = rgb_curr >> 8 & 0x1F; + gambatte::video_pixel_t b_curr = rgb_curr & 0x1F; - float r_prev = static_cast(rgb_prev >> 16 & 0x1F); - float g_prev = static_cast(rgb_prev >> 8 & 0x1F); - float b_prev = static_cast(rgb_prev & 0x1F); + gambatte::video_pixel_t r_prev = rgb_prev >> 16 & 0x1F; + gambatte::video_pixel_t g_prev = rgb_prev >> 8 & 0x1F; + gambatte::video_pixel_t b_prev = rgb_prev & 0x1F; #endif - /* Mix colours for current frame and convert back to video_pixel_t */ - gambatte::video_pixel_t r_mix = - static_cast(((r_curr * 0.5f) + (r_prev * 0.5f)) + 0.5f) & 0x1F; - gambatte::video_pixel_t g_mix = - static_cast(((g_curr * 0.5f) + (g_prev * 0.5f)) + 0.5f) & 0x1F; - gambatte::video_pixel_t b_mix = - static_cast(((b_curr * 0.5f) + (b_prev * 0.5f)) + 0.5f) & 0x1F; + /* Mix colours */ + gambatte::video_pixel_t r_mix = (r_curr >> 1) + (r_prev >> 1) + (((r_curr & 0x1) + (r_prev & 0x1)) >> 1); + gambatte::video_pixel_t g_mix = (g_curr >> 1) + (g_prev >> 1) + (((g_curr & 0x1) + (g_prev & 0x1)) >> 1); + gambatte::video_pixel_t b_mix = (b_curr >> 1) + (b_prev >> 1) + (((b_curr & 0x1) + (b_prev & 0x1)) >> 1); - // Repack colours for current frame + /* Repack colours for current frame */ #ifdef VIDEO_RGB565 *(curr + x) = r_mix << 11 | g_mix << 6 | b_mix; #else @@ -168,43 +164,6 @@ static void blend_frames_mix(void) } } -static void blend_frames_mix_fast(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); - - /* Store colours for next frame */ - *(prev + x) = rgb_curr; - - /* Mix colours for current frame - * > Fast one-shot method (bit twiddling) - * > Causes mild darkening of colours due to - * rounding errors */ -#ifdef VIDEO_RGB565 - *(curr + x) = (((rgb_curr >> 11 & 0x1F) >> 1) + ((rgb_prev >> 11 & 0x1F) >> 1)) << 11 - | (((rgb_curr >> 6 & 0x1F) >> 1) + ((rgb_prev >> 6 & 0x1F) >> 1)) << 6 - | (((rgb_curr & 0x1F) >> 1) + ((rgb_prev & 0x1F) >> 1)); -#else - *(curr + x) = (((rgb_curr >> 16 & 0x1F) >> 1) + ((rgb_prev >> 16 & 0x1F) >> 1)) << 16 - | (((rgb_curr >> 8 & 0x1F) >> 1) + ((rgb_prev >> 8 & 0x1F) >> 1)) << 8 - | (((rgb_curr & 0x1F) >> 1) + ((rgb_prev & 0x1F) >> 1)); -#endif - } - - curr += VIDEO_PITCH; - prev += VIDEO_PITCH; - } -} - static void blend_frames_lcd_ghost(void) { gambatte::video_pixel_t *curr = video_buf; @@ -428,7 +387,6 @@ static void init_frame_blending(void) switch (frame_blend_type) { case FRAME_BLEND_MIX: - case FRAME_BLEND_MIX_FAST: /* Simple 50:50 blending requires a single buffer */ if (!allocate_video_buf_prev(&video_buf_prev_1)) return; @@ -487,9 +445,6 @@ static void init_frame_blending(void) case FRAME_BLEND_MIX: blend_frames = blend_frames_mix; return; - case FRAME_BLEND_MIX_FAST: - blend_frames = blend_frames_mix_fast; - return; case FRAME_BLEND_LCD_GHOSTING: blend_frames = blend_frames_lcd_ghost; return; @@ -563,8 +518,6 @@ static void check_frame_blend_variable(void) { if (!strcmp(var.value, "mix")) frame_blend_type = FRAME_BLEND_MIX; - else if (!strcmp(var.value, "mix_fast")) - frame_blend_type = FRAME_BLEND_MIX_FAST; else if (!strcmp(var.value, "lcd_ghosting")) frame_blend_type = FRAME_BLEND_LCD_GHOSTING; else if (!strcmp(var.value, "lcd_ghosting_fast")) diff --git a/libgambatte/libretro/libretro_core_options.h b/libgambatte/libretro/libretro_core_options.h index 3524444..cdb0d02 100644 --- a/libgambatte/libretro/libretro_core_options.h +++ b/libgambatte/libretro/libretro_core_options.h @@ -295,8 +295,7 @@ struct retro_core_option_definition option_defs_us[] = { "Simulates LCD ghosting effects. 'Simple' performs a 50:50 mix of the current and previous frames. 'LCD Ghosting' mimics natural LCD response times by combining multiple buffered frames. 'Simple' blending is required when playing games that rely on LCD ghosting for transparency effects (Wave Race, Ballistic, Chikyuu Kaihou Gun ZAS...).", { { "disabled", NULL }, - { "mix", "Simple (Accurate)" }, - { "mix_fast", "Simple (Fast)" }, + { "mix", "Simple" }, { "lcd_ghosting", "LCD Ghosting (Accurate)" }, { "lcd_ghosting_fast", "LCD Ghosting (Fast)" }, { NULL, NULL },